From b153c0920960a6059b67969469166fb29c0105d7 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 1 Sep 2008 20:42:46 +0000 Subject: [PATCH] Add a bunch of new error location reports to parse-analysis error messages. There are still some weak spots around JOIN USING and relation alias lists, but most errors reported within backend/parser/ now have locations. --- contrib/cube/expected/cube.out | 60 +++++ contrib/cube/expected/cube_1.out | 60 +++++ contrib/cube/expected/cube_2.out | 60 +++++ contrib/seg/expected/seg.out | 18 ++ contrib/seg/expected/seg_1.out | 18 ++ src/backend/bootstrap/bootparse.y | 6 +- src/backend/bootstrap/bootstrap.c | 4 +- src/backend/catalog/namespace.c | 4 +- src/backend/catalog/toasting.c | 4 +- src/backend/commands/tablecmds.c | 5 +- src/backend/commands/trigger.c | 6 +- src/backend/nodes/copyfuncs.c | 12 +- src/backend/nodes/equalfuncs.c | 12 +- src/backend/nodes/makefuncs.c | 5 +- src/backend/nodes/nodeFuncs.c | 13 +- src/backend/nodes/outfuncs.c | 8 +- src/backend/nodes/readfuncs.c | 5 +- src/backend/optimizer/util/plancat.c | 6 +- src/backend/optimizer/util/var.c | 217 +++++++++------- src/backend/parser/analyze.c | 233 +++++++++++------- src/backend/parser/gram.y | 145 ++++++----- src/backend/parser/parse_agg.c | 25 +- src/backend/parser/parse_clause.c | 188 ++++++++++---- src/backend/parser/parse_coerce.c | 20 +- src/backend/parser/parse_expr.c | 50 ++-- src/backend/parser/parse_func.c | 5 +- src/backend/parser/parse_node.c | 72 +++++- src/backend/parser/parse_relation.c | 128 ++++++---- src/backend/parser/parse_target.c | 42 ++-- src/backend/parser/parse_type.c | 12 +- src/backend/parser/parse_utilcmd.c | 8 +- src/backend/parser/scan.l | 25 +- src/backend/rewrite/rewriteManip.c | 80 +++++- src/backend/tcop/utility.c | 10 +- src/backend/utils/adt/ruleutils.c | 5 +- src/backend/utils/error/elog.c | 19 +- src/include/catalog/catversion.h | 4 +- src/include/nodes/makefuncs.h | 4 +- src/include/nodes/parsenodes.h | 17 +- src/include/nodes/primnodes.h | 3 +- src/include/optimizer/var.h | 7 +- src/include/parser/gramparse.h | 3 +- src/include/parser/parse_node.h | 17 +- src/include/parser/parse_relation.h | 12 +- src/include/rewrite/rewriteManip.h | 3 +- src/include/utils/elog.h | 3 +- src/pl/plperl/expected/plperl.out | 10 + src/pl/plpgsql/src/pl_comp.c | 6 +- src/test/regress/expected/abstime.out | 6 + src/test/regress/expected/aggregates.out | 2 + src/test/regress/expected/alter_table.out | 6 + src/test/regress/expected/arrays.out | 12 + src/test/regress/expected/boolean.out | 2 + src/test/regress/expected/box.out | 4 + src/test/regress/expected/circle.out | 6 + src/test/regress/expected/create_type.out | 2 + src/test/regress/expected/date.out | 78 ++++++ src/test/regress/expected/enum.out | 2 + src/test/regress/expected/errors.out | 8 + .../expected/float4-exp-three-digits.out | 30 +++ src/test/regress/expected/float4.out | 30 +++ .../float8-exp-three-digits-win32.out | 38 +++ .../regress/expected/float8-small-is-zero.out | 30 +++ .../expected/float8-small-is-zero_1.out | 30 +++ src/test/regress/expected/float8.out | 38 +++ src/test/regress/expected/horology.out | 6 +- src/test/regress/expected/inet.out | 8 + src/test/regress/expected/insert.out | 8 + src/test/regress/expected/int2.out | 16 ++ src/test/regress/expected/int4.out | 16 ++ .../expected/int8-exp-three-digits.out | 18 ++ src/test/regress/expected/int8.out | 18 ++ src/test/regress/expected/interval.out | 12 + src/test/regress/expected/lseg.out | 8 + src/test/regress/expected/numeric.out | 20 ++ src/test/regress/expected/oid.out | 20 ++ src/test/regress/expected/path.out | 4 + src/test/regress/expected/point.out | 6 + src/test/regress/expected/polygon.out | 10 + src/test/regress/expected/prepared_xacts.out | 4 + src/test/regress/expected/rangefuncs.out | 2 + src/test/regress/expected/reltime.out | 4 + src/test/regress/expected/rowtypes.out | 4 + .../regress/expected/select_distinct_on.out | 2 + src/test/regress/expected/select_having.out | 4 + src/test/regress/expected/select_having_1.out | 4 + src/test/regress/expected/select_having_2.out | 4 + src/test/regress/expected/select_implicit.out | 4 + .../regress/expected/select_implicit_1.out | 4 + .../regress/expected/select_implicit_2.out | 4 + src/test/regress/expected/temp.out | 6 + src/test/regress/expected/time.out | 2 + src/test/regress/expected/timestamp.out | 16 ++ src/test/regress/expected/timestamptz.out | 16 ++ src/test/regress/expected/timetz.out | 2 + src/test/regress/expected/tinterval.out | 4 + src/test/regress/expected/transactions.out | 4 + src/test/regress/expected/truncate.out | 2 + src/test/regress/expected/txid.out | 12 + src/test/regress/expected/uuid.out | 12 + src/test/regress/expected/xml.out | 8 + src/test/regress/expected/xml_1.out | 62 +++++ .../regress/output/create_function_1.source | 3 +- 103 files changed, 1877 insertions(+), 485 deletions(-) diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out index 86b33483a5..101a63b723 100644 --- a/contrib/cube/expected/cube.out +++ b/contrib/cube/expected/cube.out @@ -257,88 +257,144 @@ SELECT '[(0,0,0,0),(1,0,0,0)]'::cube AS cube; -- invalid input: parse errors SELECT ''::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT ''::cube AS cube; + ^ DETAIL: syntax error at end of input SELECT 'ABC'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT 'ABC'::cube AS cube; + ^ DETAIL: syntax error at or near "A" SELECT '()'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '()'::cube AS cube; + ^ DETAIL: syntax error at or near ")" SELECT '[]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[]'::cube AS cube; + ^ DETAIL: syntax error at or near "]" SELECT '[()]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[()]'::cube AS cube; + ^ DETAIL: syntax error at or near ")" SELECT '[(1)]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[(1)]'::cube AS cube; + ^ DETAIL: syntax error at or near "]" SELECT '[(1),]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[(1),]'::cube AS cube; + ^ DETAIL: syntax error at or near "]" SELECT '[(1),2]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[(1),2]'::cube AS cube; + ^ DETAIL: syntax error at or near "2" SELECT '[(1),(2),(3)]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[(1),(2),(3)]'::cube AS cube; + ^ DETAIL: syntax error at or near "," SELECT '1,'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '1,'::cube AS cube; + ^ DETAIL: syntax error at end of input SELECT '1,2,'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '1,2,'::cube AS cube; + ^ DETAIL: syntax error at end of input SELECT '1,,2'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '1,,2'::cube AS cube; + ^ DETAIL: syntax error at or near "," SELECT '(1,)'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '(1,)'::cube AS cube; + ^ DETAIL: syntax error at or near ")" SELECT '(1,2,)'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '(1,2,)'::cube AS cube; + ^ DETAIL: syntax error at or near ")" SELECT '(1,,2)'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '(1,,2)'::cube AS cube; + ^ DETAIL: syntax error at or near "," -- invalid input: semantic errors and trailing garbage SELECT '[(1),(2)],'::cube AS cube; -- 0 ERROR: bad cube representation +LINE 1: SELECT '[(1),(2)],'::cube AS cube; + ^ DETAIL: syntax error at or near "," SELECT '[(1,2,3),(2,3)]'::cube AS cube; -- 1 ERROR: bad cube representation +LINE 1: SELECT '[(1,2,3),(2,3)]'::cube AS cube; + ^ DETAIL: Different point dimensions in (1,2,3) and (2,3). SELECT '[(1,2),(1,2,3)]'::cube AS cube; -- 1 ERROR: bad cube representation +LINE 1: SELECT '[(1,2),(1,2,3)]'::cube AS cube; + ^ DETAIL: Different point dimensions in (1,2) and (1,2,3). SELECT '(1),(2),'::cube AS cube; -- 2 ERROR: bad cube representation +LINE 1: SELECT '(1),(2),'::cube AS cube; + ^ DETAIL: syntax error at or near "," SELECT '(1,2,3),(2,3)'::cube AS cube; -- 3 ERROR: bad cube representation +LINE 1: SELECT '(1,2,3),(2,3)'::cube AS cube; + ^ DETAIL: Different point dimensions in (1,2,3) and (2,3). SELECT '(1,2),(1,2,3)'::cube AS cube; -- 3 ERROR: bad cube representation +LINE 1: SELECT '(1,2),(1,2,3)'::cube AS cube; + ^ DETAIL: Different point dimensions in (1,2) and (1,2,3). SELECT '(1,2,3)ab'::cube AS cube; -- 4 ERROR: bad cube representation +LINE 1: SELECT '(1,2,3)ab'::cube AS cube; + ^ DETAIL: syntax error at or near "a" SELECT '(1,2,3)a'::cube AS cube; -- 5 ERROR: bad cube representation +LINE 1: SELECT '(1,2,3)a'::cube AS cube; + ^ DETAIL: syntax error at or near "a" SELECT '(1,2)('::cube AS cube; -- 5 ERROR: bad cube representation +LINE 1: SELECT '(1,2)('::cube AS cube; + ^ DETAIL: syntax error at or near "(" SELECT '1,2ab'::cube AS cube; -- 6 ERROR: bad cube representation +LINE 1: SELECT '1,2ab'::cube AS cube; + ^ DETAIL: syntax error at or near "a" SELECT '1 e7'::cube AS cube; -- 6 ERROR: bad cube representation +LINE 1: SELECT '1 e7'::cube AS cube; + ^ DETAIL: syntax error at or near "e" SELECT '1,2a'::cube AS cube; -- 7 ERROR: bad cube representation +LINE 1: SELECT '1,2a'::cube AS cube; + ^ DETAIL: syntax error at or near "a" SELECT '1..2'::cube AS cube; -- 7 ERROR: bad cube representation +LINE 1: SELECT '1..2'::cube AS cube; + ^ DETAIL: syntax error at or near ".2" -- -- Testing building cubes from float8 values @@ -430,9 +486,13 @@ ERROR: Index out of bounds -- select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube; ERROR: bad cube representation +LINE 1: select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0... + ^ DETAIL: A cube cannot have more than 100 dimensions. select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube; ERROR: bad cube representation +LINE 1: select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0... + ^ DETAIL: A cube cannot have more than 100 dimensions. -- -- testing the operators diff --git a/contrib/cube/expected/cube_1.out b/contrib/cube/expected/cube_1.out index 8609c26106..55f6861daf 100644 --- a/contrib/cube/expected/cube_1.out +++ b/contrib/cube/expected/cube_1.out @@ -257,88 +257,144 @@ SELECT '[(0,0,0,0),(1,0,0,0)]'::cube AS cube; -- invalid input: parse errors SELECT ''::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT ''::cube AS cube; + ^ DETAIL: syntax error at end of input SELECT 'ABC'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT 'ABC'::cube AS cube; + ^ DETAIL: syntax error at or near "A" SELECT '()'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '()'::cube AS cube; + ^ DETAIL: syntax error at or near ")" SELECT '[]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[]'::cube AS cube; + ^ DETAIL: syntax error at or near "]" SELECT '[()]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[()]'::cube AS cube; + ^ DETAIL: syntax error at or near ")" SELECT '[(1)]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[(1)]'::cube AS cube; + ^ DETAIL: syntax error at or near "]" SELECT '[(1),]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[(1),]'::cube AS cube; + ^ DETAIL: syntax error at or near "]" SELECT '[(1),2]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[(1),2]'::cube AS cube; + ^ DETAIL: syntax error at or near "2" SELECT '[(1),(2),(3)]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[(1),(2),(3)]'::cube AS cube; + ^ DETAIL: syntax error at or near "," SELECT '1,'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '1,'::cube AS cube; + ^ DETAIL: syntax error at end of input SELECT '1,2,'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '1,2,'::cube AS cube; + ^ DETAIL: syntax error at end of input SELECT '1,,2'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '1,,2'::cube AS cube; + ^ DETAIL: syntax error at or near "," SELECT '(1,)'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '(1,)'::cube AS cube; + ^ DETAIL: syntax error at or near ")" SELECT '(1,2,)'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '(1,2,)'::cube AS cube; + ^ DETAIL: syntax error at or near ")" SELECT '(1,,2)'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '(1,,2)'::cube AS cube; + ^ DETAIL: syntax error at or near "," -- invalid input: semantic errors and trailing garbage SELECT '[(1),(2)],'::cube AS cube; -- 0 ERROR: bad cube representation +LINE 1: SELECT '[(1),(2)],'::cube AS cube; + ^ DETAIL: syntax error at or near "," SELECT '[(1,2,3),(2,3)]'::cube AS cube; -- 1 ERROR: bad cube representation +LINE 1: SELECT '[(1,2,3),(2,3)]'::cube AS cube; + ^ DETAIL: Different point dimensions in (1,2,3) and (2,3). SELECT '[(1,2),(1,2,3)]'::cube AS cube; -- 1 ERROR: bad cube representation +LINE 1: SELECT '[(1,2),(1,2,3)]'::cube AS cube; + ^ DETAIL: Different point dimensions in (1,2) and (1,2,3). SELECT '(1),(2),'::cube AS cube; -- 2 ERROR: bad cube representation +LINE 1: SELECT '(1),(2),'::cube AS cube; + ^ DETAIL: syntax error at or near "," SELECT '(1,2,3),(2,3)'::cube AS cube; -- 3 ERROR: bad cube representation +LINE 1: SELECT '(1,2,3),(2,3)'::cube AS cube; + ^ DETAIL: Different point dimensions in (1,2,3) and (2,3). SELECT '(1,2),(1,2,3)'::cube AS cube; -- 3 ERROR: bad cube representation +LINE 1: SELECT '(1,2),(1,2,3)'::cube AS cube; + ^ DETAIL: Different point dimensions in (1,2) and (1,2,3). SELECT '(1,2,3)ab'::cube AS cube; -- 4 ERROR: bad cube representation +LINE 1: SELECT '(1,2,3)ab'::cube AS cube; + ^ DETAIL: syntax error at or near "a" SELECT '(1,2,3)a'::cube AS cube; -- 5 ERROR: bad cube representation +LINE 1: SELECT '(1,2,3)a'::cube AS cube; + ^ DETAIL: syntax error at or near "a" SELECT '(1,2)('::cube AS cube; -- 5 ERROR: bad cube representation +LINE 1: SELECT '(1,2)('::cube AS cube; + ^ DETAIL: syntax error at or near "(" SELECT '1,2ab'::cube AS cube; -- 6 ERROR: bad cube representation +LINE 1: SELECT '1,2ab'::cube AS cube; + ^ DETAIL: syntax error at or near "a" SELECT '1 e7'::cube AS cube; -- 6 ERROR: bad cube representation +LINE 1: SELECT '1 e7'::cube AS cube; + ^ DETAIL: syntax error at or near "e" SELECT '1,2a'::cube AS cube; -- 7 ERROR: bad cube representation +LINE 1: SELECT '1,2a'::cube AS cube; + ^ DETAIL: syntax error at or near "a" SELECT '1..2'::cube AS cube; -- 7 ERROR: bad cube representation +LINE 1: SELECT '1..2'::cube AS cube; + ^ DETAIL: syntax error at or near ".2" -- -- Testing building cubes from float8 values @@ -430,9 +486,13 @@ ERROR: Index out of bounds -- select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube; ERROR: bad cube representation +LINE 1: select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0... + ^ DETAIL: A cube cannot have more than 100 dimensions. select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube; ERROR: bad cube representation +LINE 1: select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0... + ^ DETAIL: A cube cannot have more than 100 dimensions. -- -- testing the operators diff --git a/contrib/cube/expected/cube_2.out b/contrib/cube/expected/cube_2.out index d8737c3cb3..c449395818 100644 --- a/contrib/cube/expected/cube_2.out +++ b/contrib/cube/expected/cube_2.out @@ -257,88 +257,144 @@ SELECT '[(0,0,0,0),(1,0,0,0)]'::cube AS cube; -- invalid input: parse errors SELECT ''::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT ''::cube AS cube; + ^ DETAIL: syntax error at end of input SELECT 'ABC'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT 'ABC'::cube AS cube; + ^ DETAIL: syntax error at or near "A" SELECT '()'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '()'::cube AS cube; + ^ DETAIL: syntax error at or near ")" SELECT '[]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[]'::cube AS cube; + ^ DETAIL: syntax error at or near "]" SELECT '[()]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[()]'::cube AS cube; + ^ DETAIL: syntax error at or near ")" SELECT '[(1)]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[(1)]'::cube AS cube; + ^ DETAIL: syntax error at or near "]" SELECT '[(1),]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[(1),]'::cube AS cube; + ^ DETAIL: syntax error at or near "]" SELECT '[(1),2]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[(1),2]'::cube AS cube; + ^ DETAIL: syntax error at or near "2" SELECT '[(1),(2),(3)]'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '[(1),(2),(3)]'::cube AS cube; + ^ DETAIL: syntax error at or near "," SELECT '1,'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '1,'::cube AS cube; + ^ DETAIL: syntax error at end of input SELECT '1,2,'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '1,2,'::cube AS cube; + ^ DETAIL: syntax error at end of input SELECT '1,,2'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '1,,2'::cube AS cube; + ^ DETAIL: syntax error at or near "," SELECT '(1,)'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '(1,)'::cube AS cube; + ^ DETAIL: syntax error at or near ")" SELECT '(1,2,)'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '(1,2,)'::cube AS cube; + ^ DETAIL: syntax error at or near ")" SELECT '(1,,2)'::cube AS cube; ERROR: bad cube representation +LINE 1: SELECT '(1,,2)'::cube AS cube; + ^ DETAIL: syntax error at or near "," -- invalid input: semantic errors and trailing garbage SELECT '[(1),(2)],'::cube AS cube; -- 0 ERROR: bad cube representation +LINE 1: SELECT '[(1),(2)],'::cube AS cube; + ^ DETAIL: syntax error at or near "," SELECT '[(1,2,3),(2,3)]'::cube AS cube; -- 1 ERROR: bad cube representation +LINE 1: SELECT '[(1,2,3),(2,3)]'::cube AS cube; + ^ DETAIL: Different point dimensions in (1,2,3) and (2,3). SELECT '[(1,2),(1,2,3)]'::cube AS cube; -- 1 ERROR: bad cube representation +LINE 1: SELECT '[(1,2),(1,2,3)]'::cube AS cube; + ^ DETAIL: Different point dimensions in (1,2) and (1,2,3). SELECT '(1),(2),'::cube AS cube; -- 2 ERROR: bad cube representation +LINE 1: SELECT '(1),(2),'::cube AS cube; + ^ DETAIL: syntax error at or near "," SELECT '(1,2,3),(2,3)'::cube AS cube; -- 3 ERROR: bad cube representation +LINE 1: SELECT '(1,2,3),(2,3)'::cube AS cube; + ^ DETAIL: Different point dimensions in (1,2,3) and (2,3). SELECT '(1,2),(1,2,3)'::cube AS cube; -- 3 ERROR: bad cube representation +LINE 1: SELECT '(1,2),(1,2,3)'::cube AS cube; + ^ DETAIL: Different point dimensions in (1,2) and (1,2,3). SELECT '(1,2,3)ab'::cube AS cube; -- 4 ERROR: bad cube representation +LINE 1: SELECT '(1,2,3)ab'::cube AS cube; + ^ DETAIL: syntax error at or near "a" SELECT '(1,2,3)a'::cube AS cube; -- 5 ERROR: bad cube representation +LINE 1: SELECT '(1,2,3)a'::cube AS cube; + ^ DETAIL: syntax error at or near "a" SELECT '(1,2)('::cube AS cube; -- 5 ERROR: bad cube representation +LINE 1: SELECT '(1,2)('::cube AS cube; + ^ DETAIL: syntax error at or near "(" SELECT '1,2ab'::cube AS cube; -- 6 ERROR: bad cube representation +LINE 1: SELECT '1,2ab'::cube AS cube; + ^ DETAIL: syntax error at or near "a" SELECT '1 e7'::cube AS cube; -- 6 ERROR: bad cube representation +LINE 1: SELECT '1 e7'::cube AS cube; + ^ DETAIL: syntax error at or near "e" SELECT '1,2a'::cube AS cube; -- 7 ERROR: bad cube representation +LINE 1: SELECT '1,2a'::cube AS cube; + ^ DETAIL: syntax error at or near "a" SELECT '1..2'::cube AS cube; -- 7 ERROR: bad cube representation +LINE 1: SELECT '1..2'::cube AS cube; + ^ DETAIL: syntax error at or near ".2" -- -- Testing building cubes from float8 values @@ -430,9 +486,13 @@ ERROR: Index out of bounds -- select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube; ERROR: bad cube representation +LINE 1: select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0... + ^ DETAIL: A cube cannot have more than 100 dimensions. select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube; ERROR: bad cube representation +LINE 1: select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0... + ^ DETAIL: A cube cannot have more than 100 dimensions. -- -- testing the operators diff --git a/contrib/seg/expected/seg.out b/contrib/seg/expected/seg.out index 69bcfa1441..bd099a222c 100644 --- a/contrib/seg/expected/seg.out +++ b/contrib/seg/expected/seg.out @@ -394,30 +394,48 @@ SELECT '100(+-)1'::seg AS seg; -- invalid input SELECT ''::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT ''::seg AS seg; + ^ DETAIL: syntax error at end of input SELECT 'ABC'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT 'ABC'::seg AS seg; + ^ DETAIL: syntax error at or near "A" SELECT '1ABC'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT '1ABC'::seg AS seg; + ^ DETAIL: syntax error at or near "A" SELECT '1.'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT '1.'::seg AS seg; + ^ DETAIL: syntax error at or near "." SELECT '1.....'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT '1.....'::seg AS seg; + ^ DETAIL: syntax error at or near ".." SELECT '.1'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT '.1'::seg AS seg; + ^ DETAIL: syntax error at or near "." SELECT '1..2.'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT '1..2.'::seg AS seg; + ^ DETAIL: syntax error at or near "." SELECT '1 e7'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT '1 e7'::seg AS seg; + ^ DETAIL: syntax error at or near "e" SELECT '1e700'::seg AS seg; ERROR: "1e700" is out of range for type real +LINE 1: SELECT '1e700'::seg AS seg; + ^ -- -- testing the operators -- diff --git a/contrib/seg/expected/seg_1.out b/contrib/seg/expected/seg_1.out index aef3df8aea..c92cd83510 100644 --- a/contrib/seg/expected/seg_1.out +++ b/contrib/seg/expected/seg_1.out @@ -394,30 +394,48 @@ SELECT '100(+-)1'::seg AS seg; -- invalid input SELECT ''::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT ''::seg AS seg; + ^ DETAIL: syntax error at end of input SELECT 'ABC'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT 'ABC'::seg AS seg; + ^ DETAIL: syntax error at or near "A" SELECT '1ABC'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT '1ABC'::seg AS seg; + ^ DETAIL: syntax error at or near "A" SELECT '1.'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT '1.'::seg AS seg; + ^ DETAIL: syntax error at or near "." SELECT '1.....'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT '1.....'::seg AS seg; + ^ DETAIL: syntax error at or near ".." SELECT '.1'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT '.1'::seg AS seg; + ^ DETAIL: syntax error at or near "." SELECT '1..2.'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT '1..2.'::seg AS seg; + ^ DETAIL: syntax error at or near "." SELECT '1 e7'::seg AS seg; ERROR: bad seg representation +LINE 1: SELECT '1 e7'::seg AS seg; + ^ DETAIL: syntax error at or near "e" SELECT '1e700'::seg AS seg; ERROR: "1e700" is out of range for type real +LINE 1: SELECT '1e700'::seg AS seg; + ^ -- -- testing the operators -- diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y index da76d76d9d..8019b244ae 100644 --- a/src/backend/bootstrap/bootparse.y +++ b/src/backend/bootstrap/bootparse.y @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.92 2008/05/09 23:32:04 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.93 2008/09/01 20:42:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -247,7 +247,7 @@ Boot_DeclareIndexStmt: { do_start(); - DefineIndex(makeRangeVar(NULL, LexIDStr($6)), + DefineIndex(makeRangeVar(NULL, LexIDStr($6), -1), LexIDStr($3), $4, LexIDStr($8), @@ -265,7 +265,7 @@ Boot_DeclareUniqueIndexStmt: { do_start(); - DefineIndex(makeRangeVar(NULL, LexIDStr($7)), + DefineIndex(makeRangeVar(NULL, LexIDStr($7), -1), LexIDStr($4), $5, LexIDStr($9), diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 25eba1406f..0689fb1f1a 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.244 2008/06/24 17:58:27 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.245 2008/09/01 20:42:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -637,7 +637,7 @@ boot_openrel(char *relname) elog(DEBUG4, "open relation %s, attrsize %d", relname, (int) ATTRIBUTE_TUPLE_SIZE); - boot_reldesc = heap_openrv(makeRangeVar(NULL, relname), NoLock); + boot_reldesc = heap_openrv(makeRangeVar(NULL, relname, -1), NoLock); numattr = boot_reldesc->rd_rel->relnatts; for (i = 0; i < numattr; i++) { diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 7f0ea88c43..de827f74b2 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.110 2008/08/30 01:39:13 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.111 2008/09/01 20:42:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2156,7 +2156,7 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p) RangeVar * makeRangeVarFromNameList(List *names) { - RangeVar *rel = makeRangeVar(NULL, NULL); + RangeVar *rel = makeRangeVar(NULL, NULL, -1); switch (list_length(names)) { diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c index 0171d1f733..d4f04346c9 100644 --- a/src/backend/catalog/toasting.c +++ b/src/backend/catalog/toasting.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.10 2008/05/09 23:32:04 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.11 2008/09/01 20:42:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -73,7 +73,7 @@ BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid) { Relation rel; - rel = heap_openrv(makeRangeVar(NULL, relName), AccessExclusiveLock); + rel = heap_openrv(makeRangeVar(NULL, relName, -1), AccessExclusiveLock); /* Note: during bootstrap may see uncataloged relation */ if (rel->rd_rel->relkind != RELKIND_RELATION && diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 6f2303f62c..8b7b101595 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.264 2008/08/28 23:09:45 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.265 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -5112,7 +5112,8 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint, * Reconstruct a RangeVar for my relation (not passed in, unfortunately). */ myRel = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)), - pstrdup(RelationGetRelationName(rel))); + pstrdup(RelationGetRelationName(rel)), + -1); /* Make changes-so-far visible */ CommandCounterIncrement(); diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 44f13df361..3461056c57 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.236 2008/07/18 20:26:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.237 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -655,7 +655,7 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid) else { /* Work around ancient pg_dump bug that omitted constrrel */ - fkcon->pktable = makeRangeVar(NULL, pk_table_name); + fkcon->pktable = makeRangeVar(NULL, pk_table_name, -1); } } else @@ -667,7 +667,7 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid) else { /* Work around ancient pg_dump bug that omitted constrrel */ - atstmt->relation = makeRangeVar(NULL, fk_table_name); + atstmt->relation = makeRangeVar(NULL, fk_table_name, -1); } } atstmt->cmds = list_make1(atcmd); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 67a25500da..6e2028142b 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.403 2008/08/30 01:39:13 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.404 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -722,6 +722,7 @@ _copyRangeVar(RangeVar *from) COPY_SCALAR_FIELD(inhOpt); COPY_SCALAR_FIELD(istemp); COPY_NODE_FIELD(alias); + COPY_LOCATION_FIELD(location); return newnode; } @@ -1773,10 +1774,11 @@ _copySortBy(SortBy *from) { SortBy *newnode = makeNode(SortBy); + COPY_NODE_FIELD(node); COPY_SCALAR_FIELD(sortby_dir); COPY_SCALAR_FIELD(sortby_nulls); COPY_NODE_FIELD(useOp); - COPY_NODE_FIELD(node); + COPY_LOCATION_FIELD(location); return newnode; } @@ -2406,7 +2408,7 @@ _copyNotifyStmt(NotifyStmt *from) { NotifyStmt *newnode = makeNode(NotifyStmt); - COPY_NODE_FIELD(relation); + COPY_STRING_FIELD(conditionname); return newnode; } @@ -2416,7 +2418,7 @@ _copyListenStmt(ListenStmt *from) { ListenStmt *newnode = makeNode(ListenStmt); - COPY_NODE_FIELD(relation); + COPY_STRING_FIELD(conditionname); return newnode; } @@ -2426,7 +2428,7 @@ _copyUnlistenStmt(UnlistenStmt *from) { UnlistenStmt *newnode = makeNode(UnlistenStmt); - COPY_NODE_FIELD(relation); + COPY_STRING_FIELD(conditionname); return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 298d03aa9b..f0939b4777 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -22,7 +22,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.330 2008/08/30 01:39:13 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.331 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -106,6 +106,7 @@ _equalRangeVar(RangeVar *a, RangeVar *b) COMPARE_SCALAR_FIELD(inhOpt); COMPARE_SCALAR_FIELD(istemp); COMPARE_NODE_FIELD(alias); + COMPARE_LOCATION_FIELD(location); return true; } @@ -1230,7 +1231,7 @@ _equalRuleStmt(RuleStmt *a, RuleStmt *b) static bool _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b) { - COMPARE_NODE_FIELD(relation); + COMPARE_STRING_FIELD(conditionname); return true; } @@ -1238,7 +1239,7 @@ _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b) static bool _equalListenStmt(ListenStmt *a, ListenStmt *b) { - COMPARE_NODE_FIELD(relation); + COMPARE_STRING_FIELD(conditionname); return true; } @@ -1246,7 +1247,7 @@ _equalListenStmt(ListenStmt *a, ListenStmt *b) static bool _equalUnlistenStmt(UnlistenStmt *a, UnlistenStmt *b) { - COMPARE_NODE_FIELD(relation); + COMPARE_STRING_FIELD(conditionname); return true; } @@ -1837,10 +1838,11 @@ _equalTypeCast(TypeCast *a, TypeCast *b) static bool _equalSortBy(SortBy *a, SortBy *b) { + COMPARE_NODE_FIELD(node); COMPARE_SCALAR_FIELD(sortby_dir); COMPARE_SCALAR_FIELD(sortby_nulls); COMPARE_NODE_FIELD(useOp); - COMPARE_NODE_FIELD(node); + COMPARE_LOCATION_FIELD(location); return true; } diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index 5ab853c37b..42539f6f97 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.59 2008/08/28 23:09:46 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.60 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -266,7 +266,7 @@ makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, CoercionForm rformat) * creates a RangeVar node (rather oversimplified case) */ RangeVar * -makeRangeVar(char *schemaname, char *relname) +makeRangeVar(char *schemaname, char *relname, int location) { RangeVar *r = makeNode(RangeVar); @@ -276,6 +276,7 @@ makeRangeVar(char *schemaname, char *relname) r->inhOpt = INH_DEFAULT; r->istemp = false; r->alias = NULL; + r->location = location; return r; } diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index fa1bb347b9..a061641566 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.31 2008/08/28 23:09:46 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.32 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -613,6 +613,9 @@ exprLocation(Node *expr) return -1; switch (nodeTag(expr)) { + case T_RangeVar: + loc = ((RangeVar *) expr)->location; + break; case T_Var: loc = ((Var *) expr)->location; break; @@ -789,6 +792,10 @@ exprLocation(Node *expr) /* just use argument's location */ loc = exprLocation((Node *) ((TargetEntry *) expr)->expr); break; + case T_IntoClause: + /* use the contained RangeVar's location --- close enough */ + loc = exprLocation((Node *) ((IntoClause *) expr)->rel); + break; case T_List: { /* report location of first list member that has a location */ @@ -852,6 +859,10 @@ exprLocation(Node *expr) loc = leftmostLoc(loc, tc->location); } break; + case T_SortBy: + /* just use argument's location (ignore operator, if any) */ + loc = exprLocation(((SortBy *) expr)->node); + break; case T_TypeName: loc = ((TypeName *) expr)->location; break; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 882dd0f9f1..15ced48445 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.337 2008/08/30 01:39:14 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.338 2008/09/01 20:42:44 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -667,6 +667,7 @@ _outRangeVar(StringInfo str, RangeVar *node) WRITE_ENUM_FIELD(inhOpt, InhOption); WRITE_BOOL_FIELD(istemp); WRITE_NODE_FIELD(alias); + WRITE_LOCATION_FIELD(location); } static void @@ -1609,7 +1610,7 @@ _outNotifyStmt(StringInfo str, NotifyStmt *node) { WRITE_NODE_TYPE("NOTIFY"); - WRITE_NODE_FIELD(relation); + WRITE_STRING_FIELD(conditionname); } static void @@ -2038,10 +2039,11 @@ _outSortBy(StringInfo str, SortBy *node) { WRITE_NODE_TYPE("SORTBY"); + WRITE_NODE_FIELD(node); WRITE_ENUM_FIELD(sortby_dir, SortByDir); WRITE_ENUM_FIELD(sortby_nulls, SortByNulls); WRITE_NODE_FIELD(useOp); - WRITE_NODE_FIELD(node); + WRITE_LOCATION_FIELD(location); } static void diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index ee363502f6..1eca85d0b6 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.213 2008/08/28 23:09:46 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.214 2008/09/01 20:42:44 tgl Exp $ * * NOTES * Path and Plan nodes do not have any readfuncs support, because we @@ -179,7 +179,7 @@ _readNotifyStmt(void) { READ_LOCALS(NotifyStmt); - READ_NODE_FIELD(relation); + READ_STRING_FIELD(conditionname); READ_DONE(); } @@ -278,6 +278,7 @@ _readRangeVar(void) READ_ENUM_FIELD(inhOpt, InhOption); READ_BOOL_FIELD(istemp); READ_NODE_FIELD(alias); + READ_LOCATION_FIELD(location); READ_DONE(); } diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 8f025ac3a4..e6cd2f26b9 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.150 2008/08/25 22:42:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.151 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -733,7 +733,7 @@ build_physical_tlist(PlannerInfo *root, RelOptInfo *rel) break; case RTE_FUNCTION: - expandRTE(rte, varno, 0, true /* include dropped */ , + expandRTE(rte, varno, 0, -1, true /* include dropped */ , NULL, &colvars); foreach(l, colvars) { @@ -758,7 +758,7 @@ build_physical_tlist(PlannerInfo *root, RelOptInfo *rel) break; case RTE_VALUES: - expandRTE(rte, varno, 0, false /* dropped not applicable */ , + expandRTE(rte, varno, 0, -1, false /* dropped not applicable */ , NULL, &colvars); foreach(l, colvars) { diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index e9fd15e6f3..748a3cb93a 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.78 2008/08/28 23:09:46 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.79 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,10 +30,16 @@ typedef struct typedef struct { - int varno; - int varattno; + int var_location; int sublevels_up; -} contain_var_reference_context; +} locate_var_of_level_context; + +typedef struct +{ + int var_location; + int relid; + int sublevels_up; +} locate_var_of_relation_context; typedef struct { @@ -56,11 +62,12 @@ typedef struct static bool pull_varnos_walker(Node *node, pull_varnos_context *context); static bool pull_varattnos_walker(Node *node, Bitmapset **varattnos); -static bool contain_var_reference_walker(Node *node, - contain_var_reference_context *context); static bool contain_var_clause_walker(Node *node, void *context); static bool contain_vars_of_level_walker(Node *node, int *sublevels_up); -static bool contain_vars_above_level_walker(Node *node, int *sublevels_up); +static bool locate_var_of_level_walker(Node *node, + locate_var_of_level_context *context); +static bool locate_var_of_relation_walker(Node *node, + locate_var_of_relation_context *context); static bool find_minimum_var_level_walker(Node *node, find_minimum_var_level_context *context); static bool pull_var_clause_walker(Node *node, @@ -136,6 +143,7 @@ pull_varnos_walker(Node *node, pull_varnos_context *context) (void *) context); } + /* * pull_varattnos * Find all the distinct attribute numbers present in an expression tree, @@ -178,69 +186,6 @@ pull_varattnos_walker(Node *node, Bitmapset **varattnos) } -/* - * contain_var_reference - * - * Detect whether a parsetree contains any references to a specified - * attribute of a specified rtable entry. - * - * NOTE: this is used on not-yet-planned expressions. It may therefore find - * bare SubLinks, and if so it needs to recurse into them to look for uplevel - * references to the desired rtable entry! But when we find a completed - * SubPlan, we only need to look at the parameters passed to the subplan. - */ -bool -contain_var_reference(Node *node, int varno, int varattno, int levelsup) -{ - contain_var_reference_context context; - - context.varno = varno; - context.varattno = varattno; - context.sublevels_up = levelsup; - - /* - * Must be prepared to start with a Query or a bare expression tree; if - * it's a Query, we don't want to increment sublevels_up. - */ - return query_or_expression_tree_walker(node, - contain_var_reference_walker, - (void *) &context, - 0); -} - -static bool -contain_var_reference_walker(Node *node, - contain_var_reference_context *context) -{ - if (node == NULL) - return false; - if (IsA(node, Var)) - { - Var *var = (Var *) node; - - if (var->varno == context->varno && - var->varattno == context->varattno && - var->varlevelsup == context->sublevels_up) - return true; - return false; - } - if (IsA(node, Query)) - { - /* Recurse into RTE subquery or not-yet-planned sublink subquery */ - bool result; - - context->sublevels_up++; - result = query_tree_walker((Query *) node, - contain_var_reference_walker, - (void *) context, 0); - context->sublevels_up--; - return result; - } - return expression_tree_walker(node, contain_var_reference_walker, - (void *) context); -} - - /* * contain_var_clause * Recursively scan a clause to discover whether it contains any Var nodes @@ -273,6 +218,7 @@ contain_var_clause_walker(Node *node, void *context) return expression_tree_walker(node, contain_var_clause_walker, context); } + /* * contain_vars_of_level * Recursively scan a clause to discover whether it contains any Var nodes @@ -328,53 +274,146 @@ contain_vars_of_level_walker(Node *node, int *sublevels_up) (void *) sublevels_up); } + /* - * contain_vars_above_level - * Recursively scan a clause to discover whether it contains any Var nodes - * above the specified query level. (For example, pass zero to detect - * all nonlocal Vars.) + * locate_var_of_level + * Find the parse location of any Var of the specified query level. * - * Returns true if any such Var found. + * Returns -1 if no such Var is in the querytree, or if they all have + * unknown parse location. (The former case is probably caller error, + * but we don't bother to distinguish it from the latter case.) * * Will recurse into sublinks. Also, may be invoked directly on a Query. + * + * Note: it might seem appropriate to merge this functionality into + * contain_vars_of_level, but that would complicate that function's API. + * Currently, the only uses of this function are for error reporting, + * and so shaving cycles probably isn't very important. */ -bool -contain_vars_above_level(Node *node, int levelsup) +int +locate_var_of_level(Node *node, int levelsup) { - int sublevels_up = levelsup; + locate_var_of_level_context context; - return query_or_expression_tree_walker(node, - contain_vars_above_level_walker, - (void *) &sublevels_up, + context.var_location = -1; /* in case we find nothing */ + context.sublevels_up = levelsup; + + (void) query_or_expression_tree_walker(node, + locate_var_of_level_walker, + (void *) &context, 0); + + return context.var_location; } static bool -contain_vars_above_level_walker(Node *node, int *sublevels_up) +locate_var_of_level_walker(Node *node, + locate_var_of_level_context *context) { if (node == NULL) return false; if (IsA(node, Var)) { - if (((Var *) node)->varlevelsup > *sublevels_up) + Var *var = (Var *) node; + + if (var->varlevelsup == context->sublevels_up && + var->location >= 0) + { + context->var_location = var->location; return true; /* abort tree traversal and return true */ + } + return false; + } + if (IsA(node, CurrentOfExpr)) + { + /* since CurrentOfExpr doesn't carry location, nothing we can do */ + return false; } if (IsA(node, Query)) { /* Recurse into subselects */ bool result; - (*sublevels_up)++; + context->sublevels_up++; result = query_tree_walker((Query *) node, - contain_vars_above_level_walker, - (void *) sublevels_up, + locate_var_of_level_walker, + (void *) context, 0); - (*sublevels_up)--; + context->sublevels_up--; return result; } return expression_tree_walker(node, - contain_vars_above_level_walker, - (void *) sublevels_up); + locate_var_of_level_walker, + (void *) context); +} + + +/* + * locate_var_of_relation + * Find the parse location of any Var of the specified relation. + * + * Returns -1 if no such Var is in the querytree, or if they all have + * unknown parse location. + * + * Will recurse into sublinks. Also, may be invoked directly on a Query. + */ +int +locate_var_of_relation(Node *node, int relid, int levelsup) +{ + locate_var_of_relation_context context; + + context.var_location = -1; /* in case we find nothing */ + context.relid = relid; + context.sublevels_up = levelsup; + + (void) query_or_expression_tree_walker(node, + locate_var_of_relation_walker, + (void *) &context, + 0); + + return context.var_location; +} + +static bool +locate_var_of_relation_walker(Node *node, + locate_var_of_relation_context *context) +{ + if (node == NULL) + return false; + if (IsA(node, Var)) + { + Var *var = (Var *) node; + + if (var->varno == context->relid && + var->varlevelsup == context->sublevels_up && + var->location >= 0) + { + context->var_location = var->location; + return true; /* abort tree traversal and return true */ + } + return false; + } + if (IsA(node, CurrentOfExpr)) + { + /* since CurrentOfExpr doesn't carry location, nothing we can do */ + return false; + } + if (IsA(node, Query)) + { + /* Recurse into subselects */ + bool result; + + context->sublevels_up++; + result = query_tree_walker((Query *) node, + locate_var_of_relation_walker, + (void *) context, + 0); + context->sublevels_up--; + return result; + } + return expression_tree_walker(node, + locate_var_of_relation_walker, + (void *) context); } diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index b513d61c07..18585b860b 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -17,7 +17,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.378 2008/08/28 23:09:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.379 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,16 +36,10 @@ #include "parser/parse_relation.h" #include "parser/parse_target.h" #include "parser/parsetree.h" +#include "rewrite/rewriteManip.h" #include "utils/rel.h" -typedef struct -{ - Oid *paramTypes; - int numParams; -} check_parameter_resolution_context; - - static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt); static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt); static List *transformInsertRow(ParseState *pstate, List *exprlist, @@ -62,9 +56,9 @@ static Query *transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt); static Query *transformExplainStmt(ParseState *pstate, ExplainStmt *stmt); -static void transformLockingClause(Query *qry, LockingClause *lc); -static bool check_parameter_resolution_walker(Node *node, - check_parameter_resolution_context *context); +static void transformLockingClause(ParseState *pstate, + Query *qry, LockingClause *lc); +static bool check_parameter_resolution_walker(Node *node, ParseState *pstate); /* @@ -122,21 +116,15 @@ parse_analyze_varparams(Node *parseTree, const char *sourceText, query = transformStmt(pstate, parseTree); + /* make sure all is well with parameter types */ + if (pstate->p_numparams > 0) + check_parameter_resolution_walker((Node *) query, pstate); + *paramTypes = pstate->p_paramtypes; *numParams = pstate->p_numparams; free_parsestate(pstate); - /* make sure all is well with parameter types */ - if (*numParams > 0) - { - check_parameter_resolution_context context; - - context.paramTypes = *paramTypes; - context.numParams = *numParams; - check_parameter_resolution_walker((Node *) query, &context); - } - return query; } @@ -383,13 +371,16 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) free_parsestate(sub_pstate); /* The grammar should have produced a SELECT, but it might have INTO */ - Assert(IsA(selectQuery, Query)); - Assert(selectQuery->commandType == CMD_SELECT); - Assert(selectQuery->utilityStmt == NULL); + if (!IsA(selectQuery, Query) || + selectQuery->commandType != CMD_SELECT || + selectQuery->utilityStmt != NULL) + elog(ERROR, "unexpected non-SELECT command in INSERT ... SELECT"); if (selectQuery->intoClause) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("INSERT ... SELECT cannot specify INTO"))); + errmsg("INSERT ... SELECT cannot specify INTO"), + parser_errposition(pstate, + exprLocation((Node *) selectQuery->intoClause)))); /* * Make the source be a subquery in the INSERT's rangetable, and add @@ -477,7 +468,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("VALUES lists must all be the same length"))); + errmsg("VALUES lists must all be the same length"), + parser_errposition(pstate, + exprLocation((Node *) sublist)))); } /* Prepare row for assignment to target table */ @@ -496,7 +489,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) if (pstate->p_joinlist != NIL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("VALUES must not contain table references"))); + errmsg("VALUES must not contain table references"), + parser_errposition(pstate, + locate_var_of_level((Node *) exprsLists, 0)))); /* * Another thing we can't currently support is NEW/OLD references in @@ -509,7 +504,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("VALUES must not contain OLD or NEW references"), - errhint("Use SELECT ... UNION ALL ... instead."))); + errhint("Use SELECT ... UNION ALL ... instead."), + parser_errposition(pstate, + locate_var_of_level((Node *) exprsLists, 0)))); /* * Generate the VALUES RTE @@ -524,7 +521,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) /* * Generate list of Vars referencing the RTE */ - expandRTE(rte, rtr->rtindex, 0, false, NULL, &exprList); + expandRTE(rte, rtr->rtindex, 0, -1, false, NULL, &exprList); } else { @@ -603,7 +600,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) if (pstate->p_hasAggs) ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), - errmsg("cannot use aggregate function in VALUES"))); + errmsg("cannot use aggregate function in VALUES"), + parser_errposition(pstate, + locate_agg_of_level((Node *) qry, 0)))); return qry; } @@ -633,12 +632,18 @@ transformInsertRow(ParseState *pstate, List *exprlist, if (list_length(exprlist) > list_length(icolumns)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("INSERT has more expressions than target columns"))); + errmsg("INSERT has more expressions than target columns"), + parser_errposition(pstate, + exprLocation(list_nth(exprlist, + list_length(icolumns)))))); if (stmtcols != NIL && list_length(exprlist) < list_length(icolumns)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("INSERT has more target columns than expressions"))); + errmsg("INSERT has more target columns than expressions"), + parser_errposition(pstate, + exprLocation(list_nth(icolumns, + list_length(exprlist)))))); /* * Prepare columns for assignment to target table. @@ -770,7 +775,7 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) foreach(l, stmt->lockingClause) { - transformLockingClause(qry, (LockingClause *) lfirst(l)); + transformLockingClause(pstate, qry, (LockingClause *) lfirst(l)); } return qry; @@ -838,7 +843,9 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("VALUES lists must all be the same length"))); + errmsg("VALUES lists must all be the same length"), + parser_errposition(pstate, + exprLocation((Node *) sublist)))); } exprsLists = lappend(exprsLists, sublist); @@ -902,7 +909,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) * Generate a targetlist as though expanding "*" */ Assert(pstate->p_next_resno == 1); - qry->targetList = expandRelAttrs(pstate, rte, rtr->rtindex, 0); + qry->targetList = expandRelAttrs(pstate, rte, rtr->rtindex, 0, -1); /* * The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE to a @@ -940,7 +947,9 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) if (list_length(pstate->p_joinlist) != 1) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("VALUES must not contain table references"))); + errmsg("VALUES must not contain table references"), + parser_errposition(pstate, + locate_var_of_level((Node *) newExprsLists, 0)))); /* * Another thing we can't currently support is NEW/OLD references in rules @@ -953,7 +962,9 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("VALUES must not contain OLD or NEW references"), - errhint("Use SELECT ... UNION ALL ... instead."))); + errhint("Use SELECT ... UNION ALL ... instead."), + parser_errposition(pstate, + locate_var_of_level((Node *) newExprsLists, 0)))); qry->rtable = pstate->p_rtable; qry->jointree = makeFromExpr(pstate->p_joinlist, NULL); @@ -963,7 +974,9 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) if (pstate->p_hasAggs) ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), - errmsg("cannot use aggregate function in VALUES"))); + errmsg("cannot use aggregate function in VALUES"), + parser_errposition(pstate, + locate_agg_of_level((Node *) newExprsLists, 0)))); return qry; } @@ -1155,7 +1168,9 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("invalid UNION/INTERSECT/EXCEPT ORDER BY clause"), errdetail("Only result column names can be used, not expressions or functions."), - errhint("Add the expression/function to every SELECT, or move the UNION into a FROM clause."))); + errhint("Add the expression/function to every SELECT, or move the UNION into a FROM clause."), + parser_errposition(pstate, + exprLocation(list_nth(qry->targetList, tllen))))); qry->limitOffset = transformLimitClause(pstate, limitOffset, "OFFSET"); @@ -1185,7 +1200,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) foreach(l, lockingClause) { - transformLockingClause(qry, (LockingClause *) lfirst(l)); + transformLockingClause(pstate, qry, (LockingClause *) lfirst(l)); } return qry; @@ -1198,9 +1213,9 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) * In addition to returning the transformed node, we return a list of * expression nodes showing the type, typmod, and location (for error messages) * of each output column of the set-op node. This is used only during the - * internal recursion of this function. We use SetToDefault nodes for - * this purpose, since they carry exactly the fields needed, but any other - * expression node type would do as well. + * internal recursion of this function. At the upper levels we use + * SetToDefault nodes for this purpose, since they carry exactly the fields + * needed, but any other expression node type would do as well. */ static Node * transformSetOperationTree(ParseState *pstate, SelectStmt *stmt, @@ -1216,7 +1231,10 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt, if (stmt->intoClause) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT"))); + errmsg("INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT"), + parser_errposition(pstate, + exprLocation((Node *) stmt->intoClause)))); + /* We don't support FOR UPDATE/SHARE with set ops at the moment. */ if (stmt->lockingClause) ereport(ERROR, @@ -1273,25 +1291,21 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt, if (contain_vars_of_level((Node *) selectQuery, 1)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level"))); + errmsg("UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level"), + parser_errposition(pstate, + locate_var_of_level((Node *) selectQuery, 1)))); } /* - * Extract information about the result columns. + * Extract a list of the result expressions for upper-level checking. */ *colInfo = NIL; foreach(tl, selectQuery->targetList) { TargetEntry *tle = (TargetEntry *) lfirst(tl); - SetToDefault *cinfo; - if (tle->resjunk) - continue; - cinfo = makeNode(SetToDefault); - cinfo->typeId = exprType((Node *) tle->expr); - cinfo->typeMod = exprTypmod((Node *) tle->expr); - cinfo->location = exprLocation((Node *) tle->expr); - *colInfo = lappend(*colInfo, cinfo); + if (!tle->resjunk) + *colInfo = lappend(*colInfo, tle->expr); } /* @@ -1356,12 +1370,12 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt, op->groupClauses = NIL; forboth(lci, lcolinfo, rci, rcolinfo) { - SetToDefault *lcolinfo = (SetToDefault *) lfirst(lci); - SetToDefault *rcolinfo = (SetToDefault *) lfirst(rci); - Oid lcoltype = lcolinfo->typeId; - Oid rcoltype = rcolinfo->typeId; - int32 lcoltypmod = lcolinfo->typeMod; - int32 rcoltypmod = rcolinfo->typeMod; + Node *lcolinfo = (Node *) lfirst(lci); + Node *rcolinfo = (Node *) lfirst(rci); + Oid lcoltype = exprType(lcolinfo); + Oid rcoltype = exprType(rcolinfo); + int32 lcoltypmod = exprTypmod(lcolinfo); + int32 rcoltypmod = exprTypmod(rcolinfo); Node *bestexpr; SetToDefault *rescolinfo; Oid rescoltype; @@ -1379,18 +1393,16 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt, rescoltypmod = -1; /* verify the coercions are actually possible */ - if (lcoltype != UNKNOWNOID) - (void) coerce_to_common_type(pstate, (Node *) lcolinfo, - rescoltype, context); - if (rcoltype != UNKNOWNOID) - (void) coerce_to_common_type(pstate, (Node *) rcolinfo, - rescoltype, context); + (void) coerce_to_common_type(pstate, lcolinfo, + rescoltype, context); + (void) coerce_to_common_type(pstate, rcolinfo, + rescoltype, context); /* emit results */ rescolinfo = makeNode(SetToDefault); rescolinfo->typeId = rescoltype; rescolinfo->typeMod = rescoltypmod; - rescolinfo->location = ((SetToDefault *) bestexpr)->location; + rescolinfo->location = exprLocation(bestexpr); *colInfo = lappend(*colInfo, rescolinfo); op->colTypes = lappend_oid(op->colTypes, rescoltype); @@ -1406,12 +1418,18 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt, SortGroupClause *grpcl = makeNode(SortGroupClause); Oid sortop; Oid eqop; + ParseCallbackState pcbstate; + + setup_parser_errposition_callback(&pcbstate, pstate, + rescolinfo->location); /* determine the eqop and optional sortop */ get_sort_group_operators(rescoltype, false, true, false, &sortop, &eqop, NULL); + cancel_parser_errposition_callback(&pcbstate); + /* we don't have a tlist yet, so can't assign sortgrouprefs */ grpcl->tleSortGroupRef = 0; grpcl->eqop = eqop; @@ -1510,7 +1528,9 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt) if (pstate->p_hasAggs) ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), - errmsg("cannot use aggregate function in UPDATE"))); + errmsg("cannot use aggregate function in UPDATE"), + parser_errposition(pstate, + locate_agg_of_level((Node *) qry, 0)))); /* * Now we are done with SELECT-like processing, and can get on with @@ -1607,13 +1627,28 @@ transformReturningList(ParseState *pstate, List *returningList) if (pstate->p_hasAggs) ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), - errmsg("cannot use aggregate function in RETURNING"))); + errmsg("cannot use aggregate function in RETURNING"), + parser_errposition(pstate, + locate_agg_of_level((Node *) rlist, 0)))); /* no new relation references please */ if (list_length(pstate->p_rtable) != length_rtable) + { + int vlocation = -1; + int relid; + + /* try to locate such a reference to point to */ + for (relid = length_rtable + 1; relid <= list_length(pstate->p_rtable); relid++) + { + vlocation = locate_var_of_relation((Node *) rlist, relid, 0); + if (vlocation >= 0) + break; + } ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("RETURNING cannot contain references to other relations"))); + errmsg("RETURNING cannot contain references to other relations"), + parser_errposition(pstate, vlocation))); + } /* mark column origins */ markTargetListOrigins(pstate, rlist); @@ -1653,16 +1688,19 @@ transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt) result = transformStmt(pstate, stmt->query); + /* Grammar should not have allowed anything but SELECT */ if (!IsA(result, Query) || result->commandType != CMD_SELECT || result->utilityStmt != NULL) - elog(ERROR, "unexpected non-SELECT command in cursor statement"); + elog(ERROR, "unexpected non-SELECT command in DECLARE CURSOR"); /* But we must explicitly disallow DECLARE CURSOR ... SELECT INTO */ if (result->intoClause) ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_DEFINITION), - errmsg("DECLARE CURSOR cannot specify INTO"))); + errmsg("DECLARE CURSOR cannot specify INTO"), + parser_errposition(pstate, + exprLocation((Node *) result->intoClause)))); /* FOR UPDATE and WITH HOLD are not compatible */ if (result->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD)) @@ -1761,10 +1799,10 @@ CheckSelectLocking(Query *qry) * This basically involves replacing names by integer relids. * * NB: if you need to change this, see also markQueryForLocking() - * in rewriteHandler.c. + * in rewriteHandler.c, and isLockedRel() in parse_relation.c. */ static void -transformLockingClause(Query *qry, LockingClause *lc) +transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc) { List *lockedRels = lc->lockedRels; ListCell *l; @@ -1801,7 +1839,7 @@ transformLockingClause(Query *qry, LockingClause *lc) * FOR UPDATE/SHARE of subquery is propagated to all of * subquery's rels */ - transformLockingClause(rte->subquery, allrels); + transformLockingClause(pstate, rte->subquery, allrels); break; default: /* ignore JOIN, SPECIAL, FUNCTION RTEs */ @@ -1814,7 +1852,14 @@ transformLockingClause(Query *qry, LockingClause *lc) /* just the named tables */ foreach(l, lockedRels) { - char *relname = strVal(lfirst(l)); + RangeVar *thisrel = (RangeVar *) lfirst(l); + + /* For simplicity we insist on unqualified alias names here */ + if (thisrel->catalogname || thisrel->schemaname) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("SELECT FOR UPDATE/SHARE must specify unqualified relation names"), + parser_errposition(pstate, thisrel->location))); i = 0; foreach(rt, qry->rtable) @@ -1822,7 +1867,7 @@ transformLockingClause(Query *qry, LockingClause *lc) RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt); ++i; - if (strcmp(rte->eref->aliasname, relname) == 0) + if (strcmp(rte->eref->aliasname, thisrel->relname) == 0) { switch (rte->rtekind) { @@ -1837,27 +1882,31 @@ transformLockingClause(Query *qry, LockingClause *lc) * FOR UPDATE/SHARE of subquery is propagated to * all of subquery's rels */ - transformLockingClause(rte->subquery, allrels); + transformLockingClause(pstate, rte->subquery, allrels); break; case RTE_JOIN: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("SELECT FOR UPDATE/SHARE cannot be applied to a join"))); + errmsg("SELECT FOR UPDATE/SHARE cannot be applied to a join"), + parser_errposition(pstate, thisrel->location))); break; case RTE_SPECIAL: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("SELECT FOR UPDATE/SHARE cannot be applied to NEW or OLD"))); + errmsg("SELECT FOR UPDATE/SHARE cannot be applied to NEW or OLD"), + parser_errposition(pstate, thisrel->location))); break; case RTE_FUNCTION: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("SELECT FOR UPDATE/SHARE cannot be applied to a function"))); + errmsg("SELECT FOR UPDATE/SHARE cannot be applied to a function"), + parser_errposition(pstate, thisrel->location))); break; case RTE_VALUES: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("SELECT FOR UPDATE/SHARE cannot be applied to VALUES"))); + errmsg("SELECT FOR UPDATE/SHARE cannot be applied to VALUES"), + parser_errposition(pstate, thisrel->location))); break; default: elog(ERROR, "unrecognized RTE type: %d", @@ -1871,7 +1920,8 @@ transformLockingClause(Query *qry, LockingClause *lc) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_TABLE), errmsg("relation \"%s\" in FOR UPDATE/SHARE clause not found in FROM clause", - relname))); + thisrel->relname), + parser_errposition(pstate, thisrel->location))); } } } @@ -1919,8 +1969,7 @@ applyLockingClause(Query *qry, Index rtindex, bool forUpdate, bool noWait) * and yet other instances seen later might have gotten coerced. */ static bool -check_parameter_resolution_walker(Node *node, - check_parameter_resolution_context *context) +check_parameter_resolution_walker(Node *node, ParseState *pstate) { if (node == NULL) return false; @@ -1933,16 +1982,18 @@ check_parameter_resolution_walker(Node *node, int paramno = param->paramid; if (paramno <= 0 || /* shouldn't happen, but... */ - paramno > context->numParams) + paramno > pstate->p_numparams) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PARAMETER), - errmsg("there is no parameter $%d", paramno))); + errmsg("there is no parameter $%d", paramno), + parser_errposition(pstate, param->location))); - if (param->paramtype != context->paramTypes[paramno - 1]) + if (param->paramtype != pstate->p_paramtypes[paramno - 1]) ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_PARAMETER), errmsg("could not determine data type of parameter $%d", - paramno))); + paramno), + parser_errposition(pstate, param->location))); } return false; } @@ -1951,8 +2002,8 @@ check_parameter_resolution_walker(Node *node, /* Recurse into RTE subquery or not-yet-planned sublink subquery */ return query_tree_walker((Query *) node, check_parameter_resolution_walker, - (void *) context, 0); + (void *) pstate, 0); } return expression_tree_walker(node, check_parameter_resolution_walker, - (void *) context); + (void *) pstate); } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 78e81fbf56..26a3198d37 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.620 2008/08/30 01:39:14 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.621 2008/09/01 20:42:44 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -55,6 +55,7 @@ #include "catalog/namespace.h" #include "commands/defrem.h" #include "nodes/makefuncs.h" +#include "nodes/nodeFuncs.h" #include "parser/gramparse.h" #include "storage/lmgr.h" #include "utils/date.h" @@ -1215,7 +1216,8 @@ zone_value: if (($3 & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("time zone interval must be HOUR or HOUR TO MINUTE"))); + errmsg("time zone interval must be HOUR or HOUR TO MINUTE"), + scanner_errposition(@3))); t->typmods = list_make1(makeIntConst($3, @3)); } $$ = makeStringConstCast($2, @2, t); @@ -1227,7 +1229,8 @@ zone_value: && (($6 & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("time zone interval must be HOUR or HOUR TO MINUTE"))); + errmsg("time zone interval must be HOUR or HOUR TO MINUTE"), + scanner_errposition(@6))); t->typmods = list_make2(makeIntConst($6, @6), makeIntConst($3, @3)); $$ = makeStringConstCast($5, @5, t); @@ -2286,7 +2289,8 @@ key_match: MATCH FULL { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("MATCH PARTIAL not yet implemented"))); + errmsg("MATCH PARTIAL not yet implemented"), + scanner_errposition(@1))); $$ = FKCONSTR_MATCH_PARTIAL; } | MATCH SIMPLE @@ -2378,7 +2382,8 @@ CreateAsStmt: if (n->intoClause != NULL) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("CREATE TABLE AS cannot specify INTO"))); + errmsg("CREATE TABLE AS cannot specify INTO"), + scanner_errposition(exprLocation((Node *) n->intoClause)))); $4->rel->istemp = $2; n->intoClause = $4; $$ = $6; @@ -2799,7 +2804,8 @@ ConstraintAttributeSpec: if ($1 == 0 && $2 != 0) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"))); + errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"), + scanner_errposition(@1))); $$ = $1 | $2; } | ConstraintTimeSpec @@ -2814,7 +2820,8 @@ ConstraintAttributeSpec: if ($2 == 0 && $1 != 0) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"))); + errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"), + scanner_errposition(@1))); $$ = $1 | $2; } | /*EMPTY*/ @@ -2986,9 +2993,11 @@ DefineStmt: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper qualified name (too many dotted names): %s", - NameListToString($3)))); + NameListToString($3)), + scanner_errposition(@3))); break; } + r->location = @3; n->typevar = r; n->coldeflist = $6; $$ = (Node *)n; @@ -3128,12 +3137,12 @@ opclass_item: n->number = $2; $$ = (Node *) n; } - | OPERATOR Iconst any_operator '(' oper_argtypes ')' opt_recheck + | OPERATOR Iconst any_operator oper_argtypes opt_recheck { CreateOpClassItem *n = makeNode(CreateOpClassItem); n->itemtype = OPCLASS_ITEM_OPERATOR; n->name = $3; - n->args = $5; + n->args = $4; n->number = $2; $$ = (Node *) n; } @@ -3178,7 +3187,8 @@ opt_recheck: RECHECK ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("RECHECK is no longer supported"), - errhint("Update your data type."))); + errhint("Update your data type."), + scanner_errposition(@1))); $$ = TRUE; } | /*EMPTY*/ { $$ = FALSE; } @@ -3445,14 +3455,13 @@ CommentStmt: n->comment = $7; $$ = (Node *) n; } - | COMMENT ON OPERATOR any_operator '(' oper_argtypes ')' - IS comment_text + | COMMENT ON OPERATOR any_operator oper_argtypes IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_OPERATOR; n->objname = $4; - n->objargs = $6; - n->comment = $9; + n->objargs = $5; + n->comment = $7; $$ = (Node *) n; } | COMMENT ON CONSTRAINT name ON any_name IS comment_text @@ -4088,8 +4097,8 @@ opt_class: any_name { $$ = $1; } ; opt_asc_desc: ASC { $$ = SORTBY_ASC; } - | DESC { $$ = SORTBY_DESC; } - | /*EMPTY*/ { $$ = SORTBY_DEFAULT; } + | DESC { $$ = SORTBY_DESC; } + | /*EMPTY*/ { $$ = SORTBY_DEFAULT; } ; opt_nulls_order: NULLS_FIRST { $$ = SORTBY_NULLS_FIRST; } @@ -4464,42 +4473,43 @@ RemoveAggrStmt: ; RemoveOperStmt: - DROP OPERATOR any_operator '(' oper_argtypes ')' opt_drop_behavior + DROP OPERATOR any_operator oper_argtypes opt_drop_behavior { RemoveFuncStmt *n = makeNode(RemoveFuncStmt); n->kind = OBJECT_OPERATOR; n->name = $3; - n->args = $5; - n->behavior = $7; + n->args = $4; + n->behavior = $5; n->missing_ok = false; $$ = (Node *)n; } - | DROP OPERATOR IF_P EXISTS any_operator '(' oper_argtypes ')' opt_drop_behavior + | DROP OPERATOR IF_P EXISTS any_operator oper_argtypes opt_drop_behavior { RemoveFuncStmt *n = makeNode(RemoveFuncStmt); n->kind = OBJECT_OPERATOR; n->name = $5; - n->args = $7; - n->behavior = $9; + n->args = $6; + n->behavior = $7; n->missing_ok = true; $$ = (Node *)n; } ; oper_argtypes: - Typename + '(' Typename ')' { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("missing argument"), - errhint("Use NONE to denote the missing argument of a unary operator."))); + errhint("Use NONE to denote the missing argument of a unary operator."), + scanner_errposition(@3))); } - | Typename ',' Typename - { $$ = list_make2($1, $3); } - | NONE ',' Typename /* left unary */ - { $$ = list_make2(NULL, $3); } - | Typename ',' NONE /* right unary */ - { $$ = list_make2($1, NULL); } + | '(' Typename ',' Typename ')' + { $$ = list_make2($2, $4); } + | '(' NONE ',' Typename ')' /* left unary */ + { $$ = list_make2(NULL, $4); } + | '(' Typename ',' NONE ')' /* right unary */ + { $$ = list_make2($2, NULL); } ; any_operator: @@ -4939,13 +4949,13 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $7; $$ = (Node *)n; } - | ALTER OPERATOR any_operator '(' oper_argtypes ')' OWNER TO RoleId + | ALTER OPERATOR any_operator oper_argtypes OWNER TO RoleId { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_OPERATOR; n->object = $3; - n->objarg = $5; - n->newowner = $9; + n->objarg = $4; + n->newowner = $7; $$ = (Node *)n; } | ALTER OPERATOR CLASS any_name USING access_method OWNER TO RoleId @@ -5108,7 +5118,7 @@ DropRuleStmt: /***************************************************************************** * * QUERY: - * NOTIFY can appear both in rule bodies and + * NOTIFY can appear both in rule bodies and * as a query-level command * *****************************************************************************/ @@ -5116,9 +5126,7 @@ DropRuleStmt: NotifyStmt: NOTIFY ColId { NotifyStmt *n = makeNode(NotifyStmt); - n->relation = makeNode(RangeVar); - n->relation->relname = $2; - n->relation->schemaname = NULL; + n->conditionname = $2; $$ = (Node *)n; } ; @@ -5126,9 +5134,7 @@ NotifyStmt: NOTIFY ColId ListenStmt: LISTEN ColId { ListenStmt *n = makeNode(ListenStmt); - n->relation = makeNode(RangeVar); - n->relation->relname = $2; - n->relation->schemaname = NULL; + n->conditionname = $2; $$ = (Node *)n; } ; @@ -5137,15 +5143,13 @@ UnlistenStmt: UNLISTEN ColId { UnlistenStmt *n = makeNode(UnlistenStmt); - n->relation = makeNode(RangeVar); - n->relation->relname = $2; - n->relation->schemaname = NULL; + n->conditionname = $2; $$ = (Node *)n; } | UNLISTEN '*' { UnlistenStmt *n = makeNode(UnlistenStmt); - n->relation = NULL; + n->conditionname = NULL; $$ = (Node *)n; } ; @@ -6119,7 +6123,8 @@ multiple_set_clause: if (list_length($2) != list_length($5)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("number of columns does not match number of values"))); + errmsg("number of columns does not match number of values"), + scanner_errposition(@1))); forboth(col_cell, $2, val_cell, $5) { ResTarget *res_col = (ResTarget *) lfirst(col_cell); @@ -6419,6 +6424,7 @@ sortby: a_expr USING qual_all_Op opt_nulls_order $$->sortby_dir = SORTBY_USING; $$->sortby_nulls = $4; $$->useOp = $3; + $$->location = @3; } | a_expr opt_asc_desc opt_nulls_order { @@ -6427,6 +6433,7 @@ sortby: a_expr USING qual_all_Op opt_nulls_order $$->sortby_dir = $2; $$->sortby_nulls = $3; $$->useOp = NIL; + $$->location = -1; /* no operator */ } ; @@ -6446,7 +6453,8 @@ select_limit: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("LIMIT #,# syntax is not supported"), - errhint("Use separate LIMIT and OFFSET clauses."))); + errhint("Use separate LIMIT and OFFSET clauses."), + scanner_errposition(@1))); } ; @@ -6514,7 +6522,7 @@ for_locking_item: ; locked_rels_list: - OF name_list { $$ = $2; } + OF qualified_name_list { $$ = $2; } | /* EMPTY */ { $$ = NIL; } ; @@ -6629,12 +6637,14 @@ table_ref: relation_expr ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("VALUES in FROM must have an alias"), - errhint("For example, FROM (VALUES ...) [AS] foo."))); + errhint("For example, FROM (VALUES ...) [AS] foo."), + scanner_errposition(@1))); else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("subquery in FROM must have an alias"), - errhint("For example, FROM (SELECT ...) [AS] foo."))); + errhint("For example, FROM (SELECT ...) [AS] foo."), + scanner_errposition(@1))); $$ = NULL; } | select_with_parens alias_clause @@ -7089,7 +7099,8 @@ opt_float: '(' Iconst ')' if ($2 < 1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("precision for type float must be at least 1 bit"))); + errmsg("precision for type float must be at least 1 bit"), + scanner_errposition(@2))); else if ($2 <= 24) $$ = SystemTypeName("float4"); else if ($2 <= 53) @@ -7097,7 +7108,8 @@ opt_float: '(' Iconst ')' else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("precision for type float must be less than 54 bits"))); + errmsg("precision for type float must be less than 54 bits"), + scanner_errposition(@2))); } | /*EMPTY*/ { @@ -7734,7 +7746,8 @@ a_expr: c_expr { $$ = $1; } */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("UNIQUE predicate is not yet implemented"))); + errmsg("UNIQUE predicate is not yet implemented"), + scanner_errposition(@1))); } | a_expr IS DOCUMENT_P %prec IS { @@ -8874,6 +8887,7 @@ qualified_name: $$->catalogname = NULL; $$->schemaname = NULL; $$->relname = $1; + $$->location = @1; } | relation_name indirection { @@ -8895,9 +8909,11 @@ qualified_name: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper qualified name (too many dotted names): %s", - NameListToString(lcons(makeString($1), $2))))); + NameListToString(lcons(makeString($1), $2))), + scanner_errposition(@1))); break; } + $$->location = @1; } ; @@ -9494,7 +9510,8 @@ SpecialRuleRelation: else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("OLD used in query that is not in a rule"))); + errmsg("OLD used in query that is not in a rule"), + scanner_errposition(@1))); } | NEW { @@ -9503,7 +9520,8 @@ SpecialRuleRelation: else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("NEW used in query that is not in a rule"))); + errmsg("NEW used in query that is not in a rule"), + scanner_errposition(@1))); } ; @@ -9689,13 +9707,15 @@ makeOverlaps(List *largs, List *rargs, int location) else if (list_length(largs) != 2) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("wrong number of parameters on left side of OVERLAPS expression"))); + errmsg("wrong number of parameters on left side of OVERLAPS expression"), + scanner_errposition(location))); if (list_length(rargs) == 1) rargs = lappend(rargs, rargs); else if (list_length(rargs) != 2) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("wrong number of parameters on right side of OVERLAPS expression"))); + errmsg("wrong number of parameters on right side of OVERLAPS expression"), + scanner_errposition(location))); n->args = list_concat(largs, rargs); n->agg_star = FALSE; n->agg_distinct = FALSE; @@ -9813,7 +9833,8 @@ insertSelectOptions(SelectStmt *stmt, if (stmt->sortClause) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple ORDER BY clauses not allowed"))); + errmsg("multiple ORDER BY clauses not allowed"), + scanner_errposition(exprLocation((Node *) sortClause)))); stmt->sortClause = sortClause; } /* We can handle multiple locking clauses, though */ @@ -9823,7 +9844,8 @@ insertSelectOptions(SelectStmt *stmt, if (stmt->limitOffset) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple OFFSET clauses not allowed"))); + errmsg("multiple OFFSET clauses not allowed"), + scanner_errposition(exprLocation(limitOffset)))); stmt->limitOffset = limitOffset; } if (limitCount) @@ -9831,7 +9853,8 @@ insertSelectOptions(SelectStmt *stmt, if (stmt->limitCount) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple LIMIT clauses not allowed"))); + errmsg("multiple LIMIT clauses not allowed"), + scanner_errposition(exprLocation(limitCount)))); stmt->limitCount = limitCount; } } diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index 215557396f..d85f64c7ab 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.82 2008/08/28 23:09:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.83 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -70,7 +70,9 @@ transformAggregateCall(ParseState *pstate, Aggref *agg) if (checkExprHasAggs((Node *) agg->args)) ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), - errmsg("aggregate function calls cannot be nested"))); + errmsg("aggregate function calls cannot be nested"), + parser_errposition(pstate, + locate_agg_of_level((Node *) agg->args, 0)))); } if (min_varlevel < 0) @@ -117,11 +119,15 @@ parseCheckAggregates(ParseState *pstate, Query *qry) if (checkExprHasAggs(qry->jointree->quals)) ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), - errmsg("aggregates not allowed in WHERE clause"))); + errmsg("aggregates not allowed in WHERE clause"), + parser_errposition(pstate, + locate_agg_of_level(qry->jointree->quals, 0)))); if (checkExprHasAggs((Node *) qry->jointree->fromlist)) ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), - errmsg("aggregates not allowed in JOIN conditions"))); + errmsg("aggregates not allowed in JOIN conditions"), + parser_errposition(pstate, + locate_agg_of_level((Node *) qry->jointree->fromlist, 0)))); /* * No aggregates allowed in GROUP BY clauses, either. @@ -140,7 +146,9 @@ parseCheckAggregates(ParseState *pstate, Query *qry) if (checkExprHasAggs(expr)) ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), - errmsg("aggregates not allowed in GROUP BY clause"))); + errmsg("aggregates not allowed in GROUP BY clause"), + parser_errposition(pstate, + locate_agg_of_level(expr, 0)))); groupClauses = lcons(expr, groupClauses); } @@ -327,13 +335,14 @@ check_ungrouped_columns_walker(Node *node, ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), errmsg("column \"%s.%s\" must appear in the GROUP BY clause or be used in an aggregate function", - rte->eref->aliasname, attname))); + rte->eref->aliasname, attname), + parser_errposition(context->pstate, var->location))); else ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), errmsg("subquery uses ungrouped column \"%s.%s\" from outer query", - rte->eref->aliasname, attname))); - + rte->eref->aliasname, attname), + parser_errposition(context->pstate, var->location))); } if (IsA(node, Query)) diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 5285f0ba3d..2f547f29be 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.178 2008/08/30 01:39:14 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.179 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -66,12 +66,13 @@ static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype, Var *l_colvar, Var *r_colvar); static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause); +static int get_matching_location(int sortgroupref, + List *sortgrouprefs, List *exprs); static List *addTargetToSortList(ParseState *pstate, TargetEntry *tle, - List *sortlist, List *targetlist, - SortByDir sortby_dir, SortByNulls sortby_nulls, - List *sortby_opname, bool resolveUnknown); + List *sortlist, List *targetlist, SortBy *sortby, + bool resolveUnknown); static List *addTargetToGroupList(ParseState *pstate, TargetEntry *tle, - List *grouplist, List *targetlist, + List *grouplist, List *targetlist, int location, bool resolveUnknown); @@ -163,7 +164,8 @@ setTargetTable(ParseState *pstate, RangeVar *relation, * free_parsestate() will eventually do the corresponding heap_close(), * but *not* release the lock. */ - pstate->p_target_relation = heap_openrv(relation, RowExclusiveLock); + pstate->p_target_relation = parserOpenTable(pstate, relation, + RowExclusiveLock); /* * Now build an RTE. @@ -390,7 +392,9 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j, ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("JOIN/ON clause refers to \"%s\", which is not part of JOIN", - rt_fetch(varno, pstate->p_rtable)->eref->aliasname))); + rt_fetch(varno, pstate->p_rtable)->eref->aliasname), + parser_errposition(pstate, + locate_var_of_relation(result, varno, 0)))); } bms_free(clause_varnos); @@ -431,12 +435,11 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r) /* * We require user to supply an alias for a subselect, per SQL92. To relax * this, we'd have to be prepared to gin up a unique alias for an - * unlabeled subselect. + * unlabeled subselect. (This is just elog, not ereport, because the + * grammar should have enforced it already.) */ if (r->alias == NULL) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("subquery in FROM must have an alias"))); + elog(ERROR, "subquery in FROM must have an alias"); /* * Analyze and transform the subquery. @@ -447,13 +450,16 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r) * Check that we got something reasonable. Many of these conditions are * impossible given restrictions of the grammar, but check 'em anyway. */ - if (query->commandType != CMD_SELECT || + if (!IsA(query, Query) || + query->commandType != CMD_SELECT || query->utilityStmt != NULL) - elog(ERROR, "expected SELECT query from subquery in FROM"); - if (query->intoClause != NULL) + elog(ERROR, "unexpected non-SELECT command in subquery in FROM"); + if (query->intoClause) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("subquery in FROM cannot have SELECT INTO"))); + errmsg("subquery in FROM cannot have SELECT INTO"), + parser_errposition(pstate, + exprLocation((Node *) query->intoClause)))); /* * The subquery cannot make use of any variables from FROM items created @@ -473,7 +479,9 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r) if (contain_vars_of_level((Node *) query, 1)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("subquery in FROM cannot refer to other relations of same query level"))); + errmsg("subquery in FROM cannot refer to other relations of same query level"), + parser_errposition(pstate, + locate_var_of_level((Node *) query, 1)))); } /* @@ -522,7 +530,9 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) if (contain_vars_of_level(funcexpr, 0)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("function expression in FROM cannot refer to other relations of same query level"))); + errmsg("function expression in FROM cannot refer to other relations of same query level"), + parser_errposition(pstate, + locate_var_of_level(funcexpr, 0)))); } /* @@ -534,7 +544,9 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) if (checkExprHasAggs(funcexpr)) ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), - errmsg("cannot use aggregate function in function expression in FROM"))); + errmsg("cannot use aggregate function in function expression in FROM"), + parser_errposition(pstate, + locate_agg_of_level(funcexpr, 0)))); } /* @@ -709,9 +721,9 @@ transformFromClauseItem(ParseState *pstate, Node *n, * * Note: expandRTE returns new lists, safe for me to modify */ - expandRTE(l_rte, l_rtindex, 0, false, + expandRTE(l_rte, l_rtindex, 0, -1, false, &l_colnames, &l_colvars); - expandRTE(r_rte, r_rtindex, 0, false, + expandRTE(r_rte, r_rtindex, 0, -1, false, &r_colnames, &r_colvars); /* @@ -1109,7 +1121,9 @@ transformLimitClause(ParseState *pstate, Node *clause, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), /* translator: %s is name of a SQL construct, eg LIMIT */ errmsg("argument of %s must not contain variables", - constructName))); + constructName), + parser_errposition(pstate, + locate_var_of_level(qual, 0)))); } if (checkExprHasAggs(qual)) { @@ -1117,7 +1131,9 @@ transformLimitClause(ParseState *pstate, Node *clause, (errcode(ERRCODE_GROUPING_ERROR), /* translator: %s is name of a SQL construct, eg LIMIT */ errmsg("argument of %s must not contain aggregates", - constructName))); + constructName), + parser_errposition(pstate, + locate_agg_of_level(qual, 0)))); } return qual; @@ -1365,6 +1381,7 @@ transformGroupClause(ParseState *pstate, List *grouplist, if (!found) result = addTargetToGroupList(pstate, tle, result, *targetlist, + exprLocation(gexpr), true); } @@ -1396,10 +1413,7 @@ transformSortClause(ParseState *pstate, targetlist, ORDER_CLAUSE); sortlist = addTargetToSortList(pstate, tle, - sortlist, *targetlist, - sortby->sortby_dir, - sortby->sortby_nulls, - sortby->useOp, + sortlist, *targetlist, sortby, resolveUnknown); } @@ -1450,7 +1464,9 @@ transformDistinctClause(ParseState *pstate, if (tle->resjunk) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("for SELECT DISTINCT, ORDER BY expressions must appear in select list"))); + errmsg("for SELECT DISTINCT, ORDER BY expressions must appear in select list"), + parser_errposition(pstate, + exprLocation((Node *) tle->expr)))); result = lappend(result, copyObject(scl)); } @@ -1466,6 +1482,7 @@ transformDistinctClause(ParseState *pstate, continue; /* ignore junk */ result = addTargetToGroupList(pstate, tle, result, *targetlist, + exprLocation((Node *) tle->expr), true); } @@ -1490,28 +1507,29 @@ transformDistinctOnClause(ParseState *pstate, List *distinctlist, List **targetlist, List *sortClause) { List *result = NIL; - ListCell *slitem; - ListCell *dlitem; - Bitmapset *refnos = NULL; - int sortgroupref; + List *sortgrouprefs = NIL; bool skipped_sortitem; + ListCell *lc; + ListCell *lc2; /* * Add all the DISTINCT ON expressions to the tlist (if not already * present, they are added as resjunk items). Assign sortgroupref - * numbers to them, and form a bitmapset of these numbers. (A - * bitmapset is convenient here because we don't care about order - * and we can discard duplicates.) + * numbers to them, and make a list of these numbers. (NB: we rely + * below on the sortgrouprefs list being one-for-one with the original + * distinctlist. Also notice that we could have duplicate DISTINCT ON + * expressions and hence duplicate entries in sortgrouprefs.) */ - foreach(dlitem, distinctlist) + foreach(lc, distinctlist) { - Node *dexpr = (Node *) lfirst(dlitem); + Node *dexpr = (Node *) lfirst(lc); + int sortgroupref; TargetEntry *tle; tle = findTargetlistEntry(pstate, dexpr, targetlist, DISTINCT_ON_CLAUSE); sortgroupref = assignSortGroupRef(tle, *targetlist); - refnos = bms_add_member(refnos, sortgroupref); + sortgrouprefs = lappend_int(sortgrouprefs, sortgroupref); } /* @@ -1523,16 +1541,20 @@ transformDistinctOnClause(ParseState *pstate, List *distinctlist, * skipped an ORDER BY item that wasn't in DISTINCT ON. */ skipped_sortitem = false; - foreach(slitem, sortClause) + foreach(lc, sortClause) { - SortGroupClause *scl = (SortGroupClause *) lfirst(slitem); + SortGroupClause *scl = (SortGroupClause *) lfirst(lc); - if (bms_is_member(scl->tleSortGroupRef, refnos)) + if (list_member_int(sortgrouprefs, scl->tleSortGroupRef)) { if (skipped_sortitem) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("SELECT DISTINCT ON expressions must match initial ORDER BY expressions"))); + errmsg("SELECT DISTINCT ON expressions must match initial ORDER BY expressions"), + parser_errposition(pstate, + get_matching_location(scl->tleSortGroupRef, + sortgrouprefs, + distinctlist)))); else result = lappend(result, copyObject(scl)); } @@ -1549,8 +1571,10 @@ transformDistinctOnClause(ParseState *pstate, List *distinctlist, * better to throw an error or warning here. But historically we've * allowed it, so keep doing so.) */ - while ((sortgroupref = bms_first_member(refnos)) >= 0) + forboth(lc, distinctlist, lc2, sortgrouprefs) { + Node *dexpr = (Node *) lfirst(lc); + int sortgroupref = lfirst_int(lc2); TargetEntry *tle = get_sortgroupref_tle(sortgroupref, *targetlist); if (targetIsInSortList(tle, InvalidOid, result)) @@ -1558,15 +1582,44 @@ transformDistinctOnClause(ParseState *pstate, List *distinctlist, if (skipped_sortitem) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("SELECT DISTINCT ON expressions must match initial ORDER BY expressions"))); + errmsg("SELECT DISTINCT ON expressions must match initial ORDER BY expressions"), + parser_errposition(pstate, exprLocation(dexpr)))); result = addTargetToGroupList(pstate, tle, result, *targetlist, + exprLocation(dexpr), true); } return result; } +/* + * get_matching_location + * Get the exprLocation of the exprs member corresponding to the + * (first) member of sortgrouprefs that equals sortgroupref. + * + * This is used so that we can point at a troublesome DISTINCT ON entry. + * (Note that we need to use the original untransformed DISTINCT ON list + * item, as whatever TLE it corresponds to will very possibly have a + * parse location pointing to some matching entry in the SELECT list + * or ORDER BY list.) + */ +static int +get_matching_location(int sortgroupref, List *sortgrouprefs, List *exprs) +{ + ListCell *lcs; + ListCell *lce; + + forboth(lcs, sortgrouprefs, lce, exprs) + { + if (lfirst_int(lcs) == sortgroupref) + return exprLocation((Node *) lfirst(lce)); + } + /* if no match, caller blew it */ + elog(ERROR, "get_matching_location: no matching sortgroupref"); + return -1; /* keep compiler quiet */ +} + /* * addTargetToSortList * If the given targetlist entry isn't already in the SortGroupClause @@ -1582,14 +1635,15 @@ transformDistinctOnClause(ParseState *pstate, List *distinctlist, */ static List * addTargetToSortList(ParseState *pstate, TargetEntry *tle, - List *sortlist, List *targetlist, - SortByDir sortby_dir, SortByNulls sortby_nulls, - List *sortby_opname, bool resolveUnknown) + List *sortlist, List *targetlist, SortBy *sortby, + bool resolveUnknown) { Oid restype = exprType((Node *) tle->expr); Oid sortop; Oid eqop; bool reverse; + int location; + ParseCallbackState pcbstate; /* if tlist item is an UNKNOWN literal, change it to TEXT */ if (restype == UNKNOWNOID && resolveUnknown) @@ -1602,8 +1656,21 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle, restype = TEXTOID; } + /* + * Rather than clutter the API of get_sort_group_operators and the other + * functions we're about to use, make use of error context callback to + * mark any error reports with a parse position. We point to the operator + * location if present, else to the expression being sorted. (NB: use + * the original untransformed expression here; the TLE entry might well + * point at a duplicate expression in the regular SELECT list.) + */ + location = sortby->location; + if (location < 0) + location = exprLocation(sortby->node); + setup_parser_errposition_callback(&pcbstate, pstate, location); + /* determine the sortop, eqop, and directionality */ - switch (sortby_dir) + switch (sortby->sortby_dir) { case SORTBY_DEFAULT: case SORTBY_ASC: @@ -1619,8 +1686,8 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle, reverse = true; break; case SORTBY_USING: - Assert(sortby_opname != NIL); - sortop = compatible_oper_opid(sortby_opname, + Assert(sortby->useOp != NIL); + sortop = compatible_oper_opid(sortby->useOp, restype, restype, false); @@ -1635,17 +1702,19 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle, ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("operator %s is not a valid ordering operator", - strVal(llast(sortby_opname))), + strVal(llast(sortby->useOp))), errhint("Ordering operators must be \"<\" or \">\" members of btree operator families."))); break; default: - elog(ERROR, "unrecognized sortby_dir: %d", sortby_dir); + elog(ERROR, "unrecognized sortby_dir: %d", sortby->sortby_dir); sortop = InvalidOid; /* keep compiler quiet */ eqop = InvalidOid; reverse = false; break; } + cancel_parser_errposition_callback(&pcbstate); + /* avoid making duplicate sortlist entries */ if (!targetIsInSortList(tle, sortop, sortlist)) { @@ -1656,7 +1725,7 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle, sortcl->eqop = eqop; sortcl->sortop = sortop; - switch (sortby_nulls) + switch (sortby->sortby_nulls) { case SORTBY_NULLS_DEFAULT: /* NULLS FIRST is default for DESC; other way for ASC */ @@ -1669,7 +1738,8 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle, sortcl->nulls_first = false; break; default: - elog(ERROR, "unrecognized sortby_nulls: %d", sortby_nulls); + elog(ERROR, "unrecognized sortby_nulls: %d", + sortby->sortby_nulls); break; } @@ -1690,6 +1760,11 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle, * the TLE is considered "already in the list" if it appears there with any * sorting semantics. * + * location is the parse location to be fingered in event of trouble. Note + * that we can't rely on exprLocation(tle->expr), because that might point + * to a SELECT item that matches the GROUP BY item; it'd be pretty confusing + * to report such a location. + * * If resolveUnknown is TRUE, convert TLEs of type UNKNOWN to TEXT. If not, * do nothing (which implies the search for an equality operator will fail). * pstate should be provided if resolveUnknown is TRUE, but can be NULL @@ -1699,7 +1774,7 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle, */ static List * addTargetToGroupList(ParseState *pstate, TargetEntry *tle, - List *grouplist, List *targetlist, + List *grouplist, List *targetlist, int location, bool resolveUnknown) { Oid restype = exprType((Node *) tle->expr); @@ -1721,12 +1796,17 @@ addTargetToGroupList(ParseState *pstate, TargetEntry *tle, if (!targetIsInSortList(tle, InvalidOid, grouplist)) { SortGroupClause *grpcl = makeNode(SortGroupClause); + ParseCallbackState pcbstate; + + setup_parser_errposition_callback(&pcbstate, pstate, location); /* determine the eqop and optional sortop */ get_sort_group_operators(restype, false, true, false, &sortop, &eqop, NULL); + cancel_parser_errposition_callback(&pcbstate); + grpcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist); grpcl->eqop = eqop; grpcl->sortop = sortop; diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index cd9b7b0cfb..efe45974c3 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.165 2008/08/28 23:09:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.166 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -180,6 +180,7 @@ coerce_type(ParseState *pstate, Node *node, Oid baseTypeId; int32 baseTypeMod; Type targetType; + ParseCallbackState pcbstate; /* * If the target type is a domain, we want to call its base type's @@ -207,6 +208,12 @@ coerce_type(ParseState *pstate, Node *node, else newcon->location = location; + /* + * Set up to point at the constant's text if the input routine + * throws an error. + */ + setup_parser_errposition_callback(&pcbstate, pstate, con->location); + /* * We pass typmod -1 to the input routine, primarily because existing * input routines follow implicit-coercion semantics for length @@ -223,6 +230,8 @@ coerce_type(ParseState *pstate, Node *node, else newcon->constvalue = stringTypeDatum(targetType, NULL, -1); + cancel_parser_errposition_callback(&pcbstate); + result = (Node *) newcon; /* If target is a domain, apply constraints. */ @@ -257,7 +266,8 @@ coerce_type(ParseState *pstate, Node *node, paramno > toppstate->p_numparams) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PARAMETER), - errmsg("there is no parameter $%d", paramno))); + errmsg("there is no parameter $%d", paramno), + parser_errposition(pstate, param->location))); if (toppstate->p_paramtypes[paramno - 1] == UNKNOWNOID) { @@ -277,7 +287,8 @@ coerce_type(ParseState *pstate, Node *node, paramno), errdetail("%s versus %s", format_type_be(toppstate->p_paramtypes[paramno - 1]), - format_type_be(targetTypeId)))); + format_type_be(targetTypeId)), + parser_errposition(pstate, param->location))); } param->paramtype = targetTypeId; @@ -819,10 +830,11 @@ coerce_record_to_complex(ParseState *pstate, Node *node, { int rtindex = ((Var *) node)->varno; int sublevels_up = ((Var *) node)->varlevelsup; + int vlocation = ((Var *) node)->location; RangeTblEntry *rte; rte = GetRTEByRangeTablePosn(pstate, rtindex, sublevels_up); - expandRTE(rte, rtindex, sublevels_up, false, + expandRTE(rte, rtindex, sublevels_up, vlocation, false, NULL, &args); } else diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 8496e7291c..1091d87473 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.233 2008/08/30 01:39:14 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.234 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -122,7 +122,7 @@ transformExpr(ParseState *pstate, Node *expr) A_Const *con = (A_Const *) expr; Value *val = &con->val; - result = (Node *) make_const(val, con->location); + result = (Node *) make_const(pstate, val, con->location); break; } @@ -454,6 +454,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) * "rel.*". */ if (refnameRangeTblEntry(pstate, NULL, name1, + cref->location, &levels_up) != NULL) node = transformWholeRowRef(pstate, NULL, name1, cref->location); @@ -621,7 +622,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) * return a pointer to it. */ static Oid * -find_param_type(ParseState *pstate, int paramno) +find_param_type(ParseState *pstate, int paramno, int location) { Oid *result; @@ -635,14 +636,15 @@ find_param_type(ParseState *pstate, int paramno) if (paramno <= 0) /* probably can't happen? */ ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PARAMETER), - errmsg("there is no parameter $%d", paramno))); + errmsg("there is no parameter $%d", paramno), + parser_errposition(pstate, location))); if (paramno > pstate->p_numparams) { if (!pstate->p_variableparams) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PARAMETER), - errmsg("there is no parameter $%d", - paramno))); + errmsg("there is no parameter $%d", paramno), + parser_errposition(pstate, location))); /* Okay to enlarge param array */ if (pstate->p_paramtypes) pstate->p_paramtypes = (Oid *) repalloc(pstate->p_paramtypes, @@ -672,7 +674,7 @@ static Node * transformParamRef(ParseState *pstate, ParamRef *pref) { int paramno = pref->number; - Oid *pptype = find_param_type(pstate, paramno); + Oid *pptype = find_param_type(pstate, paramno, pref->location); Param *param; param = makeNode(Param); @@ -1235,10 +1237,22 @@ transformSubLink(ParseState *pstate, SubLink *sublink) pstate->p_hasSubLinks = true; qtree = parse_sub_analyze(sublink->subselect, pstate); - if (qtree->commandType != CMD_SELECT || - qtree->utilityStmt != NULL || - qtree->intoClause != NULL) - elog(ERROR, "bad query in sub-select"); + + /* + * Check that we got something reasonable. Many of these conditions are + * impossible given restrictions of the grammar, but check 'em anyway. + */ + if (!IsA(qtree, Query) || + qtree->commandType != CMD_SELECT || + qtree->utilityStmt != NULL) + elog(ERROR, "unexpected non-SELECT command in SubLink"); + if (qtree->intoClause) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("subquery cannot have SELECT INTO"), + parser_errposition(pstate, + exprLocation((Node *) qtree->intoClause)))); + sublink->subselect = (Node *) qtree; if (sublink->subLinkType == EXISTS_SUBLINK) @@ -1445,7 +1459,8 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a, ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("could not find element type for data type %s", - format_type_be(array_type)))); + format_type_be(array_type)), + parser_errposition(pstate, a->location))); } else { @@ -1455,7 +1470,8 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a, ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("could not find array type for data type %s", - format_type_be(element_type)))); + format_type_be(element_type)), + parser_errposition(pstate, a->location))); } coerce_hard = false; } @@ -1823,7 +1839,7 @@ transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr) /* If a parameter is used, it must be of type REFCURSOR */ if (cexpr->cursor_name == NULL) { - Oid *pptype = find_param_type(pstate, cexpr->cursor_param); + Oid *pptype = find_param_type(pstate, cexpr->cursor_param, -1); if (pstate->p_variableparams && *pptype == UNKNOWNOID) { @@ -1866,12 +1882,12 @@ transformWholeRowRef(ParseState *pstate, char *schemaname, char *relname, /* Look up the referenced RTE, creating it if needed */ - rte = refnameRangeTblEntry(pstate, schemaname, relname, + rte = refnameRangeTblEntry(pstate, schemaname, relname, location, &sublevels_up); if (rte == NULL) - rte = addImplicitRTE(pstate, makeRangeVar(schemaname, relname), - location); + rte = addImplicitRTE(pstate, + makeRangeVar(schemaname, relname, location)); vnum = RTERangeTablePosn(pstate, rte, &sublevels_up); diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 31317800c1..bbbc5fe7a9 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.206 2008/08/28 23:09:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.207 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -270,7 +270,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("could not find array type for data type %s", - format_type_be(newa->element_typeid)))); + format_type_be(newa->element_typeid)), + parser_errposition(pstate, exprLocation((Node *) vargs)))); newa->multidims = false; newa->location = exprLocation((Node *) vargs); diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index 1760e49285..532dbe319d 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.102 2008/08/28 23:09:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.103 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,6 +29,9 @@ #include "utils/varbit.h" +static void pcb_error_callback(void *arg); + + /* * make_parsestate * Allocate and initialize a new ParseState. @@ -112,6 +115,62 @@ parser_errposition(ParseState *pstate, int location) } +/* + * setup_parser_errposition_callback + * Arrange for non-parser errors to report an error position + * + * Sometimes the parser calls functions that aren't part of the parser + * subsystem and can't reasonably be passed a ParseState; yet we would + * like any errors thrown in those functions to be tagged with a parse + * error location. Use this function to set up an error context stack + * entry that will accomplish that. Usage pattern: + * + * declare a local variable "ParseCallbackState pcbstate" + * ... + * setup_parser_errposition_callback(&pcbstate, pstate, location); + * call function that might throw error; + * cancel_parser_errposition_callback(&pcbstate); + */ +void +setup_parser_errposition_callback(ParseCallbackState *pcbstate, + ParseState *pstate, int location) +{ + /* Setup error traceback support for ereport() */ + pcbstate->pstate = pstate; + pcbstate->location = location; + pcbstate->errcontext.callback = pcb_error_callback; + pcbstate->errcontext.arg = (void *) pcbstate; + pcbstate->errcontext.previous = error_context_stack; + error_context_stack = &pcbstate->errcontext; +} + +/* + * Cancel a previously-set-up errposition callback. + */ +void +cancel_parser_errposition_callback(ParseCallbackState *pcbstate) +{ + /* Pop the error context stack */ + error_context_stack = pcbstate->errcontext.previous; +} + +/* + * Error context callback for inserting parser error location. + * + * Note that this will be called for *any* error occurring while the + * callback is installed. We avoid inserting an irrelevant error location + * if the error is a query cancel --- are there any other important cases? + */ +static void +pcb_error_callback(void *arg) +{ + ParseCallbackState *pcbstate = (ParseCallbackState *) arg; + + if (geterrcode() != ERRCODE_QUERY_CANCELED) + (void) parser_errposition(pcbstate->pstate, pcbstate->location); +} + + /* * make_var * Build a Var node for an attribute identified by RTE and attrno @@ -344,14 +403,15 @@ transformArraySubscripts(ParseState *pstate, * too many examples that fail if we try. */ Const * -make_const(Value *value, int location) +make_const(ParseState *pstate, Value *value, int location) { + Const *con; Datum val; int64 val64; Oid typeid; int typelen; bool typebyval; - Const *con; + ParseCallbackState pcbstate; switch (nodeTag(value)) { @@ -392,10 +452,13 @@ make_const(Value *value, int location) } else { + /* arrange to report location if numeric_in() fails */ + setup_parser_errposition_callback(&pcbstate, pstate, location); val = DirectFunctionCall3(numeric_in, CStringGetDatum(strVal(value)), ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1)); + cancel_parser_errposition_callback(&pcbstate); typeid = NUMERICOID; typelen = -1; /* variable len */ @@ -417,10 +480,13 @@ make_const(Value *value, int location) break; case T_BitString: + /* arrange to report location if bit_in() fails */ + setup_parser_errposition_callback(&pcbstate, pstate, location); val = DirectFunctionCall3(bit_in, CStringGetDatum(strVal(value)), ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1)); + cancel_parser_errposition_callback(&pcbstate); typeid = BITOID; typelen = -1; typebyval = false; diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index f7eb825f5d..6accd96f0d 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.134 2008/08/28 23:09:48 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.135 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,20 +36,20 @@ bool add_missing_from; static RangeTblEntry *scanNameSpaceForRefname(ParseState *pstate, - const char *refname); -static RangeTblEntry *scanNameSpaceForRelid(ParseState *pstate, Oid relid); + const char *refname, int location); +static RangeTblEntry *scanNameSpaceForRelid(ParseState *pstate, Oid relid, + int location); static bool isLockedRel(ParseState *pstate, char *refname); static void expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, - bool include_dropped, + int location, bool include_dropped, List **colnames, List **colvars); static void expandTupleDesc(TupleDesc tupdesc, Alias *eref, int rtindex, int sublevels_up, - bool include_dropped, + int location, bool include_dropped, List **colnames, List **colvars); static int specialAttNum(const char *attname); -static void warnAutoRange(ParseState *pstate, RangeVar *relation, - int location); +static void warnAutoRange(ParseState *pstate, RangeVar *relation); /* @@ -77,6 +77,7 @@ RangeTblEntry * refnameRangeTblEntry(ParseState *pstate, const char *schemaname, const char *refname, + int location, int *sublevels_up) { Oid relId = InvalidOid; @@ -99,9 +100,9 @@ refnameRangeTblEntry(ParseState *pstate, RangeTblEntry *result; if (OidIsValid(relId)) - result = scanNameSpaceForRelid(pstate, relId); + result = scanNameSpaceForRelid(pstate, relId, location); else - result = scanNameSpaceForRefname(pstate, refname); + result = scanNameSpaceForRefname(pstate, refname, location); if (result) return result; @@ -122,7 +123,7 @@ refnameRangeTblEntry(ParseState *pstate, * if no match. Raise error if multiple matches. */ static RangeTblEntry * -scanNameSpaceForRefname(ParseState *pstate, const char *refname) +scanNameSpaceForRefname(ParseState *pstate, const char *refname, int location) { RangeTblEntry *result = NULL; ListCell *l; @@ -137,7 +138,8 @@ scanNameSpaceForRefname(ParseState *pstate, const char *refname) ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_ALIAS), errmsg("table reference \"%s\" is ambiguous", - refname))); + refname), + parser_errposition(pstate, location))); result = rte; } } @@ -154,7 +156,7 @@ scanNameSpaceForRefname(ParseState *pstate, const char *refname) * acts the way it does. */ static RangeTblEntry * -scanNameSpaceForRelid(ParseState *pstate, Oid relid) +scanNameSpaceForRelid(ParseState *pstate, Oid relid, int location) { RangeTblEntry *result = NULL; ListCell *l; @@ -172,7 +174,8 @@ scanNameSpaceForRelid(ParseState *pstate, Oid relid) ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_ALIAS), errmsg("table reference %u is ambiguous", - relid))); + relid), + parser_errposition(pstate, location))); result = rte; } } @@ -466,14 +469,15 @@ qualifiedNameToVar(ParseState *pstate, RangeTblEntry *rte; int sublevels_up; - rte = refnameRangeTblEntry(pstate, schemaname, refname, &sublevels_up); + rte = refnameRangeTblEntry(pstate, schemaname, refname, location, + &sublevels_up); if (rte == NULL) { if (!implicitRTEOK) return NULL; - rte = addImplicitRTE(pstate, makeRangeVar(schemaname, refname), - location); + rte = addImplicitRTE(pstate, + makeRangeVar(schemaname, refname, location)); } return scanRTEForColumn(pstate, rte, colname, location); @@ -607,6 +611,28 @@ buildScalarFunctionAlias(Node *funcexpr, char *funcname, eref->colnames = list_make1(makeString(eref->aliasname)); } +/* + * Open a table during parse analysis + * + * This is essentially just the same as heap_openrv(), except that it + * arranges to include the RangeVar's parse location in any resulting error. + * + * Note: properly, lockmode should be declared LOCKMODE not int, but that + * would require importing storage/lock.h into parse_relation.h. Since + * LOCKMODE is typedef'd as int anyway, that seems like overkill. + */ +Relation +parserOpenTable(ParseState *pstate, const RangeVar *relation, int lockmode) +{ + Relation rel; + ParseCallbackState pcbstate; + + setup_parser_errposition_callback(&pcbstate, pstate, relation->location); + rel = heap_openrv(relation, lockmode); + cancel_parser_errposition_callback(&pcbstate); + return rel; +} + /* * Add an entry for a relation to the pstate's range table (p_rtable). * @@ -638,7 +664,7 @@ addRangeTableEntry(ParseState *pstate, * depending on whether we're doing SELECT FOR UPDATE/SHARE. */ lockmode = isLockedRel(pstate, refname) ? RowShareLock : AccessShareLock; - rel = heap_openrv(relation, lockmode); + rel = parserOpenTable(pstate, relation, lockmode); rte->relid = RelationGetRelid(rel); /* @@ -859,14 +885,16 @@ addRangeTableEntryForFunction(ParseState *pstate, if (functypclass != TYPEFUNC_RECORD) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("a column definition list is only allowed for functions returning \"record\""))); + errmsg("a column definition list is only allowed for functions returning \"record\""), + parser_errposition(pstate, exprLocation(funcexpr)))); } else { if (functypclass == TYPEFUNC_RECORD) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("a column definition list is required for functions returning \"record\""))); + errmsg("a column definition list is required for functions returning \"record\""), + parser_errposition(pstate, exprLocation(funcexpr)))); } if (functypclass == TYPEFUNC_COMPOSITE) @@ -901,7 +929,8 @@ addRangeTableEntryForFunction(ParseState *pstate, ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("column \"%s\" cannot be declared SETOF", - attrname))); + attrname), + parser_errposition(pstate, n->typename->location))); attrtype = typenameTypeId(pstate, n->typename, &attrtypmod); eref->colnames = lappend(eref->colnames, makeString(attrname)); rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype); @@ -912,7 +941,8 @@ addRangeTableEntryForFunction(ParseState *pstate, ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("function \"%s\" in FROM has unsupported return type %s", - funcname, format_type_be(funcrettype)))); + funcname, format_type_be(funcrettype)), + parser_errposition(pstate, exprLocation(funcexpr)))); /*---------- * Flags: @@ -1107,9 +1137,9 @@ isLockedRel(ParseState *pstate, char *refname) foreach(l2, lc->lockedRels) { - char *rname = strVal(lfirst(l2)); + RangeVar *thisrel = (RangeVar *) lfirst(l2); - if (strcmp(refname, rname) == 0) + if (strcmp(refname, thisrel->relname) == 0) return true; } } @@ -1150,12 +1180,12 @@ addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, * a conflicting name. */ RangeTblEntry * -addImplicitRTE(ParseState *pstate, RangeVar *relation, int location) +addImplicitRTE(ParseState *pstate, RangeVar *relation) { RangeTblEntry *rte; /* issue warning or error as needed */ - warnAutoRange(pstate, relation, location); + warnAutoRange(pstate, relation); /* * Note that we set inFromCl true, so that the RTE will be listed @@ -1179,9 +1209,9 @@ addImplicitRTE(ParseState *pstate, RangeVar *relation, int location) * results. If include_dropped is TRUE then empty strings and NULL constants * (not Vars!) are returned for dropped columns. * - * rtindex and sublevels_up are the varno and varlevelsup values to use - * in the created Vars. Ordinarily rtindex should match the actual position - * of the RTE in its rangetable. + * rtindex, sublevels_up, and location are the varno, varlevelsup, and location + * values to use in the created Vars. Ordinarily rtindex should match the + * actual position of the RTE in its rangetable. * * The output lists go into *colnames and *colvars. * If only one of the two kinds of output list is needed, pass NULL for the @@ -1189,7 +1219,7 @@ addImplicitRTE(ParseState *pstate, RangeVar *relation, int location) */ void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, - bool include_dropped, + int location, bool include_dropped, List **colnames, List **colvars) { int varattno; @@ -1203,7 +1233,8 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, { case RTE_RELATION: /* Ordinary relation RTE */ - expandRelation(rte->relid, rte->eref, rtindex, sublevels_up, + expandRelation(rte->relid, rte->eref, + rtindex, sublevels_up, location, include_dropped, colnames, colvars); break; case RTE_SUBQUERY: @@ -1239,6 +1270,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, exprType((Node *) te->expr), exprTypmod((Node *) te->expr), sublevels_up); + varnode->location = location; *colvars = lappend(*colvars, varnode); } @@ -1259,7 +1291,8 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, { /* Composite data type, e.g. a table's row type */ Assert(tupdesc); - expandTupleDesc(tupdesc, rte->eref, rtindex, sublevels_up, + expandTupleDesc(tupdesc, rte->eref, + rtindex, sublevels_up, location, include_dropped, colnames, colvars); } else if (functypclass == TYPEFUNC_SCALAR) @@ -1276,6 +1309,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, varnode = makeVar(rtindex, 1, funcrettype, -1, sublevels_up); + varnode->location = location; *colvars = lappend(*colvars, varnode); } @@ -1302,6 +1336,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, attrtype, attrtypmod, sublevels_up); + varnode->location = location; *colvars = lappend(*colvars, varnode); } } @@ -1343,6 +1378,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, exprType(col), exprTypmod(col), sublevels_up); + varnode->location = location; *colvars = lappend(*colvars, varnode); } } @@ -1401,6 +1437,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, exprType(avar), exprTypmod(avar), sublevels_up); + varnode->location = location; *colvars = lappend(*colvars, varnode); } @@ -1417,14 +1454,15 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, */ static void expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, - bool include_dropped, + int location, bool include_dropped, List **colnames, List **colvars) { Relation rel; /* Get the tupledesc and turn it over to expandTupleDesc */ rel = relation_open(relid, AccessShareLock); - expandTupleDesc(rel->rd_att, eref, rtindex, sublevels_up, include_dropped, + expandTupleDesc(rel->rd_att, eref, rtindex, sublevels_up, + location, include_dropped, colnames, colvars); relation_close(rel, AccessShareLock); } @@ -1435,7 +1473,7 @@ expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, static void expandTupleDesc(TupleDesc tupdesc, Alias *eref, int rtindex, int sublevels_up, - bool include_dropped, + int location, bool include_dropped, List **colnames, List **colvars) { int maxattrs = tupdesc->natts; @@ -1482,6 +1520,7 @@ expandTupleDesc(TupleDesc tupdesc, Alias *eref, varnode = makeVar(rtindex, attr->attnum, attr->atttypid, attr->atttypmod, sublevels_up); + varnode->location = location; *colvars = lappend(*colvars, varnode); } @@ -1491,15 +1530,15 @@ expandTupleDesc(TupleDesc tupdesc, Alias *eref, /* * expandRelAttrs - * Workhorse for "*" expansion: produce a list of targetentries - * for the attributes of the rte + * for the attributes of the RTE * * As with expandRTE, rtindex/sublevels_up determine the varno/varlevelsup - * fields of the Vars produced. pstate->p_next_resno determines the resnos - * assigned to the TLEs. + * fields of the Vars produced, and location sets their location. + * pstate->p_next_resno determines the resnos assigned to the TLEs. */ List * expandRelAttrs(ParseState *pstate, RangeTblEntry *rte, - int rtindex, int sublevels_up) + int rtindex, int sublevels_up, int location) { List *names, *vars; @@ -1507,7 +1546,7 @@ expandRelAttrs(ParseState *pstate, RangeTblEntry *rte, *var; List *te_list = NIL; - expandRTE(rte, rtindex, sublevels_up, false, + expandRTE(rte, rtindex, sublevels_up, location, false, &names, &vars); forboth(name, names, var, vars) @@ -1523,7 +1562,7 @@ expandRelAttrs(ParseState *pstate, RangeTblEntry *rte, te_list = lappend(te_list, te); } - Assert(name == NULL && var == NULL); /* lists not the same length? */ + Assert(name == NULL && var == NULL); /* lists not the same length? */ return te_list; } @@ -1966,7 +2005,7 @@ attnumTypeId(Relation rd, int attid) * a warning. */ static void -warnAutoRange(ParseState *pstate, RangeVar *relation, int location) +warnAutoRange(ParseState *pstate, RangeVar *relation) { RangeTblEntry *rte; int sublevels_up; @@ -1991,6 +2030,7 @@ warnAutoRange(ParseState *pstate, RangeVar *relation, int location) if (rte && rte->alias && strcmp(rte->eref->aliasname, relation->relname) != 0 && refnameRangeTblEntry(pstate, NULL, rte->eref->aliasname, + relation->location, &sublevels_up) == rte) badAlias = rte->eref->aliasname; @@ -2006,7 +2046,7 @@ warnAutoRange(ParseState *pstate, RangeVar *relation, int location) badAlias) : errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.", rte->eref->aliasname)), - parser_errposition(pstate, location))); + parser_errposition(pstate, relation->location))); else ereport(ERROR, (errcode(ERRCODE_UNDEFINED_TABLE), @@ -2015,7 +2055,7 @@ warnAutoRange(ParseState *pstate, RangeVar *relation, int location) relation->relname) : errmsg("missing FROM-clause entry for table \"%s\"", relation->relname)), - parser_errposition(pstate, location))); + parser_errposition(pstate, relation->location))); } else { @@ -2033,6 +2073,6 @@ warnAutoRange(ParseState *pstate, RangeVar *relation, int location) (rte ? errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.", rte->eref->aliasname) : 0)), - parser_errposition(pstate, location))); + parser_errposition(pstate, relation->location))); } } diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index df87f3874c..20d91a142f 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.163 2008/08/30 01:39:14 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.164 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -45,7 +45,7 @@ static Node *transformAssignmentIndirection(ParseState *pstate, int location); static List *ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, bool targetlist); -static List *ExpandAllTables(ParseState *pstate); +static List *ExpandAllTables(ParseState *pstate, int location); static List *ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind, bool targetlist); static int FigureColnameInternal(Node *node, char **name); @@ -836,7 +836,7 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, * need not handle the targetlist==false case here. */ Assert(targetlist); - return ExpandAllTables(pstate); + return ExpandAllTables(pstate, cref->location); } else { @@ -889,11 +889,12 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, break; } - rte = refnameRangeTblEntry(pstate, schemaname, relname, + rte = refnameRangeTblEntry(pstate, schemaname, relname, cref->location, &sublevels_up); if (rte == NULL) - rte = addImplicitRTE(pstate, makeRangeVar(schemaname, relname), - cref->location); + rte = addImplicitRTE(pstate, + makeRangeVar(schemaname, relname, + cref->location)); /* Require read access --- see comments in setTargetTable() */ rte->requiredPerms |= ACL_SELECT; @@ -901,12 +902,13 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, rtindex = RTERangeTablePosn(pstate, rte, &sublevels_up); if (targetlist) - return expandRelAttrs(pstate, rte, rtindex, sublevels_up); + return expandRelAttrs(pstate, rte, rtindex, sublevels_up, + cref->location); else { List *vars; - expandRTE(rte, rtindex, sublevels_up, false, + expandRTE(rte, rtindex, sublevels_up, cref->location, false, NULL, &vars); return vars; } @@ -923,7 +925,7 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, * etc. */ static List * -ExpandAllTables(ParseState *pstate) +ExpandAllTables(ParseState *pstate, int location) { List *target = NIL; ListCell *l; @@ -932,7 +934,8 @@ ExpandAllTables(ParseState *pstate) if (!pstate->p_varnamespace) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("SELECT * with no tables specified is not valid"))); + errmsg("SELECT * with no tables specified is not valid"), + parser_errposition(pstate, location))); foreach(l, pstate->p_varnamespace) { @@ -943,7 +946,8 @@ ExpandAllTables(ParseState *pstate) rte->requiredPerms |= ACL_SELECT; target = list_concat(target, - expandRelAttrs(pstate, rte, rtindex, 0)); + expandRelAttrs(pstate, rte, rtindex, 0, + location)); } return target; @@ -1014,12 +1018,16 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind, ((Var *) expr)->varattno == InvalidAttrNumber) { Var *var = (Var *) expr; + Var *newvar; - fieldnode = (Node *) makeVar(var->varno, - i + 1, - att->atttypid, - att->atttypmod, - var->varlevelsup); + newvar = makeVar(var->varno, + i + 1, + att->atttypid, + att->atttypmod, + var->varlevelsup); + newvar->location = var->location; + + fieldnode = (Node *) newvar; } else { @@ -1088,7 +1096,7 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup) *lvar; int i; - expandRTE(rte, var->varno, 0, false, + expandRTE(rte, var->varno, 0, var->location, false, &names, &vars); tupleDesc = CreateTemplateTupleDesc(list_length(vars), false); diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c index 7f6f161745..960542029f 100644 --- a/src/backend/parser/parse_type.c +++ b/src/backend/parser/parse_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.98 2008/08/30 01:39:14 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.99 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -69,7 +69,7 @@ LookupTypeName(ParseState *pstate, const TypeName *typename, else if (typename->pct_type) { /* Handle %TYPE reference to type of an existing field */ - RangeVar *rel = makeRangeVar(NULL, NULL); + RangeVar *rel = makeRangeVar(NULL, NULL, typename->location); char *field = NULL; Oid relid; AttrNumber attnum; @@ -122,7 +122,7 @@ LookupTypeName(ParseState *pstate, const TypeName *typename, /* this construct should never have an array indicator */ Assert(typename->arrayBounds == NIL); - /* emit nuisance notice */ + /* emit nuisance notice (intentionally not errposition'd) */ ereport(NOTICE, (errmsg("type reference %s converted to %s", TypeNameToString(typename), @@ -247,6 +247,7 @@ typenameTypeMod(ParseState *pstate, const TypeName *typename, Type typ) int n; ListCell *l; ArrayType *arrtypmod; + ParseCallbackState pcbstate; /* Return prespecified typmod if no typmod expressions */ if (typename->typmods == NIL) @@ -321,9 +322,14 @@ typenameTypeMod(ParseState *pstate, const TypeName *typename, Type typ) arrtypmod = construct_array(datums, n, CSTRINGOID, -2, false, 'c'); + /* arrange to report location if type's typmodin function fails */ + setup_parser_errposition_callback(&pcbstate, pstate, typename->location); + result = DatumGetInt32(OidFunctionCall1(typmodin, PointerGetDatum(arrtypmod))); + cancel_parser_errposition_callback(&pcbstate); + pfree(datums); pfree(arrtypmod); diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index ae3ddeb202..4e0efe84bb 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -19,7 +19,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.16 2008/08/28 23:09:48 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.17 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -346,7 +346,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, * TABLE. */ seqstmt = makeNode(CreateSeqStmt); - seqstmt->sequence = makeRangeVar(snamespace, sname); + seqstmt->sequence = makeRangeVar(snamespace, sname, -1); seqstmt->options = NIL; cxt->blist = lappend(cxt->blist, seqstmt); @@ -357,7 +357,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, * done after this CREATE/ALTER TABLE. */ altseqstmt = makeNode(AlterSeqStmt); - altseqstmt->sequence = makeRangeVar(snamespace, sname); + altseqstmt->sequence = makeRangeVar(snamespace, sname, -1); attnamelist = list_make3(makeString(snamespace), makeString(cxt->relation->relname), makeString(column->colname)); @@ -548,7 +548,7 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, bool including_indexes = false; ListCell *elem; - relation = heap_openrv(inhRelation->relation, AccessShareLock); + relation = parserOpenTable(pstate, inhRelation->relation, AccessShareLock); if (relation->rd_rel->relkind != RELKIND_RELATION) ereport(ERROR, diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index 804bfe7127..dec0669d8b 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -24,7 +24,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.145 2008/08/29 13:02:32 petere Exp $ + * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.146 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -77,7 +77,8 @@ static void addlit(char *ytext, int yleng); static void addlitchar(unsigned char ychar); static char *litbufdup(void); -static int lexer_errposition(void); +#define lexer_errposition() scanner_errposition(yylloc) + static void check_escape_warning(void); static void check_string_escape_warning(unsigned char ychar); @@ -756,22 +757,27 @@ other . %% /* - * lexer_errposition - * Report a lexical-analysis-time cursor position, if possible. + * scanner_errposition + * Report a lexer or grammar error 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. + * Note that this can only be used for messages emitted during raw parsing + * (essentially, scan.l and gram.y), since it requires scanbuf to still be + * valid. */ -static int -lexer_errposition(void) +int +scanner_errposition(int location) { int pos; + Assert(scanbuf != NULL); /* else called from wrong place */ + if (location < 0) + return 0; /* no-op if location is unknown */ + /* Convert byte offset to character number */ - pos = pg_mbstrlen_with_len(scanbuf, yylloc) + 1; + pos = pg_mbstrlen_with_len(scanbuf, location) + 1; /* And pass it to the ereport mechanism */ return errposition(pos); } @@ -849,6 +855,7 @@ scanner_finish(void) { yy_delete_buffer(scanbufhandle); pfree(scanbuf); + scanbuf = NULL; } diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index f75c1888ab..c8652ff5f2 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.112 2008/08/28 23:09:48 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.113 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,8 +28,16 @@ typedef struct int sublevels_up; } contain_aggs_of_level_context; +typedef struct +{ + int agg_location; + int sublevels_up; +} locate_agg_of_level_context; + static bool contain_aggs_of_level_walker(Node *node, contain_aggs_of_level_context *context); +static bool locate_agg_of_level_walker(Node *node, + locate_agg_of_level_context *context); static bool checkExprHasSubLink_walker(Node *node, void *context); static Relids offset_relid_set(Relids relids, int offset); static Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid); @@ -37,7 +45,8 @@ static Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid); /* * checkExprHasAggs - - * Check if an expression contains an aggregate function call. + * Check if an expression contains an aggregate function call of the + * current query level. */ bool checkExprHasAggs(Node *node) @@ -101,6 +110,71 @@ contain_aggs_of_level_walker(Node *node, (void *) context); } +/* + * locate_agg_of_level - + * Find the parse location of any aggregate of the specified query level. + * + * Returns -1 if no such agg is in the querytree, or if they all have + * unknown parse location. (The former case is probably caller error, + * but we don't bother to distinguish it from the latter case.) + * + * Note: it might seem appropriate to merge this functionality into + * contain_aggs_of_level, but that would complicate that function's API. + * Currently, the only uses of this function are for error reporting, + * and so shaving cycles probably isn't very important. + */ +int +locate_agg_of_level(Node *node, int levelsup) +{ + locate_agg_of_level_context context; + + context.agg_location = -1; /* in case we find nothing */ + context.sublevels_up = levelsup; + + /* + * Must be prepared to start with a Query or a bare expression tree; if + * it's a Query, we don't want to increment sublevels_up. + */ + (void) query_or_expression_tree_walker(node, + locate_agg_of_level_walker, + (void *) &context, + 0); + + return context.agg_location; +} + +static bool +locate_agg_of_level_walker(Node *node, + locate_agg_of_level_context *context) +{ + if (node == NULL) + return false; + if (IsA(node, Aggref)) + { + if (((Aggref *) node)->agglevelsup == context->sublevels_up && + ((Aggref *) node)->location >= 0) + { + context->agg_location = ((Aggref *) node)->location; + return true; /* abort the tree traversal and return true */ + } + /* else fall through to examine argument */ + } + if (IsA(node, Query)) + { + /* Recurse into subselects */ + bool result; + + context->sublevels_up++; + result = query_tree_walker((Query *) node, + locate_agg_of_level_walker, + (void *) context, 0); + context->sublevels_up--; + return result; + } + return expression_tree_walker(node, locate_agg_of_level_walker, + (void *) context); +} + /* * checkExprHasSubLink - * Check if an expression contains a SubLink. @@ -980,7 +1054,7 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context) * this is a JOIN), then omit dropped columns. */ expandRTE(context->target_rte, - this_varno, this_varlevelsup, + this_varno, this_varlevelsup, var->location, (var->vartype != RECORDOID), NULL, &fields); /* Adjust the generated per-field Vars... */ diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 2f9078c2fb..b867df5581 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.297 2008/08/30 01:39:14 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.298 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -801,7 +801,7 @@ ProcessUtility(Node *parsetree, { NotifyStmt *stmt = (NotifyStmt *) parsetree; - Async_Notify(stmt->relation->relname); + Async_Notify(stmt->conditionname); } break; @@ -809,7 +809,7 @@ ProcessUtility(Node *parsetree, { ListenStmt *stmt = (ListenStmt *) parsetree; - Async_Listen(stmt->relation->relname); + Async_Listen(stmt->conditionname); } break; @@ -817,8 +817,8 @@ ProcessUtility(Node *parsetree, { UnlistenStmt *stmt = (UnlistenStmt *) parsetree; - if (stmt->relation) - Async_Unlisten(stmt->relation->relname); + if (stmt->conditionname) + Async_Unlisten(stmt->conditionname); else Async_UnlistenAll(); } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index bad6fcac69..66bbaaaa68 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.281 2008/08/25 22:42:34 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.282 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2713,8 +2713,7 @@ get_utility_query_def(Query *query, deparse_context *context) appendContextKeyword(context, "", 0, PRETTYINDENT_STD, 1); appendStringInfo(buf, "NOTIFY %s", - quote_qualified_identifier(stmt->relation->schemaname, - stmt->relation->relname)); + quote_identifier(stmt->conditionname)); } else { diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 46b7853e50..d2315fb1f6 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -42,7 +42,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.205 2008/07/09 15:56:49 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.206 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -879,6 +879,23 @@ internalerrquery(const char *query) return 0; /* return value does not matter */ } +/* + * geterrcode --- return the currently set SQLSTATE error code + * + * This is only intended for use in error callback subroutines, since there + * is no other place outside elog.c where the concept is meaningful. + */ +int +geterrcode(void) +{ + ErrorData *edata = &errordata[errordata_stack_depth]; + + /* we don't bother incrementing recursion_depth */ + CHECK_STACK_DEPTH(); + + return edata->sqlerrcode; +} + /* * geterrposition --- return the currently set error position (0 if none) * diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 8e287a80db..ecf1004838 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.481 2008/08/28 23:09:48 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.482 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200808281 +#define CATALOG_VERSION_NO 200808311 #endif diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h index d8ffa44224..d4e58cfe5f 100644 --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.62 2008/08/28 23:09:48 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.63 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -56,7 +56,7 @@ extern Alias *makeAlias(const char *aliasname, List *colnames); extern RelabelType *makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, CoercionForm rformat); -extern RangeVar *makeRangeVar(char *schemaname, char *relname); +extern RangeVar *makeRangeVar(char *schemaname, char *relname, int location); extern TypeName *makeTypeName(char *typnam); extern TypeName *makeTypeNameFromNameList(List *names); diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 7eea317589..2a4f6f1421 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -13,7 +13,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.373 2008/08/30 01:39:14 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.374 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -358,10 +358,11 @@ typedef struct ResTarget typedef struct SortBy { NodeTag type; - SortByDir sortby_dir; /* ASC/DESC/USING */ + Node *node; /* expression to sort on */ + SortByDir sortby_dir; /* ASC/DESC/USING/default */ SortByNulls sortby_nulls; /* NULLS FIRST/LAST */ List *useOp; /* name of op to use, if SORTBY_USING */ - Node *node; /* expression to sort on */ + int location; /* operator location, or -1 if none/unknown */ } SortBy; /* @@ -466,7 +467,9 @@ typedef struct DefElem * LockingClause - raw representation of FOR UPDATE/SHARE options * * Note: lockedRels == NIL means "all relations in query". Otherwise it - * is a list of String nodes giving relation eref names. + * is a list of RangeVar nodes. (We use RangeVar mainly because it carries + * a location field --- currently, parse analysis insists on unqualified + * names in LockingClause.) */ typedef struct LockingClause { @@ -1742,7 +1745,7 @@ typedef struct RuleStmt typedef struct NotifyStmt { NodeTag type; - RangeVar *relation; /* qualified name to notify */ + char *conditionname; /* condition name to notify */ } NotifyStmt; /* ---------------------- @@ -1752,7 +1755,7 @@ typedef struct NotifyStmt typedef struct ListenStmt { NodeTag type; - RangeVar *relation; /* name to listen on */ + char *conditionname; /* condition name to listen on */ } ListenStmt; /* ---------------------- @@ -1762,7 +1765,7 @@ typedef struct ListenStmt typedef struct UnlistenStmt { NodeTag type; - RangeVar *relation; /* name to unlisten on, or NULL for all */ + char *conditionname; /* name to unlisten on, or NULL for all */ } UnlistenStmt; /* ---------------------- diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index e4de091a75..e144251dd1 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.140 2008/08/28 23:09:48 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.141 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -76,6 +76,7 @@ typedef struct RangeVar * on children? */ bool istemp; /* is this a temp relation/sequence? */ Alias *alias; /* table alias & optional column aliases */ + int location; /* token location, or -1 if unknown */ } RangeVar; /* diff --git a/src/include/optimizer/var.h b/src/include/optimizer/var.h index b0980b5e7d..4a8f84e553 100644 --- a/src/include/optimizer/var.h +++ b/src/include/optimizer/var.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/var.h,v 1.37 2008/01/01 19:45:58 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/var.h,v 1.38 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,11 +19,10 @@ extern Relids pull_varnos(Node *node); extern void pull_varattnos(Node *node, Bitmapset **varattnos); -extern bool contain_var_reference(Node *node, int varno, int varattno, - int levelsup); extern bool contain_var_clause(Node *node); extern bool contain_vars_of_level(Node *node, int levelsup); -extern bool contain_vars_above_level(Node *node, int levelsup); +extern int locate_var_of_level(Node *node, int levelsup); +extern int locate_var_of_relation(Node *node, int relid, int levelsup); extern int find_minimum_var_level(Node *node); extern List *pull_var_clause(Node *node, bool includeUpperVars); extern Node *flatten_join_alias_vars(PlannerInfo *root, Node *node); diff --git a/src/include/parser/gramparse.h b/src/include/parser/gramparse.h index 6bb87c6751..e99f0017cb 100644 --- a/src/include/parser/gramparse.h +++ b/src/include/parser/gramparse.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.41 2008/04/04 11:47:19 mha Exp $ + * $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.42 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -47,6 +47,7 @@ extern int filtered_base_yylex(void); extern void scanner_init(const char *str); extern void scanner_finish(void); extern int base_yylex(void); +extern int scanner_errposition(int location); extern void base_yyerror(const char *message); /* from gram.y */ diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index fa6b14d4d3..460655d3b1 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.55 2008/08/28 23:09:48 tgl Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.56 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -82,10 +82,23 @@ typedef struct ParseState RangeTblEntry *p_target_rangetblentry; } ParseState; +/* Support for parser_errposition_callback function */ +typedef struct ParseCallbackState +{ + ParseState *pstate; + int location; + ErrorContextCallback errcontext; +} ParseCallbackState; + + extern ParseState *make_parsestate(ParseState *parentParseState); extern void free_parsestate(ParseState *pstate); extern int parser_errposition(ParseState *pstate, int location); +extern void setup_parser_errposition_callback(ParseCallbackState *pcbstate, + ParseState *pstate, int location); +extern void cancel_parser_errposition_callback(ParseCallbackState *pcbstate); + extern Var *make_var(ParseState *pstate, RangeTblEntry *rte, int attrno, int location); extern Oid transformArrayType(Oid arrayType); @@ -96,6 +109,6 @@ extern ArrayRef *transformArraySubscripts(ParseState *pstate, int32 elementTypMod, List *indirection, Node *assignFrom); -extern Const *make_const(Value *value, int location); +extern Const *make_const(ParseState *pstate, Value *value, int location); #endif /* PARSE_NODE_H */ diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h index 04889541e7..1c4e1b6b8e 100644 --- a/src/include/parser/parse_relation.h +++ b/src/include/parser/parse_relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.57 2008/01/01 19:45:58 momjian Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.58 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,7 @@ extern bool add_missing_from; extern RangeTblEntry *refnameRangeTblEntry(ParseState *pstate, const char *schemaname, const char *refname, + int location, int *sublevels_up); extern void checkNameSpaceConflicts(ParseState *pstate, List *namespace1, List *namespace2); @@ -40,6 +41,8 @@ extern Node *qualifiedNameToVar(ParseState *pstate, char *colname, bool implicitRTEOK, int location); +extern Relation parserOpenTable(ParseState *pstate, const RangeVar *relation, + int lockmode); extern RangeTblEntry *addRangeTableEntry(ParseState *pstate, RangeVar *relation, Alias *alias, @@ -72,13 +75,12 @@ extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate, extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace); -extern RangeTblEntry *addImplicitRTE(ParseState *pstate, RangeVar *relation, - int location); +extern RangeTblEntry *addImplicitRTE(ParseState *pstate, RangeVar *relation); extern void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, - bool include_dropped, + int location, bool include_dropped, List **colnames, List **colvars); extern List *expandRelAttrs(ParseState *pstate, RangeTblEntry *rte, - int rtindex, int sublevels_up); + int rtindex, int sublevels_up, int location); extern int attnameAttNum(Relation rd, const char *attname, bool sysColOK); extern Name attnumAttName(Relation rd, int attid); extern Oid attnumTypeId(Relation rd, int attid); diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h index a870ce889b..50b4443de0 100644 --- a/src/include/rewrite/rewriteManip.h +++ b/src/include/rewrite/rewriteManip.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.46 2008/08/22 00:16:04 tgl Exp $ + * $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.47 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,6 +36,7 @@ extern void AddQual(Query *parsetree, Node *qual); extern void AddInvertedQual(Query *parsetree, Node *qual); extern bool contain_aggs_of_level(Node *node, int levelsup); +extern int locate_agg_of_level(Node *node, int levelsup); extern bool checkExprHasAggs(Node *node); extern bool checkExprHasSubLink(Node *node); diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index b7777e8f5f..034fd420b5 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.93 2008/04/16 23:59:40 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.94 2008/09/01 20:42:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -151,6 +151,7 @@ extern int errposition(int cursorpos); extern int internalerrposition(int cursorpos); extern int internalerrquery(const char *query); +extern int geterrcode(void); extern int geterrposition(void); extern int getinternalerrposition(void); diff --git a/src/pl/plperl/expected/plperl.out b/src/pl/plperl/expected/plperl.out index e39d117424..9b3e716814 100644 --- a/src/pl/plperl/expected/plperl.out +++ b/src/pl/plperl/expected/plperl.out @@ -137,6 +137,8 @@ SELECT perl_record(); SELECT * FROM perl_record(); ERROR: a column definition list is required for functions returning "record" +LINE 1: SELECT * FROM perl_record(); + ^ SELECT * FROM perl_record() AS (f1 integer, f2 text, f3 text); f1 | f2 | f3 ----+----+---- @@ -150,6 +152,8 @@ SELECT perl_record(); ERROR: function returning record called in context that cannot accept type record SELECT * FROM perl_record(); ERROR: a column definition list is required for functions returning "record" +LINE 1: SELECT * FROM perl_record(); + ^ SELECT * FROM perl_record() AS (f1 integer, f2 text, f3 text); f1 | f2 | f3 ----+-------+------- @@ -163,6 +167,8 @@ SELECT perl_record_set(); ERROR: set-valued function called in context that cannot accept a set SELECT * FROM perl_record_set(); ERROR: a column definition list is required for functions returning "record" +LINE 1: SELECT * FROM perl_record_set(); + ^ SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text); f1 | f2 | f3 ----+----+---- @@ -179,6 +185,8 @@ SELECT perl_record_set(); ERROR: set-valued function called in context that cannot accept a set SELECT * FROM perl_record_set(); ERROR: a column definition list is required for functions returning "record" +LINE 1: SELECT * FROM perl_record_set(); + ^ SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text); ERROR: setof-composite-returning Perl function must call return_next with reference to hash CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$ @@ -192,6 +200,8 @@ SELECT perl_record_set(); ERROR: set-valued function called in context that cannot accept a set SELECT * FROM perl_record_set(); ERROR: a column definition list is required for functions returning "record" +LINE 1: SELECT * FROM perl_record_set(); + ^ SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text); f1 | f2 | f3 ----+-------+------------ diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index 43664459ab..1355c827d1 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.129 2008/08/29 13:02:33 petere Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.130 2008/09/01 20:42:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1272,7 +1272,7 @@ plpgsql_parse_tripwordtype(char *word) word[i] = '%'; pfree(cp[3]); - relvar = makeRangeVar(cp[0], cp[1]); + relvar = makeRangeVar(cp[0], cp[1], -1); classOid = RangeVarGetRelid(relvar, true); if (!OidIsValid(classOid)) goto done; @@ -1393,7 +1393,7 @@ plpgsql_parse_dblwordrowtype(char *word) word[i] = '%'; /* Lookup the relation */ - relvar = makeRangeVar(cp[0], cp[1]); + relvar = makeRangeVar(cp[0], cp[1], -1); classOid = RangeVarGetRelid(relvar, true); if (!OidIsValid(classOid)) ereport(ERROR, diff --git a/src/test/regress/expected/abstime.out b/src/test/regress/expected/abstime.out index 309fb1d671..a04f091666 100644 --- a/src/test/regress/expected/abstime.out +++ b/src/test/regress/expected/abstime.out @@ -29,12 +29,18 @@ INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'May 10, 1947 23:59:12'); -- what happens if we specify slightly misformatted abstime? INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 35, 1946 10:00:00'); ERROR: date/time field value out of range: "Feb 35, 1946 10:00:00" +LINE 1: INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 35, 1946 10:00:00'... + ^ HINT: Perhaps you need a different "datestyle" setting. INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 28, 1984 25:08:10'); ERROR: date/time field value out of range: "Feb 28, 1984 25:08:10" +LINE 1: INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 28, 1984 25:08:10'... + ^ -- badly formatted abstimes: these should result in invalid abstimes INSERT INTO ABSTIME_TBL (f1) VALUES ('bad date format'); ERROR: invalid input syntax for type abstime: "bad date format" +LINE 1: INSERT INTO ABSTIME_TBL (f1) VALUES ('bad date format'); + ^ INSERT INTO ABSTIME_TBL (f1) VALUES ('Jun 10, 1843'); -- test abstime operators SELECT '' AS eight, * FROM ABSTIME_TBL; diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index ae65314166..46f6f18ed0 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -293,6 +293,8 @@ group by ten having exists (select 1 from onek b where sum(distinct a.four + b.four) = b.four); ERROR: aggregates not allowed in WHERE clause +LINE 4: where sum(distinct a.four + b.four) = b.four)... + ^ -- -- test for bitwise integer aggregates -- diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index daf9482c4a..15179540a2 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -112,6 +112,8 @@ SELECT * FROM tmp_new; ALTER TABLE tmp RENAME TO tmp_new2; SELECT * FROM tmp; -- should fail ERROR: relation "tmp" does not exist +LINE 1: SELECT * FROM tmp; + ^ SELECT * FROM tmp_new; tmptable ---------- @@ -780,8 +782,12 @@ LINE 1: update atacc1 set b = 2 where "........pg.dropped.1........"... -- INSERTs insert into atacc1 values (10, 11, 12, 13); ERROR: INSERT has more expressions than target columns +LINE 1: insert into atacc1 values (10, 11, 12, 13); + ^ insert into atacc1 values (default, 11, 12, 13); ERROR: INSERT has more expressions than target columns +LINE 1: insert into atacc1 values (default, 11, 12, 13); + ^ insert into atacc1 values (11, 12, 13); insert into atacc1 (a) values (10); ERROR: column "a" of relation "atacc1" does not exist diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out index 5103d6868d..bcf5280b14 100644 --- a/src/test/regress/expected/arrays.out +++ b/src/test/regress/expected/arrays.out @@ -775,16 +775,28 @@ select 'foo' ilike all (array['F%', '%O']); -- t -- none of the following should be accepted select '{{1,{2}},{2,3}}'::text[]; ERROR: malformed array literal: "{{1,{2}},{2,3}}" +LINE 1: select '{{1,{2}},{2,3}}'::text[]; + ^ select '{{},{}}'::text[]; ERROR: malformed array literal: "{{},{}}" +LINE 1: select '{{},{}}'::text[]; + ^ select E'{{1,2},\\{2,3}}'::text[]; ERROR: malformed array literal: "{{1,2},\{2,3}}" +LINE 1: select E'{{1,2},\\{2,3}}'::text[]; + ^ select '{{"1 2" x},{3}}'::text[]; ERROR: malformed array literal: "{{"1 2" x},{3}}" +LINE 1: select '{{"1 2" x},{3}}'::text[]; + ^ select '{}}'::text[]; ERROR: malformed array literal: "{}}" +LINE 1: select '{}}'::text[]; + ^ select '{ }}'::text[]; ERROR: malformed array literal: "{ }}" +LINE 1: select '{ }}'::text[]; + ^ select array[]; ERROR: cannot determine type of empty array LINE 1: select array[]; diff --git a/src/test/regress/expected/boolean.out b/src/test/regress/expected/boolean.out index 511987e8b9..e66f33702b 100644 --- a/src/test/regress/expected/boolean.out +++ b/src/test/regress/expected/boolean.out @@ -137,6 +137,8 @@ INSERT INTO BOOLTBL2 (f1) VALUES (bool 'FALSE'); INSERT INTO BOOLTBL2 (f1) VALUES (bool 'XXX'); ERROR: invalid input syntax for type boolean: "XXX" +LINE 2: VALUES (bool 'XXX'); + ^ -- BOOLTBL2 should be full of false's at this point SELECT '' AS f_4, BOOLTBL2.* FROM BOOLTBL2; f_4 | f1 diff --git a/src/test/regress/expected/box.out b/src/test/regress/expected/box.out index cd2179f092..2a94e33465 100644 --- a/src/test/regress/expected/box.out +++ b/src/test/regress/expected/box.out @@ -25,8 +25,12 @@ INSERT INTO BOX_TBL (f1) VALUES ('(3.0, 3.0,3.0,3.0)'); -- badly formatted box inputs INSERT INTO BOX_TBL (f1) VALUES ('(2.3, 4.5)'); ERROR: invalid input syntax for type box: "(2.3, 4.5)" +LINE 1: INSERT INTO BOX_TBL (f1) VALUES ('(2.3, 4.5)'); + ^ INSERT INTO BOX_TBL (f1) VALUES ('asdfasdf(ad'); ERROR: invalid input syntax for type box: "asdfasdf(ad" +LINE 1: INSERT INTO BOX_TBL (f1) VALUES ('asdfasdf(ad'); + ^ SELECT '' AS four, * FROM BOX_TBL; four | f1 ------+--------------------- diff --git a/src/test/regress/expected/circle.out b/src/test/regress/expected/circle.out index a63e348aca..9ba4a0495d 100644 --- a/src/test/regress/expected/circle.out +++ b/src/test/regress/expected/circle.out @@ -11,10 +11,16 @@ INSERT INTO CIRCLE_TBL VALUES ('<(100,1),115>'); -- bad values INSERT INTO CIRCLE_TBL VALUES ('<(-100,0),-100>'); ERROR: invalid input syntax for type circle: "<(-100,0),-100>" +LINE 1: INSERT INTO CIRCLE_TBL VALUES ('<(-100,0),-100>'); + ^ INSERT INTO CIRCLE_TBL VALUES ('1abc,3,5'); ERROR: invalid input syntax for type circle: "1abc,3,5" +LINE 1: INSERT INTO CIRCLE_TBL VALUES ('1abc,3,5'); + ^ INSERT INTO CIRCLE_TBL VALUES ('(3,(1,2),3)'); ERROR: invalid input syntax for type circle: "(3,(1,2),3)" +LINE 1: INSERT INTO CIRCLE_TBL VALUES ('(3,(1,2),3)'); + ^ SELECT * FROM CIRCLE_TBL; f1 ---------------- diff --git a/src/test/regress/expected/create_type.out b/src/test/regress/expected/create_type.out index 72556a88f8..1d3a22612d 100644 --- a/src/test/regress/expected/create_type.out +++ b/src/test/regress/expected/create_type.out @@ -107,6 +107,8 @@ DROP TABLE default_test; -- (we have borrowed numeric's typmod functions) CREATE TEMP TABLE mytab (foo widget(42,13,7)); -- should fail ERROR: invalid NUMERIC type modifier +LINE 1: CREATE TEMP TABLE mytab (foo widget(42,13,7)); + ^ CREATE TEMP TABLE mytab (foo widget(42,13)); SELECT format_type(atttypid,atttypmod) FROM pg_attribute WHERE attrelid = 'mytab'::regclass AND attnum > 0; diff --git a/src/test/regress/expected/date.out b/src/test/regress/expected/date.out index 24018de560..a4acf3e9c9 100644 --- a/src/test/regress/expected/date.out +++ b/src/test/regress/expected/date.out @@ -11,6 +11,8 @@ INSERT INTO DATE_TBL VALUES ('1996-03-02'); INSERT INTO DATE_TBL VALUES ('1997-02-28'); INSERT INTO DATE_TBL VALUES ('1997-02-29'); ERROR: date/time field value out of range: "1997-02-29" +LINE 1: INSERT INTO DATE_TBL VALUES ('1997-02-29'); + ^ INSERT INTO DATE_TBL VALUES ('1997-03-01'); INSERT INTO DATE_TBL VALUES ('1997-03-02'); INSERT INTO DATE_TBL VALUES ('2000-04-01'); @@ -87,12 +89,18 @@ SELECT date '1999-01-18'; SELECT date '1/8/1999'; ERROR: date/time field value out of range: "1/8/1999" +LINE 1: SELECT date '1/8/1999'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '1/18/1999'; ERROR: date/time field value out of range: "1/18/1999" +LINE 1: SELECT date '1/18/1999'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '18/1/1999'; ERROR: date/time field value out of range: "18/1/1999" +LINE 1: SELECT date '18/1/1999'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '01/02/03'; date @@ -126,6 +134,8 @@ SELECT date 'J2451187'; SELECT date 'January 8, 99 BC'; ERROR: date/time field value out of range: "January 8, 99 BC" +LINE 1: SELECT date 'January 8, 99 BC'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '99-Jan-08'; date @@ -141,6 +151,8 @@ SELECT date '1999-Jan-08'; SELECT date '08-Jan-99'; ERROR: date/time field value out of range: "08-Jan-99" +LINE 1: SELECT date '08-Jan-99'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '08-Jan-1999'; date @@ -150,6 +162,8 @@ SELECT date '08-Jan-1999'; SELECT date 'Jan-08-99'; ERROR: date/time field value out of range: "Jan-08-99" +LINE 1: SELECT date 'Jan-08-99'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date 'Jan-08-1999'; date @@ -159,8 +173,12 @@ SELECT date 'Jan-08-1999'; SELECT date '99-08-Jan'; ERROR: invalid input syntax for type date: "99-08-Jan" +LINE 1: SELECT date '99-08-Jan'; + ^ SELECT date '1999-08-Jan'; ERROR: invalid input syntax for type date: "1999-08-Jan" +LINE 1: SELECT date '1999-08-Jan'; + ^ SELECT date '99 Jan 08'; date ------------ @@ -175,6 +193,8 @@ SELECT date '1999 Jan 08'; SELECT date '08 Jan 99'; ERROR: date/time field value out of range: "08 Jan 99" +LINE 1: SELECT date '08 Jan 99'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '08 Jan 1999'; date @@ -184,6 +204,8 @@ SELECT date '08 Jan 1999'; SELECT date 'Jan 08 99'; ERROR: date/time field value out of range: "Jan 08 99" +LINE 1: SELECT date 'Jan 08 99'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date 'Jan 08 1999'; date @@ -217,15 +239,23 @@ SELECT date '1999-01-08'; SELECT date '08-01-99'; ERROR: date/time field value out of range: "08-01-99" +LINE 1: SELECT date '08-01-99'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '08-01-1999'; ERROR: date/time field value out of range: "08-01-1999" +LINE 1: SELECT date '08-01-1999'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '01-08-99'; ERROR: date/time field value out of range: "01-08-99" +LINE 1: SELECT date '01-08-99'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '01-08-1999'; ERROR: date/time field value out of range: "01-08-1999" +LINE 1: SELECT date '01-08-1999'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '99-08-01'; date @@ -253,15 +283,23 @@ SELECT date '1999 01 08'; SELECT date '08 01 99'; ERROR: date/time field value out of range: "08 01 99" +LINE 1: SELECT date '08 01 99'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '08 01 1999'; ERROR: date/time field value out of range: "08 01 1999" +LINE 1: SELECT date '08 01 1999'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '01 08 99'; ERROR: date/time field value out of range: "01 08 99" +LINE 1: SELECT date '01 08 99'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '01 08 1999'; ERROR: date/time field value out of range: "01 08 1999" +LINE 1: SELECT date '01 08 1999'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '99 08 01'; date @@ -302,6 +340,8 @@ SELECT date '1/8/1999'; SELECT date '1/18/1999'; ERROR: date/time field value out of range: "1/18/1999" +LINE 1: SELECT date '1/18/1999'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '18/1/1999'; date @@ -347,6 +387,8 @@ SELECT date 'January 8, 99 BC'; SELECT date '99-Jan-08'; ERROR: date/time field value out of range: "99-Jan-08" +LINE 1: SELECT date '99-Jan-08'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '1999-Jan-08'; date @@ -380,10 +422,16 @@ SELECT date 'Jan-08-1999'; SELECT date '99-08-Jan'; ERROR: invalid input syntax for type date: "99-08-Jan" +LINE 1: SELECT date '99-08-Jan'; + ^ SELECT date '1999-08-Jan'; ERROR: invalid input syntax for type date: "1999-08-Jan" +LINE 1: SELECT date '1999-08-Jan'; + ^ SELECT date '99 Jan 08'; ERROR: date/time field value out of range: "99 Jan 08" +LINE 1: SELECT date '99 Jan 08'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '1999 Jan 08'; date @@ -417,6 +465,8 @@ SELECT date 'Jan 08 1999'; SELECT date '99 08 Jan'; ERROR: invalid input syntax for type date: "99 08 Jan" +LINE 1: SELECT date '99 08 Jan'; + ^ SELECT date '1999 08 Jan'; date ------------ @@ -425,6 +475,8 @@ SELECT date '1999 08 Jan'; SELECT date '99-01-08'; ERROR: date/time field value out of range: "99-01-08" +LINE 1: SELECT date '99-01-08'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '1999-01-08'; date @@ -458,6 +510,8 @@ SELECT date '01-08-1999'; SELECT date '99-08-01'; ERROR: date/time field value out of range: "99-08-01" +LINE 1: SELECT date '99-08-01'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '1999-08-01'; date @@ -467,6 +521,8 @@ SELECT date '1999-08-01'; SELECT date '99 01 08'; ERROR: date/time field value out of range: "99 01 08" +LINE 1: SELECT date '99 01 08'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '1999 01 08'; date @@ -500,6 +556,8 @@ SELECT date '01 08 1999'; SELECT date '99 08 01'; ERROR: date/time field value out of range: "99 08 01" +LINE 1: SELECT date '99 08 01'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '1999 08 01'; date @@ -540,6 +598,8 @@ SELECT date '1/18/1999'; SELECT date '18/1/1999'; ERROR: date/time field value out of range: "18/1/1999" +LINE 1: SELECT date '18/1/1999'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '01/02/03'; date @@ -579,6 +639,8 @@ SELECT date 'January 8, 99 BC'; SELECT date '99-Jan-08'; ERROR: date/time field value out of range: "99-Jan-08" +LINE 1: SELECT date '99-Jan-08'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '1999-Jan-08'; date @@ -612,10 +674,16 @@ SELECT date 'Jan-08-1999'; SELECT date '99-08-Jan'; ERROR: invalid input syntax for type date: "99-08-Jan" +LINE 1: SELECT date '99-08-Jan'; + ^ SELECT date '1999-08-Jan'; ERROR: invalid input syntax for type date: "1999-08-Jan" +LINE 1: SELECT date '1999-08-Jan'; + ^ SELECT date '99 Jan 08'; ERROR: invalid input syntax for type date: "99 Jan 08" +LINE 1: SELECT date '99 Jan 08'; + ^ SELECT date '1999 Jan 08'; date ------------ @@ -648,6 +716,8 @@ SELECT date 'Jan 08 1999'; SELECT date '99 08 Jan'; ERROR: invalid input syntax for type date: "99 08 Jan" +LINE 1: SELECT date '99 08 Jan'; + ^ SELECT date '1999 08 Jan'; date ------------ @@ -656,6 +726,8 @@ SELECT date '1999 08 Jan'; SELECT date '99-01-08'; ERROR: date/time field value out of range: "99-01-08" +LINE 1: SELECT date '99-01-08'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '1999-01-08'; date @@ -689,6 +761,8 @@ SELECT date '01-08-1999'; SELECT date '99-08-01'; ERROR: date/time field value out of range: "99-08-01" +LINE 1: SELECT date '99-08-01'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '1999-08-01'; date @@ -698,6 +772,8 @@ SELECT date '1999-08-01'; SELECT date '99 01 08'; ERROR: date/time field value out of range: "99 01 08" +LINE 1: SELECT date '99 01 08'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '1999 01 08'; date @@ -731,6 +807,8 @@ SELECT date '01 08 1999'; SELECT date '99 08 01'; ERROR: date/time field value out of range: "99 08 01" +LINE 1: SELECT date '99 08 01'; + ^ HINT: Perhaps you need a different "datestyle" setting. SELECT date '1999 08 01'; date diff --git a/src/test/regress/expected/enum.out b/src/test/regress/expected/enum.out index 4fa2d07ada..56240c0e7a 100644 --- a/src/test/regress/expected/enum.out +++ b/src/test/regress/expected/enum.out @@ -22,6 +22,8 @@ SELECT 'red'::rainbow; SELECT 'mauve'::rainbow; ERROR: invalid input value for enum rainbow: "mauve" +LINE 1: SELECT 'mauve'::rainbow; + ^ -- -- Basic table creation, row selection -- diff --git a/src/test/regress/expected/errors.out b/src/test/regress/expected/errors.out index 257722e94a..55822e0b9b 100644 --- a/src/test/regress/expected/errors.out +++ b/src/test/regress/expected/errors.out @@ -25,6 +25,8 @@ LINE 1: select; -- no such relation select * from nonesuch; ERROR: relation "nonesuch" does not exist +LINE 1: select * from nonesuch; + ^ -- missing target list select from pg_database; ERROR: syntax error at or near "from" @@ -66,6 +68,8 @@ LINE 1: delete from; -- no such relation delete from nonesuch; ERROR: relation "nonesuch" does not exist +LINE 1: delete from nonesuch; + ^ -- -- DROP @@ -245,6 +249,8 @@ LINE 1: drop operator === (); -- no such operator drop operator === (int4); ERROR: missing argument +LINE 1: drop operator === (int4); + ^ HINT: Use NONE to denote the missing argument of a unary operator. -- no such operator by that name drop operator === (int4, int4); @@ -252,6 +258,8 @@ ERROR: operator does not exist: integer === integer -- no such type1 drop operator = (nonesuch); ERROR: missing argument +LINE 1: drop operator = (nonesuch); + ^ HINT: Use NONE to denote the missing argument of a unary operator. -- no such type1 drop operator = ( , int4); diff --git a/src/test/regress/expected/float4-exp-three-digits.out b/src/test/regress/expected/float4-exp-three-digits.out index fd8d0b319e..b849910151 100644 --- a/src/test/regress/expected/float4-exp-three-digits.out +++ b/src/test/regress/expected/float4-exp-three-digits.out @@ -10,29 +10,53 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20'); -- test for over and under flow INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70'); ERROR: value out of range: overflow +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70'); ERROR: value out of range: overflow +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70'); ERROR: value out of range: underflow +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70'); ERROR: value out of range: underflow +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70'); + ^ -- bad input INSERT INTO FLOAT4_TBL(f1) VALUES (''); ERROR: invalid input syntax for type real: "" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES (''); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES (' '); ERROR: invalid input syntax for type real: " " +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES (' '); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz'); ERROR: invalid input syntax for type real: "xyz" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0'); ERROR: invalid input syntax for type real: "5.0.0" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0'); ERROR: invalid input syntax for type real: "5 . 0" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('5. 0'); ERROR: invalid input syntax for type real: "5. 0" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5. 0'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES (' - 3.0'); ERROR: invalid input syntax for type real: " - 3.0" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES (' - 3.0'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5'); ERROR: invalid input syntax for type real: "123 5" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5'); + ^ -- special inputs SELECT 'NaN'::float4; float4 @@ -67,10 +91,16 @@ SELECT ' -INFINiTY '::float4; -- bad special inputs SELECT 'N A N'::float4; ERROR: invalid input syntax for type real: "N A N" +LINE 1: SELECT 'N A N'::float4; + ^ SELECT 'NaN x'::float4; ERROR: invalid input syntax for type real: "NaN x" +LINE 1: SELECT 'NaN x'::float4; + ^ SELECT ' INFINITY x'::float4; ERROR: invalid input syntax for type real: " INFINITY x" +LINE 1: SELECT ' INFINITY x'::float4; + ^ SELECT 'Infinity'::float4 + 100.0; ?column? ---------- diff --git a/src/test/regress/expected/float4.out b/src/test/regress/expected/float4.out index b3bc431a15..2c19e7eb08 100644 --- a/src/test/regress/expected/float4.out +++ b/src/test/regress/expected/float4.out @@ -10,29 +10,53 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20'); -- test for over and under flow INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70'); ERROR: value out of range: overflow +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70'); ERROR: value out of range: overflow +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70'); ERROR: value out of range: underflow +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70'); ERROR: value out of range: underflow +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70'); + ^ -- bad input INSERT INTO FLOAT4_TBL(f1) VALUES (''); ERROR: invalid input syntax for type real: "" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES (''); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES (' '); ERROR: invalid input syntax for type real: " " +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES (' '); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz'); ERROR: invalid input syntax for type real: "xyz" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0'); ERROR: invalid input syntax for type real: "5.0.0" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0'); ERROR: invalid input syntax for type real: "5 . 0" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('5. 0'); ERROR: invalid input syntax for type real: "5. 0" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5. 0'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES (' - 3.0'); ERROR: invalid input syntax for type real: " - 3.0" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES (' - 3.0'); + ^ INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5'); ERROR: invalid input syntax for type real: "123 5" +LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5'); + ^ -- special inputs SELECT 'NaN'::float4; float4 @@ -67,10 +91,16 @@ SELECT ' -INFINiTY '::float4; -- bad special inputs SELECT 'N A N'::float4; ERROR: invalid input syntax for type real: "N A N" +LINE 1: SELECT 'N A N'::float4; + ^ SELECT 'NaN x'::float4; ERROR: invalid input syntax for type real: "NaN x" +LINE 1: SELECT 'NaN x'::float4; + ^ SELECT ' INFINITY x'::float4; ERROR: invalid input syntax for type real: " INFINITY x" +LINE 1: SELECT ' INFINITY x'::float4; + ^ SELECT 'Infinity'::float4 + 100.0; ?column? ---------- diff --git a/src/test/regress/expected/float8-exp-three-digits-win32.out b/src/test/regress/expected/float8-exp-three-digits-win32.out index 55615c498f..4d133b42dc 100644 --- a/src/test/regress/expected/float8-exp-three-digits-win32.out +++ b/src/test/regress/expected/float8-exp-three-digits-win32.out @@ -10,29 +10,53 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); -- test for underflow and overflow handling SELECT '10e400'::float8; ERROR: "10e400" is out of range for type double precision +LINE 1: SELECT '10e400'::float8; + ^ SELECT '-10e400'::float8; ERROR: "-10e400" is out of range for type double precision +LINE 1: SELECT '-10e400'::float8; + ^ SELECT '10e-400'::float8; ERROR: "10e-400" is out of range for type double precision +LINE 1: SELECT '10e-400'::float8; + ^ SELECT '-10e-400'::float8; ERROR: "-10e-400" is out of range for type double precision +LINE 1: SELECT '-10e-400'::float8; + ^ -- bad input INSERT INTO FLOAT8_TBL(f1) VALUES (''); ERROR: invalid input syntax for type double precision: "" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (''); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES (' '); ERROR: invalid input syntax for type double precision: " " +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' '); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz'); ERROR: invalid input syntax for type double precision: "xyz" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0'); ERROR: invalid input syntax for type double precision: "5.0.0" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0'); ERROR: invalid input syntax for type double precision: "5 . 0" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0'); ERROR: invalid input syntax for type double precision: "5. 0" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); ERROR: invalid input syntax for type double precision: " - 3" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); ERROR: invalid input syntax for type double precision: "123 5" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); + ^ -- special inputs SELECT 'NaN'::float8; float8 @@ -67,10 +91,16 @@ SELECT ' -INFINiTY '::float8; -- bad special inputs SELECT 'N A N'::float8; ERROR: invalid input syntax for type double precision: "N A N" +LINE 1: SELECT 'N A N'::float8; + ^ SELECT 'NaN x'::float8; ERROR: invalid input syntax for type double precision: "NaN x" +LINE 1: SELECT 'NaN x'::float8; + ^ SELECT ' INFINITY x'::float8; ERROR: invalid input syntax for type double precision: " INFINITY x" +LINE 1: SELECT ' INFINITY x'::float8; + ^ SELECT 'Infinity'::float8 + 100.0; ?column? ---------- @@ -376,12 +406,20 @@ SELECT '' AS five, * FROM FLOAT8_TBL; -- test for over- and underflow INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); ERROR: "10e400" is out of range for type double precision +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400'); ERROR: "-10e400" is out of range for type double precision +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400'); ERROR: "10e-400" is out of range for type double precision +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400'); ERROR: "-10e-400" is out of range for type double precision +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400'); + ^ -- maintain external table consistency across platforms -- delete all values and reinsert well-behaved ones DELETE FROM FLOAT8_TBL; diff --git a/src/test/regress/expected/float8-small-is-zero.out b/src/test/regress/expected/float8-small-is-zero.out index 50af50556e..6c756a6f8e 100644 --- a/src/test/regress/expected/float8-small-is-zero.out +++ b/src/test/regress/expected/float8-small-is-zero.out @@ -10,8 +10,12 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); -- test for underflow and overflow handling SELECT '10e400'::float8; ERROR: "10e400" is out of range for type double precision +LINE 1: SELECT '10e400'::float8; + ^ SELECT '-10e400'::float8; ERROR: "-10e400" is out of range for type double precision +LINE 1: SELECT '-10e400'::float8; + ^ SELECT '10e-400'::float8; float8 -------- @@ -27,20 +31,36 @@ SELECT '-10e-400'::float8; -- bad input INSERT INTO FLOAT8_TBL(f1) VALUES (''); ERROR: invalid input syntax for type double precision: "" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (''); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES (' '); ERROR: invalid input syntax for type double precision: " " +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' '); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz'); ERROR: invalid input syntax for type double precision: "xyz" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0'); ERROR: invalid input syntax for type double precision: "5.0.0" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0'); ERROR: invalid input syntax for type double precision: "5 . 0" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0'); ERROR: invalid input syntax for type double precision: "5. 0" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); ERROR: invalid input syntax for type double precision: " - 3" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); ERROR: invalid input syntax for type double precision: "123 5" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); + ^ -- special inputs SELECT 'NaN'::float8; float8 @@ -75,10 +95,16 @@ SELECT ' -INFINiTY '::float8; -- bad special inputs SELECT 'N A N'::float8; ERROR: invalid input syntax for type double precision: "N A N" +LINE 1: SELECT 'N A N'::float8; + ^ SELECT 'NaN x'::float8; ERROR: invalid input syntax for type double precision: "NaN x" +LINE 1: SELECT 'NaN x'::float8; + ^ SELECT ' INFINITY x'::float8; ERROR: invalid input syntax for type double precision: " INFINITY x" +LINE 1: SELECT ' INFINITY x'::float8; + ^ SELECT 'Infinity'::float8 + 100.0; ?column? ---------- @@ -384,8 +410,12 @@ SELECT '' AS five, * FROM FLOAT8_TBL; -- test for over- and underflow INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); ERROR: "10e400" is out of range for type double precision +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400'); ERROR: "-10e400" is out of range for type double precision +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400'); INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400'); -- maintain external table consistency across platforms diff --git a/src/test/regress/expected/float8-small-is-zero_1.out b/src/test/regress/expected/float8-small-is-zero_1.out index 83919802ca..8b25f0955c 100644 --- a/src/test/regress/expected/float8-small-is-zero_1.out +++ b/src/test/regress/expected/float8-small-is-zero_1.out @@ -10,8 +10,12 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); -- test for underflow and overflow handling SELECT '10e400'::float8; ERROR: "10e400" is out of range for type double precision +LINE 1: SELECT '10e400'::float8; + ^ SELECT '-10e400'::float8; ERROR: "-10e400" is out of range for type double precision +LINE 1: SELECT '-10e400'::float8; + ^ SELECT '10e-400'::float8; float8 -------- @@ -27,20 +31,36 @@ SELECT '-10e-400'::float8; -- bad input INSERT INTO FLOAT8_TBL(f1) VALUES (''); ERROR: invalid input syntax for type double precision: "" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (''); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES (' '); ERROR: invalid input syntax for type double precision: " " +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' '); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz'); ERROR: invalid input syntax for type double precision: "xyz" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0'); ERROR: invalid input syntax for type double precision: "5.0.0" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0'); ERROR: invalid input syntax for type double precision: "5 . 0" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0'); ERROR: invalid input syntax for type double precision: "5. 0" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); ERROR: invalid input syntax for type double precision: " - 3" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); ERROR: invalid input syntax for type double precision: "123 5" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); + ^ -- special inputs SELECT 'NaN'::float8; float8 @@ -75,10 +95,16 @@ SELECT ' -INFINiTY '::float8; -- bad special inputs SELECT 'N A N'::float8; ERROR: invalid input syntax for type double precision: "N A N" +LINE 1: SELECT 'N A N'::float8; + ^ SELECT 'NaN x'::float8; ERROR: invalid input syntax for type double precision: "NaN x" +LINE 1: SELECT 'NaN x'::float8; + ^ SELECT ' INFINITY x'::float8; ERROR: invalid input syntax for type double precision: " INFINITY x" +LINE 1: SELECT ' INFINITY x'::float8; + ^ SELECT 'Infinity'::float8 + 100.0; ?column? ---------- @@ -384,8 +410,12 @@ SELECT '' AS five, * FROM FLOAT8_TBL; -- test for over- and underflow INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); ERROR: "10e400" is out of range for type double precision +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400'); ERROR: "-10e400" is out of range for type double precision +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400'); INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400'); -- maintain external table consistency across platforms diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out index f81d9b2bac..e9e71bb7aa 100644 --- a/src/test/regress/expected/float8.out +++ b/src/test/regress/expected/float8.out @@ -10,29 +10,53 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); -- test for underflow and overflow handling SELECT '10e400'::float8; ERROR: "10e400" is out of range for type double precision +LINE 1: SELECT '10e400'::float8; + ^ SELECT '-10e400'::float8; ERROR: "-10e400" is out of range for type double precision +LINE 1: SELECT '-10e400'::float8; + ^ SELECT '10e-400'::float8; ERROR: "10e-400" is out of range for type double precision +LINE 1: SELECT '10e-400'::float8; + ^ SELECT '-10e-400'::float8; ERROR: "-10e-400" is out of range for type double precision +LINE 1: SELECT '-10e-400'::float8; + ^ -- bad input INSERT INTO FLOAT8_TBL(f1) VALUES (''); ERROR: invalid input syntax for type double precision: "" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (''); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES (' '); ERROR: invalid input syntax for type double precision: " " +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' '); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz'); ERROR: invalid input syntax for type double precision: "xyz" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0'); ERROR: invalid input syntax for type double precision: "5.0.0" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0'); ERROR: invalid input syntax for type double precision: "5 . 0" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0'); ERROR: invalid input syntax for type double precision: "5. 0" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); ERROR: invalid input syntax for type double precision: " - 3" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); ERROR: invalid input syntax for type double precision: "123 5" +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); + ^ -- special inputs SELECT 'NaN'::float8; float8 @@ -67,10 +91,16 @@ SELECT ' -INFINiTY '::float8; -- bad special inputs SELECT 'N A N'::float8; ERROR: invalid input syntax for type double precision: "N A N" +LINE 1: SELECT 'N A N'::float8; + ^ SELECT 'NaN x'::float8; ERROR: invalid input syntax for type double precision: "NaN x" +LINE 1: SELECT 'NaN x'::float8; + ^ SELECT ' INFINITY x'::float8; ERROR: invalid input syntax for type double precision: " INFINITY x" +LINE 1: SELECT ' INFINITY x'::float8; + ^ SELECT 'Infinity'::float8 + 100.0; ?column? ---------- @@ -376,12 +406,20 @@ SELECT '' AS five, * FROM FLOAT8_TBL; -- test for over- and underflow INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); ERROR: "10e400" is out of range for type double precision +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400'); ERROR: "-10e400" is out of range for type double precision +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400'); ERROR: "10e-400" is out of range for type double precision +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400'); + ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400'); ERROR: "-10e-400" is out of range for type double precision +LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400'); + ^ -- maintain external table consistency across platforms -- delete all values and reinsert well-behaved ones DELETE FROM FLOAT8_TBL; diff --git a/src/test/regress/expected/horology.out b/src/test/regress/expected/horology.out index 9c101ad9a0..926a2cfde6 100644 --- a/src/test/regress/expected/horology.out +++ b/src/test/regress/expected/horology.out @@ -80,6 +80,8 @@ SELECT timestamp with time zone '12/27/2001 04:05:06.789-08'; -- should fail in mdy mode: SELECT timestamp with time zone '27/12/2001 04:05:06.789-08'; ERROR: date/time field value out of range: "27/12/2001 04:05:06.789-08" +LINE 1: SELECT timestamp with time zone '27/12/2001 04:05:06.789-08'... + ^ HINT: Perhaps you need a different "datestyle" setting. set datestyle to dmy; SELECT timestamp with time zone '27/12/2001 04:05:06.789-08'; @@ -841,11 +843,11 @@ SELECT time '03:30' + interval '1 month 04:01' AS "07:31:00"; SELECT CAST(time with time zone '01:02-08' AS interval) AS "+00:01"; ERROR: cannot cast type time with time zone to interval LINE 1: SELECT CAST(time with time zone '01:02-08' AS interval) AS "... - ^ + ^ SELECT CAST(interval '02:03' AS time with time zone) AS "02:03:00-08"; ERROR: cannot cast type interval to time with time zone LINE 1: SELECT CAST(interval '02:03' AS time with time zone) AS "02:... - ^ + ^ SELECT time with time zone '01:30-08' - interval '02:01' AS "23:29:00-08"; 23:29:00-08 ------------- diff --git a/src/test/regress/expected/inet.out b/src/test/regress/expected/inet.out index 9ecb37e29b..abb59d4acf 100644 --- a/src/test/regress/expected/inet.out +++ b/src/test/regress/expected/inet.out @@ -25,15 +25,23 @@ INSERT INTO INET_TBL (c, i) VALUES ('::ffff:1.2.3.4', '::4.3.2.1/24'); -- check that CIDR rejects invalid input: INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/30', '192.168.1.226'); ERROR: invalid cidr value: "192.168.1.2/30" +LINE 1: INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/30', '192.1... + ^ DETAIL: Value has bits set to right of mask. INSERT INTO INET_TBL (c, i) VALUES ('1234::1234::1234', '::1.2.3.4'); ERROR: invalid input syntax for type cidr: "1234::1234::1234" +LINE 1: INSERT INTO INET_TBL (c, i) VALUES ('1234::1234::1234', '::1... + ^ -- check that CIDR rejects invalid input when converting from text: INSERT INTO INET_TBL (c, i) VALUES (cidr('192.168.1.2/30'), '192.168.1.226'); ERROR: invalid cidr value: "192.168.1.2/30" +LINE 1: INSERT INTO INET_TBL (c, i) VALUES (cidr('192.168.1.2/30'), ... + ^ DETAIL: Value has bits set to right of mask. INSERT INTO INET_TBL (c, i) VALUES (cidr('ffff:ffff:ffff:ffff::/24'), '::192.168.1.226'); ERROR: invalid cidr value: "ffff:ffff:ffff:ffff::/24" +LINE 1: INSERT INTO INET_TBL (c, i) VALUES (cidr('ffff:ffff:ffff:fff... + ^ DETAIL: Value has bits set to right of mask. SELECT '' AS ten, c AS cidr, i AS inet FROM INET_TBL; ten | cidr | inet diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out index b4e6c306b4..d8510ea334 100644 --- a/src/test/regress/expected/insert.out +++ b/src/test/regress/expected/insert.out @@ -22,12 +22,20 @@ select * from inserttest; -- insert into inserttest (col1, col2, col3) values (DEFAULT, DEFAULT); ERROR: INSERT has more target columns than expressions +LINE 1: insert into inserttest (col1, col2, col3) values (DEFAULT, D... + ^ insert into inserttest (col1, col2, col3) values (1, 2); ERROR: INSERT has more target columns than expressions +LINE 1: insert into inserttest (col1, col2, col3) values (1, 2); + ^ insert into inserttest (col1) values (1, 2); ERROR: INSERT has more expressions than target columns +LINE 1: insert into inserttest (col1) values (1, 2); + ^ insert into inserttest (col1) values (DEFAULT, DEFAULT); ERROR: INSERT has more expressions than target columns +LINE 1: insert into inserttest (col1) values (DEFAULT, DEFAULT); + ^ select * from inserttest; col1 | col2 | col3 ------+------+--------- diff --git a/src/test/regress/expected/int2.out b/src/test/regress/expected/int2.out index e34e85bc97..61ac956cb7 100644 --- a/src/test/regress/expected/int2.out +++ b/src/test/regress/expected/int2.out @@ -9,24 +9,40 @@ INSERT INTO INT2_TBL(f1) VALUES (' 1234 '); INSERT INTO INT2_TBL(f1) VALUES (' -1234'); INSERT INTO INT2_TBL(f1) VALUES ('34.5'); ERROR: invalid input syntax for integer: "34.5" +LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('34.5'); + ^ -- largest and smallest values INSERT INTO INT2_TBL(f1) VALUES ('32767'); INSERT INTO INT2_TBL(f1) VALUES ('-32767'); -- bad input values -- should give errors INSERT INTO INT2_TBL(f1) VALUES ('100000'); ERROR: value "100000" is out of range for type smallint +LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('100000'); + ^ INSERT INTO INT2_TBL(f1) VALUES ('asdf'); ERROR: invalid input syntax for integer: "asdf" +LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('asdf'); + ^ INSERT INTO INT2_TBL(f1) VALUES (' '); ERROR: invalid input syntax for integer: " " +LINE 1: INSERT INTO INT2_TBL(f1) VALUES (' '); + ^ INSERT INTO INT2_TBL(f1) VALUES ('- 1234'); ERROR: invalid input syntax for integer: "- 1234" +LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('- 1234'); + ^ INSERT INTO INT2_TBL(f1) VALUES ('4 444'); ERROR: invalid input syntax for integer: "4 444" +LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('4 444'); + ^ INSERT INTO INT2_TBL(f1) VALUES ('123 dt'); ERROR: invalid input syntax for integer: "123 dt" +LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('123 dt'); + ^ INSERT INTO INT2_TBL(f1) VALUES (''); ERROR: invalid input syntax for integer: "" +LINE 1: INSERT INTO INT2_TBL(f1) VALUES (''); + ^ SELECT '' AS five, * FROM INT2_TBL; five | f1 ------+-------- diff --git a/src/test/regress/expected/int4.out b/src/test/regress/expected/int4.out index 3e0eff13a3..a21bbda2c9 100644 --- a/src/test/regress/expected/int4.out +++ b/src/test/regress/expected/int4.out @@ -9,24 +9,40 @@ INSERT INTO INT4_TBL(f1) VALUES ('123456 '); INSERT INTO INT4_TBL(f1) VALUES (' -123456'); INSERT INTO INT4_TBL(f1) VALUES ('34.5'); ERROR: invalid input syntax for integer: "34.5" +LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('34.5'); + ^ -- largest and smallest values INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); -- bad input values -- should give errors INSERT INTO INT4_TBL(f1) VALUES ('1000000000000'); ERROR: value "1000000000000" is out of range for type integer +LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('1000000000000'); + ^ INSERT INTO INT4_TBL(f1) VALUES ('asdf'); ERROR: invalid input syntax for integer: "asdf" +LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('asdf'); + ^ INSERT INTO INT4_TBL(f1) VALUES (' '); ERROR: invalid input syntax for integer: " " +LINE 1: INSERT INTO INT4_TBL(f1) VALUES (' '); + ^ INSERT INTO INT4_TBL(f1) VALUES (' asdf '); ERROR: invalid input syntax for integer: " asdf " +LINE 1: INSERT INTO INT4_TBL(f1) VALUES (' asdf '); + ^ INSERT INTO INT4_TBL(f1) VALUES ('- 1234'); ERROR: invalid input syntax for integer: "- 1234" +LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('- 1234'); + ^ INSERT INTO INT4_TBL(f1) VALUES ('123 5'); ERROR: invalid input syntax for integer: "123 5" +LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('123 5'); + ^ INSERT INTO INT4_TBL(f1) VALUES (''); ERROR: invalid input syntax for integer: "" +LINE 1: INSERT INTO INT4_TBL(f1) VALUES (''); + ^ SELECT '' AS five, * FROM INT4_TBL; five | f1 ------+------------- diff --git a/src/test/regress/expected/int8-exp-three-digits.out b/src/test/regress/expected/int8-exp-three-digits.out index e3697f8344..12af98f0b5 100644 --- a/src/test/regress/expected/int8-exp-three-digits.out +++ b/src/test/regress/expected/int8-exp-three-digits.out @@ -11,18 +11,32 @@ INSERT INTO INT8_TBL VALUES('4567890123456789','-4567890123456789'); -- bad inputs INSERT INTO INT8_TBL(q1) VALUES (' '); ERROR: invalid input syntax for integer: " " +LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' '); + ^ INSERT INTO INT8_TBL(q1) VALUES ('xxx'); ERROR: invalid input syntax for integer: "xxx" +LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('xxx'); + ^ INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485'); ERROR: value "3908203590239580293850293850329485" is out of range for type bigint +LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('39082035902395802938502938... + ^ INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934'); ERROR: value "-1204982019841029840928340329840934" is out of range for type bigint +LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340... + ^ INSERT INTO INT8_TBL(q1) VALUES ('- 123'); ERROR: invalid input syntax for integer: "- 123" +LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('- 123'); + ^ INSERT INTO INT8_TBL(q1) VALUES (' 345 5'); ERROR: invalid input syntax for integer: " 345 5" +LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' 345 5'); + ^ INSERT INTO INT8_TBL(q1) VALUES (''); ERROR: invalid input syntax for integer: "" +LINE 1: INSERT INTO INT8_TBL(q1) VALUES (''); + ^ SELECT * FROM INT8_TBL; q1 | q2 ------------------+------------------- @@ -309,6 +323,8 @@ select '-9223372036854775808'::int8; select '-9223372036854775809'::int8; ERROR: value "-9223372036854775809" is out of range for type bigint +LINE 1: select '-9223372036854775809'::int8; + ^ select '9223372036854775807'::int8; int8 --------------------- @@ -317,3 +333,5 @@ select '9223372036854775807'::int8; select '9223372036854775808'::int8; ERROR: value "9223372036854775808" is out of range for type bigint +LINE 1: select '9223372036854775808'::int8; + ^ diff --git a/src/test/regress/expected/int8.out b/src/test/regress/expected/int8.out index 52cdabab74..f1cc62d680 100644 --- a/src/test/regress/expected/int8.out +++ b/src/test/regress/expected/int8.out @@ -11,18 +11,32 @@ INSERT INTO INT8_TBL VALUES('4567890123456789','-4567890123456789'); -- bad inputs INSERT INTO INT8_TBL(q1) VALUES (' '); ERROR: invalid input syntax for integer: " " +LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' '); + ^ INSERT INTO INT8_TBL(q1) VALUES ('xxx'); ERROR: invalid input syntax for integer: "xxx" +LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('xxx'); + ^ INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485'); ERROR: value "3908203590239580293850293850329485" is out of range for type bigint +LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('39082035902395802938502938... + ^ INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934'); ERROR: value "-1204982019841029840928340329840934" is out of range for type bigint +LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340... + ^ INSERT INTO INT8_TBL(q1) VALUES ('- 123'); ERROR: invalid input syntax for integer: "- 123" +LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('- 123'); + ^ INSERT INTO INT8_TBL(q1) VALUES (' 345 5'); ERROR: invalid input syntax for integer: " 345 5" +LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' 345 5'); + ^ INSERT INTO INT8_TBL(q1) VALUES (''); ERROR: invalid input syntax for integer: "" +LINE 1: INSERT INTO INT8_TBL(q1) VALUES (''); + ^ SELECT * FROM INT8_TBL; q1 | q2 ------------------+------------------- @@ -309,6 +323,8 @@ select '-9223372036854775808'::int8; select '-9223372036854775809'::int8; ERROR: value "-9223372036854775809" is out of range for type bigint +LINE 1: select '-9223372036854775809'::int8; + ^ select '9223372036854775807'::int8; int8 --------------------- @@ -317,3 +333,5 @@ select '9223372036854775807'::int8; select '9223372036854775808'::int8; ERROR: value "9223372036854775808" is out of range for type bigint +LINE 1: select '9223372036854775808'::int8; + ^ diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out index 72a031df5f..049850af8e 100644 --- a/src/test/regress/expected/interval.out +++ b/src/test/regress/expected/interval.out @@ -71,8 +71,12 @@ INSERT INTO INTERVAL_TBL (f1) VALUES ('5 months 12 hours'); -- badly formatted interval INSERT INTO INTERVAL_TBL (f1) VALUES ('badly formatted interval'); ERROR: invalid input syntax for type interval: "badly formatted interval" +LINE 1: INSERT INTO INTERVAL_TBL (f1) VALUES ('badly formatted inter... + ^ INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 30 eons ago'); ERROR: invalid input syntax for type interval: "@ 30 eons ago" +LINE 1: INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 30 eons ago'); + ^ -- test interval operators SELECT '' AS ten, * FROM INTERVAL_TBL; ten | f1 @@ -343,9 +347,17 @@ SELECT '3 days 5 milliseconds'::interval; SELECT '1 second 2 seconds'::interval; -- error ERROR: invalid input syntax for type interval: "1 second 2 seconds" +LINE 1: SELECT '1 second 2 seconds'::interval; + ^ SELECT '10 milliseconds 20 milliseconds'::interval; -- error ERROR: invalid input syntax for type interval: "10 milliseconds 20 milliseconds" +LINE 1: SELECT '10 milliseconds 20 milliseconds'::interval; + ^ SELECT '5.5 seconds 3 milliseconds'::interval; -- error ERROR: invalid input syntax for type interval: "5.5 seconds 3 milliseconds" +LINE 1: SELECT '5.5 seconds 3 milliseconds'::interval; + ^ SELECT '1:20:05 5 microseconds'::interval; -- error ERROR: invalid input syntax for type interval: "1:20:05 5 microseconds" +LINE 1: SELECT '1:20:05 5 microseconds'::interval; + ^ diff --git a/src/test/regress/expected/lseg.out b/src/test/regress/expected/lseg.out index 9e0e6cb2df..bba1f3ee80 100644 --- a/src/test/regress/expected/lseg.out +++ b/src/test/regress/expected/lseg.out @@ -12,12 +12,20 @@ INSERT INTO LSEG_TBL VALUES ('(11,22,33,44)'); -- bad values for parser testing INSERT INTO LSEG_TBL VALUES ('(3asdf,2 ,3,4r2)'); ERROR: invalid input syntax for type lseg: "(3asdf,2 ,3,4r2)" +LINE 1: INSERT INTO LSEG_TBL VALUES ('(3asdf,2 ,3,4r2)'); + ^ INSERT INTO LSEG_TBL VALUES ('[1,2,3, 4'); ERROR: invalid input syntax for type lseg: "[1,2,3, 4" +LINE 1: INSERT INTO LSEG_TBL VALUES ('[1,2,3, 4'); + ^ INSERT INTO LSEG_TBL VALUES ('[(,2),(3,4)]'); ERROR: invalid input syntax for type lseg: "[(,2),(3,4)]" +LINE 1: INSERT INTO LSEG_TBL VALUES ('[(,2),(3,4)]'); + ^ INSERT INTO LSEG_TBL VALUES ('[(1,2),(3,4)'); ERROR: invalid input syntax for type lseg: "[(1,2),(3,4)" +LINE 1: INSERT INTO LSEG_TBL VALUES ('[(1,2),(3,4)'); + ^ select * from LSEG_TBL; s ------------------------------- diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out index 1c5047455e..c2fe7070b5 100644 --- a/src/test/regress/expected/numeric.out +++ b/src/test/regress/expected/numeric.out @@ -1231,25 +1231,45 @@ INSERT INTO num_input_test(n1) VALUES ('555.50'); INSERT INTO num_input_test(n1) VALUES ('-555.50'); INSERT INTO num_input_test(n1) VALUES ('NaN '); ERROR: invalid input syntax for type numeric: "NaN " +LINE 1: INSERT INTO num_input_test(n1) VALUES ('NaN '); + ^ INSERT INTO num_input_test(n1) VALUES (' nan'); ERROR: invalid input syntax for type numeric: " nan" +LINE 1: INSERT INTO num_input_test(n1) VALUES (' nan'); + ^ -- bad inputs INSERT INTO num_input_test(n1) VALUES (' '); ERROR: invalid input syntax for type numeric: " " +LINE 1: INSERT INTO num_input_test(n1) VALUES (' '); + ^ INSERT INTO num_input_test(n1) VALUES (' 1234 %'); ERROR: invalid input syntax for type numeric: " 1234 %" +LINE 1: INSERT INTO num_input_test(n1) VALUES (' 1234 %'); + ^ INSERT INTO num_input_test(n1) VALUES ('xyz'); ERROR: invalid input syntax for type numeric: "xyz" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('xyz'); + ^ INSERT INTO num_input_test(n1) VALUES ('- 1234'); ERROR: invalid input syntax for type numeric: "- 1234" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('- 1234'); + ^ INSERT INTO num_input_test(n1) VALUES ('5 . 0'); ERROR: invalid input syntax for type numeric: "5 . 0" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('5 . 0'); + ^ INSERT INTO num_input_test(n1) VALUES ('5. 0 '); ERROR: invalid input syntax for type numeric: "5. 0 " +LINE 1: INSERT INTO num_input_test(n1) VALUES ('5. 0 '); + ^ INSERT INTO num_input_test(n1) VALUES (''); ERROR: invalid input syntax for type numeric: "" +LINE 1: INSERT INTO num_input_test(n1) VALUES (''); + ^ INSERT INTO num_input_test(n1) VALUES (' N aN '); ERROR: invalid input syntax for type numeric: " N aN " +LINE 1: INSERT INTO num_input_test(n1) VALUES (' N aN '); + ^ SELECT * FROM num_input_test; n1 --------- diff --git a/src/test/regress/expected/oid.out b/src/test/regress/expected/oid.out index e01db08c20..008b5a246b 100644 --- a/src/test/regress/expected/oid.out +++ b/src/test/regress/expected/oid.out @@ -14,24 +14,44 @@ INSERT INTO OID_TBL(f1) VALUES (' 15 '); -- bad inputs INSERT INTO OID_TBL(f1) VALUES (''); ERROR: invalid input syntax for type oid: "" +LINE 1: INSERT INTO OID_TBL(f1) VALUES (''); + ^ INSERT INTO OID_TBL(f1) VALUES (' '); ERROR: invalid input syntax for type oid: " " +LINE 1: INSERT INTO OID_TBL(f1) VALUES (' '); + ^ INSERT INTO OID_TBL(f1) VALUES ('asdfasd'); ERROR: invalid input syntax for type oid: "asdfasd" +LINE 1: INSERT INTO OID_TBL(f1) VALUES ('asdfasd'); + ^ INSERT INTO OID_TBL(f1) VALUES ('99asdfasd'); ERROR: invalid input syntax for type oid: "99asdfasd" +LINE 1: INSERT INTO OID_TBL(f1) VALUES ('99asdfasd'); + ^ INSERT INTO OID_TBL(f1) VALUES ('5 d'); ERROR: invalid input syntax for type oid: "5 d" +LINE 1: INSERT INTO OID_TBL(f1) VALUES ('5 d'); + ^ INSERT INTO OID_TBL(f1) VALUES (' 5d'); ERROR: invalid input syntax for type oid: " 5d" +LINE 1: INSERT INTO OID_TBL(f1) VALUES (' 5d'); + ^ INSERT INTO OID_TBL(f1) VALUES ('5 5'); ERROR: invalid input syntax for type oid: "5 5" +LINE 1: INSERT INTO OID_TBL(f1) VALUES ('5 5'); + ^ INSERT INTO OID_TBL(f1) VALUES (' - 500'); ERROR: invalid input syntax for type oid: " - 500" +LINE 1: INSERT INTO OID_TBL(f1) VALUES (' - 500'); + ^ INSERT INTO OID_TBL(f1) VALUES ('32958209582039852935'); ERROR: value "32958209582039852935" is out of range for type oid +LINE 1: INSERT INTO OID_TBL(f1) VALUES ('32958209582039852935'); + ^ INSERT INTO OID_TBL(f1) VALUES ('-23582358720398502385'); ERROR: value "-23582358720398502385" is out of range for type oid +LINE 1: INSERT INTO OID_TBL(f1) VALUES ('-23582358720398502385'); + ^ SELECT '' AS six, * FROM OID_TBL; six | f1 -----+------------ diff --git a/src/test/regress/expected/path.out b/src/test/regress/expected/path.out index f5671c7a13..08d6d61dda 100644 --- a/src/test/regress/expected/path.out +++ b/src/test/regress/expected/path.out @@ -14,8 +14,12 @@ INSERT INTO PATH_TBL VALUES ('(11,12,13,14)'); -- bad values for parser testing INSERT INTO PATH_TBL VALUES ('[(,2),(3,4)]'); ERROR: invalid input syntax for type path: "[(,2),(3,4)]" +LINE 1: INSERT INTO PATH_TBL VALUES ('[(,2),(3,4)]'); + ^ INSERT INTO PATH_TBL VALUES ('[(1,2),(3,4)'); ERROR: invalid input syntax for type path: "[(1,2),(3,4)" +LINE 1: INSERT INTO PATH_TBL VALUES ('[(1,2),(3,4)'); + ^ SELECT f1 FROM PATH_TBL; f1 --------------------------- diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out index a31a4b39b7..9d1bd434e9 100644 --- a/src/test/regress/expected/point.out +++ b/src/test/regress/expected/point.out @@ -10,11 +10,17 @@ INSERT INTO POINT_TBL(f1) VALUES ('(-5.0,-12.0)'); -- bad format points INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf'); ERROR: invalid input syntax for type point: "asdfasdf" +LINE 1: INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf'); + ^ INSERT INTO POINT_TBL(f1) VALUES ('10.0,10.0'); INSERT INTO POINT_TBL(f1) VALUES ('(10.0 10.0)'); ERROR: invalid input syntax for type point: "(10.0 10.0)" +LINE 1: INSERT INTO POINT_TBL(f1) VALUES ('(10.0 10.0)'); + ^ INSERT INTO POINT_TBL(f1) VALUES ('(10.0,10.0'); ERROR: invalid input syntax for type point: "(10.0,10.0" +LINE 1: INSERT INTO POINT_TBL(f1) VALUES ('(10.0,10.0'); + ^ SELECT '' AS six, * FROM POINT_TBL; six | f1 -----+------------ diff --git a/src/test/regress/expected/polygon.out b/src/test/regress/expected/polygon.out index 2edda04b4e..56b72aaa8e 100644 --- a/src/test/regress/expected/polygon.out +++ b/src/test/regress/expected/polygon.out @@ -22,14 +22,24 @@ INSERT INTO POLYGON_TBL(f1) VALUES ('(0.0,1.0),(0.0,1.0)'); -- bad polygon input strings INSERT INTO POLYGON_TBL(f1) VALUES ('0.0'); ERROR: invalid input syntax for type polygon: "0.0" +LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('0.0'); + ^ INSERT INTO POLYGON_TBL(f1) VALUES ('(0.0 0.0'); ERROR: invalid input syntax for type polygon: "(0.0 0.0" +LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('(0.0 0.0'); + ^ INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2)'); ERROR: invalid input syntax for type polygon: "(0,1,2)" +LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2)'); + ^ INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2,3'); ERROR: invalid input syntax for type polygon: "(0,1,2,3" +LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2,3'); + ^ INSERT INTO POLYGON_TBL(f1) VALUES ('asdf'); ERROR: invalid input syntax for type polygon: "asdf" +LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('asdf'); + ^ SELECT '' AS four, * FROM POLYGON_TBL; four | f1 ------+--------------------- diff --git a/src/test/regress/expected/prepared_xacts.out b/src/test/regress/expected/prepared_xacts.out index 258706da8e..535dbe4cbf 100644 --- a/src/test/regress/expected/prepared_xacts.out +++ b/src/test/regress/expected/prepared_xacts.out @@ -148,6 +148,8 @@ ERROR: cursor "foo" does not exist -- Table doesn't exist, the creation hasn't been committed yet SELECT * FROM pxtest2; ERROR: relation "pxtest2" does not exist +LINE 1: SELECT * FROM pxtest2; + ^ -- There should be two prepared transactions SELECT gid FROM pg_prepared_xacts; gid @@ -202,6 +204,8 @@ SELECT gid FROM pg_prepared_xacts; COMMIT PREPARED 'regress-two'; SELECT * FROM pxtest3; ERROR: relation "pxtest3" does not exist +LINE 1: SELECT * FROM pxtest3; + ^ -- There should be no prepared transactions SELECT gid FROM pg_prepared_xacts; gid diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out index 90111553d9..e8a9013550 100644 --- a/src/test/regress/expected/rangefuncs.out +++ b/src/test/regress/expected/rangefuncs.out @@ -20,6 +20,8 @@ CREATE FUNCTION foot(int) returns setof foo2 as 'SELECT * FROM foo2 WHERE fooid -- supposed to fail with ERROR select * from foo2, foot(foo2.fooid) z where foo2.f2 = z.f2; ERROR: function expression in FROM cannot refer to other relations of same query level +LINE 1: select * from foo2, foot(foo2.fooid) z where foo2.f2 = z.f2; + ^ -- function in subselect select * from foo2 where f2 in (select f2 from foot(foo2.fooid) z where z.fooid = foo2.fooid) ORDER BY 1,2; fooid | f2 diff --git a/src/test/regress/expected/reltime.out b/src/test/regress/expected/reltime.out index 8f4faef124..14fdc6aeec 100644 --- a/src/test/regress/expected/reltime.out +++ b/src/test/regress/expected/reltime.out @@ -11,8 +11,12 @@ INSERT INTO RELTIME_TBL (f1) VALUES ('@ 14 seconds ago'); -- badly formatted reltimes INSERT INTO RELTIME_TBL (f1) VALUES ('badly formatted reltime'); ERROR: invalid input syntax for type reltime: "badly formatted reltime" +LINE 1: INSERT INTO RELTIME_TBL (f1) VALUES ('badly formatted reltim... + ^ INSERT INTO RELTIME_TBL (f1) VALUES ('@ 30 eons ago'); ERROR: invalid input syntax for type reltime: "@ 30 eons ago" +LINE 1: INSERT INTO RELTIME_TBL (f1) VALUES ('@ 30 eons ago'); + ^ -- test reltime operators SELECT '' AS six, * FROM RELTIME_TBL; six | f1 diff --git a/src/test/regress/expected/rowtypes.out b/src/test/regress/expected/rowtypes.out index 6af1aa705f..73ae3ce10e 100644 --- a/src/test/regress/expected/rowtypes.out +++ b/src/test/regress/expected/rowtypes.out @@ -45,9 +45,13 @@ select '(Joe,)'::fullname; -- ok, null 2nd column select '(Joe)'::fullname; -- bad ERROR: malformed record literal: "(Joe)" +LINE 1: select '(Joe)'::fullname; + ^ DETAIL: Too few columns. select '(Joe,,)'::fullname; -- bad ERROR: malformed record literal: "(Joe,,)" +LINE 1: select '(Joe,,)'::fullname; + ^ DETAIL: Too many columns. create temp table quadtable(f1 int, q quad); insert into quadtable values (1, ((3.3,4.4),(5.5,6.6))); diff --git a/src/test/regress/expected/select_distinct_on.out b/src/test/regress/expected/select_distinct_on.out index c4b03e95f7..fc6dda7477 100644 --- a/src/test/regress/expected/select_distinct_on.out +++ b/src/test/regress/expected/select_distinct_on.out @@ -17,6 +17,8 @@ SELECT DISTINCT ON (string4, ten) string4, two, ten FROM tmp ORDER BY string4 using <, two using <, ten using <; ERROR: SELECT DISTINCT ON expressions must match initial ORDER BY expressions +LINE 1: SELECT DISTINCT ON (string4, ten) string4, two, ten + ^ SELECT DISTINCT ON (string4, ten) string4, ten, two FROM tmp ORDER BY string4 using <, ten using >, two using <; diff --git a/src/test/regress/expected/select_having.out b/src/test/regress/expected/select_having.out index dc4dee06b1..3950c0b404 100644 --- a/src/test/regress/expected/select_having.out +++ b/src/test/regress/expected/select_having.out @@ -65,8 +65,12 @@ SELECT min(a), max(a) FROM test_having HAVING min(a) < max(a); -- errors: ungrouped column references SELECT a FROM test_having HAVING min(a) < max(a); ERROR: column "test_having.a" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: SELECT a FROM test_having HAVING min(a) < max(a); + ^ SELECT 1 AS one FROM test_having HAVING a > 1; ERROR: column "test_having.a" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: SELECT 1 AS one FROM test_having HAVING a > 1; + ^ -- the really degenerate case: need not scan table at all SELECT 1 AS one FROM test_having HAVING 1 > 2; one diff --git a/src/test/regress/expected/select_having_1.out b/src/test/regress/expected/select_having_1.out index de721dd803..5c58da154c 100644 --- a/src/test/regress/expected/select_having_1.out +++ b/src/test/regress/expected/select_having_1.out @@ -65,8 +65,12 @@ SELECT min(a), max(a) FROM test_having HAVING min(a) < max(a); -- errors: ungrouped column references SELECT a FROM test_having HAVING min(a) < max(a); ERROR: column "test_having.a" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: SELECT a FROM test_having HAVING min(a) < max(a); + ^ SELECT 1 AS one FROM test_having HAVING a > 1; ERROR: column "test_having.a" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: SELECT 1 AS one FROM test_having HAVING a > 1; + ^ -- the really degenerate case: need not scan table at all SELECT 1 AS one FROM test_having HAVING 1 > 2; one diff --git a/src/test/regress/expected/select_having_2.out b/src/test/regress/expected/select_having_2.out index 542436e5ea..7087fb1c0c 100644 --- a/src/test/regress/expected/select_having_2.out +++ b/src/test/regress/expected/select_having_2.out @@ -65,8 +65,12 @@ SELECT min(a), max(a) FROM test_having HAVING min(a) < max(a); -- errors: ungrouped column references SELECT a FROM test_having HAVING min(a) < max(a); ERROR: column "test_having.a" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: SELECT a FROM test_having HAVING min(a) < max(a); + ^ SELECT 1 AS one FROM test_having HAVING a > 1; ERROR: column "test_having.a" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: SELECT 1 AS one FROM test_having HAVING a > 1; + ^ -- the really degenerate case: need not scan table at all SELECT 1 AS one FROM test_having HAVING 1 > 2; one diff --git a/src/test/regress/expected/select_implicit.out b/src/test/regress/expected/select_implicit.out index 14ee2b6205..b358ee9fcc 100644 --- a/src/test/regress/expected/select_implicit.out +++ b/src/test/regress/expected/select_implicit.out @@ -45,6 +45,8 @@ SELECT count(*) FROM test_missing_target GROUP BY test_missing_target.c ORDER BY -- failure expected SELECT count(*) FROM test_missing_target GROUP BY a ORDER BY b; ERROR: column "test_missing_target.b" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: ...ECT count(*) FROM test_missing_target GROUP BY a ORDER BY b; + ^ -- w/o existing GROUP BY target and w/o existing same ORDER BY target SELECT count(*) FROM test_missing_target GROUP BY b ORDER BY b; count @@ -240,6 +242,8 @@ ORDER BY lower(test_missing_target.c); -- failure expected SELECT count(a) FROM test_missing_target GROUP BY a ORDER BY b; ERROR: column "test_missing_target.b" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: ...ECT count(a) FROM test_missing_target GROUP BY a ORDER BY b; + ^ -- w/o existing GROUP BY target and w/o existing same ORDER BY target SELECT count(b) FROM test_missing_target GROUP BY b/2 ORDER BY b/2; count diff --git a/src/test/regress/expected/select_implicit_1.out b/src/test/regress/expected/select_implicit_1.out index feb33ec576..1527ce4277 100644 --- a/src/test/regress/expected/select_implicit_1.out +++ b/src/test/regress/expected/select_implicit_1.out @@ -45,6 +45,8 @@ SELECT count(*) FROM test_missing_target GROUP BY test_missing_target.c ORDER BY -- failure expected SELECT count(*) FROM test_missing_target GROUP BY a ORDER BY b; ERROR: column "test_missing_target.b" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: ...ECT count(*) FROM test_missing_target GROUP BY a ORDER BY b; + ^ -- w/o existing GROUP BY target and w/o existing same ORDER BY target SELECT count(*) FROM test_missing_target GROUP BY b ORDER BY b; count @@ -240,6 +242,8 @@ ORDER BY lower(test_missing_target.c); -- failure expected SELECT count(a) FROM test_missing_target GROUP BY a ORDER BY b; ERROR: column "test_missing_target.b" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: ...ECT count(a) FROM test_missing_target GROUP BY a ORDER BY b; + ^ -- w/o existing GROUP BY target and w/o existing same ORDER BY target SELECT count(b) FROM test_missing_target GROUP BY b/2 ORDER BY b/2; count diff --git a/src/test/regress/expected/select_implicit_2.out b/src/test/regress/expected/select_implicit_2.out index fac106353f..4217af7ba4 100644 --- a/src/test/regress/expected/select_implicit_2.out +++ b/src/test/regress/expected/select_implicit_2.out @@ -45,6 +45,8 @@ SELECT count(*) FROM test_missing_target GROUP BY test_missing_target.c ORDER BY -- failure expected SELECT count(*) FROM test_missing_target GROUP BY a ORDER BY b; ERROR: column "test_missing_target.b" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: ...ECT count(*) FROM test_missing_target GROUP BY a ORDER BY b; + ^ -- w/o existing GROUP BY target and w/o existing same ORDER BY target SELECT count(*) FROM test_missing_target GROUP BY b ORDER BY b; count @@ -240,6 +242,8 @@ ORDER BY lower(test_missing_target.c); -- failure expected SELECT count(a) FROM test_missing_target GROUP BY a ORDER BY b; ERROR: column "test_missing_target.b" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: ...ECT count(a) FROM test_missing_target GROUP BY a ORDER BY b; + ^ -- w/o existing GROUP BY target and w/o existing same ORDER BY target SELECT count(b) FROM test_missing_target GROUP BY b/2 ORDER BY b/2; count diff --git a/src/test/regress/expected/temp.out b/src/test/regress/expected/temp.out index da126a3aff..c39a88ad51 100644 --- a/src/test/regress/expected/temp.out +++ b/src/test/regress/expected/temp.out @@ -45,6 +45,8 @@ CREATE TEMP TABLE temptest(col int); \c SELECT * FROM temptest; ERROR: relation "temptest" does not exist +LINE 1: SELECT * FROM temptest; + ^ -- Test ON COMMIT DELETE ROWS CREATE TEMP TABLE temptest(col int) ON COMMIT DELETE ROWS; BEGIN; @@ -94,6 +96,8 @@ SELECT * FROM temptest; COMMIT; SELECT * FROM temptest; ERROR: relation "temptest" does not exist +LINE 1: SELECT * FROM temptest; + ^ BEGIN; CREATE TEMP TABLE temptest(col) ON COMMIT DROP AS SELECT 1; SELECT * FROM temptest; @@ -105,6 +109,8 @@ SELECT * FROM temptest; COMMIT; SELECT * FROM temptest; ERROR: relation "temptest" does not exist +LINE 1: SELECT * FROM temptest; + ^ -- ON COMMIT is only allowed for TEMP CREATE TABLE temptest(col int) ON COMMIT DELETE ROWS; ERROR: ON COMMIT can only be used on temporary tables diff --git a/src/test/regress/expected/time.out b/src/test/regress/expected/time.out index 6e21828cf7..8e0afe69e0 100644 --- a/src/test/regress/expected/time.out +++ b/src/test/regress/expected/time.out @@ -16,6 +16,8 @@ INSERT INTO TIME_TBL VALUES ('2003-07-07 15:36:39 America/New_York'); -- this should fail (the timezone offset is not known) INSERT INTO TIME_TBL VALUES ('15:36:39 America/New_York'); ERROR: invalid input syntax for type time: "15:36:39 America/New_York" +LINE 1: INSERT INTO TIME_TBL VALUES ('15:36:39 America/New_York'); + ^ SELECT f1 AS "Time" FROM TIME_TBL; Time ------------- diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out index 81b3eb87ca..a0924c7fe3 100644 --- a/src/test/regress/expected/timestamp.out +++ b/src/test/regress/expected/timestamp.out @@ -82,14 +82,22 @@ INSERT INTO TIMESTAMP_TBL VALUES ('epoch'); -- Obsolete special values INSERT INTO TIMESTAMP_TBL VALUES ('invalid'); ERROR: date/time value "invalid" is no longer supported +LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('invalid'); + ^ INSERT INTO TIMESTAMP_TBL VALUES ('current'); ERROR: date/time value "current" is no longer supported +LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('current'); + ^ -- Postgres v6.0 standard output format INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST'); INSERT INTO TIMESTAMP_TBL VALUES ('Invalid Abstime'); ERROR: date/time value "Invalid Abstime" is no longer supported +LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('Invalid Abstime'); + ^ INSERT INTO TIMESTAMP_TBL VALUES ('Undefined Abstime'); ERROR: date/time value "Undefined Abstime" is no longer supported +LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('Undefined Abstime'); + ^ -- Variations on Postgres v6.1 standard output format INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01.000001 1997 PST'); INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01.999999 1997 PST'); @@ -129,6 +137,8 @@ INSERT INTO TIMESTAMP_TBL VALUES ('19970210 173201 America/New_York'); -- this fails (even though TZ is a no-op, we still look it up) INSERT INTO TIMESTAMP_TBL VALUES ('19970710 173201 America/Does_not_exist'); ERROR: time zone "america/does_not_exist" not recognized +LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('19970710 173201 America/D... + ^ -- Check date conversion and date arithmetic INSERT INTO TIMESTAMP_TBL VALUES ('1997-06-10 18:32:01 PDT'); INSERT INTO TIMESTAMP_TBL VALUES ('Feb 10 17:32:01 1997'); @@ -156,6 +166,8 @@ INSERT INTO TIMESTAMP_TBL VALUES ('Jan 01 17:32:01 1997'); INSERT INTO TIMESTAMP_TBL VALUES ('Feb 28 17:32:01 1997'); INSERT INTO TIMESTAMP_TBL VALUES ('Feb 29 17:32:01 1997'); ERROR: date/time field value out of range: "Feb 29 17:32:01 1997" +LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('Feb 29 17:32:01 1997'); + ^ INSERT INTO TIMESTAMP_TBL VALUES ('Mar 01 17:32:01 1997'); INSERT INTO TIMESTAMP_TBL VALUES ('Dec 30 17:32:01 1997'); INSERT INTO TIMESTAMP_TBL VALUES ('Dec 31 17:32:01 1997'); @@ -166,8 +178,12 @@ INSERT INTO TIMESTAMP_TBL VALUES ('Jan 01 17:32:01 2001'); -- Currently unsupported syntax and ranges INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 -0097'); ERROR: time zone displacement out of range: "Feb 16 17:32:01 -0097" +LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 -0097'); + ^ INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 5097 BC'); ERROR: timestamp out of range: "Feb 16 17:32:01 5097 BC" +LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 5097 BC')... + ^ SELECT '' AS "64", d1 FROM TIMESTAMP_TBL; 64 | d1 ----+----------------------------- diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out index 92fa5cfaae..31012f80b6 100644 --- a/src/test/regress/expected/timestamptz.out +++ b/src/test/regress/expected/timestamptz.out @@ -81,14 +81,22 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('epoch'); -- Obsolete special values INSERT INTO TIMESTAMPTZ_TBL VALUES ('invalid'); ERROR: date/time value "invalid" is no longer supported +LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('invalid'); + ^ INSERT INTO TIMESTAMPTZ_TBL VALUES ('current'); ERROR: date/time value "current" is no longer supported +LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('current'); + ^ -- Postgres v6.0 standard output format INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST'); INSERT INTO TIMESTAMPTZ_TBL VALUES ('Invalid Abstime'); ERROR: date/time value "Invalid Abstime" is no longer supported +LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('Invalid Abstime'); + ^ INSERT INTO TIMESTAMPTZ_TBL VALUES ('Undefined Abstime'); ERROR: date/time value "Undefined Abstime" is no longer supported +LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('Undefined Abstime'); + ^ -- Variations on Postgres v6.1 standard output format INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01.000001 1997 PST'); INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01.999999 1997 PST'); @@ -141,6 +149,8 @@ SELECT '19970710 173201' AT TIME ZONE 'America/New_York'; INSERT INTO TIMESTAMPTZ_TBL VALUES ('19970710 173201 America/Does_not_exist'); ERROR: time zone "america/does_not_exist" not recognized +LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('19970710 173201 America... + ^ SELECT '19970710 173201' AT TIME ZONE 'America/Does_not_exist'; ERROR: time zone "America/Does_not_exist" not recognized -- Daylight saving time for timestamps beyond 32-bit time_t range. @@ -195,6 +205,8 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('Jan 01 17:32:01 1997'); INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 28 17:32:01 1997'); INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 29 17:32:01 1997'); ERROR: date/time field value out of range: "Feb 29 17:32:01 1997" +LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 29 17:32:01 1997'); + ^ INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mar 01 17:32:01 1997'); INSERT INTO TIMESTAMPTZ_TBL VALUES ('Dec 30 17:32:01 1997'); INSERT INTO TIMESTAMPTZ_TBL VALUES ('Dec 31 17:32:01 1997'); @@ -205,8 +217,12 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('Jan 01 17:32:01 2001'); -- Currently unsupported syntax and ranges INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 -0097'); ERROR: time zone displacement out of range: "Feb 16 17:32:01 -0097" +LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 -0097')... + ^ INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 5097 BC'); ERROR: timestamp out of range: "Feb 16 17:32:01 5097 BC" +LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 5097 BC... + ^ -- Alternative field order that we've historically supported (sort of) -- with regular and POSIXy timezone specs SELECT 'Wed Jul 11 10:51:14 America/New_York 2001'::timestamptz; diff --git a/src/test/regress/expected/timetz.out b/src/test/regress/expected/timetz.out index 44e8b25b30..43911312f9 100644 --- a/src/test/regress/expected/timetz.out +++ b/src/test/regress/expected/timetz.out @@ -17,6 +17,8 @@ INSERT INTO TIMETZ_TBL VALUES ('2003-07-07 15:36:39 America/New_York'); -- this should fail (the timezone offset is not known) INSERT INTO TIMETZ_TBL VALUES ('15:36:39 America/New_York'); ERROR: invalid input syntax for type time with time zone: "15:36:39 America/New_York" +LINE 1: INSERT INTO TIMETZ_TBL VALUES ('15:36:39 America/New_York'); + ^ SELECT f1 AS "Time TZ" FROM TIMETZ_TBL; Time TZ ---------------- diff --git a/src/test/regress/expected/tinterval.out b/src/test/regress/expected/tinterval.out index 1b4586b87a..89e850cf61 100644 --- a/src/test/regress/expected/tinterval.out +++ b/src/test/regress/expected/tinterval.out @@ -18,9 +18,13 @@ INSERT INTO TINTERVAL_TBL (f1) INSERT INTO TINTERVAL_TBL (f1) VALUES ('["bad time specifications" ""]'); ERROR: invalid input syntax for type abstime: "bad time specifications" +LINE 2: VALUES ('["bad time specifications" ""]'); + ^ INSERT INTO TINTERVAL_TBL (f1) VALUES ('["" "infinity"]'); ERROR: invalid input syntax for type abstime: "" +LINE 2: VALUES ('["" "infinity"]'); + ^ -- test tinterval operators SELECT '' AS five, * FROM TINTERVAL_TBL; five | f1 diff --git a/src/test/regress/expected/transactions.out b/src/test/regress/expected/transactions.out index 7c469f13c0..51bb3668f3 100644 --- a/src/test/regress/expected/transactions.out +++ b/src/test/regress/expected/transactions.out @@ -93,6 +93,8 @@ SELECT * FROM foo; -- should be empty SELECT * FROM bar; -- shouldn't exist ERROR: relation "bar" does not exist +LINE 1: SELECT * FROM bar; + ^ SELECT * FROM barbaz; -- should be empty a --- @@ -109,6 +111,8 @@ BEGIN; SAVEPOINT one; INSERT into bar VALUES (1); ERROR: relation "bar" does not exist +LINE 1: INSERT into bar VALUES (1); + ^ ROLLBACK TO one; RELEASE SAVEPOINT one; SAVEPOINT two; diff --git a/src/test/regress/expected/truncate.out b/src/test/regress/expected/truncate.out index c9134ee233..3055679f7e 100644 --- a/src/test/regress/expected/truncate.out +++ b/src/test/regress/expected/truncate.out @@ -257,3 +257,5 @@ SELECT * FROM truncate_a; DROP TABLE truncate_a; SELECT nextval('truncate_a_id1'); -- fail, seq should have been dropped ERROR: relation "truncate_a_id1" does not exist +LINE 1: SELECT nextval('truncate_a_id1'); + ^ diff --git a/src/test/regress/expected/txid.out b/src/test/regress/expected/txid.out index 59b629358a..930b86a656 100644 --- a/src/test/regress/expected/txid.out +++ b/src/test/regress/expected/txid.out @@ -15,14 +15,24 @@ select '12:18:14,16'::txid_snapshot; -- errors select '31:12:'::txid_snapshot; ERROR: invalid input for txid_snapshot: "31:12:" +LINE 1: select '31:12:'::txid_snapshot; + ^ select '0:1:'::txid_snapshot; ERROR: invalid input for txid_snapshot: "0:1:" +LINE 1: select '0:1:'::txid_snapshot; + ^ select '12:13:0'::txid_snapshot; ERROR: invalid input for txid_snapshot: "12:13:0" +LINE 1: select '12:13:0'::txid_snapshot; + ^ select '12:16:14,13'::txid_snapshot; ERROR: invalid input for txid_snapshot: "12:16:14,13" +LINE 1: select '12:16:14,13'::txid_snapshot; + ^ select '12:16:14,14'::txid_snapshot; ERROR: invalid input for txid_snapshot: "12:16:14,14" +LINE 1: select '12:16:14,14'::txid_snapshot; + ^ create temp table snapshot_test ( nr integer, snap txid_snapshot @@ -224,3 +234,5 @@ SELECT txid_snapshot '1:9223372036854775807:3'; SELECT txid_snapshot '1:9223372036854775808:3'; ERROR: invalid input for txid_snapshot: "1:9223372036854775808:3" +LINE 1: SELECT txid_snapshot '1:9223372036854775808:3'; + ^ diff --git a/src/test/regress/expected/uuid.out b/src/test/regress/expected/uuid.out index 179bf60d98..03bd73bd0c 100644 --- a/src/test/regress/expected/uuid.out +++ b/src/test/regress/expected/uuid.out @@ -14,19 +14,31 @@ CREATE TABLE guid2 -- too long INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111F'); ERROR: invalid input syntax for uuid: "11111111-1111-1111-1111-111111111111F" +LINE 1: INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-111... + ^ -- too short INSERT INTO guid1(guid_field) VALUES('{11111111-1111-1111-1111-11111111111}'); ERROR: invalid input syntax for uuid: "{11111111-1111-1111-1111-11111111111}" +LINE 1: INSERT INTO guid1(guid_field) VALUES('{11111111-1111-1111-11... + ^ -- valid data but invalid format INSERT INTO guid1(guid_field) VALUES('111-11111-1111-1111-1111-111111111111'); ERROR: invalid input syntax for uuid: "111-11111-1111-1111-1111-111111111111" +LINE 1: INSERT INTO guid1(guid_field) VALUES('111-11111-1111-1111-11... + ^ INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222 '); ERROR: invalid input syntax for uuid: "{22222222-2222-2222-2222-222222222222 " +LINE 1: INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-22... + ^ -- invalid data INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-G111-111111111111'); ERROR: invalid input syntax for uuid: "11111111-1111-1111-G111-111111111111" +LINE 1: INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-G11... + ^ INSERT INTO guid1(guid_field) VALUES('11+11111-1111-1111-1111-111111111111'); ERROR: invalid input syntax for uuid: "11+11111-1111-1111-1111-111111111111" +LINE 1: INSERT INTO guid1(guid_field) VALUES('11+11111-1111-1111-111... + ^ --inserting three input formats INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111'); INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222}'); diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out index f29c61b23c..fe5ccb8adc 100644 --- a/src/test/regress/expected/xml.out +++ b/src/test/regress/expected/xml.out @@ -6,6 +6,8 @@ INSERT INTO xmltest VALUES (1, 'one'); INSERT INTO xmltest VALUES (2, 'two'); INSERT INTO xmltest VALUES (3, '' IS NOT DOCUMENT; ERROR: invalid XML content +LINE 1: SELECT '<>' IS NOT DOCUMENT; + ^ DETAIL: Entity: line 1: parser error : StartTag: invalid element name <> ^ @@ -384,6 +390,8 @@ EXECUTE foo (''); EXECUTE foo ('bad'); ERROR: invalid XML document +LINE 1: EXECUTE foo ('bad'); + ^ DETAIL: Entity: line 1: parser error : Start tag expected, '<' not found bad ^ diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out index ff3bfb77bf..596031dd13 100644 --- a/src/test/regress/expected/xml_1.out +++ b/src/test/regress/expected/xml_1.out @@ -4,14 +4,20 @@ CREATE TABLE xmltest ( ); INSERT INTO xmltest VALUES (1, 'one'); ERROR: unsupported XML feature +LINE 1: INSERT INTO xmltest VALUES (1, 'one'); + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. INSERT INTO xmltest VALUES (2, 'two'); ERROR: unsupported XML feature +LINE 1: INSERT INTO xmltest VALUES (2, 'two'); + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. INSERT INTO xmltest VALUES (3, '', NULL, ''); ERROR: unsupported XML feature +LINE 1: SELECT xmlconcat('', NULL, '', NULL, ''); ERROR: unsupported XML feature +LINE 1: SELECT xmlconcat('', NULL, '', version no value, standalone no value); ERROR: unsupported XML feature +LINE 1: SELECT xmlroot(xml '', version no value, standalone no... + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xmlroot(xml '', version '2.0'); ERROR: unsupported XML feature +LINE 1: SELECT xmlroot(xml '', version '2.0'); + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xmlroot(xml '', version no value, standalone yes); ERROR: unsupported XML feature +LINE 1: SELECT xmlroot(xml '', version no value, standalone ye... + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xmlroot(xml '', version no value, standalone yes); ERROR: unsupported XML feature +LINE 1: SELECT xmlroot(xml '', version no... + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xmlroot(xmlroot(xml '', version '1.0'), version '1.1', standalone no); ERROR: unsupported XML feature +LINE 1: SELECT xmlroot(xmlroot(xml '', version '1.0'), version... + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xmlroot('', version no value, standalone no); ERROR: unsupported XML feature +LINE 1: SELECT xmlroot('... + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xmlroot('', version no value, standalone no value); ERROR: unsupported XML feature +LINE 1: SELECT xmlroot('... + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xmlroot('', version no value); ERROR: unsupported XML feature +LINE 1: SELECT xmlroot('... + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xmlroot ( @@ -235,30 +265,44 @@ SELECT xmlserialize(content data as character varying(20)) FROM xmltest; SELECT xmlserialize(content 'good' as char(10)); ERROR: unsupported XML feature +LINE 1: SELECT xmlserialize(content 'good' as char(10)); + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xmlserialize(document 'bad' as text); ERROR: unsupported XML feature +LINE 1: SELECT xmlserialize(document 'bad' as text); + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xml 'bar' IS DOCUMENT; ERROR: unsupported XML feature +LINE 1: SELECT xml 'bar' IS DOCUMENT; + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xml 'barfoo' IS DOCUMENT; ERROR: unsupported XML feature +LINE 1: SELECT xml 'barfoo' IS DOCUMENT; + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xml '' IS NOT DOCUMENT; ERROR: unsupported XML feature +LINE 1: SELECT xml '' IS NOT DOCUMENT; + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xml 'abc' IS NOT DOCUMENT; ERROR: unsupported XML feature +LINE 1: SELECT xml 'abc' IS NOT DOCUMENT; + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT '<>' IS NOT DOCUMENT; ERROR: unsupported XML feature +LINE 1: SELECT '<>' IS NOT DOCUMENT; + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xmlagg(data) FROM xmltest; @@ -288,6 +332,8 @@ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. PREPARE foo (xml) AS SELECT xmlconcat('', $1); ERROR: unsupported XML feature +LINE 1: PREPARE foo (xml) AS SELECT xmlconcat('', $1); + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SET XML OPTION DOCUMENT; @@ -304,6 +350,8 @@ ERROR: prepared statement "foo" does not exist CREATE VIEW xmlview1 AS SELECT xmlcomment('test'); CREATE VIEW xmlview2 AS SELECT xmlconcat('hello', 'you'); ERROR: unsupported XML feature +LINE 1: CREATE VIEW xmlview2 AS SELECT xmlconcat('hello', 'you'); + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. CREATE VIEW xmlview3 AS SELECT xmlelement(name element, xmlattributes (1 as ":one:", 'deuce' as two), 'content&'); @@ -321,14 +369,20 @@ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. CREATE VIEW xmlview7 AS SELECT xmlroot(xml '', version no value, standalone yes); ERROR: unsupported XML feature +LINE 1: CREATE VIEW xmlview7 AS SELECT xmlroot(xml '', version... + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. CREATE VIEW xmlview8 AS SELECT xmlserialize(content 'good' as char(10)); ERROR: unsupported XML feature +LINE 1: ...EATE VIEW xmlview8 AS SELECT xmlserialize(content 'good' as ... + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. CREATE VIEW xmlview9 AS SELECT xmlserialize(content 'good' as text); ERROR: unsupported XML feature +LINE 1: ...EATE VIEW xmlview9 AS SELECT xmlserialize(content 'good' as ... + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT table_name, view_definition FROM information_schema.views @@ -352,17 +406,25 @@ SELECT xpath(NULL, NULL) IS NULL FROM xmltest; SELECT xpath('', ''); ERROR: unsupported XML feature +LINE 1: SELECT xpath('', ''); + ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. SELECT xpath('//text()', 'number one'); ERROR: unsupported XML feature +LINE 1: SELECT xpath('//text()', 'number one', ARRAY[ARRAY['loc', 'http://127.0.0.1']]); ERROR: unsupported XML feature +LINE 1: SELECT xpath('//loc:piece/@id', '