diff options
Diffstat (limited to 'src/backend')
35 files changed, 742 insertions, 584 deletions
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index 4c40ef3c119..8726797524b 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.114 2006/03/05 15:58:20 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.115 2006/03/14 22:48:18 tgl Exp $ * * NOTES * some of the executor utility code such as "ExecTypeFromTL" should be @@ -499,7 +499,7 @@ BuildDescForRelation(List *schema) attname))); TupleDescInitEntry(desc, attnum, attname, - typenameTypeId(entry->typename), + typenameTypeId(NULL, entry->typename), atttypmod, attdim); /* Fill in additional stuff not handled by TupleDescInitEntry */ diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index 054c531a9e7..2f40eca1152 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.78 2006/03/05 15:58:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.79 2006/03/14 22:48:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -171,9 +171,9 @@ AggregateCreate(const char *aggName, /* handle sortop, if supplied */ if (aggsortopName) - sortop = LookupOperName(aggsortopName, + sortop = LookupOperName(NULL, aggsortopName, aggBaseType, aggBaseType, - false); + false, -1); /* * Everything looks okay. Try to create the pg_proc entry for the diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index c9c19e4ec32..c51c841800e 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_operator.c,v 1.95 2006/03/05 15:58:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_operator.c,v 1.96 2006/03/14 22:48:18 tgl Exp $ * * NOTES * these routines moved here from commands/define.c and somewhat cleaned up. @@ -175,8 +175,9 @@ OperatorLookup(List *operatorName, Oid operatorObjectId; RegProcedure oprcode; - operatorObjectId = LookupOperName(operatorName, leftObjectId, - rightObjectId, true); + operatorObjectId = LookupOperName(NULL, operatorName, + leftObjectId, rightObjectId, + true, -1); if (!OidIsValid(operatorObjectId)) { *defined = false; diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index 99c7d531f91..3c0855238e2 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.32 2006/03/05 15:58:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.33 2006/03/14 22:48:18 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -129,9 +129,9 @@ DefineAggregate(List *names, List *parameters) if (pg_strcasecmp(TypeNameToString(baseType), "ANY") == 0) baseTypeId = ANYOID; else - baseTypeId = typenameTypeId(baseType); + baseTypeId = typenameTypeId(NULL, baseType); - transTypeId = typenameTypeId(transType); + transTypeId = typenameTypeId(NULL, transType); if (get_typtype(transTypeId) == 'p' && transTypeId != ANYARRAYOID && transTypeId != ANYELEMENTOID) @@ -176,7 +176,7 @@ RemoveAggregate(RemoveAggrStmt *stmt) * that the aggregate is to apply to all basetypes (eg, COUNT). */ if (aggType) - basetypeID = typenameTypeId(aggType); + basetypeID = typenameTypeId(NULL, aggType); else basetypeID = ANYOID; @@ -231,7 +231,7 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname) * COUNT). */ if (basetype) - basetypeOid = typenameTypeId(basetype); + basetypeOid = typenameTypeId(NULL, basetype); else basetypeOid = ANYOID; @@ -311,7 +311,7 @@ AlterAggregateOwner(List *name, TypeName *basetype, Oid newOwnerId) * COUNT). */ if (basetype) - basetypeOid = typenameTypeId(basetype); + basetypeOid = typenameTypeId(NULL, basetype); else basetypeOid = ANYOID; diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 8f85dcb8d94..07d82785254 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -7,7 +7,7 @@ * Copyright (c) 1996-2006, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.87 2006/03/05 15:58:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.88 2006/03/14 22:48:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -39,6 +39,7 @@ #include "commands/dbcommands.h" #include "commands/tablespace.h" #include "miscadmin.h" +#include "nodes/makefuncs.h" #include "parser/parse_func.h" #include "parser/parse_oper.h" #include "parser/parse_type.h" @@ -846,13 +847,11 @@ CommentType(List *typename, char *comment) Oid oid; /* XXX a bit of a crock; should accept TypeName in COMMENT syntax */ - tname = makeNode(TypeName); - tname->names = typename; - tname->typmod = -1; + tname = makeTypeNameFromNameList(typename); /* Find the type's oid */ - oid = typenameTypeId(tname); + oid = typenameTypeId(NULL, tname); /* Check object security */ @@ -881,7 +880,7 @@ CommentAggregate(List *aggregate, List *arguments, char *comment) /* First, attempt to determine the base aggregate oid */ if (aggtype) - baseoid = typenameTypeId(aggtype); + baseoid = typenameTypeId(NULL, aggtype); else baseoid = ANYOID; @@ -945,9 +944,11 @@ CommentOperator(List *opername, List *arguments, char *comment) Oid oid; /* Look up the operator */ - oid = LookupOperNameTypeNames(opername, typenode1, typenode2, false); + oid = LookupOperNameTypeNames(NULL, opername, + typenode1, typenode2, + false, -1); - /* Valid user's ability to comment on this operator */ + /* Check user's privilege to comment on this operator */ if (!pg_oper_ownercheck(oid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER, NameListToString(opername)); @@ -1352,19 +1353,8 @@ CommentCast(List *qualname, List *arguments, char *comment) targettype = (TypeName *) linitial(arguments); Assert(IsA(targettype, TypeName)); - sourcetypeid = typenameTypeId(sourcetype); - if (!OidIsValid(sourcetypeid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("source data type %s does not exist", - TypeNameToString(sourcetype)))); - - targettypeid = typenameTypeId(targettype); - if (!OidIsValid(targettypeid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("target data type %s does not exist", - TypeNameToString(targettype)))); + sourcetypeid = typenameTypeId(NULL, sourcetype); + targettypeid = typenameTypeId(NULL, targettype); tuple = SearchSysCache(CASTSOURCETARGET, ObjectIdGetDatum(sourcetypeid), diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c index 15ee606c8de..98cded67cc4 100644 --- a/src/backend/commands/define.c +++ b/src/backend/commands/define.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/define.c,v 1.94 2006/03/05 15:58:24 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/define.c,v 1.95 2006/03/14 22:48:18 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -37,6 +37,7 @@ #include "catalog/namespace.h" #include "commands/defrem.h" +#include "nodes/makefuncs.h" #include "parser/parse_type.h" #include "parser/scansup.h" #include "utils/int8.h" @@ -219,14 +220,8 @@ defGetTypeName(DefElem *def) case T_TypeName: return (TypeName *) def->arg; case T_String: - { - /* Allow quoted typename for backwards compatibility */ - TypeName *n = makeNode(TypeName); - - n->names = list_make1(def->arg); - n->typmod = -1; - return n; - } + /* Allow quoted typename for backwards compatibility */ + return makeTypeNameFromNameList(list_make1(def->arg)); default: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 4a78db5200a..1da1cf66cb3 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.72 2006/03/05 15:58:24 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.73 2006/03/14 22:48:18 tgl Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -75,7 +75,7 @@ compute_return_type(TypeName *returnType, Oid languageOid, { Oid rettype; - rettype = LookupTypeName(returnType); + rettype = LookupTypeName(NULL, returnType); if (OidIsValid(rettype)) { @@ -174,7 +174,7 @@ examine_parameter_list(List *parameters, Oid languageOid, TypeName *t = fp->argType; Oid toid; - toid = LookupTypeName(t); + toid = LookupTypeName(NULL, t); if (OidIsValid(toid)) { if (!get_typisdefined(toid)) @@ -1152,33 +1152,10 @@ CreateCast(CreateCastStmt *stmt) ObjectAddress myself, referenced; - sourcetypeid = LookupTypeName(stmt->sourcetype); - if (!OidIsValid(sourcetypeid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("source data type %s does not exist", - TypeNameToString(stmt->sourcetype)))); - - targettypeid = LookupTypeName(stmt->targettype); - if (!OidIsValid(targettypeid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("target data type %s does not exist", - TypeNameToString(stmt->targettype)))); - - /* No shells, no pseudo-types allowed */ - if (!get_typisdefined(sourcetypeid)) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("source data type %s is only a shell", - TypeNameToString(stmt->sourcetype)))); - - if (!get_typisdefined(targettypeid)) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("target data type %s is only a shell", - TypeNameToString(stmt->targettype)))); + sourcetypeid = typenameTypeId(NULL, stmt->sourcetype); + targettypeid = typenameTypeId(NULL, stmt->targettype); + /* No pseudo-types allowed */ if (get_typtype(sourcetypeid) == 'p') ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), @@ -1400,19 +1377,8 @@ DropCast(DropCastStmt *stmt) HeapTuple tuple; ObjectAddress object; - sourcetypeid = LookupTypeName(stmt->sourcetype); - if (!OidIsValid(sourcetypeid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("source data type %s does not exist", - TypeNameToString(stmt->sourcetype)))); - - targettypeid = LookupTypeName(stmt->targettype); - if (!OidIsValid(targettypeid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("target data type %s does not exist", - TypeNameToString(stmt->targettype)))); + sourcetypeid = typenameTypeId(NULL, stmt->sourcetype); + targettypeid = typenameTypeId(NULL, stmt->targettype); tuple = SearchSysCache(CASTSOURCETARGET, ObjectIdGetDatum(sourcetypeid), diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index 7aa941262bf..d66c403e515 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.42 2006/03/05 15:58:24 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.43 2006/03/14 22:48:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -144,7 +144,7 @@ DefineOpClass(CreateOpClassStmt *stmt) errmsg("must be superuser to create an operator class"))); /* Look up the datatype */ - typeoid = typenameTypeId(stmt->datatype); + typeoid = typenameTypeId(NULL, stmt->datatype); #ifdef NOT_USED /* XXX this is unnecessary given the superuser check above */ @@ -185,16 +185,16 @@ DefineOpClass(CreateOpClassStmt *stmt) TypeName *typeName1 = (TypeName *) linitial(item->args); TypeName *typeName2 = (TypeName *) lsecond(item->args); - operOid = LookupOperNameTypeNames(item->name, - typeName1, - typeName2, - false); + operOid = LookupOperNameTypeNames(NULL, item->name, + typeName1, typeName2, + false, -1); } else { /* Default to binary op on input datatype */ - operOid = LookupOperName(item->name, typeoid, typeoid, - false); + operOid = LookupOperName(NULL, item->name, + typeoid, typeoid, + false, -1); } #ifdef NOT_USED @@ -246,7 +246,7 @@ DefineOpClass(CreateOpClassStmt *stmt) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("storage type specified more than once"))); - storageoid = typenameTypeId(item->storedtype); + storageoid = typenameTypeId(NULL, item->storedtype); #ifdef NOT_USED /* XXX this is unnecessary given the superuser check above */ diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c index e835aa94c1b..c40dbf9d821 100644 --- a/src/backend/commands/operatorcmds.c +++ b/src/backend/commands/operatorcmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.28 2006/03/05 15:58:24 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.29 2006/03/14 22:48:18 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -152,9 +152,9 @@ DefineOperator(List *names, List *parameters) /* Transform type names to type OIDs */ if (typeName1) - typeId1 = typenameTypeId(typeName1); + typeId1 = typenameTypeId(NULL, typeName1); if (typeName2) - typeId2 = typenameTypeId(typeName2); + typeId2 = typenameTypeId(NULL, typeName2); /* * If any of the mergejoin support operators were given, then canMerge is @@ -210,8 +210,9 @@ RemoveOperator(RemoveOperStmt *stmt) HeapTuple tup; ObjectAddress object; - operOid = LookupOperNameTypeNames(operatorName, typeName1, typeName2, - false); + operOid = LookupOperNameTypeNames(NULL, operatorName, + typeName1, typeName2, + false, -1); tup = SearchSysCache(OPEROID, ObjectIdGetDatum(operOid), @@ -286,8 +287,9 @@ AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2, rel = heap_open(OperatorRelationId, RowExclusiveLock); - operOid = LookupOperNameTypeNames(name, typeName1, typeName2, - false); + operOid = LookupOperNameTypeNames(NULL, name, + typeName1, typeName2, + false, -1); AlterOperatorOwner_internal(rel, operOid, newOwnerId); diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index c171d8bfdc3..73d532da4a5 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.39 2006/03/05 15:58:24 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.40 2006/03/14 22:48:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -121,7 +121,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt) List *querytree_list; ListCell *querytree_item; - querytree_list = parse_analyze(parsetree, NULL, 0); + querytree_list = parse_analyze(parsetree, NULL, NULL, 0); foreach(querytree_item, querytree_list) { diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 2d6d1928639..5638f4fe9b7 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.128 2006/03/05 15:58:24 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.129 2006/03/14 22:48:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,7 @@ #include "commands/tablecmds.h" #include "commands/sequence.h" #include "miscadmin.h" +#include "nodes/makefuncs.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/resowner.h" @@ -112,16 +113,8 @@ DefineSequence(CreateSeqStmt *seq) stmt->tableElts = NIL; for (i = SEQ_COL_FIRSTCOL; i <= SEQ_COL_LASTCOL; i++) { - ColumnDef *coldef; - TypeName *typnam; + ColumnDef *coldef = makeNode(ColumnDef); - typnam = makeNode(TypeName); - typnam->setof = FALSE; - typnam->arrayBounds = NIL; - typnam->typmod = -1; - - coldef = makeNode(ColumnDef); - coldef->typename = typnam; coldef->inhcount = 0; coldef->is_local = true; coldef->is_not_null = true; @@ -135,48 +128,48 @@ DefineSequence(CreateSeqStmt *seq) switch (i) { case SEQ_COL_NAME: - typnam->typeid = NAMEOID; + coldef->typename = makeTypeNameFromOid(NAMEOID, -1); coldef->colname = "sequence_name"; namestrcpy(&name, seq->sequence->relname); value[i - 1] = NameGetDatum(&name); break; case SEQ_COL_LASTVAL: - typnam->typeid = INT8OID; + coldef->typename = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "last_value"; value[i - 1] = Int64GetDatumFast(new.last_value); break; case SEQ_COL_INCBY: - typnam->typeid = INT8OID; + coldef->typename = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "increment_by"; value[i - 1] = Int64GetDatumFast(new.increment_by); break; case SEQ_COL_MAXVALUE: - typnam->typeid = INT8OID; + coldef->typename = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "max_value"; value[i - 1] = Int64GetDatumFast(new.max_value); break; case SEQ_COL_MINVALUE: - typnam->typeid = INT8OID; + coldef->typename = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "min_value"; value[i - 1] = Int64GetDatumFast(new.min_value); break; case SEQ_COL_CACHE: - typnam->typeid = INT8OID; + coldef->typename = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "cache_value"; value[i - 1] = Int64GetDatumFast(new.cache_value); break; case SEQ_COL_LOG: - typnam->typeid = INT8OID; + coldef->typename = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "log_cnt"; value[i - 1] = Int64GetDatum((int64) 1); break; case SEQ_COL_CYCLE: - typnam->typeid = BOOLOID; + coldef->typename = makeTypeNameFromOid(BOOLOID, -1); coldef->colname = "is_cycled"; value[i - 1] = BoolGetDatum(new.is_cycled); break; case SEQ_COL_CALLED: - typnam->typeid = BOOLOID; + coldef->typename = makeTypeNameFromOid(BOOLOID, -1); coldef->colname = "is_called"; value[i - 1] = BoolGetDatum(false); break; diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index c484c148c25..6483578e808 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.180 2006/03/05 15:58:24 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.181 2006/03/14 22:48:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -867,7 +867,6 @@ MergeAttributes(List *schema, List *supers, bool istemp, char *attributeName = NameStr(attribute->attname); int exist_attno; ColumnDef *def; - TypeName *typename; /* * Ignore dropped columns in the parent. @@ -897,7 +896,7 @@ MergeAttributes(List *schema, List *supers, bool istemp, (errmsg("merging multiple inherited definitions of column \"%s\"", attributeName))); def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1); - if (typenameTypeId(def->typename) != attribute->atttypid || + if (typenameTypeId(NULL, def->typename) != attribute->atttypid || def->typename->typmod != attribute->atttypmod) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), @@ -919,10 +918,8 @@ MergeAttributes(List *schema, List *supers, bool istemp, */ def = makeNode(ColumnDef); def->colname = pstrdup(attributeName); - typename = makeNode(TypeName); - typename->typeid = attribute->atttypid; - typename->typmod = attribute->atttypmod; - def->typename = typename; + def->typename = makeTypeNameFromOid(attribute->atttypid, + attribute->atttypmod); def->inhcount = 1; def->is_local = false; def->is_not_null = attribute->attnotnull; @@ -1041,7 +1038,7 @@ MergeAttributes(List *schema, List *supers, bool istemp, (errmsg("merging column \"%s\" with inherited definition", attributeName))); def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1); - if (typenameTypeId(def->typename) != typenameTypeId(newdef->typename) || + if (typenameTypeId(NULL, def->typename) != typenameTypeId(NULL, newdef->typename) || def->typename->typmod != newdef->typename->typmod) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), @@ -2955,7 +2952,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel, Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple); /* Okay if child matches by type */ - if (typenameTypeId(colDef->typename) != childatt->atttypid || + if (typenameTypeId(NULL, colDef->typename) != childatt->atttypid || colDef->typename->typmod != childatt->atttypmod) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), @@ -3009,7 +3006,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel, MaxHeapAttributeNumber))); i = minattnum + 1; - typeTuple = typenameType(colDef->typename); + typeTuple = typenameType(NULL, colDef->typename); tform = (Form_pg_type) GETSTRUCT(typeTuple); typeOid = HeapTupleGetOid(typeTuple); @@ -3991,8 +3988,9 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, * the right answer from the test below on opclass membership unless * we select the proper operator.) */ - Operator o = oper(list_make1(makeString("=")), - pktypoid[i], fktypoid[i], true); + Operator o = oper(NULL, list_make1(makeString("=")), + pktypoid[i], fktypoid[i], + true, -1); if (o == NULL) ereport(ERROR, @@ -4773,12 +4771,7 @@ ATPrepAlterColumnType(List **wqueue, colName))); /* Look up the target type */ - targettype = LookupTypeName(typename); - if (!OidIsValid(targettype)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type \"%s\" does not exist", - TypeNameToString(typename)))); + targettype = typenameTypeId(NULL, typename); /* make sure datatype is legal for a column */ CheckAttributeType(colName, targettype); @@ -4904,7 +4897,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, colName))); /* Look up the target type (should not fail, since prep found it) */ - typeTuple = typenameType(typename); + typeTuple = typenameType(NULL, typename); tform = (Form_pg_type) GETSTRUCT(typeTuple); targettype = HeapTupleGetOid(typeTuple); @@ -5265,7 +5258,7 @@ ATPostAlterTypeParse(char *cmd, List **wqueue) Node *parsetree = (Node *) lfirst(list_item); querytree_list = list_concat(querytree_list, - parse_analyze(parsetree, NULL, 0)); + parse_analyze(parsetree, cmd, NULL, 0)); } /* diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 933f76c12d5..83143496dbc 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.88 2006/03/05 15:58:25 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.89 2006/03/14 22:48:18 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -47,7 +47,7 @@ #include "executor/executor.h" #include "miscadmin.h" #include "nodes/execnodes.h" -#include "nodes/nodes.h" +#include "nodes/makefuncs.h" #include "optimizer/clauses.h" #include "optimizer/planmain.h" #include "optimizer/var.h" @@ -80,7 +80,7 @@ static Oid findTypeReceiveFunction(List *procname, Oid typeOid); static Oid findTypeSendFunction(List *procname, Oid typeOid); static Oid findTypeAnalyzeFunction(List *procname, Oid typeOid); static List *get_rels_with_domain(Oid domainOid, LOCKMODE lockmode); -static void domainOwnerCheck(HeapTuple tup, TypeName *typename); +static void checkDomainOwner(HeapTuple tup, TypeName *typename); static char *domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, int typMod, Constraint *constr, @@ -196,7 +196,7 @@ DefineType(List *names, List *parameters) } else if (pg_strcasecmp(defel->defname, "element") == 0) { - elemType = typenameTypeId(defGetTypeName(defel)); + elemType = typenameTypeId(NULL, defGetTypeName(defel)); /* disallow arrays of pseudotypes */ if (get_typtype(elemType) == 'p') ereport(ERROR, @@ -445,13 +445,10 @@ RemoveType(List *names, DropBehavior behavior, bool missing_ok) ObjectAddress object; /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeNode(TypeName); - typename->names = names; - typename->typmod = -1; - typename->arrayBounds = NIL; + typename = makeTypeNameFromNameList(names); /* Use LookupTypeName here so that shell types can be removed. */ - typeoid = LookupTypeName(typename); + typeoid = LookupTypeName(NULL, typename); if (!OidIsValid(typeoid)) { if (!missing_ok) @@ -586,7 +583,7 @@ DefineDomain(CreateDomainStmt *stmt) /* * Look up the base type. */ - typeTup = typenameType(stmt->typename); + typeTup = typenameType(NULL, stmt->typename); baseType = (Form_pg_type) GETSTRUCT(typeTup); basetypeoid = HeapTupleGetOid(typeTup); @@ -840,13 +837,10 @@ RemoveDomain(List *names, DropBehavior behavior, bool missing_ok) ObjectAddress object; /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeNode(TypeName); - typename->names = names; - typename->typmod = -1; - typename->arrayBounds = NIL; + typename = makeTypeNameFromNameList(names); /* Use LookupTypeName here so that shell types can be removed. */ - typeoid = LookupTypeName(typename); + typeoid = LookupTypeName(NULL, typename); if (!OidIsValid(typeoid)) { if (!missing_ok) @@ -1172,39 +1166,27 @@ AlterDomainDefault(List *names, Node *defaultRaw) Form_pg_type typTup; /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeNode(TypeName); - typename->names = names; - typename->typmod = -1; - typename->arrayBounds = NIL; + typename = makeTypeNameFromNameList(names); + domainoid = typenameTypeId(NULL, typename); - /* Lock the domain in the type table */ + /* Look up the domain in the type table */ rel = heap_open(TypeRelationId, RowExclusiveLock); - /* Use LookupTypeName here so that shell types can be removed. */ - domainoid = LookupTypeName(typename); - if (!OidIsValid(domainoid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type \"%s\" does not exist", - TypeNameToString(typename)))); - tup = SearchSysCacheCopy(TYPEOID, ObjectIdGetDatum(domainoid), 0, 0, 0); if (!HeapTupleIsValid(tup)) elog(ERROR, "cache lookup failed for type %u", domainoid); + typTup = (Form_pg_type) GETSTRUCT(tup); - /* Doesn't return if user isn't allowed to alter the domain */ - domainOwnerCheck(tup, typename); + /* Check it's a domain and check user has permission for ALTER DOMAIN */ + checkDomainOwner(tup, typename); /* Setup new tuple */ MemSet(new_record, (Datum) 0, sizeof(new_record)); MemSet(new_record_nulls, ' ', sizeof(new_record_nulls)); MemSet(new_record_repl, ' ', sizeof(new_record_repl)); - /* Useful later */ - typTup = (Form_pg_type) GETSTRUCT(tup); - /* Store the new default, if null then skip this step */ if (defaultRaw) { @@ -1295,22 +1277,12 @@ AlterDomainNotNull(List *names, bool notNull) Form_pg_type typTup; /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeNode(TypeName); - typename->names = names; - typename->typmod = -1; - typename->arrayBounds = NIL; + typename = makeTypeNameFromNameList(names); + domainoid = typenameTypeId(NULL, typename); - /* Lock the type table */ + /* Look up the domain in the type table */ typrel = heap_open(TypeRelationId, RowExclusiveLock); - /* Use LookupTypeName here so that shell types can be found (why?). */ - domainoid = LookupTypeName(typename); - if (!OidIsValid(domainoid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type \"%s\" does not exist", - TypeNameToString(typename)))); - tup = SearchSysCacheCopy(TYPEOID, ObjectIdGetDatum(domainoid), 0, 0, 0); @@ -1318,8 +1290,8 @@ AlterDomainNotNull(List *names, bool notNull) elog(ERROR, "cache lookup failed for type %u", domainoid); typTup = (Form_pg_type) GETSTRUCT(tup); - /* Doesn't return if user isn't allowed to alter the domain */ - domainOwnerCheck(tup, typename); + /* Check it's a domain and check user has permission for ALTER DOMAIN */ + checkDomainOwner(tup, typename); /* Is the domain already set to the desired constraint? */ if (typTup->typnotnull == notNull) @@ -1394,7 +1366,8 @@ AlterDomainNotNull(List *names, bool notNull) * Implements the ALTER DOMAIN DROP CONSTRAINT statement */ void -AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior behavior) +AlterDomainDropConstraint(List *names, const char *constrName, + DropBehavior behavior) { TypeName *typename; Oid domainoid; @@ -1406,30 +1379,20 @@ AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior beha HeapTuple contup; /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeNode(TypeName); - typename->names = names; - typename->typmod = -1; - typename->arrayBounds = NIL; + typename = makeTypeNameFromNameList(names); + domainoid = typenameTypeId(NULL, typename); - /* Lock the type table */ + /* Look up the domain in the type table */ rel = heap_open(TypeRelationId, RowExclusiveLock); - /* Use LookupTypeName here so that shell types can be removed. */ - domainoid = LookupTypeName(typename); - if (!OidIsValid(domainoid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type \"%s\" does not exist", - TypeNameToString(typename)))); - tup = SearchSysCacheCopy(TYPEOID, ObjectIdGetDatum(domainoid), 0, 0, 0); if (!HeapTupleIsValid(tup)) elog(ERROR, "cache lookup failed for type %u", domainoid); - /* Doesn't return if user isn't allowed to alter the domain */ - domainOwnerCheck(tup, typename); + /* Check it's a domain and check user has permission for ALTER DOMAIN */ + checkDomainOwner(tup, typename); /* Grab an appropriate lock on the pg_constraint relation */ conrel = heap_open(ConstraintRelationId, RowExclusiveLock); @@ -1491,22 +1454,12 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) Constraint *constr; /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeNode(TypeName); - typename->names = names; - typename->typmod = -1; - typename->arrayBounds = NIL; + typename = makeTypeNameFromNameList(names); + domainoid = typenameTypeId(NULL, typename); - /* Lock the type table */ + /* Look up the domain in the type table */ typrel = heap_open(TypeRelationId, RowExclusiveLock); - /* Use LookupTypeName here so that shell types can be found (why?). */ - domainoid = LookupTypeName(typename); - if (!OidIsValid(domainoid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type \"%s\" does not exist", - TypeNameToString(typename)))); - tup = SearchSysCacheCopy(TYPEOID, ObjectIdGetDatum(domainoid), 0, 0, 0); @@ -1514,8 +1467,8 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) elog(ERROR, "cache lookup failed for type %u", domainoid); typTup = (Form_pg_type) GETSTRUCT(tup); - /* Doesn't return if user isn't allowed to alter the domain */ - domainOwnerCheck(tup, typename); + /* Check it's a domain and check user has permission for ALTER DOMAIN */ + checkDomainOwner(tup, typename); /* Check for unsupported constraint types */ if (IsA(newConstraint, FkConstraint)) @@ -1782,14 +1735,13 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode) } /* - * domainOwnerCheck + * checkDomainOwner * - * Throw an error if the current user doesn't have permission to modify - * the domain in an ALTER DOMAIN statement, or if the type isn't actually - * a domain. + * Check that the type is actually a domain and that the current user + * has permission to do ALTER DOMAIN on it. Throw an error if not. */ static void -domainOwnerCheck(HeapTuple tup, TypeName *typename) +checkDomainOwner(HeapTuple tup, TypeName *typename) { Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup); @@ -2079,22 +2031,19 @@ AlterTypeOwner(List *names, Oid newOwnerId) AclResult aclresult; /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeNode(TypeName); - typename->names = names; - typename->typmod = -1; - typename->arrayBounds = NIL; - - /* Lock the type table */ - rel = heap_open(TypeRelationId, RowExclusiveLock); + typename = makeTypeNameFromNameList(names); - /* Use LookupTypeName here so that shell types can be processed (why?) */ - typeOid = LookupTypeName(typename); + /* Use LookupTypeName here so that shell types can be processed */ + typeOid = LookupTypeName(NULL, typename); if (!OidIsValid(typeOid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type \"%s\" does not exist", TypeNameToString(typename)))); + /* Look up the type in the type table */ + rel = heap_open(TypeRelationId, RowExclusiveLock); + tup = SearchSysCacheCopy(TYPEOID, ObjectIdGetDatum(typeOid), 0, 0, 0); @@ -2206,19 +2155,9 @@ AlterTypeNamespace(List *names, const char *newschema) Oid typeOid; Oid nspOid; - /* get type OID */ - typename = makeNode(TypeName); - typename->names = names; - typename->typmod = -1; - typename->arrayBounds = NIL; - - typeOid = LookupTypeName(typename); - - if (!OidIsValid(typeOid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type \"%s\" does not exist", - TypeNameToString(typename)))); + /* Make a TypeName so we can use standard type lookup machinery */ + typename = makeTypeNameFromNameList(names); + typeOid = typenameTypeId(NULL, typename); /* check permissions on type */ if (!pg_type_ownercheck(typeOid, GetUserId())) diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index bdecdad247b..490e0aa3519 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.93 2006/03/05 15:58:25 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.94 2006/03/14 22:48:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -114,14 +114,10 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace) if (!tle->resjunk) { ColumnDef *def = makeNode(ColumnDef); - TypeName *typename = makeNode(TypeName); def->colname = pstrdup(tle->resname); - - typename->typeid = exprType((Node *) tle->expr); - typename->typmod = exprTypmod((Node *) tle->expr); - def->typename = typename; - + def->typename = makeTypeNameFromOid(exprType((Node *) tle->expr), + exprTypmod((Node *) tle->expr)); def->inhcount = 0; def->is_local = true; def->is_not_null = false; diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 2f0d73caf78..183bc89b020 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.148 2006/03/05 15:58:26 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.149 2006/03/14 22:48:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1282,7 +1282,7 @@ _SPI_prepare_plan(const char *src, _SPI_plan *plan) Node *parsetree = (Node *) lfirst(list_item); List *query_list; - query_list = pg_analyze_and_rewrite(parsetree, argtypes, nargs); + query_list = pg_analyze_and_rewrite(parsetree, src, argtypes, nargs); query_list_list = lappend(query_list_list, query_list); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index f37daaf3a6f..b38efcdec8b 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 - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.329 2006/03/05 15:58:27 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.330 2006/03/14 22:48:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1418,6 +1418,7 @@ _copyAExpr(A_Expr *from) COPY_NODE_FIELD(name); COPY_NODE_FIELD(lexpr); COPY_NODE_FIELD(rexpr); + COPY_SCALAR_FIELD(location); return newnode; } @@ -1428,6 +1429,7 @@ _copyColumnRef(ColumnRef *from) ColumnRef *newnode = makeNode(ColumnRef); COPY_NODE_FIELD(fields); + COPY_SCALAR_FIELD(location); return newnode; } @@ -1482,6 +1484,7 @@ _copyFuncCall(FuncCall *from) COPY_NODE_FIELD(args); COPY_SCALAR_FIELD(agg_star); COPY_SCALAR_FIELD(agg_distinct); + COPY_SCALAR_FIELD(location); return newnode; } @@ -1532,6 +1535,7 @@ _copyTypeName(TypeName *from) COPY_SCALAR_FIELD(pct_type); COPY_SCALAR_FIELD(typmod); COPY_NODE_FIELD(arrayBounds); + COPY_SCALAR_FIELD(location); return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 757acd9fb91..0275b01c28e 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.265 2006/03/05 15:58:27 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.266 2006/03/14 22:48:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1540,6 +1540,7 @@ _equalAExpr(A_Expr *a, A_Expr *b) COMPARE_NODE_FIELD(name); COMPARE_NODE_FIELD(lexpr); COMPARE_NODE_FIELD(rexpr); + COMPARE_SCALAR_FIELD(location); return true; } @@ -1548,6 +1549,7 @@ static bool _equalColumnRef(ColumnRef *a, ColumnRef *b) { COMPARE_NODE_FIELD(fields); + COMPARE_SCALAR_FIELD(location); return true; } @@ -1577,6 +1579,7 @@ _equalFuncCall(FuncCall *a, FuncCall *b) COMPARE_NODE_FIELD(args); COMPARE_SCALAR_FIELD(agg_star); COMPARE_SCALAR_FIELD(agg_distinct); + COMPARE_SCALAR_FIELD(location); return true; } @@ -1619,6 +1622,7 @@ _equalTypeName(TypeName *a, TypeName *b) COMPARE_SCALAR_FIELD(pct_type); COMPARE_SCALAR_FIELD(typmod); COMPARE_NODE_FIELD(arrayBounds); + COMPARE_SCALAR_FIELD(location); return true; } diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index f69b6e6244b..784dd57831d 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.49 2006/03/05 15:58:27 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.50 2006/03/14 22:48:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,7 +25,8 @@ * makes an A_Expr node */ A_Expr * -makeA_Expr(A_Expr_Kind kind, List *name, Node *lexpr, Node *rexpr) +makeA_Expr(A_Expr_Kind kind, List *name, + Node *lexpr, Node *rexpr, int location) { A_Expr *a = makeNode(A_Expr); @@ -33,6 +34,7 @@ makeA_Expr(A_Expr_Kind kind, List *name, Node *lexpr, Node *rexpr) a->name = name; a->lexpr = lexpr; a->rexpr = rexpr; + a->location = location; return a; } @@ -42,7 +44,7 @@ makeA_Expr(A_Expr_Kind kind, List *name, Node *lexpr, Node *rexpr) */ A_Expr * makeSimpleA_Expr(A_Expr_Kind kind, const char *name, - Node *lexpr, Node *rexpr) + Node *lexpr, Node *rexpr, int location) { A_Expr *a = makeNode(A_Expr); @@ -50,6 +52,7 @@ makeSimpleA_Expr(A_Expr_Kind kind, const char *name, a->name = list_make1(makeString((char *) name)); a->lexpr = lexpr; a->rexpr = rexpr; + a->location = location; return a; } @@ -253,6 +256,8 @@ makeRangeVar(char *schemaname, char *relname) /* * makeTypeName - * build a TypeName node for an unqualified name. + * + * typmod is defaulted, but can be changed later by caller. */ TypeName * makeTypeName(char *typnam) @@ -261,6 +266,39 @@ makeTypeName(char *typnam) n->names = list_make1(makeString(typnam)); n->typmod = -1; + n->location = -1; + return n; +} + +/* + * makeTypeNameFromNameList - + * build a TypeName node for a String list representing a qualified name. + * + * typmod is defaulted, but can be changed later by caller. + */ +TypeName * +makeTypeNameFromNameList(List *names) +{ + TypeName *n = makeNode(TypeName); + + n->names = names; + n->typmod = -1; + n->location = -1; + return n; +} + +/* + * makeTypeNameFromOid - + * build a TypeName node to represent a type already known by OID. + */ +TypeName * +makeTypeNameFromOid(Oid typeid, int32 typmod) +{ + TypeName *n = makeNode(TypeName); + + n->typeid = typeid; + n->typmod = typmod; + n->location = -1; return n; } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 7bb20628c60..ef87fedbc21 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.269 2006/03/05 15:58:27 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.270 2006/03/14 22:48:19 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -1400,6 +1400,7 @@ _outFuncCall(StringInfo str, FuncCall *node) WRITE_NODE_FIELD(args); WRITE_BOOL_FIELD(agg_star); WRITE_BOOL_FIELD(agg_distinct); + WRITE_INT_FIELD(location); } static void @@ -1449,6 +1450,7 @@ _outTypeName(StringInfo str, TypeName *node) WRITE_BOOL_FIELD(pct_type); WRITE_INT_FIELD(typmod); WRITE_NODE_FIELD(arrayBounds); + /* location is deliberately not stored */ } static void @@ -1648,6 +1650,7 @@ _outAExpr(StringInfo str, A_Expr *node) WRITE_NODE_FIELD(lexpr); WRITE_NODE_FIELD(rexpr); + WRITE_INT_FIELD(location); } static void @@ -1687,6 +1690,7 @@ _outColumnRef(StringInfo str, ColumnRef *node) WRITE_NODE_TYPE("COLUMNREF"); WRITE_NODE_FIELD(fields); + WRITE_INT_FIELD(location); } static void diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 2733db62b3a..c7490a9567c 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.185 2006/03/05 15:58:28 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.186 2006/03/14 22:48:19 tgl Exp $ * * NOTES * Path and Plan nodes do not have any readfuncs support, because we @@ -893,6 +893,8 @@ _readTypeName(void) READ_BOOL_FIELD(pct_type); READ_INT_FIELD(typmod); READ_NODE_FIELD(arrayBounds); + /* location is deliberately not stored */ + local_node->location = -1; READ_DONE(); } diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index d980cde06bc..1c04a8784d2 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.116 2006/03/07 01:00:15 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.117 2006/03/14 22:48:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -992,8 +992,9 @@ process_implied_equality(PlannerInfo *root, */ ltype = exprType(item1); rtype = exprType(item2); - eq_operator = compatible_oper(list_make1(makeString("=")), - ltype, rtype, true); + eq_operator = compatible_oper(NULL, list_make1(makeString("=")), + ltype, rtype, + true, -1); if (!HeapTupleIsValid(eq_operator)) { /* diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 37d693b9950..aa21dfdac95 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.209 2006/03/05 15:58:31 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.210 2006/03/14 22:48:19 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -2637,7 +2637,7 @@ inline_function(Oid funcid, Oid result_type, List *args, if (list_length(raw_parsetree_list) != 1) goto fail; - querytree_list = parse_analyze(linitial(raw_parsetree_list), + querytree_list = parse_analyze(linitial(raw_parsetree_list), src, argtypes, funcform->pronargs); if (list_length(querytree_list) != 1) diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 645a740be0e..1c4dc363034 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.330 2006/03/05 15:58:32 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.331 2006/03/14 22:48:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -146,6 +146,9 @@ static bool check_parameter_resolution_walker(Node *node, * parse_analyze * Analyze a raw parse tree and transform it to Query form. * + * If available, pass the source text from which the raw parse tree was + * generated; it's OK to pass NULL if this is not available. + * * Optionally, information about $n parameter types can be supplied. * References to $n indexes not defined by paramTypes[] are disallowed. * @@ -155,11 +158,13 @@ static bool check_parameter_resolution_walker(Node *node, * a dummy CMD_UTILITY Query node. */ List * -parse_analyze(Node *parseTree, Oid *paramTypes, int numParams) +parse_analyze(Node *parseTree, const char *sourceText, + Oid *paramTypes, int numParams) { ParseState *pstate = make_parsestate(NULL); List *result; + pstate->p_sourcetext = sourceText; pstate->p_paramtypes = paramTypes; pstate->p_numparams = numParams; pstate->p_variableparams = false; @@ -179,11 +184,13 @@ parse_analyze(Node *parseTree, Oid *paramTypes, int numParams) * be modified or enlarged (via repalloc). */ List * -parse_analyze_varparams(Node *parseTree, Oid **paramTypes, int *numParams) +parse_analyze_varparams(Node *parseTree, const char *sourceText, + Oid **paramTypes, int *numParams) { ParseState *pstate = make_parsestate(NULL); List *result; + pstate->p_sourcetext = sourceText; pstate->p_paramtypes = *paramTypes; pstate->p_numparams = *numParams; pstate->p_variableparams = true; @@ -921,6 +928,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, funccallnode->args = list_make1(snamenode); funccallnode->agg_star = false; funccallnode->agg_distinct = false; + funccallnode->location = -1; constraint = makeNode(Constraint); constraint->contype = CONSTR_DEFAULT; @@ -1097,7 +1105,6 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1]; char *attributeName = NameStr(attribute->attname); ColumnDef *def; - TypeName *typename; /* * Ignore dropped columns in the parent. @@ -1113,10 +1120,8 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, */ def = makeNode(ColumnDef); def->colname = pstrdup(attributeName); - typename = makeNode(TypeName); - typename->typeid = attribute->atttypid; - typename->typmod = attribute->atttypmod; - def->typename = typename; + def->typename = makeTypeNameFromOid(attribute->atttypid, + attribute->atttypmod); def->inhcount = 0; def->is_local = false; def->is_not_null = attribute->attnotnull; @@ -2608,7 +2613,7 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt) foreach(l, stmt->argtypes) { TypeName *tn = lfirst(l); - Oid toid = typenameTypeId(tn); + Oid toid = typenameTypeId(pstate, tn); argtoids[i++] = toid; } @@ -2621,6 +2626,7 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt) * from context. */ queries = parse_analyze_varparams((Node *) stmt->query, + pstate->p_sourcetext, &argtoids, &nargs); /* @@ -3029,7 +3035,7 @@ transformColumnType(ParseState *pstate, ColumnDef *column) /* * All we really need to do here is verify that the type is valid. */ - Type ctype = typenameType(column->typename); + Type ctype = typenameType(pstate, column->typename); ReleaseSysCache(ctype); } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index c86a6888f20..acaddb13651 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.534 2006/03/07 01:00:16 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.535 2006/03/14 22:48:20 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -61,6 +61,10 @@ #include "utils/numeric.h" +/* Location tracking support --- simpler than bison's default */ +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current = Rhs[1]; + extern List *parsetree; /* final parse result is delivered here */ static bool QueryIsRule = FALSE; @@ -72,7 +76,7 @@ static bool QueryIsRule = FALSE; */ /*#define __YYSCLASS*/ -static Node *makeColumnRef(char *relname, List *indirection); +static Node *makeColumnRef(char *relname, List *indirection, int location); static Node *makeTypeCast(Node *arg, TypeName *typename); static Node *makeStringConst(char *str, TypeName *typename); static Node *makeIntConst(int val); @@ -81,7 +85,7 @@ static Node *makeAConst(Value *v); static Node *makeRowNullTest(NullTestType test, RowExpr *row); static DefElem *makeDefElem(char *name, Node *arg); static A_Const *makeBoolAConst(bool state); -static FuncCall *makeOverlaps(List *largs, List *rargs); +static FuncCall *makeOverlaps(List *largs, List *rargs, int location); static void check_qualified_name(List *names); static List *check_func_name(List *names); static List *extractArgTypes(List *parameters); @@ -90,12 +94,13 @@ static void insertSelectOptions(SelectStmt *stmt, List *sortClause, Node *lockingClause, Node *limitOffset, Node *limitCount); static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg); -static Node *doNegate(Node *n); +static Node *doNegate(Node *n, int location); static void doNegateFloat(Value *v); %} %name-prefix="base_yy" +%locations %union { @@ -3705,6 +3710,7 @@ func_type: Typename { $$ = $1; } $$->names = lcons(makeString($1), $2); $$->pct_type = true; $$->typmod = -1; + $$->location = @1; } | SETOF type_name attrs '%' TYPE_P { @@ -3713,6 +3719,7 @@ func_type: Typename { $$ = $1; } $$->pct_type = true; $$->typmod = -1; $$->setof = TRUE; + $$->location = @2; } ; @@ -6053,6 +6060,7 @@ SimpleTypename: $$ = makeNode(TypeName); $$->names = lcons(makeString($1), $2); $$->typmod = -1; + $$->location = @1; } ; @@ -6077,6 +6085,7 @@ GenericType: type_name { $$ = makeTypeName($1); + $$->location = @1; } ; @@ -6540,6 +6549,7 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($5, $1); n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @2; $$ = (Node *) n; } /* @@ -6552,44 +6562,44 @@ a_expr: c_expr { $$ = $1; } * also to b_expr and to the MathOp list above. */ | '+' a_expr %prec UMINUS - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1); } | '-' a_expr %prec UMINUS - { $$ = doNegate($2); } + { $$ = doNegate($2, @1); } | a_expr '+' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2); } | a_expr '-' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2); } | a_expr '*' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2); } | a_expr '/' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2); } | a_expr '%' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2); } | a_expr '^' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2); } | a_expr '<' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2); } | a_expr '>' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); } | a_expr '=' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); } | a_expr qual_Op a_expr %prec Op - { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3); } + { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2); } | qual_Op a_expr %prec Op - { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2); } + { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1); } | a_expr qual_Op %prec POSTFIXOP - { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL); } + { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2); } | a_expr AND a_expr - { $$ = (Node *) makeA_Expr(AEXPR_AND, NIL, $1, $3); } + { $$ = (Node *) makeA_Expr(AEXPR_AND, NIL, $1, $3, @2); } | a_expr OR a_expr - { $$ = (Node *) makeA_Expr(AEXPR_OR, NIL, $1, $3); } + { $$ = (Node *) makeA_Expr(AEXPR_OR, NIL, $1, $3, @2); } | NOT a_expr - { $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, $2); } + { $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, $2, @1); } | a_expr LIKE a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, $3, @2); } | a_expr LIKE a_expr ESCAPE a_expr { FuncCall *n = makeNode(FuncCall); @@ -6597,10 +6607,11 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($3, $5); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, (Node *) n); + n->location = @4; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, (Node *) n, @2); } | a_expr NOT LIKE a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, $4); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, $4, @2); } | a_expr NOT LIKE a_expr ESCAPE a_expr { FuncCall *n = makeNode(FuncCall); @@ -6608,10 +6619,11 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($4, $6); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, (Node *) n); + n->location = @5; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, (Node *) n, @2); } | a_expr ILIKE a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, $3, @2); } | a_expr ILIKE a_expr ESCAPE a_expr { FuncCall *n = makeNode(FuncCall); @@ -6619,10 +6631,11 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($3, $5); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, (Node *) n); + n->location = @4; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, (Node *) n, @2); } | a_expr NOT ILIKE a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, $4); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, $4, @2); } | a_expr NOT ILIKE a_expr ESCAPE a_expr { FuncCall *n = makeNode(FuncCall); @@ -6630,7 +6643,8 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($4, $6); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, (Node *) n); + n->location = @5; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, (Node *) n, @2); } | a_expr SIMILAR TO a_expr %prec SIMILAR @@ -6642,7 +6656,8 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($4, (Node *) c); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n); + n->location = @2; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n, @2); } | a_expr SIMILAR TO a_expr ESCAPE a_expr { @@ -6651,7 +6666,8 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($4, $6); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n); + n->location = @5; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n, @2); } | a_expr NOT SIMILAR TO a_expr %prec SIMILAR { @@ -6662,7 +6678,8 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($5, (Node *) c); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n); + n->location = @5; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2); } | a_expr NOT SIMILAR TO a_expr ESCAPE a_expr { @@ -6671,7 +6688,8 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($5, $7); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n); + n->location = @6; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2); } /* NullTest clause @@ -6733,7 +6751,7 @@ a_expr: c_expr { $$ = $1; } } | row OVERLAPS row { - $$ = (Node *)makeOverlaps($1, $3); + $$ = (Node *)makeOverlaps($1, $3, @2); } | a_expr IS TRUE_P { @@ -6779,54 +6797,63 @@ a_expr: c_expr { $$ = $1; } } | a_expr IS DISTINCT FROM a_expr %prec IS { - $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5); + $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5, @2); } | a_expr IS NOT DISTINCT FROM a_expr %prec IS { $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, - "=", $1, $6)); + "=", $1, $6, @2), + @2); } | a_expr IS OF '(' type_list ')' %prec IS { - $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5); + $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2); } | a_expr IS NOT OF '(' type_list ')' %prec IS { - $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6); + $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2); } | a_expr BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN { $$ = (Node *) makeA_Expr(AEXPR_AND, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4), - (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6)); + (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6, @2), + @2); } | a_expr NOT BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN { $$ = (Node *) makeA_Expr(AEXPR_OR, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5), - (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7)); + (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7, @2), + @2); } | a_expr BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN { $$ = (Node *) makeA_Expr(AEXPR_OR, NIL, (Node *) makeA_Expr(AEXPR_AND, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4), - (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6)), + (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6, @2), + @2), (Node *) makeA_Expr(AEXPR_AND, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $6), - (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $4))); + (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $6, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $4, @2), + @2), + @2); } | a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN { $$ = (Node *) makeA_Expr(AEXPR_AND, NIL, (Node *) makeA_Expr(AEXPR_OR, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5), - (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7)), + (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7, @2), + @2), (Node *) makeA_Expr(AEXPR_OR, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $7), - (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $5))); + (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $7, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $5, @2), + @2), + @2); } | a_expr IN_P in_expr { @@ -6843,7 +6870,7 @@ a_expr: c_expr { $$ = $1; } else { /* generate scalar IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3); + $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3, @2); } } | a_expr NOT IN_P in_expr @@ -6858,12 +6885,12 @@ a_expr: c_expr { $$ = $1; } n->testexpr = $1; n->operName = list_make1(makeString("=")); /* Stick a NOT on top */ - $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, (Node *) n); + $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, (Node *) n, @2); } else { /* generate scalar NOT IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4); + $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4, @2); } } | a_expr subquery_Op sub_type select_with_parens %prec Op @@ -6878,9 +6905,9 @@ a_expr: c_expr { $$ = $1; } | a_expr subquery_Op sub_type '(' a_expr ')' %prec Op { if ($3 == ANY_SUBLINK) - $$ = (Node *) makeA_Expr(AEXPR_OP_ANY, $2, $1, $5); + $$ = (Node *) makeA_Expr(AEXPR_OP_ANY, $2, $1, $5, @2); else - $$ = (Node *) makeA_Expr(AEXPR_OP_ALL, $2, $1, $5); + $$ = (Node *) makeA_Expr(AEXPR_OP_ALL, $2, $1, $5, @2); } | UNIQUE select_with_parens { @@ -6913,49 +6940,49 @@ b_expr: c_expr | b_expr TYPECAST Typename { $$ = makeTypeCast($1, $3); } | '+' b_expr %prec UMINUS - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1); } | '-' b_expr %prec UMINUS - { $$ = doNegate($2); } + { $$ = doNegate($2, @1); } | b_expr '+' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2); } | b_expr '-' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2); } | b_expr '*' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2); } | b_expr '/' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2); } | b_expr '%' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2); } | b_expr '^' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2); } | b_expr '<' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2); } | b_expr '>' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); } | b_expr '=' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); } | b_expr qual_Op b_expr %prec Op - { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3); } + { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2); } | qual_Op b_expr %prec Op - { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2); } + { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1); } | b_expr qual_Op %prec POSTFIXOP - { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL); } + { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2); } | b_expr IS DISTINCT FROM b_expr %prec IS { - $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5); + $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5, @2); } | b_expr IS NOT DISTINCT FROM b_expr %prec IS { $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, - NULL, (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $6)); + NULL, (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $6, @2), @2); } | b_expr IS OF '(' type_list ')' %prec IS { - $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5); + $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2); } | b_expr IS NOT OF '(' type_list ')' %prec IS { - $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6); + $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2); } ; @@ -7052,6 +7079,7 @@ func_expr: func_name '(' ')' n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | func_name '(' expr_list ')' @@ -7061,6 +7089,7 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | func_name '(' ALL expr_list ')' @@ -7074,6 +7103,7 @@ func_expr: func_name '(' ')' * "must be an aggregate", but there's no provision * for that in FuncCall at the moment. */ + n->location = @1; $$ = (Node *)n; } | func_name '(' DISTINCT expr_list ')' @@ -7083,6 +7113,7 @@ func_expr: func_name '(' ')' n->args = $4; n->agg_star = FALSE; n->agg_distinct = TRUE; + n->location = @1; $$ = (Node *)n; } | func_name '(' '*' ')' @@ -7108,6 +7139,7 @@ func_expr: func_name '(' ')' n->args = list_make1(star); n->agg_star = TRUE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | CURRENT_DATE @@ -7196,6 +7228,7 @@ func_expr: func_name '(' ')' n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | CURRENT_TIMESTAMP '(' Iconst ')' @@ -7331,6 +7364,7 @@ func_expr: func_name '(' ')' n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | CURRENT_USER @@ -7340,6 +7374,7 @@ func_expr: func_name '(' ')' n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | SESSION_USER @@ -7349,6 +7384,7 @@ func_expr: func_name '(' ')' n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | USER @@ -7358,6 +7394,7 @@ func_expr: func_name '(' ')' n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | CAST '(' a_expr AS Typename ')' @@ -7369,6 +7406,7 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | OVERLAY '(' overlay_list ')' @@ -7383,6 +7421,7 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | POSITION '(' position_list ')' @@ -7393,6 +7432,7 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | SUBSTRING '(' substr_list ')' @@ -7405,6 +7445,7 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | TREAT '(' a_expr AS Typename ')' @@ -7413,7 +7454,7 @@ func_expr: func_name '(' ')' * which is defined to be a subtype of the original expression. * In SQL99, this is intended for use with structured UDTs, * but let's make this a generally useful form allowing stronger - * coersions than are handled by implicit casting. + * coercions than are handled by implicit casting. */ FuncCall *n = makeNode(FuncCall); /* Convert SystemTypeName() to SystemFuncName() even though @@ -7421,6 +7462,9 @@ func_expr: func_name '(' ')' */ n->funcname = SystemFuncName(((Value *)llast($5->names))->val.str); n->args = list_make1($3); + n->agg_star = FALSE; + n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | TRIM '(' BOTH trim_list ')' @@ -7433,6 +7477,7 @@ func_expr: func_name '(' ')' n->args = $4; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | TRIM '(' LEADING trim_list ')' @@ -7442,6 +7487,7 @@ func_expr: func_name '(' ')' n->args = $4; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | TRIM '(' TRAILING trim_list ')' @@ -7451,6 +7497,7 @@ func_expr: func_name '(' ')' n->args = $4; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | TRIM '(' trim_list ')' @@ -7460,6 +7507,7 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | CONVERT '(' a_expr USING any_name ')' @@ -7474,6 +7522,7 @@ func_expr: func_name '(' ')' n->args = list_make2($3, c); n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | CONVERT '(' expr_list ')' @@ -7483,11 +7532,12 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | NULLIF '(' a_expr ',' a_expr ')' { - $$ = (Node *) makeSimpleA_Expr(AEXPR_NULLIF, "=", $3, $5); + $$ = (Node *) makeSimpleA_Expr(AEXPR_NULLIF, "=", $3, $5, @1); } | COALESCE '(' expr_list ')' { @@ -7797,11 +7847,11 @@ case_arg: a_expr { $$ = $1; } */ columnref: relation_name { - $$ = makeColumnRef($1, NIL); + $$ = makeColumnRef($1, NIL, @1); } | relation_name indirection { - $$ = makeColumnRef($1, $2); + $$ = makeColumnRef($1, $2, @1); } ; @@ -7875,6 +7925,7 @@ target_el: a_expr AS ColLabel { ColumnRef *n = makeNode(ColumnRef); n->fields = list_make1(makeString("*")); + n->location = @1; $$ = makeNode(ResTarget); $$->name = NULL; @@ -8585,7 +8636,7 @@ SpecialRuleRelation: %% static Node * -makeColumnRef(char *relname, List *indirection) +makeColumnRef(char *relname, List *indirection, int location) { /* * Generate a ColumnRef node, with an A_Indirection node added if there @@ -8597,6 +8648,7 @@ makeColumnRef(char *relname, List *indirection) int nfields = 0; ListCell *l; + c->location = location; foreach(l, indirection) { if (IsA(lfirst(l), A_Indices)) @@ -8750,9 +8802,9 @@ makeRowNullTest(NullTestType test, RowExpr *row) if (result == NULL) result = (Node *) n; else if (test == IS_NOT_NULL) - result = (Node *) makeA_Expr(AEXPR_OR, NIL, result, (Node *)n); + result = (Node *) makeA_Expr(AEXPR_OR, NIL, result, (Node *)n, -1); else - result = (Node *) makeA_Expr(AEXPR_AND, NIL, result, (Node *)n); + result = (Node *) makeA_Expr(AEXPR_AND, NIL, result, (Node *)n, -1); } if (result == NULL) @@ -8768,9 +8820,10 @@ makeRowNullTest(NullTestType test, RowExpr *row) * Create and populate a FuncCall node to support the OVERLAPS operator. */ static FuncCall * -makeOverlaps(List *largs, List *rargs) +makeOverlaps(List *largs, List *rargs, int location) { FuncCall *n = makeNode(FuncCall); + n->funcname = SystemFuncName("overlaps"); if (list_length(largs) == 1) largs = lappend(largs, largs); @@ -8787,6 +8840,7 @@ makeOverlaps(List *largs, List *rargs) n->args = list_concat(largs, rargs); n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = location; return n; } @@ -8944,6 +8998,7 @@ SystemTypeName(char *name) n->names = list_make2(makeString("pg_catalog"), makeString(name)); n->typmod = -1; + n->location = -1; return n; } @@ -8987,7 +9042,7 @@ exprIsNullConstant(Node *arg) * until we know what the desired type is. */ static Node * -doNegate(Node *n) +doNegate(Node *n, int location) { if (IsA(n, A_Const)) { @@ -9005,7 +9060,7 @@ doNegate(Node *n) } } - return (Node *) makeSimpleA_Expr(AEXPR_OP, "-", NULL, n); + return (Node *) makeSimpleA_Expr(AEXPR_OP, "-", NULL, n, location); } static void diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index fdc2e41b3aa..4384a4eaab8 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.147 2006/03/05 21:34:34 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.148 2006/03/14 22:48:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -303,7 +303,9 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars) Node *rvar = (Node *) lfirst(rvars); A_Expr *e; - e = makeSimpleA_Expr(AEXPR_OP, "=", copyObject(lvar), copyObject(rvar)); + e = makeSimpleA_Expr(AEXPR_OP, "=", + copyObject(lvar), copyObject(rvar), + -1); if (result == NULL) result = (Node *) e; @@ -311,7 +313,7 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars) { A_Expr *a; - a = makeA_Expr(AEXPR_AND, NIL, result, (Node *) e); + a = makeA_Expr(AEXPR_AND, NIL, result, (Node *) e, -1); result = (Node *) a; } } @@ -1182,6 +1184,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause) list_length(((ColumnRef *) node)->fields) == 1) { char *name = strVal(linitial(((ColumnRef *) node)->fields)); + int location = ((ColumnRef *) node)->location; if (clause == GROUP_CLAUSE) { @@ -1201,7 +1204,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause) * breaks no cases that are legal per spec, and it seems a more * self-consistent behavior. */ - if (colNameToVar(pstate, name, true) != NULL) + if (colNameToVar(pstate, name, true, location) != NULL) name = NULL; } @@ -1225,7 +1228,8 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause) * construct, eg ORDER BY */ errmsg("%s \"%s\" is ambiguous", - clauseText[clause], name))); + clauseText[clause], name), + parser_errposition(pstate, location))); } else target_result = tle; diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index ab4d681fdfd..cae682c9e77 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.190 2006/03/05 15:58:33 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.191 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,18 +57,18 @@ static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m); static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b); static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref); static Node *transformWholeRowRef(ParseState *pstate, char *schemaname, - char *relname); + char *relname, int location); static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b); static Node *transformIndirection(ParseState *pstate, Node *basenode, List *indirection); static Node *typecast_expression(ParseState *pstate, Node *expr, TypeName *typename); static Node *make_row_comparison_op(ParseState *pstate, List *opname, - List *largs, List *rargs); + List *largs, List *rargs, int location); static Node *make_row_distinct_op(ParseState *pstate, List *opname, - RowExpr *lrow, RowExpr *rrow); + RowExpr *lrow, RowExpr *rrow, int location); static Expr *make_distinct_op(ParseState *pstate, List *opname, - Node *ltree, Node *rtree); + Node *ltree, Node *rtree, int location); /* @@ -308,7 +308,8 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection) result = ParseFuncOrColumn(pstate, list_make1(n), list_make1(result), - false, false, true); + false, false, true, + -1); } } /* process trailing subscripts, if any */ @@ -361,7 +362,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) char *name = strVal(linitial(cref->fields)); /* Try to identify as an unqualified column */ - node = colNameToVar(pstate, name, false); + node = colNameToVar(pstate, name, false, cref->location); if (node == NULL) { @@ -391,12 +392,14 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) */ if (refnameRangeTblEntry(pstate, NULL, name, &levels_up) != NULL) - node = transformWholeRowRef(pstate, NULL, name); + node = transformWholeRowRef(pstate, NULL, name, + cref->location); else ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" does not exist", - name))); + name), + parser_errposition(pstate, cref->location))); } break; } @@ -408,12 +411,14 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) /* Whole-row reference? */ if (strcmp(name2, "*") == 0) { - node = transformWholeRowRef(pstate, NULL, name1); + node = transformWholeRowRef(pstate, NULL, name1, + cref->location); break; } /* Try to identify as a once-qualified column */ - node = qualifiedNameToVar(pstate, NULL, name1, name2, true); + node = qualifiedNameToVar(pstate, NULL, name1, name2, true, + cref->location); if (node == NULL) { /* @@ -421,11 +426,13 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) * it as a function call. Here, we will create an * implicit RTE for tables not already entered. */ - node = transformWholeRowRef(pstate, NULL, name1); + node = transformWholeRowRef(pstate, NULL, name1, + cref->location); node = ParseFuncOrColumn(pstate, list_make1(makeString(name2)), list_make1(node), - false, false, true); + false, false, true, + cref->location); } break; } @@ -438,20 +445,24 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) /* Whole-row reference? */ if (strcmp(name3, "*") == 0) { - node = transformWholeRowRef(pstate, name1, name2); + node = transformWholeRowRef(pstate, name1, name2, + cref->location); break; } /* Try to identify as a twice-qualified column */ - node = qualifiedNameToVar(pstate, name1, name2, name3, true); + node = qualifiedNameToVar(pstate, name1, name2, name3, true, + cref->location); if (node == NULL) { /* Try it as a function call */ - node = transformWholeRowRef(pstate, name1, name2); + node = transformWholeRowRef(pstate, name1, name2, + cref->location); node = ParseFuncOrColumn(pstate, list_make1(makeString(name3)), list_make1(node), - false, false, true); + false, false, true, + cref->location); } break; } @@ -469,25 +480,30 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cross-database references are not implemented: %s", - NameListToString(cref->fields)))); + NameListToString(cref->fields)), + parser_errposition(pstate, cref->location))); /* Whole-row reference? */ if (strcmp(name4, "*") == 0) { - node = transformWholeRowRef(pstate, name2, name3); + node = transformWholeRowRef(pstate, name2, name3, + cref->location); break; } /* Try to identify as a twice-qualified column */ - node = qualifiedNameToVar(pstate, name2, name3, name4, true); + node = qualifiedNameToVar(pstate, name2, name3, name4, true, + cref->location); if (node == NULL) { /* Try it as a function call */ - node = transformWholeRowRef(pstate, name2, name3); + node = transformWholeRowRef(pstate, name2, name3, + cref->location); node = ParseFuncOrColumn(pstate, list_make1(makeString(name4)), list_make1(node), - false, false, true); + false, false, true, + cref->location); } break; } @@ -495,7 +511,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper qualified name (too many dotted names): %s", - NameListToString(cref->fields)))); + NameListToString(cref->fields)), + parser_errposition(pstate, cref->location))); node = NULL; /* keep compiler quiet */ break; } @@ -614,7 +631,8 @@ transformAExprOp(ParseState *pstate, A_Expr *a) result = make_row_comparison_op(pstate, a->name, ((RowExpr *) lexpr)->args, - ((RowExpr *) rexpr)->args); + ((RowExpr *) rexpr)->args, + a->location); } else { @@ -625,7 +643,8 @@ transformAExprOp(ParseState *pstate, A_Expr *a) result = (Node *) make_op(pstate, a->name, lexpr, - rexpr); + rexpr, + a->location); } return result; @@ -678,7 +697,8 @@ transformAExprOpAny(ParseState *pstate, A_Expr *a) a->name, true, lexpr, - rexpr); + rexpr, + a->location); } static Node * @@ -691,7 +711,8 @@ transformAExprOpAll(ParseState *pstate, A_Expr *a) a->name, false, lexpr, - rexpr); + rexpr, + a->location); } static Node * @@ -706,7 +727,8 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a) /* "row op row" */ return make_row_distinct_op(pstate, a->name, (RowExpr *) lexpr, - (RowExpr *) rexpr); + (RowExpr *) rexpr, + a->location); } else { @@ -714,7 +736,8 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a) return (Node *) make_distinct_op(pstate, a->name, lexpr, - rexpr); + rexpr, + a->location); } } @@ -728,11 +751,13 @@ transformAExprNullIf(ParseState *pstate, A_Expr *a) result = (Node *) make_op(pstate, a->name, lexpr, - rexpr); + rexpr, + a->location); if (((OpExpr *) result)->opresulttype != BOOLOID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("NULLIF requires = operator to yield boolean"))); + errmsg("NULLIF requires = operator to yield boolean"), + parser_errposition(pstate, a->location))); /* * We rely on NullIfExpr and OpExpr being the same struct @@ -758,7 +783,7 @@ transformAExprOf(ParseState *pstate, A_Expr *a) ltype = exprType(lexpr); foreach(telem, (List *) a->rexpr) { - rtype = LookupTypeName(lfirst(telem)); + rtype = typenameTypeId(pstate, lfirst(telem)); matched = (rtype == ltype); if (matched) break; @@ -864,7 +889,8 @@ transformAExprIn(ParseState *pstate, A_Expr *a) a->name, useOr, lexpr, - (Node *) newa); + (Node *) newa, + a->location); } } @@ -883,17 +909,20 @@ transformAExprIn(ParseState *pstate, A_Expr *a) !IsA(rexpr, RowExpr)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("arguments of row IN must all be row expressions"))); + errmsg("arguments of row IN must all be row expressions"), + parser_errposition(pstate, a->location))); cmp = make_row_comparison_op(pstate, a->name, (List *) copyObject(((RowExpr *) lexpr)->args), - ((RowExpr *) rexpr)->args); + ((RowExpr *) rexpr)->args, + a->location); } else cmp = (Node *) make_op(pstate, a->name, copyObject(lexpr), - rexpr); + rexpr, + a->location); cmp = coerce_to_boolean(pstate, cmp, "IN"); if (result == NULL) @@ -931,7 +960,8 @@ transformFuncCall(ParseState *pstate, FuncCall *fn) targs, fn->agg_star, fn->agg_distinct, - false); + false, + fn->location); } static Node * @@ -994,7 +1024,8 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c) /* shorthand form was specified, so expand... */ warg = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) placeholder, - warg); + warg, + -1); } neww->expr = (Expr *) transformExpr(pstate, warg); @@ -1173,7 +1204,8 @@ transformSubLink(ParseState *pstate, SubLink *sublink) sublink->testexpr = make_row_comparison_op(pstate, sublink->operName, left_list, - right_list); + right_list, + -1); } return result; @@ -1394,7 +1426,8 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b) * a rowtype; either a named composite type, or RECORD. */ static Node * -transformWholeRowRef(ParseState *pstate, char *schemaname, char *relname) +transformWholeRowRef(ParseState *pstate, char *schemaname, char *relname, + int location) { Node *result; RangeTblEntry *rte; @@ -1408,7 +1441,8 @@ transformWholeRowRef(ParseState *pstate, char *schemaname, char *relname) &sublevels_up); if (rte == NULL) - rte = addImplicitRTE(pstate, makeRangeVar(schemaname, relname)); + rte = addImplicitRTE(pstate, makeRangeVar(schemaname, relname), + location); vnum = RTERangeTablePosn(pstate, rte, &sublevels_up); @@ -1877,7 +1911,7 @@ typecast_expression(ParseState *pstate, Node *expr, TypeName *typename) Oid inputType = exprType(expr); Oid targetType; - targetType = typenameTypeId(typename); + targetType = typenameTypeId(pstate, typename); if (inputType == InvalidOid) return expr; /* do nothing if NULL input */ @@ -1891,7 +1925,8 @@ typecast_expression(ParseState *pstate, Node *expr, TypeName *typename) (errcode(ERRCODE_CANNOT_COERCE), errmsg("cannot cast type %s to %s", format_type_be(inputType), - format_type_be(targetType)))); + format_type_be(targetType)), + parser_errposition(pstate, typename->location))); return expr; } @@ -1910,7 +1945,7 @@ typecast_expression(ParseState *pstate, Node *expr, TypeName *typename) */ static Node * make_row_comparison_op(ParseState *pstate, List *opname, - List *largs, List *rargs) + List *largs, List *rargs, int location) { RowCompareExpr *rcexpr; RowCompareType rctype; @@ -1929,7 +1964,8 @@ make_row_comparison_op(ParseState *pstate, List *opname, if (nopers != list_length(rargs)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("unequal number of entries in row expressions"))); + errmsg("unequal number of entries in row expressions"), + parser_errposition(pstate, location))); /* * We can't compare zero-length rows because there is no principled @@ -1938,7 +1974,8 @@ make_row_comparison_op(ParseState *pstate, List *opname, if (nopers == 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot compare rows of zero length"))); + errmsg("cannot compare rows of zero length"), + parser_errposition(pstate, location))); /* * Identify all the pairwise operators, using make_op so that @@ -1951,7 +1988,7 @@ make_row_comparison_op(ParseState *pstate, List *opname, Node *rarg = (Node *) lfirst(r); OpExpr *cmp; - cmp = (OpExpr *) make_op(pstate, opname, larg, rarg); + cmp = (OpExpr *) make_op(pstate, opname, larg, rarg, location); Assert(IsA(cmp, OpExpr)); /* @@ -1964,11 +2001,13 @@ make_row_comparison_op(ParseState *pstate, List *opname, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("row comparison operator must yield type boolean, " "not type %s", - format_type_be(cmp->opresulttype)))); + format_type_be(cmp->opresulttype)), + parser_errposition(pstate, location))); if (expression_returns_set((Node *) cmp)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("row comparison operator must not return a set"))); + errmsg("row comparison operator must not return a set"), + parser_errposition(pstate, location))); opexprs = lappend(opexprs, cmp); } @@ -2021,7 +2060,8 @@ make_row_comparison_op(ParseState *pstate, List *opname, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("could not determine interpretation of row comparison operator %s", strVal(llast(opname))), - errhint("Row comparison operators must be associated with btree operator classes."))); + errhint("Row comparison operators must be associated with btree operator classes."), + parser_errposition(pstate, location))); rctype = 0; /* keep compiler quiet */ break; case BMS_SINGLETON: @@ -2069,7 +2109,8 @@ make_row_comparison_op(ParseState *pstate, List *opname, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("could not determine interpretation of row comparison operator %s", strVal(llast(opname))), - errdetail("There are multiple equally-plausible candidates."))); + errdetail("There are multiple equally-plausible candidates."), + parser_errposition(pstate, location))); break; } } @@ -2120,7 +2161,8 @@ make_row_comparison_op(ParseState *pstate, List *opname, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("could not determine interpretation of row comparison operator %s", strVal(llast(opname))), - errdetail("There are multiple equally-plausible candidates."))); + errdetail("There are multiple equally-plausible candidates."), + parser_errposition(pstate, location))); } /* @@ -2158,7 +2200,8 @@ make_row_comparison_op(ParseState *pstate, List *opname, */ static Node * make_row_distinct_op(ParseState *pstate, List *opname, - RowExpr *lrow, RowExpr *rrow) + RowExpr *lrow, RowExpr *rrow, + int location) { Node *result = NULL; List *largs = lrow->args; @@ -2169,7 +2212,8 @@ make_row_distinct_op(ParseState *pstate, List *opname, if (list_length(largs) != list_length(rargs)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("unequal number of entries in row expressions"))); + errmsg("unequal number of entries in row expressions"), + parser_errposition(pstate, location))); forboth(l, largs, r, rargs) { @@ -2177,7 +2221,7 @@ make_row_distinct_op(ParseState *pstate, List *opname, Node *rarg = (Node *) lfirst(r); Node *cmp; - cmp = (Node *) make_distinct_op(pstate, opname, larg, rarg); + cmp = (Node *) make_distinct_op(pstate, opname, larg, rarg, location); if (result == NULL) result = cmp; else @@ -2198,15 +2242,17 @@ make_row_distinct_op(ParseState *pstate, List *opname, * make the node for an IS DISTINCT FROM operator */ static Expr * -make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree) +make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree, + int location) { Expr *result; - result = make_op(pstate, opname, ltree, rtree); + result = make_op(pstate, opname, ltree, rtree, location); if (((OpExpr *) result)->opresulttype != BOOLOID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("IS DISTINCT FROM requires = operator to yield boolean"))); + errmsg("IS DISTINCT FROM requires = operator to yield boolean"), + parser_errposition(pstate, location))); /* * We rely on DistinctExpr and OpExpr being same struct diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index d6b4307a61a..35e826881fd 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.184 2006/03/05 15:58:33 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.185 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,8 +34,9 @@ static Node *ParseComplexProjection(ParseState *pstate, char *funcname, - Node *first_arg); -static void unknown_attribute(ParseState *pstate, Node *relref, char *attname); + Node *first_arg, int location); +static void unknown_attribute(ParseState *pstate, Node *relref, char *attname, + int location); /* @@ -59,7 +60,8 @@ static void unknown_attribute(ParseState *pstate, Node *relref, char *attname); */ Node * ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, - bool agg_star, bool agg_distinct, bool is_column) + bool agg_star, bool agg_distinct, bool is_column, + int location) { Oid rettype; Oid funcid; @@ -83,7 +85,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, ereport(ERROR, (errcode(ERRCODE_TOO_MANY_ARGUMENTS), errmsg("cannot pass more than %d arguments to a function", - FUNC_MAX_ARGS))); + FUNC_MAX_ARGS), + parser_errposition(pstate, location))); /* * Extract arg type info in preparation for function lookup. @@ -131,7 +134,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, { retval = ParseComplexProjection(pstate, strVal(linitial(funcname)), - first_arg); + first_arg, + location); if (retval) return retval; @@ -174,12 +178,14 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("%s(*) specified, but %s is not an aggregate function", NameListToString(funcname), - NameListToString(funcname)))); + NameListToString(funcname)), + parser_errposition(pstate, location))); if (agg_distinct) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("DISTINCT specified, but %s is not an aggregate function", - NameListToString(funcname)))); + NameListToString(funcname)), + parser_errposition(pstate, location))); } else if (fdresult != FUNCDETAIL_AGGREGATE) { @@ -193,7 +199,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, { Assert(nargs == 1); Assert(list_length(funcname) == 1); - unknown_attribute(pstate, first_arg, strVal(linitial(funcname))); + unknown_attribute(pstate, first_arg, strVal(linitial(funcname)), + location); } /* @@ -206,7 +213,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, func_signature_string(funcname, nargs, actual_arg_types)), errhint("Could not choose a best candidate function. " - "You may need to add explicit type casts."))); + "You may need to add explicit type casts."), + parser_errposition(pstate, location))); else ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), @@ -214,7 +222,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, func_signature_string(funcname, nargs, actual_arg_types)), errhint("No function matches the given name and argument types. " - "You may need to add explicit type casts."))); + "You may need to add explicit type casts."), + parser_errposition(pstate, location))); } /* @@ -262,7 +271,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, if (retset) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("aggregates may not return sets"))); + errmsg("aggregates may not return sets"), + parser_errposition(pstate, location))); } return retval; @@ -726,11 +736,9 @@ func_get_detail(List *funcname, if (nargs == 1 && fargs != NIL) { Oid targetType; - TypeName *tn = makeNode(TypeName); - tn->names = funcname; - tn->typmod = -1; - targetType = LookupTypeName(tn); + targetType = LookupTypeName(NULL, + makeTypeNameFromNameList(funcname)); if (OidIsValid(targetType) && !ISCOMPLEX(targetType)) { @@ -953,7 +961,8 @@ make_fn_arguments(ParseState *pstate, * transformed expression tree. If not, return NULL. */ static Node * -ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg) +ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg, + int location) { TupleDesc tupdesc; int i; @@ -977,7 +986,7 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg) ((Var *) first_arg)->varno, ((Var *) first_arg)->varlevelsup); /* Return a Var if funcname matches a column, else NULL */ - return scanRTEForColumn(pstate, rte, funcname); + return scanRTEForColumn(pstate, rte, funcname, location); } /* @@ -1019,7 +1028,8 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg) * helper routine for delivering "column does not exist" error message */ static void -unknown_attribute(ParseState *pstate, Node *relref, char *attname) +unknown_attribute(ParseState *pstate, Node *relref, char *attname, + int location) { RangeTblEntry *rte; @@ -1033,7 +1043,8 @@ unknown_attribute(ParseState *pstate, Node *relref, char *attname) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column %s.%s does not exist", - rte->eref->aliasname, attname))); + rte->eref->aliasname, attname), + parser_errposition(pstate, location))); } else { @@ -1044,18 +1055,21 @@ unknown_attribute(ParseState *pstate, Node *relref, char *attname) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" not found in data type %s", - attname, format_type_be(relTypeId)))); + attname, format_type_be(relTypeId)), + parser_errposition(pstate, location))); else if (relTypeId == RECORDOID) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("could not identify column \"%s\" in record data type", - attname))); + attname), + parser_errposition(pstate, location))); else ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("column notation .%s applied to type %s, " "which is not a composite type", - attname, format_type_be(relTypeId)))); + attname, format_type_be(relTypeId)), + parser_errposition(pstate, location))); } } @@ -1219,7 +1233,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError) { TypeName *t = (TypeName *) lfirst(args_item); - argoids[i] = LookupTypeName(t); + argoids[i] = LookupTypeName(NULL, t); if (!OidIsValid(argoids[i])) ereport(ERROR, diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index 2ac869c9fcd..23d73a13f25 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -8,13 +8,14 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.91 2006/03/05 15:58:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.92 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "catalog/pg_type.h" +#include "mb/pg_wchar.h" #include "nodes/makefuncs.h" #include "parser/parsetree.h" #include "parser/parse_coerce.h" @@ -44,13 +45,47 @@ make_parsestate(ParseState *parentParseState) pstate->p_next_resno = 1; if (parentParseState) + { + pstate->p_sourcetext = parentParseState->p_sourcetext; pstate->p_variableparams = parentParseState->p_variableparams; + } return pstate; } /* + * parser_errposition + * Report a parse-analysis-time cursor position, if possible. + * + * This is expected to be used within an ereport() call. The return value + * is a dummy (always 0, in fact). + * + * The locations stored in raw parsetrees are byte offsets into the source + * string. We have to convert them to 1-based character indexes for reporting + * to clients. (We do things this way to avoid unnecessary overhead in the + * normal non-error case: computing character indexes would be much more + * expensive than storing token offsets.) + */ +int +parser_errposition(ParseState *pstate, int location) +{ + int pos; + + /* No-op if location was not provided */ + if (location < 0) + return 0; + /* Can't do anything if source text is not available */ + if (pstate == NULL || pstate->p_sourcetext == NULL) + return 0; + /* Convert offset to character number */ + pos = pg_mbstrlen_with_len(pstate->p_sourcetext, location) + 1; + /* And pass it to the ereport mechanism */ + return errposition(pos); +} + + +/* * make_var * Build a Var node for an attribute identified by RTE and attrno */ diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index 2bd65b2e126..e483372e852 100644 --- a/src/backend/parser/parse_oper.c +++ b/src/backend/parser/parse_oper.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.85 2006/03/05 15:58:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.86 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,8 +37,9 @@ static FuncDetailCode oper_select_candidate(int nargs, Oid *operOid); static const char *op_signature_string(List *op, char oprkind, Oid arg1, Oid arg2); -static void op_error(List *op, char oprkind, Oid arg1, Oid arg2, - FuncDetailCode fdresult); +static void op_error(ParseState *pstate, List *op, char oprkind, + Oid arg1, Oid arg2, + FuncDetailCode fdresult, int location); static Expr *make_op_expr(ParseState *pstate, Operator op, Node *ltree, Node *rtree, Oid ltypeId, Oid rtypeId); @@ -56,10 +57,12 @@ static Expr *make_op_expr(ParseState *pstate, Operator op, * namespace search path. * * If the operator is not found, we return InvalidOid if noError is true, - * else raise an error. + * else raise an error. pstate and location are used only to report the + * error position; pass NULL/-1 if not available. */ Oid -LookupOperName(List *opername, Oid oprleft, Oid oprright, bool noError) +LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, + bool noError, int location) { FuncCandidateList clist; char oprkind; @@ -86,7 +89,8 @@ LookupOperName(List *opername, Oid oprleft, Oid oprright, bool noError) (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("operator does not exist: %s", op_signature_string(opername, oprkind, - oprleft, oprright)))); + oprleft, oprright)), + parser_errposition(pstate, location))); return InvalidOid; } @@ -99,8 +103,9 @@ LookupOperName(List *opername, Oid oprleft, Oid oprright, bool noError) * Pass oprleft = NULL for a prefix op, oprright = NULL for a postfix op. */ Oid -LookupOperNameTypeNames(List *opername, TypeName *oprleft, - TypeName *oprright, bool noError) +LookupOperNameTypeNames(ParseState *pstate, List *opername, + TypeName *oprleft, TypeName *oprright, + bool noError, int location) { Oid leftoid, rightoid; @@ -108,27 +113,15 @@ LookupOperNameTypeNames(List *opername, TypeName *oprleft, if (oprleft == NULL) leftoid = InvalidOid; else - { - leftoid = LookupTypeName(oprleft); - if (!OidIsValid(leftoid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type %s does not exist", - TypeNameToString(oprleft)))); - } + leftoid = typenameTypeId(pstate, oprleft); + if (oprright == NULL) rightoid = InvalidOid; else - { - rightoid = LookupTypeName(oprright); - if (!OidIsValid(rightoid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type %s does not exist", - TypeNameToString(oprright)))); - } + rightoid = typenameTypeId(pstate, oprright); - return LookupOperName(opername, leftoid, rightoid, noError); + return LookupOperName(pstate, opername, leftoid, rightoid, + noError, location); } /* @@ -500,13 +493,15 @@ oper_select_candidate(int nargs, * you need an exact- or binary-compatible match; see compatible_oper. * * If no matching operator found, return NULL if noError is true, - * raise an error if it is false. + * raise an error if it is false. pstate and location are used only to report + * the error position; pass NULL/-1 if not available. * * NOTE: on success, the returned object is a syscache entry. The caller * must ReleaseSysCache() the entry when done with it. */ Operator -oper(List *opname, Oid ltypeId, Oid rtypeId, bool noError) +oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, + bool noError, int location) { FuncCandidateList clist; Oid inputOids[2]; @@ -549,7 +544,7 @@ oper(List *opname, Oid ltypeId, Oid rtypeId, bool noError) } if (!HeapTupleIsValid(tup) && !noError) - op_error(opname, 'b', ltypeId, rtypeId, fdresult); + op_error(pstate, opname, 'b', ltypeId, rtypeId, fdresult, location); return (Operator) tup; } @@ -562,13 +557,14 @@ oper(List *opname, Oid ltypeId, Oid rtypeId, bool noError) * are accepted). Otherwise, the semantics are the same. */ Operator -compatible_oper(List *op, Oid arg1, Oid arg2, bool noError) +compatible_oper(ParseState *pstate, List *op, Oid arg1, Oid arg2, + bool noError, int location) { Operator optup; Form_pg_operator opform; /* oper() will find the best available match */ - optup = oper(op, arg1, arg2, noError); + optup = oper(pstate, op, arg1, arg2, noError, location); if (optup == (Operator) NULL) return (Operator) NULL; /* must be noError case */ @@ -585,7 +581,8 @@ compatible_oper(List *op, Oid arg1, Oid arg2, bool noError) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("operator requires run-time type coercion: %s", - op_signature_string(op, 'b', arg1, arg2)))); + op_signature_string(op, 'b', arg1, arg2)), + parser_errposition(pstate, location))); return (Operator) NULL; } @@ -602,7 +599,7 @@ compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError) Operator optup; Oid result; - optup = compatible_oper(op, arg1, arg2, noError); + optup = compatible_oper(NULL, op, arg1, arg2, noError, -1); if (optup != NULL) { result = oprid(optup); @@ -621,13 +618,14 @@ compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError) * you need an exact- or binary-compatible match. * * If no matching operator found, return NULL if noError is true, - * raise an error if it is false. + * raise an error if it is false. pstate and location are used only to report + * the error position; pass NULL/-1 if not available. * * NOTE: on success, the returned object is a syscache entry. The caller * must ReleaseSysCache() the entry when done with it. */ Operator -right_oper(List *op, Oid arg, bool noError) +right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location) { FuncCandidateList clist; Oid operOid = InvalidOid; @@ -669,7 +667,7 @@ right_oper(List *op, Oid arg, bool noError) } if (!HeapTupleIsValid(tup) && !noError) - op_error(op, 'r', arg, InvalidOid, fdresult); + op_error(pstate, op, 'r', arg, InvalidOid, fdresult, location); return (Operator) tup; } @@ -683,13 +681,14 @@ right_oper(List *op, Oid arg, bool noError) * you need an exact- or binary-compatible match. * * If no matching operator found, return NULL if noError is true, - * raise an error if it is false. + * raise an error if it is false. pstate and location are used only to report + * the error position; pass NULL/-1 if not available. * * NOTE: on success, the returned object is a syscache entry. The caller * must ReleaseSysCache() the entry when done with it. */ Operator -left_oper(List *op, Oid arg, bool noError) +left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location) { FuncCandidateList clist; Oid operOid = InvalidOid; @@ -736,7 +735,7 @@ left_oper(List *op, Oid arg, bool noError) } if (!HeapTupleIsValid(tup) && !noError) - op_error(op, 'l', InvalidOid, arg, fdresult); + op_error(pstate, op, 'l', InvalidOid, arg, fdresult, location); return (Operator) tup; } @@ -771,7 +770,9 @@ op_signature_string(List *op, char oprkind, Oid arg1, Oid arg2) * op_error - utility routine to complain about an unresolvable operator */ static void -op_error(List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult) +op_error(ParseState *pstate, List *op, char oprkind, + Oid arg1, Oid arg2, + FuncDetailCode fdresult, int location) { if (fdresult == FUNCDETAIL_MULTIPLE) ereport(ERROR, @@ -779,14 +780,16 @@ op_error(List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult) errmsg("operator is not unique: %s", op_signature_string(op, oprkind, arg1, arg2)), errhint("Could not choose a best candidate operator. " - "You may need to add explicit type casts."))); + "You may need to add explicit type casts."), + parser_errposition(pstate, location))); else ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("operator does not exist: %s", op_signature_string(op, oprkind, arg1, arg2)), errhint("No operator matches the given name and argument type(s). " - "You may need to add explicit type casts."))); + "You may need to add explicit type casts."), + parser_errposition(pstate, location))); } /* @@ -800,7 +803,8 @@ op_error(List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult) * processing is wanted. */ Expr * -make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree) +make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree, + int location) { Oid ltypeId, rtypeId; @@ -813,21 +817,21 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree) /* right operator */ ltypeId = exprType(ltree); rtypeId = InvalidOid; - tup = right_oper(opname, ltypeId, false); + tup = right_oper(pstate, opname, ltypeId, false, location); } else if (ltree == NULL) { /* left operator */ rtypeId = exprType(rtree); ltypeId = InvalidOid; - tup = left_oper(opname, rtypeId, false); + tup = left_oper(pstate, opname, rtypeId, false, location); } else { /* otherwise, binary operator */ ltypeId = exprType(ltree); rtypeId = exprType(rtree); - tup = oper(opname, ltypeId, rtypeId, false); + tup = oper(pstate, opname, ltypeId, rtypeId, false, location); } /* Do typecasting and build the expression tree */ @@ -845,7 +849,8 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree) Expr * make_scalar_array_op(ParseState *pstate, List *opname, bool useOr, - Node *ltree, Node *rtree) + Node *ltree, Node *rtree, + int location) { Oid ltypeId, rtypeId, @@ -875,11 +880,12 @@ make_scalar_array_op(ParseState *pstate, List *opname, if (!OidIsValid(rtypeId)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("op ANY/ALL (array) requires array on right side"))); + errmsg("op ANY/ALL (array) requires array on right side"), + parser_errposition(pstate, location))); } /* Now resolve the operator */ - tup = oper(opname, ltypeId, rtypeId, false); + tup = oper(pstate, opname, ltypeId, rtypeId, false, location); opform = (Form_pg_operator) GETSTRUCT(tup); args = list_make2(ltree, rtree); @@ -904,11 +910,13 @@ make_scalar_array_op(ParseState *pstate, List *opname, if (rettype != BOOLOID) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("op ANY/ALL (array) requires operator to yield boolean"))); + errmsg("op ANY/ALL (array) requires operator to yield boolean"), + parser_errposition(pstate, location))); if (get_func_retset(opform->oprcode)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("op ANY/ALL (array) requires operator not to return a set"))); + errmsg("op ANY/ALL (array) requires operator not to return a set"), + parser_errposition(pstate, location))); /* * Now switch back to the array type on the right, arranging for any @@ -919,7 +927,8 @@ make_scalar_array_op(ParseState *pstate, List *opname, ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("could not find array type for data type %s", - format_type_be(declared_arg_types[1])))); + format_type_be(declared_arg_types[1])), + parser_errposition(pstate, location))); actual_arg_types[1] = atypeId; declared_arg_types[1] = res_atypeId; diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index af8086a81a8..d0f78b119cd 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.119 2006/03/05 15:58:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.120 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -47,7 +47,8 @@ static void expandTupleDesc(TupleDesc tupdesc, Alias *eref, bool include_dropped, List **colnames, List **colvars); static int specialAttNum(const char *attname); -static void warnAutoRange(ParseState *pstate, RangeVar *relation); +static void warnAutoRange(ParseState *pstate, RangeVar *relation, + int location); /* @@ -329,7 +330,8 @@ GetRTEByRangeTablePosn(ParseState *pstate, * FROM will be marked as requiring read access from the beginning. */ Node * -scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname) +scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname, + int location) { Node *result = NULL; int attnum = 0; @@ -357,7 +359,8 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname) ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_COLUMN), errmsg("column reference \"%s\" is ambiguous", - colname))); + colname), + parser_errposition(pstate, location))); result = (Node *) make_var(pstate, rte, attnum); /* Require read access */ rte->requiredPerms |= ACL_SELECT; @@ -404,7 +407,8 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname) * If localonly is true, only names in the innermost query are considered. */ Node * -colNameToVar(ParseState *pstate, char *colname, bool localonly) +colNameToVar(ParseState *pstate, char *colname, bool localonly, + int location) { Node *result = NULL; ParseState *orig_pstate = pstate; @@ -419,7 +423,7 @@ colNameToVar(ParseState *pstate, char *colname, bool localonly) Node *newresult; /* use orig_pstate here to get the right sublevels_up */ - newresult = scanRTEForColumn(orig_pstate, rte, colname); + newresult = scanRTEForColumn(orig_pstate, rte, colname, location); if (newresult) { @@ -427,7 +431,8 @@ colNameToVar(ParseState *pstate, char *colname, bool localonly) ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_COLUMN), errmsg("column reference \"%s\" is ambiguous", - colname))); + colname), + parser_errposition(orig_pstate, location))); result = newresult; } } @@ -454,7 +459,8 @@ qualifiedNameToVar(ParseState *pstate, char *schemaname, char *refname, char *colname, - bool implicitRTEOK) + bool implicitRTEOK, + int location) { RangeTblEntry *rte; int sublevels_up; @@ -465,10 +471,11 @@ qualifiedNameToVar(ParseState *pstate, { if (!implicitRTEOK) return NULL; - rte = addImplicitRTE(pstate, makeRangeVar(schemaname, refname)); + rte = addImplicitRTE(pstate, makeRangeVar(schemaname, refname), + location); } - return scanRTEForColumn(pstate, rte, colname); + return scanRTEForColumn(pstate, rte, colname, location); } /* @@ -1043,12 +1050,12 @@ addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, * a conflicting name. */ RangeTblEntry * -addImplicitRTE(ParseState *pstate, RangeVar *relation) +addImplicitRTE(ParseState *pstate, RangeVar *relation, int location) { RangeTblEntry *rte; /* issue warning or error as needed */ - warnAutoRange(pstate, relation); + warnAutoRange(pstate, relation, location); /* * Note that we set inFromCl true, so that the RTE will be listed * explicitly if the parsetree is ever decompiled by ruleutils.c. This @@ -1196,7 +1203,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, Var *varnode; Oid atttypid; - atttypid = typenameTypeId(colDef->typename); + atttypid = typenameTypeId(NULL, colDef->typename); varnode = makeVar(rtindex, attnum, @@ -1543,7 +1550,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum, { ColumnDef *colDef = list_nth(rte->coldeflist, attnum - 1); - *vartype = typenameTypeId(colDef->typename); + *vartype = typenameTypeId(NULL, colDef->typename); *vartypmod = colDef->typename->typmod; } else @@ -1802,7 +1809,7 @@ attnumTypeId(Relation rd, int attid) * a warning. */ static void -warnAutoRange(ParseState *pstate, RangeVar *relation) +warnAutoRange(ParseState *pstate, RangeVar *relation, int location) { RangeTblEntry *rte; int sublevels_up; @@ -1841,7 +1848,8 @@ warnAutoRange(ParseState *pstate, RangeVar *relation) errhint("Perhaps you meant to reference the table alias \"%s\".", badAlias) : errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.", - rte->eref->aliasname)))); + rte->eref->aliasname)), + parser_errposition(pstate, location))); else ereport(ERROR, (errcode(ERRCODE_UNDEFINED_TABLE), @@ -1849,7 +1857,8 @@ warnAutoRange(ParseState *pstate, RangeVar *relation) errmsg("missing FROM-clause entry in subquery for table \"%s\"", relation->relname) : errmsg("missing FROM-clause entry for table \"%s\"", - relation->relname)))); + relation->relname)), + parser_errposition(pstate, location))); } else { @@ -1866,6 +1875,7 @@ warnAutoRange(ParseState *pstate, RangeVar *relation) badAlias) : (rte ? errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.", - rte->eref->aliasname) : 0)))); + rte->eref->aliasname) : 0)), + parser_errposition(pstate, location))); } } diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 63ce087e71c..300e02d90b9 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.140 2006/03/05 15:58:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.141 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -718,7 +718,8 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cross-database references are not implemented: %s", - NameListToString(fields)))); + NameListToString(fields)), + parser_errposition(pstate, cref->location))); schemaname = strVal(lsecond(fields)); relname = strVal(lthird(fields)); break; @@ -727,7 +728,8 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper qualified name (too many dotted names): %s", - NameListToString(fields)))); + NameListToString(fields)), + parser_errposition(pstate, cref->location))); schemaname = NULL; /* keep compiler quiet */ relname = NULL; break; @@ -736,8 +738,8 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref) rte = refnameRangeTblEntry(pstate, schemaname, relname, &sublevels_up); if (rte == NULL) - rte = addImplicitRTE(pstate, makeRangeVar(schemaname, - relname)); + rte = addImplicitRTE(pstate, makeRangeVar(schemaname, relname), + cref->location); rtindex = RTERangeTablePosn(pstate, rte, &sublevels_up); diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c index 41143540576..e88e6c37c1e 100644 --- a/src/backend/parser/parse_type.c +++ b/src/backend/parser/parse_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.78 2006/03/05 15:58:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.79 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -35,9 +35,11 @@ * * NB: even if the returned OID is not InvalidOid, the type might be * just a shell. Caller should check typisdefined before using the type. + * + * pstate is only used for error location info, and may be NULL. */ Oid -LookupTypeName(const TypeName *typename) +LookupTypeName(ParseState *pstate, const TypeName *typename) { Oid restype; @@ -60,7 +62,8 @@ LookupTypeName(const TypeName *typename) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper %%TYPE reference (too few dotted names): %s", - NameListToString(typename->names)))); + NameListToString(typename->names)), + parser_errposition(pstate, typename->location))); break; case 2: rel->relname = strVal(linitial(typename->names)); @@ -81,7 +84,8 @@ LookupTypeName(const TypeName *typename) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper %%TYPE reference (too many dotted names): %s", - NameListToString(typename->names)))); + NameListToString(typename->names)), + parser_errposition(pstate, typename->location))); break; } @@ -92,7 +96,8 @@ LookupTypeName(const TypeName *typename) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" of relation \"%s\" does not exist", - field, rel->relname))); + field, rel->relname), + parser_errposition(pstate, typename->location))); restype = get_atttype(relid, attnum); /* this construct should never have an array indicator */ @@ -190,21 +195,24 @@ TypeNameToString(const TypeName *typename) * a suitable error message if the type cannot be found or is not defined. */ Oid -typenameTypeId(const TypeName *typename) +typenameTypeId(ParseState *pstate, const TypeName *typename) { Oid typoid; - typoid = LookupTypeName(typename); + typoid = LookupTypeName(pstate, typename); if (!OidIsValid(typoid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type \"%s\" does not exist", - TypeNameToString(typename)))); + TypeNameToString(typename)), + parser_errposition(pstate, typename->location))); + if (!get_typisdefined(typoid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type \"%s\" is only a shell", - TypeNameToString(typename)))); + TypeNameToString(typename)), + parser_errposition(pstate, typename->location))); return typoid; } @@ -215,17 +223,18 @@ typenameTypeId(const TypeName *typename) * NB: caller must ReleaseSysCache the type tuple when done with it. */ Type -typenameType(const TypeName *typename) +typenameType(ParseState *pstate, const TypeName *typename) { Oid typoid; HeapTuple tup; - typoid = LookupTypeName(typename); + typoid = LookupTypeName(pstate, typename); if (!OidIsValid(typoid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type \"%s\" does not exist", - TypeNameToString(typename)))); + TypeNameToString(typename)), + parser_errposition(pstate, typename->location))); tup = SearchSysCache(TYPEOID, ObjectIdGetDatum(typoid), 0, 0, 0); @@ -235,7 +244,8 @@ typenameType(const TypeName *typename) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type \"%s\" is only a shell", - TypeNameToString(typename)))); + TypeNameToString(typename)), + parser_errposition(pstate, typename->location))); return (Type) tup; } @@ -447,7 +457,7 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod) if (typename->setof) goto fail; - *type_id = typenameTypeId(typename); + *type_id = typenameTypeId(NULL, typename); *typmod = typename->typmod; pfree(buf.data); diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index 3d63cb73c8a..0ac8d346a7b 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -24,7 +24,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.132 2006/03/07 01:00:17 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.133 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -74,20 +74,19 @@ static int literalalloc; /* current allocated buffer size */ static void addlit(char *ytext, int yleng); static void addlitchar(unsigned char ychar); static char *litbufdup(void); -static int pg_err_position(void); + +static int lexer_errposition(void); static void check_escape_warning(void); static void check_string_escape_warning(unsigned char ychar); /* + * Each call to yylex must set yylloc to the location of the found token + * (expressed as a byte offset from the start of the input text). * When we parse a token that requires multiple lexer rules to process, - * we set token_start to point at the true start of the token, for use - * by yyerror(). yytext will point at just the text consumed by the last - * rule, so it's not very helpful (e.g., it might contain just the last - * quote mark of a quoted identifier). But to avoid cluttering every rule - * with setting token_start, we allow token_start = NULL to denote that - * it's okay to use yytext. + * this should be done in the first such rule, else yylloc will point + * into the middle of the token. */ -static char *token_start; +#define SET_YYLLOC() (yylloc = yytext - scanbuf) /* Handles to the buffer that the lexer uses internally */ static YY_BUFFER_STATE scanbufhandle; @@ -316,17 +315,13 @@ other . %% -%{ - /* code to execute during start of each call of yylex() */ - token_start = NULL; -%} - {whitespace} { /* ignore */ } {xcstart} { - token_start = yytext; + /* Set location in case of syntax error in comment */ + SET_YYLLOC(); xcdepth = 0; BEGIN(xc); /* Put back any characters past slash-star; see above */ @@ -341,11 +336,7 @@ other . <xc>{xcstop} { if (xcdepth <= 0) - { BEGIN(INITIAL); - /* reset token_start for next token */ - token_start = NULL; - } else xcdepth--; } @@ -371,7 +362,7 @@ other . * In the meantime, place a leading "b" on the string * to mark it for the input routine as a binary string. */ - token_start = yytext; + SET_YYLLOC(); BEGIN(xb); startlit(); addlitchar('b'); @@ -400,7 +391,7 @@ other . * In the meantime, place a leading "x" on the string * to mark it for the input routine as a hex string. */ - token_start = yytext; + SET_YYLLOC(); BEGIN(xh); startlit(); addlitchar('x'); @@ -421,6 +412,7 @@ other . */ const ScanKeyword *keyword; + SET_YYLLOC(); yyless(1); /* eat only 'n' this time */ /* nchar had better be a keyword! */ keyword = ScanKeywordLookup("nchar"); @@ -431,7 +423,7 @@ other . {xqstart} { warn_on_first_escape = true; - token_start = yytext; + SET_YYLLOC(); if (standard_conforming_strings) BEGIN(xq); else @@ -440,7 +432,7 @@ other . } {xestart} { warn_on_first_escape = false; - token_start = yytext; + SET_YYLLOC(); BEGIN(xe); startlit(); } @@ -490,7 +482,7 @@ other . <xq,xe><<EOF>> { yyerror("unterminated quoted string"); } {dolqdelim} { - token_start = yytext; + SET_YYLLOC(); dolqstart = pstrdup(yytext); BEGIN(xdolq); startlit(); @@ -533,7 +525,7 @@ other . <xdolq><<EOF>> { yyerror("unterminated dollar-quoted string"); } {xdstart} { - token_start = yytext; + SET_YYLLOC(); BEGIN(xd); startlit(); } @@ -558,10 +550,12 @@ other . <xd><<EOF>> { yyerror("unterminated quoted identifier"); } {typecast} { + SET_YYLLOC(); return TYPECAST; } {self} { + SET_YYLLOC(); return yytext[0]; } @@ -611,6 +605,8 @@ other . nchars--; /* else remove the +/-, and check again */ } + SET_YYLLOC(); + if (nchars < yyleng) { /* Strip the unwanted chars from the token */ @@ -644,6 +640,7 @@ other . } {param} { + SET_YYLLOC(); yylval.ival = atol(yytext + 1); return PARAM; } @@ -652,6 +649,7 @@ other . long val; char* endptr; + SET_YYLLOC(); errno = 0; val = strtol(yytext, &endptr, 10); if (*endptr != '\0' || errno == ERANGE @@ -669,10 +667,12 @@ other . return ICONST; } {decimal} { + SET_YYLLOC(); yylval.str = pstrdup(yytext); return FCONST; } {real} { + SET_YYLLOC(); yylval.str = pstrdup(yytext); return FCONST; } @@ -684,12 +684,14 @@ other . * syntax error anyway, we don't bother to distinguish. */ yyless(yyleng-1); + SET_YYLLOC(); yylval.str = pstrdup(yytext); return FCONST; } {realfail2} { /* throw back the [Ee][+-], and proceed as above */ yyless(yyleng-2); + SET_YYLLOC(); yylval.str = pstrdup(yytext); return FCONST; } @@ -699,6 +701,8 @@ other . const ScanKeyword *keyword; char *ident; + SET_YYLLOC(); + /* Is it a keyword? */ keyword = ScanKeywordLookup(yytext); if (keyword != NULL) @@ -717,25 +721,52 @@ other . } {other} { + SET_YYLLOC(); return yytext[0]; } +<<EOF>> { + SET_YYLLOC(); + yyterminate(); + } + %% +/* + * lexer_errposition + * Report a lexical-analysis-time cursor position, if possible. + * + * This is expected to be used within an ereport() call. The return value + * is a dummy (always 0, in fact). + * + * Note that this can only be used for messages from the lexer itself, + * since it depends on scanbuf to still be valid. + */ static int -pg_err_position(void) +lexer_errposition(void) { - const char *loc = token_start ? token_start : yytext; + int pos; - /* in multibyte encodings, return index in characters not bytes */ - return pg_mbstrlen_with_len(scanbuf, loc - scanbuf) + 1; + /* Convert byte offset to character number */ + pos = pg_mbstrlen_with_len(scanbuf, yylloc) + 1; + /* And pass it to the ereport mechanism */ + return errposition(pos); } +/* + * yyerror + * Report a lexer or grammar error. + * + * The message's cursor position identifies the most recently lexed token. + * This is OK for syntax error messages from the Bison parser, because Bison + * parsers report error as soon as the first unparsable token is reached. + * Beware of using yyerror for other purposes, as the cursor position might + * be misleading! + */ void yyerror(const char *message) { - const char *loc = token_start ? token_start : yytext; - int cursorpos = pg_err_position(); + const char *loc = scanbuf + yylloc; if (*loc == YY_END_OF_BUFFER_CHAR) { @@ -743,7 +774,7 @@ yyerror(const char *message) (errcode(ERRCODE_SYNTAX_ERROR), /* translator: %s is typically "syntax error" */ errmsg("%s at end of input", _(message)), - errposition(cursorpos))); + lexer_errposition())); } else { @@ -751,7 +782,7 @@ yyerror(const char *message) (errcode(ERRCODE_SYNTAX_ERROR), /* translator: first %s is typically "syntax error" */ errmsg("%s at or near \"%s\"", _(message), loc), - errposition(cursorpos))); + lexer_errposition())); } } @@ -878,7 +909,7 @@ check_string_escape_warning(unsigned char ychar) (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), errmsg("nonstandard use of \\' in a string literal"), errhint("Use '' to write quotes in strings, or use the escape string syntax (E'...')."), - errposition(pg_err_position()))); + lexer_errposition())); warn_on_first_escape = false; /* warn only once per string */ } else if (ychar == '\\') @@ -888,7 +919,7 @@ check_string_escape_warning(unsigned char ychar) (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), errmsg("nonstandard use of \\\\ in a string literal"), errhint("Use the escape string syntax for backslashes, e.g., E'\\\\'."), - errposition(pg_err_position()))); + lexer_errposition())); warn_on_first_escape = false; /* warn only once per string */ } else @@ -903,6 +934,6 @@ check_escape_warning(void) (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), errmsg("nonstandard use of escape in a string literal"), errhint("Use the escape string syntax for escapes, e.g., E'\\r\\n'."), - errposition(pg_err_position()))); + lexer_errposition())); warn_on_first_escape = false; /* warn only once per string */ } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index a94d2691e88..78cb8c3f811 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.481 2006/03/05 15:58:40 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.482 2006/03/14 22:48:21 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -501,6 +501,7 @@ pg_parse_and_rewrite(const char *query_string, /* string to execute */ querytree_list = list_concat(querytree_list, pg_analyze_and_rewrite(parsetree, + query_string, paramTypes, numParams)); } @@ -625,7 +626,8 @@ log_after_parse(List *raw_parsetree_list, const char *query_string, * NOTE: for reasons mentioned above, this must be separate from raw parsing. */ List * -pg_analyze_and_rewrite(Node *parsetree, Oid *paramTypes, int numParams) +pg_analyze_and_rewrite(Node *parsetree, const char *query_string, + Oid *paramTypes, int numParams) { List *querytree_list; @@ -635,7 +637,8 @@ pg_analyze_and_rewrite(Node *parsetree, Oid *paramTypes, int numParams) if (log_parser_stats) ResetUsage(); - querytree_list = parse_analyze(parsetree, paramTypes, numParams); + querytree_list = parse_analyze(parsetree, query_string, + paramTypes, numParams); if (log_parser_stats) ShowUsage("PARSE ANALYSIS STATISTICS"); @@ -946,7 +949,8 @@ exec_simple_query(const char *query_string) */ oldcontext = MemoryContextSwitchTo(MessageContext); - querytree_list = pg_analyze_and_rewrite(parsetree, NULL, 0); + querytree_list = pg_analyze_and_rewrite(parsetree, query_string, + NULL, 0); plantree_list = pg_plan_queries(querytree_list, NULL, true); @@ -1257,6 +1261,7 @@ exec_parse_message(const char *query_string, /* string to execute */ ResetUsage(); querytree_list = parse_analyze_varparams(parsetree, + query_string, ¶mTypes, &numParams); diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 030f8c52b2f..9942bcc291b 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -2,7 +2,7 @@ * ruleutils.c - Functions to convert stored expressions/querytrees * back to source text * - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.215 2006/03/11 16:43:21 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.216 2006/03/14 22:48:22 tgl Exp $ **********************************************************************/ #include "postgres.h" @@ -4479,7 +4479,7 @@ get_from_clause_coldeflist(List *coldeflist, deparse_context *context) int32 atttypmod; attname = n->colname; - atttypeid = typenameTypeId(n->typename); + atttypeid = typenameTypeId(NULL, n->typename); atttypmod = n->typename->typmod; if (i > 0) @@ -4868,13 +4868,16 @@ generate_operator_name(Oid operid, Oid arg1, Oid arg2) switch (operform->oprkind) { case 'b': - p_result = oper(list_make1(makeString(oprname)), arg1, arg2, true); + p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2, + true, -1); break; case 'l': - p_result = left_oper(list_make1(makeString(oprname)), arg2, true); + p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2, + true, -1); break; case 'r': - p_result = right_oper(list_make1(makeString(oprname)), arg1, true); + p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1, + true, -1); break; default: elog(ERROR, "unrecognized oprkind: %d", operform->oprkind); |