aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/common/tupdesc.c12
-rw-r--r--src/backend/executor/nodeFunctionscan.c15
-rw-r--r--src/backend/parser/parse_relation.c72
-rw-r--r--src/backend/utils/cache/lsyscache.c38
-rw-r--r--src/include/utils/lsyscache.h12
5 files changed, 94 insertions, 55 deletions
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index ed932d35ab6..b85b7eb5e65 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.106 2004/08/29 05:06:39 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.107 2004/10/20 16:04:47 tgl Exp $
*
* NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be
@@ -607,13 +607,13 @@ RelationNameGetTupleDesc(const char *relname)
TupleDesc
TypeGetTupleDesc(Oid typeoid, List *colaliases)
{
- char functyptype = get_typtype(typeoid);
+ TypeFuncClass functypclass = get_type_func_class(typeoid);
TupleDesc tupdesc = NULL;
/*
* Build a suitable tupledesc representing the output rows
*/
- if (functyptype == 'c')
+ if (functypclass == TYPEFUNC_COMPOSITE)
{
/* Composite data type, e.g. a table's row type */
tupdesc = CreateTupleDescCopy(lookup_rowtype_tupdesc(typeoid, -1));
@@ -643,9 +643,9 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases)
tupdesc->tdtypmod = -1;
}
}
- else if (functyptype == 'b' || functyptype == 'd')
+ else if (functypclass == TYPEFUNC_SCALAR)
{
- /* Must be a base data type, i.e. scalar */
+ /* Base data type, i.e. scalar */
char *attname;
/* the alias list is required for base types */
@@ -671,7 +671,7 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases)
-1,
0);
}
- else if (typeoid == RECORDOID)
+ else if (functypclass == TYPEFUNC_RECORD)
{
/* XXX can't support this because typmod wasn't passed in ... */
ereport(ERROR,
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 032235b8f3e..8407eafb9b8 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.27 2004/09/22 17:41:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.28 2004/10/20 16:04:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -132,7 +132,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate)
FunctionScanState *scanstate;
RangeTblEntry *rte;
Oid funcrettype;
- char functyptype;
+ TypeFuncClass functypclass;
TupleDesc tupdesc = NULL;
/*
@@ -184,16 +184,16 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate)
* Now determine if the function returns a simple or composite type,
* and build an appropriate tupdesc.
*/
- functyptype = get_typtype(funcrettype);
+ functypclass = get_type_func_class(funcrettype);
- if (functyptype == 'c')
+ if (functypclass == TYPEFUNC_COMPOSITE)
{
/* Composite data type, e.g. a table's row type */
tupdesc = CreateTupleDescCopy(lookup_rowtype_tupdesc(funcrettype, -1));
}
- else if (functyptype == 'b' || functyptype == 'd')
+ else if (functypclass == TYPEFUNC_SCALAR)
{
- /* Must be a base data type, i.e. scalar */
+ /* Base data type, i.e. scalar */
char *attname = strVal(linitial(rte->eref->colnames));
tupdesc = CreateTemplateTupleDesc(1, false);
@@ -204,9 +204,8 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate)
-1,
0);
}
- else if (funcrettype == RECORDOID)
+ else if (functypclass == TYPEFUNC_RECORD)
{
- /* Must be a pseudo type, i.e. record */
tupdesc = BuildDescForRelation(rte->coldeflist);
}
else
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 442170a2eee..84781f4d4aa 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.100 2004/08/29 05:06:44 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.101 2004/10/20 16:04:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -966,7 +966,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
{
RangeTblEntry *rte = makeNode(RangeTblEntry);
Oid funcrettype = exprType(funcexpr);
- char functyptype;
+ TypeFuncClass functypclass;
Alias *alias = rangefunc->alias;
List *coldeflist = rangefunc->coldeflist;
Alias *eref;
@@ -1008,18 +1008,15 @@ addRangeTableEntryForFunction(ParseState *pstate,
errmsg("a column definition list is required for functions returning \"record\"")));
}
- functyptype = get_typtype(funcrettype);
+ functypclass = get_type_func_class(funcrettype);
- if (functyptype == 'c')
+ if (functypclass == TYPEFUNC_COMPOSITE)
{
- /*
- * Named composite data type, i.e. a table's row type
- */
+ /* Composite data type, e.g. a table's row type */
Oid funcrelid = typeidTypeRelid(funcrettype);
Relation rel;
- if (!OidIsValid(funcrelid)) /* shouldn't happen if typtype is
- * 'c' */
+ if (!OidIsValid(funcrelid)) /* shouldn't happen */
elog(ERROR, "invalid typrelid for complex type %u", funcrettype);
/*
@@ -1038,12 +1035,10 @@ addRangeTableEntryForFunction(ParseState *pstate,
*/
relation_close(rel, NoLock);
}
- else if (functyptype == 'b' || functyptype == 'd')
+ else if (functypclass == TYPEFUNC_SCALAR)
{
- /*
- * Must be a base data type, i.e. scalar. Just add one alias
- * column named for the function.
- */
+ /* Base data type, i.e. scalar */
+ /* Just add one alias column named for the function. */
if (alias && alias->colnames != NIL)
{
if (list_length(alias->colnames) != 1)
@@ -1056,7 +1051,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
else
eref->colnames = list_make1(makeString(eref->aliasname));
}
- else if (functyptype == 'p' && funcrettype == RECORDOID)
+ else if (functypclass == TYPEFUNC_RECORD)
{
ListCell *col;
@@ -1073,8 +1068,8 @@ addRangeTableEntryForFunction(ParseState *pstate,
else
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("function \"%s\" in FROM has unsupported return type",
- funcname)));
+ errmsg("function \"%s\" in FROM has unsupported return type %s",
+ funcname, format_type_be(funcrettype))));
/*----------
* Flags:
@@ -1314,9 +1309,9 @@ expandRTE(List *rtable, int rtindex, int sublevels_up,
{
/* Function RTE */
Oid funcrettype = exprType(rte->funcexpr);
- char functyptype = get_typtype(funcrettype);
+ TypeFuncClass functypclass = get_type_func_class(funcrettype);
- if (functyptype == 'c')
+ if (functypclass == TYPEFUNC_COMPOSITE)
{
/*
* Composite data type, i.e. a table's row type
@@ -1332,11 +1327,9 @@ expandRTE(List *rtable, int rtindex, int sublevels_up,
expandRelation(funcrelid, rte->eref, rtindex, sublevels_up,
include_dropped, colnames, colvars);
}
- else if (functyptype == 'b' || functyptype == 'd')
+ else if (functypclass == TYPEFUNC_SCALAR)
{
- /*
- * Must be a base data type, i.e. scalar
- */
+ /* Base data type, i.e. scalar */
if (colnames)
*colnames = lappend(*colnames,
linitial(rte->eref->colnames));
@@ -1352,7 +1345,7 @@ expandRTE(List *rtable, int rtindex, int sublevels_up,
*colvars = lappend(*colvars, varnode);
}
}
- else if (functyptype == 'p' && funcrettype == RECORDOID)
+ else if (functypclass == TYPEFUNC_RECORD)
{
List *coldeflist = rte->coldeflist;
ListCell *col;
@@ -1389,9 +1382,10 @@ expandRTE(List *rtable, int rtindex, int sublevels_up,
}
}
else
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("function in FROM has unsupported return type")));
+ {
+ /* addRangeTableEntryForFunction should've caught this */
+ elog(ERROR, "function in FROM has unsupported return type");
+ }
}
break;
case RTE_JOIN:
@@ -1669,14 +1663,15 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
{
/* Function RTE */
Oid funcrettype = exprType(rte->funcexpr);
- char functyptype = get_typtype(funcrettype);
+ TypeFuncClass functypclass = get_type_func_class(funcrettype);
List *coldeflist = rte->coldeflist;
- if (functyptype == 'c')
+ if (functypclass == TYPEFUNC_COMPOSITE)
{
/*
- * Composite data type, i.e. a table's row type Same
- * as ordinary relation RTE
+ * Composite data type, i.e. a table's row type
+ *
+ * Same as ordinary relation RTE
*/
Oid funcrelid = typeidTypeRelid(funcrettype);
HeapTuple tp;
@@ -1709,15 +1704,13 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
*vartypmod = att_tup->atttypmod;
ReleaseSysCache(tp);
}
- else if (functyptype == 'b' || functyptype == 'd')
+ else if (functypclass == TYPEFUNC_SCALAR)
{
- /*
- * Must be a base data type, i.e. scalar
- */
+ /* Base data type, i.e. scalar */
*vartype = funcrettype;
*vartypmod = -1;
}
- else if (functyptype == 'p' && funcrettype == RECORDOID)
+ else if (functypclass == TYPEFUNC_RECORD)
{
ColumnDef *colDef = list_nth(coldeflist, attnum - 1);
@@ -1725,9 +1718,10 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
*vartypmod = -1;
}
else
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("function in FROM has unsupported return type")));
+ {
+ /* addRangeTableEntryForFunction should've caught this */
+ elog(ERROR, "function in FROM has unsupported return type");
+ }
}
break;
case RTE_JOIN:
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 9dc2bbd524b..2e3848947c8 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.116 2004/08/29 05:06:50 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.117 2004/10/20 16:04:49 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -1548,6 +1548,42 @@ get_typtype(Oid typid)
}
/*
+ * get_type_func_class
+ *
+ * Given the type OID, obtain its TYPEFUNC classification.
+ *
+ * This is intended to centralize a bunch of formerly ad-hoc code for
+ * classifying types. The categories used here are useful for deciding
+ * how to handle functions returning the datatype.
+ */
+TypeFuncClass
+get_type_func_class(Oid typid)
+{
+ switch (get_typtype(typid))
+ {
+ case 'c':
+ return TYPEFUNC_COMPOSITE;
+ case 'b':
+ case 'd':
+ return TYPEFUNC_SCALAR;
+ case 'p':
+ if (typid == RECORDOID)
+ return TYPEFUNC_RECORD;
+ /*
+ * We treat VOID and CSTRING as legitimate scalar datatypes,
+ * mostly for the convenience of the JDBC driver (which wants
+ * to be able to do "SELECT * FROM foo()" for all legitimately
+ * user-callable functions).
+ */
+ if (typid == VOIDOID || typid == CSTRINGOID)
+ return TYPEFUNC_SCALAR;
+ return TYPEFUNC_OTHER;
+ }
+ /* shouldn't get here, probably */
+ return TYPEFUNC_OTHER;
+}
+
+/*
* get_typ_typrelid
*
* Given the type OID, get the typrelid (InvalidOid if not a complex
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 496d2bcf11f..3a016b7a52d 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.90 2004/08/29 05:06:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.91 2004/10/20 16:04:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,6 +24,15 @@ typedef enum IOFuncSelector
IOFunc_send
} IOFuncSelector;
+/* Type categories for get_type_func_class */
+typedef enum TypeFuncClass
+{
+ TYPEFUNC_SCALAR,
+ TYPEFUNC_COMPOSITE,
+ TYPEFUNC_RECORD,
+ TYPEFUNC_OTHER
+} TypeFuncClass;
+
extern bool op_in_opclass(Oid opno, Oid opclass);
extern void get_op_opclass_properties(Oid opno, Oid opclass,
int *strategy, Oid *subtype,
@@ -85,6 +94,7 @@ extern char get_typstorage(Oid typid);
extern int32 get_typtypmod(Oid typid);
extern Node *get_typdefault(Oid typid);
extern char get_typtype(Oid typid);
+extern TypeFuncClass get_type_func_class(Oid typid);
extern Oid get_typ_typrelid(Oid typid);
extern Oid get_element_type(Oid typid);
extern Oid get_array_type(Oid typid);