LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - tsvector.c (source / functions) Coverage Total Hit UIC UBC GIC GNC CBC DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 69.2 % 247 171 76 1 170 3
Current Date: 2024-04-14 14:21:10 Functions: 66.7 % 9 6 3 1 5
Baseline: 16@8cea358b128 Branches: 55.3 % 150 83 1 66 1 82
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 100.0 % 1 1 1
(180,240] days: 0.0 % 2 0 2
(240..) days: 69.7 % 244 170 74 170
Function coverage date bins:
(240..) days: 66.7 % 9 6 3 1 5
Branch coverage date bins:
(180,240] days: 0.0 % 2 0 2
(240..) days: 56.1 % 148 83 1 64 1 82

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

Generated by: LCOV version 2.1-beta2-3-g6141622