* Build equality expression that can be evaluated using ExecQual(), returning * true if the expression context's inner/outer tuple are NOT DISTINCT. I.e * two nulls match, a null and a not-null don't match. * * desc: tuple descriptor of the to-be-compared tuples * numCols: the number of attributes to be examined * keyColIdx: array of attribute column numbers * eqFunctions: array of function
| 4032 | * parent: parent executor node |
| 4033 | */ |
| 4034 | ExprState * |
| 4035 | ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, |
| 4036 | const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, |
| 4037 | int numCols, |
| 4038 | const AttrNumber *keyColIdx, |
| 4039 | const Oid *eqfunctions, |
| 4040 | const Oid *collations, |
| 4041 | PlanState *parent) |
| 4042 | { |
| 4043 | ExprState *state = makeNode(ExprState); |
| 4044 | ExprEvalStep scratch = {0}; |
| 4045 | int maxatt = -1; |
| 4046 | List *adjust_jumps = NIL; |
| 4047 | ListCell *lc; |
| 4048 | |
| 4049 | /* |
| 4050 | * When no columns are actually compared, the result's always true. See |
| 4051 | * special case in ExecQual(). |
| 4052 | */ |
| 4053 | if (numCols == 0) |
| 4054 | return NULL; |
| 4055 | |
| 4056 | state->expr = NULL; |
| 4057 | state->flags = EEO_FLAG_IS_QUAL; |
| 4058 | state->parent = parent; |
| 4059 | |
| 4060 | scratch.resvalue = &state->resvalue; |
| 4061 | scratch.resnull = &state->resnull; |
| 4062 | |
| 4063 | /* compute max needed attribute */ |
| 4064 | for (int natt = 0; natt < numCols; natt++) |
| 4065 | { |
| 4066 | int attno = keyColIdx[natt]; |
| 4067 | |
| 4068 | if (attno > maxatt) |
| 4069 | maxatt = attno; |
| 4070 | } |
| 4071 | Assert(maxatt >= 0); |
| 4072 | |
| 4073 | /* push deform steps */ |
| 4074 | scratch.opcode = EEOP_INNER_FETCHSOME; |
| 4075 | scratch.d.fetch.last_var = maxatt; |
| 4076 | scratch.d.fetch.fixed = false; |
| 4077 | scratch.d.fetch.known_desc = ldesc; |
| 4078 | scratch.d.fetch.kind = lops; |
| 4079 | if (ExecComputeSlotInfo(state, &scratch)) |
| 4080 | ExprEvalPushStep(state, &scratch); |
| 4081 | |
| 4082 | scratch.opcode = EEOP_OUTER_FETCHSOME; |
| 4083 | scratch.d.fetch.last_var = maxatt; |
| 4084 | scratch.d.fetch.fixed = false; |
| 4085 | scratch.d.fetch.known_desc = rdesc; |
| 4086 | scratch.d.fetch.kind = rops; |
| 4087 | if (ExecComputeSlotInfo(state, &scratch)) |
| 4088 | ExprEvalPushStep(state, &scratch); |
| 4089 | |
| 4090 | /* |
| 4091 | * Start comparing at the last field (least significant sort key). That's |
no test coverage detected