PostgreSQL Source Code git master
Loading...
Searching...
No Matches
parse_oper.h File Reference
#include "access/htup.h"
#include "nodes/parsenodes.h"
#include "parser/parse_node.h"
Include dependency graph for parse_oper.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef HeapTuple Operator
 

Functions

Oid LookupOperName (ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
 
Oid LookupOperWithArgs (ObjectWithArgs *oper, bool noError)
 
Operator oper (ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
 
Operator left_oper (ParseState *pstate, List *op, Oid arg, bool noError, int location)
 
Operator compatible_oper (ParseState *pstate, List *op, Oid arg1, Oid arg2, bool noError, int location)
 
const charop_signature_string (List *op, Oid arg1, Oid arg2)
 
void get_sort_group_operators (Oid argtype, bool needLT, bool needEQ, bool needGT, Oid *ltOpr, Oid *eqOpr, Oid *gtOpr, bool *isHashable)
 
Oid compatible_oper_opid (List *op, Oid arg1, Oid arg2, bool noError)
 
Oid oprid (Operator op)
 
Oid oprfuncid (Operator op)
 
Exprmake_op (ParseState *pstate, List *opname, Node *ltree, Node *rtree, Node *last_srf, int location)
 
Exprmake_scalar_array_op (ParseState *pstate, List *opname, bool useOr, Node *ltree, Node *rtree, int location)
 

Typedef Documentation

◆ Operator

Definition at line 22 of file parse_oper.h.

Function Documentation

◆ compatible_oper()

Operator compatible_oper ( ParseState pstate,
List op,
Oid  arg1,
Oid  arg2,
bool  noError,
int  location 
)
extern

Definition at line 454 of file parse_oper.c.

456{
459
460 /* oper() will find the best available match */
461 optup = oper(pstate, op, arg1, arg2, noError, location);
462 if (optup == (Operator) NULL)
463 return (Operator) NULL; /* must be noError case */
464
465 /* but is it good enough? */
467 if (IsBinaryCoercible(arg1, opform->oprleft) &&
468 IsBinaryCoercible(arg2, opform->oprright))
469 return optup;
470
471 /* nope... */
473
474 if (!noError)
477 errmsg("operator requires run-time type coercion: %s",
479 parser_errposition(pstate, location)));
480
481 return (Operator) NULL;
482}
int errcode(int sqlerrcode)
Definition elog.c:874
int errmsg(const char *fmt,...)
Definition elog.c:1093
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
static void * GETSTRUCT(const HeapTupleData *tuple)
bool IsBinaryCoercible(Oid srctype, Oid targettype)
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition parse_oper.c:372
const char * op_signature_string(List *op, Oid arg1, Oid arg2)
Definition parse_oper.c:608
END_CATALOG_STRUCT typedef FormData_pg_operator * Form_pg_operator
Definition pg_operator.h:87
static int fb(int x)
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264

References ereport, errcode(), errmsg(), ERROR, fb(), Form_pg_operator, GETSTRUCT(), IsBinaryCoercible(), op_signature_string(), oper(), parser_errposition(), and ReleaseSysCache().

Referenced by compatible_oper_opid().

◆ compatible_oper_opid()

Oid compatible_oper_opid ( List op,
Oid  arg1,
Oid  arg2,
bool  noError 
)
extern

Definition at line 491 of file parse_oper.c.

492{
494 Oid result;
495
497 if (optup != NULL)
498 {
499 result = oprid(optup);
501 return result;
502 }
503 return InvalidOid;
504}
Oid oprid(Operator op)
Definition parse_oper.c:240
Operator compatible_oper(ParseState *pstate, List *op, Oid arg1, Oid arg2, bool noError, int location)
Definition parse_oper.c:454
#define InvalidOid
unsigned int Oid

References compatible_oper(), fb(), InvalidOid, oprid(), and ReleaseSysCache().

Referenced by addTargetToSortList(), and ComputeIndexAttrs().

◆ get_sort_group_operators()

void get_sort_group_operators ( Oid  argtype,
bool  needLT,
bool  needEQ,
bool  needGT,
Oid ltOpr,
Oid eqOpr,
Oid gtOpr,
bool isHashable 
)
extern

Definition at line 182 of file parse_oper.c.

186{
187 TypeCacheEntry *typentry;
188 int cache_flags;
189 Oid lt_opr;
190 Oid eq_opr;
191 Oid gt_opr;
192 bool hashable;
193
194 /*
195 * Look up the operators using the type cache.
196 *
197 * Note: the search algorithm used by typcache.c ensures that the results
198 * are consistent, ie all from matching opclasses.
199 */
200 if (isHashable != NULL)
203 else
205
206 typentry = lookup_type_cache(argtype, cache_flags);
207 lt_opr = typentry->lt_opr;
208 eq_opr = typentry->eq_opr;
209 gt_opr = typentry->gt_opr;
210 hashable = OidIsValid(typentry->hash_proc);
211
212 /* Report errors if needed */
213 if ((needLT && !OidIsValid(lt_opr)) ||
214 (needGT && !OidIsValid(gt_opr)))
217 errmsg("could not identify an ordering operator for type %s",
218 format_type_be(argtype)),
219 errhint("Use an explicit ordering operator or modify the query.")));
220 if (needEQ && !OidIsValid(eq_opr))
223 errmsg("could not identify an equality operator for type %s",
224 format_type_be(argtype))));
225
226 /* Return results as needed */
227 if (ltOpr)
228 *ltOpr = lt_opr;
229 if (eqOpr)
230 *eqOpr = eq_opr;
231 if (gtOpr)
232 *gtOpr = gt_opr;
233 if (isHashable)
234 *isHashable = hashable;
235}
#define OidIsValid(objectId)
Definition c.h:800
int errhint(const char *fmt,...) pg_attribute_printf(1
char * format_type_be(Oid type_oid)
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:389
#define TYPECACHE_EQ_OPR
Definition typcache.h:138
#define TYPECACHE_GT_OPR
Definition typcache.h:140
#define TYPECACHE_LT_OPR
Definition typcache.h:139
#define TYPECACHE_HASH_PROC
Definition typcache.h:142

References TypeCacheEntry::eq_opr, ereport, errcode(), errhint(), errmsg(), ERROR, fb(), format_type_be(), TypeCacheEntry::gt_opr, TypeCacheEntry::hash_proc, lookup_type_cache(), TypeCacheEntry::lt_opr, OidIsValid, TYPECACHE_EQ_OPR, TYPECACHE_GT_OPR, TYPECACHE_HASH_PROC, and TYPECACHE_LT_OPR.

Referenced by addTargetToGroupList(), addTargetToSortList(), init_grouping_targets(), makeSortGroupClauseForSetOp(), and std_typanalyze().

◆ left_oper()

Operator left_oper ( ParseState pstate,
List op,
Oid  arg,
bool  noError,
int  location 
)
extern

Definition at line 522 of file parse_oper.c.

523{
524 Oid operOid;
526 bool key_ok;
527 int fgc_flags = 0;
530
531 /*
532 * Try to find the mapping in the lookaside cache.
533 */
534 key_ok = make_oper_cache_key(pstate, &key, op, InvalidOid, arg, location);
535
536 if (key_ok)
537 {
539 if (OidIsValid(operOid))
540 {
543 return (Operator) tup;
544 }
545 }
546
547 /*
548 * First try for an "exact" match.
549 */
551 if (!OidIsValid(operOid))
552 {
553 /*
554 * Otherwise, search for the most suitable candidate.
555 */
557
558 /* Get prefix operators of given name */
559 clist = OpernameGetCandidates(op, 'l', false, &fgc_flags);
560
561 /* No operators found? Then fail... */
562 if (clist != NULL)
563 {
564 /*
565 * The returned list has args in the form (0, oprright). Move the
566 * useful data into args[0] to keep oper_select_candidate simple.
567 * XXX we are assuming here that we may scribble on the list!
568 */
570
571 for (clisti = clist; clisti != NULL; clisti = clisti->next)
572 {
573 clisti->args[0] = clisti->args[1];
574 }
575
576 /*
577 * We must run oper_select_candidate even if only one candidate,
578 * otherwise we may falsely return a non-type-compatible operator.
579 */
581 }
582 }
583
584 if (OidIsValid(operOid))
586
588 {
589 if (key_ok)
591 }
592 else if (!noError)
593 op_error(pstate, op, InvalidOid, arg,
594 fdresult, fgc_flags, location);
595
596 return (Operator) tup;
597}
Datum arg
Definition elog.c:1322
#define HeapTupleIsValid(tuple)
Definition htup.h:78
Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
Definition namespace.c:1834
FuncCandidateList OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok, int *fgc_flags)
Definition namespace.c:1947
FuncDetailCode
Definition parse_func.h:23
@ FUNCDETAIL_NOTFOUND
Definition parse_func.h:24
static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid)
static FuncDetailCode oper_select_candidate(int nargs, Oid *input_typeids, FuncCandidateList candidates, Oid *operOid)
Definition parse_oper.c:314
static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId, int location)
Definition parse_oper.c:981
static void op_error(ParseState *pstate, List *op, Oid arg1, Oid arg2, FuncDetailCode fdresult, int fgc_flags, int location)
Definition parse_oper.c:628
static Oid find_oper_cache_entry(OprCacheKey *key)
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
Oid args[FLEXIBLE_ARRAY_MEMBER]
Definition namespace.h:39
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:220

