summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorTom Lane2006-03-14 22:48:25 +0000
committerTom Lane2006-03-14 22:48:25 +0000
commit20ab467d76d78271006818d2baf4c9c8658d1f38 (patch)
tree7a536111b5cc4e494ac75558aad5655dfc8ab964 /src/backend
parent48fb696753e267447f99914c7968d0b4ffb5c5dc (diff)
Improve parser so that we can show an error cursor position for errors
during parse analysis, not only errors detected in the flex/bison stages. This is per my earlier proposal. This commit includes all the basic infrastructure, but locations are only tracked and reported for errors involving column references, function calls, and operators. More could be done later but this seems like a good set to start with. I've also moved the ReportSyntaxErrorPosition logic out of psql and into libpq, which should make it available to more people --- even within psql this is an improvement because warnings weren't handled by ReportSyntaxErrorPosition.
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/common/tupdesc.c4
-rw-r--r--src/backend/catalog/pg_aggregate.c6
-rw-r--r--src/backend/catalog/pg_operator.c7
-rw-r--r--src/backend/commands/aggregatecmds.c12
-rw-r--r--src/backend/commands/comment.c32
-rw-r--r--src/backend/commands/define.c13
-rw-r--r--src/backend/commands/functioncmds.c50
-rw-r--r--src/backend/commands/opclasscmds.c18
-rw-r--r--src/backend/commands/operatorcmds.c16
-rw-r--r--src/backend/commands/schemacmds.c4
-rw-r--r--src/backend/commands/sequence.c31
-rw-r--r--src/backend/commands/tablecmds.c33
-rw-r--r--src/backend/commands/typecmds.c151
-rw-r--r--src/backend/commands/view.c10
-rw-r--r--src/backend/executor/spi.c4
-rw-r--r--src/backend/nodes/copyfuncs.c6
-rw-r--r--src/backend/nodes/equalfuncs.c6
-rw-r--r--src/backend/nodes/makefuncs.c44
-rw-r--r--src/backend/nodes/outfuncs.c6
-rw-r--r--src/backend/nodes/readfuncs.c4
-rw-r--r--src/backend/optimizer/plan/initsplan.c7
-rw-r--r--src/backend/optimizer/util/clauses.c4
-rw-r--r--src/backend/parser/analyze.c26
-rw-r--r--src/backend/parser/gram.y221
-rw-r--r--src/backend/parser/parse_clause.c14
-rw-r--r--src/backend/parser/parse_expr.c162
-rw-r--r--src/backend/parser/parse_func.c62
-rw-r--r--src/backend/parser/parse_node.c37
-rw-r--r--src/backend/parser/parse_oper.c111
-rw-r--r--src/backend/parser/parse_relation.c46
-rw-r--r--src/backend/parser/parse_target.c12
-rw-r--r--src/backend/parser/parse_type.c38
-rw-r--r--src/backend/parser/scan.l103
-rw-r--r--src/backend/tcop/postgres.c13
-rw-r--r--src/backend/utils/adt/ruleutils.c13
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,
&paramTypes,
&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);