LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - tsvector.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: ba12a202ce1b5581dc0ed149cf3f637d7897ad5d vs 2866d8c7dbfc9d882a7d80fef93fbbe763709932 Lines: 68.5 % 248 170 78 2 168 3
Current Date: 2026-08-27 14:31:44 +0300 Functions: 75.0 % 8 6 2 2 4
Baseline: lcov-20260827-baseline Branches: 52.6 % 156 82 74 82
Baseline Date: 2026-08-27 14:31:58 +0300 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 40.0 % 10 4 6 2 2
(30,360] days: 100.0 % 6 6 6
(360..) days: 69.0 % 232 160 72 160
Function coverage date bins:
(360..) days: 75.0 % 8 6 2 2 4
Branch coverage date bins:
(7,30] days: 7.1 % 14 1 13 1
(30,360] days: 100.0 % 2 2 2
(360..) days: 56.4 % 140 79 61 79

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

Generated by: LCOV version 2.0-1