1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-10 09:21:54 +03:00

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.
This commit is contained in:
Tom Lane 2006-03-14 22:48:25 +00:00
parent 48fb696753
commit 20ab467d76
80 changed files with 1347 additions and 997 deletions

View File

@ -881,7 +881,9 @@ SELECT earth_box(ll_to_earth(90,180),
-- --
SELECT is_point(ll_to_earth(0,0)); SELECT is_point(ll_to_earth(0,0));
ERROR: function is_point(earth) does not exist ERROR: function is_point(earth) does not exist
HINT: No function matches the given name and argument types. You may need to add explicit typecasts. LINE 1: SELECT is_point(ll_to_earth(0,0));
^
HINT: No function matches the given name and argument types. You may need to add explicit type casts.
SELECT cube_dim(ll_to_earth(0,0)) <= 3; SELECT cube_dim(ll_to_earth(0,0)) <= 3;
?column? ?column?
---------- ----------
@ -897,7 +899,9 @@ SELECT abs(cube_distance(ll_to_earth(0,0), '(0)'::cube) / earth() - 1) <
SELECT is_point(ll_to_earth(30,60)); SELECT is_point(ll_to_earth(30,60));
ERROR: function is_point(earth) does not exist ERROR: function is_point(earth) does not exist
HINT: No function matches the given name and argument types. You may need to add explicit typecasts. LINE 1: SELECT is_point(ll_to_earth(30,60));
^
HINT: No function matches the given name and argument types. You may need to add explicit type casts.
SELECT cube_dim(ll_to_earth(30,60)) <= 3; SELECT cube_dim(ll_to_earth(30,60)) <= 3;
?column? ?column?
---------- ----------
@ -913,7 +917,9 @@ SELECT abs(cube_distance(ll_to_earth(30,60), '(0)'::cube) / earth() - 1) <
SELECT is_point(ll_to_earth(60,90)); SELECT is_point(ll_to_earth(60,90));
ERROR: function is_point(earth) does not exist ERROR: function is_point(earth) does not exist
HINT: No function matches the given name and argument types. You may need to add explicit typecasts. LINE 1: SELECT is_point(ll_to_earth(60,90));
^
HINT: No function matches the given name and argument types. You may need to add explicit type casts.
SELECT cube_dim(ll_to_earth(60,90)) <= 3; SELECT cube_dim(ll_to_earth(60,90)) <= 3;
?column? ?column?
---------- ----------
@ -929,7 +935,9 @@ SELECT abs(cube_distance(ll_to_earth(60,90), '(0)'::cube) / earth() - 1) <
SELECT is_point(ll_to_earth(-30,-90)); SELECT is_point(ll_to_earth(-30,-90));
ERROR: function is_point(earth) does not exist ERROR: function is_point(earth) does not exist
HINT: No function matches the given name and argument types. You may need to add explicit typecasts. LINE 1: SELECT is_point(ll_to_earth(-30,-90));
^
HINT: No function matches the given name and argument types. You may need to add explicit type casts.
SELECT cube_dim(ll_to_earth(-30,-90)) <= 3; SELECT cube_dim(ll_to_earth(-30,-90)) <= 3;
?column? ?column?
---------- ----------

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be * some of the executor utility code such as "ExecTypeFromTL" should be
@ -499,7 +499,7 @@ BuildDescForRelation(List *schema)
attname))); attname)));
TupleDescInitEntry(desc, attnum, attname, TupleDescInitEntry(desc, attnum, attname,
typenameTypeId(entry->typename), typenameTypeId(NULL, entry->typename),
atttypmod, attdim); atttypmod, attdim);
/* Fill in additional stuff not handled by TupleDescInitEntry */ /* Fill in additional stuff not handled by TupleDescInitEntry */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 */ /* handle sortop, if supplied */
if (aggsortopName) if (aggsortopName)
sortop = LookupOperName(aggsortopName, sortop = LookupOperName(NULL, aggsortopName,
aggBaseType, aggBaseType, aggBaseType, aggBaseType,
false); false, -1);
/* /*
* Everything looks okay. Try to create the pg_proc entry for the * Everything looks okay. Try to create the pg_proc entry for the

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* these routines moved here from commands/define.c and somewhat cleaned up. * these routines moved here from commands/define.c and somewhat cleaned up.
@ -175,8 +175,9 @@ OperatorLookup(List *operatorName,
Oid operatorObjectId; Oid operatorObjectId;
RegProcedure oprcode; RegProcedure oprcode;
operatorObjectId = LookupOperName(operatorName, leftObjectId, operatorObjectId = LookupOperName(NULL, operatorName,
rightObjectId, true); leftObjectId, rightObjectId,
true, -1);
if (!OidIsValid(operatorObjectId)) if (!OidIsValid(operatorObjectId))
{ {
*defined = false; *defined = false;

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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 * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * 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) if (pg_strcasecmp(TypeNameToString(baseType), "ANY") == 0)
baseTypeId = ANYOID; baseTypeId = ANYOID;
else else
baseTypeId = typenameTypeId(baseType); baseTypeId = typenameTypeId(NULL, baseType);
transTypeId = typenameTypeId(transType); transTypeId = typenameTypeId(NULL, transType);
if (get_typtype(transTypeId) == 'p' && if (get_typtype(transTypeId) == 'p' &&
transTypeId != ANYARRAYOID && transTypeId != ANYARRAYOID &&
transTypeId != ANYELEMENTOID) transTypeId != ANYELEMENTOID)
@ -176,7 +176,7 @@ RemoveAggregate(RemoveAggrStmt *stmt)
* that the aggregate is to apply to all basetypes (eg, COUNT). * that the aggregate is to apply to all basetypes (eg, COUNT).
*/ */
if (aggType) if (aggType)
basetypeID = typenameTypeId(aggType); basetypeID = typenameTypeId(NULL, aggType);
else else
basetypeID = ANYOID; basetypeID = ANYOID;
@ -231,7 +231,7 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
* COUNT). * COUNT).
*/ */
if (basetype) if (basetype)
basetypeOid = typenameTypeId(basetype); basetypeOid = typenameTypeId(NULL, basetype);
else else
basetypeOid = ANYOID; basetypeOid = ANYOID;
@ -311,7 +311,7 @@ AlterAggregateOwner(List *name, TypeName *basetype, Oid newOwnerId)
* COUNT). * COUNT).
*/ */
if (basetype) if (basetype)
basetypeOid = typenameTypeId(basetype); basetypeOid = typenameTypeId(NULL, basetype);
else else
basetypeOid = ANYOID; basetypeOid = ANYOID;

View File

@ -7,7 +7,7 @@
* Copyright (c) 1996-2006, PostgreSQL Global Development Group * Copyright (c) 1996-2006, PostgreSQL Global Development Group
* *
* IDENTIFICATION * 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/dbcommands.h"
#include "commands/tablespace.h" #include "commands/tablespace.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "parser/parse_oper.h" #include "parser/parse_oper.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
@ -846,13 +847,11 @@ CommentType(List *typename, char *comment)
Oid oid; Oid oid;
/* XXX a bit of a crock; should accept TypeName in COMMENT syntax */ /* XXX a bit of a crock; should accept TypeName in COMMENT syntax */
tname = makeNode(TypeName); tname = makeTypeNameFromNameList(typename);
tname->names = typename;
tname->typmod = -1;
/* Find the type's oid */ /* Find the type's oid */
oid = typenameTypeId(tname); oid = typenameTypeId(NULL, tname);
/* Check object security */ /* Check object security */
@ -881,7 +880,7 @@ CommentAggregate(List *aggregate, List *arguments, char *comment)
/* First, attempt to determine the base aggregate oid */ /* First, attempt to determine the base aggregate oid */
if (aggtype) if (aggtype)
baseoid = typenameTypeId(aggtype); baseoid = typenameTypeId(NULL, aggtype);
else else
baseoid = ANYOID; baseoid = ANYOID;
@ -945,9 +944,11 @@ CommentOperator(List *opername, List *arguments, char *comment)
Oid oid; Oid oid;
/* Look up the operator */ /* 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())) if (!pg_oper_ownercheck(oid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER, aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
NameListToString(opername)); NameListToString(opername));
@ -1352,19 +1353,8 @@ CommentCast(List *qualname, List *arguments, char *comment)
targettype = (TypeName *) linitial(arguments); targettype = (TypeName *) linitial(arguments);
Assert(IsA(targettype, TypeName)); Assert(IsA(targettype, TypeName));
sourcetypeid = typenameTypeId(sourcetype); sourcetypeid = typenameTypeId(NULL, sourcetype);
if (!OidIsValid(sourcetypeid)) targettypeid = typenameTypeId(NULL, targettype);
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))));
tuple = SearchSysCache(CASTSOURCETARGET, tuple = SearchSysCache(CASTSOURCETARGET,
ObjectIdGetDatum(sourcetypeid), ObjectIdGetDatum(sourcetypeid),

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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 * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
@ -37,6 +37,7 @@
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "nodes/makefuncs.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "parser/scansup.h" #include "parser/scansup.h"
#include "utils/int8.h" #include "utils/int8.h"
@ -219,14 +220,8 @@ defGetTypeName(DefElem *def)
case T_TypeName: case T_TypeName:
return (TypeName *) def->arg; return (TypeName *) def->arg;
case T_String: case T_String:
{
/* Allow quoted typename for backwards compatibility */ /* Allow quoted typename for backwards compatibility */
TypeName *n = makeNode(TypeName); return makeTypeNameFromNameList(list_make1(def->arg));
n->names = list_make1(def->arg);
n->typmod = -1;
return n;
}
default: default:
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * 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 * DESCRIPTION
* These routines take the parse tree and pick out the * These routines take the parse tree and pick out the
@ -75,7 +75,7 @@ compute_return_type(TypeName *returnType, Oid languageOid,
{ {
Oid rettype; Oid rettype;
rettype = LookupTypeName(returnType); rettype = LookupTypeName(NULL, returnType);
if (OidIsValid(rettype)) if (OidIsValid(rettype))
{ {
@ -174,7 +174,7 @@ examine_parameter_list(List *parameters, Oid languageOid,
TypeName *t = fp->argType; TypeName *t = fp->argType;
Oid toid; Oid toid;
toid = LookupTypeName(t); toid = LookupTypeName(NULL, t);
if (OidIsValid(toid)) if (OidIsValid(toid))
{ {
if (!get_typisdefined(toid)) if (!get_typisdefined(toid))
@ -1152,33 +1152,10 @@ CreateCast(CreateCastStmt *stmt)
ObjectAddress myself, ObjectAddress myself,
referenced; referenced;
sourcetypeid = LookupTypeName(stmt->sourcetype); sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
if (!OidIsValid(sourcetypeid)) targettypeid = typenameTypeId(NULL, stmt->targettype);
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))));
/* No pseudo-types allowed */
if (get_typtype(sourcetypeid) == 'p') if (get_typtype(sourcetypeid) == 'p')
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
@ -1400,19 +1377,8 @@ DropCast(DropCastStmt *stmt)
HeapTuple tuple; HeapTuple tuple;
ObjectAddress object; ObjectAddress object;
sourcetypeid = LookupTypeName(stmt->sourcetype); sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
if (!OidIsValid(sourcetypeid)) targettypeid = typenameTypeId(NULL, stmt->targettype);
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))));
tuple = SearchSysCache(CASTSOURCETARGET, tuple = SearchSysCache(CASTSOURCETARGET,
ObjectIdGetDatum(sourcetypeid), ObjectIdGetDatum(sourcetypeid),

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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"))); errmsg("must be superuser to create an operator class")));
/* Look up the datatype */ /* Look up the datatype */
typeoid = typenameTypeId(stmt->datatype); typeoid = typenameTypeId(NULL, stmt->datatype);
#ifdef NOT_USED #ifdef NOT_USED
/* XXX this is unnecessary given the superuser check above */ /* XXX this is unnecessary given the superuser check above */
@ -185,16 +185,16 @@ DefineOpClass(CreateOpClassStmt *stmt)
TypeName *typeName1 = (TypeName *) linitial(item->args); TypeName *typeName1 = (TypeName *) linitial(item->args);
TypeName *typeName2 = (TypeName *) lsecond(item->args); TypeName *typeName2 = (TypeName *) lsecond(item->args);
operOid = LookupOperNameTypeNames(item->name, operOid = LookupOperNameTypeNames(NULL, item->name,
typeName1, typeName1, typeName2,
typeName2, false, -1);
false);
} }
else else
{ {
/* Default to binary op on input datatype */ /* Default to binary op on input datatype */
operOid = LookupOperName(item->name, typeoid, typeoid, operOid = LookupOperName(NULL, item->name,
false); typeoid, typeoid,
false, -1);
} }
#ifdef NOT_USED #ifdef NOT_USED
@ -246,7 +246,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("storage type specified more than once"))); errmsg("storage type specified more than once")));
storageoid = typenameTypeId(item->storedtype); storageoid = typenameTypeId(NULL, item->storedtype);
#ifdef NOT_USED #ifdef NOT_USED
/* XXX this is unnecessary given the superuser check above */ /* XXX this is unnecessary given the superuser check above */

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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 * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * 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 */ /* Transform type names to type OIDs */
if (typeName1) if (typeName1)
typeId1 = typenameTypeId(typeName1); typeId1 = typenameTypeId(NULL, typeName1);
if (typeName2) if (typeName2)
typeId2 = typenameTypeId(typeName2); typeId2 = typenameTypeId(NULL, typeName2);
/* /*
* If any of the mergejoin support operators were given, then canMerge is * If any of the mergejoin support operators were given, then canMerge is
@ -210,8 +210,9 @@ RemoveOperator(RemoveOperStmt *stmt)
HeapTuple tup; HeapTuple tup;
ObjectAddress object; ObjectAddress object;
operOid = LookupOperNameTypeNames(operatorName, typeName1, typeName2, operOid = LookupOperNameTypeNames(NULL, operatorName,
false); typeName1, typeName2,
false, -1);
tup = SearchSysCache(OPEROID, tup = SearchSysCache(OPEROID,
ObjectIdGetDatum(operOid), ObjectIdGetDatum(operOid),
@ -286,8 +287,9 @@ AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
rel = heap_open(OperatorRelationId, RowExclusiveLock); rel = heap_open(OperatorRelationId, RowExclusiveLock);
operOid = LookupOperNameTypeNames(name, typeName1, typeName2, operOid = LookupOperNameTypeNames(NULL, name,
false); typeName1, typeName2,
false, -1);
AlterOperatorOwner_internal(rel, operOid, newOwnerId); AlterOperatorOwner_internal(rel, operOid, newOwnerId);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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; List *querytree_list;
ListCell *querytree_item; ListCell *querytree_item;
querytree_list = parse_analyze(parsetree, NULL, 0); querytree_list = parse_analyze(parsetree, NULL, NULL, 0);
foreach(querytree_item, querytree_list) foreach(querytree_item, querytree_list)
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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/tablecmds.h"
#include "commands/sequence.h" #include "commands/sequence.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/resowner.h" #include "utils/resowner.h"
@ -112,16 +113,8 @@ DefineSequence(CreateSeqStmt *seq)
stmt->tableElts = NIL; stmt->tableElts = NIL;
for (i = SEQ_COL_FIRSTCOL; i <= SEQ_COL_LASTCOL; i++) for (i = SEQ_COL_FIRSTCOL; i <= SEQ_COL_LASTCOL; i++)
{ {
ColumnDef *coldef; ColumnDef *coldef = makeNode(ColumnDef);
TypeName *typnam;
typnam = makeNode(TypeName);
typnam->setof = FALSE;
typnam->arrayBounds = NIL;
typnam->typmod = -1;
coldef = makeNode(ColumnDef);
coldef->typename = typnam;
coldef->inhcount = 0; coldef->inhcount = 0;
coldef->is_local = true; coldef->is_local = true;
coldef->is_not_null = true; coldef->is_not_null = true;
@ -135,48 +128,48 @@ DefineSequence(CreateSeqStmt *seq)
switch (i) switch (i)
{ {
case SEQ_COL_NAME: case SEQ_COL_NAME:
typnam->typeid = NAMEOID; coldef->typename = makeTypeNameFromOid(NAMEOID, -1);
coldef->colname = "sequence_name"; coldef->colname = "sequence_name";
namestrcpy(&name, seq->sequence->relname); namestrcpy(&name, seq->sequence->relname);
value[i - 1] = NameGetDatum(&name); value[i - 1] = NameGetDatum(&name);
break; break;
case SEQ_COL_LASTVAL: case SEQ_COL_LASTVAL:
typnam->typeid = INT8OID; coldef->typename = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "last_value"; coldef->colname = "last_value";
value[i - 1] = Int64GetDatumFast(new.last_value); value[i - 1] = Int64GetDatumFast(new.last_value);
break; break;
case SEQ_COL_INCBY: case SEQ_COL_INCBY:
typnam->typeid = INT8OID; coldef->typename = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "increment_by"; coldef->colname = "increment_by";
value[i - 1] = Int64GetDatumFast(new.increment_by); value[i - 1] = Int64GetDatumFast(new.increment_by);
break; break;
case SEQ_COL_MAXVALUE: case SEQ_COL_MAXVALUE:
typnam->typeid = INT8OID; coldef->typename = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "max_value"; coldef->colname = "max_value";
value[i - 1] = Int64GetDatumFast(new.max_value); value[i - 1] = Int64GetDatumFast(new.max_value);
break; break;
case SEQ_COL_MINVALUE: case SEQ_COL_MINVALUE:
typnam->typeid = INT8OID; coldef->typename = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "min_value"; coldef->colname = "min_value";
value[i - 1] = Int64GetDatumFast(new.min_value); value[i - 1] = Int64GetDatumFast(new.min_value);
break; break;
case SEQ_COL_CACHE: case SEQ_COL_CACHE:
typnam->typeid = INT8OID; coldef->typename = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "cache_value"; coldef->colname = "cache_value";
value[i - 1] = Int64GetDatumFast(new.cache_value); value[i - 1] = Int64GetDatumFast(new.cache_value);
break; break;
case SEQ_COL_LOG: case SEQ_COL_LOG:
typnam->typeid = INT8OID; coldef->typename = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "log_cnt"; coldef->colname = "log_cnt";
value[i - 1] = Int64GetDatum((int64) 1); value[i - 1] = Int64GetDatum((int64) 1);
break; break;
case SEQ_COL_CYCLE: case SEQ_COL_CYCLE:
typnam->typeid = BOOLOID; coldef->typename = makeTypeNameFromOid(BOOLOID, -1);
coldef->colname = "is_cycled"; coldef->colname = "is_cycled";
value[i - 1] = BoolGetDatum(new.is_cycled); value[i - 1] = BoolGetDatum(new.is_cycled);
break; break;
case SEQ_COL_CALLED: case SEQ_COL_CALLED:
typnam->typeid = BOOLOID; coldef->typename = makeTypeNameFromOid(BOOLOID, -1);
coldef->colname = "is_called"; coldef->colname = "is_called";
value[i - 1] = BoolGetDatum(false); value[i - 1] = BoolGetDatum(false);
break; break;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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); char *attributeName = NameStr(attribute->attname);
int exist_attno; int exist_attno;
ColumnDef *def; ColumnDef *def;
TypeName *typename;
/* /*
* Ignore dropped columns in the parent. * 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\"", (errmsg("merging multiple inherited definitions of column \"%s\"",
attributeName))); attributeName)));
def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1); 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) def->typename->typmod != attribute->atttypmod)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
@ -919,10 +918,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
*/ */
def = makeNode(ColumnDef); def = makeNode(ColumnDef);
def->colname = pstrdup(attributeName); def->colname = pstrdup(attributeName);
typename = makeNode(TypeName); def->typename = makeTypeNameFromOid(attribute->atttypid,
typename->typeid = attribute->atttypid; attribute->atttypmod);
typename->typmod = attribute->atttypmod;
def->typename = typename;
def->inhcount = 1; def->inhcount = 1;
def->is_local = false; def->is_local = false;
def->is_not_null = attribute->attnotnull; def->is_not_null = attribute->attnotnull;
@ -1041,7 +1038,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
(errmsg("merging column \"%s\" with inherited definition", (errmsg("merging column \"%s\" with inherited definition",
attributeName))); attributeName)));
def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1); 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) def->typename->typmod != newdef->typename->typmod)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
@ -2955,7 +2952,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple); Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
/* Okay if child matches by type */ /* Okay if child matches by type */
if (typenameTypeId(colDef->typename) != childatt->atttypid || if (typenameTypeId(NULL, colDef->typename) != childatt->atttypid ||
colDef->typename->typmod != childatt->atttypmod) colDef->typename->typmod != childatt->atttypmod)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
@ -3009,7 +3006,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
MaxHeapAttributeNumber))); MaxHeapAttributeNumber)));
i = minattnum + 1; i = minattnum + 1;
typeTuple = typenameType(colDef->typename); typeTuple = typenameType(NULL, colDef->typename);
tform = (Form_pg_type) GETSTRUCT(typeTuple); tform = (Form_pg_type) GETSTRUCT(typeTuple);
typeOid = HeapTupleGetOid(typeTuple); typeOid = HeapTupleGetOid(typeTuple);
@ -3991,8 +3988,9 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
* the right answer from the test below on opclass membership unless * the right answer from the test below on opclass membership unless
* we select the proper operator.) * we select the proper operator.)
*/ */
Operator o = oper(list_make1(makeString("=")), Operator o = oper(NULL, list_make1(makeString("=")),
pktypoid[i], fktypoid[i], true); pktypoid[i], fktypoid[i],
true, -1);
if (o == NULL) if (o == NULL)
ereport(ERROR, ereport(ERROR,
@ -4773,12 +4771,7 @@ ATPrepAlterColumnType(List **wqueue,
colName))); colName)));
/* Look up the target type */ /* Look up the target type */
targettype = LookupTypeName(typename); targettype = typenameTypeId(NULL, typename);
if (!OidIsValid(targettype))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist",
TypeNameToString(typename))));
/* make sure datatype is legal for a column */ /* make sure datatype is legal for a column */
CheckAttributeType(colName, targettype); CheckAttributeType(colName, targettype);
@ -4904,7 +4897,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
colName))); colName)));
/* Look up the target type (should not fail, since prep found it) */ /* 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); tform = (Form_pg_type) GETSTRUCT(typeTuple);
targettype = HeapTupleGetOid(typeTuple); targettype = HeapTupleGetOid(typeTuple);
@ -5265,7 +5258,7 @@ ATPostAlterTypeParse(char *cmd, List **wqueue)
Node *parsetree = (Node *) lfirst(list_item); Node *parsetree = (Node *) lfirst(list_item);
querytree_list = list_concat(querytree_list, querytree_list = list_concat(querytree_list,
parse_analyze(parsetree, NULL, 0)); parse_analyze(parsetree, cmd, NULL, 0));
} }
/* /*

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
@ -47,7 +47,7 @@
#include "executor/executor.h" #include "executor/executor.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "nodes/execnodes.h" #include "nodes/execnodes.h"
#include "nodes/nodes.h" #include "nodes/makefuncs.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "optimizer/planmain.h" #include "optimizer/planmain.h"
#include "optimizer/var.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 findTypeSendFunction(List *procname, Oid typeOid);
static Oid findTypeAnalyzeFunction(List *procname, Oid typeOid); static Oid findTypeAnalyzeFunction(List *procname, Oid typeOid);
static List *get_rels_with_domain(Oid domainOid, LOCKMODE lockmode); 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, static char *domainAddConstraint(Oid domainOid, Oid domainNamespace,
Oid baseTypeOid, Oid baseTypeOid,
int typMod, Constraint *constr, int typMod, Constraint *constr,
@ -196,7 +196,7 @@ DefineType(List *names, List *parameters)
} }
else if (pg_strcasecmp(defel->defname, "element") == 0) else if (pg_strcasecmp(defel->defname, "element") == 0)
{ {
elemType = typenameTypeId(defGetTypeName(defel)); elemType = typenameTypeId(NULL, defGetTypeName(defel));
/* disallow arrays of pseudotypes */ /* disallow arrays of pseudotypes */
if (get_typtype(elemType) == 'p') if (get_typtype(elemType) == 'p')
ereport(ERROR, ereport(ERROR,
@ -445,13 +445,10 @@ RemoveType(List *names, DropBehavior behavior, bool missing_ok)
ObjectAddress object; ObjectAddress object;
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeNode(TypeName); typename = makeTypeNameFromNameList(names);
typename->names = names;
typename->typmod = -1;
typename->arrayBounds = NIL;
/* Use LookupTypeName here so that shell types can be removed. */ /* Use LookupTypeName here so that shell types can be removed. */
typeoid = LookupTypeName(typename); typeoid = LookupTypeName(NULL, typename);
if (!OidIsValid(typeoid)) if (!OidIsValid(typeoid))
{ {
if (!missing_ok) if (!missing_ok)
@ -586,7 +583,7 @@ DefineDomain(CreateDomainStmt *stmt)
/* /*
* Look up the base type. * Look up the base type.
*/ */
typeTup = typenameType(stmt->typename); typeTup = typenameType(NULL, stmt->typename);
baseType = (Form_pg_type) GETSTRUCT(typeTup); baseType = (Form_pg_type) GETSTRUCT(typeTup);
basetypeoid = HeapTupleGetOid(typeTup); basetypeoid = HeapTupleGetOid(typeTup);
@ -840,13 +837,10 @@ RemoveDomain(List *names, DropBehavior behavior, bool missing_ok)
ObjectAddress object; ObjectAddress object;
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeNode(TypeName); typename = makeTypeNameFromNameList(names);
typename->names = names;
typename->typmod = -1;
typename->arrayBounds = NIL;
/* Use LookupTypeName here so that shell types can be removed. */ /* Use LookupTypeName here so that shell types can be removed. */
typeoid = LookupTypeName(typename); typeoid = LookupTypeName(NULL, typename);
if (!OidIsValid(typeoid)) if (!OidIsValid(typeoid))
{ {
if (!missing_ok) if (!missing_ok)
@ -1172,39 +1166,27 @@ AlterDomainDefault(List *names, Node *defaultRaw)
Form_pg_type typTup; Form_pg_type typTup;
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeNode(TypeName); typename = makeTypeNameFromNameList(names);
typename->names = names; domainoid = typenameTypeId(NULL, typename);
typename->typmod = -1;
typename->arrayBounds = NIL;
/* Lock the domain in the type table */ /* Look up the domain in the type table */
rel = heap_open(TypeRelationId, RowExclusiveLock); 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, tup = SearchSysCacheCopy(TYPEOID,
ObjectIdGetDatum(domainoid), ObjectIdGetDatum(domainoid),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for type %u", domainoid); 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 */ /* Check it's a domain and check user has permission for ALTER DOMAIN */
domainOwnerCheck(tup, typename); checkDomainOwner(tup, typename);
/* Setup new tuple */ /* Setup new tuple */
MemSet(new_record, (Datum) 0, sizeof(new_record)); MemSet(new_record, (Datum) 0, sizeof(new_record));
MemSet(new_record_nulls, ' ', sizeof(new_record_nulls)); MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));
MemSet(new_record_repl, ' ', sizeof(new_record_repl)); 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 */ /* Store the new default, if null then skip this step */
if (defaultRaw) if (defaultRaw)
{ {
@ -1295,22 +1277,12 @@ AlterDomainNotNull(List *names, bool notNull)
Form_pg_type typTup; Form_pg_type typTup;
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeNode(TypeName); typename = makeTypeNameFromNameList(names);
typename->names = names; domainoid = typenameTypeId(NULL, typename);
typename->typmod = -1;
typename->arrayBounds = NIL;
/* Lock the type table */ /* Look up the domain in the type table */
typrel = heap_open(TypeRelationId, RowExclusiveLock); 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, tup = SearchSysCacheCopy(TYPEOID,
ObjectIdGetDatum(domainoid), ObjectIdGetDatum(domainoid),
0, 0, 0); 0, 0, 0);
@ -1318,8 +1290,8 @@ AlterDomainNotNull(List *names, bool notNull)
elog(ERROR, "cache lookup failed for type %u", domainoid); elog(ERROR, "cache lookup failed for type %u", domainoid);
typTup = (Form_pg_type) GETSTRUCT(tup); typTup = (Form_pg_type) GETSTRUCT(tup);
/* Doesn't return if user isn't allowed to alter the domain */ /* Check it's a domain and check user has permission for ALTER DOMAIN */
domainOwnerCheck(tup, typename); checkDomainOwner(tup, typename);
/* Is the domain already set to the desired constraint? */ /* Is the domain already set to the desired constraint? */
if (typTup->typnotnull == notNull) if (typTup->typnotnull == notNull)
@ -1394,7 +1366,8 @@ AlterDomainNotNull(List *names, bool notNull)
* Implements the ALTER DOMAIN DROP CONSTRAINT statement * Implements the ALTER DOMAIN DROP CONSTRAINT statement
*/ */
void void
AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior behavior) AlterDomainDropConstraint(List *names, const char *constrName,
DropBehavior behavior)
{ {
TypeName *typename; TypeName *typename;
Oid domainoid; Oid domainoid;
@ -1406,30 +1379,20 @@ AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior beha
HeapTuple contup; HeapTuple contup;
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeNode(TypeName); typename = makeTypeNameFromNameList(names);
typename->names = names; domainoid = typenameTypeId(NULL, typename);
typename->typmod = -1;
typename->arrayBounds = NIL;
/* Lock the type table */ /* Look up the domain in the type table */
rel = heap_open(TypeRelationId, RowExclusiveLock); 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, tup = SearchSysCacheCopy(TYPEOID,
ObjectIdGetDatum(domainoid), ObjectIdGetDatum(domainoid),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for type %u", domainoid); elog(ERROR, "cache lookup failed for type %u", domainoid);
/* Doesn't return if user isn't allowed to alter the domain */ /* Check it's a domain and check user has permission for ALTER DOMAIN */
domainOwnerCheck(tup, typename); checkDomainOwner(tup, typename);
/* Grab an appropriate lock on the pg_constraint relation */ /* Grab an appropriate lock on the pg_constraint relation */
conrel = heap_open(ConstraintRelationId, RowExclusiveLock); conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
@ -1491,22 +1454,12 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
Constraint *constr; Constraint *constr;
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeNode(TypeName); typename = makeTypeNameFromNameList(names);
typename->names = names; domainoid = typenameTypeId(NULL, typename);
typename->typmod = -1;
typename->arrayBounds = NIL;
/* Lock the type table */ /* Look up the domain in the type table */
typrel = heap_open(TypeRelationId, RowExclusiveLock); 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, tup = SearchSysCacheCopy(TYPEOID,
ObjectIdGetDatum(domainoid), ObjectIdGetDatum(domainoid),
0, 0, 0); 0, 0, 0);
@ -1514,8 +1467,8 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
elog(ERROR, "cache lookup failed for type %u", domainoid); elog(ERROR, "cache lookup failed for type %u", domainoid);
typTup = (Form_pg_type) GETSTRUCT(tup); typTup = (Form_pg_type) GETSTRUCT(tup);
/* Doesn't return if user isn't allowed to alter the domain */ /* Check it's a domain and check user has permission for ALTER DOMAIN */
domainOwnerCheck(tup, typename); checkDomainOwner(tup, typename);
/* Check for unsupported constraint types */ /* Check for unsupported constraint types */
if (IsA(newConstraint, FkConstraint)) 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 * Check that the type is actually a domain and that the current user
* the domain in an ALTER DOMAIN statement, or if the type isn't actually * has permission to do ALTER DOMAIN on it. Throw an error if not.
* a domain.
*/ */
static void static void
domainOwnerCheck(HeapTuple tup, TypeName *typename) checkDomainOwner(HeapTuple tup, TypeName *typename)
{ {
Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup); Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup);
@ -2079,22 +2031,19 @@ AlterTypeOwner(List *names, Oid newOwnerId)
AclResult aclresult; AclResult aclresult;
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeNode(TypeName); typename = makeTypeNameFromNameList(names);
typename->names = names;
typename->typmod = -1;
typename->arrayBounds = NIL;
/* Lock the type table */ /* Use LookupTypeName here so that shell types can be processed */
rel = heap_open(TypeRelationId, RowExclusiveLock); typeOid = LookupTypeName(NULL, typename);
/* Use LookupTypeName here so that shell types can be processed (why?) */
typeOid = LookupTypeName(typename);
if (!OidIsValid(typeOid)) if (!OidIsValid(typeOid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist", errmsg("type \"%s\" does not exist",
TypeNameToString(typename)))); TypeNameToString(typename))));
/* Look up the type in the type table */
rel = heap_open(TypeRelationId, RowExclusiveLock);
tup = SearchSysCacheCopy(TYPEOID, tup = SearchSysCacheCopy(TYPEOID,
ObjectIdGetDatum(typeOid), ObjectIdGetDatum(typeOid),
0, 0, 0); 0, 0, 0);
@ -2206,19 +2155,9 @@ AlterTypeNamespace(List *names, const char *newschema)
Oid typeOid; Oid typeOid;
Oid nspOid; Oid nspOid;
/* get type OID */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeNode(TypeName); typename = makeTypeNameFromNameList(names);
typename->names = names; typeOid = typenameTypeId(NULL, typename);
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))));
/* check permissions on type */ /* check permissions on type */
if (!pg_type_ownercheck(typeOid, GetUserId())) if (!pg_type_ownercheck(typeOid, GetUserId()))

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) if (!tle->resjunk)
{ {
ColumnDef *def = makeNode(ColumnDef); ColumnDef *def = makeNode(ColumnDef);
TypeName *typename = makeNode(TypeName);
def->colname = pstrdup(tle->resname); def->colname = pstrdup(tle->resname);
def->typename = makeTypeNameFromOid(exprType((Node *) tle->expr),
typename->typeid = exprType((Node *) tle->expr); exprTypmod((Node *) tle->expr));
typename->typmod = exprTypmod((Node *) tle->expr);
def->typename = typename;
def->inhcount = 0; def->inhcount = 0;
def->is_local = true; def->is_local = true;
def->is_not_null = false; def->is_not_null = false;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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); Node *parsetree = (Node *) lfirst(list_item);
List *query_list; 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); query_list_list = lappend(query_list_list, query_list);

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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(name);
COPY_NODE_FIELD(lexpr); COPY_NODE_FIELD(lexpr);
COPY_NODE_FIELD(rexpr); COPY_NODE_FIELD(rexpr);
COPY_SCALAR_FIELD(location);
return newnode; return newnode;
} }
@ -1428,6 +1429,7 @@ _copyColumnRef(ColumnRef *from)
ColumnRef *newnode = makeNode(ColumnRef); ColumnRef *newnode = makeNode(ColumnRef);
COPY_NODE_FIELD(fields); COPY_NODE_FIELD(fields);
COPY_SCALAR_FIELD(location);
return newnode; return newnode;
} }
@ -1482,6 +1484,7 @@ _copyFuncCall(FuncCall *from)
COPY_NODE_FIELD(args); COPY_NODE_FIELD(args);
COPY_SCALAR_FIELD(agg_star); COPY_SCALAR_FIELD(agg_star);
COPY_SCALAR_FIELD(agg_distinct); COPY_SCALAR_FIELD(agg_distinct);
COPY_SCALAR_FIELD(location);
return newnode; return newnode;
} }
@ -1532,6 +1535,7 @@ _copyTypeName(TypeName *from)
COPY_SCALAR_FIELD(pct_type); COPY_SCALAR_FIELD(pct_type);
COPY_SCALAR_FIELD(typmod); COPY_SCALAR_FIELD(typmod);
COPY_NODE_FIELD(arrayBounds); COPY_NODE_FIELD(arrayBounds);
COPY_SCALAR_FIELD(location);
return newnode; return newnode;
} }