References arg, _FuncCandidateList::args, fb(), find_oper_cache_entry(), FUNCDETAIL_NOTFOUND, HeapTupleIsValid, InvalidOid, make_oper_cache_entry(), make_oper_cache_key(), ObjectIdGetDatum(), OidIsValid, op_error(), oper_select_candidate(), OpernameGetCandidates(), OpernameGetOprid(), and SearchSysCache1().

Referenced by generate_operator_name(), and make_op().

◆ LookupOperName()

Oid LookupOperName ( ParseState pstate,
List opername,
Oid  oprleft,
Oid  oprright,
bool  noError,
int  location 
)
extern

Definition at line 101 of file parse_oper.c.

103{
104 Oid result;
105
106 result = OpernameGetOprid(opername, oprleft, oprright);
107 if (OidIsValid(result))
108 return result;
109
110 /* we don't use op_error here because only an exact match is wanted */
111 if (!noError)
112 {
113 if (!OidIsValid(oprright))
116 errmsg("postfix operators are not supported"),
117 parser_errposition(pstate, location)));
118
121 errmsg("operator does not exist: %s",
122 op_signature_string(opername, oprleft, oprright)),
123 parser_errposition(pstate, location)));
124 }
125
126 return InvalidOid;
127}

References ereport, errcode(), errmsg(), ERROR, fb(), InvalidOid, OidIsValid, op_signature_string(), OpernameGetOprid(), and parser_errposition().

