diff options
Diffstat (limited to 'src/backend/parser/catalog_utils.c')
-rw-r--r-- | src/backend/parser/catalog_utils.c | 2457 |
1 files changed, 1317 insertions, 1140 deletions
diff --git a/src/backend/parser/catalog_utils.c b/src/backend/parser/catalog_utils.c index 043c2865060..41e6fffac9b 100644 --- a/src/backend/parser/catalog_utils.c +++ b/src/backend/parser/catalog_utils.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/Attic/catalog_utils.c,v 1.22 1997/08/22 00:02:05 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/Attic/catalog_utils.c,v 1.23 1997/09/07 04:44:42 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -48,83 +48,110 @@ #include "utils/lsyscache.h" #include "storage/lmgr.h" -#include "port-protos.h" /* strdup() */ - -struct { - char *field; - int code; -} special_attr[] = { - { "ctid", SelfItemPointerAttributeNumber }, - { "oid", ObjectIdAttributeNumber }, - { "xmin", MinTransactionIdAttributeNumber }, - { "cmin", MinCommandIdAttributeNumber }, - { "xmax", MaxTransactionIdAttributeNumber }, - { "cmax", MaxCommandIdAttributeNumber }, - { "chain", ChainItemPointerAttributeNumber }, - { "anchor", AnchorItemPointerAttributeNumber }, - { "tmin", MinAbsoluteTimeAttributeNumber }, - { "tmax", MaxAbsoluteTimeAttributeNumber }, - { "vtype", VersionTypeAttributeNumber } +#include "port-protos.h" /* strdup() */ + +struct +{ + char *field; + int code; +} special_attr[] = + +{ + { + "ctid", SelfItemPointerAttributeNumber + }, + { + "oid", ObjectIdAttributeNumber + }, + { + "xmin", MinTransactionIdAttributeNumber + }, + { + "cmin", MinCommandIdAttributeNumber + }, + { + "xmax", MaxTransactionIdAttributeNumber + }, + { + "cmax", MaxCommandIdAttributeNumber + }, + { + "chain", ChainItemPointerAttributeNumber + }, + { + "anchor", AnchorItemPointerAttributeNumber + }, + { + "tmin", MinAbsoluteTimeAttributeNumber + }, + { + "tmax", MaxAbsoluteTimeAttributeNumber + }, + { + "vtype", VersionTypeAttributeNumber + } }; #define SPECIALS (sizeof(special_attr)/sizeof(*special_attr)) - -static char *attnum_type[SPECIALS] = { - "tid", - "oid", - "xid", - "cid", - "xid", - "cid", - "tid", - "tid", - "abstime", - "abstime", - "char" - }; - -#define MAXFARGS 8 /* max # args to a c or postquel function */ + +static char *attnum_type[SPECIALS] = { + "tid", + "oid", + "xid", + "cid", + "xid", + "cid", + "tid", + "tid", + "abstime", + "abstime", + "char" +}; + +#define MAXFARGS 8 /* max # args to a c or postquel function */ /* - * This structure is used to explore the inheritance hierarchy above - * nodes in the type tree in order to disambiguate among polymorphic - * functions. + * This structure is used to explore the inheritance hierarchy above + * nodes in the type tree in order to disambiguate among polymorphic + * functions. */ -typedef struct _InhPaths { - int nsupers; /* number of superclasses */ - Oid self; /* this class */ - Oid *supervec; /* vector of superclasses */ -} InhPaths; +typedef struct _InhPaths +{ + int nsupers; /* number of superclasses */ + Oid self; /* this class */ + Oid *supervec; /* vector of superclasses */ +} InhPaths; /* - * This structure holds a list of possible functions or operators that - * agree with the known name and argument types of the function/operator. + * This structure holds a list of possible functions or operators that + * agree with the known name and argument types of the function/operator. */ -typedef struct _CandidateList { - Oid *args; - struct _CandidateList *next; -} *CandidateList; - -static Oid **argtype_inherit(int nargs, Oid *oid_array); -static Oid **genxprod(InhPaths *arginh, int nargs); -static int findsupers(Oid relid, Oid **supervec); -static bool check_typeid(Oid id); -static char *instr1(TypeTupleForm tp, char *string, int typlen); -static void op_error(char *op, Oid arg1, Oid arg2); +typedef struct _CandidateList +{ + Oid *args; + struct _CandidateList *next; +} *CandidateList; + +static Oid **argtype_inherit(int nargs, Oid * oid_array); +static Oid **genxprod(InhPaths * arginh, int nargs); +static int findsupers(Oid relid, Oid ** supervec); +static bool check_typeid(Oid id); +static char *instr1(TypeTupleForm tp, char *string, int typlen); +static void op_error(char *op, Oid arg1, Oid arg2); /* check to see if a type id is valid, - * returns true if it is. By using this call before calling + * returns true if it is. By using this call before calling * get_id_type or get_id_typname, more meaningful error messages * can be produced because the caller typically has more context of - * what's going on - jolly + * what's going on - jolly */ -static bool +static bool check_typeid(Oid id) { - return (SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(id), - 0,0,0) != NULL); + return (SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(id), + 0, 0, 0) != NULL); } @@ -132,46 +159,50 @@ check_typeid(Oid id) Type get_id_type(Oid id) { - HeapTuple tup; - - if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id), - 0,0,0))) { - elog ( WARN, "type id lookup of %ud failed", id); - return(NULL); - } - return((Type) tup); + HeapTuple tup; + + if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id), + 0, 0, 0))) + { + elog(WARN, "type id lookup of %ud failed", id); + return (NULL); + } + return ((Type) tup); } /* return a type name, given a typeid */ -char* +char * get_id_typname(Oid id) { - HeapTuple tup; - TypeTupleForm typetuple; - - if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id), - 0,0,0))) { - elog ( WARN, "type id lookup of %ud failed", id); - return(NULL); - } - typetuple = (TypeTupleForm)GETSTRUCT(tup); - return (typetuple->typname).data; + HeapTuple tup; + TypeTupleForm typetuple; + + if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id), + 0, 0, 0))) + { + elog(WARN, "type id lookup of %ud failed", id); + return (NULL); + } + typetuple = (TypeTupleForm) GETSTRUCT(tup); + return (typetuple->typname).data; } /* return a Type structure, given type name */ Type type(char *s) { - HeapTuple tup; - - if (s == NULL) { - elog ( WARN , "type(): Null type" ); - } - - if (!(tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(s), 0,0,0))) { - elog (WARN , "type name lookup of %s failed", s); - } - return((Type) tup); + HeapTuple tup; + + if (s == NULL) + { + elog(WARN, "type(): Null type"); + } + + if (!(tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(s), 0, 0, 0))) + { + elog(WARN, "type name lookup of %s failed", s); + } + return ((Type) tup); } /* given attribute id, return type of that attribute */ @@ -179,297 +210,327 @@ type(char *s) Oid att_typeid(Relation rd, int attid) { - - if (attid < 0) { - return(typeid(type(attnum_type[-attid-1]))); - } - /* -1 because varattno (where attid comes from) returns one - more than index */ - return(rd->rd_att->attrs[attid-1]->atttypid); + + if (attid < 0) + { + return (typeid(type(attnum_type[-attid - 1]))); + } + + /* + * -1 because varattno (where attid comes from) returns one more than + * index + */ + return (rd->rd_att->attrs[attid - 1]->atttypid); } int att_attnelems(Relation rd, int attid) { - return(rd->rd_att->attrs[attid-1]->attnelems); + return (rd->rd_att->attrs[attid - 1]->attnelems); } /* given type, return the type OID */ Oid typeid(Type tp) { - if (tp == NULL) { - elog ( WARN , "typeid() called with NULL type struct"); - } - return(tp->t_oid); + if (tp == NULL) + { + elog(WARN, "typeid() called with NULL type struct"); + } + return (tp->t_oid); } /* given type (as type struct), return the length of type */ int16 tlen(Type t) { - TypeTupleForm typ; - - typ = (TypeTupleForm)GETSTRUCT(t); - return(typ->typlen); + TypeTupleForm typ; + + typ = (TypeTupleForm) GETSTRUCT(t); + return (typ->typlen); } /* given type (as type struct), return the value of its 'byval' attribute.*/ bool tbyval(Type t) { - TypeTupleForm typ; - - typ = (TypeTupleForm)GETSTRUCT(t); - return(typ->typbyval); + TypeTupleForm typ; + + typ = (TypeTupleForm) GETSTRUCT(t); + return (typ->typbyval); } /* given type (as type struct), return the name of type */ -char* +char * tname(Type t) { - TypeTupleForm typ; - - typ = (TypeTupleForm)GETSTRUCT(t); - return (typ->typname).data; + TypeTupleForm typ; + + typ = (TypeTupleForm) GETSTRUCT(t); + return (typ->typname).data; } /* given type (as type struct), return wether type is passed by value */ int tbyvalue(Type t) { - TypeTupleForm typ; - - typ = (TypeTupleForm) GETSTRUCT(t); - return(typ->typbyval); + TypeTupleForm typ; + + typ = (TypeTupleForm) GETSTRUCT(t); + return (typ->typbyval); } /* given a type, return its typetype ('c' for 'c'atalog types) */ static char typetypetype(Type t) { - TypeTupleForm typ; - - typ = (TypeTupleForm) GETSTRUCT(t); - return(typ->typtype); + TypeTupleForm typ; + + typ = (TypeTupleForm) GETSTRUCT(t); + return (typ->typtype); } /* given operator, return the operator OID */ Oid oprid(Operator op) { - return(op->t_oid); + return (op->t_oid); } /* - * given opname, leftTypeId and rightTypeId, - * find all possible (arg1, arg2) pairs for which an operator named - * opname exists, such that leftTypeId can be coerced to arg1 and - * rightTypeId can be coerced to arg2 + * given opname, leftTypeId and rightTypeId, + * find all possible (arg1, arg2) pairs for which an operator named + * opname exists, such that leftTypeId can be coerced to arg1 and + * rightTypeId can be coerced to arg2 */ static int binary_oper_get_candidates(char *opname, - Oid leftTypeId, - Oid rightTypeId, - CandidateList *candidates) + Oid leftTypeId, + Oid rightTypeId, + CandidateList * candidates) { - CandidateList current_candidate; - Relation pg_operator_desc; - HeapScanDesc pg_operator_scan; - HeapTuple tup; - OperatorTupleForm oper; - Buffer buffer; - int nkeys; - int ncandidates = 0; - ScanKeyData opKey[3]; - - *candidates = NULL; - - ScanKeyEntryInitialize(&opKey[0], 0, - Anum_pg_operator_oprname, - NameEqualRegProcedure, - NameGetDatum(opname)); - - ScanKeyEntryInitialize(&opKey[1], 0, - Anum_pg_operator_oprkind, - CharacterEqualRegProcedure, - CharGetDatum('b')); - - - if (leftTypeId == UNKNOWNOID) { - if (rightTypeId == UNKNOWNOID) { - nkeys = 2; - } else { - nkeys = 3; - - ScanKeyEntryInitialize(&opKey[2], 0, - Anum_pg_operator_oprright, - ObjectIdEqualRegProcedure, - ObjectIdGetDatum(rightTypeId)); - } - } else if (rightTypeId == UNKNOWNOID) { - nkeys = 3; - - ScanKeyEntryInitialize(&opKey[2], 0, - Anum_pg_operator_oprleft, - ObjectIdEqualRegProcedure, - ObjectIdGetDatum(leftTypeId)); - } else { - /* currently only "unknown" can be coerced */ - return 0; - } - - pg_operator_desc = heap_openr(OperatorRelationName); - pg_operator_scan = heap_beginscan(pg_operator_desc, - 0, - SelfTimeQual, - nkeys, - opKey); - - do { - tup = heap_getnext(pg_operator_scan, 0, &buffer); - if (HeapTupleIsValid(tup)) { - current_candidate = (CandidateList)palloc(sizeof(struct _CandidateList)); - current_candidate->args = (Oid *)palloc(2 * sizeof(Oid)); - - oper = (OperatorTupleForm)GETSTRUCT(tup); - current_candidate->args[0] = oper->oprleft; - current_candidate->args[1] = oper->oprright; - current_candidate->next = *candidates; - *candidates = current_candidate; - ncandidates++; - ReleaseBuffer(buffer); + CandidateList current_candidate; + Relation pg_operator_desc; + HeapScanDesc pg_operator_scan; + HeapTuple tup; + OperatorTupleForm oper; + Buffer buffer; + int nkeys; + int ncandidates = 0; + ScanKeyData opKey[3]; + + *candidates = NULL; + + ScanKeyEntryInitialize(&opKey[0], 0, + Anum_pg_operator_oprname, + NameEqualRegProcedure, + NameGetDatum(opname)); + + ScanKeyEntryInitialize(&opKey[1], 0, + Anum_pg_operator_oprkind, + CharacterEqualRegProcedure, + CharGetDatum('b')); + + + if (leftTypeId == UNKNOWNOID) + { + if (rightTypeId == UNKNOWNOID) + { + nkeys = 2; + } + else + { + nkeys = 3; + + ScanKeyEntryInitialize(&opKey[2], 0, + Anum_pg_operator_oprright, + ObjectIdEqualRegProcedure, + ObjectIdGetDatum(rightTypeId)); + } + } + else if (rightTypeId == UNKNOWNOID) + { + nkeys = 3; + + ScanKeyEntryInitialize(&opKey[2], 0, + Anum_pg_operator_oprleft, + ObjectIdEqualRegProcedure, + ObjectIdGetDatum(leftTypeId)); } - } while(HeapTupleIsValid(tup)); - - heap_endscan(pg_operator_scan); - heap_close(pg_operator_desc); - - return ncandidates; + else + { + /* currently only "unknown" can be coerced */ + return 0; + } + + pg_operator_desc = heap_openr(OperatorRelationName); + pg_operator_scan = heap_beginscan(pg_operator_desc, + 0, + SelfTimeQual, + nkeys, + opKey); + + do + { + tup = heap_getnext(pg_operator_scan, 0, &buffer); + if (HeapTupleIsValid(tup)) + { + current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList)); + current_candidate->args = (Oid *) palloc(2 * sizeof(Oid)); + + oper = (OperatorTupleForm) GETSTRUCT(tup); + current_candidate->args[0] = oper->oprleft; + current_candidate->args[1] = oper->oprright; + current_candidate->next = *candidates; + *candidates = current_candidate; + ncandidates++; + ReleaseBuffer(buffer); + } + } while (HeapTupleIsValid(tup)); + + heap_endscan(pg_operator_scan); + heap_close(pg_operator_desc); + + return ncandidates; } /* * equivalentOpersAfterPromotion - - * checks if a list of candidate operators obtained from - * binary_oper_get_candidates() contain equivalent operators. If - * this routine is called, we have more than 1 candidate and need to - * decided whether to pick one of them. This routine returns true if - * the all the candidates operate on the same data types after - * promotion (int2, int4, float4 -> float8). + * checks if a list of candidate operators obtained from + * binary_oper_get_candidates() contain equivalent operators. If + * this routine is called, we have more than 1 candidate and need to + * decided whether to pick one of them. This routine returns true if + * the all the candidates operate on the same data types after + * promotion (int2, int4, float4 -> float8). */ -static bool +static bool equivalentOpersAfterPromotion(CandidateList candidates) { - CandidateList result; - CandidateList promotedCandidates = NULL; - Oid leftarg, rightarg; - - for (result = candidates; result != NULL; result = result->next) { - CandidateList c; - c = (CandidateList)palloc(sizeof(*c)); - c->args = (Oid *)palloc(2 * sizeof(Oid)); - switch (result->args[0]) { - case FLOAT4OID: - case INT4OID: - case INT2OID: - case CASHOID: - c->args[0] = FLOAT8OID; - break; - default: - c->args[0] = result->args[0]; - break; + CandidateList result; + CandidateList promotedCandidates = NULL; + Oid leftarg, + rightarg; + + for (result = candidates; result != NULL; result = result->next) + { + CandidateList c; + + c = (CandidateList) palloc(sizeof(*c)); + c->args = (Oid *) palloc(2 * sizeof(Oid)); + switch (result->args[0]) + { + case FLOAT4OID: + case INT4OID: + case INT2OID: + case CASHOID: + c->args[0] = FLOAT8OID; + break; + default: + c->args[0] = result->args[0]; + break; + } + switch (result->args[1]) + { + case FLOAT4OID: + case INT4OID: + case INT2OID: + case CASHOID: + c->args[1] = FLOAT8OID; + break; + default: + c->args[1] = result->args[1]; + break; + } + c->next = promotedCandidates; + promotedCandidates = c; } - switch (result->args[1]) { - case FLOAT4OID: - case INT4OID: - case INT2OID: - case CASHOID: - c->args[1] = FLOAT8OID; - break; - default: - c->args[1] = result->args[1]; - break; + + /* + * if we get called, we have more than 1 candidates so we can do the + * following safely + */ + leftarg = promotedCandidates->args[0]; + rightarg = promotedCandidates->args[1]; + + for (result = promotedCandidates->next; result != NULL; result = result->next) + { + if (result->args[0] != leftarg || result->args[1] != rightarg) + + /* + * this list contains operators that operate on different data + * types even after promotion. Hence we can't decide on which + * one to pick. The user must do explicit type casting. + */ + return FALSE; } - c->next = promotedCandidates; - promotedCandidates = c; - } - - /* if we get called, we have more than 1 candidates so we can do the - following safely */ - leftarg = promotedCandidates->args[0]; - rightarg = promotedCandidates->args[1]; - - for (result=promotedCandidates->next; result!=NULL; result=result->next) { - if (result->args[0]!=leftarg || result->args[1]!=rightarg) - /* - * this list contains operators that operate on different - * data types even after promotion. Hence we can't decide on - * which one to pick. The user must do explicit type casting. - */ - return FALSE; - } - - /* all the candidates are equivalent in the following sense: they operate - on equivalent data types and picking any one of them is as good. */ - return TRUE; + + /* + * all the candidates are equivalent in the following sense: they + * operate on equivalent data types and picking any one of them is as + * good. + */ + return TRUE; } - + /* - * given a choice of argument type pairs for a binary operator, - * try to choose a default pair + * given a choice of argument type pairs for a binary operator, + * try to choose a default pair */ -static CandidateList +static CandidateList binary_oper_select_candidate(Oid arg1, - Oid arg2, - CandidateList candidates) + Oid arg2, + CandidateList candidates) { - CandidateList result; - - /* - * if both are "unknown", there is no way to select a candidate - * - * current wisdom holds that the default operator should be one - * in which both operands have the same type (there will only - * be one such operator) - * - * 7.27.93 - I have decided not to do this; it's too hard to - * justify, and it's easy enough to typecast explicitly -avi - * [the rest of this routine were commented out since then -ay] - */ - - if (arg1 == UNKNOWNOID && arg2 == UNKNOWNOID) - return (NULL); + CandidateList result; + + /* + * if both are "unknown", there is no way to select a candidate + * + * current wisdom holds that the default operator should be one in which + * both operands have the same type (there will only be one such + * operator) + * + * 7.27.93 - I have decided not to do this; it's too hard to justify, and + * it's easy enough to typecast explicitly -avi [the rest of this + * routine were commented out since then -ay] + */ + + if (arg1 == UNKNOWNOID && arg2 == UNKNOWNOID) + return (NULL); + + /* + * 6/23/95 - I don't complete agree with avi. In particular, casting + * floats is a pain for users. Whatever the rationale behind not doing + * this is, I need the following special case to work. + * + * In the WHERE clause of a query, if a float is specified without + * quotes, we treat it as float8. I added the float48* operators so + * that we can operate on float4 and float8. But now we have more than + * one matching operator if the right arg is unknown (eg. float + * specified with quotes). This break some stuff in the regression + * test where there are floats in quotes not properly casted. Below is + * the solution. In addition to requiring the operator operates on the + * same type for both operands [as in the code Avi originally + * commented out], we also require that the operators be equivalent in + * some sense. (see equivalentOpersAfterPromotion for details.) - ay + * 6/95 + */ + if (!equivalentOpersAfterPromotion(candidates)) + return NULL; + + /* + * if we get here, any one will do but we're more picky and require + * both operands be the same. + */ + for (result = candidates; result != NULL; result = result->next) + { + if (result->args[0] == result->args[1]) + return result; + } - /* - * 6/23/95 - I don't complete agree with avi. In particular, casting - * floats is a pain for users. Whatever the rationale behind not doing - * this is, I need the following special case to work. - * - * In the WHERE clause of a query, if a float is specified without - * quotes, we treat it as float8. I added the float48* operators so - * that we can operate on float4 and float8. But now we have more - * than one matching operator if the right arg is unknown (eg. float - * specified with quotes). This break some stuff in the regression - * test where there are floats in quotes not properly casted. Below - * is the solution. In addition to requiring the operator operates - * on the same type for both operands [as in the code Avi originally - * commented out], we also require that the operators be equivalent - * in some sense. (see equivalentOpersAfterPromotion for details.) - * - ay 6/95 - */ - if (!equivalentOpersAfterPromotion(candidates)) - return NULL; - - /* if we get here, any one will do but we're more picky and require - both operands be the same. */ - for (result = candidates; result != NULL; result = result->next) { - if (result->args[0] == result->args[1]) - return result; - } - - return (NULL); + return (NULL); } /* Given operator, types of arg1, and arg2, return oper struct */ @@ -477,135 +538,158 @@ binary_oper_select_candidate(Oid arg1, Operator oper(char *op, Oid arg1, Oid arg2, bool noWarnings) { - HeapTuple tup; - CandidateList candidates; - int ncandidates; - - if (!arg2) arg2=arg1; - if (!arg1) arg1=arg2; - - if (!(tup = SearchSysCacheTuple(OPRNAME, - PointerGetDatum(op), - ObjectIdGetDatum(arg1), - ObjectIdGetDatum(arg2), - Int8GetDatum('b')))) { - ncandidates = binary_oper_get_candidates(op, arg1, arg2, &candidates); - if (ncandidates == 0) { - /* - * no operators of the desired types found - */ - if (!noWarnings) - op_error(op, arg1, arg2); - return(NULL); - } else if (ncandidates == 1) { - /* - * exactly one operator of the desired types found - */ - tup = SearchSysCacheTuple(OPRNAME, - PointerGetDatum(op), - ObjectIdGetDatum(candidates->args[0]), - ObjectIdGetDatum(candidates->args[1]), - Int8GetDatum('b')); - Assert(HeapTupleIsValid(tup)); - } else { - /* - * multiple operators of the desired types found - */ - candidates = binary_oper_select_candidate(arg1, arg2, candidates); - if (candidates != NULL) { - /* we chose one of them */ - tup = SearchSysCacheTuple(OPRNAME, - PointerGetDatum(op), - ObjectIdGetDatum(candidates->args[0]), - ObjectIdGetDatum(candidates->args[1]), - Int8GetDatum('b')); - Assert(HeapTupleIsValid(tup)); - } else { - Type tp1, tp2; - - /* we chose none of them */ - tp1 = get_id_type(arg1); - tp2 = get_id_type(arg2); - if (!noWarnings) { - elog(NOTICE, "there is more than one operator %s for types", op); - elog(NOTICE, "%s and %s. You will have to retype this query", - tname(tp1), tname(tp2)); - elog(WARN, "using an explicit cast"); + HeapTuple tup; + CandidateList candidates; + int ncandidates; + + if (!arg2) + arg2 = arg1; + if (!arg1) + arg1 = arg2; + + if (!(tup = SearchSysCacheTuple(OPRNAME, + PointerGetDatum(op), + ObjectIdGetDatum(arg1), + ObjectIdGetDatum(arg2), + Int8GetDatum('b')))) + { + ncandidates = binary_oper_get_candidates(op, arg1, arg2, &candidates); + if (ncandidates == 0) + { + + /* + * no operators of the desired types found + */ + if (!noWarnings) + op_error(op, arg1, arg2); + return (NULL); + } + else if (ncandidates == 1) + { + + /* + * exactly one operator of the desired types found + */ + tup = SearchSysCacheTuple(OPRNAME, + PointerGetDatum(op), + ObjectIdGetDatum(candidates->args[0]), + ObjectIdGetDatum(candidates->args[1]), + Int8GetDatum('b')); + Assert(HeapTupleIsValid(tup)); + } + else + { + + /* + * multiple operators of the desired types found + */ + candidates = binary_oper_select_candidate(arg1, arg2, candidates); + if (candidates != NULL) + { + /* we chose one of them */ + tup = SearchSysCacheTuple(OPRNAME, + PointerGetDatum(op), + ObjectIdGetDatum(candidates->args[0]), + ObjectIdGetDatum(candidates->args[1]), + Int8GetDatum('b')); + Assert(HeapTupleIsValid(tup)); + } + else + { + Type tp1, + tp2; + + /* we chose none of them */ + tp1 = get_id_type(arg1); + tp2 = get_id_type(arg2); + if (!noWarnings) + { + elog(NOTICE, "there is more than one operator %s for types", op); + elog(NOTICE, "%s and %s. You will have to retype this query", + tname(tp1), tname(tp2)); + elog(WARN, "using an explicit cast"); + } + return (NULL); + } } - return(NULL); - } } - } - return((Operator) tup); + return ((Operator) tup); } /* - * 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 + * 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 int unary_oper_get_candidates(char *op, - Oid typeId, - CandidateList *candidates, - char rightleft) + Oid typeId, + CandidateList * candidates, + char rightleft) { - CandidateList current_candidate; - Relation pg_operator_desc; - HeapScanDesc pg_operator_scan; - HeapTuple tup; - OperatorTupleForm oper; - Buffer buffer; - int ncandidates = 0; - - static ScanKeyData opKey[2] = { - { 0, Anum_pg_operator_oprname, NameEqualRegProcedure }, - { 0, Anum_pg_operator_oprkind, CharacterEqualRegProcedure } }; - - *candidates = NULL; - - fmgr_info(NameEqualRegProcedure, (func_ptr *) &opKey[0].sk_func, - &opKey[0].sk_nargs); - opKey[0].sk_argument = NameGetDatum(op); - fmgr_info(CharacterEqualRegProcedure, (func_ptr *) &opKey[1].sk_func, - &opKey[1].sk_nargs); - opKey[1].sk_argument = CharGetDatum(rightleft); - - /* currently, only "unknown" can be coerced */ - /* but we should allow types that are internally the same to be "coerced" */ - if (typeId != UNKNOWNOID) { - return 0; - } - - pg_operator_desc = heap_openr(OperatorRelationName); - pg_operator_scan = heap_beginscan(pg_operator_desc, - 0, - SelfTimeQual, - 2, - opKey); - - do { - tup = heap_getnext(pg_operator_scan, 0, &buffer); - if (HeapTupleIsValid(tup)) { - current_candidate = (CandidateList)palloc(sizeof(struct _CandidateList)); - current_candidate->args = (Oid *)palloc(sizeof(Oid)); - - oper = (OperatorTupleForm)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++; - ReleaseBuffer(buffer); + CandidateList current_candidate; + Relation pg_operator_desc; + HeapScanDesc pg_operator_scan; + HeapTuple tup; + OperatorTupleForm oper; + Buffer buffer; + int ncandidates = 0; + + static ScanKeyData opKey[2] = { + {0, Anum_pg_operator_oprname, NameEqualRegProcedure}, + {0, Anum_pg_operator_oprkind, CharacterEqualRegProcedure}}; + + *candidates = NULL; + + fmgr_info(NameEqualRegProcedure, (func_ptr *) & opKey[0].sk_func, + &opKey[0].sk_nargs); + opKey[0].sk_argument = NameGetDatum(op); + fmgr_info(CharacterEqualRegProcedure, (func_ptr *) & opKey[1].sk_func, + &opKey[1].sk_nargs); + opKey[1].sk_argument = CharGetDatum(rightleft); + + /* currently, only "unknown" can be coerced */ + + /* + * but we should allow types that are internally the same to be + * "coerced" + */ + if (typeId != UNKNOWNOID) + { + return 0; } - } while(HeapTupleIsValid(tup)); - - heap_endscan(pg_operator_scan); - heap_close(pg_operator_desc); - - return ncandidates; + + pg_operator_desc = heap_openr(OperatorRelationName); + pg_operator_scan = heap_beginscan(pg_operator_desc, + 0, + SelfTimeQual, + 2, + opKey); + + do + { + tup = heap_getnext(pg_operator_scan, 0, &buffer); + if (HeapTupleIsValid(tup)) + { + current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList)); + current_candidate->args = (Oid *) palloc(sizeof(Oid)); + + oper = (OperatorTupleForm) 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++; + ReleaseBuffer(buffer); + } + } while (HeapTupleIsValid(tup)); + + heap_endscan(pg_operator_scan); + heap_close(pg_operator_desc); + + return ncandidates; } /* Given unary right-side operator (operator on right), return oper struct */ @@ -613,42 +697,44 @@ unary_oper_get_candidates(char *op, Operator right_oper(char *op, Oid arg) { - HeapTuple tup; - CandidateList candidates; - int ncandidates; - - /* - if (!OpCache) { - init_op_cache(); - } - */ - if (!(tup = SearchSysCacheTuple(OPRNAME, - PointerGetDatum(op), - ObjectIdGetDatum(arg), - ObjectIdGetDatum(InvalidOid), - Int8GetDatum('r')))) { - ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'r'); - if (ncandidates == 0) { - elog ( WARN , - "Can't find right op: %s for type %d", op, arg ); - return(NULL); - } - else if (ncandidates == 1) { - tup = SearchSysCacheTuple(OPRNAME, - PointerGetDatum(op), - ObjectIdGetDatum(candidates->args[0]), - ObjectIdGetDatum(InvalidOid), - Int8GetDatum('r')); - Assert(HeapTupleIsValid(tup)); - } - else { - elog(NOTICE, "there is more than one right operator %s", op); - elog(NOTICE, "you will have to retype this query"); - elog(WARN, "using an explicit cast"); - return(NULL); + HeapTuple tup; + CandidateList candidates; + int ncandidates; + + /* + * if (!OpCache) { init_op_cache(); } + */ + if (!(tup = SearchSysCacheTuple(OPRNAME, + PointerGetDatum(op), + ObjectIdGetDatum(arg), + ObjectIdGetDatum(InvalidOid), + Int8GetDatum('r')))) + { + ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'r'); + if (ncandidates == 0) + { + elog(WARN, + "Can't find right op: %s for type %d", op, arg); + return (NULL); + } + else if (ncandidates == 1) + { + tup = SearchSysCacheTuple(OPRNAME, + PointerGetDatum(op), + ObjectIdGetDatum(candidates->args[0]), + ObjectIdGetDatum(InvalidOid), + Int8GetDatum('r')); + Assert(HeapTupleIsValid(tup)); + } + else + { + elog(NOTICE, "there is more than one right operator %s", op); + elog(NOTICE, "you will have to retype this query"); + elog(WARN, "using an explicit cast"); + return (NULL); + } } - } - return((Operator) tup); + return ((Operator) tup); } /* Given unary left-side operator (operator on left), return oper struct */ @@ -656,42 +742,44 @@ right_oper(char *op, Oid arg) Operator left_oper(char *op, Oid arg) { - HeapTuple tup; - CandidateList candidates; - int ncandidates; - - /* - if (!OpCache) { - init_op_cache(); - } - */ - if (!(tup = SearchSysCacheTuple(OPRNAME, - PointerGetDatum(op), - ObjectIdGetDatum(InvalidOid), - ObjectIdGetDatum(arg), - Int8GetDatum('l')))) { - ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'l'); - if (ncandidates == 0) { - elog ( WARN , - "Can't find left op: %s for type %d", op, arg ); - return(NULL); - } - else if (ncandidates == 1) { - tup = SearchSysCacheTuple(OPRNAME, - PointerGetDatum(op), - ObjectIdGetDatum(InvalidOid), - ObjectIdGetDatum(candidates->args[0]), - Int8GetDatum('l')); - Assert(HeapTupleIsValid(tup)); - } - else { - elog(NOTICE, "there is more than one left operator %s", op); - elog(NOTICE, "you will have to retype this query"); - elog(WARN, "using an explicit cast"); - return(NULL); + HeapTuple tup; + CandidateList candidates; + int ncandidates; + + /* + * if (!OpCache) { init_op_cache(); } + */ + if (!(tup = SearchSysCacheTuple(OPRNAME, + PointerGetDatum(op), + ObjectIdGetDatum(InvalidOid), + ObjectIdGetDatum(arg), + Int8GetDatum('l')))) + { + ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'l'); + if (ncandidates == 0) + { + elog(WARN, + "Can't find left op: %s for type %d", op, arg); + return (NULL); + } + else if (ncandidates == 1) + { + tup = SearchSysCacheTuple(OPRNAME, + PointerGetDatum(op), + ObjectIdGetDatum(InvalidOid), + ObjectIdGetDatum(candidates->args[0]), + Int8GetDatum('l')); + Assert(HeapTupleIsValid(tup)); + } + else + { + elog(NOTICE, "there is more than one left operator %s", op); + elog(NOTICE, "you will have to retype this query"); + elog(WARN, "using an explicit cast"); + return (NULL); + } } - } - return((Operator) tup); + return ((Operator) tup); } /* given range variable, return id of variable */ @@ -699,22 +787,26 @@ left_oper(char *op, Oid arg) int varattno(Relation rd, char *a) { - int i; - - for (i = 0; i < rd->rd_rel->relnatts; i++) { - if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a)) { - return(i+1); + int i; + + for (i = 0; i < rd->rd_rel->relnatts; i++) + { + if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a)) + { + return (i + 1); + } } - } - for (i = 0; i < SPECIALS; i++) { - if (!strcmp(special_attr[i].field, a)) { - return(special_attr[i].code); + for (i = 0; i < SPECIALS; i++) + { + if (!strcmp(special_attr[i].field, a)) + { + return (special_attr[i].code); + } } - } - - elog(WARN,"Relation %s does not have attribute %s\n", - RelationGetRelationName(rd), a ); - return(-1); + + elog(WARN, "Relation %s does not have attribute %s\n", + RelationGetRelationName(rd), a); + return (-1); } /* Given range variable, return whether attribute of this name @@ -725,104 +817,118 @@ varattno(Relation rd, char *a) bool varisset(Relation rd, char *name) { - int i; - - /* First check if this is a system attribute */ - for (i = 0; i < SPECIALS; i++) { - if (! strcmp(special_attr[i].field, name)) { - return(false); /* no sys attr is a set */ + int i; + + /* First check if this is a system attribute */ + for (i = 0; i < SPECIALS; i++) + { + if (!strcmp(special_attr[i].field, name)) + { + return (false); /* no sys attr is a set */ + } } - } - return (get_attisset(rd->rd_id, name)); + return (get_attisset(rd->rd_id, name)); } /* given range variable, return id of variable */ int nf_varattno(Relation rd, char *a) { - int i; - - for (i = 0; i < rd->rd_rel->relnatts; i++) { - if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a)) { - return(i+1); + int i; + + for (i = 0; i < rd->rd_rel->relnatts; i++) + { + if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a)) + { + return (i + 1); + } } - } - for (i = 0; i < SPECIALS; i++) { - if (!strcmp(special_attr[i].field, a)) { - return(special_attr[i].code); + for (i = 0; i < SPECIALS; i++) + { + if (!strcmp(special_attr[i].field, a)) + { + return (special_attr[i].code); + } } - } - return InvalidAttrNumber; + return InvalidAttrNumber; } /*------------- * given an attribute number and a relation, return its relation name */ -char* +char * getAttrName(Relation rd, int attrno) { - char *name; - int i; - - if (attrno<0) { - for (i = 0; i < SPECIALS; i++) { - if (special_attr[i].code == attrno) { - name = special_attr[i].field; - return(name); - } + char *name; + int i; + + if (attrno < 0) + { + for (i = 0; i < SPECIALS; i++) + { + if (special_attr[i].code == attrno) + { + name = special_attr[i].field; + return (name); + } + } + elog(WARN, "Illegal attr no %d for relation %s\n", + attrno, RelationGetRelationName(rd)); + } + else if (attrno >= 1 && attrno <= RelationGetNumberOfAttributes(rd)) + { + name = (rd->rd_att->attrs[attrno - 1]->attname).data; + return (name); + } + else + { + elog(WARN, "Illegal attr no %d for relation %s\n", + attrno, RelationGetRelationName(rd)); } - elog(WARN, "Illegal attr no %d for relation %s\n", - attrno, RelationGetRelationName(rd)); - } else if (attrno >=1 && attrno<= RelationGetNumberOfAttributes(rd)) { - name = (rd->rd_att->attrs[attrno-1]->attname).data; - return(name); - } else { - elog(WARN, "Illegal attr no %d for relation %s\n", - attrno, RelationGetRelationName(rd)); - } - - /* - * Shouldn't get here, but we want lint to be happy... - */ - - return(NULL); + + /* + * Shouldn't get here, but we want lint to be happy... + */ + + return (NULL); } /* Given a typename and value, returns the ascii form of the value */ #ifdef NOT_USED -char * -outstr(char *typename, /* Name of type of value */ - char *value) /* Could be of any type */ +char * +outstr(char *typename, /* Name of type of value */ + char *value) /* Could be of any type */ { - TypeTupleForm tp; - Oid op; - - tp = (TypeTupleForm ) GETSTRUCT(type(typename)); - op = tp->typoutput; - return((char *) fmgr(op, value)); + TypeTupleForm tp; + Oid op; + + tp = (TypeTupleForm) GETSTRUCT(type(typename)); + op = tp->typoutput; + return ((char *) fmgr(op, value)); } + #endif /* Given a Type and a string, return the internal form of that string */ -char * +char * instr2(Type tp, char *string, int typlen) { - return(instr1((TypeTupleForm ) GETSTRUCT(tp), string, typlen)); + return (instr1((TypeTupleForm) GETSTRUCT(tp), string, typlen)); } /* Given a type structure and a string, returns the internal form of that string */ -static char * +static char * instr1(TypeTupleForm tp, char *string, int typlen) { - Oid op; - Oid typelem; - - op = tp->typinput; - typelem = tp->typelem; /* XXX - used for array_in */ - /* typlen is for bpcharin() and varcharin() */ - return((char *) fmgr(op, string, typelem, typlen)); + Oid op; + Oid typelem; + + op = tp->typinput; + typelem = tp->typelem; /* XXX - used for array_in */ + /* typlen is for bpcharin() and varcharin() */ + return ((char *) fmgr(op, string, typelem, typlen)); } /* Given the attribute type of an array return the arrtribute type of @@ -831,151 +937,160 @@ instr1(TypeTupleForm tp, char *string, int typlen) Oid GetArrayElementType(Oid typearray) { - HeapTuple type_tuple; - TypeTupleForm type_struct_array; - - type_tuple = SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(typearray), - 0,0,0); - - if (!HeapTupleIsValid(type_tuple)) - elog(WARN, "GetArrayElementType: Cache lookup failed for type %d\n", - typearray); - - /* get the array type struct from the type tuple */ - type_struct_array = (TypeTupleForm) GETSTRUCT(type_tuple); - - if (type_struct_array->typelem == InvalidOid) { - elog(WARN, "GetArrayElementType: type %s is not an array", - (Name)&(type_struct_array->typname.data[0])); - } - - return(type_struct_array->typelem); + HeapTuple type_tuple; + TypeTupleForm type_struct_array; + + type_tuple = SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(typearray), + 0, 0, 0); + + if (!HeapTupleIsValid(type_tuple)) + elog(WARN, "GetArrayElementType: Cache lookup failed for type %d\n", + typearray); + + /* get the array type struct from the type tuple */ + type_struct_array = (TypeTupleForm) GETSTRUCT(type_tuple); + + if (type_struct_array->typelem == InvalidOid) + { + elog(WARN, "GetArrayElementType: type %s is not an array", + (Name) & (type_struct_array->typname.data[0])); + } + + return (type_struct_array->typelem); } Oid funcid_get_rettype(Oid funcid) { - HeapTuple func_tuple = NULL; - Oid funcrettype = (Oid)0; - - func_tuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(funcid), - 0,0,0); - - if ( !HeapTupleIsValid ( func_tuple )) - elog (WARN, "function %d does not exist", funcid); - - funcrettype = (Oid) - ((Form_pg_proc)GETSTRUCT(func_tuple))->prorettype ; - - return (funcrettype); + HeapTuple func_tuple = NULL; + Oid funcrettype = (Oid) 0; + + func_tuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(funcid), + 0, 0, 0); + + if (!HeapTupleIsValid(func_tuple)) + elog(WARN, "function %d does not exist", funcid); + + funcrettype = (Oid) + ((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype; + + return (funcrettype); } /* * get a list of all argument type vectors for which a function named * funcname taking nargs arguments exists */ -static CandidateList +static CandidateList func_get_candidates(char *funcname, int nargs) { - Relation heapRelation; - Relation idesc; - ScanKeyData skey; - HeapTuple tuple; - IndexScanDesc sd; - RetrieveIndexResult indexRes; - Buffer buffer; - Form_pg_proc pgProcP; - bool bufferUsed = FALSE; - CandidateList candidates = NULL; - CandidateList current_candidate; - int i; - - heapRelation = heap_openr(ProcedureRelationName); - ScanKeyEntryInitialize(&skey, - (bits16)0x0, - (AttrNumber)1, - (RegProcedure)NameEqualRegProcedure, - (Datum)funcname); - - idesc = index_openr(ProcedureNameIndex); - - sd = index_beginscan(idesc, false, 1, &skey); - - do { - tuple = (HeapTuple)NULL; - if (bufferUsed) { - ReleaseBuffer(buffer); - bufferUsed = FALSE; - } - - indexRes = index_getnext(sd, ForwardScanDirection); - if (indexRes) { - ItemPointer iptr; - - iptr = &indexRes->heap_iptr; - tuple = heap_fetch(heapRelation, NowTimeQual, iptr, &buffer); - pfree(indexRes); - if (HeapTupleIsValid(tuple)) { - pgProcP = (Form_pg_proc)GETSTRUCT(tuple); - bufferUsed = TRUE; - if (pgProcP->pronargs == nargs) { - current_candidate = (CandidateList) - palloc(sizeof(struct _CandidateList)); - current_candidate->args = (Oid *) - palloc(8 * sizeof(Oid)); - memset(current_candidate->args, 0, 8 * sizeof(Oid)); - for (i=0; i<nargs; i++) { - current_candidate->args[i] = - pgProcP->proargtypes[i]; - } - - current_candidate->next = candidates; - candidates = current_candidate; + Relation heapRelation; + Relation idesc; + ScanKeyData skey; + HeapTuple tuple; + IndexScanDesc sd; + RetrieveIndexResult indexRes; + Buffer buffer; + Form_pg_proc pgProcP; + bool bufferUsed = FALSE; + CandidateList candidates = NULL; + CandidateList current_candidate; + int i; + + heapRelation = heap_openr(ProcedureRelationName); + ScanKeyEntryInitialize(&skey, + (bits16) 0x0, + (AttrNumber) 1, + (RegProcedure) NameEqualRegProcedure, + (Datum) funcname); + + idesc = index_openr(ProcedureNameIndex); + + sd = index_beginscan(idesc, false, 1, &skey); + + do + { + tuple = (HeapTuple) NULL; + if (bufferUsed) + { + ReleaseBuffer(buffer); + bufferUsed = FALSE; } - } - } - } while (indexRes); - - index_endscan(sd); - index_close(idesc); - heap_close(heapRelation); - - return candidates; + + indexRes = index_getnext(sd, ForwardScanDirection); + if (indexRes) + { + ItemPointer iptr; + + iptr = &indexRes->heap_iptr; + tuple = heap_fetch(heapRelation, NowTimeQual, iptr, &buffer); + pfree(indexRes); + if (HeapTupleIsValid(tuple)) + { + pgProcP = (Form_pg_proc) GETSTRUCT(tuple); + bufferUsed = TRUE; + if (pgProcP->pronargs == nargs) + { + current_candidate = (CandidateList) + palloc(sizeof(struct _CandidateList)); + current_candidate->args = (Oid *) + palloc(8 * sizeof(Oid)); + memset(current_candidate->args, 0, 8 * sizeof(Oid)); + for (i = 0; i < nargs; i++) + { + current_candidate->args[i] = + pgProcP->proargtypes[i]; + } + + current_candidate->next = candidates; + candidates = current_candidate; + } + } + } + } while (indexRes); + + index_endscan(sd); + index_close(idesc); + heap_close(heapRelation); + + return candidates; } /* * can input_typeids be coerced to func_typeids? */ -static bool -can_coerce(int nargs, Oid *input_typeids, Oid *func_typeids) +static bool +can_coerce(int nargs, Oid * input_typeids, Oid * func_typeids) { - int i; - Type tp; - - /* - * right now, we only coerce "unknown", and we cannot coerce it to a - * relation type - */ - for (i=0; i<nargs; i++) { - if (input_typeids[i] != func_typeids[i]) { - if ((input_typeids[i] == BPCHAROID && func_typeids[i] == TEXTOID) || - (input_typeids[i] == BPCHAROID && func_typeids[i] == VARCHAROID) || - (input_typeids[i] == VARCHAROID && func_typeids[i] == TEXTOID) || - (input_typeids[i] == VARCHAROID && func_typeids[i] == BPCHAROID) || - (input_typeids[i] == CASHOID && func_typeids[i] == INT4OID) || - (input_typeids[i] == INT4OID && func_typeids[i] == CASHOID)) - ; /* these are OK */ - else if (input_typeids[i] != UNKNOWNOID || func_typeids[i] == 0) - return false; - - tp = get_id_type(input_typeids[i]); - if (typetypetype(tp) == 'c' ) - return false; + int i; + Type tp; + + /* + * right now, we only coerce "unknown", and we cannot coerce it to a + * relation type + */ + for (i = 0; i < nargs; i++) + { + if (input_typeids[i] != func_typeids[i]) + { + if ((input_typeids[i] == BPCHAROID && func_typeids[i] == TEXTOID) || + (input_typeids[i] == BPCHAROID && func_typeids[i] == VARCHAROID) || + (input_typeids[i] == VARCHAROID && func_typeids[i] == TEXTOID) || + (input_typeids[i] == VARCHAROID && func_typeids[i] == BPCHAROID) || + (input_typeids[i] == CASHOID && func_typeids[i] == INT4OID) || + (input_typeids[i] == INT4OID && func_typeids[i] == CASHOID)) + ; /* these are OK */ + else if (input_typeids[i] != UNKNOWNOID || func_typeids[i] == 0) + return false; + + tp = get_id_type(input_typeids[i]); + if (typetypetype(tp) == 'c') + return false; + } } - } - - return true; + + return true; } /* @@ -986,32 +1101,34 @@ can_coerce(int nargs, Oid *input_typeids, Oid *func_typeids) */ static int match_argtypes(int nargs, - Oid *input_typeids, - CandidateList function_typeids, - CandidateList *candidates) /* return value */ + Oid * input_typeids, + CandidateList function_typeids, + CandidateList * candidates) /* return value */ { - CandidateList current_candidate; - CandidateList matching_candidate; - Oid *current_typeids; - int ncandidates = 0; - - *candidates = NULL; - - for (current_candidate = function_typeids; - current_candidate != NULL; - current_candidate = current_candidate->next) { - current_typeids = current_candidate->args; - if (can_coerce(nargs, input_typeids, current_typeids)) { - matching_candidate = (CandidateList) - palloc(sizeof(struct _CandidateList)); - matching_candidate->args = current_typeids; - matching_candidate->next = *candidates; - *candidates = matching_candidate; - ncandidates++; + CandidateList current_candidate; + CandidateList matching_candidate; + Oid *current_typeids; + int ncandidates = 0; + + *candidates = NULL; + + for (current_candidate = function_typeids; + current_candidate != NULL; + current_candidate = current_candidate->next) + { + current_typeids = current_candidate->args; + if (can_coerce(nargs, input_typeids, current_typeids)) + { + matching_candidate = (CandidateList) + palloc(sizeof(struct _CandidateList)); + matching_candidate->args = current_typeids; + matching_candidate->next = *candidates; + *candidates = matching_candidate; + ncandidates++; + } } - } - - return ncandidates; + + return ncandidates; } /* @@ -1020,442 +1137,483 @@ match_argtypes(int nargs, * returns the selected argtype array if the conflict can be resolved, * otherwise returns NULL */ -static Oid * +static Oid * func_select_candidate(int nargs, - Oid *input_typeids, - CandidateList candidates) + Oid * input_typeids, + CandidateList candidates) { - /* XXX no conflict resolution implemeneted yet */ - return (NULL); + /* XXX no conflict resolution implemeneted yet */ + return (NULL); } bool func_get_detail(char *funcname, - int nargs, - Oid *oid_array, - Oid *funcid, /* return value */ - Oid *rettype, /* return value */ - bool *retset, /* return value */ - Oid **true_typeids) /* return value */ + int nargs, + Oid * oid_array, + Oid * funcid, /* return value */ + Oid * rettype, /* return value */ + bool * retset, /* return value */ + Oid ** true_typeids) /* return value */ { - Oid **input_typeid_vector; - Oid *current_input_typeids; - CandidateList function_typeids; - CandidateList current_function_typeids; - HeapTuple ftup; - Form_pg_proc pform; - - /* - * attempt to find named function in the system catalogs - * with arguments exactly as specified - so that the normal - * case is just as quick as before - */ - ftup = SearchSysCacheTuple(PRONAME, - PointerGetDatum(funcname), - Int32GetDatum(nargs), - PointerGetDatum(oid_array), - 0); - *true_typeids = oid_array; - - /* - * If an exact match isn't found : - * 1) get a vector of all possible input arg type arrays constructed - * from the superclasses of the original input arg types - * 2) get a list of all possible argument type arrays to the - * function with given name and number of arguments - * 3) for each input arg type array from vector #1 : - * a) find how many of the function arg type arrays from list #2 - * it can be coerced to - * b) - if the answer is one, we have our function - * - if the answer is more than one, attempt to resolve the - * conflict - * - if the answer is zero, try the next array from vector #1 - */ - if (!HeapTupleIsValid(ftup)) { - function_typeids = func_get_candidates(funcname, nargs); - - if (function_typeids != NULL) { - int ncandidates = 0; - - input_typeid_vector = argtype_inherit(nargs, oid_array); - current_input_typeids = oid_array; - - do { - ncandidates = match_argtypes(nargs, current_input_typeids, - function_typeids, - ¤t_function_typeids); - if (ncandidates == 1) { - *true_typeids = current_function_typeids->args; - ftup = SearchSysCacheTuple(PRONAME, - PointerGetDatum(funcname), - Int32GetDatum(nargs), - PointerGetDatum(*true_typeids), - 0); - Assert(HeapTupleIsValid(ftup)); + Oid **input_typeid_vector; + Oid *current_input_typeids; + CandidateList function_typeids; + CandidateList current_function_typeids; + HeapTuple ftup; + Form_pg_proc pform; + + /* + * attempt to find named function in the system catalogs with + * arguments exactly as specified - so that the normal case is just as + * quick as before + */ + ftup = SearchSysCacheTuple(PRONAME, + PointerGetDatum(funcname), + Int32GetDatum(nargs), + PointerGetDatum(oid_array), + 0); + *true_typeids = oid_array; + + /* + * If an exact match isn't found : 1) get a vector of all possible + * input arg type arrays constructed from the superclasses of the + * original input arg types 2) get a list of all possible argument + * type arrays to the function with given name and number of arguments + * 3) for each input arg type array from vector #1 : a) find how many + * of the function arg type arrays from list #2 it can be coerced to + * b) - if the answer is one, we have our function - if the answer is + * more than one, attempt to resolve the conflict - if the answer is + * zero, try the next array from vector #1 + */ + if (!HeapTupleIsValid(ftup)) + { + function_typeids = func_get_candidates(funcname, nargs); + + if (function_typeids != NULL) + { + int ncandidates = 0; + + input_typeid_vector = argtype_inherit(nargs, oid_array); + current_input_typeids = oid_array; + + do + { + ncandidates = match_argtypes(nargs, current_input_typeids, + function_typeids, + ¤t_function_typeids); + if (ncandidates == 1) + { + *true_typeids = current_function_typeids->args; + ftup = SearchSysCacheTuple(PRONAME, + PointerGetDatum(funcname), + Int32GetDatum(nargs), + PointerGetDatum(*true_typeids), + 0); + Assert(HeapTupleIsValid(ftup)); + } + else if (ncandidates > 1) + { + *true_typeids = + func_select_candidate(nargs, + current_input_typeids, + current_function_typeids); + if (*true_typeids == NULL) + { + elog(NOTICE, "there is more than one function named \"%s\"", + funcname); + elog(NOTICE, "that satisfies the given argument types. you will have to"); + elog(NOTICE, "retype your query using explicit typecasts."); + func_error("func_get_detail", funcname, nargs, oid_array); + } + else + { + ftup = SearchSysCacheTuple(PRONAME, + PointerGetDatum(funcname), + Int32GetDatum(nargs), + PointerGetDatum(*true_typeids), + 0); + Assert(HeapTupleIsValid(ftup)); + } + } + current_input_typeids = *input_typeid_vector++; + } + while (current_input_typeids != + InvalidOid && ncandidates == 0); } - else if (ncandidates > 1) { - *true_typeids = - func_select_candidate(nargs, - current_input_typeids, - current_function_typeids); - if (*true_typeids == NULL) { - elog(NOTICE, "there is more than one function named \"%s\"", - funcname); - elog(NOTICE, "that satisfies the given argument types. you will have to"); - elog(NOTICE, "retype your query using explicit typecasts."); - func_error("func_get_detail", funcname, nargs, oid_array); - } - else { - ftup = SearchSysCacheTuple(PRONAME, - PointerGetDatum(funcname), - Int32GetDatum(nargs), - PointerGetDatum(*true_typeids), - 0); - Assert(HeapTupleIsValid(ftup)); - } + } + + if (!HeapTupleIsValid(ftup)) + { + Type tp; + + if (nargs == 1) + { + tp = get_id_type(oid_array[0]); + if (typetypetype(tp) == 'c') + elog(WARN, "no such attribute or function \"%s\"", + funcname); } - current_input_typeids = *input_typeid_vector++; - } - while (current_input_typeids != - InvalidOid && ncandidates == 0); + func_error("func_get_detail", funcname, nargs, oid_array); } - } - - if (!HeapTupleIsValid(ftup)) { - Type tp; - - if (nargs == 1) { - tp = get_id_type(oid_array[0]); - if (typetypetype(tp) == 'c') - elog(WARN, "no such attribute or function \"%s\"", - funcname); + else + { + pform = (Form_pg_proc) GETSTRUCT(ftup); + *funcid = ftup->t_oid; + *rettype = pform->prorettype; + *retset = pform->proretset; + + return (true); } - func_error("func_get_detail", funcname, nargs, oid_array); - } else { - pform = (Form_pg_proc) GETSTRUCT(ftup); - *funcid = ftup->t_oid; - *rettype = pform->prorettype; - *retset = pform->proretset; - - return (true); - } /* shouldn't reach here */ - return (false); + return (false); } /* - * argtype_inherit() -- Construct an argtype vector reflecting the - * inheritance properties of the supplied argv. + * argtype_inherit() -- Construct an argtype vector reflecting the + * inheritance properties of the supplied argv. * - * This function is used to disambiguate among functions with the - * same name but different signatures. It takes an array of eight - * type ids. For each type id in the array that's a complex type - * (a class), it walks up the inheritance tree, finding all - * superclasses of that type. A vector of new Oid type arrays - * is returned to the caller, reflecting the structure of the - * inheritance tree above the supplied arguments. + * This function is used to disambiguate among functions with the + * same name but different signatures. It takes an array of eight + * type ids. For each type id in the array that's a complex type + * (a class), it walks up the inheritance tree, finding all + * superclasses of that type. A vector of new Oid type arrays + * is returned to the caller, reflecting the structure of the + * inheritance tree above the supplied arguments. * - * The order of this vector is as follows: all superclasses of the - * rightmost complex class are explored first. The exploration - * continues from right to left. This policy means that we favor - * keeping the leftmost argument type as low in the inheritance tree - * as possible. This is intentional; it is exactly what we need to - * do for method dispatch. The last type array we return is all - * zeroes. This will match any functions for which return types are - * not defined. There are lots of these (mostly builtins) in the - * catalogs. + * The order of this vector is as follows: all superclasses of the + * rightmost complex class are explored first. The exploration + * continues from right to left. This policy means that we favor + * keeping the leftmost argument type as low in the inheritance tree + * as possible. This is intentional; it is exactly what we need to + * do for method dispatch. The last type array we return is all + * zeroes. This will match any functions for which return types are + * not defined. There are lots of these (mostly builtins) in the + * catalogs. */ -static Oid ** -argtype_inherit(int nargs, Oid *oid_array) +static Oid ** +argtype_inherit(int nargs, Oid * oid_array) { - Oid relid; - int i; - InhPaths arginh[MAXFARGS]; - - for (i = 0; i < MAXFARGS; i++) { - if (i < nargs) { - arginh[i].self = oid_array[i]; - if ((relid = typeid_get_relid(oid_array[i])) != InvalidOid) { - arginh[i].nsupers = findsupers(relid, &(arginh[i].supervec)); - } else { - arginh[i].nsupers = 0; - arginh[i].supervec = (Oid *) NULL; - } - } else { - arginh[i].self = InvalidOid; - arginh[i].nsupers = 0; - arginh[i].supervec = (Oid *) NULL; + Oid relid; + int i; + InhPaths arginh[MAXFARGS]; + + for (i = 0; i < MAXFARGS; i++) + { + if (i < nargs) + { + arginh[i].self = oid_array[i]; + if ((relid = typeid_get_relid(oid_array[i])) != InvalidOid) + { + arginh[i].nsupers = findsupers(relid, &(arginh[i].supervec)); + } + else + { + arginh[i].nsupers = 0; + arginh[i].supervec = (Oid *) NULL; + } + } + else + { + arginh[i].self = InvalidOid; + arginh[i].nsupers = 0; + arginh[i].supervec = (Oid *) NULL; + } } - } - - /* return an ordered cross-product of the classes involved */ - return (genxprod(arginh, nargs)); + + /* return an ordered cross-product of the classes involved */ + return (genxprod(arginh, nargs)); } -typedef struct _SuperQE { - Oid sqe_relid; -} SuperQE; +typedef struct _SuperQE +{ + Oid sqe_relid; +} SuperQE; static int -findsupers(Oid relid, Oid **supervec) +findsupers(Oid relid, Oid ** supervec) { - Oid *relidvec; - Relation inhrel; - HeapScanDesc inhscan; - ScanKeyData skey; - HeapTuple inhtup; - TupleDesc inhtupdesc; - int nvisited; - SuperQE *qentry, *vnode; - Dllist *visited, *queue; - Dlelem *qe, *elt; - - Relation rd; - Buffer buf; - Datum d; - bool newrelid; - char isNull; - - nvisited = 0; - queue = DLNewList(); - visited = DLNewList(); - - - inhrel = heap_openr(InheritsRelationName); - RelationSetLockForRead(inhrel); - inhtupdesc = RelationGetTupleDescriptor(inhrel); - - /* - * Use queue to do a breadth-first traversal of the inheritance - * graph from the relid supplied up to the root. - */ - do { - ScanKeyEntryInitialize(&skey, 0x0, Anum_pg_inherits_inhrel, - ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relid)); - - inhscan = heap_beginscan(inhrel, 0, NowTimeQual, 1, &skey); - - while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0, &buf))) { - qentry = (SuperQE *) palloc(sizeof(SuperQE)); - - d = (Datum) fastgetattr(inhtup, Anum_pg_inherits_inhparent, - inhtupdesc, &isNull); - qentry->sqe_relid = DatumGetObjectId(d); - - /* put this one on the queue */ - DLAddTail(queue, DLNewElem(qentry)); - - ReleaseBuffer(buf); + Oid *relidvec; + Relation inhrel; + HeapScanDesc inhscan; + ScanKeyData skey; + HeapTuple inhtup; + TupleDesc inhtupdesc; + int nvisited; + SuperQE *qentry, + *vnode; + Dllist *visited, + *queue; + Dlelem *qe, + *elt; + + Relation rd; + Buffer buf; + Datum d; + bool newrelid; + char isNull; + + nvisited = 0; + queue = DLNewList(); + visited = DLNewList(); + + + inhrel = heap_openr(InheritsRelationName); + RelationSetLockForRead(inhrel); + inhtupdesc = RelationGetTupleDescriptor(inhrel); + + /* + * Use queue to do a breadth-first traversal of the inheritance graph + * from the relid supplied up to the root. + */ + do + { + ScanKeyEntryInitialize(&skey, 0x0, Anum_pg_inherits_inhrel, + ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relid)); + + inhscan = heap_beginscan(inhrel, 0, NowTimeQual, 1, &skey); + + while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0, &buf))) + { + qentry = (SuperQE *) palloc(sizeof(SuperQE)); + + d = (Datum) fastgetattr(inhtup, Anum_pg_inherits_inhparent, + inhtupdesc, &isNull); + qentry->sqe_relid = DatumGetObjectId(d); + + /* put this one on the queue */ + DLAddTail(queue, DLNewElem(qentry)); + + ReleaseBuffer(buf); + } + + heap_endscan(inhscan); + + /* pull next unvisited relid off the queue */ + do + { + qe = DLRemHead(queue); + qentry = qe ? (SuperQE *) DLE_VAL(qe) : NULL; + + if (qentry == (SuperQE *) NULL) + break; + + relid = qentry->sqe_relid; + newrelid = true; + + for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt)) + { + vnode = (SuperQE *) DLE_VAL(elt); + if (vnode && (qentry->sqe_relid == vnode->sqe_relid)) + { + newrelid = false; + break; + } + } + } while (!newrelid); + + if (qentry != (SuperQE *) NULL) + { + + /* save the type id, rather than the relation id */ + if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL) + elog(WARN, "relid %d does not exist", qentry->sqe_relid); + qentry->sqe_relid = typeid(type(RelationGetRelationName(rd)->data)); + heap_close(rd); + + DLAddTail(visited, qe); + + nvisited++; + } + } while (qentry != (SuperQE *) NULL); + + RelationUnsetLockForRead(inhrel); + heap_close(inhrel); + + if (nvisited > 0) + { + relidvec = (Oid *) palloc(nvisited * sizeof(Oid)); + *supervec = relidvec; + + for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt)) + { + vnode = (SuperQE *) DLE_VAL(elt); + *relidvec++ = vnode->sqe_relid; + } + } - - heap_endscan(inhscan); - - /* pull next unvisited relid off the queue */ - do { - qe = DLRemHead(queue); - qentry = qe ? (SuperQE*)DLE_VAL(qe) : NULL; - - if (qentry == (SuperQE *) NULL) - break; - - relid = qentry->sqe_relid; - newrelid = true; - - for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt)) { - vnode = (SuperQE*)DLE_VAL(elt); - if (vnode && (qentry->sqe_relid == vnode->sqe_relid)) { - newrelid = false; - break; - } - } - } while (!newrelid); - - if (qentry != (SuperQE *) NULL) { - - /* save the type id, rather than the relation id */ - if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL) - elog(WARN, "relid %d does not exist", qentry->sqe_relid); - qentry->sqe_relid = typeid(type(RelationGetRelationName(rd)->data)); - heap_close(rd); - - DLAddTail(visited, qe); - - nvisited++; + else + { + *supervec = (Oid *) NULL; } - } while (qentry != (SuperQE *) NULL); - - RelationUnsetLockForRead(inhrel); - heap_close(inhrel); - - if (nvisited > 0) { - relidvec = (Oid *) palloc(nvisited * sizeof(Oid)); - *supervec = relidvec; - - for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt)) { - vnode = (SuperQE*)DLE_VAL(elt); - *relidvec++ = vnode->sqe_relid; - } - - } else { - *supervec = (Oid *) NULL; - } - - return (nvisited); + + return (nvisited); } -static Oid ** -genxprod(InhPaths *arginh, int nargs) +static Oid ** +genxprod(InhPaths * arginh, int nargs) { - int nanswers; - Oid **result, **iter; - Oid *oneres; - int i, j; - int cur[MAXFARGS]; - - nanswers = 1; - for (i = 0; i < nargs; i++) { - nanswers *= (arginh[i].nsupers + 2); - cur[i] = 0; - } - - iter = result = (Oid **) palloc(sizeof(Oid *) * nanswers); - - /* compute the cross product from right to left */ - for (;;) { - oneres = (Oid *) palloc(MAXFARGS * sizeof(Oid)); - memset(oneres, 0, MAXFARGS * sizeof(Oid)); - - for (i = nargs - 1; i >= 0 && cur[i] > arginh[i].nsupers; i--) - continue; - - /* if we're done, terminate with NULL pointer */ - if (i < 0) { - *iter = NULL; - return (result); + int nanswers; + Oid **result, + **iter; + Oid *oneres; + int i, + j; + int cur[MAXFARGS]; + + nanswers = 1; + for (i = 0; i < nargs; i++) + { + nanswers *= (arginh[i].nsupers + 2); + cur[i] = 0; } - - /* no, increment this column and zero the ones after it */ - cur[i] = cur[i] + 1; - for (j = nargs - 1; j > i; j--) - cur[j] = 0; - - for (i = 0; i < nargs; i++) { - if (cur[i] == 0) - oneres[i] = arginh[i].self; - else if (cur[i] > arginh[i].nsupers) - oneres[i] = 0; /* wild card */ - else - oneres[i] = arginh[i].supervec[cur[i] - 1]; + + iter = result = (Oid **) palloc(sizeof(Oid *) * nanswers); + + /* compute the cross product from right to left */ + for (;;) + { + oneres = (Oid *) palloc(MAXFARGS * sizeof(Oid)); + memset(oneres, 0, MAXFARGS * sizeof(Oid)); + + for (i = nargs - 1; i >= 0 && cur[i] > arginh[i].nsupers; i--) + continue; + + /* if we're done, terminate with NULL pointer */ + if (i < 0) + { + *iter = NULL; + return (result); + } + + /* no, increment this column and zero the ones after it */ + cur[i] = cur[i] + 1; + for (j = nargs - 1; j > i; j--) + cur[j] = 0; + + for (i = 0; i < nargs; i++) + { + if (cur[i] == 0) + oneres[i] = arginh[i].self; + else if (cur[i] > arginh[i].nsupers) + oneres[i] = 0; /* wild card */ + else + oneres[i] = arginh[i].supervec[cur[i] - 1]; + } + + *iter++ = oneres; } - - *iter++ = oneres; - } } /* Given a type id, returns the in-conversion function of the type */ Oid typeid_get_retinfunc(Oid type_id) { - HeapTuple typeTuple; - TypeTupleForm type; - Oid infunc; - typeTuple = SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(type_id), - 0,0,0); - if ( !HeapTupleIsValid ( typeTuple )) - elog(WARN, - "typeid_get_retinfunc: Invalid type - oid = %u", - type_id); - - type = (TypeTupleForm) GETSTRUCT(typeTuple); - infunc = type->typinput; - return(infunc); + HeapTuple typeTuple; + TypeTupleForm type; + Oid infunc; + + typeTuple = SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(type_id), + 0, 0, 0); + if (!HeapTupleIsValid(typeTuple)) + elog(WARN, + "typeid_get_retinfunc: Invalid type - oid = %u", + type_id); + + type = (TypeTupleForm) GETSTRUCT(typeTuple); + infunc = type->typinput; + return (infunc); } /* Given a type id, returns the out-conversion function of the type */ Oid typeid_get_retoutfunc(Oid type_id) { - HeapTuple typeTuple; - TypeTupleForm type; - Oid outfunc; - typeTuple = SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(type_id), - 0,0,0); - if ( !HeapTupleIsValid ( typeTuple )) - elog(WARN, - "typeid_get_retoutfunc: Invalid type - oid = %u", - type_id); - - type = (TypeTupleForm) GETSTRUCT(typeTuple); - outfunc = type->typoutput; - return(outfunc); + HeapTuple typeTuple; + TypeTupleForm type; + Oid outfunc; + + typeTuple = SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(type_id), + 0, 0, 0); + if (!HeapTupleIsValid(typeTuple)) + elog(WARN, + "typeid_get_retoutfunc: Invalid type - oid = %u", + type_id); + + type = (TypeTupleForm) GETSTRUCT(typeTuple); + outfunc = type->typoutput; + return (outfunc); } Oid typeid_get_relid(Oid type_id) { - HeapTuple typeTuple; - TypeTupleForm type; - Oid infunc; - typeTuple = SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(type_id), - 0,0,0); - if ( !HeapTupleIsValid ( typeTuple )) - elog(WARN, "typeid_get_relid: Invalid type - oid = %u ", type_id); - - type = (TypeTupleForm) GETSTRUCT(typeTuple); - infunc = type->typrelid; - return(infunc); + HeapTuple typeTuple; + TypeTupleForm type; + Oid infunc; + + typeTuple = SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(type_id), + 0, 0, 0); + if (!HeapTupleIsValid(typeTuple)) + elog(WARN, "typeid_get_relid: Invalid type - oid = %u ", type_id); + + type = (TypeTupleForm) GETSTRUCT(typeTuple); + infunc = type->typrelid; + return (infunc); } Oid get_typrelid(Type typ) { - TypeTupleForm typtup; - - typtup = (TypeTupleForm) GETSTRUCT(typ); - - return (typtup->typrelid); + TypeTupleForm typtup; + + typtup = (TypeTupleForm) GETSTRUCT(typ); + + return (typtup->typrelid); } Oid get_typelem(Oid type_id) { - HeapTuple typeTuple; - TypeTupleForm type; - - if (!(typeTuple = SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(type_id), - 0,0,0))) { - elog (WARN , "type id lookup of %u failed", type_id); - } - type = (TypeTupleForm) GETSTRUCT(typeTuple); - - return (type->typelem); + HeapTuple typeTuple; + TypeTupleForm type; + + if (!(typeTuple = SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(type_id), + 0, 0, 0))) + { + elog(WARN, "type id lookup of %u failed", type_id); + } + type = (TypeTupleForm) GETSTRUCT(typeTuple); + + return (type->typelem); } #ifdef NOT_USED char FindDelimiter(char *typename) { - char delim; - HeapTuple typeTuple; - TypeTupleForm type; - - - if (!(typeTuple = SearchSysCacheTuple(TYPNAME, - PointerGetDatum(typename), - 0,0,0))) { - elog (WARN , "type name lookup of %s failed", typename); - } - type = (TypeTupleForm) GETSTRUCT(typeTuple); - - delim = type->typdelim; - return (delim); + char delim; + HeapTuple typeTuple; + TypeTupleForm type; + + + if (!(typeTuple = SearchSysCacheTuple(TYPNAME, + PointerGetDatum(typename), + 0, 0, 0))) + { + elog(WARN, "type name lookup of %s failed", typename); + } + type = (TypeTupleForm) GETSTRUCT(typeTuple); + + delim = type->typdelim; + return (delim); } + #endif /* @@ -1465,26 +1623,33 @@ FindDelimiter(char *typename) static void op_error(char *op, Oid arg1, Oid arg2) { - Type tp1 = NULL, tp2 = NULL; - - if (check_typeid(arg1)) { - tp1 = get_id_type(arg1); - } else { - elog(WARN, "left hand side of operator %s has an unknown type, probably a bad attribute name", op); - } - - if (check_typeid(arg2)) { - tp2 = get_id_type(arg2); - } else { - elog(WARN, "right hand side of operator %s has an unknown type, probably a bad attribute name", op); - } - - elog(NOTICE, "there is no operator %s for types %s and %s", - op, tname(tp1),tname(tp2)); - elog(NOTICE, "You will either have to retype this query using an"); - elog(NOTICE, "explicit cast, or you will have to define the operator"); - elog(WARN, "%s for %s and %s using CREATE OPERATOR", - op, tname(tp1),tname(tp2)); + Type tp1 = NULL, + tp2 = NULL; + + if (check_typeid(arg1)) + { + tp1 = get_id_type(arg1); + } + else + { + elog(WARN, "left hand side of operator %s has an unknown type, probably a bad attribute name", op); + } + + if (check_typeid(arg2)) + { + tp2 = get_id_type(arg2); + } + else + { + elog(WARN, "right hand side of operator %s has an unknown type, probably a bad attribute name", op); + } + + elog(NOTICE, "there is no operator %s for types %s and %s", + op, tname(tp1), tname(tp2)); + elog(NOTICE, "You will either have to retype this query using an"); + elog(NOTICE, "explicit cast, or you will have to define the operator"); + elog(WARN, "%s for %s and %s using CREATE OPERATOR", + op, tname(tp1), tname(tp2)); } /* @@ -1492,27 +1657,32 @@ op_error(char *op, Oid arg1, Oid arg2) * argument types */ void -func_error(char *caller, char *funcname, int nargs, Oid *argtypes) +func_error(char *caller, char *funcname, int nargs, Oid * argtypes) { - char p[(NAMEDATALEN+2)*MAXFMGRARGS], *ptr; - int i; - - ptr = p; - *ptr = '\0'; - for (i=0; i<nargs; i++) { - if (i) { - *ptr++ = ','; - *ptr++ = ' '; + char p[(NAMEDATALEN + 2) * MAXFMGRARGS], + *ptr; + int i; + + ptr = p; + *ptr = '\0'; + for (i = 0; i < nargs; i++) + { + if (i) + { + *ptr++ = ','; + *ptr++ = ' '; + } + if (argtypes[i] != 0) + { + strcpy(ptr, tname(get_id_type(argtypes[i]))); + *(ptr + NAMEDATALEN) = '\0'; + } + else + strcpy(ptr, "opaque"); + ptr += strlen(ptr); } - if (argtypes[i] != 0) { - strcpy(ptr, tname(get_id_type(argtypes[i]))); - *(ptr + NAMEDATALEN) = '\0'; - } else - strcpy(ptr, "opaque"); - ptr += strlen(ptr); - } - - elog(WARN, "%s: function %s(%s) does not exist", caller, funcname, p); + + elog(WARN, "%s: function %s(%s) does not exist", caller, funcname, p); } /* @@ -1522,12 +1692,19 @@ func_error(char *caller, char *funcname, int nargs, Oid *argtypes) void agg_error(char *caller, char *aggname, Oid basetypeID) { - /* basetypeID that is Invalid (zero) means aggregate over all types. (count) */ - - if (basetypeID == InvalidOid) { - elog(WARN, "%s: aggregate '%s' for all types does not exist", caller, aggname); - } else { - elog(WARN, "%s: aggregate '%s' for '%s' does not exist", caller, aggname, - tname(get_id_type(basetypeID))); - } + + /* + * basetypeID that is Invalid (zero) means aggregate over all types. + * (count) + */ + + if (basetypeID == InvalidOid) + { + elog(WARN, "%s: aggregate '%s' for all types does not exist", caller, aggname); + } + else + { + elog(WARN, "%s: aggregate '%s' for '%s' does not exist", caller, aggname, + tname(get_id_type(basetypeID))); + } } |