View File

@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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(name);
COMPARE_NODE_FIELD(lexpr); COMPARE_NODE_FIELD(lexpr);
COMPARE_NODE_FIELD(rexpr); COMPARE_NODE_FIELD(rexpr);
COMPARE_SCALAR_FIELD(location);
return true; return true;
} }
@ -1548,6 +1549,7 @@ static bool
_equalColumnRef(ColumnRef *a, ColumnRef *b) _equalColumnRef(ColumnRef *a, ColumnRef *b)
{ {
COMPARE_NODE_FIELD(fields); COMPARE_NODE_FIELD(fields);
COMPARE_SCALAR_FIELD(location);
return true; return true;
} }
@ -1577,6 +1579,7 @@ _equalFuncCall(FuncCall *a, FuncCall *b)
COMPARE_NODE_FIELD(args); COMPARE_NODE_FIELD(args);
COMPARE_SCALAR_FIELD(agg_star); COMPARE_SCALAR_FIELD(agg_star);
COMPARE_SCALAR_FIELD(agg_distinct); COMPARE_SCALAR_FIELD(agg_distinct);
COMPARE_SCALAR_FIELD(location);
return true; return true;
} }
@ -1619,6 +1622,7 @@ _equalTypeName(TypeName *a, TypeName *b)
COMPARE_SCALAR_FIELD(pct_type); COMPARE_SCALAR_FIELD(pct_type);
COMPARE_SCALAR_FIELD(typmod); COMPARE_SCALAR_FIELD(typmod);
COMPARE_NODE_FIELD(arrayBounds); COMPARE_NODE_FIELD(arrayBounds);
COMPARE_SCALAR_FIELD(location);
return true; return true;
} }

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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 * makes an A_Expr node
*/ */
A_Expr * 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); 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->name = name;
a->lexpr = lexpr; a->lexpr = lexpr;
a->rexpr = rexpr; a->rexpr = rexpr;
a->location = location;
return a; return a;
} }
@ -42,7 +44,7 @@ makeA_Expr(A_Expr_Kind kind, List *name, Node *lexpr, Node *rexpr)
*/ */
A_Expr * A_Expr *
makeSimpleA_Expr(A_Expr_Kind kind, const char *name, 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); 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->name = list_make1(makeString((char *) name));
a->lexpr = lexpr; a->lexpr = lexpr;
a->rexpr = rexpr; a->rexpr = rexpr;
a->location = location;
return a; return a;
} }
@ -253,6 +256,8 @@ makeRangeVar(char *schemaname, char *relname)
/* /*
* makeTypeName - * makeTypeName -
* build a TypeName node for an unqualified name. * build a TypeName node for an unqualified name.
*
* typmod is defaulted, but can be changed later by caller.
*/ */
TypeName * TypeName *
makeTypeName(char *typnam) makeTypeName(char *typnam)
@ -261,6 +266,39 @@ makeTypeName(char *typnam)
n->names = list_make1(makeString(typnam)); n->names = list_make1(makeString(typnam));
n->typmod = -1; 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; return n;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * 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_NODE_FIELD(args);
WRITE_BOOL_FIELD(agg_star); WRITE_BOOL_FIELD(agg_star);
WRITE_BOOL_FIELD(agg_distinct); WRITE_BOOL_FIELD(agg_distinct);
WRITE_INT_FIELD(location);
} }
static void static void
@ -1449,6 +1450,7 @@ _outTypeName(StringInfo str, TypeName *node)
WRITE_BOOL_FIELD(pct_type); WRITE_BOOL_FIELD(pct_type);
WRITE_INT_FIELD(typmod); WRITE_INT_FIELD(typmod);
WRITE_NODE_FIELD(arrayBounds); WRITE_NODE_FIELD(arrayBounds);
/* location is deliberately not stored */
} }
static void static void
@ -1648,6 +1650,7 @@ _outAExpr(StringInfo str, A_Expr *node)
WRITE_NODE_FIELD(lexpr); WRITE_NODE_FIELD(lexpr);
WRITE_NODE_FIELD(rexpr); WRITE_NODE_FIELD(rexpr);
WRITE_INT_FIELD(location);
} }
static void static void
@ -1687,6 +1690,7 @@ _outColumnRef(StringInfo str, ColumnRef *node)
WRITE_NODE_TYPE("COLUMNREF"); WRITE_NODE_TYPE("COLUMNREF");
WRITE_NODE_FIELD(fields); WRITE_NODE_FIELD(fields);
WRITE_INT_FIELD(location);
} }
static void static void

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Path and Plan nodes do not have any readfuncs support, because we * Path and Plan nodes do not have any readfuncs support, because we
@ -893,6 +893,8 @@ _readTypeName(void)
READ_BOOL_FIELD(pct_type); READ_BOOL_FIELD(pct_type);
READ_INT_FIELD(typmod); READ_INT_FIELD(typmod);
READ_NODE_FIELD(arrayBounds); READ_NODE_FIELD(arrayBounds);
/* location is deliberately not stored */
local_node->location = -1;
READ_DONE(); READ_DONE();
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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); ltype = exprType(item1);
rtype = exprType(item2); rtype = exprType(item2);
eq_operator = compatible_oper(list_make1(makeString("=")), eq_operator = compatible_oper(NULL, list_make1(makeString("=")),
ltype, rtype, true); ltype, rtype,
true, -1);
if (!HeapTupleIsValid(eq_operator)) if (!HeapTupleIsValid(eq_operator))
{ {
/* /*

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -2637,7 +2637,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
if (list_length(raw_parsetree_list) != 1) if (list_length(raw_parsetree_list) != 1)
goto fail; goto fail;
querytree_list = parse_analyze(linitial(raw_parsetree_list), querytree_list = parse_analyze(linitial(raw_parsetree_list), src,
argtypes, funcform->pronargs); argtypes, funcform->pronargs);
if (list_length(querytree_list) != 1) if (list_length(querytree_list) != 1)

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 * parse_analyze
* Analyze a raw parse tree and transform it to Query form. * 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. * Optionally, information about $n parameter types can be supplied.
* References to $n indexes not defined by paramTypes[] are disallowed. * 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. * a dummy CMD_UTILITY Query node.
*/ */
List * 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); ParseState *pstate = make_parsestate(NULL);
List *result; List *result;
pstate->p_sourcetext = sourceText;
pstate->p_paramtypes = paramTypes; pstate->p_paramtypes = paramTypes;
pstate->p_numparams = numParams; pstate->p_numparams = numParams;
pstate->p_variableparams = false; pstate->p_variableparams = false;
@ -179,11 +184,13 @@ parse_analyze(Node *parseTree, Oid *paramTypes, int numParams)
* be modified or enlarged (via repalloc). * be modified or enlarged (via repalloc).
*/ */
List * 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); ParseState *pstate = make_parsestate(NULL);
List *result; List *result;
pstate->p_sourcetext = sourceText;
pstate->p_paramtypes = *paramTypes; pstate->p_paramtypes = *paramTypes;
pstate->p_numparams = *numParams; pstate->p_numparams = *numParams;
pstate->p_variableparams = true; pstate->p_variableparams = true;
@ -921,6 +928,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
funccallnode->args = list_make1(snamenode); funccallnode->args = list_make1(snamenode);
funccallnode->agg_star = false; funccallnode->agg_star = false;
funccallnode->agg_distinct = false; funccallnode->agg_distinct = false;
funccallnode->location = -1;
constraint = makeNode(Constraint); constraint = makeNode(Constraint);
constraint->contype = CONSTR_DEFAULT; constraint->contype = CONSTR_DEFAULT;
@ -1097,7 +1105,6 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1]; Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
char *attributeName = NameStr(attribute->attname); char *attributeName = NameStr(attribute->attname);
ColumnDef *def; ColumnDef *def;
TypeName *typename;
/* /*
* Ignore dropped columns in the parent. * Ignore dropped columns in the parent.
@ -1113,10 +1120,8 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
*/ */
def = makeNode(ColumnDef); def = makeNode(ColumnDef);
def->colname = pstrdup(attributeName); def->colname = pstrdup(attributeName);
typename = makeNode(TypeName); def->typename = makeTypeNameFromOid(attribute->atttypid,
typename->typeid = attribute->atttypid; attribute->atttypmod);
typename->typmod = attribute->atttypmod;
def->typename = typename;
def->inhcount = 0; def->inhcount = 0;
def->is_local = false; def->is_local = false;
def->is_not_null = attribute->attnotnull; def->is_not_null = attribute->attnotnull;
@ -2608,7 +2613,7 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt)
foreach(l, stmt->argtypes) foreach(l, stmt->argtypes)
{ {
TypeName *tn = lfirst(l); TypeName *tn = lfirst(l);
Oid toid = typenameTypeId(tn); Oid toid = typenameTypeId(pstate, tn);
argtoids[i++] = toid; argtoids[i++] = toid;
} }
@ -2621,6 +2626,7 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt)
* from context. * from context.
*/ */
queries = parse_analyze_varparams((Node *) stmt->query, queries = parse_analyze_varparams((Node *) stmt->query,
pstate->p_sourcetext,
&argtoids, &nargs); &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. * 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); ReleaseSysCache(ctype);
} }

View File

