mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
pgindent run.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.283 2003/08/01 00:15:22 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.284 2003/08/04 00:43:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -89,7 +89,7 @@ typedef struct
|
||||
{
|
||||
Oid *paramTypes;
|
||||
int numParams;
|
||||
} check_parameter_resolution_context;
|
||||
} check_parameter_resolution_context;
|
||||
|
||||
|
||||
static List *do_parse_analyze(Node *parseTree, ParseState *pstate);
|
||||
@@ -106,7 +106,7 @@ static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
|
||||
static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt);
|
||||
static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
|
||||
static Query *transformDeclareCursorStmt(ParseState *pstate,
|
||||
DeclareCursorStmt *stmt);
|
||||
DeclareCursorStmt * stmt);
|
||||
static Query *transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt);
|
||||
static Query *transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt);
|
||||
static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
|
||||
@@ -114,18 +114,18 @@ static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
|
||||
static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
|
||||
List **extras_before, List **extras_after);
|
||||
static void transformColumnDefinition(ParseState *pstate,
|
||||
CreateStmtContext *cxt,
|
||||
ColumnDef *column);
|
||||
CreateStmtContext *cxt,
|
||||
ColumnDef *column);
|
||||
static void transformTableConstraint(ParseState *pstate,
|
||||
CreateStmtContext *cxt,
|
||||
Constraint *constraint);
|
||||
CreateStmtContext *cxt,
|
||||
Constraint *constraint);
|
||||
static void transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
InhRelation *inhrelation);
|
||||
InhRelation * inhrelation);
|
||||
static void transformIndexConstraints(ParseState *pstate,
|
||||
CreateStmtContext *cxt);
|
||||
CreateStmtContext *cxt);
|
||||
static void transformFKConstraints(ParseState *pstate,
|
||||
CreateStmtContext *cxt,
|
||||
bool isAddConstraint);
|
||||
CreateStmtContext *cxt,
|
||||
bool isAddConstraint);
|
||||
static void applyColumnNames(List *dst, List *src);
|
||||
static List *getSetColTypes(ParseState *pstate, Node *node);
|
||||
static void transformForUpdate(Query *qry, List *forUpdate);
|
||||
@@ -135,7 +135,7 @@ static bool relationHasPrimaryKey(Oid relationOid);
|
||||
static void release_pstate_resources(ParseState *pstate);
|
||||
static FromExpr *makeFromExpr(List *fromlist, Node *quals);
|
||||
static bool check_parameter_resolution_walker(Node *node,
|
||||
check_parameter_resolution_context *context);
|
||||
check_parameter_resolution_context * context);
|
||||
|
||||
|
||||
/*
|
||||
@@ -229,6 +229,7 @@ static List *
|
||||
do_parse_analyze(Node *parseTree, ParseState *pstate)
|
||||
{
|
||||
List *result = NIL;
|
||||
|
||||
/* Lists to return extra commands from transformation */
|
||||
List *extras_before = NIL;
|
||||
List *extras_after = NIL;
|
||||
@@ -258,9 +259,10 @@ do_parse_analyze(Node *parseTree, ParseState *pstate)
|
||||
|
||||
/*
|
||||
* Make sure that only the original query is marked original. We have
|
||||
* to do this explicitly since recursive calls of do_parse_analyze will
|
||||
* have marked some of the added-on queries as "original". Also mark
|
||||
* only the original query as allowed to set the command-result tag.
|
||||
* to do this explicitly since recursive calls of do_parse_analyze
|
||||
* will have marked some of the added-on queries as "original". Also
|
||||
* mark only the original query as allowed to set the command-result
|
||||
* tag.
|
||||
*/
|
||||
foreach(listscan, result)
|
||||
{
|
||||
@@ -419,7 +421,7 @@ transformStmt(ParseState *pstate, Node *parseTree,
|
||||
|
||||
case T_DeclareCursorStmt:
|
||||
result = transformDeclareCursorStmt(pstate,
|
||||
(DeclareCursorStmt *) parseTree);
|
||||
(DeclareCursorStmt *) parseTree);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -593,10 +595,10 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
*
|
||||
* HACK: unknown-type constants and params in the INSERT's targetlist
|
||||
* are copied up as-is rather than being referenced as subquery
|
||||
* outputs. This is to ensure that when we try to coerce them
|
||||
* to the target column's datatype, the right things happen (see
|
||||
* special cases in coerce_type). Otherwise, this fails:
|
||||
* INSERT INTO foo SELECT 'bar', ... FROM baz
|
||||
* outputs. This is to ensure that when we try to coerce them to
|
||||
* the target column's datatype, the right things happen (see
|
||||
* special cases in coerce_type). Otherwise, this fails: INSERT
|
||||
* INTO foo SELECT 'bar', ... FROM baz
|
||||
*/
|
||||
qry->targetList = NIL;
|
||||
foreach(tl, selectQuery->targetList)
|
||||
@@ -608,7 +610,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
if (resnode->resjunk)
|
||||
continue;
|
||||
if (tle->expr &&
|
||||
(IsA(tle->expr, Const) || IsA(tle->expr, Param)) &&
|
||||
(IsA(tle->expr, Const) ||IsA(tle->expr, Param)) &&
|
||||
exprType((Node *) tle->expr) == UNKNOWNOID)
|
||||
expr = tle->expr;
|
||||
else
|
||||
@@ -661,7 +663,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
if (icolumns == NIL || attnos == NIL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("INSERT has more expressions than target columns")));
|
||||
errmsg("INSERT has more expressions than target columns")));
|
||||
|
||||
col = (ResTarget *) lfirst(icolumns);
|
||||
Assert(IsA(col, ResTarget));
|
||||
@@ -675,15 +677,14 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that the targetlist has the same number of entries that
|
||||
* were present in the columns list. Don't do the check unless
|
||||
* an explicit columns list was given, though.
|
||||
* statements.
|
||||
* Ensure that the targetlist has the same number of entries that were
|
||||
* present in the columns list. Don't do the check unless an explicit
|
||||
* columns list was given, though. statements.
|
||||
*/
|
||||
if (stmt->cols != NIL && (icolumns != NIL || attnos != NIL))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("INSERT has more target columns than expressions")));
|
||||
errmsg("INSERT has more target columns than expressions")));
|
||||
|
||||
/* done building the range table and jointree */
|
||||
qry->rtable = pstate->p_rtable;
|
||||
@@ -1054,7 +1055,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting NULL/NOT NULL declarations for \"%s.%s\"",
|
||||
cxt->relation->relname, column->colname)));
|
||||
cxt->relation->relname, column->colname)));
|
||||
column->is_not_null = FALSE;
|
||||
saw_nullable = true;
|
||||
break;
|
||||
@@ -1064,7 +1065,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting NULL/NOT NULL declarations for \"%s.%s\"",
|
||||
cxt->relation->relname, column->colname)));
|
||||
cxt->relation->relname, column->colname)));
|
||||
column->is_not_null = TRUE;
|
||||
saw_nullable = true;
|
||||
break;
|
||||
@@ -1074,7 +1075,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("multiple DEFAULT values specified for \"%s.%s\"",
|
||||
cxt->relation->relname, column->colname)));
|
||||
cxt->relation->relname, column->colname)));
|
||||
column->raw_default = constraint->raw_expr;
|
||||
Assert(constraint->cooked_expr == NULL);
|
||||
break;
|
||||
@@ -1170,7 +1171,7 @@ transformTableConstraint(ParseState *pstate, CreateStmtContext *cxt,
|
||||
*/
|
||||
static void
|
||||
transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
InhRelation *inhRelation)
|
||||
InhRelation * inhRelation)
|
||||
{
|
||||
AttrNumber parent_attno;
|
||||
|
||||
@@ -1188,7 +1189,7 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
inhRelation->relation->relname)));
|
||||
|
||||
/*
|
||||
* Check for SELECT privilages
|
||||
* Check for SELECT privilages
|
||||
*/
|
||||
aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
|
||||
ACL_SELECT);
|
||||
@@ -1200,8 +1201,8 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
constr = tupleDesc->constr;
|
||||
|
||||
/*
|
||||
* Insert the inherited attributes into the cxt for the
|
||||
* new table definition.
|
||||
* Insert the inherited attributes into the cxt for the new table
|
||||
* definition.
|
||||
*/
|
||||
for (parent_attno = 1; parent_attno <= tupleDesc->natts;
|
||||
parent_attno++)
|
||||
@@ -1220,8 +1221,8 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
/*
|
||||
* Create a new inherited column.
|
||||
*
|
||||
* For constraints, ONLY the NOT NULL constraint is inherited
|
||||
* by the new column definition per SQL99.
|
||||
* For constraints, ONLY the NOT NULL constraint is inherited by the
|
||||
* new column definition per SQL99.
|
||||
*/
|
||||
def = makeNode(ColumnDef);
|
||||
def->colname = pstrdup(attributeName);
|
||||
@@ -1265,9 +1266,8 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
Assert(this_default != NULL);
|
||||
|
||||
/*
|
||||
* If default expr could contain any vars, we'd need to
|
||||
* fix 'em, but it can't; so default is ready to apply to
|
||||
* child.
|
||||
* If default expr could contain any vars, we'd need to fix
|
||||
* 'em, but it can't; so default is ready to apply to child.
|
||||
*/
|
||||
|
||||
def->cooked_default = pstrdup(this_default);
|
||||
@@ -1275,9 +1275,9 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the parent rel, but keep our AccessShareLock on it until
|
||||
* xact commit. That will prevent someone else from deleting or
|
||||
* ALTERing the parent before the child is committed.
|
||||
* Close the parent rel, but keep our AccessShareLock on it until xact
|
||||
* commit. That will prevent someone else from deleting or ALTERing
|
||||
* the parent before the child is committed.
|
||||
*/
|
||||
heap_close(relation, NoLock);
|
||||
}
|
||||
@@ -1340,8 +1340,8 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
/*
|
||||
* Make sure referenced keys exist. If we are making a PRIMARY
|
||||
* KEY index, also make sure they are NOT NULL, if possible.
|
||||
* (Although we could leave it to DefineIndex to mark the columns NOT
|
||||
* NULL, it's more efficient to get it right the first time.)
|
||||
* (Although we could leave it to DefineIndex to mark the columns
|
||||
* NOT NULL, it's more efficient to get it right the first time.)
|
||||
*/
|
||||
foreach(keys, constraint->keys)
|
||||
{
|
||||
@@ -1390,8 +1390,8 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
if (rel->rd_rel->relkind != RELKIND_RELATION)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("inherited table \"%s\" is not a relation",
|
||||
inh->relname)));
|
||||
errmsg("inherited table \"%s\" is not a relation",
|
||||
inh->relname)));
|
||||
for (count = 0; count < rel->rd_att->natts; count++)
|
||||
{
|
||||
Form_pg_attribute inhattr = rel->rd_att->attrs[count];
|
||||
@@ -1402,11 +1402,13 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
if (strcmp(key, inhname) == 0)
|
||||
{
|
||||
found = true;
|
||||
|
||||
/*
|
||||
* We currently have no easy way to force an
|
||||
* inherited column to be NOT NULL at creation, if
|
||||
* its parent wasn't so already. We leave it to
|
||||
* DefineIndex to fix things up in this case.
|
||||
* inherited column to be NOT NULL at
|
||||
* creation, if its parent wasn't so already.
|
||||
* We leave it to DefineIndex to fix things up
|
||||
* in this case.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
@@ -1425,9 +1427,10 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
if (HeapTupleIsValid(atttuple))
|
||||
{
|
||||
found = true;
|
||||
|
||||
/*
|
||||
* If it's not already NOT NULL, leave it to DefineIndex
|
||||
* to fix later.
|
||||
* If it's not already NOT NULL, leave it to
|
||||
* DefineIndex to fix later.
|
||||
*/
|
||||
ReleaseSysCache(atttuple);
|
||||
}
|
||||
@@ -1436,8 +1439,8 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
if (!found)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("column \"%s\" named in key does not exist",
|
||||
key)));
|
||||
errmsg("column \"%s\" named in key does not exist",
|
||||
key)));
|
||||
|
||||
/* Check for PRIMARY KEY(foo, foo) */
|
||||
foreach(columns, index->indexParams)
|
||||
@@ -1446,10 +1449,10 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
if (iparam->name && strcmp(key, iparam->name) == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_COLUMN),
|
||||
/* translator: second %s is PRIMARY KEY or UNIQUE */
|
||||
errmsg("column \"%s\" appears twice in %s constraint",
|
||||
key,
|
||||
index->primary ? "PRIMARY KEY" : "UNIQUE")));
|
||||
/* translator: second %s is PRIMARY KEY or UNIQUE */
|
||||
errmsg("column \"%s\" appears twice in %s constraint",
|
||||
key,
|
||||
index->primary ? "PRIMARY KEY" : "UNIQUE")));
|
||||
}
|
||||
|
||||
/* OK, add it to the index definition */
|
||||
@@ -1543,7 +1546,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
ereport(NOTICE,
|
||||
(errmsg("%s / %s%s will create implicit index \"%s\" for table \"%s\"",
|
||||
cxt->stmtType,
|
||||
(strcmp(cxt->stmtType, "ALTER TABLE") == 0) ? "ADD " : "",
|
||||
(strcmp(cxt->stmtType, "ALTER TABLE") == 0) ? "ADD " : "",
|
||||
(index->primary ? "PRIMARY KEY" : "UNIQUE"),
|
||||
index->idxname, cxt->relation->relname)));
|
||||
}
|
||||
@@ -1557,13 +1560,13 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt,
|
||||
return;
|
||||
|
||||
ereport(NOTICE,
|
||||
(errmsg("%s will create implicit trigger(s) for FOREIGN KEY check(s)",
|
||||
cxt->stmtType)));
|
||||
(errmsg("%s will create implicit trigger(s) for FOREIGN KEY check(s)",
|
||||
cxt->stmtType)));
|
||||
|
||||
/*
|
||||
* For ALTER TABLE ADD CONSTRAINT, nothing to do. For CREATE TABLE or
|
||||
* ALTER TABLE ADD COLUMN, gin up an ALTER TABLE ADD CONSTRAINT command
|
||||
* to execute after the basic command is complete.
|
||||
* ALTER TABLE ADD COLUMN, gin up an ALTER TABLE ADD CONSTRAINT
|
||||
* command to execute after the basic command is complete.
|
||||
*
|
||||
* Note: the ADD CONSTRAINT command must also execute after any index
|
||||
* creation commands. Thus, this should run after
|
||||
@@ -1575,7 +1578,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt,
|
||||
AlterTableStmt *alterstmt = makeNode(AlterTableStmt);
|
||||
List *fkclist;
|
||||
|
||||
alterstmt->subtype = 'c'; /* preprocessed add constraint */
|
||||
alterstmt->subtype = 'c'; /* preprocessed add constraint */
|
||||
alterstmt->relation = cxt->relation;
|
||||
alterstmt->name = NULL;
|
||||
alterstmt->def = (Node *) cxt->fkconstraints;
|
||||
@@ -1628,7 +1631,7 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
|
||||
/* take care of any index expressions */
|
||||
foreach(l, stmt->indexParams)
|
||||
{
|
||||
IndexElem *ielem = (IndexElem *) lfirst(l);
|
||||
IndexElem *ielem = (IndexElem *) lfirst(l);
|
||||
|
||||
if (ielem->expr)
|
||||
{
|
||||
@@ -1641,6 +1644,7 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
|
||||
addRTEtoQuery(pstate, rte, false, true);
|
||||
}
|
||||
ielem->expr = transformExpr(pstate, ielem->expr);
|
||||
|
||||
/*
|
||||
* We check only that the result type is legitimate; this is
|
||||
* for consistency with what transformWhereClause() checks for
|
||||
@@ -1649,7 +1653,7 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
|
||||
if (expression_returns_set(ielem->expr))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("index expression may not return a set")));
|
||||
errmsg("index expression may not return a set")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1829,10 +1833,10 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
|
||||
sub_qry = getInsertSelectQuery(top_subqry, NULL);
|
||||
|
||||
/*
|
||||
* If the sub_qry is a setop, we cannot attach any qualifications
|
||||
* to it, because the planner won't notice them. This could
|
||||
* perhaps be relaxed someday, but for now, we may as well reject
|
||||
* such a rule immediately.
|
||||
* If the sub_qry is a setop, we cannot attach any
|
||||
* qualifications to it, because the planner won't notice
|
||||
* them. This could perhaps be relaxed someday, but for now,
|
||||
* we may as well reject such a rule immediately.
|
||||
*/
|
||||
if (sub_qry->setOperations != NULL && stmt->whereClause != NULL)
|
||||
ereport(ERROR,
|
||||
@@ -1854,12 +1858,12 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
|
||||
case CMD_SELECT:
|
||||
if (has_old)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("ON SELECT rule may not use OLD")));
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("ON SELECT rule may not use OLD")));
|
||||
if (has_new)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("ON SELECT rule may not use NEW")));
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("ON SELECT rule may not use NEW")));
|
||||
break;
|
||||
case CMD_UPDATE:
|
||||
/* both are OK */
|
||||
@@ -1867,14 +1871,14 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
|
||||
case CMD_INSERT:
|
||||
if (has_old)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("ON INSERT rule may not use OLD")));
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("ON INSERT rule may not use OLD")));
|
||||
break;
|
||||
case CMD_DELETE:
|
||||
if (has_new)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("ON DELETE rule may not use NEW")));
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("ON DELETE rule may not use NEW")));
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unrecognized event type: %d",
|
||||
@@ -1902,9 +1906,10 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
|
||||
if (has_old || (has_new && stmt->event == CMD_UPDATE))
|
||||
{
|
||||
/*
|
||||
* If sub_qry is a setop, manipulating its jointree will do
|
||||
* no good at all, because the jointree is dummy. (This
|
||||
* should be a can't-happen case because of prior tests.)
|
||||
* If sub_qry is a setop, manipulating its jointree will
|
||||
* do no good at all, because the jointree is dummy.
|
||||
* (This should be a can't-happen case because of prior
|
||||
* tests.)
|
||||
*/
|
||||
if (sub_qry->setOperations != NULL)
|
||||
ereport(ERROR,
|
||||
@@ -1978,7 +1983,7 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
qry->sortClause = transformSortClause(pstate,
|
||||
stmt->sortClause,
|
||||
qry->targetList,
|
||||
true /* fix unknowns */);
|
||||
true /* fix unknowns */ );
|
||||
|
||||
qry->groupClause = transformGroupClause(pstate,
|
||||
stmt->groupClause,
|
||||
@@ -2107,10 +2112,10 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
* make lists of the dummy vars and their names for use in parsing
|
||||
* ORDER BY.
|
||||
*
|
||||
* Note: we use leftmostRTI as the varno of the dummy variables.
|
||||
* It shouldn't matter too much which RT index they have, as long
|
||||
* as they have one that corresponds to a real RT entry; else funny
|
||||
* things may happen when the tree is mashed by rule rewriting.
|
||||
* Note: we use leftmostRTI as the varno of the dummy variables. It
|
||||
* shouldn't matter too much which RT index they have, as long as they
|
||||
* have one that corresponds to a real RT entry; else funny things may
|
||||
* happen when the tree is mashed by rule rewriting.
|
||||
*/
|
||||
qry->targetList = NIL;
|
||||
targetvars = NIL;
|
||||
@@ -2144,8 +2149,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
/*
|
||||
* Handle SELECT INTO/CREATE TABLE AS.
|
||||
*
|
||||
* Any column names from CREATE TABLE AS need to be attached to both
|
||||
* the top level and the leftmost subquery. We do not do this earlier
|
||||
* Any column names from CREATE TABLE AS need to be attached to both the
|
||||
* top level and the leftmost subquery. We do not do this earlier
|
||||
* because we do *not* want the targetnames list to be affected.
|
||||
*/
|
||||
qry->into = into;
|
||||
@@ -2192,7 +2197,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
qry->sortClause = transformSortClause(pstate,
|
||||
sortClause,
|
||||
qry->targetList,
|
||||
false /* no unknowns expected */);
|
||||
false /* no unknowns expected */ );
|
||||
|
||||
pstate->p_namespace = sv_namespace;
|
||||
pstate->p_rtable = sv_rtable;
|
||||
@@ -2290,9 +2295,9 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
|
||||
|
||||
/*
|
||||
* Check for bogus references to Vars on the current query level
|
||||
* (but upper-level references are okay).
|
||||
* Normally this can't happen because the namespace will be empty,
|
||||
* but it could happen if we are inside a rule.
|
||||
* (but upper-level references are okay). Normally this can't
|
||||
* happen because the namespace will be empty, but it could happen
|
||||
* if we are inside a rule.
|
||||
*/
|
||||
if (pstate->p_namespace)
|
||||
{
|
||||
@@ -2352,8 +2357,8 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
|
||||
if (length(lcoltypes) != length(rcoltypes))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("each %s query must have the same number of columns",
|
||||
context)));
|
||||
errmsg("each %s query must have the same number of columns",
|
||||
context)));
|
||||
op->colTypes = NIL;
|
||||
while (lcoltypes != NIL)
|
||||
{
|
||||
@@ -2422,7 +2427,7 @@ applyColumnNames(List *dst, List *src)
|
||||
if (length(src) > length(dst))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("CREATE TABLE AS specifies too many column names")));
|
||||
errmsg("CREATE TABLE AS specifies too many column names")));
|
||||
|
||||
while (src != NIL && dst != NIL)
|
||||
{
|
||||
@@ -2538,8 +2543,8 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
|
||||
* handling are 'A'dd column and Add 'C'onstraint. These largely
|
||||
* re-use code from CREATE TABLE.
|
||||
*
|
||||
* If we need to do any parse transformation, get exclusive lock on
|
||||
* the relation to make sure it won't change before we execute the
|
||||
* If we need to do any parse transformation, get exclusive lock on the
|
||||
* relation to make sure it won't change before we execute the
|
||||
* command.
|
||||
*/
|
||||
switch (stmt->subtype)
|
||||
@@ -2574,7 +2579,7 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
|
||||
*extras_before = nconc(*extras_before, cxt.blist);
|
||||
*extras_after = nconc(cxt.alist, *extras_after);
|
||||
|
||||
heap_close(rel, NoLock); /* close rel, keep lock */
|
||||
heap_close(rel, NoLock); /* close rel, keep lock */
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
@@ -2614,7 +2619,7 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
|
||||
*extras_before = nconc(*extras_before, cxt.blist);
|
||||
*extras_after = nconc(cxt.alist, *extras_after);
|
||||
|
||||
heap_close(rel, NoLock); /* close rel, keep lock */
|
||||
heap_close(rel, NoLock); /* close rel, keep lock */
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
@@ -2638,7 +2643,7 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
|
||||
}
|
||||
|
||||
static Query *
|
||||
transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
|
||||
transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt * stmt)
|
||||
{
|
||||
Query *result = makeNode(Query);
|
||||
List *extras_before = NIL,
|
||||
@@ -2672,7 +2677,7 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt)
|
||||
{
|
||||
Query *result = makeNode(Query);
|
||||
List *argtype_oids = NIL; /* argtype OIDs in a list */
|
||||
Oid *argtoids = NULL; /* and as an array */
|
||||
Oid *argtoids = NULL; /* and as an array */
|
||||
int nargs;
|
||||
List *queries;
|
||||
|
||||
@@ -2757,11 +2762,11 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt)
|
||||
if (pstate->p_hasSubLinks)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot use sub-select in EXECUTE parameter")));
|
||||
errmsg("cannot use sub-select in EXECUTE parameter")));
|
||||
if (pstate->p_hasAggs)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_GROUPING_ERROR),
|
||||
errmsg("cannot use aggregate in EXECUTE parameter")));
|
||||
errmsg("cannot use aggregate in EXECUTE parameter")));
|
||||
|
||||
given_type_id = exprType(expr);
|
||||
expected_type_id = lfirsto(paramtypes);
|
||||
@@ -2801,15 +2806,15 @@ CheckSelectForUpdate(Query *qry)
|
||||
if (qry->distinctClause != NIL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("SELECT FOR UPDATE is not allowed with DISTINCT clause")));
|
||||
errmsg("SELECT FOR UPDATE is not allowed with DISTINCT clause")));
|
||||
if (qry->groupClause != NIL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("SELECT FOR UPDATE is not allowed with GROUP BY clause")));
|
||||
errmsg("SELECT FOR UPDATE is not allowed with GROUP BY clause")));
|
||||
if (qry->hasAggs)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("SELECT FOR UPDATE is not allowed with AGGREGATE")));
|
||||
errmsg("SELECT FOR UPDATE is not allowed with AGGREGATE")));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2915,7 +2920,7 @@ relationHasPrimaryKey(Oid relationOid)
|
||||
indexTuple = SearchSysCache(INDEXRELID,
|
||||
ObjectIdGetDatum(indexoid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(indexTuple)) /* should not happen */
|
||||
if (!HeapTupleIsValid(indexTuple)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for index %u", indexoid);
|
||||
result = ((Form_pg_index) GETSTRUCT(indexTuple))->indisprimary;
|
||||
ReleaseSysCache(indexTuple);
|
||||
@@ -2981,7 +2986,7 @@ transformConstraintAttrs(List *constraintList)
|
||||
!IsA(lastprimarynode, FkConstraint))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("misplaced NOT DEFERRABLE clause")));
|
||||
errmsg("misplaced NOT DEFERRABLE clause")));
|
||||
if (saw_deferrability)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
@@ -2999,7 +3004,7 @@ transformConstraintAttrs(List *constraintList)
|
||||
!IsA(lastprimarynode, FkConstraint))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("misplaced INITIALLY DEFERRED clause")));
|
||||
errmsg("misplaced INITIALLY DEFERRED clause")));
|
||||
if (saw_initially)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
@@ -3023,7 +3028,7 @@ transformConstraintAttrs(List *constraintList)
|
||||
!IsA(lastprimarynode, FkConstraint))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("misplaced INITIALLY IMMEDIATE clause")));
|
||||
errmsg("misplaced INITIALLY IMMEDIATE clause")));
|
||||
if (saw_initially)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
@@ -3135,10 +3140,10 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
|
||||
elp->relation->schemaname = cxt.schemaname;
|
||||
else if (strcmp(cxt.schemaname, elp->relation->schemaname) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
|
||||
errmsg("CREATE specifies a schema (%s)"
|
||||
" different from the one being created (%s)",
|
||||
elp->relation->schemaname, cxt.schemaname)));
|
||||
(errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
|
||||
errmsg("CREATE specifies a schema (%s)"
|
||||
" different from the one being created (%s)",
|
||||
elp->relation->schemaname, cxt.schemaname)));
|
||||
|
||||
/*
|
||||
* XXX todo: deal with constraints
|
||||
@@ -3156,10 +3161,10 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
|
||||
elp->view->schemaname = cxt.schemaname;
|
||||
else if (strcmp(cxt.schemaname, elp->view->schemaname) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
|
||||
errmsg("CREATE specifies a schema (%s)"
|
||||
" different from the one being created (%s)",
|
||||
elp->view->schemaname, cxt.schemaname)));
|
||||
(errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
|
||||
errmsg("CREATE specifies a schema (%s)"
|
||||
" different from the one being created (%s)",
|
||||
elp->view->schemaname, cxt.schemaname)));
|
||||
|
||||
/*
|
||||
* XXX todo: deal with references between views
|
||||
@@ -3195,7 +3200,7 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
|
||||
*/
|
||||
static bool
|
||||
check_parameter_resolution_walker(Node *node,
|
||||
check_parameter_resolution_context *context)
|
||||
check_parameter_resolution_context * context)
|
||||
{
|
||||
if (node == NULL)
|
||||
return false;
|
||||
@@ -3207,17 +3212,17 @@ check_parameter_resolution_walker(Node *node,
|
||||
{
|
||||
int paramno = param->paramid;
|
||||
|
||||
if (paramno <= 0 || /* shouldn't happen, but... */
|
||||
if (paramno <= 0 || /* shouldn't happen, but... */
|
||||
paramno > context->numParams)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_PARAMETER),
|
||||
errmsg("there is no parameter $%d", paramno)));
|
||||
|
||||
if (param->paramtype != context->paramTypes[paramno-1])
|
||||
if (param->paramtype != context->paramTypes[paramno - 1])
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_AMBIGUOUS_PARAMETER),
|
||||
errmsg("could not determine datatype of parameter $%d",
|
||||
paramno)));
|
||||
errmsg("could not determine datatype of parameter $%d",
|
||||
paramno)));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.55 2003/07/19 20:20:52 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.56 2003/08/04 00:43:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -44,7 +44,7 @@ static bool check_ungrouped_columns_walker(Node *node,
|
||||
* Finish initial transformation of an aggregate call
|
||||
*
|
||||
* parse_func.c has recognized the function as an aggregate, and has set
|
||||
* up all the fields of the Aggref except agglevelsup. Here we must
|
||||
* up all the fields of the Aggref except agglevelsup. Here we must
|
||||
* determine which query level the aggregate actually belongs to, set
|
||||
* agglevelsup accordingly, and mark p_hasAggs true in the corresponding
|
||||
* pstate level.
|
||||
@@ -56,22 +56,22 @@ transformAggregateCall(ParseState *pstate, Aggref *agg)
|
||||
|
||||
/*
|
||||
* The aggregate's level is the same as the level of the lowest-level
|
||||
* variable or aggregate in its argument; or if it contains no variables
|
||||
* at all, we presume it to be local.
|
||||
* variable or aggregate in its argument; or if it contains no
|
||||
* variables at all, we presume it to be local.
|
||||
*/
|
||||
min_varlevel = find_minimum_var_level((Node *) agg->target);
|
||||
|
||||
/*
|
||||
* An aggregate can't directly contain another aggregate call of the
|
||||
* same level (though outer aggs are okay). We can skip this check
|
||||
* if we didn't find any local vars or aggs.
|
||||
* same level (though outer aggs are okay). We can skip this check if
|
||||
* we didn't find any local vars or aggs.
|
||||
*/
|
||||
if (min_varlevel == 0)
|
||||
{
|
||||
if (checkExprHasAggs((Node *) agg->target))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_GROUPING_ERROR),
|
||||
errmsg("aggregate function calls may not be nested")));
|
||||
errmsg("aggregate function calls may not be nested")));
|
||||
}
|
||||
|
||||
if (min_varlevel < 0)
|
||||
@@ -142,17 +142,17 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
|
||||
if (checkExprHasAggs(expr))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_GROUPING_ERROR),
|
||||
errmsg("aggregates not allowed in GROUP BY clause")));
|
||||
errmsg("aggregates not allowed in GROUP BY clause")));
|
||||
groupClauses = lcons(expr, groupClauses);
|
||||
if (!IsA(expr, Var))
|
||||
have_non_var_grouping = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are join alias vars involved, we have to flatten them
|
||||
* to the underlying vars, so that aliased and unaliased vars will be
|
||||
* correctly taken as equal. We can skip the expense of doing this
|
||||
* if no rangetable entries are RTE_JOIN kind.
|
||||
* If there are join alias vars involved, we have to flatten them to
|
||||
* the underlying vars, so that aliased and unaliased vars will be
|
||||
* correctly taken as equal. We can skip the expense of doing this if
|
||||
* no rangetable entries are RTE_JOIN kind.
|
||||
*/
|
||||
hasJoinRTEs = false;
|
||||
foreach(lst, pstate->p_rtable)
|
||||
@@ -168,7 +168,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
|
||||
|
||||
if (hasJoinRTEs)
|
||||
groupClauses = (List *) flatten_join_alias_vars(qry,
|
||||
(Node *) groupClauses);
|
||||
(Node *) groupClauses);
|
||||
|
||||
/*
|
||||
* Check the targetlist and HAVING clause for ungrouped variables.
|
||||
@@ -235,22 +235,22 @@ check_ungrouped_columns_walker(Node *node,
|
||||
|
||||
/*
|
||||
* If we find an aggregate call of the original level, do not recurse
|
||||
* into its arguments; ungrouped vars in the arguments are not an error.
|
||||
* We can also skip looking at the arguments of aggregates of higher
|
||||
* levels, since they could not possibly contain Vars that are of concern
|
||||
* to us (see transformAggregateCall). We do need to look into the
|
||||
* arguments of aggregates of lower levels, however.
|
||||
* into its arguments; ungrouped vars in the arguments are not an
|
||||
* error. We can also skip looking at the arguments of aggregates of
|
||||
* higher levels, since they could not possibly contain Vars that are
|
||||
* of concern to us (see transformAggregateCall). We do need to look
|
||||
* into the arguments of aggregates of lower levels, however.
|
||||
*/
|
||||
if (IsA(node, Aggref) &&
|
||||
(int) ((Aggref *) node)->agglevelsup >= context->sublevels_up)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If we have any GROUP BY items that are not simple Vars,
|
||||
* check to see if subexpression as a whole matches any GROUP BY item.
|
||||
* We need to do this at every recursion level so that we recognize
|
||||
* GROUPed-BY expressions before reaching variables within them.
|
||||
* But this only works at the outer query level, as noted above.
|
||||
* If we have any GROUP BY items that are not simple Vars, check to
|
||||
* see if subexpression as a whole matches any GROUP BY item. We need
|
||||
* to do this at every recursion level so that we recognize GROUPed-BY
|
||||
* expressions before reaching variables within them. But this only
|
||||
* works at the outer query level, as noted above.
|
||||
*/
|
||||
if (context->have_non_var_grouping && context->sublevels_up == 0)
|
||||
{
|
||||
@@ -264,7 +264,7 @@ check_ungrouped_columns_walker(Node *node,
|
||||
/*
|
||||
* If we have an ungrouped Var of the original query level, we have a
|
||||
* failure. Vars below the original query level are not a problem,
|
||||
* and neither are Vars from above it. (If such Vars are ungrouped as
|
||||
* and neither are Vars from above it. (If such Vars are ungrouped as
|
||||
* far as their own query level is concerned, that's someone else's
|
||||
* problem...)
|
||||
*/
|
||||
@@ -276,6 +276,7 @@ check_ungrouped_columns_walker(Node *node,
|
||||
|
||||
if (var->varlevelsup != context->sublevels_up)
|
||||
return false; /* it's not local to my query, ignore */
|
||||
|
||||
/*
|
||||
* Check for a match, if we didn't do it above.
|
||||
*/
|
||||
@@ -283,13 +284,13 @@ check_ungrouped_columns_walker(Node *node,
|
||||
{
|
||||
foreach(gl, context->groupClauses)
|
||||
{
|
||||
Var *gvar = (Var *) lfirst(gl);
|
||||
Var *gvar = (Var *) lfirst(gl);
|
||||
|
||||
if (IsA(gvar, Var) &&
|
||||
gvar->varno == var->varno &&
|
||||
gvar->varattno == var->varattno &&
|
||||
gvar->varlevelsup == 0)
|
||||
return false; /* acceptable, we're okay */
|
||||
return false; /* acceptable, we're okay */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,10 +366,10 @@ build_aggregate_fnexprs(Oid agg_input_type,
|
||||
(void) get_func_signature(transfn_oid, transfn_arg_types, &transfn_nargs);
|
||||
|
||||
/*
|
||||
* Build arg list to use in the transfn FuncExpr node. We really
|
||||
* only care that transfn can discover the actual argument types
|
||||
* at runtime using get_fn_expr_argtype(), so it's okay to use
|
||||
* Param nodes that don't correspond to any real Param.
|
||||
* Build arg list to use in the transfn FuncExpr node. We really only
|
||||
* care that transfn can discover the actual argument types at runtime
|
||||
* using get_fn_expr_argtype(), so it's okay to use Param nodes that
|
||||
* don't correspond to any real Param.
|
||||
*/
|
||||
arg0 = makeNode(Param);
|
||||
arg0->paramkind = PARAM_EXEC;
|
||||
@@ -385,33 +386,31 @@ build_aggregate_fnexprs(Oid agg_input_type,
|
||||
args = makeList2(arg0, arg1);
|
||||
}
|
||||
else
|
||||
{
|
||||
args = makeList1(arg0);
|
||||
|
||||
*transfnexpr = (Expr *) makeFuncExpr(transfn_oid,
|
||||
agg_state_type,
|
||||
args,
|
||||
COERCE_DONTCARE);
|
||||
|
||||
/* see if we have a final function */
|
||||
if (!OidIsValid(finalfn_oid))
|
||||
{
|
||||
*finalfnexpr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*transfnexpr = (Expr *) makeFuncExpr(transfn_oid,
|
||||
agg_state_type,
|
||||
args,
|
||||
COERCE_DONTCARE);
|
||||
|
||||
/* see if we have a final function */
|
||||
if (!OidIsValid(finalfn_oid))
|
||||
{
|
||||
*finalfnexpr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build expr tree for final function
|
||||
*/
|
||||
/*
|
||||
* Build expr tree for final function
|
||||
*/
|
||||
arg0 = makeNode(Param);
|
||||
arg0->paramkind = PARAM_EXEC;
|
||||
arg0->paramid = -1;
|
||||
arg0->paramtype = agg_state_type;
|
||||
args = makeList1(arg0);
|
||||
|
||||
*finalfnexpr = (Expr *) makeFuncExpr(finalfn_oid,
|
||||
agg_result_type,
|
||||
args,
|
||||
COERCE_DONTCARE);
|
||||
*finalfnexpr = (Expr *) makeFuncExpr(finalfn_oid,
|
||||
agg_result_type,
|
||||
args,
|
||||
COERCE_DONTCARE);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.118 2003/07/19 20:20:52 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.119 2003/08/04 00:43:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -60,8 +60,8 @@ static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype,
|
||||
static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node,
|
||||
List *tlist, int clause);
|
||||
static List *addTargetToSortList(ParseState *pstate, TargetEntry *tle,
|
||||
List *sortlist, List *targetlist,
|
||||
List *opname, bool resolveUnknown);
|
||||
List *sortlist, List *targetlist,
|
||||
List *opname, bool resolveUnknown);
|
||||
|
||||
|
||||
/*
|
||||
@@ -337,7 +337,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
errmsg("JOIN/ON clause refers to \"%s\", which is not part of JOIN",
|
||||
rt_fetch(varno, pstate->p_rtable)->eref->aliasname)));
|
||||
rt_fetch(varno, pstate->p_rtable)->eref->aliasname)));
|
||||
}
|
||||
}
|
||||
bms_free(clause_varnos);
|
||||
@@ -422,17 +422,19 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
|
||||
errmsg("sub-select in FROM may not have SELECT INTO")));
|
||||
|
||||
/*
|
||||
* The subquery cannot make use of any variables from FROM items created
|
||||
* earlier in the current query. Per SQL92, the scope of a FROM item
|
||||
* does not include other FROM items. Formerly we hacked the namespace
|
||||
* so that the other variables weren't even visible, but it seems more
|
||||
* useful to leave them visible and give a specific error message.
|
||||
* The subquery cannot make use of any variables from FROM items
|
||||
* created earlier in the current query. Per SQL92, the scope of a
|
||||
* FROM item does not include other FROM items. Formerly we hacked
|
||||
* the namespace so that the other variables weren't even visible, but
|
||||
* it seems more useful to leave them visible and give a specific
|
||||
* error message.
|
||||
*
|
||||
* XXX this will need further work to support SQL99's LATERAL() feature,
|
||||
* wherein such references would indeed be legal.
|
||||
*
|
||||
* We can skip groveling through the subquery if there's not anything
|
||||
* visible in the current query. Also note that outer references are OK.
|
||||
* visible in the current query. Also note that outer references are
|
||||
* OK.
|
||||
*/
|
||||
if (pstate->p_namespace)
|
||||
{
|
||||
@@ -482,9 +484,9 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
|
||||
|
||||
/*
|
||||
* The function parameters cannot make use of any variables from other
|
||||
* FROM items. (Compare to transformRangeSubselect(); the coding is
|
||||
* different though because we didn't parse as a sub-select with its own
|
||||
* level of namespace.)
|
||||
* FROM items. (Compare to transformRangeSubselect(); the coding is
|
||||
* different though because we didn't parse as a sub-select with its
|
||||
* own level of namespace.)
|
||||
*
|
||||
* XXX this will need further work to support SQL99's LATERAL() feature,
|
||||
* wherein such references would indeed be legal.
|
||||
@@ -1017,7 +1019,7 @@ transformLimitClause(ParseState *pstate, Node *clause,
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
/* translator: %s is name of a SQL construct, eg LIMIT */
|
||||
/* translator: %s is name of a SQL construct, eg LIMIT */
|
||||
errmsg("argument of %s must not contain variables",
|
||||
constructName)));
|
||||
}
|
||||
@@ -1025,7 +1027,7 @@ transformLimitClause(ParseState *pstate, Node *clause,
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_GROUPING_ERROR),
|
||||
/* translator: %s is name of a SQL construct, eg LIMIT */
|
||||
/* translator: %s is name of a SQL construct, eg LIMIT */
|
||||
errmsg("argument of %s must not contain aggregates",
|
||||
constructName)));
|
||||
}
|
||||
@@ -1033,7 +1035,7 @@ transformLimitClause(ParseState *pstate, Node *clause,
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
/* translator: %s is name of a SQL construct, eg LIMIT */
|
||||
/* translator: %s is name of a SQL construct, eg LIMIT */
|
||||
errmsg("argument of %s must not contain sub-selects",
|
||||
constructName)));
|
||||
}
|
||||
@@ -1135,7 +1137,11 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
|
||||
if (!equal(target_result->expr, tle->expr))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_AMBIGUOUS_COLUMN),
|
||||
/* translator: first %s is name of a SQL construct, eg ORDER BY */
|
||||
|
||||
/*
|
||||
* translator: first %s is name of a SQL
|
||||
* construct, eg ORDER BY
|
||||
*/
|
||||
errmsg("%s \"%s\" is ambiguous",
|
||||
clauseText[clause], name)));
|
||||
}
|
||||
@@ -1157,7 +1163,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
|
||||
if (!IsA(val, Integer))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
/* translator: %s is name of a SQL construct, eg ORDER BY */
|
||||
/* translator: %s is name of a SQL construct, eg ORDER BY */
|
||||
errmsg("non-integer constant in %s",
|
||||
clauseText[clause])));
|
||||
target_pos = intVal(val);
|
||||
@@ -1174,7 +1180,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
|
||||
}
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
/* translator: %s is name of a SQL construct, eg ORDER BY */
|
||||
/* translator: %s is name of a SQL construct, eg ORDER BY */
|
||||
errmsg("%s position %d is not in target list",
|
||||
clauseText[clause], target_pos)));
|
||||
}
|
||||
@@ -1250,10 +1256,10 @@ transformGroupClause(ParseState *pstate, List *grouplist,
|
||||
/*
|
||||
* If the GROUP BY clause matches the ORDER BY clause, we want to
|
||||
* adopt the ordering operators from the latter rather than using
|
||||
* the default ops. This allows "GROUP BY foo ORDER BY foo DESC" to
|
||||
* be done with only one sort step. Note we are assuming that any
|
||||
* user-supplied ordering operator will bring equal values together,
|
||||
* which is all that GROUP BY needs.
|
||||
* the default ops. This allows "GROUP BY foo ORDER BY foo DESC"
|
||||
* to be done with only one sort step. Note we are assuming that
|
||||
* any user-supplied ordering operator will bring equal values
|
||||
* together, which is all that GROUP BY needs.
|
||||
*/
|
||||
if (sortClause &&
|
||||
((SortClause *) lfirst(sortClause))->tleSortGroupRef ==
|
||||
@@ -1422,7 +1428,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (slitem == NIL) /* should not happen */
|
||||
if (slitem == NIL) /* should not happen */
|
||||
elog(ERROR, "failed to add DISTINCT ON clause to target list");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.106 2003/07/28 00:09:15 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.107 2003/08/04 00:43:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -30,8 +30,8 @@
|
||||
|
||||
|
||||
static Node *coerce_type_typmod(Node *node,
|
||||
Oid targetTypeId, int32 targetTypMod,
|
||||
CoercionForm cformat, bool isExplicit);
|
||||
Oid targetTypeId, int32 targetTypMod,
|
||||
CoercionForm cformat, bool isExplicit);
|
||||
|
||||
|
||||
/*
|
||||
@@ -39,12 +39,12 @@ static Node *coerce_type_typmod(Node *node,
|
||||
* Convert an expression to a target type and typmod.
|
||||
*
|
||||
* This is the general-purpose entry point for arbitrary type coercion
|
||||
* operations. Direct use of the component operations can_coerce_type,
|
||||
* operations. Direct use of the component operations can_coerce_type,
|
||||
* coerce_type, and coerce_type_typmod should be restricted to special
|
||||
* cases (eg, when the conversion is expected to succeed).
|
||||
*
|
||||
* Returns the possibly-transformed expression tree, or NULL if the type
|
||||
* conversion is not possible. (We do this, rather than ereport'ing directly,
|
||||
* conversion is not possible. (We do this, rather than ereport'ing directly,
|
||||
* so that callers can generate custom error messages indicating context.)
|
||||
*
|
||||
* pstate - parse state (can be NULL, see coerce_type)
|
||||
@@ -66,14 +66,14 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
|
||||
else if (ccontext >= COERCION_ASSIGNMENT)
|
||||
{
|
||||
/*
|
||||
* String hacks to get transparent conversions for char and varchar:
|
||||
* if a coercion to text is available, use it for forced coercions to
|
||||
* char(n) or varchar(n) or domains thereof.
|
||||
* String hacks to get transparent conversions for char and
|
||||
* varchar: if a coercion to text is available, use it for forced
|
||||
* coercions to char(n) or varchar(n) or domains thereof.
|
||||
*
|
||||
* This is pretty grotty, but seems easier to maintain than providing
|
||||
* entries in pg_cast that parallel all the ones for text.
|
||||
*/
|
||||
Oid targetbasetype = getBaseType(targettype);
|
||||
Oid targetbasetype = getBaseType(targettype);
|
||||
|
||||
if (targetbasetype == BPCHAROID || targetbasetype == VARCHAROID)
|
||||
{
|
||||
@@ -91,7 +91,10 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* need a RelabelType if no typmod coercion will be performed */
|
||||
/*
|
||||
* need a RelabelType if no typmod coercion will be
|
||||
* performed
|
||||
*/
|
||||
if (targettypmod < 0)
|
||||
expr = (Node *) makeRelabelType((Expr *) expr,
|
||||
targettype, -1,
|
||||
@@ -127,13 +130,13 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
|
||||
* The caller should already have determined that the coercion is possible;
|
||||
* see can_coerce_type.
|
||||
*
|
||||
* No coercion to a typmod (length) is performed here. The caller must
|
||||
* No coercion to a typmod (length) is performed here. The caller must
|
||||
* call coerce_type_typmod as well, if a typmod constraint is wanted.
|
||||
* (But if the target type is a domain, it may internally contain a
|
||||
* typmod constraint, which will be applied inside coerce_to_domain.)
|
||||
*
|
||||
* pstate is only used in the case that we are able to resolve the type of
|
||||
* a previously UNKNOWN Param. It is okay to pass pstate = NULL if the
|
||||
* a previously UNKNOWN Param. It is okay to pass pstate = NULL if the
|
||||
* caller does not want type information updated for Params.
|
||||
*/
|
||||
Node *
|
||||
@@ -191,8 +194,9 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
* Any length constraint will be applied later by our caller.
|
||||
*
|
||||
* Note that we call stringTypeDatum using the domain's pg_type
|
||||
* row, if it's a domain. This works because the domain row has
|
||||
* the same typinput and typelem as the base type --- ugly...
|
||||
* row, if it's a domain. This works because the domain row
|
||||
* has the same typinput and typelem as the base type ---
|
||||
* ugly...
|
||||
*/
|
||||
newcon->constvalue = stringTypeDatum(targetType, val, -1);
|
||||
pfree(val);
|
||||
@@ -232,12 +236,12 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
(errcode(ERRCODE_UNDEFINED_PARAMETER),
|
||||
errmsg("there is no parameter $%d", paramno)));
|
||||
|
||||
if (toppstate->p_paramtypes[paramno-1] == UNKNOWNOID)
|
||||
if (toppstate->p_paramtypes[paramno - 1] == UNKNOWNOID)
|
||||
{
|
||||
/* We've successfully resolved the type */
|
||||
toppstate->p_paramtypes[paramno-1] = targetTypeId;
|
||||
toppstate->p_paramtypes[paramno - 1] = targetTypeId;
|
||||
}
|
||||
else if (toppstate->p_paramtypes[paramno-1] == targetTypeId)
|
||||
else if (toppstate->p_paramtypes[paramno - 1] == targetTypeId)
|
||||
{
|
||||
/* We previously resolved the type, and it matches */
|
||||
}
|
||||
@@ -246,10 +250,10 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
/* Ooops */
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_AMBIGUOUS_PARAMETER),
|
||||
errmsg("inconsistent types deduced for parameter $%d",
|
||||
paramno),
|
||||
errmsg("inconsistent types deduced for parameter $%d",
|
||||
paramno),
|
||||
errdetail("%s versus %s",
|
||||
format_type_be(toppstate->p_paramtypes[paramno-1]),
|
||||
format_type_be(toppstate->p_paramtypes[paramno - 1]),
|
||||
format_type_be(targetTypeId))));
|
||||
}
|
||||
|
||||
@@ -298,7 +302,7 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
* higher-level code.
|
||||
*
|
||||
* Also, domains may have value restrictions beyond the base type
|
||||
* that must be accounted for. If the destination is a domain
|
||||
* that must be accounted for. If the destination is a domain
|
||||
* then we won't need a RelabelType node.
|
||||
*/
|
||||
result = coerce_to_domain(node, InvalidOid, targetTypeId,
|
||||
@@ -306,10 +310,11 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
if (result == node)
|
||||
{
|
||||
/*
|
||||
* XXX could we label result with exprTypmod(node) instead of
|
||||
* default -1 typmod, to save a possible length-coercion
|
||||
* later? Would work if both types have same interpretation of
|
||||
* typmod, which is likely but not certain.
|
||||
* XXX could we label result with exprTypmod(node) instead
|
||||
* of default -1 typmod, to save a possible
|
||||
* length-coercion later? Would work if both types have
|
||||
* same interpretation of typmod, which is likely but not
|
||||
* certain.
|
||||
*/
|
||||
result = (Node *) makeRelabelType((Expr *) result,
|
||||
targetTypeId, -1,
|
||||
@@ -386,7 +391,7 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
|
||||
if (targetTypeId == ANYARRAYOID ||
|
||||
targetTypeId == ANYELEMENTOID)
|
||||
{
|
||||
have_generics = true; /* do more checking later */
|
||||
have_generics = true; /* do more checking later */
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -437,7 +442,7 @@ Node *
|
||||
coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId, CoercionForm cformat)
|
||||
{
|
||||
CoerceToDomain *result;
|
||||
int32 typmod;
|
||||
int32 typmod;
|
||||
|
||||
/* Get the base type if it hasn't been supplied */
|
||||
if (baseTypeId == InvalidOid)
|
||||
@@ -448,17 +453,18 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId, CoercionForm cformat)
|
||||
return arg;
|
||||
|
||||
/*
|
||||
* If the domain applies a typmod to its base type, build the appropriate
|
||||
* coercion step. Mark it implicit for display purposes, because we don't
|
||||
* want it shown separately by ruleutils.c; but the isExplicit flag passed
|
||||
* to the conversion function depends on the manner in which the domain
|
||||
* coercion is invoked, so that the semantics of implicit and explicit
|
||||
* coercion differ. (Is that really the behavior we want?)
|
||||
* If the domain applies a typmod to its base type, build the
|
||||
* appropriate coercion step. Mark it implicit for display purposes,
|
||||
* because we don't want it shown separately by ruleutils.c; but the
|
||||
* isExplicit flag passed to the conversion function depends on the
|
||||
* manner in which the domain coercion is invoked, so that the
|
||||
* semantics of implicit and explicit coercion differ. (Is that
|
||||
* really the behavior we want?)
|
||||
*
|
||||
* NOTE: because we apply this as part of the fixed expression structure,
|
||||
* ALTER DOMAIN cannot alter the typtypmod. But it's unclear that that
|
||||
* would be safe to do anyway, without lots of knowledge about what the
|
||||
* base type thinks the typmod means.
|
||||
* ALTER DOMAIN cannot alter the typtypmod. But it's unclear that
|
||||
* that would be safe to do anyway, without lots of knowledge about
|
||||
* what the base type thinks the typmod means.
|
||||
*/
|
||||
typmod = get_typtypmod(typeId);
|
||||
if (typmod >= 0)
|
||||
@@ -467,9 +473,10 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId, CoercionForm cformat)
|
||||
(cformat != COERCE_IMPLICIT_CAST));
|
||||
|
||||
/*
|
||||
* Now build the domain coercion node. This represents run-time checking
|
||||
* of any constraints currently attached to the domain. This also
|
||||
* ensures that the expression is properly labeled as to result type.
|
||||
* Now build the domain coercion node. This represents run-time
|
||||
* checking of any constraints currently attached to the domain. This
|
||||
* also ensures that the expression is properly labeled as to result
|
||||
* type.
|
||||
*/
|
||||
result = makeNode(CoerceToDomain);
|
||||
result->arg = (Expr *) arg;
|
||||
@@ -568,15 +575,15 @@ coerce_to_boolean(ParseState *pstate, Node *node,
|
||||
if (node == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
/* translator: first %s is name of a SQL construct, eg WHERE */
|
||||
errmsg("argument of %s must be type boolean, not type %s",
|
||||
constructName, format_type_be(inputTypeId))));
|
||||
/* translator: first %s is name of a SQL construct, eg WHERE */
|
||||
errmsg("argument of %s must be type boolean, not type %s",
|
||||
constructName, format_type_be(inputTypeId))));
|
||||
}
|
||||
|
||||
if (expression_returns_set(node))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
/* translator: %s is name of a SQL construct, eg WHERE */
|
||||
/* translator: %s is name of a SQL construct, eg WHERE */
|
||||
errmsg("argument of %s must not return a set",
|
||||
constructName)));
|
||||
|
||||
@@ -607,15 +614,15 @@ coerce_to_integer(ParseState *pstate, Node *node,
|
||||
if (node == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
/* translator: first %s is name of a SQL construct, eg LIMIT */
|
||||
errmsg("argument of %s must be type integer, not type %s",
|
||||
constructName, format_type_be(inputTypeId))));
|
||||
/* translator: first %s is name of a SQL construct, eg LIMIT */
|
||||
errmsg("argument of %s must be type integer, not type %s",
|
||||
constructName, format_type_be(inputTypeId))));
|
||||
}
|
||||
|
||||
if (expression_returns_set(node))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
/* translator: %s is name of a SQL construct, eg LIMIT */
|
||||
/* translator: %s is name of a SQL construct, eg LIMIT */
|
||||
errmsg("argument of %s must not return a set",
|
||||
constructName)));
|
||||
|
||||
@@ -664,19 +671,24 @@ select_common_type(List *typeids, const char *context)
|
||||
*/
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
/* translator: first %s is name of a SQL construct, eg CASE */
|
||||
|
||||
/*
|
||||
* translator: first %s is name of a SQL construct, eg
|
||||
* CASE
|
||||
*/
|
||||
errmsg("%s types %s and %s cannot be matched",
|
||||
context,
|
||||
format_type_be(ptype),
|
||||
format_type_be(ntype))));
|
||||
}
|
||||
else if (!IsPreferredType(pcategory, ptype) &&
|
||||
can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
|
||||
!can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
|
||||
can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
|
||||
!can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
|
||||
{
|
||||
/*
|
||||
* take new type if can coerce to it implicitly but not the
|
||||
* other way; but if we have a preferred type, stay on it.
|
||||
* take new type if can coerce to it implicitly but not
|
||||
* the other way; but if we have a preferred type, stay on
|
||||
* it.
|
||||
*/
|
||||
ptype = ntype;
|
||||
pcategory = TypeCategory(ptype);
|
||||
@@ -725,7 +737,7 @@ coerce_to_common_type(ParseState *pstate, Node *node,
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_CANNOT_COERCE),
|
||||
/* translator: first %s is name of a SQL construct, eg CASE */
|
||||
/* translator: first %s is name of a SQL construct, eg CASE */
|
||||
errmsg("%s could not convert type %s to %s",
|
||||
context,
|
||||
format_type_be(inputTypeId),
|
||||
@@ -744,8 +756,8 @@ coerce_to_common_type(ParseState *pstate, Node *node,
|
||||
* and must in fact be varlena arrays.
|
||||
* 2) All arguments declared ANYELEMENT must have matching datatypes.
|
||||
* 3) If there are arguments of both ANYELEMENT and ANYARRAY, make sure
|
||||
* the actual ANYELEMENT datatype is in fact the element type for
|
||||
* the actual ANYARRAY datatype.
|
||||
* the actual ANYELEMENT datatype is in fact the element type for
|
||||
* the actual ANYARRAY datatype.
|
||||
*
|
||||
* If we have UNKNOWN input (ie, an untyped literal) for any ANYELEMENT
|
||||
* or ANYARRAY argument, assume it is okay.
|
||||
@@ -763,13 +775,13 @@ check_generic_type_consistency(Oid *actual_arg_types,
|
||||
Oid array_typelem;
|
||||
|
||||
/*
|
||||
* Loop through the arguments to see if we have any that are
|
||||
* ANYARRAY or ANYELEMENT. If so, require the actual types to be
|
||||
* Loop through the arguments to see if we have any that are ANYARRAY
|
||||
* or ANYELEMENT. If so, require the actual types to be
|
||||
* self-consistent
|
||||
*/
|
||||
for (j = 0; j < nargs; j++)
|
||||
{
|
||||
Oid actual_type = actual_arg_types[j];
|
||||
Oid actual_type = actual_arg_types[j];
|
||||
|
||||
if (declared_arg_types[j] == ANYELEMENTOID)
|
||||
{
|
||||
@@ -798,7 +810,10 @@ check_generic_type_consistency(Oid *actual_arg_types,
|
||||
|
||||
if (!OidIsValid(elem_typeid))
|
||||
{
|
||||
/* if we don't have an element type yet, use the one we just got */
|
||||
/*
|
||||
* if we don't have an element type yet, use the one we just
|
||||
* got
|
||||
*/
|
||||
elem_typeid = array_typelem;
|
||||
}
|
||||
else if (array_typelem != elem_typeid)
|
||||
@@ -831,23 +846,23 @@ check_generic_type_consistency(Oid *actual_arg_types,
|
||||
* if it is declared ANYARRAY or ANYELEMENT:
|
||||
*
|
||||
* 1) If return type is ANYARRAY, and any argument is ANYARRAY, use the
|
||||
* argument's actual type as the function's return type.
|
||||
* argument's actual type as the function's return type.
|
||||
* 2) If return type is ANYARRAY, no argument is ANYARRAY, but any argument
|
||||
* is ANYELEMENT, use the actual type of the argument to determine
|
||||
* the function's return type, i.e. the element type's corresponding
|
||||
* array type.
|
||||
* is ANYELEMENT, use the actual type of the argument to determine
|
||||
* the function's return type, i.e. the element type's corresponding
|
||||
* array type.
|
||||
* 3) If return type is ANYARRAY, no argument is ANYARRAY or ANYELEMENT,
|
||||
* generate an ERROR. This condition is prevented by CREATE FUNCTION
|
||||
* and is therefore not expected here.
|
||||
* generate an ERROR. This condition is prevented by CREATE FUNCTION
|
||||
* and is therefore not expected here.
|
||||
* 4) If return type is ANYELEMENT, and any argument is ANYELEMENT, use the
|
||||
* argument's actual type as the function's return type.
|
||||
* argument's actual type as the function's return type.
|
||||
* 5) If return type is ANYELEMENT, no argument is ANYELEMENT, but any
|
||||
* argument is ANYARRAY, use the actual type of the argument to determine
|
||||
* the function's return type, i.e. the array type's corresponding
|
||||
* element type.
|
||||
* argument is ANYARRAY, use the actual type of the argument to determine
|
||||
* the function's return type, i.e. the array type's corresponding
|
||||
* element type.
|
||||
* 6) If return type is ANYELEMENT, no argument is ANYARRAY or ANYELEMENT,
|
||||
* generate an ERROR. This condition is prevented by CREATE FUNCTION
|
||||
* and is therefore not expected here.
|
||||
* generate an ERROR. This condition is prevented by CREATE FUNCTION
|
||||
* and is therefore not expected here.
|
||||
*/
|
||||
Oid
|
||||
enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
@@ -863,13 +878,13 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
Oid array_typelem = InvalidOid;
|
||||
|
||||
/*
|
||||
* Loop through the arguments to see if we have any that are
|
||||
* ANYARRAY or ANYELEMENT. If so, require the actual types to be
|
||||
* Loop through the arguments to see if we have any that are ANYARRAY
|
||||
* or ANYELEMENT. If so, require the actual types to be
|
||||
* self-consistent
|
||||
*/
|
||||
for (j = 0; j < nargs; j++)
|
||||
{
|
||||
Oid actual_type = actual_arg_types[j];
|
||||
Oid actual_type = actual_arg_types[j];
|
||||
|
||||
if (declared_arg_types[j] == ANYELEMENTOID)
|
||||
{
|
||||
@@ -882,7 +897,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("arguments declared ANYELEMENT are not all alike"),
|
||||
errmsg("arguments declared ANYELEMENT are not all alike"),
|
||||
errdetail("%s versus %s",
|
||||
format_type_be(elem_typeid),
|
||||
format_type_be(actual_type))));
|
||||
@@ -899,7 +914,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
if (OidIsValid(array_typeid) && actual_type != array_typeid)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("arguments declared ANYARRAY are not all alike"),
|
||||
errmsg("arguments declared ANYARRAY are not all alike"),
|
||||
errdetail("%s versus %s",
|
||||
format_type_be(array_typeid),
|
||||
format_type_be(actual_type))));
|
||||
@@ -921,12 +936,15 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
if (!OidIsValid(array_typelem))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("argument declared ANYARRAY is not an array but %s",
|
||||
format_type_be(array_typeid))));
|
||||
errmsg("argument declared ANYARRAY is not an array but %s",
|
||||
format_type_be(array_typeid))));
|
||||
|
||||
if (!OidIsValid(elem_typeid))
|
||||
{
|
||||
/* if we don't have an element type yet, use the one we just got */
|
||||
/*
|
||||
* if we don't have an element type yet, use the one we just
|
||||
* got
|
||||
*/
|
||||
elem_typeid = array_typelem;
|
||||
}
|
||||
else if (array_typelem != elem_typeid)
|
||||
@@ -955,15 +973,13 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
{
|
||||
for (j = 0; j < nargs; j++)
|
||||
{
|
||||
Oid actual_type = actual_arg_types[j];
|
||||
Oid actual_type = actual_arg_types[j];
|
||||
|
||||
if (actual_type != UNKNOWNOID)
|
||||
continue;
|
||||
|
||||
if (declared_arg_types[j] == ANYELEMENTOID)
|
||||
{
|
||||
declared_arg_types[j] = elem_typeid;
|
||||
}
|
||||
else if (declared_arg_types[j] == ANYARRAYOID)
|
||||
{
|
||||
if (!OidIsValid(array_typeid))
|
||||
@@ -989,8 +1005,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
if (!OidIsValid(array_typeid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("could not find array type for datatype %s",
|
||||
format_type_be(elem_typeid))));
|
||||
errmsg("could not find array type for datatype %s",
|
||||
format_type_be(elem_typeid))));
|
||||
}
|
||||
return array_typeid;
|
||||
}
|
||||
@@ -1026,7 +1042,7 @@ resolve_generic_type(Oid declared_type,
|
||||
if (context_declared_type == ANYARRAYOID)
|
||||
{
|
||||
/* Use actual type, but it must be an array */
|
||||
Oid array_typelem = get_element_type(context_actual_type);
|
||||
Oid array_typelem = get_element_type(context_actual_type);
|
||||
|
||||
if (!OidIsValid(array_typelem))
|
||||
ereport(ERROR,
|
||||
@@ -1038,13 +1054,13 @@ resolve_generic_type(Oid declared_type,
|
||||
else if (context_declared_type == ANYELEMENTOID)
|
||||
{
|
||||
/* Use the array type corresponding to actual type */
|
||||
Oid array_typeid = get_array_type(context_actual_type);
|
||||
Oid array_typeid = get_array_type(context_actual_type);
|
||||
|
||||
if (!OidIsValid(array_typeid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("could not find array type for datatype %s",
|
||||
format_type_be(context_actual_type))));
|
||||
errmsg("could not find array type for datatype %s",
|
||||
format_type_be(context_actual_type))));
|
||||
return array_typeid;
|
||||
}
|
||||
}
|
||||
@@ -1053,7 +1069,7 @@ resolve_generic_type(Oid declared_type,
|
||||
if (context_declared_type == ANYARRAYOID)
|
||||
{
|
||||
/* Use the element type corresponding to actual type */
|
||||
Oid array_typelem = get_element_type(context_actual_type);
|
||||
Oid array_typelem = get_element_type(context_actual_type);
|
||||
|
||||
if (!OidIsValid(array_typelem))
|
||||
ereport(ERROR,
|
||||
@@ -1207,8 +1223,8 @@ IsPreferredType(CATEGORY category, Oid type)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* This switch should agree with TypeCategory(), above. Note that
|
||||
* at this point, category certainly matches the type.
|
||||
* This switch should agree with TypeCategory(), above. Note that at
|
||||
* this point, category certainly matches the type.
|
||||
*/
|
||||
switch (category)
|
||||
{
|
||||
@@ -1279,8 +1295,8 @@ IsPreferredType(CATEGORY category, Oid type)
|
||||
* Check if srctype is binary-coercible to targettype.
|
||||
*
|
||||
* This notion allows us to cheat and directly exchange values without
|
||||
* going through the trouble of calling a conversion function. Note that
|
||||
* in general, this should only be an implementation shortcut. Before 7.4,
|
||||
* going through the trouble of calling a conversion function. Note that
|
||||
* in general, this should only be an implementation shortcut. Before 7.4,
|
||||
* this was also used as a heuristic for resolving overloaded functions and
|
||||
* operators, but that's basically a bad idea.
|
||||
*
|
||||
@@ -1293,7 +1309,7 @@ IsPreferredType(CATEGORY category, Oid type)
|
||||
* ANYARRAY type.
|
||||
*
|
||||
* This function replaces IsBinaryCompatible(), which was an inherently
|
||||
* symmetric test. Since the pg_cast entries aren't necessarily symmetric,
|
||||
* symmetric test. Since the pg_cast entries aren't necessarily symmetric,
|
||||
* the order of the operands is now significant.
|
||||
*/
|
||||
bool
|
||||
@@ -1415,16 +1431,16 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If there's no pg_cast entry, perhaps we are dealing with a
|
||||
* pair of array types. If so, and if the element types have
|
||||
* a suitable cast, use array_type_coerce().
|
||||
* If there's no pg_cast entry, perhaps we are dealing with a pair
|
||||
* of array types. If so, and if the element types have a
|
||||
* suitable cast, use array_type_coerce().
|
||||
*/
|
||||
Oid targetElemType;
|
||||
Oid sourceElemType;
|
||||
Oid elemfuncid;
|
||||
|
||||
if ((targetElemType = get_element_type(targetTypeId)) != InvalidOid &&
|
||||
(sourceElemType = get_element_type(sourceTypeId)) != InvalidOid)
|
||||
(sourceElemType = get_element_type(sourceTypeId)) != InvalidOid)
|
||||
{
|
||||
if (find_coercion_pathway(targetElemType, sourceElemType,
|
||||
ccontext, &elemfuncid))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.158 2003/07/28 00:09:15 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.159 2003/08/04 00:43:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -41,7 +41,7 @@ static int expr_depth_counter = 0;
|
||||
bool Transform_null_equals = false;
|
||||
|
||||
static Node *typecast_expression(ParseState *pstate, Node *expr,
|
||||
TypeName *typename);
|
||||
TypeName *typename);
|
||||
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
|
||||
static Node *transformIndirection(ParseState *pstate, Node *basenode,
|
||||
List *indirection);
|
||||
@@ -130,10 +130,10 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
toppstate = toppstate->parentParseState;
|
||||
|
||||
/* Check parameter number is in range */
|
||||
if (paramno <= 0) /* probably can't happen? */
|
||||
if (paramno <= 0) /* probably can't happen? */
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_PARAMETER),
|
||||
errmsg("there is no parameter $%d", paramno)));
|
||||
errmsg("there is no parameter $%d", paramno)));
|
||||
if (paramno > toppstate->p_numparams)
|
||||
{
|
||||
if (!toppstate->p_variableparams)
|
||||
@@ -152,20 +152,20 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
/* Zero out the previously-unreferenced slots */
|
||||
MemSet(toppstate->p_paramtypes + toppstate->p_numparams,
|
||||
0,
|
||||
(paramno - toppstate->p_numparams) * sizeof(Oid));
|
||||
(paramno - toppstate->p_numparams) * sizeof(Oid));
|
||||
toppstate->p_numparams = paramno;
|
||||
}
|
||||
if (toppstate->p_variableparams)
|
||||
{
|
||||
/* If not seen before, initialize to UNKNOWN type */
|
||||
if (toppstate->p_paramtypes[paramno-1] == InvalidOid)
|
||||
toppstate->p_paramtypes[paramno-1] = UNKNOWNOID;
|
||||
if (toppstate->p_paramtypes[paramno - 1] == InvalidOid)
|
||||
toppstate->p_paramtypes[paramno - 1] = UNKNOWNOID;
|
||||
}
|
||||
|
||||
param = makeNode(Param);
|
||||
param->paramkind = PARAM_NUM;
|
||||
param->paramid = (AttrNumber) paramno;
|
||||
param->paramtype = toppstate->p_paramtypes[paramno-1];
|
||||
param->paramtype = toppstate->p_paramtypes[paramno - 1];
|
||||
result = (Node *) param;
|
||||
|
||||
/* handle qualification, if any */
|
||||
@@ -254,9 +254,9 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
else
|
||||
{
|
||||
Node *lexpr = transformExpr(pstate,
|
||||
a->lexpr);
|
||||
a->lexpr);
|
||||
Node *rexpr = transformExpr(pstate,
|
||||
a->rexpr);
|
||||
a->rexpr);
|
||||
|
||||
result = (Node *) make_op(pstate,
|
||||
a->name,
|
||||
@@ -276,8 +276,8 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
rexpr = coerce_to_boolean(pstate, rexpr, "AND");
|
||||
|
||||
result = (Node *) makeBoolExpr(AND_EXPR,
|
||||
makeList2(lexpr,
|
||||
rexpr));
|
||||
makeList2(lexpr,
|
||||
rexpr));
|
||||
}
|
||||
break;
|
||||
case AEXPR_OR:
|
||||
@@ -291,8 +291,8 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
rexpr = coerce_to_boolean(pstate, rexpr, "OR");
|
||||
|
||||
result = (Node *) makeBoolExpr(OR_EXPR,
|
||||
makeList2(lexpr,
|
||||
rexpr));
|
||||
makeList2(lexpr,
|
||||
rexpr));
|
||||
}
|
||||
break;
|
||||
case AEXPR_NOT:
|
||||
@@ -303,7 +303,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
rexpr = coerce_to_boolean(pstate, rexpr, "NOT");
|
||||
|
||||
result = (Node *) makeBoolExpr(NOT_EXPR,
|
||||
makeList1(rexpr));
|
||||
makeList1(rexpr));
|
||||
}
|
||||
break;
|
||||
case AEXPR_OP_ANY:
|
||||
@@ -314,7 +314,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
a->rexpr);
|
||||
|
||||
result = (Node *) make_scalar_array_op(pstate,
|
||||
a->name,
|
||||
a->name,
|
||||
true,
|
||||
lexpr,
|
||||
rexpr);
|
||||
@@ -328,7 +328,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
a->rexpr);
|
||||
|
||||
result = (Node *) make_scalar_array_op(pstate,
|
||||
a->name,
|
||||
a->name,
|
||||
false,
|
||||
lexpr,
|
||||
rexpr);
|
||||
@@ -347,10 +347,12 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
rexpr);
|
||||
if (((OpExpr *) result)->opresulttype != BOOLOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("IS DISTINCT FROM requires = operator to yield boolean")));
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("IS DISTINCT FROM requires = operator to yield boolean")));
|
||||
|
||||
/*
|
||||
* We rely on DistinctExpr and OpExpr being same struct
|
||||
* We rely on DistinctExpr and OpExpr being
|
||||
* same struct
|
||||
*/
|
||||
NodeSetTag(result, T_DistinctExpr);
|
||||
}
|
||||
@@ -368,10 +370,12 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
rexpr);
|
||||
if (((OpExpr *) result)->opresulttype != BOOLOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("NULLIF requires = operator to yield boolean")));
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("NULLIF requires = operator to yield boolean")));
|
||||
|
||||
/*
|
||||
* We rely on NullIfExpr and OpExpr being same struct
|
||||
* We rely on NullIfExpr and OpExpr being same
|
||||
* struct
|
||||
*/
|
||||
NodeSetTag(result, T_NullIfExpr);
|
||||
}
|
||||
@@ -425,8 +429,8 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
List *args;
|
||||
|
||||
/*
|
||||
* Transform the list of arguments. We use a shallow
|
||||
* list copy and then transform-in-place to avoid O(N^2)
|
||||
* Transform the list of arguments. We use a shallow list
|
||||
* copy and then transform-in-place to avoid O(N^2)
|
||||
* behavior from repeated lappend's.
|
||||
*/
|
||||
targs = listCopy(fn->args);
|
||||
@@ -489,7 +493,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
((TargetEntry *) lfirst(tlist))->resdom->resjunk)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("sub-select must return a column")));
|
||||
errmsg("sub-select must return a column")));
|
||||
while ((tlist = lnext(tlist)) != NIL)
|
||||
{
|
||||
if (!((TargetEntry *) lfirst(tlist))->resdom->resjunk)
|
||||
@@ -499,8 +503,9 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
}
|
||||
|
||||
/*
|
||||
* EXPR and ARRAY need no lefthand or combining operator.
|
||||
* These fields should be NIL already, but make sure.
|
||||
* EXPR and ARRAY need no lefthand or combining
|
||||
* operator. These fields should be NIL already, but
|
||||
* make sure.
|
||||
*/
|
||||
sublink->lefthand = NIL;
|
||||
sublink->operName = NIL;
|
||||
@@ -523,9 +528,10 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
lfirst(elist) = transformExpr(pstate, lfirst(elist));
|
||||
|
||||
/*
|
||||
* If the expression is "<> ALL" (with unqualified opname)
|
||||
* then convert it to "NOT IN". This is a hack to improve
|
||||
* efficiency of expressions output by pre-7.4 Postgres.
|
||||
* If the expression is "<> ALL" (with unqualified
|
||||
* opname) then convert it to "NOT IN". This is a
|
||||
* hack to improve efficiency of expressions output by
|
||||
* pre-7.4 Postgres.
|
||||
*/
|
||||
if (sublink->subLinkType == ALL_SUBLINK &&
|
||||
length(op) == 1 && strcmp(opname, "<>") == 0)
|
||||
@@ -549,14 +555,14 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
strcmp(opname, "<>") != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("row comparison cannot use operator %s",
|
||||
opname)));
|
||||
errmsg("row comparison cannot use operator %s",
|
||||
opname)));
|
||||
|
||||
/*
|
||||
* To build the list of combining operator OIDs, we must
|
||||
* scan subquery's targetlist to find values that will
|
||||
* be matched against lefthand values. We need to
|
||||
* ignore resjunk targets, so doing the outer
|
||||
* To build the list of combining operator OIDs, we
|
||||
* must scan subquery's targetlist to find values that
|
||||
* will be matched against lefthand values. We need
|
||||
* to ignore resjunk targets, so doing the outer
|
||||
* iteration over right_list is easier than doing it
|
||||
* over left_list.
|
||||
*/
|
||||
@@ -576,7 +582,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
if (left_list == NIL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("sub-select has too many columns")));
|
||||
errmsg("sub-select has too many columns")));
|
||||
lexpr = lfirst(left_list);
|
||||
left_list = lnext(left_list);
|
||||
|
||||
@@ -596,14 +602,14 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("operator %s must return boolean, not type %s",
|
||||
opname,
|
||||
format_type_be(opform->oprresult)),
|
||||
format_type_be(opform->oprresult)),
|
||||
errhint("The operator of a quantified predicate subquery must return boolean.")));
|
||||
|
||||
if (get_func_retset(opform->oprcode))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("operator %s must not return a set",
|
||||
opname),
|
||||
errmsg("operator %s must not return a set",
|
||||
opname),
|
||||
errhint("The operator of a quantified predicate subquery must return boolean.")));
|
||||
|
||||
sublink->operOids = lappendo(sublink->operOids,
|
||||
@@ -614,7 +620,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
if (left_list != NIL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("sub-select has too few columns")));
|
||||
errmsg("sub-select has too few columns")));
|
||||
|
||||
if (needNot)
|
||||
{
|
||||
@@ -657,7 +663,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
neww->expr = (Expr *) transformExpr(pstate, warg);
|
||||
|
||||
neww->expr = (Expr *) coerce_to_boolean(pstate,
|
||||
(Node *) neww->expr,
|
||||
(Node *) neww->expr,
|
||||
"CASE/WHEN");
|
||||
|
||||
/*
|
||||
@@ -747,8 +753,8 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
/* Transform the element expressions */
|
||||
foreach(element, a->elements)
|
||||
{
|
||||
Node *e = (Node *) lfirst(element);
|
||||
Node *newe;
|
||||
Node *e = (Node *) lfirst(element);
|
||||
Node *newe;
|
||||
|
||||
newe = transformExpr(pstate, e);
|
||||
newelems = lappend(newelems, newe);
|
||||
@@ -761,8 +767,8 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
/* Coerce arguments to common type if necessary */
|
||||
foreach(element, newelems)
|
||||
{
|
||||
Node *e = (Node *) lfirst(element);
|
||||
Node *newe;
|
||||
Node *e = (Node *) lfirst(element);
|
||||
Node *newe;
|
||||
|
||||
newe = coerce_to_common_type(pstate, e,
|
||||
element_type,
|
||||
@@ -837,15 +843,15 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
{
|
||||
CoalesceExpr *c = (CoalesceExpr *) expr;
|
||||
CoalesceExpr *newc = makeNode(CoalesceExpr);
|
||||
List *newargs = NIL;
|
||||
List *newcoercedargs = NIL;
|
||||
List *typeids = NIL;
|
||||
List *args;
|
||||
List *newargs = NIL;
|
||||
List *newcoercedargs = NIL;
|
||||
List *typeids = NIL;
|
||||
List *args;
|
||||
|
||||
foreach(args, c->args)
|
||||
{
|
||||
Node *e = (Node *) lfirst(args);
|
||||
Node *newe;
|
||||
Node *e = (Node *) lfirst(args);
|
||||
Node *newe;
|
||||
|
||||
newe = transformExpr(pstate, e);
|
||||
newargs = lappend(newargs, newe);
|
||||
@@ -857,8 +863,8 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
/* Convert arguments if necessary */
|
||||
foreach(args, newargs)
|
||||
{
|
||||
Node *e = (Node *) lfirst(args);
|
||||
Node *newe;
|
||||
Node *e = (Node *) lfirst(args);
|
||||
Node *newe;
|
||||
|
||||
newe = coerce_to_common_type(pstate, e,
|
||||
newc->coalescetype,
|
||||
@@ -1026,9 +1032,9 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
|
||||
* Not known as a column of any range-table entry.
|
||||
*
|
||||
* Consider the possibility that it's VALUE in a domain
|
||||
* check expression. (We handle VALUE as a name, not a
|
||||
* keyword, to avoid breaking a lot of applications that
|
||||
* have used VALUE as a column name in the past.)
|
||||
* check expression. (We handle VALUE as a name, not
|
||||
* a keyword, to avoid breaking a lot of applications
|
||||
* that have used VALUE as a column name in the past.)
|
||||
*/
|
||||
if (pstate->p_value_substitute != NULL &&
|
||||
strcmp(name, "value") == 0)
|
||||
@@ -1059,7 +1065,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("attribute \"%s\" not found", name)));
|
||||
errmsg("attribute \"%s\" not found", name)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1175,8 +1181,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
|
||||
default:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("improper qualified name (too many dotted names): %s",
|
||||
NameListToString(cref->fields))));
|
||||
errmsg("improper qualified name (too many dotted names): %s",
|
||||
NameListToString(cref->fields))));
|
||||
node = NULL; /* keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
@@ -1246,14 +1252,15 @@ exprType(Node *expr)
|
||||
Assert(!tent->resdom->resjunk);
|
||||
if (sublink->subLinkType == EXPR_SUBLINK)
|
||||
type = tent->resdom->restype;
|
||||
else /* ARRAY_SUBLINK */
|
||||
else
|
||||
/* ARRAY_SUBLINK */
|
||||
{
|
||||
type = get_array_type(tent->resdom->restype);
|
||||
if (!OidIsValid(type))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("could not find array type for datatype %s",
|
||||
format_type_be(tent->resdom->restype))));
|
||||
format_type_be(tent->resdom->restype))));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1266,9 +1273,10 @@ exprType(Node *expr)
|
||||
case T_SubPlan:
|
||||
{
|
||||
/*
|
||||
* Although the parser does not ever deal with already-planned
|
||||
* expression trees, we support SubPlan nodes in this routine
|
||||
* for the convenience of ruleutils.c.
|
||||
* Although the parser does not ever deal with
|
||||
* already-planned expression trees, we support SubPlan
|
||||
* nodes in this routine for the convenience of
|
||||
* ruleutils.c.
|
||||
*/
|
||||
SubPlan *subplan = (SubPlan *) expr;
|
||||
|
||||
@@ -1283,14 +1291,15 @@ exprType(Node *expr)
|
||||
Assert(!tent->resdom->resjunk);
|
||||
if (subplan->subLinkType == EXPR_SUBLINK)
|
||||
type = tent->resdom->restype;
|
||||
else /* ARRAY_SUBLINK */
|
||||
else
|
||||
/* ARRAY_SUBLINK */
|
||||
{
|
||||
type = get_array_type(tent->resdom->restype);
|
||||
if (!OidIsValid(type))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("could not find array type for datatype %s",
|
||||
format_type_be(tent->resdom->restype))));
|
||||
format_type_be(tent->resdom->restype))));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1337,9 +1346,10 @@ exprType(Node *expr)
|
||||
type = ((SetToDefault *) expr)->typeId;
|
||||
break;
|
||||
case T_RangeVar:
|
||||
|
||||
/*
|
||||
* If someone uses a bare relation name in an expression,
|
||||
* we will likely first notice a problem here (see comments in
|
||||
* If someone uses a bare relation name in an expression, we
|
||||
* will likely first notice a problem here (see comments in
|
||||
* transformColumnRef()). Issue an appropriate error message.
|
||||
*/
|
||||
ereport(ERROR,
|
||||
@@ -1438,14 +1448,14 @@ exprTypmod(Node *expr)
|
||||
* that typmod, else use -1
|
||||
*/
|
||||
CoalesceExpr *cexpr = (CoalesceExpr *) expr;
|
||||
Oid coalescetype = cexpr->coalescetype;
|
||||
int32 typmod;
|
||||
List *arg;
|
||||
Oid coalescetype = cexpr->coalescetype;
|
||||
int32 typmod;
|
||||
List *arg;
|
||||
|
||||
typmod = exprTypmod((Node *) lfirst(cexpr->args));
|
||||
foreach(arg, cexpr->args)
|
||||
{
|
||||
Node *e = (Node *) lfirst(arg);
|
||||
Node *e = (Node *) lfirst(arg);
|
||||
|
||||
if (exprType(e) != coalescetype)
|
||||
return -1;
|
||||
@@ -1505,9 +1515,9 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If it's not a two-argument or three-argument function with the second
|
||||
* argument being an int4 constant, it can't have been created from a
|
||||
* length coercion (it must be a type coercion, instead).
|
||||
* If it's not a two-argument or three-argument function with the
|
||||
* second argument being an int4 constant, it can't have been created
|
||||
* from a length coercion (it must be a type coercion, instead).
|
||||
*/
|
||||
nargs = length(func->args);
|
||||
if (nargs < 2 || nargs > 3)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.157 2003/07/28 00:09:15 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.158 2003/08/04 00:43:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -86,8 +86,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
if (nargs > FUNC_MAX_ARGS)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
|
||||
errmsg("cannot pass more than %d arguments to a function",
|
||||
FUNC_MAX_ARGS)));
|
||||
errmsg("cannot pass more than %d arguments to a function",
|
||||
FUNC_MAX_ARGS)));
|
||||
|
||||
if (fargs)
|
||||
{
|
||||
@@ -262,9 +262,9 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
if (agg_star)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("%s(*) specified, but %s is not an aggregate function",
|
||||
NameListToString(funcname),
|
||||
NameListToString(funcname))));
|
||||
errmsg("%s(*) specified, but %s is not an aggregate function",
|
||||
NameListToString(funcname),
|
||||
NameListToString(funcname))));
|
||||
if (agg_distinct)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
@@ -298,8 +298,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("attribute \"%s\" not found in datatype %s",
|
||||
colname, format_type_be(relTypeId))));
|
||||
errmsg("attribute \"%s\" not found in datatype %s",
|
||||
colname, format_type_be(relTypeId))));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -311,8 +311,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
errmsg("function %s is not unique",
|
||||
func_signature_string(funcname, nargs,
|
||||
actual_arg_types)),
|
||||
errhint("Could not choose a best candidate function. "
|
||||
"You may need to add explicit typecasts.")));
|
||||
errhint("Could not choose a best candidate function. "
|
||||
"You may need to add explicit typecasts.")));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
@@ -392,7 +392,7 @@ int
|
||||
func_match_argtypes(int nargs,
|
||||
Oid *input_typeids,
|
||||
FuncCandidateList raw_candidates,
|
||||
FuncCandidateList *candidates) /* return value */
|
||||
FuncCandidateList *candidates) /* return value */
|
||||
{
|
||||
FuncCandidateList current_candidate;
|
||||
FuncCandidateList next_candidate;
|
||||
@@ -495,12 +495,13 @@ func_select_candidate(int nargs,
|
||||
/*
|
||||
* If any input types are domains, reduce them to their base types.
|
||||
* This ensures that we will consider functions on the base type to be
|
||||
* "exact matches" in the exact-match heuristic; it also makes it possible
|
||||
* to do something useful with the type-category heuristics. Note that
|
||||
* this makes it difficult, but not impossible, to use functions declared
|
||||
* to take a domain as an input datatype. Such a function will be
|
||||
* selected over the base-type function only if it is an exact match at
|
||||
* all argument positions, and so was already chosen by our caller.
|
||||
* "exact matches" in the exact-match heuristic; it also makes it
|
||||
* possible to do something useful with the type-category heuristics.
|
||||
* Note that this makes it difficult, but not impossible, to use
|
||||
* functions declared to take a domain as an input datatype. Such a
|
||||
* function will be selected over the base-type function only if it is
|
||||
* an exact match at all argument positions, and so was already chosen
|
||||
* by our caller.
|
||||
*/
|
||||
for (i = 0; i < nargs; i++)
|
||||
input_base_typeids[i] = getBaseType(input_typeids[i]);
|
||||
@@ -550,13 +551,14 @@ func_select_candidate(int nargs,
|
||||
return candidates;
|
||||
|
||||
/*
|
||||
* Still too many candidates? Now look for candidates which have either
|
||||
* exact matches or preferred types at the args that will require coercion.
|
||||
* (Restriction added in 7.4: preferred type must be of same category as
|
||||
* input type; give no preference to cross-category conversions to
|
||||
* preferred types.) Keep all candidates if none match.
|
||||
* Still too many candidates? Now look for candidates which have
|
||||
* either exact matches or preferred types at the args that will
|
||||
* require coercion. (Restriction added in 7.4: preferred type must be
|
||||
* of same category as input type; give no preference to
|
||||
* cross-category conversions to preferred types.) Keep all
|
||||
* candidates if none match.
|
||||
*/
|
||||
for (i = 0; i < nargs; i++) /* avoid multiple lookups */
|
||||
for (i = 0; i < nargs; i++) /* avoid multiple lookups */
|
||||
slot_category[i] = TypeCategory(input_base_typeids[i]);
|
||||
ncandidates = 0;
|
||||
nbestMatch = 0;
|
||||
@@ -602,10 +604,11 @@ func_select_candidate(int nargs,
|
||||
* Still too many candidates? Try assigning types for the unknown
|
||||
* columns.
|
||||
*
|
||||
* NOTE: for a binary operator with one unknown and one non-unknown input,
|
||||
* we already tried the heuristic of looking for a candidate with the
|
||||
* known input type on both sides (see binary_oper_exact()). That's
|
||||
* essentially a special case of the general algorithm we try next.
|
||||
* NOTE: for a binary operator with one unknown and one non-unknown
|
||||
* input, we already tried the heuristic of looking for a candidate
|
||||
* with the known input type on both sides (see binary_oper_exact()).
|
||||
* That's essentially a special case of the general algorithm we try
|
||||
* next.
|
||||
*
|
||||
* We do this by examining each unknown argument position to see if we
|
||||
* can determine a "type category" for it. If any candidate has an
|
||||
@@ -815,9 +818,10 @@ func_get_detail(List *funcname,
|
||||
* constant to a specific type.
|
||||
*
|
||||
* The reason we can restrict our check to binary-compatible
|
||||
* coercions here is that we expect non-binary-compatible coercions
|
||||
* to have an implementation function named after the target type.
|
||||
* That function will be found by normal lookup if appropriate.
|
||||
* coercions here is that we expect non-binary-compatible
|
||||
* coercions to have an implementation function named after the
|
||||
* target type. That function will be found by normal lookup if
|
||||
* appropriate.
|
||||
*
|
||||
* NB: it's important that this code stays in sync with what
|
||||
* coerce_type can do, because the caller will try to apply
|
||||
@@ -895,7 +899,7 @@ func_get_detail(List *funcname,
|
||||
{
|
||||
best_candidate = func_select_candidate(nargs,
|
||||
current_input_typeids,
|
||||
current_candidates);
|
||||
current_candidates);
|
||||
|
||||
/*
|
||||
* If we were able to choose a best candidate, we're
|
||||
@@ -960,7 +964,7 @@ func_get_detail(List *funcname,
|
||||
* finding all superclasses of that type. A vector of new Oid type
|
||||
* arrays is returned to the caller, listing possible alternative
|
||||
* interpretations of the input typeids as members of their superclasses
|
||||
* rather than the actually given argument types. The vector is
|
||||
* rather than the actually given argument types. The vector is
|
||||
* terminated by a NULL pointer.
|
||||
*
|
||||
* The order of this vector is as follows: all superclasses of the
|
||||
@@ -1123,14 +1127,14 @@ gen_cross_product(InhPaths *arginh, int nargs)
|
||||
/*
|
||||
* We also need an extra slot for the terminating NULL in the result
|
||||
* array, but that cancels out with the fact that we don't want to
|
||||
* generate the zero-changes case. So we need exactly nanswers slots.
|
||||
* generate the zero-changes case. So we need exactly nanswers slots.
|
||||
*/
|
||||
result = (Oid **) palloc(sizeof(Oid *) * nanswers);
|
||||
j = 0;
|
||||
|
||||
/*
|
||||
* Compute the cross product from right to left. When cur[i] == 0,
|
||||
* generate the original input type at position i. When cur[i] == k
|
||||
* generate the original input type at position i. When cur[i] == k
|
||||
* for k > 0, generate its k'th supertype.
|
||||
*/
|
||||
MemSet(cur, 0, sizeof(cur));
|
||||
@@ -1138,7 +1142,7 @@ gen_cross_product(InhPaths *arginh, int nargs)
|
||||
for (;;)
|
||||
{
|
||||
/*
|
||||
* Find a column we can increment. All the columns after it get
|
||||
* Find a column we can increment. All the columns after it get
|
||||
* reset to zero. (Essentially, we're adding one to the multi-
|
||||
* digit number represented by cur[].)
|
||||
*/
|
||||
@@ -1263,8 +1267,8 @@ setup_field_select(Node *input, char *attname, Oid relid)
|
||||
if (attno == InvalidAttrNumber)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("attribute \"%s\" of relation \"%s\" does not exist",
|
||||
attname, get_rel_name(relid))));
|
||||
errmsg("attribute \"%s\" of relation \"%s\" does not exist",
|
||||
attname, get_rel_name(relid))));
|
||||
|
||||
fselect->arg = (Expr *) input;
|
||||
fselect->fieldnum = attno;
|
||||
@@ -1448,7 +1452,7 @@ find_aggregate_func(List *aggname, Oid basetype, bool noError)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("function %s(%s) is not an aggregate",
|
||||
NameListToString(aggname), format_type_be(basetype))));
|
||||
NameListToString(aggname), format_type_be(basetype))));
|
||||
}
|
||||
|
||||
ReleaseSysCache(ftup);
|
||||
@@ -1485,7 +1489,7 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("function %s does not exist",
|
||||
func_signature_string(funcname, nargs, argtypes))));
|
||||
func_signature_string(funcname, nargs, argtypes))));
|
||||
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.79 2003/07/19 20:20:52 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.80 2003/08/04 00:43:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -121,8 +121,8 @@ transformArraySubscripts(ParseState *pstate,
|
||||
if (elementType == InvalidOid)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("cannot subscript type %s because it is not an array",
|
||||
format_type_be(arrayType))));
|
||||
errmsg("cannot subscript type %s because it is not an array",
|
||||
format_type_be(arrayType))));
|
||||
|
||||
/*
|
||||
* A list containing only single subscripts refers to a single array
|
||||
@@ -173,14 +173,14 @@ transformArraySubscripts(ParseState *pstate,
|
||||
subexpr = transformExpr(pstate, ai->lidx);
|
||||
/* If it's not int4 already, try to coerce */
|
||||
subexpr = coerce_to_target_type(pstate,
|
||||
subexpr, exprType(subexpr),
|
||||
subexpr, exprType(subexpr),
|
||||
INT4OID, -1,
|
||||
COERCION_ASSIGNMENT,
|
||||
COERCE_IMPLICIT_CAST);
|
||||
if (subexpr == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("array subscript must have type integer")));
|
||||
errmsg("array subscript must have type integer")));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.71 2003/07/28 00:09:15 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.72 2003/08/04 00:43:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -31,13 +31,13 @@
|
||||
static Oid binary_oper_exact(Oid arg1, Oid arg2,
|
||||
FuncCandidateList candidates);
|
||||
static FuncDetailCode oper_select_candidate(int nargs,
|
||||
Oid *input_typeids,
|
||||
FuncCandidateList candidates,
|
||||
Oid *operOid);
|
||||
Oid *input_typeids,
|
||||
FuncCandidateList candidates,
|
||||
Oid *operOid);
|
||||
static const char *op_signature_string(List *op, char oprkind,
|
||||
Oid arg1, Oid arg2);
|
||||
Oid arg1, Oid arg2);
|
||||
static void op_error(List *op, char oprkind, Oid arg1, Oid arg2,
|
||||
FuncDetailCode fdresult);
|
||||
FuncDetailCode fdresult);
|
||||
|
||||
|
||||
/*
|
||||
@@ -140,9 +140,9 @@ equality_oper(Oid argtype, bool noError)
|
||||
|
||||
/*
|
||||
* If the datatype is an array, then we can use array_eq ... but only
|
||||
* if there is a suitable equality operator for the element type.
|
||||
* (We must run this test first, since compatible_oper will find
|
||||
* array_eq, but would not notice the lack of an element operator.)
|
||||
* if there is a suitable equality operator for the element type. (We
|
||||
* must run this test first, since compatible_oper will find array_eq,
|
||||
* but would not notice the lack of an element operator.)
|
||||
*/
|
||||
elem_type = get_element_type(argtype);
|
||||
if (OidIsValid(elem_type))
|
||||
@@ -184,8 +184,8 @@ equality_oper(Oid argtype, bool noError)
|
||||
if (!noError)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("could not identify an equality operator for type %s",
|
||||
format_type_be(argtype))));
|
||||
errmsg("could not identify an equality operator for type %s",
|
||||
format_type_be(argtype))));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -202,10 +202,10 @@ ordering_oper(Oid argtype, bool noError)
|
||||
|
||||
/*
|
||||
* If the datatype is an array, then we can use array_lt ... but only
|
||||
* if there is a suitable ordering operator for the element type.
|
||||
* (We must run this test first, since the code below would find
|
||||
* array_lt if there's an element = operator, but would not notice the
|
||||
* lack of an element < operator.)
|
||||
* if there is a suitable ordering operator for the element type. (We
|
||||
* must run this test first, since the code below would find array_lt
|
||||
* if there's an element = operator, but would not notice the lack of
|
||||
* an element < operator.)
|
||||
*/
|
||||
elem_type = get_element_type(argtype);
|
||||
if (OidIsValid(elem_type))
|
||||
@@ -222,15 +222,15 @@ ordering_oper(Oid argtype, bool noError)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Find the type's equality operator, and use its lsortop (it *must*
|
||||
* be mergejoinable). We use this definition because for sorting and
|
||||
* grouping purposes, it's important that the equality and ordering
|
||||
* operators are consistent.
|
||||
* Find the type's equality operator, and use its lsortop (it
|
||||
* *must* be mergejoinable). We use this definition because for
|
||||
* sorting and grouping purposes, it's important that the equality
|
||||
* and ordering operators are consistent.
|
||||
*/
|
||||
optup = equality_oper(argtype, noError);
|
||||
if (optup != NULL)
|
||||
{
|
||||
Oid lsortop;
|
||||
Oid lsortop;
|
||||
|
||||
lsortop = ((Form_pg_operator) GETSTRUCT(optup))->oprlsortop;
|
||||
ReleaseSysCache(optup);
|
||||
@@ -247,8 +247,8 @@ ordering_oper(Oid argtype, bool noError)
|
||||
if (!noError)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("could not identify an ordering operator for type %s",
|
||||
format_type_be(argtype)),
|
||||
errmsg("could not identify an ordering operator for type %s",
|
||||
format_type_be(argtype)),
|
||||
errhint("Use an explicit ordering operator or modify the query.")));
|
||||
return NULL;
|
||||
}
|
||||
@@ -361,13 +361,13 @@ static FuncDetailCode
|
||||
oper_select_candidate(int nargs,
|
||||
Oid *input_typeids,
|
||||
FuncCandidateList candidates,
|
||||
Oid *operOid) /* output argument */
|
||||
Oid *operOid) /* output argument */
|
||||
{
|
||||
int ncandidates;
|
||||
|
||||
/*
|
||||
* Delete any candidates that cannot actually accept the given
|
||||
* input types, whether directly or by coercion.
|
||||
* Delete any candidates that cannot actually accept the given input
|
||||
* types, whether directly or by coercion.
|
||||
*/
|
||||
ncandidates = func_match_argtypes(nargs, input_typeids,
|
||||
candidates, &candidates);
|
||||
@@ -385,8 +385,8 @@ oper_select_candidate(int nargs,
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the same heuristics as for ambiguous functions to resolve
|
||||
* the conflict.
|
||||
* Use the same heuristics as for ambiguous functions to resolve the
|
||||
* conflict.
|
||||
*/
|
||||
candidates = func_select_candidate(nargs, input_typeids, candidates);
|
||||
|
||||
@@ -397,7 +397,7 @@ oper_select_candidate(int nargs,
|
||||
}
|
||||
|
||||
*operOid = InvalidOid;
|
||||
return FUNCDETAIL_MULTIPLE; /* failed to select a best candidate */
|
||||
return FUNCDETAIL_MULTIPLE; /* failed to select a best candidate */
|
||||
}
|
||||
|
||||
|
||||
@@ -772,6 +772,7 @@ make_scalar_array_op(ParseState *pstate, List *opname,
|
||||
|
||||
ltypeId = exprType(ltree);
|
||||
atypeId = exprType(rtree);
|
||||
|
||||
/*
|
||||
* The right-hand input of the operator will be the element type of
|
||||
* the array. However, if we currently have just an untyped literal
|
||||
@@ -785,7 +786,7 @@ make_scalar_array_op(ParseState *pstate, List *opname,
|
||||
if (!OidIsValid(rtypeId))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("op ANY/ALL (array) requires array on right side")));
|
||||
errmsg("op ANY/ALL (array) requires array on right side")));
|
||||
}
|
||||
|
||||
/* Now resolve the operator */
|
||||
@@ -814,15 +815,15 @@ make_scalar_array_op(ParseState *pstate, List *opname,
|
||||
if (rettype != BOOLOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("op ANY/ALL (array) requires operator to yield boolean")));
|
||||
errmsg("op ANY/ALL (array) requires operator to yield boolean")));
|
||||
if (get_func_retset(opform->oprcode))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("op ANY/ALL (array) requires operator not to return a set")));
|
||||
|
||||
/*
|
||||
* Now switch back to the array type on the right, arranging for
|
||||
* any needed cast to be applied.
|
||||
* Now switch back to the array type on the right, arranging for any
|
||||
* needed cast to be applied.
|
||||
*/
|
||||
res_atypeId = get_array_type(declared_arg_types[1]);
|
||||
if (!OidIsValid(res_atypeId))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.85 2003/07/20 21:56:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.86 2003/08/04 00:43:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "utils/syscache.h"
|
||||
|
||||
/* GUC parameter */
|
||||
bool add_missing_from;
|
||||
bool add_missing_from;
|
||||
|
||||
static Node *scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
|
||||
const char *refname);
|
||||
@@ -365,8 +365,8 @@ scanNameSpaceForConflict(ParseState *pstate, Node *nsnode,
|
||||
if (strcmp(j->alias->aliasname, aliasname1) == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_ALIAS),
|
||||
errmsg("table name \"%s\" specified more than once",
|
||||
aliasname1)));
|
||||
errmsg("table name \"%s\" specified more than once",
|
||||
aliasname1)));
|
||||
|
||||
/*
|
||||
* Tables within an aliased join are invisible from outside
|
||||
@@ -570,8 +570,8 @@ colnameToVar(ParseState *pstate, char *colname)
|
||||
if (result)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_AMBIGUOUS_COLUMN),
|
||||
errmsg("column reference \"%s\" is ambiguous",
|
||||
colname)));
|
||||
errmsg("column reference \"%s\" is ambiguous",
|
||||
colname)));
|
||||
result = newresult;
|
||||
}
|
||||
}
|
||||
@@ -666,7 +666,7 @@ addRangeTableEntry(ParseState *pstate,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
errmsg("table \"%s\" has %d columns available but %d columns specified",
|
||||
RelationGetRelationName(rel), maxattrs, numaliases)));
|
||||
RelationGetRelationName(rel), maxattrs, numaliases)));
|
||||
|
||||
/* fill in any unspecified alias columns using actual column names */
|
||||
for (varattno = numaliases; varattno < maxattrs; varattno++)
|
||||
@@ -761,7 +761,7 @@ addRangeTableEntryForRelation(ParseState *pstate,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
errmsg("table \"%s\" has %d columns available but %d columns specified",
|
||||
RelationGetRelationName(rel), maxattrs, numaliases)));
|
||||
RelationGetRelationName(rel), maxattrs, numaliases)));
|
||||
|
||||
/* fill in any unspecified alias columns using actual column names */
|
||||
for (varattno = numaliases; varattno < maxattrs; varattno++)
|
||||
@@ -957,7 +957,8 @@ addRangeTableEntryForFunction(ParseState *pstate,
|
||||
Relation rel;
|
||||
int maxattrs;
|
||||
|
||||
if (!OidIsValid(funcrelid)) /* shouldn't happen if typtype is 'c' */
|
||||
if (!OidIsValid(funcrelid)) /* shouldn't happen if typtype is
|
||||
* 'c' */
|
||||
elog(ERROR, "invalid typrelid for complex type %u", funcrettype);
|
||||
|
||||
/*
|
||||
@@ -1003,8 +1004,8 @@ addRangeTableEntryForFunction(ParseState *pstate,
|
||||
if (numaliases > 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
errmsg("too many column aliases specified for function %s",
|
||||
funcname)));
|
||||
errmsg("too many column aliases specified for function %s",
|
||||
funcname)));
|
||||
if (numaliases == 0)
|
||||
eref->colnames = makeList1(makeString(eref->aliasname));
|
||||
}
|
||||
@@ -1026,8 +1027,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",
|
||||
funcname)));
|
||||
|
||||
/*----------
|
||||
* Flags:
|
||||
@@ -1318,7 +1319,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
|
||||
int maxattrs;
|
||||
int numaliases;
|
||||
|
||||
if (!OidIsValid(funcrelid)) /* shouldn't happen */
|
||||
if (!OidIsValid(funcrelid)) /* shouldn't happen */
|
||||
elog(ERROR, "invalid typrelid for complex type %u",
|
||||
funcrettype);
|
||||
|
||||
@@ -1575,7 +1576,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
ObjectIdGetDatum(rte->relid),
|
||||
Int16GetDatum(attnum),
|
||||
0, 0);
|
||||
if (!HeapTupleIsValid(tp)) /* shouldn't happen */
|
||||
if (!HeapTupleIsValid(tp)) /* shouldn't happen */
|
||||
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
|
||||
attnum, rte->relid);
|
||||
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
|
||||
@@ -1632,7 +1633,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
HeapTuple tp;
|
||||
Form_pg_attribute att_tup;
|
||||
|
||||
if (!OidIsValid(funcrelid)) /* shouldn't happen */
|
||||
if (!OidIsValid(funcrelid)) /* shouldn't happen */
|
||||
elog(ERROR, "invalid typrelid for complex type %u",
|
||||
funcrettype);
|
||||
|
||||
@@ -1640,7 +1641,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
ObjectIdGetDatum(funcrelid),
|
||||
Int16GetDatum(attnum),
|
||||
0, 0);
|
||||
if (!HeapTupleIsValid(tp)) /* shouldn't happen */
|
||||
if (!HeapTupleIsValid(tp)) /* shouldn't happen */
|
||||
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
|
||||
attnum, funcrelid);
|
||||
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
|
||||
@@ -1720,7 +1721,7 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
|
||||
ObjectIdGetDatum(rte->relid),
|
||||
Int16GetDatum(attnum),
|
||||
0, 0);
|
||||
if (!HeapTupleIsValid(tp)) /* shouldn't happen */
|
||||
if (!HeapTupleIsValid(tp)) /* shouldn't happen */
|
||||
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
|
||||
attnum, rte->relid);
|
||||
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
|
||||
@@ -1752,7 +1753,7 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
|
||||
ObjectIdGetDatum(funcrelid),
|
||||
Int16GetDatum(attnum),
|
||||
0, 0);
|
||||
if (!HeapTupleIsValid(tp)) /* shouldn't happen */
|
||||
if (!HeapTupleIsValid(tp)) /* shouldn't happen */
|
||||
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
|
||||
attnum, funcrelid);
|
||||
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
|
||||
@@ -1927,7 +1928,7 @@ warnAutoRange(ParseState *pstate, RangeVar *relation)
|
||||
else
|
||||
ereport(NOTICE,
|
||||
(errcode(ERRCODE_UNDEFINED_TABLE),
|
||||
errmsg("adding missing FROM-clause entry for table \"%s\"",
|
||||
relation->relname)));
|
||||
errmsg("adding missing FROM-clause entry for table \"%s\"",
|
||||
relation->relname)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.108 2003/07/28 00:09:15 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.109 2003/08/04 00:43:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -66,7 +66,7 @@ transformTargetEntry(ParseState *pstate,
|
||||
errmsg("relation reference \"%s\" cannot be used as a targetlist entry",
|
||||
((RangeVar *) expr)->relname),
|
||||
errhint("Write \"%s\".* to denote all the columns of the relation.",
|
||||
((RangeVar *) expr)->relname)));
|
||||
((RangeVar *) expr)->relname)));
|
||||
|
||||
type_id = exprType(expr);
|
||||
type_mod = exprTypmod(expr);
|
||||
@@ -152,8 +152,8 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
*/
|
||||
if (strcmp(name1, get_database_name(MyDatabaseId)) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cross-database references are not implemented")));
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cross-database references are not implemented")));
|
||||
schemaname = strVal(lsecond(fields));
|
||||
relname = strVal(lthird(fields));
|
||||
break;
|
||||
@@ -286,7 +286,7 @@ markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var)
|
||||
case RTE_JOIN:
|
||||
{
|
||||
/* Join RTE --- recursively inspect the alias variable */
|
||||
Var *aliasvar;
|
||||
Var *aliasvar;
|
||||
|
||||
Assert(attnum > 0 && attnum <= length(rte->joinaliasvars));
|
||||
aliasvar = (Var *) nth(attnum - 1, rte->joinaliasvars);
|
||||
@@ -322,7 +322,7 @@ updateTargetListEntry(ParseState *pstate,
|
||||
int attrno,
|
||||
List *indirection)
|
||||
{
|
||||
Oid type_id; /* type of value provided */
|
||||
Oid type_id; /* type of value provided */
|
||||
Oid attrtype; /* type of target column */
|
||||
int32 attrtypmod;
|
||||
Resdom *resnode = tle->resdom;
|
||||
@@ -341,13 +341,13 @@ updateTargetListEntry(ParseState *pstate,
|
||||
* If the expression is a DEFAULT placeholder, insert the attribute's
|
||||
* type/typmod into it so that exprType will report the right things.
|
||||
* (We expect that the eventually substituted default expression will
|
||||
* in fact have this type and typmod.) Also, reject trying to update
|
||||
* in fact have this type and typmod.) Also, reject trying to update
|
||||
* an array element with DEFAULT, since there can't be any default for
|
||||
* individual elements of a column.
|
||||
*/
|
||||
if (tle->expr && IsA(tle->expr, SetToDefault))
|
||||
{
|
||||
SetToDefault *def = (SetToDefault *) tle->expr;
|
||||
SetToDefault *def = (SetToDefault *) tle->expr;
|
||||
|
||||
def->typeId = attrtype;
|
||||
def->typeMod = attrtypmod;
|
||||
@@ -496,8 +496,8 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
|
||||
if (intMember(attrno, *attrnos))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_COLUMN),
|
||||
errmsg("attribute \"%s\" specified more than once",
|
||||
name)));
|
||||
errmsg("attribute \"%s\" specified more than once",
|
||||
name)));
|
||||
*attrnos = lappendi(*attrnos, attrno);
|
||||
}
|
||||
}
|
||||
@@ -551,7 +551,7 @@ ExpandAllTables(ParseState *pstate)
|
||||
if (!found_table)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("SELECT * with no tables specified is not valid")));
|
||||
errmsg("SELECT * with no tables specified is not valid")));
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.59 2003/07/20 21:56:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.60 2003/08/04 00:43:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -91,8 +91,8 @@ LookupTypeName(const TypeName *typename)
|
||||
if (attnum == InvalidAttrNumber)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("attribute \"%s\" of relation \"%s\" does not exist",
|
||||
field, rel->relname)));
|
||||
errmsg("attribute \"%s\" of relation \"%s\" does not exist",
|
||||
field, rel->relname)));
|
||||
restype = get_atttype(relid, attnum);
|
||||
|
||||
/* this construct should never have an array indicator */
|
||||
@@ -229,7 +229,7 @@ typenameType(const TypeName *typename)
|
||||
tup = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(typoid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for type %u", typoid);
|
||||
if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
|
||||
ereport(ERROR,
|
||||
|
||||
Reference in New Issue
Block a user