~ubuntu-branches/ubuntu/natty/postgresql-8.4/natty-security

« back to all changes in this revision

Viewing changes to src/backend/utils/adt/tsvector_op.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-07-11 16:59:35 UTC
  • mfrom: (5.1.1 karmic)
  • Revision ID: james.westby@ubuntu.com-20090711165935-jfwin6gfrxf0gfsi
Tags: 8.4.0-2
* debian/libpq-dev.install: Ship catalog/genbki.h. (Closes: #536139)
* debian/rules: Drop --enable-cassert for final release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 *
8
8
 *
9
9
 * IDENTIFICATION
10
 
 *        $PostgreSQL: pgsql/src/backend/utils/adt/tsvector_op.c,v 1.21 2009/01/07 13:44:36 tgl Exp $
 
10
 *        $PostgreSQL: pgsql/src/backend/utils/adt/tsvector_op.c,v 1.23 2009/06/11 14:49:04 momjian Exp $
11
11
 *
12
12
 *-------------------------------------------------------------------------
13
13
 */
38
38
 
39
39
typedef struct StatEntry
40
40
{
41
 
        uint32          ndoc; /* zero indicates that we already was here while
42
 
                                                 walking throug the tree */
 
41
        uint32          ndoc;                   /* zero indicates that we already was here
 
42
                                                                 * while walking throug the tree */
43
43
        uint32          nentry;
44
44
        struct StatEntry *left;
45
45
        struct StatEntry *right;
54
54
        int4            weight;
55
55
 
56
56
        uint32          maxdepth;
57
 
        
58
 
        StatEntry       **stack;
 
57
 
 
58
        StatEntry **stack;
59
59
        uint32          stackpos;
60
60
 
61
 
        StatEntry*      root;
 
61
        StatEntry  *root;
62
62
} TSVectorStat;
63
63
 
64
64
#define STATHDRSIZE (offsetof(TSVectorStat, data))
127
127
                        {
128
128
                                return (aptr->haspos > bptr->haspos) ? -1 : 1;
129
129
                        }
130
 
                        else if ( (res=tsCompareString( STRPTR(a) + aptr->pos, aptr->len, STRPTR(b) + bptr->pos, bptr->len, false)) !=0 )
 
130
                        else if ((res = tsCompareString(STRPTR(a) + aptr->pos, aptr->len, STRPTR(b) + bptr->pos, bptr->len, false)) != 0)
131
131
                        {
132
132
                                return res;
133
133
                        }
172
172
        PG_FREE_IF_COPY(a,0);                                                           \
173
173
        PG_FREE_IF_COPY(b,1);                                                           \
174
174
        PG_RETURN_##ret( res action 0 );                                        \
175
 
}
 
175
}       \
 
176
/* keep compiler quiet - no extra ; */                                  \
 
177
extern int no_such_variable
176
178
 
177
179
TSVECTORCMPFUNC(lt, <, BOOL);
178
180
TSVECTORCMPFUNC(le, <=, BOOL);
522
524
}
523
525
 
524
526
/*
525
 
 * Compare two strings by tsvector rules. 
 
527
 * Compare two strings by tsvector rules.
526
528
 * if isPrefix = true then it returns not-zero value if b has prefix a
527
529
 */
