LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - tsvector.c (source / functions) Coverage Total Hit UBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 69.8 % 245 171 74 171
Current Date: 2025-09-06 07:49:51 +0900 Functions: 75.0 % 8 6 2 6
Baseline: lcov-20250906-005545-baseline Branches: 55.3 % 150 83 67 83
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 80.0 % 5 4 1 4
(360..) days: 69.6 % 240 167 73 167
Function coverage date bins:
(360..) days: 75.0 % 8 6 2 6
Branch coverage date bins:
(30,360] days: 0.0 % 4 0 4
(360..) days: 56.8 % 146 83 63 83

 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-2025, 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
 3438 teodor@sigaev.ru           36                 :CBC         504 : compareWordEntryPos(const void *a, const void *b)
                                 37                 :                : {
 6505 bruce@momjian.us           38                 :            504 :     int         apos = WEP_GETPOS(*(const WordEntryPos *) a);
                                 39                 :            504 :     int         bpos = WEP_GETPOS(*(const WordEntryPos *) b);
                                 40                 :                : 
  568 nathan@postgresql.or       41                 :            504 :     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
 6505 bruce@momjian.us           52                 :           4803 : uniquePos(WordEntryPos *a, int l)
                                 53                 :                : {
                                 54                 :                :     WordEntryPos *ptr,
                                 55                 :                :                *res;
                                 56                 :                : 
 6574 teodor@sigaev.ru           57         [ +  + ]:           4803 :     if (l <= 1)
 6591 tgl@sss.pgh.pa.us          58                 :           4536 :         return l;
                                 59                 :                : 
  942 peter@eisentraut.org       60                 :            267 :     qsort(a, l, sizeof(WordEntryPos), compareWordEntryPos);
                                 61                 :                : 
 6528 tgl@sss.pgh.pa.us          62                 :            267 :     res = a;
 6591                            63                 :            267 :     ptr = a + 1;
                                 64         [ +  + ]:            726 :     while (ptr - a < l)
                                 65                 :                :     {
                                 66         [ +  + ]:            459 :         if (WEP_GETPOS(*ptr) != WEP_GETPOS(*res))
                                 67                 :                :         {
                                 68                 :            447 :             res++;
                                 69                 :            447 :             *res = *ptr;
 6528                            70         [ +  - ]:            447 :             if (res - a >= MAXNUMPOS - 1 ||
                                 71         [ +  - ]:            447 :                 WEP_GETPOS(*res) == MAXENTRYPOS - 1)
                                 72                 :                :                 break;
                                 73                 :                :         }
 6591                            74         [ +  + ]:             12 :         else if (WEP_GETWEIGHT(*ptr) > WEP_GETWEIGHT(*res))
                                 75                 :              3 :             WEP_SETWEIGHT(*res, WEP_GETWEIGHT(*ptr));
                                 76                 :            459 :         ptr++;
                                 77                 :                :     }
                                 78                 :                : 
                                 79                 :            267 :     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
 6574 teodor@sigaev.ru           87                 :         536253 : compareentry(const void *va, const void *vb, void *arg)
                                 88                 :                : {
  157 tgl@sss.pgh.pa.us          89                 :         536253 :     const WordEntry *a = (const WordEntry *) va;
                                 90                 :         536253 :     const WordEntry *b = (const WordEntry *) vb;
 6591                            91                 :         536253 :     char       *BufferStr = (char *) arg;
                                 92                 :                : 
  157                            93                 :        1072506 :     return tsCompareString(&BufferStr[a->pos], a->len,
                                 94                 :         536253 :                            &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
 6505 bruce@momjian.us          103                 :           1853 : uniqueentry(WordEntryIN *a, int l, char *buf, int *outbuflen)
                                104                 :                : {
                                105                 :                :     int         buflen;
                                106                 :                :     WordEntryIN *ptr,
                                107                 :                :                *res;
                                108                 :                : 
 6574 teodor@sigaev.ru          109         [ -  + ]:           1853 :     Assert(l >= 1);
                                110                 :                : 
 6528 tgl@sss.pgh.pa.us         111         [ +  + ]:           1853 :     if (l > 1)
  942 peter@eisentraut.org      112                 :           1802 :         qsort_arg(a, l, sizeof(WordEntryIN), compareentry, buf);
                                113                 :                : 
 6528 tgl@sss.pgh.pa.us         114                 :           1853 :     buflen = 0;
 6574 teodor@sigaev.ru          115                 :           1853 :     res = a;
 6591 tgl@sss.pgh.pa.us         116                 :           1853 :     ptr = a + 1;
                                117         [ +  + ]:          90414 :     while (ptr - a < l)
                                118                 :                :     {
                                119         [ +  + ]:          88561 :         if (!(ptr->entry.len == res->entry.len &&
 6528                           120                 :          88027 :               strncmp(&buf[ptr->entry.pos], &buf[res->entry.pos],
                                121         [ +  + ]:          88027 :                       res->entry.len) == 0))
                                122                 :                :         {
                                123                 :                :             /* done accumulating data into *res, count space needed */
                                124                 :          85798 :             buflen += res->entry.len;
 6591                           125         [ +  + ]:          85798 :             if (res->entry.haspos)
                                126                 :                :             {
 6574 teodor@sigaev.ru          127                 :           4497 :                 res->poslen = uniquePos(res->pos, res->poslen);
 6528 tgl@sss.pgh.pa.us         128                 :           4497 :                 buflen = SHORTALIGN(buflen);
                                129                 :           4497 :                 buflen += res->poslen * sizeof(WordEntryPos) + sizeof(uint16);
                                130                 :                :             }
 6591                           131                 :          85798 :             res++;
 4201 heikki.linnakangas@i      132         [ +  + ]:          85798 :             if (res != ptr)
                                133                 :          44286 :                 memcpy(res, ptr, sizeof(WordEntryIN));
                                134                 :                :         }
 6591 tgl@sss.pgh.pa.us         135         [ +  + ]:           2763 :         else if (ptr->entry.haspos)
                                136                 :                :         {
                                137         [ +  + ]:            159 :             if (res->entry.haspos)
                                138                 :                :             {
                                139                 :                :                 /* append ptr's positions to res's positions */
 6505 bruce@momjian.us          140                 :            156 :                 int         newlen = ptr->poslen + res->poslen;
                                141                 :                : 
 6528 tgl@sss.pgh.pa.us         142                 :            156 :                 res->pos = (WordEntryPos *)
                                143                 :            156 :                     repalloc(res->pos, newlen * sizeof(WordEntryPos));
                                144                 :            156 :                 memcpy(&res->pos[res->poslen], ptr->pos,
                                145                 :            156 :                        ptr->poslen * sizeof(WordEntryPos));
 6574 teodor@sigaev.ru          146                 :            156 :                 res->poslen = newlen;
 6591 tgl@sss.pgh.pa.us         147                 :            156 :                 pfree(ptr->pos);
                                148                 :                :             }
                                149                 :                :             else
                                150                 :                :             {
                                151                 :                :                 /* just give ptr's positions to pos */
                                152                 :              3 :                 res->entry.haspos = 1;
                                153                 :              3 :                 res->pos = ptr->pos;
 6528                           154                 :              3 :                 res->poslen = ptr->poslen;
                                155                 :                :             }
                                156                 :                :         }
 6591                           157                 :          88561 :         ptr++;
                                158                 :                :     }
                                159                 :                : 
                                160                 :                :     /* count space needed for last item */
 6528                           161                 :           1853 :     buflen += res->entry.len;
 6591                           162         [ +  + ]:           1853 :     if (res->entry.haspos)
                                163                 :                :     {
 6574 teodor@sigaev.ru          164                 :            306 :         res->poslen = uniquePos(res->pos, res->poslen);
 6528 tgl@sss.pgh.pa.us         165                 :            306 :         buflen = SHORTALIGN(buflen);
                                166                 :            306 :         buflen += res->poslen * sizeof(WordEntryPos) + sizeof(uint16);
                                167                 :                :     }
                                168                 :                : 
                                169                 :           1853 :     *outbuflen = buflen;
 6591                           170                 :           1853 :     return res + 1 - a;
                                171                 :                : }
                                172                 :                : 
                                173                 :                : 
                                174                 :                : Datum
                                175                 :           1886 : tsvectorin(PG_FUNCTION_ARGS)
                                176                 :                : {
                                177                 :           1886 :     char       *buf = PG_GETARG_CSTRING(0);
  984                           178                 :           1886 :     Node       *escontext = fcinfo->context;
                                179                 :                :     TSVectorParseState state;
                                180                 :                :     WordEntryIN *arr;
                                181                 :                :     int         totallen;
                                182                 :                :     int         arrlen;         /* allocated size of arr */
                                183                 :                :     WordEntry  *inarr;
 6574 teodor@sigaev.ru          184                 :           1886 :     int         len = 0;
                                185                 :                :     TSVector    in;
                                186                 :                :     int         i;
                                187                 :                :     char       *token;
                                188                 :                :     int         toklen;
                                189                 :                :     WordEntryPos *pos;
                                190                 :                :     int         poslen;
                                191                 :                :     char       *strbuf;
                                192                 :                :     int         stroff;
                                193                 :                : 
                                194                 :                :     /*
                                195                 :                :      * Tokens are appended to tmpbuf, cur is a pointer to the end of used
                                196                 :                :      * space in tmpbuf.
                                197                 :                :      */
                                198                 :                :     char       *tmpbuf;
                                199                 :                :     char       *cur;
 6505 bruce@momjian.us          200                 :           1886 :     int         buflen = 256;   /* allocated size of tmpbuf */
                                201                 :                : 
  984 tgl@sss.pgh.pa.us         202                 :           1886 :     state = init_tsvector_parser(buf, 0, escontext);
                                203                 :                : 
 6574 teodor@sigaev.ru          204                 :           1886 :     arrlen = 64;
                                205                 :           1886 :     arr = (WordEntryIN *) palloc(sizeof(WordEntryIN) * arrlen);
 6591 tgl@sss.pgh.pa.us         206                 :           1886 :     cur = tmpbuf = (char *) palloc(buflen);
                                207                 :                : 
 6574 teodor@sigaev.ru          208         [ +  + ]:          92300 :     while (gettoken_tsvector(state, &token, &toklen, &pos, &poslen, NULL))
                                209                 :                :     {
                                210         [ -  + ]:          90414 :         if (toklen >= MAXSTRLEN)
  984 tgl@sss.pgh.pa.us         211         [ #  # ]:UBC           0 :             ereturn(escontext, (Datum) 0,
                                212                 :                :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                213                 :                :                      errmsg("word is too long (%ld bytes, max %ld bytes)",
                                214                 :                :                             (long) toklen,
                                215                 :                :                             (long) (MAXSTRLEN - 1))));
                                216                 :                : 
 6591 tgl@sss.pgh.pa.us         217         [ -  + ]:CBC       90414 :         if (cur - tmpbuf > MAXSTRPOS)
  984 tgl@sss.pgh.pa.us         218         [ #  # ]:UBC           0 :             ereturn(escontext, (Datum) 0,
                                219                 :                :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                220                 :                :                      errmsg("string is too long for tsvector (%ld bytes, max %ld bytes)",
                                221                 :                :                             (long) (cur - tmpbuf), (long) MAXSTRPOS)));
                                222                 :                : 
                                223                 :                :         /*
                                224                 :                :          * Enlarge buffers if needed
                                225                 :                :          */
 6574 teodor@sigaev.ru          226         [ +  + ]:CBC       90414 :         if (len >= arrlen)
                                227                 :                :         {
                                228                 :            657 :             arrlen *= 2;
                                229                 :                :             arr = (WordEntryIN *)
  942 peter@eisentraut.org      230                 :            657 :                 repalloc(arr, sizeof(WordEntryIN) * arrlen);
                                231                 :                :         }
 6574 teodor@sigaev.ru          232         [ -  + ]:          90414 :         while ((cur - tmpbuf) + toklen >= buflen)
                                233                 :                :         {
 6505 bruce@momjian.us          234                 :UBC           0 :             int         dist = cur - tmpbuf;
                                235                 :                : 
 6574 teodor@sigaev.ru          236                 :              0 :             buflen *= 2;
  942 peter@eisentraut.org      237                 :              0 :             tmpbuf = (char *) repalloc(tmpbuf, buflen);
 6574 teodor@sigaev.ru          238                 :              0 :             cur = tmpbuf + dist;
                                239                 :                :         }
 6574 teodor@sigaev.ru          240                 :CBC       90414 :         arr[len].entry.len = toklen;
 6591 tgl@sss.pgh.pa.us         241                 :          90414 :         arr[len].entry.pos = cur - tmpbuf;
  942 peter@eisentraut.org      242                 :          90414 :         memcpy(cur, token, toklen);
 6574 teodor@sigaev.ru          243                 :          90414 :         cur += toklen;
                                244                 :                : 
                                245         [ +  + ]:          90414 :         if (poslen != 0)
                                246                 :                :         {
 6591 tgl@sss.pgh.pa.us         247                 :           4959 :             arr[len].entry.haspos = 1;
 6574 teodor@sigaev.ru          248                 :           4959 :             arr[len].pos = pos;
                                249                 :           4959 :             arr[len].poslen = poslen;
                                250                 :                :         }
                                251                 :                :         else
                                252                 :                :         {
 6591 tgl@sss.pgh.pa.us         253                 :          85455 :             arr[len].entry.haspos = 0;
 6528                           254                 :          85455 :             arr[len].pos = NULL;
                                255                 :          85455 :             arr[len].poslen = 0;
                                256                 :                :         }
 6591                           257                 :          90414 :         len++;
                                258                 :                :     }
                                259                 :                : 
 6574 teodor@sigaev.ru          260                 :           1883 :     close_tsvector_parser(state);
                                261                 :                : 
                                262                 :                :     /* Did gettoken_tsvector fail? */
  984 tgl@sss.pgh.pa.us         263   [ +  +  +  -  :           1883 :     if (SOFT_ERROR_OCCURRED(escontext))
                                              +  + ]
                                264                 :              6 :         PG_RETURN_NULL();
                                265                 :                : 
 6591                           266         [ +  + ]:           1877 :     if (len > 0)
                                267                 :           1853 :         len = uniqueentry(arr, len, tmpbuf, &buflen);
                                268                 :                :     else
                                269                 :             24 :         buflen = 0;
                                270                 :                : 
 6528                           271         [ -  + ]:           1877 :     if (buflen > MAXSTRPOS)
  984 tgl@sss.pgh.pa.us         272         [ #  # ]:UBC           0 :         ereturn(escontext, (Datum) 0,
                                273                 :                :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                274                 :                :                  errmsg("string is too long for tsvector (%d bytes, max %d bytes)", buflen, MAXSTRPOS)));
                                275                 :                : 
 6591 tgl@sss.pgh.pa.us         276                 :CBC        1877 :     totallen = CALCDATASIZE(len, buflen);
                                277                 :           1877 :     in = (TSVector) palloc0(totallen);
                                278                 :           1877 :     SET_VARSIZE(in, totallen);
                                279                 :           1877 :     in->size = len;
                                280                 :           1877 :     inarr = ARRPTR(in);
 6528                           281                 :           1877 :     strbuf = STRPTR(in);
                                282                 :           1877 :     stroff = 0;
 6591                           283         [ +  + ]:          89528 :     for (i = 0; i < len; i++)
                                284                 :                :     {
 6528                           285                 :          87651 :         memcpy(strbuf + stroff, &tmpbuf[arr[i].entry.pos], arr[i].entry.len);
                                286                 :          87651 :         arr[i].entry.pos = stroff;
                                287                 :          87651 :         stroff += arr[i].entry.len;
 6591                           288         [ +  + ]:          87651 :         if (arr[i].entry.haspos)
                                289                 :                :         {
                                290                 :                :             /* This should be unreachable because of MAXNUMPOS restrictions */
 6528                           291         [ -  + ]:           4803 :             if (arr[i].poslen > 0xFFFF)
 6574 teodor@sigaev.ru          292         [ #  # ]:UBC           0 :                 elog(ERROR, "positions array too long");
                                293                 :                : 
                                294                 :                :             /* Copy number of positions */
 6528 tgl@sss.pgh.pa.us         295                 :CBC        4803 :             stroff = SHORTALIGN(stroff);
                                296                 :           4803 :             *(uint16 *) (strbuf + stroff) = (uint16) arr[i].poslen;
                                297                 :           4803 :             stroff += sizeof(uint16);
                                298                 :                : 
                                299                 :                :             /* Copy positions */
                                300                 :           4803 :             memcpy(strbuf + stroff, arr[i].pos, arr[i].poslen * sizeof(WordEntryPos));
                                301                 :           4803 :             stroff += arr[i].poslen * sizeof(WordEntryPos);
                                302                 :                : 
 6591                           303                 :           4803 :             pfree(arr[i].pos);
                                304                 :                :         }
                                305                 :          87651 :         inarr[i] = arr[i].entry;
                                306                 :                :     }
                                307                 :                : 
 6528                           308         [ -  + ]:           1877 :     Assert((strbuf + stroff - (char *) in) == totallen);
                                309                 :                : 
 6591                           310                 :           1877 :     PG_RETURN_TSVECTOR(in);
                                311                 :                : }
                                312                 :                : 
                                313                 :                : Datum
                                314                 :           2378 : tsvectorout(PG_FUNCTION_ARGS)
                                315                 :                : {
                                316                 :           2378 :     TSVector    out = PG_GETARG_TSVECTOR(0);
                                317                 :                :     char       *outbuf;
                                318                 :                :     int32       i,
                                319                 :           2378 :                 lenbuf = 0,
                                320                 :                :                 pp;
                                321                 :           2378 :     WordEntry  *ptr = ARRPTR(out);
                                322                 :                :     char       *curbegin,
                                323                 :                :                *curin,
                                324                 :                :                *curout;
                                325                 :                : 
                                326                 :           2378 :     lenbuf = out->size * 2 /* '' */ + out->size - 1 /* space */ + 2 /* \0 */ ;
                                327         [ +  + ]:         118939 :     for (i = 0; i < out->size; i++)
                                328                 :                :     {
                                329                 :         116561 :         lenbuf += ptr[i].len * 2 * pg_database_encoding_max_length() /* for escape */ ;
                                330         [ +  + ]:         116561 :         if (ptr[i].haspos)
                                331         [ +  - ]:           6559 :             lenbuf += 1 /* : */ + 7 /* int2 + , + weight */ * POSDATALEN(out, &(ptr[i]));
                                332                 :                :     }
                                333                 :                : 
                                334                 :           2378 :     curout = outbuf = (char *) palloc(lenbuf);
                                335         [ +  + ]:         118939 :     for (i = 0; i < out->size; i++)
                                336                 :                :     {
                                337                 :         116561 :         curbegin = curin = STRPTR(out) + ptr->pos;
                                338         [ +  + ]:         116561 :         if (i != 0)
                                339                 :         114276 :             *curout++ = ' ';
                                340                 :         116561 :         *curout++ = '\'';
                                341         [ +  + ]:         353066 :         while (curin - curbegin < ptr->len)
                                342                 :                :         {
                                343                 :         236505 :             int         len = pg_mblen(curin);
                                344                 :                : 
                                345         [ +  + ]:         236505 :             if (t_iseq(curin, '\''))
                                346                 :             13 :                 *curout++ = '\'';
 6504 teodor@sigaev.ru          347         [ +  + ]:         236492 :             else if (t_iseq(curin, '\\'))
                                348                 :             45 :                 *curout++ = '\\';
                                349                 :                : 
 6591 tgl@sss.pgh.pa.us         350         [ +  + ]:         473010 :             while (len--)
                                351                 :         236505 :                 *curout++ = *curin++;
                                352                 :                :         }
                                353                 :                : 
                                354                 :         116561 :         *curout++ = '\'';
                                355   [ +  +  +  + ]:         116561 :         if ((pp = POSDATALEN(out, ptr)) != 0)
                                356                 :                :         {
                                357                 :                :             WordEntryPos *wptr;
                                358                 :                : 
                                359                 :           6559 :             *curout++ = ':';
                                360                 :           6559 :             wptr = POSDATAPTR(out, ptr);
                                361         [ +  + ]:          13584 :             while (pp)
                                362                 :                :             {
                                363                 :           7025 :                 curout += sprintf(curout, "%d", WEP_GETPOS(*wptr));
                                364   [ +  +  +  + ]:           7025 :                 switch (WEP_GETWEIGHT(*wptr))
                                365                 :                :                 {
                                366                 :             58 :                     case 3:
                                367                 :             58 :                         *curout++ = 'A';
                                368                 :             58 :                         break;
                                369                 :             34 :                     case 2:
                                370                 :             34 :                         *curout++ = 'B';
                                371                 :             34 :                         break;
                                372                 :            115 :                     case 1:
                                373                 :            115 :                         *curout++ = 'C';
                                374                 :            115 :                         break;
                                375                 :           6818 :                     case 0:
                                376                 :                :                     default:
                                377                 :           6818 :                         break;
                                378                 :                :                 }
                                379                 :                : 
                                380         [ +  + ]:           7025 :                 if (pp > 1)
                                381                 :            466 :                     *curout++ = ',';
                                382                 :           7025 :                 pp--;
                                383                 :           7025 :                 wptr++;
                                384                 :                :             }
                                385                 :                :         }
                                386                 :         116561 :         ptr++;
                                387                 :                :     }
                                388                 :                : 
                                389                 :           2378 :     *curout = '\0';
                                390         [ +  + ]:           2378 :     PG_FREE_IF_COPY(out, 0);
                                391                 :           2378 :     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
 6591 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                 :                : 
 2887 andres@anarazel.de        417                 :              0 :     pq_sendint32(&buf, vec->size);
 6591 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                 :                :          */
 6574 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);
 2887 andres@anarazel.de        430                 :              0 :         pq_sendint16(&buf, npos);
                                431                 :                : 
 6505 bruce@momjian.us          432         [ #  # ]:              0 :         if (npos > 0)
                                433                 :                :         {
 6591 tgl@sss.pgh.pa.us         434                 :              0 :             WordEntryPos *wepptr = POSDATAPTR(vec, weptr);
                                435                 :                : 
 6574 teodor@sigaev.ru          436         [ #  # ]:              0 :             for (j = 0; j < npos; j++)
 2887 andres@anarazel.de        437                 :              0 :                 pq_sendint16(&buf, wepptr[j]);
                                438                 :                :         }
 6591 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 */
 5952 teodor@sigaev.ru          457                 :              0 :     bool        needSort = false;
                                458                 :                : 
 6574                           459                 :              0 :     nentries = pq_getmsgint(buf, sizeof(int32));
                                460   [ #  #  #  # ]:              0 :     if (nentries < 0 || nentries > (MaxAllocSize / sizeof(WordEntry)))
 6591 tgl@sss.pgh.pa.us         461         [ #  # ]:              0 :         elog(ERROR, "invalid size of tsvector");
                                462                 :                : 
 6574 teodor@sigaev.ru          463                 :              0 :     hdrlen = DATAHDRSIZE + sizeof(WordEntry) * nentries;
                                464                 :                : 
 6505 bruce@momjian.us          465                 :              0 :     len = hdrlen * 2;           /* times two to make room for lexemes */
 6591 tgl@sss.pgh.pa.us         466                 :              0 :     vec = (TSVector) palloc0(len);
 6574 teodor@sigaev.ru          467                 :              0 :     vec->size = nentries;
                                468                 :                : 
                                469                 :              0 :     datalen = 0;
                                470         [ #  # ]:              0 :     for (i = 0; i < nentries; i++)
                                471                 :                :     {
                                472                 :                :         const char *lexeme;
                                473                 :                :         uint16      npos;
                                474                 :                :         size_t      lex_len;
                                475                 :                : 
                                476                 :              0 :         lexeme = pq_getmsgstring(buf);
                                477                 :              0 :         npos = (uint16) pq_getmsgint(buf, sizeof(uint16));
                                478                 :                : 
                                479                 :                :         /* sanity checks */
                                480                 :                : 
                                481                 :              0 :         lex_len = strlen(lexeme);
 5952 meskes@postgresql.or      482         [ #  # ]:              0 :         if (lex_len > MAXSTRLEN)
 6492 tgl@sss.pgh.pa.us         483         [ #  # ]:              0 :             elog(ERROR, "invalid tsvector: lexeme too long");
                                484                 :                : 
 6574 teodor@sigaev.ru          485         [ #  # ]:              0 :         if (datalen > MAXSTRPOS)
 6492 tgl@sss.pgh.pa.us         486         [ #  # ]:              0 :             elog(ERROR, "invalid tsvector: maximum total lexeme length exceeded");
                                487                 :                : 
 6574 teodor@sigaev.ru          488         [ #  # ]:              0 :         if (npos > MAXNUMPOS)
 6492 tgl@sss.pgh.pa.us         489         [ #  # ]:              0 :             elog(ERROR, "unexpected number of tsvector positions");
                                490                 :                : 
                                491                 :                :         /*
                                492                 :                :          * Looks valid. Fill the WordEntry struct, and copy lexeme.
                                493                 :                :          *
                                494                 :                :          * But make sure the buffer is large enough first.
                                495                 :                :          */
 6574 teodor@sigaev.ru          496                 :              0 :         while (hdrlen + SHORTALIGN(datalen + lex_len) +
  706 tgl@sss.pgh.pa.us         497         [ #  # ]:              0 :                sizeof(uint16) + npos * sizeof(WordEntryPos) >= len)
                                498                 :                :         {
 6591                           499                 :              0 :             len *= 2;
                                500                 :              0 :             vec = (TSVector) repalloc(vec, len);
                                501                 :                :         }
                                502                 :                : 
 6574 teodor@sigaev.ru          503                 :              0 :         vec->entries[i].haspos = (npos > 0) ? 1 : 0;
                                504                 :              0 :         vec->entries[i].len = lex_len;
                                505                 :              0 :         vec->entries[i].pos = datalen;
                                506                 :                : 
                                507                 :              0 :         memcpy(STRPTR(vec) + datalen, lexeme, lex_len);
                                508                 :                : 
                                509                 :              0 :         datalen += lex_len;
                                510                 :                : 
  157 tgl@sss.pgh.pa.us         511   [ #  #  #  # ]:              0 :         if (i > 0 && compareentry(&vec->entries[i],
 6528                           512                 :              0 :                                   &vec->entries[i - 1],
                                513                 :              0 :                                   STRPTR(vec)) <= 0)
 5952 teodor@sigaev.ru          514                 :              0 :             needSort = true;
                                515                 :                : 
                                516                 :                :         /* Receive positions */
 6574                           517         [ #  # ]:              0 :         if (npos > 0)
                                518                 :                :         {
                                519                 :                :             uint16      j;
                                520                 :                :             WordEntryPos *wepptr;
                                521                 :                : 
                                522                 :                :             /*
                                523                 :                :              * Pad to 2-byte alignment if necessary. Though we used palloc0
                                524                 :                :              * for the initial allocation, subsequent repalloc'd memory areas
                                525                 :                :              * are not initialized to zero.
                                526                 :                :              */
                                527         [ #  # ]:              0 :             if (datalen != SHORTALIGN(datalen))
                                528                 :                :             {
                                529                 :              0 :                 *(STRPTR(vec) + datalen) = '\0';
                                530                 :              0 :                 datalen = SHORTALIGN(datalen);
                                531                 :                :             }
                                532                 :                : 
                                533                 :              0 :             memcpy(STRPTR(vec) + datalen, &npos, sizeof(uint16));
                                534                 :                : 
                                535                 :              0 :             wepptr = POSDATAPTR(vec, &vec->entries[i]);
 6591 tgl@sss.pgh.pa.us         536         [ #  # ]:              0 :             for (j = 0; j < npos; j++)
                                537                 :                :             {
 6574 teodor@sigaev.ru          538                 :              0 :                 wepptr[j] = (WordEntryPos) pq_getmsgint(buf, sizeof(WordEntryPos));
 6591 tgl@sss.pgh.pa.us         539   [ #  #  #  # ]:              0 :                 if (j > 0 && WEP_GETPOS(wepptr[j]) <= WEP_GETPOS(wepptr[j - 1]))
 6530                           540         [ #  # ]:              0 :                     elog(ERROR, "position information is misordered");
                                541                 :                :             }
                                542                 :                : 
  706                           543                 :              0 :             datalen += sizeof(uint16) + npos * sizeof(WordEntryPos);
                                544                 :                :         }
                                545                 :                :     }
                                546                 :                : 
 6574 teodor@sigaev.ru          547                 :              0 :     SET_VARSIZE(vec, hdrlen + datalen);
                                548                 :                : 
 5952                           549         [ #  # ]:              0 :     if (needSort)
  942 peter@eisentraut.org      550                 :              0 :         qsort_arg(ARRPTR(vec), vec->size, sizeof(WordEntry),
                                551                 :              0 :                   compareentry, STRPTR(vec));
                                552                 :                : 
 6591 tgl@sss.pgh.pa.us         553                 :              0 :     PG_RETURN_TSVECTOR(vec);
                                554                 :                : }
        

Generated by: LCOV version 2.4-beta