@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -61,6 +61,10 @@
#include "utils/numeric.h" #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 */ extern List *parsetree; /* final parse result is delivered here */
static bool QueryIsRule = FALSE; static bool QueryIsRule = FALSE;
@ -72,7 +76,7 @@ static bool QueryIsRule = FALSE;
*/ */
/*#define __YYSCLASS*/ /*#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 *makeTypeCast(Node *arg, TypeName *typename);
static Node *makeStringConst(char *str, TypeName *typename); static Node *makeStringConst(char *str, TypeName *typename);
static Node *makeIntConst(int val); static Node *makeIntConst(int val);
@ -81,7 +85,7 @@ static Node *makeAConst(Value *v);
static Node *makeRowNullTest(NullTestType test, RowExpr *row); static Node *makeRowNullTest(NullTestType test, RowExpr *row);
static DefElem *makeDefElem(char *name, Node *arg); static DefElem *makeDefElem(char *name, Node *arg);
static A_Const *makeBoolAConst(bool state); 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 void check_qualified_name(List *names);
static List *check_func_name(List *names); static List *check_func_name(List *names);
static List *extractArgTypes(List *parameters); static List *extractArgTypes(List *parameters);
@ -90,12 +94,13 @@ static void insertSelectOptions(SelectStmt *stmt,
List *sortClause, Node *lockingClause, List *sortClause, Node *lockingClause,
Node *limitOffset, Node *limitCount); Node *limitOffset, Node *limitCount);
static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg); 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); static void doNegateFloat(Value *v);
%} %}
%name-prefix="base_yy" %name-prefix="base_yy"
%locations
%union %union
{ {
@ -3705,6 +3710,7 @@ func_type: Typename { $$ = $1; }
$$->names = lcons(makeString($1), $2); $$->names = lcons(makeString($1), $2);
$$->pct_type = true; $$->pct_type = true;
$$->typmod = -1; $$->typmod = -1;
$$->location = @1;
} }
| SETOF type_name attrs '%' TYPE_P | SETOF type_name attrs '%' TYPE_P
{ {
@ -3713,6 +3719,7 @@ func_type: Typename { $$ = $1; }
$$->pct_type = true; $$->pct_type = true;
$$->typmod = -1; $$->typmod = -1;
$$->setof = TRUE; $$->setof = TRUE;
$$->location = @2;
} }
; ;
@ -6053,6 +6060,7 @@ SimpleTypename:
$$ = makeNode(TypeName); $$ = makeNode(TypeName);
$$->names = lcons(makeString($1), $2); $$->names = lcons(makeString($1), $2);
$$->typmod = -1; $$->typmod = -1;
$$->location = @1;
} }
; ;
@ -6077,6 +6085,7 @@ GenericType:
type_name type_name
{ {
$$ = makeTypeName($1); $$ = makeTypeName($1);
$$->location = @1;
} }
; ;
@ -6540,6 +6549,7 @@ a_expr: c_expr { $$ = $1; }
n->args = list_make2($5, $1); n->args = list_make2($5, $1);
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @2;
$$ = (Node *) n; $$ = (Node *) n;
} }
/* /*
@ -6552,44 +6562,44 @@ a_expr: c_expr { $$ = $1; }
* also to b_expr and to the MathOp list above. * also to b_expr and to the MathOp list above.
*/ */
| '+' a_expr %prec UMINUS | '+' a_expr %prec UMINUS
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1); }
| '-' a_expr %prec UMINUS | '-' a_expr %prec UMINUS
{ $$ = doNegate($2); } { $$ = doNegate($2, @1); }
| a_expr '+' a_expr | a_expr '+' a_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2); }
| a_expr '-' a_expr | a_expr '-' a_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2); }
| a_expr '*' a_expr | a_expr '*' a_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2); }
| a_expr '/' a_expr | a_expr '/' a_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2); }
| a_expr '%' a_expr | a_expr '%' a_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2); }
| a_expr '^' a_expr | a_expr '^' a_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2); }
| a_expr '<' a_expr | a_expr '<' a_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2); }
| a_expr '>' a_expr | a_expr '>' a_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); }
| a_expr '=' a_expr | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | a_expr LIKE a_expr ESCAPE a_expr
{ {
FuncCall *n = makeNode(FuncCall); FuncCall *n = makeNode(FuncCall);
@ -6597,10 +6607,11 @@ a_expr: c_expr { $$ = $1; }
n->args = list_make2($3, $5); n->args = list_make2($3, $5);
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = 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 | 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 | a_expr NOT LIKE a_expr ESCAPE a_expr
{ {
FuncCall *n = makeNode(FuncCall); FuncCall *n = makeNode(FuncCall);
@ -6608,10 +6619,11 @@ a_expr: c_expr { $$ = $1; }
n->args = list_make2($4, $6); n->args = list_make2($4, $6);
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = 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 | 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 | a_expr ILIKE a_expr ESCAPE a_expr
{ {
FuncCall *n = makeNode(FuncCall); FuncCall *n = makeNode(FuncCall);
@ -6619,10 +6631,11 @@ a_expr: c_expr { $$ = $1; }
n->args = list_make2($3, $5); n->args = list_make2($3, $5);
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = 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 | 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 | a_expr NOT ILIKE a_expr ESCAPE a_expr
{ {
FuncCall *n = makeNode(FuncCall); FuncCall *n = makeNode(FuncCall);
@ -6630,7 +6643,8 @@ a_expr: c_expr { $$ = $1; }
n->args = list_make2($4, $6); n->args = list_make2($4, $6);
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = 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 | 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->args = list_make2($4, (Node *) c);
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = 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 | 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->args = list_make2($4, $6);
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = 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 | 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->args = list_make2($5, (Node *) c);
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = 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 | 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->args = list_make2($5, $7);
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = 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 /* NullTest clause
@ -6733,7 +6751,7 @@ a_expr: c_expr { $$ = $1; }
} }
| row OVERLAPS row | row OVERLAPS row
{ {
$$ = (Node *)makeOverlaps($1, $3); $$ = (Node *)makeOverlaps($1, $3, @2);
} }
| a_expr IS TRUE_P | a_expr IS TRUE_P
{ {
@ -6779,54 +6797,63 @@ a_expr: c_expr { $$ = $1; }
} }
| a_expr IS DISTINCT FROM a_expr %prec IS | 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 | a_expr IS NOT DISTINCT FROM a_expr %prec IS
{ {
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
(Node *) makeSimpleA_Expr(AEXPR_DISTINCT, (Node *) makeSimpleA_Expr(AEXPR_DISTINCT,
"=", $1, $6)); "=", $1, $6, @2),
@2);
} }
| a_expr IS OF '(' type_list ')' %prec IS | 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 | 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 | a_expr BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN
{ {
$$ = (Node *) makeA_Expr(AEXPR_AND, NIL, $$ = (Node *) makeA_Expr(AEXPR_AND, NIL,
(Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4), (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4, @2),
(Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6)); (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6, @2),
@2);
} }
| a_expr NOT BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN | a_expr NOT BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN
{ {
$$ = (Node *) makeA_Expr(AEXPR_OR, NIL, $$ = (Node *) makeA_Expr(AEXPR_OR, NIL,
(Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5), (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5, @2),
(Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7)); (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7, @2),
@2);
} }
| a_expr BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN | a_expr BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN
{ {
$$ = (Node *) makeA_Expr(AEXPR_OR, NIL, $$ = (Node *) makeA_Expr(AEXPR_OR, NIL,
(Node *) makeA_Expr(AEXPR_AND, NIL, (Node *) makeA_Expr(AEXPR_AND, NIL,
(Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4), (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4, @2),
(Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6)), (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6, @2),
@2),
(Node *) makeA_Expr(AEXPR_AND, NIL, (Node *) makeA_Expr(AEXPR_AND, NIL,
(Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $6), (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $6, @2),
(Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $4))); (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $4, @2),
@2),
@2);
} }
| a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN | a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN
{ {
$$ = (Node *) makeA_Expr(AEXPR_AND, NIL, $$ = (Node *) makeA_Expr(AEXPR_AND, NIL,
(Node *) makeA_Expr(AEXPR_OR, NIL, (Node *) makeA_Expr(AEXPR_OR, NIL,
(Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5), (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5, @2),
(Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7)), (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7, @2),
@2),
(Node *) makeA_Expr(AEXPR_OR, NIL, (Node *) makeA_Expr(AEXPR_OR, NIL,
(Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $7), (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $7, @2),
(Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $5))); (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $5, @2),
@2),
@2);
} }
| a_expr IN_P in_expr | a_expr IN_P in_expr
{ {
@ -6843,7 +6870,7 @@ a_expr: c_expr { $$ = $1; }
else else
{ {
/* generate scalar IN expression */ /* 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 | a_expr NOT IN_P in_expr
@ -6858,12 +6885,12 @@ a_expr: c_expr { $$ = $1; }
n->testexpr = $1; n->testexpr = $1;
n->operName = list_make1(makeString("=")); n->operName = list_make1(makeString("="));
/* Stick a NOT on top */ /* 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 else
{ {
/* generate scalar NOT IN expression */ /* 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 | 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 | a_expr subquery_Op sub_type '(' a_expr ')' %prec Op
{ {
if ($3 == ANY_SUBLINK) if ($3 == ANY_SUBLINK)
$$ = (Node *) makeA_Expr(AEXPR_OP_ANY, $2, $1, $5); $$ = (Node *) makeA_Expr(AEXPR_OP_ANY, $2, $1, $5, @2);
else else
$$ = (Node *) makeA_Expr(AEXPR_OP_ALL, $2, $1, $5); $$ = (Node *) makeA_Expr(AEXPR_OP_ALL, $2, $1, $5, @2);
} }
| UNIQUE select_with_parens | UNIQUE select_with_parens
{ {
@ -6913,49 +6940,49 @@ b_expr: c_expr
| b_expr TYPECAST Typename | b_expr TYPECAST Typename
{ $$ = makeTypeCast($1, $3); } { $$ = makeTypeCast($1, $3); }
| '+' b_expr %prec UMINUS | '+' b_expr %prec UMINUS
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1); }
| '-' b_expr %prec UMINUS | '-' b_expr %prec UMINUS
{ $$ = doNegate($2); } { $$ = doNegate($2, @1); }
| b_expr '+' b_expr | b_expr '+' b_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2); }
| b_expr '-' b_expr | b_expr '-' b_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2); }
| b_expr '*' b_expr | b_expr '*' b_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2); }
| b_expr '/' b_expr | b_expr '/' b_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2); }
| b_expr '%' b_expr | b_expr '%' b_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2); }
| b_expr '^' b_expr | b_expr '^' b_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2); }
| b_expr '<' b_expr | b_expr '<' b_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2); }
| b_expr '>' b_expr | b_expr '>' b_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3); } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); }
| b_expr '=' b_expr | 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 | 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 | 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 | 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 | 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 | b_expr IS NOT DISTINCT FROM b_expr %prec IS
{ {
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, $$ = (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 | 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 | 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->args = NIL;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| func_name '(' expr_list ')' | func_name '(' expr_list ')'
@ -7061,6 +7089,7 @@ func_expr: func_name '(' ')'
n->args = $3; n->args = $3;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| func_name '(' ALL expr_list ')' | func_name '(' ALL expr_list ')'
@ -7074,6 +7103,7 @@ func_expr: func_name '(' ')'
* "must be an aggregate", but there's no provision * "must be an aggregate", but there's no provision
* for that in FuncCall at the moment. * for that in FuncCall at the moment.
*/ */
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| func_name '(' DISTINCT expr_list ')' | func_name '(' DISTINCT expr_list ')'
@ -7083,6 +7113,7 @@ func_expr: func_name '(' ')'
n->args = $4; n->args = $4;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = TRUE; n->agg_distinct = TRUE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| func_name '(' '*' ')' | func_name '(' '*' ')'
@ -7108,6 +7139,7 @@ func_expr: func_name '(' ')'
n->args = list_make1(star); n->args = list_make1(star);
n->agg_star = TRUE; n->agg_star = TRUE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| CURRENT_DATE | CURRENT_DATE
@ -7196,6 +7228,7 @@ func_expr: func_name '(' ')'
n->args = NIL; n->args = NIL;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| CURRENT_TIMESTAMP '(' Iconst ')' | CURRENT_TIMESTAMP '(' Iconst ')'
@ -7331,6 +7364,7 @@ func_expr: func_name '(' ')'
n->args = NIL; n->args = NIL;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| CURRENT_USER | CURRENT_USER
@ -7340,6 +7374,7 @@ func_expr: func_name '(' ')'
n->args = NIL; n->args = NIL;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| SESSION_USER | SESSION_USER
@ -7349,6 +7384,7 @@ func_expr: func_name '(' ')'
n->args = NIL; n->args = NIL;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| USER | USER
@ -7358,6 +7394,7 @@ func_expr: func_name '(' ')'
n->args = NIL; n->args = NIL;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| CAST '(' a_expr AS Typename ')' | CAST '(' a_expr AS Typename ')'
@ -7369,6 +7406,7 @@ func_expr: func_name '(' ')'
n->args = $3; n->args = $3;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| OVERLAY '(' overlay_list ')' | OVERLAY '(' overlay_list ')'
@ -7383,6 +7421,7 @@ func_expr: func_name '(' ')'
n->args = $3; n->args = $3;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| POSITION '(' position_list ')' | POSITION '(' position_list ')'
@ -7393,6 +7432,7 @@ func_expr: func_name '(' ')'
n->args = $3; n->args = $3;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| SUBSTRING '(' substr_list ')' | SUBSTRING '(' substr_list ')'
@ -7405,6 +7445,7 @@ func_expr: func_name '(' ')'
n->args = $3; n->args = $3;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| TREAT '(' a_expr AS Typename ')' | TREAT '(' a_expr AS Typename ')'
@ -7413,7 +7454,7 @@ func_expr: func_name '(' ')'
* which is defined to be a subtype of the original expression. * which is defined to be a subtype of the original expression.
* In SQL99, this is intended for use with structured UDTs, * In SQL99, this is intended for use with structured UDTs,
* but let's make this a generally useful form allowing stronger * 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); FuncCall *n = makeNode(FuncCall);
/* Convert SystemTypeName() to SystemFuncName() even though /* Convert SystemTypeName() to SystemFuncName() even though
@ -7421,6 +7462,9 @@ func_expr: func_name '(' ')'
*/ */
n->funcname = SystemFuncName(((Value *)llast($5->names))->val.str); n->funcname = SystemFuncName(((Value *)llast($5->names))->val.str);
n->args = list_make1($3); n->args = list_make1($3);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| TRIM '(' BOTH trim_list ')' | TRIM '(' BOTH trim_list ')'
@ -7433,6 +7477,7 @@ func_expr: func_name '(' ')'
n->args = $4; n->args = $4;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| TRIM '(' LEADING trim_list ')' | TRIM '(' LEADING trim_list ')'
@ -7442,6 +7487,7 @@ func_expr: func_name '(' ')'
n->args = $4; n->args = $4;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| TRIM '(' TRAILING trim_list ')' | TRIM '(' TRAILING trim_list ')'
@ -7451,6 +7497,7 @@ func_expr: func_name '(' ')'
n->args = $4; n->args = $4;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| TRIM '(' trim_list ')' | TRIM '(' trim_list ')'
@ -7460,6 +7507,7 @@ func_expr: func_name '(' ')'
n->args = $3; n->args = $3;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| CONVERT '(' a_expr USING any_name ')' | CONVERT '(' a_expr USING any_name ')'
@ -7474,6 +7522,7 @@ func_expr: func_name '(' ')'
n->args = list_make2($3, c); n->args = list_make2($3, c);
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| CONVERT '(' expr_list ')' | CONVERT '(' expr_list ')'
@ -7483,11 +7532,12 @@ func_expr: func_name '(' ')'
n->args = $3; n->args = $3;
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| NULLIF '(' a_expr ',' a_expr ')' | NULLIF '(' a_expr ',' a_expr ')'
{ {
$$ = (Node *) makeSimpleA_Expr(AEXPR_NULLIF, "=", $3, $5); $$ = (Node *) makeSimpleA_Expr(AEXPR_NULLIF, "=", $3, $5, @1);
} }
| COALESCE '(' expr_list ')' | COALESCE '(' expr_list ')'
{ {
@ -7797,11 +7847,11 @@ case_arg: a_expr { $$ = $1; }
*/ */
columnref: relation_name columnref: relation_name
{ {
$$ = makeColumnRef($1, NIL); $$ = makeColumnRef($1, NIL, @1);
} }
| relation_name indirection | relation_name indirection
{ {
$$ = makeColumnRef($1, $2); $$ = makeColumnRef($1, $2, @1);
} }
; ;
@ -7875,6 +7925,7 @@ target_el: a_expr AS ColLabel
{ {
ColumnRef *n = makeNode(ColumnRef); ColumnRef *n = makeNode(ColumnRef);
n->fields = list_make1(makeString("*")); n->fields = list_make1(makeString("*"));
n->location = @1;
$$ = makeNode(ResTarget); $$ = makeNode(ResTarget);
$$->name = NULL; $$->name = NULL;
@ -8585,7 +8636,7 @@ SpecialRuleRelation:
%% %%
static Node * 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 * Generate a ColumnRef node, with an A_Indirection node added if there
@ -8597,6 +8648,7 @@ makeColumnRef(char *relname, List *indirection)
int nfields = 0; int nfields = 0;
ListCell *l; ListCell *l;
c->location = location;
foreach(l, indirection) foreach(l, indirection)
{ {
if (IsA(lfirst(l), A_Indices)) if (IsA(lfirst(l), A_Indices))
@ -8750,9 +8802,9 @@ makeRowNullTest(NullTestType test, RowExpr *row)
if (result == NULL) if (result == NULL)
result = (Node *) n; result = (Node *) n;
else if (test == IS_NOT_NULL) 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 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) if (result == NULL)
@ -8768,9 +8820,10 @@ makeRowNullTest(NullTestType test, RowExpr *row)
* Create and populate a FuncCall node to support the OVERLAPS operator. * Create and populate a FuncCall node to support the OVERLAPS operator.
*/ */
static FuncCall * static FuncCall *
makeOverlaps(List *largs, List *rargs) makeOverlaps(List *largs, List *rargs, int location)
{ {
FuncCall *n = makeNode(FuncCall); FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("overlaps"); n->funcname = SystemFuncName("overlaps");
if (list_length(largs) == 1) if (list_length(largs) == 1)
largs = lappend(largs, largs); largs = lappend(largs, largs);
@ -8787,6 +8840,7 @@ makeOverlaps(List *largs, List *rargs)
n->args = list_concat(largs, rargs); n->args = list_concat(largs, rargs);
n->agg_star = FALSE; n->agg_star = FALSE;
n->agg_distinct = FALSE; n->agg_distinct = FALSE;
n->location = location;
return n; return n;
} }
@ -8944,6 +8998,7 @@ SystemTypeName(char *name)
n->names = list_make2(makeString("pg_catalog"), makeString(name)); n->names = list_make2(makeString("pg_catalog"), makeString(name));
n->typmod = -1; n->typmod = -1;
n->location = -1;
return n; return n;
} }
@ -8987,7 +9042,7 @@ exprIsNullConstant(Node *arg)
* until we know what the desired type is. * until we know what the desired type is.
*/ */
static Node * static Node *
doNegate(Node *n) doNegate(Node *n, int location)
{ {
if (IsA(n, A_Const)) 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 static void

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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); Node *rvar = (Node *) lfirst(rvars);
A_Expr *e; 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) if (result == NULL)
result = (Node *) e; result = (Node *) e;
@ -311,7 +313,7 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars)
{ {
A_Expr *a; 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; result = (Node *) a;
} }
} }
@ -1182,6 +1184,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause)
list_length(((ColumnRef *) node)->fields) == 1) list_length(((ColumnRef *) node)->fields) == 1)
{ {
char *name = strVal(linitial(((ColumnRef *) node)->fields)); char *name = strVal(linitial(((ColumnRef *) node)->fields));
int location = ((ColumnRef *) node)->location;
if (clause == GROUP_CLAUSE) 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 * breaks no cases that are legal per spec, and it seems a more
* self-consistent behavior. * self-consistent behavior.
*/ */
if (colNameToVar(pstate, name, true) != NULL) if (colNameToVar(pstate, name, true, location) != NULL)
name = NULL; name = NULL;
} }
@ -1225,7 +1228,8 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause)
* construct, eg ORDER BY * construct, eg ORDER BY
*/ */
errmsg("%s \"%s\" is ambiguous", errmsg("%s \"%s\" is ambiguous",
clauseText[clause], name))); clauseText[clause], name),
parser_errposition(pstate, location)));
} }
else else
target_result = tle; target_result = tle;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 *transformBooleanTest(ParseState *pstate, BooleanTest *b);
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref); static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
static Node *transformWholeRowRef(ParseState *pstate, char *schemaname, static Node *transformWholeRowRef(ParseState *pstate, char *schemaname,
char *relname); char *relname, int location);
static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b); static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
static Node *transformIndirection(ParseState *pstate, Node *basenode, static Node *transformIndirection(ParseState *pstate, Node *basenode,
List *indirection); List *indirection);
static Node *typecast_expression(ParseState *pstate, Node *expr, static Node *typecast_expression(ParseState *pstate, Node *expr,
TypeName *typename); TypeName *typename);
static Node *make_row_comparison_op(ParseState *pstate, List *opname, 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, 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, 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, result = ParseFuncOrColumn(pstate,
list_make1(n), list_make1(n),
list_make1(result), list_make1(result),
false, false, true); false, false, true,
-1);
} }
} }
/* process trailing subscripts, if any */ /* process trailing subscripts, if any */
@ -361,7 +362,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
char *name = strVal(linitial(cref->fields)); char *name = strVal(linitial(cref->fields));
/* Try to identify as an unqualified column */ /* Try to identify as an unqualified column */
node = colNameToVar(pstate, name, false); node = colNameToVar(pstate, name, false, cref->location);
if (node == NULL) if (node == NULL)
{ {
@ -391,12 +392,14 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
*/ */
if (refnameRangeTblEntry(pstate, NULL, name, if (refnameRangeTblEntry(pstate, NULL, name,
&levels_up) != NULL) &levels_up) != NULL)
node = transformWholeRowRef(pstate, NULL, name); node = transformWholeRowRef(pstate, NULL, name,
cref->location);
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN), (errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" does not exist", errmsg("column \"%s\" does not exist",
name))); name),
parser_errposition(pstate, cref->location)));
} }
break; break;
} }
@ -408,12 +411,14 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
/* Whole-row reference? */ /* Whole-row reference? */
if (strcmp(name2, "*") == 0) if (strcmp(name2, "*") == 0)
{ {
node = transformWholeRowRef(pstate, NULL, name1); node = transformWholeRowRef(pstate, NULL, name1,
cref->location);
break; break;
} }
/* Try to identify as a once-qualified column */ /* 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) if (node == NULL)
{ {
/* /*
@ -421,11 +426,13 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
* it as a function call. Here, we will create an * it as a function call. Here, we will create an
* implicit RTE for tables not already entered. * implicit RTE for tables not already entered.
*/ */
node = transformWholeRowRef(pstate, NULL, name1); node = transformWholeRowRef(pstate, NULL, name1,
cref->location);
node = ParseFuncOrColumn(pstate, node = ParseFuncOrColumn(pstate,
list_make1(makeString(name2)), list_make1(makeString(name2)),
list_make1(node), list_make1(node),
false, false, true); false, false, true,
cref->location);
} }
break; break;
} }
@ -438,20 +445,24 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
/* Whole-row reference? */ /* Whole-row reference? */
if (strcmp(name3, "*") == 0) if (strcmp(name3, "*") == 0)
{ {
node = transformWholeRowRef(pstate, name1, name2); node = transformWholeRowRef(pstate, name1, name2,
cref->location);
break; break;
} }
/* Try to identify as a twice-qualified column */ /* 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) if (node == NULL)
{ {
/* Try it as a function call */ /* Try it as a function call */
node = transformWholeRowRef(pstate, name1, name2); node = transformWholeRowRef(pstate, name1, name2,
cref->location);
node = ParseFuncOrColumn(pstate, node = ParseFuncOrColumn(pstate,
list_make1(makeString(name3)), list_make1(makeString(name3)),
list_make1(node), list_make1(node),
false, false, true); false, false, true,
cref->location);
} }
break; break;
} }
@ -469,25 +480,30 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cross-database references are not implemented: %s", errmsg("cross-database references are not implemented: %s",
NameListToString(cref->fields)))); NameListToString(cref->fields)),
parser_errposition(pstate, cref->location)));
/* Whole-row reference? */ /* Whole-row reference? */
if (strcmp(name4, "*") == 0) if (strcmp(name4, "*") == 0)
{ {
node = transformWholeRowRef(pstate, name2, name3); node = transformWholeRowRef(pstate, name2, name3,
cref->location);
break; break;
} }
/* Try to identify as a twice-qualified column */ /* 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) if (node == NULL)
{ {
/* Try it as a function call */ /* Try it as a function call */
node = transformWholeRowRef(pstate, name2, name3); node = transformWholeRowRef(pstate, name2, name3,
cref->location);
node = ParseFuncOrColumn(pstate, node = ParseFuncOrColumn(pstate,
list_make1(makeString(name4)), list_make1(makeString(name4)),
list_make1(node), list_make1(node),
false, false, true); false, false, true,
cref->location);
} }
break; break;
} }
@ -495,7 +511,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("improper qualified name (too many dotted names): %s", 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 */ node = NULL; /* keep compiler quiet */
break; break;
} }
@ -614,7 +631,8 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
result = make_row_comparison_op(pstate, result = make_row_comparison_op(pstate,
a->name, a->name,
((RowExpr *) lexpr)->args, ((RowExpr *) lexpr)->args,
((RowExpr *) rexpr)->args); ((RowExpr *) rexpr)->args,
a->location);
} }
else else
{ {
@ -625,7 +643,8 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
result = (Node *) make_op(pstate, result = (Node *) make_op(pstate,
a->name, a->name,
lexpr, lexpr,
rexpr); rexpr,
a->location);
} }
return result; return result;
@ -678,7 +697,8 @@ transformAExprOpAny(ParseState *pstate, A_Expr *a)
a->name, a->name,
true, true,
lexpr, lexpr,
rexpr); rexpr,
a->location);
} }
static Node * static Node *
@ -691,7 +711,8 @@ transformAExprOpAll(ParseState *pstate, A_Expr *a)
a->name, a->name,
false, false,
lexpr, lexpr,
rexpr); rexpr,
a->location);
} }
static Node * static Node *
@ -706,7 +727,8 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a)
/* "row op row" */ /* "row op row" */
return make_row_distinct_op(pstate, a->name, return make_row_distinct_op(pstate, a->name,
(RowExpr *) lexpr, (RowExpr *) lexpr,
(RowExpr *) rexpr); (RowExpr *) rexpr,
a->location);
} }
else else
{ {
@ -714,7 +736,8 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a)
return (Node *) make_distinct_op(pstate, return (Node *) make_distinct_op(pstate,
a->name, a->name,
lexpr, lexpr,
rexpr); rexpr,
a->location);
} }
} }
@ -728,11 +751,13 @@ transformAExprNullIf(ParseState *pstate, A_Expr *a)
result = (Node *) make_op(pstate, result = (Node *) make_op(pstate,
a->name, a->name,
lexpr, lexpr,
rexpr); rexpr,
a->location);
if (((OpExpr *) result)->opresulttype != BOOLOID) if (((OpExpr *) result)->opresulttype != BOOLOID)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (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 * We rely on NullIfExpr and OpExpr being the same struct
@ -758,7 +783,7 @@ transformAExprOf(ParseState *pstate, A_Expr *a)
ltype = exprType(lexpr); ltype = exprType(lexpr);
foreach(telem, (List *) a->rexpr) foreach(telem, (List *) a->rexpr)
{ {
rtype = LookupTypeName(lfirst(telem)); rtype = typenameTypeId(pstate, lfirst(telem));
matched = (rtype == ltype); matched = (rtype == ltype);
if (matched) if (matched)
break; break;
@ -864,7 +889,8 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
a->name, a->name,
useOr, useOr,
lexpr, lexpr,
(Node *) newa); (Node *) newa,
a->location);
} }
} }
@ -883,17 +909,20 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
!IsA(rexpr, RowExpr)) !IsA(rexpr, RowExpr))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_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, cmp = make_row_comparison_op(pstate,
a->name, a->name,
(List *) copyObject(((RowExpr *) lexpr)->args), (List *) copyObject(((RowExpr *) lexpr)->args),
((RowExpr *) rexpr)->args); ((RowExpr *) rexpr)->args,
a->location);
} }
else else
cmp = (Node *) make_op(pstate, cmp = (Node *) make_op(pstate,
a->name, a->name,
copyObject(lexpr), copyObject(lexpr),
rexpr); rexpr,
a->location);
cmp = coerce_to_boolean(pstate, cmp, "IN"); cmp = coerce_to_boolean(pstate, cmp, "IN");
if (result == NULL) if (result == NULL)
@ -931,7 +960,8 @@ transformFuncCall(ParseState *pstate, FuncCall *fn)
targs, targs,
fn->agg_star, fn->agg_star,
fn->agg_distinct, fn->agg_distinct,
false); false,
fn->location);
} }
static Node * static Node *
@ -994,7 +1024,8 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
/* shorthand form was specified, so expand... */ /* shorthand form was specified, so expand... */
warg = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", warg = (Node *) makeSimpleA_Expr(AEXPR_OP, "=",
(Node *) placeholder, (Node *) placeholder,
warg); warg,
-1);
} }
neww->expr = (Expr *) transformExpr(pstate, warg); neww->expr = (Expr *) transformExpr(pstate, warg);
@ -1173,7 +1204,8 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
sublink->testexpr = make_row_comparison_op(pstate, sublink->testexpr = make_row_comparison_op(pstate,
sublink->operName, sublink->operName,
left_list, left_list,
right_list); right_list,
-1);
} }
return result; return result;
@ -1394,7 +1426,8 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b)
* a rowtype; either a named composite type, or RECORD. * a rowtype; either a named composite type, or RECORD.
*/ */
static Node * static Node *
transformWholeRowRef(ParseState *pstate, char *schemaname, char *relname) transformWholeRowRef(ParseState *pstate, char *schemaname, char *relname,
int location)
{ {
Node *result; Node *result;
RangeTblEntry *rte; RangeTblEntry *rte;
@ -1408,7 +1441,8 @@ transformWholeRowRef(ParseState *pstate, char *schemaname, char *relname)
&sublevels_up); &sublevels_up);
if (rte == NULL) if (rte == NULL)
rte = addImplicitRTE(pstate, makeRangeVar(schemaname, relname)); rte = addImplicitRTE(pstate, makeRangeVar(schemaname, relname),
location);
vnum = RTERangeTablePosn(pstate, rte, &sublevels_up); vnum = RTERangeTablePosn(pstate, rte, &sublevels_up);
@ -1877,7 +1911,7 @@ typecast_expression(ParseState *pstate, Node *expr, TypeName *typename)
Oid inputType = exprType(expr); Oid inputType = exprType(expr);
Oid targetType; Oid targetType;
targetType = typenameTypeId(typename); targetType = typenameTypeId(pstate, typename);
if (inputType == InvalidOid) if (inputType == InvalidOid)
return expr; /* do nothing if NULL input */ return expr; /* do nothing if NULL input */
@ -1891,7 +1925,8 @@ typecast_expression(ParseState *pstate, Node *expr, TypeName *typename)
(errcode(ERRCODE_CANNOT_COERCE), (errcode(ERRCODE_CANNOT_COERCE),
errmsg("cannot cast type %s to %s", errmsg("cannot cast type %s to %s",
format_type_be(inputType), format_type_be(inputType),
format_type_be(targetType)))); format_type_be(targetType)),
parser_errposition(pstate, typename->location)));
return expr; return expr;
} }
@ -1910,7 +1945,7 @@ typecast_expression(ParseState *pstate, Node *expr, TypeName *typename)
*/ */
static Node * static Node *
make_row_comparison_op(ParseState *pstate, List *opname, make_row_comparison_op(ParseState *pstate, List *opname,
List *largs, List *rargs) List *largs, List *rargs, int location)
{ {
RowCompareExpr *rcexpr; RowCompareExpr *rcexpr;
RowCompareType rctype; RowCompareType rctype;
@ -1929,7 +1964,8 @@ make_row_comparison_op(ParseState *pstate, List *opname,
if (nopers != list_length(rargs)) if (nopers != list_length(rargs))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_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 * 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) if (nopers == 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (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 * 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); Node *rarg = (Node *) lfirst(r);
OpExpr *cmp; OpExpr *cmp;
cmp = (OpExpr *) make_op(pstate, opname, larg, rarg); cmp = (OpExpr *) make_op(pstate, opname, larg, rarg, location);
Assert(IsA(cmp, OpExpr)); Assert(IsA(cmp, OpExpr));
/* /*
@ -1964,11 +2001,13 @@ make_row_comparison_op(ParseState *pstate, List *opname,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("row comparison operator must yield type boolean, " errmsg("row comparison operator must yield type boolean, "
"not type %s", "not type %s",
format_type_be(cmp->opresulttype)))); format_type_be(cmp->opresulttype)),
parser_errposition(pstate, location)));
if (expression_returns_set((Node *) cmp)) if (expression_returns_set((Node *) cmp))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (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); opexprs = lappend(opexprs, cmp);
} }
@ -2021,7 +2060,8 @@ make_row_comparison_op(ParseState *pstate, List *opname,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("could not determine interpretation of row comparison operator %s", errmsg("could not determine interpretation of row comparison operator %s",
strVal(llast(opname))), 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 */ rctype = 0; /* keep compiler quiet */
break; break;
case BMS_SINGLETON: case BMS_SINGLETON:
@ -2069,7 +2109,8 @@ make_row_comparison_op(ParseState *pstate, List *opname,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("could not determine interpretation of row comparison operator %s", errmsg("could not determine interpretation of row comparison operator %s",
strVal(llast(opname))), strVal(llast(opname))),
errdetail("There are multiple equally-plausible candidates."))); errdetail("There are multiple equally-plausible candidates."),
parser_errposition(pstate, location)));
break; break;
} }
} }
@ -2120,7 +2161,8 @@ make_row_comparison_op(ParseState *pstate, List *opname,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("could not determine interpretation of row comparison operator %s", errmsg("could not determine interpretation of row comparison operator %s",
strVal(llast(opname))), 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 * static Node *
make_row_distinct_op(ParseState *pstate, List *opname, make_row_distinct_op(ParseState *pstate, List *opname,
RowExpr *lrow, RowExpr *rrow) RowExpr *lrow, RowExpr *rrow,
int location)
{ {
Node *result = NULL; Node *result = NULL;
List *largs = lrow->args; List *largs = lrow->args;
@ -2169,7 +2212,8 @@ make_row_distinct_op(ParseState *pstate, List *opname,
if (list_length(largs) != list_length(rargs)) if (list_length(largs) != list_length(rargs))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_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) forboth(l, largs, r, rargs)
{ {
@ -2177,7 +2221,7 @@ make_row_distinct_op(ParseState *pstate, List *opname,
Node *rarg = (Node *) lfirst(r); Node *rarg = (Node *) lfirst(r);
Node *cmp; Node *cmp;
cmp = (Node *) make_distinct_op(pstate, opname, larg, rarg); cmp = (Node *) make_distinct_op(pstate, opname, larg, rarg, location);
if (result == NULL) if (result == NULL)
result = cmp; result = cmp;
else else
@ -2198,15 +2242,17 @@ make_row_distinct_op(ParseState *pstate, List *opname,
* make the node for an IS DISTINCT FROM operator * make the node for an IS DISTINCT FROM operator
*/ */
static Expr * 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; Expr *result;
result = make_op(pstate, opname, ltree, rtree); result = make_op(pstate, opname, ltree, rtree, location);
if (((OpExpr *) result)->opresulttype != BOOLOID) if (((OpExpr *) result)->opresulttype != BOOLOID)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (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 * We rely on DistinctExpr and OpExpr being same struct

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, static Node *ParseComplexProjection(ParseState *pstate, char *funcname,
Node *first_arg); Node *first_arg, int location);
static void unknown_attribute(ParseState *pstate, Node *relref, char *attname); 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 * Node *
ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, 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 rettype;
Oid funcid; Oid funcid;
@ -83,7 +85,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS), (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg("cannot pass more than %d arguments to a function", 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. * Extract arg type info in preparation for function lookup.
@ -131,7 +134,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
{ {
retval = ParseComplexProjection(pstate, retval = ParseComplexProjection(pstate,
strVal(linitial(funcname)), strVal(linitial(funcname)),
first_arg); first_arg,
location);
if (retval) if (retval)
return retval; return retval;
@ -174,12 +178,14 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s(*) specified, but %s is not an aggregate function", errmsg("%s(*) specified, but %s is not an aggregate function",
NameListToString(funcname), NameListToString(funcname),
NameListToString(funcname)))); NameListToString(funcname)),
parser_errposition(pstate, location)));
if (agg_distinct) if (agg_distinct)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("DISTINCT specified, but %s is not an aggregate function", errmsg("DISTINCT specified, but %s is not an aggregate function",
NameListToString(funcname)))); NameListToString(funcname)),
parser_errposition(pstate, location)));
} }
else if (fdresult != FUNCDETAIL_AGGREGATE) else if (fdresult != FUNCDETAIL_AGGREGATE)
{ {
@ -193,7 +199,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
{ {
Assert(nargs == 1); Assert(nargs == 1);
Assert(list_length(funcname) == 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, func_signature_string(funcname, nargs,
actual_arg_types)), actual_arg_types)),
errhint("Could not choose a best candidate function. " 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 else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION), (errcode(ERRCODE_UNDEFINED_FUNCTION),
@ -214,7 +222,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
func_signature_string(funcname, nargs, func_signature_string(funcname, nargs,
actual_arg_types)), actual_arg_types)),
errhint("No function matches the given name and argument 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) if (retset)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("aggregates may not return sets"))); errmsg("aggregates may not return sets"),
parser_errposition(pstate, location)));
} }
return retval; return retval;
@ -726,11 +736,9 @@ func_get_detail(List *funcname,
if (nargs == 1 && fargs != NIL) if (nargs == 1 && fargs != NIL)
{ {
Oid targetType; Oid targetType;
TypeName *tn = makeNode(TypeName);
tn->names = funcname; targetType = LookupTypeName(NULL,
tn->typmod = -1; makeTypeNameFromNameList(funcname));
targetType = LookupTypeName(tn);
if (OidIsValid(targetType) && if (OidIsValid(targetType) &&
!ISCOMPLEX(targetType)) !ISCOMPLEX(targetType))
{ {
@ -953,7 +961,8 @@ make_fn_arguments(ParseState *pstate,
* transformed expression tree. If not, return NULL. * transformed expression tree. If not, return NULL.
*/ */
static Node * static Node *
ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg) ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg,
int location)
{ {
TupleDesc tupdesc; TupleDesc tupdesc;
int i; int i;
@ -977,7 +986,7 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg)
((Var *) first_arg)->varno, ((Var *) first_arg)->varno,
((Var *) first_arg)->varlevelsup); ((Var *) first_arg)->varlevelsup);
/* Return a Var if funcname matches a column, else NULL */ /* 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 * helper routine for delivering "column does not exist" error message
*/ */
static void static void
unknown_attribute(ParseState *pstate, Node *relref, char *attname) unknown_attribute(ParseState *pstate, Node *relref, char *attname,
int location)
{ {
RangeTblEntry *rte; RangeTblEntry *rte;
@ -1033,7 +1043,8 @@ unknown_attribute(ParseState *pstate, Node *relref, char *attname)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN), (errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column %s.%s does not exist", errmsg("column %s.%s does not exist",
rte->eref->aliasname, attname))); rte->eref->aliasname, attname),
parser_errposition(pstate, location)));
} }
else else
{ {
@ -1044,18 +1055,21 @@ unknown_attribute(ParseState *pstate, Node *relref, char *attname)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN), (errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" not found in data type %s", 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) else if (relTypeId == RECORDOID)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN), (errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("could not identify column \"%s\" in record data type", errmsg("could not identify column \"%s\" in record data type",
attname))); attname),
parser_errposition(pstate, location)));
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("column notation .%s applied to type %s, " errmsg("column notation .%s applied to type %s, "
"which is not a composite type", "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); TypeName *t = (TypeName *) lfirst(args_item);
argoids[i] = LookupTypeName(t); argoids[i] = LookupTypeName(NULL, t);
if (!OidIsValid(argoids[i])) if (!OidIsValid(argoids[i]))
ereport(ERROR, ereport(ERROR,

View File

@ -8,13 +8,14 @@
* *
* *
* IDENTIFICATION * 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 "postgres.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "mb/pg_wchar.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "parser/parsetree.h" #include "parser/parsetree.h"
#include "parser/parse_coerce.h" #include "parser/parse_coerce.h"
@ -44,12 +45,46 @@ make_parsestate(ParseState *parentParseState)
pstate->p_next_resno = 1; pstate->p_next_resno = 1;
if (parentParseState) if (parentParseState)
{
pstate->p_sourcetext = parentParseState->p_sourcetext;
pstate->p_variableparams = parentParseState->p_variableparams; pstate->p_variableparams = parentParseState->p_variableparams;
}
return pstate; 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 * make_var
* Build a Var node for an attribute identified by RTE and attrno * Build a Var node for an attribute identified by RTE and attrno

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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); Oid *operOid);
static const char *op_signature_string(List *op, char oprkind, static const char *op_signature_string(List *op, char oprkind,
Oid arg1, Oid arg2); Oid arg1, Oid arg2);
static void op_error(List *op, char oprkind, Oid arg1, Oid arg2, static void op_error(ParseState *pstate, List *op, char oprkind,
FuncDetailCode fdresult); Oid arg1, Oid arg2,
FuncDetailCode fdresult, int location);
static Expr *make_op_expr(ParseState *pstate, Operator op, static Expr *make_op_expr(ParseState *pstate, Operator op,
Node *ltree, Node *rtree, Node *ltree, Node *rtree,
Oid ltypeId, Oid rtypeId); Oid ltypeId, Oid rtypeId);
@ -56,10 +57,12 @@ static Expr *make_op_expr(ParseState *pstate, Operator op,
* namespace search path. * namespace search path.
* *
* If the operator is not found, we return InvalidOid if noError is true, * 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 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; FuncCandidateList clist;
char oprkind; char oprkind;
@ -86,7 +89,8 @@ LookupOperName(List *opername, Oid oprleft, Oid oprright, bool noError)
(errcode(ERRCODE_UNDEFINED_FUNCTION), (errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("operator does not exist: %s", errmsg("operator does not exist: %s",
op_signature_string(opername, oprkind, op_signature_string(opername, oprkind,
oprleft, oprright)))); oprleft, oprright)),
parser_errposition(pstate, location)));
return InvalidOid; 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. * Pass oprleft = NULL for a prefix op, oprright = NULL for a postfix op.
*/ */
Oid Oid
LookupOperNameTypeNames(List *opername, TypeName *oprleft, LookupOperNameTypeNames(ParseState *pstate, List *opername,
TypeName *oprright, bool noError) TypeName *oprleft, TypeName *oprright,
bool noError, int location)
{ {
Oid leftoid, Oid leftoid,
rightoid; rightoid;
@ -108,27 +113,15 @@ LookupOperNameTypeNames(List *opername, TypeName *oprleft,
if (oprleft == NULL) if (oprleft == NULL)
leftoid = InvalidOid; leftoid = InvalidOid;
else else
{ leftoid = typenameTypeId(pstate, oprleft);
leftoid = LookupTypeName(oprleft);
if (!OidIsValid(leftoid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type %s does not exist",
TypeNameToString(oprleft))));
}
if (oprright == NULL) if (oprright == NULL)
rightoid = InvalidOid; rightoid = InvalidOid;
else else
{ rightoid = typenameTypeId(pstate, oprright);
rightoid = LookupTypeName(oprright);
if (!OidIsValid(rightoid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type %s does not exist",
TypeNameToString(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. * you need an exact- or binary-compatible match; see compatible_oper.
* *
* If no matching operator found, return NULL if noError is true, * 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 * NOTE: on success, the returned object is a syscache entry. The caller
* must ReleaseSysCache() the entry when done with it. * must ReleaseSysCache() the entry when done with it.
*/ */
Operator 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; FuncCandidateList clist;
Oid inputOids[2]; Oid inputOids[2];
@ -549,7 +544,7 @@ oper(List *opname, Oid ltypeId, Oid rtypeId, bool noError)
} }
if (!HeapTupleIsValid(tup) && !noError) if (!HeapTupleIsValid(tup) && !noError)
op_error(opname, 'b', ltypeId, rtypeId, fdresult); op_error(pstate, opname, 'b', ltypeId, rtypeId, fdresult, location);
return (Operator) tup; return (Operator) tup;
} }
@ -562,13 +557,14 @@ oper(List *opname, Oid ltypeId, Oid rtypeId, bool noError)
* are accepted). Otherwise, the semantics are the same. * are accepted). Otherwise, the semantics are the same.
*/ */
Operator 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; Operator optup;
Form_pg_operator opform; Form_pg_operator opform;
/* oper() will find the best available match */ /* 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) if (optup == (Operator) NULL)
return (Operator) NULL; /* must be noError case */ return (Operator) NULL; /* must be noError case */
@ -585,7 +581,8 @@ compatible_oper(List *op, Oid arg1, Oid arg2, bool noError)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION), (errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("operator requires run-time type coercion: %s", 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; return (Operator) NULL;
} }
@ -602,7 +599,7 @@ compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError)
Operator optup; Operator optup;
Oid result; Oid result;
optup = compatible_oper(op, arg1, arg2, noError); optup = compatible_oper(NULL, op, arg1, arg2, noError, -1);
if (optup != NULL) if (optup != NULL)
{ {
result = oprid(optup); 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. * you need an exact- or binary-compatible match.
* *
* If no matching operator found, return NULL if noError is true, * 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 * NOTE: on success, the returned object is a syscache entry. The caller
* must ReleaseSysCache() the entry when done with it. * must ReleaseSysCache() the entry when done with it.
*/ */
Operator Operator
right_oper(List *op, Oid arg, bool noError) right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
{ {
FuncCandidateList clist; FuncCandidateList clist;
Oid operOid = InvalidOid; Oid operOid = InvalidOid;
@ -669,7 +667,7 @@ right_oper(List *op, Oid arg, bool noError)
} }
if (!HeapTupleIsValid(tup) && !noError) if (!HeapTupleIsValid(tup) && !noError)
op_error(op, 'r', arg, InvalidOid, fdresult); op_error(pstate, op, 'r', arg, InvalidOid, fdresult, location);
return (Operator) tup; return (Operator) tup;
} }
@ -683,13 +681,14 @@ right_oper(List *op, Oid arg, bool noError)
* you need an exact- or binary-compatible match. * you need an exact- or binary-compatible match.
* *
* If no matching operator found, return NULL if noError is true, * 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 * NOTE: on success, the returned object is a syscache entry. The caller
* must ReleaseSysCache() the entry when done with it. * must ReleaseSysCache() the entry when done with it.
*/ */
Operator Operator
left_oper(List *op, Oid arg, bool noError) left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
{ {
FuncCandidateList clist; FuncCandidateList clist;
Oid operOid = InvalidOid; Oid operOid = InvalidOid;
@ -736,7 +735,7 @@ left_oper(List *op, Oid arg, bool noError)
} }
if (!HeapTupleIsValid(tup) && !noError) if (!HeapTupleIsValid(tup) && !noError)
op_error(op, 'l', InvalidOid, arg, fdresult); op_error(pstate, op, 'l', InvalidOid, arg, fdresult, location);
return (Operator) tup; 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 * op_error - utility routine to complain about an unresolvable operator
*/ */
static void 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) if (fdresult == FUNCDETAIL_MULTIPLE)
ereport(ERROR, ereport(ERROR,
@ -779,14 +780,16 @@ op_error(List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult)
errmsg("operator is not unique: %s", errmsg("operator is not unique: %s",
op_signature_string(op, oprkind, arg1, arg2)), op_signature_string(op, oprkind, arg1, arg2)),
errhint("Could not choose a best candidate operator. " 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 else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION), (errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("operator does not exist: %s", errmsg("operator does not exist: %s",
op_signature_string(op, oprkind, arg1, arg2)), op_signature_string(op, oprkind, arg1, arg2)),
errhint("No operator matches the given name and argument type(s). " 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. * processing is wanted.
*/ */
Expr * 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, Oid ltypeId,
rtypeId; rtypeId;
@ -813,21 +817,21 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree)
/* right operator */ /* right operator */
ltypeId = exprType(ltree); ltypeId = exprType(ltree);
rtypeId = InvalidOid; rtypeId = InvalidOid;
tup = right_oper(opname, ltypeId, false); tup = right_oper(pstate, opname, ltypeId, false, location);
} }
else if (ltree == NULL) else if (ltree == NULL)
{ {
/* left operator */ /* left operator */
rtypeId = exprType(rtree); rtypeId = exprType(rtree);
ltypeId = InvalidOid; ltypeId = InvalidOid;
tup = left_oper(opname, rtypeId, false); tup = left_oper(pstate, opname, rtypeId, false, location);
} }
else else
{ {
/* otherwise, binary operator */ /* otherwise, binary operator */
ltypeId = exprType(ltree); ltypeId = exprType(ltree);
rtypeId = exprType(rtree); rtypeId = exprType(rtree);
tup = oper(opname, ltypeId, rtypeId, false); tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
} }
/* Do typecasting and build the expression tree */ /* Do typecasting and build the expression tree */
@ -845,7 +849,8 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree)
Expr * Expr *
make_scalar_array_op(ParseState *pstate, List *opname, make_scalar_array_op(ParseState *pstate, List *opname,
bool useOr, bool useOr,
Node *ltree, Node *rtree) Node *ltree, Node *rtree,
int location)
{ {
Oid ltypeId, Oid ltypeId,
rtypeId, rtypeId,
@ -875,11 +880,12 @@ make_scalar_array_op(ParseState *pstate, List *opname,
if (!OidIsValid(rtypeId)) if (!OidIsValid(rtypeId))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (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 */ /* Now resolve the operator */
tup = oper(opname, ltypeId, rtypeId, false); tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
opform = (Form_pg_operator) GETSTRUCT(tup); opform = (Form_pg_operator) GETSTRUCT(tup);
args = list_make2(ltree, rtree); args = list_make2(ltree, rtree);
@ -904,11 +910,13 @@ make_scalar_array_op(ParseState *pstate, List *opname,
if (rettype != BOOLOID) if (rettype != BOOLOID)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (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)) if (get_func_retset(opform->oprcode))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (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 * 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, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("could not find array type for data type %s", 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; actual_arg_types[1] = atypeId;
declared_arg_types[1] = res_atypeId; declared_arg_types[1] = res_atypeId;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, bool include_dropped,
List **colnames, List **colvars); List **colnames, List **colvars);
static int specialAttNum(const char *attname); 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. * FROM will be marked as requiring read access from the beginning.
*/ */
Node * Node *
scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname) scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname,
int location)
{ {
Node *result = NULL; Node *result = NULL;
int attnum = 0; int attnum = 0;
@ -357,7 +359,8 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_COLUMN), (errcode(ERRCODE_AMBIGUOUS_COLUMN),
errmsg("column reference \"%s\" is ambiguous", errmsg("column reference \"%s\" is ambiguous",
colname))); colname),
parser_errposition(pstate, location)));
result = (Node *) make_var(pstate, rte, attnum); result = (Node *) make_var(pstate, rte, attnum);
/* Require read access */ /* Require read access */
rte->requiredPerms |= ACL_SELECT; 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. * If localonly is true, only names in the innermost query are considered.
*/ */
Node * Node *
colNameToVar(ParseState *pstate, char *colname, bool localonly) colNameToVar(ParseState *pstate, char *colname, bool localonly,
int location)
{ {
Node *result = NULL; Node *result = NULL;
ParseState *orig_pstate = pstate; ParseState *orig_pstate = pstate;
@ -419,7 +423,7 @@ colNameToVar(ParseState *pstate, char *colname, bool localonly)
Node *newresult; Node *newresult;
/* use orig_pstate here to get the right sublevels_up */ /* 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) if (newresult)
{ {
@ -427,7 +431,8 @@ colNameToVar(ParseState *pstate, char *colname, bool localonly)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_COLUMN), (errcode(ERRCODE_AMBIGUOUS_COLUMN),
errmsg("column reference \"%s\" is ambiguous", errmsg("column reference \"%s\" is ambiguous",
colname))); colname),
parser_errposition(orig_pstate, location)));
result = newresult; result = newresult;
} }
} }
@ -454,7 +459,8 @@ qualifiedNameToVar(ParseState *pstate,
char *schemaname, char *schemaname,
char *refname, char *refname,
char *colname, char *colname,
bool implicitRTEOK) bool implicitRTEOK,
int location)
{ {
RangeTblEntry *rte; RangeTblEntry *rte;
int sublevels_up; int sublevels_up;
@ -465,10 +471,11 @@ qualifiedNameToVar(ParseState *pstate,
{ {
if (!implicitRTEOK) if (!implicitRTEOK)
return NULL; 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. * a conflicting name.
*/ */
RangeTblEntry * RangeTblEntry *
addImplicitRTE(ParseState *pstate, RangeVar *relation) addImplicitRTE(ParseState *pstate, RangeVar *relation, int location)
{ {
RangeTblEntry *rte; RangeTblEntry *rte;
/* issue warning or error as needed */ /* 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 * Note that we set inFromCl true, so that the RTE will be listed
* explicitly if the parsetree is ever decompiled by ruleutils.c. This * 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; Var *varnode;
Oid atttypid; Oid atttypid;
atttypid = typenameTypeId(colDef->typename); atttypid = typenameTypeId(NULL, colDef->typename);
varnode = makeVar(rtindex, varnode = makeVar(rtindex,
attnum, attnum,
@ -1543,7 +1550,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
{ {
ColumnDef *colDef = list_nth(rte->coldeflist, attnum - 1); ColumnDef *colDef = list_nth(rte->coldeflist, attnum - 1);
*vartype = typenameTypeId(colDef->typename); *vartype = typenameTypeId(NULL, colDef->typename);
*vartypmod = colDef->typename->typmod; *vartypmod = colDef->typename->typmod;
} }
else else
@ -1802,7 +1809,7 @@ attnumTypeId(Relation rd, int attid)
* a warning. * a warning.
*/ */
static void static void
warnAutoRange(ParseState *pstate, RangeVar *relation) warnAutoRange(ParseState *pstate, RangeVar *relation, int location)
{ {
RangeTblEntry *rte; RangeTblEntry *rte;
int sublevels_up; int sublevels_up;
@ -1841,7 +1848,8 @@ warnAutoRange(ParseState *pstate, RangeVar *relation)
errhint("Perhaps you meant to reference the table alias \"%s\".", errhint("Perhaps you meant to reference the table alias \"%s\".",
badAlias) : badAlias) :
errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.", 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 else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE), (errcode(ERRCODE_UNDEFINED_TABLE),
@ -1849,7 +1857,8 @@ warnAutoRange(ParseState *pstate, RangeVar *relation)
errmsg("missing FROM-clause entry in subquery for table \"%s\"", errmsg("missing FROM-clause entry in subquery for table \"%s\"",
relation->relname) : relation->relname) :
errmsg("missing FROM-clause entry for table \"%s\"", errmsg("missing FROM-clause entry for table \"%s\"",
relation->relname)))); relation->relname)),
parser_errposition(pstate, location)));
} }
else else
{ {
@ -1866,6 +1875,7 @@ warnAutoRange(ParseState *pstate, RangeVar *relation)
badAlias) : badAlias) :
(rte ? (rte ?
errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.", 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)));
} }
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cross-database references are not implemented: %s", errmsg("cross-database references are not implemented: %s",
NameListToString(fields)))); NameListToString(fields)),
parser_errposition(pstate, cref->location)));
schemaname = strVal(lsecond(fields)); schemaname = strVal(lsecond(fields));
relname = strVal(lthird(fields)); relname = strVal(lthird(fields));
break; break;
@ -727,7 +728,8 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("improper qualified name (too many dotted names): %s", errmsg("improper qualified name (too many dotted names): %s",
NameListToString(fields)))); NameListToString(fields)),
parser_errposition(pstate, cref->location)));
schemaname = NULL; /* keep compiler quiet */ schemaname = NULL; /* keep compiler quiet */
relname = NULL; relname = NULL;
break; break;
@ -736,8 +738,8 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref)
rte = refnameRangeTblEntry(pstate, schemaname, relname, rte = refnameRangeTblEntry(pstate, schemaname, relname,
&sublevels_up); &sublevels_up);
if (rte == NULL) if (rte == NULL)
rte = addImplicitRTE(pstate, makeRangeVar(schemaname, rte = addImplicitRTE(pstate, makeRangeVar(schemaname, relname),
relname)); cref->location);
rtindex = RTERangeTablePosn(pstate, rte, &sublevels_up); rtindex = RTERangeTablePosn(pstate, rte, &sublevels_up);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NB: even if the returned OID is not InvalidOid, the type might be
* just a shell. Caller should check typisdefined before using the type. * just a shell. Caller should check typisdefined before using the type.
*
* pstate is only used for error location info, and may be NULL.
*/ */
Oid Oid
LookupTypeName(const TypeName *typename) LookupTypeName(ParseState *pstate, const TypeName *typename)
{ {
Oid restype; Oid restype;
@ -60,7 +62,8 @@ LookupTypeName(const TypeName *typename)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("improper %%TYPE reference (too few dotted names): %s", errmsg("improper %%TYPE reference (too few dotted names): %s",
NameListToString(typename->names)))); NameListToString(typename->names)),
parser_errposition(pstate, typename->location)));
break; break;
case 2: case 2:
rel->relname = strVal(linitial(typename->names)); rel->relname = strVal(linitial(typename->names));
@ -81,7 +84,8 @@ LookupTypeName(const TypeName *typename)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("improper %%TYPE reference (too many dotted names): %s", errmsg("improper %%TYPE reference (too many dotted names): %s",
NameListToString(typename->names)))); NameListToString(typename->names)),
parser_errposition(pstate, typename->location)));
break; break;
} }
@ -92,7 +96,8 @@ LookupTypeName(const TypeName *typename)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN), (errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" of relation \"%s\" does not exist", 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); restype = get_atttype(relid, attnum);
/* this construct should never have an array indicator */ /* 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. * a suitable error message if the type cannot be found or is not defined.
*/ */
Oid Oid
typenameTypeId(const TypeName *typename) typenameTypeId(ParseState *pstate, const TypeName *typename)
{ {
Oid typoid; Oid typoid;
typoid = LookupTypeName(typename); typoid = LookupTypeName(pstate, typename);
if (!OidIsValid(typoid)) if (!OidIsValid(typoid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist", errmsg("type \"%s\" does not exist",
TypeNameToString(typename)))); TypeNameToString(typename)),
parser_errposition(pstate, typename->location)));
if (!get_typisdefined(typoid)) if (!get_typisdefined(typoid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" is only a shell", errmsg("type \"%s\" is only a shell",
TypeNameToString(typename)))); TypeNameToString(typename)),
parser_errposition(pstate, typename->location)));
return typoid; return typoid;
} }
@ -215,17 +223,18 @@ typenameTypeId(const TypeName *typename)
* NB: caller must ReleaseSysCache the type tuple when done with it. * NB: caller must ReleaseSysCache the type tuple when done with it.
*/ */
Type Type
typenameType(const TypeName *typename) typenameType(ParseState *pstate, const TypeName *typename)
{ {
Oid typoid; Oid typoid;
HeapTuple tup; HeapTuple tup;
typoid = LookupTypeName(typename); typoid = LookupTypeName(pstate, typename);
if (!OidIsValid(typoid)) if (!OidIsValid(typoid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist", errmsg("type \"%s\" does not exist",
TypeNameToString(typename)))); TypeNameToString(typename)),
parser_errposition(pstate, typename->location)));
tup = SearchSysCache(TYPEOID, tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typoid), ObjectIdGetDatum(typoid),
0, 0, 0); 0, 0, 0);
@ -235,7 +244,8 @@ typenameType(const TypeName *typename)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" is only a shell", errmsg("type \"%s\" is only a shell",
TypeNameToString(typename)))); TypeNameToString(typename)),
parser_errposition(pstate, typename->location)));
return (Type) tup; return (Type) tup;
} }
@ -447,7 +457,7 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod)
if (typename->setof) if (typename->setof)
goto fail; goto fail;
*type_id = typenameTypeId(typename); *type_id = typenameTypeId(NULL, typename);
*typmod = typename->typmod; *typmod = typename->typmod;
pfree(buf.data); pfree(buf.data);

