📄 equalfuncs.c
字号:
/*------------------------------------------------------------------------- * * equalfuncs.c * Equality functions to compare node trees. * * NOTE: we currently support comparing all node types found in parse * trees. We do not support comparing executor state trees; there * is no need for that, and no point in maintaining all the code that * would be needed. We also do not support comparing Path trees, mainly * because the circular linkages between RelOptInfo and Path nodes can't * be handled easily in a simple depth-first traversal. * * Currently, in fact, equal() doesn't know how to compare Plan trees * either. This might need to be fixed someday. * * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.253.2.1 2005/11/14 23:54:34 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "nodes/params.h"#include "nodes/parsenodes.h"#include "nodes/relation.h"#include "utils/datum.h"/* * Macros to simplify comparison of different kinds of fields. Use these * wherever possible to reduce the chance for silly typos. Note that these * hard-wire the convention that the local variables in an Equal routine are * named 'a' and 'b'. *//* Compare a simple scalar field (int, float, bool, enum, etc) */#define COMPARE_SCALAR_FIELD(fldname) \ do { \ if (a->fldname != b->fldname) \ return false; \ } while (0)/* Compare a field that is a pointer to some kind of Node or Node tree */#define COMPARE_NODE_FIELD(fldname) \ do { \ if (!equal(a->fldname, b->fldname)) \ return false; \ } while (0)/* Compare a field that is a pointer to a Bitmapset */#define COMPARE_BITMAPSET_FIELD(fldname) \ do { \ if (!bms_equal(a->fldname, b->fldname)) \ return false; \ } while (0)/* Compare a field that is a pointer to a C string, or perhaps NULL */#define COMPARE_STRING_FIELD(fldname) \ do { \ if (!equalstr(a->fldname, b->fldname)) \ return false; \ } while (0)/* Macro for comparing string fields that might be NULL */#define equalstr(a, b) \ (((a) != NULL && (b) != NULL) ? (strcmp(a, b) == 0) : (a) == (b))/* Compare a field that is a pointer to a simple palloc'd object of size sz */#define COMPARE_POINTER_FIELD(fldname, sz) \ do { \ if (memcmp(a->fldname, b->fldname, (sz)) != 0) \ return false; \ } while (0)/* * Stuff from primnodes.h */static bool_equalAlias(Alias *a, Alias *b){ COMPARE_STRING_FIELD(aliasname); COMPARE_NODE_FIELD(colnames); return true;}static bool_equalRangeVar(RangeVar *a, RangeVar *b){ COMPARE_STRING_FIELD(catalogname); COMPARE_STRING_FIELD(schemaname); COMPARE_STRING_FIELD(relname); COMPARE_SCALAR_FIELD(inhOpt); COMPARE_SCALAR_FIELD(istemp); COMPARE_NODE_FIELD(alias); return true;}/* * We don't need an _equalExpr because Expr is an abstract supertype which * should never actually get instantiated. Also, since it has no common * fields except NodeTag, there's no need for a helper routine to factor * out comparing the common fields... */static bool_equalVar(Var *a, Var *b){ COMPARE_SCALAR_FIELD(varno); COMPARE_SCALAR_FIELD(varattno); COMPARE_SCALAR_FIELD(vartype); COMPARE_SCALAR_FIELD(vartypmod); COMPARE_SCALAR_FIELD(varlevelsup); COMPARE_SCALAR_FIELD(varnoold); COMPARE_SCALAR_FIELD(varoattno); return true;}static bool_equalConst(Const *a, Const *b){ COMPARE_SCALAR_FIELD(consttype); COMPARE_SCALAR_FIELD(constlen); COMPARE_SCALAR_FIELD(constisnull); COMPARE_SCALAR_FIELD(constbyval); /* * We treat all NULL constants of the same type as equal. Someday this * might need to change? But datumIsEqual doesn't work on nulls, so... */ if (a->constisnull) return true; return datumIsEqual(a->constvalue, b->constvalue, a->constbyval, a->constlen);}static bool_equalParam(Param *a, Param *b){ COMPARE_SCALAR_FIELD(paramkind); COMPARE_SCALAR_FIELD(paramtype); switch (a->paramkind) { case PARAM_NAMED: COMPARE_STRING_FIELD(paramname); break; case PARAM_NUM: case PARAM_EXEC: COMPARE_SCALAR_FIELD(paramid); break; default: elog(ERROR, "unrecognized paramkind: %d", a->paramkind); } return true;}static bool_equalAggref(Aggref *a, Aggref *b){ COMPARE_SCALAR_FIELD(aggfnoid); COMPARE_SCALAR_FIELD(aggtype); COMPARE_NODE_FIELD(target); COMPARE_SCALAR_FIELD(agglevelsup); COMPARE_SCALAR_FIELD(aggstar); COMPARE_SCALAR_FIELD(aggdistinct); return true;}static bool_equalArrayRef(ArrayRef *a, ArrayRef *b){ COMPARE_SCALAR_FIELD(refrestype); COMPARE_SCALAR_FIELD(refarraytype); COMPARE_SCALAR_FIELD(refelemtype); COMPARE_NODE_FIELD(refupperindexpr); COMPARE_NODE_FIELD(reflowerindexpr); COMPARE_NODE_FIELD(refexpr); COMPARE_NODE_FIELD(refassgnexpr); return true;}static bool_equalFuncExpr(FuncExpr *a, FuncExpr *b){ COMPARE_SCALAR_FIELD(funcid); COMPARE_SCALAR_FIELD(funcresulttype); COMPARE_SCALAR_FIELD(funcretset); /* * Special-case COERCE_DONTCARE, so that planner can build coercion nodes * that are equal() to both explicit and implicit coercions. */ if (a->funcformat != b->funcformat && a->funcformat != COERCE_DONTCARE && b->funcformat != COERCE_DONTCARE) return false; COMPARE_NODE_FIELD(args); return true;}static bool_equalOpExpr(OpExpr *a, OpExpr *b){ COMPARE_SCALAR_FIELD(opno); /* * Special-case opfuncid: it is allowable for it to differ if one node * contains zero and the other doesn't. This just means that the one node * isn't as far along in the parse/plan pipeline and hasn't had the * opfuncid cache filled yet. */ if (a->opfuncid != b->opfuncid && a->opfuncid != 0 && b->opfuncid != 0) return false; COMPARE_SCALAR_FIELD(opresulttype); COMPARE_SCALAR_FIELD(opretset); COMPARE_NODE_FIELD(args); return true;}static bool_equalDistinctExpr(DistinctExpr *a, DistinctExpr *b){ COMPARE_SCALAR_FIELD(opno); /* * Special-case opfuncid: it is allowable for it to differ if one node * contains zero and the other doesn't. This just means that the one node * isn't as far along in the parse/plan pipeline and hasn't had the * opfuncid cache filled yet. */ if (a->opfuncid != b->opfuncid && a->opfuncid != 0 && b->opfuncid != 0) return false; COMPARE_SCALAR_FIELD(opresulttype); COMPARE_SCALAR_FIELD(opretset); COMPARE_NODE_FIELD(args); return true;}static bool_equalScalarArrayOpExpr(ScalarArrayOpExpr *a, ScalarArrayOpExpr *b){ COMPARE_SCALAR_FIELD(opno); /* * Special-case opfuncid: it is allowable for it to differ if one node * contains zero and the other doesn't. This just means that the one node * isn't as far along in the parse/plan pipeline and hasn't had the * opfuncid cache filled yet. */ if (a->opfuncid != b->opfuncid && a->opfuncid != 0 && b->opfuncid != 0) return false; COMPARE_SCALAR_FIELD(useOr); COMPARE_NODE_FIELD(args); return true;}static bool_equalBoolExpr(BoolExpr *a, BoolExpr *b){ COMPARE_SCALAR_FIELD(boolop); COMPARE_NODE_FIELD(args); return true;}static bool_equalSubLink(SubLink *a, SubLink *b){ COMPARE_SCALAR_FIELD(subLinkType); COMPARE_SCALAR_FIELD(useOr); COMPARE_NODE_FIELD(lefthand); COMPARE_NODE_FIELD(operName); COMPARE_NODE_FIELD(operOids); COMPARE_NODE_FIELD(subselect); return true;}static bool_equalSubPlan(SubPlan *a, SubPlan *b){ COMPARE_SCALAR_FIELD(subLinkType); COMPARE_SCALAR_FIELD(useOr); COMPARE_NODE_FIELD(exprs); COMPARE_NODE_FIELD(paramIds); /* should compare plans, but have to settle for comparing plan IDs */ COMPARE_SCALAR_FIELD(plan_id); COMPARE_NODE_FIELD(rtable); COMPARE_SCALAR_FIELD(useHashTable); COMPARE_SCALAR_FIELD(unknownEqFalse); COMPARE_NODE_FIELD(setParam); COMPARE_NODE_FIELD(parParam); COMPARE_NODE_FIELD(args); return true;}static bool_equalFieldSelect(FieldSelect *a, FieldSelect *b){ COMPARE_NODE_FIELD(arg); COMPARE_SCALAR_FIELD(fieldnum); COMPARE_SCALAR_FIELD(resulttype); COMPARE_SCALAR_FIELD(resulttypmod); return true;}static bool_equalFieldStore(FieldStore *a, FieldStore *b){ COMPARE_NODE_FIELD(arg); COMPARE_NODE_FIELD(newvals); COMPARE_NODE_FIELD(fieldnums); COMPARE_SCALAR_FIELD(resulttype); return true;}static bool_equalRelabelType(RelabelType *a, RelabelType *b){ COMPARE_NODE_FIELD(arg); COMPARE_SCALAR_FIELD(resulttype); COMPARE_SCALAR_FIELD(resulttypmod); /* * Special-case COERCE_DONTCARE, so that planner can build coercion nodes * that are equal() to both explicit and implicit coercions. */ if (a->relabelformat != b->relabelformat && a->relabelformat != COERCE_DONTCARE && b->relabelformat != COERCE_DONTCARE) return false; return true;}static bool_equalConvertRowtypeExpr(ConvertRowtypeExpr *a, ConvertRowtypeExpr *b){ COMPARE_NODE_FIELD(arg); COMPARE_SCALAR_FIELD(resulttype); /* * Special-case COERCE_DONTCARE, so that planner can build coercion nodes * that are equal() to both explicit and implicit coercions. */ if (a->convertformat != b->convertformat && a->convertformat != COERCE_DONTCARE && b->convertformat != COERCE_DONTCARE) return false; return true;}static bool_equalCaseExpr(CaseExpr *a, CaseExpr *b){ COMPARE_SCALAR_FIELD(casetype); COMPARE_NODE_FIELD(arg); COMPARE_NODE_FIELD(args); COMPARE_NODE_FIELD(defresult); return true;}static bool_equalCaseWhen(CaseWhen *a, CaseWhen *b){ COMPARE_NODE_FIELD(expr); COMPARE_NODE_FIELD(result); return true;}static bool_equalCaseTestExpr(CaseTestExpr *a, CaseTestExpr *b){ COMPARE_SCALAR_FIELD(typeId); COMPARE_SCALAR_FIELD(typeMod); return true;}static bool_equalArrayExpr(ArrayExpr *a, ArrayExpr *b){ COMPARE_SCALAR_FIELD(array_typeid); COMPARE_SCALAR_FIELD(element_typeid); COMPARE_NODE_FIELD(elements); COMPARE_SCALAR_FIELD(multidims); return true;}static bool_equalRowExpr(RowExpr *a, RowExpr *b){ COMPARE_NODE_FIELD(args); COMPARE_SCALAR_FIELD(row_typeid); /* * Special-case COERCE_DONTCARE, so that planner can build coercion nodes * that are equal() to both explicit and implicit coercions. */ if (a->row_format != b->row_format && a->row_format != COERCE_DONTCARE && b->row_format != COERCE_DONTCARE) return false; return true;}static bool_equalCoalesceExpr(CoalesceExpr *a, CoalesceExpr *b){ COMPARE_SCALAR_FIELD(coalescetype); COMPARE_NODE_FIELD(args); return true;}static bool_equalMinMaxExpr(MinMaxExpr *a, MinMaxExpr *b){ COMPARE_SCALAR_FIELD(minmaxtype); COMPARE_SCALAR_FIELD(op); COMPARE_NODE_FIELD(args); return true;}static bool_equalNullIfExpr(NullIfExpr *a, NullIfExpr *b){ COMPARE_SCALAR_FIELD(opno); /* * Special-case opfuncid: it is allowable for it to differ if one node * contains zero and the other doesn't. This just means that the one node * isn't as far along in the parse/plan pipeline and hasn't had the * opfuncid cache filled yet. */ if (a->opfuncid != b->opfuncid && a->opfuncid != 0 && b->opfuncid != 0) return false; COMPARE_SCALAR_FIELD(opresulttype); COMPARE_SCALAR_FIELD(opretset); COMPARE_NODE_FIELD(args); return true;}static bool_equalNullTest(NullTest *a, NullTest *b){ COMPARE_NODE_FIELD(arg); COMPARE_SCALAR_FIELD(nulltesttype); return true;}static bool_equalBooleanTest(BooleanTest *a, BooleanTest *b){ COMPARE_NODE_FIELD(arg); COMPARE_SCALAR_FIELD(booltesttype); return true;}static bool_equalCoerceToDomain(CoerceToDomain *a, CoerceToDomain *b){ COMPARE_NODE_FIELD(arg); COMPARE_SCALAR_FIELD(resulttype); COMPARE_SCALAR_FIELD(resulttypmod); /* * Special-case COERCE_DONTCARE, so that planner can build coercion nodes * that are equal() to both explicit and implicit coercions. */ if (a->coercionformat != b->coercionformat && a->coercionformat != COERCE_DONTCARE && b->coercionformat != COERCE_DONTCARE) return false; return true;}static bool_equalCoerceToDomainValue(CoerceToDomainValue *a, CoerceToDomainValue *b){ COMPARE_SCALAR_FIELD(typeId); COMPARE_SCALAR_FIELD(typeMod); return true;}static bool_equalSetToDefault(SetToDefault *a, SetToDefault *b){ COMPARE_SCALAR_FIELD(typeId); COMPARE_SCALAR_FIELD(typeMod); return true;}static bool_equalTargetEntry(TargetEntry *a, TargetEntry *b){ COMPARE_NODE_FIELD(expr); COMPARE_SCALAR_FIELD(resno); COMPARE_STRING_FIELD(resname); COMPARE_SCALAR_FIELD(ressortgroupref); COMPARE_SCALAR_FIELD(resorigtbl); COMPARE_SCALAR_FIELD(resorigcol); COMPARE_SCALAR_FIELD(resjunk); return true;}static bool_equalRangeTblRef(RangeTblRef *a, RangeTblRef *b){ COMPARE_SCALAR_FIELD(rtindex); return true;}static bool_equalJoinExpr(JoinExpr *a, JoinExpr *b){ COMPARE_SCALAR_FIELD(jointype); COMPARE_SCALAR_FIELD(isNatural); COMPARE_NODE_FIELD(larg); COMPARE_NODE_FIELD(rarg); COMPARE_NODE_FIELD(using);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -