LCOV - differential code coverage report
Current view: top level - src/backend/nodes - equalfuncs.c (source / functions) Coverage Total Hit UNC UIC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 76.8 % 69 53 5 11 2 45 4 2 5 6 9 45
Current Date: 2023-04-08 17:13:01 Functions: 83.3 % 6 5 1 4 1 1 1 4
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 100.0 % 2 2 2
Legend: Lines: hit not hit (120,180] days: 100.0 % 2 2 2
(240..) days: 75.4 % 65 49 5 11 2 45 2 5 6
Function coverage date bins:
(120,180] days: 100.0 % 1 1 1
(240..) days: 66.7 % 6 4 1 4 1

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * equalfuncs.c
                                  4                 :  *    Equality functions to compare node trees.
                                  5                 :  *
                                  6                 :  * NOTE: it is intentional that parse location fields (in nodes that have
                                  7                 :  * one) are not compared.  This is because we want, for example, a variable
                                  8                 :  * "x" to be considered equal() to another reference to "x" in the query.
                                  9                 :  *
                                 10                 :  *
                                 11                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                 12                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                 13                 :  *
                                 14                 :  * IDENTIFICATION
                                 15                 :  *    src/backend/nodes/equalfuncs.c
                                 16                 :  *
                                 17                 :  *-------------------------------------------------------------------------
                                 18                 :  */
                                 19                 : 
                                 20                 : #include "postgres.h"
                                 21                 : 
                                 22                 : #include "miscadmin.h"
                                 23                 : #include "utils/datum.h"
                                 24                 : 
                                 25                 : 
                                 26                 : /*
                                 27                 :  * Macros to simplify comparison of different kinds of fields.  Use these
                                 28                 :  * wherever possible to reduce the chance for silly typos.  Note that these
                                 29                 :  * hard-wire the convention that the local variables in an Equal routine are
                                 30                 :  * named 'a' and 'b'.
                                 31                 :  */
                                 32                 : 
                                 33                 : /* Compare a simple scalar field (int, float, bool, enum, etc) */
                                 34                 : #define COMPARE_SCALAR_FIELD(fldname) \
                                 35                 :     do { \
                                 36                 :         if (a->fldname != b->fldname) \
                                 37                 :             return false; \
                                 38                 :     } while (0)
                                 39                 : 
                                 40                 : /* Compare a field that is a pointer to some kind of Node or Node tree */
                                 41                 : #define COMPARE_NODE_FIELD(fldname) \
                                 42                 :     do { \
                                 43                 :         if (!equal(a->fldname, b->fldname)) \
                                 44                 :             return false; \
                                 45                 :     } while (0)
                                 46                 : 
                                 47                 : /* Compare a field that is a pointer to a Bitmapset */
                                 48                 : #define COMPARE_BITMAPSET_FIELD(fldname) \
                                 49                 :     do { \
                                 50                 :         if (!bms_equal(a->fldname, b->fldname)) \
                                 51                 :             return false; \
                                 52                 :     } while (0)
                                 53                 : 
                                 54                 : /* Compare a field that is a pointer to a C string, or perhaps NULL */
                                 55                 : #define COMPARE_STRING_FIELD(fldname) \
                                 56                 :     do { \
                                 57                 :         if (!equalstr(a->fldname, b->fldname)) \
                                 58                 :             return false; \
                                 59                 :     } while (0)
                                 60                 : 
                                 61                 : /* Macro for comparing string fields that might be NULL */
                                 62                 : #define equalstr(a, b)  \
                                 63                 :     (((a) != NULL && (b) != NULL) ? (strcmp(a, b) == 0) : (a) == (b))
                                 64                 : 
                                 65                 : /* Compare a field that is an inline array */
                                 66                 : #define COMPARE_ARRAY_FIELD(fldname) \
                                 67                 :     do { \
                                 68                 :         if (memcmp(a->fldname, b->fldname, sizeof(a->fldname)) != 0) \
                                 69                 :             return false; \
                                 70                 :     } while (0)
                                 71                 : 
                                 72                 : /* Compare a field that is a pointer to a simple palloc'd object of size sz */
                                 73                 : #define COMPARE_POINTER_FIELD(fldname, sz) \
                                 74                 :     do { \
                                 75                 :         if (memcmp(a->fldname, b->fldname, (sz)) != 0) \
                                 76                 :             return false; \
                                 77                 :     } while (0)
                                 78                 : 
                                 79                 : /* Compare a parse location field (this is a no-op, per note above) */
                                 80                 : #define COMPARE_LOCATION_FIELD(fldname) \
                                 81                 :     ((void) 0)
                                 82                 : 
                                 83                 : /* Compare a CoercionForm field (also a no-op, per comment in primnodes.h) */
 3831 tgl                        84 ECB             : #define COMPARE_COERCIONFORM_FIELD(fldname) \
                                 85                 :     ((void) 0)
                                 86                 : 
 8655                            87                 : 
                                 88                 : #include "equalfuncs.funcs.c"
  274 peter                      89                 : 
                                 90                 : 
                                 91                 : /*
                                 92                 :  * Support functions for nodes with custom_copy_equal attribute
                                 93                 :  */
                                 94                 : 
 9344 bruce                      95                 : static bool
 4141 peter_e                    96 GIC       60014 : _equalConst(const Const *a, const Const *b)
 9770 scrappy                    97 ECB             : {
 7440 tgl                        98 CBC       60014 :     COMPARE_SCALAR_FIELD(consttype);
 5867 tgl                        99 GIC       50471 :     COMPARE_SCALAR_FIELD(consttypmod);
 4443 peter_e                   100 CBC       50461 :     COMPARE_SCALAR_FIELD(constcollid);
 7440 tgl                       101 GBC       48097 :     COMPARE_SCALAR_FIELD(constlen);
                                102           48097 :     COMPARE_SCALAR_FIELD(constisnull);
 7440 tgl                       103 GIC       48023 :     COMPARE_SCALAR_FIELD(constbyval);
 5337 tgl                       104 EUB             :     COMPARE_LOCATION_FIELD(location);
 8397 bruce                     105                 : 
                                106                 :     /*
                                107                 :      * We treat all NULL constants of the same type as equal. Someday this
 6385                           108                 :      * might need to change?  But datumIsEqual doesn't work on nulls, so...
 8507 tgl                       109                 :      */
 8507 tgl                       110 GIC       48023 :     if (a->constisnull)
                                111             598 :         return true;
 8306                           112           47425 :     return datumIsEqual(a->constvalue, b->constvalue,
                                113           47425 :                         a->constbyval, a->constlen);
                                114                 : }
                                115                 : 
                                116                 : static bool
  274 peter                     117 UIC           0 : _equalExtensibleNode(const ExtensibleNode *a, const ExtensibleNode *b)
                                118                 : {
                                119                 :     const ExtensibleNodeMethods *methods;
                                120                 : 
                                121               0 :     COMPARE_STRING_FIELD(extnodename);
                                122                 : 
                                123                 :     /* At this point, we know extnodename is the same for both nodes. */
                                124               0 :     methods = GetExtensibleNodeMethods(a->extnodename, false);
                                125                 : 
                                126                 :     /* compare the private fields */
                                127               0 :     if (!methods->nodeEqual(a, b))
                                128               0 :         return false;
                                129                 : 
 4931 tgl                       130               0 :     return true;
                                131                 : }
                                132                 : 
                                133                 : static bool
  274 peter                     134 GIC          75 : _equalA_Const(const A_Const *a, const A_Const *b)
                                135                 : {
   21 tgl                       136 GNC          75 :     COMPARE_SCALAR_FIELD(isnull);
                                137                 :     /* Hack for in-line val field.  Also val is not valid if isnull is true */
                                138              75 :     if (!a->isnull &&
  274 peter                     139 GIC          75 :         !equal(&a->val, &b->val))
 7423 tgl                       140 UIC           0 :         return false;
                                141                 :     COMPARE_LOCATION_FIELD(location);
                                142                 : 
 7423 tgl                       143 GIC          75 :     return true;
                                144                 : }
                                145                 : 
                                146                 : static bool
  147 tgl                       147 GNC       17226 : _equalBitmapset(const Bitmapset *a, const Bitmapset *b)
                                148                 : {
                                149           17226 :     return bms_equal(a, b);
                                150                 : }
                                151                 : 
                                152                 : /*
                                153                 :  * Lists are handled specially
                                154                 :  */
                                155                 : static bool
  274 peter                     156 GIC     1608669 : _equalList(const List *a, const List *b)
                                157                 : {
                                158                 :     const ListCell *item_a;
                                159                 :     const ListCell *item_b;
                                160                 : 
                                161                 :     /*
                                162                 :      * Try to reject by simple scalar checks before grovelling through all the
                                163                 :      * list elements...
                                164                 :      */
                                165         1608669 :     COMPARE_SCALAR_FIELD(type);
                                166         1608669 :     COMPARE_SCALAR_FIELD(length);
                                167                 : 
                                168                 :     /*
                                169                 :      * We place the switch outside the loop for the sake of efficiency; this
                                170                 :      * may not be worth doing...
                                171                 :      */
                                172         1561184 :     switch (a->type)
                                173                 :     {
                                174          162133 :         case T_List:
                                175          399909 :             forboth(item_a, a, item_b, b)
                                176                 :             {
                                177          295952 :                 if (!equal(lfirst(item_a), lfirst(item_b)))
                                178           58176 :                     return false;
                                179                 :             }
                                180          103957 :             break;
                                181             195 :         case T_IntList:
                                182            1628 :             forboth(item_a, a, item_b, b)
                                183                 :             {
                                184            1441 :                 if (lfirst_int(item_a) != lfirst_int(item_b))
                                185               8 :                     return false;
                                186                 :             }
                                187             187 :             break;
                                188         1398856 :         case T_OidList:
                                189         2579886 :             forboth(item_a, a, item_b, b)
                                190                 :             {
                                191         1422420 :                 if (lfirst_oid(item_a) != lfirst_oid(item_b))
                                192          241390 :                     return false;
                                193                 :             }
                                194         1157466 :             break;
  271 alvherre                  195 UNC           0 :         case T_XidList:
                                196               0 :             forboth(item_a, a, item_b, b)
                                197                 :             {
                                198               0 :                 if (lfirst_xid(item_a) != lfirst_xid(item_b))
                                199               0 :                     return false;
                                200                 :             }
                                201               0 :             break;
  274 peter                     202 UIC           0 :         default:
                                203               0 :             elog(ERROR, "unrecognized list node type: %d",
                                204                 :                  (int) a->type);
                                205                 :             return false;       /* keep compiler quiet */
                                206                 :     }
                                207                 : 
                                208                 :     /*
                                209                 :      * If we got here, we should have run out of elements of both lists
                                210                 :      */
  274 peter                     211 GIC     1261610 :     Assert(item_a == NULL);
                                212         1261610 :     Assert(item_b == NULL);
                                213                 : 
 7531 tgl                       214         1261610 :     return true;
                                215                 : }
                                216                 : 
                                217                 : 
                                218                 : /*
                                219                 :  * equal
                                220                 :  *    returns whether two nodes are equal
                                221                 :  */
                                222                 : bool
  274 peter                     223         4694945 : equal(const void *a, const void *b)
                                224                 : {
                                225                 :     bool        retval;
                                226                 : 
                                227         4694945 :     if (a == b)
                                228          129538 :         return true;
                                229                 : 
                                230                 :     /*
                                231                 :      * note that a!=b, so only one of them can be NULL
                                232                 :      */
                                233         4565407 :     if (a == NULL || b == NULL)
                                234           94194 :         return false;
                                235                 : 
                                236                 :     /*
                                237                 :      * are they the same type of nodes?
                                238                 :      */
                                239         4471213 :     if (nodeTag(a) != nodeTag(b))
                                240          614878 :         return false;
                                241                 : 
                                242                 :     /* Guard against stack overflow due to overly complex expressions */
                                243         3856335 :     check_stack_depth();
                                244                 : 
                                245         3856335 :     switch (nodeTag(a))
                                246                 :     {
                                247                 : #include "equalfuncs.switch.c"
                                248                 : 
 9344 bruce                     249         1608669 :         case T_List:
                                250                 :         case T_IntList:
                                251                 :         case T_OidList:
                                252                 :         case T_XidList:
 6892 neilc                     253         1608669 :             retval = _equalList(a, b);
 9344 bruce                     254         1608669 :             break;
                                255                 : 
 9344 bruce                     256 UIC           0 :         default:
 7201 tgl                       257               0 :             elog(ERROR, "unrecognized node type: %d",
                                258                 :                  (int) nodeTag(a));
                                259                 :             retval = false;     /* keep compiler quiet */
                                260                 :             break;
                                261                 :     }
                                262                 : 
 9345 bruce                     263 GIC     3856335 :     return retval;
                                264                 : }
        

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