View File

@ -24,7 +24,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 addlit(char *ytext, int yleng);
static void addlitchar(unsigned char ychar); static void addlitchar(unsigned char ychar);
static char *litbufdup(void); static char *litbufdup(void);
static int pg_err_position(void);
static int lexer_errposition(void);
static void check_escape_warning(void); static void check_escape_warning(void);
static void check_string_escape_warning(unsigned char ychar); 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, * 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 * this should be done in the first such rule, else yylloc will point
* by yyerror(). yytext will point at just the text consumed by the last * into the middle of the token.
* 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.
*/ */
static char *token_start; #define SET_YYLLOC() (yylloc = yytext - scanbuf)
/* Handles to the buffer that the lexer uses internally */ /* Handles to the buffer that the lexer uses internally */
static YY_BUFFER_STATE scanbufhandle; static YY_BUFFER_STATE scanbufhandle;
@ -316,17 +315,13 @@ other .
%% %%
%{
/* code to execute during start of each call of yylex() */
token_start = NULL;
%}
{whitespace} { {whitespace} {
/* ignore */ /* ignore */
} }
{xcstart} { {xcstart} {
token_start = yytext; /* Set location in case of syntax error in comment */
SET_YYLLOC();
xcdepth = 0; xcdepth = 0;
BEGIN(xc); BEGIN(xc);
/* Put back any characters past slash-star; see above */ /* Put back any characters past slash-star; see above */
@ -341,11 +336,7 @@ other .
<xc>{xcstop} { <xc>{xcstop} {
if (xcdepth <= 0) if (xcdepth <= 0)
{
BEGIN(INITIAL); BEGIN(INITIAL);
/* reset token_start for next token */
token_start = NULL;
}
else else
xcdepth--; xcdepth--;
} }
@ -371,7 +362,7 @@ other .
* In the meantime, place a leading "b" on the string * In the meantime, place a leading "b" on the string
* to mark it for the input routine as a binary string. * to mark it for the input routine as a binary string.
*/ */
token_start = yytext; SET_YYLLOC();
BEGIN(xb); BEGIN(xb);
startlit(); startlit();
addlitchar('b'); addlitchar('b');
@ -400,7 +391,7 @@ other .
* In the meantime, place a leading "x" on the string * In the meantime, place a leading "x" on the string
* to mark it for the input routine as a hex string. * to mark it for the input routine as a hex string.
*/ */
token_start = yytext; SET_YYLLOC();
BEGIN(xh); BEGIN(xh);
startlit(); startlit();
addlitchar('x'); addlitchar('x');
@ -421,6 +412,7 @@ other .
*/ */
const ScanKeyword *keyword; const ScanKeyword *keyword;
SET_YYLLOC();
yyless(1); /* eat only 'n' this time */ yyless(1); /* eat only 'n' this time */
/* nchar had better be a keyword! */ /* nchar had better be a keyword! */
keyword = ScanKeywordLookup("nchar"); keyword = ScanKeywordLookup("nchar");
@ -431,7 +423,7 @@ other .
{xqstart} { {xqstart} {
warn_on_first_escape = true; warn_on_first_escape = true;
token_start = yytext; SET_YYLLOC();
if (standard_conforming_strings) if (standard_conforming_strings)
BEGIN(xq); BEGIN(xq);
else else
@ -440,7 +432,7 @@ other .
} }
{xestart} { {xestart} {
warn_on_first_escape = false; warn_on_first_escape = false;
token_start = yytext; SET_YYLLOC();
BEGIN(xe); BEGIN(xe);
startlit(); startlit();
} }
@ -490,7 +482,7 @@ other .
<xq,xe><<EOF>> { yyerror("unterminated quoted string"); } <xq,xe><<EOF>> { yyerror("unterminated quoted string"); }
{dolqdelim} { {dolqdelim} {
token_start = yytext; SET_YYLLOC();
dolqstart = pstrdup(yytext); dolqstart = pstrdup(yytext);
BEGIN(xdolq); BEGIN(xdolq);
startlit(); startlit();
@ -533,7 +525,7 @@ other .
<xdolq><<EOF>> { yyerror("unterminated dollar-quoted string"); } <xdolq><<EOF>> { yyerror("unterminated dollar-quoted string"); }
{xdstart} { {xdstart} {
token_start = yytext; SET_YYLLOC();
BEGIN(xd); BEGIN(xd);
startlit(); startlit();
} }
@ -558,10 +550,12 @@ other .
<xd><<EOF>> { yyerror("unterminated quoted identifier"); } <xd><<EOF>> { yyerror("unterminated quoted identifier"); }
{typecast} { {typecast} {
SET_YYLLOC();
return TYPECAST; return TYPECAST;
} }
{self} { {self} {
SET_YYLLOC();
return yytext[0]; return yytext[0];
} }
@ -611,6 +605,8 @@ other .
nchars--; /* else remove the +/-, and check again */ nchars--; /* else remove the +/-, and check again */
} }
SET_YYLLOC();
if (nchars < yyleng) if (nchars < yyleng)
{ {
/* Strip the unwanted chars from the token */ /* Strip the unwanted chars from the token */
@ -644,6 +640,7 @@ other .
} }
{param} { {param} {
SET_YYLLOC();
yylval.ival = atol(yytext + 1); yylval.ival = atol(yytext + 1);
return PARAM; return PARAM;
} }
@ -652,6 +649,7 @@ other .
long val; long val;
char* endptr; char* endptr;
SET_YYLLOC();
errno = 0; errno = 0;
val = strtol(yytext, &endptr, 10); val = strtol(yytext, &endptr, 10);
if (*endptr != '\0' || errno == ERANGE if (*endptr != '\0' || errno == ERANGE
@ -669,10 +667,12 @@ other .
return ICONST; return ICONST;
} }
{decimal} { {decimal} {
SET_YYLLOC();
yylval.str = pstrdup(yytext); yylval.str = pstrdup(yytext);
return FCONST; return FCONST;
} }
{real} { {real} {
SET_YYLLOC();
yylval.str = pstrdup(yytext); yylval.str = pstrdup(yytext);
return FCONST; return FCONST;
} }
@ -684,12 +684,14 @@ other .
* syntax error anyway, we don't bother to distinguish. * syntax error anyway, we don't bother to distinguish.
*/ */
yyless(yyleng-1); yyless(yyleng-1);
SET_YYLLOC();
yylval.str = pstrdup(yytext); yylval.str = pstrdup(yytext);
return FCONST; return FCONST;
} }
{realfail2} { {realfail2} {
/* throw back the [Ee][+-], and proceed as above */ /* throw back the [Ee][+-], and proceed as above */
yyless(yyleng-2); yyless(yyleng-2);
SET_YYLLOC();
yylval.str = pstrdup(yytext); yylval.str = pstrdup(yytext);
return FCONST; return FCONST;
} }
@ -699,6 +701,8 @@ other .
const ScanKeyword *keyword; const ScanKeyword *keyword;
char *ident; char *ident;
SET_YYLLOC();
/* Is it a keyword? */ /* Is it a keyword? */
keyword = ScanKeywordLookup(yytext); keyword = ScanKeywordLookup(yytext);
if (keyword != NULL) if (keyword != NULL)
@ -717,25 +721,52 @@ other .
} }
{other} { {other} {
SET_YYLLOC();
return yytext[0]; 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 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 */ /* Convert byte offset to character number */
return pg_mbstrlen_with_len(scanbuf, loc - scanbuf) + 1; 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 void
yyerror(const char *message) yyerror(const char *message)
{ {
const char *loc = token_start ? token_start : yytext; const char *loc = scanbuf + yylloc;
int cursorpos = pg_err_position();
if (*loc == YY_END_OF_BUFFER_CHAR) if (*loc == YY_END_OF_BUFFER_CHAR)
{ {
@ -743,7 +774,7 @@ yyerror(const char *message)
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
/* translator: %s is typically "syntax error" */ /* translator: %s is typically "syntax error" */
errmsg("%s at end of input", _(message)), errmsg("%s at end of input", _(message)),
errposition(cursorpos))); lexer_errposition()));
} }
else else
{ {
@ -751,7 +782,7 @@ yyerror(const char *message)
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
/* translator: first %s is typically "syntax error" */ /* translator: first %s is typically "syntax error" */
errmsg("%s at or near \"%s\"", _(message), loc), 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), (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
errmsg("nonstandard use of \\' in a string literal"), errmsg("nonstandard use of \\' in a string literal"),
errhint("Use '' to write quotes in strings, or use the escape string syntax (E'...')."), 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 */ warn_on_first_escape = false; /* warn only once per string */
} }
else if (ychar == '\\') else if (ychar == '\\')
@ -888,7 +919,7 @@ check_string_escape_warning(unsigned char ychar)
(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
errmsg("nonstandard use of \\\\ in a string literal"), errmsg("nonstandard use of \\\\ in a string literal"),
errhint("Use the escape string syntax for backslashes, e.g., E'\\\\'."), 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 */ warn_on_first_escape = false; /* warn only once per string */
} }
else else
@ -903,6 +934,6 @@ check_escape_warning(void)
(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
errmsg("nonstandard use of escape in a string literal"), errmsg("nonstandard use of escape in a string literal"),
errhint("Use the escape string syntax for escapes, e.g., E'\\r\\n'."), 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 */ warn_on_first_escape = false; /* warn only once per string */
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* this is the "main" module of the postgres backend and * 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, querytree_list = list_concat(querytree_list,
pg_analyze_and_rewrite(parsetree, pg_analyze_and_rewrite(parsetree,
query_string,
paramTypes, paramTypes,
numParams)); 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. * NOTE: for reasons mentioned above, this must be separate from raw parsing.
*/ */
List * 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; List *querytree_list;
@ -635,7 +637,8 @@ pg_analyze_and_rewrite(Node *parsetree, Oid *paramTypes, int numParams)
if (log_parser_stats) if (log_parser_stats)
ResetUsage(); ResetUsage();
querytree_list = parse_analyze(parsetree, paramTypes, numParams); querytree_list = parse_analyze(parsetree, query_string,
paramTypes, numParams);
if (log_parser_stats) if (log_parser_stats)
ShowUsage("PARSE ANALYSIS STATISTICS"); ShowUsage("PARSE ANALYSIS STATISTICS");
@ -946,7 +949,8 @@ exec_simple_query(const char *query_string)
*/ */
oldcontext = MemoryContextSwitchTo(MessageContext); 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); plantree_list = pg_plan_queries(querytree_list, NULL, true);
@ -1257,6 +1261,7 @@ exec_parse_message(const char *query_string, /* string to execute */
ResetUsage(); ResetUsage();
querytree_list = parse_analyze_varparams(parsetree, querytree_list = parse_analyze_varparams(parsetree,
query_string,
&paramTypes, &paramTypes,
&numParams); &numParams);

View File

@ -2,7 +2,7 @@
* ruleutils.c - Functions to convert stored expressions/querytrees * ruleutils.c - Functions to convert stored expressions/querytrees
* back to source text * 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" #include "postgres.h"
@ -4479,7 +4479,7 @@ get_from_clause_coldeflist(List *coldeflist, deparse_context *context)
int32 atttypmod; int32 atttypmod;
attname = n->colname; attname = n->colname;
atttypeid = typenameTypeId(n->typename); atttypeid = typenameTypeId(NULL, n->typename);
atttypmod = n->typename->typmod; atttypmod = n->typename->typmod;
if (i > 0) if (i > 0)
@ -4868,13 +4868,16 @@ generate_operator_name(Oid operid, Oid arg1, Oid arg2)
switch (operform->oprkind) switch (operform->oprkind)
{ {
case 'b': 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; break;
case 'l': 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; break;
case 'r': 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; break;
default: default:
elog(ERROR, "unrecognized oprkind: %d", operform->oprkind); elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2006, PostgreSQL Global Development Group * Copyright (c) 2000-2006, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.115 2006/03/06 19:49:20 momjian Exp $ * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.116 2006/03/14 22:48:22 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "common.h" #include "common.h"
@ -428,234 +428,6 @@ ResetCancelConn(void)
} }
/*
* on errors, print syntax error position if available.
*
* the query is expected to be in the client encoding.
*/
static void
ReportSyntaxErrorPosition(const PGresult *result, const char *query)
{
#define DISPLAY_SIZE 60 /* screen width limit, in screen cols */
#define MIN_RIGHT_CUT 10 /* try to keep this far away from EOL */
int loc = 0;
const char *sp;
int clen,
slen,
i,
w,
*qidx,
*scridx,
qoffset,
scroffset,
ibeg,
iend,
loc_line;
char *wquery;
bool beg_trunc,
end_trunc;
PQExpBufferData msg;
if (pset.verbosity == PQERRORS_TERSE)
return;
sp = PQresultErrorField(result, PG_DIAG_STATEMENT_POSITION);
if (sp == NULL)
{
sp = PQresultErrorField(result, PG_DIAG_INTERNAL_POSITION);
if (sp == NULL)
return; /* no syntax error */
query = PQresultErrorField(result, PG_DIAG_INTERNAL_QUERY);
}
if (query == NULL)
return; /* nothing to reference location to */
if (sscanf(sp, "%d", &loc) != 1)
{
psql_error("INTERNAL ERROR: unexpected statement position \"%s\"\n",
sp);
return;
}
/* Make a writable copy of the query, and a buffer for messages. */
wquery = pg_strdup(query);
initPQExpBuffer(&msg);
/*
* The returned cursor position is measured in logical characters. Each
* character might occupy multiple physical bytes in the string, and in
* some Far Eastern character sets it might take more than one screen
* column as well. We compute the starting byte offset and starting
* screen column of each logical character, and store these in qidx[] and
* scridx[] respectively.
*/
/* we need a safe allocation size... */
slen = strlen(query) + 1;
qidx = (int *) pg_malloc(slen * sizeof(int));
scridx = (int *) pg_malloc(slen * sizeof(int));
qoffset = 0;
scroffset = 0;
for (i = 0; query[qoffset] != '\0'; i++)
{
qidx[i] = qoffset;
scridx[i] = scroffset;
w = PQdsplen(&query[qoffset], pset.encoding);
/* treat control chars as width 1; see tab hack below */
if (w <= 0)
w = 1;
scroffset += w;
qoffset += PQmblen(&query[qoffset], pset.encoding);
}
qidx[i] = qoffset;
scridx[i] = scroffset;
clen = i;
psql_assert(clen < slen);
/* convert loc to zero-based offset in qidx/scridx arrays */
loc--;
/* do we have something to show? */
if (loc >= 0 && loc <= clen)
{
/* input line number of our syntax error. */
loc_line = 1;
/* first included char of extract. */
ibeg = 0;
/* last-plus-1 included char of extract. */
iend = clen;
/*
* Replace tabs with spaces in the writable copy. (Later we might
* want to think about coping with their variable screen width, but
* not today.)
*
* Extract line number and begin and end indexes of line containing
* error location. There will not be any newlines or carriage returns
* in the selected extract.
*/
for (i = 0; i < clen; i++)
{
/* character length must be 1 or it's not ASCII */
if ((qidx[i + 1] - qidx[i]) == 1)
{
if (wquery[qidx[i]] == '\t')
wquery[qidx[i]] = ' ';
else if (wquery[qidx[i]] == '\r' || wquery[qidx[i]] == '\n')
{
if (i < loc)
{
/*
* count lines before loc. Each \r or \n counts as a
* line except when \r \n appear together.
*/
if (wquery[qidx[i]] == '\r' ||
i == 0 ||
(qidx[i] - qidx[i - 1]) != 1 ||
wquery[qidx[i - 1]] != '\r')
loc_line++;
/* extract beginning = last line start before loc. */
ibeg = i + 1;
}
else
{
/* set extract end. */
iend = i;
/* done scanning. */
break;
}
}
}
}
/* If the line extracted is too long, we truncate it. */
beg_trunc = false;
end_trunc = false;
if (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
{
/*
* We first truncate right if it is enough. This code might be
* off a space or so on enforcing MIN_RIGHT_CUT if there's a wide
* character right there, but that should be okay.
*/
if (scridx[ibeg] + DISPLAY_SIZE >= scridx[loc] + MIN_RIGHT_CUT)
{
while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
iend--;
end_trunc = true;
}
else
{
/* Truncate right if not too close to loc. */
while (scridx[loc] + MIN_RIGHT_CUT < scridx[iend])
{
iend--;
end_trunc = true;
}
/* Truncate left if still too long. */
while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
{
ibeg++;
beg_trunc = true;
}
}
}
/* the extract MUST contain the target position! */
psql_assert(ibeg <= loc && loc <= iend);
/* truncate working copy at desired endpoint */
wquery[qidx[iend]] = '\0';
/* Begin building the finished message. */
printfPQExpBuffer(&msg, _("LINE %d: "), loc_line);
if (beg_trunc)
appendPQExpBufferStr(&msg, "...");
/*
* While we have the prefix in the msg buffer, compute its screen
* width.
*/
scroffset = 0;
for (i = 0; i < msg.len; i += PQmblen(&msg.data[i], pset.encoding))
{
w = PQdsplen(&msg.data[i], pset.encoding);
if (w <= 0)
w = 1;
scroffset += w;
}
/* Finish and emit the message. */
appendPQExpBufferStr(&msg, &wquery[qidx[ibeg]]);
if (end_trunc)
appendPQExpBufferStr(&msg, "...");
psql_error("%s\n", msg.data);
/* Now emit the cursor marker line. */
scroffset += scridx[loc] - scridx[ibeg];
resetPQExpBuffer(&msg);
for (i = 0; i < scroffset; i++)
appendPQExpBufferChar(&msg, ' ');
appendPQExpBufferChar(&msg, '^');
psql_error("%s\n", msg.data);
}
/* Clean up. */
termPQExpBuffer(&msg);
free(wquery);
free(qidx);
free(scridx);
}
/* /*
* AcceptResult * AcceptResult
* *
@ -704,8 +476,6 @@ AcceptResult(const PGresult *result, const char *query)
if (strlen(error)) if (strlen(error))
psql_error("%s", error); psql_error("%s", error);
ReportSyntaxErrorPosition(result, query);
CheckConnection(); CheckConnection();
} }

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.54 2006/03/05 15:58:56 momjian Exp $ * $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.55 2006/03/14 22:48:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -18,10 +18,10 @@
extern A_Expr *makeA_Expr(A_Expr_Kind kind, List *name, extern A_Expr *makeA_Expr(A_Expr_Kind kind, List *name,
Node *lexpr, Node *rexpr); Node *lexpr, Node *rexpr, int location);
extern A_Expr *makeSimpleA_Expr(A_Expr_Kind kind, const char *name, extern A_Expr *makeSimpleA_Expr(A_Expr_Kind kind, const char *name,
Node *lexpr, Node *rexpr); Node *lexpr, Node *rexpr, int location);
extern Var *makeVar(Index varno, extern Var *makeVar(Index varno,
AttrNumber varattno, AttrNumber varattno,
@ -56,6 +56,8 @@ extern RelabelType *makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod,
extern RangeVar *makeRangeVar(char *schemaname, char *relname); extern RangeVar *makeRangeVar(char *schemaname, char *relname);
extern TypeName *makeTypeName(char *typnam); extern TypeName *makeTypeName(char *typnam);
extern TypeName *makeTypeNameFromNameList(List *names);
extern TypeName *makeTypeNameFromOid(Oid typeid, int32 typmod);
extern FuncExpr *makeFuncExpr(Oid funcid, Oid rettype, extern FuncExpr *makeFuncExpr(Oid funcid, Oid rettype,
List *args, CoercionForm fformat); List *args, CoercionForm fformat);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.303 2006/03/05 15:58:56 momjian Exp $ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.304 2006/03/14 22:48:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -142,6 +142,11 @@ typedef struct Query
* Most of these node types appear in raw parsetrees output by the grammar, * Most of these node types appear in raw parsetrees output by the grammar,
* and get transformed to something else by the analyzer. A few of them * and get transformed to something else by the analyzer. A few of them
* are used as-is in transformed querytrees. * are used as-is in transformed querytrees.
*
* Many of the node types used in raw parsetrees include a "location" field.
* This is a byte (not character) offset in the original source text, to be
* used for positioning an error cursor when there is an analysis-time
* error related to the node.
****************************************************************************/ ****************************************************************************/
/* /*
@ -165,6 +170,7 @@ typedef struct TypeName
bool pct_type; /* %TYPE specified? */ bool pct_type; /* %TYPE specified? */
int32 typmod; /* type modifier */ int32 typmod; /* type modifier */
List *arrayBounds; /* array bounds */ List *arrayBounds; /* array bounds */
int location; /* token location, or -1 if unknown */
} TypeName; } TypeName;
/* /*
@ -182,6 +188,7 @@ typedef struct ColumnRef
{ {
NodeTag type; NodeTag type;
List *fields; /* field names (list of Value strings) */ List *fields; /* field names (list of Value strings) */
int location; /* token location, or -1 if unknown */
} ColumnRef; } ColumnRef;
/* /*
@ -217,6 +224,7 @@ typedef struct A_Expr
List *name; /* possibly-qualified name of operator */ List *name; /* possibly-qualified name of operator */
Node *lexpr; /* left argument, or NULL if none */ Node *lexpr; /* left argument, or NULL if none */
Node *rexpr; /* right argument, or NULL if none */ Node *rexpr; /* right argument, or NULL if none */
int location; /* token location, or -1 if unknown */
} A_Expr; } A_Expr;
/* /*
@ -226,7 +234,7 @@ typedef struct A_Const
{ {
NodeTag type; NodeTag type;
Value val; /* the value (with the tag) */ Value val; /* the value (with the tag) */
TypeName *typename; /* typecast */ TypeName *typename; /* typecast, or NULL if none */
} A_Const; } A_Const;
/* /*
@ -235,8 +243,8 @@ typedef struct A_Const
* NOTE: for mostly historical reasons, A_Const parsenodes contain * NOTE: for mostly historical reasons, A_Const parsenodes contain
* room for a TypeName; we only generate a separate TypeCast node if the * room for a TypeName; we only generate a separate TypeCast node if the
* argument to be casted is not a constant. In theory either representation * argument to be casted is not a constant. In theory either representation
* would work, but it is convenient to have the target type immediately * would work, but the combined representation saves a bit of code in many
* available while resolving a constant's datatype. * productions in gram.y.
*/ */
typedef struct TypeCast typedef struct TypeCast
{ {
@ -260,6 +268,7 @@ typedef struct FuncCall
List *args; /* the arguments (list of exprs) */ List *args; /* the arguments (list of exprs) */
bool agg_star; /* argument was really '*' */ bool agg_star; /* argument was really '*' */
bool agg_distinct; /* arguments were labeled DISTINCT */ bool agg_distinct; /* arguments were labeled DISTINCT */
int location; /* token location, or -1 if unknown */
} FuncCall; } FuncCall;
/* /*

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/parser/analyze.h,v 1.31 2006/03/05 15:58:57 momjian Exp $ * $PostgreSQL: pgsql/src/include/parser/analyze.h,v 1.32 2006/03/14 22:48:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -16,9 +16,10 @@
#include "parser/parse_node.h" #include "parser/parse_node.h"
extern List *parse_analyze(Node *parseTree, Oid *paramTypes, int numParams); extern List *parse_analyze(Node *parseTree, const char *sourceText,
extern List *parse_analyze_varparams(Node *parseTree, Oid **paramTypes, Oid *paramTypes, int numParams);
int *numParams); extern List *parse_analyze_varparams(Node *parseTree, const char *sourceText,
Oid **paramTypes, int *numParams);
extern List *parse_sub_analyze(Node *parseTree, ParseState *parentParseState); extern List *parse_sub_analyze(Node *parseTree, ParseState *parentParseState);
extern List *analyzeCreateSchemaStmt(CreateSchemaStmt *stmt); extern List *analyzeCreateSchemaStmt(CreateSchemaStmt *stmt);
extern void CheckSelectLocking(Query *qry, bool forUpdate); extern void CheckSelectLocking(Query *qry, bool forUpdate);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.33 2006/03/07 01:00:18 tgl Exp $ * $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.34 2006/03/14 22:48:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -17,6 +17,15 @@
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
/*
* We track token locations in terms of byte offsets from the start of the
* source string, not the column number/line number representation that
* bison uses by default. Also, to minimize overhead we track only one
* location (usually the first token location) for each construct, not
* the beginning and ending locations as bison does by default. It's
* therefore sufficient to make YYLTYPE an int.
*/
#define YYLTYPE int
/* from scan.l */ /* from scan.l */
extern void scanner_init(const char *str); extern void scanner_init(const char *str);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/parser/parse_func.h,v 1.54 2006/03/05 15:58:57 momjian Exp $ * $PostgreSQL: pgsql/src/include/parser/parse_func.h,v 1.55 2006/03/14 22:48:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -43,7 +43,8 @@ typedef enum
extern Node *ParseFuncOrColumn(ParseState *pstate, extern Node *ParseFuncOrColumn(ParseState *pstate,
List *funcname, List *fargs, List *funcname, List *fargs,
bool agg_star, bool agg_distinct, bool is_column); bool agg_star, bool agg_distinct, bool is_column,
int location);
extern FuncDetailCode func_get_detail(List *funcname, List *fargs, extern FuncDetailCode func_get_detail(List *funcname, List *fargs,
int nargs, Oid *argtypes, int nargs, Oid *argtypes,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.47 2006/03/05 15:58:57 momjian Exp $ * $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.48 2006/03/14 22:48:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -20,6 +20,15 @@
/* /*
* State information used during parse analysis * State information used during parse analysis
* *
* parentParseState: NULL in a top-level ParseState. When parsing a subquery,
* links to current parse state of outer query.
*
* p_sourcetext: source string that generated the raw parsetree being
* analyzed, or NULL if not available. (The string is used only to
* generate cursor positions in error messages: we need it to convert
* byte-wise locations in parse structures to character-wise cursor
* positions.)
*
* p_rtable: list of RTEs that will become the rangetable of the query. * p_rtable: list of RTEs that will become the rangetable of the query.
* Note that neither relname nor refname of these entries are necessarily * Note that neither relname nor refname of these entries are necessarily
* unique; searching the rtable by name is a bad idea. * unique; searching the rtable by name is a bad idea.
@ -53,6 +62,7 @@
typedef struct ParseState typedef struct ParseState
{ {
struct ParseState *parentParseState; /* stack link */ struct ParseState *parentParseState; /* stack link */
const char *p_sourcetext; /* source text, or NULL if not available */
List *p_rtable; /* range table so far */ List *p_rtable; /* range table so far */
List *p_joinlist; /* join items so far (will become FromExpr List *p_joinlist; /* join items so far (will become FromExpr
* node's fromlist) */ * node's fromlist) */
@ -73,6 +83,8 @@ typedef struct ParseState
} ParseState; } ParseState;
extern ParseState *make_parsestate(ParseState *parentParseState); extern ParseState *make_parsestate(ParseState *parentParseState);
extern int parser_errposition(ParseState *pstate, int location);
extern Var *make_var(ParseState *pstate, RangeTblEntry *rte, int attrno); extern Var *make_var(ParseState *pstate, RangeTblEntry *rte, int attrno);
extern Oid transformArrayType(Oid arrayType); extern Oid transformArrayType(Oid arrayType);
extern ArrayRef *transformArraySubscripts(ParseState *pstate, extern ArrayRef *transformArraySubscripts(ParseState *pstate,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/parser/parse_oper.h,v 1.38 2006/03/05 15:58:57 momjian Exp $ * $PostgreSQL: pgsql/src/include/parser/parse_oper.h,v 1.39 2006/03/14 22:48:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -21,20 +21,27 @@
typedef HeapTuple Operator; typedef HeapTuple Operator;
/* Routines to look up an operator given name and exact input type(s) */ /* Routines to look up an operator given name and exact input type(s) */
extern Oid LookupOperName(List *opername, Oid oprleft, Oid oprright, extern Oid LookupOperName(ParseState *pstate, List *opername,
bool noError); Oid oprleft, Oid oprright,
extern Oid LookupOperNameTypeNames(List *opername, TypeName *oprleft, bool noError, int location);
TypeName *oprright, bool noError); extern Oid LookupOperNameTypeNames(ParseState *pstate, List *opername,
TypeName *oprleft, TypeName *oprright,
bool noError, int location);
/* Routines to find operators matching a name and given input types */ /* Routines to find operators matching a name and given input types */
/* NB: the selected operator may require coercion of the input types! */ /* NB: the selected operator may require coercion of the input types! */
extern Operator oper(List *op, Oid arg1, Oid arg2, bool noError); extern Operator oper(ParseState *pstate, List *op, Oid arg1, Oid arg2,
extern Operator right_oper(List *op, Oid arg, bool noError); bool noError, int location);
extern Operator left_oper(List *op, Oid arg, bool noError); extern Operator right_oper(ParseState *pstate, List *op, Oid arg,
bool noError, int location);
extern Operator left_oper(ParseState *pstate, List *op, Oid arg,
bool noError, int location);
/* Routines to find operators that DO NOT require coercion --- ie, their */ /* Routines to find operators that DO NOT require coercion --- ie, their */
/* input types are either exactly as given, or binary-compatible */ /* input types are either exactly as given, or binary-compatible */
extern Operator compatible_oper(List *op, Oid arg1, Oid arg2, bool noError); extern Operator compatible_oper(ParseState *pstate, List *op,
Oid arg1, Oid arg2,
bool noError, int location);
/* currently no need for compatible_left_oper/compatible_right_oper */ /* currently no need for compatible_left_oper/compatible_right_oper */
@ -55,9 +62,9 @@ extern Oid oprfuncid(Operator op);
/* Build expression tree for an operator invocation */ /* Build expression tree for an operator invocation */
extern Expr *make_op(ParseState *pstate, List *opname, extern Expr *make_op(ParseState *pstate, List *opname,
Node *ltree, Node *rtree); Node *ltree, Node *rtree, int location);
extern Expr *make_scalar_array_op(ParseState *pstate, List *opname, extern Expr *make_scalar_array_op(ParseState *pstate, List *opname,
bool useOr, bool useOr,
Node *ltree, Node *rtree); Node *ltree, Node *rtree, int location);
#endif /* PARSE_OPER_H */ #endif /* PARSE_OPER_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.52 2006/03/05 15:58:57 momjian Exp $ * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.53 2006/03/14 22:48:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -31,13 +31,15 @@ extern RangeTblEntry *GetRTEByRangeTablePosn(ParseState *pstate,
int varno, int varno,
int sublevels_up); int sublevels_up);
extern Node *scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, extern Node *scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
char *colname); char *colname, int location);
extern Node *colNameToVar(ParseState *pstate, char *colname, bool localonly); extern Node *colNameToVar(ParseState *pstate, char *colname, bool localonly,
int location);
extern Node *qualifiedNameToVar(ParseState *pstate, extern Node *qualifiedNameToVar(ParseState *pstate,
char *schemaname, char *schemaname,
char *refname, char *refname,
char *colname, char *colname,
bool implicitRTEOK); bool implicitRTEOK,
int location);
extern RangeTblEntry *addRangeTableEntry(ParseState *pstate, extern RangeTblEntry *addRangeTableEntry(ParseState *pstate,
RangeVar *relation, RangeVar *relation,
Alias *alias, Alias *alias,
@ -66,7 +68,8 @@ extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate,
extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
bool addToJoinList, bool addToJoinList,
bool addToRelNameSpace, bool addToVarNameSpace); bool addToRelNameSpace, bool addToVarNameSpace);
extern RangeTblEntry *addImplicitRTE(ParseState *pstate, RangeVar *relation); extern RangeTblEntry *addImplicitRTE(ParseState *pstate, RangeVar *relation,
int location);
extern void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, extern void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
bool include_dropped, bool include_dropped,
List **colnames, List **colvars); List **colnames, List **colvars);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/parser/parse_type.h,v 1.31 2006/03/05 15:58:57 momjian Exp $ * $PostgreSQL: pgsql/src/include/parser/parse_type.h,v 1.32 2006/03/14 22:48:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -20,10 +20,10 @@
typedef HeapTuple Type; typedef HeapTuple Type;
extern Oid LookupTypeName(const TypeName *typename); extern Oid LookupTypeName(ParseState *pstate, const TypeName *typename);
extern char *TypeNameToString(const TypeName *typename); extern char *TypeNameToString(const TypeName *typename);
extern Oid typenameTypeId(const TypeName *typename); extern Oid typenameTypeId(ParseState *pstate, const TypeName *typename);
extern Type typenameType(const TypeName *typename); extern Type typenameType(ParseState *pstate, const TypeName *typename);
extern Type typeidType(Oid id); extern Type typeidType(Oid id);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.80 2006/03/05 15:59:00 momjian Exp $ * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.81 2006/03/14 22:48:23 tgl Exp $
* *
* OLD COMMENTS * OLD COMMENTS
* This file was created so that other c files could get the two * This file was created so that other c files could get the two
@ -47,7 +47,7 @@ extern LogStmtLevel log_statement;
extern List *pg_parse_and_rewrite(const char *query_string, extern List *pg_parse_and_rewrite(const char *query_string,
Oid *paramTypes, int numParams); Oid *paramTypes, int numParams);
extern List *pg_parse_query(const char *query_string); extern List *pg_parse_query(const char *query_string);
extern List *pg_analyze_and_rewrite(Node *parsetree, extern List *pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
Oid *paramTypes, int numParams); Oid *paramTypes, int numParams);
extern Plan *pg_plan_query(Query *querytree, ParamListInfo boundParams); extern Plan *pg_plan_query(Query *querytree, ParamListInfo boundParams);
extern List *pg_plan_queries(List *querytrees, ParamListInfo boundParams, extern List *pg_plan_queries(List *querytrees, ParamListInfo boundParams,

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.327 2006/03/05 15:59:08 momjian Exp $ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.328 2006/03/14 22:48:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1918,6 +1918,8 @@ freePGconn(PGconn *conn)
free(conn->krbsrvname); free(conn->krbsrvname);
#endif #endif
/* Note that conn->Pfdebug is not ours to close or free */ /* Note that conn->Pfdebug is not ours to close or free */
if (conn->last_query)
free(conn->last_query);
pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist); pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist);
notify = conn->notifyHead; notify = conn->notifyHead;
while (notify != NULL) while (notify != NULL)

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.181 2006/03/05 15:59:09 momjian Exp $ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.182 2006/03/14 22:48:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -667,6 +667,12 @@ PQsendQuery(PGconn *conn, const char *query)
/* remember we are using simple query protocol */ /* remember we are using simple query protocol */
conn->queryclass = PGQUERY_SIMPLE; conn->queryclass = PGQUERY_SIMPLE;
/* and remember the query text too, if possible */
/* if insufficient memory, last_query just winds up NULL */
if (conn->last_query)
free(conn->last_query);
conn->last_query = strdup(query);
/* /*
* Give the data a push. In nonblock mode, don't complain if we're unable * Give the data a push. In nonblock mode, don't complain if we're unable
* to send it all; PQgetResult() will do any additional flushing needed. * to send it all; PQgetResult() will do any additional flushing needed.
@ -788,6 +794,12 @@ PQsendPrepare(PGconn *conn,
/* remember we are doing just a Parse */ /* remember we are doing just a Parse */
conn->queryclass = PGQUERY_PREPARE; conn->queryclass = PGQUERY_PREPARE;
/* and remember the query text too, if possible */
/* if insufficient memory, last_query just winds up NULL */
if (conn->last_query)
free(conn->last_query);
conn->last_query = strdup(query);
/* /*
* Give the data a push. In nonblock mode, don't complain if we're unable * Give the data a push. In nonblock mode, don't complain if we're unable
* to send it all; PQgetResult() will do any additional flushing needed. * to send it all; PQgetResult() will do any additional flushing needed.
@ -1017,6 +1029,15 @@ PQsendQueryGuts(PGconn *conn,
/* remember we are using extended query protocol */ /* remember we are using extended query protocol */
conn->queryclass = PGQUERY_EXTENDED; conn->queryclass = PGQUERY_EXTENDED;
/* and remember the query text too, if possible */
/* if insufficient memory, last_query just winds up NULL */
if (conn->last_query)
free(conn->last_query);
if (command)
conn->last_query = strdup(command);
else
conn->last_query = NULL;
/* /*
* Give the data a push. In nonblock mode, don't complain if we're unable * Give the data a push. In nonblock mode, don't complain if we're unable
* to send it all; PQgetResult() will do any additional flushing needed. * to send it all; PQgetResult() will do any additional flushing needed.

View File

@ -8,13 +8,12 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-protocol3.c,v 1.25 2006/03/05 15:59:09 momjian Exp $ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-protocol3.c,v 1.26 2006/03/14 22:48:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include <errno.h>
#include <ctype.h> #include <ctype.h>
#include <fcntl.h> #include <fcntl.h>
@ -51,6 +50,8 @@ static int getParameterStatus(PGconn *conn);
static int getNotify(PGconn *conn); static int getNotify(PGconn *conn);
static int getCopyStart(PGconn *conn, ExecStatusType copytype); static int getCopyStart(PGconn *conn, ExecStatusType copytype);
static int getReadyForQuery(PGconn *conn); static int getReadyForQuery(PGconn *conn);
static void reportErrorPosition(PQExpBuffer msg, const char *query,
int loc, int encoding);
static int build_startup_packet(const PGconn *conn, char *packet, static int build_startup_packet(const PGconn *conn, char *packet,
const PQEnvironmentOption *options); const PQEnvironmentOption *options);
@ -614,6 +615,8 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
PQExpBufferData workBuf; PQExpBufferData workBuf;
char id; char id;
const char *val; const char *val;
const char *querytext = NULL;
int querypos = 0;
/* /*
* Since the fields might be pretty long, we create a temporary * Since the fields might be pretty long, we create a temporary
@ -666,22 +669,46 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
val = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION); val = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION);
if (val) if (val)
{ {
if (conn->verbosity != PQERRORS_TERSE && conn->last_query != NULL)
{
/* emit position as a syntax cursor display */
querytext = conn->last_query;
querypos = atoi(val);
}
else
{
/* emit position as text addition to primary message */
/* translator: %s represents a digit string */ /* translator: %s represents a digit string */
appendPQExpBuffer(&workBuf, libpq_gettext(" at character %s"), val); appendPQExpBuffer(&workBuf, libpq_gettext(" at character %s"),
val);
}
} }
else else
{ {
val = PQresultErrorField(res, PG_DIAG_INTERNAL_POSITION); val = PQresultErrorField(res, PG_DIAG_INTERNAL_POSITION);
if (val) if (val)
{ {
querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
if (conn->verbosity != PQERRORS_TERSE && querytext != NULL)
{
/* emit position as a syntax cursor display */
querypos = atoi(val);
}
else
{
/* emit position as text addition to primary message */
/* translator: %s represents a digit string */ /* translator: %s represents a digit string */
appendPQExpBuffer(&workBuf, libpq_gettext(" at character %s"), appendPQExpBuffer(&workBuf, libpq_gettext(" at character %s"),
val); val);
} }
} }
}
appendPQExpBufferChar(&workBuf, '\n'); appendPQExpBufferChar(&workBuf, '\n');
if (conn->verbosity != PQERRORS_TERSE) if (conn->verbosity != PQERRORS_TERSE)
{ {
if (querytext && querypos > 0)
reportErrorPosition(&workBuf, querytext, querypos,
conn->client_encoding);
val = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL); val = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
if (val) if (val)
appendPQExpBuffer(&workBuf, libpq_gettext("DETAIL: %s\n"), val); appendPQExpBuffer(&workBuf, libpq_gettext("DETAIL: %s\n"), val);
@ -746,6 +773,212 @@ fail:
return EOF; return EOF;
} }
/*
* Add an error-location display to the error message under construction.
*
* The cursor location is measured in logical characters; the query string
* is presumed to be in the specified encoding.
*/
static void
reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
{
#define DISPLAY_SIZE 60 /* screen width limit, in screen cols */
#define MIN_RIGHT_CUT 10 /* try to keep this far away from EOL */
char *wquery;
int clen,
slen,
i,
w,
*qidx,
*scridx,
qoffset,
scroffset,
ibeg,
iend,
loc_line;
bool beg_trunc,
end_trunc;
/* Need a writable copy of the query */
wquery = strdup(query);
if (wquery == NULL)
return; /* fail silently if out of memory */
/*
* Each character might occupy multiple physical bytes in the string, and
* in some Far Eastern character sets it might take more than one screen
* column as well. We compute the starting byte offset and starting
* screen column of each logical character, and store these in qidx[] and
* scridx[] respectively.
*/
/* we need a safe allocation size... */
slen = strlen(query) + 1;
qidx = (int *) malloc(slen * sizeof(int));
if (qidx == NULL)
{
free(wquery);
return;
}
scridx = (int *) malloc(slen * sizeof(int));
if (scridx == NULL)
{
free(qidx);
free(wquery);
return;
}
qoffset = 0;
scroffset = 0;
for (i = 0; query[qoffset] != '\0'; i++)
{
qidx[i] = qoffset;
scridx[i] = scroffset;
w = pg_encoding_dsplen(encoding, &query[qoffset]);
/* treat control chars as width 1; see tab hack below */
if (w <= 0)
w = 1;
scroffset += w;
qoffset += pg_encoding_mblen(encoding, &query[qoffset]);
}
qidx[i] = qoffset;
scridx[i] = scroffset;
clen = i;
/* convert loc to zero-based offset in qidx/scridx arrays */
loc--;
/* do we have something to show? */
if (loc >= 0 && loc <= clen)
{
/* input line number of our syntax error. */
loc_line = 1;
/* first included char of extract. */
ibeg = 0;
/* last-plus-1 included char of extract. */
iend = clen;
/*
* Replace tabs with spaces in the writable copy. (Later we might
* want to think about coping with their variable screen width, but
* not today.)
*
* Extract line number and begin and end indexes of line containing
* error location. There will not be any newlines or carriage returns
* in the selected extract.
*/
for (i = 0; i < clen; i++)
{
/* character length must be 1 or it's not ASCII */
if ((qidx[i + 1] - qidx[i]) == 1)
{
if (wquery[qidx[i]] == '\t')
wquery[qidx[i]] = ' ';
else if (wquery[qidx[i]] == '\r' || wquery[qidx[i]] == '\n')
{
if (i < loc)
{
/*
* count lines before loc. Each \r or \n counts
* as a line except when \r \n appear together.
*/
if (wquery[qidx[i]] == '\r' ||
i == 0 ||
(qidx[i] - qidx[i - 1]) != 1 ||
wquery[qidx[i - 1]] != '\r')
loc_line++;
/* extract beginning = last line start before loc. */
ibeg = i + 1;
}
else
{
/* set extract end. */
iend = i;
/* done scanning. */
break;
}
}
}
}
/* If the line extracted is too long, we truncate it. */
beg_trunc = false;
end_trunc = false;
if (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
{
/*
* We first truncate right if it is enough. This code might be
* off a space or so on enforcing MIN_RIGHT_CUT if there's a wide
* character right there, but that should be okay.
*/
if (scridx[ibeg] + DISPLAY_SIZE >= scridx[loc] + MIN_RIGHT_CUT)
{
while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
iend--;
end_trunc = true;
}
else
{
/* Truncate right if not too close to loc. */
while (scridx[loc] + MIN_RIGHT_CUT < scridx[iend])
{
iend--;
end_trunc = true;
}
/* Truncate left if still too long. */
while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
{
ibeg++;
beg_trunc = true;
}
}
}
/* truncate working copy at desired endpoint */
wquery[qidx[iend]] = '\0';
/* Begin building the finished message. */
i = msg->len;
appendPQExpBuffer(msg, libpq_gettext("LINE %d: "), loc_line);
if (beg_trunc)
appendPQExpBufferStr(msg, "...");
/*
* While we have the prefix in the msg buffer, compute its screen
* width.
*/
scroffset = 0;
for (; i < msg->len; i += pg_encoding_mblen(encoding, &msg->data[i]))
{
w = pg_encoding_dsplen(encoding, &msg->data[i]);
if (w <= 0)
w = 1;
scroffset += w;
}
/* Finish up the LINE message line. */
appendPQExpBufferStr(msg, &wquery[qidx[ibeg]]);
if (end_trunc)
appendPQExpBufferStr(msg, "...");
appendPQExpBufferChar(msg, '\n');
/* Now emit the cursor marker line. */
scroffset += scridx[loc] - scridx[ibeg];
for (i = 0; i < scroffset; i++)
appendPQExpBufferChar(msg, ' ');
appendPQExpBufferChar(msg, '^');
appendPQExpBufferChar(msg, '\n');
}
/* Clean up. */
free(scridx);
free(qidx);
free(wquery);
}
/* /*
* Attempt to read a ParameterStatus message. * Attempt to read a ParameterStatus message.

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.111 2006/03/05 15:59:10 momjian Exp $ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.112 2006/03/14 22:48:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -278,6 +278,7 @@ struct pg_conn
PGAsyncStatusType asyncStatus; PGAsyncStatusType asyncStatus;
PGTransactionStatusType xactStatus; /* never changes to ACTIVE */ PGTransactionStatusType xactStatus; /* never changes to ACTIVE */
PGQueryClass queryclass; PGQueryClass queryclass;
char *last_query; /* last SQL command, or NULL if unknown */
bool options_valid; /* true if OK to attempt connection */ bool options_valid; /* true if OK to attempt connection */
bool nonblocking; /* whether this connection is using nonblock bool nonblocking; /* whether this connection is using nonblock
* sending semantics */ * sending semantics */

View File

@ -39,6 +39,8 @@ ERROR: creation of Perl function failed: Global symbol "$global" requires expli
Global symbol "$other_global" requires explicit package name at line 4. Global symbol "$other_global" requires explicit package name at line 4.
select uses_global(); select uses_global();
ERROR: function uses_global() does not exist ERROR: function uses_global() does not exist
LINE 1: select uses_global();
^
HINT: No function matches the given name and argument types. You may need to add explicit type casts. HINT: No function matches the given name and argument types. You may need to add explicit type casts.
SET plperl.use_strict = false; SET plperl.use_strict = false;
create or replace function uses_global() returns text language plperl as $$ create or replace function uses_global() returns text language plperl as $$

View File

@ -1,7 +1,7 @@
/********************************************************************** /**********************************************************************
* plperl.c - perl as a procedural language for PostgreSQL * plperl.c - perl as a procedural language for PostgreSQL
* *
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.105 2006/03/11 16:43:22 momjian Exp $ * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.106 2006/03/14 22:48:23 tgl Exp $
* *
**********************************************************************/ **********************************************************************/
@ -19,12 +19,13 @@
#include "commands/trigger.h" #include "commands/trigger.h"
#include "executor/spi.h" #include "executor/spi.h"
#include "funcapi.h" #include "funcapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_type.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/typcache.h" #include "utils/typcache.h"
#include "miscadmin.h"
#include "mb/pg_wchar.h"
#include "parser/parse_type.h"
/* define this before the perl headers get a chance to mangle DLLIMPORT */ /* define this before the perl headers get a chance to mangle DLLIMPORT */
extern DLLIMPORT bool check_function_bodies; extern DLLIMPORT bool check_function_bodies;
@ -1950,7 +1951,6 @@ plperl_spi_prepare(char* query, int argc, SV ** argv)
plperl_query_desc *qdesc; plperl_query_desc *qdesc;
void *plan; void *plan;
int i; int i;
HeapTuple typeTup;
MemoryContext oldcontext = CurrentMemoryContext; MemoryContext oldcontext = CurrentMemoryContext;
ResourceOwner oldowner = CurrentResourceOwner; ResourceOwner oldowner = CurrentResourceOwner;
@ -1977,33 +1977,18 @@ plperl_spi_prepare(char* query, int argc, SV ** argv)
************************************************************/ ************************************************************/
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
{ {
char *argcopy; List *names;
List *names = NIL; HeapTuple typeTup;
ListCell *l;
TypeName *typename;
/************************************************************ /* Parse possibly-qualified type name and look it up in pg_type */
* Use SplitIdentifierString() on a copy of the type name, names = stringToQualifiedNameList(SvPV(argv[i], PL_na),
* turn the resulting pointer list into a TypeName node "plperl_spi_prepare");
* and call typenameType() to get the pg_type tuple. typeTup = typenameType(NULL, makeTypeNameFromNameList(names));
************************************************************/
argcopy = pstrdup(SvPV(argv[i],PL_na));
SplitIdentifierString(argcopy, '.', &names);
typename = makeNode(TypeName);
foreach(l, names)
typename->names = lappend(typename->names, makeString(lfirst(l)));
typeTup = typenameType(typename);
qdesc->argtypes[i] = HeapTupleGetOid(typeTup); qdesc->argtypes[i] = HeapTupleGetOid(typeTup);
perm_fmgr_info(((Form_pg_type) GETSTRUCT(typeTup))->typinput, perm_fmgr_info(((Form_pg_type) GETSTRUCT(typeTup))->typinput,
&(qdesc->arginfuncs[i])); &(qdesc->arginfuncs[i]));
qdesc->argtypioparams[i] = getTypeIOParam(typeTup); qdesc->argtypioparams[i] = getTypeIOParam(typeTup);
ReleaseSysCache(typeTup); ReleaseSysCache(typeTup);
list_free(typename->names);
pfree(typename);
list_free(names);
pfree(argcopy);
} }
/************************************************************ /************************************************************

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.100 2006/03/09 21:29:36 momjian Exp $ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.101 2006/03/14 22:48:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1082,7 +1082,7 @@ plpgsql_parse_wordtype(char *word)
* Word wasn't found on the namestack. Try to find a data type with that * Word wasn't found on the namestack. Try to find a data type with that
* name, but ignore pg_type entries that are in fact class types. * name, but ignore pg_type entries that are in fact class types.
*/ */
typeOid = LookupTypeName(makeTypeName(cp[0])); typeOid = LookupTypeName(NULL, makeTypeName(cp[0]));
if (OidIsValid(typeOid)) if (OidIsValid(typeOid))
{ {
HeapTuple typeTup; HeapTuple typeTup;

View File

@ -1,7 +1,7 @@
/********************************************************************** /**********************************************************************
* plpython.c - python as a procedural language for PostgreSQL * plpython.c - python as a procedural language for PostgreSQL
* *
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.75 2006/03/11 16:43:22 momjian Exp $ * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.76 2006/03/14 22:48:24 tgl Exp $
* *
********************************************************************* *********************************************************************
*/ */
@ -23,6 +23,7 @@
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/syscache.h" #include "utils/syscache.h"
@ -1873,6 +1874,7 @@ PLy_spi_prepare(PyObject * self, PyObject * args)
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)
{ {
char *sptr; char *sptr;
List *names;
HeapTuple typeTup; HeapTuple typeTup;
Form_pg_type typeStruct; Form_pg_type typeStruct;
@ -1882,9 +1884,13 @@ PLy_spi_prepare(PyObject * self, PyObject * args)
sptr = PyString_AsString(optr); sptr = PyString_AsString(optr);
/* /*
* XXX should extend this to allow qualified type names * Parse possibly-qualified type name and look it up in
* pg_type
*/ */
typeTup = typenameType(makeTypeName(sptr)); names = stringToQualifiedNameList(sptr,
"PLy_spi_prepare");
typeTup = typenameType(NULL,
makeTypeNameFromNameList(names));
Py_DECREF(optr); Py_DECREF(optr);
optr = NULL; /* this is important */ optr = NULL; /* this is important */

View File

@ -2,7 +2,7 @@
* pltcl.c - PostgreSQL support for Tcl as * pltcl.c - PostgreSQL support for Tcl as
* procedural language (PL) * procedural language (PL)
* *
* $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.100 2006/03/11 16:43:22 momjian Exp $ * $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.101 2006/03/14 22:48:24 tgl Exp $
* *
**********************************************************************/ **********************************************************************/
@ -1754,7 +1754,6 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
pltcl_query_desc *qdesc; pltcl_query_desc *qdesc;
void *plan; void *plan;
int i; int i;
HeapTuple typeTup;
Tcl_HashEntry *hashent; Tcl_HashEntry *hashent;
int hashnew; int hashnew;
Tcl_HashTable *query_hash; Tcl_HashTable *query_hash;
@ -1802,33 +1801,18 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
************************************************************/ ************************************************************/
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)
{ {
char *argcopy; List *names;
List *names = NIL; HeapTuple typeTup;
ListCell *l;
TypeName *typename;
/************************************************************ /* Parse possibly-qualified type name and look it up in pg_type */
* Use SplitIdentifierString() on a copy of the type name, names = stringToQualifiedNameList(args[i],
* turn the resulting pointer list into a TypeName node "pltcl_SPI_prepare");
* and call typenameType() to get the pg_type tuple. typeTup = typenameType(NULL, makeTypeNameFromNameList(names));
************************************************************/
argcopy = pstrdup(args[i]);
SplitIdentifierString(argcopy, '.', &names);
typename = makeNode(TypeName);
foreach(l, names)
typename->names = lappend(typename->names, makeString(lfirst(l)));
typeTup = typenameType(typename);
qdesc->argtypes[i] = HeapTupleGetOid(typeTup); qdesc->argtypes[i] = HeapTupleGetOid(typeTup);
perm_fmgr_info(((Form_pg_type) GETSTRUCT(typeTup))->typinput, perm_fmgr_info(((Form_pg_type) GETSTRUCT(typeTup))->typinput,
&(qdesc->arginfuncs[i])); &(qdesc->arginfuncs[i]));
qdesc->argtypioparams[i] = getTypeIOParam(typeTup); qdesc->argtypioparams[i] = getTypeIOParam(typeTup);
ReleaseSysCache(typeTup); ReleaseSysCache(typeTup);
list_free(typename->names);
pfree(typename);
list_free(names);
pfree(argcopy);
} }
/************************************************************ /************************************************************

View File

@ -616,12 +616,20 @@ select * from atacc1;
select * from atacc1 order by a; select * from atacc1 order by a;
ERROR: column "a" does not exist ERROR: column "a" does not exist
LINE 1: select * from atacc1 order by a;
^
select * from atacc1 order by "........pg.dropped.1........"; select * from atacc1 order by "........pg.dropped.1........";
ERROR: column "........pg.dropped.1........" does not exist ERROR: column "........pg.dropped.1........" does not exist
LINE 1: select * from atacc1 order by "........pg.dropped.1........"...
^
select * from atacc1 group by a; select * from atacc1 group by a;
ERROR: column "a" does not exist ERROR: column "a" does not exist
LINE 1: select * from atacc1 group by a;
^
select * from atacc1 group by "........pg.dropped.1........"; select * from atacc1 group by "........pg.dropped.1........";
ERROR: column "........pg.dropped.1........" does not exist ERROR: column "........pg.dropped.1........" does not exist
LINE 1: select * from atacc1 group by "........pg.dropped.1........"...
^
select atacc1.* from atacc1; select atacc1.* from atacc1;
b | c | d b | c | d
---+---+--- ---+---+---
@ -630,8 +638,12 @@ select atacc1.* from atacc1;
select a from atacc1; select a from atacc1;
ERROR: column "a" does not exist ERROR: column "a" does not exist
LINE 1: select a from atacc1;
^
select atacc1.a from atacc1; select atacc1.a from atacc1;
ERROR: column atacc1.a does not exist ERROR: column atacc1.a does not exist
LINE 1: select atacc1.a from atacc1;
^
select b,c,d from atacc1; select b,c,d from atacc1;
b | c | d b | c | d
---+---+--- ---+---+---
@ -640,25 +652,41 @@ select b,c,d from atacc1;
select a,b,c,d from atacc1; select a,b,c,d from atacc1;
ERROR: column "a" does not exist ERROR: column "a" does not exist
LINE 1: select a,b,c,d from atacc1;
^
select * from atacc1 where a = 1; select * from atacc1 where a = 1;
ERROR: column "a" does not exist ERROR: column "a" does not exist
LINE 1: select * from atacc1 where a = 1;
^
select "........pg.dropped.1........" from atacc1; select "........pg.dropped.1........" from atacc1;
ERROR: column "........pg.dropped.1........" does not exist ERROR: column "........pg.dropped.1........" does not exist
LINE 1: select "........pg.dropped.1........" from atacc1;
^
select atacc1."........pg.dropped.1........" from atacc1; select atacc1."........pg.dropped.1........" from atacc1;
ERROR: column atacc1.........pg.dropped.1........ does not exist ERROR: column atacc1.........pg.dropped.1........ does not exist
LINE 1: select atacc1."........pg.dropped.1........" from atacc1;
^
select "........pg.dropped.1........",b,c,d from atacc1; select "........pg.dropped.1........",b,c,d from atacc1;
ERROR: column "........pg.dropped.1........" does not exist ERROR: column "........pg.dropped.1........" does not exist
LINE 1: select "........pg.dropped.1........",b,c,d from atacc1;
^
select * from atacc1 where "........pg.dropped.1........" = 1; select * from atacc1 where "........pg.dropped.1........" = 1;
ERROR: column "........pg.dropped.1........" does not exist ERROR: column "........pg.dropped.1........" does not exist
LINE 1: select * from atacc1 where "........pg.dropped.1........" = ...
^
-- UPDATEs -- UPDATEs
update atacc1 set a = 3; update atacc1 set a = 3;
ERROR: column "a" of relation "atacc1" does not exist ERROR: column "a" of relation "atacc1" does not exist
update atacc1 set b = 2 where a = 3; update atacc1 set b = 2 where a = 3;
ERROR: column "a" does not exist ERROR: column "a" does not exist
LINE 1: update atacc1 set b = 2 where a = 3;
^
update atacc1 set "........pg.dropped.1........" = 3; update atacc1 set "........pg.dropped.1........" = 3;
ERROR: column "........pg.dropped.1........" of relation "atacc1" does not exist ERROR: column "........pg.dropped.1........" of relation "atacc1" does not exist
update atacc1 set b = 2 where "........pg.dropped.1........" = 3; update atacc1 set b = 2 where "........pg.dropped.1........" = 3;
ERROR: column "........pg.dropped.1........" does not exist ERROR: column "........pg.dropped.1........" does not exist
LINE 1: update atacc1 set b = 2 where "........pg.dropped.1........"...
^
-- INSERTs -- INSERTs
insert into atacc1 values (10, 11, 12, 13); insert into atacc1 values (10, 11, 12, 13);
ERROR: INSERT has more expressions than target columns ERROR: INSERT has more expressions than target columns
@ -685,8 +713,12 @@ ERROR: column "........pg.dropped.1........" of relation "atacc1" does not exis
-- DELETEs -- DELETEs
delete from atacc1 where a = 3; delete from atacc1 where a = 3;
ERROR: column "a" does not exist ERROR: column "a" does not exist
LINE 1: delete from atacc1 where a = 3;
^
delete from atacc1 where "........pg.dropped.1........" = 3; delete from atacc1 where "........pg.dropped.1........" = 3;
ERROR: column "........pg.dropped.1........" does not exist ERROR: column "........pg.dropped.1........" does not exist
LINE 1: delete from atacc1 where "........pg.dropped.1........" = 3;
^
delete from atacc1; delete from atacc1;
-- try dropping a non-existent column, should fail -- try dropping a non-existent column, should fail
alter table atacc1 drop bar; alter table atacc1 drop bar;
@ -926,6 +958,8 @@ select f1 from c1;
alter table c1 drop column f1; alter table c1 drop column f1;
select f1 from c1; select f1 from c1;
ERROR: column "f1" does not exist ERROR: column "f1" does not exist
LINE 1: select f1 from c1;
^
drop table p1 cascade; drop table p1 cascade;
NOTICE: drop cascades to table c1 NOTICE: drop cascades to table c1
create table p1 (f1 int, f2 int); create table p1 (f1 int, f2 int);
@ -937,6 +971,8 @@ alter table p1 drop column f1;
-- c1.f1 is dropped now, since there is no local definition for it -- c1.f1 is dropped now, since there is no local definition for it
select f1 from c1; select f1 from c1;
ERROR: column "f1" does not exist ERROR: column "f1" does not exist
LINE 1: select f1 from c1;
^
drop table p1 cascade; drop table p1 cascade;
NOTICE: drop cascades to table c1 NOTICE: drop cascades to table c1
create table p1 (f1 int, f2 int); create table p1 (f1 int, f2 int);
@ -1035,6 +1071,8 @@ select oid > 0, * from altstartwith;
alter table altstartwith set without oids; alter table altstartwith set without oids;
select oid > 0, * from altstartwith; -- fails select oid > 0, * from altstartwith; -- fails
ERROR: column "oid" does not exist ERROR: column "oid" does not exist
LINE 1: select oid > 0, * from altstartwith;
^
select * from altstartwith; select * from altstartwith;
col col
----- -----
@ -1062,8 +1100,12 @@ alter table altwithoid set without oids;
alter table altinhoid set without oids; alter table altinhoid set without oids;
select oid > 0, * from altwithoid; -- fails select oid > 0, * from altwithoid; -- fails
ERROR: column "oid" does not exist ERROR: column "oid" does not exist
LINE 1: select oid > 0, * from altwithoid;
^
select oid > 0, * from altinhoid; -- fails select oid > 0, * from altinhoid; -- fails
ERROR: column "oid" does not exist ERROR: column "oid" does not exist
LINE 1: select oid > 0, * from altinhoid;
^
select * from altwithoid; select * from altwithoid;
col col
----- -----

View File

@ -393,8 +393,12 @@ select 33.4 > all (array[1,2,3]);
-- errors -- errors
select 33 * any ('{1,2,3}'); select 33 * any ('{1,2,3}');
ERROR: op ANY/ALL (array) requires operator to yield boolean ERROR: op ANY/ALL (array) requires operator to yield boolean
LINE 1: select 33 * any ('{1,2,3}');
^
select 33 * any (44); select 33 * any (44);
ERROR: op ANY/ALL (array) requires array on right side ERROR: op ANY/ALL (array) requires array on right side
LINE 1: select 33 * any (44);
^
-- nulls -- nulls
select 33 = any (null::int[]); select 33 = any (null::int[]);
?column? ?column?

View File

@ -19,7 +19,7 @@ select 1;
-- missing relation name -- missing relation name
select; select;
ERROR: syntax error at or near ";" at character 7 ERROR: syntax error at or near ";"
LINE 1: select; LINE 1: select;
^ ^
-- no such relation -- no such relation
@ -27,32 +27,40 @@ select * from nonesuch;
ERROR: relation "nonesuch" does not exist ERROR: relation "nonesuch" does not exist
-- missing target list -- missing target list
select from pg_database; select from pg_database;
ERROR: syntax error at or near "from" at character 8 ERROR: syntax error at or near "from"
LINE 1: select from pg_database; LINE 1: select from pg_database;
^ ^
-- bad name in target list -- bad name in target list
select nonesuch from pg_database; select nonesuch from pg_database;
ERROR: column "nonesuch" does not exist ERROR: column "nonesuch" does not exist
LINE 1: select nonesuch from pg_database;
^
-- bad attribute name on lhs of operator -- bad attribute name on lhs of operator
select * from pg_database where nonesuch = pg_database.datname; select * from pg_database where nonesuch = pg_database.datname;
ERROR: column "nonesuch" does not exist ERROR: column "nonesuch" does not exist
LINE 1: select * from pg_database where nonesuch = pg_database.datna...
^
-- bad attribute name on rhs of operator -- bad attribute name on rhs of operator
select * from pg_database where pg_database.datname = nonesuch; select * from pg_database where pg_database.datname = nonesuch;
ERROR: column "nonesuch" does not exist ERROR: column "nonesuch" does not exist
LINE 1: ...ect * from pg_database where pg_database.datname = nonesuch;
^
-- bad select distinct on syntax, distinct attribute missing -- bad select distinct on syntax, distinct attribute missing
select distinct on (foobar) from pg_database; select distinct on (foobar) from pg_database;
ERROR: syntax error at or near "from" at character 29 ERROR: syntax error at or near "from"
LINE 1: select distinct on (foobar) from pg_database; LINE 1: select distinct on (foobar) from pg_database;
^ ^
-- bad select distinct on syntax, distinct attribute not in target list -- bad select distinct on syntax, distinct attribute not in target list
select distinct on (foobar) * from pg_database; select distinct on (foobar) * from pg_database;
ERROR: column "foobar" does not exist ERROR: column "foobar" does not exist
LINE 1: select distinct on (foobar) * from pg_database;
^
-- --
-- DELETE -- DELETE
-- missing relation name (this had better not wildcard!) -- missing relation name (this had better not wildcard!)
delete from; delete from;
ERROR: syntax error at or near ";" at character 12 ERROR: syntax error at or near ";"
LINE 1: delete from; LINE 1: delete from;
^ ^
-- no such relation -- no such relation
@ -63,7 +71,7 @@ ERROR: relation "nonesuch" does not exist
-- missing relation name (this had better not wildcard!) -- missing relation name (this had better not wildcard!)
drop table; drop table;
ERROR: syntax error at or near ";" at character 11 ERROR: syntax error at or near ";"
LINE 1: drop table; LINE 1: drop table;
^ ^
-- no such relation -- no such relation
@ -75,7 +83,7 @@ ERROR: table "nonesuch" does not exist
-- relation renaming -- relation renaming
-- missing relation name -- missing relation name
alter table rename; alter table rename;
ERROR: syntax error at or near ";" at character 19 ERROR: syntax error at or near ";"
LINE 1: alter table rename; LINE 1: alter table rename;
^ ^
-- no such relation -- no such relation
@ -131,12 +139,12 @@ ERROR: aggregate basetype must be specified
-- missing index name -- missing index name
drop index; drop index;
ERROR: syntax error at or near ";" at character 11 ERROR: syntax error at or near ";"
LINE 1: drop index; LINE 1: drop index;
^ ^
-- bad index name -- bad index name
drop index 314159; drop index 314159;
ERROR: syntax error at or near "314159" at character 12 ERROR: syntax error at or near "314159"
LINE 1: drop index 314159; LINE 1: drop index 314159;
^ ^
-- no such index -- no such index
@ -147,17 +155,17 @@ ERROR: index "nonesuch" does not exist
-- missing aggregate name -- missing aggregate name
drop aggregate; drop aggregate;
ERROR: syntax error at or near ";" at character 15 ERROR: syntax error at or near ";"
LINE 1: drop aggregate; LINE 1: drop aggregate;
^ ^
-- missing aggregate type -- missing aggregate type
drop aggregate newcnt1; drop aggregate newcnt1;
ERROR: syntax error at or near ";" at character 23 ERROR: syntax error at or near ";"
LINE 1: drop aggregate newcnt1; LINE 1: drop aggregate newcnt1;
^ ^
-- bad aggregate name -- bad aggregate name
drop aggregate 314159 (int); drop aggregate 314159 (int);
ERROR: syntax error at or near "314159" at character 16 ERROR: syntax error at or near "314159"
LINE 1: drop aggregate 314159 (int); LINE 1: drop aggregate 314159 (int);
^ ^
-- bad aggregate type -- bad aggregate type
@ -174,12 +182,12 @@ ERROR: aggregate newcnt(real) does not exist
-- missing function name -- missing function name
drop function (); drop function ();
ERROR: syntax error at or near "(" at character 15 ERROR: syntax error at or near "("
LINE 1: drop function (); LINE 1: drop function ();
^ ^
-- bad function name -- bad function name
drop function 314159(); drop function 314159();
ERROR: syntax error at or near "314159" at character 15 ERROR: syntax error at or near "314159"
LINE 1: drop function 314159(); LINE 1: drop function 314159();
^ ^
-- no such function -- no such function
@ -190,12 +198,12 @@ ERROR: function nonesuch() does not exist
-- missing type name -- missing type name
drop type; drop type;
ERROR: syntax error at or near ";" at character 10 ERROR: syntax error at or near ";"
LINE 1: drop type; LINE 1: drop type;
^ ^
-- bad type name -- bad type name
drop type 314159; drop type 314159;
ERROR: syntax error at or near "314159" at character 11 ERROR: syntax error at or near "314159"
LINE 1: drop type 314159; LINE 1: drop type 314159;
^ ^
-- no such type -- no such type
@ -206,32 +214,32 @@ ERROR: type "nonesuch" does not exist
-- missing everything -- missing everything
drop operator; drop operator;
ERROR: syntax error at or near ";" at character 14 ERROR: syntax error at or near ";"
LINE 1: drop operator; LINE 1: drop operator;
^ ^
-- bad operator name -- bad operator name
drop operator equals; drop operator equals;
ERROR: syntax error at or near ";" at character 21 ERROR: syntax error at or near ";"
LINE 1: drop operator equals; LINE 1: drop operator equals;
^ ^
-- missing type list -- missing type list
drop operator ===; drop operator ===;
ERROR: syntax error at or near ";" at character 18 ERROR: syntax error at or near ";"
LINE 1: drop operator ===; LINE 1: drop operator ===;
^ ^
-- missing parentheses -- missing parentheses
drop operator int4, int4; drop operator int4, int4;
ERROR: syntax error at or near "," at character 19 ERROR: syntax error at or near ","
LINE 1: drop operator int4, int4; LINE 1: drop operator int4, int4;
^ ^
-- missing operator name -- missing operator name
drop operator (int4, int4); drop operator (int4, int4);
ERROR: syntax error at or near "(" at character 15 ERROR: syntax error at or near "("
LINE 1: drop operator (int4, int4); LINE 1: drop operator (int4, int4);
^ ^
-- missing type list contents -- missing type list contents
drop operator === (); drop operator === ();
ERROR: syntax error at or near ")" at character 20 ERROR: syntax error at or near ")"
LINE 1: drop operator === (); LINE 1: drop operator === ();
^ ^
-- no such operator -- no such operator
@ -247,18 +255,18 @@ ERROR: missing argument
HINT: Use NONE to denote the missing argument of a unary operator. HINT: Use NONE to denote the missing argument of a unary operator.
-- no such type1 -- no such type1
drop operator = ( , int4); drop operator = ( , int4);
ERROR: syntax error at or near "," at character 19 ERROR: syntax error at or near ","
LINE 1: drop operator = ( , int4); LINE 1: drop operator = ( , int4);
^ ^
-- no such type1 -- no such type1
drop operator = (nonesuch, int4); drop operator = (nonesuch, int4);
ERROR: type nonesuch does not exist ERROR: type "nonesuch" does not exist
-- no such type2 -- no such type2
drop operator = (int4, nonesuch); drop operator = (int4, nonesuch);
ERROR: type nonesuch does not exist ERROR: type "nonesuch" does not exist
-- no such type2 -- no such type2
drop operator = (int4, ); drop operator = (int4, );
ERROR: syntax error at or near ")" at character 24 ERROR: syntax error at or near ")"
LINE 1: drop operator = (int4, ); LINE 1: drop operator = (int4, );
^ ^
-- --
@ -266,12 +274,12 @@ LINE 1: drop operator = (int4, );
-- missing rule name -- missing rule name
drop rule; drop rule;
ERROR: syntax error at or near ";" at character 10 ERROR: syntax error at or near ";"
LINE 1: drop rule; LINE 1: drop rule;
^ ^
-- bad rule name -- bad rule name
drop rule 314159; drop rule 314159;
ERROR: syntax error at or near "314159" at character 11 ERROR: syntax error at or near "314159"
LINE 1: drop rule 314159; LINE 1: drop rule 314159;
^ ^
-- no such rule -- no such rule
@ -279,15 +287,15 @@ drop rule nonesuch on noplace;
ERROR: relation "noplace" does not exist ERROR: relation "noplace" does not exist
-- these postquel variants are no longer supported -- these postquel variants are no longer supported
drop tuple rule nonesuch; drop tuple rule nonesuch;
ERROR: syntax error at or near "tuple" at character 6 ERROR: syntax error at or near "tuple"
LINE 1: drop tuple rule nonesuch; LINE 1: drop tuple rule nonesuch;
^ ^
drop instance rule nonesuch on noplace; drop instance rule nonesuch on noplace;
ERROR: syntax error at or near "instance" at character 6 ERROR: syntax error at or near "instance"
LINE 1: drop instance rule nonesuch on noplace; LINE 1: drop instance rule nonesuch on noplace;
^ ^
drop rewrite rule nonesuch; drop rewrite rule nonesuch;
ERROR: syntax error at or near "rewrite" at character 6 ERROR: syntax error at or near "rewrite"
LINE 1: drop rewrite rule nonesuch; LINE 1: drop rewrite rule nonesuch;
^ ^
-- --
@ -319,35 +327,35 @@ ERROR: division by zero
-- Test psql's reporting of syntax error location -- Test psql's reporting of syntax error location
-- --
xxx; xxx;
ERROR: syntax error at or near "xxx" at character 1 ERROR: syntax error at or near "xxx"
LINE 1: xxx; LINE 1: xxx;
^ ^
CREATE foo; CREATE foo;
ERROR: syntax error at or near "foo" at character 8 ERROR: syntax error at or near "foo"
LINE 1: CREATE foo; LINE 1: CREATE foo;
^ ^
CREATE TABLE ; CREATE TABLE ;
ERROR: syntax error at or near ";" at character 14 ERROR: syntax error at or near ";"
LINE 1: CREATE TABLE ; LINE 1: CREATE TABLE ;
^ ^
CREATE TABLE CREATE TABLE
\g \g
ERROR: syntax error at end of input at character 13 ERROR: syntax error at end of input
LINE 1: CREATE TABLE LINE 1: CREATE TABLE
^ ^
INSERT INTO foo VALUES(123) foo; INSERT INTO foo VALUES(123) foo;
ERROR: syntax error at or near "foo" at character 29 ERROR: syntax error at or near "foo"
LINE 1: INSERT INTO foo VALUES(123) foo; LINE 1: INSERT INTO foo VALUES(123) foo;
^ ^
INSERT INTO 123 INSERT INTO 123
VALUES(123); VALUES(123);
ERROR: syntax error at or near "123" at character 13 ERROR: syntax error at or near "123"
LINE 1: INSERT INTO 123 LINE 1: INSERT INTO 123
^ ^
INSERT INTO foo INSERT INTO foo
VALUES(123) 123 VALUES(123) 123
; ;
ERROR: syntax error at or near "123" at character 30 ERROR: syntax error at or near "123"
LINE 2: VALUES(123) 123 LINE 2: VALUES(123) 123
^ ^
-- with a tab -- with a tab
@ -355,24 +363,24 @@ CREATE TABLE foo
(id INT4 UNIQUE NOT NULL, id2 TEXT NOT NULL PRIMARY KEY, (id INT4 UNIQUE NOT NULL, id2 TEXT NOT NULL PRIMARY KEY,
id3 INTEGER NOT NUL, id3 INTEGER NOT NUL,
id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQUE NOT NULL); id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQUE NOT NULL);
ERROR: syntax error at or near "NUL" at character 94 ERROR: syntax error at or near "NUL"
LINE 3: id3 INTEGER NOT NUL, LINE 3: id3 INTEGER NOT NUL,
^ ^
-- long line to be truncated on the left -- long line to be truncated on the left
CREATE TABLE foo(id INT4 UNIQUE NOT NULL, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, CREATE TABLE foo(id INT4 UNIQUE NOT NULL, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL,
id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQUE NOT NULL); id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQUE NOT NULL);
ERROR: syntax error at or near "NUL" at character 90 ERROR: syntax error at or near "NUL"
LINE 1: ...T NULL, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, LINE 1: ...T NULL, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL,
^ ^
-- long line to be truncated on the right -- long line to be truncated on the right
CREATE TABLE foo( CREATE TABLE foo(
id3 INTEGER NOT NUL, id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQUE NOT NULL, id INT4 UNIQUE NOT NULL, id2 TEXT NOT NULL PRIMARY KEY); id3 INTEGER NOT NUL, id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQUE NOT NULL, id INT4 UNIQUE NOT NULL, id2 TEXT NOT NULL PRIMARY KEY);
ERROR: syntax error at or near "NUL" at character 35 ERROR: syntax error at or near "NUL"
LINE 2: id3 INTEGER NOT NUL, id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQ... LINE 2: id3 INTEGER NOT NUL, id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQ...
^ ^
-- long line to be truncated both ways -- long line to be truncated both ways
CREATE TABLE foo(id INT4 UNIQUE NOT NULL, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQUE NOT NULL); CREATE TABLE foo(id INT4 UNIQUE NOT NULL, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQUE NOT NULL);
ERROR: syntax error at or near "NUL" at character 90 ERROR: syntax error at or near "NUL"
LINE 1: ...L, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, id4 I... LINE 1: ...L, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, id4 I...
^ ^
-- long line to be truncated on the left, many lines -- long line to be truncated on the left, many lines
@ -389,7 +397,7 @@ UNIQUE
NOT NOT
NULL) NULL)
; ;
ERROR: syntax error at or near "NUL" at character 101 ERROR: syntax error at or near "NUL"
LINE 4: ...T NULL, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, LINE 4: ...T NULL, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL,
^ ^
-- long line to be truncated on the right, many lines -- long line to be truncated on the right, many lines
@ -399,7 +407,7 @@ TABLE
foo( foo(
id3 INTEGER NOT NUL, id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQUE NOT NULL, id INT4 UNIQUE NOT NULL, id2 TEXT NOT NULL PRIMARY KEY) id3 INTEGER NOT NUL, id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQUE NOT NULL, id INT4 UNIQUE NOT NULL, id2 TEXT NOT NULL PRIMARY KEY)
; ;
ERROR: syntax error at or near "NUL" at character 47 ERROR: syntax error at or near "NUL"
LINE 5: id3 INTEGER NOT NUL, id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQ... LINE 5: id3 INTEGER NOT NUL, id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQ...
^ ^
-- long line to be truncated both ways, many lines -- long line to be truncated both ways, many lines
@ -412,7 +420,7 @@ INT4
UNIQUE NOT NULL, idx INT4 UNIQUE NOT NULL, idy INT4 UNIQUE NOT NULL, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQUE NOT NULL, UNIQUE NOT NULL, idx INT4 UNIQUE NOT NULL, idy INT4 UNIQUE NOT NULL, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, id4 INT4 UNIQUE NOT NULL, id5 TEXT UNIQUE NOT NULL,
idz INT4 UNIQUE NOT NULL, idz INT4 UNIQUE NOT NULL,
idv INT4 UNIQUE NOT NULL); idv INT4 UNIQUE NOT NULL);
ERROR: syntax error at or near "NUL" at character 157 ERROR: syntax error at or near "NUL"
LINE 7: ...L, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, id4 I... LINE 7: ...L, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, id4 I...
^ ^
-- more than 10 lines... -- more than 10 lines...
@ -438,7 +446,7 @@ INT4
UNIQUE UNIQUE
NOT NOT
NULL); NULL);
ERROR: syntax error at or near "NUL" at character 190 ERROR: syntax error at or near "NUL"
LINE 16: ...L, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, id4 I... LINE 16: ...L, id2 TEXT NOT NULL PRIMARY KEY, id3 INTEGER NOT NUL, id4 I...
^ ^
-- Check that stack depth detection mechanism works and -- Check that stack depth detection mechanism works and

View File

@ -105,6 +105,8 @@ SELECT '' AS one, p1.f1
SELECT '' AS count, p.f1, l.s, l.s # p.f1 AS intersection SELECT '' AS count, p.f1, l.s, l.s # p.f1 AS intersection
FROM LSEG_TBL l, POINT_TBL p; FROM LSEG_TBL l, POINT_TBL p;
ERROR: operator does not exist: lseg # point ERROR: operator does not exist: lseg # point
LINE 1: SELECT '' AS count, p.f1, l.s, l.s # p.f1 AS intersection
^
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts. HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
-- closest point -- closest point
SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest

View File

@ -105,6 +105,8 @@ SELECT '' AS one, p1.f1
SELECT '' AS count, p.f1, l.s, l.s # p.f1 AS intersection SELECT '' AS count, p.f1, l.s, l.s # p.f1 AS intersection
FROM LSEG_TBL l, POINT_TBL p; FROM LSEG_TBL l, POINT_TBL p;
ERROR: operator does not exist: lseg # point ERROR: operator does not exist: lseg # point
LINE 1: SELECT '' AS count, p.f1, l.s, l.s # p.f1 AS intersection
^
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts. HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
-- closest point -- closest point
SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest

View File

@ -105,6 +105,8 @@ SELECT '' AS one, p1.f1
SELECT '' AS count, p.f1, l.s, l.s # p.f1 AS intersection SELECT '' AS count, p.f1, l.s, l.s # p.f1 AS intersection
FROM LSEG_TBL l, POINT_TBL p; FROM LSEG_TBL l, POINT_TBL p;
ERROR: operator does not exist: lseg # point ERROR: operator does not exist: lseg # point
LINE 1: SELECT '' AS count, p.f1, l.s, l.s # p.f1 AS intersection
^
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts. HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
-- closest point -- closest point
SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest

View File

@ -306,6 +306,8 @@ SELECT date '1991-02-03' - time '04:05:06' AS "Subtract Time";
SELECT date '1991-02-03' - time with time zone '04:05:06 UTC' AS "Subtract Time UTC"; SELECT date '1991-02-03' - time with time zone '04:05:06 UTC' AS "Subtract Time UTC";
ERROR: operator does not exist: date - time with time zone ERROR: operator does not exist: date - time with time zone
LINE 1: SELECT date '1991-02-03' - time with time zone '04:05:06 UTC...
^
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts. HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
-- --
-- timestamp, interval arithmetic -- timestamp, interval arithmetic

View File

@ -337,6 +337,8 @@ SELECT '' AS "xxx", *
SELECT '' AS "xxx", i, k, t SELECT '' AS "xxx", i, k, t
FROM J1_TBL CROSS JOIN J2_TBL; FROM J1_TBL CROSS JOIN J2_TBL;
ERROR: column reference "i" is ambiguous ERROR: column reference "i" is ambiguous
LINE 1: SELECT '' AS "xxx", i, k, t
^
-- resolve previous ambiguity by specifying the table name -- resolve previous ambiguity by specifying the table name
SELECT '' AS "xxx", t1.i, k, t SELECT '' AS "xxx", t1.i, k, t
FROM J1_TBL t1 CROSS JOIN J2_TBL t2; FROM J1_TBL t1 CROSS JOIN J2_TBL t2;

View File

@ -337,6 +337,8 @@ SELECT '' AS "xxx", *
SELECT '' AS "xxx", i, k, t SELECT '' AS "xxx", i, k, t
FROM J1_TBL CROSS JOIN J2_TBL; FROM J1_TBL CROSS JOIN J2_TBL;
ERROR: column reference "i" is ambiguous ERROR: column reference "i" is ambiguous
LINE 1: SELECT '' AS "xxx", i, k, t
^
-- resolve previous ambiguity by specifying the table name -- resolve previous ambiguity by specifying the table name
SELECT '' AS "xxx", t1.i, k, t SELECT '' AS "xxx", t1.i, k, t
FROM J1_TBL t1 CROSS JOIN J2_TBL t2; FROM J1_TBL t1 CROSS JOIN J2_TBL t2;

View File

@ -1747,7 +1747,7 @@ create function f1(in i int, out j int) returns int as $$
begin begin
return i+1; return i+1;
end$$ language plpgsql; end$$ language plpgsql;
ERROR: RETURN cannot have a parameter in function with OUT parameters at or near "i" at character 74 ERROR: RETURN cannot have a parameter in function with OUT parameters at or near "i"
LINE 3: return i+1; LINE 3: return i+1;
^ ^
create function f1(in i int, out j int) as $$ create function f1(in i int, out j int) as $$
@ -2323,11 +2323,11 @@ begin
a := 10; a := 10;
return a; return a;
end$$ language plpgsql; end$$ language plpgsql;
ERROR: syntax error at or near "Johnny" at character 1 ERROR: syntax error at or near "Johnny"
QUERY: Johnny Yuma
CONTEXT: SQL statement in PL/PgSQL function "bad_sql1" near line 4
LINE 1: Johnny Yuma LINE 1: Johnny Yuma
^ ^
QUERY: Johnny Yuma
CONTEXT: SQL statement in PL/PgSQL function "bad_sql1" near line 4
create function bad_sql2() returns int as $$ create function bad_sql2() returns int as $$
declare r record; declare r record;
begin begin
@ -2336,27 +2336,27 @@ begin
end loop; end loop;
return 5; return 5;
end;$$ language plpgsql; end;$$ language plpgsql;
ERROR: syntax error at or near "fought" at character 11 ERROR: syntax error at or near "fought"
QUERY: select I fought the law, the law won
CONTEXT: SQL statement in PL/PgSQL function "bad_sql2" near line 3
LINE 1: select I fought the law, the law won LINE 1: select I fought the law, the law won
^ ^
QUERY: select I fought the law, the law won
CONTEXT: SQL statement in PL/PgSQL function "bad_sql2" near line 3
-- a RETURN expression is mandatory, except for void-returning -- a RETURN expression is mandatory, except for void-returning
-- functions, where it is not allowed -- functions, where it is not allowed
create function missing_return_expr() returns int as $$ create function missing_return_expr() returns int as $$
begin begin
return ; return ;
end;$$ language plpgsql; end;$$ language plpgsql;
ERROR: syntax error at end of input at character 8 ERROR: syntax error at end of input
QUERY: SELECT
CONTEXT: SQL statement in PL/PgSQL function "missing_return_expr" near line 2
LINE 1: SELECT LINE 1: SELECT
^ ^
QUERY: SELECT
CONTEXT: SQL statement in PL/PgSQL function "missing_return_expr" near line 2
create function void_return_expr() returns void as $$ create function void_return_expr() returns void as $$
begin begin
return 5; return 5;
end;$$ language plpgsql; end;$$ language plpgsql;
ERROR: RETURN cannot have a parameter in function returning void at or near "5" at character 72 ERROR: RETURN cannot have a parameter in function returning void at or near "5"
LINE 3: return 5; LINE 3: return 5;
^ ^
-- VOID functions are allowed to omit RETURN -- VOID functions are allowed to omit RETURN
@ -2426,8 +2426,10 @@ end; $$ language plpgsql;
-- blocks -- blocks
select excpt_test1(); select excpt_test1();
ERROR: column "sqlstate" does not exist ERROR: column "sqlstate" does not exist
CONTEXT: SQL statement "SELECT sqlstate" LINE 1: SELECT sqlstate
PL/pgSQL function "excpt_test1" line 2 at raise ^
QUERY: SELECT sqlstate
CONTEXT: PL/pgSQL function "excpt_test1" line 2 at raise
create function excpt_test2() returns void as $$ create function excpt_test2() returns void as $$
begin begin
begin begin
@ -2439,8 +2441,10 @@ end; $$ language plpgsql;
-- should fail -- should fail
select excpt_test2(); select excpt_test2();
ERROR: column "sqlstate" does not exist ERROR: column "sqlstate" does not exist
CONTEXT: SQL statement "SELECT sqlstate" LINE 1: SELECT sqlstate
PL/pgSQL function "excpt_test2" line 4 at raise ^
QUERY: SELECT sqlstate
CONTEXT: PL/pgSQL function "excpt_test2" line 4 at raise
create function excpt_test3() returns void as $$ create function excpt_test3() returns void as $$
begin begin
begin begin
@ -2695,7 +2699,7 @@ begin
end loop flbl1; end loop flbl1;
end; end;
$$ language plpgsql; $$ language plpgsql;
ERROR: no such label at or near "flbl1" at character 101 ERROR: no such label at or near "flbl1"
LINE 5: end loop flbl1; LINE 5: end loop flbl1;
^ ^
-- should fail: end label does not match start label -- should fail: end label does not match start label

View File

@ -116,6 +116,8 @@ HINT: You will need to rewrite or cast the expression.
-- invalid type -- invalid type
PREPARE q4(nonexistenttype) AS SELECT $1; PREPARE q4(nonexistenttype) AS SELECT $1;
ERROR: type "nonexistenttype" does not exist ERROR: type "nonexistenttype" does not exist
LINE 1: PREPARE q4(nonexistenttype) AS SELECT $1;
^
-- create table as execute -- create table as execute
PREPARE q5(int, text) AS PREPARE q5(int, text) AS
SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2; SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2;

View File

@ -63,6 +63,8 @@ begin;
set local add_missing_from = false; set local add_missing_from = false;
select f1, q.c1 from quadtable; -- fails, q is a table reference select f1, q.c1 from quadtable; -- fails, q is a table reference
ERROR: missing FROM-clause entry for table "q" ERROR: missing FROM-clause entry for table "q"
LINE 1: select f1, q.c1 from quadtable;
^
rollback; rollback;
select f1, (q).c1, (qq.q).c1.i from quadtable qq; select f1, (q).c1, (qq.q).c1.i from quadtable qq;
f1 | c1 | i f1 | c1 | i
@ -199,6 +201,8 @@ select ROW('ABC','DEF') ~>=~ ROW('DEF','ABC') as false;
select ROW('ABC','DEF') ~~ ROW('DEF','ABC') as fail; select ROW('ABC','DEF') ~~ ROW('DEF','ABC') as fail;
ERROR: could not determine interpretation of row comparison operator ~~ ERROR: could not determine interpretation of row comparison operator ~~
LINE 1: select ROW('ABC','DEF') ~~ ROW('DEF','ABC') as fail;
^
HINT: Row comparison operators must be associated with btree operator classes. HINT: Row comparison operators must be associated with btree operator classes.
-- Check row comparison with a subselect -- Check row comparison with a subselect
select unique1, unique2 from tenk1 select unique1, unique2 from tenk1

View File

@ -121,6 +121,8 @@ SELECT count(*) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a WHERE x.a = y.a
GROUP BY b ORDER BY b; GROUP BY b ORDER BY b;
ERROR: column reference "b" is ambiguous ERROR: column reference "b" is ambiguous
LINE 3: GROUP BY b ORDER BY b;
^
-- order w/ target under ambiguous condition -- order w/ target under ambiguous condition
-- failure NOT expected -- failure NOT expected
SELECT a, a FROM test_missing_target SELECT a, a FROM test_missing_target
@ -287,6 +289,8 @@ SELECT count(x.a) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a WHERE x.a = y.a
GROUP BY b/2 ORDER BY b/2; GROUP BY b/2 ORDER BY b/2;
ERROR: column reference "b" is ambiguous ERROR: column reference "b" is ambiguous
LINE 3: GROUP BY b/2 ORDER BY b/2;
^
-- group w/ existing GROUP BY target under ambiguous condition -- group w/ existing GROUP BY target under ambiguous condition
SELECT x.b/2, count(x.b) FROM test_missing_target x, test_missing_target y SELECT x.b/2, count(x.b) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a WHERE x.a = y.a
@ -304,6 +308,8 @@ SELECT count(b) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a WHERE x.a = y.a
GROUP BY x.b/2; GROUP BY x.b/2;
ERROR: column reference "b" is ambiguous ERROR: column reference "b" is ambiguous
LINE 1: SELECT count(b) FROM test_missing_target x, test_missing_tar...
^
-- group w/o existing GROUP BY target under ambiguous condition -- group w/o existing GROUP BY target under ambiguous condition
-- into a table -- into a table
SELECT count(x.b) INTO TABLE test_missing_target3 SELECT count(x.b) INTO TABLE test_missing_target3

View File

@ -121,6 +121,8 @@ SELECT count(*) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a WHERE x.a = y.a
GROUP BY b ORDER BY b; GROUP BY b ORDER BY b;
ERROR: column reference "b" is ambiguous ERROR: column reference "b" is ambiguous
LINE 3: GROUP BY b ORDER BY b;
^
-- order w/ target under ambiguous condition -- order w/ target under ambiguous condition
-- failure NOT expected -- failure NOT expected
SELECT a, a FROM test_missing_target SELECT a, a FROM test_missing_target
@ -287,6 +289,8 @@ SELECT count(x.a) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a WHERE x.a = y.a
GROUP BY b/2 ORDER BY b/2; GROUP BY b/2 ORDER BY b/2;
ERROR: column reference "b" is ambiguous ERROR: column reference "b" is ambiguous
LINE 3: GROUP BY b/2 ORDER BY b/2;
^
-- group w/ existing GROUP BY target under ambiguous condition -- group w/ existing GROUP BY target under ambiguous condition
SELECT x.b/2, count(x.b) FROM test_missing_target x, test_missing_target y SELECT x.b/2, count(x.b) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a WHERE x.a = y.a
@ -304,6 +308,8 @@ SELECT count(b) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a WHERE x.a = y.a
GROUP BY x.b/2; GROUP BY x.b/2;
ERROR: column reference "b" is ambiguous ERROR: column reference "b" is ambiguous
LINE 1: SELECT count(b) FROM test_missing_target x, test_missing_tar...
^
-- group w/o existing GROUP BY target under ambiguous condition -- group w/o existing GROUP BY target under ambiguous condition
-- into a table -- into a table
SELECT count(x.b) INTO TABLE test_missing_target3 SELECT count(x.b) INTO TABLE test_missing_target3

View File

@ -121,6 +121,8 @@ SELECT count(*) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a WHERE x.a = y.a
GROUP BY b ORDER BY b; GROUP BY b ORDER BY b;
ERROR: column reference "b" is ambiguous ERROR: column reference "b" is ambiguous
LINE 3: GROUP BY b ORDER BY b;
^
-- order w/ target under ambiguous condition -- order w/ target under ambiguous condition
-- failure NOT expected -- failure NOT expected
SELECT a, a FROM test_missing_target SELECT a, a FROM test_missing_target
@ -287,6 +289,8 @@ SELECT count(x.a) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a WHERE x.a = y.a
GROUP BY b/2 ORDER BY b/2; GROUP BY b/2 ORDER BY b/2;
ERROR: column reference "b" is ambiguous ERROR: column reference "b" is ambiguous
LINE 3: GROUP BY b/2 ORDER BY b/2;
^
-- group w/ existing GROUP BY target under ambiguous condition -- group w/ existing GROUP BY target under ambiguous condition
SELECT x.b/2, count(x.b) FROM test_missing_target x, test_missing_target y SELECT x.b/2, count(x.b) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a WHERE x.a = y.a
@ -304,6 +308,8 @@ SELECT count(b) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a WHERE x.a = y.a
GROUP BY x.b/2; GROUP BY x.b/2;
ERROR: column reference "b" is ambiguous ERROR: column reference "b" is ambiguous
LINE 1: SELECT count(b) FROM test_missing_target x, test_missing_tar...
^
-- group w/o existing GROUP BY target under ambiguous condition -- group w/o existing GROUP BY target under ambiguous condition
-- into a table -- into a table
SELECT count(x.b) INTO TABLE test_missing_target3 SELECT count(x.b) INTO TABLE test_missing_target3

View File

@ -18,7 +18,7 @@ SELECT 'first line'
' - next line' /* this comment is not allowed here */ ' - next line' /* this comment is not allowed here */
' - third line' ' - third line'
AS "Illegal comment within continuation"; AS "Illegal comment within continuation";
ERROR: syntax error at or near "' - third line'" at character 75 ERROR: syntax error at or near "' - third line'"
LINE 3: ' - third line' LINE 3: ' - third line'
^ ^
-- --
@ -927,17 +927,29 @@ show standard_conforming_strings;
(1 row) (1 row)
select 'a\bcd' as f1, 'a\b''cd' as f2, 'a\b''''cd' as f3, 'abcd\' as f4, 'ab\''cd' as f5, '\\' as f6; select 'a\bcd' as f1, 'a\b''cd' as f2, 'a\b''''cd' as f3, 'abcd\' as f4, 'ab\''cd' as f5, '\\' as f6;
WARNING: nonstandard use of escape in a string literal at character 8 WARNING: nonstandard use of escape in a string literal
LINE 1: select 'a\bcd' as f1, 'a\b''cd' as f2, 'a\b''''cd' as f3, 'a...
^
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'. HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
WARNING: nonstandard use of escape in a string literal at character 23 WARNING: nonstandard use of escape in a string literal
LINE 1: select 'a\bcd' as f1, 'a\b''cd' as f2, 'a\b''''cd' as f3, 'a...
^
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'. HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
WARNING: nonstandard use of escape in a string literal at character 40 WARNING: nonstandard use of escape in a string literal
LINE 1: select 'a\bcd' as f1, 'a\b''cd' as f2, 'a\b''''cd' as f3, 'a...
^
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'. HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
WARNING: nonstandard use of escape in a string literal at character 59 WARNING: nonstandard use of escape in a string literal
LINE 1: ...a\bcd' as f1, 'a\b''cd' as f2, 'a\b''''cd' as f3, 'abcd\' ...
^
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'. HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
WARNING: nonstandard use of escape in a string literal at character 76 WARNING: nonstandard use of escape in a string literal
LINE 1: ...b''cd' as f2, 'a\b''''cd' as f3, 'abcd\' as f4, 'ab\''cd' ...
^
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'. HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
WARNING: nonstandard use of escape in a string literal at character 93 WARNING: nonstandard use of escape in a string literal
LINE 1: ...b''''cd' as f3, 'abcd\' as f4, 'ab\''cd' as f5, '\\' as f6...
^
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'. HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
f1 | f2 | f3 | f4 | f5 | f6 f1 | f2 | f3 | f4 | f5 | f6
-------+--------+---------+-------+--------+---- -------+--------+---------+-------+--------+----
@ -946,17 +958,29 @@ HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
set standard_conforming_strings = off; set standard_conforming_strings = off;
select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' as f4, 'ab\\\'cd' as f5, '\\\\' as f6; select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' as f4, 'ab\\\'cd' as f5, '\\\\' as f6;
WARNING: nonstandard use of \\ in a string literal at character 8 WARNING: nonstandard use of \\ in a string literal
LINE 1: select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3,...
^
HINT: Use the escape string syntax for backslashes, e.g., E'\\'. HINT: Use the escape string syntax for backslashes, e.g., E'\\'.
WARNING: nonstandard use of \\ in a string literal at character 24 WARNING: nonstandard use of \\ in a string literal
LINE 1: select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3,...
^
HINT: Use the escape string syntax for backslashes, e.g., E'\\'. HINT: Use the escape string syntax for backslashes, e.g., E'\\'.
WARNING: nonstandard use of \\ in a string literal at character 42 WARNING: nonstandard use of \\ in a string literal
LINE 1: select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3,...
^
HINT: Use the escape string syntax for backslashes, e.g., E'\\'. HINT: Use the escape string syntax for backslashes, e.g., E'\\'.
WARNING: nonstandard use of \\ in a string literal at character 62 WARNING: nonstandard use of \\ in a string literal
LINE 1: ...bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' ...
^
HINT: Use the escape string syntax for backslashes, e.g., E'\\'. HINT: Use the escape string syntax for backslashes, e.g., E'\\'.
WARNING: nonstandard use of \\ in a string literal at character 80 WARNING: nonstandard use of \\ in a string literal
LINE 1: ...'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' as f4, 'ab\\\'cd'...
^
HINT: Use the escape string syntax for backslashes, e.g., E'\\'. HINT: Use the escape string syntax for backslashes, e.g., E'\\'.
WARNING: nonstandard use of \\ in a string literal at character 98 WARNING: nonstandard use of \\ in a string literal
LINE 1: ...'''cd' as f3, 'abcd\\' as f4, 'ab\\\'cd' as f5, '\\\\' as ...
^
HINT: Use the escape string syntax for backslashes, e.g., E'\\'. HINT: Use the escape string syntax for backslashes, e.g., E'\\'.
f1 | f2 | f3 | f4 | f5 | f6 f1 | f2 | f3 | f4 | f5 | f6
-------+--------+---------+-------+--------+---- -------+--------+---------+-------+--------+----

View File

@ -70,4 +70,6 @@ SELECT f1 AS "Eight" FROM TIME_TBL WHERE f1 >= '00:00';
-- where we do mixed-type arithmetic. - thomas 2000-12-02 -- where we do mixed-type arithmetic. - thomas 2000-12-02
SELECT f1 + time '00:01' AS "Illegal" FROM TIME_TBL; SELECT f1 + time '00:01' AS "Illegal" FROM TIME_TBL;
ERROR: operator is not unique: time without time zone + time without time zone ERROR: operator is not unique: time without time zone + time without time zone
LINE 1: SELECT f1 + time '00:01' AS "Illegal" FROM TIME_TBL;
^
HINT: Could not choose a best candidate operator. You may need to add explicit type casts. HINT: Could not choose a best candidate operator. You may need to add explicit type casts.

View File

@ -77,4 +77,6 @@ SELECT f1 AS "Ten" FROM TIMETZ_TBL WHERE f1 >= '00:00-07';
-- where we do mixed-type arithmetic. - thomas 2000-12-02 -- where we do mixed-type arithmetic. - thomas 2000-12-02
SELECT f1 + time with time zone '00:01' AS "Illegal" FROM TIMETZ_TBL; SELECT f1 + time with time zone '00:01' AS "Illegal" FROM TIMETZ_TBL;
ERROR: operator does not exist: time with time zone + time with time zone ERROR: operator does not exist: time with time zone + time with time zone
LINE 1: SELECT f1 + time with time zone '00:01' AS "Illegal" FROM TI...
^
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts. HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.

View File

@ -140,6 +140,8 @@ BEGIN;
SAVEPOINT one; SAVEPOINT one;
SELECT foo; SELECT foo;
ERROR: column "foo" does not exist ERROR: column "foo" does not exist
LINE 1: SELECT foo;
^
ROLLBACK TO SAVEPOINT one; ROLLBACK TO SAVEPOINT one;
RELEASE SAVEPOINT one; RELEASE SAVEPOINT one;
SAVEPOINT two; SAVEPOINT two;
@ -188,6 +190,8 @@ BEGIN;
INSERT INTO savepoints VALUES (5); INSERT INTO savepoints VALUES (5);
SELECT foo; SELECT foo;
ERROR: column "foo" does not exist ERROR: column "foo" does not exist
LINE 1: SELECT foo;
^
COMMIT; COMMIT;
SELECT * FROM savepoints; SELECT * FROM savepoints;
a a

View File

@ -405,6 +405,8 @@ ORDER BY q2,q1;
-- This should fail, because q2 isn't a name of an EXCEPT output column -- This should fail, because q2 isn't a name of an EXCEPT output column
SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1; SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1;
ERROR: column "q2" does not exist ERROR: column "q2" does not exist
LINE 1: ... int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1...
^
-- But this should work: -- But this should work:
SELECT q1 FROM int8_tbl EXCEPT (((SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1))); SELECT q1 FROM int8_tbl EXCEPT (((SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1)));
q1 q1

View File

@ -45,6 +45,8 @@ BEGIN;
SET LOCAL add_missing_from = false; SET LOCAL add_missing_from = false;
UPDATE update_test AS t SET b = update_test.b + 10 WHERE t.a = 10; UPDATE update_test AS t SET b = update_test.b + 10 WHERE t.a = 10;
ERROR: invalid reference to FROM-clause entry for table "update_test" ERROR: invalid reference to FROM-clause entry for table "update_test"
LINE 1: UPDATE update_test AS t SET b = update_test.b + 10 WHERE t.a...
^
HINT: Perhaps you meant to reference the table alias "t". HINT: Perhaps you meant to reference the table alias "t".
ROLLBACK; ROLLBACK;
DROP TABLE update_test; DROP TABLE update_test;

View File

@ -43,6 +43,8 @@ SELECT count(oid) FROM wi;
-- should fail -- should fail
SELECT count(oid) FROM wo; SELECT count(oid) FROM wo;
ERROR: column "oid" does not exist ERROR: column "oid" does not exist
LINE 1: SELECT count(oid) FROM wo;
^
VACUUM ANALYZE wi; VACUUM ANALYZE wi;
VACUUM ANALYZE wo; VACUUM ANALYZE wo;
SELECT min(relpages) < max(relpages), min(reltuples) - max(reltuples) SELECT min(relpages) < max(relpages), min(reltuples) - max(reltuples)
@ -76,6 +78,8 @@ SELECT count(oid) FROM create_table_test2;
-- should fail -- should fail
SELECT count(oid) FROM create_table_test3; SELECT count(oid) FROM create_table_test3;
ERROR: column "oid" does not exist ERROR: column "oid" does not exist
LINE 1: SELECT count(oid) FROM create_table_test3;
^
PREPARE table_source(int) AS PREPARE table_source(int) AS
SELECT a + b AS c1, a - b AS c2, $1 AS c3 FROM create_table_test; SELECT a + b AS c1, a - b AS c2, $1 AS c3 FROM create_table_test;
CREATE TABLE execute_with WITH OIDS AS EXECUTE table_source(1); CREATE TABLE execute_with WITH OIDS AS EXECUTE table_source(1);
@ -89,6 +93,8 @@ SELECT count(oid) FROM execute_with;
-- should fail -- should fail
SELECT count(oid) FROM execute_without; SELECT count(oid) FROM execute_without;
ERROR: column "oid" does not exist ERROR: column "oid" does not exist
LINE 1: SELECT count(oid) FROM execute_without;
^
DROP TABLE create_table_test; DROP TABLE create_table_test;
DROP TABLE create_table_test2; DROP TABLE create_table_test2;
DROP TABLE create_table_test3; DROP TABLE create_table_test3;

View File

@ -45,14 +45,14 @@ SELECT '' AS four, * FROM DEFAULTEXPR_TBL;
-- syntax errors -- syntax errors
-- test for extraneous comma -- test for extraneous comma
CREATE TABLE error_tbl (i int DEFAULT (100, )); CREATE TABLE error_tbl (i int DEFAULT (100, ));
ERROR: syntax error at or near ")" at character 45 ERROR: syntax error at or near ")"
LINE 1: CREATE TABLE error_tbl (i int DEFAULT (100, )); LINE 1: CREATE TABLE error_tbl (i int DEFAULT (100, ));
^ ^
-- this will fail because gram.y uses b_expr not a_expr for defaults, -- this will fail because gram.y uses b_expr not a_expr for defaults,
-- to avoid a shift/reduce conflict that arises from NOT NULL being -- to avoid a shift/reduce conflict that arises from NOT NULL being
-- part of the column definition syntax: -- part of the column definition syntax:
CREATE TABLE error_tbl (b1 bool DEFAULT 1 IN (1, 2)); CREATE TABLE error_tbl (b1 bool DEFAULT 1 IN (1, 2));
ERROR: syntax error at or near "IN" at character 43 ERROR: syntax error at or near "IN"
LINE 1: CREATE TABLE error_tbl (b1 bool DEFAULT 1 IN (1, 2)); LINE 1: CREATE TABLE error_tbl (b1 bool DEFAULT 1 IN (1, 2));
^ ^
-- this should work, however: -- this should work, however:

View File

@ -55,7 +55,7 @@ DETAIL: Actual return type is "unknown".
CONTEXT: SQL function "test1" CONTEXT: SQL function "test1"
CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL
AS 'not even SQL'; AS 'not even SQL';
ERROR: syntax error at or near "not" at character 62 ERROR: syntax error at or near "not"
LINE 2: AS 'not even SQL'; LINE 2: AS 'not even SQL';
^ ^
CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL