* cdbpathlocus_for_insert * Build DistributionKeys that match the policy of the given relation. * * This is used for INSERT or split UPDATE, where 'pathtarget' the target list of * subpath that's producing the rows to be inserted/updated. * * As a side-effect, this assigns sortgrouprefs to any volatile expressions * that are used in the distribution keys. * * If the target table is dist
| 218 | * is always partitioned type. |
| 219 | */ |
| 220 | CdbPathLocus |
| 221 | cdbpathlocus_for_insert(PlannerInfo *root, GpPolicy *policy, |
| 222 | PathTarget *pathtarget) |
| 223 | { |
| 224 | CdbPathLocus targetLocus; |
| 225 | |
| 226 | Assert(policy->ptype == POLICYTYPE_PARTITIONED); |
| 227 | |
| 228 | /* rows are distributed by hashing on specified columns */ |
| 229 | List *distkeys = NIL; |
| 230 | Index maxRef = 0; |
| 231 | bool failed = false; |
| 232 | |
| 233 | for (int i = 0; i < list_length(pathtarget->exprs); i++) |
| 234 | maxRef = Max(maxRef, pathtarget->sortgrouprefs[i]); |
| 235 | |
| 236 | for (int i = 0; i < policy->nattrs; ++i) |
| 237 | { |
| 238 | AttrNumber attno = policy->attrs[i]; |
| 239 | DistributionKey *cdistkey; |
| 240 | Expr *expr; |
| 241 | Oid typeoid; |
| 242 | Oid eqopoid; |
| 243 | Oid opfamily = get_opclass_family(policy->opclasses[i]); |
| 244 | Oid opcintype = get_opclass_input_type(policy->opclasses[i]); |
| 245 | List *mergeopfamilies; |
| 246 | EquivalenceClass *eclass; |
| 247 | |
| 248 | expr = list_nth(pathtarget->exprs, attno - 1); |
| 249 | typeoid = exprType((Node *) expr); |
| 250 | |
| 251 | /* |
| 252 | * Look up the equality operator corresponding to the distribution |
| 253 | * opclass. |
| 254 | */ |
| 255 | eqopoid = get_opfamily_member(opfamily, opcintype, opcintype, 1); |
| 256 | |
| 257 | if (pathtarget->sortgrouprefs[attno - 1] == 0 && |
| 258 | contain_volatile_functions((Node *) expr)) |
| 259 | { |
| 260 | /* |
| 261 | * sortgrouprefs should never be zero if the expression is volatile! |
| 262 | */ |
| 263 | pathtarget->sortgrouprefs[attno - 1] = ++maxRef; |
| 264 | } |
| 265 | |
| 266 | /* |
| 267 | * Get Oid of the sort operator that would be used for a sort-merge |
| 268 | * equijoin on a pair of exprs of the same type. |
| 269 | */ |
| 270 | if (failed || eqopoid == InvalidOid || !op_mergejoinable(eqopoid, typeoid)) |
| 271 | { |
| 272 | /* |
| 273 | * It's in principle possible that there is no b-tree operator family |
| 274 | * that's compatible with the hash opclass's equality operator. However, |
| 275 | * we cannot construct an EquivalenceClass without the b-tree operator |
| 276 | * family, and therefore cannot build a DistributionKey to represent it. |
| 277 | * Bail out. (That makes the distribution key rather useless.) |
no test coverage detected