From: Tom Lane Date: Fri, 8 Mar 2002 04:37:18 +0000 (+0000) Subject: Fix copying/equality-check bugs in GrantStmt and ConstraintsSetStmt, X-Git-Tag: REL7_3~1924 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cf68a686a6368ebd6e9e37ded4481bf1bd4a8b8e;p=postgresql Fix copying/equality-check bugs in GrantStmt and ConstraintsSetStmt, per reports from Fernando Nasser. Also, rearrange order of declarations in parsenodes.h as suggested by Fernando. --- diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 61a4eacbac..e25b83b455 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -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.104 2002/03/06 06:09:36 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.105 2002/03/08 04:37:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1781,6 +1781,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt) foreach(l, stmt->constraints) { + char *cname = strVal(lfirst(l)); ScanKeyData skey; SysScanDesc tgscan; HeapTuple htup; @@ -1788,7 +1789,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt) /* * Check that only named constraints are set explicitly */ - if (strcmp((char *) lfirst(l), "") == 0) + if (strlen(cname) == 0) elog(ERROR, "unnamed constraints cannot be set explicitly"); /* @@ -1798,7 +1799,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt) (bits16) 0x0, (AttrNumber) Anum_pg_trigger_tgconstrname, (RegProcedure) F_NAMEEQ, - PointerGetDatum((char *) lfirst(l))); + PointerGetDatum(cname)); tgscan = systable_beginscan(tgrel, TriggerConstrNameIndex, true, SnapshotNow, 1, &skey); @@ -1822,7 +1823,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt) pg_trigger->tgfoid != F_RI_FKEY_RESTRICT_UPD && pg_trigger->tgfoid != F_RI_FKEY_RESTRICT_DEL) elog(ERROR, "Constraint '%s' is not deferrable", - (char *) lfirst(l)); + cname); constr_oid = htup->t_data->t_oid; loid = lappendi(loid, constr_oid); @@ -1835,7 +1836,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt) * Not found ? */ if (!found) - elog(ERROR, "Constraint '%s' does not exist", (char *) lfirst(l)); + elog(ERROR, "Constraint '%s' does not exist", cname); } heap_close(tgrel, AccessShareLock); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 234fd95ba2..ae9ac43045 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -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.167 2002/03/07 16:35:34 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.168 2002/03/08 04:37:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1898,7 +1898,7 @@ _copyGrantStmt(GrantStmt *from) newnode->is_grant = from->is_grant; newnode->objtype = from->objtype; Node_Copy(from, newnode, objects); - Node_Copy(from, newnode, privileges); + newnode->privileges = listCopy(from->privileges); Node_Copy(from, newnode, grantees); return newnode; @@ -1924,8 +1924,6 @@ _copyFuncWithArgs(FuncWithArgs *from) if (from->funcname) newnode->funcname = pstrdup(from->funcname); - else - newnode->funcname = NULL; Node_Copy(from, newnode, funcargs); return newnode; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 03ce9510ad..b9269c5a83 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -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.115 2002/03/07 16:35:34 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.116 2002/03/08 04:37:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -763,7 +763,7 @@ _equalGrantStmt(GrantStmt *a, GrantStmt *b) return false; if (!equal(a->objects, b->objects)) return false; - if (!equal(a->privileges, b->privileges)) + if (!equali(a->privileges, b->privileges)) return false; if (!equal(a->grantees, b->grantees)) return false; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 2b1edd266e..c166a74459 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.287 2002/03/07 16:35:35 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.288 2002/03/08 04:37:17 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -286,7 +286,6 @@ static void doNegateFloat(Value *v); ConstraintTimeSpec %type constraints_set_list -%type constraints_set_namelist %type constraints_set_mode /* @@ -1034,37 +1033,12 @@ ConstraintsSetStmt: SET CONSTRAINTS constraints_set_list constraints_set_mode } ; - -constraints_set_list: ALL - { - $$ = NIL; - } - | constraints_set_namelist - { - $$ = $1; - } +constraints_set_list: ALL { $$ = NIL; } + | name_list { $$ = $1; } ; - -constraints_set_namelist: ColId - { - $$ = makeList1($1); - } - | constraints_set_namelist ',' ColId - { - $$ = lappend($1, $3); - } - ; - - -constraints_set_mode: DEFERRED - { - $$ = TRUE; - } - | IMMEDIATE - { - $$ = FALSE; - } +constraints_set_mode: DEFERRED { $$ = TRUE; } + | IMMEDIATE { $$ = FALSE; } ; diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index c154913c2b..996c2b9c73 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.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: parsenodes.h,v 1.158 2002/03/07 16:35:40 momjian Exp $ + * $Id: parsenodes.h,v 1.159 2002/03/08 04:37:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,15 @@ #include "nodes/primnodes.h" + +typedef enum InhOption +{ + INH_NO, /* Do NOT scan child tables */ + INH_YES, /* DO scan child tables */ + INH_DEFAULT /* Use current SQL_inheritance option */ +} InhOption; + + /***************************************************************************** * Query Tree *****************************************************************************/ @@ -93,1308 +102,1294 @@ typedef struct Query } Query; -typedef enum InhOption -{ - INH_NO, /* Do NOT scan child tables */ - INH_YES, /* DO scan child tables */ - INH_DEFAULT /* Use current SQL_inheritance option */ -} InhOption; - -/***************************************************************************** - * Other Statements (no optimizations required) +/**************************************************************************** + * Supporting data structures for Parse Trees * - * Some of them require a little bit of transformation (which is also - * done by transformStmt). The whole structure is then passed on to - * ProcessUtility (by-passing the optimization step) as the utilityStmt - * field in Query. - *****************************************************************************/ + * Most of these node types appear in raw parsetrees output by the grammar, + * and get transformed to something else by the analyzer. A few of them + * are used as-is in transformed querytrees. + ****************************************************************************/ -/* ---------------------- - * Alter Table - * - * The fields are used in different ways by the different variants of - * this command. - * ---------------------- +/* + * TypeName - specifies a type in definitions */ -typedef struct AlterTableStmt +typedef struct TypeName { NodeTag type; - char subtype; /*------------ - * A = add column - * T = alter column default - * S = alter column statistics - * M = alter column storage - * D = drop column - * C = add constraint - * X = drop constraint - * E = create toast table - * U = change owner - *------------ - */ - char *relname; /* table to work on */ - InhOption inhOpt; /* recursively act on children? */ - char *name; /* column or constraint name to act on, or - * new owner */ - Node *def; /* definition of new column or constraint */ - int behavior; /* CASCADE or RESTRICT drop behavior */ -} AlterTableStmt; + char *name; /* name of the type */ + bool timezone; /* timezone specified? */ + bool setof; /* is a set? */ + int32 typmod; /* type modifier */ + List *arrayBounds; /* array bounds */ + char *attrname; /* field name when using %TYPE */ +} TypeName; -/* ---------------------- - * Grant Statement - * ---------------------- +/* + * ParamNo - specifies a parameter reference */ - -typedef struct GrantStmt +typedef struct ParamNo { NodeTag type; - bool is_grant; /* not revoke */ - int objtype; - List *objects; - List *privileges; - List *grantees; -} GrantStmt; - + int number; /* the number of the parameter */ + TypeName *typename; /* the typecast */ + List *indirection; /* array references */ +} ParamNo; -typedef struct PrivGrantee +/* + * A_Expr - binary expressions + */ +typedef struct A_Expr { NodeTag type; - char *username; /* if both are NULL then PUBLIC */ - char *groupname; -} PrivGrantee; - + int oper; /* type of operation (OP,OR,AND,NOT) */ + char *opname; /* name of operator */ + Node *lexpr; /* left argument */ + Node *rexpr; /* right argument */ +} A_Expr; -typedef struct FuncWithArgs +/* + * Attr - + * specifies an Attribute (ie. a Column); could have nested dots or + * array references. + * + */ +typedef struct Attr { NodeTag type; - char *funcname; - List *funcargs; -} FuncWithArgs; - + 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; -/* This is only used internally in gram.y. */ -typedef struct PrivTarget +/* + * A_Const - a constant expression + */ +typedef struct A_Const { NodeTag type; - int objtype; - List *objs; -} PrivTarget; - + Value val; /* the value (with the tag) */ + TypeName *typename; /* typecast */ +} A_Const; -/* ---------------------- - * Close Portal Statement - * ---------------------- +/* + * TypeCast - a CAST expression + * + * NOTE: for mostly historical reasons, A_Const and ParamNo 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. */ -typedef struct ClosePortalStmt +typedef struct TypeCast { NodeTag type; - char *portalname; /* name of the portal (cursor) */ -} ClosePortalStmt; + Node *arg; /* the expression being casted */ + TypeName *typename; /* the target type */ +} TypeCast; -/* ---------------------- - * Copy Statement - * ---------------------- +/* + * CaseExpr - a CASE expression */ -typedef struct CopyStmt +typedef struct CaseExpr { NodeTag type; - bool binary; /* is a binary copy? */ - char *relname; /* the relation to copy */ - bool oids; /* copy oid's? */ - int direction; /* TO or FROM */ - char *filename; /* if NULL, use stdin/stdout */ - char *delimiter; /* delimiter character, \t by default */ - char *null_print; /* how to print NULLs, `\N' by default */ -} CopyStmt; + Oid casetype; + Node *arg; /* implicit equality comparison argument */ + List *args; /* the arguments (list of WHEN clauses) */ + Node *defresult; /* the default result (ELSE clause) */ +} CaseExpr; -/* ---------------------- - * Create Table Statement - * - * NOTE: in the raw gram.y output, ColumnDef, Constraint, and FkConstraint - * nodes are intermixed in tableElts, and constraints is NIL. After parse - * analysis, tableElts contains just ColumnDefs, and constraints contains - * just Constraint nodes (in fact, only CONSTR_CHECK nodes, in the present - * implementation). - * ---------------------- +/* + * CaseWhen - an argument to a CASE expression */ -typedef struct CreateStmt +typedef struct CaseWhen { NodeTag type; - char *relname; /* name of relation to create */ - List *tableElts; /* column definitions (list of ColumnDef) */ - List *inhRelnames; /* relations to inherit from (list of - * T_String Values) */ - List *constraints; /* constraints (list of Constraint nodes) */ - bool istemp; /* is this a temp table? */ - bool hasoids; /* should it have OIDs? */ -} CreateStmt; + Node *expr; /* comparison expression */ + Node *result; /* substitution result */ +} CaseWhen; -/* ---------- - * Definitions for plain (non-FOREIGN KEY) constraints in CreateStmt - * - * XXX probably these ought to be unified with FkConstraints at some point? - * - * For constraints that use expressions (CONSTR_DEFAULT, CONSTR_CHECK) - * we may have the expression in either "raw" form (an untransformed - * parse tree) or "cooked" form (the nodeToString representation of - * an executable expression tree), depending on how this Constraint - * node was created (by parsing, or by inheritance from an existing - * relation). We should never have both in the same node! +/* ---------------- + * NullTest * - * Constraint attributes (DEFERRABLE etc) are initially represented as - * separate Constraint nodes for simplicity of parsing. analyze.c makes - * a pass through the constraints list to attach the info to the appropriate - * FkConstraint node (and, perhaps, someday to other kinds of constraints). - * ---------- + * NullTest represents the operation of testing a value for NULLness. + * Currently, we only support scalar input values, but eventually a + * row-constructor input should be supported. + * The appropriate test is performed and returned as a boolean Datum. + * ---------------- */ -typedef enum ConstrType /* types of constraints */ +typedef enum NullTestType { - CONSTR_NULL, /* not SQL92, but a lot of people expect - * it */ - CONSTR_NOTNULL, - CONSTR_DEFAULT, - CONSTR_CHECK, - CONSTR_PRIMARY, - CONSTR_UNIQUE, - CONSTR_ATTR_DEFERRABLE, /* attributes for previous constraint node */ - CONSTR_ATTR_NOT_DEFERRABLE, - CONSTR_ATTR_DEFERRED, - CONSTR_ATTR_IMMEDIATE -} ConstrType; + IS_NULL, IS_NOT_NULL +} NullTestType; -typedef struct Constraint +typedef struct NullTest { NodeTag type; - ConstrType contype; - char *name; /* name, or NULL if unnamed */ - Node *raw_expr; /* expr, as untransformed parse tree */ - char *cooked_expr; /* expr, as nodeToString representation */ - List *keys; /* Ident nodes naming referenced column(s) */ -} Constraint; - + Node *arg; /* input expression */ + NullTestType nulltesttype; /* IS NULL, IS NOT NULL */ +} NullTest; -/* ---------- - * Definitions for FOREIGN KEY constraints in CreateStmt - * ---------- +/* ---------------- + * BooleanTest + * + * BooleanTest represents the operation of determining whether a boolean + * is TRUE, FALSE, or UNKNOWN (ie, NULL). All six meaningful combinations + * are supported. Note that a NULL input does *not* cause a NULL result. + * The appropriate test is performed and returned as a boolean Datum. + * ---------------- */ -#define FKCONSTR_ON_KEY_NOACTION 0x0000 -#define FKCONSTR_ON_KEY_RESTRICT 0x0001 -#define FKCONSTR_ON_KEY_CASCADE 0x0002 -#define FKCONSTR_ON_KEY_SETNULL 0x0004 -#define FKCONSTR_ON_KEY_SETDEFAULT 0x0008 -#define FKCONSTR_ON_DELETE_MASK 0x000F -#define FKCONSTR_ON_DELETE_SHIFT 0 - -#define FKCONSTR_ON_UPDATE_MASK 0x00F0 -#define FKCONSTR_ON_UPDATE_SHIFT 4 - -typedef struct FkConstraint +typedef enum BoolTestType { - NodeTag type; - char *constr_name; /* Constraint name */ - char *pktable_name; /* Primary key table name */ - List *fk_attrs; /* Attributes of foreign key */ - List *pk_attrs; /* Corresponding attrs in PK table */ - char *match_type; /* FULL or PARTIAL */ - int32 actions; /* ON DELETE/UPDATE actions */ - bool deferrable; /* DEFERRABLE */ - bool initdeferred; /* INITIALLY DEFERRED */ -} FkConstraint; - - -/* ---------------------- - * Create/Drop TRIGGER Statements - * ---------------------- - */ + IS_TRUE, IS_NOT_TRUE, IS_FALSE, IS_NOT_FALSE, IS_UNKNOWN, IS_NOT_UNKNOWN +} BoolTestType; -typedef struct CreateTrigStmt +typedef struct BooleanTest { NodeTag type; - char *trigname; /* TRIGGER' name */ - char *relname; /* triggered relation */ - char *funcname; /* function to call (or NULL) */ - List *args; /* list of (T_String) Values or NULL */ - bool before; /* BEFORE/AFTER */ - bool row; /* ROW/STATEMENT */ - char actions[4]; /* Insert, Update, Delete */ - char *lang; /* currently not used, always NULL */ - char *text; /* AS 'text' */ - List *attr; /* UPDATE OF a, b,... (NI) or NULL */ - char *when; /* WHEN 'a > 10 ...' (NI) or NULL */ - - /* The following are used for referential */ - /* integrity constraint triggers */ - bool isconstraint; /* This is an RI trigger */ - bool deferrable; /* [NOT] DEFERRABLE */ - bool initdeferred; /* INITIALLY {DEFERRED|IMMEDIATE} */ - char *constrrelname; /* opposite relation */ -} CreateTrigStmt; + Node *arg; /* input expression */ + BoolTestType booltesttype; /* test type */ +} BooleanTest; -typedef struct DropTrigStmt +/* + * ColumnDef - column definition (used in various creates) + * + * If the column has a default value, we may have the value expression + * in either "raw" form (an untransformed parse tree) or "cooked" form + * (the nodeToString representation of an executable expression tree), + * depending on how this ColumnDef node was created (by parsing, or by + * inheritance from an existing relation). We should never have both + * in the same node! + * + * The constraints list may contain a CONSTR_DEFAULT item in a raw + * parsetree produced by gram.y, but transformCreateStmt will remove + * the item and set raw_default instead. CONSTR_DEFAULT items + * should not appear in any subsequent processing. + */ +typedef struct ColumnDef { NodeTag type; - char *trigname; /* TRIGGER' name */ - char *relname; /* triggered relation */ -} DropTrigStmt; - + char *colname; /* name of column */ + TypeName *typename; /* type of column */ + bool is_not_null; /* NOT NULL constraint specified? */ + Node *raw_default; /* default value (untransformed parse + * tree) */ + char *cooked_default; /* nodeToString representation */ + List *constraints; /* other constraints on column */ +} ColumnDef; -/* ---------------------- - * Create/Drop PROCEDURAL LANGUAGE Statement - * ---------------------- +/* + * 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). */ -typedef struct CreatePLangStmt +typedef struct Ident { NodeTag type; - char *plname; /* PL name */ - char *plhandler; /* PL call handler function */ - char *plcompiler; /* lancompiler text */ - bool pltrusted; /* PL is trusted */ -} CreatePLangStmt; + char *name; /* its name */ + List *indirection; /* array references */ + bool isRel; /* is this a relation or a column? */ +} Ident; -typedef struct DropPLangStmt +/* + * FuncCall - a function or aggregate invocation + * + * agg_star indicates we saw a 'foo(*)' construct, while agg_distinct + * indicates we saw 'foo(DISTINCT ...)'. In either case, the construct + * *must* be an aggregate call. Otherwise, it might be either an + * aggregate or some other kind of function. + */ +typedef struct FuncCall { NodeTag type; - char *plname; /* PL name */ -} DropPLangStmt; - + char *funcname; /* name of function */ + List *args; /* the arguments (list of exprs) */ + bool agg_star; /* argument was really '*' */ + bool agg_distinct; /* arguments were labeled DISTINCT */ +} FuncCall; -/* ---------------------- - * Create/Alter/Drop User Statements - * ---------------------- +/* + * A_Indices - array reference or bounds ([lidx:uidx] or [uidx]) */ -typedef struct CreateUserStmt +typedef struct A_Indices { NodeTag type; - char *user; /* PostgreSQL user login name */ - List *options; /* List of DefElem nodes */ -} CreateUserStmt; + Node *lidx; /* could be NULL */ + Node *uidx; +} A_Indices; -typedef struct AlterUserStmt +/* + * ResTarget - + * result target (used in target list of pre-transformed Parse trees) + * + * In a SELECT or INSERT target list, 'name' is either NULL or + * the column name assigned to the value. (If there is an 'AS ColumnLabel' + * clause, the grammar sets 'name' from it; otherwise 'name' is initially NULL + * and is filled in during the parse analysis phase.) + * The 'indirection' field is not used at all. + * + * In an UPDATE target list, 'name' is the name of the destination column, + * and 'indirection' stores any subscripts attached to the destination. + * That is, our representation is UPDATE table SET name [indirection] = val. + */ +typedef struct ResTarget { NodeTag type; - char *user; /* PostgreSQL user login name */ - List *options; /* List of DefElem nodes */ -} AlterUserStmt; + char *name; /* column name or NULL */ + List *indirection; /* subscripts for destination column, or + * NIL */ + Node *val; /* the value expression to compute or + * assign */ +} ResTarget; -typedef struct AlterUserSetStmt +/* + * SortGroupBy - for ORDER BY clause + */ +typedef struct SortGroupBy { NodeTag type; - char *user; - char *variable; - List *value; -} AlterUserSetStmt; + char *useOp; /* operator to use */ + Node *node; /* Expression */ +} SortGroupBy; -typedef struct DropUserStmt +/* + * RangeVar - range variable, used in FROM clauses + */ +typedef struct RangeVar { NodeTag type; - List *users; /* List of users to remove */ -} DropUserStmt; - + char *relname; /* the relation name */ + InhOption inhOpt; /* expand rel by inheritance? */ + Attr *name; /* optional table alias & column aliases */ +} RangeVar; -/* ---------------------- - * Create/Alter/Drop Group Statements - * ---------------------- +/* + * RangeSubselect - subquery appearing in a FROM clause */ -typedef struct CreateGroupStmt +typedef struct RangeSubselect { NodeTag type; - char *name; /* name of the new group */ - List *options; /* List of DefElem nodes */ -} CreateGroupStmt; + Node *subquery; /* the untransformed sub-select clause */ + Attr *name; /* table alias & optional column aliases */ +} RangeSubselect; -typedef struct AlterGroupStmt +/* + * IndexElem - index parameters (used in CREATE INDEX) + * + * For a plain index, each 'name' is an attribute name in the heap relation, + * and 'args' is NIL. For a functional index, only one IndexElem is allowed. + * It has name = name of function and args = list of attribute names that + * are the function's arguments. + */ +typedef struct IndexElem { NodeTag type; - char *name; /* name of group to alter */ - int action; /* +1 = add, -1 = drop user */ - List *listUsers; /* list of users to add/drop */ -} AlterGroupStmt; + char *name; /* name of attribute to index, or function */ + List *args; /* list of names of function arguments */ + char *class; /* name of desired opclass; NULL = default */ +} IndexElem; -typedef struct DropGroupStmt +/* + * DefElem - + * a definition (used in definition lists in the form of defname = arg) + */ +typedef struct DefElem { NodeTag type; - char *name; -} DropGroupStmt; - + char *defname; + Node *arg; /* a (Value *) or a (TypeName *) */ +} DefElem; -/* ---------------------- - * Create SEQUENCE Statement - * ---------------------- - */ -typedef struct CreateSeqStmt -{ - NodeTag type; - char *seqname; /* the relation to create */ - bool istemp; /* is this a temp sequence? */ - List *options; -} CreateSeqStmt; +/**************************************************************************** + * Nodes for a Query tree + ****************************************************************************/ -/* ---------------------- - * Create Version Statement - * ---------------------- +/* + * TargetEntry - + * a target entry (used in the transformed target list) + * + * one of resdom or fjoin is not NULL. a target list is + * (( expr) ( expr) ...) */ -typedef struct VersionStmt +typedef struct TargetEntry { NodeTag type; - char *relname; /* the new relation */ - int direction; /* FORWARD | BACKWARD */ - char *fromRelname; /* relation to create a version */ - char *date; /* date of the snapshot */ -} VersionStmt; + Resdom *resdom; /* fjoin overload this to be a list?? */ + Fjoin *fjoin; + Node *expr; +} TargetEntry; -/* ---------------------- - * Create {Operator|Type|Aggregate} Statement - * ---------------------- +/*-------------------- + * RangeTblEntry - + * A range table is a List of RangeTblEntry nodes. + * + * Currently we use the same node type for both plain relation references + * and sub-selects in the FROM clause. It might be cleaner to abstract + * the common fields into a "superclass" nodetype. + * + * alias is an Attr 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 + * real or aliases). Note that system columns (OID etc) are not included + * in the column list. + * eref->relname is required to be present, and should generally be used + * to identify the RTE for error messages etc. + * + * inh is TRUE for relation references that should be expanded to include + * inheritance children, if the rel has any. This *must* be FALSE for + * subquery RTEs. + * + * inFromCl marks those range variables that are listed in the FROM clause. + * In SQL, the query can only refer to range variables listed in the + * FROM clause, but POSTQUEL allows you to refer to tables not listed, + * in which case a range table entry will be generated. We still support + * this POSTQUEL feature, although there is some doubt whether it's + * convenient or merely confusing. The flag is needed since an + * implicitly-added RTE shouldn't change the namespace for unqualified + * column names processed later, and it also shouldn't affect the + * expansion of '*'. + * + * checkForRead, checkForWrite, and checkAsUser control run-time access + * permissions checks. A rel will be checked for read or write access + * (or both, or neither) per checkForRead and checkForWrite. If + * checkAsUser is not InvalidOid, then do the permissions checks using + * the access rights of that user, not the current effective user ID. + * (This allows rules to act as setuid gateways.) + *-------------------- */ -typedef struct DefineStmt +typedef struct RangeTblEntry { NodeTag type; - int defType; /* OPERATOR|P_TYPE|AGGREGATE */ - char *defname; - List *definition; /* a list of DefElem */ -} DefineStmt; + /* + * Fields valid for a plain relation RTE (else NULL/zero): + */ + char *relname; /* real name of the relation */ + Oid relid; /* OID of the relation */ -/* ---------------------- - * Drop Table|Sequence|View|Index|Rule|Type Statement - * ---------------------- - */ + /* + * Fields valid for a subquery RTE (else NULL): + */ + Query *subquery; /* the sub-query */ -#define DROP_TABLE 1 -#define DROP_SEQUENCE 2 -#define DROP_VIEW 3 -#define DROP_INDEX 4 -#define DROP_RULE 5 -#define DROP_TYPE_P 6 + /* + * Fields valid in all RTEs: + */ + Attr *alias; /* user-written alias clause, if any */ + Attr *eref; /* expanded reference names */ + bool inh; /* inheritance requested? */ + bool inFromCl; /* present in FROM clause */ + bool checkForRead; /* check rel for read access */ + bool checkForWrite; /* check rel for write access */ + Oid checkAsUser; /* if not zero, check access as this user */ +} RangeTblEntry; -typedef struct DropStmt +/* + * SortClause - + * representation of ORDER BY clauses + * + * tleSortGroupRef must match ressortgroupref of exactly one Resdom of the + * associated targetlist; that is the expression to be sorted (or grouped) by. + * sortop is the OID of the ordering operator. + * + * SortClauses are also used to identify Resdoms that we will do a "Unique" + * filter step on (for SELECT DISTINCT and SELECT DISTINCT ON). The + * distinctClause list is simply a copy of the relevant members of the + * sortClause list. Note that distinctClause can be a subset of sortClause, + * but cannot have members not present in sortClause; and the members that + * do appear must be in the same order as in sortClause. + */ +typedef struct SortClause { NodeTag type; - List *names; - int removeType; -} DropStmt; + Index tleSortGroupRef; /* reference into targetlist */ + Oid sortop; /* the sort operator to use */ +} SortClause; -/* ---------------------- - * Truncate Table Statement - * ---------------------- +/* + * GroupClause - + * representation of GROUP BY clauses + * + * GroupClause is exactly like SortClause except for the nodetag value + * (it's probably not even really necessary to have two different + * nodetags...). We have routines that operate interchangeably on both. */ -typedef struct TruncateStmt -{ - NodeTag type; - char *relName; /* relation to be truncated */ -} TruncateStmt; +typedef SortClause GroupClause; + + +/***************************************************************************** + * Optimizable Statements + *****************************************************************************/ /* ---------------------- - * Comment On Statement + * Insert Statement * ---------------------- */ -typedef struct CommentStmt +typedef struct InsertStmt { NodeTag type; - int objtype; /* Object's type */ - char *objname; /* Name of the object */ - char *objproperty; /* Property Id (such as column) */ - List *objlist; /* Arguments for VAL objects */ - char *comment; /* The comment to insert */ -} CommentStmt; + char *relname; /* relation to insert into */ + List *cols; /* optional: names of the target columns */ + + /* + * An INSERT statement has *either* VALUES or SELECT, never both. If + * VALUES, a targetList is supplied (empty for DEFAULT VALUES). If + * SELECT, a complete SelectStmt (or set-operation tree) is supplied. + */ + List *targetList; /* the target list (of ResTarget) */ + Node *selectStmt; /* the source SELECT */ +} InsertStmt; /* ---------------------- - * Begin Recipe Statement + * Delete Statement * ---------------------- */ -typedef struct RecipeStmt +typedef struct DeleteStmt { NodeTag type; - char *recipeName; /* name of the recipe */ -} RecipeStmt; + char *relname; /* relation to delete from */ + Node *whereClause; /* qualifications */ + InhOption inhOpt; /* recursively act on children? */ +} DeleteStmt; /* ---------------------- - * Fetch Statement + * Update Statement * ---------------------- */ -typedef struct FetchStmt +typedef struct UpdateStmt { NodeTag type; - int direction; /* FORWARD or BACKWARD */ - int howMany; /* amount to fetch ("ALL" --> 0) */ - char *portalname; /* name of portal (cursor) */ - bool ismove; /* TRUE if MOVE */ -} FetchStmt; + char *relname; /* relation to update */ + List *targetList; /* the target list (of ResTarget) */ + Node *whereClause; /* qualifications */ + List *fromClause; /* the from clause */ + InhOption inhOpt; /* recursively act on children? */ +} UpdateStmt; /* ---------------------- - * Create Index Statement + * Select Statement + * + * A "simple" SELECT is represented in the output of gram.y by a single + * SelectStmt node. A SELECT construct containing set operators (UNION, + * INTERSECT, EXCEPT) is represented by a tree of SelectStmt nodes, in + * which the leaf nodes are component SELECTs and the internal nodes + * represent UNION, INTERSECT, or EXCEPT operators. Using the same node + * type for both leaf and internal nodes allows gram.y to stick ORDER BY, + * LIMIT, etc, clause values into a SELECT statement without worrying + * whether it is a simple or compound SELECT. * ---------------------- */ -typedef struct IndexStmt +typedef enum SetOperation +{ + SETOP_NONE = 0, + SETOP_UNION, + SETOP_INTERSECT, + SETOP_EXCEPT +} SetOperation; + +typedef struct SelectStmt { NodeTag type; - char *idxname; /* name of the index */ - char *relname; /* name of relation to index on */ - char *accessMethod; /* name of access method (eg. btree) */ - List *indexParams; /* a list of IndexElem */ - Node *whereClause; /* qualification (partial-index predicate) */ - List *rangetable; /* range table for qual, filled in by - * transformStmt() */ - bool unique; /* is index unique? */ - bool primary; /* is index on primary key? */ -} IndexStmt; + + /* + * These fields are used only in "leaf" SelectStmts. + */ + 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? */ + List *intoColNames; /* column names for into table */ + List *targetList; /* the target list (of ResTarget) */ + List *fromClause; /* the FROM clause */ + Node *whereClause; /* WHERE qualification */ + List *groupClause; /* GROUP BY clauses */ + Node *havingClause; /* HAVING conditional-expression */ + + /* + * These fields are used in both "leaf" SelectStmts and upper-level + * SelectStmts. portalname/binary may only be set at the top level. + */ + List *sortClause; /* sort clause (a list of SortGroupBy's) */ + char *portalname; /* the portal (cursor) to create */ + bool binary; /* a binary (internal) portal? */ + Node *limitOffset; /* # of result tuples to skip */ + Node *limitCount; /* # of result tuples to return */ + List *forUpdate; /* FOR UPDATE clause */ + + /* + * These fields are used only in upper-level SelectStmts. + */ + SetOperation op; /* type of set op */ + bool all; /* ALL specified? */ + struct SelectStmt *larg; /* left child */ + struct SelectStmt *rarg; /* right child */ + /* Eventually add fields for CORRESPONDING spec here */ +} SelectStmt; /* ---------------------- - * Create Function Statement + * Set Operation node for post-analysis query trees + * + * After parse analysis, a SELECT with set operations is represented by a + * top-level Query node containing the leaf SELECTs as subqueries in its + * range table. Its setOperations field shows the tree of set operations, + * with leaf SelectStmt nodes replaced by RangeTblRef nodes, and internal + * nodes replaced by SetOperationStmt nodes. * ---------------------- */ -typedef struct ProcedureStmt +typedef struct SetOperationStmt { NodeTag type; - bool replace; /* T => replace if already exists */ - char *funcname; /* name of function to create */ - List *argTypes; /* list of argument types (TypeName nodes) */ - Node *returnType; /* the return type (a TypeName node) */ - List *withClause; /* a list of DefElem */ - List *as; /* definition of function body */ - char *language; /* C, SQL, etc */ -} ProcedureStmt; + SetOperation op; /* type of set op */ + bool all; /* ALL specified? */ + Node *larg; /* left child */ + Node *rarg; /* right child */ + /* Eventually add fields for CORRESPONDING spec here */ + + /* Fields derived during parse analysis: */ + List *colTypes; /* integer list of OIDs of output column + * types */ +} SetOperationStmt; + + +/***************************************************************************** + * Other Statements (no optimizations required) + * + * Some of them require a little bit of transformation (which is also + * done by transformStmt). The whole structure is then passed on to + * ProcessUtility (by-passing the optimization step) as the utilityStmt + * field in Query. + *****************************************************************************/ /* ---------------------- - * Drop Aggregate Statement + * Alter Table + * + * The fields are used in different ways by the different variants of + * this command. * ---------------------- */ -typedef struct RemoveAggrStmt +typedef struct AlterTableStmt { NodeTag type; - char *aggname; /* aggregate to drop */ - Node *aggtype; /* TypeName for input datatype, or NULL */ -} RemoveAggrStmt; + char subtype; /*------------ + * A = add column + * T = alter column default + * S = alter column statistics + * M = alter column storage + * D = drop column + * C = add constraint + * X = drop constraint + * E = create toast table + * U = change owner + *------------ + */ + char *relname; /* table to work on */ + InhOption inhOpt; /* recursively act on children? */ + char *name; /* column or constraint name to act on, or + * new owner */ + Node *def; /* definition of new column or constraint */ + int behavior; /* CASCADE or RESTRICT drop behavior */ +} AlterTableStmt; /* ---------------------- - * Drop Function Statement + * Grant Statement * ---------------------- */ -typedef struct RemoveFuncStmt + +typedef struct GrantStmt { NodeTag type; - char *funcname; /* function to drop */ - List *args; /* types of the arguments */ -} RemoveFuncStmt; + bool is_grant; /* not revoke */ + int objtype; + List *objects; /* list of names (as Value strings) */ + List *privileges; /* integer list of privilege codes */ + List *grantees; /* list of PrivGrantee nodes */ +} GrantStmt; -/* ---------------------- - * Drop Operator Statement - * ---------------------- - */ -typedef struct RemoveOperStmt + +typedef struct PrivGrantee { NodeTag type; - char *opname; /* operator to drop */ - List *args; /* types of the arguments */ -} RemoveOperStmt; + char *username; /* if both are NULL then PUBLIC */ + char *groupname; +} PrivGrantee; -/* ---------------------- - * Alter Table Statement - * ---------------------- - */ -typedef struct RenameStmt + +typedef struct FuncWithArgs { NodeTag type; - char *relname; /* relation to be altered */ - InhOption inhOpt; /* recursively act on children? */ - char *column; /* if NULL, rename the relation name to - * the new name. Otherwise, rename this - * column name. */ - char *newname; /* the new name */ -} RenameStmt; + char *funcname; + List *funcargs; /* list of Typename nodes */ +} FuncWithArgs; -/* ---------------------- - * Create Rule Statement - * ---------------------- - */ -typedef struct RuleStmt + +/* This is only used internally in gram.y. */ +typedef struct PrivTarget { NodeTag type; - char *rulename; /* name of the rule */ - Node *whereClause; /* qualifications */ - CmdType event; /* RETRIEVE */ - struct Attr *object; /* object affected */ - bool instead; /* is a 'do instead'? */ - List *actions; /* the action statements */ -} RuleStmt; + int objtype; + List *objs; +} PrivTarget; + /* ---------------------- - * Notify Statement + * Close Portal Statement * ---------------------- */ -typedef struct NotifyStmt +typedef struct ClosePortalStmt { NodeTag type; - char *relname; /* relation to notify */ -} NotifyStmt; + char *portalname; /* name of the portal (cursor) */ +} ClosePortalStmt; /* ---------------------- - * Listen Statement + * Copy Statement * ---------------------- */ -typedef struct ListenStmt +typedef struct CopyStmt { NodeTag type; - char *relname; /* relation to listen on */ -} ListenStmt; + bool binary; /* is a binary copy? */ + char *relname; /* the relation to copy */ + bool oids; /* copy oid's? */ + int direction; /* TO or FROM */ + char *filename; /* if NULL, use stdin/stdout */ + char *delimiter; /* delimiter character, \t by default */ + char *null_print; /* how to print NULLs, `\N' by default */ +} CopyStmt; /* ---------------------- - * Unlisten Statement + * Create Table Statement + * + * NOTE: in the raw gram.y output, ColumnDef, Constraint, and FkConstraint + * nodes are intermixed in tableElts, and constraints is NIL. After parse + * analysis, tableElts contains just ColumnDefs, and constraints contains + * just Constraint nodes (in fact, only CONSTR_CHECK nodes, in the present + * implementation). * ---------------------- */ -typedef struct UnlistenStmt +typedef struct CreateStmt { NodeTag type; - char *relname; /* relation to unlisten on */ -} UnlistenStmt; + char *relname; /* name of relation to create */ + List *tableElts; /* column definitions (list of ColumnDef) */ + List *inhRelnames; /* relations to inherit from (list of + * T_String Values) */ + List *constraints; /* constraints (list of Constraint nodes) */ + bool istemp; /* is this a temp table? */ + bool hasoids; /* should it have OIDs? */ +} CreateStmt; -/* ---------------------- - * {Begin|Abort|End} Transaction Statement - * ---------------------- +/* ---------- + * Definitions for plain (non-FOREIGN KEY) constraints in CreateStmt + * + * XXX probably these ought to be unified with FkConstraints at some point? + * + * For constraints that use expressions (CONSTR_DEFAULT, CONSTR_CHECK) + * we may have the expression in either "raw" form (an untransformed + * parse tree) or "cooked" form (the nodeToString representation of + * an executable expression tree), depending on how this Constraint + * node was created (by parsing, or by inheritance from an existing + * relation). We should never have both in the same node! + * + * Constraint attributes (DEFERRABLE etc) are initially represented as + * separate Constraint nodes for simplicity of parsing. analyze.c makes + * a pass through the constraints list to attach the info to the appropriate + * FkConstraint node (and, perhaps, someday to other kinds of constraints). + * ---------- */ -typedef struct TransactionStmt + +typedef enum ConstrType /* types of constraints */ +{ + CONSTR_NULL, /* not SQL92, but a lot of people expect + * it */ + CONSTR_NOTNULL, + CONSTR_DEFAULT, + CONSTR_CHECK, + CONSTR_PRIMARY, + CONSTR_UNIQUE, + CONSTR_ATTR_DEFERRABLE, /* attributes for previous constraint node */ + CONSTR_ATTR_NOT_DEFERRABLE, + CONSTR_ATTR_DEFERRED, + CONSTR_ATTR_IMMEDIATE +} ConstrType; + +typedef struct Constraint { NodeTag type; - int command; /* BEGIN|END|ABORT */ -} TransactionStmt; + ConstrType contype; + char *name; /* name, or NULL if unnamed */ + Node *raw_expr; /* expr, as untransformed parse tree */ + char *cooked_expr; /* expr, as nodeToString representation */ + List *keys; /* Ident nodes naming referenced column(s) */ +} Constraint; -/* ---------------------- - * Create View Statement - * ---------------------- +/* ---------- + * Definitions for FOREIGN KEY constraints in CreateStmt + * ---------- */ -typedef struct ViewStmt +#define FKCONSTR_ON_KEY_NOACTION 0x0000 +#define FKCONSTR_ON_KEY_RESTRICT 0x0001 +#define FKCONSTR_ON_KEY_CASCADE 0x0002 +#define FKCONSTR_ON_KEY_SETNULL 0x0004 +#define FKCONSTR_ON_KEY_SETDEFAULT 0x0008 + +#define FKCONSTR_ON_DELETE_MASK 0x000F +#define FKCONSTR_ON_DELETE_SHIFT 0 + +#define FKCONSTR_ON_UPDATE_MASK 0x00F0 +#define FKCONSTR_ON_UPDATE_SHIFT 4 + +typedef struct FkConstraint { NodeTag type; - char *viewname; /* name of the view */ - List *aliases; /* target column names */ - Query *query; /* the SQL statement */ -} ViewStmt; + char *constr_name; /* Constraint name */ + char *pktable_name; /* Primary key table name */ + List *fk_attrs; /* Attributes of foreign key */ + List *pk_attrs; /* Corresponding attrs in PK table */ + char *match_type; /* FULL or PARTIAL */ + int32 actions; /* ON DELETE/UPDATE actions */ + bool deferrable; /* DEFERRABLE */ + bool initdeferred; /* INITIALLY DEFERRED */ +} FkConstraint; /* ---------------------- - * Load Statement + * Create/Drop TRIGGER Statements * ---------------------- */ -typedef struct LoadStmt + +typedef struct CreateTrigStmt { NodeTag type; - char *filename; /* file to load */ -} LoadStmt; + char *trigname; /* TRIGGER' name */ + char *relname; /* triggered relation */ + char *funcname; /* function to call (or NULL) */ + List *args; /* list of (T_String) Values or NULL */ + bool before; /* BEFORE/AFTER */ + bool row; /* ROW/STATEMENT */ + char actions[4]; /* Insert, Update, Delete */ + char *lang; /* currently not used, always NULL */ + char *text; /* AS 'text' */ + List *attr; /* UPDATE OF a, b,... (NI) or NULL */ + char *when; /* WHEN 'a > 10 ...' (NI) or NULL */ -/* ---------------------- - * Createdb Statement - * ---------------------- - */ -typedef struct CreatedbStmt + /* The following are used for referential */ + /* integrity constraint triggers */ + bool isconstraint; /* This is an RI trigger */ + bool deferrable; /* [NOT] DEFERRABLE */ + bool initdeferred; /* INITIALLY {DEFERRED|IMMEDIATE} */ + char *constrrelname; /* opposite relation */ +} CreateTrigStmt; + +typedef struct DropTrigStmt { NodeTag type; - char *dbname; /* name of database to create */ - char *dbowner; /* name of owner (NULL = default) */ - char *dbpath; /* location of database (NULL = default) */ - char *dbtemplate; /* template to use (NULL = default) */ - int encoding; /* MULTIBYTE encoding (-1 = use default) */ -} CreatedbStmt; + char *trigname; /* TRIGGER' name */ + char *relname; /* triggered relation */ +} DropTrigStmt; /* ---------------------- - * Alter Database + * Create/Drop PROCEDURAL LANGUAGE Statement * ---------------------- */ -typedef struct AlterDatabaseSetStmt +typedef struct CreatePLangStmt { NodeTag type; - char *dbname; - char *variable; - List *value; -} AlterDatabaseSetStmt; + char *plname; /* PL name */ + char *plhandler; /* PL call handler function */ + char *plcompiler; /* lancompiler text */ + bool pltrusted; /* PL is trusted */ +} CreatePLangStmt; -/* ---------------------- - * Dropdb Statement - * ---------------------- - */ -typedef struct DropdbStmt +typedef struct DropPLangStmt { NodeTag type; - char *dbname; /* database to drop */ -} DropdbStmt; + char *plname; /* PL name */ +} DropPLangStmt; /* ---------------------- - * Cluster Statement (support pbrown's cluster index implementation) + * Create/Alter/Drop User Statements * ---------------------- */ -typedef struct ClusterStmt +typedef struct CreateUserStmt { NodeTag type; - char *relname; /* relation being indexed */ - char *indexname; /* original index defined */ -} ClusterStmt; + char *user; /* PostgreSQL user login name */ + List *options; /* List of DefElem nodes */ +} CreateUserStmt; -/* ---------------------- - * Vacuum and Analyze Statements - * - * Even though these are nominally two statements, it's convenient to use - * just one node type for both. - * ---------------------- - */ -typedef struct VacuumStmt +typedef struct AlterUserStmt { NodeTag type; - bool vacuum; /* do VACUUM step */ - bool full; /* do FULL (non-concurrent) vacuum */ - 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 */ - List *va_cols; /* list of column names, or NIL for all */ -} VacuumStmt; + char *user; /* PostgreSQL user login name */ + List *options; /* List of DefElem nodes */ +} AlterUserStmt; -/* ---------------------- - * Explain Statement - * ---------------------- - */ -typedef struct ExplainStmt +typedef struct AlterUserSetStmt { NodeTag type; - Query *query; /* the query */ - bool verbose; /* print plan info */ - bool analyze; /* get statistics by executing plan */ -} ExplainStmt; + char *user; + char *variable; + List *value; +} AlterUserSetStmt; -/* ---------------------- - * Checkpoint Statement - * ---------------------- - */ -typedef struct CheckPointStmt +typedef struct DropUserStmt { NodeTag type; -} CheckPointStmt; + List *users; /* List of users to remove */ +} DropUserStmt; /* ---------------------- - * Set Statement + * Create/Alter/Drop Group Statements * ---------------------- */ - -typedef struct VariableSetStmt +typedef struct CreateGroupStmt { NodeTag type; - char *name; - List *args; -} VariableSetStmt; + char *name; /* name of the new group */ + List *options; /* List of DefElem nodes */ +} CreateGroupStmt; -/* ---------------------- - * Show Statement - * ---------------------- - */ +typedef struct AlterGroupStmt +{ + NodeTag type; + char *name; /* name of group to alter */ + int action; /* +1 = add, -1 = drop user */ + List *listUsers; /* list of users to add/drop */ +} AlterGroupStmt; -typedef struct VariableShowStmt +typedef struct DropGroupStmt { NodeTag type; char *name; -} VariableShowStmt; +} DropGroupStmt; /* ---------------------- - * Reset Statement + * Create SEQUENCE Statement * ---------------------- */ -typedef struct VariableResetStmt +typedef struct CreateSeqStmt { NodeTag type; - char *name; -} VariableResetStmt; + char *seqname; /* the relation to create */ + bool istemp; /* is this a temp sequence? */ + List *options; +} CreateSeqStmt; /* ---------------------- - * LOCK Statement + * Create Version Statement * ---------------------- */ -typedef struct LockStmt +typedef struct VersionStmt { NodeTag type; - List *rellist; /* relations to lock */ - int mode; /* lock mode */ -} LockStmt; - + char *relname; /* the new relation */ + int direction; /* FORWARD | BACKWARD */ + char *fromRelname; /* relation to create a version */ + char *date; /* date of the snapshot */ +} VersionStmt; /* ---------------------- - * SET CONSTRAINTS Statement + * Create {Operator|Type|Aggregate} Statement * ---------------------- */ -typedef struct ConstraintsSetStmt +typedef struct DefineStmt { NodeTag type; - List *constraints; - bool deferred; -} ConstraintsSetStmt; + int defType; /* OPERATOR|P_TYPE|AGGREGATE */ + char *defname; + List *definition; /* a list of DefElem */ +} DefineStmt; /* ---------------------- - * REINDEX Statement + * Drop Table|Sequence|View|Index|Rule|Type Statement * ---------------------- */ -typedef struct ReindexStmt -{ - NodeTag type; - int reindexType; /* INDEX|TABLE|DATABASE */ - const char *name; /* name to reindex */ - bool force; - bool all; -} ReindexStmt; +#define DROP_TABLE 1 +#define DROP_SEQUENCE 2 +#define DROP_VIEW 3 +#define DROP_INDEX 4 +#define DROP_RULE 5 +#define DROP_TYPE_P 6 -/***************************************************************************** - * Optimizable Statements - *****************************************************************************/ +typedef struct DropStmt +{ + NodeTag type; + List *names; + int removeType; +} DropStmt; /* ---------------------- - * Insert Statement + * Truncate Table Statement * ---------------------- */ -typedef struct InsertStmt +typedef struct TruncateStmt { NodeTag type; - char *relname; /* relation to insert into */ - List *cols; /* optional: names of the target columns */ - - /* - * An INSERT statement has *either* VALUES or SELECT, never both. If - * VALUES, a targetList is supplied (empty for DEFAULT VALUES). If - * SELECT, a complete SelectStmt (or set-operation tree) is supplied. - */ - List *targetList; /* the target list (of ResTarget) */ - Node *selectStmt; /* the source SELECT */ -} InsertStmt; + char *relName; /* relation to be truncated */ +} TruncateStmt; /* ---------------------- - * Delete Statement + * Comment On Statement * ---------------------- */ -typedef struct DeleteStmt +typedef struct CommentStmt { NodeTag type; - char *relname; /* relation to delete from */ - Node *whereClause; /* qualifications */ - InhOption inhOpt; /* recursively act on children? */ -} DeleteStmt; + int objtype; /* Object's type */ + char *objname; /* Name of the object */ + char *objproperty; /* Property Id (such as column) */ + List *objlist; /* Arguments for VAL objects */ + char *comment; /* The comment to insert */ +} CommentStmt; /* ---------------------- - * Update Statement + * Begin Recipe Statement * ---------------------- */ -typedef struct UpdateStmt +typedef struct RecipeStmt { NodeTag type; - char *relname; /* relation to update */ - List *targetList; /* the target list (of ResTarget) */ - Node *whereClause; /* qualifications */ - List *fromClause; /* the from clause */ - InhOption inhOpt; /* recursively act on children? */ -} UpdateStmt; + char *recipeName; /* name of the recipe */ +} RecipeStmt; /* ---------------------- - * Select Statement - * - * A "simple" SELECT is represented in the output of gram.y by a single - * SelectStmt node. A SELECT construct containing set operators (UNION, - * INTERSECT, EXCEPT) is represented by a tree of SelectStmt nodes, in - * which the leaf nodes are component SELECTs and the internal nodes - * represent UNION, INTERSECT, or EXCEPT operators. Using the same node - * type for both leaf and internal nodes allows gram.y to stick ORDER BY, - * LIMIT, etc, clause values into a SELECT statement without worrying - * whether it is a simple or compound SELECT. + * Fetch Statement * ---------------------- */ -typedef enum SetOperation -{ - SETOP_NONE = 0, - SETOP_UNION, - SETOP_INTERSECT, - SETOP_EXCEPT -} SetOperation; - -typedef struct SelectStmt +typedef struct FetchStmt { NodeTag type; - - /* - * These fields are used only in "leaf" SelectStmts. - */ - 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? */ - List *intoColNames; /* column names for into table */ - List *targetList; /* the target list (of ResTarget) */ - List *fromClause; /* the FROM clause */ - Node *whereClause; /* WHERE qualification */ - List *groupClause; /* GROUP BY clauses */ - Node *havingClause; /* HAVING conditional-expression */ - - /* - * These fields are used in both "leaf" SelectStmts and upper-level - * SelectStmts. portalname/binary may only be set at the top level. - */ - List *sortClause; /* sort clause (a list of SortGroupBy's) */ - char *portalname; /* the portal (cursor) to create */ - bool binary; /* a binary (internal) portal? */ - Node *limitOffset; /* # of result tuples to skip */ - Node *limitCount; /* # of result tuples to return */ - List *forUpdate; /* FOR UPDATE clause */ - - /* - * These fields are used only in upper-level SelectStmts. - */ - SetOperation op; /* type of set op */ - bool all; /* ALL specified? */ - struct SelectStmt *larg; /* left child */ - struct SelectStmt *rarg; /* right child */ - /* Eventually add fields for CORRESPONDING spec here */ -} SelectStmt; + int direction; /* FORWARD or BACKWARD */ + int howMany; /* amount to fetch ("ALL" --> 0) */ + char *portalname; /* name of portal (cursor) */ + bool ismove; /* TRUE if MOVE */ +} FetchStmt; /* ---------------------- - * Set Operation node for post-analysis query trees - * - * After parse analysis, a SELECT with set operations is represented by a - * top-level Query node containing the leaf SELECTs as subqueries in its - * range table. Its setOperations field shows the tree of set operations, - * with leaf SelectStmt nodes replaced by RangeTblRef nodes, and internal - * nodes replaced by SetOperationStmt nodes. + * Create Index Statement * ---------------------- */ -typedef struct SetOperationStmt +typedef struct IndexStmt { NodeTag type; - SetOperation op; /* type of set op */ - bool all; /* ALL specified? */ - Node *larg; /* left child */ - Node *rarg; /* right child */ - /* Eventually add fields for CORRESPONDING spec here */ - - /* Fields derived during parse analysis: */ - List *colTypes; /* integer list of OIDs of output column - * types */ -} SetOperationStmt; - -/**************************************************************************** - * Supporting data structures for Parse Trees - * - * Most of these node types appear in raw parsetrees output by the grammar, - * and get transformed to something else by the analyzer. A few of them - * are used as-is in transformed querytrees. - ****************************************************************************/ + char *idxname; /* name of the index */ + char *relname; /* name of relation to index on */ + char *accessMethod; /* name of access method (eg. btree) */ + List *indexParams; /* a list of IndexElem */ + Node *whereClause; /* qualification (partial-index predicate) */ + List *rangetable; /* range table for qual, filled in by + * transformStmt() */ + bool unique; /* is index unique? */ + bool primary; /* is index on primary key? */ +} IndexStmt; -/* - * TypeName - specifies a type in definitions +/* ---------------------- + * Create Function Statement + * ---------------------- */ -typedef struct TypeName +typedef struct ProcedureStmt { NodeTag type; - char *name; /* name of the type */ - bool timezone; /* timezone specified? */ - bool setof; /* is a set? */ - int32 typmod; /* type modifier */ - List *arrayBounds; /* array bounds */ - char *attrname; /* field name when using %TYPE */ -} TypeName; + bool replace; /* T => replace if already exists */ + char *funcname; /* name of function to create */ + List *argTypes; /* list of argument types (TypeName nodes) */ + Node *returnType; /* the return type (a TypeName node) */ + List *withClause; /* a list of DefElem */ + List *as; /* definition of function body */ + char *language; /* C, SQL, etc */ +} ProcedureStmt; -/* - * ParamNo - specifies a parameter reference +/* ---------------------- + * Drop Aggregate Statement + * ---------------------- */ -typedef struct ParamNo +typedef struct RemoveAggrStmt { NodeTag type; - int number; /* the number of the parameter */ - TypeName *typename; /* the typecast */ - List *indirection; /* array references */ -} ParamNo; + char *aggname; /* aggregate to drop */ + Node *aggtype; /* TypeName for input datatype, or NULL */ +} RemoveAggrStmt; -/* - * A_Expr - binary expressions +/* ---------------------- + * Drop Function Statement + * ---------------------- */ -typedef struct A_Expr +typedef struct RemoveFuncStmt { NodeTag type; - int oper; /* type of operation (OP,OR,AND,NOT) */ - char *opname; /* name of operator */ - Node *lexpr; /* left argument */ - Node *rexpr; /* right argument */ -} A_Expr; + char *funcname; /* function to drop */ + List *args; /* types of the arguments */ +} RemoveFuncStmt; -/* - * Attr - - * specifies an Attribute (ie. a Column); could have nested dots or - * array references. - * +/* ---------------------- + * Drop Operator Statement + * ---------------------- */ -typedef struct Attr +typedef struct RemoveOperStmt { 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; + char *opname; /* operator to drop */ + List *args; /* types of the arguments */ +} RemoveOperStmt; -/* - * A_Const - a constant expression +/* ---------------------- + * Alter Table Statement + * ---------------------- */ -typedef struct A_Const +typedef struct RenameStmt { NodeTag type; - Value val; /* the value (with the tag) */ - TypeName *typename; /* typecast */ -} A_Const; + char *relname; /* relation to be altered */ + InhOption inhOpt; /* recursively act on children? */ + char *column; /* if NULL, rename the relation name to + * the new name. Otherwise, rename this + * column name. */ + char *newname; /* the new name */ +} RenameStmt; -/* - * TypeCast - a CAST expression - * - * NOTE: for mostly historical reasons, A_Const and ParamNo 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. +/* ---------------------- + * Create Rule Statement + * ---------------------- */ -typedef struct TypeCast +typedef struct RuleStmt { NodeTag type; - Node *arg; /* the expression being casted */ - TypeName *typename; /* the target type */ -} TypeCast; + char *rulename; /* name of the rule */ + Node *whereClause; /* qualifications */ + CmdType event; /* RETRIEVE */ + struct Attr *object; /* object affected */ + bool instead; /* is a 'do instead'? */ + List *actions; /* the action statements */ +} RuleStmt; -/* - * CaseExpr - a CASE expression +/* ---------------------- + * Notify Statement + * ---------------------- */ -typedef struct CaseExpr +typedef struct NotifyStmt { NodeTag type; - Oid casetype; - Node *arg; /* implicit equality comparison argument */ - List *args; /* the arguments (list of WHEN clauses) */ - Node *defresult; /* the default result (ELSE clause) */ -} CaseExpr; + char *relname; /* relation to notify */ +} NotifyStmt; -/* - * CaseWhen - an argument to a CASE expression +/* ---------------------- + * Listen Statement + * ---------------------- */ -typedef struct CaseWhen +typedef struct ListenStmt { NodeTag type; - Node *expr; /* comparison expression */ - Node *result; /* substitution result */ -} CaseWhen; + char *relname; /* relation to listen on */ +} ListenStmt; -/* ---------------- - * NullTest - * - * NullTest represents the operation of testing a value for NULLness. - * Currently, we only support scalar input values, but eventually a - * row-constructor input should be supported. - * The appropriate test is performed and returned as a boolean Datum. - * ---------------- +/* ---------------------- + * Unlisten Statement + * ---------------------- */ - -typedef enum NullTestType +typedef struct UnlistenStmt { - IS_NULL, IS_NOT_NULL -} NullTestType; + NodeTag type; + char *relname; /* relation to unlisten on */ +} UnlistenStmt; -typedef struct NullTest +/* ---------------------- + * {Begin|Abort|End} Transaction Statement + * ---------------------- + */ +typedef struct TransactionStmt { NodeTag type; - Node *arg; /* input expression */ - NullTestType nulltesttype; /* IS NULL, IS NOT NULL */ -} NullTest; + int command; /* BEGIN|END|ABORT */ +} TransactionStmt; -/* ---------------- - * BooleanTest - * - * BooleanTest represents the operation of determining whether a boolean - * is TRUE, FALSE, or UNKNOWN (ie, NULL). All six meaningful combinations - * are supported. Note that a NULL input does *not* cause a NULL result. - * The appropriate test is performed and returned as a boolean Datum. - * ---------------- +/* ---------------------- + * Create View Statement + * ---------------------- */ - -typedef enum BoolTestType +typedef struct ViewStmt { - IS_TRUE, IS_NOT_TRUE, IS_FALSE, IS_NOT_FALSE, IS_UNKNOWN, IS_NOT_UNKNOWN -} BoolTestType; + NodeTag type; + char *viewname; /* name of the view */ + List *aliases; /* target column names */ + Query *query; /* the SQL statement */ +} ViewStmt; -typedef struct BooleanTest +/* ---------------------- + * Load Statement + * ---------------------- + */ +typedef struct LoadStmt { NodeTag type; - Node *arg; /* input expression */ - BoolTestType booltesttype; /* test type */ -} BooleanTest; + char *filename; /* file to load */ +} LoadStmt; -/* - * ColumnDef - column definition (used in various creates) - * - * If the column has a default value, we may have the value expression - * in either "raw" form (an untransformed parse tree) or "cooked" form - * (the nodeToString representation of an executable expression tree), - * depending on how this ColumnDef node was created (by parsing, or by - * inheritance from an existing relation). We should never have both - * in the same node! - * - * The constraints list may contain a CONSTR_DEFAULT item in a raw - * parsetree produced by gram.y, but transformCreateStmt will remove - * the item and set raw_default instead. CONSTR_DEFAULT items - * should not appear in any subsequent processing. +/* ---------------------- + * Createdb Statement + * ---------------------- */ -typedef struct ColumnDef +typedef struct CreatedbStmt { NodeTag type; - char *colname; /* name of column */ - TypeName *typename; /* type of column */ - bool is_not_null; /* NOT NULL constraint specified? */ - Node *raw_default; /* default value (untransformed parse - * tree) */ - char *cooked_default; /* nodeToString representation */ - List *constraints; /* other constraints on column */ -} ColumnDef; + char *dbname; /* name of database to create */ + char *dbowner; /* name of owner (NULL = default) */ + char *dbpath; /* location of database (NULL = default) */ + char *dbtemplate; /* template to use (NULL = default) */ + int encoding; /* MULTIBYTE encoding (-1 = use default) */ +} CreatedbStmt; -/* - * 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). +/* ---------------------- + * Alter Database + * ---------------------- */ -typedef struct Ident +typedef struct AlterDatabaseSetStmt { NodeTag type; - char *name; /* its name */ - List *indirection; /* array references */ - bool isRel; /* is this a relation or a column? */ -} Ident; + char *dbname; + char *variable; + List *value; +} AlterDatabaseSetStmt; -/* - * FuncCall - a function or aggregate invocation - * - * agg_star indicates we saw a 'foo(*)' construct, while agg_distinct - * indicates we saw 'foo(DISTINCT ...)'. In either case, the construct - * *must* be an aggregate call. Otherwise, it might be either an - * aggregate or some other kind of function. +/* ---------------------- + * Dropdb Statement + * ---------------------- */ -typedef struct FuncCall +typedef struct DropdbStmt { NodeTag type; - char *funcname; /* name of function */ - List *args; /* the arguments (list of exprs) */ - bool agg_star; /* argument was really '*' */ - bool agg_distinct; /* arguments were labeled DISTINCT */ -} FuncCall; + char *dbname; /* database to drop */ +} DropdbStmt; -/* - * A_Indices - array reference or bounds ([lidx:uidx] or [uidx]) +/* ---------------------- + * Cluster Statement (support pbrown's cluster index implementation) + * ---------------------- */ -typedef struct A_Indices +typedef struct ClusterStmt { NodeTag type; - Node *lidx; /* could be NULL */ - Node *uidx; -} A_Indices; + char *relname; /* relation being indexed */ + char *indexname; /* original index defined */ +} ClusterStmt; -/* - * ResTarget - - * result target (used in target list of pre-transformed Parse trees) - * - * In a SELECT or INSERT target list, 'name' is either NULL or - * the column name assigned to the value. (If there is an 'AS ColumnLabel' - * clause, the grammar sets 'name' from it; otherwise 'name' is initially NULL - * and is filled in during the parse analysis phase.) - * The 'indirection' field is not used at all. +/* ---------------------- + * Vacuum and Analyze Statements * - * In an UPDATE target list, 'name' is the name of the destination column, - * and 'indirection' stores any subscripts attached to the destination. - * That is, our representation is UPDATE table SET name [indirection] = val. + * Even though these are nominally two statements, it's convenient to use + * just one node type for both. + * ---------------------- */ -typedef struct ResTarget +typedef struct VacuumStmt { NodeTag type; - char *name; /* column name or NULL */ - List *indirection; /* subscripts for destination column, or - * NIL */ - Node *val; /* the value expression to compute or - * assign */ -} ResTarget; + bool vacuum; /* do VACUUM step */ + bool full; /* do FULL (non-concurrent) vacuum */ + 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 */ + List *va_cols; /* list of column names, or NIL for all */ +} VacuumStmt; -/* - * SortGroupBy - for ORDER BY clause +/* ---------------------- + * Explain Statement + * ---------------------- */ -typedef struct SortGroupBy +typedef struct ExplainStmt { NodeTag type; - char *useOp; /* operator to use */ - Node *node; /* Expression */ -} SortGroupBy; + Query *query; /* the query */ + bool verbose; /* print plan info */ + bool analyze; /* get statistics by executing plan */ +} ExplainStmt; -/* - * RangeVar - range variable, used in FROM clauses +/* ---------------------- + * Checkpoint Statement + * ---------------------- */ -typedef struct RangeVar +typedef struct CheckPointStmt { NodeTag type; - char *relname; /* the relation name */ - InhOption inhOpt; /* expand rel by inheritance? */ - Attr *name; /* optional table alias & column aliases */ -} RangeVar; +} CheckPointStmt; -/* - * RangeSubselect - subquery appearing in a FROM clause +/* ---------------------- + * Set Statement + * ---------------------- */ -typedef struct RangeSubselect + +typedef struct VariableSetStmt { NodeTag type; - Node *subquery; /* the untransformed sub-select clause */ - Attr *name; /* table alias & optional column aliases */ -} RangeSubselect; + char *name; + List *args; +} VariableSetStmt; -/* - * IndexElem - index parameters (used in CREATE INDEX) - * - * For a plain index, each 'name' is an attribute name in the heap relation, - * and 'args' is NIL. For a functional index, only one IndexElem is allowed. - * It has name = name of function and args = list of attribute names that - * are the function's arguments. +/* ---------------------- + * Show Statement + * ---------------------- */ -typedef struct IndexElem + +typedef struct VariableShowStmt { NodeTag type; - char *name; /* name of attribute to index, or function */ - List *args; /* list of names of function arguments */ - char *class; /* name of desired opclass; NULL = default */ -} IndexElem; + char *name; +} VariableShowStmt; -/* - * DefElem - - * a definition (used in definition lists in the form of defname = arg) +/* ---------------------- + * Reset Statement + * ---------------------- */ -typedef struct DefElem + +typedef struct VariableResetStmt { NodeTag type; - char *defname; - Node *arg; /* a (Value *) or a (TypeName *) */ -} DefElem; - - -/**************************************************************************** - * Nodes for a Query tree - ****************************************************************************/ + char *name; +} VariableResetStmt; -/* - * TargetEntry - - * a target entry (used in the transformed target list) - * - * one of resdom or fjoin is not NULL. a target list is - * (( expr) ( expr) ...) +/* ---------------------- + * LOCK Statement + * ---------------------- */ -typedef struct TargetEntry +typedef struct LockStmt { NodeTag type; - Resdom *resdom; /* fjoin overload this to be a list?? */ - Fjoin *fjoin; - Node *expr; -} TargetEntry; + List *rellist; /* relations to lock */ + int mode; /* lock mode */ +} LockStmt; -/*-------------------- - * RangeTblEntry - - * A range table is a List of RangeTblEntry nodes. - * - * Currently we use the same node type for both plain relation references - * and sub-selects in the FROM clause. It might be cleaner to abstract - * the common fields into a "superclass" nodetype. - * - * alias is an Attr 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 - * real or aliases). Note that system columns (OID etc) are not included - * in the column list. - * eref->relname is required to be present, and should generally be used - * to identify the RTE for error messages etc. - * - * inh is TRUE for relation references that should be expanded to include - * inheritance children, if the rel has any. This *must* be FALSE for - * subquery RTEs. - * - * inFromCl marks those range variables that are listed in the FROM clause. - * In SQL, the query can only refer to range variables listed in the - * FROM clause, but POSTQUEL allows you to refer to tables not listed, - * in which case a range table entry will be generated. We still support - * this POSTQUEL feature, although there is some doubt whether it's - * convenient or merely confusing. The flag is needed since an - * implicitly-added RTE shouldn't change the namespace for unqualified - * column names processed later, and it also shouldn't affect the - * expansion of '*'. - * - * checkForRead, checkForWrite, and checkAsUser control run-time access - * permissions checks. A rel will be checked for read or write access - * (or both, or neither) per checkForRead and checkForWrite. If - * checkAsUser is not InvalidOid, then do the permissions checks using - * the access rights of that user, not the current effective user ID. - * (This allows rules to act as setuid gateways.) - *-------------------- +/* ---------------------- + * SET CONSTRAINTS Statement + * ---------------------- */ -typedef struct RangeTblEntry +typedef struct ConstraintsSetStmt { NodeTag type; + List *constraints; /* List of names as Value strings */ + bool deferred; +} ConstraintsSetStmt; - /* - * Fields valid for a plain relation RTE (else NULL/zero): - */ - char *relname; /* real name of the relation */ - Oid relid; /* OID of the relation */ - - /* - * Fields valid for a subquery RTE (else NULL): - */ - Query *subquery; /* the sub-query */ - - /* - * Fields valid in all RTEs: - */ - Attr *alias; /* user-written alias clause, if any */ - Attr *eref; /* expanded reference names */ - bool inh; /* inheritance requested? */ - bool inFromCl; /* present in FROM clause */ - bool checkForRead; /* check rel for read access */ - bool checkForWrite; /* check rel for write access */ - Oid checkAsUser; /* if not zero, check access as this user */ -} RangeTblEntry; - -/* - * SortClause - - * representation of ORDER BY clauses - * - * tleSortGroupRef must match ressortgroupref of exactly one Resdom of the - * associated targetlist; that is the expression to be sorted (or grouped) by. - * sortop is the OID of the ordering operator. - * - * SortClauses are also used to identify Resdoms that we will do a "Unique" - * filter step on (for SELECT DISTINCT and SELECT DISTINCT ON). The - * distinctClause list is simply a copy of the relevant members of the - * sortClause list. Note that distinctClause can be a subset of sortClause, - * but cannot have members not present in sortClause; and the members that - * do appear must be in the same order as in sortClause. +/* ---------------------- + * REINDEX Statement + * ---------------------- */ -typedef struct SortClause +typedef struct ReindexStmt { NodeTag type; - Index tleSortGroupRef; /* reference into targetlist */ - Oid sortop; /* the sort operator to use */ -} SortClause; - -/* - * GroupClause - - * representation of GROUP BY clauses - * - * GroupClause is exactly like SortClause except for the nodetag value - * (it's probably not even really necessary to have two different - * nodetags...). We have routines that operate interchangeably on both. - */ -typedef SortClause GroupClause; + int reindexType; /* INDEX|TABLE|DATABASE */ + const char *name; /* name to reindex */ + bool force; + bool all; +} ReindexStmt; #endif /* PARSENODES_H */