#include "postgres.h"
#include "miscadmin.h"
#include "utils/datum.h"
#define COMPARE_SCALAR_FIELD(fldname) \
do { \
if (a->fldname != b->fldname) \
return false; \
} while (0)
#define COMPARE_NODE_FIELD(fldname) \
do { \
if (!equal(a->fldname, b->fldname)) \
return false; \
} while (0)
#define COMPARE_BITMAPSET_FIELD(fldname) \
do { \
if (!bms_equal(a->fldname, b->fldname)) \
return false; \
} while (0)
#define COMPARE_STRING_FIELD(fldname) \
do { \
if (!equalstr(a->fldname, b->fldname)) \
return false; \
} while (0)
#define equalstr(a, b) \
(((a) != NULL && (b) != NULL) ? (strcmp(a, b) == 0) : (a) == (b))
#define COMPARE_ARRAY_FIELD(fldname) \
do { \
if (memcmp(a->fldname, b->fldname, sizeof(a->fldname)) != 0) \
return false; \
} while (0)
#define COMPARE_POINTER_FIELD(fldname, sz) \
do { \
if (memcmp(a->fldname, b->fldname, (sz)) != 0) \
return false; \
} while (0)
#define COMPARE_LOCATION_FIELD(fldname) \
((void) 0)
#define COMPARE_COERCIONFORM_FIELD(fldname) \
((void) 0)
#include "equalfuncs.funcs.c"
static bool
_equalConst(const Const *a, const Const *b)
{
COMPARE_SCALAR_FIELD(consttype);
COMPARE_SCALAR_FIELD(consttypmod);
COMPARE_SCALAR_FIELD(constcollid);
COMPARE_SCALAR_FIELD(constlen);
COMPARE_SCALAR_FIELD(constisnull);
COMPARE_SCALAR_FIELD(constbyval);
COMPARE_LOCATION_FIELD(location);
if (a->constisnull)
return true;
return datumIsEqual(a->constvalue, b->constvalue,
a->constbyval, a->constlen);
}
static bool
_equalExtensibleNode(const ExtensibleNode *a, const ExtensibleNode *b)
{
const ExtensibleNodeMethods *methods;
COMPARE_STRING_FIELD(extnodename);
methods = GetExtensibleNodeMethods(a->extnodename, false);
if (!methods->nodeEqual(a, b))
return false;
return true;
}
static bool
_equalA_Const(const A_Const *a, const A_Const *b)
{
COMPARE_SCALAR_FIELD(isnull);
if (!a->isnull &&
!equal(&a->val, &b->val))
return false;
COMPARE_LOCATION_FIELD(location);
return true;
}
static bool
_equalBitmapset(const Bitmapset *a, const Bitmapset *b)
{
return bms_equal(a, b);
}
static bool
_equalList(const List *a, const List *b)
{
const ListCell *item_a;
const ListCell *item_b;
COMPARE_SCALAR_FIELD(type);
COMPARE_SCALAR_FIELD(length);
switch (a->type)
{
case T_List:
forboth(item_a, a, item_b, b)
{
if (!equal(lfirst(item_a), lfirst(item_b)))
return false;
}
break;
case T_IntList:
forboth(item_a, a, item_b, b)
{
if (lfirst_int(item_a) != lfirst_int(item_b))
return false;
}
break;
case T_OidList:
forboth(item_a, a, item_b, b)
{
if (lfirst_oid(item_a) != lfirst_oid(item_b))
return false;
}
break;
case T_XidList:
forboth(item_a, a, item_b, b)
{
if (lfirst_xid(item_a) != lfirst_xid(item_b))
return false;
}
break;
default:
elog(ERROR, "unrecognized list node type: %d",
(int) a->type);
return false;
}
Assert(item_a == NULL);
Assert(item_b == NULL);
return true;
}
bool
equal(const void *a, const void *b)
{
bool retval;
if (a == b)
return true;
if (a == NULL || b == NULL)
return false;
if (nodeTag(a) != nodeTag(b))
return false;
check_stack_depth();
switch (nodeTag(a))
{
#include "equalfuncs.switch.c"
case T_List:
case T_IntList:
case T_OidList:
case T_XidList:
retval = _equalList(a, b);
break;
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(a));
retval = false;
break;
}
return retval;
}