📄 parse_oper.c
字号:
return (ncandidates == 1) ? candidates->args : NULL;} /* oper_select_candidate() *//* oper_exact() * Given operator, and arguments, return oper struct. * Inputs: * arg1, arg2: Type IDs */Operatoroper_exact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWarnings){ HeapTuple tup; Node *tree; /* Unspecified type for one of the arguments? then use the other */ if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid)) arg1 = arg2; else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid)) arg2 = arg1; tup = SearchSysCacheTuple(OPRNAME, PointerGetDatum(op), ObjectIdGetDatum(arg1), ObjectIdGetDatum(arg2), CharGetDatum('b')); /* * Did not find anything? then try flipping arguments on a commutative * operator... */ if (!HeapTupleIsValid(tup) && (arg1 != arg2)) { tup = SearchSysCacheTuple(OPRNAME, PointerGetDatum(op), ObjectIdGetDatum(arg2), ObjectIdGetDatum(arg1), CharGetDatum('b')); if (HeapTupleIsValid(tup)) { Form_pg_operator opform; opform = (Form_pg_operator) GETSTRUCT(tup); if (opform->oprcom == tup->t_data->t_oid) { if ((ltree != NULL) && (rtree != NULL)) { tree = *ltree; *ltree = *rtree; *rtree = tree; } } /* disable for now... - thomas 1998-05-14 */ else tup = NULL; } if (!HeapTupleIsValid(tup) && (!noWarnings)) op_error(op, arg1, arg2); } return tup;} /* oper_exact() *//* oper_inexact() * Given operator, types of arg1, and arg2, return oper struct. * Inputs: * arg1, arg2: Type IDs */Operatoroper_inexact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWarnings){ HeapTuple tup; CandidateList candidates; int ncandidates; Oid *targetOids; Oid inputOids[2]; /* Unspecified type for one of the arguments? then use the other */ if (arg2 == InvalidOid) arg2 = arg1; if (arg1 == InvalidOid) arg1 = arg2; ncandidates = binary_oper_get_candidates(op, arg1, arg2, &candidates); /* No operators found? Then throw error or return null... */ if (ncandidates == 0) { if (!noWarnings) op_error(op, arg1, arg2); return NULL; } /* Or found exactly one? Then proceed... */ else if (ncandidates == 1) { tup = SearchSysCacheTuple(OPRNAME, PointerGetDatum(op), ObjectIdGetDatum(candidates->args[0]), ObjectIdGetDatum(candidates->args[1]), CharGetDatum('b')); Assert(HeapTupleIsValid(tup)); } /* Otherwise, multiple operators of the desired types found... */ else { inputOids[0] = arg1; inputOids[1] = arg2; targetOids = oper_select_candidate(2, inputOids, candidates); if (targetOids != NULL) { tup = SearchSysCacheTuple(OPRNAME, PointerGetDatum(op), ObjectIdGetDatum(targetOids[0]), ObjectIdGetDatum(targetOids[1]), CharGetDatum('b')); } else tup = NULL; /* Could not choose one, for whatever reason... */ if (!HeapTupleIsValid(tup)) { if (!noWarnings) { elog(ERROR, "Unable to identify an operator '%s' for types '%s' and '%s'" "\n\tYou will have to retype this query using an explicit cast", op, typeTypeName(typeidType(arg1)), typeTypeName(typeidType(arg2))); } return NULL; } } return (Operator) tup;} /* oper_inexact() *//* oper() * Given operator, types of arg1, and arg2, return oper struct. * Inputs: * arg1, arg2: Type IDs */Operatoroper(char *opname, Oid ltypeId, Oid rtypeId, bool noWarnings){ HeapTuple tup; /* check for exact match on this operator... */ if (HeapTupleIsValid(tup = oper_exact(opname, ltypeId, rtypeId, NULL, NULL, TRUE))) { } /* try to find a match on likely candidates... */ else if (HeapTupleIsValid(tup = oper_inexact(opname, ltypeId, rtypeId, NULL, NULL, TRUE))) { } else if (!noWarnings) { elog(ERROR, "Unable to identify a binary operator '%s' for types %s and %s", opname, typeTypeName(typeidType(ltypeId)), typeTypeName(typeidType(rtypeId))); } return (Operator) tup;} /* oper() *//* unary_oper_get_candidates() * given opname and typeId, find all possible types for which * a right/left unary operator named opname exists, * such that typeId can be coerced to it */static intunary_oper_get_candidates(char *op, Oid typeId, CandidateList *candidates, char rightleft){ CandidateList current_candidate; Relation pg_operator_desc; HeapScanDesc pg_operator_scan; HeapTuple tup; Form_pg_operator oper; int ncandidates = 0; static ScanKeyData opKey[2] = { {0, Anum_pg_operator_oprname, F_NAMEEQ}, {0, Anum_pg_operator_oprkind, F_CHAREQ}}; *candidates = NULL; fmgr_info(F_NAMEEQ, (FmgrInfo *) &opKey[0].sk_func); opKey[0].sk_argument = NameGetDatum(op); fmgr_info(F_CHAREQ, (FmgrInfo *) &opKey[1].sk_func); opKey[1].sk_argument = CharGetDatum(rightleft); pg_operator_desc = heap_openr(OperatorRelationName); pg_operator_scan = heap_beginscan(pg_operator_desc, 0, SnapshotSelf, /* ??? */ 2, opKey); while (HeapTupleIsValid(tup = heap_getnext(pg_operator_scan, 0))) { current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList)); current_candidate->args = (Oid *) palloc(sizeof(Oid)); oper = (Form_pg_operator) GETSTRUCT(tup); if (rightleft == 'r') current_candidate->args[0] = oper->oprleft; else current_candidate->args[0] = oper->oprright; current_candidate->next = *candidates; *candidates = current_candidate; ncandidates++; } heap_endscan(pg_operator_scan); heap_close(pg_operator_desc); return ncandidates;} /* unary_oper_get_candidates() *//* Given unary right-side operator (operator on right), return oper struct *//* arg-- type id */Operatorright_oper(char *op, Oid arg){ HeapTuple tup; CandidateList candidates; int ncandidates; Oid *targetOid; tup = SearchSysCacheTuple(OPRNAME, PointerGetDatum(op), ObjectIdGetDatum(arg), ObjectIdGetDatum(InvalidOid), CharGetDatum('r')); if (!HeapTupleIsValid(tup)) { ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'r'); if (ncandidates == 0) { elog(ERROR, "Can't find right op '%s' for type %u", op, arg); return NULL; } else if (ncandidates == 1) { tup = SearchSysCacheTuple(OPRNAME, PointerGetDatum(op), ObjectIdGetDatum(candidates->args[0]), ObjectIdGetDatum(InvalidOid), CharGetDatum('r')); Assert(HeapTupleIsValid(tup)); } else { targetOid = oper_select_candidate(1, &arg, candidates); if (targetOid != NULL) { tup = SearchSysCacheTuple(OPRNAME, PointerGetDatum(op), ObjectIdGetDatum(InvalidOid), ObjectIdGetDatum(*targetOid), CharGetDatum('r')); } else tup = NULL; if (!HeapTupleIsValid(tup)) { elog(ERROR, "Unable to convert right operator '%s' from type '%s'", op, typeidTypeName(arg)); return NULL; } } } return (Operator) tup;} /* right_oper() *//* Given unary left-side operator (operator on left), return oper struct *//* arg--type id */Operatorleft_oper(char *op, Oid arg){ HeapTuple tup; CandidateList candidates; int ncandidates; Oid *targetOid; tup = SearchSysCacheTuple(OPRNAME, PointerGetDatum(op), ObjectIdGetDatum(InvalidOid), ObjectIdGetDatum(arg), CharGetDatum('l')); if (!HeapTupleIsValid(tup)) { ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'l'); if (ncandidates == 0) { elog(ERROR, "Can't find left op '%s' for type %u", op, arg); return NULL; } else if (ncandidates == 1) { tup = SearchSysCacheTuple(OPRNAME, PointerGetDatum(op), ObjectIdGetDatum(InvalidOid), ObjectIdGetDatum(candidates->args[0]), CharGetDatum('l')); Assert(HeapTupleIsValid(tup)); } else { targetOid = oper_select_candidate(1, &arg, candidates); if (targetOid != NULL) { tup = SearchSysCacheTuple(OPRNAME, PointerGetDatum(op), ObjectIdGetDatum(InvalidOid), ObjectIdGetDatum(*targetOid), CharGetDatum('l')); } else tup = NULL; if (!HeapTupleIsValid(tup)) { elog(ERROR, "Unable to convert left operator '%s' from type '%s'", op, typeidTypeName(arg)); return NULL; } } } return (Operator) tup;} /* left_oper() *//* op_error() * Give a somewhat useful error message when the operator for two types * is not found. */static voidop_error(char *op, Oid arg1, Oid arg2){ Type tp1 = NULL, tp2 = NULL; if (typeidIsValid(arg1)) tp1 = typeidType(arg1); else { elog(ERROR, "Left hand side of operator '%s' has an unknown type" "\n\tProbably a bad attribute name", op); } if (typeidIsValid(arg2)) tp2 = typeidType(arg2); else { elog(ERROR, "Right hand side of operator %s has an unknown type" "\n\tProbably a bad attribute name", op); } elog(ERROR, "There is no operator '%s' for types '%s' and '%s'" "\n\tYou will either have to retype this query using an explicit cast," "\n\tor you will have to define the operator using CREATE OPERATOR", op, typeTypeName(tp1), typeTypeName(tp2));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -