/* * init_scankeys * * Initialize the scan keys. */ static void init_scankeys(TupleDesc tupleDesc, int nkeys, ScanKey scanKeys, StrategyNumber *strategyNumbers) { int keyNo; Assert(nkeys <= tupleDesc->natts); for (keyNo = 0; keyNo < nkeys; keyNo ++) { ScanKey scanKey = (ScanKey)(((char *)scanKeys) + keyNo * sizeof(ScanKeyData)); RegProcedure opfuncid; StrategyNumber strategyNumber = strategyNumbers[keyNo]; Assert(strategyNumber <= BTMaxStrategyNumber && strategyNumber != InvalidStrategy); if (strategyNumber == BTEqualStrategyNumber) { opfuncid = equality_oper_funcid(tupleDesc->attrs[keyNo]->atttypid); ScanKeyEntryInitialize(scanKey, 0, /* sk_flag */ keyNo + 1, /* attribute number to scan */ BTEqualStrategyNumber, /* strategy */ InvalidOid, /* strategy subtype */ opfuncid, /* reg proc to use */ 0 /* constant */ ); } else { Oid gtOid, leOid; gtOid = reverse_ordering_oper_opid(tupleDesc->attrs[keyNo]->atttypid); leOid = get_negator(gtOid); opfuncid = get_opcode(leOid); ScanKeyEntryInitialize(scanKey, 0, /* sk_flag */ keyNo + 1, /* attribute number to scan */ strategyNumber, /* strategy */ InvalidOid, /* strategy subtype */ opfuncid, /* reg proc to use */ 0 /* constant */ ); } } }
/* * get_op_btree_interpretation * Given an operator's OID, find out which btree opclasses it belongs to, * and what strategy number it has within each one. The results are * returned as an OID list and a parallel integer list. * * In addition to the normal btree operators, we consider a <> operator to be * a "member" of an opclass if its negator is the opclass' equality operator. * ROWCOMPARE_NE is returned as the strategy number for this case. */ void get_op_btree_interpretation(Oid opno, List **opclasses, List **opstrats) { Oid lefttype, righttype; CatCList *catlist; bool op_negated; int i; *opclasses = NIL; *opstrats = NIL; /* * Get the nominal left-hand input type of the operator; we will ignore * opclasses that don't have that as the expected input datatype. This is * a kluge to avoid being confused by binary-compatible opclasses (such as * text_ops and varchar_ops, which share the same operators). */ op_input_types(opno, &lefttype, &righttype); Assert(OidIsValid(lefttype)); /* * Find all the pg_amop entries containing the operator. */ catlist = SearchSysCacheList(AMOPOPID, 1, ObjectIdGetDatum(opno), 0, 0, 0); /* * If we can't find any opclass containing the op, perhaps it is a <> * operator. See if it has a negator that is in an opclass. */ op_negated = false; if (catlist->n_members == 0) { Oid op_negator = get_negator(opno); if (OidIsValid(op_negator)) { op_negated = true; ReleaseSysCacheList(catlist); catlist = SearchSysCacheList(AMOPOPID, 1, ObjectIdGetDatum(op_negator), 0, 0, 0); } } /* Now search the opclasses */ for (i = 0; i < catlist->n_members; i++) { HeapTuple op_tuple = &catlist->members[i]->tuple; Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple); Oid opclass_id; StrategyNumber op_strategy; opclass_id = op_form->amopclaid; /* must be btree */ if (!opclass_is_btree(opclass_id)) continue; /* must match operator input type exactly */ if (get_opclass_input_type(opclass_id) != lefttype) continue; /* Get the operator's btree strategy number */ op_strategy = (StrategyNumber) op_form->amopstrategy; Assert(op_strategy >= 1 && op_strategy <= 5); if (op_negated) { /* Only consider negators that are = */ if (op_strategy != BTEqualStrategyNumber) continue; op_strategy = ROWCOMPARE_NE; } *opclasses = lappend_oid(*opclasses, opclass_id); *opstrats = lappend_int(*opstrats, op_strategy); } ReleaseSysCacheList(catlist); }