Referenced by AggregateCreate(), DefineOpClass(), LookupOperWithArgs(), and OperatorLookup().

◆ LookupOperWithArgs()

Oid LookupOperWithArgs ( ObjectWithArgs oper,
bool  noError 
)
extern

Definition at line 135 of file parse_oper.c.

136{
137 TypeName *oprleft,
138 *oprright;
139 Oid leftoid,
140 rightoid;
141
142 Assert(list_length(oper->objargs) == 2);
143 oprleft = linitial_node(TypeName, oper->objargs);
144 oprright = lsecond_node(TypeName, oper->objargs);
145
146 if (oprleft == NULL)
148 else
150
151 if (oprright == NULL)
153 else
155
156 return LookupOperName(NULL, oper->objname, leftoid, rightoid,
157 noError, -1);
158}
#define Assert(condition)
Definition c.h:885
Oid LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
Definition parse_oper.c:101
Oid LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, bool missing_ok)
Definition parse_type.c:232
static int list_length(const List *l)
Definition pg_list.h:152
#define linitial_node(type, l)
Definition pg_list.h:181
#define lsecond_node(type, l)
Definition pg_list.h:186

References Assert, fb(), InvalidOid, linitial_node, list_length(), LookupOperName(), LookupTypeNameOid(), lsecond_node, and oper().

