aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/analyze.c40
-rw-r--r--src/backend/parser/gram.y140
-rw-r--r--src/backend/parser/parse_agg.c15
-rw-r--r--src/backend/parser/parse_coerce.c27
-rw-r--r--src/backend/parser/parse_expr.c17
-rw-r--r--src/backend/parser/parse_func.c146
-rw-r--r--src/backend/parser/parse_target.c47
7 files changed, 238 insertions, 194 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 0de9c5bb851..8b3f218b83a 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.227 2002/04/05 11:56:51 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.228 2002/04/09 20:35:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,6 +22,7 @@
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "parser/analyze.h"
+#include "parser/gramparse.h"
#include "parser/parsetree.h"
#include "parser/parse_agg.h"
#include "parser/parse_clause.h"
@@ -859,7 +860,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
snamenode->val.type = T_String;
snamenode->val.val.str = qstring;
funccallnode = makeNode(FuncCall);
- funccallnode->funcname = "nextval";
+ funccallnode->funcname = SystemFuncName("nextval");
funccallnode->args = makeList1(snamenode);
funccallnode->agg_star = false;
funccallnode->agg_distinct = false;
@@ -1197,7 +1198,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
foreach(columns, index->indexParams)
{
iparam = (IndexElem *) lfirst(columns);
- if (strcmp(key->name, iparam->name) == 0)
+ if (iparam->name && strcmp(key->name, iparam->name) == 0)
elog(ERROR, "%s: column \"%s\" appears twice in %s constraint",
cxt->stmtType, key->name,
index->primary ? "PRIMARY KEY" : "UNIQUE");
@@ -1206,6 +1207,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
/* OK, add it to the index definition */
iparam = makeNode(IndexElem);
iparam->name = pstrdup(key->name);
+ iparam->funcname = NIL;
iparam->args = NIL;
iparam->class = NULL;
index->indexParams = lappend(index->indexParams, iparam);
@@ -1281,7 +1283,9 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
if (index->idxname == NULL && index->indexParams != NIL)
{
iparam = lfirst(index->indexParams);
- index->idxname = CreateIndexName((cxt->relation)->relname, iparam->name,
+ index->idxname = CreateIndexName(cxt->relation->relname,
+ iparam->name ? iparam->name :
+ strVal(llast(iparam->funcname)),
"key", cxt->alist);
}
if (index->idxname == NULL) /* should not happen */
@@ -1292,7 +1296,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
cxt->stmtType,
(strcmp(cxt->stmtType, "ALTER TABLE") == 0) ? "ADD " : "",
(index->primary ? "PRIMARY KEY" : "UNIQUE"),
- index->idxname, (cxt->relation)->relname);
+ index->idxname, cxt->relation->relname);
}
}
@@ -1365,6 +1369,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
IndexElem *ielem = lfirst(attr);
Ident *pkattr = (Ident *) makeNode(Ident);
+ Assert(ielem->name); /* no func index here */
pkattr->name = pstrdup(ielem->name);
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs,
pkattr);
@@ -1417,7 +1422,8 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
{
IndexElem *indparm = lfirst(indparms);
- if (strcmp(indparm->name, pkattr->name) == 0)
+ if (indparm->name &&
+ strcmp(indparm->name, pkattr->name) == 0)
{
found = true;
break;
@@ -1470,7 +1476,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
fk_trigger->trigname = fkconstraint->constr_name;
fk_trigger->relation = cxt->relation;
- fk_trigger->funcname = "RI_FKey_check_ins";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins");
fk_trigger->before = false;
fk_trigger->row = true;
fk_trigger->actions[0] = 'i';
@@ -1542,21 +1548,21 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
>> FKCONSTR_ON_DELETE_SHIFT)
{
case FKCONSTR_ON_KEY_NOACTION:
- fk_trigger->funcname = "RI_FKey_noaction_del";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_del");
break;
case FKCONSTR_ON_KEY_RESTRICT:
fk_trigger->deferrable = false;
fk_trigger->initdeferred = false;
- fk_trigger->funcname = "RI_FKey_restrict_del";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_del");
break;
case FKCONSTR_ON_KEY_CASCADE:
- fk_trigger->funcname = "RI_FKey_cascade_del";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_del");
break;
case FKCONSTR_ON_KEY_SETNULL:
- fk_trigger->funcname = "RI_FKey_setnull_del";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_del");
break;
case FKCONSTR_ON_KEY_SETDEFAULT:
- fk_trigger->funcname = "RI_FKey_setdefault_del";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_del");
break;
default:
elog(ERROR, "Only one ON DELETE action can be specified for FOREIGN KEY constraint");
@@ -1614,21 +1620,21 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
>> FKCONSTR_ON_UPDATE_SHIFT)
{
case FKCONSTR_ON_KEY_NOACTION:
- fk_trigger->funcname = "RI_FKey_noaction_upd";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_upd");
break;
case FKCONSTR_ON_KEY_RESTRICT:
fk_trigger->deferrable = false;
fk_trigger->initdeferred = false;
- fk_trigger->funcname = "RI_FKey_restrict_upd";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_upd");
break;
case FKCONSTR_ON_KEY_CASCADE:
- fk_trigger->funcname = "RI_FKey_cascade_upd";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_upd");
break;
case FKCONSTR_ON_KEY_SETNULL:
- fk_trigger->funcname = "RI_FKey_setnull_upd";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_upd");
break;
case FKCONSTR_ON_KEY_SETDEFAULT:
- fk_trigger->funcname = "RI_FKey_setdefault_upd";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_upd");
break;
default:
elog(ERROR, "Only one ON UPDATE action can be specified for FOREIGN KEY constraint");
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 6ba8766e1ac..3488fb0762f 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.300 2002/04/05 11:56:53 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.301 2002/04/09 20:35:51 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -175,8 +175,9 @@ static bool set_name_needs_quotes(const char *name);
%type <str> relation_name, copy_file_name, copy_delimiter, copy_null,
database_name, access_method_clause, access_method, attr_name,
- class, index_name, name, function_name, file_name,
- func_name, handler_name
+ class, index_name, name, function_name, file_name
+
+%type <list> func_name, handler_name
%type <range> qualified_name, OptConstrFromTable
@@ -1859,9 +1860,9 @@ opt_trusted: TRUSTED { $$ = TRUE; }
* Work around by using name and dotted_name separately.
*/
handler_name: name
- { $$ = $1; }
+ { $$ = makeList1(makeString($1)); }
| dotted_name
- { $$ = strVal(lfirst($1)); /* XXX changing soon */ }
+ { $$ = $1; }
;
opt_lancompiler: LANCOMPILER Sconst { $$ = $2; }
@@ -2081,7 +2082,7 @@ DefineStmt: CREATE AGGREGATE func_name definition
{
DefineStmt *n = makeNode(DefineStmt);
n->defType = AGGREGATE;
- n->defnames = makeList1(makeString($3)); /* XXX */
+ n->defnames = $3;
n->definition = $4;
$$ = (Node *)n;
}
@@ -2199,54 +2200,21 @@ TruncateStmt: TRUNCATE opt_table qualified_name
*
*****************************************************************************/
-CommentStmt: COMMENT ON comment_type name IS comment_text
+CommentStmt: COMMENT ON comment_type any_name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = $3;
n->objname = $4;
- n->objproperty = NULL;
- n->objlist = NULL;
+ n->objargs = NIL;
n->comment = $6;
$$ = (Node *) n;
}
- | COMMENT ON COLUMN ColId '.' attr_name IS comment_text
- {
- /*
- * We can't use qualified_name here as the '.' causes a shift/red;
- * with ColId we do not test for NEW and OLD as table names, but it is OK
- * as they would fail anyway as COMMENT cannot appear in a RULE.
- * ColumnRef is also innapropriate as we don't take subscripts
- * or '*' and have a very precise number of elements (2 or 3)
- * so we do it from scratch.
- */
- CommentStmt *n = makeNode(CommentStmt);
- n->objtype = COLUMN;
- n->objschema = NULL;
- n->objname = $4;
- n->objproperty = $6;
- n->objlist = NULL;
- n->comment = $8;
- $$ = (Node *) n;
- }
- | COMMENT ON COLUMN ColId '.' ColId '.' attr_name IS comment_text
- {
- CommentStmt *n = makeNode(CommentStmt);
- n->objtype = COLUMN;
- n->objschema = $4;
- n->objname = $6;
- n->objproperty = $8;
- n->objlist = NULL;
- n->comment = $10;
- $$ = (Node *) n;
- }
| COMMENT ON AGGREGATE func_name '(' aggr_argtype ')' IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = AGGREGATE;
- n->objschema = NULL;
n->objname = $4;
- n->objproperty = NULL;
- n->objlist = makeList1($6);
+ n->objargs = makeList1($6);
n->comment = $9;
$$ = (Node *) n;
}
@@ -2254,10 +2222,8 @@ CommentStmt: COMMENT ON comment_type name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = FUNCTION;
- n->objschema = NULL;
n->objname = $4;
- n->objproperty = NULL;
- n->objlist = $5;
+ n->objargs = $5;
n->comment = $7;
$$ = (Node *) n;
}
@@ -2265,28 +2231,24 @@ CommentStmt: COMMENT ON comment_type name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OPERATOR;
- n->objschema = NULL;
- n->objname = $4;
- n->objproperty = NULL;
- n->objlist = $6;
+ n->objname = makeList1(makeString($4)); /* XXX */
+ n->objargs = $6;
n->comment = $9;
$$ = (Node *) n;
}
- | COMMENT ON TRIGGER name ON qualified_name IS comment_text
+ | COMMENT ON TRIGGER name ON any_name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = TRIGGER;
- /* NOTE: schemaname here refers to the table in objproperty */
- n->objschema = $6->schemaname;
- n->objname = $4;
- n->objproperty = $6->relname;
- n->objlist = NULL;
+ n->objname = lappend($6, makeString($4));
+ n->objargs = NIL;
n->comment = $8;
$$ = (Node *) n;
}
;
-comment_type: DATABASE { $$ = DATABASE; }
+comment_type: COLUMN { $$ = COLUMN; }
+ | DATABASE { $$ = DATABASE; }
| INDEX { $$ = INDEX; }
| RULE { $$ = RULE; }
| SEQUENCE { $$ = SEQUENCE; }
@@ -2650,7 +2612,8 @@ index_list: index_list ',' index_elem { $$ = lappend($1, $3); }
func_index: func_name '(' name_list ')' opt_class
{
$$ = makeNode(IndexElem);
- $$->name = $1;
+ $$->name = NULL;
+ $$->funcname = $1;
$$->args = $3;
$$->class = $5;
}
@@ -2660,6 +2623,7 @@ index_elem: attr_name opt_class
{
$$ = makeNode(IndexElem);
$$->name = $1;
+ $$->funcname = NIL;
$$->args = NIL;
$$->class = $2;
}
@@ -2726,7 +2690,7 @@ ProcedureStmt: CREATE opt_or_replace FUNCTION func_name func_args
{
ProcedureStmt *n = makeNode(ProcedureStmt);
n->replace = $2;
- n->funcname = makeList1(makeString($4)); /* XXX */
+ n->funcname = $4;
n->argTypes = $5;
n->returnType = $7;
n->withClause = $12;
@@ -4680,7 +4644,7 @@ row_expr: '(' row_descriptor ')' IN select_with_parens
FuncCall *n = makeNode(FuncCall);
List *largs = $2;
List *rargs = $6;
- n->funcname = xlateSqlFunc("overlaps");
+ n->funcname = SystemFuncName("overlaps");
if (length(largs) == 1)
largs = lappend(largs, $2);
else if (length(largs) != 2)
@@ -4755,7 +4719,7 @@ a_expr: c_expr
| a_expr AT TIME ZONE c_expr
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "timezone";
+ n->funcname = SystemFuncName("timezone");
n->args = makeList2($5, $1);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -4820,7 +4784,7 @@ a_expr: c_expr
| a_expr LIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "like_escape";
+ n->funcname = SystemFuncName("like_escape");
n->args = makeList2($3, $5);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -4831,7 +4795,7 @@ a_expr: c_expr
| a_expr NOT LIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "like_escape";
+ n->funcname = SystemFuncName("like_escape");
n->args = makeList2($4, $6);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -4842,7 +4806,7 @@ a_expr: c_expr
| a_expr ILIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "like_escape";
+ n->funcname = SystemFuncName("like_escape");
n->args = makeList2($3, $5);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -4853,7 +4817,7 @@ a_expr: c_expr
| a_expr NOT ILIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "like_escape";
+ n->funcname = SystemFuncName("like_escape");
n->args = makeList2($4, $6);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5300,7 +5264,7 @@ c_expr: columnref
| CURRENT_USER opt_empty_parentheses
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "current_user";
+ n->funcname = SystemFuncName("current_user");
n->args = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5309,7 +5273,7 @@ c_expr: columnref
| SESSION_USER opt_empty_parentheses
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "session_user";
+ n->funcname = SystemFuncName("session_user");
n->args = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5318,7 +5282,7 @@ c_expr: columnref
| USER opt_empty_parentheses
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "current_user";
+ n->funcname = SystemFuncName("current_user");
n->args = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5327,7 +5291,7 @@ c_expr: columnref
| EXTRACT '(' extract_list ')'
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "date_part";
+ n->funcname = SystemFuncName("date_part");
n->args = $3;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5337,7 +5301,7 @@ c_expr: columnref
{
/* position(A in B) is converted to position(B, A) */
FuncCall *n = makeNode(FuncCall);
- n->funcname = "position";
+ n->funcname = SystemFuncName("position");
n->args = $3;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5349,7 +5313,7 @@ c_expr: columnref
* substring(A, B, C) - thomas 2000-11-28
*/
FuncCall *n = makeNode(FuncCall);
- n->funcname = "substring";
+ n->funcname = SystemFuncName("substring");
n->args = $3;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5361,7 +5325,7 @@ c_expr: columnref
* - thomas 1997-07-19
*/
FuncCall *n = makeNode(FuncCall);
- n->funcname = "btrim";
+ n->funcname = SystemFuncName("btrim");
n->args = $4;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5370,7 +5334,7 @@ c_expr: columnref
| TRIM '(' LEADING trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "ltrim";
+ n->funcname = SystemFuncName("ltrim");
n->args = $4;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5379,7 +5343,7 @@ c_expr: columnref
| TRIM '(' TRAILING trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "rtrim";
+ n->funcname = SystemFuncName("rtrim");
n->args = $4;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5388,7 +5352,7 @@ c_expr: columnref
| TRIM '(' trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "btrim";
+ n->funcname = SystemFuncName("btrim");
n->args = $3;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5798,19 +5762,11 @@ class: ColId { $$ = $1; };
index_name: ColId { $$ = $1; };
file_name: Sconst { $$ = $1; };
-/* func_name will soon return a List ... but not yet */
-/*
func_name: function_name
- { $$ = makeList1(makeString($1)); }
+ { $$ = makeList1(makeString(xlateSqlFunc($1))); }
| dotted_name
{ $$ = $1; }
;
-*/
-func_name: function_name
- { $$ = $1; }
- | dotted_name
- { $$ = strVal(lfirst($1)); }
- ;
/* Constants
@@ -5942,9 +5898,9 @@ type_name: IDENT { $$ = $1; }
/* Function identifier --- names that can be function names.
*/
-function_name: IDENT { $$ = xlateSqlFunc($1); }
- | unreserved_keyword { $$ = xlateSqlFunc($1); }
- | func_name_keyword { $$ = xlateSqlFunc($1); }
+function_name: IDENT { $$ = $1; }
+ | unreserved_keyword { $$ = $1; }
+ | func_name_keyword { $$ = $1; }
;
/* Column label --- allowed labels in "AS" clauses.
@@ -6459,6 +6415,8 @@ makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg)
/* xlateSqlFunc()
* Convert alternate function names to internal Postgres functions.
*
+ * NOTE: these conversions are only applied to unqualified function names.
+ *
* Do not convert "float", since that is handled elsewhere
* for FLOAT(p) syntax.
*
@@ -6482,6 +6440,8 @@ xlateSqlFunc(char *name)
/* xlateSqlType()
* Convert alternate type names to internal Postgres types.
*
+ * NOTE: these conversions are only applied to unqualified type names.
+ *
* NB: do NOT put "char" -> "bpchar" here, because that renders it impossible
* to refer to our single-byte char type, even with quotes. (Without quotes,
* CHAR is a keyword, and the code above produces "bpchar" for it.)
@@ -6521,6 +6481,14 @@ xlateSqlType(char *name)
return name;
} /* xlateSqlType() */
+/* SystemFuncName()
+ * Build a properly-qualified reference to a built-in function.
+ */
+List *
+SystemFuncName(char *name)
+{
+ return makeList2(makeString("pg_catalog"), makeString(name));
+}
void parser_init(Oid *typev, int nargs)
{
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index dc939a71801..3812579a4db 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -8,12 +8,13 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.47 2002/03/21 16:00:58 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.48 2002/04/09 20:35:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "catalog/namespace.h"
#include "catalog/pg_aggregate.h"
#include "optimizer/clauses.h"
#include "optimizer/tlist.h"
@@ -187,7 +188,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual)
Aggref *
-ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
+ParseAgg(ParseState *pstate, List *aggname, Oid basetype,
List *args, bool agg_star, bool agg_distinct)
{
HeapTuple aggtuple;
@@ -195,7 +196,7 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
Aggref *aggref;
aggtuple = SearchSysCache(AGGNAME,
- PointerGetDatum(aggname),
+ PointerGetDatum(strVal(llast(aggname))),
ObjectIdGetDatum(basetype),
0, 0);
/* shouldn't happen --- caller should have checked already */
@@ -218,7 +219,7 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
*/
aggref = makeNode(Aggref);
- aggref->aggname = pstrdup(aggname);
+ aggref->aggname = pstrdup(strVal(llast(aggname)));
aggref->basetype = aggform->aggbasetype;
aggref->aggtype = aggform->aggfinaltype;
aggref->target = lfirst(args);
@@ -237,7 +238,7 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
* basetype
*/
void
-agg_error(char *caller, char *aggname, Oid basetypeID)
+agg_error(const char *caller, List *aggname, Oid basetypeID)
{
/*
* basetypeID that is Invalid (zero) means aggregate over all types.
@@ -246,8 +247,8 @@ agg_error(char *caller, char *aggname, Oid basetypeID)
if (basetypeID == InvalidOid)
elog(ERROR, "%s: aggregate '%s' for all types does not exist",
- caller, aggname);
+ caller, NameListToString(aggname));
else
elog(ERROR, "%s: aggregate '%s' for type %s does not exist",
- caller, aggname, format_type_be(basetypeID));
+ caller, NameListToString(aggname), format_type_be(basetypeID));
}
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 690a047915a..4dd5777e1e1 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.68 2002/03/20 19:44:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.69 2002/04/09 20:35:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -657,7 +657,8 @@ PreferredType(CATEGORY category, Oid type)
* Look for a coercion function between two types.
*
* A coercion function must be named after (the internal name of) its
- * result type, and must accept exactly the specified input type.
+ * result type, and must accept exactly the specified input type. We
+ * also require it to be defined in the same namespace as its result type.
*
* This routine is also used to look for length-coercion functions, which
* are similar but accept a second argument. secondArgType is the type
@@ -669,14 +670,19 @@ PreferredType(CATEGORY category, Oid type)
static Oid
find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType)
{
- char *funcname;
+ Type targetType;
+ char *typname;
+ Oid typnamespace;
Oid oid_array[FUNC_MAX_ARGS];
int nargs;
HeapTuple ftup;
Form_pg_proc pform;
Oid funcid;
- funcname = typeidTypeName(targetTypeId);
+ targetType = typeidType(targetTypeId);
+ typname = NameStr(((Form_pg_type) GETSTRUCT(targetType))->typname);
+ typnamespace = ((Form_pg_type) GETSTRUCT(targetType))->typnamespace;
+
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
oid_array[0] = inputTypeId;
if (OidIsValid(secondArgType))
@@ -687,22 +693,27 @@ find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType)
else
nargs = 1;
- ftup = SearchSysCache(PROCNAME,
- PointerGetDatum(funcname),
- Int32GetDatum(nargs),
+ ftup = SearchSysCache(PROCNAMENSP,
+ CStringGetDatum(typname),
+ Int16GetDatum(nargs),
PointerGetDatum(oid_array),
- 0);
+ ObjectIdGetDatum(typnamespace));
if (!HeapTupleIsValid(ftup))
+ {
+ ReleaseSysCache(targetType);
return InvalidOid;
+ }
/* Make sure the function's result type is as expected, too */
pform = (Form_pg_proc) GETSTRUCT(ftup);
if (pform->prorettype != targetTypeId)
{
ReleaseSysCache(ftup);
+ ReleaseSysCache(targetType);
return InvalidOid;
}
funcid = ftup->t_data->t_oid;
ReleaseSysCache(ftup);
+ ReleaseSysCache(targetType);
return funcid;
}
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 2a5a7698d85..f8449716061 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.112 2002/03/29 19:06:11 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.113 2002/04/09 20:35:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -129,7 +129,8 @@ transformExpr(ParseState *pstate, Node *expr)
/* handle qualification, if any */
foreach(fields, pref->fields)
{
- result = ParseFuncOrColumn(pstate, strVal(lfirst(fields)),
+ result = ParseFuncOrColumn(pstate,
+ makeList1(lfirst(fields)),
makeList1(result),
false, false, true);
}
@@ -158,7 +159,8 @@ transformExpr(ParseState *pstate, Node *expr)
/* handle qualification, if any */
foreach(fields, efs->fields)
{
- result = ParseFuncOrColumn(pstate, strVal(lfirst(fields)),
+ result = ParseFuncOrColumn(pstate,
+ makeList1(lfirst(fields)),
makeList1(result),
false, false, true);
}
@@ -728,7 +730,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
rv = makeNode(RangeVar);
rv->relname = name1;
rv->inhOpt = INH_DEFAULT;
- node = ParseFuncOrColumn(pstate, name2,
+ node = ParseFuncOrColumn(pstate,
+ makeList1(makeString(name2)),
makeList1(rv),
false, false, true);
}
@@ -761,7 +764,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
rv->schemaname = name1;
rv->relname = name2;
rv->inhOpt = INH_DEFAULT;
- node = ParseFuncOrColumn(pstate, name3,
+ node = ParseFuncOrColumn(pstate,
+ makeList1(makeString(name3)),
makeList1(rv),
false, false, true);
}
@@ -801,7 +805,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
rv->schemaname = name2;
rv->relname = name3;
rv->inhOpt = INH_DEFAULT;
- node = ParseFuncOrColumn(pstate, name4,
+ node = ParseFuncOrColumn(pstate,
+ makeList1(makeString(name4)),
makeList1(rv),
false, false, true);
}
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 578402fd255..a86195126ff 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.124 2002/04/06 06:59:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.125 2002/04/09 20:35:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -54,7 +54,7 @@ static int match_argtypes(int nargs,
static FieldSelect *setup_field_select(Node *input, char *attname, Oid relid);
static FuncCandidateList func_select_candidate(int nargs, Oid *input_typeids,
FuncCandidateList candidates);
-static int agg_get_candidates(char *aggname, Oid typeId,
+static int agg_get_candidates(List *aggname, Oid typeId,
FuncCandidateList *candidates);
static Oid agg_select_candidate(Oid typeid, FuncCandidateList candidates);
@@ -64,22 +64,22 @@ static Oid agg_select_candidate(Oid typeid, FuncCandidateList candidates);
*
* For historical reasons, Postgres tries to treat the notations tab.col
* and col(tab) as equivalent: if a single-argument function call has an
- * argument of complex type and the function name matches any attribute
- * of the type, we take it as a column projection.
+ * argument of complex type and the (unqualified) function name matches
+ * any attribute of the type, we take it as a column projection.
*
* Hence, both cases come through here. The is_column parameter tells us
* which syntactic construct is actually being dealt with, but this is
* intended to be used only to deliver an appropriate error message,
* not to affect the semantics. When is_column is true, we should have
- * a single argument (the putative table), function name equal to the
- * column name, and no aggregate decoration.
+ * a single argument (the putative table), unqualified function name
+ * equal to the column name, and no aggregate decoration.
*
* In the function-call case, the argument expressions have been transformed
* already. In the column case, we may get either a transformed expression
* or a RangeVar node as argument.
*/
Node *
-ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
+ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
bool agg_star, bool agg_distinct, bool is_column)
{
Oid rettype;
@@ -113,23 +113,28 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
{
first_arg = lfirst(fargs);
if (first_arg == NULL) /* should not happen */
- elog(ERROR, "Function '%s' does not allow NULL input", funcname);
+ elog(ERROR, "Function '%s' does not allow NULL input",
+ NameListToString(funcname));
}
/*
* check for column projection: if function has one argument, and that
- * argument is of complex type, then the function could be a projection.
+ * argument is of complex type, and function name is not qualified,
+ * then the "function call" could be a projection. We also check
+ * that there wasn't any aggregate decoration.
*/
- /* We only have one parameter, and it's not got aggregate decoration */
- if (nargs == 1 && !must_be_agg)
+ if (nargs == 1 && !must_be_agg && length(funcname) == 1)
{
+ char *cname = strVal(lfirst(funcname));
+
/* Is it a not-yet-transformed RangeVar node? */
if (IsA(first_arg, RangeVar))
{
/* First arg is a relation. This could be a projection. */
refname = ((RangeVar *) first_arg)->relname;
- retval = qualifiedNameToVar(pstate, refname, funcname, true);
+ /* XXX WRONG: ignores possible qualification of argument */
+ retval = qualifiedNameToVar(pstate, refname, cname, true);
if (retval)
return retval;
}
@@ -140,9 +145,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
* ParseComplexProjection can't handle the projection, we have
* to keep going.
*/
- retval = ParseComplexProjection(pstate,
- funcname,
- first_arg);
+ retval = ParseComplexProjection(pstate, cname, first_arg);
if (retval)
return retval;
}
@@ -175,7 +178,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
/* try for exact match first... */
if (SearchSysCacheExists(AGGNAME,
- PointerGetDatum(funcname),
+ PointerGetDatum(strVal(llast(funcname))),
ObjectIdGetDatum(basetype),
0, 0))
return (Node *) ParseAgg(pstate, funcname, basetype,
@@ -183,7 +186,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
/* check for aggregate-that-accepts-any-type (eg, COUNT) */
if (SearchSysCacheExists(AGGNAME,
- PointerGetDatum(funcname),
+ PointerGetDatum(strVal(llast(funcname))),
ObjectIdGetDatum(0),
0, 0))
return (Node *) ParseAgg(pstate, funcname, 0,
@@ -211,7 +214,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
{
/* Multiple possible matches --- give up */
elog(ERROR, "Unable to select an aggregate function %s(%s)",
- funcname, format_type_be(basetype));
+ NameListToString(funcname), format_type_be(basetype));
}
}
@@ -222,7 +225,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
* function could not have been meant.
*/
elog(ERROR, "There is no aggregate function %s(%s)",
- funcname, format_type_be(basetype));
+ NameListToString(funcname), format_type_be(basetype));
}
}
@@ -275,7 +278,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
*/
if (is_column)
elog(ERROR, "No such attribute %s.%s",
- refname, funcname);
+ refname, strVal(lfirst(funcname)));
else
{
elog(ERROR, "Cannot pass result of sub-select or join %s to a function",
@@ -329,7 +332,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
* give an error message that is appropriate for that case.
*/
if (is_column)
- elog(ERROR, "Attribute \"%s\" not found", funcname);
+ elog(ERROR, "Attribute \"%s\" not found",
+ strVal(lfirst(funcname)));
/* Else generate a detailed complaint */
func_error(NULL, funcname, nargs, oid_array,
"Unable to identify a function that satisfies the "
@@ -373,7 +377,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
static int
-agg_get_candidates(char *aggname,
+agg_get_candidates(List *aggname,
Oid typeId,
FuncCandidateList *candidates)
{
@@ -388,7 +392,7 @@ agg_get_candidates(char *aggname,
ScanKeyEntryInitialize(&aggKey[0], 0,
Anum_pg_aggregate_aggname,
F_NAMEEQ,
- NameGetDatum(aggname));
+ NameGetDatum(strVal(llast(aggname))));
pg_aggregate_desc = heap_openr(AggregateRelationName, AccessShareLock);
pg_aggregate_scan = systable_beginscan(pg_aggregate_desc,
@@ -862,7 +866,7 @@ func_select_candidate(int nargs,
* d) if the answer is zero, try the next array from vector #1
*/
FuncDetailCode
-func_get_detail(char *funcname,
+func_get_detail(List *funcname,
List *fargs,
int nargs,
Oid *argtypes,
@@ -875,7 +879,7 @@ func_get_detail(char *funcname,
FuncCandidateList best_candidate;
/* Get list of possible candidates from namespace search */
- function_typeids = FuncnameGetCandidates(makeList1(makeString(funcname)), nargs);
+ function_typeids = FuncnameGetCandidates(funcname, nargs);
/*
* See if there is an exact match
@@ -917,15 +921,11 @@ func_get_detail(char *funcname,
if (nargs == 1)
{
Oid targetType;
+ TypeName *tn = makeNode(TypeName);
- /* XXX WRONG: need to search searchpath for name; but little
- * point in fixing before we revise this code for qualified
- * funcnames too.
- */
- targetType = GetSysCacheOid(TYPENAMENSP,
- PointerGetDatum(funcname),
- ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
- 0, 0);
+ tn->names = funcname;
+ tn->typmod = -1;
+ targetType = LookupTypeName(tn);
if (OidIsValid(targetType) &&
!ISCOMPLEX(targetType))
{
@@ -1409,7 +1409,7 @@ ParseComplexProjection(ParseState *pstate,
* argument types
*/
void
-func_error(const char *caller, const char *funcname,
+func_error(const char *caller, List *funcname,
int nargs, const Oid *argtypes,
const char *msg)
{
@@ -1439,13 +1439,87 @@ func_error(const char *caller, const char *funcname,
if (caller == NULL)
{
elog(ERROR, "Function '%s(%s)' does not exist%s%s",
- funcname, p,
+ NameListToString(funcname), p,
((msg != NULL) ? "\n\t" : ""), ((msg != NULL) ? msg : ""));
}
else
{
elog(ERROR, "%s: function '%s(%s)' does not exist%s%s",
- caller, funcname, p,
+ caller, NameListToString(funcname), p,
((msg != NULL) ? "\n\t" : ""), ((msg != NULL) ? msg : ""));
}
}
+
+/*
+ * LookupFuncName
+ * Given a possibly-qualified function name and a set of argument types,
+ * look up the function. Returns InvalidOid if no such function.
+ *
+ * If the function name is not schema-qualified, it is sought in the current
+ * namespace search path.
+ */
+Oid
+LookupFuncName(List *funcname, int nargs, const Oid *argtypes)
+{
+ FuncCandidateList clist;
+
+ clist = FuncnameGetCandidates(funcname, nargs);
+
+ while (clist)
+ {
+ if (memcmp(argtypes, clist->args, nargs * sizeof(Oid)) == 0)
+ return clist->oid;
+ clist = clist->next;
+ }
+
+ return InvalidOid;
+}
+
+/*
+ * LookupFuncNameTypeNames
+ * Like LookupFuncName, but the argument types are specified by a
+ * list of TypeName nodes. Also, if we fail to find the function
+ * and caller is not NULL, then an error is reported via func_error.
+ *
+ * "opaque" is accepted as a typename only if opaqueOK is true.
+ */
+Oid
+LookupFuncNameTypeNames(List *funcname, List *argtypes, bool opaqueOK,
+ const char *caller)
+{
+ Oid funcoid;
+ Oid argoids[FUNC_MAX_ARGS];
+ int argcount;
+ int i;
+
+ MemSet(argoids, 0, FUNC_MAX_ARGS * sizeof(Oid));
+ argcount = length(argtypes);
+ if (argcount > FUNC_MAX_ARGS)
+ elog(ERROR, "functions cannot have more than %d arguments",
+ FUNC_MAX_ARGS);
+
+ for (i = 0; i < argcount; i++)
+ {
+ TypeName *t = (TypeName *) lfirst(argtypes);
+
+ argoids[i] = LookupTypeName(t);
+ if (!OidIsValid(argoids[i]))
+ {
+ char *typnam = TypeNameToString(t);
+
+ if (opaqueOK && strcmp(typnam, "opaque") == 0)
+ argoids[i] = InvalidOid;
+ else
+ elog(ERROR, "Type \"%s\" does not exist", typnam);
+ }
+
+ argtypes = lnext(argtypes);
+ }
+
+ funcoid = LookupFuncName(funcname, argcount, argoids);
+
+ if (!OidIsValid(funcoid) && caller != NULL)
+ func_error(caller, funcname, argcount, argoids, NULL);
+
+ return funcoid;
+}
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index e8e82a45c3b..83c53de5d1d 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.82 2002/04/05 11:56:53 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.83 2002/04/09 20:35:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -498,48 +498,34 @@ FigureColnameInternal(Node *node, char **name)
return 2;
case T_ColumnRef:
{
- List *fields = ((ColumnRef *) node)->fields;
+ char *cname = strVal(llast(((ColumnRef *) node)->fields));
- while (lnext(fields) != NIL)
- fields = lnext(fields);
- if (strcmp(strVal(lfirst(fields)), "*") != 0)
+ if (strcmp(cname, "*") != 0)
{
- *name = strVal(lfirst(fields));
+ *name = cname;
return 2;
}
}
break;
case T_ExprFieldSelect:
{
- List *fields = ((ExprFieldSelect *) node)->fields;
+ char *fname = strVal(llast(((ExprFieldSelect *) node)->fields));
- if (fields)
+ if (strcmp(fname, "*") != 0)
{
- while (lnext(fields) != NIL)
- fields = lnext(fields);
- if (strcmp(strVal(lfirst(fields)), "*") != 0)
- {
- *name = strVal(lfirst(fields));
- return 2;
- }
+ *name = fname;
+ return 2;
}
}
break;
case T_FuncCall:
- *name = ((FuncCall *) node)->funcname;
+ *name = strVal(llast(((FuncCall *) node)->funcname));
return 2;
case T_A_Const:
if (((A_Const *) node)->typename != NULL)
{
- List *names = ((A_Const *) node)->typename->names;
-
- if (names != NIL)
- {
- while (lnext(names) != NIL)
- names = lnext(names);
- *name = strVal(lfirst(names));
- return 1;
- }
+ *name = strVal(llast(((A_Const *) node)->typename->names));
+ return 1;
}
break;
case T_TypeCast:
@@ -549,15 +535,8 @@ FigureColnameInternal(Node *node, char **name)
{
if (((TypeCast *) node)->typename != NULL)
{
- List *names = ((TypeCast *) node)->typename->names;
-
- if (names != NIL)
- {
- while (lnext(names) != NIL)
- names = lnext(names);
- *name = strVal(lfirst(names));
- return 1;
- }
+ *name = strVal(llast(((TypeCast *) node)->typename->names));
+ return 1;
}
}
break;