LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - tsquery_util.c (source / functions) Coverage Total Hit LBC UIC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 98.9 % 178 176 1 1 110 1 65 2 109 1
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 13 13 13 13
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 100.0 % 1 1 1
Legend: Lines: hit not hit (240..) days: 98.9 % 177 175 1 1 110 65 2 108
Function coverage date bins:
(240..) days: 50.0 % 26 13 13 13

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * tsquery_util.c
                                  4                 :  *    Utilities for tsquery datatype
                                  5                 :  *
                                  6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  7                 :  *
                                  8                 :  *
                                  9                 :  * IDENTIFICATION
                                 10                 :  *    src/backend/utils/adt/tsquery_util.c
                                 11                 :  *
                                 12                 :  *-------------------------------------------------------------------------
                                 13                 :  */
                                 14                 : 
                                 15                 : #include "postgres.h"
                                 16                 : 
                                 17                 : #include "miscadmin.h"
                                 18                 : #include "tsearch/ts_utils.h"
                                 19                 : #include "varatt.h"
                                 20                 : 
                                 21                 : /*
                                 22                 :  * Build QTNode tree for a tsquery given in QueryItem array format.
                                 23                 :  */
                                 24                 : QTNode *
 5624 bruce                      25 GIC        4455 : QT2QTN(QueryItem *in, char *operand)
 5710 tgl                        26 ECB             : {
 5710 tgl                        27 GIC        4455 :     QTNode     *node = (QTNode *) palloc0(sizeof(QTNode));
 5710 tgl                        28 ECB             : 
                                 29                 :     /* since this function recurses, it could be driven to stack overflow. */
 5693 teodor                     30 GIC        4455 :     check_stack_depth();
 5693 teodor                     31 ECB             : 
 5710 tgl                        32 GIC        4455 :     node->valnode = in;
 5710 tgl                        33 ECB             : 
 5693 teodor                     34 GIC        4455 :     if (in->type == QI_OPR)
 5710 tgl                        35 ECB             :     {
 5710 tgl                        36 GIC        1679 :         node->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
 5710 tgl                        37 CBC        1679 :         node->child[0] = QT2QTN(in + 1, operand);
                                 38            1679 :         node->sign = node->child[0]->sign;
 5015 peter_e                    39            1679 :         if (in->qoperator.oper == OP_NOT)
 5710 tgl                        40              21 :             node->nchild = 1;
 5710 tgl                        41 ECB             :         else
                                 42                 :         {
 5710 tgl                        43 GIC        1658 :             node->nchild = 2;
 5015 peter_e                    44 CBC        1658 :             node->child[1] = QT2QTN(in + in->qoperator.left, operand);
 5710 tgl                        45            1658 :             node->sign |= node->child[1]->sign;
 5710 tgl                        46 ECB             :         }
                                 47                 :     }
 5710 tgl                        48 GIC        2776 :     else if (operand)
 5710 tgl                        49 ECB             :     {
 5015 peter_e                    50 GIC        2776 :         node->word = operand + in->qoperand.distance;
 4632 tgl                        51 CBC        2776 :         node->sign = ((uint32) 1) << (((unsigned int) in->qoperand.valcrc) % 32);
 5710 tgl                        52 ECB             :     }
                                 53                 : 
 5710 tgl                        54 GIC        4455 :     return node;
 5710 tgl                        55 ECB             : }
                                 56                 : 
                                 57                 : /*
                                 58                 :  * Free a QTNode tree.
                                 59                 :  *
                                 60                 :  * Referenced "word" and "valnode" items are freed if marked as transient
                                 61                 :  * by flags.
                                 62                 :  */
                                 63                 : void
 5624 bruce                      64 GIC        4920 : QTNFree(QTNode *in)
 5710 tgl                        65 ECB             : {
 5710 tgl                        66 GIC        4920 :     if (!in)
 5710 tgl                        67 CBC           6 :         return;
 5710 tgl                        68 ECB             : 
                                 69                 :     /* since this function recurses, it could be driven to stack overflow. */
 5693 teodor                     70 GIC        4914 :     check_stack_depth();
 5693 teodor                     71 ECB             : 
 5693 teodor                     72 GIC        4914 :     if (in->valnode->type == QI_VAL && in->word && (in->flags & QTN_WORDFREE) != 0)
 5710 tgl                        73 CBC         306 :         pfree(in->word);
 5710 tgl                        74 ECB             : 
 2352 tgl                        75 GIC        4914 :     if (in->valnode->type == QI_OPR)
 5710 tgl                        76 ECB             :     {
                                 77                 :         int         i;
                                 78                 : 
 2352 tgl                        79 GIC        5529 :         for (i = 0; i < in->nchild; i++)
 2352 tgl                        80 CBC        3697 :             QTNFree(in->child[i]);
 5710 tgl                        81 ECB             :     }
 2352 tgl                        82 GIC        4914 :     if (in->child)
 2352 tgl                        83 CBC        1832 :         pfree(in->child);
 2352 tgl                        84 ECB             : 
 2352 tgl                        85 GIC        4914 :     if (in->flags & QTN_NEEDFREE)
 2352 tgl                        86 CBC         576 :         pfree(in->valnode);
 5710 tgl                        87 ECB             : 
 5710 tgl                        88 GIC        4914 :     pfree(in);
 5710 tgl                        89 ECB             : }
                                 90                 : 
                                 91                 : /*
                                 92                 :  * Sort comparator for QTNodes.
                                 93                 :  *
                                 94                 :  * The sort order is somewhat arbitrary.
                                 95                 :  */
                                 96                 : int
 5624 bruce                      97 GIC        2007 : QTNodeCompare(QTNode *an, QTNode *bn)
 5710 tgl                        98 ECB             : {
                                 99                 :     /* since this function recurses, it could be driven to stack overflow. */
 5693 teodor                    100 GIC        2007 :     check_stack_depth();
 5693 teodor                    101 ECB             : 
 5710 tgl                       102 GIC        2007 :     if (an->valnode->type != bn->valnode->type)
 5710 tgl                       103 CBC         591 :         return (an->valnode->type > bn->valnode->type) ? -1 : 1;
 5624 bruce                     104 ECB             : 
 5693 teodor                    105 GIC        1416 :     if (an->valnode->type == QI_OPR)
 5710 tgl                       106 ECB             :     {
 5015 peter_e                   107 GIC         277 :         QueryOperator *ao = &an->valnode->qoperator;
 5015 peter_e                   108 CBC         277 :         QueryOperator *bo = &bn->valnode->qoperator;
 5693 teodor                    109 ECB             : 
 5624 bruce                     110 GIC         277 :         if (ao->oper != bo->oper)
 5693 teodor                    111 CBC          24 :             return (ao->oper > bo->oper) ? -1 : 1;
 5693 teodor                    112 ECB             : 
 5693 teodor                    113 GIC         253 :         if (an->nchild != bn->nchild)
 5693 teodor                    114 CBC          54 :             return (an->nchild > bn->nchild) ? -1 : 1;
 5693 teodor                    115 ECB             : 
                                116                 :         {
                                117                 :             int         i,
                                118                 :                         res;
                                119                 : 
 5693 teodor                    120 GIC         339 :             for (i = 0; i < an->nchild; i++)
 5693 teodor                    121 CBC         269 :                 if ((res = QTNodeCompare(an->child[i], bn->child[i])) != 0)
                                122             129 :                     return res;
 5693 teodor                    123 ECB             :         }
                                124                 : 
 2558 teodor                    125 GIC          70 :         if (ao->oper == OP_PHRASE && ao->distance != bo->distance)
 2558 teodor                    126 CBC           3 :             return (ao->distance > bo->distance) ? -1 : 1;
 2558 teodor                    127 ECB             : 
 5693 teodor                    128 GIC          67 :         return 0;
 5710 tgl                       129 ECB             :     }
 4632 tgl                       130 GIC        1139 :     else if (an->valnode->type == QI_VAL)
 5710 tgl                       131 ECB             :     {
 5015 peter_e                   132 GIC        1139 :         QueryOperand *ao = &an->valnode->qoperand;
 5015 peter_e                   133 CBC        1139 :         QueryOperand *bo = &bn->valnode->qoperand;
 5710 tgl                       134 ECB             : 
 5693 teodor                    135 GIC        1139 :         if (ao->valcrc != bo->valcrc)
 5693 teodor                    136 ECB             :         {
 5693 teodor                    137 GIC         876 :             return (ao->valcrc > bo->valcrc) ? -1 : 1;
 5693 teodor                    138 ECB             :         }
                                139                 : 
 5050 bruce                     140 GIC         263 :         return tsCompareString(an->word, ao->length, bn->word, bo->length, false);
 5693 teodor                    141 ECB             :     }
                                142                 :     else
                                143                 :     {
 4632 tgl                       144 UIC           0 :         elog(ERROR, "unrecognized QueryItem type: %d", an->valnode->type);
 4632 tgl                       145 EUB             :         return 0;               /* keep compiler quiet */
                                146                 :     }
                                147                 : }
                                148                 : 
                                149                 : /*
                                150                 :  * qsort comparator for QTNode pointers.
                                151                 :  */
                                152                 : static int
 5710 tgl                       153 GIC        1518 : cmpQTN(const void *a, const void *b)
 5710 tgl                       154 ECB             : {
 3955 bruce                     155 GIC        1518 :     return QTNodeCompare(*(QTNode *const *) a, *(QTNode *const *) b);
 5710 tgl                       156 ECB             : }
                                157                 : 
                                158                 : /*
                                159                 :  * Canonicalize a QTNode tree by sorting the children of AND/OR nodes
                                160                 :  * into an arbitrary but well-defined order.
                                161                 :  */
                                162                 : void
 5624 bruce                     163 GIC        4542 : QTNSort(QTNode *in)
 5710 tgl                       164 ECB             : {
                                165                 :     int         i;
                                166                 : 
                                167                 :     /* since this function recurses, it could be driven to stack overflow. */
 5693 teodor                    168 GIC        4542 :     check_stack_depth();
 5693 teodor                    169 ECB             : 
 5693 teodor                    170 GIC        4542 :     if (in->valnode->type != QI_OPR)
 5710 tgl                       171 CBC        2958 :         return;
 5710 tgl                       172 ECB             : 
 5710 tgl                       173 GIC        5199 :     for (i = 0; i < in->nchild; i++)
 5710 tgl                       174 CBC        3615 :         QTNSort(in->child[i]);
 2558 teodor                    175            1584 :     if (in->nchild > 1 && in->valnode->qoperator.oper != OP_PHRASE)
   61 peter                     176 GNC         924 :         qsort(in->child, in->nchild, sizeof(QTNode *), cmpQTN);
 5710 tgl                       177 ECB             : }
                                178                 : 
                                179                 : /*
                                180                 :  * Are two QTNode trees equal according to QTNodeCompare?
                                181                 :  */
                                182                 : bool
 5624 bruce                     183 GIC          99 : QTNEq(QTNode *a, QTNode *b)
 5710 tgl                       184 ECB             : {
 5710 tgl                       185 GIC          99 :     uint32      sign = a->sign & b->sign;
 5710 tgl                       186 ECB             : 
 5710 tgl                       187 GIC          99 :     if (!(sign == a->sign && sign == b->sign))
 2352 tgl                       188 CBC           3 :         return false;
 5710 tgl                       189 ECB             : 
  578 michael                   190 GIC          96 :     return (QTNodeCompare(a, b) == 0);
 5710 tgl                       191 ECB             : }
                                192                 : 
                                193                 : /*
                                194                 :  * Remove unnecessary intermediate nodes. For example:
                                195                 :  *
                                196                 :  *  OR          OR
                                197                 :  * a  OR    -> a b c
                                198                 :  *   b  c
                                199                 :  */
                                200                 : void
 5624 bruce                     201 GIC        4374 : QTNTernary(QTNode *in)
 5710 tgl                       202 ECB             : {
                                203                 :     int         i;
                                204                 : 
                                205                 :     /* since this function recurses, it could be driven to stack overflow. */
 5693 teodor                    206 GIC        4374 :     check_stack_depth();
 5693 teodor                    207 ECB             : 
 5693 teodor                    208 GIC        4374 :     if (in->valnode->type != QI_OPR)
 5710 tgl                       209 CBC        2769 :         return;
 5710 tgl                       210 ECB             : 
 5710 tgl                       211 GIC        5073 :     for (i = 0; i < in->nchild; i++)
 5710 tgl                       212 CBC        3468 :         QTNTernary(in->child[i]);
 5710 tgl                       213 ECB             : 
                                214                 :     /* Only AND and OR are associative, so don't flatten other node types */
 2352 tgl                       215 GIC        1605 :     if (in->valnode->qoperator.oper != OP_AND &&
 2352 tgl                       216 CBC        1008 :         in->valnode->qoperator.oper != OP_OR)
                                217             624 :         return;
 2352 tgl                       218 ECB             : 
 5710 tgl                       219 GIC        3213 :     for (i = 0; i < in->nchild; i++)
 5710 tgl                       220 ECB             :     {
 5693 teodor                    221 GIC        2232 :         QTNode     *cc = in->child[i];
 5693 teodor                    222 ECB             : 
 2558 teodor                    223 GIC        2232 :         if (cc->valnode->type == QI_OPR &&
 2352 tgl                       224 CBC         777 :             in->valnode->qoperator.oper == cc->valnode->qoperator.oper)
 5710 tgl                       225 ECB             :         {
 5710 tgl                       226 GIC         165 :             int         oldnchild = in->nchild;
 5710 tgl                       227 ECB             : 
 5710 tgl                       228 GIC         165 :             in->nchild += cc->nchild - 1;
 5710 tgl                       229 CBC         165 :             in->child = (QTNode **) repalloc(in->child, in->nchild * sizeof(QTNode *));
 5710 tgl                       230 ECB             : 
 5710 tgl                       231 GIC         165 :             if (i + 1 != oldnchild)
 5710 tgl                       232 CBC          18 :                 memmove(in->child + i + cc->nchild, in->child + i + 1,
                                233              18 :                         (oldnchild - i - 1) * sizeof(QTNode *));
 5710 tgl                       234 ECB             : 
 5710 tgl                       235 GIC         165 :             memcpy(in->child + i, cc->child, cc->nchild * sizeof(QTNode *));
 5710 tgl                       236 CBC         165 :             i += cc->nchild - 1;
 5710 tgl                       237 ECB             : 
 5624 bruce                     238 GIC         165 :             if (cc->flags & QTN_NEEDFREE)
 5693 teodor                    239 CBC          54 :                 pfree(cc->valnode);
 5710 tgl                       240             165 :             pfree(cc);
 5710 tgl                       241 ECB             :         }
                                242                 :     }
                                243                 : }
                                244                 : 
                                245                 : /*
                                246                 :  * Convert a tree to binary tree by inserting intermediate nodes.
                                247                 :  * (Opposite of QTNTernary)
                                248                 :  */
                                249                 : void
 5624 bruce                     250 GIC         591 : QTNBinary(QTNode *in)
 5710 tgl                       251 ECB             : {
                                252                 :     int         i;
                                253                 : 
                                254                 :     /* since this function recurses, it could be driven to stack overflow. */
 5693 teodor                    255 GIC         591 :     check_stack_depth();
 5693 teodor                    256 ECB             : 
 5693 teodor                    257 GIC         591 :     if (in->valnode->type != QI_OPR)
 5710 tgl                       258 CBC         363 :         return;
 5710 tgl                       259 ECB             : 
 5710 tgl                       260 GIC         732 :     for (i = 0; i < in->nchild; i++)
 5710 tgl                       261 CBC         504 :         QTNBinary(in->child[i]);
 5710 tgl                       262 ECB             : 
 5710 tgl                       263 GIC         288 :     while (in->nchild > 2)
 5710 tgl                       264 ECB             :     {
 5710 tgl                       265 GIC          60 :         QTNode     *nn = (QTNode *) palloc0(sizeof(QTNode));
 5710 tgl                       266 ECB             : 
 5710 tgl                       267 GIC          60 :         nn->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
 5710 tgl                       268 CBC          60 :         nn->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
 5710 tgl                       269 ECB             : 
 5710 tgl                       270 GIC          60 :         nn->nchild = 2;
 5710 tgl                       271 CBC          60 :         nn->flags = QTN_NEEDFREE;
 5710 tgl                       272 ECB             : 
 5710 tgl                       273 GIC          60 :         nn->child[0] = in->child[0];
 5710 tgl                       274 CBC          60 :         nn->child[1] = in->child[1];
                                275              60 :         nn->sign = nn->child[0]->sign | nn->child[1]->sign;
 5710 tgl                       276 ECB             : 
 5710 tgl                       277 GIC          60 :         nn->valnode->type = in->valnode->type;
 5015 peter_e                   278 CBC          60 :         nn->valnode->qoperator.oper = in->valnode->qoperator.oper;
 5710 tgl                       279 ECB             : 
 5710 tgl                       280 GIC          60 :         in->child[0] = nn;
 5710 tgl                       281 CBC          60 :         in->child[1] = in->child[in->nchild - 1];
                                282              60 :         in->nchild--;
 5710 tgl                       283 ECB             :     }
                                284                 : }
                                285                 : 
                                286                 : /*
                                287                 :  * Count the total length of operand strings in tree (including '\0'-
                                288                 :  * terminators) and the total number of nodes.
                                289                 :  * Caller must initialize *sumlen and *nnode to zeroes.
                                290                 :  */
                                291                 : static void
 5624 bruce                     292 GIC         993 : cntsize(QTNode *in, int *sumlen, int *nnode)
 5710 tgl                       293 ECB             : {
                                294                 :     /* since this function recurses, it could be driven to stack overflow. */
 5693 teodor                    295 GIC         993 :     check_stack_depth();
 5693 teodor                    296 ECB             : 
 5710 tgl                       297 GIC         993 :     *nnode += 1;
 5693 teodor                    298 CBC         993 :     if (in->valnode->type == QI_OPR)
 5710 tgl                       299 ECB             :     {
                                300                 :         int         i;
                                301                 : 
 5710 tgl                       302 GIC        1281 :         for (i = 0; i < in->nchild; i++)
 5710 tgl                       303 CBC         846 :             cntsize(in->child[i], sumlen, nnode);
 5710 tgl                       304 ECB             :     }
                                305                 :     else
                                306                 :     {
 5015 peter_e                   307 GIC         558 :         *sumlen += in->valnode->qoperand.length + 1;
 5710 tgl                       308 ECB             :     }
 5710 tgl                       309 GIC         993 : }
 5710 tgl                       310 ECB             : 
                                311                 : typedef struct
                                312                 : {
                                313                 :     QueryItem  *curitem;
                                314                 :     char       *operand;
                                315                 :     char       *curoperand;
                                316                 : } QTN2QTState;
                                317                 : 
                                318                 : /*
                                319                 :  * Recursively convert a QTNode tree into flat tsquery format.
                                320                 :  * Caller must have allocated arrays of the correct size.
                                321                 :  */
                                322                 : static void
 5624 bruce                     323 GIC         993 : fillQT(QTN2QTState *state, QTNode *in)
 5710 tgl                       324 ECB             : {
                                325                 :     /* since this function recurses, it could be driven to stack overflow. */
 5693 teodor                    326 GIC         993 :     check_stack_depth();
 5693 teodor                    327 ECB             : 
 5693 teodor                    328 GIC         993 :     if (in->valnode->type == QI_VAL)
 5710 tgl                       329 ECB             :     {
 5693 teodor                    330 GIC         558 :         memcpy(state->curitem, in->valnode, sizeof(QueryOperand));
 5693 teodor                    331 ECB             : 
 5015 peter_e                   332 GIC         558 :         memcpy(state->curoperand, in->word, in->valnode->qoperand.length);
 5015 peter_e                   333 CBC         558 :         state->curitem->qoperand.distance = state->curoperand - state->operand;
                                334             558 :         state->curoperand[in->valnode->qoperand.length] = '\0';
                                335             558 :         state->curoperand += in->valnode->qoperand.length + 1;
 5710 tgl                       336             558 :         state->curitem++;
 5710 tgl                       337 ECB             :     }
                                338                 :     else
                                339                 :     {
 5710 tgl                       340 GIC         435 :         QueryItem  *curitem = state->curitem;
 5710 tgl                       341 ECB             : 
 5693 teodor                    342 GIC         435 :         Assert(in->valnode->type == QI_OPR);
 5693 teodor                    343 ECB             : 
 5693 teodor                    344 GIC         435 :         memcpy(state->curitem, in->valnode, sizeof(QueryOperator));
 5693 teodor                    345 ECB             : 
 5710 tgl                       346 GIC         435 :         Assert(in->nchild <= 2);
 5710 tgl                       347 CBC         435 :         state->curitem++;
 5710 tgl                       348 ECB             : 
 5710 tgl                       349 GIC         435 :         fillQT(state, in->child[0]);
 5710 tgl                       350 ECB             : 
 5710 tgl                       351 GIC         435 :         if (in->nchild == 2)
 5710 tgl                       352 ECB             :         {
 5015 peter_e                   353 GIC         411 :             curitem->qoperator.left = state->curitem - curitem;
 5710 tgl                       354 CBC         411 :             fillQT(state, in->child[1]);
 5710 tgl                       355 ECB             :         }
                                356                 :     }
 5710 tgl                       357 GIC         993 : }
 5710 tgl                       358 ECB             : 
                                359                 : /*
                                360                 :  * Build flat tsquery from a QTNode tree.
                                361                 :  */
                                362                 : TSQuery
 5624 bruce                     363 GIC         147 : QTN2QT(QTNode *in)
 5710 tgl                       364 ECB             : {
                                365                 :     TSQuery     out;
                                366                 :     int         len;
 5710 tgl                       367 GIC         147 :     int         sumlen = 0,
 5710 tgl                       368 CBC         147 :                 nnode = 0;
 5710 tgl                       369 ECB             :     QTN2QTState state;
                                370                 : 
 5710 tgl                       371 GIC         147 :     cntsize(in, &sumlen, &nnode);
 3338 noah                      372 ECB             : 
 3338 noah                      373 GIC         147 :     if (TSQUERY_TOO_BIG(nnode, sumlen))
 3338 noah                      374 LBC           0 :         ereport(ERROR,
 3338 noah                      375 EUB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                376                 :                  errmsg("tsquery is too large")));
 5710 tgl                       377 GIC         147 :     len = COMPUTESIZE(nnode, sumlen);
 5710 tgl                       378 ECB             : 
 4338 tgl                       379 GIC         147 :     out = (TSQuery) palloc0(len);
 5710 tgl                       380 CBC         147 :     SET_VARSIZE(out, len);
                                381             147 :     out->size = nnode;
 5710 tgl                       382 ECB             : 
 5710 tgl                       383 GIC         147 :     state.curitem = GETQUERY(out);
 5710 tgl                       384 CBC         147 :     state.operand = state.curoperand = GETOPERAND(out);
 5710 tgl                       385 ECB             : 
 5710 tgl                       386 GIC         147 :     fillQT(&state, in);
 5710 tgl                       387 CBC         147 :     return out;
 5710 tgl                       388 ECB             : }
                                389                 : 
                                390                 : /*
                                391                 :  * Copy a QTNode tree.
                                392                 :  *
                                393                 :  * Modifiable copies of the words and valnodes are made, too.
                                394                 :  */
                                395                 : QTNode *
 5624 bruce                     396 GIC         510 : QTNCopy(QTNode *in)
 5710 tgl                       397 ECB             : {
                                398                 :     QTNode     *out;
                                399                 : 
                                400                 :     /* since this function recurses, it could be driven to stack overflow. */
 5693 teodor                    401 GIC         510 :     check_stack_depth();
 5693 teodor                    402 ECB             : 
 5693 teodor                    403 GIC         510 :     out = (QTNode *) palloc(sizeof(QTNode));
 5710 tgl                       404 ECB             : 
 5710 tgl                       405 GIC         510 :     *out = *in;
 5710 tgl                       406 CBC         510 :     out->valnode = (QueryItem *) palloc(sizeof(QueryItem));
                                407             510 :     *(out->valnode) = *(in->valnode);
                                408             510 :     out->flags |= QTN_NEEDFREE;
 5710 tgl                       409 ECB             : 
 5693 teodor                    410 GIC         510 :     if (in->valnode->type == QI_VAL)
 5710 tgl                       411 ECB             :     {
 5015 peter_e                   412 GIC         306 :         out->word = palloc(in->valnode->qoperand.length + 1);
 5015 peter_e                   413 CBC         306 :         memcpy(out->word, in->word, in->valnode->qoperand.length);
                                414             306 :         out->word[in->valnode->qoperand.length] = '\0';
 5710 tgl                       415             306 :         out->flags |= QTN_WORDFREE;
 5710 tgl                       416 ECB             :     }
                                417                 :     else
                                418                 :     {
                                419                 :         int         i;
                                420                 : 
 5710 tgl                       421 GIC         204 :         out->child = (QTNode **) palloc(sizeof(QTNode *) * in->nchild);
 5710 tgl                       422 ECB             : 
 5710 tgl                       423 GIC         609 :         for (i = 0; i < in->nchild; i++)
 5710 tgl                       424 CBC         405 :             out->child[i] = QTNCopy(in->child[i]);
 5710 tgl                       425 ECB             :     }
                                426                 : 
 5710 tgl                       427 GIC         510 :     return out;
 5710 tgl                       428 ECB             : }
                                429                 : 
                                430                 : /*
                                431                 :  * Clear the specified flag bit(s) in all nodes of a QTNode tree.
                                432                 :  */
                                433                 : void
 5624 bruce                     434 GIC        2622 : QTNClearFlags(QTNode *in, uint32 flags)
 5647 tgl                       435 ECB             : {
                                436                 :     /* since this function recurses, it could be driven to stack overflow. */
 5647 tgl                       437 GIC        2622 :     check_stack_depth();
 5647 tgl                       438 ECB             : 
 5647 tgl                       439 GIC        2622 :     in->flags &= ~flags;
 5647 tgl                       440 ECB             : 
 5647 tgl                       441 GIC        2622 :     if (in->valnode->type != QI_VAL)
 5647 tgl                       442 ECB             :     {
                                443                 :         int         i;
                                444                 : 
 5647 tgl                       445 GIC        3204 :         for (i = 0; i < in->nchild; i++)
 5647 tgl                       446 CBC        2226 :             QTNClearFlags(in->child[i], flags);
 5647 tgl                       447 ECB             :     }
 5647 tgl                       448 GIC        2622 : }
        

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