Referenced by AlterOperator(), AlterOpFamilyAdd(), DefineOpClass(), and get_object_address().

◆ make_op()

Expr * make_op ( ParseState pstate,
List opname,
Node ltree,
Node rtree,
Node last_srf,
int  location 
)
extern

Definition at line 704 of file parse_oper.c.

706{
707 Oid ltypeId,
708 rtypeId;
713 int nargs;
714 List *args;
715 Oid rettype;
716 OpExpr *result;
717
718 /* Check it's not a postfix operator */
719 if (rtree == NULL)
722 errmsg("postfix operators are not supported")));
723
724 /* Select the operator */
725 if (ltree == NULL)
726 {
727 /* prefix operator */
730 tup = left_oper(pstate, opname, rtypeId, false, location);
731 }
732 else
733 {
734 /* otherwise, binary operator */
737 tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
738 }
739
741
742 /* Check it's not a shell */
743 if (!RegProcedureIsValid(opform->oprcode))
746 errmsg("operator is only a shell: %s",
748 opform->oprleft,
749 opform->oprright)),
750 parser_errposition(pstate, location)));
751
752 /* Do typecasting and build the expression tree */
753 if (ltree == NULL)
754 {
755 /* prefix operator */
758 declared_arg_types[0] = opform->oprright;
759 nargs = 1;
760 }
761 else
762 {
763 /* otherwise, binary operator */
767 declared_arg_types[0] = opform->oprleft;
768 declared_arg_types[1] = opform->oprright;
769 nargs = 2;
770 }
771
772 /*
773 * enforce consistency with polymorphic argument and return types,
774 * possibly adjusting return type or declared_arg_types (which will be
775 * used as the cast destination by make_fn_arguments)
776 */
779 nargs,
780 opform->oprresult,
781 false);
782
783 /* perform the necessary typecasting of arguments */
785
786 /* and build the expression node */
787 result = makeNode(OpExpr);
788 result->opno = oprid(tup);
789 result->opfuncid = opform->oprcode;
790 result->opresulttype = rettype;
791 result->opretset = get_func_retset(opform->oprcode);
792 /* opcollid and inputcollid will be set by parse_collate.c */
793 result->args = args;
794 result->location = location;
795
796 /* if it returns a set, check that's OK */
797 if (result->opretset)
798 {
799 check_srf_call_placement(pstate, last_srf, location);
800 /* ... and remember it for error checks at higher levels */
801 pstate->p_last_srf = (Node *) result;
802 }
803
805
806 return (Expr *) result;
807}
#define RegProcedureIsValid(p)
Definition c.h:804
bool get_func_retset(Oid funcid)
Definition lsyscache.c:1892
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
#define makeNode(_type_)
Definition nodes.h:161
Oid enforce_generic_type_consistency(const Oid *actual_arg_types, Oid *declared_arg_types, int nargs, Oid rettype, bool allow_poly)
void make_fn_arguments(ParseState *pstate, List *fargs, Oid *actual_arg_types, Oid *declared_arg_types)
void check_srf_call_placement(ParseState *pstate, Node *last_srf, int location)
Operator left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition parse_oper.c:522
#define list_make1(x1)
Definition pg_list.h:212
#define list_make2(x1, x2)
Definition pg_list.h:214
Definition pg_list.h:54
Definition nodes.h:135
Oid opno
Definition primnodes.h:851
List * args
Definition primnodes.h:869
ParseLoc location
Definition primnodes.h:872
Node * p_last_srf
Definition parse_node.h:227
Definition ltree.h:43

