LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - tsvector.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 69.5 % 249 173 6 2 42 26 2 75 8 88 47 77 1 6
Current Date: 2023-04-08 17:13:01 Functions: 66.7 % 9 6 3 6 3 6
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 57.1 % 14 8 6 8
Legend: Lines: hit not hit (240..) days: 70.2 % 235 165 2 42 26 2 75 88 43 77
Function coverage date bins:
(240..) days: 33.3 % 18 6 3 6 3 6

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * tsvector.c
                                  4                 :  *    I/O functions for tsvector
                                  5                 :  *
                                  6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  7                 :  *
                                  8                 :  *
                                  9                 :  * IDENTIFICATION
                                 10                 :  *    src/backend/utils/adt/tsvector.c
                                 11                 :  *
                                 12                 :  *-------------------------------------------------------------------------
                                 13                 :  */
                                 14                 : 
                                 15                 : #include "postgres.h"
                                 16                 : 
                                 17                 : #include "libpq/pqformat.h"
                                 18                 : #include "nodes/miscnodes.h"
                                 19                 : #include "tsearch/ts_locale.h"
                                 20                 : #include "tsearch/ts_utils.h"
                                 21                 : #include "utils/builtins.h"
                                 22                 : #include "utils/memutils.h"
                                 23                 : #include "varatt.h"
                                 24                 : 
                                 25                 : typedef struct
                                 26                 : {
                                 27                 :     WordEntry   entry;          /* must be first! */
                                 28                 :     WordEntryPos *pos;
                                 29                 :     int         poslen;         /* number of elements in pos */
                                 30                 : } WordEntryIN;
                                 31                 : 
                                 32                 : 
                                 33                 : /* Compare two WordEntryPos values for qsort */
                                 34                 : int
 2557 teodor                     35 GIC         504 : compareWordEntryPos(const void *a, const void *b)
                                 36                 : {
 5624 bruce                      37 CBC         504 :     int         apos = WEP_GETPOS(*(const WordEntryPos *) a);
 5624 bruce                      38 GIC         504 :     int         bpos = WEP_GETPOS(*(const WordEntryPos *) b);
 5693 teodor                     39 ECB             : 
 5693 teodor                     40 CBC         504 :     if (apos == bpos)
 5710 tgl                        41 GIC          12 :         return 0;
 5693 teodor                     42 CBC         492 :     return (apos > bpos) ? 1 : -1;
 5710 tgl                        43 ECB             : }
                                 44                 : 
                                 45                 : /*
                                 46                 :  * Removes duplicate pos entries. If there's two entries with same pos but
                                 47                 :  * different weight, the higher weight is retained, so we can't use
                                 48                 :  * qunique here.
                                 49                 :  *
                                 50                 :  * Returns new length.
                                 51                 :  */
                                 52                 : static int
 5624 bruce                      53 GIC        4803 : uniquePos(WordEntryPos *a, int l)
                                 54                 : {
 5710 tgl                        55 ECB             :     WordEntryPos *ptr,
                                 56                 :                *res;
                                 57                 : 
 5693 teodor                     58 GIC        4803 :     if (l <= 1)
 5710 tgl                        59            4536 :         return l;
 5710 tgl                        60 ECB             : 
   61 peter                      61 GNC         267 :     qsort(a, l, sizeof(WordEntryPos), compareWordEntryPos);
                                 62                 : 
 5647 tgl                        63 CBC         267 :     res = a;
 5710 tgl                        64 GIC         267 :     ptr = a + 1;
 5710 tgl                        65 CBC         726 :     while (ptr - a < l)
 5710 tgl                        66 ECB             :     {
 5710 tgl                        67 CBC         459 :         if (WEP_GETPOS(*ptr) != WEP_GETPOS(*res))
                                 68                 :         {
                                 69             447 :             res++;
 5710 tgl                        70 GIC         447 :             *res = *ptr;
 5647 tgl                        71 CBC         447 :             if (res - a >= MAXNUMPOS - 1 ||
                                 72             447 :                 WEP_GETPOS(*res) == MAXENTRYPOS - 1)
 5710 tgl                        73 ECB             :                 break;
                                 74                 :         }
 5710 tgl                        75 GIC          12 :         else if (WEP_GETWEIGHT(*ptr) > WEP_GETWEIGHT(*res))
                                 76               3 :             WEP_SETWEIGHT(*res, WEP_GETWEIGHT(*ptr));
 5710 tgl                        77 CBC         459 :         ptr++;
 5710 tgl                        78 ECB             :     }
                                 79                 : 
 5710 tgl                        80 GIC         267 :     return res + 1 - a;
                                 81                 : }
 5710 tgl                        82 ECB             : 
                                 83                 : /* Compare two WordEntryIN values for qsort */
                                 84                 : static int
 5693 teodor                     85 GIC      536253 : compareentry(const void *va, const void *vb, void *arg)
                                 86                 : {
 5647 tgl                        87 CBC      536253 :     const WordEntryIN *a = (const WordEntryIN *) va;
 5647 tgl                        88 GIC      536253 :     const WordEntryIN *b = (const WordEntryIN *) vb;
 5710 tgl                        89 CBC      536253 :     char       *BufferStr = (char *) arg;
 5710 tgl                        90 ECB             : 
 5050 bruce                      91 CBC     1072506 :     return tsCompareString(&BufferStr[a->entry.pos], a->entry.len,
 5050 bruce                      92 GIC      536253 :                            &BufferStr[b->entry.pos], b->entry.len,
 5050 bruce                      93 ECB             :                            false);
 5710 tgl                        94                 : }
                                 95                 : 
                                 96                 : /*
                                 97                 :  * Sort an array of WordEntryIN, remove duplicates.
                                 98                 :  * *outbuflen receives the amount of space needed for strings and positions.
                                 99                 :  */
                                100                 : static int
 5624 bruce                     101 GIC        1853 : uniqueentry(WordEntryIN *a, int l, char *buf, int *outbuflen)
                                102                 : {
 5624 bruce                     103 ECB             :     int         buflen;
                                104                 :     WordEntryIN *ptr,
                                105                 :                *res;
                                106                 : 
 5693 teodor                    107 GIC        1853 :     Assert(l >= 1);
                                108                 : 
 5647 tgl                       109 CBC        1853 :     if (l > 1)
   61 peter                     110 GNC        1802 :         qsort_arg(a, l, sizeof(WordEntryIN), compareentry, buf);
 5693 teodor                    111 ECB             : 
 5647 tgl                       112 GIC        1853 :     buflen = 0;
 5693 teodor                    113 CBC        1853 :     res = a;
 5710 tgl                       114            1853 :     ptr = a + 1;
                                115           90414 :     while (ptr - a < l)
 5710 tgl                       116 ECB             :     {
 5710 tgl                       117 GIC       88561 :         if (!(ptr->entry.len == res->entry.len &&
 5647 tgl                       118 CBC       88027 :               strncmp(&buf[ptr->entry.pos], &buf[res->entry.pos],
                                119           88027 :                       res->entry.len) == 0))
 5710 tgl                       120 ECB             :         {
                                121                 :             /* done accumulating data into *res, count space needed */
 5647 tgl                       122 GIC       85798 :             buflen += res->entry.len;
 5710 tgl                       123 CBC       85798 :             if (res->entry.haspos)
 5710 tgl                       124 ECB             :             {
 5693 teodor                    125 GIC        4497 :                 res->poslen = uniquePos(res->pos, res->poslen);
 5647 tgl                       126 CBC        4497 :                 buflen = SHORTALIGN(buflen);
                                127            4497 :                 buflen += res->poslen * sizeof(WordEntryPos) + sizeof(uint16);
 5710 tgl                       128 ECB             :             }
 5710 tgl                       129 GIC       85798 :             res++;
 3320 heikki.linnakangas        130 CBC       85798 :             if (res != ptr)
                                131           44286 :                 memcpy(res, ptr, sizeof(WordEntryIN));
 5710 tgl                       132 ECB             :         }
 5710 tgl                       133 GIC        2763 :         else if (ptr->entry.haspos)
 5710 tgl                       134 ECB             :         {
 5710 tgl                       135 GIC         159 :             if (res->entry.haspos)
 5710 tgl                       136 ECB             :             {
                                137                 :                 /* append ptr's positions to res's positions */
 5624 bruce                     138 GIC         156 :                 int         newlen = ptr->poslen + res->poslen;
 5693 teodor                    139 ECB             : 
 5647 tgl                       140 GIC         156 :                 res->pos = (WordEntryPos *)
 5647 tgl                       141 CBC         156 :                     repalloc(res->pos, newlen * sizeof(WordEntryPos));
                                142             156 :                 memcpy(&res->pos[res->poslen], ptr->pos,
                                143             156 :                        ptr->poslen * sizeof(WordEntryPos));
 5693 teodor                    144             156 :                 res->poslen = newlen;
 5710 tgl                       145             156 :                 pfree(ptr->pos);
 5710 tgl                       146 ECB             :             }
                                147                 :             else
                                148                 :             {
                                149                 :                 /* just give ptr's positions to pos */
 5710 tgl                       150 GIC           3 :                 res->entry.haspos = 1;
 5710 tgl                       151 CBC           3 :                 res->pos = ptr->pos;
 5647                           152               3 :                 res->poslen = ptr->poslen;
 5710 tgl                       153 ECB             :             }
                                154                 :         }
 5710 tgl                       155 GIC       88561 :         ptr++;
 5710 tgl                       156 ECB             :     }
                                157                 : 
                                158                 :     /* count space needed for last item */
 5647 tgl                       159 GIC        1853 :     buflen += res->entry.len;
 5710 tgl                       160 CBC        1853 :     if (res->entry.haspos)
 5710 tgl                       161 ECB             :     {
 5693 teodor                    162 GIC         306 :         res->poslen = uniquePos(res->pos, res->poslen);
 5647 tgl                       163 CBC         306 :         buflen = SHORTALIGN(buflen);
                                164             306 :         buflen += res->poslen * sizeof(WordEntryPos) + sizeof(uint16);
 5710 tgl                       165 ECB             :     }
                                166                 : 
 5647 tgl                       167 GIC        1853 :     *outbuflen = buflen;
 5710 tgl                       168 CBC        1853 :     return res + 1 - a;
 5710 tgl                       169 ECB             : }
                                170                 : 
                                171                 : static int
 5624 bruce                     172 UIC           0 : WordEntryCMP(WordEntry *a, WordEntry *b, char *buf)
 5710 tgl                       173 EUB             : {
 5710 tgl                       174 UIC           0 :     return compareentry(a, b, buf);
 5710 tgl                       175 EUB             : }
                                176                 : 
                                177                 : 
                                178                 : Datum
 5710 tgl                       179 GIC        1886 : tsvectorin(PG_FUNCTION_ARGS)
 5710 tgl                       180 ECB             : {
 5710 tgl                       181 GIC        1886 :     char       *buf = PG_GETARG_CSTRING(0);
  103 tgl                       182 GNC        1886 :     Node       *escontext = fcinfo->context;
 5710 tgl                       183 ECB             :     TSVectorParseState state;
                                184                 :     WordEntryIN *arr;
                                185                 :     int         totallen;
                                186                 :     int         arrlen;         /* allocated size of arr */
                                187                 :     WordEntry  *inarr;
 5693 teodor                    188 GIC        1886 :     int         len = 0;
                                189                 :     TSVector    in;
 5693 teodor                    190 ECB             :     int         i;
                                191                 :     char       *token;
                                192                 :     int         toklen;
                                193                 :     WordEntryPos *pos;
                                194                 :     int         poslen;
                                195                 :     char       *strbuf;
                                196                 :     int         stroff;
                                197                 : 
                                198                 :     /*
                                199                 :      * Tokens are appended to tmpbuf, cur is a pointer to the end of used
                                200                 :      * space in tmpbuf.
                                201                 :      */
                                202                 :     char       *tmpbuf;
                                203                 :     char       *cur;
 5624 bruce                     204 GIC        1886 :     int         buflen = 256;   /* allocated size of tmpbuf */
                                205                 : 
  103 tgl                       206 GNC        1886 :     state = init_tsvector_parser(buf, 0, escontext);
                                207                 : 
 5693 teodor                    208 CBC        1886 :     arrlen = 64;
 5693 teodor                    209 GIC        1886 :     arr = (WordEntryIN *) palloc(sizeof(WordEntryIN) * arrlen);
 5710 tgl                       210 CBC        1886 :     cur = tmpbuf = (char *) palloc(buflen);
 5710 tgl                       211 ECB             : 
 5693 teodor                    212 CBC       92300 :     while (gettoken_tsvector(state, &token, &toklen, &pos, &poslen, NULL))
                                213                 :     {
                                214           90414 :         if (toklen >= MAXSTRLEN)
  103 tgl                       215 UNC           0 :             ereturn(escontext, (Datum) 0,
 5647 tgl                       216 ECB             :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 5710 tgl                       217 EUB             :                      errmsg("word is too long (%ld bytes, max %ld bytes)",
                                218                 :                             (long) toklen,
                                219                 :                             (long) (MAXSTRLEN - 1))));
                                220                 : 
 5710 tgl                       221 GIC       90414 :         if (cur - tmpbuf > MAXSTRPOS)
  103 tgl                       222 UNC           0 :             ereturn(escontext, (Datum) 0,
 5647 tgl                       223 ECB             :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 5050 bruce                     224 EUB             :                      errmsg("string is too long for tsvector (%ld bytes, max %ld bytes)",
                                225                 :                             (long) (cur - tmpbuf), (long) MAXSTRPOS)));
                                226                 : 
                                227                 :         /*
                                228                 :          * Enlarge buffers if needed
                                229                 :          */
 5693 teodor                    230 GIC       90414 :         if (len >= arrlen)
                                231                 :         {
 5693 teodor                    232 CBC         657 :             arrlen *= 2;
                                233                 :             arr = (WordEntryIN *)
   61 peter                     234 GNC         657 :                 repalloc(arr, sizeof(WordEntryIN) * arrlen);
                                235                 :         }
 5693 teodor                    236 CBC       90414 :         while ((cur - tmpbuf) + toklen >= buflen)
                                237                 :         {
 5624 bruce                     238 LBC           0 :             int         dist = cur - tmpbuf;
                                239                 : 
 5693 teodor                    240 UBC           0 :             buflen *= 2;
   61 peter                     241 UNC           0 :             tmpbuf = (char *) repalloc(tmpbuf, buflen);
 5693 teodor                    242 UBC           0 :             cur = tmpbuf + dist;
 5693 teodor                    243 EUB             :         }
 5693 teodor                    244 GBC       90414 :         arr[len].entry.len = toklen;
 5710 tgl                       245 GIC       90414 :         arr[len].entry.pos = cur - tmpbuf;
   61 peter                     246 GNC       90414 :         memcpy(cur, token, toklen);
 5693 teodor                    247 CBC       90414 :         cur += toklen;
 5710 tgl                       248 ECB             : 
 5693 teodor                    249 CBC       90414 :         if (poslen != 0)
                                250                 :         {
 5710 tgl                       251            4959 :             arr[len].entry.haspos = 1;
 5693 teodor                    252 GIC        4959 :             arr[len].pos = pos;
 5693 teodor                    253 CBC        4959 :             arr[len].poslen = poslen;
 5710 tgl                       254 ECB             :         }
                                255                 :         else
                                256                 :         {
 5710 tgl                       257 GIC       85455 :             arr[len].entry.haspos = 0;
 5647                           258           85455 :             arr[len].pos = NULL;
 5647 tgl                       259 CBC       85455 :             arr[len].poslen = 0;
 5647 tgl                       260 ECB             :         }
 5710 tgl                       261 CBC       90414 :         len++;
                                262                 :     }
 5693 teodor                    263 ECB             : 
 5693 teodor                    264 GIC        1883 :     close_tsvector_parser(state);
                                265                 : 
                                266                 :     /* Did gettoken_tsvector fail? */
  103 tgl                       267 GNC        1883 :     if (SOFT_ERROR_OCCURRED(escontext))
                                268               6 :         PG_RETURN_NULL();
                                269                 : 
 5710 tgl                       270 CBC        1877 :     if (len > 0)
 5710 tgl                       271 GIC        1853 :         len = uniqueentry(arr, len, tmpbuf, &buflen);
                                272                 :     else
 5710 tgl                       273 CBC          24 :         buflen = 0;
 5647 tgl                       274 ECB             : 
 5647 tgl                       275 GIC        1877 :     if (buflen > MAXSTRPOS)
  103 tgl                       276 UNC           0 :         ereturn(escontext, (Datum) 0,
 5647 tgl                       277 ECB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                278                 :                  errmsg("string is too long for tsvector (%d bytes, max %d bytes)", buflen, MAXSTRPOS)));
                                279                 : 
 5710 tgl                       280 GIC        1877 :     totallen = CALCDATASIZE(len, buflen);
 5710 tgl                       281 CBC        1877 :     in = (TSVector) palloc0(totallen);
 5710 tgl                       282 GBC        1877 :     SET_VARSIZE(in, totallen);
 5710 tgl                       283 GIC        1877 :     in->size = len;
                                284            1877 :     inarr = ARRPTR(in);
 5647                           285            1877 :     strbuf = STRPTR(in);
 5647 tgl                       286 CBC        1877 :     stroff = 0;
 5710                           287           89528 :     for (i = 0; i < len; i++)
 5710 tgl                       288 ECB             :     {
 5647 tgl                       289 CBC       87651 :         memcpy(strbuf + stroff, &tmpbuf[arr[i].entry.pos], arr[i].entry.len);
                                290           87651 :         arr[i].entry.pos = stroff;
                                291           87651 :         stroff += arr[i].entry.len;
 5710                           292           87651 :         if (arr[i].entry.haspos)
 5710 tgl                       293 ECB             :         {
                                294                 :             /* This should be unreachable because of MAXNUMPOS restrictions */
 5647 tgl                       295 GIC        4803 :             if (arr[i].poslen > 0xFFFF)
 5693 teodor                    296 LBC           0 :                 elog(ERROR, "positions array too long");
 5693 teodor                    297 ECB             : 
 5647 tgl                       298                 :             /* Copy number of positions */
 5647 tgl                       299 CBC        4803 :             stroff = SHORTALIGN(stroff);
 5647 tgl                       300 GIC        4803 :             *(uint16 *) (strbuf + stroff) = (uint16) arr[i].poslen;
                                301            4803 :             stroff += sizeof(uint16);
 5693 teodor                    302 ECB             : 
 5693 teodor                    303 EUB             :             /* Copy positions */
 5647 tgl                       304 GIC        4803 :             memcpy(strbuf + stroff, arr[i].pos, arr[i].poslen * sizeof(WordEntryPos));
                                305            4803 :             stroff += arr[i].poslen * sizeof(WordEntryPos);
 5693 teodor                    306 ECB             : 
 5710 tgl                       307 CBC        4803 :             pfree(arr[i].pos);
 5710 tgl                       308 ECB             :         }
 5710 tgl                       309 GIC       87651 :         inarr[i] = arr[i].entry;
                                310                 :     }
 5710 tgl                       311 ECB             : 
 5647 tgl                       312 CBC        1877 :     Assert((strbuf + stroff - (char *) in) == totallen);
                                313                 : 
 5710                           314            1877 :     PG_RETURN_TSVECTOR(in);
                                315                 : }
 5710 tgl                       316 ECB             : 
                                317                 : Datum
 5710 tgl                       318 GIC        2378 : tsvectorout(PG_FUNCTION_ARGS)
 5710 tgl                       319 ECB             : {
 5710 tgl                       320 GIC        2378 :     TSVector    out = PG_GETARG_TSVECTOR(0);
 5710 tgl                       321 ECB             :     char       *outbuf;
                                322                 :     int32       i,
 5710 tgl                       323 GIC        2378 :                 lenbuf = 0,
                                324                 :                 pp;
 5710 tgl                       325 CBC        2378 :     WordEntry  *ptr = ARRPTR(out);
                                326                 :     char       *curbegin,
 5710 tgl                       327 ECB             :                *curin,
                                328                 :                *curout;
                                329                 : 
 5710 tgl                       330 CBC        2378 :     lenbuf = out->size * 2 /* '' */ + out->size - 1 /* space */ + 2 /* \0 */ ;
 5710 tgl                       331 GIC      118939 :     for (i = 0; i < out->size; i++)
 5710 tgl                       332 ECB             :     {
 5710 tgl                       333 GIC      116561 :         lenbuf += ptr[i].len * 2 * pg_database_encoding_max_length() /* for escape */ ;
                                334          116561 :         if (ptr[i].haspos)
                                335            6559 :             lenbuf += 1 /* : */ + 7 /* int2 + , + weight */ * POSDATALEN(out, &(ptr[i]));
                                336                 :     }
 5710 tgl                       337 ECB             : 
 5710 tgl                       338 CBC        2378 :     curout = outbuf = (char *) palloc(lenbuf);
 5710 tgl                       339 GIC      118939 :     for (i = 0; i < out->size; i++)
 5710 tgl                       340 ECB             :     {
 5710 tgl                       341 CBC      116561 :         curbegin = curin = STRPTR(out) + ptr->pos;
                                342          116561 :         if (i != 0)
 5710 tgl                       343 GIC      114276 :             *curout++ = ' ';
                                344          116561 :         *curout++ = '\'';
 5710 tgl                       345 CBC      353066 :         while (curin - curbegin < ptr->len)
 5710 tgl                       346 ECB             :         {
 5710 tgl                       347 GIC      236505 :             int         len = pg_mblen(curin);
 5710 tgl                       348 ECB             : 
 5710 tgl                       349 CBC      236505 :             if (t_iseq(curin, '\''))
                                350              13 :                 *curout++ = '\'';
 5623 teodor                    351          236492 :             else if (t_iseq(curin, '\\'))
                                352              45 :                 *curout++ = '\\';
                                353                 : 
 5710 tgl                       354          473010 :             while (len--)
 5710 tgl                       355 GIC      236505 :                 *curout++ = *curin++;
 5710 tgl                       356 ECB             :         }
                                357                 : 
 5710 tgl                       358 CBC      116561 :         *curout++ = '\'';
                                359          116561 :         if ((pp = POSDATALEN(out, ptr)) != 0)
                                360                 :         {
 5710 tgl                       361 ECB             :             WordEntryPos *wptr;
                                362                 : 
 5710 tgl                       363 GIC        6559 :             *curout++ = ':';
                                364            6559 :             wptr = POSDATAPTR(out, ptr);
 5710 tgl                       365 CBC       13584 :             while (pp)
 5710 tgl                       366 ECB             :             {
 5710 tgl                       367 GIC        7025 :                 curout += sprintf(curout, "%d", WEP_GETPOS(*wptr));
                                368            7025 :                 switch (WEP_GETWEIGHT(*wptr))
                                369                 :                 {
 5710 tgl                       370 CBC          58 :                     case 3:
                                371              58 :                         *curout++ = 'A';
                                372              58 :                         break;
 5710 tgl                       373 GIC          34 :                     case 2:
 5710 tgl                       374 CBC          34 :                         *curout++ = 'B';
                                375              34 :                         break;
 5710 tgl                       376 GIC         115 :                     case 1:
 5710 tgl                       377 CBC         115 :                         *curout++ = 'C';
                                378             115 :                         break;
                                379            6818 :                     case 0:
 5710 tgl                       380 ECB             :                     default:
 5710 tgl                       381 CBC        6818 :                         break;
 5710 tgl                       382 ECB             :                 }
                                383                 : 
 5710 tgl                       384 CBC        7025 :                 if (pp > 1)
                                385             466 :                     *curout++ = ',';
                                386            7025 :                 pp--;
 5710 tgl                       387 GIC        7025 :                 wptr++;
 5710 tgl                       388 ECB             :             }
                                389                 :         }
 5710 tgl                       390 GIC      116561 :         ptr++;
 5710 tgl                       391 ECB             :     }
                                392                 : 
 5710 tgl                       393 CBC        2378 :     *curout = '\0';
                                394            2378 :     PG_FREE_IF_COPY(out, 0);
 5710 tgl                       395 GIC        2378 :     PG_RETURN_CSTRING(outbuf);
                                396                 : }
 5710 tgl                       397 ECB             : 
                                398                 : /*
                                399                 :  * Binary Input / Output functions. The binary format is as follows:
 5693 teodor                    400                 :  *
                                401                 :  * uint32   number of lexemes
 5624 bruce                     402                 :  *
                                403                 :  * for each lexeme:
                                404                 :  *      lexeme text in client encoding, null-terminated
                                405                 :  *      uint16  number of positions
                                406                 :  *      for each position:
                                407                 :  *          uint16 WordEntryPos
                                408                 :  */
                                409                 : 
                                410                 : Datum
 5710 tgl                       411 UIC           0 : tsvectorsend(PG_FUNCTION_ARGS)
                                412                 : {
                                413               0 :     TSVector    vec = PG_GETARG_TSVECTOR(0);
                                414                 :     StringInfoData buf;
                                415                 :     int         i,
                                416                 :                 j;
                                417               0 :     WordEntry  *weptr = ARRPTR(vec);
 5710 tgl                       418 EUB             : 
 5710 tgl                       419 UIC           0 :     pq_begintypsend(&buf);
 5710 tgl                       420 EUB             : 
 2006 andres                    421 UIC           0 :     pq_sendint32(&buf, vec->size);
 5710 tgl                       422               0 :     for (i = 0; i < vec->size; i++)
                                423                 :     {
 5624 bruce                     424 EUB             :         uint16      npos;
                                425                 : 
                                426                 :         /*
                                427                 :          * the strings in the TSVector array are not null-terminated, so we
                                428                 :          * have to send the null-terminator separately
 5710 tgl                       429                 :          */
 5693 teodor                    430 UIC           0 :         pq_sendtext(&buf, STRPTR(vec) + weptr->pos, weptr->len);
                                431               0 :         pq_sendbyte(&buf, '\0');
                                432                 : 
                                433               0 :         npos = POSDATALEN(vec, weptr);
 2006 andres                    434               0 :         pq_sendint16(&buf, npos);
                                435                 : 
 5624 bruce                     436               0 :         if (npos > 0)
 5710 tgl                       437 EUB             :         {
 5710 tgl                       438 UBC           0 :             WordEntryPos *wepptr = POSDATAPTR(vec, weptr);
                                439                 : 
 5693 teodor                    440               0 :             for (j = 0; j < npos; j++)
 2006 andres                    441               0 :                 pq_sendint16(&buf, wepptr[j]);
                                442                 :         }
 5710 tgl                       443               0 :         weptr++;
                                444                 :     }
 5710 tgl                       445 EUB             : 
 5710 tgl                       446 UIC           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 5710 tgl                       447 EUB             : }
                                448                 : 
                                449                 : Datum
 5710 tgl                       450 UBC           0 : tsvectorrecv(PG_FUNCTION_ARGS)
                                451                 : {
 5710 tgl                       452 UIC           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
 5710 tgl                       453 EUB             :     TSVector    vec;
                                454                 :     int         i;
                                455                 :     int32       nentries;
                                456                 :     int         datalen;        /* number of bytes used in the variable size
 5624 bruce                     457                 :                                  * area after fixed size TSVector header and
                                458                 :                                  * WordEntries */
 5693 teodor                    459                 :     Size        hdrlen;
                                460                 :     Size        len;            /* allocated size of vec */
 5071 teodor                    461 UIC           0 :     bool        needSort = false;
                                462                 : 
 5693                           463               0 :     nentries = pq_getmsgint(buf, sizeof(int32));
                                464               0 :     if (nentries < 0 || nentries > (MaxAllocSize / sizeof(WordEntry)))
 5710 tgl                       465               0 :         elog(ERROR, "invalid size of tsvector");
                                466                 : 
 5693 teodor                    467               0 :     hdrlen = DATAHDRSIZE + sizeof(WordEntry) * nentries;
 5710 tgl                       468 EUB             : 
 5624 bruce                     469 UIC           0 :     len = hdrlen * 2;           /* times two to make room for lexemes */
 5710 tgl                       470 UBC           0 :     vec = (TSVector) palloc0(len);
 5693 teodor                    471               0 :     vec->size = nentries;
 5710 tgl                       472 EUB             : 
 5693 teodor                    473 UIC           0 :     datalen = 0;
 5693 teodor                    474 UBC           0 :     for (i = 0; i < nentries; i++)
                                475                 :     {
 5693 teodor                    476 EUB             :         const char *lexeme;
 5624 bruce                     477                 :         uint16      npos;
                                478                 :         size_t      lex_len;
                                479                 : 
 5693 teodor                    480 UBC           0 :         lexeme = pq_getmsgstring(buf);
                                481               0 :         npos = (uint16) pq_getmsgint(buf, sizeof(uint16));
                                482                 : 
                                483                 :         /* sanity checks */
                                484                 : 
 5693 teodor                    485 UIC           0 :         lex_len = strlen(lexeme);
 5071 meskes                    486               0 :         if (lex_len > MAXSTRLEN)
 5611 tgl                       487 UBC           0 :             elog(ERROR, "invalid tsvector: lexeme too long");
 5693 teodor                    488 EUB             : 
 5693 teodor                    489 UIC           0 :         if (datalen > MAXSTRPOS)
 5611 tgl                       490               0 :             elog(ERROR, "invalid tsvector: maximum total lexeme length exceeded");
                                491                 : 
 5693 teodor                    492 UBC           0 :         if (npos > MAXNUMPOS)
 5611 tgl                       493               0 :             elog(ERROR, "unexpected number of tsvector positions");
 5710 tgl                       494 EUB             : 
                                495                 :         /*
 5693 teodor                    496                 :          * Looks valid. Fill the WordEntry struct, and copy lexeme.
                                497                 :          *
                                498                 :          * But make sure the buffer is large enough first.
 5710 tgl                       499                 :          */
 5693 teodor                    500 UBC           0 :         while (hdrlen + SHORTALIGN(datalen + lex_len) +
 5693 teodor                    501 UIC           0 :                (npos + 1) * sizeof(WordEntryPos) >= len)
                                502                 :         {
 5710 tgl                       503               0 :             len *= 2;
                                504               0 :             vec = (TSVector) repalloc(vec, len);
                                505                 :         }
                                506                 : 
 5693 teodor                    507 UBC           0 :         vec->entries[i].haspos = (npos > 0) ? 1 : 0;
                                508               0 :         vec->entries[i].len = lex_len;
 5693 teodor                    509 UIC           0 :         vec->entries[i].pos = datalen;
 5693 teodor                    510 EUB             : 
 5693 teodor                    511 UBC           0 :         memcpy(STRPTR(vec) + datalen, lexeme, lex_len);
                                512                 : 
 5693 teodor                    513 UIC           0 :         datalen += lex_len;
 5710 tgl                       514 EUB             : 
 5647 tgl                       515 UBC           0 :         if (i > 0 && WordEntryCMP(&vec->entries[i],
                                516               0 :                                   &vec->entries[i - 1],
 5647 tgl                       517 UIC           0 :                                   STRPTR(vec)) <= 0)
 5071 teodor                    518 UBC           0 :             needSort = true;
                                519                 : 
 5693 teodor                    520 EUB             :         /* Receive positions */
 5693 teodor                    521 UIC           0 :         if (npos > 0)
 5710 tgl                       522 EUB             :         {
 5693 teodor                    523                 :             uint16      j;
 5710 tgl                       524                 :             WordEntryPos *wepptr;
                                525                 : 
                                526                 :             /*
                                527                 :              * Pad to 2-byte alignment if necessary. Though we used palloc0
 5624 bruce                     528                 :              * for the initial allocation, subsequent repalloc'd memory areas
                                529                 :              * are not initialized to zero.
                                530                 :              */
 5693 teodor                    531 UIC           0 :             if (datalen != SHORTALIGN(datalen))
                                532                 :             {
                                533               0 :                 *(STRPTR(vec) + datalen) = '\0';
                                534               0 :                 datalen = SHORTALIGN(datalen);
                                535                 :             }
                                536                 : 
                                537               0 :             memcpy(STRPTR(vec) + datalen, &npos, sizeof(uint16));
 5693 teodor                    538 EUB             : 
 5693 teodor                    539 UIC           0 :             wepptr = POSDATAPTR(vec, &vec->entries[i]);
 5710 tgl                       540 UBC           0 :             for (j = 0; j < npos; j++)
 5710 tgl                       541 EUB             :             {
 5693 teodor                    542 UIC           0 :                 wepptr[j] = (WordEntryPos) pq_getmsgint(buf, sizeof(WordEntryPos));
 5710 tgl                       543               0 :                 if (j > 0 && WEP_GETPOS(wepptr[j]) <= WEP_GETPOS(wepptr[j - 1]))
 5649 tgl                       544 UBC           0 :                     elog(ERROR, "position information is misordered");
                                545                 :             }
 5710 tgl                       546 EUB             : 
 5710 tgl                       547 UBC           0 :             datalen += (npos + 1) * sizeof(WordEntry);
                                548                 :         }
 5710 tgl                       549 EUB             :     }
                                550                 : 
 5693 teodor                    551 UBC           0 :     SET_VARSIZE(vec, hdrlen + datalen);
                                552                 : 
 5071 teodor                    553 UIC           0 :     if (needSort)
   61 peter                     554 UNC           0 :         qsort_arg(ARRPTR(vec), vec->size, sizeof(WordEntry),
                                555               0 :                   compareentry, STRPTR(vec));
                                556                 : 
 5710 tgl                       557 UIC           0 :     PG_RETURN_TSVECTOR(vec);
 5710 tgl                       558 EUB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a