mirror of
https://github.com/postgres/postgres.git
synced 2025-08-25 20:23:07 +03:00
pgindent run on all C files. Java run to follow. initdb/regression
tests pass.
This commit is contained in:
@@ -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.203 2001/10/23 17:39:02 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.204 2001/10/25 05:49:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -77,15 +77,15 @@ static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
|
||||
static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
|
||||
static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt);
|
||||
static void transformColumnDefinition(ParseState *pstate,
|
||||
CreateStmtContext *cxt,
|
||||
ColumnDef *column);
|
||||
CreateStmtContext *cxt,
|
||||
ColumnDef *column);
|
||||
static void transformTableConstraint(ParseState *pstate,
|
||||
CreateStmtContext *cxt,
|
||||
Constraint *constraint);
|
||||
CreateStmtContext *cxt,
|
||||
Constraint *constraint);
|
||||
static void transformIndexConstraints(ParseState *pstate,
|
||||
CreateStmtContext *cxt);
|
||||
CreateStmtContext *cxt);
|
||||
static void transformFKConstraints(ParseState *pstate,
|
||||
CreateStmtContext *cxt);
|
||||
CreateStmtContext *cxt);
|
||||
static Node *transformTypeRefs(ParseState *pstate, Node *stmt);
|
||||
|
||||
static void transformTypeRefsList(ParseState *pstate, List *l);
|
||||
@@ -97,7 +97,7 @@ static void transformColumnType(ParseState *pstate, ColumnDef *column);
|
||||
static void transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid);
|
||||
static void transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid);
|
||||
static bool relationHasPrimaryKey(char *relname);
|
||||
static Oid transformFkeyGetColType(CreateStmtContext *cxt, char *colname);
|
||||
static Oid transformFkeyGetColType(CreateStmtContext *cxt, char *colname);
|
||||
static void release_pstate_resources(ParseState *pstate);
|
||||
static FromExpr *makeFromExpr(List *fromlist, Node *quals);
|
||||
|
||||
@@ -170,7 +170,6 @@ transformStmt(ParseState *pstate, Node *parseTree)
|
||||
|
||||
switch (nodeTag(parseTree))
|
||||
{
|
||||
|
||||
/*
|
||||
* Non-optimizable statements
|
||||
*/
|
||||
@@ -197,8 +196,8 @@ transformStmt(ParseState *pstate, Node *parseTree)
|
||||
* insert these into the actual query tree. - thomas
|
||||
* 2000-03-08
|
||||
*
|
||||
* Outer loop is over targetlist to make it easier to
|
||||
* skip junk targetlist entries.
|
||||
* Outer loop is over targetlist to make it easier to skip
|
||||
* junk targetlist entries.
|
||||
*/
|
||||
if (n->aliases != NIL)
|
||||
{
|
||||
@@ -214,14 +213,15 @@ transformStmt(ParseState *pstate, Node *parseTree)
|
||||
Assert(IsA(te, TargetEntry));
|
||||
rd = te->resdom;
|
||||
Assert(IsA(rd, Resdom));
|
||||
if (rd->resjunk) /* junk columns don't get aliases */
|
||||
if (rd->resjunk) /* junk columns don't get
|
||||
* aliases */
|
||||
continue;
|
||||
id = (Ident *) lfirst(aliaslist);
|
||||
Assert(IsA(id, Ident));
|
||||
rd->resname = pstrdup(id->name);
|
||||
aliaslist = lnext(aliaslist);
|
||||
if (aliaslist == NIL)
|
||||
break; /* done assigning aliases */
|
||||
break; /* done assigning aliases */
|
||||
}
|
||||
|
||||
if (aliaslist != NIL)
|
||||
@@ -466,7 +466,6 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* For INSERT ... VALUES, transform the given list of values to
|
||||
* form a targetlist for the INSERT.
|
||||
@@ -548,7 +547,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
|
||||
te = makeTargetEntry(makeResdom(attrno,
|
||||
thisatt->atttypid,
|
||||
thisatt->atttypmod,
|
||||
pstrdup(NameStr(thisatt->attname)),
|
||||
pstrdup(NameStr(thisatt->attname)),
|
||||
false),
|
||||
stringToNode(defval[ndef].adbin));
|
||||
qry->targetList = lappend(qry->targetList, te);
|
||||
@@ -828,16 +827,16 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
CreateSeqStmt *sequence;
|
||||
|
||||
/*
|
||||
* Create appropriate constraints for SERIAL. We do
|
||||
* this in full, rather than shortcutting, so that we
|
||||
* will detect any conflicting constraints the user
|
||||
* wrote (like a different DEFAULT).
|
||||
* Create appropriate constraints for SERIAL. We do this in full,
|
||||
* rather than shortcutting, so that we will detect any
|
||||
* conflicting constraints the user wrote (like a different
|
||||
* DEFAULT).
|
||||
*/
|
||||
sname = makeObjectName(cxt->relname, column->colname, "seq");
|
||||
|
||||
/*
|
||||
* Create an expression tree representing the function
|
||||
* call nextval('"sequencename"')
|
||||
* Create an expression tree representing the function call
|
||||
* nextval('"sequencename"')
|
||||
*/
|
||||
qstring = palloc(strlen(sname) + 2 + 1);
|
||||
sprintf(qstring, "\"%s\"", sname);
|
||||
@@ -860,7 +859,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
|
||||
constraint = makeNode(Constraint);
|
||||
constraint->contype = CONSTR_UNIQUE;
|
||||
constraint->name = NULL; /* assign later */
|
||||
constraint->name = NULL; /* assign later */
|
||||
column->constraints = lappend(column->constraints, constraint);
|
||||
|
||||
constraint = makeNode(Constraint);
|
||||
@@ -868,9 +867,9 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
column->constraints = lappend(column->constraints, constraint);
|
||||
|
||||
/*
|
||||
* Build a CREATE SEQUENCE command to create the
|
||||
* sequence object, and add it to the list of things
|
||||
* to be done before this CREATE/ALTER TABLE.
|
||||
* Build a CREATE SEQUENCE command to create the sequence object,
|
||||
* and add it to the list of things to be done before this
|
||||
* CREATE/ALTER TABLE.
|
||||
*/
|
||||
sequence = makeNode(CreateSeqStmt);
|
||||
sequence->seqname = pstrdup(sname);
|
||||
@@ -878,7 +877,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
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->seqname, cxt->relname, column->colname);
|
||||
|
||||
cxt->blist = lappend(cxt->blist, sequence);
|
||||
}
|
||||
@@ -893,10 +892,9 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
|
||||
constraint = lfirst(clist);
|
||||
|
||||
/*
|
||||
* If this column constraint is a FOREIGN KEY
|
||||
* constraint, then we fill in the current attributes
|
||||
* name and throw it into the list of FK constraints
|
||||
* to be processed later.
|
||||
* If this column constraint is a FOREIGN KEY constraint, then we
|
||||
* fill in the current attributes name and throw it into the list
|
||||
* of FK constraints to be processed later.
|
||||
*/
|
||||
if (IsA(constraint, FkConstraint))
|
||||
{
|
||||
@@ -1041,9 +1039,9 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
List *indexlist = NIL;
|
||||
|
||||
/*
|
||||
* Run through the constraints that need to generate an index.
|
||||
* For PRIMARY KEY, mark each column as NOT NULL and create an index.
|
||||
* For UNIQUE, create an index as for PRIMARY KEY, but do not insist on
|
||||
* Run through the constraints that need to generate an index. For
|
||||
* PRIMARY KEY, mark each column as NOT NULL and create an index. For
|
||||
* UNIQUE, create an index as for PRIMARY KEY, but do not insist on
|
||||
* NOT NULL.
|
||||
*/
|
||||
foreach(listptr, cxt->ixconstraints)
|
||||
@@ -1083,8 +1081,8 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
index->whereClause = NULL;
|
||||
|
||||
/*
|
||||
* Make sure referenced keys exist. If we are making a
|
||||
* PRIMARY KEY index, also make sure they are NOT NULL.
|
||||
* Make sure referenced keys exist. If we are making a PRIMARY
|
||||
* KEY index, also make sure they are NOT NULL.
|
||||
*/
|
||||
foreach(keys, constraint->keys)
|
||||
{
|
||||
@@ -1112,9 +1110,9 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
else if (SystemAttributeByName(key->name, cxt->hasoids) != NULL)
|
||||
{
|
||||
/*
|
||||
* column will be a system column in the new table,
|
||||
* so accept it. System columns can't ever be null,
|
||||
* so no need to worry about PRIMARY/NOT NULL constraint.
|
||||
* column will be a system column in the new table, so
|
||||
* accept it. System columns can't ever be null, so no
|
||||
* need to worry about PRIMARY/NOT NULL constraint.
|
||||
*/
|
||||
found = true;
|
||||
}
|
||||
@@ -1181,6 +1179,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
if (HeapTupleIsValid(atttuple))
|
||||
{
|
||||
found = true;
|
||||
|
||||
/*
|
||||
* We require pre-existing column to be already marked
|
||||
* NOT NULL.
|
||||
@@ -1275,8 +1274,8 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
* Finally, select unique names for all not-previously-named indices,
|
||||
* and display notice messages.
|
||||
*
|
||||
* XXX in ALTER TABLE case, we fail to consider name collisions
|
||||
* against pre-existing indexes.
|
||||
* XXX in ALTER TABLE case, we fail to consider name collisions against
|
||||
* pre-existing indexes.
|
||||
*/
|
||||
foreach(indexlist, cxt->alist)
|
||||
{
|
||||
@@ -1307,9 +1306,9 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
List *fk_attr;
|
||||
List *pk_attr;
|
||||
Ident *id;
|
||||
Oid pktypoid[INDEX_MAX_KEYS];
|
||||
Oid fktypoid[INDEX_MAX_KEYS];
|
||||
int i;
|
||||
Oid pktypoid[INDEX_MAX_KEYS];
|
||||
Oid fktypoid[INDEX_MAX_KEYS];
|
||||
int i;
|
||||
|
||||
if (cxt->fkconstraints == NIL)
|
||||
return;
|
||||
@@ -1320,7 +1319,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
foreach(fkclist, cxt->fkconstraints)
|
||||
{
|
||||
FkConstraint *fkconstraint = (FkConstraint *) lfirst(fkclist);
|
||||
int attnum;
|
||||
int attnum;
|
||||
List *fkattrs;
|
||||
|
||||
/*
|
||||
@@ -1329,12 +1328,12 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
if (fkconstraint->constr_name == NULL)
|
||||
fkconstraint->constr_name = "<unnamed>";
|
||||
|
||||
for (attnum=0; attnum<INDEX_MAX_KEYS; attnum++)
|
||||
for (attnum = 0; attnum < INDEX_MAX_KEYS; attnum++)
|
||||
pktypoid[attnum] = fktypoid[attnum] = InvalidOid;
|
||||
|
||||
/*
|
||||
* Look up the referencing attributes to make sure they exist
|
||||
* (or will exist) in this table, and remember their type OIDs.
|
||||
* Look up the referencing attributes to make sure they exist (or
|
||||
* will exist) in this table, and remember their type OIDs.
|
||||
*/
|
||||
attnum = 0;
|
||||
foreach(fkattrs, fkconstraint->fk_attrs)
|
||||
@@ -1361,7 +1360,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
/* Use the to-be-created primary key */
|
||||
List *attr;
|
||||
|
||||
attnum=0;
|
||||
attnum = 0;
|
||||
foreach(attr, cxt->pkey->indexParams)
|
||||
{
|
||||
IndexElem *ielem = lfirst(attr);
|
||||
@@ -1376,7 +1375,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
elog(ERROR, "Can only have %d keys in a foreign key",
|
||||
INDEX_MAX_KEYS);
|
||||
pktypoid[attnum++] = transformFkeyGetColType(cxt,
|
||||
ielem->name);
|
||||
ielem->name);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1410,7 +1409,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
if (length(ind->indexParams) !=
|
||||
length(fkconstraint->pk_attrs))
|
||||
continue;
|
||||
attnum=0;
|
||||
attnum = 0;
|
||||
foreach(pkattrs, fkconstraint->pk_attrs)
|
||||
{
|
||||
Ident *pkattr = lfirst(pkattrs);
|
||||
@@ -1433,14 +1432,17 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
elog(ERROR, "Can only have %d keys in a foreign key",
|
||||
INDEX_MAX_KEYS);
|
||||
pktypoid[attnum++] = transformFkeyGetColType(cxt,
|
||||
pkattr->name);
|
||||
pkattr->name);
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
/* In ALTER TABLE case, such an index may already exist */
|
||||
/*
|
||||
* In ALTER TABLE case, such an index may already
|
||||
* exist
|
||||
*/
|
||||
if (OidIsValid(cxt->relOid))
|
||||
transformFkeyCheckAttrs(fkconstraint, pktypoid);
|
||||
else
|
||||
@@ -1454,12 +1456,13 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
for (i = 0; i < INDEX_MAX_KEYS && fktypoid[i] != 0; i++)
|
||||
{
|
||||
/*
|
||||
* fktypoid[i] is the foreign key table's i'th element's type oid
|
||||
* pktypoid[i] is the primary key table's i'th element's type oid
|
||||
* We let oper() do our work for us, including elog(ERROR) if the
|
||||
* types don't compare with =
|
||||
* fktypoid[i] is the foreign key table's i'th element's type
|
||||
* oid pktypoid[i] is the primary key table's i'th element's
|
||||
* type oid We let oper() do our work for us, including
|
||||
* elog(ERROR) if the types don't compare with =
|
||||
*/
|
||||
Operator o=oper("=", fktypoid[i], pktypoid[i], false);
|
||||
Operator o = oper("=", fktypoid[i], pktypoid[i], false);
|
||||
|
||||
ReleaseSysCache(o);
|
||||
}
|
||||
|
||||
@@ -1492,7 +1495,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(cxt->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->pktable_name));
|
||||
makeString(fkconstraint->pktable_name));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->match_type));
|
||||
fk_attr = fkconstraint->fk_attrs;
|
||||
@@ -1519,8 +1522,8 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
fkactions = lappend(fkactions, (Node *) fk_trigger);
|
||||
|
||||
/*
|
||||
* Build a CREATE CONSTRAINT TRIGGER statement for the ON
|
||||
* DELETE action fired on the PK table !!!
|
||||
* Build a CREATE CONSTRAINT TRIGGER statement for the ON DELETE
|
||||
* action fired on the PK table !!!
|
||||
*/
|
||||
fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
|
||||
fk_trigger->trigname = fkconstraint->constr_name;
|
||||
@@ -1569,7 +1572,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(cxt->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->pktable_name));
|
||||
makeString(fkconstraint->pktable_name));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->match_type));
|
||||
fk_attr = fkconstraint->fk_attrs;
|
||||
@@ -1591,8 +1594,8 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
fkactions = lappend(fkactions, (Node *) fk_trigger);
|
||||
|
||||
/*
|
||||
* Build a CREATE CONSTRAINT TRIGGER statement for the ON
|
||||
* UPDATE action fired on the PK table !!!
|
||||
* Build a CREATE CONSTRAINT TRIGGER statement for the ON UPDATE
|
||||
* action fired on the PK table !!!
|
||||
*/
|
||||
fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
|
||||
fk_trigger->trigname = fkconstraint->constr_name;
|
||||
@@ -1641,7 +1644,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(cxt->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->pktable_name));
|
||||
makeString(fkconstraint->pktable_name));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->match_type));
|
||||
fk_attr = fkconstraint->fk_attrs;
|
||||
@@ -1664,9 +1667,9 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach completed list of extra actions to cxt->alist. We cannot
|
||||
* do this earlier, because we assume above that cxt->alist still
|
||||
* holds only IndexStmts.
|
||||
* Attach completed list of extra actions to cxt->alist. We cannot do
|
||||
* this earlier, because we assume above that cxt->alist still holds
|
||||
* only IndexStmts.
|
||||
*/
|
||||
cxt->alist = nconc(cxt->alist, fkactions);
|
||||
}
|
||||
@@ -1688,11 +1691,11 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
|
||||
if (stmt->whereClause)
|
||||
{
|
||||
/*
|
||||
* Put the parent table into the rtable so that the WHERE clause can
|
||||
* refer to its fields without qualification. Note that this only
|
||||
* works if the parent table already exists --- so we can't easily
|
||||
* support predicates on indexes created implicitly by CREATE TABLE.
|
||||
* Fortunately, that's not necessary.
|
||||
* Put the parent table into the rtable so that the WHERE clause
|
||||
* can refer to its fields without qualification. Note that this
|
||||
* only works if the parent table already exists --- so we can't
|
||||
* easily support predicates on indexes created implicitly by
|
||||
* CREATE TABLE. Fortunately, that's not necessary.
|
||||
*/
|
||||
rte = addRangeTableEntry(pstate, stmt->relname, NULL, false, true);
|
||||
|
||||
@@ -1849,8 +1852,8 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
|
||||
|
||||
/*
|
||||
* We cannot support utility-statement actions (eg NOTIFY)
|
||||
* with nonempty rule WHERE conditions, because there's no
|
||||
* way to make the utility action execute conditionally.
|
||||
* with nonempty rule WHERE conditions, because there's no way
|
||||
* to make the utility action execute conditionally.
|
||||
*/
|
||||
if (top_subqry->commandType == CMD_UTILITY &&
|
||||
stmt->whereClause != NULL)
|
||||
@@ -2041,7 +2044,8 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
* The tree of set operations is converted into the setOperations field of
|
||||
* the top-level Query.
|
||||
*/
|
||||
static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
static Query *
|
||||
transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
{
|
||||
Query *qry = makeNode(Query);
|
||||
SelectStmt *leftmostSelect;
|
||||
@@ -2481,7 +2485,6 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
||||
|
||||
if (resnode->resjunk)
|
||||
{
|
||||
|
||||
/*
|
||||
* Resjunk nodes need no additional processing, but be sure
|
||||
* they have names and resnos that do not match any target
|
||||
@@ -2518,7 +2521,7 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
|
||||
|
||||
/*
|
||||
* The only subtypes that currently require parse transformation
|
||||
* handling are 'A'dd column and Add 'C'onstraint. These largely
|
||||
* handling are 'A'dd column and Add 'C'onstraint. These largely
|
||||
* re-use code from CREATE TABLE.
|
||||
*/
|
||||
switch (stmt->subtype)
|
||||
@@ -2532,8 +2535,8 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
|
||||
PointerGetDatum(stmt->relname),
|
||||
0, 0, 0);
|
||||
cxt.hasoids = SearchSysCacheExists(ATTNUM,
|
||||
ObjectIdGetDatum(cxt.relOid),
|
||||
Int16GetDatum(ObjectIdAttributeNumber),
|
||||
ObjectIdGetDatum(cxt.relOid),
|
||||
Int16GetDatum(ObjectIdAttributeNumber),
|
||||
0, 0);
|
||||
cxt.columns = NIL;
|
||||
cxt.ckconstraints = NIL;
|
||||
@@ -2564,8 +2567,8 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
|
||||
PointerGetDatum(stmt->relname),
|
||||
0, 0, 0);
|
||||
cxt.hasoids = SearchSysCacheExists(ATTNUM,
|
||||
ObjectIdGetDatum(cxt.relOid),
|
||||
Int16GetDatum(ObjectIdAttributeNumber),
|
||||
ObjectIdGetDatum(cxt.relOid),
|
||||
Int16GetDatum(ObjectIdAttributeNumber),
|
||||
0, 0);
|
||||
cxt.columns = NIL;
|
||||
cxt.ckconstraints = NIL;
|
||||
@@ -2612,48 +2615,46 @@ transformTypeRefs(ParseState *pstate, Node *stmt)
|
||||
switch (nodeTag(stmt))
|
||||
{
|
||||
case T_ProcedureStmt:
|
||||
{
|
||||
ProcedureStmt *ps = (ProcedureStmt *) stmt;
|
||||
{
|
||||
ProcedureStmt *ps = (ProcedureStmt *) stmt;
|
||||
|
||||
transformTypeRefsList(pstate, ps->argTypes);
|
||||
transformTypeRef(pstate, (TypeName *) ps->returnType);
|
||||
transformTypeRefsList(pstate, ps->withClause);
|
||||
}
|
||||
break;
|
||||
transformTypeRefsList(pstate, ps->argTypes);
|
||||
transformTypeRef(pstate, (TypeName *) ps->returnType);
|
||||
transformTypeRefsList(pstate, ps->withClause);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_CommentStmt:
|
||||
{
|
||||
CommentStmt *cs = (CommentStmt *) stmt;
|
||||
{
|
||||
CommentStmt *cs = (CommentStmt *) stmt;
|
||||
|
||||
transformTypeRefsList(pstate, cs->objlist);
|
||||
}
|
||||
break;
|
||||
transformTypeRefsList(pstate, cs->objlist);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_RemoveFuncStmt:
|
||||
{
|
||||
RemoveFuncStmt *rs = (RemoveFuncStmt *) stmt;
|
||||
{
|
||||
RemoveFuncStmt *rs = (RemoveFuncStmt *) stmt;
|
||||
|
||||
transformTypeRefsList(pstate, rs->args);
|
||||
}
|
||||
break;
|
||||
transformTypeRefsList(pstate, rs->args);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_DefineStmt:
|
||||
{
|
||||
DefineStmt *ds = (DefineStmt *) stmt;
|
||||
List *ele;
|
||||
|
||||
foreach(ele, ds->definition)
|
||||
{
|
||||
DefElem *de = (DefElem *) lfirst(ele);
|
||||
DefineStmt *ds = (DefineStmt *) stmt;
|
||||
List *ele;
|
||||
|
||||
if (de->arg != NULL
|
||||
&& IsA(de->arg, TypeName))
|
||||
foreach(ele, ds->definition)
|
||||
{
|
||||
transformTypeRef(pstate, (TypeName *) de->arg);
|
||||
DefElem *de = (DefElem *) lfirst(ele);
|
||||
|
||||
if (de->arg != NULL
|
||||
&& IsA(de->arg, TypeName))
|
||||
transformTypeRef(pstate, (TypeName *) de->arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "Unsupported type %d in transformTypeRefs",
|
||||
@@ -2674,7 +2675,7 @@ transformTypeRefsList(ParseState *pstate, List *l)
|
||||
|
||||
foreach(ele, l)
|
||||
{
|
||||
Node *elem = lfirst(ele);
|
||||
Node *elem = lfirst(ele);
|
||||
|
||||
if (elem && IsA(elem, TypeName))
|
||||
transformTypeRef(pstate, (TypeName *) elem);
|
||||
@@ -2687,16 +2688,16 @@ transformTypeRefsList(ParseState *pstate, List *l)
|
||||
static void
|
||||
transformTypeRef(ParseState *pstate, TypeName *tn)
|
||||
{
|
||||
Attr *att;
|
||||
Node *n;
|
||||
Var *v;
|
||||
char *tyn;
|
||||
Attr *att;
|
||||
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);
|
||||
if (! IsA(n, Var))
|
||||
if (!IsA(n, Var))
|
||||
elog(ERROR, "unsupported expression in %%TYPE");
|
||||
v = (Var *) n;
|
||||
tyn = typeidTypeName(v->vartype);
|
||||
@@ -2841,7 +2842,7 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
|
||||
{
|
||||
/* go through the fkconstraint->pk_attrs list */
|
||||
List *attrl;
|
||||
int attnum = 0;
|
||||
int attnum = 0;
|
||||
|
||||
foreach(attrl, fkconstraint->pk_attrs)
|
||||
{
|
||||
@@ -2893,7 +2894,7 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
|
||||
HeapTuple indexTuple = NULL;
|
||||
Form_pg_index indexStruct = NULL;
|
||||
int i;
|
||||
int attnum=0;
|
||||
int attnum = 0;
|
||||
|
||||
/*
|
||||
* Open the referenced table
|
||||
@@ -3022,7 +3023,7 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
|
||||
|
||||
if (strcmp(col->colname, colname) == 0)
|
||||
{
|
||||
char *buff = TypeNameToInternalName(col->typename);
|
||||
char *buff = TypeNameToInternalName(col->typename);
|
||||
|
||||
result = typenameTypeId(buff);
|
||||
if (!OidIsValid(result))
|
||||
@@ -3231,7 +3232,6 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
|
||||
*/
|
||||
if (typeTypeRelid(ctype) != InvalidOid)
|
||||
{
|
||||
|
||||
/*
|
||||
* (Eventually add in here that the set can only contain one
|
||||
* element.)
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.45 2001/08/09 18:28:17 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.46 2001/10/25 05:49:36 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -240,7 +240,6 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
|
||||
void
|
||||
agg_error(char *caller, char *aggname, Oid basetypeID)
|
||||
{
|
||||
|
||||
/*
|
||||
* basetypeID that is Invalid (zero) means aggregate over all types.
|
||||
* (count)
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.82 2001/08/09 18:28:17 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.83 2001/10/25 05:49:37 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -179,7 +179,7 @@ interpretInhOption(InhOption inhOpt)
|
||||
{
|
||||
switch (inhOpt)
|
||||
{
|
||||
case INH_NO:
|
||||
case INH_NO:
|
||||
return false;
|
||||
case INH_YES:
|
||||
return true;
|
||||
@@ -288,9 +288,9 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars)
|
||||
result = transformExpr(pstate, result, EXPR_COLUMN_FIRST);
|
||||
|
||||
/*
|
||||
* We expect the result to yield bool directly, otherwise complain.
|
||||
* We could try coerce_to_boolean() here, but it seems likely that an
|
||||
* "=" operator that doesn't return bool is wrong anyway.
|
||||
* We expect the result to yield bool directly, otherwise complain. We
|
||||
* could try coerce_to_boolean() here, but it seems likely that an "="
|
||||
* operator that doesn't return bool is wrong anyway.
|
||||
*/
|
||||
if (exprType(result) != BOOLOID)
|
||||
elog(ERROR, "JOIN/USING clause must return type boolean, not type %s",
|
||||
@@ -328,7 +328,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
|
||||
/* This part is just like transformWhereClause() */
|
||||
result = transformExpr(pstate, j->quals, EXPR_COLUMN_FIRST);
|
||||
|
||||
if (! coerce_to_boolean(pstate, &result))
|
||||
if (!coerce_to_boolean(pstate, &result))
|
||||
elog(ERROR, "JOIN/ON clause must return type boolean, not type %s",
|
||||
format_type_be(exprType(result)));
|
||||
|
||||
@@ -608,7 +608,6 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
|
||||
|
||||
if (j->using)
|
||||
{
|
||||
|
||||
/*
|
||||
* JOIN/USING (or NATURAL JOIN, as transformed above).
|
||||
* Transform the list into an explicit ON-condition, and
|
||||
@@ -734,7 +733,6 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
|
||||
*/
|
||||
if (j->alias)
|
||||
{
|
||||
|
||||
/*
|
||||
* If a column alias list is specified, substitute the alias
|
||||
* names into my output-column list
|
||||
@@ -775,7 +773,7 @@ transformWhereClause(ParseState *pstate, Node *clause)
|
||||
|
||||
qual = transformExpr(pstate, clause, EXPR_COLUMN_FIRST);
|
||||
|
||||
if (! coerce_to_boolean(pstate, &qual))
|
||||
if (!coerce_to_boolean(pstate, &qual))
|
||||
elog(ERROR, "WHERE clause must return type boolean, not type %s",
|
||||
format_type_be(exprType(qual)));
|
||||
|
||||
@@ -840,13 +838,12 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
|
||||
* an expression.
|
||||
*----------
|
||||
*/
|
||||
if (IsA(node, Ident) && ((Ident *) node)->indirection == NIL)
|
||||
if (IsA(node, Ident) &&((Ident *) node)->indirection == NIL)
|
||||
{
|
||||
char *name = ((Ident *) node)->name;
|
||||
|
||||
if (clause == GROUP_CLAUSE)
|
||||
{
|
||||
|
||||
/*
|
||||
* In GROUP BY, we must prefer a match against a FROM-clause
|
||||
* column to one against the targetlist. Look to see if there
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.63 2001/10/04 17:52:24 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.64 2001/10/25 05:49:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -47,7 +47,6 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
||||
}
|
||||
else if (inputTypeId == UNKNOWNOID && IsA(node, Const))
|
||||
{
|
||||
|
||||
/*
|
||||
* Input is a string constant with previously undetermined type.
|
||||
* Apply the target type's typinput function to it to produce a
|
||||
@@ -90,7 +89,6 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
||||
}
|
||||
else if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
|
||||
{
|
||||
|
||||
/*
|
||||
* We don't really need to do a conversion, but we do need to
|
||||
* attach a RelabelType node so that the expression will be seen
|
||||
@@ -118,7 +116,6 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* Otherwise, find the appropriate type conversion function
|
||||
* (caller should have determined that there is one), and generate
|
||||
@@ -240,7 +237,7 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
|
||||
oid_array[0] = inputTypeId;
|
||||
|
||||
ftup = SearchSysCache(PROCNAME,
|
||||
PointerGetDatum(typeidTypeName(targetTypeId)),
|
||||
PointerGetDatum(typeidTypeName(targetTypeId)),
|
||||
Int32GetDatum(1),
|
||||
PointerGetDatum(oid_array),
|
||||
0);
|
||||
@@ -324,7 +321,7 @@ coerce_type_typmod(ParseState *pstate, Node *node,
|
||||
* (AND, OR, NOT, etc).
|
||||
*
|
||||
* If successful, update *pnode to be the transformed argument (if any
|
||||
* transformation is needed), and return TRUE. If fail, return FALSE.
|
||||
* transformation is needed), and return TRUE. If fail, return FALSE.
|
||||
* (The caller must check for FALSE and emit a suitable error message.)
|
||||
*/
|
||||
bool
|
||||
@@ -336,7 +333,7 @@ coerce_to_boolean(ParseState *pstate, Node **pnode)
|
||||
if (inputTypeId == BOOLOID)
|
||||
return true; /* no work */
|
||||
targetTypeId = BOOLOID;
|
||||
if (! can_coerce_type(1, &inputTypeId, &targetTypeId))
|
||||
if (!can_coerce_type(1, &inputTypeId, &targetTypeId))
|
||||
return false; /* fail, but let caller choose error msg */
|
||||
*pnode = coerce_type(pstate, *pnode, inputTypeId, targetTypeId, -1);
|
||||
return true;
|
||||
@@ -384,7 +381,6 @@ select_common_type(List *typeids, const char *context)
|
||||
}
|
||||
else if (TypeCategory(ntype) != pcategory)
|
||||
{
|
||||
|
||||
/*
|
||||
* both types in different categories? then not much
|
||||
* hope...
|
||||
@@ -396,7 +392,6 @@ select_common_type(List *typeids, const char *context)
|
||||
&& !IsPreferredType(pcategory, ptype)
|
||||
&& can_coerce_type(1, &ptype, &ntype))
|
||||
{
|
||||
|
||||
/*
|
||||
* new one is preferred and can convert? then take it...
|
||||
*/
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.103 2001/10/08 21:46:59 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.104 2001/10/25 05:49:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -40,11 +40,11 @@ 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);
|
||||
Node *expr, TypeName *typename);
|
||||
static Node *transformAttr(ParseState *pstate, Attr *att, int precedence);
|
||||
static Node *transformIdent(ParseState *pstate, Ident *ident, int precedence);
|
||||
static Node *transformIndirection(ParseState *pstate, Node *basenode,
|
||||
List *indirection);
|
||||
List *indirection);
|
||||
|
||||
|
||||
/*
|
||||
@@ -159,16 +159,18 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
case OP:
|
||||
{
|
||||
/*
|
||||
* Special-case "foo = NULL" and "NULL = foo" for
|
||||
* compatibility with standards-broken products
|
||||
* (like Microsoft's). Turn these into IS NULL exprs.
|
||||
* Special-case "foo = NULL" and "NULL = foo"
|
||||
* for compatibility with standards-broken
|
||||
* products (like Microsoft's). Turn these
|
||||
* into IS NULL exprs.
|
||||
*/
|
||||
if (Transform_null_equals &&
|
||||
strcmp(a->opname, "=") == 0 &&
|
||||
(exprIsNullConstant(a->lexpr) ||
|
||||
exprIsNullConstant(a->rexpr)))
|
||||
{
|
||||
NullTest *n = makeNode(NullTest);
|
||||
NullTest *n = makeNode(NullTest);
|
||||
|
||||
n->nulltesttype = IS_NULL;
|
||||
|
||||
if (exprIsNullConstant(a->lexpr))
|
||||
@@ -183,11 +185,11 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
else
|
||||
{
|
||||
Node *lexpr = transformExpr(pstate,
|
||||
a->lexpr,
|
||||
precedence);
|
||||
a->lexpr,
|
||||
precedence);
|
||||
Node *rexpr = transformExpr(pstate,
|
||||
a->rexpr,
|
||||
precedence);
|
||||
a->rexpr,
|
||||
precedence);
|
||||
|
||||
result = (Node *) make_op(a->opname,
|
||||
lexpr,
|
||||
@@ -205,12 +207,12 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
precedence);
|
||||
Expr *expr = makeNode(Expr);
|
||||
|
||||
if (! coerce_to_boolean(pstate, &lexpr))
|
||||
if (!coerce_to_boolean(pstate, &lexpr))
|
||||
elog(ERROR, "left-hand side of AND is type '%s', not '%s'",
|
||||
format_type_be(exprType(lexpr)),
|
||||
format_type_be(BOOLOID));
|
||||
|
||||
if (! coerce_to_boolean(pstate, &rexpr))
|
||||
if (!coerce_to_boolean(pstate, &rexpr))
|
||||
elog(ERROR, "right-hand side of AND is type '%s', not '%s'",
|
||||
format_type_be(exprType(rexpr)),
|
||||
format_type_be(BOOLOID));
|
||||
@@ -231,12 +233,12 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
precedence);
|
||||
Expr *expr = makeNode(Expr);
|
||||
|
||||
if (! coerce_to_boolean(pstate, &lexpr))
|
||||
if (!coerce_to_boolean(pstate, &lexpr))
|
||||
elog(ERROR, "left-hand side of OR is type '%s', not '%s'",
|
||||
format_type_be(exprType(lexpr)),
|
||||
format_type_be(BOOLOID));
|
||||
|
||||
if (! coerce_to_boolean(pstate, &rexpr))
|
||||
if (!coerce_to_boolean(pstate, &rexpr))
|
||||
elog(ERROR, "right-hand side of OR is type '%s', not '%s'",
|
||||
format_type_be(exprType(rexpr)),
|
||||
format_type_be(BOOLOID));
|
||||
@@ -254,7 +256,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
precedence);
|
||||
Expr *expr = makeNode(Expr);
|
||||
|
||||
if (! coerce_to_boolean(pstate, &rexpr))
|
||||
if (!coerce_to_boolean(pstate, &rexpr))
|
||||
elog(ERROR, "argument to NOT is type '%s', not '%s'",
|
||||
format_type_be(exprType(rexpr)),
|
||||
format_type_be(BOOLOID));
|
||||
@@ -315,7 +317,6 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
|
||||
if (sublink->subLinkType == EXISTS_SUBLINK)
|
||||
{
|
||||
|
||||
/*
|
||||
* EXISTS needs no lefthand or combining operator.
|
||||
* These fields should be NIL already, but make sure.
|
||||
@@ -456,7 +457,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
}
|
||||
neww->expr = transformExpr(pstate, warg, precedence);
|
||||
|
||||
if (! coerce_to_boolean(pstate, &neww->expr))
|
||||
if (!coerce_to_boolean(pstate, &neww->expr))
|
||||
elog(ERROR, "WHEN clause must have a boolean result");
|
||||
|
||||
/*
|
||||
@@ -541,11 +542,11 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
|
||||
case T_BooleanTest:
|
||||
{
|
||||
BooleanTest *b = (BooleanTest *) expr;
|
||||
BooleanTest *b = (BooleanTest *) expr;
|
||||
|
||||
b->arg = transformExpr(pstate, b->arg, precedence);
|
||||
|
||||
if (! coerce_to_boolean(pstate, &b->arg))
|
||||
if (!coerce_to_boolean(pstate, &b->arg))
|
||||
{
|
||||
const char *clausename;
|
||||
|
||||
@@ -572,7 +573,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
default:
|
||||
elog(ERROR, "transformExpr: unexpected booltesttype %d",
|
||||
(int) b->booltesttype);
|
||||
clausename = NULL; /* keep compiler quiet */
|
||||
clausename = NULL; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
elog(ERROR, "Argument of %s must be boolean",
|
||||
@@ -645,7 +646,7 @@ transformIdent(ParseState *pstate, Ident *ident, int precedence)
|
||||
* appear
|
||||
*/
|
||||
if (ident->indirection == NIL &&
|
||||
refnameRangeOrJoinEntry(pstate, ident->name, &sublevels_up) != NULL)
|
||||
refnameRangeOrJoinEntry(pstate, ident->name, &sublevels_up) != NULL)
|
||||
{
|
||||
ident->isRel = TRUE;
|
||||
result = (Node *) ident;
|
||||
@@ -1023,7 +1024,6 @@ TypeNameToInternalName(TypeName *typename)
|
||||
Assert(typename->attrname == NULL);
|
||||
if (typename->arrayBounds != NIL)
|
||||
{
|
||||
|
||||
/*
|
||||
* By convention, the name of an array type is the name of its
|
||||
* element type with "_" prepended.
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.111 2001/10/04 22:06:46 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.112 2001/10/25 05:49:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -106,16 +106,16 @@ ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, int precedence)
|
||||
}
|
||||
|
||||
/*
|
||||
* parse function
|
||||
* parse function
|
||||
*
|
||||
* This code is confusing because the database can accept
|
||||
* relation.column, column.function, or relation.column.function.
|
||||
* 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.
|
||||
* the rest.
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
@@ -146,10 +146,10 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
Expr *expr;
|
||||
|
||||
/*
|
||||
* Most of the rest of the parser just assumes that functions do
|
||||
* not have more than FUNC_MAX_ARGS parameters. We have to test
|
||||
* here to protect against array overruns, etc. Of course, this
|
||||
* may not be a function, but the test doesn't hurt.
|
||||
* Most of the rest of the parser just assumes that functions do not
|
||||
* have more than FUNC_MAX_ARGS parameters. We have to test here to
|
||||
* protect against array overruns, etc. Of course, this may not be a
|
||||
* function, but the test doesn't hurt.
|
||||
*/
|
||||
if (nargs > FUNC_MAX_ARGS)
|
||||
elog(ERROR, "Cannot pass more than %d arguments to a function",
|
||||
@@ -165,15 +165,15 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
/*
|
||||
* 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 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.
|
||||
*/
|
||||
/* 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)
|
||||
if (IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel)
|
||||
{
|
||||
Ident *ident = (Ident *) first_arg;
|
||||
|
||||
@@ -188,7 +188,6 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
}
|
||||
else if (ISCOMPLEX(exprType(first_arg)))
|
||||
{
|
||||
|
||||
/*
|
||||
* Attempt to handle projection of a complex argument. If
|
||||
* ParseComplexProjection can't handle the projection, we have
|
||||
@@ -231,7 +230,7 @@ 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, Ident) &&((Ident *) first_arg)->isRel)
|
||||
elog(ERROR, "Aggregate functions cannot be applied to relation names");
|
||||
could_be_agg = true;
|
||||
}
|
||||
@@ -239,7 +238,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
{
|
||||
/* 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);
|
||||
!(IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel);
|
||||
}
|
||||
|
||||
if (could_be_agg)
|
||||
@@ -295,7 +294,6 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
|
||||
if (must_be_agg)
|
||||
{
|
||||
|
||||
/*
|
||||
* No matching agg, but we had '*' or DISTINCT, so a plain
|
||||
* function could not have been meant.
|
||||
@@ -318,7 +316,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
{
|
||||
Node *arg = lfirst(i);
|
||||
|
||||
if (IsA(arg, Ident) && ((Ident *) arg)->isRel)
|
||||
if (IsA(arg, Ident) &&((Ident *) arg)->isRel)
|
||||
{
|
||||
RangeTblEntry *rte;
|
||||
int vnum;
|
||||
@@ -339,9 +337,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
rte = (RangeTblEntry *) rteorjoin;
|
||||
else if (IsA(rteorjoin, JoinExpr))
|
||||
{
|
||||
|
||||
/*
|
||||
* The relation name refers to a join. We can't support
|
||||
* The relation name refers to a join. We can't support
|
||||
* functions on join tuples (since we don't have a named
|
||||
* type for the join tuples), so error out.
|
||||
*/
|
||||
@@ -360,8 +357,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* There are multiple arguments, so it must be a function
|
||||
* call.
|
||||
* There are multiple arguments, so it must be a
|
||||
* function call.
|
||||
*/
|
||||
elog(ERROR, "Cannot pass result of join %s to a function",
|
||||
refname);
|
||||
@@ -378,24 +375,26 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
vnum = RTERangeTablePosn(pstate, rte, &sublevels_up);
|
||||
|
||||
/*
|
||||
* The parameter to be passed to the function is the whole tuple
|
||||
* from the relation. We build a special VarNode to reflect
|
||||
* this -- it has varno set to the correct range table entry,
|
||||
* but has varattno == 0 to signal that the whole tuple is the
|
||||
* argument. Also, it has typmod set to sizeof(Pointer) to
|
||||
* signal that the runtime representation will be a pointer
|
||||
* not an Oid.
|
||||
* The parameter to be passed to the function is the whole
|
||||
* tuple from the relation. We build a special VarNode to
|
||||
* reflect this -- it has varno set to the correct range table
|
||||
* entry, but has varattno == 0 to signal that the whole tuple
|
||||
* is the argument. Also, it has typmod set to
|
||||
* sizeof(Pointer) to signal that the runtime representation
|
||||
* will be a pointer not an Oid.
|
||||
*/
|
||||
if (rte->relname == NULL)
|
||||
{
|
||||
/*
|
||||
* RTE is a subselect; must fail for lack of a specific type
|
||||
* RTE is a subselect; must fail for lack of a specific
|
||||
* 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)
|
||||
* 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",
|
||||
refname, funcname);
|
||||
@@ -449,14 +448,14 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
}
|
||||
else
|
||||
{
|
||||
FuncDetailCode fdresult;
|
||||
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.
|
||||
* disambiguation for polymorphic functions, handles inheritance,
|
||||
* and returns the funcid and type and set or singleton status of
|
||||
* the function's return value. it also returns the true argument
|
||||
* types to the function.
|
||||
*/
|
||||
fdresult = func_get_detail(funcname, fargs, nargs, oid_array,
|
||||
&funcid, &rettype, &retset,
|
||||
@@ -464,8 +463,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
if (fdresult == FUNCDETAIL_COERCION)
|
||||
{
|
||||
/*
|
||||
* We can do it as a trivial coercion.
|
||||
* coerce_type can handle these cases, so why duplicate code...
|
||||
* 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);
|
||||
@@ -1019,7 +1018,6 @@ func_select_candidate(int nargs,
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* Remember conflict, but keep going (might find
|
||||
* STRING)
|
||||
@@ -1101,7 +1099,7 @@ func_select_candidate(int nargs,
|
||||
* (exact match) is as quick as possible.
|
||||
*
|
||||
* If an exact match isn't found:
|
||||
* 1) check for possible interpretation as a trivial type coercion
|
||||
* 1) check for possible interpretation as a trivial type coercion
|
||||
* 2) get a vector of all possible input arg type arrays constructed
|
||||
* from the superclasses of the original input arg types
|
||||
* 3) get a list of all possible argument type arrays to the function
|
||||
@@ -1145,23 +1143,24 @@ func_get_detail(char *funcname,
|
||||
* that this is really a type-coercion request: a single-argument
|
||||
* function call where the function name is a type name. If so,
|
||||
* and if we can do the coercion trivially (no run-time function
|
||||
* call needed), then go ahead and treat the "function call" as
|
||||
* a coercion. This interpretation needs to be given higher
|
||||
* priority than interpretations involving a type coercion followed
|
||||
* by a function call, otherwise we can produce surprising results.
|
||||
* For example, we want "text(varchar)" to be interpreted as a
|
||||
* trivial coercion, not as "text(name(varchar))" which the code
|
||||
* below this point is entirely capable of selecting.
|
||||
* call needed), then go ahead and treat the "function call" as a
|
||||
* coercion. This interpretation needs to be given higher
|
||||
* priority than interpretations involving a type coercion
|
||||
* followed by a function call, otherwise we can produce
|
||||
* surprising results. For example, we want "text(varchar)" to be
|
||||
* interpreted as a trivial coercion, not as "text(name(varchar))"
|
||||
* which the code below this point is entirely capable of
|
||||
* selecting.
|
||||
*
|
||||
* "Trivial" coercions are ones that involve binary-compatible
|
||||
* types and ones that are coercing a previously-unknown-type
|
||||
* literal constant to a specific type.
|
||||
* "Trivial" coercions are ones that involve binary-compatible types
|
||||
* and ones that are coercing a previously-unknown-type literal
|
||||
* constant to a specific type.
|
||||
*
|
||||
* NB: it's important that this code stays in sync with what
|
||||
* coerce_type can do, because the caller will try to apply
|
||||
* coerce_type if we return FUNCDETAIL_COERCION. If we return
|
||||
* that result for something coerce_type can't handle, we'll
|
||||
* cause infinite recursion between this module and coerce_type!
|
||||
* that result for something coerce_type can't handle, we'll cause
|
||||
* infinite recursion between this module and coerce_type!
|
||||
*/
|
||||
if (nargs == 1)
|
||||
{
|
||||
@@ -1627,7 +1626,6 @@ ParseComplexProjection(ParseState *pstate,
|
||||
}
|
||||
case T_Var:
|
||||
{
|
||||
|
||||
/*
|
||||
* The argument is a set, so this is either a projection
|
||||
* or a function call on this set.
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.55 2001/08/09 18:28:18 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.56 2001/10/25 05:49:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -235,7 +235,7 @@ make_var(ParseState *pstate, RangeTblEntry *rte, int attrno)
|
||||
* forceSlice If true, treat subscript as array slice in all cases
|
||||
* assignFrom NULL for array fetch, else transformed expression for source.
|
||||
*/
|
||||
ArrayRef *
|
||||
ArrayRef *
|
||||
transformArraySubscripts(ParseState *pstate,
|
||||
Node *arrayBase,
|
||||
Oid arrayType,
|
||||
@@ -467,7 +467,7 @@ make_const(Value *value)
|
||||
case T_String:
|
||||
val = DirectFunctionCall1(textin, CStringGetDatum(strVal(value)));
|
||||
|
||||
typeid = UNKNOWNOID;/* will be coerced later */
|
||||
typeid = UNKNOWNOID; /* will be coerced later */
|
||||
typelen = -1; /* variable len */
|
||||
typebyval = false;
|
||||
break;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.50 2001/08/09 18:28:18 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.51 2001/10/25 05:49:40 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -481,7 +481,6 @@ oper_select_candidate(int nargs,
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* Remember conflict, but keep going (might find
|
||||
* STRING)
|
||||
@@ -835,7 +834,6 @@ right_oper(char *op, Oid arg)
|
||||
unary_op_error(op, arg, FALSE);
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* We must run oper_select_candidate even if only one
|
||||
* candidate, otherwise we may falsely return a
|
||||
@@ -892,7 +890,6 @@ left_oper(char *op, Oid arg)
|
||||
unary_op_error(op, arg, TRUE);
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* We must run oper_select_candidate even if only one
|
||||
* candidate, otherwise we may falsely return a
|
||||
@@ -957,11 +954,11 @@ unary_op_error(char *op, Oid arg, bool is_left_op)
|
||||
{
|
||||
if (is_left_op)
|
||||
elog(ERROR, "Unable to identify a prefix operator '%s' for type '%s'"
|
||||
"\n\tYou may need to add parentheses or an explicit cast",
|
||||
"\n\tYou may need to add parentheses or an explicit cast",
|
||||
op, format_type_be(arg));
|
||||
else
|
||||
elog(ERROR, "Unable to identify a postfix operator '%s' for type '%s'"
|
||||
"\n\tYou may need to add parentheses or an explicit cast",
|
||||
"\n\tYou may need to add parentheses or an explicit cast",
|
||||
op, format_type_be(arg));
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.58 2001/10/23 17:39:02 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.59 2001/10/25 05:49:40 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -967,7 +967,7 @@ specialAttNum(char *a)
|
||||
{
|
||||
Form_pg_attribute sysatt;
|
||||
|
||||
sysatt = SystemAttributeByName(a, true /* "oid" will be accepted */);
|
||||
sysatt = SystemAttributeByName(a, true /* "oid" will be accepted */ );
|
||||
if (sysatt != NULL)
|
||||
return sysatt->attnum;
|
||||
return InvalidAttrNumber;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.74 2001/10/08 21:48:51 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.75 2001/10/25 05:49:40 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
static List *ExpandAllTables(ParseState *pstate);
|
||||
static char *FigureColname(Node *node);
|
||||
static int FigureColnameInternal(Node *node, char **name);
|
||||
static int FigureColnameInternal(Node *node, char **name);
|
||||
|
||||
|
||||
/*
|
||||
@@ -57,8 +57,8 @@ transformTargetEntry(ParseState *pstate,
|
||||
if (expr == NULL)
|
||||
expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST);
|
||||
|
||||
if (IsA(expr, Ident) && ((Ident *)expr)->isRel)
|
||||
elog(ERROR,"You can't use relation names alone in the target list, try relation.*.");
|
||||
if (IsA(expr, Ident) &&((Ident *) expr)->isRel)
|
||||
elog(ERROR, "You can't use relation names alone in the target list, try relation.*.");
|
||||
|
||||
type_id = exprType(expr);
|
||||
type_mod = exprTypmod(expr);
|
||||
@@ -104,7 +104,6 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
|
||||
if (att->relname != NULL && strcmp(att->relname, "*") == 0)
|
||||
{
|
||||
|
||||
/*
|
||||
* Target item is a single '*', expand all tables (eg.
|
||||
* SELECT * FROM emp)
|
||||
@@ -115,7 +114,6 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
else if (att->attrs != NIL &&
|
||||
strcmp(strVal(lfirst(att->attrs)), "*") == 0)
|
||||
{
|
||||
|
||||
/*
|
||||
* Target item is relation.*, expand that table (eg.
|
||||
* SELECT emp.*, dname FROM emp, dept)
|
||||
@@ -221,7 +219,6 @@ updateTargetListEntry(ParseState *pstate,
|
||||
|
||||
if (pstate->p_is_insert)
|
||||
{
|
||||
|
||||
/*
|
||||
* The command is INSERT INTO table (arraycol[subscripts]) ...
|
||||
* so there is not really a source array value to work with.
|
||||
@@ -234,7 +231,6 @@ updateTargetListEntry(ParseState *pstate,
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* Build a Var for the array to be updated.
|
||||
*/
|
||||
@@ -253,7 +249,6 @@ updateTargetListEntry(ParseState *pstate,
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* For normal non-subscripted target column, do type checking and
|
||||
* coercion. But accept InvalidOid, which indicates the source is
|
||||
@@ -347,7 +342,6 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
|
||||
|
||||
if (cols == NIL)
|
||||
{
|
||||
|
||||
/*
|
||||
* Generate default column list for INSERT.
|
||||
*/
|
||||
@@ -373,7 +367,6 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* Do initial validation of user-supplied INSERT column list.
|
||||
*/
|
||||
@@ -461,7 +454,7 @@ ExpandAllTables(ParseState *pstate)
|
||||
static char *
|
||||
FigureColname(Node *node)
|
||||
{
|
||||
char *name = NULL;
|
||||
char *name = NULL;
|
||||
|
||||
FigureColnameInternal(node, &name);
|
||||
if (name != NULL)
|
||||
@@ -473,7 +466,7 @@ FigureColname(Node *node)
|
||||
static int
|
||||
FigureColnameInternal(Node *node, char **name)
|
||||
{
|
||||
int strength = 0;
|
||||
int strength = 0;
|
||||
|
||||
if (node == NULL)
|
||||
return strength;
|
||||
@@ -506,7 +499,7 @@ FigureColnameInternal(Node *node, char **name)
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case T_TypeCast:
|
||||
case T_TypeCast:
|
||||
strength = FigureColnameInternal(((TypeCast *) node)->arg,
|
||||
name);
|
||||
if (strength <= 1)
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.36 2001/10/09 04:15:38 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.37 2001/10/25 05:49:40 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -139,7 +139,6 @@ typeTypElem(Type typ)
|
||||
|
||||
return typtup->typelem;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef NOT_USED
|
||||
@@ -153,7 +152,6 @@ typeInfunc(Type typ)
|
||||
|
||||
return typtup->typinput;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef NOT_USED
|
||||
@@ -167,7 +165,6 @@ typeOutfunc(Type typ)
|
||||
|
||||
return typtup->typoutput;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Given a type structure and a string, returns the internal form of
|
||||
@@ -207,7 +204,6 @@ typeidOutfunc(Oid type_id)
|
||||
ReleaseSysCache(typeTuple);
|
||||
return outfunc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* return a type name, given a typeid */
|
||||
@@ -279,12 +275,12 @@ typenameTypeId(char *s)
|
||||
void
|
||||
parseTypeString(const char *str, Oid *type_id, int32 *typmod)
|
||||
{
|
||||
char *buf;
|
||||
List *raw_parsetree_list;
|
||||
char *buf;
|
||||
List *raw_parsetree_list;
|
||||
SelectStmt *stmt;
|
||||
ResTarget *restarget;
|
||||
A_Const *aconst;
|
||||
TypeName *typename;
|
||||
ResTarget *restarget;
|
||||
A_Const *aconst;
|
||||
TypeName *typename;
|
||||
|
||||
buf = (char *) palloc(strlen(str) + 16);
|
||||
sprintf(buf, "SELECT (NULL::%s)", str);
|
||||
|
@@ -14,7 +14,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.49 2001/03/22 03:59:42 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.50 2001/10/25 05:49:40 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
#if defined(FLEX_SCANNER)
|
||||
extern void DeleteBuffer(void);
|
||||
|
||||
#endif /* FLEX_SCANNER */
|
||||
|
||||
char *parseString; /* the char* which holds the string to be
|
||||
|
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/scansup.c,v 1.20 2001/01/24 19:43:03 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/scansup.c,v 1.21 2001/10/25 05:49:40 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -50,7 +50,6 @@ scanstr(char *s)
|
||||
{
|
||||
if (s[i] == '\'')
|
||||
{
|
||||
|
||||
/*
|
||||
* Note: if scanner is working right, unescaped quotes can
|
||||
* only appear in pairs, so there should be another character.
|
||||
|
Reference in New Issue
Block a user