mirror of
https://github.com/postgres/postgres.git
synced 2025-11-16 15:02:33 +03:00
Implement types regprocedure, regoper, regoperator, regclass, regtype
per pghackers discussion. Add some more typsanity tests, and clean up some problems exposed thereby (broken or missing array types for some built-in types). Also, clean up loose ends from unknownin/out patch.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.125 2002/03/26 19:15:16 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.126 2002/04/25 02:56:55 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -109,12 +109,14 @@ static struct typinfo Procid[] = {
|
||||
{"int2vector", INT2VECTOROID, 0, INDEX_MAX_KEYS * 2, F_INT2VECTORIN, F_INT2VECTOROUT},
|
||||
{"int4", INT4OID, 0, 4, F_INT4IN, F_INT4OUT},
|
||||
{"regproc", REGPROCOID, 0, 4, F_REGPROCIN, F_REGPROCOUT},
|
||||
{"regclass", REGCLASSOID, 0, 4, F_REGCLASSIN, F_REGCLASSOUT},
|
||||
{"regtype", REGTYPEOID, 0, 4, F_REGTYPEIN, F_REGTYPEOUT},
|
||||
{"text", TEXTOID, 0, -1, F_TEXTIN, F_TEXTOUT},
|
||||
{"oid", OIDOID, 0, 4, F_OIDIN, F_OIDOUT},
|
||||
{"tid", TIDOID, 0, 6, F_TIDIN, F_TIDOUT},
|
||||
{"xid", XIDOID, 0, 4, F_XIDIN, F_XIDOUT},
|
||||
{"cid", CIDOID, 0, 4, F_CIDIN, F_CIDOUT},
|
||||
{"oidvector", 30, 0, INDEX_MAX_KEYS * 4, F_OIDVECTORIN, F_OIDVECTOROUT},
|
||||
{"oidvector", OIDVECTOROID, 0, INDEX_MAX_KEYS * 4, F_OIDVECTORIN, F_OIDVECTOROUT},
|
||||
{"smgr", 210, 0, 2, F_SMGRIN, F_SMGROUT},
|
||||
{"_int4", 1007, INT4OID, -1, F_ARRAY_IN, F_ARRAY_OUT},
|
||||
{"_aclitem", 1034, 1033, -1, F_ARRAY_IN, F_ARRAY_OUT}
|
||||
@@ -600,7 +602,7 @@ DefineAttr(char *name, char *type, int attnum)
|
||||
attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
|
||||
attlen = attrtypes[attnum]->attlen = Ap->am_typ.typlen;
|
||||
attrtypes[attnum]->attbyval = Ap->am_typ.typbyval;
|
||||
attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;;
|
||||
attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;
|
||||
attrtypes[attnum]->attalign = Ap->am_typ.typalign;
|
||||
}
|
||||
else
|
||||
@@ -610,28 +612,37 @@ DefineAttr(char *name, char *type, int attnum)
|
||||
elog(DEBUG3, "column %s %s", NameStr(attrtypes[attnum]->attname), type);
|
||||
attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
|
||||
attlen = attrtypes[attnum]->attlen = Procid[typeoid].len;
|
||||
attrtypes[attnum]->attstorage = 'p';
|
||||
|
||||
/*
|
||||
* Cheat like mad to fill in these items from the length only.
|
||||
* This only has to work for types used in the system catalogs...
|
||||
* This only has to work for types that appear in Procid[].
|
||||
*/
|
||||
switch (attlen)
|
||||
{
|
||||
case 1:
|
||||
attrtypes[attnum]->attbyval = true;
|
||||
attrtypes[attnum]->attstorage = 'p';
|
||||
attrtypes[attnum]->attalign = 'c';
|
||||
break;
|
||||
case 2:
|
||||
attrtypes[attnum]->attbyval = true;
|
||||
attrtypes[attnum]->attstorage = 'p';
|
||||
attrtypes[attnum]->attalign = 's';
|
||||
break;
|
||||
case 4:
|
||||
attrtypes[attnum]->attbyval = true;
|
||||
attrtypes[attnum]->attstorage = 'p';
|
||||
attrtypes[attnum]->attalign = 'i';
|
||||
break;
|
||||
case -1:
|
||||
attrtypes[attnum]->attbyval = false;
|
||||
attrtypes[attnum]->attstorage = 'x';
|
||||
attrtypes[attnum]->attalign = 'i';
|
||||
break;
|
||||
default:
|
||||
/* TID and fixed-length arrays, such as oidvector */
|
||||
attrtypes[attnum]->attbyval = false;
|
||||
attrtypes[attnum]->attstorage = 'p';
|
||||
attrtypes[attnum]->attalign = 'i';
|
||||
break;
|
||||
}
|
||||
@@ -803,6 +814,13 @@ cleanup()
|
||||
|
||||
/* ----------------
|
||||
* gettype
|
||||
*
|
||||
* NB: this is really ugly; it will return an integer index into Procid[],
|
||||
* and not an OID at all, until the first reference to a type not known in
|
||||
* Procid[]. At that point it will read and cache pg_type in the Typ array,
|
||||
* and subsequently return a real OID (and set the global pointer Ap to
|
||||
* point at the found row in Typ). So caller must check whether Typ is
|
||||
* still NULL to determine what the return value is!
|
||||
* ----------------
|
||||
*/
|
||||
static Oid
|
||||
@@ -827,7 +845,7 @@ gettype(char *type)
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i <= n_types; i++)
|
||||
for (i = 0; i < n_types; i++)
|
||||
{
|
||||
if (strncmp(type, Procid[i].name, NAMEDATALEN) == 0)
|
||||
return i;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.11 2002/04/17 20:57:56 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.12 2002/04/25 02:56:55 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -365,9 +365,12 @@ OpclassnameGetOpcid(Oid amid, const char *opcname)
|
||||
* Given a possibly-qualified function name and argument count,
|
||||
* retrieve a list of the possible matches.
|
||||
*
|
||||
* If nargs is -1, we return all functions matching the given name,
|
||||
* regardless of argument count.
|
||||
*
|
||||
* We search a single namespace if the function name is qualified, else
|
||||
* all namespaces in the search path. The return list will never contain
|
||||
* multiple entries with identical argument types --- in the multiple-
|
||||
* multiple entries with identical argument lists --- in the multiple-
|
||||
* namespace case, we arrange for entries in earlier namespaces to mask
|
||||
* identical entries in later namespaces.
|
||||
*/
|
||||
@@ -423,11 +426,16 @@ FuncnameGetCandidates(List *names, int nargs)
|
||||
namespaceId = InvalidOid;
|
||||
}
|
||||
|
||||
/* Search syscache by name and nargs only */
|
||||
catlist = SearchSysCacheList(PROCNAMENSP, 2,
|
||||
CStringGetDatum(funcname),
|
||||
Int16GetDatum(nargs),
|
||||
0, 0);
|
||||
/* Search syscache by name and (optionally) nargs only */
|
||||
if (nargs >= 0)
|
||||
catlist = SearchSysCacheList(PROCNAMENSP, 2,
|
||||
CStringGetDatum(funcname),
|
||||
Int16GetDatum(nargs),
|
||||
0, 0);
|
||||
else
|
||||
catlist = SearchSysCacheList(PROCNAMENSP, 1,
|
||||
CStringGetDatum(funcname),
|
||||
0, 0, 0);
|
||||
|
||||
for (i = 0; i < catlist->n_members; i++)
|
||||
{
|
||||
@@ -436,6 +444,8 @@ FuncnameGetCandidates(List *names, int nargs)
|
||||
int pathpos = 0;
|
||||
FuncCandidateList newResult;
|
||||
|
||||
nargs = procform->pronargs;
|
||||
|
||||
if (OidIsValid(namespaceId))
|
||||
{
|
||||
/* Consider only procs in specified namespace */
|
||||
@@ -478,7 +488,8 @@ FuncnameGetCandidates(List *names, int nargs)
|
||||
|
||||
if (catlist->ordered)
|
||||
{
|
||||
if (memcmp(procform->proargtypes, resultList->args,
|
||||
if (nargs == resultList->nargs &&
|
||||
memcmp(procform->proargtypes, resultList->args,
|
||||
nargs * sizeof(Oid)) == 0)
|
||||
prevResult = resultList;
|
||||
else
|
||||
@@ -490,7 +501,8 @@ FuncnameGetCandidates(List *names, int nargs)
|
||||
prevResult;
|
||||
prevResult = prevResult->next)
|
||||
{
|
||||
if (memcmp(procform->proargtypes, prevResult->args,
|
||||
if (nargs == prevResult->nargs &&
|
||||
memcmp(procform->proargtypes, prevResult->args,
|
||||
nargs * sizeof(Oid)) == 0)
|
||||
break;
|
||||
}
|
||||
@@ -517,6 +529,7 @@ FuncnameGetCandidates(List *names, int nargs)
|
||||
+ nargs * sizeof(Oid));
|
||||
newResult->pathpos = pathpos;
|
||||
newResult->oid = proctup->t_data->t_oid;
|
||||
newResult->nargs = nargs;
|
||||
memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
|
||||
|
||||
newResult->next = resultList;
|
||||
@@ -533,14 +546,17 @@ FuncnameGetCandidates(List *names, int nargs)
|
||||
* Given a possibly-qualified operator name and operator kind,
|
||||
* retrieve a list of the possible matches.
|
||||
*
|
||||
* If oprkind is '\0', we return all operators matching the given name,
|
||||
* regardless of arguments.
|
||||
*
|
||||
* We search a single namespace if the operator name is qualified, else
|
||||
* all namespaces in the search path. The return list will never contain
|
||||
* multiple entries with identical argument types --- in the multiple-
|
||||
* multiple entries with identical argument lists --- in the multiple-
|
||||
* namespace case, we arrange for entries in earlier namespaces to mask
|
||||
* identical entries in later namespaces.
|
||||
*
|
||||
* The returned items always have two args[] entries --- one or the other
|
||||
* will be InvalidOid for a prefix or postfix oprkind.
|
||||
* will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
|
||||
*/
|
||||
FuncCandidateList
|
||||
OpernameGetCandidates(List *names, char oprkind)
|
||||
@@ -606,8 +622,8 @@ OpernameGetCandidates(List *names, char oprkind)
|
||||
int pathpos = 0;
|
||||
FuncCandidateList newResult;
|
||||
|
||||
/* Ignore operators of wrong kind */
|
||||
if (operform->oprkind != oprkind)
|
||||
/* Ignore operators of wrong kind, if specific kind requested */
|
||||
if (oprkind && operform->oprkind != oprkind)
|
||||
continue;
|
||||
|
||||
if (OidIsValid(namespaceId))
|
||||
@@ -690,6 +706,7 @@ OpernameGetCandidates(List *names, char oprkind)
|
||||
palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid));
|
||||
newResult->pathpos = pathpos;
|
||||
newResult->oid = opertup->t_data->t_oid;
|
||||
newResult->nargs = 2;
|
||||
newResult->args[0] = operform->oprleft;
|
||||
newResult->args[1] = operform->oprright;
|
||||
newResult->next = resultList;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.66 2002/04/16 23:08:10 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.67 2002/04/25 02:56:55 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* these routines moved here from commands/define.c and somewhat cleaned up.
|
||||
@@ -138,7 +138,7 @@ OperatorGet(const char *operatorName,
|
||||
ObjectIdGetDatum(operatorNamespace));
|
||||
if (HeapTupleIsValid(tup))
|
||||
{
|
||||
regproc oprcode = ((Form_pg_operator) GETSTRUCT(tup))->oprcode;
|
||||
RegProcedure oprcode = ((Form_pg_operator) GETSTRUCT(tup))->oprcode;
|
||||
|
||||
operatorObjectId = tup->t_data->t_oid;
|
||||
*defined = RegProcedureIsValid(oprcode);
|
||||
@@ -168,7 +168,7 @@ OperatorLookup(List *operatorName,
|
||||
bool *defined)
|
||||
{
|
||||
Oid operatorObjectId;
|
||||
regproc oprcode;
|
||||
RegProcedure oprcode;
|
||||
|
||||
operatorObjectId = LookupOperName(operatorName, leftObjectId,
|
||||
rightObjectId);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.70 2002/04/11 20:00:00 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.71 2002/04/25 02:56:55 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -81,8 +81,7 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
||||
|
||||
if (!con->constisnull)
|
||||
{
|
||||
/* We know the source constant is really of type 'text' */
|
||||
char *val = DatumGetCString(DirectFunctionCall1(textout,
|
||||
char *val = DatumGetCString(DirectFunctionCall1(unknownout,
|
||||
con->constvalue));
|
||||
|
||||
newcon->constvalue = stringTypeDatum(targetType, val, atttypmod);
|
||||
@@ -477,6 +476,11 @@ TypeCategory(Oid inType)
|
||||
|
||||
case (OIDOID):
|
||||
case (REGPROCOID):
|
||||
case (REGPROCEDUREOID):
|
||||
case (REGOPEROID):
|
||||
case (REGOPERATOROID):
|
||||
case (REGCLASSOID):
|
||||
case (REGTYPEOID):
|
||||
case (INT2OID):
|
||||
case (INT4OID):
|
||||
case (INT8OID):
|
||||
@@ -540,38 +544,72 @@ TypeCategory(Oid inType)
|
||||
* to allow for better type extensibility.
|
||||
*/
|
||||
|
||||
#define TypeIsTextGroup(t) \
|
||||
((t) == TEXTOID || \
|
||||
(t) == BPCHAROID || \
|
||||
(t) == VARCHAROID)
|
||||
|
||||
/* Notice OidGroup is a subset of Int4GroupA */
|
||||
#define TypeIsOidGroup(t) \
|
||||
((t) == OIDOID || \
|
||||
(t) == REGPROCOID || \
|
||||
(t) == REGPROCEDUREOID || \
|
||||
(t) == REGOPEROID || \
|
||||
(t) == REGOPERATOROID || \
|
||||
(t) == REGCLASSOID || \
|
||||
(t) == REGTYPEOID)
|
||||
|
||||
/*
|
||||
* This macro describes hard-coded knowledge of binary compatibility
|
||||
* for built-in types.
|
||||
* INT4 is binary-compatible with many types, but we don't want to allow
|
||||
* implicit coercion directly between, say, OID and AbsTime. So we subdivide
|
||||
* the categories.
|
||||
*/
|
||||
#define IS_BINARY_COMPATIBLE(a,b) \
|
||||
(((a) == BPCHAROID && (b) == TEXTOID) \
|
||||
|| ((a) == BPCHAROID && (b) == VARCHAROID) \
|
||||
|| ((a) == VARCHAROID && (b) == TEXTOID) \
|
||||
|| ((a) == VARCHAROID && (b) == BPCHAROID) \
|
||||
|| ((a) == TEXTOID && (b) == BPCHAROID) \
|
||||
|| ((a) == TEXTOID && (b) == VARCHAROID) \
|
||||
|| ((a) == OIDOID && (b) == INT4OID) \
|
||||
|| ((a) == OIDOID && (b) == REGPROCOID) \
|
||||
|| ((a) == INT4OID && (b) == OIDOID) \
|
||||
|| ((a) == INT4OID && (b) == REGPROCOID) \
|
||||
|| ((a) == REGPROCOID && (b) == OIDOID) \
|
||||
|| ((a) == REGPROCOID && (b) == INT4OID) \
|
||||
|| ((a) == ABSTIMEOID && (b) == INT4OID) \
|
||||
|| ((a) == INT4OID && (b) == ABSTIMEOID) \
|
||||
|| ((a) == RELTIMEOID && (b) == INT4OID) \
|
||||
|| ((a) == INT4OID && (b) == RELTIMEOID) \
|
||||
|| ((a) == INETOID && (b) == CIDROID) \
|
||||
|| ((a) == CIDROID && (b) == INETOID) \
|
||||
|| ((a) == BITOID && (b) == VARBITOID) \
|
||||
|| ((a) == VARBITOID && (b) == BITOID))
|
||||
#define TypeIsInt4GroupA(t) \
|
||||
((t) == INT4OID || \
|
||||
TypeIsOidGroup(t))
|
||||
|
||||
#define TypeIsInt4GroupB(t) \
|
||||
((t) == INT4OID || \
|
||||
(t) == ABSTIMEOID)
|
||||
|
||||
#define TypeIsInt4GroupC(t) \
|
||||
((t) == INT4OID || \
|
||||
(t) == RELTIMEOID)
|
||||
|
||||
#define TypeIsInetGroup(t) \
|
||||
((t) == INETOID || \
|
||||
(t) == CIDROID)
|
||||
|
||||
#define TypeIsBitGroup(t) \
|
||||
((t) == BITOID || \
|
||||
(t) == VARBITOID)
|
||||
|
||||
|
||||
static bool
|
||||
DirectlyBinaryCompatible(Oid type1, Oid type2)
|
||||
{
|
||||
if (type1 == type2)
|
||||
return true;
|
||||
if (TypeIsTextGroup(type1) && TypeIsTextGroup(type2))
|
||||
return true;
|
||||
if (TypeIsInt4GroupA(type1) && TypeIsInt4GroupA(type2))
|
||||
return true;
|
||||
if (TypeIsInt4GroupB(type1) && TypeIsInt4GroupB(type2))
|
||||
return true;
|
||||
if (TypeIsInt4GroupC(type1) && TypeIsInt4GroupC(type2))
|
||||
return true;
|
||||
if (TypeIsInetGroup(type1) && TypeIsInetGroup(type2))
|
||||
return true;
|
||||
if (TypeIsBitGroup(type1) && TypeIsBitGroup(type2))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
IsBinaryCompatible(Oid type1, Oid type2)
|
||||
{
|
||||
if (type1 == type2)
|
||||
return true;
|
||||
if (IS_BINARY_COMPATIBLE(type1, type2))
|
||||
if (DirectlyBinaryCompatible(type1, type2))
|
||||
return true;
|
||||
/*
|
||||
* Perhaps the types are domains; if so, look at their base types
|
||||
@@ -580,9 +618,7 @@ IsBinaryCompatible(Oid type1, Oid type2)
|
||||
type1 = getBaseType(type1);
|
||||
if (OidIsValid(type2))
|
||||
type2 = getBaseType(type2);
|
||||
if (type1 == type2)
|
||||
return true;
|
||||
if (IS_BINARY_COMPATIBLE(type1, type2))
|
||||
if (DirectlyBinaryCompatible(type1, type2))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -627,7 +663,7 @@ PreferredType(CATEGORY category, Oid type)
|
||||
break;
|
||||
|
||||
case (NUMERIC_TYPE):
|
||||
if (type == OIDOID)
|
||||
if (TypeIsOidGroup(type))
|
||||
result = OIDOID;
|
||||
else if (type == NUMERICOID)
|
||||
result = NUMERICOID;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.62 2002/04/16 23:08:11 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.63 2002/04/25 02:56:55 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -424,7 +424,8 @@ make_const(Value *value)
|
||||
break;
|
||||
|
||||
case T_String:
|
||||
val = DirectFunctionCall1(textin, CStringGetDatum(strVal(value)));
|
||||
val = DirectFunctionCall1(unknownin,
|
||||
CStringGetDatum(strVal(value)));
|
||||
|
||||
typeid = UNKNOWNOID; /* will be coerced later */
|
||||
typelen = -1; /* variable len */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
* back to source text
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.98 2002/04/19 23:13:54 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.99 2002/04/25 02:56:55 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@@ -123,7 +123,7 @@ static void get_delete_query_def(Query *query, deparse_context *context);
|
||||
static void get_utility_query_def(Query *query, deparse_context *context);
|
||||
static void get_basic_select_query(Query *query, deparse_context *context);
|
||||
static void get_setop_query(Node *setOp, Query *query,
|
||||
deparse_context *context, bool toplevel);
|
||||
deparse_context *context);
|
||||
static void get_rule_sortgroupclause(SortClause *srt, List *tlist,
|
||||
bool force_colno,
|
||||
deparse_context *context);
|
||||
@@ -142,7 +142,6 @@ static void get_from_clause_item(Node *jtnode, Query *query,
|
||||
static void get_opclass_name(Oid opclass, Oid actual_datatype,
|
||||
StringInfo buf);
|
||||
static bool tleIsArrayAssign(TargetEntry *tle);
|
||||
static char *quote_identifier(char *ident);
|
||||
static char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
|
||||
|
||||
#define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
|
||||
@@ -1109,7 +1108,7 @@ get_select_query_def(Query *query, deparse_context *context)
|
||||
*/
|
||||
if (query->setOperations)
|
||||
{
|
||||
get_setop_query(query->setOperations, query, context, true);
|
||||
get_setop_query(query->setOperations, query, context);
|
||||
/* ORDER BY clauses must be simple in this case */
|
||||
force_colno = true;
|
||||
}
|
||||
@@ -1266,8 +1265,7 @@ get_basic_select_query(Query *query, deparse_context *context)
|
||||
}
|
||||
|
||||
static void
|
||||
get_setop_query(Node *setOp, Query *query, deparse_context *context,
|
||||
bool toplevel)
|
||||
get_setop_query(Node *setOp, Query *query, deparse_context *context)
|
||||
{
|
||||
StringInfo buf = context->buf;
|
||||
|
||||
@@ -1284,33 +1282,29 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context,
|
||||
{
|
||||
SetOperationStmt *op = (SetOperationStmt *) setOp;
|
||||
|
||||
/*
|
||||
* Must suppress parens at top level of a setop tree because of
|
||||
* grammar limitations...
|
||||
*/
|
||||
if (!toplevel)
|
||||
appendStringInfo(buf, "(");
|
||||
get_setop_query(op->larg, query, context, false);
|
||||
appendStringInfo(buf, "((");
|
||||
get_setop_query(op->larg, query, context);
|
||||
switch (op->op)
|
||||
{
|
||||
case SETOP_UNION:
|
||||
appendStringInfo(buf, " UNION ");
|
||||
appendStringInfo(buf, ") UNION ");
|
||||
break;
|
||||
case SETOP_INTERSECT:
|
||||
appendStringInfo(buf, " INTERSECT ");
|
||||
appendStringInfo(buf, ") INTERSECT ");
|
||||
break;
|
||||
case SETOP_EXCEPT:
|
||||
appendStringInfo(buf, " EXCEPT ");
|
||||
appendStringInfo(buf, ") EXCEPT ");
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "get_setop_query: unexpected set op %d",
|
||||
(int) op->op);
|
||||
}
|
||||
if (op->all)
|
||||
appendStringInfo(buf, "ALL ");
|
||||
get_setop_query(op->rarg, query, context, false);
|
||||
if (!toplevel)
|
||||
appendStringInfo(buf, ")");
|
||||
appendStringInfo(buf, "ALL (");
|
||||
else
|
||||
appendStringInfo(buf, "(");
|
||||
get_setop_query(op->rarg, query, context);
|
||||
appendStringInfo(buf, "))");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2585,8 +2579,8 @@ tleIsArrayAssign(TargetEntry *tle)
|
||||
* space-wasteful but well worth it for notational simplicity.
|
||||
* ----------
|
||||
*/
|
||||
static char *
|
||||
quote_identifier(char *ident)
|
||||
const char *
|
||||
quote_identifier(const char *ident)
|
||||
{
|
||||
/*
|
||||
* Can avoid quoting if ident starts with a lowercase letter and
|
||||
@@ -2603,7 +2597,7 @@ quote_identifier(char *ident)
|
||||
safe = (ident[0] >= 'a' && ident[0] <= 'z');
|
||||
if (safe)
|
||||
{
|
||||
char *ptr;
|
||||
const char *ptr;
|
||||
|
||||
for (ptr = ident + 1; *ptr; ptr++)
|
||||
{
|
||||
@@ -2628,7 +2622,7 @@ quote_identifier(char *ident)
|
||||
* Note: ScanKeywordLookup() does case-insensitive comparison, but
|
||||
* that's fine, since we already know we have all-lower-case.
|
||||
*/
|
||||
if (ScanKeywordLookup(ident) != NULL)
|
||||
if (ScanKeywordLookup((char *) ident) != NULL)
|
||||
safe = false;
|
||||
}
|
||||
|
||||
@@ -2640,6 +2634,26 @@ quote_identifier(char *ident)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ----------
|
||||
* quote_qualified_identifier - Quote a possibly-qualified identifier
|
||||
*
|
||||
* Return a name of the form namespace.ident, or just ident if namespace
|
||||
* is NULL, quoting each component if necessary. The result is palloc'd.
|
||||
* ----------
|
||||
*/
|
||||
char *
|
||||
quote_qualified_identifier(const char *namespace,
|
||||
const char *ident)
|
||||
{
|
||||
StringInfoData buf;
|
||||
|
||||
initStringInfo(&buf);
|
||||
if (namespace)
|
||||
appendStringInfo(&buf, "%s.", quote_identifier(namespace));
|
||||
appendStringInfo(&buf, "%s", quote_identifier(ident));
|
||||
return buf.data;
|
||||
}
|
||||
|
||||
/* ----------
|
||||
* get_relid_attribute_name
|
||||
* Get an attribute name by its relations Oid and its attnum
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.109 2002/04/21 19:48:13 thomas Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.110 2002/04/25 02:56:55 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1991,6 +1991,11 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
|
||||
case NUMERICOID:
|
||||
case OIDOID:
|
||||
case REGPROCOID:
|
||||
case REGPROCEDUREOID:
|
||||
case REGOPEROID:
|
||||
case REGOPERATOROID:
|
||||
case REGCLASSOID:
|
||||
case REGTYPEOID:
|
||||
*scaledvalue = convert_numeric_to_scalar(value, valuetypid);
|
||||
*scaledlobound = convert_numeric_to_scalar(lobound, boundstypid);
|
||||
*scaledhibound = convert_numeric_to_scalar(hibound, boundstypid);
|
||||
@@ -2088,6 +2093,11 @@ convert_numeric_to_scalar(Datum value, Oid typid)
|
||||
value));
|
||||
case OIDOID:
|
||||
case REGPROCOID:
|
||||
case REGPROCEDUREOID:
|
||||
case REGOPEROID:
|
||||
case REGOPERATOROID:
|
||||
case REGCLASSOID:
|
||||
case REGTYPEOID:
|
||||
/* we can treat OIDs as integers... */
|
||||
return (double) DatumGetObjectId(value);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.84 2002/04/24 02:12:53 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.85 2002/04/25 02:56:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -21,6 +21,13 @@
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/pg_locale.h"
|
||||
|
||||
|
||||
typedef struct varlena unknown;
|
||||
|
||||
#define DatumGetUnknownP(X) ((unknown *) PG_DETOAST_DATUM(X))
|
||||
#define PG_GETARG_UNKNOWN_P(n) DatumGetUnknownP(PG_GETARG_DATUM(n))
|
||||
#define PG_RETURN_UNKNOWN_P(x) PG_RETURN_POINTER(x)
|
||||
|
||||
static int text_cmp(text *arg1, text *arg2);
|
||||
|
||||
|
||||
|
||||
9
src/backend/utils/cache/catcache.c
vendored
9
src/backend/utils/cache/catcache.c
vendored
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.94 2002/04/06 06:59:22 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.95 2002/04/25 02:56:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -136,8 +136,13 @@ GetCCHashFunc(Oid keytype)
|
||||
return hashint4;
|
||||
case TEXTOID:
|
||||
return hashvarlena;
|
||||
case REGPROCOID:
|
||||
case OIDOID:
|
||||
case REGPROCOID:
|
||||
case REGPROCEDUREOID:
|
||||
case REGOPEROID:
|
||||
case REGOPERATOROID:
|
||||
case REGCLASSOID:
|
||||
case REGTYPEOID:
|
||||
return hashoid;
|
||||
case OIDVECTOROID:
|
||||
return hashoidvector;
|
||||
|
||||
Reference in New Issue
Block a user