References OpExpr::args, check_srf_call_placement(), enforce_generic_type_consistency(), ereport, errcode(), errmsg(), ERROR, exprType(), fb(), Form_pg_operator, get_func_retset(), GETSTRUCT(), InvalidOid, left_oper(), list_make1, list_make2, OpExpr::location, make_fn_arguments(), makeNode, op_signature_string(), oper(), OpExpr::opno, oprid(), ParseState::p_last_srf, parser_errposition(), RegProcedureIsValid, and ReleaseSysCache().

Referenced by make_distinct_op(), make_row_comparison_op(), transformAExprIn(), transformAExprNullIf(), and transformAExprOp().

◆ make_scalar_array_op()

Expr * make_scalar_array_op ( ParseState pstate,
List opname,
bool  useOr,
Node ltree,
Node rtree,
int  location 
)
extern

Definition at line 814 of file parse_oper.c.

818{
819 Oid ltypeId,
820 rtypeId,
821 atypeId,
827 List *args;
828 Oid rettype;
829 ScalarArrayOpExpr *result;
830
833
834 /*
835 * The right-hand input of the operator will be the element type of the
836 * array. However, if we currently have just an untyped literal on the
837 * right, stay with that and hope we can resolve the operator.
838 */
839 if (atypeId == UNKNOWNOID)
841 else
842 {
844 if (!OidIsValid(rtypeId))
847 errmsg("op ANY/ALL (array) requires array on right side"),
848 parser_errposition(pstate, location)));
849 }
850
851 /* Now resolve the operator */
852 tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
854
855 /* Check it's not a shell */
856 if (!RegProcedureIsValid(opform->oprcode))
859 errmsg("operator is only a shell: %s",
861 opform->oprleft,
862 opform->oprright)),
863 parser_errposition(pstate, location)));
864
868 declared_arg_types[0] = opform->oprleft;
869 declared_arg_types[1] = opform->oprright;
870
871 /*
872 * enforce consistency with polymorphic argument and return types,
873 * possibly adjusting return type or declared_arg_types (which will be
874 * used as the cast destination by make_fn_arguments)
875 */
878 2,
879 opform->oprresult,
880 false);
881
882 /*
883 * Check that operator result is boolean
884 */
885 if (rettype != BOOLOID)
888 errmsg("op ANY/ALL (array) requires operator to yield boolean"),
889 parser_errposition(pstate, location)));
890 if (get_func_retset(opform->oprcode))
893 errmsg("op ANY/ALL (array) requires operator not to return a set"),
894 parser_errposition(pstate, location)));
895
896 /*
897 * Now switch back to the array type on the right, arranging for any
898 * needed cast to be applied. Beware of polymorphic operators here;
899 * enforce_generic_type_consistency may or may not have replaced a
900 * polymorphic type with a real one.
901 */
903 {
904 /* assume the actual array type is OK */
906 }
907 else
908 {
913 errmsg("could not find array type for data type %s",
915 parser_errposition(pstate, location)));
916 }
919
920 /* perform the necessary typecasting of arguments */
922
923 /* and build the expression node */
924 result = makeNode(ScalarArrayOpExpr);
925 result->opno = oprid(tup);
926 result->opfuncid = opform->oprcode;
927 result->hashfuncid = InvalidOid;
928 result->negfuncid = InvalidOid;
929 result->useOr = useOr;
930 /* inputcollid will be set by parse_collate.c */
931 result->args = args;
932 result->location = location;
933
935
936 return (Expr *) result;
937}
Oid get_base_element_type(Oid typid)
Definition lsyscache.c:2984
Oid get_array_type(Oid typid)
Definition lsyscache.c:2939
ParseLoc location
Definition primnodes.h:952

