LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - tsquery_rewrite.c (source / functions) Coverage Total Hit UNC UBC GNC CBC DUB DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 88.4 % 189 167 4 18 9 158 4 9
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 5 5 2 3
Baseline: 16@8cea358b128 Branches: 61.1 % 144 88 56 88
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (60,120] days: 69.2 % 13 9 4 9
(240..) days: 89.8 % 176 158 18 158
Function coverage date bins:
(240..) days: 100.0 % 5 5 2 3
Branch coverage date bins:
(240..) days: 61.1 % 144 88 56 88

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * tsquery_rewrite.c
                                  4                 :                :  *    Utilities for reconstructing tsquery
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                  7                 :                :  *
                                  8                 :                :  *
                                  9                 :                :  * IDENTIFICATION
                                 10                 :                :  *    src/backend/utils/adt/tsquery_rewrite.c
                                 11                 :                :  *
                                 12                 :                :  *-------------------------------------------------------------------------
                                 13                 :                :  */
                                 14                 :                : 
                                 15                 :                : #include "postgres.h"
                                 16                 :                : 
                                 17                 :                : #include "catalog/pg_type.h"
                                 18                 :                : #include "executor/spi.h"
                                 19                 :                : #include "miscadmin.h"
                                 20                 :                : #include "tsearch/ts_utils.h"
                                 21                 :                : #include "utils/builtins.h"
                                 22                 :                : 
                                 23                 :                : 
                                 24                 :                : /*
                                 25                 :                :  * If "node" is equal to "ex", return a copy of "subs" instead.
                                 26                 :                :  * If "ex" matches a subset of node's children, return a modified version
                                 27                 :                :  * of "node" in which those children are replaced with a copy of "subs".
                                 28                 :                :  * Otherwise return "node" unmodified.
                                 29                 :                :  *
                                 30                 :                :  * The QTN_NOCHANGE bit is set in successfully modified nodes, so that
                                 31                 :                :  * we won't uselessly recurse into them.
                                 32                 :                :  * Also, set *isfind true if we make a replacement.
                                 33                 :                :  */
                                 34                 :                : static QTNode *
 5995 bruce@momjian.us           35                 :CBC        2376 : findeq(QTNode *node, QTNode *ex, QTNode *subs, bool *isfind)
                                 36                 :                : {
                                 37                 :                :     /* Can't match unless signature matches and node type matches. */
                                 38         [ +  + ]:           2376 :     if ((node->sign & ex->sign) != ex->sign ||
 6064 teodor@sigaev.ru           39         [ +  + ]:            213 :         node->valnode->type != ex->valnode->type)
 6081 tgl@sss.pgh.pa.us          40                 :           2214 :         return node;
                                 41                 :                : 
                                 42                 :                :     /* Ignore nodes marked NOCHANGE, too. */
                                 43         [ +  + ]:            162 :     if (node->flags & QTN_NOCHANGE)
                                 44                 :             21 :         return node;
                                 45                 :                : 
 6064 teodor@sigaev.ru           46         [ +  + ]:            141 :     if (node->valnode->type == QI_OPR)
                                 47                 :                :     {
                                 48                 :                :         /* Must be same operator. */
 5386 peter_e@gmx.net            49         [ +  + ]:             72 :         if (node->valnode->qoperator.oper != ex->valnode->qoperator.oper)
 6064 teodor@sigaev.ru           50                 :             21 :             return node;
                                 51                 :                : 
 6081 tgl@sss.pgh.pa.us          52         [ +  + ]:             51 :         if (node->nchild == ex->nchild)
                                 53                 :                :         {
                                 54                 :                :             /*
                                 55                 :                :              * Simple case: when same number of children, match if equal.
                                 56                 :                :              * (This is reliable when the children were sorted earlier.)
                                 57                 :                :              */
                                 58         [ +  + ]:             30 :             if (QTNEq(node, ex))
                                 59                 :                :             {
                                 60                 :                :                 /* Match; delete node and return a copy of subs instead. */
                                 61                 :             24 :                 QTNFree(node);
                                 62         [ +  - ]:             24 :                 if (subs)
                                 63                 :                :                 {
                                 64                 :             24 :                     node = QTNCopy(subs);
                                 65                 :             24 :                     node->flags |= QTN_NOCHANGE;
                                 66                 :                :                 }
                                 67                 :                :                 else
 6081 tgl@sss.pgh.pa.us          68                 :UBC           0 :                     node = NULL;
 6081 tgl@sss.pgh.pa.us          69                 :CBC          24 :                 *isfind = true;
                                 70                 :                :             }
                                 71                 :                :         }
 2723                            72   [ +  -  +  - ]:             21 :         else if (node->nchild > ex->nchild && ex->nchild > 0)
                                 73                 :                :         {
                                 74                 :                :             /*
                                 75                 :                :              * AND and OR are commutative/associative, so we should check if a
                                 76                 :                :              * subset of the children match.  For example, if node is A|B|C,
                                 77                 :                :              * and ex is B|C, we have a match after we notionally convert node
                                 78                 :                :              * to A|(B|C).  This does not work for NOT or PHRASE nodes, but we
                                 79                 :                :              * can't get here for those node types because they have a fixed
                                 80                 :                :              * number of children.
                                 81                 :                :              *
                                 82                 :                :              * Because we expect that the children are sorted, it suffices to
                                 83                 :                :              * make one pass through the two lists to find the matches.
                                 84                 :                :              */
                                 85                 :                :             bool       *matched;
                                 86                 :                :             int         nmatched;
                                 87                 :                :             int         i,
                                 88                 :                :                         j;
                                 89                 :                : 
                                 90                 :                :             /* Assert that the subset rule is OK */
                                 91   [ -  +  -  - ]:             21 :             Assert(node->valnode->qoperator.oper == OP_AND ||
                                 92                 :                :                    node->valnode->qoperator.oper == OP_OR);
                                 93                 :                : 
                                 94                 :                :             /* matched[] will record which children of node matched */
                                 95                 :             21 :             matched = (bool *) palloc0(node->nchild * sizeof(bool));
                                 96                 :             21 :             nmatched = 0;
                                 97                 :             21 :             i = j = 0;
                                 98   [ +  +  +  + ]:            105 :             while (i < node->nchild && j < ex->nchild)
                                 99                 :                :             {
                                100                 :             84 :                 int         cmp = QTNodeCompare(node->child[i], ex->child[j]);
                                101                 :                : 
                                102         [ +  + ]:             84 :                 if (cmp == 0)
                                103                 :                :                 {
                                104                 :                :                     /* match! */
                                105                 :             60 :                     matched[i] = true;
                                106                 :             60 :                     nmatched++;
                                107                 :             60 :                     i++, j++;
                                108                 :                :                 }
                                109         [ +  - ]:             24 :                 else if (cmp < 0)
                                110                 :                :                 {
                                111                 :                :                     /* node->child[i] has no match, ignore it */
                                112                 :             24 :                     i++;
                                113                 :                :                 }
                                114                 :                :                 else
                                115                 :                :                 {
                                116                 :                :                     /* ex->child[j] has no match; we can give up immediately */
 2723 tgl@sss.pgh.pa.us         117                 :UBC           0 :                     break;
                                118                 :                :                 }
                                119                 :                :             }
                                120                 :                : 
 2723 tgl@sss.pgh.pa.us         121         [ +  - ]:CBC          21 :             if (nmatched == ex->nchild)
                                122                 :                :             {
                                123                 :                :                 /* collapse out the matched children of node */
                                124                 :             21 :                 j = 0;
                                125         [ +  + ]:            108 :                 for (i = 0; i < node->nchild; i++)
                                126                 :                :                 {
                                127         [ +  + ]:             87 :                     if (matched[i])
                                128                 :             60 :                         QTNFree(node->child[i]);
                                129                 :                :                     else
                                130                 :             27 :                         node->child[j++] = node->child[i];
                                131                 :                :                 }
                                132                 :                : 
                                133                 :                :                 /* and instead insert a copy of subs */
                                134         [ +  - ]:             21 :                 if (subs)
                                135                 :                :                 {
                                136                 :             21 :                     subs = QTNCopy(subs);
                                137                 :             21 :                     subs->flags |= QTN_NOCHANGE;
                                138                 :             21 :                     node->child[j++] = subs;
                                139                 :                :                 }
                                140                 :                : 
                                141                 :             21 :                 node->nchild = j;
                                142                 :                : 
                                143                 :                :                 /*
                                144                 :                :                  * At this point we might have a node with zero or one child,
                                145                 :                :                  * which should be simplified.  But we leave it to our caller
                                146                 :                :                  * (dofindsubquery) to take care of that.
                                147                 :                :                  */
                                148                 :                : 
                                149                 :                :                 /*
                                150                 :                :                  * Re-sort the node to put new child in the right place.  This
                                151                 :                :                  * is a bit bogus, because it won't matter for findsubquery's
                                152                 :                :                  * remaining processing, and it's insufficient to prepare the
                                153                 :                :                  * tree for another search (we would need to re-flatten as
                                154                 :                :                  * well, and we don't want to do that because we'd lose the
                                155                 :                :                  * QTN_NOCHANGE marking on the new child).  But it's needed to
                                156                 :                :                  * keep the results the same as the regression tests expect.
                                157                 :                :                  */
                                158                 :             21 :                 QTNSort(node);
                                159                 :                : 
                                160                 :             21 :                 *isfind = true;
                                161                 :                :             }
                                162                 :                : 
                                163                 :             21 :             pfree(matched);
                                164                 :                :         }
                                165                 :                :     }
                                166                 :                :     else
                                167                 :                :     {
 6064 teodor@sigaev.ru          168         [ -  + ]:             69 :         Assert(node->valnode->type == QI_VAL);
                                169                 :                : 
 5386 peter_e@gmx.net           170         [ -  + ]:             69 :         if (node->valnode->qoperand.valcrc != ex->valnode->qoperand.valcrc)
 6064 teodor@sigaev.ru          171                 :UBC           0 :             return node;
 6064 teodor@sigaev.ru          172         [ +  - ]:CBC          69 :         else if (QTNEq(node, ex))
                                173                 :                :         {
                                174                 :             69 :             QTNFree(node);
                                175         [ +  + ]:             69 :             if (subs)
                                176                 :                :             {
                                177                 :             60 :                 node = QTNCopy(subs);
                                178                 :             60 :                 node->flags |= QTN_NOCHANGE;
                                179                 :                :             }
                                180                 :                :             else
                                181                 :                :             {
                                182                 :              9 :                 node = NULL;
                                183                 :                :             }
                                184                 :             69 :             *isfind = true;
                                185                 :                :         }
                                186                 :                :     }
                                187                 :                : 
 6081 tgl@sss.pgh.pa.us         188                 :            120 :     return node;
                                189                 :                : }
                                190                 :                : 
                                191                 :                : /*
                                192                 :                :  * Recursive guts of findsubquery(): attempt to replace "ex" with "subs"
                                193                 :                :  * at the root node, and if we failed to do so, recursively match against
                                194                 :                :  * child nodes.
                                195                 :                :  *
                                196                 :                :  * Delete any void subtrees resulting from the replacement.
                                197                 :                :  * In the following example '5' is replaced by empty operand:
                                198                 :                :  *
                                199                 :                :  *    AND       ->     6
                                200                 :                :  *   /   \
                                201                 :                :  *  5    OR
                                202                 :                :  *      /  \
                                203                 :                :  *     6    5
                                204                 :                :  */
                                205                 :                : static QTNode *
 5995 bruce@momjian.us          206                 :           2376 : dofindsubquery(QTNode *root, QTNode *ex, QTNode *subs, bool *isfind)
                                207                 :                : {
                                208                 :                :     /* since this function recurses, it could be driven to stack overflow. */
 6064 teodor@sigaev.ru          209                 :           2376 :     check_stack_depth();
                                210                 :                : 
                                211                 :                :     /* also, since it's a bit expensive, let's check for query cancel. */
 2723 tgl@sss.pgh.pa.us         212         [ -  + ]:           2376 :     CHECK_FOR_INTERRUPTS();
                                213                 :                : 
                                214                 :                :     /* match at the node itself */
 6081                           215                 :           2376 :     root = findeq(root, ex, subs, isfind);
                                216                 :                : 
                                217                 :                :     /* unless we matched here, consider matches at child nodes */
 2681                           218   [ +  +  +  + ]:           2376 :     if (root && (root->flags & QTN_NOCHANGE) == 0 &&
                                219         [ +  + ]:           2262 :         root->valnode->type == QI_OPR)
                                220                 :                :     {
                                221                 :                :         int         i,
 6081                           222                 :            846 :                     j = 0;
                                223                 :                : 
                                224                 :                :         /*
                                225                 :                :          * Any subtrees that are replaced by NULL must be dropped from the
                                226                 :                :          * tree.
                                227                 :                :          */
                                228         [ +  + ]:           2802 :         for (i = 0; i < root->nchild; i++)
                                229                 :                :         {
 2681                           230                 :           1956 :             root->child[j] = dofindsubquery(root->child[i], ex, subs, isfind);
                                231         [ +  + ]:           1956 :             if (root->child[j])
 6081                           232                 :           1947 :                 j++;
                                233                 :                :         }
                                234                 :                : 
                                235                 :            846 :         root->nchild = j;
                                236                 :                : 
                                237                 :                :         /*
                                238                 :                :          * If we have just zero or one remaining child node, simplify out this
                                239                 :                :          * operator node.
                                240                 :                :          */
 5374 teodor@sigaev.ru          241         [ +  + ]:            846 :         if (root->nchild == 0)
                                242                 :                :         {
 6081 tgl@sss.pgh.pa.us         243                 :              3 :             QTNFree(root);
                                244                 :              3 :             root = NULL;
                                245                 :                :         }
 5374 teodor@sigaev.ru          246   [ +  +  +  + ]:            843 :         else if (root->nchild == 1 && root->valnode->qoperator.oper != OP_NOT)
                                247                 :                :         {
 6081 tgl@sss.pgh.pa.us         248                 :              6 :             QTNode     *nroot = root->child[0];
                                249                 :                : 
                                250                 :              6 :             pfree(root);
                                251                 :              6 :             root = nroot;
                                252                 :                :         }
                                253                 :                :     }
                                254                 :                : 
                                255                 :           2376 :     return root;
                                256                 :                : }
                                257                 :                : 
                                258                 :                : /*
                                259                 :                :  * Substitute "subs" for "ex" throughout the QTNode tree at root.
                                260                 :                :  *
                                261                 :                :  * If isfind isn't NULL, set *isfind to show whether we made any substitution.
                                262                 :                :  *
                                263                 :                :  * Both "root" and "ex" must have been through QTNTernary and QTNSort
                                264                 :                :  * to ensure reliable matching.
                                265                 :                :  */
                                266                 :                : QTNode *
 5995 bruce@momjian.us          267                 :            420 : findsubquery(QTNode *root, QTNode *ex, QTNode *subs, bool *isfind)
                                268                 :                : {
 6081 tgl@sss.pgh.pa.us         269                 :            420 :     bool        DidFind = false;
                                270                 :                : 
                                271                 :            420 :     root = dofindsubquery(root, ex, subs, &DidFind);
                                272                 :                : 
                                273         [ -  + ]:            420 :     if (isfind)
 6081 tgl@sss.pgh.pa.us         274                 :UBC           0 :         *isfind = DidFind;
                                275                 :                : 
 6081 tgl@sss.pgh.pa.us         276                 :CBC         420 :     return root;
                                277                 :                : }
                                278                 :                : 
                                279                 :                : Datum
 6017                           280                 :             66 : tsquery_rewrite_query(PG_FUNCTION_ARGS)
                                281                 :                : {
 6081                           282                 :             66 :     TSQuery     query = PG_GETARG_TSQUERY_COPY(0);
 2590 noah@leadboat.com         283                 :             66 :     text       *in = PG_GETARG_TEXT_PP(1);
  103 rhaas@postgresql.org      284                 :GNC          66 :     TSQuery     rewritten = query;
 6081 tgl@sss.pgh.pa.us         285                 :CBC          66 :     MemoryContext outercontext = CurrentMemoryContext;
                                286                 :                :     MemoryContext oldcontext;
                                287                 :                :     QTNode     *tree;
                                288                 :                :     char       *buf;
                                289                 :                :     SPIPlanPtr  plan;
                                290                 :                :     Portal      portal;
                                291                 :                :     bool        isnull;
                                292                 :                : 
                                293         [ -  + ]:             66 :     if (query->size == 0)
                                294                 :                :     {
 6081 tgl@sss.pgh.pa.us         295         [ #  # ]:UBC           0 :         PG_FREE_IF_COPY(in, 1);
  103 rhaas@postgresql.org      296                 :UNC           0 :         PG_RETURN_POINTER(rewritten);
                                297                 :                :     }
                                298                 :                : 
 6081 tgl@sss.pgh.pa.us         299                 :CBC          66 :     tree = QT2QTN(GETQUERY(query), GETOPERAND(query));
                                300                 :             66 :     QTNTernary(tree);
                                301                 :             66 :     QTNSort(tree);
                                302                 :                : 
 5864                           303                 :             66 :     buf = text_to_cstring(in);
                                304                 :                : 
 6081                           305                 :             66 :     SPI_connect();
                                306                 :                : 
                                307         [ -  + ]:             66 :     if ((plan = SPI_prepare(buf, 0, NULL)) == NULL)
 6081 tgl@sss.pgh.pa.us         308         [ #  # ]:UBC           0 :         elog(ERROR, "SPI_prepare(\"%s\") failed", buf);
                                309                 :                : 
 6017 tgl@sss.pgh.pa.us         310         [ -  + ]:CBC          66 :     if ((portal = SPI_cursor_open(NULL, plan, NULL, NULL, true)) == NULL)
 6081 tgl@sss.pgh.pa.us         311         [ #  # ]:UBC           0 :         elog(ERROR, "SPI_cursor_open(\"%s\") failed", buf);
                                312                 :                : 
 6081 tgl@sss.pgh.pa.us         313                 :CBC          66 :     SPI_cursor_fetch(portal, true, 100);
                                314                 :                : 
 6017                           315         [ +  - ]:             66 :     if (SPI_tuptable == NULL ||
                                316   [ +  -  +  - ]:            132 :         SPI_tuptable->tupdesc->natts != 2 ||
 6081                           317         [ -  + ]:            132 :         SPI_gettypeid(SPI_tuptable->tupdesc, 1) != TSQUERYOID ||
                                318                 :             66 :         SPI_gettypeid(SPI_tuptable->tupdesc, 2) != TSQUERYOID)
 6081 tgl@sss.pgh.pa.us         319         [ #  # ]:UBC           0 :         ereport(ERROR,
                                320                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                321                 :                :                  errmsg("ts_rewrite query must return two tsquery columns")));
                                322                 :                : 
 6081 tgl@sss.pgh.pa.us         323   [ +  +  +  - ]:CBC         132 :     while (SPI_processed > 0 && tree)
                                324                 :                :     {
                                325                 :                :         uint64      i;
                                326                 :                : 
                                327   [ +  +  +  - ]:            462 :         for (i = 0; i < SPI_processed && tree; i++)
                                328                 :                :         {
                                329                 :            396 :             Datum       qdata = SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &isnull);
                                330                 :                :             Datum       sdata;
                                331                 :                : 
                                332         [ -  + ]:            396 :             if (isnull)
 6081 tgl@sss.pgh.pa.us         333                 :UBC           0 :                 continue;
                                334                 :                : 
 6081 tgl@sss.pgh.pa.us         335                 :CBC         396 :             sdata = SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &isnull);
                                336                 :                : 
                                337         [ +  - ]:            396 :             if (!isnull)
                                338                 :                :             {
                                339                 :            396 :                 TSQuery     qtex = DatumGetTSQuery(qdata);
                                340                 :            396 :                 TSQuery     qtsubs = DatumGetTSQuery(sdata);
                                341                 :                :                 QTNode     *qex,
                                342                 :            396 :                            *qsubs = NULL;
                                343                 :                : 
                                344         [ -  + ]:            396 :                 if (qtex->size == 0)
                                345                 :                :                 {
 6081 tgl@sss.pgh.pa.us         346         [ #  # ]:UBC           0 :                     if (qtex != (TSQuery) DatumGetPointer(qdata))
                                347                 :              0 :                         pfree(qtex);
                                348         [ #  # ]:              0 :                     if (qtsubs != (TSQuery) DatumGetPointer(sdata))
                                349                 :              0 :                         pfree(qtsubs);
                                350                 :              0 :                     continue;
                                351                 :                :                 }
                                352                 :                : 
 6081 tgl@sss.pgh.pa.us         353                 :CBC         396 :                 qex = QT2QTN(GETQUERY(qtex), GETOPERAND(qtex));
                                354                 :                : 
                                355                 :            396 :                 QTNTernary(qex);
                                356                 :            396 :                 QTNSort(qex);
                                357                 :                : 
                                358         [ +  - ]:            396 :                 if (qtsubs->size)
                                359                 :            396 :                     qsubs = QT2QTN(GETQUERY(qtsubs), GETOPERAND(qtsubs));
                                360                 :                : 
                                361                 :            396 :                 oldcontext = MemoryContextSwitchTo(outercontext);
                                362                 :            396 :                 tree = findsubquery(tree, qex, qsubs, NULL);
                                363                 :            396 :                 MemoryContextSwitchTo(oldcontext);
                                364                 :                : 
                                365                 :            396 :                 QTNFree(qex);
                                366         [ -  + ]:            396 :                 if (qtex != (TSQuery) DatumGetPointer(qdata))
 6081 tgl@sss.pgh.pa.us         367                 :UBC           0 :                     pfree(qtex);
 6081 tgl@sss.pgh.pa.us         368                 :CBC         396 :                 QTNFree(qsubs);
                                369         [ -  + ]:            396 :                 if (qtsubs != (TSQuery) DatumGetPointer(sdata))
 6081 tgl@sss.pgh.pa.us         370                 :UBC           0 :                     pfree(qtsubs);
                                371                 :                : 
 6018 tgl@sss.pgh.pa.us         372         [ +  - ]:CBC         396 :                 if (tree)
                                373                 :                :                 {
                                374                 :                :                     /* ready the tree for another pass */
                                375                 :            396 :                     QTNClearFlags(tree, QTN_NOCHANGE);
 2723                           376                 :            396 :                     QTNTernary(tree);
 6018                           377                 :            396 :                     QTNSort(tree);
                                378                 :                :                 }
                                379                 :                :             }
                                380                 :                :         }
                                381                 :                : 
 6081                           382                 :             66 :         SPI_freetuptable(SPI_tuptable);
                                383                 :             66 :         SPI_cursor_fetch(portal, true, 100);
                                384                 :                :     }
                                385                 :                : 
                                386                 :             66 :     SPI_freetuptable(SPI_tuptable);
                                387                 :             66 :     SPI_cursor_close(portal);
                                388                 :             66 :     SPI_freeplan(plan);
                                389                 :             66 :     SPI_finish();
                                390                 :                : 
                                391         [ +  - ]:             66 :     if (tree)
                                392                 :                :     {
                                393                 :             66 :         QTNBinary(tree);
  103 rhaas@postgresql.org      394                 :GNC          66 :         rewritten = QTN2QT(tree);
 6081 tgl@sss.pgh.pa.us         395                 :CBC          66 :         QTNFree(tree);
                                396         [ +  - ]:             66 :         PG_FREE_IF_COPY(query, 0);
                                397                 :                :     }
                                398                 :                :     else
                                399                 :                :     {
  103 rhaas@postgresql.org      400                 :UNC           0 :         SET_VARSIZE(rewritten, HDRSIZETQ);
                                401                 :              0 :         rewritten->size = 0;
                                402                 :                :     }
                                403                 :                : 
 6081 tgl@sss.pgh.pa.us         404                 :CBC          66 :     pfree(buf);
                                405         [ -  + ]:             66 :     PG_FREE_IF_COPY(in, 1);
  103 rhaas@postgresql.org      406                 :GNC          66 :     PG_RETURN_POINTER(rewritten);
                                407                 :                : }
                                408                 :                : 
                                409                 :                : Datum
 6017 tgl@sss.pgh.pa.us         410                 :CBC          24 : tsquery_rewrite(PG_FUNCTION_ARGS)
                                411                 :                : {
 6081                           412                 :             24 :     TSQuery     query = PG_GETARG_TSQUERY_COPY(0);
                                413                 :             24 :     TSQuery     ex = PG_GETARG_TSQUERY(1);
                                414                 :             24 :     TSQuery     subst = PG_GETARG_TSQUERY(2);
  103 rhaas@postgresql.org      415                 :GNC          24 :     TSQuery     rewritten = query;
                                416                 :                :     QTNode     *tree,
                                417                 :                :                *qex,
 6081 tgl@sss.pgh.pa.us         418                 :CBC          24 :                *subs = NULL;
                                419                 :                : 
                                420   [ +  -  -  + ]:             24 :     if (query->size == 0 || ex->size == 0)
                                421                 :                :     {
 6081 tgl@sss.pgh.pa.us         422         [ #  # ]:UBC           0 :         PG_FREE_IF_COPY(ex, 1);
                                423         [ #  # ]:              0 :         PG_FREE_IF_COPY(subst, 2);
  103 rhaas@postgresql.org      424                 :UNC           0 :         PG_RETURN_POINTER(rewritten);
                                425                 :                :     }
                                426                 :                : 
 6081 tgl@sss.pgh.pa.us         427                 :CBC          24 :     tree = QT2QTN(GETQUERY(query), GETOPERAND(query));
                                428                 :             24 :     QTNTernary(tree);
                                429                 :             24 :     QTNSort(tree);
                                430                 :                : 
                                431                 :             24 :     qex = QT2QTN(GETQUERY(ex), GETOPERAND(ex));
                                432                 :             24 :     QTNTernary(qex);
                                433                 :             24 :     QTNSort(qex);
                                434                 :                : 
                                435         [ +  + ]:             24 :     if (subst->size)
                                436                 :             18 :         subs = QT2QTN(GETQUERY(subst), GETOPERAND(subst));
                                437                 :                : 
                                438                 :             24 :     tree = findsubquery(tree, qex, subs, NULL);
                                439                 :                : 
                                440                 :             24 :     QTNFree(qex);
                                441                 :             24 :     QTNFree(subs);
                                442                 :                : 
                                443         [ +  + ]:             24 :     if (!tree)
                                444                 :                :     {
  103 rhaas@postgresql.org      445                 :GNC           3 :         SET_VARSIZE(rewritten, HDRSIZETQ);
                                446                 :              3 :         rewritten->size = 0;
 6081 tgl@sss.pgh.pa.us         447         [ -  + ]:CBC           3 :         PG_FREE_IF_COPY(ex, 1);
                                448         [ -  + ]:              3 :         PG_FREE_IF_COPY(subst, 2);
  103 rhaas@postgresql.org      449                 :GNC           3 :         PG_RETURN_POINTER(rewritten);
                                450                 :                :     }
                                451                 :                :     else
                                452                 :                :     {
 6081 tgl@sss.pgh.pa.us         453                 :CBC          21 :         QTNBinary(tree);
  103 rhaas@postgresql.org      454                 :GNC          21 :         rewritten = QTN2QT(tree);
 6081 tgl@sss.pgh.pa.us         455                 :CBC          21 :         QTNFree(tree);
                                456                 :                :     }
                                457                 :                : 
                                458         [ +  - ]:             21 :     PG_FREE_IF_COPY(query, 0);
                                459         [ -  + ]:             21 :     PG_FREE_IF_COPY(ex, 1);
                                460         [ -  + ]:             21 :     PG_FREE_IF_COPY(subst, 2);
  103 rhaas@postgresql.org      461                 :GNC          21 :     PG_RETURN_POINTER(rewritten);
                                462                 :                : }
        

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