mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-27 22:52:07 +02:00
First phase of SCHEMA changes, concentrating on fixing the grammar and
the parsetree representation. As yet we don't *do* anything with schema names, just drop 'em on the floor; but you can enter schema-compatible command syntax, and there's even a primitive CREATE SCHEMA command. No doc updates yet, except to note that you can now extract a field from a function-returning-row's result with (foo(...)).fieldname.
This commit is contained in:
parent
8c9c8ca2b5
commit
95ef6a3448
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.49 2002/03/11 05:03:52 petere Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.50 2002/03/21 16:00:28 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="xfunc">
|
||||
@ -306,7 +306,8 @@ CREATE FUNCTION new_emp() RETURNS EMP AS '
|
||||
<para>
|
||||
The target list order must be exactly the same as
|
||||
that in which the columns appear in the table associated
|
||||
with the composite type.
|
||||
with the composite type. (Naming the columns, as we did above,
|
||||
is irrelevant to the system.)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
@ -328,10 +329,35 @@ ERROR: function declared to return emp returns varchar instead of text at colum
|
||||
there are some unpleasant restrictions on how functions returning
|
||||
composite types can be used. Briefly, when calling a function that
|
||||
returns a row, we cannot retrieve the entire row. We must either
|
||||
project a single attribute out of the row or pass the entire row into
|
||||
extract a single attribute out of the row or pass the entire row into
|
||||
another function. (Trying to display the entire row value will yield
|
||||
a meaningless number.) For example,
|
||||
|
||||
<programlisting>
|
||||
SELECT (new_emp()).name;
|
||||
</programlisting>
|
||||
|
||||
<screen>
|
||||
name
|
||||
------
|
||||
None
|
||||
</screen>
|
||||
|
||||
We need the extra parentheses to keep the parser from getting confused:
|
||||
|
||||
<screen>
|
||||
SELECT new_emp().name;
|
||||
ERROR: parser: parse error at or near "."
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Another approach is to use
|
||||
functional notation for extracting attributes. The simple way
|
||||
to explain this is that we can use the
|
||||
notations <literal>attribute(table)</> and <literal>table.attribute</>
|
||||
interchangeably:
|
||||
|
||||
<programlisting>
|
||||
SELECT name(new_emp());
|
||||
</programlisting>
|
||||
@ -343,13 +369,6 @@ SELECT name(new_emp());
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This example makes use of the
|
||||
function notation for projecting attributes. The simple way
|
||||
to explain this is that we can usually use the
|
||||
notations <literal>attribute(table)</> and <literal>table.attribute</>
|
||||
interchangeably:
|
||||
|
||||
<programlisting>
|
||||
--
|
||||
-- this is the same as:
|
||||
@ -367,19 +386,6 @@ SELECT name(EMP) AS youngster
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The reason why, in general, we must use the function
|
||||
syntax for projecting attributes of function return
|
||||
values is that the parser just doesn't understand
|
||||
the dot syntax for projection when combined
|
||||
with function calls.
|
||||
|
||||
<screen>
|
||||
SELECT new_emp().name AS nobody;
|
||||
ERROR: parser: parse error at or near "."
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Another way to use a function returning a row result is to declare a
|
||||
second function accepting a row type parameter, and pass the function
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.56 2002/03/06 06:09:24 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.57 2002/03/21 16:00:29 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* See acl.h.
|
||||
@ -200,7 +200,7 @@ ExecuteGrantStmt_Table(GrantStmt *stmt)
|
||||
|
||||
foreach(i, stmt->objects)
|
||||
{
|
||||
char *relname = strVal(lfirst(i));
|
||||
char *relname = ((RangeVar *) lfirst(i))->relname;
|
||||
Relation relation;
|
||||
HeapTuple tuple;
|
||||
Form_pg_class pg_class_tuple;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.189 2002/03/20 19:43:34 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.190 2002/03/21 16:00:29 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -1728,7 +1728,7 @@ AddRelationRawConstraints(Relation rel,
|
||||
/*
|
||||
* Transform raw parsetree to executable expression.
|
||||
*/
|
||||
expr = transformExpr(pstate, cdef->raw_expr, EXPR_COLUMN_FIRST);
|
||||
expr = transformExpr(pstate, cdef->raw_expr);
|
||||
|
||||
/*
|
||||
* Make sure it yields a boolean result.
|
||||
@ -1863,7 +1863,7 @@ cookDefault(ParseState *pstate,
|
||||
/*
|
||||
* Transform raw parsetree to executable expression.
|
||||
*/
|
||||
expr = transformExpr(pstate, raw_default, EXPR_COLUMN_FIRST);
|
||||
expr = transformExpr(pstate, raw_default);
|
||||
|
||||
/*
|
||||
* Make sure default expr does not refer to any vars.
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.161 2002/03/14 22:44:50 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.162 2002/03/21 16:00:31 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* The PerformAddAttribute() code, like most of the relation
|
||||
@ -33,7 +33,7 @@
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/command.h"
|
||||
#include "commands/trigger.h"
|
||||
#include "commands/defrem.h" /* For add constraint unique, primary */
|
||||
#include "commands/defrem.h"
|
||||
#include "executor/execdefs.h"
|
||||
#include "executor/executor.h"
|
||||
#include "miscadmin.h"
|
||||
@ -44,7 +44,8 @@
|
||||
#include "parser/parse_expr.h"
|
||||
#include "parser/parse_oper.h"
|
||||
#include "parser/parse_relation.h"
|
||||
#include "parser/analyze.h" /* For add constraint unique, primary */
|
||||
#include "parser/analyze.h"
|
||||
#include "tcop/utility.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
@ -1279,8 +1280,7 @@ AlterTableAddConstraint(char *relationName,
|
||||
* Convert the A_EXPR in raw_expr into an
|
||||
* EXPR
|
||||
*/
|
||||
expr = transformExpr(pstate, constr->raw_expr,
|
||||
EXPR_COLUMN_FIRST);
|
||||
expr = transformExpr(pstate, constr->raw_expr);
|
||||
|
||||
/*
|
||||
* Make sure it yields a boolean result.
|
||||
@ -1366,7 +1366,7 @@ AlterTableAddConstraint(char *relationName,
|
||||
List *list;
|
||||
int count;
|
||||
|
||||
if (is_temp_rel_name(fkconstraint->pktable_name) &&
|
||||
if (is_temp_rel_name(fkconstraint->pktable->relname) &&
|
||||
!is_temp_rel_name(relationName))
|
||||
elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint.");
|
||||
|
||||
@ -1375,10 +1375,10 @@ AlterTableAddConstraint(char *relationName,
|
||||
* someone doesn't delete rows out from under us.
|
||||
*/
|
||||
|
||||
pkrel = heap_openr(fkconstraint->pktable_name, AccessExclusiveLock);
|
||||
pkrel = heap_openr(fkconstraint->pktable->relname, AccessExclusiveLock);
|
||||
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
|
||||
elog(ERROR, "referenced table \"%s\" not a relation",
|
||||
fkconstraint->pktable_name);
|
||||
fkconstraint->pktable->relname);
|
||||
heap_close(pkrel, NoLock);
|
||||
|
||||
/*
|
||||
@ -1417,7 +1417,7 @@ AlterTableAddConstraint(char *relationName,
|
||||
else
|
||||
trig.tgargs[0] = "<unknown>";
|
||||
trig.tgargs[1] = (char *) relationName;
|
||||
trig.tgargs[2] = fkconstraint->pktable_name;
|
||||
trig.tgargs[2] = fkconstraint->pktable->relname;
|
||||
trig.tgargs[3] = fkconstraint->match_type;
|
||||
count = 4;
|
||||
foreach(list, fkconstraint->fk_attrs)
|
||||
@ -1936,9 +1936,10 @@ LockTableCommand(LockStmt *lockstmt)
|
||||
* at a time
|
||||
*/
|
||||
|
||||
foreach(p, lockstmt->rellist)
|
||||
foreach(p, lockstmt->relations)
|
||||
{
|
||||
char *relname = strVal(lfirst(p));
|
||||
RangeVar *relation = lfirst(p);
|
||||
char *relname = relation->relname;
|
||||
int aclresult;
|
||||
Relation rel;
|
||||
|
||||
@ -1962,3 +1963,94 @@ LockTableCommand(LockStmt *lockstmt)
|
||||
relation_close(rel, NoLock); /* close rel, keep lock */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CREATE SCHEMA
|
||||
*/
|
||||
void
|
||||
CreateSchemaCommand(CreateSchemaStmt *stmt)
|
||||
{
|
||||
const char *schemaName = stmt->schemaname;
|
||||
const char *authId = stmt->authid;
|
||||
List *parsetree_list;
|
||||
List *parsetree_item;
|
||||
const char *owner_name;
|
||||
Oid owner_userid;
|
||||
Oid saved_userid;
|
||||
|
||||
saved_userid = GetUserId();
|
||||
|
||||
if (!authId)
|
||||
{
|
||||
owner_userid = saved_userid;
|
||||
owner_name = GetUserName(owner_userid);
|
||||
}
|
||||
else if (superuser())
|
||||
{
|
||||
owner_name = authId;
|
||||
/* The following will error out if user does not exist */
|
||||
owner_userid = get_usesysid(owner_name);
|
||||
/*
|
||||
* Set the current user to the requested authorization so
|
||||
* that objects created in the statement have the requested
|
||||
* owner. (This will revert to session user on error or at
|
||||
* the end of this routine.)
|
||||
*/
|
||||
SetUserId(owner_userid);
|
||||
}
|
||||
else /* not superuser */
|
||||
{
|
||||
owner_userid = saved_userid;
|
||||
owner_name = GetUserName(owner_userid);
|
||||
if (strcmp(authId, owner_name) != 0)
|
||||
elog(ERROR, "CREATE SCHEMA: permission denied"
|
||||
"\n\t\"%s\" is not a superuser, so cannot create a schema for \"%s\"",
|
||||
owner_name, authId);
|
||||
}
|
||||
|
||||
/* FIXME FENN: Create the schema here */
|
||||
(void) schemaName; /* suppress compiler warning for now... */
|
||||
|
||||
/*
|
||||
* Let commands in the schema-element-list know about the schema
|
||||
*/
|
||||
CommandCounterIncrement();
|
||||
|
||||
/*
|
||||
* Examine the list of commands embedded in the CREATE SCHEMA command,
|
||||
* and reorganize them into a sequentially executable order with no
|
||||
* forward references. Note that the result is still a list of raw
|
||||
* parsetrees in need of parse analysis --- we cannot, in general,
|
||||
* run analyze.c on one statement until we have actually executed the
|
||||
* prior ones.
|
||||
*/
|
||||
parsetree_list = analyzeCreateSchemaStmt(stmt);
|
||||
|
||||
/*
|
||||
* Analyze and execute each command contained in the CREATE SCHEMA
|
||||
*/
|
||||
foreach(parsetree_item, parsetree_list)
|
||||
{
|
||||
Node *parsetree = (Node *) lfirst(parsetree_item);
|
||||
List *querytree_list,
|
||||
*querytree_item;
|
||||
|
||||
querytree_list = parse_analyze(parsetree, NULL);
|
||||
|
||||
foreach(querytree_item, querytree_list)
|
||||
{
|
||||
Query *querytree = (Query *) lfirst(querytree_item);
|
||||
|
||||
/* schemas should contain only utility stmts */
|
||||
Assert(querytree->commandType == CMD_UTILITY);
|
||||
/* do this step */
|
||||
ProcessUtility(querytree->utilityStmt, None, NULL);
|
||||
/* make sure later steps can see the object created here */
|
||||
CommandCounterIncrement();
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset current user */
|
||||
SetUserId(saved_userid);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.88 2002/03/20 19:43:42 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.89 2002/03/21 16:00:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -69,7 +69,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
* Truncate relname to appropriate length (probably a waste of time,
|
||||
* as parser should have done this already).
|
||||
*/
|
||||
StrNCpy(relname, stmt->relname, NAMEDATALEN);
|
||||
StrNCpy(relname, (stmt->relation)->relname, NAMEDATALEN);
|
||||
|
||||
/*
|
||||
* Merge domain attributes into the known columns before processing table
|
||||
@ -82,8 +82,9 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
* Look up inheritance ancestors and generate relation schema,
|
||||
* including inherited attributes.
|
||||
*/
|
||||
schema = MergeAttributes(schema, stmt->inhRelnames, stmt->istemp,
|
||||
&inheritOids, &old_constraints, &parentHasOids);
|
||||
schema = MergeAttributes(schema, stmt->inhRelations,
|
||||
stmt->relation->istemp,
|
||||
&inheritOids, &old_constraints, &parentHasOids);
|
||||
|
||||
numberOfAttributes = length(schema);
|
||||
if (numberOfAttributes <= 0)
|
||||
@ -147,7 +148,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
relationId = heap_create_with_catalog(relname, descriptor,
|
||||
relkind,
|
||||
stmt->hasoids || parentHasOids,
|
||||
stmt->istemp,
|
||||
stmt->relation->istemp,
|
||||
allowSystemTableMods);
|
||||
|
||||
StoreCatalogInheritance(relationId, inheritOids);
|
||||
@ -414,6 +415,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
|
||||
/*
|
||||
* Reject duplicate names in the list of parents, too.
|
||||
*
|
||||
* XXX needs to be smarter about schema-qualified table names.
|
||||
*/
|
||||
foreach(entry, supers)
|
||||
{
|
||||
@ -421,9 +424,10 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
|
||||
foreach(rest, lnext(entry))
|
||||
{
|
||||
if (strcmp(strVal(lfirst(entry)), strVal(lfirst(rest))) == 0)
|
||||
if (strcmp(((RangeVar *) lfirst(entry))->relname,
|
||||
((RangeVar *) lfirst(rest))->relname) == 0)
|
||||
elog(ERROR, "CREATE TABLE: inherited relation \"%s\" duplicated",
|
||||
strVal(lfirst(entry)));
|
||||
((RangeVar *) lfirst(entry))->relname);
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,7 +439,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
child_attno = 0;
|
||||
foreach(entry, supers)
|
||||
{
|
||||
char *name = strVal(lfirst(entry));
|
||||
char *name = ((RangeVar *) lfirst(entry))->relname;
|
||||
Relation relation;
|
||||
TupleDesc tupleDesc;
|
||||
TupleConstr *constr;
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.71 2002/03/12 00:51:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.72 2002/03/21 16:00:32 tgl Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -310,9 +310,9 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
|
||||
|
||||
appendStringInfo(str, " on %s",
|
||||
stringStringInfo(rte->relname));
|
||||
if (strcmp(rte->eref->relname, rte->relname) != 0)
|
||||
if (strcmp(rte->eref->aliasname, rte->relname) != 0)
|
||||
appendStringInfo(str, " %s",
|
||||
stringStringInfo(rte->eref->relname));
|
||||
stringStringInfo(rte->eref->aliasname));
|
||||
}
|
||||
break;
|
||||
case T_SubqueryScan:
|
||||
@ -322,7 +322,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
|
||||
es->rtable);
|
||||
|
||||
appendStringInfo(str, " %s",
|
||||
stringStringInfo(rte->eref->relname));
|
||||
stringStringInfo(rte->eref->aliasname));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.71 2002/03/15 19:20:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.72 2002/03/21 16:00:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -123,7 +123,7 @@ DefineSequence(CreateSeqStmt *seq)
|
||||
case SEQ_COL_NAME:
|
||||
typnam->name = "name";
|
||||
coldef->colname = "sequence_name";
|
||||
namestrcpy(&name, seq->seqname);
|
||||
namestrcpy(&name, seq->sequence->relname);
|
||||
value[i - 1] = NameGetDatum(&name);
|
||||
break;
|
||||
case SEQ_COL_LASTVAL:
|
||||
@ -170,15 +170,14 @@ DefineSequence(CreateSeqStmt *seq)
|
||||
stmt->tableElts = lappend(stmt->tableElts, coldef);
|
||||
}
|
||||
|
||||
stmt->relname = seq->seqname;
|
||||
stmt->inhRelnames = NIL;
|
||||
stmt->relation = seq->sequence;
|
||||
stmt->inhRelations = NIL;
|
||||
stmt->constraints = NIL;
|
||||
stmt->istemp = seq->istemp;
|
||||
stmt->hasoids = false;
|
||||
|
||||
DefineRelation(stmt, RELKIND_SEQUENCE);
|
||||
|
||||
rel = heap_openr(seq->seqname, AccessExclusiveLock);
|
||||
rel = heap_openr(seq->sequence->relname, AccessExclusiveLock);
|
||||
tupDesc = RelationGetDescr(rel);
|
||||
|
||||
/* Initialize first page of relation with special magic number */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.105 2002/03/08 04:37:14 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.106 2002/03/21 16:00:34 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -71,10 +71,11 @@ CreateTrigger(CreateTrigStmt *stmt)
|
||||
char *constrname = "";
|
||||
Oid constrrelid = InvalidOid;
|
||||
|
||||
if (!allowSystemTableMods && IsSystemRelationName(stmt->relname))
|
||||
elog(ERROR, "CreateTrigger: can't create trigger for system relation %s", stmt->relname);
|
||||
if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname))
|
||||
elog(ERROR, "CreateTrigger: can't create trigger for system relation %s",
|
||||
stmt->relation->relname);
|
||||
|
||||
if (pg_aclcheck(stmt->relname, GetUserId(),
|
||||
if (pg_aclcheck(stmt->relation->relname, GetUserId(),
|
||||
stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER)
|
||||
!= ACLCHECK_OK)
|
||||
elog(ERROR, "permission denied");
|
||||
@ -89,7 +90,7 @@ CreateTrigger(CreateTrigStmt *stmt)
|
||||
stmt->trigname = constrtrigname;
|
||||
sprintf(constrtrigname, "RI_ConstraintTrigger_%u", newoid());
|
||||
|
||||
if (strcmp(stmt->constrrelname, "") == 0)
|
||||
if (stmt->constrrel == NULL)
|
||||
constrrelid = InvalidOid;
|
||||
else
|
||||
{
|
||||
@ -97,17 +98,17 @@ CreateTrigger(CreateTrigStmt *stmt)
|
||||
* NoLock is probably sufficient here, since we're only
|
||||
* interested in getting the relation's OID...
|
||||
*/
|
||||
rel = heap_openr(stmt->constrrelname, NoLock);
|
||||
rel = heap_openr(stmt->constrrel->relname, NoLock);
|
||||
constrrelid = rel->rd_id;
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
}
|
||||
|
||||
rel = heap_openr(stmt->relname, AccessExclusiveLock);
|
||||
rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
|
||||
|
||||
if (rel->rd_rel->relkind != RELKIND_RELATION)
|
||||
elog(ERROR, "CreateTrigger: relation \"%s\" is not a table",
|
||||
stmt->relname);
|
||||
stmt->relation->relname);
|
||||
|
||||
TRIGGER_CLEAR_TYPE(tgtype);
|
||||
if (stmt->before)
|
||||
@ -159,7 +160,7 @@ CreateTrigger(CreateTrigStmt *stmt)
|
||||
|
||||
if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
|
||||
elog(ERROR, "CreateTrigger: trigger %s already defined on relation %s",
|
||||
stmt->trigname, stmt->relname);
|
||||
stmt->trigname, stmt->relation->relname);
|
||||
found++;
|
||||
}
|
||||
systable_endscan(tgscan);
|
||||
@ -283,11 +284,11 @@ CreateTrigger(CreateTrigStmt *stmt)
|
||||
*/
|
||||
pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
|
||||
tuple = SearchSysCacheCopy(RELNAME,
|
||||
PointerGetDatum(stmt->relname),
|
||||
PointerGetDatum(stmt->relation->relname),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "CreateTrigger: relation %s not found in pg_class",
|
||||
stmt->relname);
|
||||
stmt->relation->relname);
|
||||
|
||||
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
|
||||
simple_heap_update(pgrel, &tuple->t_self, tuple);
|
||||
@ -320,19 +321,19 @@ DropTrigger(DropTrigStmt *stmt)
|
||||
int found = 0;
|
||||
int tgfound = 0;
|
||||
|
||||
if (!allowSystemTableMods && IsSystemRelationName(stmt->relname))
|
||||
if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname))
|
||||
elog(ERROR, "DropTrigger: can't drop trigger for system relation %s",
|
||||
stmt->relname);
|
||||
stmt->relation->relname);
|
||||
|
||||
if (!pg_ownercheck(GetUserId(), stmt->relname, RELNAME))
|
||||
elog(ERROR, "%s: %s", stmt->relname,
|
||||
if (!pg_ownercheck(GetUserId(), stmt->relation->relname, RELNAME))
|
||||
elog(ERROR, "%s: %s", stmt->relation->relname,
|
||||
aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
|
||||
|
||||
rel = heap_openr(stmt->relname, AccessExclusiveLock);
|
||||
rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
|
||||
|
||||
if (rel->rd_rel->relkind != RELKIND_RELATION)
|
||||
elog(ERROR, "DropTrigger: relation \"%s\" is not a table",
|
||||
stmt->relname);
|
||||
stmt->relation->relname);
|
||||
|
||||
/*
|
||||
* Search pg_trigger, delete target trigger, count remaining triggers
|
||||
@ -366,10 +367,10 @@ DropTrigger(DropTrigStmt *stmt)
|
||||
|
||||
if (tgfound == 0)
|
||||
elog(ERROR, "DropTrigger: there is no trigger %s on relation %s",
|
||||
stmt->trigname, stmt->relname);
|
||||
stmt->trigname, stmt->relation->relname);
|
||||
if (tgfound > 1)
|
||||
elog(NOTICE, "DropTrigger: found (and deleted) %d triggers %s on relation %s",
|
||||
tgfound, stmt->trigname, stmt->relname);
|
||||
tgfound, stmt->trigname, stmt->relation->relname);
|
||||
|
||||
/*
|
||||
* Update relation's pg_class entry. Crucial side-effect: other
|
||||
@ -378,11 +379,11 @@ DropTrigger(DropTrigStmt *stmt)
|
||||
*/
|
||||
pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
|
||||
tuple = SearchSysCacheCopy(RELNAME,
|
||||
PointerGetDatum(stmt->relname),
|
||||
PointerGetDatum(stmt->relation->relname),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "DropTrigger: relation %s not found in pg_class",
|
||||
stmt->relname);
|
||||
stmt->relation->relname);
|
||||
|
||||
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
|
||||
simple_heap_update(pgrel, &tuple->t_self, tuple);
|
||||
@ -478,20 +479,23 @@ RelationRemoveTriggers(Relation rel)
|
||||
{
|
||||
Form_pg_trigger pg_trigger;
|
||||
Relation refrel;
|
||||
DropTrigStmt stmt;
|
||||
DropTrigStmt *stmt = makeNode(DropTrigStmt);
|
||||
|
||||
pg_trigger = (Form_pg_trigger) GETSTRUCT(tup);
|
||||
|
||||
stmt.trigname = pstrdup(NameStr(pg_trigger->tgname));
|
||||
stmt->trigname = pstrdup(NameStr(pg_trigger->tgname));
|
||||
|
||||
/* May as well grab AccessExclusiveLock, since DropTrigger will. */
|
||||
refrel = heap_open(pg_trigger->tgrelid, AccessExclusiveLock);
|
||||
stmt.relname = pstrdup(RelationGetRelationName(refrel));
|
||||
stmt->relation = makeNode(RangeVar);
|
||||
/* XXX bogus: what about schema? */
|
||||
stmt->relation->relname = pstrdup(RelationGetRelationName(refrel));
|
||||
heap_close(refrel, NoLock);
|
||||
|
||||
elog(NOTICE, "DROP TABLE implicitly drops referential integrity trigger from table \"%s\"", stmt.relname);
|
||||
elog(NOTICE, "DROP TABLE implicitly drops referential integrity trigger from table \"%s\"",
|
||||
stmt->relation->relname);
|
||||
|
||||
DropTrigger(&stmt);
|
||||
DropTrigger(stmt);
|
||||
|
||||
/*
|
||||
* Need to do a command counter increment here to show up new
|
||||
@ -500,9 +504,6 @@ RelationRemoveTriggers(Relation rel)
|
||||
* FK table defined on the PK table).
|
||||
*/
|
||||
CommandCounterIncrement();
|
||||
|
||||
pfree(stmt.relname);
|
||||
pfree(stmt.trigname);
|
||||
}
|
||||
systable_endscan(tgscan);
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.217 2002/03/06 06:09:38 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.218 2002/03/21 16:00:35 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -209,10 +209,10 @@ vacuum(VacuumStmt *vacstmt)
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
|
||||
/* Convert vacrel, which is just a string, to a Name */
|
||||
if (vacstmt->vacrel)
|
||||
/* Convert relname, which is just a string, to a Name */
|
||||
if (vacstmt->relation)
|
||||
{
|
||||
namestrcpy(&VacRel, vacstmt->vacrel);
|
||||
namestrcpy(&VacRel, vacstmt->relation->relname);
|
||||
VacRelName = &VacRel;
|
||||
}
|
||||
else
|
||||
@ -268,7 +268,7 @@ vacuum(VacuumStmt *vacstmt)
|
||||
static void
|
||||
vacuum_init(VacuumStmt *vacstmt)
|
||||
{
|
||||
if (vacstmt->vacuum && vacstmt->vacrel == NULL)
|
||||
if (vacstmt->vacuum && vacstmt->relation == NULL)
|
||||
{
|
||||
/*
|
||||
* Compute the initially applicable OldestXmin and FreezeLimit
|
||||
@ -308,7 +308,7 @@ vacuum_shutdown(VacuumStmt *vacstmt)
|
||||
* row with info about the transaction IDs used, and try to truncate
|
||||
* pg_clog.
|
||||
*/
|
||||
if (vacstmt->vacuum && vacstmt->vacrel == NULL)
|
||||
if (vacstmt->vacuum && vacstmt->relation == NULL)
|
||||
{
|
||||
vac_update_dbstats(MyDatabaseId,
|
||||
initialOldestXmin, initialFreezeLimit);
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: view.c,v 1.58 2001/10/25 05:49:26 momjian Exp $
|
||||
* $Id: view.c,v 1.59 2002/03/21 16:00:36 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -41,6 +41,7 @@ static void
|
||||
DefineVirtualRelation(char *relname, List *tlist)
|
||||
{
|
||||
CreateStmt *createStmt = makeNode(CreateStmt);
|
||||
RangeVar *rel = makeNode(RangeVar);
|
||||
List *attrList,
|
||||
*t;
|
||||
|
||||
@ -83,11 +84,13 @@ DefineVirtualRelation(char *relname, List *tlist)
|
||||
* now create the parameters for keys/inheritance etc. All of them are
|
||||
* nil...
|
||||
*/
|
||||
createStmt->relname = relname;
|
||||
rel->relname = relname;
|
||||
rel->schemaname = NULL; /* XXX wrong */
|
||||
rel->istemp = false;
|
||||
createStmt->relation = rel;
|
||||
createStmt->tableElts = attrList;
|
||||
createStmt->inhRelnames = NIL;
|
||||
createStmt->inhRelations = NIL;
|
||||
createStmt->constraints = NIL;
|
||||
createStmt->istemp = false;
|
||||
createStmt->hasoids = false;
|
||||
|
||||
/*
|
||||
@ -101,21 +104,24 @@ FormViewRetrieveRule(char *viewName, Query *viewParse)
|
||||
{
|
||||
RuleStmt *rule;
|
||||
char *rname;
|
||||
Attr *attr;
|
||||
RangeVar *rel;
|
||||
|
||||
/*
|
||||
* Create a RuleStmt that corresponds to the suitable rewrite rule
|
||||
* args for DefineQueryRewrite();
|
||||
*/
|
||||
rule = makeNode(RuleStmt);
|
||||
rname = MakeRetrieveViewRuleName(viewName);
|
||||
|
||||
attr = makeNode(Attr);
|
||||
attr->relname = pstrdup(viewName);
|
||||
rel = makeNode(RangeVar);
|
||||
rel->relname = pstrdup(viewName);
|
||||
rel->inhOpt = INH_NO;
|
||||
rel->alias = NULL;
|
||||
|
||||
rule = makeNode(RuleStmt);
|
||||
rule->relation = rel;
|
||||
rule->rulename = pstrdup(rname);
|
||||
rule->whereClause = NULL;
|
||||
rule->event = CMD_SELECT;
|
||||
rule->object = attr;
|
||||
rule->instead = true;
|
||||
rule->actions = makeList1(viewParse);
|
||||
|
||||
@ -191,10 +197,10 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
|
||||
* table... OLD first, then NEW....
|
||||
*/
|
||||
rt_entry1 = addRangeTableEntry(NULL, viewName,
|
||||
makeAttr("*OLD*", NULL),
|
||||
makeAlias("*OLD*", NIL),
|
||||
false, false);
|
||||
rt_entry2 = addRangeTableEntry(NULL, viewName,
|
||||
makeAttr("*NEW*", NULL),
|
||||
makeAlias("*NEW*", NIL),
|
||||
false, false);
|
||||
/* Must override addRangeTableEntry's default access-check flags */
|
||||
rt_entry1->checkForRead = false;
|
||||
|
@ -27,7 +27,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.152 2002/03/06 06:09:42 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.153 2002/03/21 16:00:37 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -707,7 +707,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
|
||||
/*
|
||||
* create the "into" relation
|
||||
*/
|
||||
intoName = parseTree->into;
|
||||
intoName = parseTree->into->relname;
|
||||
|
||||
/*
|
||||
* have to copy tupType to get rid of constraints
|
||||
@ -718,7 +718,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
|
||||
heap_create_with_catalog(intoName,
|
||||
tupdesc,
|
||||
RELKIND_RELATION, true,
|
||||
parseTree->isTemp,
|
||||
parseTree->into->istemp,
|
||||
allowSystemTableMods);
|
||||
|
||||
FreeTupleDesc(tupdesc);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.67 2002/02/27 19:34:59 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.68 2002/03/21 16:00:38 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -775,7 +775,8 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
|
||||
|
||||
/* Modify the parsetree to be a cursor */
|
||||
queryTree->isPortal = true;
|
||||
queryTree->into = pstrdup(name);
|
||||
queryTree->into = makeNode(RangeVar);
|
||||
queryTree->into->relname = pstrdup(name);
|
||||
queryTree->isBinary = false;
|
||||
|
||||
/* Create the QueryDesc object and the executor state */
|
||||
@ -1145,7 +1146,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
|
||||
if (parseTree->isPortal)
|
||||
{
|
||||
isRetrieveIntoPortal = true;
|
||||
intoName = parseTree->into;
|
||||
intoName = parseTree->into->relname;
|
||||
parseTree->isBinary = false; /* */
|
||||
|
||||
return SPI_ERROR_CURSOR;
|
||||
|
@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.171 2002/03/20 19:43:58 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.172 2002/03/21 16:00:39 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -733,18 +733,6 @@ _copyVar(Var *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static Attr *
|
||||
_copyAttr(Attr *from)
|
||||
{
|
||||
Attr *newnode = makeNode(Attr);
|
||||
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, attrs);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _copyOper
|
||||
* ----------------
|
||||
@ -1515,8 +1503,7 @@ _copyFkConstraint(FkConstraint *from)
|
||||
|
||||
if (from->constr_name)
|
||||
newnode->constr_name = pstrdup(from->constr_name);
|
||||
if (from->pktable_name)
|
||||
newnode->pktable_name = pstrdup(from->pktable_name);
|
||||
Node_Copy(from, newnode, pktable);
|
||||
Node_Copy(from, newnode, fk_attrs);
|
||||
Node_Copy(from, newnode, pk_attrs);
|
||||
if (from->match_type)
|
||||
@ -1553,6 +1540,29 @@ _copyAExpr(A_Expr *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static ColumnRef *
|
||||
_copyColumnRef(ColumnRef *from)
|
||||
{
|
||||
ColumnRef *newnode = makeNode(ColumnRef);
|
||||
|
||||
Node_Copy(from, newnode, fields);
|
||||
Node_Copy(from, newnode, indirection);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static ParamRef *
|
||||
_copyParamRef(ParamRef *from)
|
||||
{
|
||||
ParamRef *newnode = makeNode(ParamRef);
|
||||
|
||||
newnode->number = from->number;
|
||||
Node_Copy(from, newnode, fields);
|
||||
Node_Copy(from, newnode, indirection);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static A_Const *
|
||||
_copyAConst(A_Const *from)
|
||||
{
|
||||
@ -1564,27 +1574,12 @@ _copyAConst(A_Const *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static ParamNo *
|
||||
_copyParamNo(ParamNo *from)
|
||||
{
|
||||
ParamNo *newnode = makeNode(ParamNo);
|
||||
|
||||
newnode->number = from->number;
|
||||
Node_Copy(from, newnode, typename);
|
||||
Node_Copy(from, newnode, indirection);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static Ident *
|
||||
_copyIdent(Ident *from)
|
||||
{
|
||||
Ident *newnode = makeNode(Ident);
|
||||
|
||||
if (from->name)
|
||||
newnode->name = pstrdup(from->name);
|
||||
Node_Copy(from, newnode, indirection);
|
||||
newnode->isRel = from->isRel;
|
||||
newnode->name = pstrdup(from->name);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -1614,6 +1609,18 @@ _copyAIndices(A_Indices *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static ExprFieldSelect *
|
||||
_copyExprFieldSelect(ExprFieldSelect *from)
|
||||
{
|
||||
ExprFieldSelect *newnode = makeNode(ExprFieldSelect);
|
||||
|
||||
Node_Copy(from, newnode, arg);
|
||||
Node_Copy(from, newnode, fields);
|
||||
Node_Copy(from, newnode, indirection);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static ResTarget *
|
||||
_copyResTarget(ResTarget *from)
|
||||
{
|
||||
@ -1654,15 +1661,32 @@ _copySortGroupBy(SortGroupBy *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static Alias *
|
||||
_copyAlias(Alias *from)
|
||||
{
|
||||
Alias *newnode = makeNode(Alias);
|
||||
|
||||
if (from->aliasname)
|
||||
newnode->aliasname = pstrdup(from->aliasname);
|
||||
Node_Copy(from, newnode, colnames);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static RangeVar *
|
||||
_copyRangeVar(RangeVar *from)
|
||||
{
|
||||
RangeVar *newnode = makeNode(RangeVar);
|
||||
|
||||
if (from->catalogname)
|
||||
newnode->catalogname = pstrdup(from->catalogname);
|
||||
if (from->schemaname)
|
||||
newnode->schemaname = pstrdup(from->schemaname);
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
newnode->inhOpt = from->inhOpt;
|
||||
Node_Copy(from, newnode, name);
|
||||
newnode->istemp = from->istemp;
|
||||
Node_Copy(from, newnode, alias);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -1673,7 +1697,7 @@ _copyRangeSubselect(RangeSubselect *from)
|
||||
RangeSubselect *newnode = makeNode(RangeSubselect);
|
||||
|
||||
Node_Copy(from, newnode, subquery);
|
||||
Node_Copy(from, newnode, name);
|
||||
Node_Copy(from, newnode, alias);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -1756,11 +1780,9 @@ _copyQuery(Query *from)
|
||||
newnode->commandType = from->commandType;
|
||||
Node_Copy(from, newnode, utilityStmt);
|
||||
newnode->resultRelation = from->resultRelation;
|
||||
if (from->into)
|
||||
newnode->into = pstrdup(from->into);
|
||||
Node_Copy(from, newnode, into);
|
||||
newnode->isPortal = from->isPortal;
|
||||
newnode->isBinary = from->isBinary;
|
||||
newnode->isTemp = from->isTemp;
|
||||
newnode->hasAggs = from->hasAggs;
|
||||
newnode->hasSubLinks = from->hasSubLinks;
|
||||
newnode->originalQuery = from->originalQuery;
|
||||
@ -1798,8 +1820,7 @@ _copyInsertStmt(InsertStmt *from)
|
||||
{
|
||||
InsertStmt *newnode = makeNode(InsertStmt);
|
||||
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, relation);
|
||||
Node_Copy(from, newnode, cols);
|
||||
Node_Copy(from, newnode, targetList);
|
||||
Node_Copy(from, newnode, selectStmt);
|
||||
@ -1812,10 +1833,8 @@ _copyDeleteStmt(DeleteStmt *from)
|
||||
{
|
||||
DeleteStmt *newnode = makeNode(DeleteStmt);
|
||||
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, relation);
|
||||
Node_Copy(from, newnode, whereClause);
|
||||
newnode->inhOpt = from->inhOpt;
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -1825,12 +1844,10 @@ _copyUpdateStmt(UpdateStmt *from)
|
||||
{
|
||||
UpdateStmt *newnode = makeNode(UpdateStmt);
|
||||
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, relation);
|
||||
Node_Copy(from, newnode, targetList);
|
||||
Node_Copy(from, newnode, whereClause);
|
||||
Node_Copy(from, newnode, fromClause);
|
||||
newnode->inhOpt = from->inhOpt;
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -1841,9 +1858,7 @@ _copySelectStmt(SelectStmt *from)
|
||||
SelectStmt *newnode = makeNode(SelectStmt);
|
||||
|
||||
Node_Copy(from, newnode, distinctClause);
|
||||
if (from->into)
|
||||
newnode->into = pstrdup(from->into);
|
||||
newnode->istemp = from->istemp;
|
||||
Node_Copy(from, newnode, into);
|
||||
Node_Copy(from, newnode, intoColNames);
|
||||
Node_Copy(from, newnode, targetList);
|
||||
Node_Copy(from, newnode, fromClause);
|
||||
@ -1885,9 +1900,7 @@ _copyAlterTableStmt(AlterTableStmt *from)
|
||||
AlterTableStmt *newnode = makeNode(AlterTableStmt);
|
||||
|
||||
newnode->subtype = from->subtype;
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
newnode->inhOpt = from->inhOpt;
|
||||
Node_Copy(from, newnode, relation);
|
||||
if (from->name)
|
||||
newnode->name = pstrdup(from->name);
|
||||
Node_Copy(from, newnode, def);
|
||||
@ -1951,8 +1964,7 @@ _copyClusterStmt(ClusterStmt *from)
|
||||
{
|
||||
ClusterStmt *newnode = makeNode(ClusterStmt);
|
||||
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, relation);
|
||||
if (from->indexname)
|
||||
newnode->indexname = pstrdup(from->indexname);
|
||||
|
||||
@ -1965,8 +1977,7 @@ _copyCopyStmt(CopyStmt *from)
|
||||
CopyStmt *newnode = makeNode(CopyStmt);
|
||||
|
||||
newnode->binary = from->binary;
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, relation);
|
||||
newnode->oids = from->oids;
|
||||
newnode->direction = from->direction;
|
||||
if (from->filename)
|
||||
@ -1984,11 +1995,10 @@ _copyCreateStmt(CreateStmt *from)
|
||||
{
|
||||
CreateStmt *newnode = makeNode(CreateStmt);
|
||||
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, relation);
|
||||
Node_Copy(from, newnode, tableElts);
|
||||
Node_Copy(from, newnode, inhRelnames);
|
||||
Node_Copy(from, newnode, inhRelations);
|
||||
Node_Copy(from, newnode, constraints);
|
||||
newnode->istemp = from->istemp;
|
||||
newnode->hasoids = from->hasoids;
|
||||
|
||||
return newnode;
|
||||
@ -2024,7 +2034,7 @@ _copyDropStmt(DropStmt *from)
|
||||
{
|
||||
DropStmt *newnode = makeNode(DropStmt);
|
||||
|
||||
Node_Copy(from, newnode, names);
|
||||
Node_Copy(from, newnode, objects);
|
||||
newnode->removeType = from->removeType;
|
||||
newnode->behavior = from->behavior;
|
||||
|
||||
@ -2036,7 +2046,7 @@ _copyTruncateStmt(TruncateStmt *from)
|
||||
{
|
||||
TruncateStmt *newnode = makeNode(TruncateStmt);
|
||||
|
||||
newnode->relName = pstrdup(from->relName);
|
||||
Node_Copy(from, newnode, relation);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -2047,6 +2057,8 @@ _copyCommentStmt(CommentStmt *from)
|
||||
CommentStmt *newnode = makeNode(CommentStmt);
|
||||
|
||||
newnode->objtype = from->objtype;
|
||||
if (from->objschema)
|
||||
newnode->objschema = pstrdup(from->objschema);
|
||||
newnode->objname = pstrdup(from->objname);
|
||||
if (from->objproperty)
|
||||
newnode->objproperty = pstrdup(from->objproperty);
|
||||
@ -2075,7 +2087,7 @@ _copyIndexStmt(IndexStmt *from)
|
||||
IndexStmt *newnode = makeNode(IndexStmt);
|
||||
|
||||
newnode->idxname = pstrdup(from->idxname);
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, relation);
|
||||
newnode->accessMethod = pstrdup(from->accessMethod);
|
||||
Node_Copy(from, newnode, indexParams);
|
||||
Node_Copy(from, newnode, whereClause);
|
||||
@ -2140,8 +2152,7 @@ _copyRenameStmt(RenameStmt *from)
|
||||
{
|
||||
RenameStmt *newnode = makeNode(RenameStmt);
|
||||
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
newnode->inhOpt = from->inhOpt;
|
||||
Node_Copy(from, newnode, relation);
|
||||
if (from->column)
|
||||
newnode->column = pstrdup(from->column);
|
||||
if (from->newname)
|
||||
@ -2155,10 +2166,10 @@ _copyRuleStmt(RuleStmt *from)
|
||||
{
|
||||
RuleStmt *newnode = makeNode(RuleStmt);
|
||||
|
||||
Node_Copy(from, newnode, relation);
|
||||
newnode->rulename = pstrdup(from->rulename);
|
||||
Node_Copy(from, newnode, whereClause);
|
||||
newnode->event = from->event;
|
||||
Node_Copy(from, newnode, object);
|
||||
newnode->instead = from->instead;
|
||||
Node_Copy(from, newnode, actions);
|
||||
|
||||
@ -2170,8 +2181,7 @@ _copyNotifyStmt(NotifyStmt *from)
|
||||
{
|
||||
NotifyStmt *newnode = makeNode(NotifyStmt);
|
||||
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, relation);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -2181,8 +2191,7 @@ _copyListenStmt(ListenStmt *from)
|
||||
{
|
||||
ListenStmt *newnode = makeNode(ListenStmt);
|
||||
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, relation);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -2192,8 +2201,7 @@ _copyUnlistenStmt(UnlistenStmt *from)
|
||||
{
|
||||
UnlistenStmt *newnode = makeNode(UnlistenStmt);
|
||||
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, relation);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -2213,8 +2221,7 @@ _copyViewStmt(ViewStmt *from)
|
||||
{
|
||||
ViewStmt *newnode = makeNode(ViewStmt);
|
||||
|
||||
if (from->viewname)
|
||||
newnode->viewname = pstrdup(from->viewname);
|
||||
Node_Copy(from, newnode, view);
|
||||
Node_Copy(from, newnode, aliases);
|
||||
Node_Copy(from, newnode, query);
|
||||
|
||||
@ -2298,8 +2305,7 @@ _copyVacuumStmt(VacuumStmt *from)
|
||||
newnode->analyze = from->analyze;
|
||||
newnode->freeze = from->freeze;
|
||||
newnode->verbose = from->verbose;
|
||||
if (from->vacrel)
|
||||
newnode->vacrel = pstrdup(from->vacrel);
|
||||
Node_Copy(from, newnode, relation);
|
||||
Node_Copy(from, newnode, va_cols);
|
||||
|
||||
return newnode;
|
||||
@ -2322,8 +2328,7 @@ _copyCreateSeqStmt(CreateSeqStmt *from)
|
||||
{
|
||||
CreateSeqStmt *newnode = makeNode(CreateSeqStmt);
|
||||
|
||||
if (from->seqname)
|
||||
newnode->seqname = pstrdup(from->seqname);
|
||||
Node_Copy(from, newnode, sequence);
|
||||
Node_Copy(from, newnode, options);
|
||||
|
||||
return newnode;
|
||||
@ -2370,8 +2375,7 @@ _copyCreateTrigStmt(CreateTrigStmt *from)
|
||||
|
||||
if (from->trigname)
|
||||
newnode->trigname = pstrdup(from->trigname);
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, relation);
|
||||
if (from->funcname)
|
||||
newnode->funcname = pstrdup(from->funcname);
|
||||
Node_Copy(from, newnode, args);
|
||||
@ -2389,8 +2393,7 @@ _copyCreateTrigStmt(CreateTrigStmt *from)
|
||||
newnode->isconstraint = from->isconstraint;
|
||||
newnode->deferrable = from->deferrable;
|
||||
newnode->initdeferred = from->initdeferred;
|
||||
if (from->constrrelname)
|
||||
newnode->constrrelname = pstrdup(from->constrrelname);
|
||||
Node_Copy(from, newnode, constrrel);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -2402,8 +2405,7 @@ _copyDropTrigStmt(DropTrigStmt *from)
|
||||
|
||||
if (from->trigname)
|
||||
newnode->trigname = pstrdup(from->trigname);
|
||||
if (from->relname)
|
||||
newnode->relname = pstrdup(from->relname);
|
||||
Node_Copy(from, newnode, relation);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -2488,7 +2490,7 @@ _copyLockStmt(LockStmt *from)
|
||||
{
|
||||
LockStmt *newnode = makeNode(LockStmt);
|
||||
|
||||
Node_Copy(from, newnode, rellist);
|
||||
Node_Copy(from, newnode, relations);
|
||||
|
||||
newnode->mode = from->mode;
|
||||
|
||||
@ -2548,6 +2550,7 @@ _copyReindexStmt(ReindexStmt *from)
|
||||
ReindexStmt *newnode = makeNode(ReindexStmt);
|
||||
|
||||
newnode->reindexType = from->reindexType;
|
||||
Node_Copy(from, newnode, relation);
|
||||
if (from->name)
|
||||
newnode->name = pstrdup(from->name);
|
||||
newnode->force = from->force;
|
||||
@ -2556,6 +2559,19 @@ _copyReindexStmt(ReindexStmt *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static CreateSchemaStmt *
|
||||
_copyCreateSchemaStmt(CreateSchemaStmt *from)
|
||||
{
|
||||
CreateSchemaStmt *newnode = makeNode(CreateSchemaStmt);
|
||||
|
||||
newnode->schemaname = pstrdup(from->schemaname);
|
||||
if (from->authid)
|
||||
newnode->authid = pstrdup(from->authid);
|
||||
Node_Copy(from, newnode, schemaElts);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
|
||||
/* ****************************************************************
|
||||
* pg_list.h copy functions
|
||||
@ -2888,6 +2904,9 @@ copyObject(void *from)
|
||||
case T_LoadStmt:
|
||||
retval = _copyLoadStmt(from);
|
||||
break;
|
||||
case T_CreateDomainStmt:
|
||||
retval = _copyCreateDomainStmt(from);
|
||||
break;
|
||||
case T_CreatedbStmt:
|
||||
retval = _copyCreatedbStmt(from);
|
||||
break;
|
||||
@ -2960,19 +2979,22 @@ copyObject(void *from)
|
||||
case T_CheckPointStmt:
|
||||
retval = (void *) makeNode(CheckPointStmt);
|
||||
break;
|
||||
case T_CreateSchemaStmt:
|
||||
retval = _copyCreateSchemaStmt(from);
|
||||
break;
|
||||
|
||||
case T_A_Expr:
|
||||
retval = _copyAExpr(from);
|
||||
break;
|
||||
case T_Attr:
|
||||
retval = _copyAttr(from);
|
||||
case T_ColumnRef:
|
||||
retval = _copyColumnRef(from);
|
||||
break;
|
||||
case T_ParamRef:
|
||||
retval = _copyParamRef(from);
|
||||
break;
|
||||
case T_A_Const:
|
||||
retval = _copyAConst(from);
|
||||
break;
|
||||
case T_ParamNo:
|
||||
retval = _copyParamNo(from);
|
||||
break;
|
||||
case T_Ident:
|
||||
retval = _copyIdent(from);
|
||||
break;
|
||||
@ -2982,6 +3004,9 @@ copyObject(void *from)
|
||||
case T_A_Indices:
|
||||
retval = _copyAIndices(from);
|
||||
break;
|
||||
case T_ExprFieldSelect:
|
||||
retval = _copyExprFieldSelect(from);
|
||||
break;
|
||||
case T_ResTarget:
|
||||
retval = _copyResTarget(from);
|
||||
break;
|
||||
@ -2991,6 +3016,9 @@ copyObject(void *from)
|
||||
case T_SortGroupBy:
|
||||
retval = _copySortGroupBy(from);
|
||||
break;
|
||||
case T_Alias:
|
||||
retval = _copyAlias(from);
|
||||
break;
|
||||
case T_RangeVar:
|
||||
retval = _copyRangeVar(from);
|
||||
break;
|
||||
@ -3045,9 +3073,6 @@ copyObject(void *from)
|
||||
case T_FuncWithArgs:
|
||||
retval = _copyFuncWithArgs(from);
|
||||
break;
|
||||
case T_CreateDomainStmt:
|
||||
retval = _copyCreateDomainStmt(from);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "copyObject: don't know how to copy node type %d",
|
||||
|
@ -20,7 +20,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.119 2002/03/20 19:44:01 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.120 2002/03/21 16:00:39 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -579,14 +579,12 @@ _equalQuery(Query *a, Query *b)
|
||||
return false;
|
||||
if (a->resultRelation != b->resultRelation)
|
||||
return false;
|
||||
if (!equalstr(a->into, b->into))
|
||||
if (!equal(a->into, b->into))
|
||||
return false;
|
||||
if (a->isPortal != b->isPortal)
|
||||
return false;
|
||||
if (a->isBinary != b->isBinary)
|
||||
return false;
|
||||
if (a->isTemp != b->isTemp)
|
||||
return false;
|
||||
if (a->hasAggs != b->hasAggs)
|
||||
return false;
|
||||
if (a->hasSubLinks != b->hasSubLinks)
|
||||
@ -629,7 +627,7 @@ _equalQuery(Query *a, Query *b)
|
||||
static bool
|
||||
_equalInsertStmt(InsertStmt *a, InsertStmt *b)
|
||||
{
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (!equal(a->cols, b->cols))
|
||||
return false;
|
||||
@ -644,12 +642,10 @@ _equalInsertStmt(InsertStmt *a, InsertStmt *b)
|
||||
static bool
|
||||
_equalDeleteStmt(DeleteStmt *a, DeleteStmt *b)
|
||||
{
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (!equal(a->whereClause, b->whereClause))
|
||||
return false;
|
||||
if (a->inhOpt != b->inhOpt)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -657,7 +653,7 @@ _equalDeleteStmt(DeleteStmt *a, DeleteStmt *b)
|
||||
static bool
|
||||
_equalUpdateStmt(UpdateStmt *a, UpdateStmt *b)
|
||||
{
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (!equal(a->targetList, b->targetList))
|
||||
return false;
|
||||
@ -665,8 +661,6 @@ _equalUpdateStmt(UpdateStmt *a, UpdateStmt *b)
|
||||
return false;
|
||||
if (!equal(a->fromClause, b->fromClause))
|
||||
return false;
|
||||
if (a->inhOpt != b->inhOpt)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -676,9 +670,7 @@ _equalSelectStmt(SelectStmt *a, SelectStmt *b)
|
||||
{
|
||||
if (!equal(a->distinctClause, b->distinctClause))
|
||||
return false;
|
||||
if (!equalstr(a->into, b->into))
|
||||
return false;
|
||||
if (a->istemp != b->istemp)
|
||||
if (!equal(a->into, b->into))
|
||||
return false;
|
||||
if (!equal(a->intoColNames, b->intoColNames))
|
||||
return false;
|
||||
@ -738,9 +730,7 @@ _equalAlterTableStmt(AlterTableStmt *a, AlterTableStmt *b)
|
||||
{
|
||||
if (a->subtype != b->subtype)
|
||||
return false;
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
return false;
|
||||
if (a->inhOpt != b->inhOpt)
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (!equalstr(a->name, b->name))
|
||||
return false;
|
||||
@ -795,7 +785,7 @@ _equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
|
||||
static bool
|
||||
_equalClusterStmt(ClusterStmt *a, ClusterStmt *b)
|
||||
{
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (!equalstr(a->indexname, b->indexname))
|
||||
return false;
|
||||
@ -808,7 +798,7 @@ _equalCopyStmt(CopyStmt *a, CopyStmt *b)
|
||||
{
|
||||
if (a->binary != b->binary)
|
||||
return false;
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (a->oids != b->oids)
|
||||
return false;
|
||||
@ -827,16 +817,14 @@ _equalCopyStmt(CopyStmt *a, CopyStmt *b)
|
||||
static bool
|
||||
_equalCreateStmt(CreateStmt *a, CreateStmt *b)
|
||||
{
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (!equal(a->tableElts, b->tableElts))
|
||||
return false;
|
||||
if (!equal(a->inhRelnames, b->inhRelnames))
|
||||
if (!equal(a->inhRelations, b->inhRelations))
|
||||
return false;
|
||||
if (!equal(a->constraints, b->constraints))
|
||||
return false;
|
||||
if (a->istemp != b->istemp)
|
||||
return false;
|
||||
if (a->hasoids != b->hasoids)
|
||||
return false;
|
||||
|
||||
@ -874,7 +862,7 @@ _equalDefineStmt(DefineStmt *a, DefineStmt *b)
|
||||
static bool
|
||||
_equalDropStmt(DropStmt *a, DropStmt *b)
|
||||
{
|
||||
if (!equal(a->names, b->names))
|
||||
if (!equal(a->objects, b->objects))
|
||||
return false;
|
||||
if (a->removeType != b->removeType)
|
||||
return false;
|
||||
@ -887,7 +875,7 @@ _equalDropStmt(DropStmt *a, DropStmt *b)
|
||||
static bool
|
||||
_equalTruncateStmt(TruncateStmt *a, TruncateStmt *b)
|
||||
{
|
||||
if (!equalstr(a->relName, b->relName))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -900,6 +888,8 @@ _equalCommentStmt(CommentStmt *a, CommentStmt *b)
|
||||
return false;
|
||||
if (!equalstr(a->objname, b->objname))
|
||||
return false;
|
||||
if (!equalstr(a->objschema, b->objschema))
|
||||
return false;
|
||||
if (!equalstr(a->objproperty, b->objproperty))
|
||||
return false;
|
||||
if (!equal(a->objlist, b->objlist))
|
||||
@ -930,7 +920,7 @@ _equalIndexStmt(IndexStmt *a, IndexStmt *b)
|
||||
{
|
||||
if (!equalstr(a->idxname, b->idxname))
|
||||
return false;
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (!equalstr(a->accessMethod, b->accessMethod))
|
||||
return false;
|
||||
@ -1006,9 +996,7 @@ _equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b)
|
||||
static bool
|
||||
_equalRenameStmt(RenameStmt *a, RenameStmt *b)
|
||||
{
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
return false;
|
||||
if (a->inhOpt != b->inhOpt)
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (!equalstr(a->column, b->column))
|
||||
return false;
|
||||
@ -1021,14 +1009,14 @@ _equalRenameStmt(RenameStmt *a, RenameStmt *b)
|
||||
static bool
|
||||
_equalRuleStmt(RuleStmt *a, RuleStmt *b)
|
||||
{
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (!equalstr(a->rulename, b->rulename))
|
||||
return false;
|
||||
if (!equal(a->whereClause, b->whereClause))
|
||||
return false;
|
||||
if (a->event != b->event)
|
||||
return false;
|
||||
if (!equal(a->object, b->object))
|
||||
return false;
|
||||
if (a->instead != b->instead)
|
||||
return false;
|
||||
if (!equal(a->actions, b->actions))
|
||||
@ -1040,7 +1028,7 @@ _equalRuleStmt(RuleStmt *a, RuleStmt *b)
|
||||
static bool
|
||||
_equalNotifyStmt(NotifyStmt *a, NotifyStmt *b)
|
||||
{
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -1049,7 +1037,7 @@ _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b)
|
||||
static bool
|
||||
_equalListenStmt(ListenStmt *a, ListenStmt *b)
|
||||
{
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -1058,7 +1046,7 @@ _equalListenStmt(ListenStmt *a, ListenStmt *b)
|
||||
static bool
|
||||
_equalUnlistenStmt(UnlistenStmt *a, UnlistenStmt *b)
|
||||
{
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -1076,7 +1064,7 @@ _equalTransactionStmt(TransactionStmt *a, TransactionStmt *b)
|
||||
static bool
|
||||
_equalViewStmt(ViewStmt *a, ViewStmt *b)
|
||||
{
|
||||
if (!equalstr(a->viewname, b->viewname))
|
||||
if (!equal(a->view, b->view))
|
||||
return false;
|
||||
if (!equal(a->aliases, b->aliases))
|
||||
return false;
|
||||
@ -1160,7 +1148,7 @@ _equalVacuumStmt(VacuumStmt *a, VacuumStmt *b)
|
||||
return false;
|
||||
if (a->verbose != b->verbose)
|
||||
return false;
|
||||
if (!equalstr(a->vacrel, b->vacrel))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (!equal(a->va_cols, b->va_cols))
|
||||
return false;
|
||||
@ -1184,7 +1172,7 @@ _equalExplainStmt(ExplainStmt *a, ExplainStmt *b)
|
||||
static bool
|
||||
_equalCreateSeqStmt(CreateSeqStmt *a, CreateSeqStmt *b)
|
||||
{
|
||||
if (!equalstr(a->seqname, b->seqname))
|
||||
if (!equal(a->sequence, b->sequence))
|
||||
return false;
|
||||
if (!equal(a->options, b->options))
|
||||
return false;
|
||||
@ -1226,7 +1214,7 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
|
||||
{
|
||||
if (!equalstr(a->trigname, b->trigname))
|
||||
return false;
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (!equalstr(a->funcname, b->funcname))
|
||||
return false;
|
||||
@ -1252,7 +1240,7 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
|
||||
return false;
|
||||
if (a->initdeferred != b->initdeferred)
|
||||
return false;
|
||||
if (!equalstr(a->constrrelname, b->constrrelname))
|
||||
if (!equal(a->constrrel, b->constrrel))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -1263,7 +1251,7 @@ _equalDropTrigStmt(DropTrigStmt *a, DropTrigStmt *b)
|
||||
{
|
||||
if (!equalstr(a->trigname, b->trigname))
|
||||
return false;
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -1340,7 +1328,7 @@ _equalDropUserStmt(DropUserStmt *a, DropUserStmt *b)
|
||||
static bool
|
||||
_equalLockStmt(LockStmt *a, LockStmt *b)
|
||||
{
|
||||
if (!equal(a->rellist, b->rellist))
|
||||
if (!equal(a->relations, b->relations))
|
||||
return false;
|
||||
if (a->mode != b->mode)
|
||||
return false;
|
||||
@ -1397,6 +1385,8 @@ _equalReindexStmt(ReindexStmt *a, ReindexStmt *b)
|
||||
{
|
||||
if (a->reindexType != b->reindexType)
|
||||
return false;
|
||||
if (!equal(a->relation, b->relation))
|
||||
return false;
|
||||
if (!equalstr(a->name, b->name))
|
||||
return false;
|
||||
if (a->force != b->force)
|
||||
@ -1407,6 +1397,19 @@ _equalReindexStmt(ReindexStmt *a, ReindexStmt *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalCreateSchemaStmt(CreateSchemaStmt *a, CreateSchemaStmt *b)
|
||||
{
|
||||
if (!equalstr(a->schemaname, b->schemaname))
|
||||
return false;
|
||||
if (!equalstr(a->authid, b->authid))
|
||||
return false;
|
||||
if (!equal(a->schemaElts, b->schemaElts))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalAExpr(A_Expr *a, A_Expr *b)
|
||||
{
|
||||
@ -1423,13 +1426,22 @@ _equalAExpr(A_Expr *a, A_Expr *b)
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalAttr(Attr *a, Attr *b)
|
||||
_equalColumnRef(ColumnRef *a, ColumnRef *b)
|
||||
{
|
||||
if (strcmp(a->relname, b->relname) != 0)
|
||||
if (!equal(a->fields, b->fields))
|
||||
return false;
|
||||
if (!equal(a->paramNo, b->paramNo))
|
||||
if (!equal(a->indirection, b->indirection))
|
||||
return false;
|
||||
if (!equal(a->attrs, b->attrs))
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalParamRef(ParamRef *a, ParamRef *b)
|
||||
{
|
||||
if (a->number != b->number)
|
||||
return false;
|
||||
if (!equal(a->fields, b->fields))
|
||||
return false;
|
||||
if (!equal(a->indirection, b->indirection))
|
||||
return false;
|
||||
@ -1448,28 +1460,11 @@ _equalAConst(A_Const *a, A_Const *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalParamNo(ParamNo *a, ParamNo *b)
|
||||
{
|
||||
if (a->number != b->number)
|
||||
return false;
|
||||
if (!equal(a->typename, b->typename))
|
||||
return false;
|
||||
if (!equal(a->indirection, b->indirection))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalIdent(Ident *a, Ident *b)
|
||||
{
|
||||
if (!equalstr(a->name, b->name))
|
||||
return false;
|
||||
if (!equal(a->indirection, b->indirection))
|
||||
return false;
|
||||
if (a->isRel != b->isRel)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1500,6 +1495,19 @@ _equalAIndices(A_Indices *a, A_Indices *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalExprFieldSelect(ExprFieldSelect *a, ExprFieldSelect *b)
|
||||
{
|
||||
if (!equal(a->arg, b->arg))
|
||||
return false;
|
||||
if (!equal(a->fields, b->fields))
|
||||
return false;
|
||||
if (!equal(a->indirection, b->indirection))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalResTarget(ResTarget *a, ResTarget *b)
|
||||
{
|
||||
@ -1535,14 +1543,31 @@ _equalSortGroupBy(SortGroupBy *a, SortGroupBy *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalAlias(Alias *a, Alias *b)
|
||||
{
|
||||
if (!equalstr(a->aliasname, b->aliasname))
|
||||
return false;
|
||||
if (!equal(a->colnames, b->colnames))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalRangeVar(RangeVar *a, RangeVar *b)
|
||||
{
|
||||
if (!equalstr(a->catalogname, b->catalogname))
|
||||
return false;
|
||||
if (!equalstr(a->schemaname, b->schemaname))
|
||||
return false;
|
||||
if (!equalstr(a->relname, b->relname))
|
||||
return false;
|
||||
if (a->inhOpt != b->inhOpt)
|
||||
return false;
|
||||
if (!equal(a->name, b->name))
|
||||
if (a->istemp != b->istemp)
|
||||
return false;
|
||||
if (!equal(a->alias, b->alias))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -1553,7 +1578,7 @@ _equalRangeSubselect(RangeSubselect *a, RangeSubselect *b)
|
||||
{
|
||||
if (!equal(a->subquery, b->subquery))
|
||||
return false;
|
||||
if (!equal(a->name, b->name))
|
||||
if (!equal(a->alias, b->alias))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -1704,7 +1729,7 @@ _equalFkConstraint(FkConstraint *a, FkConstraint *b)
|
||||
{
|
||||
if (!equalstr(a->constr_name, b->constr_name))
|
||||
return false;
|
||||
if (!equalstr(a->pktable_name, b->pktable_name))
|
||||
if (!equal(a->pktable, b->pktable))
|
||||
return false;
|
||||
if (!equal(a->fk_attrs, b->fk_attrs))
|
||||
return false;
|
||||
@ -2111,19 +2136,22 @@ equal(void *a, void *b)
|
||||
case T_CheckPointStmt:
|
||||
retval = true;
|
||||
break;
|
||||
case T_CreateSchemaStmt:
|
||||
retval = _equalCreateSchemaStmt(a, b);
|
||||
break;
|
||||
|
||||
case T_A_Expr:
|
||||
retval = _equalAExpr(a, b);
|
||||
break;
|
||||
case T_Attr:
|
||||
retval = _equalAttr(a, b);
|
||||
case T_ColumnRef:
|
||||
retval = _equalColumnRef(a, b);
|
||||
break;
|
||||
case T_ParamRef:
|
||||
retval = _equalParamRef(a, b);
|
||||
break;
|
||||
case T_A_Const:
|
||||
retval = _equalAConst(a, b);
|
||||
break;
|
||||
case T_ParamNo:
|
||||
retval = _equalParamNo(a, b);
|
||||
break;
|
||||
case T_Ident:
|
||||
retval = _equalIdent(a, b);
|
||||
break;
|
||||
@ -2133,6 +2161,9 @@ equal(void *a, void *b)
|
||||
case T_A_Indices:
|
||||
retval = _equalAIndices(a, b);
|
||||
break;
|
||||
case T_ExprFieldSelect:
|
||||
retval = _equalExprFieldSelect(a, b);
|
||||
break;
|
||||
case T_ResTarget:
|
||||
retval = _equalResTarget(a, b);
|
||||
break;
|
||||
@ -2142,6 +2173,9 @@ equal(void *a, void *b)
|
||||
case T_SortGroupBy:
|
||||
retval = _equalSortGroupBy(a, b);
|
||||
break;
|
||||
case T_Alias:
|
||||
retval = _equalAlias(a, b);
|
||||
break;
|
||||
case T_RangeVar:
|
||||
retval = _equalRangeVar(a, b);
|
||||
break;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.27 2002/03/20 19:44:04 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.28 2002/03/21 16:00:40 tgl Exp $
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
@ -159,19 +159,18 @@ makeNullConst(Oid consttype)
|
||||
}
|
||||
|
||||
/*
|
||||
* makeAttr -
|
||||
* creates an Attr node
|
||||
* makeAlias -
|
||||
* creates an Alias node
|
||||
*
|
||||
* NOTE: the given name is copied, but the colnames list (if any) isn't.
|
||||
*/
|
||||
Attr *
|
||||
makeAttr(char *relname, char *attname)
|
||||
Alias *
|
||||
makeAlias(const char *aliasname, List *colnames)
|
||||
{
|
||||
Attr *a = makeNode(Attr);
|
||||
Alias *a = makeNode(Alias);
|
||||
|
||||
a->relname = pstrdup(relname);
|
||||
a->paramNo = NULL;
|
||||
if (attname != NULL)
|
||||
a->attrs = makeList1(makeString(pstrdup(attname)));
|
||||
a->indirection = NULL;
|
||||
a->aliasname = pstrdup(aliasname);
|
||||
a->colnames = colnames;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.16 2001/10/28 06:25:44 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.17 2002/03/21 16:00:40 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -29,7 +29,9 @@ static bool var_is_inner(Var *var);
|
||||
bool
|
||||
single_node(Node *node)
|
||||
{
|
||||
if (IsA(node, Ident) ||IsA(node, Const) ||IsA(node, Var) ||IsA(node, Param))
|
||||
if (IsA(node, Const) ||
|
||||
IsA(node, Var) ||
|
||||
IsA(node, Param))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
@ -103,13 +105,13 @@ replace_opid(Oper *oper)
|
||||
* non_null -
|
||||
* Returns t if the node is a non-null constant, e.g., if the node has a
|
||||
* valid `constvalue' field.
|
||||
*
|
||||
*/
|
||||
bool
|
||||
non_null(Expr *c)
|
||||
{
|
||||
|
||||
if (IsA(c, Const) &&!((Const *) c)->constisnull)
|
||||
if (IsA(c, Const) &&
|
||||
!((Const *) c)->constisnull)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.149 2002/03/12 00:51:39 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.150 2002/03/21 16:00:40 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||
@ -105,20 +105,19 @@ _outOidList(StringInfo str, List *list)
|
||||
static void
|
||||
_outCreateStmt(StringInfo str, CreateStmt *node)
|
||||
{
|
||||
appendStringInfo(str, " CREATE :relname ");
|
||||
_outToken(str, node->relname);
|
||||
appendStringInfo(str, " CREATE :relation ");
|
||||
_outNode(str, node->relation);
|
||||
|
||||
appendStringInfo(str, " :columns ");
|
||||
appendStringInfo(str, " :tableElts ");
|
||||
_outNode(str, node->tableElts);
|
||||
|
||||
appendStringInfo(str, " :inhRelnames ");
|
||||
_outNode(str, node->inhRelnames);
|
||||
appendStringInfo(str, " :inhRelations ");
|
||||
_outNode(str, node->inhRelations);
|
||||
|
||||
appendStringInfo(str, " :constraints ");
|
||||
_outNode(str, node->constraints);
|
||||
|
||||
appendStringInfo(str, " :istemp %s :hasoids %s ",
|
||||
booltostr(node->istemp),
|
||||
appendStringInfo(str, " :hasoids %s ",
|
||||
booltostr(node->hasoids));
|
||||
}
|
||||
|
||||
@ -127,8 +126,8 @@ _outIndexStmt(StringInfo str, IndexStmt *node)
|
||||
{
|
||||
appendStringInfo(str, " INDEX :idxname ");
|
||||
_outToken(str, node->idxname);
|
||||
appendStringInfo(str, " :relname ");
|
||||
_outToken(str, node->relname);
|
||||
appendStringInfo(str, " :relation ");
|
||||
_outNode(str, node->relation);
|
||||
appendStringInfo(str, " :accessMethod ");
|
||||
_outToken(str, node->accessMethod);
|
||||
appendStringInfo(str, " :indexParams ");
|
||||
@ -142,6 +141,13 @@ _outIndexStmt(StringInfo str, IndexStmt *node)
|
||||
booltostr(node->primary));
|
||||
}
|
||||
|
||||
static void
|
||||
_outNotifyStmt(StringInfo str, NotifyStmt *node)
|
||||
{
|
||||
appendStringInfo(str, "NOTIFY :relation ");
|
||||
_outNode(str, node->relation);
|
||||
}
|
||||
|
||||
static void
|
||||
_outSelectStmt(StringInfo str, SelectStmt *node)
|
||||
{
|
||||
@ -213,53 +219,40 @@ _outIndexElem(StringInfo str, IndexElem *node)
|
||||
static void
|
||||
_outQuery(StringInfo str, Query *node)
|
||||
{
|
||||
appendStringInfo(str, " QUERY :command %d :utility ", node->commandType);
|
||||
|
||||
appendStringInfo(str, " QUERY :command %d ", node->commandType);
|
||||
|
||||
/*
|
||||
* Hack to work around missing outfuncs routines for a lot of the
|
||||
* utility-statement node types. (The only one we actually *need*
|
||||
* for rules support is NotifyStmt.) Someday we ought to support
|
||||
* 'em all, but for the meantime do this to avoid getting lots of
|
||||
* warnings when running with debug_print_parse on.
|
||||
*/
|
||||
if (node->utilityStmt)
|
||||
{
|
||||
/*
|
||||
* Hack to make up for lack of outfuncs for utility-stmt nodes
|
||||
*/
|
||||
switch (nodeTag(node->utilityStmt))
|
||||
{
|
||||
case T_CreateStmt:
|
||||
appendStringInfo(str, " :create ");
|
||||
_outToken(str, ((CreateStmt *) (node->utilityStmt))->relname);
|
||||
appendStringInfo(str, " ");
|
||||
_outNode(str, node->utilityStmt);
|
||||
break;
|
||||
|
||||
case T_IndexStmt:
|
||||
appendStringInfo(str, " :index ");
|
||||
_outToken(str, ((IndexStmt *) (node->utilityStmt))->idxname);
|
||||
appendStringInfo(str, " on ");
|
||||
_outToken(str, ((IndexStmt *) (node->utilityStmt))->relname);
|
||||
appendStringInfo(str, " ");
|
||||
case T_NotifyStmt:
|
||||
_outNode(str, node->utilityStmt);
|
||||
break;
|
||||
|
||||
case T_NotifyStmt:
|
||||
appendStringInfo(str, " :notify ");
|
||||
_outToken(str, ((NotifyStmt *) (node->utilityStmt))->relname);
|
||||
break;
|
||||
|
||||
default:
|
||||
appendStringInfo(str, " :utility ? ");
|
||||
appendStringInfo(str, "?");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
appendStringInfo(str, " :utility <>");
|
||||
appendStringInfo(str, "<>");
|
||||
|
||||
appendStringInfo(str, " :resultRelation %d :into ",
|
||||
node->resultRelation);
|
||||
_outToken(str, node->into);
|
||||
_outNode(str, node->into);
|
||||
|
||||
appendStringInfo(str, " :isPortal %s :isBinary %s :isTemp %s"
|
||||
appendStringInfo(str, " :isPortal %s :isBinary %s"
|
||||
" :hasAggs %s :hasSubLinks %s :rtable ",
|
||||
booltostr(node->isPortal),
|
||||
booltostr(node->isBinary),
|
||||
booltostr(node->isTemp),
|
||||
booltostr(node->hasAggs),
|
||||
booltostr(node->hasSubLinks));
|
||||
_outNode(str, node->rtable);
|
||||
@ -963,6 +956,15 @@ _outTargetEntry(StringInfo str, TargetEntry *node)
|
||||
_outNode(str, node->expr);
|
||||
}
|
||||
|
||||
static void
|
||||
_outAlias(StringInfo str, Alias *node)
|
||||
{
|
||||
appendStringInfo(str, " ALIAS :aliasname ");
|
||||
_outToken(str, node->aliasname);
|
||||
appendStringInfo(str, " :colnames ");
|
||||
_outNode(str, node->colnames);
|
||||
}
|
||||
|
||||
static void
|
||||
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
|
||||
{
|
||||
@ -1311,6 +1313,42 @@ _outValue(StringInfo str, Value *value)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_outRangeVar(StringInfo str, RangeVar *node)
|
||||
{
|
||||
appendStringInfo(str, " RANGEVAR :relation ");
|
||||
/*
|
||||
* we deliberately ignore catalogname here, since it is presently not
|
||||
* semantically meaningful
|
||||
*/
|
||||
_outToken(str, node->schemaname);
|
||||
appendStringInfo(str, " . ");
|
||||
_outToken(str, node->relname);
|
||||
appendStringInfo(str, " :inhopt %d :istemp %s",
|
||||
(int) node->inhOpt,
|
||||
booltostr(node->istemp));
|
||||
appendStringInfo(str, " :alias ");
|
||||
_outNode(str, node->alias);
|
||||
}
|
||||
|
||||
static void
|
||||
_outColumnRef(StringInfo str, ColumnRef *node)
|
||||
{
|
||||
appendStringInfo(str, " COLUMNREF :fields ");
|
||||
_outNode(str, node->fields);
|
||||
appendStringInfo(str, " :indirection ");
|
||||
_outNode(str, node->indirection);
|
||||
}
|
||||
|
||||
static void
|
||||
_outParamRef(StringInfo str, ParamRef *node)
|
||||
{
|
||||
appendStringInfo(str, " PARAMREF :number %d :fields ", node->number);
|
||||
_outNode(str, node->fields);
|
||||
appendStringInfo(str, " :indirection ");
|
||||
_outNode(str, node->indirection);
|
||||
}
|
||||
|
||||
static void
|
||||
_outIdent(StringInfo str, Ident *node)
|
||||
{
|
||||
@ -1318,15 +1356,6 @@ _outIdent(StringInfo str, Ident *node)
|
||||
_outToken(str, node->name);
|
||||
}
|
||||
|
||||
static void
|
||||
_outAttr(StringInfo str, Attr *node)
|
||||
{
|
||||
appendStringInfo(str, " ATTR :relname ");
|
||||
_outToken(str, node->relname);
|
||||
appendStringInfo(str, " :attrs ");
|
||||
_outNode(str, node->attrs);
|
||||
}
|
||||
|
||||
static void
|
||||
_outAConst(StringInfo str, A_Const *node)
|
||||
{
|
||||
@ -1336,6 +1365,17 @@ _outAConst(StringInfo str, A_Const *node)
|
||||
_outNode(str, node->typename);
|
||||
}
|
||||
|
||||
static void
|
||||
_outExprFieldSelect(StringInfo str, ExprFieldSelect *node)
|
||||
{
|
||||
appendStringInfo(str, " EXPRFIELDSELECT :arg ");
|
||||
_outNode(str, node->arg);
|
||||
appendStringInfo(str, " :fields ");
|
||||
_outNode(str, node->fields);
|
||||
appendStringInfo(str, " :indirection ");
|
||||
_outNode(str, node->indirection);
|
||||
}
|
||||
|
||||
static void
|
||||
_outConstraint(StringInfo str, Constraint *node)
|
||||
{
|
||||
@ -1384,8 +1424,8 @@ _outFkConstraint(StringInfo str, FkConstraint *node)
|
||||
{
|
||||
appendStringInfo(str, " FKCONSTRAINT :constr_name ");
|
||||
_outToken(str, node->constr_name);
|
||||
appendStringInfo(str, " :pktable_name ");
|
||||
_outToken(str, node->pktable_name);
|
||||
appendStringInfo(str, " :pktable ");
|
||||
_outNode(str, node->pktable);
|
||||
appendStringInfo(str, " :fk_attrs ");
|
||||
_outNode(str, node->fk_attrs);
|
||||
appendStringInfo(str, " :pk_attrs ");
|
||||
@ -1490,6 +1530,12 @@ _outNode(StringInfo str, void *obj)
|
||||
case T_IndexStmt:
|
||||
_outIndexStmt(str, obj);
|
||||
break;
|
||||
case T_NotifyStmt:
|
||||
_outNotifyStmt(str, obj);
|
||||
break;
|
||||
case T_SelectStmt:
|
||||
_outSelectStmt(str, obj);
|
||||
break;
|
||||
case T_ColumnDef:
|
||||
_outColumnDef(str, obj);
|
||||
break;
|
||||
@ -1628,6 +1674,9 @@ _outNode(StringInfo str, void *obj)
|
||||
case T_TargetEntry:
|
||||
_outTargetEntry(str, obj);
|
||||
break;
|
||||
case T_Alias:
|
||||
_outAlias(str, obj);
|
||||
break;
|
||||
case T_RangeTblEntry:
|
||||
_outRangeTblEntry(str, obj);
|
||||
break;
|
||||
@ -1670,12 +1719,24 @@ _outNode(StringInfo str, void *obj)
|
||||
case T_A_Expr:
|
||||
_outAExpr(str, obj);
|
||||
break;
|
||||
case T_RangeVar:
|
||||
_outRangeVar(str, obj);
|
||||
break;
|
||||
case T_ColumnRef:
|
||||
_outColumnRef(str, obj);
|
||||
break;
|
||||
case T_ParamRef:
|
||||
_outParamRef(str, obj);
|
||||
break;
|
||||
case T_Ident:
|
||||
_outIdent(str, obj);
|
||||
break;
|
||||
case T_A_Const:
|
||||
_outAConst(str, obj);
|
||||
break;
|
||||
case T_ExprFieldSelect:
|
||||
_outExprFieldSelect(str, obj);
|
||||
break;
|
||||
case T_Constraint:
|
||||
_outConstraint(str, obj);
|
||||
break;
|
||||
@ -1694,17 +1755,9 @@ _outNode(StringInfo str, void *obj)
|
||||
case T_BooleanTest:
|
||||
_outBooleanTest(str, obj);
|
||||
break;
|
||||
case T_VariableSetStmt:
|
||||
break;
|
||||
case T_SelectStmt:
|
||||
_outSelectStmt(str, obj);
|
||||
break;
|
||||
case T_FuncCall:
|
||||
_outFuncCall(str, obj);
|
||||
break;
|
||||
case T_Attr:
|
||||
_outAttr(str, obj);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(WARNING, "_outNode: don't know how to print type %d ",
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.51 2001/12/20 02:39:26 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.52 2002/03/21 16:00:41 tgl Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -154,10 +154,10 @@ print_rt(List *rtable)
|
||||
|
||||
if (rte->relname)
|
||||
printf("%d\t%s (%s)\t%u",
|
||||
i, rte->relname, rte->eref->relname, rte->relid);
|
||||
i, rte->relname, rte->eref->aliasname, rte->relid);
|
||||
else
|
||||
printf("%d\t[subquery] (%s)\t",
|
||||
i, rte->eref->relname);
|
||||
i, rte->eref->aliasname);
|
||||
printf("\t%s\t%s\n",
|
||||
(rte->inh ? "inh" : ""),
|
||||
(rte->inFromCl ? "inFromCl" : ""));
|
||||
@ -202,7 +202,7 @@ print_expr(Node *expr, List *rtable)
|
||||
Assert(var->varno > 0 &&
|
||||
(int) var->varno <= length(rtable));
|
||||
rte = rt_fetch(var->varno, rtable);
|
||||
relname = rte->eref->relname;
|
||||
relname = rte->eref->aliasname;
|
||||
attname = get_rte_attribute_name(rte, var->varattno);
|
||||
}
|
||||
break;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.116 2002/03/12 00:51:39 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.117 2002/03/21 16:00:42 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Most of the read functions for plan nodes are tested. (In fact, they
|
||||
@ -119,34 +119,19 @@ _readQuery(void)
|
||||
|
||||
local_node = makeNode(Query);
|
||||
|
||||
token = pg_strtok(&length); /* skip the :command */
|
||||
token = pg_strtok(&length); /* get the commandType */
|
||||
token = pg_strtok(&length); /* skip :command */
|
||||
token = pg_strtok(&length); /* get commandType */
|
||||
local_node->commandType = atoi(token);
|
||||
|
||||
token = pg_strtok(&length); /* skip :utility */
|
||||
token = pg_strtok(&length);
|
||||
if (length == 0)
|
||||
local_node->utilityStmt = NULL;
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Hack to make up for lack of readfuncs for utility-stmt nodes
|
||||
*
|
||||
* we can't get create or index here, can we?
|
||||
*/
|
||||
NotifyStmt *n = makeNode(NotifyStmt);
|
||||
local_node->utilityStmt = nodeRead(true);
|
||||
|
||||
n->relname = debackslash(token, length);
|
||||
local_node->utilityStmt = (Node *) n;
|
||||
}
|
||||
|
||||
token = pg_strtok(&length); /* skip the :resultRelation */
|
||||
token = pg_strtok(&length); /* skip :resultRelation */
|
||||
token = pg_strtok(&length); /* get the resultRelation */
|
||||
local_node->resultRelation = atoi(token);
|
||||
|
||||
token = pg_strtok(&length); /* skip :into */
|
||||
token = pg_strtok(&length); /* get into */
|
||||
local_node->into = nullable_string(token, length);
|
||||
local_node->into = nodeRead(true);
|
||||
|
||||
token = pg_strtok(&length); /* skip :isPortal */
|
||||
token = pg_strtok(&length); /* get isPortal */
|
||||
@ -156,10 +141,6 @@ _readQuery(void)
|
||||
token = pg_strtok(&length); /* get isBinary */
|
||||
local_node->isBinary = strtobool(token);
|
||||
|
||||
token = pg_strtok(&length); /* skip :isTemp */
|
||||
token = pg_strtok(&length); /* get isTemp */
|
||||
local_node->isTemp = strtobool(token);
|
||||
|
||||
token = pg_strtok(&length); /* skip the :hasAggs */
|
||||
token = pg_strtok(&length); /* get hasAggs */
|
||||
local_node->hasAggs = strtobool(token);
|
||||
@ -210,6 +191,25 @@ _readQuery(void)
|
||||
return local_node;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _readNotifyStmt
|
||||
* ----------------
|
||||
*/
|
||||
static NotifyStmt *
|
||||
_readNotifyStmt(void)
|
||||
{
|
||||
NotifyStmt *local_node;
|
||||
char *token;
|
||||
int length;
|
||||
|
||||
local_node = makeNode(NotifyStmt);
|
||||
|
||||
token = pg_strtok(&length); /* skip :relation */
|
||||
local_node->relation = nodeRead(true);
|
||||
|
||||
return local_node;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _readSortClause
|
||||
* ----------------
|
||||
@ -1394,21 +1394,93 @@ _readTargetEntry(void)
|
||||
return local_node;
|
||||
}
|
||||
|
||||
static Attr *
|
||||
_readAttr(void)
|
||||
static RangeVar *
|
||||
_readRangeVar(void)
|
||||
{
|
||||
Attr *local_node;
|
||||
RangeVar *local_node;
|
||||
char *token;
|
||||
int length;
|
||||
|
||||
local_node = makeNode(Attr);
|
||||
local_node = makeNode(RangeVar);
|
||||
|
||||
token = pg_strtok(&length); /* eat :relname */
|
||||
local_node->catalogname = NULL; /* not currently saved in output format */
|
||||
|
||||
token = pg_strtok(&length); /* eat :relation */
|
||||
token = pg_strtok(&length); /* get schemaname */
|
||||
local_node->schemaname = nullable_string(token, length);
|
||||
|
||||
token = pg_strtok(&length); /* eat "." */
|
||||
token = pg_strtok(&length); /* get relname */
|
||||
local_node->relname = debackslash(token, length);
|
||||
local_node->relname = nullable_string(token, length);
|
||||
|
||||
token = pg_strtok(&length); /* eat :attrs */
|
||||
local_node->attrs = nodeRead(true); /* now read it */
|
||||
token = pg_strtok(&length); /* eat :inhopt */
|
||||
token = pg_strtok(&length); /* get inhopt */
|
||||
local_node->inhOpt = (InhOption) atoi(token);
|
||||
|
||||
token = pg_strtok(&length); /* eat :istemp */
|
||||
token = pg_strtok(&length); /* get istemp */
|
||||
local_node->istemp = strtobool(token);
|
||||
|
||||
token = pg_strtok(&length); /* eat :alias */
|
||||
local_node->alias = nodeRead(true); /* now read it */
|
||||
|
||||
return local_node;
|
||||
}
|
||||
|
||||
static ColumnRef *
|
||||
_readColumnRef(void)
|
||||
{
|
||||
ColumnRef *local_node;
|
||||
char *token;
|
||||
int length;
|
||||
|
||||
local_node = makeNode(ColumnRef);
|
||||
|
||||
token = pg_strtok(&length); /* eat :fields */
|
||||
local_node->fields = nodeRead(true); /* now read it */
|
||||
|
||||
token = pg_strtok(&length); /* eat :indirection */
|
||||
local_node->indirection = nodeRead(true); /* now read it */
|
||||
|
||||
return local_node;
|
||||
}
|
||||
|
||||
static ExprFieldSelect *
|
||||
_readExprFieldSelect(void)
|
||||
{
|
||||
ExprFieldSelect *local_node;
|
||||
char *token;
|
||||
int length;
|
||||
|
||||
local_node = makeNode(ExprFieldSelect);
|
||||
|
||||
token = pg_strtok(&length); /* eat :arg */
|
||||
local_node->arg = nodeRead(true); /* now read it */
|
||||
|
||||
token = pg_strtok(&length); /* eat :fields */
|
||||
local_node->fields = nodeRead(true); /* now read it */
|
||||
|
||||
token = pg_strtok(&length); /* eat :indirection */
|
||||
local_node->indirection = nodeRead(true); /* now read it */
|
||||
|
||||
return local_node;
|
||||
}
|
||||
|
||||
static Alias *
|
||||
_readAlias(void)
|
||||
{
|
||||
Alias *local_node;
|
||||
char *token;
|
||||
int length;
|
||||
|
||||
local_node = makeNode(Alias);
|
||||
|
||||
token = pg_strtok(&length); /* eat :aliasname */
|
||||
token = pg_strtok(&length); /* get aliasname */
|
||||
local_node->aliasname = debackslash(token, length);
|
||||
|
||||
token = pg_strtok(&length); /* eat :colnames */
|
||||
local_node->colnames = nodeRead(true); /* now read it */
|
||||
|
||||
return local_node;
|
||||
}
|
||||
@ -1994,8 +2066,6 @@ parsePlanString(void)
|
||||
return_value = _readArrayRef();
|
||||
else if (length == 3 && strncmp(token, "VAR", length) == 0)
|
||||
return_value = _readVar();
|
||||
else if (length == 4 && strncmp(token, "ATTR", length) == 0)
|
||||
return_value = _readAttr();
|
||||
else if (length == 5 && strncmp(token, "CONST", length) == 0)
|
||||
return_value = _readConst();
|
||||
else if (length == 4 && strncmp(token, "FUNC", length) == 0)
|
||||
@ -2006,6 +2076,14 @@ parsePlanString(void)
|
||||
return_value = _readParam();
|
||||
else if (length == 11 && strncmp(token, "TARGETENTRY", length) == 0)
|
||||
return_value = _readTargetEntry();
|
||||
else if (length == 8 && strncmp(token, "RANGEVAR", length) == 0)
|
||||
return_value = _readRangeVar();
|
||||
else if (length == 9 && strncmp(token, "COLUMNREF", length) == 0)
|
||||
return_value = _readColumnRef();
|
||||
else if (length == 15 && strncmp(token, "EXPRFIELDSELECT", length) == 0)
|
||||
return_value = _readExprFieldSelect();
|
||||
else if (length == 5 && strncmp(token, "ALIAS", length) == 0)
|
||||
return_value = _readAlias();
|
||||
else if (length == 3 && strncmp(token, "RTE", length) == 0)
|
||||
return_value = _readRangeTblEntry();
|
||||
else if (length == 4 && strncmp(token, "PATH", length) == 0)
|
||||
@ -2032,6 +2110,8 @@ parsePlanString(void)
|
||||
return_value = _readIter();
|
||||
else if (length == 5 && strncmp(token, "QUERY", length) == 0)
|
||||
return_value = _readQuery();
|
||||
else if (length == 6 && strncmp(token, "NOTIFY", length) == 0)
|
||||
return_value = _readNotifyStmt();
|
||||
else if (length == 10 && strncmp(token, "SORTCLAUSE", length) == 0)
|
||||
return_value = _readSortClause();
|
||||
else if (length == 11 && strncmp(token, "GROUPCLAUSE", length) == 0)
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.94 2002/03/12 00:51:50 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.95 2002/03/21 16:00:44 tgl Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -687,7 +687,7 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
|
||||
rte = rt_fetch(var->varno, context->query->rtable);
|
||||
attname = get_rte_attribute_name(rte, var->varattno);
|
||||
elog(ERROR, "Sub-SELECT uses un-GROUPed attribute %s.%s from outer query",
|
||||
rte->eref->relname, attname);
|
||||
rte->eref->aliasname, attname);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1670,7 +1670,6 @@ expression_tree_walker(Node *node,
|
||||
return false;
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_Ident:
|
||||
case T_Const:
|
||||
case T_Var:
|
||||
case T_Param:
|
||||
@ -1963,7 +1962,6 @@ expression_tree_mutator(Node *node,
|
||||
return NULL;
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_Ident:
|
||||
case T_Const:
|
||||
case T_Var:
|
||||
case T_Param:
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.220 2002/03/12 00:51:52 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.221 2002/03/21 16:00:48 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -43,13 +43,30 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* State shared by transformCreateSchemaStmt and its subroutines */
|
||||
typedef struct
|
||||
{
|
||||
const char *stmtType; /* "CREATE TABLE" or "ALTER TABLE" */
|
||||
char *schemaname; /* name of schema */
|
||||
char *authid; /* owner of schema */
|
||||
List *tables; /* CREATE TABLE items */
|
||||
List *views; /* CREATE VIEW items */
|
||||
List *grants; /* GRANT items */
|
||||
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
|
||||
* creating the schema */
|
||||
List *alist; /* "after list" of things to do after
|
||||
* creating the schema */
|
||||
} CreateSchemaStmtContext;
|
||||
|
||||
/* State shared by transformCreateStmt and its subroutines */
|
||||
typedef struct
|
||||
{
|
||||
const char *stmtType; /* "CREATE TABLE" or "ALTER TABLE" */
|
||||
char *relname; /* name of relation */
|
||||
List *inhRelnames; /* names of relations to inherit from */
|
||||
bool istemp; /* is it to be a temp relation? */
|
||||
RangeVar *relation; /* relation to create */
|
||||
List *inhRelations; /* relations to inherit from */
|
||||
bool hasoids; /* does relation have an OID column? */
|
||||
Oid relOid; /* OID of table, if ALTER TABLE case */
|
||||
List *columns; /* ColumnDef items */
|
||||
@ -330,8 +347,8 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
|
||||
qry->commandType = CMD_DELETE;
|
||||
|
||||
/* set up range table with just the result rel */
|
||||
qry->resultRelation = setTargetTable(pstate, stmt->relname,
|
||||
interpretInhOption(stmt->inhOpt),
|
||||
qry->resultRelation = setTargetTable(pstate, stmt->relation->relname,
|
||||
interpretInhOption(stmt->relation->inhOpt),
|
||||
true);
|
||||
|
||||
qry->distinctClause = NIL;
|
||||
@ -398,7 +415,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
* table is also mentioned in the SELECT part. Note that the target
|
||||
* table is not added to the joinlist or namespace.
|
||||
*/
|
||||
qry->resultRelation = setTargetTable(pstate, stmt->relname,
|
||||
qry->resultRelation = setTargetTable(pstate, stmt->relation->relname,
|
||||
false, false);
|
||||
|
||||
/*
|
||||
@ -443,7 +460,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
*/
|
||||
rte = addRangeTableEntryForSubquery(pstate,
|
||||
selectQuery,
|
||||
makeAttr("*SELECT*", NULL),
|
||||
makeAlias("*SELECT*", NIL),
|
||||
true);
|
||||
rtr = makeNode(RangeTblRef);
|
||||
/* assume new rte is at end */
|
||||
@ -515,14 +532,15 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
foreach(tl, qry->targetList)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(tl);
|
||||
Ident *id;
|
||||
ResTarget *col;
|
||||
|
||||
Assert(!tle->resdom->resjunk);
|
||||
if (icolumns == NIL || attnos == NIL)
|
||||
elog(ERROR, "INSERT has more expressions than target columns");
|
||||
id = (Ident *) lfirst(icolumns);
|
||||
updateTargetListEntry(pstate, tle, id->name, lfirsti(attnos),
|
||||
id->indirection);
|
||||
col = (ResTarget *) lfirst(icolumns);
|
||||
Assert(IsA(col, ResTarget));
|
||||
updateTargetListEntry(pstate, tle, col->name, lfirsti(attnos),
|
||||
col->indirection);
|
||||
icolumns = lnext(icolumns);
|
||||
attnos = lnext(attnos);
|
||||
}
|
||||
@ -691,9 +709,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
|
||||
List *elements;
|
||||
|
||||
cxt.stmtType = "CREATE TABLE";
|
||||
cxt.relname = stmt->relname;
|
||||
cxt.inhRelnames = stmt->inhRelnames;
|
||||
cxt.istemp = stmt->istemp;
|
||||
cxt.relation = stmt->relation;
|
||||
cxt.inhRelations = stmt->inhRelations;
|
||||
cxt.hasoids = stmt->hasoids;
|
||||
cxt.relOid = InvalidOid;
|
||||
cxt.columns = NIL;
|
||||
@ -805,7 +822,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
* conflicting constraints the user wrote (like a different
|
||||
* DEFAULT).
|
||||
*/
|
||||
sname = makeObjectName(cxt->relname, column->colname, "seq");
|
||||
sname = makeObjectName((cxt->relation)->relname, column->colname, "seq");
|
||||
|
||||
/*
|
||||
* Create an expression tree representing the function call
|
||||
@ -845,12 +862,12 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
* CREATE/ALTER TABLE.
|
||||
*/
|
||||
sequence = makeNode(CreateSeqStmt);
|
||||
sequence->seqname = pstrdup(sname);
|
||||
sequence->istemp = cxt->istemp;
|
||||
sequence->sequence = copyObject(cxt->relation);
|
||||
sequence->sequence->relname = pstrdup(sname);
|
||||
sequence->options = NIL;
|
||||
|
||||
elog(NOTICE, "%s will create implicit sequence '%s' for SERIAL column '%s.%s'",
|
||||
cxt->stmtType, sequence->seqname, cxt->relname, column->colname);
|
||||
cxt->stmtType, sequence->sequence->relname, (cxt->relation)->relname, column->colname);
|
||||
|
||||
cxt->blist = lappend(cxt->blist, sequence);
|
||||
}
|
||||
@ -875,9 +892,6 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
Ident *id = makeNode(Ident);
|
||||
|
||||
id->name = column->colname;
|
||||
id->indirection = NIL;
|
||||
id->isRel = false;
|
||||
|
||||
fkconstraint->fk_attrs = makeList1(id);
|
||||
|
||||
cxt->fkconstraints = lappend(cxt->fkconstraints, fkconstraint);
|
||||
@ -891,7 +905,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
case CONSTR_NULL:
|
||||
if (saw_nullable && column->is_not_null)
|
||||
elog(ERROR, "%s/(NOT) NULL conflicting declaration for '%s.%s'",
|
||||
cxt->stmtType, cxt->relname, column->colname);
|
||||
cxt->stmtType, (cxt->relation)->relname, column->colname);
|
||||
column->is_not_null = FALSE;
|
||||
saw_nullable = true;
|
||||
break;
|
||||
@ -899,7 +913,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
case CONSTR_NOTNULL:
|
||||
if (saw_nullable && !column->is_not_null)
|
||||
elog(ERROR, "%s/(NOT) NULL conflicting declaration for '%s.%s'",
|
||||
cxt->stmtType, cxt->relname, column->colname);
|
||||
cxt->stmtType, (cxt->relation)->relname, column->colname);
|
||||
column->is_not_null = TRUE;
|
||||
saw_nullable = true;
|
||||
break;
|
||||
@ -907,14 +921,14 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
case CONSTR_DEFAULT:
|
||||
if (column->raw_default != NULL)
|
||||
elog(ERROR, "%s/DEFAULT multiple values specified for '%s.%s'",
|
||||
cxt->stmtType, cxt->relname, column->colname);
|
||||
cxt->stmtType, (cxt->relation)->relname, column->colname);
|
||||
column->raw_default = constraint->raw_expr;
|
||||
Assert(constraint->cooked_expr == NULL);
|
||||
break;
|
||||
|
||||
case CONSTR_PRIMARY:
|
||||
if (constraint->name == NULL)
|
||||
constraint->name = makeObjectName(cxt->relname,
|
||||
constraint->name = makeObjectName((cxt->relation)->relname,
|
||||
NULL,
|
||||
"pkey");
|
||||
if (constraint->keys == NIL)
|
||||
@ -928,7 +942,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
|
||||
case CONSTR_UNIQUE:
|
||||
if (constraint->name == NULL)
|
||||
constraint->name = makeObjectName(cxt->relname,
|
||||
constraint->name = makeObjectName((cxt->relation)->relname,
|
||||
column->colname,
|
||||
"key");
|
||||
if (constraint->keys == NIL)
|
||||
@ -942,7 +956,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
|
||||
case CONSTR_CHECK:
|
||||
if (constraint->name == NULL)
|
||||
constraint->name = makeObjectName(cxt->relname,
|
||||
constraint->name = makeObjectName((cxt->relation)->relname,
|
||||
column->colname,
|
||||
NULL);
|
||||
cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
|
||||
@ -970,7 +984,7 @@ transformTableConstraint(ParseState *pstate, CreateStmtContext *cxt,
|
||||
{
|
||||
case CONSTR_PRIMARY:
|
||||
if (constraint->name == NULL)
|
||||
constraint->name = makeObjectName(cxt->relname,
|
||||
constraint->name = makeObjectName((cxt->relation)->relname,
|
||||
NULL,
|
||||
"pkey");
|
||||
cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
|
||||
@ -1034,21 +1048,21 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
/* In ALTER TABLE case, a primary index might already exist */
|
||||
if (cxt->pkey != NULL ||
|
||||
(OidIsValid(cxt->relOid) &&
|
||||
relationHasPrimaryKey(cxt->relname)))
|
||||
relationHasPrimaryKey((cxt->relation)->relname)))
|
||||
elog(ERROR, "%s / PRIMARY KEY multiple primary keys"
|
||||
" for table '%s' are not allowed",
|
||||
cxt->stmtType, cxt->relname);
|
||||
cxt->stmtType, (cxt->relation)->relname);
|
||||
cxt->pkey = index;
|
||||
}
|
||||
|
||||
if (constraint->name != NULL)
|
||||
index->idxname = pstrdup(constraint->name);
|
||||
else if (constraint->contype == CONSTR_PRIMARY)
|
||||
index->idxname = makeObjectName(cxt->relname, NULL, "pkey");
|
||||
index->idxname = makeObjectName((cxt->relation)->relname, NULL, "pkey");
|
||||
else
|
||||
index->idxname = NULL; /* will set it later */
|
||||
|
||||
index->relname = cxt->relname;
|
||||
index->relation = cxt->relation;
|
||||
index->accessMethod = DEFAULT_INDEX_TYPE;
|
||||
index->indexParams = NIL;
|
||||
index->whereClause = NULL;
|
||||
@ -1089,19 +1103,19 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
*/
|
||||
found = true;
|
||||
}
|
||||
else if (cxt->inhRelnames)
|
||||
else if (cxt->inhRelations)
|
||||
{
|
||||
/* try inherited tables */
|
||||
List *inher;
|
||||
|
||||
foreach(inher, cxt->inhRelnames)
|
||||
foreach(inher, cxt->inhRelations)
|
||||
{
|
||||
Value *inh = lfirst(inher);
|
||||
RangeVar *inh = lfirst(inher);
|
||||
Relation rel;
|
||||
int count;
|
||||
|
||||
Assert(IsA(inh, String));
|
||||
rel = heap_openr(strVal(inh), AccessShareLock);
|
||||
Assert(IsA(inh, RangeVar));
|
||||
rel = heap_openr(inh->relname, AccessShareLock);
|
||||
if (rel->rd_rel->relkind != RELKIND_RELATION)
|
||||
elog(ERROR, "inherited table \"%s\" is not a relation",
|
||||
strVal(inh));
|
||||
@ -1257,7 +1271,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
if (index->idxname == NULL && index->indexParams != NIL)
|
||||
{
|
||||
iparam = lfirst(index->indexParams);
|
||||
index->idxname = CreateIndexName(cxt->relname, iparam->name,
|
||||
index->idxname = CreateIndexName((cxt->relation)->relname, iparam->name,
|
||||
"key", cxt->alist);
|
||||
}
|
||||
if (index->idxname == NULL) /* should not happen */
|
||||
@ -1268,7 +1282,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
cxt->stmtType,
|
||||
(strcmp(cxt->stmtType, "ALTER TABLE") == 0) ? "ADD " : "",
|
||||
(index->primary ? "PRIMARY KEY" : "UNIQUE"),
|
||||
index->idxname, cxt->relname);
|
||||
index->idxname, (cxt->relation)->relname);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1328,7 +1342,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
*/
|
||||
if (fkconstraint->pk_attrs == NIL)
|
||||
{
|
||||
if (strcmp(fkconstraint->pktable_name, cxt->relname) != 0)
|
||||
if (strcmp(fkconstraint->pktable->relname, (cxt->relation)->relname) != 0)
|
||||
transformFkeyGetPrimaryKey(fkconstraint, pktypoid);
|
||||
else if (cxt->pkey != NULL)
|
||||
{
|
||||
@ -1342,8 +1356,6 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
Ident *pkattr = (Ident *) makeNode(Ident);
|
||||
|
||||
pkattr->name = pstrdup(ielem->name);
|
||||
pkattr->indirection = NIL;
|
||||
pkattr->isRel = false;
|
||||
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs,
|
||||
pkattr);
|
||||
if (attnum >= INDEX_MAX_KEYS)
|
||||
@ -1360,13 +1372,13 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
transformFkeyGetPrimaryKey(fkconstraint, pktypoid);
|
||||
else
|
||||
elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
|
||||
fkconstraint->pktable_name);
|
||||
fkconstraint->pktable->relname);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Validate the specified referenced key list */
|
||||
if (strcmp(fkconstraint->pktable_name, cxt->relname) != 0)
|
||||
if (strcmp(fkconstraint->pktable->relname, (cxt->relation)->relname) != 0)
|
||||
transformFkeyCheckAttrs(fkconstraint, pktypoid);
|
||||
else
|
||||
{
|
||||
@ -1422,7 +1434,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
transformFkeyCheckAttrs(fkconstraint, pktypoid);
|
||||
else
|
||||
elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
|
||||
fkconstraint->pktable_name);
|
||||
fkconstraint->pktable->relname);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1447,7 +1459,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
*/
|
||||
fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
|
||||
fk_trigger->trigname = fkconstraint->constr_name;
|
||||
fk_trigger->relname = cxt->relname;
|
||||
fk_trigger->relation = cxt->relation;
|
||||
fk_trigger->funcname = "RI_FKey_check_ins";
|
||||
fk_trigger->before = false;
|
||||
fk_trigger->row = true;
|
||||
@ -1462,15 +1474,15 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
fk_trigger->isconstraint = true;
|
||||
fk_trigger->deferrable = fkconstraint->deferrable;
|
||||
fk_trigger->initdeferred = fkconstraint->initdeferred;
|
||||
fk_trigger->constrrelname = fkconstraint->pktable_name;
|
||||
fk_trigger->constrrel = fkconstraint->pktable;
|
||||
|
||||
fk_trigger->args = NIL;
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->constr_name));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(cxt->relname));
|
||||
makeString((cxt->relation)->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->pktable_name));
|
||||
makeString(fkconstraint->pktable->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->match_type));
|
||||
fk_attr = fkconstraint->fk_attrs;
|
||||
@ -1478,7 +1490,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
if (length(fk_attr) != length(pk_attr))
|
||||
elog(ERROR, "number of key attributes in referenced table must be equal to foreign key"
|
||||
"\n\tIllegal FOREIGN KEY definition references \"%s\"",
|
||||
fkconstraint->pktable_name);
|
||||
fkconstraint->pktable->relname);
|
||||
|
||||
while (fk_attr != NIL)
|
||||
{
|
||||
@ -1502,7 +1514,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
*/
|
||||
fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
|
||||
fk_trigger->trigname = fkconstraint->constr_name;
|
||||
fk_trigger->relname = fkconstraint->pktable_name;
|
||||
fk_trigger->relation = fkconstraint->pktable;
|
||||
fk_trigger->before = false;
|
||||
fk_trigger->row = true;
|
||||
fk_trigger->actions[0] = 'd';
|
||||
@ -1515,7 +1527,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
fk_trigger->isconstraint = true;
|
||||
fk_trigger->deferrable = fkconstraint->deferrable;
|
||||
fk_trigger->initdeferred = fkconstraint->initdeferred;
|
||||
fk_trigger->constrrelname = cxt->relname;
|
||||
fk_trigger->constrrel = cxt->relation;
|
||||
switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK)
|
||||
>> FKCONSTR_ON_DELETE_SHIFT)
|
||||
{
|
||||
@ -1545,9 +1557,9 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->constr_name));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(cxt->relname));
|
||||
makeString((cxt->relation)->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->pktable_name));
|
||||
makeString(fkconstraint->pktable->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->match_type));
|
||||
fk_attr = fkconstraint->fk_attrs;
|
||||
@ -1574,7 +1586,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
*/
|
||||
fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
|
||||
fk_trigger->trigname = fkconstraint->constr_name;
|
||||
fk_trigger->relname = fkconstraint->pktable_name;
|
||||
fk_trigger->relation = fkconstraint->pktable;
|
||||
fk_trigger->before = false;
|
||||
fk_trigger->row = true;
|
||||
fk_trigger->actions[0] = 'u';
|
||||
@ -1587,7 +1599,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
fk_trigger->isconstraint = true;
|
||||
fk_trigger->deferrable = fkconstraint->deferrable;
|
||||
fk_trigger->initdeferred = fkconstraint->initdeferred;
|
||||
fk_trigger->constrrelname = cxt->relname;
|
||||
fk_trigger->constrrel = cxt->relation;
|
||||
switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK)
|
||||
>> FKCONSTR_ON_UPDATE_SHIFT)
|
||||
{
|
||||
@ -1617,9 +1629,9 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->constr_name));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(cxt->relname));
|
||||
makeString((cxt->relation)->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->pktable_name));
|
||||
makeString(fkconstraint->pktable->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->match_type));
|
||||
fk_attr = fkconstraint->fk_attrs;
|
||||
@ -1672,7 +1684,7 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
|
||||
* easily support predicates on indexes created implicitly by
|
||||
* CREATE TABLE. Fortunately, that's not necessary.
|
||||
*/
|
||||
rte = addRangeTableEntry(pstate, stmt->relname, NULL, false, true);
|
||||
rte = addRangeTableEntry(pstate, stmt->relation->relname, NULL, false, true);
|
||||
|
||||
/* no to join list, yes to namespace */
|
||||
addRTEtoQuery(pstate, rte, false, true);
|
||||
@ -1712,7 +1724,7 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
|
||||
* beforehand. We don't need to hold a refcount on the relcache
|
||||
* entry, however.
|
||||
*/
|
||||
heap_close(heap_openr(stmt->object->relname, AccessExclusiveLock),
|
||||
heap_close(heap_openr(stmt->relation->relname, AccessExclusiveLock),
|
||||
NoLock);
|
||||
|
||||
/*
|
||||
@ -1721,11 +1733,11 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
|
||||
* rule qualification.
|
||||
*/
|
||||
Assert(pstate->p_rtable == NIL);
|
||||
oldrte = addRangeTableEntry(pstate, stmt->object->relname,
|
||||
makeAttr("*OLD*", NULL),
|
||||
oldrte = addRangeTableEntry(pstate, stmt->relation->relname,
|
||||
makeAlias("*OLD*", NIL),
|
||||
false, true);
|
||||
newrte = addRangeTableEntry(pstate, stmt->object->relname,
|
||||
makeAttr("*NEW*", NULL),
|
||||
newrte = addRangeTableEntry(pstate, stmt->relation->relname,
|
||||
makeAlias("*NEW*", NIL),
|
||||
false, true);
|
||||
/* Must override addRangeTableEntry's default access-check flags */
|
||||
oldrte->checkForRead = false;
|
||||
@ -1812,11 +1824,11 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
|
||||
* or they won't be accessible at all. We decide later
|
||||
* whether to put them in the joinlist.
|
||||
*/
|
||||
oldrte = addRangeTableEntry(sub_pstate, stmt->object->relname,
|
||||
makeAttr("*OLD*", NULL),
|
||||
oldrte = addRangeTableEntry(sub_pstate, stmt->relation->relname,
|
||||
makeAlias("*OLD*", NIL),
|
||||
false, false);
|
||||
newrte = addRangeTableEntry(sub_pstate, stmt->object->relname,
|
||||
makeAttr("*NEW*", NULL),
|
||||
newrte = addRangeTableEntry(sub_pstate, stmt->relation->relname,
|
||||
makeAlias("*NEW*", NIL),
|
||||
false, false);
|
||||
oldrte->checkForRead = false;
|
||||
newrte->checkForRead = false;
|
||||
@ -1950,8 +1962,8 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
if (!IsTransactionBlock())
|
||||
elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks");
|
||||
|
||||
qry->into = stmt->portalname;
|
||||
qry->isTemp = stmt->istemp;
|
||||
qry->into = makeNode(RangeVar);
|
||||
qry->into->relname = stmt->portalname;
|
||||
qry->isPortal = TRUE;
|
||||
qry->isBinary = stmt->binary; /* internal portal */
|
||||
}
|
||||
@ -1959,7 +1971,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
{
|
||||
/* SELECT */
|
||||
qry->into = stmt->into;
|
||||
qry->isTemp = stmt->istemp;
|
||||
qry->isPortal = FALSE;
|
||||
qry->isBinary = FALSE;
|
||||
}
|
||||
@ -2033,8 +2044,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
int leftmostRTI;
|
||||
Query *leftmostQuery;
|
||||
SetOperationStmt *sostmt;
|
||||
char *into;
|
||||
bool istemp;
|
||||
RangeVar *into;
|
||||
List *intoColNames;
|
||||
char *portalname;
|
||||
bool binary;
|
||||
@ -2065,14 +2075,12 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) &&
|
||||
leftmostSelect->larg == NULL);
|
||||
into = leftmostSelect->into;
|
||||
istemp = leftmostSelect->istemp;
|
||||
intoColNames = leftmostSelect->intoColNames;
|
||||
portalname = stmt->portalname;
|
||||
binary = stmt->binary;
|
||||
|
||||
/* clear them to prevent complaints in transformSetOperationTree() */
|
||||
leftmostSelect->into = NULL;
|
||||
leftmostSelect->istemp = false;
|
||||
leftmostSelect->intoColNames = NIL;
|
||||
stmt->portalname = NULL;
|
||||
stmt->binary = false;
|
||||
@ -2174,8 +2182,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
if (!IsTransactionBlock())
|
||||
elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks");
|
||||
|
||||
qry->into = portalname;
|
||||
qry->isTemp = istemp;
|
||||
qry->into = makeNode(RangeVar);
|
||||
qry->into->relname = portalname;
|
||||
qry->isPortal = TRUE;
|
||||
qry->isBinary = binary; /* internal portal */
|
||||
}
|
||||
@ -2183,7 +2191,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
{
|
||||
/* SELECT */
|
||||
qry->into = into;
|
||||
qry->isTemp = istemp;
|
||||
qry->isPortal = FALSE;
|
||||
qry->isBinary = FALSE;
|
||||
}
|
||||
@ -2325,8 +2332,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
|
||||
sprintf(selectName, "*SELECT* %d", length(pstate->p_rtable) + 1);
|
||||
rte = addRangeTableEntryForSubquery(pstate,
|
||||
selectQuery,
|
||||
makeAttr(pstrdup(selectName),
|
||||
NULL),
|
||||
makeAlias(selectName, NIL),
|
||||
false);
|
||||
|
||||
/*
|
||||
@ -2468,8 +2474,8 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
||||
qry->commandType = CMD_UPDATE;
|
||||
pstate->p_is_update = true;
|
||||
|
||||
qry->resultRelation = setTargetTable(pstate, stmt->relname,
|
||||
interpretInhOption(stmt->inhOpt),
|
||||
qry->resultRelation = setTargetTable(pstate, stmt->relation->relname,
|
||||
interpretInhOption(stmt->relation->inhOpt),
|
||||
true);
|
||||
|
||||
/*
|
||||
@ -2553,11 +2559,11 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
|
||||
{
|
||||
case 'A':
|
||||
cxt.stmtType = "ALTER TABLE";
|
||||
cxt.relname = stmt->relname;
|
||||
cxt.inhRelnames = NIL;
|
||||
cxt.istemp = is_temp_rel_name(stmt->relname);
|
||||
cxt.relation = stmt->relation;
|
||||
cxt.inhRelations = NIL;
|
||||
cxt.relation->istemp = is_temp_rel_name(stmt->relation->relname);
|
||||
cxt.relOid = GetSysCacheOid(RELNAME,
|
||||
PointerGetDatum(stmt->relname),
|
||||
PointerGetDatum((stmt->relation)->relname),
|
||||
0, 0, 0);
|
||||
cxt.hasoids = SearchSysCacheExists(ATTNUM,
|
||||
ObjectIdGetDatum(cxt.relOid),
|
||||
@ -2585,11 +2591,11 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
|
||||
|
||||
case 'C':
|
||||
cxt.stmtType = "ALTER TABLE";
|
||||
cxt.relname = stmt->relname;
|
||||
cxt.inhRelnames = NIL;
|
||||
cxt.istemp = is_temp_rel_name(stmt->relname);
|
||||
cxt.relation = stmt->relation;
|
||||
cxt.inhRelations = NIL;
|
||||
cxt.relation->istemp = is_temp_rel_name(stmt->relation->relname);
|
||||
cxt.relOid = GetSysCacheOid(RELNAME,
|
||||
PointerGetDatum(stmt->relname),
|
||||
PointerGetDatum((stmt->relation)->relname),
|
||||
0, 0, 0);
|
||||
cxt.hasoids = SearchSysCacheExists(ATTNUM,
|
||||
ObjectIdGetDatum(cxt.relOid),
|
||||
@ -2713,15 +2719,18 @@ transformTypeRefsList(ParseState *pstate, List *l)
|
||||
static void
|
||||
transformTypeRef(ParseState *pstate, TypeName *tn)
|
||||
{
|
||||
Attr *att;
|
||||
ColumnRef *cref;
|
||||
Node *n;
|
||||
Var *v;
|
||||
char *tyn;
|
||||
|
||||
if (tn->attrname == NULL)
|
||||
return;
|
||||
att = makeAttr(tn->name, tn->attrname);
|
||||
n = transformExpr(pstate, (Node *) att, EXPR_COLUMN_FIRST);
|
||||
/* XXX this needs work; can't type name be qualified? */
|
||||
cref = makeNode(ColumnRef);
|
||||
cref->fields = makeList2(makeString(tn->name), makeString(tn->attrname));
|
||||
cref->indirection = NIL;
|
||||
n = transformExpr(pstate, (Node *) cref);
|
||||
if (!IsA(n, Var))
|
||||
elog(ERROR, "unsupported expression in %%TYPE");
|
||||
v = (Var *) n;
|
||||
@ -2791,7 +2800,7 @@ transformForUpdate(Query *qry, List *forUpdate)
|
||||
RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
|
||||
|
||||
++i;
|
||||
if (strcmp(rte->eref->relname, relname) == 0)
|
||||
if (strcmp(rte->eref->aliasname, relname) == 0)
|
||||
{
|
||||
if (rte->subquery)
|
||||
{
|
||||
@ -2835,11 +2844,11 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
|
||||
/*
|
||||
* Open the referenced table
|
||||
*/
|
||||
pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock);
|
||||
pkrel = heap_openr(fkconstraint->pktable->relname, AccessShareLock);
|
||||
|
||||
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
|
||||
elog(ERROR, "Referenced relation \"%s\" is not a table",
|
||||
fkconstraint->pktable_name);
|
||||
fkconstraint->pktable->relname);
|
||||
|
||||
/*
|
||||
* Get the list of index OIDs for the table from the relcache, and
|
||||
@ -2901,7 +2910,7 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
|
||||
}
|
||||
if (!found)
|
||||
elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
|
||||
fkconstraint->pktable_name);
|
||||
fkconstraint->pktable->relname);
|
||||
|
||||
freeList(indexoidlist);
|
||||
heap_close(pkrel, AccessShareLock);
|
||||
@ -2928,11 +2937,11 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
|
||||
/*
|
||||
* Open the referenced table
|
||||
*/
|
||||
pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock);
|
||||
pkrel = heap_openr(fkconstraint->pktable->relname, AccessShareLock);
|
||||
|
||||
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
|
||||
elog(ERROR, "Referenced relation \"%s\" is not a table",
|
||||
fkconstraint->pktable_name);
|
||||
fkconstraint->pktable->relname);
|
||||
|
||||
/*
|
||||
* Get the list of index OIDs for the table from the relcache, and
|
||||
@ -2965,7 +2974,7 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
|
||||
*/
|
||||
if (indexStruct == NULL)
|
||||
elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
|
||||
fkconstraint->pktable_name);
|
||||
fkconstraint->pktable->relname);
|
||||
|
||||
/*
|
||||
* Now build the list of PK attributes from the indkey definition
|
||||
@ -2977,8 +2986,6 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
|
||||
Ident *pkattr = makeNode(Ident);
|
||||
|
||||
pkattr->name = pstrdup(NameStr(*attnumAttName(pkrel, pkattno)));
|
||||
pkattr->indirection = NIL;
|
||||
pkattr->isRel = false;
|
||||
pktypoid[attnum++] = attnumTypeId(pkrel, pkattno);
|
||||
|
||||
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
|
||||
@ -3070,14 +3077,14 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
|
||||
if (sysatt)
|
||||
return sysatt->atttypid;
|
||||
/* Look for column among inherited columns (if CREATE TABLE case) */
|
||||
foreach(inher, cxt->inhRelnames)
|
||||
foreach(inher, cxt->inhRelations)
|
||||
{
|
||||
Value *inh = lfirst(inher);
|
||||
RangeVar *inh = lfirst(inher);
|
||||
Relation rel;
|
||||
int count;
|
||||
|
||||
Assert(IsA(inh, String));
|
||||
rel = heap_openr(strVal(inh), AccessShareLock);
|
||||
Assert(IsA(inh, RangeVar));
|
||||
rel = heap_openr(inh->relname, AccessShareLock);
|
||||
if (rel->rd_rel->relkind != RELKIND_RELATION)
|
||||
elog(ERROR, "inherited table \"%s\" is not a relation",
|
||||
strVal(inh));
|
||||
@ -3248,3 +3255,104 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
|
||||
|
||||
ReleaseSysCache(ctype);
|
||||
}
|
||||
|
||||
/*
|
||||
* analyzeCreateSchemaStmt -
|
||||
* analyzes the "create schema" statement
|
||||
*
|
||||
* Split the schema element list into individual commands and place
|
||||
* them in the result list in an order such that there are no
|
||||
* forward references (e.g. GRANT to a table created later in the list).
|
||||
*
|
||||
* SQL92 also allows constraints to make forward references, so thumb through
|
||||
* the table columns and move forward references to a posterior alter-table
|
||||
* command.
|
||||
*
|
||||
* The result is a list of parse nodes that still need to be analyzed ---
|
||||
* but we can't analyze the later commands until we've executed the earlier
|
||||
* ones, because of possible inter-object references.
|
||||
*
|
||||
* Note: Called from commands/command.c
|
||||
*/
|
||||
List *
|
||||
analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
|
||||
{
|
||||
CreateSchemaStmtContext cxt;
|
||||
List *result;
|
||||
List *elements;
|
||||
|
||||
cxt.stmtType = "CREATE SCHEMA";
|
||||
cxt.schemaname = stmt->schemaname;
|
||||
cxt.authid = stmt->authid;
|
||||
cxt.tables = NIL;
|
||||
cxt.views = NIL;
|
||||
cxt.grants = NIL;
|
||||
cxt.fwconstraints = NIL;
|
||||
cxt.alters = NIL;
|
||||
cxt.blist = NIL;
|
||||
cxt.alist = NIL;
|
||||
|
||||
/*
|
||||
* Run through each schema element in the schema element list.
|
||||
* Separate statements by type, and do preliminary analysis.
|
||||
*/
|
||||
foreach(elements, stmt->schemaElts)
|
||||
{
|
||||
Node *element = lfirst(elements);
|
||||
|
||||
switch (nodeTag(element))
|
||||
{
|
||||
case T_CreateStmt:
|
||||
{
|
||||
CreateStmt *elp = (CreateStmt *) element;
|
||||
|
||||
if (elp->relation->schemaname == NULL)
|
||||
elp->relation->schemaname = cxt.schemaname;
|
||||
else if (strcmp(cxt.schemaname, elp->relation->schemaname))
|
||||
elog(ERROR, "New table refers to a schema (%s)"
|
||||
" different from the one being created (%s)",
|
||||
elp->relation->schemaname, cxt.schemaname);
|
||||
|
||||
/*
|
||||
* XXX todo: deal with constraints
|
||||
*/
|
||||
|
||||
cxt.tables = lappend(cxt.tables, element);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_ViewStmt:
|
||||
{
|
||||
ViewStmt *elp = (ViewStmt *) element;
|
||||
|
||||
if (elp->view->schemaname == NULL)
|
||||
elp->view->schemaname = cxt.schemaname;
|
||||
else if (strcmp(cxt.schemaname, elp->view->schemaname))
|
||||
elog(ERROR, "New view refers to a schema (%s)"
|
||||
" different from the one being created (%s)",
|
||||
elp->view->schemaname, cxt.schemaname);
|
||||
|
||||
/*
|
||||
* XXX todo: deal with references between views
|
||||
*/
|
||||
|
||||
cxt.views = lappend(cxt.views, element);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_GrantStmt:
|
||||
cxt.grants = lappend(cxt.grants, element);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "parser: unsupported schema node (internal error)");
|
||||
}
|
||||
}
|
||||
|
||||
result = NIL;
|
||||
result = nconc(result, cxt.tables);
|
||||
result = nconc(result, cxt.views);
|
||||
result = nconc(result, cxt.grants);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.46 2001/10/25 05:49:36 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.47 2002/03/21 16:00:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -116,7 +116,7 @@ check_ungrouped_columns_walker(Node *node,
|
||||
rte = rt_fetch(var->varno, context->pstate->p_rtable);
|
||||
attname = get_rte_attribute_name(rte, var->varattno);
|
||||
elog(ERROR, "Attribute %s.%s must be GROUPed or used in an aggregate function",
|
||||
rte->eref->relname, attname);
|
||||
rte->eref->aliasname, attname);
|
||||
}
|
||||
/* Otherwise, recurse. */
|
||||
return expression_tree_walker(node, check_ungrouped_columns_walker,
|
||||
@ -188,8 +188,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual)
|
||||
|
||||
Aggref *
|
||||
ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
|
||||
List *args, bool agg_star, bool agg_distinct,
|
||||
int precedence)
|
||||
List *args, bool agg_star, bool agg_distinct)
|
||||
{
|
||||
HeapTuple aggtuple;
|
||||
Form_pg_aggregate aggform;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.84 2002/03/12 00:51:54 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.85 2002/03/21 16:00:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -285,7 +285,7 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars)
|
||||
* transformJoinOnClause() does. Just invoke transformExpr() to fix
|
||||
* up the operators, and we're done.
|
||||
*/
|
||||
result = transformExpr(pstate, result, EXPR_COLUMN_FIRST);
|
||||
result = transformExpr(pstate, result);
|
||||
|
||||
/*
|
||||
* We expect the result to yield bool directly, otherwise complain. We
|
||||
@ -326,7 +326,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
|
||||
pstate->p_namespace = makeList2(j->larg, j->rarg);
|
||||
|
||||
/* This part is just like transformWhereClause() */
|
||||
result = transformExpr(pstate, j->quals, EXPR_COLUMN_FIRST);
|
||||
result = transformExpr(pstate, j->quals);
|
||||
|
||||
if (!coerce_to_boolean(pstate, &result))
|
||||
elog(ERROR, "JOIN/ON clause must return type boolean, not type %s",
|
||||
@ -350,7 +350,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
|
||||
if (!intMember(varno, containedRels))
|
||||
{
|
||||
elog(ERROR, "JOIN/ON clause refers to \"%s\", which is not part of JOIN",
|
||||
rt_fetch(varno, pstate->p_rtable)->eref->relname);
|
||||
rt_fetch(varno, pstate->p_rtable)->eref->aliasname);
|
||||
}
|
||||
}
|
||||
freeList(clause_varnos);
|
||||
@ -375,7 +375,7 @@ transformTableEntry(ParseState *pstate, RangeVar *r)
|
||||
* automatically generate the range variable if not specified. However
|
||||
* there are times we need to know whether the entries are legitimate.
|
||||
*/
|
||||
rte = addRangeTableEntry(pstate, relname, r->name,
|
||||
rte = addRangeTableEntry(pstate, relname, r->alias,
|
||||
interpretInhOption(r->inhOpt), true);
|
||||
|
||||
/*
|
||||
@ -408,7 +408,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
|
||||
* relax this, we'd have to be prepared to gin up a unique alias for
|
||||
* an unlabeled subselect.
|
||||
*/
|
||||
if (r->name == NULL)
|
||||
if (r->alias == NULL)
|
||||
elog(ERROR, "sub-select in FROM must have an alias");
|
||||
|
||||
/*
|
||||
@ -444,7 +444,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
|
||||
/*
|
||||
* OK, build an RTE for the subquery.
|
||||
*/
|
||||
rte = addRangeTableEntryForSubquery(pstate, query, r->name, true);
|
||||
rte = addRangeTableEntryForSubquery(pstate, query, r->alias, true);
|
||||
|
||||
/*
|
||||
* We create a RangeTblRef, but we do not add it to the joinlist or
|
||||
@ -748,11 +748,11 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
|
||||
*/
|
||||
if (j->alias)
|
||||
{
|
||||
if (j->alias->attrs != NIL)
|
||||
if (j->alias->colnames != NIL)
|
||||
{
|
||||
if (length(j->alias->attrs) > length(res_colnames))
|
||||
if (length(j->alias->colnames) > length(res_colnames))
|
||||
elog(ERROR, "Column alias list for \"%s\" has too many entries",
|
||||
j->alias->relname);
|
||||
j->alias->aliasname);
|
||||
}
|
||||
}
|
||||
|
||||
@ -791,7 +791,7 @@ transformWhereClause(ParseState *pstate, Node *clause)
|
||||
if (clause == NULL)
|
||||
return NULL;
|
||||
|
||||
qual = transformExpr(pstate, clause, EXPR_COLUMN_FIRST);
|
||||
qual = transformExpr(pstate, clause);
|
||||
|
||||
if (!coerce_to_boolean(pstate, &qual))
|
||||
elog(ERROR, "WHERE clause must return type boolean, not type %s",
|
||||
@ -858,9 +858,11 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
|
||||
* an expression.
|
||||
*----------
|
||||
*/
|
||||
if (IsA(node, Ident) &&((Ident *) node)->indirection == NIL)
|
||||
if (IsA(node, ColumnRef) &&
|
||||
length(((ColumnRef *) node)->fields) == 1 &&
|
||||
((ColumnRef *) node)->indirection == NIL)
|
||||
{
|
||||
char *name = ((Ident *) node)->name;
|
||||
char *name = strVal(lfirst(((ColumnRef *) node)->fields));
|
||||
|
||||
if (clause == GROUP_CLAUSE)
|
||||
{
|
||||
@ -934,7 +936,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
|
||||
* willing to match a resjunk target here, though the above cases must
|
||||
* ignore resjunk targets.
|
||||
*/
|
||||
expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST);
|
||||
expr = transformExpr(pstate, node);
|
||||
|
||||
foreach(tl, tlist)
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.110 2002/03/20 19:44:25 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.111 2002/03/21 16:01:03 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "miscadmin.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
#include "nodes/params.h"
|
||||
#include "parser/analyze.h"
|
||||
@ -41,8 +42,7 @@ bool Transform_null_equals = false;
|
||||
static Node *parser_typecast_constant(Value *expr, TypeName *typename);
|
||||
static Node *parser_typecast_expression(ParseState *pstate,
|
||||
Node *expr, TypeName *typename);
|
||||
static Node *transformAttr(ParseState *pstate, Attr *att, int precedence);
|
||||
static Node *transformIdent(ParseState *pstate, Ident *ident, int precedence);
|
||||
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
|
||||
static Node *transformIndirection(ParseState *pstate, Node *basenode,
|
||||
List *indirection);
|
||||
|
||||
@ -85,7 +85,7 @@ parse_expr_init(void)
|
||||
* input and output of transformExpr; see SubLink for example.
|
||||
*/
|
||||
Node *
|
||||
transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
transformExpr(ParseState *pstate, Node *expr)
|
||||
{
|
||||
Node *result = NULL;
|
||||
|
||||
@ -105,9 +105,37 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
|
||||
switch (nodeTag(expr))
|
||||
{
|
||||
case T_Attr:
|
||||
case T_ColumnRef:
|
||||
{
|
||||
result = transformAttr(pstate, (Attr *) expr, precedence);
|
||||
result = transformColumnRef(pstate, (ColumnRef *) expr);
|
||||
break;
|
||||
}
|
||||
case T_ParamRef:
|
||||
{
|
||||
ParamRef *pref = (ParamRef *) expr;
|
||||
int paramno = pref->number;
|
||||
Oid paramtyp = param_type(paramno);
|
||||
Param *param;
|
||||
List *fields;
|
||||
|
||||
if (!OidIsValid(paramtyp))
|
||||
elog(ERROR, "Parameter '$%d' is out of range", paramno);
|
||||
param = makeNode(Param);
|
||||
param->paramkind = PARAM_NUM;
|
||||
param->paramid = (AttrNumber) paramno;
|
||||
param->paramname = "<unnamed>";
|
||||
param->paramtype = paramtyp;
|
||||
result = (Node *) param;
|
||||
/* handle qualification, if any */
|
||||
foreach(fields, pref->fields)
|
||||
{
|
||||
result = ParseFuncOrColumn(pstate, strVal(lfirst(fields)),
|
||||
makeList1(result),
|
||||
false, false, true);
|
||||
}
|
||||
/* handle subscripts, if any */
|
||||
result = transformIndirection(pstate, result,
|
||||
pref->indirection);
|
||||
break;
|
||||
}
|
||||
case T_A_Const:
|
||||
@ -121,31 +149,28 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
result = (Node *) make_const(val);
|
||||
break;
|
||||
}
|
||||
case T_ParamNo:
|
||||
case T_ExprFieldSelect:
|
||||
{
|
||||
ParamNo *pno = (ParamNo *) expr;
|
||||
int paramno = pno->number;
|
||||
Oid toid = param_type(paramno);
|
||||
Param *param = makeNode(Param);
|
||||
ExprFieldSelect *efs = (ExprFieldSelect *) expr;
|
||||
List *fields;
|
||||
|
||||
if (!OidIsValid(toid))
|
||||
elog(ERROR, "Parameter '$%d' is out of range", paramno);
|
||||
param->paramkind = PARAM_NUM;
|
||||
param->paramid = (AttrNumber) paramno;
|
||||
param->paramname = "<unnamed>";
|
||||
param->paramtype = toid;
|
||||
result = transformIndirection(pstate, (Node *) param,
|
||||
pno->indirection);
|
||||
/* cope with typecast applied to param */
|
||||
if (pno->typename != NULL)
|
||||
result = parser_typecast_expression(pstate, result,
|
||||
pno->typename);
|
||||
result = transformExpr(pstate, efs->arg);
|
||||
/* handle qualification, if any */
|
||||
foreach(fields, efs->fields)
|
||||
{
|
||||
result = ParseFuncOrColumn(pstate, strVal(lfirst(fields)),
|
||||
makeList1(result),
|
||||
false, false, true);
|
||||
}
|
||||
/* handle subscripts, if any */
|
||||
result = transformIndirection(pstate, result,
|
||||
efs->indirection);
|
||||
break;
|
||||
}
|
||||
case T_TypeCast:
|
||||
{
|
||||
TypeCast *tc = (TypeCast *) expr;
|
||||
Node *arg = transformExpr(pstate, tc->arg, precedence);
|
||||
Node *arg = transformExpr(pstate, tc->arg);
|
||||
|
||||
result = parser_typecast_expression(pstate, arg, tc->typename);
|
||||
break;
|
||||
@ -179,17 +204,14 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
n->arg = a->lexpr;
|
||||
|
||||
result = transformExpr(pstate,
|
||||
(Node *) n,
|
||||
precedence);
|
||||
(Node *) n);
|
||||
}
|
||||
else
|
||||
{
|
||||
Node *lexpr = transformExpr(pstate,
|
||||
a->lexpr,
|
||||
precedence);
|
||||
a->lexpr);
|
||||
Node *rexpr = transformExpr(pstate,
|
||||
a->rexpr,
|
||||
precedence);
|
||||
a->rexpr);
|
||||
|
||||
result = (Node *) make_op(a->opname,
|
||||
lexpr,
|
||||
@ -200,11 +222,9 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
case AND:
|
||||
{
|
||||
Node *lexpr = transformExpr(pstate,
|
||||
a->lexpr,
|
||||
precedence);
|
||||
a->lexpr);
|
||||
Node *rexpr = transformExpr(pstate,
|
||||
a->rexpr,
|
||||
precedence);
|
||||
a->rexpr);
|
||||
Expr *expr = makeNode(Expr);
|
||||
|
||||
if (!coerce_to_boolean(pstate, &lexpr))
|
||||
@ -226,11 +246,9 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
case OR:
|
||||
{
|
||||
Node *lexpr = transformExpr(pstate,
|
||||
a->lexpr,
|
||||
precedence);
|
||||
a->lexpr);
|
||||
Node *rexpr = transformExpr(pstate,
|
||||
a->rexpr,
|
||||
precedence);
|
||||
a->rexpr);
|
||||
Expr *expr = makeNode(Expr);
|
||||
|
||||
if (!coerce_to_boolean(pstate, &lexpr))
|
||||
@ -252,8 +270,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
case NOT:
|
||||
{
|
||||
Node *rexpr = transformExpr(pstate,
|
||||
a->rexpr,
|
||||
precedence);
|
||||
a->rexpr);
|
||||
Expr *expr = makeNode(Expr);
|
||||
|
||||
if (!coerce_to_boolean(pstate, &rexpr))
|
||||
@ -270,11 +287,6 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_Ident:
|
||||
{
|
||||
result = transformIdent(pstate, (Ident *) expr, precedence);
|
||||
break;
|
||||
}
|
||||
case T_FuncCall:
|
||||
{
|
||||
FuncCall *fn = (FuncCall *) expr;
|
||||
@ -283,14 +295,13 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
/* transform the list of arguments */
|
||||
foreach(args, fn->args)
|
||||
lfirst(args) = transformExpr(pstate,
|
||||
(Node *) lfirst(args),
|
||||
precedence);
|
||||
(Node *) lfirst(args));
|
||||
result = ParseFuncOrColumn(pstate,
|
||||
fn->funcname,
|
||||
fn->args,
|
||||
fn->agg_star,
|
||||
fn->agg_distinct,
|
||||
precedence);
|
||||
false);
|
||||
break;
|
||||
}
|
||||
case T_SubLink:
|
||||
@ -357,8 +368,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
List *elist;
|
||||
|
||||
foreach(elist, left_list)
|
||||
lfirst(elist) = transformExpr(pstate, lfirst(elist),
|
||||
precedence);
|
||||
lfirst(elist) = transformExpr(pstate, lfirst(elist));
|
||||
|
||||
Assert(IsA(sublink->oper, A_Expr));
|
||||
op = ((A_Expr *) sublink->oper)->opname;
|
||||
@ -455,7 +465,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
a->rexpr = warg;
|
||||
warg = (Node *) a;
|
||||
}
|
||||
neww->expr = transformExpr(pstate, warg, precedence);
|
||||
neww->expr = transformExpr(pstate, warg);
|
||||
|
||||
if (!coerce_to_boolean(pstate, &neww->expr))
|
||||
elog(ERROR, "WHEN clause must have a boolean result");
|
||||
@ -472,7 +482,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
n->val.type = T_Null;
|
||||
warg = (Node *) n;
|
||||
}
|
||||
neww->result = transformExpr(pstate, warg, precedence);
|
||||
neww->result = transformExpr(pstate, warg);
|
||||
|
||||
newargs = lappend(newargs, neww);
|
||||
typeids = lappendi(typeids, exprType(neww->result));
|
||||
@ -496,7 +506,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
n->val.type = T_Null;
|
||||
defresult = (Node *) n;
|
||||
}
|
||||
newc->defresult = transformExpr(pstate, defresult, precedence);
|
||||
newc->defresult = transformExpr(pstate, defresult);
|
||||
|
||||
/*
|
||||
* Note: default result is considered the most significant
|
||||
@ -534,7 +544,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
{
|
||||
NullTest *n = (NullTest *) expr;
|
||||
|
||||
n->arg = transformExpr(pstate, n->arg, precedence);
|
||||
n->arg = transformExpr(pstate, n->arg);
|
||||
/* the argument can be any type, so don't coerce it */
|
||||
result = expr;
|
||||
break;
|
||||
@ -544,7 +554,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
{
|
||||
BooleanTest *b = (BooleanTest *) expr;
|
||||
|
||||
b->arg = transformExpr(pstate, b->arg, precedence);
|
||||
b->arg = transformExpr(pstate, b->arg);
|
||||
|
||||
if (!coerce_to_boolean(pstate, &b->arg))
|
||||
{
|
||||
@ -627,47 +637,183 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
|
||||
}
|
||||
|
||||
static Node *
|
||||
transformAttr(ParseState *pstate, Attr *att, int precedence)
|
||||
transformColumnRef(ParseState *pstate, ColumnRef *cref)
|
||||
{
|
||||
Node *basenode;
|
||||
int numnames = length(cref->fields);
|
||||
Node *node;
|
||||
RangeVar *rv;
|
||||
|
||||
basenode = ParseNestedFuncOrColumn(pstate, att, precedence);
|
||||
return transformIndirection(pstate, basenode, att->indirection);
|
||||
}
|
||||
|
||||
static Node *
|
||||
transformIdent(ParseState *pstate, Ident *ident, int precedence)
|
||||
{
|
||||
Node *result = NULL;
|
||||
int sublevels_up;
|
||||
|
||||
/*
|
||||
* try to find the ident as a relation ... but not if subscripts
|
||||
* appear
|
||||
/*----------
|
||||
* The allowed syntaxes are:
|
||||
*
|
||||
* A First try to resolve as unqualified column name;
|
||||
* if no luck, try to resolve as unqual. table name (A.*).
|
||||
* A.B A is an unqual. table name; B is either a
|
||||
* column or function name (trying column name first).
|
||||
* A.B.C schema A, table B, col or func name C.
|
||||
* A.B.C.D catalog A, schema B, table C, col or func D.
|
||||
* A.* A is an unqual. table name; means whole-row value.
|
||||
* A.B.* whole-row value of table B in schema A.
|
||||
* A.B.C.* whole-row value of table C in schema B in catalog A.
|
||||
*
|
||||
* We do not need to cope with bare "*"; that will only be accepted by
|
||||
* the grammar at the top level of a SELECT list, and transformTargetList
|
||||
* will take care of it before it ever gets here.
|
||||
*
|
||||
* Currently, if a catalog name is given then it must equal the current
|
||||
* database name; we check it here and then discard it.
|
||||
*
|
||||
* For whole-row references, the result is an untransformed RangeVar,
|
||||
* which will work as the argument to a function call, but not in any
|
||||
* other context at present. (We could instead coerce to a whole-row Var,
|
||||
* but that will fail for subselect and join RTEs, because there is no
|
||||
* pg_type entry for their rowtypes.)
|
||||
*----------
|
||||
*/
|
||||
if (ident->indirection == NIL &&
|
||||
refnameRangeTblEntry(pstate, ident->name, &sublevels_up) != NULL)
|
||||
switch (numnames)
|
||||
{
|
||||
ident->isRel = TRUE;
|
||||
result = (Node *) ident;
|
||||
}
|
||||
|
||||
if (result == NULL || precedence == EXPR_COLUMN_FIRST)
|
||||
{
|
||||
/* try to find the ident as a column */
|
||||
Node *var = colnameToVar(pstate, ident->name);
|
||||
|
||||
if (var != NULL)
|
||||
case 1:
|
||||
{
|
||||
ident->isRel = FALSE;
|
||||
result = transformIndirection(pstate, var, ident->indirection);
|
||||
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.
|
||||
*/
|
||||
int levels_up;
|
||||
|
||||
if (cref->indirection == NIL &&
|
||||
refnameRangeTblEntry(pstate, 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 = name1;
|
||||
rv->inhOpt = INH_DEFAULT;
|
||||
node = (Node *) rv;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try to identify as a once-qualified column */
|
||||
node = qualifiedNameToVar(pstate, 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, 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;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try to identify as a twice-qualified column */
|
||||
/* XXX do something with schema name here */
|
||||
node = qualifiedNameToVar(pstate, 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, 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;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try to identify as a twice-qualified column */
|
||||
/* XXX do something with schema name here */
|
||||
node = qualifiedNameToVar(pstate, 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, name4,
|
||||
makeList1(rv),
|
||||
false, false, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
elog(ERROR, "Invalid qualified name syntax (too many names)");
|
||||
node = NULL; /* keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == NULL)
|
||||
elog(ERROR, "Attribute '%s' not found", ident->name);
|
||||
|
||||
return result;
|
||||
return transformIndirection(pstate, node, cref->indirection);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -748,10 +894,6 @@ exprType(Node *expr)
|
||||
case T_BooleanTest:
|
||||
type = BOOLOID;
|
||||
break;
|
||||
case T_Ident:
|
||||
/* XXX is this right? */
|
||||
type = UNKNOWNOID;
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "Do not know how to get type for %d node",
|
||||
nodeTag(expr));
|
||||
|
@ -8,11 +8,10 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.118 2002/03/20 19:44:29 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.119 2002/03/21 16:01:06 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/genam.h"
|
||||
@ -36,8 +35,7 @@
|
||||
|
||||
static Node *ParseComplexProjection(ParseState *pstate,
|
||||
char *funcname,
|
||||
Node *first_arg,
|
||||
bool *attisset);
|
||||
Node *first_arg);
|
||||
static Oid **argtype_inherit(int nargs, Oid *argtypes);
|
||||
|
||||
static int find_inheritors(Oid relid, Oid **supervec);
|
||||
@ -60,75 +58,31 @@ static Oid agg_select_candidate(Oid typeid, CandidateList candidates);
|
||||
|
||||
|
||||
/*
|
||||
** ParseNestedFuncOrColumn
|
||||
** Given a nested dot expression (i.e. (relation func ... attr), build up
|
||||
** a tree with of Iter and Func nodes.
|
||||
*/
|
||||
Node *
|
||||
ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, int precedence)
|
||||
{
|
||||
List *mutator_iter;
|
||||
Node *retval = NULL;
|
||||
|
||||
if (attr->paramNo != NULL)
|
||||
{
|
||||
Param *param = (Param *) transformExpr(pstate,
|
||||
(Node *) attr->paramNo,
|
||||
EXPR_RELATION_FIRST);
|
||||
|
||||
retval = ParseFuncOrColumn(pstate, strVal(lfirst(attr->attrs)),
|
||||
makeList1(param),
|
||||
false, false,
|
||||
precedence);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ident *ident = makeNode(Ident);
|
||||
|
||||
ident->name = attr->relname;
|
||||
ident->isRel = TRUE;
|
||||
retval = ParseFuncOrColumn(pstate, strVal(lfirst(attr->attrs)),
|
||||
makeList1(ident),
|
||||
false, false,
|
||||
precedence);
|
||||
}
|
||||
|
||||
/* Do more attributes follow this one? */
|
||||
foreach(mutator_iter, lnext(attr->attrs))
|
||||
{
|
||||
retval = ParseFuncOrColumn(pstate, strVal(lfirst(mutator_iter)),
|
||||
makeList1(retval),
|
||||
false, false,
|
||||
precedence);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* parse function
|
||||
* Parse a function call
|
||||
*
|
||||
* This code is confusing because the database can accept
|
||||
* relation.column, column.function, or relation.column.function.
|
||||
* In these cases, funcname is the last parameter, and fargs are
|
||||
* the rest.
|
||||
* For historical reasons, Postgres tries to treat the notations tab.col
|
||||
* and col(tab) as equivalent: if a single-argument function call has an
|
||||
* argument of complex type and the function name matches any attribute
|
||||
* of the type, we take it as a column projection.
|
||||
*
|
||||
* It can also be called as func(col) or func(col,col).
|
||||
* In this case, Funcname is the part before parens, and fargs
|
||||
* are the part in parens.
|
||||
*
|
||||
* FYI, projection is choosing column from a table.
|
||||
* Hence, both cases come through here. The is_column parameter tells us
|
||||
* which syntactic construct is actually being dealt with, but this is
|
||||
* intended to be used only to deliver an appropriate error message,
|
||||
* not to affect the semantics. When is_column is true, we should have
|
||||
* a single argument (the putative table), function name equal to the
|
||||
* column name, and no aggregate decoration.
|
||||
*
|
||||
* In the function-call case, the argument expressions have been transformed
|
||||
* already. In the column case, we may get either a transformed expression
|
||||
* or a RangeVar node as argument.
|
||||
*/
|
||||
Node *
|
||||
ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
bool agg_star, bool agg_distinct,
|
||||
int precedence)
|
||||
bool agg_star, bool agg_distinct, bool is_column)
|
||||
{
|
||||
Oid rettype = InvalidOid;
|
||||
Oid argrelid = InvalidOid;
|
||||
Oid funcid = InvalidOid;
|
||||
List *i = NIL;
|
||||
Oid rettype;
|
||||
Oid funcid;
|
||||
List *i;
|
||||
Node *first_arg = NULL;
|
||||
char *refname;
|
||||
int nargs = length(fargs);
|
||||
@ -140,9 +94,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
bool retset;
|
||||
bool must_be_agg = agg_star || agg_distinct;
|
||||
bool could_be_agg;
|
||||
bool attisset = false;
|
||||
Oid toid = InvalidOid;
|
||||
Expr *expr;
|
||||
FuncDetailCode fdresult;
|
||||
|
||||
/*
|
||||
* Most of the rest of the parser just assumes that functions do not
|
||||
@ -157,33 +110,26 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
if (fargs)
|
||||
{
|
||||
first_arg = lfirst(fargs);
|
||||
if (first_arg == NULL)
|
||||
if (first_arg == NULL) /* should not happen */
|
||||
elog(ERROR, "Function '%s' does not allow NULL input", funcname);
|
||||
}
|
||||
|
||||
/*
|
||||
* test for relation.column
|
||||
*
|
||||
* check for projection methods: if function takes one argument, and that
|
||||
* argument is a relation, param, or PQ function returning a complex *
|
||||
* type, then the function could be a projection.
|
||||
* check for column projection: if function has one argument, and that
|
||||
* argument is of complex type, then the function could be a projection.
|
||||
*/
|
||||
/* We only have one parameter, and it's not got aggregate decoration */
|
||||
if (nargs == 1 && !must_be_agg)
|
||||
{
|
||||
/* Is it a plain Relation name from the parser? */
|
||||
if (IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel)
|
||||
/* Is it a not-yet-transformed RangeVar node? */
|
||||
if (IsA(first_arg, RangeVar))
|
||||
{
|
||||
Ident *ident = (Ident *) first_arg;
|
||||
|
||||
/* First arg is a relation. This could be a projection. */
|
||||
refname = ident->name;
|
||||
refname = ((RangeVar *) first_arg)->relname;
|
||||
|
||||
retval = qualifiedNameToVar(pstate, refname, funcname, true);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* else drop through - attr is a set or function */
|
||||
}
|
||||
else if (ISCOMPLEX(exprType(first_arg)))
|
||||
{
|
||||
@ -194,24 +140,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
*/
|
||||
retval = ParseComplexProjection(pstate,
|
||||
funcname,
|
||||
first_arg,
|
||||
&attisset);
|
||||
if (attisset)
|
||||
{
|
||||
toid = exprType(first_arg);
|
||||
argrelid = typeidTypeRelid(toid);
|
||||
if (argrelid == InvalidOid)
|
||||
elog(ERROR, "Type '%s' is not a relation type",
|
||||
typeidTypeName(toid));
|
||||
|
||||
/*
|
||||
* A projection must match an attribute name of the rel.
|
||||
*/
|
||||
if (get_attnum(argrelid, funcname) == InvalidAttrNumber)
|
||||
elog(ERROR, "No such attribute or function '%s'",
|
||||
funcname);
|
||||
}
|
||||
|
||||
first_arg);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
@ -226,15 +155,14 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
if (nargs != 1)
|
||||
elog(ERROR, "Aggregate functions may only have one parameter");
|
||||
/* Agg's argument can't be a relation name, either */
|
||||
if (IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel)
|
||||
if (IsA(first_arg, RangeVar))
|
||||
elog(ERROR, "Aggregate functions cannot be applied to relation names");
|
||||
could_be_agg = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to parse as an aggregate if above-mentioned checks are OK */
|
||||
could_be_agg = (nargs == 1) &&
|
||||
!(IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel);
|
||||
could_be_agg = (nargs == 1) && !(IsA(first_arg, RangeVar));
|
||||
}
|
||||
|
||||
if (could_be_agg)
|
||||
@ -249,8 +177,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
ObjectIdGetDatum(basetype),
|
||||
0, 0))
|
||||
return (Node *) ParseAgg(pstate, funcname, basetype,
|
||||
fargs, agg_star, agg_distinct,
|
||||
precedence);
|
||||
fargs, agg_star, agg_distinct);
|
||||
|
||||
/* check for aggregate-that-accepts-any-type (eg, COUNT) */
|
||||
if (SearchSysCacheExists(AGGNAME,
|
||||
@ -258,8 +185,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
ObjectIdGetDatum(0),
|
||||
0, 0))
|
||||
return (Node *) ParseAgg(pstate, funcname, 0,
|
||||
fargs, agg_star, agg_distinct,
|
||||
precedence);
|
||||
fargs, agg_star, agg_distinct);
|
||||
|
||||
/*
|
||||
* No exact match yet, so see if there is another entry in the
|
||||
@ -277,8 +203,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
basetype, type, -1);
|
||||
basetype = type;
|
||||
return (Node *) ParseAgg(pstate, funcname, basetype,
|
||||
fargs, agg_star, agg_distinct,
|
||||
precedence);
|
||||
fargs, agg_star, agg_distinct);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -300,10 +225,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
}
|
||||
|
||||
/*
|
||||
* If we dropped through to here it's really a function (or a set,
|
||||
* which is implemented as a function). Extract arg type info and
|
||||
* transform relation name 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));
|
||||
|
||||
@ -311,8 +235,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
foreach(i, fargs)
|
||||
{
|
||||
Node *arg = lfirst(i);
|
||||
Oid toid;
|
||||
|
||||
if (IsA(arg, Ident) &&((Ident *) arg)->isRel)
|
||||
if (IsA(arg, RangeVar))
|
||||
{
|
||||
RangeTblEntry *rte;
|
||||
int vnum;
|
||||
@ -321,7 +246,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
/*
|
||||
* a relation
|
||||
*/
|
||||
refname = ((Ident *) arg)->name;
|
||||
refname = ((RangeVar *) arg)->relname;
|
||||
|
||||
rte = refnameRangeTblEntry(pstate, refname,
|
||||
&sublevels_up);
|
||||
@ -346,16 +271,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
* RTE is a join or subselect; must fail for lack of a
|
||||
* named tuple type
|
||||
*/
|
||||
if (nargs == 1)
|
||||
{
|
||||
/*
|
||||
* Here, we probably have an unrecognized attribute of
|
||||
* a sub-select; again can't tell if it was x.f or
|
||||
* f(x)
|
||||
*/
|
||||
elog(ERROR, "No such attribute or function %s.%s",
|
||||
if (is_column)
|
||||
elog(ERROR, "No such attribute %s.%s",
|
||||
refname, funcname);
|
||||
}
|
||||
else
|
||||
{
|
||||
elog(ERROR, "Cannot pass result of sub-select or join %s to a function",
|
||||
@ -365,93 +283,53 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
|
||||
toid = typenameTypeId(rte->relname);
|
||||
|
||||
/* replace it in the arg list */
|
||||
/* replace RangeVar in the arg list */
|
||||
lfirst(i) = makeVar(vnum,
|
||||
InvalidAttrNumber,
|
||||
toid,
|
||||
sizeof(Pointer),
|
||||
sublevels_up);
|
||||
}
|
||||
else if (!attisset)
|
||||
toid = exprType(arg);
|
||||
else
|
||||
{
|
||||
/* if attisset is true, we already set toid for the single arg */
|
||||
}
|
||||
toid = exprType(arg);
|
||||
|
||||
oid_array[argn++] = toid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is it a set, or a function?
|
||||
* 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.
|
||||
*/
|
||||
if (attisset)
|
||||
{ /* we know all of these fields already */
|
||||
|
||||
/*
|
||||
* We create a funcnode with a placeholder function seteval(). At
|
||||
* runtime, seteval() will execute the function identified by the
|
||||
* funcid it receives as parameter.
|
||||
*
|
||||
* Example: retrieve (emp.mgr.name). The plan for this will scan the
|
||||
* emp relation, projecting out the mgr attribute, which is a
|
||||
* funcid. This function is then called (via seteval()) and "name"
|
||||
* is projected from its result.
|
||||
*/
|
||||
funcid = F_SETEVAL;
|
||||
rettype = toid;
|
||||
retset = true;
|
||||
true_oid_array = oid_array;
|
||||
}
|
||||
else
|
||||
fdresult = func_get_detail(funcname, fargs, nargs, oid_array,
|
||||
&funcid, &rettype, &retset,
|
||||
&true_oid_array);
|
||||
if (fdresult == FUNCDETAIL_COERCION)
|
||||
{
|
||||
FuncDetailCode fdresult;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* We can do it as a trivial coercion. coerce_type can handle
|
||||
* these cases, so why duplicate code...
|
||||
*/
|
||||
fdresult = func_get_detail(funcname, fargs, nargs, oid_array,
|
||||
&funcid, &rettype, &retset,
|
||||
&true_oid_array);
|
||||
if (fdresult == FUNCDETAIL_COERCION)
|
||||
{
|
||||
/*
|
||||
* We can do it as a trivial coercion. coerce_type can handle
|
||||
* these cases, so why duplicate code...
|
||||
*/
|
||||
return coerce_type(pstate, lfirst(fargs),
|
||||
oid_array[0], rettype, -1);
|
||||
}
|
||||
if (fdresult != FUNCDETAIL_NORMAL)
|
||||
{
|
||||
/*
|
||||
* Oops. Time to die.
|
||||
*
|
||||
* If there is a single argument of complex type, we might be
|
||||
* dealing with the PostQuel notation rel.function instead of
|
||||
* the more usual function(rel). Give a nonspecific error
|
||||
* message that will cover both cases.
|
||||
*/
|
||||
if (nargs == 1)
|
||||
{
|
||||
Type tp = typeidType(oid_array[0]);
|
||||
|
||||
if (typeTypeFlag(tp) == 'c')
|
||||
elog(ERROR, "No such attribute or function '%s'",
|
||||
funcname);
|
||||
ReleaseSysCache(tp);
|
||||
}
|
||||
|
||||
/* Else generate a detailed complaint */
|
||||
func_error(NULL, funcname, nargs, oid_array,
|
||||
"Unable to identify a function that satisfies the "
|
||||
"given argument types"
|
||||
"\n\tYou may need to add explicit typecasts");
|
||||
}
|
||||
return coerce_type(pstate, lfirst(fargs),
|
||||
oid_array[0], rettype, -1);
|
||||
}
|
||||
if (fdresult != FUNCDETAIL_NORMAL)
|
||||
{
|
||||
/*
|
||||
* 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 (is_column)
|
||||
elog(ERROR, "Attribute \"%s\" not found", funcname);
|
||||
/* Else generate a detailed complaint */
|
||||
func_error(NULL, funcname, nargs, oid_array,
|
||||
"Unable to identify a function that satisfies the "
|
||||
"given argument types"
|
||||
"\n\tYou may need to add explicit typecasts");
|
||||
}
|
||||
|
||||
/* got it */
|
||||
@ -470,26 +348,12 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
expr->args = fargs;
|
||||
retval = (Node *) expr;
|
||||
|
||||
/*
|
||||
* For sets, we want to project out the desired attribute of the
|
||||
* tuples.
|
||||
*/
|
||||
if (attisset)
|
||||
{
|
||||
FieldSelect *fselect;
|
||||
|
||||
fselect = setup_field_select(retval, funcname, argrelid);
|
||||
rettype = fselect->resulttype;
|
||||
retval = (Node *) fselect;
|
||||
}
|
||||
|
||||
/*
|
||||
* if the function returns a set of values, then we need to iterate
|
||||
* over all the returned values in the executor, so we stick an iter
|
||||
* node here. if it returns a singleton, then we don't need the iter
|
||||
* node.
|
||||
*/
|
||||
|
||||
if (retset)
|
||||
{
|
||||
Iter *iter = makeNode(Iter);
|
||||
@ -1497,10 +1361,10 @@ make_arguments(ParseState *pstate,
|
||||
}
|
||||
|
||||
/*
|
||||
** setup_field_select
|
||||
** Build a FieldSelect node that says which attribute to project to.
|
||||
** This routine is called by ParseFuncOrColumn() when we have found
|
||||
** a projection on a function result or parameter.
|
||||
* setup_field_select
|
||||
* Build a FieldSelect node that says which attribute to project to.
|
||||
* This routine is called by ParseFuncOrColumn() when we have found
|
||||
* a projection on a function result or parameter.
|
||||
*/
|
||||
static FieldSelect *
|
||||
setup_field_select(Node *input, char *attname, Oid relid)
|
||||
@ -1521,18 +1385,31 @@ setup_field_select(Node *input, char *attname, Oid relid)
|
||||
/*
|
||||
* ParseComplexProjection -
|
||||
* handles function calls with a single argument that is of complex type.
|
||||
* This routine returns NULL if it can't handle the projection (eg. sets).
|
||||
* If the function call is actually a column projection, return a suitably
|
||||
* transformed expression tree. If not, return NULL.
|
||||
*
|
||||
* NB: argument is expected to be transformed already, ie, not a RangeVar.
|
||||
*/
|
||||
static Node *
|
||||
ParseComplexProjection(ParseState *pstate,
|
||||
char *funcname,
|
||||
Node *first_arg,
|
||||
bool *attisset)
|
||||
Node *first_arg)
|
||||
{
|
||||
Oid argtype;
|
||||
Oid argtype = exprType(first_arg);
|
||||
Oid argrelid;
|
||||
AttrNumber attnum;
|
||||
FieldSelect *fselect;
|
||||
|
||||
argrelid = typeidTypeRelid(argtype);
|
||||
if (!argrelid)
|
||||
return NULL; /* probably should not happen */
|
||||
attnum = get_attnum(argrelid, funcname);
|
||||
if (attnum == InvalidAttrNumber)
|
||||
return NULL; /* funcname does not match any column */
|
||||
|
||||
/*
|
||||
* Check for special cases where we don't want to return a FieldSelect.
|
||||
*/
|
||||
switch (nodeTag(first_arg))
|
||||
{
|
||||
case T_Iter:
|
||||
@ -1540,75 +1417,42 @@ ParseComplexProjection(ParseState *pstate,
|
||||
Iter *iter = (Iter *) first_arg;
|
||||
|
||||
/*
|
||||
* If the argument of the Iter returns a tuple, funcname
|
||||
* may be a projection. If so, we stick the FieldSelect
|
||||
* If it's an Iter, we stick the FieldSelect
|
||||
* *inside* the Iter --- this is klugy, but necessary
|
||||
* because ExecTargetList() currently does the right thing
|
||||
* only when the Iter node is at the top level of a
|
||||
* targetlist item.
|
||||
*
|
||||
* XXX Iter should go away altogether...
|
||||
*/
|
||||
argtype = iter->itertype;
|
||||
argrelid = typeidTypeRelid(argtype);
|
||||
if (argrelid &&
|
||||
get_attnum(argrelid, funcname) != InvalidAttrNumber)
|
||||
{
|
||||
fselect = setup_field_select(iter->iterexpr,
|
||||
funcname, argrelid);
|
||||
iter->iterexpr = (Node *) fselect;
|
||||
iter->itertype = fselect->resulttype;
|
||||
return (Node *) iter;
|
||||
}
|
||||
fselect = setup_field_select(iter->iterexpr,
|
||||
funcname, argrelid);
|
||||
iter->iterexpr = (Node *) fselect;
|
||||
iter->itertype = fselect->resulttype;
|
||||
return (Node *) iter;
|
||||
break;
|
||||
}
|
||||
case T_Var:
|
||||
{
|
||||
/*
|
||||
* The argument is a set, so this is either a projection
|
||||
* or a function call on this set.
|
||||
*/
|
||||
*attisset = true;
|
||||
break;
|
||||
}
|
||||
case T_Expr:
|
||||
{
|
||||
Expr *expr = (Expr *) first_arg;
|
||||
Func *funcnode;
|
||||
|
||||
if (expr->opType != FUNC_EXPR)
|
||||
break;
|
||||
Var *var = (Var *) first_arg;
|
||||
|
||||
/*
|
||||
* If the argument is a function returning a tuple,
|
||||
* funcname may be a projection
|
||||
* If the Var is a whole-row tuple, we can just replace it
|
||||
* with a simple Var reference.
|
||||
*/
|
||||
funcnode = (Func *) expr->oper;
|
||||
argtype = funcnode->functype;
|
||||
argrelid = typeidTypeRelid(argtype);
|
||||
if (argrelid &&
|
||||
get_attnum(argrelid, funcname) != InvalidAttrNumber)
|
||||
if (var->varattno == InvalidAttrNumber)
|
||||
{
|
||||
fselect = setup_field_select((Node *) expr,
|
||||
funcname, argrelid);
|
||||
return (Node *) fselect;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_Param:
|
||||
{
|
||||
Param *param = (Param *) first_arg;
|
||||
Oid vartype;
|
||||
int32 vartypmod;
|
||||
|
||||
/*
|
||||
* If the Param is a complex type, this could be a
|
||||
* projection
|
||||
*/
|
||||
argtype = param->paramtype;
|
||||
argrelid = typeidTypeRelid(argtype);
|
||||
if (argrelid &&
|
||||
get_attnum(argrelid, funcname) != InvalidAttrNumber)
|
||||
{
|
||||
fselect = setup_field_select((Node *) param,
|
||||
funcname, argrelid);
|
||||
return (Node *) fselect;
|
||||
get_atttypetypmod(argrelid, attnum,
|
||||
&vartype, &vartypmod);
|
||||
|
||||
return (Node *) makeVar(var->varno,
|
||||
attnum,
|
||||
vartype,
|
||||
vartypmod,
|
||||
var->varlevelsup);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1616,7 +1460,9 @@ ParseComplexProjection(ParseState *pstate,
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
/* Else generate a FieldSelect expression */
|
||||
fselect = setup_field_select(first_arg, funcname, argrelid);
|
||||
return (Node *) fselect;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.59 2002/03/12 00:51:55 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.60 2002/03/21 16:01:07 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -285,7 +285,7 @@ transformArraySubscripts(ParseState *pstate,
|
||||
{
|
||||
if (ai->lidx)
|
||||
{
|
||||
subexpr = transformExpr(pstate, ai->lidx, EXPR_COLUMN_FIRST);
|
||||
subexpr = transformExpr(pstate, ai->lidx);
|
||||
/* If it's not int4 already, try to coerce */
|
||||
subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr),
|
||||
INT4OID, -1);
|
||||
@ -305,7 +305,7 @@ transformArraySubscripts(ParseState *pstate,
|
||||
}
|
||||
lowerIndexpr = lappend(lowerIndexpr, subexpr);
|
||||
}
|
||||
subexpr = transformExpr(pstate, ai->uidx, EXPR_COLUMN_FIRST);
|
||||
subexpr = transformExpr(pstate, ai->uidx);
|
||||
/* If it's not int4 already, try to coerce */
|
||||
subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr),
|
||||
INT4OID, -1);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.63 2002/03/12 00:51:56 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.64 2002/03/21 16:01:09 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -104,7 +104,7 @@ scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
|
||||
int varno = ((RangeTblRef *) nsnode)->rtindex;
|
||||
RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
|
||||
|
||||
if (strcmp(rte->eref->relname, refname) == 0)
|
||||
if (strcmp(rte->eref->aliasname, refname) == 0)
|
||||
result = (Node *) rte;
|
||||
}
|
||||
else if (IsA(nsnode, JoinExpr))
|
||||
@ -113,7 +113,7 @@ scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
|
||||
|
||||
if (j->alias)
|
||||
{
|
||||
if (strcmp(j->alias->relname, refname) == 0)
|
||||
if (strcmp(j->alias->aliasname, refname) == 0)
|
||||
return (Node *) j; /* matched a join alias */
|
||||
|
||||
/*
|
||||
@ -175,7 +175,7 @@ checkNameSpaceConflicts(ParseState *pstate, Node *namespace1,
|
||||
int varno = ((RangeTblRef *) namespace1)->rtindex;
|
||||
RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
|
||||
|
||||
scanNameSpaceForConflict(pstate, namespace2, rte->eref->relname);
|
||||
scanNameSpaceForConflict(pstate, namespace2, rte->eref->aliasname);
|
||||
}
|
||||
else if (IsA(namespace1, JoinExpr))
|
||||
{
|
||||
@ -183,7 +183,7 @@ checkNameSpaceConflicts(ParseState *pstate, Node *namespace1,
|
||||
|
||||
if (j->alias)
|
||||
{
|
||||
scanNameSpaceForConflict(pstate, namespace2, j->alias->relname);
|
||||
scanNameSpaceForConflict(pstate, namespace2, j->alias->aliasname);
|
||||
|
||||
/*
|
||||
* Tables within an aliased join are invisible from outside
|
||||
@ -268,7 +268,7 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname)
|
||||
* Scan the user column names (or aliases) for a match. Complain if
|
||||
* multiple matches.
|
||||
*/
|
||||
foreach(c, rte->eref->attrs)
|
||||
foreach(c, rte->eref->colnames)
|
||||
{
|
||||
attnum++;
|
||||
if (strcmp(strVal(lfirst(c)), colname) == 0)
|
||||
@ -420,15 +420,15 @@ qualifiedNameToVar(ParseState *pstate, char *refname, char *colname,
|
||||
RangeTblEntry *
|
||||
addRangeTableEntry(ParseState *pstate,
|
||||
char *relname,
|
||||
Attr *alias,
|
||||
Alias *alias,
|
||||
bool inh,
|
||||
bool inFromCl)
|
||||
{
|
||||
RangeTblEntry *rte = makeNode(RangeTblEntry);
|
||||
char *refname = alias ? alias->relname : relname;
|
||||
char *refname = alias ? alias->aliasname : relname;
|
||||
LOCKMODE lockmode;
|
||||
Relation rel;
|
||||
Attr *eref;
|
||||
Alias *eref;
|
||||
int maxattrs;
|
||||
int numaliases;
|
||||
int varattno;
|
||||
@ -447,8 +447,8 @@ addRangeTableEntry(ParseState *pstate,
|
||||
rel = heap_openr(relname, lockmode);
|
||||
rte->relid = RelationGetRelid(rel);
|
||||
|
||||
eref = alias ? (Attr *) copyObject(alias) : makeAttr(refname, NULL);
|
||||
numaliases = length(eref->attrs);
|
||||
eref = alias ? (Alias *) copyObject(alias) : makeAlias(refname, NIL);
|
||||
numaliases = length(eref->colnames);
|
||||
|
||||
/*
|
||||
* Since the rel is open anyway, let's check that the number of column
|
||||
@ -459,13 +459,13 @@ addRangeTableEntry(ParseState *pstate,
|
||||
elog(ERROR, "Table \"%s\" has %d columns available but %d columns specified",
|
||||
refname, maxattrs, numaliases);
|
||||
|
||||
/* fill in any unspecified alias columns */
|
||||
/* fill in any unspecified alias columns using actual column names */
|
||||
for (varattno = numaliases; varattno < maxattrs; varattno++)
|
||||
{
|
||||
char *attrname;
|
||||
|
||||
attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname));
|
||||
eref->attrs = lappend(eref->attrs, makeString(attrname));
|
||||
eref->colnames = lappend(eref->colnames, makeString(attrname));
|
||||
}
|
||||
rte->eref = eref;
|
||||
|
||||
@ -512,12 +512,12 @@ addRangeTableEntry(ParseState *pstate,
|
||||
RangeTblEntry *
|
||||
addRangeTableEntryForSubquery(ParseState *pstate,
|
||||
Query *subquery,
|
||||
Attr *alias,
|
||||
Alias *alias,
|
||||
bool inFromCl)
|
||||
{
|
||||
RangeTblEntry *rte = makeNode(RangeTblEntry);
|
||||
char *refname = alias->relname;
|
||||
Attr *eref;
|
||||
char *refname = alias->aliasname;
|
||||
Alias *eref;
|
||||
int numaliases;
|
||||
int varattno;
|
||||
List *tlistitem;
|
||||
@ -529,7 +529,7 @@ addRangeTableEntryForSubquery(ParseState *pstate,
|
||||
rte->alias = alias;
|
||||
|
||||
eref = copyObject(alias);
|
||||
numaliases = length(eref->attrs);
|
||||
numaliases = length(eref->colnames);
|
||||
|
||||
/* fill in any unspecified alias columns */
|
||||
varattno = 0;
|
||||
@ -546,7 +546,7 @@ addRangeTableEntryForSubquery(ParseState *pstate,
|
||||
char *attrname;
|
||||
|
||||
attrname = pstrdup(te->resdom->resname);
|
||||
eref->attrs = lappend(eref->attrs, makeString(attrname));
|
||||
eref->colnames = lappend(eref->colnames, makeString(attrname));
|
||||
}
|
||||
}
|
||||
if (varattno < numaliases)
|
||||
@ -594,11 +594,11 @@ addRangeTableEntryForJoin(ParseState *pstate,
|
||||
List *coltypmods,
|
||||
List *leftcols,
|
||||
List *rightcols,
|
||||
Attr *alias,
|
||||
Alias *alias,
|
||||
bool inFromCl)
|
||||
{
|
||||
RangeTblEntry *rte = makeNode(RangeTblEntry);
|
||||
Attr *eref;
|
||||
Alias *eref;
|
||||
int numaliases;
|
||||
|
||||
rte->rtekind = RTE_JOIN;
|
||||
@ -612,15 +612,15 @@ addRangeTableEntryForJoin(ParseState *pstate,
|
||||
rte->joinrightcols = rightcols;
|
||||
rte->alias = alias;
|
||||
|
||||
eref = alias ? (Attr *) copyObject(alias) : makeAttr("unnamed_join", NULL);
|
||||
numaliases = length(eref->attrs);
|
||||
eref = alias ? (Alias *) copyObject(alias) : makeAlias("unnamed_join", NIL);
|
||||
numaliases = length(eref->colnames);
|
||||
|
||||
/* fill in any unspecified alias columns */
|
||||
if (numaliases < length(colnames))
|
||||
{
|
||||
while (numaliases-- > 0)
|
||||
colnames = lnext(colnames);
|
||||
eref->attrs = nconc(eref->attrs, colnames);
|
||||
eref->colnames = nconc(eref->colnames, colnames);
|
||||
}
|
||||
|
||||
rte->eref = eref;
|
||||
@ -759,7 +759,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
|
||||
|
||||
rel = heap_openr(rte->relname, AccessShareLock);
|
||||
maxattrs = RelationGetNumberOfAttributes(rel);
|
||||
numaliases = length(rte->eref->attrs);
|
||||
numaliases = length(rte->eref->colnames);
|
||||
|
||||
for (varattno = 0; varattno < maxattrs; varattno++)
|
||||
{
|
||||
@ -775,7 +775,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
|
||||
char *label;
|
||||
|
||||
if (varattno < numaliases)
|
||||
label = strVal(nth(varattno, rte->eref->attrs));
|
||||
label = strVal(nth(varattno, rte->eref->colnames));
|
||||
else
|
||||
label = NameStr(attr->attname);
|
||||
*colnames = lappend(*colnames, makeString(pstrdup(label)));
|
||||
@ -798,7 +798,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
|
||||
else if (rte->rtekind == RTE_SUBQUERY)
|
||||
{
|
||||
/* Subquery RTE */
|
||||
List *aliasp = rte->eref->attrs;
|
||||
List *aliasp = rte->eref->colnames;
|
||||
List *tlistitem;
|
||||
|
||||
varattno = 0;
|
||||
@ -836,7 +836,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
|
||||
else if (rte->rtekind == RTE_JOIN)
|
||||
{
|
||||
/* Join RTE */
|
||||
List *aliasp = rte->eref->attrs;
|
||||
List *aliasp = rte->eref->colnames;
|
||||
List *coltypes = rte->joincoltypes;
|
||||
List *coltypmods = rte->joincoltypmods;
|
||||
|
||||
@ -936,8 +936,8 @@ get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
|
||||
* If there is an alias, use it. (This path should always be taken
|
||||
* for non-relation RTEs.)
|
||||
*/
|
||||
if (attnum > 0 && attnum <= length(rte->eref->attrs))
|
||||
return strVal(nth(attnum - 1, rte->eref->attrs));
|
||||
if (attnum > 0 && attnum <= length(rte->eref->colnames))
|
||||
return strVal(nth(attnum - 1, rte->eref->colnames));
|
||||
|
||||
/*
|
||||
* Can get here for a system attribute (which never has an alias), or
|
||||
@ -946,7 +946,7 @@ get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
|
||||
*/
|
||||
if (rte->rtekind != RTE_RELATION)
|
||||
elog(ERROR, "Invalid attnum %d for rangetable entry %s",
|
||||
attnum, rte->eref->relname);
|
||||
attnum, rte->eref->aliasname);
|
||||
|
||||
/*
|
||||
* Use the real name of the table's column
|
||||
@ -1002,7 +1002,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
}
|
||||
/* falling off end of list shouldn't happen... */
|
||||
elog(ERROR, "Subquery %s does not have attribute %d",
|
||||
rte->eref->relname, attnum);
|
||||
rte->eref->aliasname, attnum);
|
||||
}
|
||||
else if (rte->rtekind == RTE_JOIN)
|
||||
{
|
||||
|
@ -8,13 +8,13 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.77 2002/03/12 00:51:56 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.78 2002/03/21 16:01:10 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "miscadmin.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
#include "parser/parsetree.h"
|
||||
#include "parser/parse_coerce.h"
|
||||
@ -56,9 +56,9 @@ transformTargetEntry(ParseState *pstate,
|
||||
|
||||
/* Transform the node if caller didn't do it already */
|
||||
if (expr == NULL)
|
||||
expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST);
|
||||
expr = transformExpr(pstate, node);
|
||||
|
||||
if (IsA(expr, Ident) &&((Ident *) expr)->isRel)
|
||||
if (IsA(expr, RangeVar))
|
||||
elog(ERROR, "You can't use relation names alone in the target list, try relation.*.");
|
||||
|
||||
type_id = exprType(expr);
|
||||
@ -99,11 +99,13 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
{
|
||||
ResTarget *res = (ResTarget *) lfirst(targetlist);
|
||||
|
||||
if (IsA(res->val, Attr))
|
||||
if (IsA(res->val, ColumnRef))
|
||||
{
|
||||
Attr *att = (Attr *) res->val;
|
||||
ColumnRef *cref = (ColumnRef *) res->val;
|
||||
List *fields = cref->fields;
|
||||
int numnames = length(fields);
|
||||
|
||||
if (att->relname != NULL && strcmp(att->relname, "*") == 0)
|
||||
if (numnames == 1 && strcmp(strVal(lfirst(fields)), "*") == 0)
|
||||
{
|
||||
/*
|
||||
* Target item is a single '*', expand all tables (eg.
|
||||
@ -112,27 +114,59 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
p_target = nconc(p_target,
|
||||
ExpandAllTables(pstate));
|
||||
}
|
||||
else if (att->attrs != NIL &&
|
||||
strcmp(strVal(lfirst(att->attrs)), "*") == 0)
|
||||
else if (strcmp(strVal(nth(numnames-1, fields)), "*") == 0)
|
||||
{
|
||||
/*
|
||||
* Target item is relation.*, expand that table (eg.
|
||||
* SELECT emp.*, dname FROM emp, dept)
|
||||
*/
|
||||
char *schemaname;
|
||||
char *relname;
|
||||
RangeTblEntry *rte;
|
||||
int sublevels_up;
|
||||
|
||||
rte = refnameRangeTblEntry(pstate, att->relname,
|
||||
switch (numnames)
|
||||
{
|
||||
case 2:
|
||||
schemaname = NULL;
|
||||
relname = strVal(lfirst(fields));
|
||||
break;
|
||||
case 3:
|
||||
schemaname = strVal(lfirst(fields));
|
||||
relname = strVal(lsecond(fields));
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
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;
|
||||
}
|
||||
default:
|
||||
elog(ERROR, "Invalid qualified name syntax (too many names)");
|
||||
schemaname = NULL; /* keep compiler quiet */
|
||||
relname = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* XXX do something with schema name */
|
||||
rte = refnameRangeTblEntry(pstate, relname,
|
||||
&sublevels_up);
|
||||
if (rte == NULL)
|
||||
rte = addImplicitRTE(pstate, att->relname);
|
||||
rte = addImplicitRTE(pstate, relname);
|
||||
|
||||
p_target = nconc(p_target,
|
||||
expandRelAttrs(pstate, rte));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Plain Attr node, treat it as an expression */
|
||||
/* Plain ColumnRef node, treat it as an expression */
|
||||
p_target = lappend(p_target,
|
||||
transformTargetEntry(pstate,
|
||||
res->val,
|
||||
@ -143,7 +177,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Everything else but Attr */
|
||||
/* Everything else but ColumnRef */
|
||||
p_target = lappend(p_target,
|
||||
transformTargetEntry(pstate,
|
||||
res->val,
|
||||
@ -317,10 +351,9 @@ CoerceTargetExpr(ParseState *pstate,
|
||||
|
||||
/*
|
||||
* checkInsertTargets -
|
||||
* generate a list of column names if not supplied or
|
||||
* generate a list of INSERT column targets if not supplied, or
|
||||
* test supplied column names to make sure they are in target table.
|
||||
* Also return an integer list of the columns' attribute numbers.
|
||||
* (used exclusively for inserts)
|
||||
*/
|
||||
List *
|
||||
checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
|
||||
@ -338,17 +371,16 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
|
||||
|
||||
for (i = 0; i < numcol; i++)
|
||||
{
|
||||
Ident *id = makeNode(Ident);
|
||||
ResTarget *col = makeNode(ResTarget);
|
||||
|
||||
#ifdef _DROP_COLUMN_HACK__
|
||||
if (COLUMN_IS_DROPPED(attr[i]))
|
||||
continue;
|
||||
#endif /* _DROP_COLUMN_HACK__ */
|
||||
id->name = palloc(NAMEDATALEN);
|
||||
StrNCpy(id->name, NameStr(attr[i]->attname), NAMEDATALEN);
|
||||
id->indirection = NIL;
|
||||
id->isRel = false;
|
||||
cols = lappend(cols, id);
|
||||
col->name = pstrdup(NameStr(attr[i]->attname));
|
||||
col->indirection = NIL;
|
||||
col->val = NULL;
|
||||
cols = lappend(cols, col);
|
||||
*attrnos = lappendi(*attrnos, i + 1);
|
||||
}
|
||||
}
|
||||
@ -361,7 +393,7 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
|
||||
|
||||
foreach(tl, cols)
|
||||
{
|
||||
char *name = ((Ident *) lfirst(tl))->name;
|
||||
char *name = ((ResTarget *) lfirst(tl))->name;
|
||||
int attrno;
|
||||
|
||||
/* Lookup column name, elog on failure */
|
||||
@ -458,19 +490,35 @@ FigureColnameInternal(Node *node, char **name)
|
||||
case T_Ident:
|
||||
*name = ((Ident *) node)->name;
|
||||
return 2;
|
||||
case T_Attr:
|
||||
case T_ColumnRef:
|
||||
{
|
||||
List *attrs = ((Attr *) node)->attrs;
|
||||
List *fields = ((ColumnRef *) node)->fields;
|
||||
|
||||
if (attrs)
|
||||
while (lnext(fields) != NIL)
|
||||
fields = lnext(fields);
|
||||
if (strcmp(strVal(lfirst(fields)), "*") != 0)
|
||||
{
|
||||
while (lnext(attrs) != NIL)
|
||||
attrs = lnext(attrs);
|
||||
*name = strVal(lfirst(attrs));
|
||||
*name = strVal(lfirst(fields));
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_ExprFieldSelect:
|
||||
{
|
||||
List *fields = ((ExprFieldSelect *) node)->fields;
|
||||
|
||||
if (fields)
|
||||
{
|
||||
while (lnext(fields) != NIL)
|
||||
fields = lnext(fields);
|
||||
if (strcmp(strVal(lfirst(fields)), "*") != 0)
|
||||
{
|
||||
*name = strVal(lfirst(fields));
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_FuncCall:
|
||||
*name = ((FuncCall *) node)->funcname;
|
||||
return 2;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.63 2001/08/12 21:35:18 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.64 2002/03/21 16:01:16 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -110,63 +110,17 @@ InsertRule(char *rulname,
|
||||
return rewriteObjectId;
|
||||
}
|
||||
|
||||
/*
|
||||
* for now, event_object must be a single attribute
|
||||
*/
|
||||
static void
|
||||
ValidateRule(int event_type,
|
||||
char *eobj_string,
|
||||
char *eslot_string,
|
||||
Node *event_qual,
|
||||
List **action,
|
||||
int is_instead,
|
||||
Oid event_attype)
|
||||
{
|
||||
if (((event_type == CMD_INSERT) || (event_type == CMD_DELETE)) &&
|
||||
eslot_string)
|
||||
{
|
||||
elog(ERROR,
|
||||
"rules not allowed for insert or delete events to an attribute");
|
||||
}
|
||||
|
||||
#ifdef NOT_USED
|
||||
|
||||
/*---------
|
||||
* on retrieve to class.attribute do instead nothing is converted to
|
||||
* 'on retrieve to class.attribute do instead:
|
||||
*
|
||||
* retrieve (attribute = NULL)'
|
||||
*
|
||||
* this is also a terrible hack that works well -- glass
|
||||
*---------
|
||||
*/
|
||||
if (is_instead && !*action && eslot_string && event_type == CMD_SELECT)
|
||||
{
|
||||
char *temp_buffer = (char *) palloc(strlen(template) + 80);
|
||||
|
||||
sprintf(temp_buffer, template, event_attype,
|
||||
get_typlen(event_attype), eslot_string,
|
||||
event_attype);
|
||||
|
||||
*action = (List *) stringToNode(temp_buffer);
|
||||
|
||||
pfree(temp_buffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DefineQueryRewrite(RuleStmt *stmt)
|
||||
{
|
||||
CmdType event_type = stmt->event;
|
||||
Attr *event_obj = stmt->object;
|
||||
RangeVar *event_obj = stmt->relation;
|
||||
Node *event_qual = stmt->whereClause;
|
||||
CmdType event_type = stmt->event;
|
||||
bool is_instead = stmt->instead;
|
||||
List *action = stmt->actions;
|
||||
Relation event_relation;
|
||||
Oid ev_relid;
|
||||
Oid ruleId;
|
||||
char *eslot_string = NULL;
|
||||
int event_attno;
|
||||
Oid event_attype;
|
||||
char *actionP,
|
||||
@ -186,23 +140,6 @@ DefineQueryRewrite(RuleStmt *stmt)
|
||||
event_relation = heap_openr(event_obj->relname, AccessExclusiveLock);
|
||||
ev_relid = RelationGetRelid(event_relation);
|
||||
|
||||
/*
|
||||
* The current rewrite handler is known to work on relation level
|
||||
* rules only. And for SELECT events, it expects one non-nothing
|
||||
* action that is instead and returns exactly a tuple of the rewritten
|
||||
* relation. This restricts SELECT rules to views.
|
||||
*
|
||||
* Jan
|
||||
*/
|
||||
if (event_obj->attrs)
|
||||
elog(ERROR, "attribute level rules currently not supported");
|
||||
|
||||
/*
|
||||
* eslot_string = strVal(lfirst(event_obj->attrs));
|
||||
*/
|
||||
else
|
||||
eslot_string = NULL;
|
||||
|
||||
/*
|
||||
* No rule actions that modify OLD or NEW
|
||||
*/
|
||||
@ -358,21 +295,8 @@ DefineQueryRewrite(RuleStmt *stmt)
|
||||
/*
|
||||
* This rule is allowed - prepare to install it.
|
||||
*/
|
||||
if (eslot_string == NULL)
|
||||
{
|
||||
event_attno = -1;
|
||||
event_attype = InvalidOid;
|
||||
}
|
||||
else
|
||||
{
|
||||
event_attno = attnameAttNum(event_relation, eslot_string);
|
||||
event_attype = attnumTypeId(event_relation, event_attno);
|
||||
}
|
||||
|
||||
/* fix bug about instead nothing */
|
||||
ValidateRule(event_type, event_obj->relname,
|
||||
eslot_string, event_qual, &action,
|
||||
is_instead, event_attype);
|
||||
event_attno = -1;
|
||||
event_attype = InvalidOid;
|
||||
|
||||
/*
|
||||
* We want the rule's table references to be checked as though by the
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.62 2002/03/12 00:51:58 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.63 2002/03/21 16:01:17 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -573,9 +573,9 @@ getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
|
||||
* they've been pushed down to the SELECT.
|
||||
*/
|
||||
if (length(parsetree->rtable) >= 2 &&
|
||||
strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->relname,
|
||||
strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->aliasname,
|
||||
"*OLD*") == 0 &&
|
||||
strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->relname,
|
||||
strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->aliasname,
|
||||
"*NEW*") == 0)
|
||||
return parsetree;
|
||||
Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr));
|
||||
@ -589,9 +589,9 @@ getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
|
||||
selectquery->commandType == CMD_SELECT))
|
||||
elog(ERROR, "getInsertSelectQuery: expected to find SELECT subquery");
|
||||
if (length(selectquery->rtable) >= 2 &&
|
||||
strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->relname,
|
||||
strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->aliasname,
|
||||
"*OLD*") == 0 &&
|
||||
strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->relname,
|
||||
strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->aliasname,
|
||||
"*NEW*") == 0)
|
||||
{
|
||||
if (subquery_ptr)
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.257 2002/03/19 16:10:48 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.258 2002/03/21 16:01:25 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* this is the "main" module of the postgres backend and
|
||||
@ -1722,7 +1722,7 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
if (!IsUnderPostmaster)
|
||||
{
|
||||
puts("\nPOSTGRES backend interactive interface ");
|
||||
puts("$Revision: 1.257 $ $Date: 2002/03/19 16:10:48 $\n");
|
||||
puts("$Revision: 1.258 $ $Date: 2002/03/21 16:01:25 $\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2216,6 +2216,10 @@ CreateCommandTag(Node *parsetree)
|
||||
tag = "CREATE DOMAIN";
|
||||
break;
|
||||
|
||||
case T_CreateSchemaStmt:
|
||||
tag = "CREATE";
|
||||
break;
|
||||
|
||||
case T_CreateStmt:
|
||||
tag = "CREATE";
|
||||
break;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.50 2002/03/06 06:10:10 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.51 2002/03/21 16:01:27 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -181,12 +181,12 @@ ProcessQuery(Query *parsetree,
|
||||
*/
|
||||
if (isRetrieveIntoPortal)
|
||||
{
|
||||
intoName = parsetree->into;
|
||||
intoName = parsetree->into->relname;
|
||||
portal = PreparePortal(intoName);
|
||||
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
|
||||
parsetree = copyObject(parsetree);
|
||||
plan = copyObject(plan);
|
||||
intoName = parsetree->into; /* use copied name in QueryDesc */
|
||||
intoName = parsetree->into->relname; /* use copied name in QueryDesc */
|
||||
|
||||
/*
|
||||
* We stay in portal's memory context for now, so that query desc,
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.135 2002/03/20 19:44:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.136 2002/03/21 16:01:30 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -218,6 +218,14 @@ ProcessUtility(Node *parsetree,
|
||||
/*
|
||||
* relation and attribute manipulation
|
||||
*/
|
||||
case T_CreateSchemaStmt:
|
||||
{
|
||||
CreateSchemaStmt *stmt = (CreateSchemaStmt *) parsetree;
|
||||
|
||||
CreateSchemaCommand(stmt);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_CreateStmt:
|
||||
DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
|
||||
|
||||
@ -226,19 +234,19 @@ ProcessUtility(Node *parsetree,
|
||||
* secondary relation too.
|
||||
*/
|
||||
CommandCounterIncrement();
|
||||
AlterTableCreateToastTable(((CreateStmt *) parsetree)->relname,
|
||||
AlterTableCreateToastTable(((CreateStmt *) parsetree)->relation->relname,
|
||||
true);
|
||||
break;
|
||||
|
||||
case T_DropStmt:
|
||||
{
|
||||
DropStmt *stmt = (DropStmt *) parsetree;
|
||||
List *args = stmt->names;
|
||||
List *args = stmt->objects;
|
||||
List *arg;
|
||||
|
||||
foreach(arg, args)
|
||||
{
|
||||
relname = strVal(lfirst(arg));
|
||||
relname = ((RangeVar *) lfirst(arg))->relname;
|
||||
|
||||
switch (stmt->removeType)
|
||||
{
|
||||
@ -299,7 +307,8 @@ ProcessUtility(Node *parsetree,
|
||||
|
||||
case T_TruncateStmt:
|
||||
{
|
||||
TruncateRelation(((TruncateStmt *) parsetree)->relName);
|
||||
relname = ((TruncateStmt *) parsetree)->relation->relname;
|
||||
TruncateRelation(relname);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -322,7 +331,7 @@ ProcessUtility(Node *parsetree,
|
||||
if (stmt->direction != FROM)
|
||||
SetQuerySnapshot();
|
||||
|
||||
DoCopy(stmt->relname,
|
||||
DoCopy(stmt->relation->relname,
|
||||
stmt->binary,
|
||||
stmt->oids,
|
||||
(bool) (stmt->direction == FROM),
|
||||
@ -345,7 +354,7 @@ ProcessUtility(Node *parsetree,
|
||||
{
|
||||
RenameStmt *stmt = (RenameStmt *) parsetree;
|
||||
|
||||
relname = stmt->relname;
|
||||
relname = stmt->relation->relname;
|
||||
if (!allowSystemTableMods && IsSystemRelationName(relname))
|
||||
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
|
||||
relname);
|
||||
@ -380,7 +389,7 @@ ProcessUtility(Node *parsetree,
|
||||
renameatt(relname, /* relname */
|
||||
stmt->column, /* old att name */
|
||||
stmt->newname, /* new att name */
|
||||
interpretInhOption(stmt->inhOpt)); /* recursive? */
|
||||
interpretInhOption(stmt->relation->inhOpt)); /* recursive? */
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -398,47 +407,47 @@ ProcessUtility(Node *parsetree,
|
||||
switch (stmt->subtype)
|
||||
{
|
||||
case 'A': /* ADD COLUMN */
|
||||
AlterTableAddColumn(stmt->relname,
|
||||
interpretInhOption(stmt->inhOpt),
|
||||
AlterTableAddColumn(stmt->relation->relname,
|
||||
interpretInhOption((stmt->relation)->inhOpt),
|
||||
(ColumnDef *) stmt->def);
|
||||
break;
|
||||
case 'T': /* ALTER COLUMN DEFAULT */
|
||||
AlterTableAlterColumnDefault(stmt->relname,
|
||||
interpretInhOption(stmt->inhOpt),
|
||||
AlterTableAlterColumnDefault(stmt->relation->relname,
|
||||
interpretInhOption((stmt->relation)->inhOpt),
|
||||
stmt->name,
|
||||
stmt->def);
|
||||
break;
|
||||
case 'S': /* ALTER COLUMN STATISTICS */
|
||||
case 'M': /* ALTER COLUMN STORAGE */
|
||||
AlterTableAlterColumnFlags(stmt->relname,
|
||||
interpretInhOption(stmt->inhOpt),
|
||||
AlterTableAlterColumnFlags(stmt->relation->relname,
|
||||
interpretInhOption(stmt->relation->inhOpt),
|
||||
stmt->name,
|
||||
stmt->def,
|
||||
&(stmt->subtype));
|
||||
break;
|
||||
case 'D': /* DROP COLUMN */
|
||||
AlterTableDropColumn(stmt->relname,
|
||||
interpretInhOption(stmt->inhOpt),
|
||||
AlterTableDropColumn(stmt->relation->relname,
|
||||
interpretInhOption(stmt->relation->inhOpt),
|
||||
stmt->name,
|
||||
stmt->behavior);
|
||||
break;
|
||||
case 'C': /* ADD CONSTRAINT */
|
||||
AlterTableAddConstraint(stmt->relname,
|
||||
interpretInhOption(stmt->inhOpt),
|
||||
AlterTableAddConstraint(stmt->relation->relname,
|
||||
interpretInhOption(stmt->relation->inhOpt),
|
||||
(List *) stmt->def);
|
||||
break;
|
||||
case 'X': /* DROP CONSTRAINT */
|
||||
AlterTableDropConstraint(stmt->relname,
|
||||
interpretInhOption(stmt->inhOpt),
|
||||
AlterTableDropConstraint(stmt->relation->relname,
|
||||
interpretInhOption(stmt->relation->inhOpt),
|
||||
stmt->name,
|
||||
stmt->behavior);
|
||||
break;
|
||||
case 'E': /* CREATE TOAST TABLE */
|
||||
AlterTableCreateToastTable(stmt->relname,
|
||||
AlterTableCreateToastTable(stmt->relation->relname,
|
||||
false);
|
||||
break;
|
||||
case 'U': /* ALTER OWNER */
|
||||
AlterTableOwner(stmt->relname,
|
||||
AlterTableOwner(stmt->relation->relname,
|
||||
stmt->name);
|
||||
break;
|
||||
default: /* oops */
|
||||
@ -487,7 +496,7 @@ ProcessUtility(Node *parsetree,
|
||||
{
|
||||
ViewStmt *stmt = (ViewStmt *) parsetree;
|
||||
|
||||
DefineView(stmt->viewname, stmt->query); /* retrieve parsetree */
|
||||
DefineView(stmt->view->relname, stmt->query); /* retrieve parsetree */
|
||||
}
|
||||
break;
|
||||
|
||||
@ -499,17 +508,17 @@ ProcessUtility(Node *parsetree,
|
||||
{
|
||||
IndexStmt *stmt = (IndexStmt *) parsetree;
|
||||
|
||||
relname = stmt->relname;
|
||||
relname = stmt->relation->relname;
|
||||
if (!allowSystemTableMods && IsSystemRelationName(relname))
|
||||
elog(ERROR, "CREATE INDEX: relation \"%s\" is a system catalog",
|
||||
relname);
|
||||
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
|
||||
elog(ERROR, "permission denied");
|
||||
|
||||
DefineIndex(stmt->relname, /* relation name */
|
||||
stmt->idxname, /* index name */
|
||||
stmt->accessMethod, /* am name */
|
||||
stmt->indexParams, /* parameters */
|
||||
DefineIndex(stmt->relation->relname, /* relation */
|
||||
stmt->idxname, /* index name */
|
||||
stmt->accessMethod, /* am name */
|
||||
stmt->indexParams, /* parameters */
|
||||
stmt->unique,
|
||||
stmt->primary,
|
||||
(Expr *) stmt->whereClause,
|
||||
@ -522,7 +531,7 @@ ProcessUtility(Node *parsetree,
|
||||
RuleStmt *stmt = (RuleStmt *) parsetree;
|
||||
int aclcheck_result;
|
||||
|
||||
relname = stmt->object->relname;
|
||||
relname = stmt->relation->relname;
|
||||
aclcheck_result = pg_aclcheck(relname, GetUserId(), ACL_RULE);
|
||||
if (aclcheck_result != ACLCHECK_OK)
|
||||
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
|
||||
@ -603,7 +612,7 @@ ProcessUtility(Node *parsetree,
|
||||
{
|
||||
NotifyStmt *stmt = (NotifyStmt *) parsetree;
|
||||
|
||||
Async_Notify(stmt->relname);
|
||||
Async_Notify(stmt->relation->relname);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -611,7 +620,7 @@ ProcessUtility(Node *parsetree,
|
||||
{
|
||||
ListenStmt *stmt = (ListenStmt *) parsetree;
|
||||
|
||||
Async_Listen(stmt->relname, MyProcPid);
|
||||
Async_Listen(stmt->relation->relname, MyProcPid);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -619,7 +628,7 @@ ProcessUtility(Node *parsetree,
|
||||
{
|
||||
UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
|
||||
|
||||
Async_Unlisten(stmt->relname, MyProcPid);
|
||||
Async_Unlisten(stmt->relation->relname, MyProcPid);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -636,7 +645,7 @@ ProcessUtility(Node *parsetree,
|
||||
{
|
||||
ClusterStmt *stmt = (ClusterStmt *) parsetree;
|
||||
|
||||
relname = stmt->relname;
|
||||
relname = stmt->relation->relname;
|
||||
if (IsSystemRelationName(relname))
|
||||
elog(ERROR, "CLUSTER: relation \"%s\" is a system catalog",
|
||||
relname);
|
||||
@ -712,7 +721,6 @@ ProcessUtility(Node *parsetree,
|
||||
|
||||
/*
|
||||
* ******************************** DOMAIN statements ****
|
||||
*
|
||||
*/
|
||||
case T_CreateDomainStmt:
|
||||
DefineDomain((CreateDomainStmt *) parsetree);
|
||||
@ -720,9 +728,7 @@ ProcessUtility(Node *parsetree,
|
||||
|
||||
/*
|
||||
* ******************************** USER statements ****
|
||||
*
|
||||
*/
|
||||
|
||||
case T_CreateUserStmt:
|
||||
CreateUser((CreateUserStmt *) parsetree);
|
||||
break;
|
||||
@ -774,7 +780,7 @@ ProcessUtility(Node *parsetree,
|
||||
switch (stmt->reindexType)
|
||||
{
|
||||
case INDEX:
|
||||
relname = (char *) stmt->name;
|
||||
relname = (char *) stmt->relation->relname;
|
||||
if (IsSystemRelationName(relname))
|
||||
{
|
||||
if (!allowSystemTableMods)
|
||||
@ -789,7 +795,7 @@ ProcessUtility(Node *parsetree,
|
||||
ReindexIndex(relname, stmt->force);
|
||||
break;
|
||||
case TABLE:
|
||||
relname = (char *) stmt->name;
|
||||
relname = (char *) stmt->relation->relname;
|
||||
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
|
||||
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
|
||||
ReindexTable(relname, stmt->force);
|
||||
|
@ -3,7 +3,7 @@
|
||||
* back to source text
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.93 2002/03/12 00:51:59 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.94 2002/03/21 16:01:34 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@ -48,6 +48,7 @@
|
||||
#include "catalog/pg_shadow.h"
|
||||
#include "executor/spi.h"
|
||||
#include "lib/stringinfo.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
#include "optimizer/clauses.h"
|
||||
#include "optimizer/tlist.h"
|
||||
#include "parser/keywords.h"
|
||||
@ -659,8 +660,7 @@ deparse_context_for(char *relname, Oid relid)
|
||||
rte->rtekind = RTE_RELATION;
|
||||
rte->relname = relname;
|
||||
rte->relid = relid;
|
||||
rte->eref = makeNode(Attr);
|
||||
rte->eref->relname = relname;
|
||||
rte->eref = makeAlias(relname, NIL);
|
||||
rte->inh = false;
|
||||
rte->inFromCl = true;
|
||||
|
||||
@ -755,9 +755,7 @@ deparse_context_for_subplan(const char *name, List *tlist,
|
||||
rte->rtekind = RTE_SPECIAL; /* XXX */
|
||||
rte->relname = pstrdup(name);
|
||||
rte->relid = InvalidOid;
|
||||
rte->eref = makeNode(Attr);
|
||||
rte->eref->relname = rte->relname;
|
||||
rte->eref->attrs = attrs;
|
||||
rte->eref = makeAlias(rte->relname, attrs);
|
||||
rte->inh = false;
|
||||
rte->inFromCl = true;
|
||||
|
||||
@ -1462,7 +1460,7 @@ get_utility_query_def(Query *query, deparse_context *context)
|
||||
{
|
||||
NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
|
||||
|
||||
appendStringInfo(buf, "NOTIFY %s", quote_identifier(stmt->relname));
|
||||
appendStringInfo(buf, "NOTIFY %s", quote_identifier(stmt->relation->relname));
|
||||
}
|
||||
else
|
||||
elog(ERROR, "get_utility_query_def: unexpected statement type");
|
||||
@ -1512,7 +1510,7 @@ get_names_for_var(Var *var, deparse_context *context,
|
||||
if (rte->rtekind == RTE_JOIN && rte->alias == NULL)
|
||||
*refname = NULL;
|
||||
else
|
||||
*refname = rte->eref->relname;
|
||||
*refname = rte->eref->aliasname;
|
||||
|
||||
if (var->varattno == InvalidAttrNumber)
|
||||
*attname = NULL;
|
||||
@ -1758,12 +1756,11 @@ get_rule_expr(Node *node, deparse_context *context)
|
||||
/*
|
||||
* If the argument is simple enough, we could emit
|
||||
* arg.fieldname, but most cases where FieldSelect is used
|
||||
* are *not* simple. For now, always use the projection-
|
||||
* function syntax.
|
||||
* are *not* simple. So, always use parenthesized syntax.
|
||||
*/
|
||||
appendStringInfo(buf, "%s(", quote_identifier(fieldname));
|
||||
appendStringInfoChar(buf, '(');
|
||||
get_rule_expr(fselect->arg, context);
|
||||
appendStringInfoChar(buf, ')');
|
||||
appendStringInfo(buf, ").%s", quote_identifier(fieldname));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2302,9 +2299,9 @@ get_from_clause(Query *query, deparse_context *context)
|
||||
|
||||
if (!rte->inFromCl)
|
||||
continue;
|
||||
if (strcmp(rte->eref->relname, "*NEW*") == 0)
|
||||
if (strcmp(rte->eref->aliasname, "*NEW*") == 0)
|
||||
continue;
|
||||
if (strcmp(rte->eref->relname, "*OLD*") == 0)
|
||||
if (strcmp(rte->eref->aliasname, "*OLD*") == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2342,15 +2339,15 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
||||
if (rte->alias != NULL)
|
||||
{
|
||||
appendStringInfo(buf, " %s",
|
||||
quote_identifier(rte->alias->relname));
|
||||
if (rte->alias->attrs != NIL)
|
||||
quote_identifier(rte->alias->aliasname));
|
||||
if (rte->alias->colnames != NIL)
|
||||
{
|
||||
List *col;
|
||||
|
||||
appendStringInfo(buf, "(");
|
||||
foreach(col, rte->alias->attrs)
|
||||
foreach(col, rte->alias->colnames)
|
||||
{
|
||||
if (col != rte->alias->attrs)
|
||||
if (col != rte->alias->colnames)
|
||||
appendStringInfo(buf, ", ");
|
||||
appendStringInfo(buf, "%s",
|
||||
quote_identifier(strVal(lfirst(col))));
|
||||
@ -2420,15 +2417,15 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
||||
if (j->alias != NULL)
|
||||
{
|
||||
appendStringInfo(buf, " %s",
|
||||
quote_identifier(j->alias->relname));
|
||||
if (j->alias->attrs != NIL)
|
||||
quote_identifier(j->alias->aliasname));
|
||||
if (j->alias->colnames != NIL)
|
||||
{
|
||||
List *col;
|
||||
|
||||
appendStringInfo(buf, "(");
|
||||
foreach(col, j->alias->attrs)
|
||||
foreach(col, j->alias->colnames)
|
||||
{
|
||||
if (col != j->alias->attrs)
|
||||
if (col != j->alias->colnames)
|
||||
appendStringInfo(buf, ", ");
|
||||
appendStringInfo(buf, "%s",
|
||||
quote_identifier(strVal(lfirst(col))));
|
||||
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: catversion.h,v 1.107 2002/03/20 19:44:48 tgl Exp $
|
||||
* $Id: catversion.h,v 1.108 2002/03/21 16:01:39 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200203191
|
||||
#define CATALOG_VERSION_NO 200203211
|
||||
|
||||
#endif
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: command.h,v 1.33 2002/03/05 05:33:29 momjian Exp $
|
||||
* $Id: command.h,v 1.34 2002/03/21 16:01:41 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -72,4 +72,9 @@ extern void AlterTableOwner(const char *relationName, const char *newOwnerName);
|
||||
*/
|
||||
extern void LockTableCommand(LockStmt *lockstmt);
|
||||
|
||||
/*
|
||||
* SCHEMA
|
||||
*/
|
||||
extern void CreateSchemaCommand(CreateSchemaStmt *parsetree);
|
||||
|
||||
#endif /* COMMAND_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: makefuncs.h,v 1.31 2002/03/20 19:45:01 tgl Exp $
|
||||
* $Id: makefuncs.h,v 1.32 2002/03/21 16:01:43 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -44,7 +44,7 @@ extern Const *makeConst(Oid consttype,
|
||||
|
||||
extern Const *makeNullConst(Oid consttype);
|
||||
|
||||
extern Attr *makeAttr(char *relname, char *attname);
|
||||
extern Alias *makeAlias(const char *aliasname, List *colnames);
|
||||
|
||||
extern RelabelType *makeRelabelType(Node *arg, Oid rtype, int32 rtypmod);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: nodes.h,v 1.101 2002/03/19 02:18:23 momjian Exp $
|
||||
* $Id: nodes.h,v 1.102 2002/03/21 16:01:44 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -195,21 +195,24 @@ typedef enum NodeTag
|
||||
T_DropGroupStmt,
|
||||
T_ReindexStmt,
|
||||
T_CheckPointStmt,
|
||||
T_CreateSchemaStmt,
|
||||
T_AlterDatabaseSetStmt,
|
||||
T_AlterUserSetStmt,
|
||||
|
||||
T_A_Expr = 700,
|
||||
T_Attr,
|
||||
T_A_Const,
|
||||
T_ParamNo,
|
||||
T_ColumnRef,
|
||||
T_ParamRef,
|
||||
T_Ident,
|
||||
T_A_Const,
|
||||
T_FuncCall,
|
||||
T_A_Indices,
|
||||
T_ExprFieldSelect,
|
||||
T_ResTarget,
|
||||
T_TypeCast,
|
||||
T_RangeSubselect,
|
||||
T_SortGroupBy,
|
||||
T_Alias,
|
||||
T_RangeVar,
|
||||
T_RangeSubselect,
|
||||
T_TypeName,
|
||||
T_IndexElem,
|
||||
T_ColumnDef,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parsenodes.h,v 1.162 2002/03/20 19:45:02 tgl Exp $
|
||||
* $Id: parsenodes.h,v 1.163 2002/03/21 16:01:46 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -49,10 +49,10 @@ typedef struct Query
|
||||
* statement */
|
||||
|
||||
int resultRelation; /* target relation (index into rtable) */
|
||||
char *into; /* portal (cursor) name */
|
||||
struct RangeVar *into; /* target relation or portal (cursor)
|
||||
* for portal just name is meaningful */
|
||||
bool isPortal; /* is this a retrieve into portal? */
|
||||
bool isBinary; /* binary portal? */
|
||||
bool isTemp; /* is 'into' a temp table? */
|
||||
|
||||
bool hasAggs; /* has aggregates in tlist or havingQual */
|
||||
bool hasSubLinks; /* has subquery SubLink */
|
||||
@ -125,15 +125,30 @@ typedef struct TypeName
|
||||
} TypeName;
|
||||
|
||||
/*
|
||||
* ParamNo - specifies a parameter reference
|
||||
* ColumnRef - specifies a reference to a column, or possibly a whole tuple
|
||||
*
|
||||
* The "fields" list must be nonempty; its last component may be "*"
|
||||
* instead of a field name. Subscripts are optional.
|
||||
*/
|
||||
typedef struct ParamNo
|
||||
typedef struct ColumnRef
|
||||
{
|
||||
NodeTag type;
|
||||
List *fields; /* field names (list of Value strings) */
|
||||
List *indirection; /* subscripts (list of A_Indices) */
|
||||
} ColumnRef;
|
||||
|
||||
/*
|
||||
* ParamRef - specifies a parameter reference
|
||||
*
|
||||
* The parameter could be qualified with field names and/or subscripts
|
||||
*/
|
||||
typedef struct ParamRef
|
||||
{
|
||||
NodeTag type;
|
||||
int number; /* the number of the parameter */
|
||||
TypeName *typename; /* the typecast */
|
||||
List *indirection; /* array references */
|
||||
} ParamNo;
|
||||
List *fields; /* field names (list of Value strings) */
|
||||
List *indirection; /* subscripts (list of A_Indices) */
|
||||
} ParamRef;
|
||||
|
||||
/*
|
||||
* A_Expr - binary expressions
|
||||
@ -147,22 +162,6 @@ typedef struct A_Expr
|
||||
Node *rexpr; /* right argument */
|
||||
} A_Expr;
|
||||
|
||||
/*
|
||||
* Attr -
|
||||
* specifies an Attribute (ie. a Column); could have nested dots or
|
||||
* array references.
|
||||
*
|
||||
*/
|
||||
typedef struct Attr
|
||||
{
|
||||
NodeTag type;
|
||||
char *relname; /* name of relation (can be "*") */
|
||||
ParamNo *paramNo; /* or a parameter */
|
||||
List *attrs; /* attributes (possibly nested); list of
|
||||
* Values (strings) */
|
||||
List *indirection; /* array refs (list of A_Indices') */
|
||||
} Attr;
|
||||
|
||||
/*
|
||||
* A_Const - a constant expression
|
||||
*/
|
||||
@ -176,11 +175,11 @@ typedef struct A_Const
|
||||
/*
|
||||
* TypeCast - a CAST expression
|
||||
*
|
||||
* NOTE: for mostly historical reasons, A_Const and ParamNo parsenodes contain
|
||||
* NOTE: for mostly historical reasons, A_Const parsenodes contain
|
||||
* room for a TypeName; we only generate a separate TypeCast node if the
|
||||
* argument to be casted is neither of those kinds of nodes. In theory either
|
||||
* representation would work, but it is convenient (especially for A_Const)
|
||||
* to have the target type immediately available.
|
||||
* argument to be casted is not a constant. In theory either representation
|
||||
* would work, but it is convenient to have the target type immediately
|
||||
* available while resolving a constant's datatype.
|
||||
*/
|
||||
typedef struct TypeCast
|
||||
{
|
||||
@ -284,17 +283,13 @@ typedef struct ColumnDef
|
||||
|
||||
/*
|
||||
* Ident -
|
||||
* an identifier (could be an attribute or a relation name). Depending
|
||||
* on the context at transformStmt time, the identifier is treated as
|
||||
* either a relation name (in which case, isRel will be set) or an
|
||||
* attribute (in which case, it will be transformed into an Attr).
|
||||
* an unqualified identifier. This is currently used only in the context
|
||||
* of column name lists.
|
||||
*/
|
||||
typedef struct Ident
|
||||
{
|
||||
NodeTag type;
|
||||
char *name; /* its name */
|
||||
List *indirection; /* array references */
|
||||
bool isRel; /* is this a relation or a column? */
|
||||
} Ident;
|
||||
|
||||
/*
|
||||
@ -324,6 +319,21 @@ typedef struct A_Indices
|
||||
Node *uidx;
|
||||
} A_Indices;
|
||||
|
||||
/*
|
||||
* ExprFieldSelect - select a field and/or array element from an expression
|
||||
*
|
||||
* This is used in the raw parsetree to represent selection from an
|
||||
* arbitrary expression (not a column or param reference). Either
|
||||
* fields or indirection may be NIL if not used.
|
||||
*/
|
||||
typedef struct ExprFieldSelect
|
||||
{
|
||||
NodeTag type;
|
||||
Node *arg; /* the thing being selected from */
|
||||
List *fields; /* field names (list of Value strings) */
|
||||
List *indirection; /* subscripts (list of A_Indices) */
|
||||
} ExprFieldSelect;
|
||||
|
||||
/*
|
||||
* ResTarget -
|
||||
* result target (used in target list of pre-transformed Parse trees)
|
||||
@ -358,15 +368,37 @@ typedef struct SortGroupBy
|
||||
Node *node; /* Expression */
|
||||
} SortGroupBy;
|
||||
|
||||
/*
|
||||
* Alias -
|
||||
* specifies an alias for a range variable; the alias might also
|
||||
* specify renaming of columns within the table.
|
||||
*/
|
||||
typedef struct Alias
|
||||
{
|
||||
NodeTag type;
|
||||
char *aliasname; /* aliased rel name (never qualified) */
|
||||
List *colnames; /* optional list of column aliases */
|
||||
/* Note: colnames is a list of Value nodes (always strings) */
|
||||
} Alias;
|
||||
|
||||
/*
|
||||
* RangeVar - range variable, used in FROM clauses
|
||||
*
|
||||
* Also used to represent table names in utility statements; there, the alias
|
||||
* field is not used, and inhOpt shows whether to apply the operation
|
||||
* recursively to child tables. In some contexts it is also useful to carry
|
||||
* a TEMP table indication here.
|
||||
*/
|
||||
typedef struct RangeVar
|
||||
{
|
||||
NodeTag type;
|
||||
char *relname; /* the relation name */
|
||||
InhOption inhOpt; /* expand rel by inheritance? */
|
||||
Attr *name; /* optional table alias & column aliases */
|
||||
char *catalogname; /* the catalog (database) name, or NULL */
|
||||
char *schemaname; /* the schema name, or NULL */
|
||||
char *relname; /* the relation/sequence name */
|
||||
InhOption inhOpt; /* expand rel by inheritance?
|
||||
* recursively act on children? */
|
||||
bool istemp; /* is this a temp relation/sequence? */
|
||||
Alias *alias; /* table alias & optional column aliases */
|
||||
} RangeVar;
|
||||
|
||||
/*
|
||||
@ -376,7 +408,7 @@ typedef struct RangeSubselect
|
||||
{
|
||||
NodeTag type;
|
||||
Node *subquery; /* the untransformed sub-select clause */
|
||||
Attr *name; /* table alias & optional column aliases */
|
||||
Alias *alias; /* table alias & optional column aliases */
|
||||
} RangeSubselect;
|
||||
|
||||
/*
|
||||
@ -437,7 +469,7 @@ typedef struct TargetEntry
|
||||
* like outer joins and join-output-column aliasing.) Other special
|
||||
* RTE types also exist, as indicated by RTEKind.
|
||||
*
|
||||
* alias is an Attr node representing the AS alias-clause attached to the
|
||||
* alias is an Alias node representing the AS alias-clause attached to the
|
||||
* FROM expression, or NULL if no clause.
|
||||
*
|
||||
* eref is the table reference name and column reference names (either
|
||||
@ -489,7 +521,7 @@ typedef struct RangeTblEntry
|
||||
*/
|
||||
|
||||
/*
|
||||
* Fields valid for a plain relation or inh_relation RTE (else NULL/zero):
|
||||
* Fields valid for a plain relation RTE (else NULL/zero):
|
||||
*/
|
||||
char *relname; /* real name of the relation */
|
||||
Oid relid; /* OID of the relation */
|
||||
@ -517,8 +549,8 @@ typedef struct RangeTblEntry
|
||||
/*
|
||||
* Fields valid in all RTEs:
|
||||
*/
|
||||
Attr *alias; /* user-written alias clause, if any */
|
||||
Attr *eref; /* expanded reference names */
|
||||
Alias *alias; /* user-written alias clause, if any */
|
||||
Alias *eref; /* expanded reference names */
|
||||
bool inh; /* inheritance requested? */
|
||||
bool inFromCl; /* present in FROM clause */
|
||||
bool checkForRead; /* check rel for read access */
|
||||
@ -570,7 +602,7 @@ typedef SortClause GroupClause;
|
||||
typedef struct InsertStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *relname; /* relation to insert into */
|
||||
RangeVar *relation; /* relation to insert into */
|
||||
List *cols; /* optional: names of the target columns */
|
||||
|
||||
/*
|
||||
@ -589,9 +621,8 @@ typedef struct InsertStmt
|
||||
typedef struct DeleteStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *relname; /* relation to delete from */
|
||||
RangeVar *relation; /* relation to delete from */
|
||||
Node *whereClause; /* qualifications */
|
||||
InhOption inhOpt; /* recursively act on children? */
|
||||
} DeleteStmt;
|
||||
|
||||
/* ----------------------
|
||||
@ -601,11 +632,10 @@ typedef struct DeleteStmt
|
||||
typedef struct UpdateStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *relname; /* relation to update */
|
||||
RangeVar *relation; /* relation to update */
|
||||
List *targetList; /* the target list (of ResTarget) */
|
||||
Node *whereClause; /* qualifications */
|
||||
List *fromClause; /* the from clause */
|
||||
InhOption inhOpt; /* recursively act on children? */
|
||||
List *fromClause; /* optional from clause for more tables */
|
||||
} UpdateStmt;
|
||||
|
||||
/* ----------------------
|
||||
@ -639,8 +669,7 @@ typedef struct SelectStmt
|
||||
List *distinctClause; /* NULL, list of DISTINCT ON exprs, or
|
||||
* lcons(NIL,NIL) for all (SELECT
|
||||
* DISTINCT) */
|
||||
char *into; /* name of table (for select into table) */
|
||||
bool istemp; /* into is a temp table? */
|
||||
RangeVar *into; /* target table (for select into table) */
|
||||
List *intoColNames; /* column names for into table */
|
||||
List *targetList; /* the target list (of ResTarget) */
|
||||
List *fromClause; /* the FROM clause */
|
||||
@ -703,6 +732,22 @@ typedef struct SetOperationStmt
|
||||
* field in Query.
|
||||
*****************************************************************************/
|
||||
|
||||
/* ----------------------
|
||||
* Create Schema Statement
|
||||
*
|
||||
* NOTE: the schemaElts list contains raw parsetrees for component statements
|
||||
* of the schema, such as CREATE TABLE, GRANT, etc. These are analyzed and
|
||||
* executed after the schema itself is created.
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct CreateSchemaStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *schemaname; /* the name of the schema to create */
|
||||
char *authid; /* the owner of the created schema */
|
||||
List *schemaElts; /* schema components (list of parsenodes) */
|
||||
} CreateSchemaStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Alter Table
|
||||
*
|
||||
@ -725,8 +770,7 @@ typedef struct AlterTableStmt
|
||||
* U = change owner
|
||||
*------------
|
||||
*/
|
||||
char *relname; /* table to work on */
|
||||
InhOption inhOpt; /* recursively act on children? */
|
||||
RangeVar *relation; /* table to work on */
|
||||
char *name; /* column or constraint name to act on, or
|
||||
* new owner */
|
||||
Node *def; /* definition of new column or constraint */
|
||||
@ -743,12 +787,12 @@ typedef struct GrantStmt
|
||||
NodeTag type;
|
||||
bool is_grant; /* not revoke */
|
||||
int objtype;
|
||||
List *objects; /* list of names (as Value strings) */
|
||||
List *objects; /* list of names (as Value strings)
|
||||
* or relations (as RangeVar's) */
|
||||
List *privileges; /* integer list of privilege codes */
|
||||
List *grantees; /* list of PrivGrantee nodes */
|
||||
} GrantStmt;
|
||||
|
||||
|
||||
typedef struct PrivGrantee
|
||||
{
|
||||
NodeTag type;
|
||||
@ -756,7 +800,6 @@ typedef struct PrivGrantee
|
||||
char *groupname;
|
||||
} PrivGrantee;
|
||||
|
||||
|
||||
typedef struct FuncWithArgs
|
||||
{
|
||||
NodeTag type;
|
||||
@ -764,7 +807,6 @@ typedef struct FuncWithArgs
|
||||
List *funcargs; /* list of Typename nodes */
|
||||
} FuncWithArgs;
|
||||
|
||||
|
||||
/* This is only used internally in gram.y. */
|
||||
typedef struct PrivTarget
|
||||
{
|
||||
@ -773,7 +815,6 @@ typedef struct PrivTarget
|
||||
List *objs;
|
||||
} PrivTarget;
|
||||
|
||||
|
||||
/* ----------------------
|
||||
* Close Portal Statement
|
||||
* ----------------------
|
||||
@ -792,7 +833,7 @@ typedef struct CopyStmt
|
||||
{
|
||||
NodeTag type;
|
||||
bool binary; /* is a binary copy? */
|
||||
char *relname; /* the relation to copy */
|
||||
RangeVar *relation; /* the relation to copy */
|
||||
bool oids; /* copy oid's? */
|
||||
int direction; /* TO or FROM */
|
||||
char *filename; /* if NULL, use stdin/stdout */
|
||||
@ -813,12 +854,10 @@ typedef struct CopyStmt
|
||||
typedef struct CreateStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *relname; /* name of relation to create */
|
||||
RangeVar *relation; /* relation to create */
|
||||
List *tableElts; /* column definitions (list of ColumnDef) */
|
||||
List *inhRelnames; /* relations to inherit from (list of
|
||||
* T_String Values) */
|
||||
List *inhRelations; /* relations to inherit from */
|
||||
List *constraints; /* constraints (list of Constraint nodes) */
|
||||
bool istemp; /* is this a temp table? */
|
||||
bool hasoids; /* should it have OIDs? */
|
||||
} CreateStmt;
|
||||
|
||||
@ -886,7 +925,7 @@ typedef struct FkConstraint
|
||||
{
|
||||
NodeTag type;
|
||||
char *constr_name; /* Constraint name */
|
||||
char *pktable_name; /* Primary key table name */
|
||||
RangeVar *pktable; /* Primary key table */
|
||||
List *fk_attrs; /* Attributes of foreign key */
|
||||
List *pk_attrs; /* Corresponding attrs in PK table */
|
||||
char *match_type; /* FULL or PARTIAL */
|
||||
@ -904,7 +943,7 @@ typedef struct CreateTrigStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *trigname; /* TRIGGER' name */
|
||||
char *relname; /* triggered relation */
|
||||
RangeVar *relation; /* triggered relation */
|
||||
char *funcname; /* function to call (or NULL) */
|
||||
List *args; /* list of (T_String) Values or NULL */
|
||||
bool before; /* BEFORE/AFTER */
|
||||
@ -920,14 +959,14 @@ typedef struct CreateTrigStmt
|
||||
bool isconstraint; /* This is an RI trigger */
|
||||
bool deferrable; /* [NOT] DEFERRABLE */
|
||||
bool initdeferred; /* INITIALLY {DEFERRED|IMMEDIATE} */
|
||||
char *constrrelname; /* opposite relation */
|
||||
RangeVar *constrrel; /* opposite relation */
|
||||
} CreateTrigStmt;
|
||||
|
||||
typedef struct DropTrigStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *trigname; /* TRIGGER' name */
|
||||
char *relname; /* triggered relation */
|
||||
RangeVar *relation; /* triggered relation */
|
||||
} DropTrigStmt;
|
||||
|
||||
/* ----------------------
|
||||
@ -1014,8 +1053,7 @@ typedef struct DropGroupStmt
|
||||
typedef struct CreateSeqStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *seqname; /* the relation to create */
|
||||
bool istemp; /* is this a temp sequence? */
|
||||
RangeVar *sequence; /* the sequence to create */
|
||||
List *options;
|
||||
} CreateSeqStmt;
|
||||
|
||||
@ -1072,7 +1110,7 @@ typedef struct CreateDomainStmt
|
||||
typedef struct DropStmt
|
||||
{
|
||||
NodeTag type;
|
||||
List *names;
|
||||
List *objects;
|
||||
int removeType;
|
||||
int behavior; /* CASCADE or RESTRICT drop behavior */
|
||||
} DropStmt;
|
||||
@ -1084,7 +1122,7 @@ typedef struct DropStmt
|
||||
typedef struct TruncateStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *relName; /* relation to be truncated */
|
||||
RangeVar *relation; /* relation to be truncated */
|
||||
} TruncateStmt;
|
||||
|
||||
/* ----------------------
|
||||
@ -1095,6 +1133,8 @@ typedef struct CommentStmt
|
||||
{
|
||||
NodeTag type;
|
||||
int objtype; /* Object's type */
|
||||
char *objschema; /* Schema where object is defined,
|
||||
* if object is schema specific */
|
||||
char *objname; /* Name of the object */
|
||||
char *objproperty; /* Property Id (such as column) */
|
||||
List *objlist; /* Arguments for VAL objects */
|
||||
@ -1132,7 +1172,7 @@ typedef struct IndexStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *idxname; /* name of the index */
|
||||
char *relname; /* name of relation to index on */
|
||||
RangeVar *relation; /* relation to build index on */
|
||||
char *accessMethod; /* name of access method (eg. btree) */
|
||||
List *indexParams; /* a list of IndexElem */
|
||||
Node *whereClause; /* qualification (partial-index predicate) */
|
||||
@ -1192,14 +1232,13 @@ typedef struct RemoveOperStmt
|
||||
} RemoveOperStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Alter Table Statement
|
||||
* Alter Table Rename Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct RenameStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *relname; /* relation to be altered */
|
||||
InhOption inhOpt; /* recursively act on children? */
|
||||
RangeVar *relation; /* relation to be altered */
|
||||
char *column; /* if NULL, rename the relation name to
|
||||
* the new name. Otherwise, rename this
|
||||
* column name. */
|
||||
@ -1213,10 +1252,10 @@ typedef struct RenameStmt
|
||||
typedef struct RuleStmt
|
||||
{
|
||||
NodeTag type;
|
||||
RangeVar *relation; /* relation the rule is for */
|
||||
char *rulename; /* name of the rule */
|
||||
Node *whereClause; /* qualifications */
|
||||
CmdType event; /* RETRIEVE */
|
||||
struct Attr *object; /* object affected */
|
||||
CmdType event; /* SELECT, INSERT, etc */
|
||||
bool instead; /* is a 'do instead'? */
|
||||
List *actions; /* the action statements */
|
||||
} RuleStmt;
|
||||
@ -1228,7 +1267,7 @@ typedef struct RuleStmt
|
||||
typedef struct NotifyStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *relname; /* relation to notify */
|
||||
RangeVar *relation; /* qualified name to notify */
|
||||
} NotifyStmt;
|
||||
|
||||
/* ----------------------
|
||||
@ -1238,7 +1277,7 @@ typedef struct NotifyStmt
|
||||
typedef struct ListenStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *relname; /* relation to listen on */
|
||||
RangeVar *relation; /* qualified name to listen on */
|
||||
} ListenStmt;
|
||||
|
||||
/* ----------------------
|
||||
@ -1248,7 +1287,7 @@ typedef struct ListenStmt
|
||||
typedef struct UnlistenStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *relname; /* relation to unlisten on */
|
||||
RangeVar *relation; /* qualified name to unlisten on, or '*' */
|
||||
} UnlistenStmt;
|
||||
|
||||
/* ----------------------
|
||||
@ -1268,7 +1307,7 @@ typedef struct TransactionStmt
|
||||
typedef struct ViewStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *viewname; /* name of the view */
|
||||
RangeVar *view; /* the view to be created */
|
||||
List *aliases; /* target column names */
|
||||
Query *query; /* the SQL statement */
|
||||
} ViewStmt;
|
||||
@ -1283,7 +1322,6 @@ typedef struct LoadStmt
|
||||
char *filename; /* file to load */
|
||||
} LoadStmt;
|
||||
|
||||
|
||||
/* ----------------------
|
||||
* Createdb Statement
|
||||
* ----------------------
|
||||
@ -1327,7 +1365,7 @@ typedef struct DropdbStmt
|
||||
typedef struct ClusterStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *relname; /* relation being indexed */
|
||||
RangeVar *relation; /* relation being indexed */
|
||||
char *indexname; /* original index defined */
|
||||
} ClusterStmt;
|
||||
|
||||
@ -1346,8 +1384,7 @@ typedef struct VacuumStmt
|
||||
bool analyze; /* do ANALYZE step */
|
||||
bool freeze; /* early-freeze option */
|
||||
bool verbose; /* print progress info */
|
||||
char *vacrel; /* name of single table to process, or
|
||||
* NULL */
|
||||
RangeVar *relation; /* single table to process, or NULL */
|
||||
List *va_cols; /* list of column names, or NIL for all */
|
||||
} VacuumStmt;
|
||||
|
||||
@ -1413,7 +1450,7 @@ typedef struct VariableResetStmt
|
||||
typedef struct LockStmt
|
||||
{
|
||||
NodeTag type;
|
||||
List *rellist; /* relations to lock */
|
||||
List *relations; /* relations to lock */
|
||||
int mode; /* lock mode */
|
||||
} LockStmt;
|
||||
|
||||
@ -1436,7 +1473,8 @@ typedef struct ReindexStmt
|
||||
{
|
||||
NodeTag type;
|
||||
int reindexType; /* INDEX|TABLE|DATABASE */
|
||||
const char *name; /* name to reindex */
|
||||
RangeVar *relation; /* Table or index to reindex */
|
||||
const char *name; /* name of database to reindex */
|
||||
bool force;
|
||||
bool all;
|
||||
} ReindexStmt;
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: primnodes.h,v 1.58 2002/03/12 00:52:02 tgl Exp $
|
||||
* $Id: primnodes.h,v 1.59 2002/03/21 16:01:48 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -508,7 +508,7 @@ typedef struct RangeTblRef
|
||||
* If he writes ON() then only "quals" is set. Note that NATURAL/USING
|
||||
* are not equivalent to ON() since they also affect the output column list.
|
||||
*
|
||||
* alias is an Attr node representing the AS alias-clause attached to the
|
||||
* alias is an Alias node representing the AS alias-clause attached to the
|
||||
* join expression, or NULL if no clause. NB: presence or absence of the
|
||||
* alias has a critical impact on semantics, because a join with an alias
|
||||
* restricts visibility of the tables/columns inside it.
|
||||
@ -527,7 +527,7 @@ typedef struct JoinExpr
|
||||
Node *rarg; /* right subtree */
|
||||
List *using; /* USING clause, if any (list of String) */
|
||||
Node *quals; /* qualifiers on join, if any */
|
||||
struct Attr *alias; /* user-written alias clause, if any */
|
||||
struct Alias *alias; /* user-written alias clause, if any */
|
||||
int rtindex; /* RT index assigned for join */
|
||||
} JoinExpr;
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: analyze.h,v 1.18 2001/11/05 17:46:34 momjian Exp $
|
||||
* $Id: analyze.h,v 1.19 2002/03/21 16:01:53 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -16,6 +16,7 @@
|
||||
#include "parser/parse_node.h"
|
||||
|
||||
extern List *parse_analyze(Node *parseTree, ParseState *parentParseState);
|
||||
extern List *analyzeCreateSchemaStmt(CreateSchemaStmt *stmt);
|
||||
|
||||
extern void CheckSelectForUpdate(Query *qry);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parse_agg.h,v 1.20 2001/11/05 17:46:34 momjian Exp $
|
||||
* $Id: parse_agg.h,v 1.21 2002/03/21 16:01:55 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -19,8 +19,7 @@
|
||||
extern void AddAggToParseState(ParseState *pstate, Aggref *aggref);
|
||||
extern void parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual);
|
||||
extern Aggref *ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
|
||||
List *args, bool agg_star, bool agg_distinct,
|
||||
int precedence);
|
||||
List *args, bool agg_star, bool agg_distinct);
|
||||
extern void agg_error(char *caller, char *aggname, Oid basetypeID);
|
||||
|
||||
#endif /* PARSE_AGG_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parse_expr.h,v 1.25 2001/11/05 17:46:34 momjian Exp $
|
||||
* $Id: parse_expr.h,v 1.26 2002/03/21 16:01:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -16,13 +16,12 @@
|
||||
|
||||
#include "parser/parse_node.h"
|
||||
|
||||
#define EXPR_COLUMN_FIRST 1
|
||||
#define EXPR_RELATION_FIRST 2
|
||||
|
||||
/* GUC parameters */
|
||||
extern int max_expr_depth;
|
||||
extern bool Transform_null_equals;
|
||||
|
||||
extern Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
|
||||
extern Node *transformExpr(ParseState *pstate, Node *expr);
|
||||
extern Oid exprType(Node *expr);
|
||||
extern int32 exprTypmod(Node *expr);
|
||||
extern bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parse_func.h,v 1.35 2001/11/05 17:46:35 momjian Exp $
|
||||
* $Id: parse_func.h,v 1.36 2002/03/21 16:02:01 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -47,12 +47,9 @@ typedef enum
|
||||
} FuncDetailCode;
|
||||
|
||||
|
||||
extern Node *ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr,
|
||||
int precedence);
|
||||
extern Node *ParseFuncOrColumn(ParseState *pstate,
|
||||
char *funcname, List *fargs,
|
||||
bool agg_star, bool agg_distinct,
|
||||
int precedence);
|
||||
bool agg_star, bool agg_distinct, bool is_column);
|
||||
|
||||
extern FuncDetailCode func_get_detail(char *funcname, List *fargs,
|
||||
int nargs, Oid *argtypes,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parse_relation.h,v 1.29 2002/03/12 00:52:04 tgl Exp $
|
||||
* $Id: parse_relation.h,v 1.30 2002/03/21 16:02:05 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -29,12 +29,12 @@ extern Node *qualifiedNameToVar(ParseState *pstate, char *refname,
|
||||
char *colname, bool implicitRTEOK);
|
||||
extern RangeTblEntry *addRangeTableEntry(ParseState *pstate,
|
||||
char *relname,
|
||||
Attr *alias,
|
||||
Alias *alias,
|
||||
bool inh,
|
||||
bool inFromCl);
|
||||
extern RangeTblEntry *addRangeTableEntryForSubquery(ParseState *pstate,
|
||||
Query *subquery,
|
||||
Attr *alias,
|
||||
Alias *alias,
|
||||
bool inFromCl);
|
||||
extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate,
|
||||
List *colnames,
|
||||
@ -43,7 +43,7 @@ extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate,
|
||||
List *coltypmods,
|
||||
List *leftcols,
|
||||
List *rightcols,
|
||||
Attr *alias,
|
||||
Alias *alias,
|
||||
bool inFromCl);
|
||||
extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
|
||||
bool addToJoinList, bool addToNameSpace);
|
||||
|
@ -396,7 +396,7 @@ drop table atacc1;
|
||||
create table atacc1 ( test int );
|
||||
-- add a check constraint (fails)
|
||||
alter table atacc1 add constraint atacc_test1 check (test1>3);
|
||||
ERROR: Attribute 'test1' not found
|
||||
ERROR: Attribute "test1" not found
|
||||
drop table atacc1;
|
||||
-- something a little more complicated
|
||||
create table atacc1 ( test int, test2 int, test3 int);
|
||||
|
@ -22,19 +22,19 @@ select * from nonesuch;
|
||||
ERROR: parser: parse error at or near "select"
|
||||
-- bad name in target list
|
||||
select nonesuch from pg_database;
|
||||
ERROR: Attribute 'nonesuch' not found
|
||||
ERROR: Attribute "nonesuch" not found
|
||||
-- bad attribute name on lhs of operator
|
||||
select * from pg_database where nonesuch = pg_database.datname;
|
||||
ERROR: Attribute 'nonesuch' not found
|
||||
ERROR: Attribute "nonesuch" not found
|
||||
-- bad attribute name on rhs of operator
|
||||
select * from pg_database where pg_database.datname = nonesuch;
|
||||
ERROR: Attribute 'nonesuch' not found
|
||||
ERROR: Attribute "nonesuch" not found
|
||||
-- bad select distinct on syntax, distinct attribute missing
|
||||
select distinct on (foobar) from pg_database;
|
||||
ERROR: parser: parse error at or near "from"
|
||||
-- bad select distinct on syntax, distinct attribute not in target list
|
||||
select distinct on (foobar) * from pg_database;
|
||||
ERROR: Attribute 'foobar' not found
|
||||
ERROR: Attribute "foobar" not found
|
||||
--
|
||||
-- DELETE
|
||||
|
||||
|
@ -1177,7 +1177,7 @@ drop rule foorule;
|
||||
-- this should fail because f1 is not exposed for unqualified reference:
|
||||
create rule foorule as on insert to foo where f1 < 100
|
||||
do instead insert into foo2 values (f1);
|
||||
ERROR: Attribute 'f1' not found
|
||||
ERROR: Attribute "f1" not found
|
||||
-- this is the correct way:
|
||||
create rule foorule as on insert to foo where f1 < 100
|
||||
do instead insert into foo2 values (new.f1);
|
||||
|
@ -406,7 +406,7 @@ ORDER BY q2,q1;
|
||||
|
||||
-- This should fail, because q2 isn't a name of an EXCEPT output column
|
||||
SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1;
|
||||
ERROR: Attribute 'q2' not found
|
||||
ERROR: Attribute "q2" not found
|
||||
-- But this should work:
|
||||
SELECT q1 FROM int8_tbl EXCEPT (((SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1)));
|
||||
q1
|
||||
|
@ -170,44 +170,44 @@ SELECT class, aa, a FROM a_star*;
|
||||
-- joe and sally play basketball, and
|
||||
-- everyone else does nothing.
|
||||
--
|
||||
SELECT p.name, p.hobbies.name FROM ONLY person p;
|
||||
SELECT p.name, name(p.hobbies) FROM ONLY person p;
|
||||
|
||||
--
|
||||
-- as above, but jeff also does post_hacking.
|
||||
--
|
||||
SELECT p.name, p.hobbies.name FROM person* p;
|
||||
SELECT p.name, name(p.hobbies) FROM person* p;
|
||||
|
||||
--
|
||||
-- the next two queries demonstrate how functions generate bogus duplicates.
|
||||
-- this is a "feature" ..
|
||||
--
|
||||
SELECT DISTINCT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r;
|
||||
SELECT DISTINCT hobbies_r.name, name(hobbies_r.equipment) FROM hobbies_r;
|
||||
|
||||
SELECT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r;
|
||||
SELECT hobbies_r.name, (hobbies_r.equipment).name FROM hobbies_r;
|
||||
|
||||
--
|
||||
-- mike needs advil and peet's coffee,
|
||||
-- joe and sally need hightops, and
|
||||
-- everyone else is fine.
|
||||
--
|
||||
SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM ONLY person p;
|
||||
SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM ONLY person p;
|
||||
|
||||
--
|
||||
-- as above, but jeff needs advil and peet's coffee as well.
|
||||
--
|
||||
SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM person* p;
|
||||
SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM person* p;
|
||||
|
||||
--
|
||||
-- just like the last two, but make sure that the target list fixup and
|
||||
-- unflattening is being done correctly.
|
||||
--
|
||||
SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM ONLY person p;
|
||||
SELECT name(equipment(p.hobbies)), p.name, name(p.hobbies) FROM ONLY person p;
|
||||
|
||||
SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM person* p;
|
||||
SELECT (p.hobbies).equipment.name, p.name, name(p.hobbies) FROM person* p;
|
||||
|
||||
SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM ONLY person p;
|
||||
SELECT (p.hobbies).equipment.name, name(p.hobbies), p.name FROM ONLY person p;
|
||||
|
||||
SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM person* p;
|
||||
SELECT name(equipment(p.hobbies)), name(p.hobbies), p.name FROM person* p;
|
||||
|
||||
SELECT user_relns() AS user_relns
|
||||
ORDER BY user_relns;
|
||||
|
@ -442,7 +442,7 @@ SELECT class, aa, a FROM a_star*;
|
||||
-- joe and sally play basketball, and
|
||||
-- everyone else does nothing.
|
||||
--
|
||||
SELECT p.name, p.hobbies.name FROM ONLY person p;
|
||||
SELECT p.name, name(p.hobbies) FROM ONLY person p;
|
||||
name | name
|
||||
-------+-------------
|
||||
mike | posthacking
|
||||
@ -453,7 +453,7 @@ SELECT p.name, p.hobbies.name FROM ONLY person p;
|
||||
--
|
||||
-- as above, but jeff also does post_hacking.
|
||||
--
|
||||
SELECT p.name, p.hobbies.name FROM person* p;
|
||||
SELECT p.name, name(p.hobbies) FROM person* p;
|
||||
name | name
|
||||
-------+-------------
|
||||
mike | posthacking
|
||||
@ -466,7 +466,7 @@ SELECT p.name, p.hobbies.name FROM person* p;
|
||||
-- the next two queries demonstrate how functions generate bogus duplicates.
|
||||
-- this is a "feature" ..
|
||||
--
|
||||
SELECT DISTINCT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r;
|
||||
SELECT DISTINCT hobbies_r.name, name(hobbies_r.equipment) FROM hobbies_r;
|
||||
name | name
|
||||
-------------+---------------
|
||||
basketball | hightops
|
||||
@ -475,7 +475,7 @@ SELECT DISTINCT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r;
|
||||
skywalking | guts
|
||||
(4 rows)
|
||||
|
||||
SELECT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r;
|
||||
SELECT hobbies_r.name, (hobbies_r.equipment).name FROM hobbies_r;
|
||||
name | name
|
||||
-------------+---------------
|
||||
posthacking | advil
|
||||
@ -492,7 +492,7 @@ SELECT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r;
|
||||
-- joe and sally need hightops, and
|
||||
-- everyone else is fine.
|
||||
--
|
||||
SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM ONLY person p;
|
||||
SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM ONLY person p;
|
||||
name | name | name
|
||||
-------+-------------+---------------
|
||||
mike | posthacking | advil
|
||||
@ -504,7 +504,7 @@ SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM ONLY person p;
|
||||
--
|
||||
-- as above, but jeff needs advil and peet's coffee as well.
|
||||
--
|
||||
SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM person* p;
|
||||
SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM person* p;
|
||||
name | name | name
|
||||
-------+-------------+---------------
|
||||
mike | posthacking | advil
|
||||
@ -519,7 +519,7 @@ SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM person* p;
|
||||
-- just like the last two, but make sure that the target list fixup and
|
||||
-- unflattening is being done correctly.
|
||||
--
|
||||
SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM ONLY person p;
|
||||
SELECT name(equipment(p.hobbies)), p.name, name(p.hobbies) FROM ONLY person p;
|
||||
name | name | name
|
||||
---------------+-------+-------------
|
||||
advil | mike | posthacking
|
||||
@ -528,7 +528,7 @@ SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM ONLY person p;
|
||||
hightops | sally | basketball
|
||||
(4 rows)
|
||||
|
||||
SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM person* p;
|
||||
SELECT (p.hobbies).equipment.name, p.name, name(p.hobbies) FROM person* p;
|
||||
name | name | name
|
||||
---------------+-------+-------------
|
||||
advil | mike | posthacking
|
||||
@ -539,7 +539,7 @@ SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM person* p;
|
||||
peet's coffee | jeff | posthacking
|
||||
(6 rows)
|
||||
|
||||
SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM ONLY person p;
|
||||
SELECT (p.hobbies).equipment.name, name(p.hobbies), p.name FROM ONLY person p;
|
||||
name | name | name
|
||||
---------------+-------------+-------
|
||||
advil | posthacking | mike
|
||||
@ -548,7 +548,7 @@ SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM ONLY person p;
|
||||
hightops | basketball | sally
|
||||
(4 rows)
|
||||
|
||||
SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM person* p;
|
||||
SELECT name(equipment(p.hobbies)), name(p.hobbies), p.name FROM person* p;
|
||||
name | name | name
|
||||
---------------+-------------+-------
|
||||
advil | posthacking | mike
|
||||
|
Loading…
Reference in New Issue
Block a user