528
530
int4
529
531
tsCompareString(char *a, int lena, char *b, int lenb, bool prefix)
530
532
{
531
 
        int cmp;
 
533
        int                     cmp;
532
534
 
533
 
        if ( lena == 0 )
 
535
        if (lena == 0)
534
536
        {
535
 
                if ( prefix )
536
 
                        cmp = 0; /* emtry string is equal to any if a prefix match */ 
 
537
                if (prefix)
 
538
                        cmp = 0;                        /* emtry string is equal to any if a prefix
 
539
                                                                 * match */
537
540
                else
538
 
                        cmp = (lenb>0) ? -1 : 0;
 
541
                        cmp = (lenb > 0) ? -1 : 0;
539
542
        }
540
 
        else if ( lenb == 0 )
 
543
        else if (lenb == 0)
541
544
        {
542
 
                cmp = (lena>0) ? 1 : 0;
 
545
                cmp = (lena > 0) ? 1 : 0;
543
546
        }
544
547
        else
545
548
        {
546
549
                cmp = memcmp(a, b, Min(lena, lenb));
547
550
 
548
 
                if ( prefix )
 
551
                if (prefix)
549
552
                {
550
 
                        if ( cmp == 0 && lena > lenb )
 
553
                        if (cmp == 0 && lena > lenb)
551
554
                        {
552
555
                                /*
553
556
                                 * b argument is not beginning with argument a
554
557
                                 */
555
 
                                cmp=1;
 
558
                                cmp = 1;
556
559
                        }
557
560
                }
558
 
                else if ( (cmp == 0) && (lena != lenb) )
 
561
                else if ((cmp == 0) && (lena != lenb))
559
562
                {
560
563
                        cmp = (lena < lenb) ? -1 : 1;
561
564
                }
599
602
        WordEntry  *StopLow = chkval->arrb;
600
603
        WordEntry  *StopHigh = chkval->arre;
601
604
        WordEntry  *StopMiddle = StopHigh;
602
 
        int                     difference = -1; 
603
 
        bool            res=false;
 
605
        int                     difference = -1;
 
606
        bool            res = false;
604
607
 
605
608
        /* Loop invariant: StopLow <= val < StopHigh */
606
609
        while (StopLow < StopHigh)
607
610
        {
608
611
                StopMiddle = StopLow + (StopHigh - StopLow) / 2;
609
 
                difference = tsCompareString( chkval->operand + val->distance, val->length,
610
 
                                                                          chkval->values + StopMiddle->pos, StopMiddle->len,
611
 
                                                                          false);
 
612
                difference = tsCompareString(chkval->operand + val->distance, val->length,
 
613
                                                   chkval->values + StopMiddle->pos, StopMiddle->len,
 
614
                                                                         false);
612
615
 
613
616
                if (difference == 0)
614
617
                {
622
625
                        StopHigh = StopMiddle;
623
626
        }
624
627
 
625
 
        if ( res == false && val->prefix == true )
 
628
        if (res == false && val->prefix == true)
626
629
        {
627
630
                /*
628
631
                 * there was a failed exact search, so we should scan further to find
629
632
                 * a prefix match.
630
633
                 */
631
 
                if ( StopLow >= StopHigh )
 
634
                if (StopLow >= StopHigh)
632
635
                        StopMiddle = StopHigh;
633
636
 
634
 
                while( res == false && StopMiddle < chkval->arre && 
635
 
                                tsCompareString( chkval->operand + val->distance, val->length,
636
 
                                                                 chkval->values + StopMiddle->pos, StopMiddle->len,
637
 
                                                                 true) == 0 )
 
637
                while (res == false && StopMiddle < chkval->arre &&
 
638
                           tsCompareString(chkval->operand + val->distance, val->length,
 
639
                                                   chkval->values + StopMiddle->pos, StopMiddle->len,
 
640
                                                           true) == 0)
638
641
                {
639
642
                        res = (val->weight && StopMiddle->haspos) ?
640
643
                                checkclass_str(chkval, StopMiddle, val) : true;
643
646
                }
644
647
        }
645
648
 
646
 
        return res; 
 
649
        return res;
647
650
}
648
651
 
649
652
/*
801
804
        return num;
802
805
}
803
806
 
804
 
#define compareStatWord(a,e,t)                                                  \
 
807
#define compareStatWord(a,e,t)                                                  \
805
808
        tsCompareString((a)->lexeme, (a)->lenlexeme,            \
806
809
                                        STRPTR(t) + (e)->pos, (e)->len,         \
807
810
                                        false)
809
812
static void
810
813
insertStatEntry(MemoryContext persistentContext, TSVectorStat *stat, TSVector txt, uint32 off)
811
814
{
812
 
        WordEntry       *we = ARRPTR(txt) + off;
813
 
        StatEntry       *node = stat->root, 
814
 
                                *pnode=NULL;
 
815
        WordEntry  *we = ARRPTR(txt) + off;
 
816
        StatEntry  *node = stat->root,
 
817
                           *pnode = NULL;
815
818
        int                     n,
816
819
                                res = 0;
817
 
        uint32          depth=1;
 
820
        uint32          depth = 1;
818
821
 
819
 
        if (stat->weight == 0) 
 
822
        if (stat->weight == 0)
820
823
                n = (we->haspos) ? POSDATALEN(txt, we) : 1;
821
824
        else
822
825
                n = (we->haspos) ? check_weight(txt, we, stat->weight) : 0;
823
826
 
824
 
        if ( n == 0 )
825
 
                return; /* nothing to insert */
 
827
        if (n == 0)
 
828
                return;                                 /* nothing to insert */
826
829
 
827
 
        while( node ) 
 
830
        while (node)
828
831
        {
829
832
                res = compareStatWord(node, we, txt);
830
833
 
835
838
                else
836
839
                {
837
840
                        pnode = node;
838
 
                        node = ( res < 0 ) ? node->left : node->right;
 
841
                        node = (res < 0) ? node->left : node->right;
839
842
                }
840
843
                depth++;
841
844
        }
845
848
 
846
849
        if (node == NULL)
847
850
        {
848
 
                node = MemoryContextAlloc(persistentContext, STATENTRYHDRSZ + we->len );
 
851
                node = MemoryContextAlloc(persistentContext, STATENTRYHDRSZ + we->len);
849
852
                node->left = node->right = NULL;
850
853
                node->ndoc = 1;
851
854
                node->nentry = n;
852
855
                node->lenlexeme = we->len;
853
856
                memcpy(node->lexeme, STRPTR(txt) + we->pos, node->lenlexeme);
854
857
 
855
 
                if ( pnode==NULL )
 
858
                if (pnode == NULL)
856
859
                {
857
860
                        stat->root = node;
858
861
                }
863
866
                        else
864
867
                                pnode->right = node;
865
868
                }
866
 
                        
 
869
 
867
870
        }
868
871
        else
869
872
        {
873
876
}
874
877
 
875
878
static void
876
 
chooseNextStatEntry(MemoryContext persistentContext, TSVectorStat *stat, TSVector txt, 
877
 
                        uint32 low, uint32 high, uint32 offset)
 
879
chooseNextStatEntry(MemoryContext persistentContext, TSVectorStat *stat, TSVector txt,
 
880
                                        uint32 low, uint32 high, uint32 offset)
878
881
{
879
 
        uint32      pos;
880
 
        uint32      middle = (low + high) >> 1;
 
882
        uint32          pos;
 
883
        uint32          middle = (low + high) >> 1;
881
884
 
882
885
        pos = (low + middle) >> 1;
883
886
        if (low != middle && pos >= offset && pos - offset < txt->size)
884
 
                insertStatEntry( persistentContext, stat, txt, pos - offset );
 
887
                insertStatEntry(persistentContext, stat, txt, pos - offset);
885
888
        pos = (high + middle + 1) >> 1;
886
889
        if (middle + 1 != high && pos >= offset && pos - offset < txt->size)
887
 
                insertStatEntry( persistentContext, stat, txt, pos - offset );
 
890
                insertStatEntry(persistentContext, stat, txt, pos - offset);
888
891
 
889
892
        if (low != middle)
890
893
                chooseNextStatEntry(persistentContext, stat, txt, low, middle, offset);
907
910
static TSVectorStat *
908
911
ts_accum(MemoryContext persistentContext, TSVectorStat *stat, Datum data)
909
912
{
910
 
        TSVector                txt = DatumGetTSVector(data);
911
 
        uint32                  i,
912
 
                                        nbit = 0,
913
 
                                        offset;
 
913
        TSVector        txt = DatumGetTSVector(data);
 
914
        uint32          i,
 
915
                                nbit = 0,
 
916
                                offset;
914
917
 
915
918
        if (stat == NULL)
916
 
        {       /* Init in first */
 
919
        {                                                       /* Init in first */
917
920
                stat = MemoryContextAllocZero(persistentContext, sizeof(TSVectorStat));
918
921
                stat->maxdepth = 1;
919
922
        }
933
936
        nbit = 1 << nbit;
934
937
        offset = (nbit - txt->size) / 2;
935
938
 
936
 
        insertStatEntry( persistentContext, stat, txt, (nbit >> 1) - offset );
 
939
        insertStatEntry(persistentContext, stat, txt, (nbit >> 1) - offset);
937
940
        chooseNextStatEntry(persistentContext, stat, txt, 0, nbit, offset);
938
941
 
939
942
        return stat;
943
946
ts_setup_firstcall(FunctionCallInfo fcinfo, FuncCallContext *funcctx,
944
947
                                   TSVectorStat *stat)
945
948
{
946
 
        TupleDesc               tupdesc;
947
 
        MemoryContext   oldcontext;
948
 
        StatEntry               *node;
 
949
        TupleDesc       tupdesc;
 
950
        MemoryContext oldcontext;
 
951
        StatEntry  *node;
949
952
 
950
953
        funcctx->user_fctx = (void *) stat;
951
954
 
952
955
        oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
953
956
 
954
957
        stat->stack = palloc0(sizeof(StatEntry *) * (stat->maxdepth + 1));
955
 
        stat->stackpos = 0; 
 
958
        stat->stackpos = 0;
956
959
 
957
960
        node = stat->root;
958
961
        /* find leftmost value */
959
962
        for (;;)
960
963
        {
961
 
                stat->stack[ stat->stackpos ] = node;
 
964
                stat->stack[stat->stackpos] = node;
962
965
                if (node->left)
963
966
                {
964
967
                        stat->stackpos++;
982
985
}
983
986
 
984
987
static StatEntry *
985
 
walkStatEntryTree(TSVectorStat *stat) 
 
988
walkStatEntryTree(TSVectorStat *stat)
986
989
{
987
 
        StatEntry       *node = stat->stack[ stat->stackpos ];
 
990
        StatEntry  *node = stat->stack[stat->stackpos];
988
991
 
989
 
        if ( node == NULL )
 
992
        if (node == NULL)
990
993
                return NULL;
991
994
 
992
 
        if ( node->ndoc != 0 )
 
995
        if (node->ndoc != 0)
993
996
        {
994
997
                /* return entry itself: we already was at left sublink */
995
998
                return node;
1029
1032
static Datum
1030
1033
ts_process_call(FuncCallContext *funcctx)
1031
1034
{
1032
 
        TSVectorStat    *st;
1033
 
        StatEntry               *entry;
 
1035
        TSVectorStat *st;
 
1036
        StatEntry  *entry;
1034
1037
 
1035
1038
        st = (TSVectorStat *) funcctx->user_fctx;
1036
1039
 
1162
1165
 
1163
1166
        if (SRF_IS_FIRSTCALL())
1164
1167
        {
1165
 
                TSVectorStat       *stat;
 
1168
                TSVectorStat *stat;
1166
1169
                text       *txt = PG_GETARG_TEXT_P(0);
1167
1170
 
1168
1171
                funcctx = SRF_FIRSTCALL_INIT();
1187
1190
 
1188
1191
        if (SRF_IS_FIRSTCALL())
1189
1192
        {
1190
 
                TSVectorStat       *stat;
 
1193
                TSVectorStat *stat;
1191
1194
                text       *txt = PG_GETARG_TEXT_P(0);
1192
1195
                text       *ws = PG_GETARG_TEXT_P(1);
1193
1196