References ScalarArrayOpExpr::args, enforce_generic_type_consistency(), ereport, errcode(), errmsg(), ERROR, exprType(), fb(), Form_pg_operator, format_type_be(), get_array_type(), get_base_element_type(), get_func_retset(), GETSTRUCT(), InvalidOid, list_make2, ScalarArrayOpExpr::location, make_fn_arguments(), makeNode, OidIsValid, op_signature_string(), oper(), ScalarArrayOpExpr::opno, oprid(), parser_errposition(), RegProcedureIsValid, ReleaseSysCache(), and ScalarArrayOpExpr::useOr.

Referenced by transformAExprIn(), transformAExprOpAll(), and transformAExprOpAny().

◆ op_signature_string()

const char * op_signature_string ( List op,
Oid  arg1,
Oid  arg2 
)
extern

Definition at line 608 of file parse_oper.c.

609{
611
613
614 if (OidIsValid(arg1))
616
618
620
621 return argbuf.data; /* return palloc'd string buffer */
622}
char * NameListToString(const List *names)
Definition namespace.c:3666
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void initStringInfo(StringInfo str)
Definition stringinfo.c:97

References appendStringInfo(), appendStringInfoString(), fb(), format_type_be(), initStringInfo(), NameListToString(), and OidIsValid.

Referenced by compatible_oper(), LookupOperName(), make_op(), make_scalar_array_op(), op_error(), and ValidateOperatorReference().

◆ oper()

Operator oper ( ParseState pstate,
List opname,
Oid  ltypeId,
Oid  rtypeId,
bool  noError,
int  location 
)
extern

Definition at line 372 of file parse_oper.c.

374{
375 Oid operOid;
377 bool key_ok;
378 int fgc_flags = 0;
381
382 /*
383 * Try to find the mapping in the lookaside cache.
384 */
385 key_ok = make_oper_cache_key(pstate, &key, opname, ltypeId, rtypeId, location);
386
387 if (key_ok)
388 {
390 if (OidIsValid(operOid))
391 {
394 return (Operator) tup;
395 }
396 }
397
398 /*
399 * First try for an "exact" match.
400 */
402 if (!OidIsValid(operOid))
403 {
404 /*
405 * Otherwise, search for the most suitable candidate.
406 */
408
409 /* Get binary operators of given name */
411
412 /* No operators found? Then fail... */
413 if (clist != NULL)
414 {
415 /*
416 * Unspecified type for one of the arguments? then use the other
417 * (XXX this is probably dead code?)
418 */
419 Oid inputOids[2];
420
421 if (rtypeId == InvalidOid)
423 else if (ltypeId == InvalidOid)
425 inputOids[0] = ltypeId;
426 inputOids[1] = rtypeId;
428 }
429 }
430
431 if (OidIsValid(operOid))
433
435 {
436 if (key_ok)
438 }
439 else if (!noError)
440 op_error(pstate, opname, ltypeId, rtypeId,
441 fdresult, fgc_flags, location);
442
443 return (Operator) tup;
444}
static Oid binary_oper_exact(List *opname, Oid arg1, Oid arg2)
Definition parse_oper.c:264

References binary_oper_exact(), fb(), find_oper_cache_entry(), FUNCDETAIL_NOTFOUND, HeapTupleIsValid, InvalidOid, make_oper_cache_entry(), make_oper_cache_key(), ObjectIdGetDatum(), OidIsValid, op_error(), oper_select_candidate(), OpernameGetCandidates(), and SearchSysCache1().

Referenced by compatible_oper(), Do_MultiXactIdWait(), generate_operator_name(), LookupOperWithArgs(), make_op(), make_SAOP_expr(), make_scalar_array_op(), makeOperatorDependencies(), multi_sort_add_dimension(), MultiXactIdWait(), pushOperator(), tsquery_opr_selec(), tsqueryrecv(), and XactLockTableWait().

◆ oprfuncid()

Oid oprfuncid ( Operator  op)
extern

Definition at line 247 of file parse_oper.c.

248{
250
251 return pgopform->oprcode;
252}

References fb(), Form_pg_operator, and GETSTRUCT().

◆ oprid()