mirror of
https://github.com/postgres/postgres.git
synced 2025-08-22 21:53:06 +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.247 2002/09/02 06:11:42 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.248 2002/09/04 20:31:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -54,7 +54,8 @@ typedef struct
|
||||
List *tables; /* CREATE TABLE items */
|
||||
List *views; /* CREATE VIEW items */
|
||||
List *grants; /* GRANT items */
|
||||
List *fwconstraints; /* Forward referencing FOREIGN KEY constraints */
|
||||
List *fwconstraints; /* Forward referencing FOREIGN KEY
|
||||
* constraints */
|
||||
List *alters; /* Generated ALTER items (from the above) */
|
||||
List *ixconstraints; /* index-creating constraints */
|
||||
List *blist; /* "before list" of things to do before
|
||||
@@ -84,13 +85,13 @@ typedef struct
|
||||
|
||||
|
||||
static Query *transformStmt(ParseState *pstate, Node *stmt,
|
||||
List **extras_before, List **extras_after);
|
||||
List **extras_before, List **extras_after);
|
||||
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
|
||||
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
List **extras_before, List **extras_after);
|
||||
List **extras_before, List **extras_after);
|
||||
static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
|
||||
static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt,
|
||||
List **extras_before, List **extras_after);
|
||||
List **extras_before, List **extras_after);
|
||||
static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
|
||||
static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
|
||||
static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt);
|
||||
@@ -98,7 +99,7 @@ static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
|
||||
static Query *transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt);
|
||||
static Query *transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt);
|
||||
static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
|
||||
List **extras_before, List **extras_after);
|
||||
List **extras_before, List **extras_after);
|
||||
static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
|
||||
List **extras_before, List **extras_after);
|
||||
static void transformColumnDefinition(ParseState *pstate,
|
||||
@@ -139,6 +140,7 @@ parse_analyze(Node *parseTree, ParseState *parentParseState)
|
||||
{
|
||||
List *result = NIL;
|
||||
ParseState *pstate = make_parsestate(parentParseState);
|
||||
|
||||
/* Lists to return extra commands from transformation */
|
||||
List *extras_before = NIL;
|
||||
List *extras_after = NIL;
|
||||
@@ -163,13 +165,13 @@ parse_analyze(Node *parseTree, ParseState *parentParseState)
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that only the original query is marked original.
|
||||
* We have to do this explicitly since recursive calls of parse_analyze
|
||||
* will have set originalQuery in some of the added-on queries.
|
||||
* Make sure that only the original query is marked original. We have
|
||||
* to do this explicitly since recursive calls of parse_analyze will
|
||||
* have set originalQuery in some of the added-on queries.
|
||||
*/
|
||||
foreach(listscan, result)
|
||||
{
|
||||
Query *q = lfirst(listscan);
|
||||
Query *q = lfirst(listscan);
|
||||
|
||||
q->originalQuery = (q == query);
|
||||
}
|
||||
@@ -194,7 +196,7 @@ release_pstate_resources(ParseState *pstate)
|
||||
*/
|
||||
static Query *
|
||||
transformStmt(ParseState *pstate, Node *parseTree,
|
||||
List **extras_before, List **extras_after)
|
||||
List **extras_before, List **extras_after)
|
||||
{
|
||||
Query *result = NULL;
|
||||
|
||||
@@ -205,7 +207,7 @@ transformStmt(ParseState *pstate, Node *parseTree,
|
||||
*/
|
||||
case T_CreateStmt:
|
||||
result = transformCreateStmt(pstate, (CreateStmt *) parseTree,
|
||||
extras_before, extras_after);
|
||||
extras_before, extras_after);
|
||||
break;
|
||||
|
||||
case T_IndexStmt:
|
||||
@@ -214,7 +216,7 @@ transformStmt(ParseState *pstate, Node *parseTree,
|
||||
|
||||
case T_RuleStmt:
|
||||
result = transformRuleStmt(pstate, (RuleStmt *) parseTree,
|
||||
extras_before, extras_after);
|
||||
extras_before, extras_after);
|
||||
break;
|
||||
|
||||
case T_ViewStmt:
|
||||
@@ -222,7 +224,7 @@ transformStmt(ParseState *pstate, Node *parseTree,
|
||||
ViewStmt *n = (ViewStmt *) parseTree;
|
||||
|
||||
n->query = transformStmt(pstate, (Node *) n->query,
|
||||
extras_before, extras_after);
|
||||
extras_before, extras_after);
|
||||
|
||||
/*
|
||||
* If a list of column names was given, run through and
|
||||
@@ -270,14 +272,14 @@ transformStmt(ParseState *pstate, Node *parseTree,
|
||||
result = makeNode(Query);
|
||||
result->commandType = CMD_UTILITY;
|
||||
n->query = transformStmt(pstate, (Node *) n->query,
|
||||
extras_before, extras_after);
|
||||
extras_before, extras_after);
|
||||
result->utilityStmt = (Node *) parseTree;
|
||||
}
|
||||
break;
|
||||
|
||||
case T_AlterTableStmt:
|
||||
result = transformAlterTableStmt(pstate, (AlterTableStmt *) parseTree,
|
||||
extras_before, extras_after);
|
||||
extras_before, extras_after);
|
||||
break;
|
||||
|
||||
case T_PrepareStmt:
|
||||
@@ -293,7 +295,7 @@ transformStmt(ParseState *pstate, Node *parseTree,
|
||||
*/
|
||||
case T_InsertStmt:
|
||||
result = transformInsertStmt(pstate, (InsertStmt *) parseTree,
|
||||
extras_before, extras_after);
|
||||
extras_before, extras_after);
|
||||
break;
|
||||
|
||||
case T_DeleteStmt:
|
||||
@@ -341,7 +343,7 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
|
||||
|
||||
/* set up range table with just the result rel */
|
||||
qry->resultRelation = setTargetTable(pstate, stmt->relation,
|
||||
interpretInhOption(stmt->relation->inhOpt),
|
||||
interpretInhOption(stmt->relation->inhOpt),
|
||||
true);
|
||||
|
||||
qry->distinctClause = NIL;
|
||||
@@ -434,10 +436,11 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
|
||||
/*
|
||||
* Note: we are not expecting that extras_before and extras_after
|
||||
* are going to be used by the transformation of the SELECT statement.
|
||||
* are going to be used by the transformation of the SELECT
|
||||
* statement.
|
||||
*/
|
||||
selectQuery = transformStmt(sub_pstate, stmt->selectStmt,
|
||||
extras_before, extras_after);
|
||||
extras_before, extras_after);
|
||||
|
||||
release_pstate_resources(sub_pstate);
|
||||
pfree(sub_pstate);
|
||||
@@ -525,7 +528,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
foreach(tl, qry->targetList)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(tl);
|
||||
ResTarget *col;
|
||||
ResTarget *col;
|
||||
|
||||
if (icolumns == NIL || attnos == NIL)
|
||||
elog(ERROR, "INSERT has more expressions than target columns");
|
||||
@@ -541,7 +544,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
Assert(IsA(col, ResTarget));
|
||||
Assert(!tle->resdom->resjunk);
|
||||
updateTargetListEntry(pstate, tle, col->name, lfirsti(attnos),
|
||||
col->indirection);
|
||||
col->indirection);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -555,9 +558,9 @@ 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
|
||||
* for select statements.
|
||||
* Ensure that the targetlist has the same number of entries that
|
||||
* were present in the columns list. Don't do the check for select
|
||||
* statements.
|
||||
*/
|
||||
if (stmt->cols != NIL && (icolumns != NIL || attnos != NIL))
|
||||
elog(ERROR, "INSERT has more target columns than expressions");
|
||||
@@ -780,8 +783,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
|
||||
q->utilityStmt = (Node *) stmt;
|
||||
stmt->tableElts = cxt.columns;
|
||||
stmt->constraints = cxt.ckconstraints;
|
||||
*extras_before = nconc (*extras_before, cxt.blist);
|
||||
*extras_after = nconc (cxt.alist, *extras_after);
|
||||
*extras_before = nconc(*extras_before, cxt.blist);
|
||||
*extras_after = nconc(cxt.alist, *extras_after);
|
||||
|
||||
return q;
|
||||
}
|
||||
@@ -839,7 +842,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
snamespace = get_namespace_name(RangeVarGetCreationNamespace(cxt->relation));
|
||||
|
||||
elog(NOTICE, "%s will create implicit sequence '%s' for SERIAL column '%s.%s'",
|
||||
cxt->stmtType, sname, cxt->relation->relname, column->colname);
|
||||
cxt->stmtType, sname, cxt->relation->relname, column->colname);
|
||||
|
||||
/*
|
||||
* Build a CREATE SEQUENCE command to create the sequence object,
|
||||
@@ -1213,9 +1216,10 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
|
||||
/*
|
||||
* Scan the index list and remove any redundant index specifications.
|
||||
* This can happen if, for instance, the user writes UNIQUE PRIMARY KEY.
|
||||
* A strict reading of SQL92 would suggest raising an error instead,
|
||||
* but that strikes me as too anal-retentive. - tgl 2001-02-14
|
||||
* This can happen if, for instance, the user writes UNIQUE PRIMARY
|
||||
* KEY. A strict reading of SQL92 would suggest raising an error
|
||||
* instead, but that strikes me as too anal-retentive. - tgl
|
||||
* 2001-02-14
|
||||
*
|
||||
* XXX in ALTER TABLE case, it'd be nice to look for duplicate
|
||||
* pre-existing indexes, too.
|
||||
@@ -1279,7 +1283,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
iparam = lfirst(index->indexParams);
|
||||
index->idxname = CreateIndexName(cxt->relation->relname,
|
||||
iparam->name ? iparam->name :
|
||||
strVal(llast(iparam->funcname)),
|
||||
strVal(llast(iparam->funcname)),
|
||||
"key", cxt->alist);
|
||||
}
|
||||
if (index->idxname == NULL) /* should not happen */
|
||||
@@ -1352,7 +1356,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
IndexElem *ielem = lfirst(attr);
|
||||
char *iname = ielem->name;
|
||||
|
||||
Assert(iname); /* no func index here */
|
||||
Assert(iname); /* no func index here */
|
||||
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs,
|
||||
makeString(iname));
|
||||
if (attnum >= INDEX_MAX_KEYS)
|
||||
@@ -1417,7 +1421,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
elog(ERROR, "Can only have %d keys in a foreign key",
|
||||
INDEX_MAX_KEYS);
|
||||
pktypoid[attnum++] = transformFkeyGetColType(cxt,
|
||||
pkattr);
|
||||
pkattr);
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
@@ -1444,8 +1448,8 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
* fktypoid[i] is the foreign key table's i'th element's type
|
||||
* pktypoid[i] is the primary key table's i'th element's type
|
||||
*
|
||||
* We let oper() do our work for us, including elog(ERROR) if
|
||||
* the types don't compare with =
|
||||
* We let oper() do our work for us, including elog(ERROR) if the
|
||||
* types don't compare with =
|
||||
*/
|
||||
Operator o = oper(makeList1(makeString("=")),
|
||||
fktypoid[i], pktypoid[i], false);
|
||||
@@ -1462,7 +1466,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
{
|
||||
AlterTableStmt *alterstmt = makeNode(AlterTableStmt);
|
||||
|
||||
alterstmt->subtype = 'c'; /* preprocessed add constraint */
|
||||
alterstmt->subtype = 'c'; /* preprocessed add constraint */
|
||||
alterstmt->relation = cxt->relation;
|
||||
alterstmt->name = NULL;
|
||||
alterstmt->def = (Node *) makeList1(fkconstraint);
|
||||
@@ -1528,7 +1532,7 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
|
||||
*/
|
||||
static Query *
|
||||
transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
|
||||
List **extras_before, List **extras_after)
|
||||
List **extras_before, List **extras_after)
|
||||
{
|
||||
Query *qry;
|
||||
RangeTblEntry *oldrte;
|
||||
@@ -1658,7 +1662,7 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
|
||||
|
||||
/* Transform the rule action statement */
|
||||
top_subqry = transformStmt(sub_pstate, action,
|
||||
extras_before, extras_after);
|
||||
extras_before, extras_after);
|
||||
|
||||
/*
|
||||
* We cannot support utility-statement actions (eg NOTIFY)
|
||||
@@ -2015,8 +2019,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (intoColNames)
|
||||
@@ -2299,7 +2303,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
||||
pstate->p_is_update = true;
|
||||
|
||||
qry->resultRelation = setTargetTable(pstate, stmt->relation,
|
||||
interpretInhOption(stmt->relation->inhOpt),
|
||||
interpretInhOption(stmt->relation->inhOpt),
|
||||
true);
|
||||
|
||||
/*
|
||||
@@ -2445,6 +2449,7 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
|
||||
/*
|
||||
* Already-transformed ADD CONSTRAINT, so just make it look
|
||||
* like the standard case.
|
||||
@@ -2466,12 +2471,12 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
|
||||
static Query *
|
||||
transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt)
|
||||
{
|
||||
Query *result = makeNode(Query);
|
||||
List *extras_before = NIL,
|
||||
*extras_after = NIL;
|
||||
List *argtype_oids = NIL; /* argtype OIDs in a list */
|
||||
Oid *argtoids = NULL; /* as an array for parser_param_set */
|
||||
int nargs;
|
||||
Query *result = makeNode(Query);
|
||||
List *extras_before = NIL,
|
||||
*extras_after = NIL;
|
||||
List *argtype_oids = NIL; /* argtype OIDs in a list */
|
||||
Oid *argtoids = NULL; /* as an array for parser_param_set */
|
||||
int nargs;
|
||||
|
||||
result->commandType = CMD_UTILITY;
|
||||
result->utilityStmt = (Node *) stmt;
|
||||
@@ -2481,15 +2486,15 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt)
|
||||
|
||||
if (nargs)
|
||||
{
|
||||
List *l;
|
||||
int i = 0;
|
||||
List *l;
|
||||
int i = 0;
|
||||
|
||||
argtoids = (Oid *) palloc(nargs * sizeof(Oid));
|
||||
|
||||
foreach (l, stmt->argtypes)
|
||||
foreach(l, stmt->argtypes)
|
||||
{
|
||||
TypeName *tn = lfirst(l);
|
||||
Oid toid = typenameTypeId(tn);
|
||||
TypeName *tn = lfirst(l);
|
||||
Oid toid = typenameTypeId(tn);
|
||||
|
||||
argtype_oids = lappendi(argtype_oids, toid);
|
||||
argtoids[i++] = toid;
|
||||
@@ -2499,12 +2504,12 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt)
|
||||
stmt->argtype_oids = argtype_oids;
|
||||
|
||||
/*
|
||||
* We need to adjust the parameters expected by the
|
||||
* rest of the system, so that $1, ... $n are parsed properly.
|
||||
* We need to adjust the parameters expected by the rest of the
|
||||
* system, so that $1, ... $n are parsed properly.
|
||||
*
|
||||
* This is somewhat of a hack; however, the main parser interface
|
||||
* only allows parameters to be specified when working with a
|
||||
* raw query string, which is not helpful here.
|
||||
* This is somewhat of a hack; however, the main parser interface only
|
||||
* allows parameters to be specified when working with a raw query
|
||||
* string, which is not helpful here.
|
||||
*/
|
||||
parser_param_set(argtoids, nargs);
|
||||
|
||||
@@ -2524,8 +2529,8 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt)
|
||||
static Query *
|
||||
transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt)
|
||||
{
|
||||
Query *result = makeNode(Query);
|
||||
List *paramtypes;
|
||||
Query *result = makeNode(Query);
|
||||
List *paramtypes;
|
||||
|
||||
result->commandType = CMD_UTILITY;
|
||||
result->utilityStmt = (Node *) stmt;
|
||||
@@ -2534,20 +2539,20 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt)
|
||||
|
||||
if (stmt->params || paramtypes)
|
||||
{
|
||||
int nparams = length(stmt->params);
|
||||
int nexpected = length(paramtypes);
|
||||
List *l;
|
||||
int i = 1;
|
||||
int nparams = length(stmt->params);
|
||||
int nexpected = length(paramtypes);
|
||||
List *l;
|
||||
int i = 1;
|
||||
|
||||
if (nparams != nexpected)
|
||||
elog(ERROR, "Wrong number of parameters, expected %d but got %d",
|
||||
nexpected, nparams);
|
||||
|
||||
foreach (l, stmt->params)
|
||||
foreach(l, stmt->params)
|
||||
{
|
||||
Node *expr = lfirst(l);
|
||||
Oid expected_type_id,
|
||||
given_type_id;
|
||||
Node *expr = lfirst(l);
|
||||
Oid expected_type_id,
|
||||
given_type_id;
|
||||
|
||||
expr = transformExpr(pstate, expr);
|
||||
|
||||
@@ -2571,7 +2576,7 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt)
|
||||
|
||||
if (!expr)
|
||||
elog(ERROR, "Parameter $%d of type %s cannot be coerced into the expected type %s"
|
||||
"\n\tYou will need to rewrite or cast the expression",
|
||||
"\n\tYou will need to rewrite or cast the expression",
|
||||
i,
|
||||
format_type_be(given_type_id),
|
||||
format_type_be(expected_type_id));
|
||||
@@ -2833,7 +2838,7 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
|
||||
|
||||
pktypoid[attnum++] = attnumTypeId(pkrel, pkattno);
|
||||
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs,
|
||||
makeString(pstrdup(NameStr(*attnumAttName(pkrel, pkattno)))));
|
||||
makeString(pstrdup(NameStr(*attnumAttName(pkrel, pkattno)))));
|
||||
}
|
||||
|
||||
ReleaseSysCache(indexTuple);
|
||||
@@ -3145,8 +3150,8 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
|
||||
elp->relation->schemaname = cxt.schemaname;
|
||||
else if (strcmp(cxt.schemaname, elp->relation->schemaname) != 0)
|
||||
elog(ERROR, "New table specifies a schema (%s)"
|
||||
" different from the one being created (%s)",
|
||||
elp->relation->schemaname, cxt.schemaname);
|
||||
" different from the one being created (%s)",
|
||||
elp->relation->schemaname, cxt.schemaname);
|
||||
|
||||
/*
|
||||
* XXX todo: deal with constraints
|
||||
@@ -3158,14 +3163,14 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
|
||||
|
||||
case T_ViewStmt:
|
||||
{
|
||||
ViewStmt *elp = (ViewStmt *) element;
|
||||
ViewStmt *elp = (ViewStmt *) element;
|
||||
|
||||
if (elp->view->schemaname == NULL)
|
||||
elp->view->schemaname = cxt.schemaname;
|
||||
else if (strcmp(cxt.schemaname, elp->view->schemaname) != 0)
|
||||
elog(ERROR, "New view specifies a schema (%s)"
|
||||
" different from the one being created (%s)",
|
||||
elp->view->schemaname, cxt.schemaname);
|
||||
" different from the one being created (%s)",
|
||||
elp->view->schemaname, cxt.schemaname);
|
||||
|
||||
/*
|
||||
* XXX todo: deal with references between views
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.96 2002/08/18 18:46:15 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.97 2002/09/04 20:31:23 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -41,8 +41,8 @@
|
||||
static char *clauseText[] = {"ORDER BY", "GROUP BY", "DISTINCT ON"};
|
||||
|
||||
static void extractRemainingColumns(List *common_colnames,
|
||||
List *src_colnames, List *src_colvars,
|
||||
List **res_colnames, List **res_colvars);
|
||||
List *src_colnames, List *src_colvars,
|
||||
List **res_colnames, List **res_colvars);
|
||||
static Node *transformJoinUsingClause(ParseState *pstate,
|
||||
List *leftVars, List *rightVars);
|
||||
static Node *transformJoinOnClause(ParseState *pstate, JoinExpr *j,
|
||||
@@ -51,11 +51,11 @@ static RangeTblRef *transformTableEntry(ParseState *pstate, RangeVar *r);
|
||||
static RangeTblRef *transformRangeSubselect(ParseState *pstate,
|
||||
RangeSubselect *r);
|
||||
static RangeTblRef *transformRangeFunction(ParseState *pstate,
|
||||
RangeFunction *r);
|
||||
RangeFunction *r);
|
||||
static Node *transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
List **containedRels);
|
||||
static Node *buildMergedJoinVar(JoinType jointype,
|
||||
Var *l_colvar, Var *r_colvar);
|
||||
Var *l_colvar, Var *r_colvar);
|
||||
static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node,
|
||||
List *tlist, int clause);
|
||||
static List *addTargetToSortList(TargetEntry *tle, List *sortlist,
|
||||
@@ -85,9 +85,9 @@ transformFromClause(ParseState *pstate, List *frmList)
|
||||
|
||||
/*
|
||||
* The grammar will have produced a list of RangeVars,
|
||||
* RangeSubselects, RangeFunctions, and/or JoinExprs. Transform each one
|
||||
* (possibly adding entries to the rtable), check for duplicate refnames,
|
||||
* and then add it to the joinlist and namespace.
|
||||
* RangeSubselects, RangeFunctions, and/or JoinExprs. Transform each
|
||||
* one (possibly adding entries to the rtable), check for duplicate
|
||||
* refnames, and then add it to the joinlist and namespace.
|
||||
*/
|
||||
foreach(fl, frmList)
|
||||
{
|
||||
@@ -466,13 +466,14 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
|
||||
funcname = strVal(llast(((FuncCall *) r->funccallnode)->funcname));
|
||||
|
||||
/*
|
||||
* Transform the raw FuncCall node. This is a bit tricky because we don't
|
||||
* want the function expression to be able to see any FROM items already
|
||||
* created in the current query (compare to transformRangeSubselect).
|
||||
* But it does need to be able to see any further-up parent states.
|
||||
* So, temporarily make the current query level have an empty namespace.
|
||||
* NOTE: this code is OK only because the expression can't legally alter
|
||||
* the namespace by causing implicit relation refs to be added.
|
||||
* Transform the raw FuncCall node. This is a bit tricky because we
|
||||
* don't want the function expression to be able to see any FROM items
|
||||
* already created in the current query (compare to
|
||||
* transformRangeSubselect). But it does need to be able to see any
|
||||
* further-up parent states. So, temporarily make the current query
|
||||
* level have an empty namespace. NOTE: this code is OK only because
|
||||
* the expression can't legally alter the namespace by causing
|
||||
* implicit relation refs to be added.
|
||||
*/
|
||||
save_namespace = pstate->p_namespace;
|
||||
pstate->p_namespace = NIL;
|
||||
@@ -482,18 +483,18 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
|
||||
pstate->p_namespace = save_namespace;
|
||||
|
||||
/*
|
||||
* We still need to check that the function parameters don't refer
|
||||
* to any other rels. That could happen despite our hack on the namespace
|
||||
* if fully-qualified names are used. So, check there are no local
|
||||
* Var references in the transformed expression. (Outer references
|
||||
* are OK, and are ignored here.)
|
||||
* We still need to check that the function parameters don't refer to
|
||||
* any other rels. That could happen despite our hack on the
|
||||
* namespace if fully-qualified names are used. So, check there are
|
||||
* no local Var references in the transformed expression. (Outer
|
||||
* references are OK, and are ignored here.)
|
||||
*/
|
||||
if (pull_varnos(funcexpr) != NIL)
|
||||
elog(ERROR, "FROM function expression may not refer to other relations of same query level");
|
||||
|
||||
/*
|
||||
* Disallow aggregate functions in the expression. (No reason to postpone
|
||||
* this check until parseCheckAggregates.)
|
||||
* Disallow aggregate functions in the expression. (No reason to
|
||||
* postpone this check until parseCheckAggregates.)
|
||||
*/
|
||||
if (pstate->p_hasAggs)
|
||||
{
|
||||
@@ -503,8 +504,9 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
|
||||
|
||||
/*
|
||||
* Insist we have a bare function call (explain.c is the only place
|
||||
* that depends on this, I think). If this fails, it's probably because
|
||||
* transformExpr interpreted the function notation as a type coercion.
|
||||
* that depends on this, I think). If this fails, it's probably
|
||||
* because transformExpr interpreted the function notation as a type
|
||||
* coercion.
|
||||
*/
|
||||
if (!funcexpr ||
|
||||
!IsA(funcexpr, Expr) ||
|
||||
@@ -596,8 +598,8 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
|
||||
j->rarg = transformFromClauseItem(pstate, j->rarg, &r_containedRels);
|
||||
|
||||
/*
|
||||
* Generate combined list of relation indexes for possible use
|
||||
* by transformJoinOnClause below.
|
||||
* Generate combined list of relation indexes for possible use by
|
||||
* transformJoinOnClause below.
|
||||
*/
|
||||
my_containedRels = nconc(l_containedRels, r_containedRels);
|
||||
|
||||
@@ -893,6 +895,7 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar)
|
||||
switch (jointype)
|
||||
{
|
||||
case JOIN_INNER:
|
||||
|
||||
/*
|
||||
* We can use either var; prefer non-coerced one if available.
|
||||
*/
|
||||
@@ -912,25 +915,25 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar)
|
||||
res_node = r_node;
|
||||
break;
|
||||
case JOIN_FULL:
|
||||
{
|
||||
/*
|
||||
* Here we must build a COALESCE expression to ensure that
|
||||
* the join output is non-null if either input is.
|
||||
*/
|
||||
CaseExpr *c = makeNode(CaseExpr);
|
||||
CaseWhen *w = makeNode(CaseWhen);
|
||||
NullTest *n = makeNode(NullTest);
|
||||
{
|
||||
/*
|
||||
* Here we must build a COALESCE expression to ensure that
|
||||
* the join output is non-null if either input is.
|
||||
*/
|
||||
CaseExpr *c = makeNode(CaseExpr);
|
||||
CaseWhen *w = makeNode(CaseWhen);
|
||||
NullTest *n = makeNode(NullTest);
|
||||
|
||||
n->arg = l_node;
|
||||
n->nulltesttype = IS_NOT_NULL;
|
||||
w->expr = (Node *) n;
|
||||
w->result = l_node;
|
||||
c->casetype = outcoltype;
|
||||
c->args = makeList1(w);
|
||||
c->defresult = r_node;
|
||||
res_node = (Node *) c;
|
||||
break;
|
||||
}
|
||||
n->arg = l_node;
|
||||
n->nulltesttype = IS_NOT_NULL;
|
||||
w->expr = (Node *) n;
|
||||
w->result = l_node;
|
||||
c->casetype = outcoltype;
|
||||
c->args = makeList1(w);
|
||||
c->defresult = r_node;
|
||||
res_node = (Node *) c;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
elog(ERROR, "buildMergedJoinVar: unexpected jointype %d",
|
||||
(int) jointype);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.82 2002/09/01 02:27:32 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.83 2002/09/04 20:31:23 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
static Oid PreferredType(CATEGORY category, Oid type);
|
||||
static bool find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
|
||||
bool isExplicit,
|
||||
Oid *funcid);
|
||||
bool isExplicit,
|
||||
Oid *funcid);
|
||||
static Oid find_typmod_coercion_function(Oid typeId);
|
||||
static Node *build_func_call(Oid funcid, Oid rettype, List *args);
|
||||
|
||||
@@ -71,8 +71,8 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
||||
* XXX if the typinput function is not cachable, we really ought to
|
||||
* postpone evaluation of the function call until runtime. But
|
||||
* there is no way to represent a typinput function call as an
|
||||
* expression tree, because C-string values are not Datums.
|
||||
* (XXX This *is* possible as of 7.3, do we want to do it?)
|
||||
* expression tree, because C-string values are not Datums. (XXX
|
||||
* This *is* possible as of 7.3, do we want to do it?)
|
||||
*/
|
||||
Const *con = (Const *) node;
|
||||
Const *newcon = makeNode(Const);
|
||||
@@ -91,10 +91,11 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
||||
con->constvalue));
|
||||
|
||||
/*
|
||||
* If target is a domain, use the typmod it applies to the base
|
||||
* type. Note that we call stringTypeDatum using the domain's
|
||||
* pg_type row, though. This works because the domain row has
|
||||
* the same typinput and typelem as the base type --- ugly...
|
||||
* If target is a domain, use the typmod it applies to the
|
||||
* base type. Note that we call stringTypeDatum using the
|
||||
* domain's pg_type row, though. This works because the
|
||||
* domain row has the same typinput and typelem as the base
|
||||
* type --- ugly...
|
||||
*/
|
||||
if (targetTyptype == 'd')
|
||||
atttypmod = getBaseTypeMod(targetTypeId, atttypmod);
|
||||
@@ -127,11 +128,12 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
||||
if (OidIsValid(funcId))
|
||||
{
|
||||
/*
|
||||
* Generate an expression tree representing run-time application
|
||||
* of the conversion function. If we are dealing with a domain
|
||||
* target type, the conversion function will yield the base type.
|
||||
* Generate an expression tree representing run-time
|
||||
* application of the conversion function. If we are dealing
|
||||
* with a domain target type, the conversion function will
|
||||
* yield the base type.
|
||||
*/
|
||||
Oid baseTypeId = getBaseType(targetTypeId);
|
||||
Oid baseTypeId = getBaseType(targetTypeId);
|
||||
|
||||
result = build_func_call(funcId, baseTypeId, makeList1(node));
|
||||
|
||||
@@ -147,19 +149,20 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
||||
}
|
||||
|
||||
/*
|
||||
* If the input is a constant, apply the type conversion function
|
||||
* now instead of delaying to runtime. (We could, of course, just
|
||||
* leave this to be done during planning/optimization; but it's a
|
||||
* very frequent special case, and we save cycles in the rewriter
|
||||
* if we fold the expression now.)
|
||||
* If the input is a constant, apply the type conversion
|
||||
* function now instead of delaying to runtime. (We could, of
|
||||
* course, just leave this to be done during
|
||||
* planning/optimization; but it's a very frequent special
|
||||
* case, and we save cycles in the rewriter if we fold the
|
||||
* expression now.)
|
||||
*
|
||||
* Note that no folding will occur if the conversion function is
|
||||
* not marked 'immutable'.
|
||||
*
|
||||
* HACK: if constant is NULL, don't fold it here. This is needed
|
||||
* by make_subplan(), which calls this routine on placeholder
|
||||
* Const nodes that mustn't be collapsed. (It'd be a lot cleaner
|
||||
* to make a separate node type for that purpose...)
|
||||
* Const nodes that mustn't be collapsed. (It'd be a lot
|
||||
* cleaner to make a separate node type for that purpose...)
|
||||
*/
|
||||
if (IsA(node, Const) &&
|
||||
!((Const *) node)->constisnull)
|
||||
@@ -168,21 +171,23 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We don't need to do a physical conversion, but we do need to
|
||||
* attach a RelabelType node so that the expression will be seen
|
||||
* to have the intended type when inspected by higher-level code.
|
||||
* We don't need to do a physical conversion, but we do need
|
||||
* to attach a RelabelType node so that the expression will be
|
||||
* seen to have the intended type when inspected by
|
||||
* higher-level code.
|
||||
*
|
||||
* Also, domains may have value restrictions beyond the base type
|
||||
* that must be accounted for.
|
||||
*/
|
||||
result = coerce_type_constraints(pstate, node,
|
||||
targetTypeId, true);
|
||||
|
||||
/*
|
||||
* 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 (wrong if target is a domain,
|
||||
* in any case).
|
||||
* 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 (wrong if target is
|
||||
* a domain, in any case).
|
||||
*/
|
||||
result = (Node *) makeRelabelType(result, targetTypeId, -1);
|
||||
}
|
||||
@@ -190,9 +195,9 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
||||
else if (typeInheritsFrom(inputTypeId, targetTypeId))
|
||||
{
|
||||
/*
|
||||
* Input class type is a subclass of target, so nothing to do
|
||||
* --- except relabel the type. This is binary compatibility
|
||||
* for complex types.
|
||||
* Input class type is a subclass of target, so nothing to do ---
|
||||
* except relabel the type. This is binary compatibility for
|
||||
* complex types.
|
||||
*/
|
||||
result = (Node *) makeRelabelType(node, targetTypeId, -1);
|
||||
}
|
||||
@@ -254,12 +259,15 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids,
|
||||
if (targetTypeId == ANYOID)
|
||||
continue;
|
||||
|
||||
/* if target is ANYARRAY and source is a varlena array type, accept */
|
||||
/*
|
||||
* if target is ANYARRAY and source is a varlena array type,
|
||||
* accept
|
||||
*/
|
||||
if (targetTypeId == ANYARRAYOID)
|
||||
{
|
||||
Oid typOutput;
|
||||
Oid typElem;
|
||||
bool typIsVarlena;
|
||||
Oid typOutput;
|
||||
Oid typElem;
|
||||
bool typIsVarlena;
|
||||
|
||||
if (getTypeOutputInfo(inputTypeId, &typOutput, &typElem,
|
||||
&typIsVarlena))
|
||||
@@ -267,10 +275,11 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids,
|
||||
if (OidIsValid(typElem) && typIsVarlena)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise reject; this assumes there are no explicit coercions
|
||||
* to ANYARRAY. If we don't reject then parse_coerce would have
|
||||
* to repeat the above test.
|
||||
* Otherwise reject; this assumes there are no explicit
|
||||
* coercions to ANYARRAY. If we don't reject then
|
||||
* parse_coerce would have to repeat the above test.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
@@ -301,15 +310,15 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids,
|
||||
|
||||
/*
|
||||
* Create an expression tree to enforce the constraints (if any)
|
||||
* that should be applied by the type. Currently this is only
|
||||
* that should be applied by the type. Currently this is only
|
||||
* interesting for domain types.
|
||||
*/
|
||||
Node *
|
||||
coerce_type_constraints(ParseState *pstate, Node *arg,
|
||||
Oid typeId, bool applyTypmod)
|
||||
{
|
||||
char *notNull = NULL;
|
||||
int32 typmod = -1;
|
||||
char *notNull = NULL;
|
||||
int32 typmod = -1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -351,9 +360,9 @@ coerce_type_constraints(ParseState *pstate, Node *arg,
|
||||
arg = coerce_type_typmod(pstate, arg, typeId, typmod);
|
||||
|
||||
/*
|
||||
* Only need to add one NOT NULL check regardless of how many
|
||||
* domains in the stack request it. The topmost domain that
|
||||
* requested it is used as the constraint name.
|
||||
* Only need to add one NOT NULL check regardless of how many domains
|
||||
* in the stack request it. The topmost domain that requested it is
|
||||
* used as the constraint name.
|
||||
*/
|
||||
if (notNull)
|
||||
{
|
||||
@@ -361,11 +370,11 @@ coerce_type_constraints(ParseState *pstate, Node *arg,
|
||||
|
||||
r->arg = arg;
|
||||
r->testtype = CONSTR_TEST_NOTNULL;
|
||||
r->name = notNull;
|
||||
r->name = notNull;
|
||||
r->check_expr = NULL;
|
||||
|
||||
arg = (Node *) r;
|
||||
}
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
@@ -904,7 +913,7 @@ build_func_call(Oid funcid, Oid rettype, List *args)
|
||||
funcnode = makeNode(Func);
|
||||
funcnode->funcid = funcid;
|
||||
funcnode->funcresulttype = rettype;
|
||||
funcnode->funcretset = false; /* only possible case here */
|
||||
funcnode->funcretset = false; /* only possible case here */
|
||||
funcnode->func_fcache = NULL;
|
||||
|
||||
expr = makeNode(Expr);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.127 2002/08/31 22:10:46 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.128 2002/09/04 20:31:23 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -194,7 +194,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
*/
|
||||
if (Transform_null_equals &&
|
||||
length(a->name) == 1 &&
|
||||
strcmp(strVal(lfirst(a->name)), "=") == 0 &&
|
||||
strcmp(strVal(lfirst(a->name)), "=") == 0 &&
|
||||
(exprIsNullConstant(a->lexpr) ||
|
||||
exprIsNullConstant(a->rexpr)))
|
||||
{
|
||||
@@ -213,9 +213,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(a->name,
|
||||
lexpr,
|
||||
@@ -277,41 +277,48 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
a->lexpr);
|
||||
Node *rexpr = transformExpr(pstate,
|
||||
a->rexpr);
|
||||
|
||||
result = (Node *) make_op(a->name,
|
||||
lexpr,
|
||||
rexpr);
|
||||
((Expr *)result)->opType = DISTINCT_EXPR;
|
||||
((Expr *) result)->opType = DISTINCT_EXPR;
|
||||
}
|
||||
break;
|
||||
case OF:
|
||||
{
|
||||
List *telem;
|
||||
A_Const *n;
|
||||
Oid ltype, rtype;
|
||||
bool matched = FALSE;
|
||||
List *telem;
|
||||
A_Const *n;
|
||||
Oid ltype,
|
||||
rtype;
|
||||
bool matched = FALSE;
|
||||
|
||||
/* Checking an expression for match to type.
|
||||
/*
|
||||
* Checking an expression for match to type.
|
||||
* Will result in a boolean constant node.
|
||||
*/
|
||||
Node *lexpr = transformExpr(pstate,
|
||||
a->lexpr);
|
||||
|
||||
ltype = exprType(lexpr);
|
||||
foreach(telem, (List *) a->rexpr)
|
||||
{
|
||||
rtype = LookupTypeName(lfirst(telem));
|
||||
matched = (rtype == ltype);
|
||||
if (matched) break;
|
||||
if (matched)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Expect two forms: equals or not equals.
|
||||
* Flip the sense of the result for not equals.
|
||||
/*
|
||||
* Expect two forms: equals or not equals.
|
||||
* Flip the sense of the result for not
|
||||
* equals.
|
||||
*/
|
||||
if (strcmp(strVal(lfirst(a->name)), "!=") == 0)
|
||||
matched = (! matched);
|
||||
matched = (!matched);
|
||||
|
||||
n = makeNode(A_Const);
|
||||
n->val.type = T_String;
|
||||
n->val.val.str = (matched? "t": "f");
|
||||
n->val.val.str = (matched ? "t" : "f");
|
||||
n->typename = SystemTypeName("bool");
|
||||
|
||||
result = transformExpr(pstate, (Node *) n);
|
||||
@@ -411,7 +418,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
|
||||
/* Combining operators other than =/<> is dubious... */
|
||||
if (length(left_list) != 1 &&
|
||||
strcmp(opname, "=") != 0 && strcmp(opname, "<>") != 0)
|
||||
strcmp(opname, "=") != 0 && strcmp(opname, "<>") != 0)
|
||||
elog(ERROR, "Row comparison cannot use operator %s",
|
||||
opname);
|
||||
|
||||
@@ -453,7 +460,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
if (opform->oprresult != BOOLOID)
|
||||
elog(ERROR, "%s has result type of %s, but must return %s"
|
||||
" to be used with quantified predicate subquery",
|
||||
opname, format_type_be(opform->oprresult),
|
||||
opname, format_type_be(opform->oprresult),
|
||||
format_type_be(BOOLOID));
|
||||
|
||||
if (get_func_retset(opform->oprcode))
|
||||
@@ -613,7 +620,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
default:
|
||||
elog(ERROR, "transformExpr: unexpected booltesttype %d",
|
||||
(int) b->booltesttype);
|
||||
clausename = NULL; /* keep compiler quiet */
|
||||
clausename = NULL; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
b->arg = transformExpr(pstate, b->arg);
|
||||
@@ -624,14 +631,14 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
break;
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
* Quietly accept node types that may be presented when we are
|
||||
* called on an already-transformed tree.
|
||||
*
|
||||
* Do any other node types need to be accepted? For now we are
|
||||
* taking a conservative approach, and only accepting node
|
||||
* types that are demonstrably necessary to accept.
|
||||
*********************************************/
|
||||
/*********************************************
|
||||
* Quietly accept node types that may be presented when we are
|
||||
* called on an already-transformed tree.
|
||||
*
|
||||
* Do any other node types need to be accepted? For now we are
|
||||
* taking a conservative approach, and only accepting node
|
||||
* types that are demonstrably necessary to accept.
|
||||
*********************************************/
|
||||
case T_Expr:
|
||||
case T_Var:
|
||||
case T_Const:
|
||||
@@ -705,146 +712,148 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
|
||||
switch (numnames)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
char *name = strVal(lfirst(cref->fields));
|
||||
|
||||
/* Try to identify as an unqualified column */
|
||||
node = colnameToVar(pstate, name);
|
||||
|
||||
if (node == NULL)
|
||||
{
|
||||
/*
|
||||
* Not known as a column of any range-table entry, so
|
||||
* try to find the name as a relation ... but not if
|
||||
* subscripts appear. Note also that only relations
|
||||
* already entered into the rangetable will be recognized.
|
||||
*
|
||||
* This is a hack for backwards compatibility with PostQUEL-
|
||||
* inspired syntax. The preferred form now is "rel.*".
|
||||
*/
|
||||
int levels_up;
|
||||
char *name = strVal(lfirst(cref->fields));
|
||||
|
||||
if (cref->indirection == NIL &&
|
||||
refnameRangeTblEntry(pstate, NULL, name,
|
||||
&levels_up) != NULL)
|
||||
/* Try to identify as an unqualified column */
|
||||
node = colnameToVar(pstate, name);
|
||||
|
||||
if (node == NULL)
|
||||
{
|
||||
/*
|
||||
* Not known as a column of any range-table entry, so
|
||||
* try to find the name as a relation ... but not if
|
||||
* subscripts appear. Note also that only relations
|
||||
* already entered into the rangetable will be
|
||||
* recognized.
|
||||
*
|
||||
* This is a hack for backwards compatibility with
|
||||
* PostQUEL- inspired syntax. The preferred form now
|
||||
* is "rel.*".
|
||||
*/
|
||||
int levels_up;
|
||||
|
||||
if (cref->indirection == NIL &&
|
||||
refnameRangeTblEntry(pstate, NULL, name,
|
||||
&levels_up) != NULL)
|
||||
{
|
||||
rv = makeNode(RangeVar);
|
||||
rv->relname = name;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = (Node *) rv;
|
||||
}
|
||||
else
|
||||
elog(ERROR, "Attribute \"%s\" not found", name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
char *name1 = strVal(lfirst(cref->fields));
|
||||
char *name2 = strVal(lsecond(cref->fields));
|
||||
|
||||
/* Whole-row reference? */
|
||||
if (strcmp(name2, "*") == 0)
|
||||
{
|
||||
rv = makeNode(RangeVar);
|
||||
rv->relname = name;
|
||||
rv->relname = name1;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = (Node *) rv;
|
||||
break;
|
||||
}
|
||||
else
|
||||
elog(ERROR, "Attribute \"%s\" not found", name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
char *name1 = strVal(lfirst(cref->fields));
|
||||
char *name2 = strVal(lsecond(cref->fields));
|
||||
|
||||
/* Whole-row reference? */
|
||||
if (strcmp(name2, "*") == 0)
|
||||
{
|
||||
rv = makeNode(RangeVar);
|
||||
rv->relname = name1;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = (Node *) rv;
|
||||
/* Try to identify as a once-qualified column */
|
||||
node = qualifiedNameToVar(pstate, NULL, name1, name2, true);
|
||||
if (node == NULL)
|
||||
{
|
||||
/*
|
||||
* Not known as a column of any range-table entry, so
|
||||
* try it as a function call. Here, we will create an
|
||||
* implicit RTE for tables not already entered.
|
||||
*/
|
||||
rv = makeNode(RangeVar);
|
||||
rv->relname = name1;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = ParseFuncOrColumn(pstate,
|
||||
makeList1(makeString(name2)),
|
||||
makeList1(rv),
|
||||
false, false, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try to identify as a once-qualified column */
|
||||
node = qualifiedNameToVar(pstate, NULL, name1, name2, true);
|
||||
if (node == NULL)
|
||||
{
|
||||
/*
|
||||
* Not known as a column of any range-table entry, so
|
||||
* try it as a function call. Here, we will create an
|
||||
* implicit RTE for tables not already entered.
|
||||
*/
|
||||
rv = makeNode(RangeVar);
|
||||
rv->relname = name1;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = ParseFuncOrColumn(pstate,
|
||||
makeList1(makeString(name2)),
|
||||
makeList1(rv),
|
||||
false, false, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
char *name1 = strVal(lfirst(cref->fields));
|
||||
char *name2 = strVal(lsecond(cref->fields));
|
||||
char *name3 = strVal(lfirst(lnext(lnext(cref->fields))));
|
||||
|
||||
/* Whole-row reference? */
|
||||
if (strcmp(name3, "*") == 0)
|
||||
{
|
||||
rv = makeNode(RangeVar);
|
||||
rv->schemaname = name1;
|
||||
rv->relname = name2;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = (Node *) rv;
|
||||
char *name1 = strVal(lfirst(cref->fields));
|
||||
char *name2 = strVal(lsecond(cref->fields));
|
||||
char *name3 = strVal(lfirst(lnext(lnext(cref->fields))));
|
||||
|
||||
/* Whole-row reference? */
|
||||
if (strcmp(name3, "*") == 0)
|
||||
{
|
||||
rv = makeNode(RangeVar);
|
||||
rv->schemaname = name1;
|
||||
rv->relname = name2;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = (Node *) rv;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try to identify as a twice-qualified column */
|
||||
node = qualifiedNameToVar(pstate, name1, name2, name3, true);
|
||||
if (node == NULL)
|
||||
{
|
||||
/* Try it as a function call */
|
||||
rv = makeNode(RangeVar);
|
||||
rv->schemaname = name1;
|
||||
rv->relname = name2;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = ParseFuncOrColumn(pstate,
|
||||
makeList1(makeString(name3)),
|
||||
makeList1(rv),
|
||||
false, false, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try to identify as a twice-qualified column */
|
||||
node = qualifiedNameToVar(pstate, name1, name2, name3, true);
|
||||
if (node == NULL)
|
||||
{
|
||||
/* Try it as a function call */
|
||||
rv = makeNode(RangeVar);
|
||||
rv->schemaname = name1;
|
||||
rv->relname = name2;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = ParseFuncOrColumn(pstate,
|
||||
makeList1(makeString(name3)),
|
||||
makeList1(rv),
|
||||
false, false, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
char *name1 = strVal(lfirst(cref->fields));
|
||||
char *name2 = strVal(lsecond(cref->fields));
|
||||
char *name3 = strVal(lfirst(lnext(lnext(cref->fields))));
|
||||
char *name4 = strVal(lfirst(lnext(lnext(lnext(cref->fields)))));
|
||||
|
||||
/*
|
||||
* We check the catalog name and then ignore it.
|
||||
*/
|
||||
if (strcmp(name1, DatabaseName) != 0)
|
||||
elog(ERROR, "Cross-database references are not implemented");
|
||||
|
||||
/* Whole-row reference? */
|
||||
if (strcmp(name4, "*") == 0)
|
||||
{
|
||||
rv = makeNode(RangeVar);
|
||||
rv->schemaname = name2;
|
||||
rv->relname = name3;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = (Node *) rv;
|
||||
char *name1 = strVal(lfirst(cref->fields));
|
||||
char *name2 = strVal(lsecond(cref->fields));
|
||||
char *name3 = strVal(lfirst(lnext(lnext(cref->fields))));
|
||||
char *name4 = strVal(lfirst(lnext(lnext(lnext(cref->fields)))));
|
||||
|
||||
/*
|
||||
* We check the catalog name and then ignore it.
|
||||
*/
|
||||
if (strcmp(name1, DatabaseName) != 0)
|
||||
elog(ERROR, "Cross-database references are not implemented");
|
||||
|
||||
/* Whole-row reference? */
|
||||
if (strcmp(name4, "*") == 0)
|
||||
{
|
||||
rv = makeNode(RangeVar);
|
||||
rv->schemaname = name2;
|
||||
rv->relname = name3;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = (Node *) rv;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try to identify as a twice-qualified column */
|
||||
node = qualifiedNameToVar(pstate, name2, name3, name4, true);
|
||||
if (node == NULL)
|
||||
{
|
||||
/* Try it as a function call */
|
||||
rv = makeNode(RangeVar);
|
||||
rv->schemaname = name2;
|
||||
rv->relname = name3;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = ParseFuncOrColumn(pstate,
|
||||
makeList1(makeString(name4)),
|
||||
makeList1(rv),
|
||||
false, false, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try to identify as a twice-qualified column */
|
||||
node = qualifiedNameToVar(pstate, name2, name3, name4, true);
|
||||
if (node == NULL)
|
||||
{
|
||||
/* Try it as a function call */
|
||||
rv = makeNode(RangeVar);
|
||||
rv->schemaname = name2;
|
||||
rv->relname = name3;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = ParseFuncOrColumn(pstate,
|
||||
makeList1(makeString(name4)),
|
||||
makeList1(rv),
|
||||
false, false, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
elog(ERROR, "Invalid qualified name syntax (too many names)");
|
||||
node = NULL; /* keep compiler quiet */
|
||||
@@ -1095,8 +1104,9 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
|
||||
}
|
||||
|
||||
/*
|
||||
* Furthermore, the name and namespace of the function must be the same
|
||||
* as its result type's name/namespace (cf. find_coercion_function).
|
||||
* Furthermore, the name and namespace of the function must be the
|
||||
* same as its result type's name/namespace (cf.
|
||||
* find_coercion_function).
|
||||
*/
|
||||
typeTuple = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(procStruct->prorettype),
|
||||
@@ -1206,7 +1216,7 @@ parser_typecast_expression(ParseState *pstate,
|
||||
{
|
||||
expr = CoerceTargetExpr(pstate, expr, inputType,
|
||||
targetType, typename->typmod,
|
||||
true); /* explicit coercion */
|
||||
true); /* explicit coercion */
|
||||
if (expr == NULL)
|
||||
elog(ERROR, "Cannot cast type '%s' to '%s'",
|
||||
format_type_be(inputType),
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.135 2002/08/22 00:01:42 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.136 2002/09/04 20:31:23 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -45,14 +45,14 @@ static void make_arguments(ParseState *pstate,
|
||||
Oid *input_typeids,
|
||||
Oid *function_typeids);
|
||||
static int match_argtypes(int nargs,
|
||||
Oid *input_typeids,
|
||||
FuncCandidateList function_typeids,
|
||||
FuncCandidateList *candidates);
|
||||
Oid *input_typeids,
|
||||
FuncCandidateList function_typeids,
|
||||
FuncCandidateList *candidates);
|
||||
static FieldSelect *setup_field_select(Node *input, char *attname, Oid relid);
|
||||
static FuncCandidateList func_select_candidate(int nargs, Oid *input_typeids,
|
||||
FuncCandidateList candidates);
|
||||
FuncCandidateList candidates);
|
||||
static void unknown_attribute(const char *schemaname, const char *relname,
|
||||
const char *attname);
|
||||
const char *attname);
|
||||
|
||||
|
||||
/*
|
||||
@@ -111,8 +111,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
/*
|
||||
* check for column projection: if function has one argument, and that
|
||||
* argument is of complex type, and function name is not qualified,
|
||||
* then the "function call" could be a projection. We also check
|
||||
* that there wasn't any aggregate decoration.
|
||||
* then the "function call" could be a projection. We also check that
|
||||
* there wasn't any aggregate decoration.
|
||||
*/
|
||||
if (nargs == 1 && !agg_star && !agg_distinct && length(funcname) == 1)
|
||||
{
|
||||
@@ -123,7 +123,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
{
|
||||
/* First arg is a relation. This could be a projection. */
|
||||
retval = qualifiedNameToVar(pstate,
|
||||
((RangeVar *) first_arg)->schemaname,
|
||||
((RangeVar *) first_arg)->schemaname,
|
||||
((RangeVar *) first_arg)->relname,
|
||||
cname,
|
||||
true);
|
||||
@@ -144,9 +144,9 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
}
|
||||
|
||||
/*
|
||||
* Okay, it's not a column projection, so it must really be a function.
|
||||
* Extract arg type info and transform RangeVar arguments into varnodes
|
||||
* of the appropriate form.
|
||||
* Okay, it's not a column projection, so it must really be a
|
||||
* function. Extract arg type info and transform RangeVar arguments
|
||||
* into varnodes of the appropriate form.
|
||||
*/
|
||||
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
|
||||
|
||||
@@ -199,6 +199,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
toid = exprType(rte->funcexpr);
|
||||
break;
|
||||
default:
|
||||
|
||||
/*
|
||||
* RTE is a join or subselect; must fail for lack of a
|
||||
* named tuple type
|
||||
@@ -209,7 +210,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
else
|
||||
elog(ERROR, "Cannot pass result of sub-select or join %s to a function",
|
||||
relname);
|
||||
toid = InvalidOid; /* keep compiler quiet */
|
||||
toid = InvalidOid; /* keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -228,10 +229,10 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
|
||||
/*
|
||||
* func_get_detail looks up the function in the catalogs, does
|
||||
* disambiguation for polymorphic functions, handles inheritance,
|
||||
* and returns the funcid and type and set or singleton status of
|
||||
* the function's return value. it also returns the true argument
|
||||
* types to the function.
|
||||
* disambiguation for polymorphic functions, handles inheritance, and
|
||||
* returns the funcid and type and set or singleton status of the
|
||||
* function's return value. it also returns the true argument types
|
||||
* to the function.
|
||||
*/
|
||||
fdresult = func_get_detail(funcname, fargs, nargs, oid_array,
|
||||
&funcid, &rettype, &retset,
|
||||
@@ -263,13 +264,13 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
/*
|
||||
* Oops. Time to die.
|
||||
*
|
||||
* If we are dealing with the attribute notation rel.function,
|
||||
* give an error message that is appropriate for that case.
|
||||
* If we are dealing with the attribute notation rel.function, give
|
||||
* an error message that is appropriate for that case.
|
||||
*/
|
||||
if (is_column)
|
||||
{
|
||||
char *colname = strVal(lfirst(funcname));
|
||||
Oid relTypeId;
|
||||
char *colname = strVal(lfirst(funcname));
|
||||
Oid relTypeId;
|
||||
|
||||
Assert(nargs == 1);
|
||||
if (IsA(first_arg, RangeVar))
|
||||
@@ -284,6 +285,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
elog(ERROR, "Attribute \"%s\" not found in datatype %s",
|
||||
colname, format_type_be(relTypeId));
|
||||
}
|
||||
|
||||
/*
|
||||
* Else generate a detailed complaint for a function
|
||||
*/
|
||||
@@ -351,7 +353,7 @@ static int
|
||||
match_argtypes(int nargs,
|
||||
Oid *input_typeids,
|
||||
FuncCandidateList function_typeids,
|
||||
FuncCandidateList *candidates) /* return value */
|
||||
FuncCandidateList *candidates) /* return value */
|
||||
{
|
||||
FuncCandidateList current_candidate;
|
||||
FuncCandidateList next_candidate;
|
||||
@@ -863,7 +865,7 @@ func_get_detail(List *funcname,
|
||||
ftup = SearchSysCache(PROCOID,
|
||||
ObjectIdGetDatum(best_candidate->oid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(ftup)) /* should not happen */
|
||||
if (!HeapTupleIsValid(ftup)) /* should not happen */
|
||||
elog(ERROR, "function %u not found", best_candidate->oid);
|
||||
pform = (Form_pg_proc) GETSTRUCT(ftup);
|
||||
*rettype = pform->prorettype;
|
||||
@@ -1172,7 +1174,7 @@ setup_field_select(Node *input, char *attname, Oid relid)
|
||||
* ParseComplexProjection -
|
||||
* handles function calls with a single argument that is of complex type.
|
||||
* If the function call is actually a column projection, return a suitably
|
||||
* transformed expression tree. If not, return NULL.
|
||||
* transformed expression tree. If not, return NULL.
|
||||
*
|
||||
* NB: argument is expected to be transformed already, ie, not a RangeVar.
|
||||
*/
|
||||
@@ -1194,7 +1196,8 @@ ParseComplexProjection(ParseState *pstate,
|
||||
return NULL; /* funcname does not match any column */
|
||||
|
||||
/*
|
||||
* Check for special cases where we don't want to return a FieldSelect.
|
||||
* Check for special cases where we don't want to return a
|
||||
* FieldSelect.
|
||||
*/
|
||||
switch (nodeTag(first_arg))
|
||||
{
|
||||
@@ -1208,8 +1211,8 @@ ParseComplexProjection(ParseState *pstate,
|
||||
*/
|
||||
if (var->varattno == InvalidAttrNumber)
|
||||
{
|
||||
Oid vartype;
|
||||
int32 vartypmod;
|
||||
Oid vartype;
|
||||
int32 vartypmod;
|
||||
|
||||
get_atttypetypmod(argrelid, attnum,
|
||||
&vartype, &vartypmod);
|
||||
@@ -1313,7 +1316,7 @@ find_aggregate_func(const char *caller, List *aggname, Oid basetype)
|
||||
ftup = SearchSysCache(PROCOID,
|
||||
ObjectIdGetDatum(oid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(ftup)) /* should not happen */
|
||||
if (!HeapTupleIsValid(ftup)) /* should not happen */
|
||||
elog(ERROR, "function %u not found", oid);
|
||||
pform = (Form_pg_proc) GETSTRUCT(ftup);
|
||||
|
||||
@@ -1367,10 +1370,10 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes)
|
||||
Oid
|
||||
LookupFuncNameTypeNames(List *funcname, List *argtypes, const char *caller)
|
||||
{
|
||||
Oid funcoid;
|
||||
Oid argoids[FUNC_MAX_ARGS];
|
||||
int argcount;
|
||||
int i;
|
||||
Oid funcoid;
|
||||
Oid argoids[FUNC_MAX_ARGS];
|
||||
int argcount;
|
||||
int i;
|
||||
|
||||
MemSet(argoids, 0, FUNC_MAX_ARGS * sizeof(Oid));
|
||||
argcount = length(argtypes);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.67 2002/08/26 17:53:58 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.68 2002/09/04 20:31:24 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -135,8 +135,8 @@ make_op(List *opname, Node *ltree, Node *rtree)
|
||||
|
||||
newop = makeOper(oprid(tup), /* opno */
|
||||
InvalidOid, /* opid */
|
||||
opform->oprresult, /* opresulttype */
|
||||
get_func_retset(opform->oprcode)); /* opretset */
|
||||
opform->oprresult, /* opresulttype */
|
||||
get_func_retset(opform->oprcode)); /* opretset */
|
||||
|
||||
result = makeNode(Expr);
|
||||
result->typeOid = opform->oprresult;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.58 2002/07/20 05:16:58 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.59 2002/09/04 20:31:24 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -29,10 +29,10 @@
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
static Oid binary_oper_exact(Oid arg1, Oid arg2,
|
||||
FuncCandidateList candidates);
|
||||
static Oid oper_select_candidate(int nargs, Oid *input_typeids,
|
||||
FuncCandidateList candidates);
|
||||
static Oid binary_oper_exact(Oid arg1, Oid arg2,
|
||||
FuncCandidateList candidates);
|
||||
static Oid oper_select_candidate(int nargs, Oid *input_typeids,
|
||||
FuncCandidateList candidates);
|
||||
static void op_error(List *op, Oid arg1, Oid arg2);
|
||||
static void unary_op_error(List *op, Oid arg, bool is_left_op);
|
||||
|
||||
@@ -52,7 +52,7 @@ Oid
|
||||
LookupOperName(List *opername, Oid oprleft, Oid oprright)
|
||||
{
|
||||
FuncCandidateList clist;
|
||||
char oprkind;
|
||||
char oprkind;
|
||||
|
||||
if (!OidIsValid(oprleft))
|
||||
oprkind = 'l';
|
||||
@@ -85,9 +85,9 @@ Oid
|
||||
LookupOperNameTypeNames(List *opername, TypeName *oprleft,
|
||||
TypeName *oprright, const char *caller)
|
||||
{
|
||||
Oid operoid;
|
||||
Oid leftoid,
|
||||
rightoid;
|
||||
Oid operoid;
|
||||
Oid leftoid,
|
||||
rightoid;
|
||||
|
||||
if (oprleft == NULL)
|
||||
leftoid = InvalidOid;
|
||||
@@ -652,7 +652,10 @@ oper(List *opname, Oid ltypeId, Oid rtypeId, bool noError)
|
||||
* Otherwise, search for the most suitable candidate.
|
||||
*/
|
||||
|
||||
/* Unspecified type for one of the arguments? then use the other */
|
||||
/*
|
||||
* Unspecified type for one of the arguments? then use the
|
||||
* other
|
||||
*/
|
||||
if (rtypeId == InvalidOid)
|
||||
rtypeId = ltypeId;
|
||||
else if (ltypeId == InvalidOid)
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.78 2002/08/29 00:17:04 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.79 2002/09/04 20:31:24 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -36,14 +36,14 @@
|
||||
static Node *scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
|
||||
const char *refname);
|
||||
static Node *scanNameSpaceForRelid(ParseState *pstate, Node *nsnode,
|
||||
Oid relid);
|
||||
Oid relid);
|
||||
static void scanNameSpaceForConflict(ParseState *pstate, Node *nsnode,
|
||||
RangeTblEntry *rte1, const char *aliasname1);
|
||||
static Node *scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
|
||||
char *colname);
|
||||
static bool isForUpdate(ParseState *pstate, char *refname);
|
||||
static bool get_rte_attribute_is_dropped(RangeTblEntry *rte,
|
||||
AttrNumber attnum);
|
||||
AttrNumber attnum);
|
||||
static int specialAttNum(const char *attname);
|
||||
static void warnAutoRange(ParseState *pstate, RangeVar *relation);
|
||||
|
||||
@@ -64,7 +64,7 @@ static void warnAutoRange(ParseState *pstate, RangeVar *relation);
|
||||
*
|
||||
* A qualified refname (schemaname != NULL) can only match a relation RTE
|
||||
* that (a) has no alias and (b) is for the same relation identified by
|
||||
* schemaname.refname. In this case we convert schemaname.refname to a
|
||||
* schemaname.refname. In this case we convert schemaname.refname to a
|
||||
* relation OID and search by relid, rather than by alias name. This is
|
||||
* peculiar, but it's what SQL92 says to do.
|
||||
*/
|
||||
@@ -189,7 +189,7 @@ scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
|
||||
|
||||
/*
|
||||
* Recursively search a namespace for a relation RTE matching the
|
||||
* given relation OID. Return the node if a unique match, or NULL
|
||||
* given relation OID. Return the node if a unique match, or NULL
|
||||
* if no match. Raise error if multiple matches (which shouldn't
|
||||
* happen if the namespace was checked correctly when it was created).
|
||||
*
|
||||
@@ -313,9 +313,7 @@ checkNameSpaceConflicts(ParseState *pstate, Node *namespace1,
|
||||
List *l;
|
||||
|
||||
foreach(l, (List *) namespace1)
|
||||
{
|
||||
checkNameSpaceConflicts(pstate, lfirst(l), namespace2);
|
||||
}
|
||||
}
|
||||
else
|
||||
elog(ERROR, "checkNameSpaceConflicts: unexpected node type %d",
|
||||
@@ -353,6 +351,7 @@ scanNameSpaceForConflict(ParseState *pstate, Node *nsnode,
|
||||
if (strcmp(j->alias->aliasname, aliasname1) == 0)
|
||||
elog(ERROR, "Table name \"%s\" specified more than once",
|
||||
aliasname1);
|
||||
|
||||
/*
|
||||
* Tables within an aliased join are invisible from outside
|
||||
* the join, according to the scope rules of SQL92 (the join
|
||||
@@ -368,9 +367,7 @@ scanNameSpaceForConflict(ParseState *pstate, Node *nsnode,
|
||||
List *l;
|
||||
|
||||
foreach(l, (List *) nsnode)
|
||||
{
|
||||
scanNameSpaceForConflict(pstate, lfirst(l), rte1, aliasname1);
|
||||
}
|
||||
}
|
||||
else
|
||||
elog(ERROR, "scanNameSpaceForConflict: unexpected node type %d",
|
||||
@@ -438,16 +435,16 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname)
|
||||
* Scan the user column names (or aliases) for a match. Complain if
|
||||
* multiple matches.
|
||||
*
|
||||
* Note: because eref->colnames may include names of dropped columns,
|
||||
* we need to check for non-droppedness before accepting a match.
|
||||
* This takes an extra cache lookup, but we can skip the lookup most
|
||||
* of the time by exploiting the knowledge that dropped columns are
|
||||
* assigned dummy names starting with '.', which is an unusual choice
|
||||
* for actual column names.
|
||||
* Note: because eref->colnames may include names of dropped columns, we
|
||||
* need to check for non-droppedness before accepting a match. This
|
||||
* takes an extra cache lookup, but we can skip the lookup most of the
|
||||
* time by exploiting the knowledge that dropped columns are assigned
|
||||
* dummy names starting with '.', which is an unusual choice for
|
||||
* actual column names.
|
||||
*
|
||||
* Should the user try to fool us by altering pg_attribute.attname
|
||||
* for a dropped column, we'll still catch it by virtue of the checks
|
||||
* in get_rte_attribute_type(), which is called by make_var(). That
|
||||
* Should the user try to fool us by altering pg_attribute.attname for a
|
||||
* dropped column, we'll still catch it by virtue of the checks in
|
||||
* get_rte_attribute_type(), which is called by make_var(). That
|
||||
* routine has to do a cache lookup anyway, so the check there is
|
||||
* cheap.
|
||||
*/
|
||||
@@ -456,7 +453,7 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname)
|
||||
attnum++;
|
||||
if (strcmp(strVal(lfirst(c)), colname) == 0)
|
||||
{
|
||||
if (colname[0] == '.' && /* see note above */
|
||||
if (colname[0] == '.' && /* see note above */
|
||||
get_rte_attribute_is_dropped(rte, attnum))
|
||||
continue;
|
||||
if (result)
|
||||
@@ -903,8 +900,8 @@ addRangeTableEntryForFunction(ParseState *pstate,
|
||||
if (coldeflist != NIL)
|
||||
{
|
||||
/*
|
||||
* we *only* allow a coldeflist for functions returning a
|
||||
* RECORD pseudo-type
|
||||
* we *only* allow a coldeflist for functions returning a RECORD
|
||||
* pseudo-type
|
||||
*/
|
||||
if (funcrettype != RECORDOID)
|
||||
elog(ERROR, "A column definition list is only allowed for functions returning RECORD");
|
||||
@@ -935,14 +932,14 @@ addRangeTableEntryForFunction(ParseState *pstate,
|
||||
funcrettype);
|
||||
|
||||
/*
|
||||
* Get the rel's relcache entry. This access ensures that we have an
|
||||
* up-to-date relcache entry for the rel.
|
||||
* Get the rel's relcache entry. This access ensures that we have
|
||||
* an up-to-date relcache entry for the rel.
|
||||
*/
|
||||
rel = relation_open(funcrelid, AccessShareLock);
|
||||
|
||||
/*
|
||||
* Since the rel is open anyway, let's check that the number of column
|
||||
* aliases is reasonable.
|
||||
* Since the rel is open anyway, let's check that the number of
|
||||
* column aliases is reasonable.
|
||||
*/
|
||||
maxattrs = RelationGetNumberOfAttributes(rel);
|
||||
if (maxattrs < numaliases)
|
||||
@@ -960,16 +957,16 @@ addRangeTableEntryForFunction(ParseState *pstate,
|
||||
|
||||
/*
|
||||
* Drop the rel refcount, but keep the access lock till end of
|
||||
* transaction so that the table can't be deleted or have its schema
|
||||
* modified underneath us.
|
||||
* transaction so that the table can't be deleted or have its
|
||||
* schema modified underneath us.
|
||||
*/
|
||||
relation_close(rel, NoLock);
|
||||
}
|
||||
else if (functyptype == 'b' || functyptype == 'd')
|
||||
{
|
||||
/*
|
||||
* Must be a base data type, i.e. scalar.
|
||||
* Just add one alias column named for the function.
|
||||
* Must be a base data type, i.e. scalar. Just add one alias
|
||||
* column named for the function.
|
||||
*/
|
||||
if (numaliases > 1)
|
||||
elog(ERROR, "Too many column aliases specified for function %s",
|
||||
@@ -1270,17 +1267,17 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
|
||||
case RTE_FUNCTION:
|
||||
{
|
||||
/* Function RTE */
|
||||
Oid funcrettype = exprType(rte->funcexpr);
|
||||
char functyptype = get_typtype(funcrettype);
|
||||
List *coldeflist = rte->coldeflist;
|
||||
Oid funcrettype = exprType(rte->funcexpr);
|
||||
char functyptype = get_typtype(funcrettype);
|
||||
List *coldeflist = rte->coldeflist;
|
||||
|
||||
if (functyptype == 'c')
|
||||
{
|
||||
/*
|
||||
* Composite data type, i.e. a table's row type
|
||||
* Same as ordinary relation RTE
|
||||
* Composite data type, i.e. a table's row type Same
|
||||
* as ordinary relation RTE
|
||||
*/
|
||||
Oid funcrelid = typeidTypeRelid(funcrettype);
|
||||
Oid funcrelid = typeidTypeRelid(funcrettype);
|
||||
Relation rel;
|
||||
int maxattrs;
|
||||
int numaliases;
|
||||
@@ -1373,10 +1370,10 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
|
||||
atttypid = typenameTypeId(colDef->typename);
|
||||
|
||||
varnode = makeVar(rtindex,
|
||||
attnum,
|
||||
atttypid,
|
||||
-1,
|
||||
sublevels_up);
|
||||
attnum,
|
||||
atttypid,
|
||||
-1,
|
||||
sublevels_up);
|
||||
|
||||
*colvars = lappend(*colvars, varnode);
|
||||
}
|
||||
@@ -1495,9 +1492,9 @@ get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
|
||||
|
||||
/*
|
||||
* If the RTE is a relation, go to the system catalogs not the
|
||||
* eref->colnames list. This is a little slower but it will give
|
||||
* the right answer if the column has been renamed since the eref
|
||||
* list was built (which can easily happen for rules).
|
||||
* eref->colnames list. This is a little slower but it will give the
|
||||
* right answer if the column has been renamed since the eref list was
|
||||
* built (which can easily happen for rules).
|
||||
*/
|
||||
if (rte->rtekind == RTE_RELATION)
|
||||
{
|
||||
@@ -1509,7 +1506,8 @@ get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise use the column name from eref. There should always be one.
|
||||
* Otherwise use the column name from eref. There should always be
|
||||
* one.
|
||||
*/
|
||||
if (attnum > 0 && attnum <= length(rte->eref->colnames))
|
||||
return strVal(nth(attnum - 1, rte->eref->colnames));
|
||||
@@ -1544,13 +1542,14 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
elog(ERROR, "Relation \"%s\" does not have attribute %d",
|
||||
get_rel_name(rte->relid), attnum);
|
||||
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
|
||||
|
||||
/*
|
||||
* If dropped column, pretend it ain't there. See notes
|
||||
* in scanRTEForColumn.
|
||||
*/
|
||||
if (att_tup->attisdropped)
|
||||
elog(ERROR, "Relation \"%s\" has no column \"%s\"",
|
||||
get_rel_name(rte->relid), NameStr(att_tup->attname));
|
||||
get_rel_name(rte->relid), NameStr(att_tup->attname));
|
||||
*vartype = att_tup->atttypid;
|
||||
*vartypmod = att_tup->atttypmod;
|
||||
ReleaseSysCache(tp);
|
||||
@@ -1579,19 +1578,19 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
case RTE_FUNCTION:
|
||||
{
|
||||
/* Function RTE */
|
||||
Oid funcrettype = exprType(rte->funcexpr);
|
||||
char functyptype = get_typtype(funcrettype);
|
||||
List *coldeflist = rte->coldeflist;
|
||||
Oid funcrettype = exprType(rte->funcexpr);
|
||||
char functyptype = get_typtype(funcrettype);
|
||||
List *coldeflist = rte->coldeflist;
|
||||
|
||||
if (functyptype == 'c')
|
||||
{
|
||||
/*
|
||||
* Composite data type, i.e. a table's row type
|
||||
* Same as ordinary relation RTE
|
||||
* Composite data type, i.e. a table's row type Same
|
||||
* as ordinary relation RTE
|
||||
*/
|
||||
Oid funcrelid = typeidTypeRelid(funcrettype);
|
||||
HeapTuple tp;
|
||||
Form_pg_attribute att_tup;
|
||||
Oid funcrelid = typeidTypeRelid(funcrettype);
|
||||
HeapTuple tp;
|
||||
Form_pg_attribute att_tup;
|
||||
|
||||
if (!OidIsValid(funcrelid))
|
||||
elog(ERROR, "Invalid typrelid for complex type %u",
|
||||
@@ -1606,9 +1605,10 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
elog(ERROR, "Relation \"%s\" does not have attribute %d",
|
||||
get_rel_name(funcrelid), attnum);
|
||||
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
|
||||
|
||||
/*
|
||||
* If dropped column, pretend it ain't there. See notes
|
||||
* in scanRTEForColumn.
|
||||
* If dropped column, pretend it ain't there. See
|
||||
* notes in scanRTEForColumn.
|
||||
*/
|
||||
if (att_tup->attisdropped)
|
||||
elog(ERROR, "Relation \"%s\" has no column \"%s\"",
|
||||
@@ -1639,11 +1639,14 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
break;
|
||||
case RTE_JOIN:
|
||||
{
|
||||
/* Join RTE --- get type info from join RTE's alias variable */
|
||||
Node *aliasvar;
|
||||
/*
|
||||
* Join RTE --- get type info from join RTE's alias
|
||||
* variable
|
||||
*/
|
||||
Node *aliasvar;
|
||||
|
||||
Assert(attnum > 0 && attnum <= length(rte->joinaliasvars));
|
||||
aliasvar = (Node *) nth(attnum-1, rte->joinaliasvars);
|
||||
aliasvar = (Node *) nth(attnum - 1, rte->joinaliasvars);
|
||||
*vartype = exprType(aliasvar);
|
||||
*vartypmod = exprTypmod(aliasvar);
|
||||
}
|
||||
@@ -1661,7 +1664,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
static bool
|
||||
get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
|
||||
{
|
||||
bool result;
|
||||
bool result;
|
||||
|
||||
switch (rte->rtekind)
|
||||
{
|
||||
@@ -1698,11 +1701,11 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
|
||||
if (OidIsValid(funcrelid))
|
||||
{
|
||||
/*
|
||||
* Composite data type, i.e. a table's row type
|
||||
* Same as ordinary relation RTE
|
||||
* Composite data type, i.e. a table's row type Same
|
||||
* as ordinary relation RTE
|
||||
*/
|
||||
HeapTuple tp;
|
||||
Form_pg_attribute att_tup;
|
||||
HeapTuple tp;
|
||||
Form_pg_attribute att_tup;
|
||||
|
||||
tp = SearchSysCache(ATTNUM,
|
||||
ObjectIdGetDatum(funcrelid),
|
||||
@@ -1748,7 +1751,7 @@ attnameAttNum(Relation rd, const char *attname, bool sysColOK)
|
||||
|
||||
for (i = 0; i < rd->rd_rel->relnatts; i++)
|
||||
{
|
||||
Form_pg_attribute att = rd->rd_att->attrs[i];
|
||||
Form_pg_attribute att = rd->rd_att->attrs[i];
|
||||
|
||||
if (namestrcmp(&(att->attname), attname) == 0 && !att->attisdropped)
|
||||
return i + 1;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.88 2002/08/19 15:08:47 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.89 2002/09/04 20:31:24 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -114,7 +114,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
p_target = nconc(p_target,
|
||||
ExpandAllTables(pstate));
|
||||
}
|
||||
else if (strcmp(strVal(nth(numnames-1, fields)), "*") == 0)
|
||||
else if (strcmp(strVal(nth(numnames - 1, fields)), "*") == 0)
|
||||
{
|
||||
/*
|
||||
* Target item is relation.*, expand that table (eg.
|
||||
@@ -136,21 +136,22 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
relname = strVal(lsecond(fields));
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
char *name1 = strVal(lfirst(fields));
|
||||
{
|
||||
char *name1 = strVal(lfirst(fields));
|
||||
|
||||
/*
|
||||
* We check the catalog name and then ignore it.
|
||||
*/
|
||||
if (strcmp(name1, DatabaseName) != 0)
|
||||
elog(ERROR, "Cross-database references are not implemented");
|
||||
schemaname = strVal(lsecond(fields));
|
||||
relname = strVal(lfirst(lnext(lnext(fields))));
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* We check the catalog name and then ignore
|
||||
* it.
|
||||
*/
|
||||
if (strcmp(name1, DatabaseName) != 0)
|
||||
elog(ERROR, "Cross-database references are not implemented");
|
||||
schemaname = strVal(lsecond(fields));
|
||||
relname = strVal(lfirst(lnext(lnext(fields))));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
elog(ERROR, "Invalid qualified name syntax (too many names)");
|
||||
schemaname = NULL; /* keep compiler quiet */
|
||||
schemaname = NULL; /* keep compiler quiet */
|
||||
relname = NULL;
|
||||
break;
|
||||
}
|
||||
@@ -180,8 +181,8 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
InsertDefault *newnode = makeNode(InsertDefault);
|
||||
|
||||
/*
|
||||
* If this is a DEFAULT element, we make a junk entry
|
||||
* which will get dropped on return to transformInsertStmt().
|
||||
* If this is a DEFAULT element, we make a junk entry which
|
||||
* will get dropped on return to transformInsertStmt().
|
||||
*/
|
||||
p_target = lappend(p_target, newnode);
|
||||
}
|
||||
@@ -385,7 +386,7 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
|
||||
|
||||
for (i = 0; i < numcol; i++)
|
||||
{
|
||||
ResTarget *col;
|
||||
ResTarget *col;
|
||||
|
||||
if (attr[i]->attisdropped)
|
||||
continue;
|
||||
@@ -503,7 +504,7 @@ FigureColnameInternal(Node *node, char **name)
|
||||
{
|
||||
case T_ColumnRef:
|
||||
{
|
||||
char *cname = strVal(llast(((ColumnRef *) node)->fields));
|
||||
char *cname = strVal(llast(((ColumnRef *) node)->fields));
|
||||
|
||||
if (strcmp(cname, "*") != 0)
|
||||
{
|
||||
@@ -514,7 +515,7 @@ FigureColnameInternal(Node *node, char **name)
|
||||
break;
|
||||
case T_ExprFieldSelect:
|
||||
{
|
||||
char *fname = strVal(llast(((ExprFieldSelect *) node)->fields));
|
||||
char *fname = strVal(llast(((ExprFieldSelect *) node)->fields));
|
||||
|
||||
if (strcmp(fname, "*") != 0)
|
||||
{
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.49 2002/08/31 22:10:46 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.50 2002/09/04 20:31:24 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -112,7 +112,7 @@ LookupTypeName(const TypeName *typename)
|
||||
if (schemaname)
|
||||
{
|
||||
/* Look in specific schema only */
|
||||
Oid namespaceId;
|
||||
Oid namespaceId;
|
||||
|
||||
namespaceId = LookupExplicitNamespace(schemaname);
|
||||
restype = GetSysCacheOid(TYPENAMENSP,
|
||||
@@ -147,7 +147,7 @@ TypeNameToString(const TypeName *typename)
|
||||
if (typename->names != NIL)
|
||||
{
|
||||
/* Emit possibly-qualified name as-is */
|
||||
List *l;
|
||||
List *l;
|
||||
|
||||
foreach(l, typename->names)
|
||||
{
|
||||
@@ -218,7 +218,7 @@ typenameType(const TypeName *typename)
|
||||
if (!HeapTupleIsValid(tup))
|
||||
elog(ERROR, "Type \"%s\" does not exist",
|
||||
TypeNameToString(typename));
|
||||
if (! ((Form_pg_type) GETSTRUCT(tup))->typisdefined)
|
||||
if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
|
||||
elog(ERROR, "Type \"%s\" is only a shell",
|
||||
TypeNameToString(typename));
|
||||
return (Type) tup;
|
||||
@@ -431,7 +431,7 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod)
|
||||
List *raw_parsetree_list;
|
||||
SelectStmt *stmt;
|
||||
ResTarget *restarget;
|
||||
TypeCast *typecast;
|
||||
TypeCast *typecast;
|
||||
TypeName *typename;
|
||||
|
||||
initStringInfo(&buf);
|
||||
|
@@ -14,7 +14,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.54 2002/08/27 04:55:11 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.55 2002/09/04 20:31:24 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
List *parsetree; /* result of parsing is left here */
|
||||
|
||||
static Oid *param_type_info; /* state for param_type() */
|
||||
static Oid *param_type_info; /* state for param_type() */
|
||||
static int param_count;
|
||||
|
||||
static int lookahead_token; /* one-token lookahead */
|
||||
|
Reference in New Issue
Block a user