diff options
Diffstat (limited to 'src/backend/parser')
| -rw-r--r-- | src/backend/parser/analyze.c | 26 | ||||
| -rw-r--r-- | src/backend/parser/gram.y | 221 | ||||
| -rw-r--r-- | src/backend/parser/parse_clause.c | 14 | ||||
| -rw-r--r-- | src/backend/parser/parse_expr.c | 162 | ||||
| -rw-r--r-- | src/backend/parser/parse_func.c | 62 | ||||
| -rw-r--r-- | src/backend/parser/parse_node.c | 37 | ||||
| -rw-r--r-- | src/backend/parser/parse_oper.c | 111 | ||||
| -rw-r--r-- | src/backend/parser/parse_relation.c | 46 | ||||
| -rw-r--r-- | src/backend/parser/parse_target.c | 12 | ||||
| -rw-r--r-- | src/backend/parser/parse_type.c | 38 | ||||
| -rw-r--r-- | src/backend/parser/scan.l | 103 |
11 files changed, 527 insertions, 305 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 645a740be0..1c4dc36303 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.330 2006/03/05 15:58:32 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.331 2006/03/14 22:48:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -146,6 +146,9 @@ static bool check_parameter_resolution_walker(Node *node, * parse_analyze * Analyze a raw parse tree and transform it to Query form. * + * If available, pass the source text from which the raw parse tree was + * generated; it's OK to pass NULL if this is not available. + * * Optionally, information about $n parameter types can be supplied. * References to $n indexes not defined by paramTypes[] are disallowed. * @@ -155,11 +158,13 @@ static bool check_parameter_resolution_walker(Node *node, * a dummy CMD_UTILITY Query node. */ List * -parse_analyze(Node *parseTree, Oid *paramTypes, int numParams) +parse_analyze(Node *parseTree, const char *sourceText, + Oid *paramTypes, int numParams) { ParseState *pstate = make_parsestate(NULL); List *result; + pstate->p_sourcetext = sourceText; pstate->p_paramtypes = paramTypes; pstate->p_numparams = numParams; pstate->p_variableparams = false; @@ -179,11 +184,13 @@ parse_analyze(Node *parseTree, Oid *paramTypes, int numParams) * be modified or enlarged (via repalloc). */ List * -parse_analyze_varparams(Node *parseTree, Oid **paramTypes, int *numParams) +parse_analyze_varparams(Node *parseTree, const char *sourceText, + Oid **paramTypes, int *numParams) { ParseState *pstate = make_parsestate(NULL); List *result; + pstate->p_sourcetext = sourceText; pstate->p_paramtypes = *paramTypes; pstate->p_numparams = *numParams; pstate->p_variableparams = true; @@ -921,6 +928,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, funccallnode->args = list_make1(snamenode); funccallnode->agg_star = false; funccallnode->agg_distinct = false; + funccallnode->location = -1; constraint = makeNode(Constraint); constraint->contype = CONSTR_DEFAULT; @@ -1097,7 +1105,6 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1]; char *attributeName = NameStr(attribute->attname); ColumnDef *def; - TypeName *typename; /* * Ignore dropped columns in the parent. @@ -1113,10 +1120,8 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, */ def = makeNode(ColumnDef); def->colname = pstrdup(attributeName); - typename = makeNode(TypeName); - typename->typeid = attribute->atttypid; - typename->typmod = attribute->atttypmod; - def->typename = typename; + def->typename = makeTypeNameFromOid(attribute->atttypid, + attribute->atttypmod); def->inhcount = 0; def->is_local = false; def->is_not_null = attribute->attnotnull; @@ -2608,7 +2613,7 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt) foreach(l, stmt->argtypes) { TypeName *tn = lfirst(l); - Oid toid = typenameTypeId(tn); + Oid toid = typenameTypeId(pstate, tn); argtoids[i++] = toid; } @@ -2621,6 +2626,7 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt) * from context. */ queries = parse_analyze_varparams((Node *) stmt->query, + pstate->p_sourcetext, &argtoids, &nargs); /* @@ -3029,7 +3035,7 @@ transformColumnType(ParseState *pstate, ColumnDef *column) /* * All we really need to do here is verify that the type is valid. */ - Type ctype = typenameType(column->typename); + Type ctype = typenameType(pstate, column->typename); ReleaseSysCache(ctype); } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index c86a6888f2..acaddb1365 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.534 2006/03/07 01:00:16 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.535 2006/03/14 22:48:20 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -61,6 +61,10 @@ #include "utils/numeric.h" +/* Location tracking support --- simpler than bison's default */ +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current = Rhs[1]; + extern List *parsetree; /* final parse result is delivered here */ static bool QueryIsRule = FALSE; @@ -72,7 +76,7 @@ static bool QueryIsRule = FALSE; */ /*#define __YYSCLASS*/ -static Node *makeColumnRef(char *relname, List *indirection); +static Node *makeColumnRef(char *relname, List *indirection, int location); static Node *makeTypeCast(Node *arg, TypeName *typename); static Node *makeStringConst(char *str, TypeName *typename); static Node *makeIntConst(int val); @@ -81,7 +85,7 @@ static Node *makeAConst(Value *v); static Node *makeRowNullTest(NullTestType test, RowExpr *row); static DefElem *makeDefElem(char *name, Node *arg); static A_Const *makeBoolAConst(bool state); -static FuncCall *makeOverlaps(List *largs, List *rargs); +static FuncCall *makeOverlaps(List *largs, List *rargs, int location); static void check_qualified_name(List *names); static List *check_func_name(List *names); static List *extractArgTypes(List *parameters); @@ -90,12 +94,13 @@ static void insertSelectOptions(SelectStmt *stmt, List *sortClause, Node *lockingClause, Node *limitOffset, Node *limitCount); static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg); -static Node *doNegate(Node *n); +static Node *doNegate(Node *n, int location); static void doNegateFloat(Value *v); %} %name-prefix="base_yy" +%locations %union { @@ -3705,6 +3710,7 @@ func_type: Typename { $$ = $1; } $$->names = lcons(makeString($1), $2); $$->pct_type = true; $$->typmod = -1; + $$->location = @1; } | SETOF type_name attrs '%' TYPE_P { @@ -3713,6 +3719,7 @@ func_type: Typename { $$ = $1; } $$->pct_type = true; $$->typmod = -1; $$->setof = TRUE; + $$->location = @2; } ; @@ -6053,6 +6060,7 @@ SimpleTypename: $$ = makeNode(TypeName); $$->names = lcons(makeString($1), $2); $$->typmod = -1; + $$->location = @1; } ; @@ -6077,6 +6085,7 @@ GenericType: type_name { $$ = makeTypeName($1); + $$->location = @1; } ; @@ -6540,6 +6549,7 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($5, $1); n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @2; $$ = (Node *) n; } /* @@ -6552,44 +6562,44 @@ a_expr: c_expr { $$ = $1; } * also to b_expr and to the MathOp list above. */ | '+' a_expr %prec UMINUS - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1); } | '-' a_expr %prec UMINUS - { $$ = doNegate($2); } + { $$ = doNegate($2, @1); } | a_expr '+' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2); } | a_expr '-' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2); } | a_expr '*' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2); } | a_expr '/' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2); } | a_expr '%' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2); } | a_expr '^' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2); } | a_expr '<' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2); } | a_expr '>' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); } | a_expr '=' a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); } | a_expr qual_Op a_expr %prec Op - { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3); } + { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2); } | qual_Op a_expr %prec Op - { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2); } + { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1); } | a_expr qual_Op %prec POSTFIXOP - { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL); } + { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2); } | a_expr AND a_expr - { $$ = (Node *) makeA_Expr(AEXPR_AND, NIL, $1, $3); } + { $$ = (Node *) makeA_Expr(AEXPR_AND, NIL, $1, $3, @2); } | a_expr OR a_expr - { $$ = (Node *) makeA_Expr(AEXPR_OR, NIL, $1, $3); } + { $$ = (Node *) makeA_Expr(AEXPR_OR, NIL, $1, $3, @2); } | NOT a_expr - { $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, $2); } + { $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, $2, @1); } | a_expr LIKE a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, $3, @2); } | a_expr LIKE a_expr ESCAPE a_expr { FuncCall *n = makeNode(FuncCall); @@ -6597,10 +6607,11 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($3, $5); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, (Node *) n); + n->location = @4; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, (Node *) n, @2); } | a_expr NOT LIKE a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, $4); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, $4, @2); } | a_expr NOT LIKE a_expr ESCAPE a_expr { FuncCall *n = makeNode(FuncCall); @@ -6608,10 +6619,11 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($4, $6); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, (Node *) n); + n->location = @5; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, (Node *) n, @2); } | a_expr ILIKE a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, $3, @2); } | a_expr ILIKE a_expr ESCAPE a_expr { FuncCall *n = makeNode(FuncCall); @@ -6619,10 +6631,11 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($3, $5); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, (Node *) n); + n->location = @4; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, (Node *) n, @2); } | a_expr NOT ILIKE a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, $4); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, $4, @2); } | a_expr NOT ILIKE a_expr ESCAPE a_expr { FuncCall *n = makeNode(FuncCall); @@ -6630,7 +6643,8 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($4, $6); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, (Node *) n); + n->location = @5; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, (Node *) n, @2); } | a_expr SIMILAR TO a_expr %prec SIMILAR @@ -6642,7 +6656,8 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($4, (Node *) c); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n); + n->location = @2; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n, @2); } | a_expr SIMILAR TO a_expr ESCAPE a_expr { @@ -6651,7 +6666,8 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($4, $6); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n); + n->location = @5; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n, @2); } | a_expr NOT SIMILAR TO a_expr %prec SIMILAR { @@ -6662,7 +6678,8 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($5, (Node *) c); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n); + n->location = @5; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2); } | a_expr NOT SIMILAR TO a_expr ESCAPE a_expr { @@ -6671,7 +6688,8 @@ a_expr: c_expr { $$ = $1; } n->args = list_make2($5, $7); n->agg_star = FALSE; n->agg_distinct = FALSE; - $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n); + n->location = @6; + $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2); } /* NullTest clause @@ -6733,7 +6751,7 @@ a_expr: c_expr { $$ = $1; } } | row OVERLAPS row { - $$ = (Node *)makeOverlaps($1, $3); + $$ = (Node *)makeOverlaps($1, $3, @2); } | a_expr IS TRUE_P { @@ -6779,54 +6797,63 @@ a_expr: c_expr { $$ = $1; } } | a_expr IS DISTINCT FROM a_expr %prec IS { - $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5); + $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5, @2); } | a_expr IS NOT DISTINCT FROM a_expr %prec IS { $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, - "=", $1, $6)); + "=", $1, $6, @2), + @2); } | a_expr IS OF '(' type_list ')' %prec IS { - $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5); + $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2); } | a_expr IS NOT OF '(' type_list ')' %prec IS { - $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6); + $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2); } | a_expr BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN { $$ = (Node *) makeA_Expr(AEXPR_AND, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4), - (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6)); + (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6, @2), + @2); } | a_expr NOT BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN { $$ = (Node *) makeA_Expr(AEXPR_OR, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5), - (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7)); + (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7, @2), + @2); } | a_expr BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN { $$ = (Node *) makeA_Expr(AEXPR_OR, NIL, (Node *) makeA_Expr(AEXPR_AND, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4), - (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6)), + (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6, @2), + @2), (Node *) makeA_Expr(AEXPR_AND, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $6), - (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $4))); + (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $6, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $4, @2), + @2), + @2); } | a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN { $$ = (Node *) makeA_Expr(AEXPR_AND, NIL, (Node *) makeA_Expr(AEXPR_OR, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5), - (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7)), + (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7, @2), + @2), (Node *) makeA_Expr(AEXPR_OR, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $7), - (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $5))); + (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $7, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $5, @2), + @2), + @2); } | a_expr IN_P in_expr { @@ -6843,7 +6870,7 @@ a_expr: c_expr { $$ = $1; } else { /* generate scalar IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3); + $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3, @2); } } | a_expr NOT IN_P in_expr @@ -6858,12 +6885,12 @@ a_expr: c_expr { $$ = $1; } n->testexpr = $1; n->operName = list_make1(makeString("=")); /* Stick a NOT on top */ - $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, (Node *) n); + $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, (Node *) n, @2); } else { /* generate scalar NOT IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4); + $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4, @2); } } | a_expr subquery_Op sub_type select_with_parens %prec Op @@ -6878,9 +6905,9 @@ a_expr: c_expr { $$ = $1; } | a_expr subquery_Op sub_type '(' a_expr ')' %prec Op { if ($3 == ANY_SUBLINK) - $$ = (Node *) makeA_Expr(AEXPR_OP_ANY, $2, $1, $5); + $$ = (Node *) makeA_Expr(AEXPR_OP_ANY, $2, $1, $5, @2); else - $$ = (Node *) makeA_Expr(AEXPR_OP_ALL, $2, $1, $5); + $$ = (Node *) makeA_Expr(AEXPR_OP_ALL, $2, $1, $5, @2); } | UNIQUE select_with_parens { @@ -6913,49 +6940,49 @@ b_expr: c_expr | b_expr TYPECAST Typename { $$ = makeTypeCast($1, $3); } | '+' b_expr %prec UMINUS - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1); } | '-' b_expr %prec UMINUS - { $$ = doNegate($2); } + { $$ = doNegate($2, @1); } | b_expr '+' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2); } | b_expr '-' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2); } | b_expr '*' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2); } | b_expr '/' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2); } | b_expr '%' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2); } | b_expr '^' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2); } | b_expr '<' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2); } | b_expr '>' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); } | b_expr '=' b_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3); } + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); } | b_expr qual_Op b_expr %prec Op - { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3); } + { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2); } | qual_Op b_expr %prec Op - { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2); } + { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1); } | b_expr qual_Op %prec POSTFIXOP - { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL); } + { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2); } | b_expr IS DISTINCT FROM b_expr %prec IS { - $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5); + $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5, @2); } | b_expr IS NOT DISTINCT FROM b_expr %prec IS { $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, - NULL, (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $6)); + NULL, (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $6, @2), @2); } | b_expr IS OF '(' type_list ')' %prec IS { - $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5); + $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2); } | b_expr IS NOT OF '(' type_list ')' %prec IS { - $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6); + $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2); } ; @@ -7052,6 +7079,7 @@ func_expr: func_name '(' ')' n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | func_name '(' expr_list ')' @@ -7061,6 +7089,7 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | func_name '(' ALL expr_list ')' @@ -7074,6 +7103,7 @@ func_expr: func_name '(' ')' * "must be an aggregate", but there's no provision * for that in FuncCall at the moment. */ + n->location = @1; $$ = (Node *)n; } | func_name '(' DISTINCT expr_list ')' @@ -7083,6 +7113,7 @@ func_expr: func_name '(' ')' n->args = $4; n->agg_star = FALSE; n->agg_distinct = TRUE; + n->location = @1; $$ = (Node *)n; } | func_name '(' '*' ')' @@ -7108,6 +7139,7 @@ func_expr: func_name '(' ')' n->args = list_make1(star); n->agg_star = TRUE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | CURRENT_DATE @@ -7196,6 +7228,7 @@ func_expr: func_name '(' ')' n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | CURRENT_TIMESTAMP '(' Iconst ')' @@ -7331,6 +7364,7 @@ func_expr: func_name '(' ')' n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | CURRENT_USER @@ -7340,6 +7374,7 @@ func_expr: func_name '(' ')' n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | SESSION_USER @@ -7349,6 +7384,7 @@ func_expr: func_name '(' ')' n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | USER @@ -7358,6 +7394,7 @@ func_expr: func_name '(' ')' n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | CAST '(' a_expr AS Typename ')' @@ -7369,6 +7406,7 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | OVERLAY '(' overlay_list ')' @@ -7383,6 +7421,7 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | POSITION '(' position_list ')' @@ -7393,6 +7432,7 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | SUBSTRING '(' substr_list ')' @@ -7405,6 +7445,7 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | TREAT '(' a_expr AS Typename ')' @@ -7413,7 +7454,7 @@ func_expr: func_name '(' ')' * which is defined to be a subtype of the original expression. * In SQL99, this is intended for use with structured UDTs, * but let's make this a generally useful form allowing stronger - * coersions than are handled by implicit casting. + * coercions than are handled by implicit casting. */ FuncCall *n = makeNode(FuncCall); /* Convert SystemTypeName() to SystemFuncName() even though @@ -7421,6 +7462,9 @@ func_expr: func_name '(' ')' */ n->funcname = SystemFuncName(((Value *)llast($5->names))->val.str); n->args = list_make1($3); + n->agg_star = FALSE; + n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | TRIM '(' BOTH trim_list ')' @@ -7433,6 +7477,7 @@ func_expr: func_name '(' ')' n->args = $4; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | TRIM '(' LEADING trim_list ')' @@ -7442,6 +7487,7 @@ func_expr: func_name '(' ')' n->args = $4; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | TRIM '(' TRAILING trim_list ')' @@ -7451,6 +7497,7 @@ func_expr: func_name '(' ')' n->args = $4; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | TRIM '(' trim_list ')' @@ -7460,6 +7507,7 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | CONVERT '(' a_expr USING any_name ')' @@ -7474,6 +7522,7 @@ func_expr: func_name '(' ')' n->args = list_make2($3, c); n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | CONVERT '(' expr_list ')' @@ -7483,11 +7532,12 @@ func_expr: func_name '(' ')' n->args = $3; n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = @1; $$ = (Node *)n; } | NULLIF '(' a_expr ',' a_expr ')' { - $$ = (Node *) makeSimpleA_Expr(AEXPR_NULLIF, "=", $3, $5); + $$ = (Node *) makeSimpleA_Expr(AEXPR_NULLIF, "=", $3, $5, @1); } | COALESCE '(' expr_list ')' { @@ -7797,11 +7847,11 @@ case_arg: a_expr { $$ = $1; } */ columnref: relation_name { - $$ = makeColumnRef($1, NIL); + $$ = makeColumnRef($1, NIL, @1); } | relation_name indirection { - $$ = makeColumnRef($1, $2); + $$ = makeColumnRef($1, $2, @1); } ; @@ -7875,6 +7925,7 @@ target_el: a_expr AS ColLabel { ColumnRef *n = makeNode(ColumnRef); n->fields = list_make1(makeString("*")); + n->location = @1; $$ = makeNode(ResTarget); $$->name = NULL; @@ -8585,7 +8636,7 @@ SpecialRuleRelation: %% static Node * -makeColumnRef(char *relname, List *indirection) +makeColumnRef(char *relname, List *indirection, int location) { /* * Generate a ColumnRef node, with an A_Indirection node added if there @@ -8597,6 +8648,7 @@ makeColumnRef(char *relname, List *indirection) int nfields = 0; ListCell *l; + c->location = location; foreach(l, indirection) { if (IsA(lfirst(l), A_Indices)) @@ -8750,9 +8802,9 @@ makeRowNullTest(NullTestType test, RowExpr *row) if (result == NULL) result = (Node *) n; else if (test == IS_NOT_NULL) - result = (Node *) makeA_Expr(AEXPR_OR, NIL, result, (Node *)n); + result = (Node *) makeA_Expr(AEXPR_OR, NIL, result, (Node *)n, -1); else - result = (Node *) makeA_Expr(AEXPR_AND, NIL, result, (Node *)n); + result = (Node *) makeA_Expr(AEXPR_AND, NIL, result, (Node *)n, -1); } if (result == NULL) @@ -8768,9 +8820,10 @@ makeRowNullTest(NullTestType test, RowExpr *row) * Create and populate a FuncCall node to support the OVERLAPS operator. */ static FuncCall * -makeOverlaps(List *largs, List *rargs) +makeOverlaps(List *largs, List *rargs, int location) { FuncCall *n = makeNode(FuncCall); + n->funcname = SystemFuncName("overlaps"); if (list_length(largs) == 1) largs = lappend(largs, largs); @@ -8787,6 +8840,7 @@ makeOverlaps(List *largs, List *rargs) n->args = list_concat(largs, rargs); n->agg_star = FALSE; n->agg_distinct = FALSE; + n->location = location; return n; } @@ -8944,6 +8998,7 @@ SystemTypeName(char *name) n->names = list_make2(makeString("pg_catalog"), makeString(name)); n->typmod = -1; + n->location = -1; return n; } @@ -8987,7 +9042,7 @@ exprIsNullConstant(Node *arg) * until we know what the desired type is. */ static Node * -doNegate(Node *n) +doNegate(Node *n, int location) { if (IsA(n, A_Const)) { @@ -9005,7 +9060,7 @@ doNegate(Node *n) } } - return (Node *) makeSimpleA_Expr(AEXPR_OP, "-", NULL, n); + return (Node *) makeSimpleA_Expr(AEXPR_OP, "-", NULL, n, location); } static void diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index fdc2e41b3a..4384a4eaab 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.147 2006/03/05 21:34:34 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.148 2006/03/14 22:48:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -303,7 +303,9 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars) Node *rvar = (Node *) lfirst(rvars); A_Expr *e; - e = makeSimpleA_Expr(AEXPR_OP, "=", copyObject(lvar), copyObject(rvar)); + e = makeSimpleA_Expr(AEXPR_OP, "=", + copyObject(lvar), copyObject(rvar), + -1); if (result == NULL) result = (Node *) e; @@ -311,7 +313,7 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars) { A_Expr *a; - a = makeA_Expr(AEXPR_AND, NIL, result, (Node *) e); + a = makeA_Expr(AEXPR_AND, NIL, result, (Node *) e, -1); result = (Node *) a; } } @@ -1182,6 +1184,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause) list_length(((ColumnRef *) node)->fields) == 1) { char *name = strVal(linitial(((ColumnRef *) node)->fields)); + int location = ((ColumnRef *) node)->location; if (clause == GROUP_CLAUSE) { @@ -1201,7 +1204,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause) * breaks no cases that are legal per spec, and it seems a more * self-consistent behavior. */ - if (colNameToVar(pstate, name, true) != NULL) + if (colNameToVar(pstate, name, true, location) != NULL) name = NULL; } @@ -1225,7 +1228,8 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause) * construct, eg ORDER BY */ errmsg("%s \"%s\" is ambiguous", - clauseText[clause], name))); + clauseText[clause], name), + parser_errposition(pstate, location))); } else target_result = tle; diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index ab4d681fdf..cae682c9e7 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.190 2006/03/05 15:58:33 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.191 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,18 +57,18 @@ static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m); static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b); static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref); static Node *transformWholeRowRef(ParseState *pstate, char *schemaname, - char *relname); + char *relname, int location); static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b); static Node *transformIndirection(ParseState *pstate, Node *basenode, List *indirection); static Node *typecast_expression(ParseState *pstate, Node *expr, TypeName *typename); static Node *make_row_comparison_op(ParseState *pstate, List *opname, - List *largs, List *rargs); + List *largs, List *rargs, int location); static Node *make_row_distinct_op(ParseState *pstate, List *opname, - RowExpr *lrow, RowExpr *rrow); + RowExpr *lrow, RowExpr *rrow, int location); static Expr *make_distinct_op(ParseState *pstate, List *opname, - Node *ltree, Node *rtree); + Node *ltree, Node *rtree, int location); /* @@ -308,7 +308,8 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection) result = ParseFuncOrColumn(pstate, list_make1(n), list_make1(result), - false, false, true); + false, false, true, + -1); } } /* process trailing subscripts, if any */ @@ -361,7 +362,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) char *name = strVal(linitial(cref->fields)); /* Try to identify as an unqualified column */ - node = colNameToVar(pstate, name, false); + node = colNameToVar(pstate, name, false, cref->location); if (node == NULL) { @@ -391,12 +392,14 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) */ if (refnameRangeTblEntry(pstate, NULL, name, &levels_up) != NULL) - node = transformWholeRowRef(pstate, NULL, name); + node = transformWholeRowRef(pstate, NULL, name, + cref->location); else ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" does not exist", - name))); + name), + parser_errposition(pstate, cref->location))); } break; } @@ -408,12 +411,14 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) /* Whole-row reference? */ if (strcmp(name2, "*") == 0) { - node = transformWholeRowRef(pstate, NULL, name1); + node = transformWholeRowRef(pstate, NULL, name1, + cref->location); break; } /* Try to identify as a once-qualified column */ - node = qualifiedNameToVar(pstate, NULL, name1, name2, true); + node = qualifiedNameToVar(pstate, NULL, name1, name2, true, + cref->location); if (node == NULL) { /* @@ -421,11 +426,13 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) * it as a function call. Here, we will create an * implicit RTE for tables not already entered. */ - node = transformWholeRowRef(pstate, NULL, name1); + node = transformWholeRowRef(pstate, NULL, name1, + cref->location); node = ParseFuncOrColumn(pstate, list_make1(makeString(name2)), list_make1(node), - false, false, true); + false, false, true, + cref->location); } break; } @@ -438,20 +445,24 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) /* Whole-row reference? */ if (strcmp(name3, "*") == 0) { - node = transformWholeRowRef(pstate, name1, name2); + node = transformWholeRowRef(pstate, name1, name2, + cref->location); break; } /* Try to identify as a twice-qualified column */ - node = qualifiedNameToVar(pstate, name1, name2, name3, true); + node = qualifiedNameToVar(pstate, name1, name2, name3, true, + cref->location); if (node == NULL) { /* Try it as a function call */ - node = transformWholeRowRef(pstate, name1, name2); + node = transformWholeRowRef(pstate, name1, name2, + cref->location); node = ParseFuncOrColumn(pstate, list_make1(makeString(name3)), list_make1(node), - false, false, true); + false, false, true, + cref->location); } break; } @@ -469,25 +480,30 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cross-database references are not implemented: %s", - NameListToString(cref->fields)))); + NameListToString(cref->fields)), + parser_errposition(pstate, cref->location))); /* Whole-row reference? */ if (strcmp(name4, "*") == 0) { - node = transformWholeRowRef(pstate, name2, name3); + node = transformWholeRowRef(pstate, name2, name3, + cref->location); break; } /* Try to identify as a twice-qualified column */ - node = qualifiedNameToVar(pstate, name2, name3, name4, true); + node = qualifiedNameToVar(pstate, name2, name3, name4, true, + cref->location); if (node == NULL) { /* Try it as a function call */ - node = transformWholeRowRef(pstate, name2, name3); + node = transformWholeRowRef(pstate, name2, name3, + cref->location); node = ParseFuncOrColumn(pstate, list_make1(makeString(name4)), list_make1(node), - false, false, true); + false, false, true, + cref->location); } break; } @@ -495,7 +511,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper qualified name (too many dotted names): %s", - NameListToString(cref->fields)))); + NameListToString(cref->fields)), + parser_errposition(pstate, cref->location))); node = NULL; /* keep compiler quiet */ break; } @@ -614,7 +631,8 @@ transformAExprOp(ParseState *pstate, A_Expr *a) result = make_row_comparison_op(pstate, a->name, ((RowExpr *) lexpr)->args, - ((RowExpr *) rexpr)->args); + ((RowExpr *) rexpr)->args, + a->location); } else { @@ -625,7 +643,8 @@ transformAExprOp(ParseState *pstate, A_Expr *a) result = (Node *) make_op(pstate, a->name, lexpr, - rexpr); + rexpr, + a->location); } return result; @@ -678,7 +697,8 @@ transformAExprOpAny(ParseState *pstate, A_Expr *a) a->name, true, lexpr, - rexpr); + rexpr, + a->location); } static Node * @@ -691,7 +711,8 @@ transformAExprOpAll(ParseState *pstate, A_Expr *a) a->name, false, lexpr, - rexpr); + rexpr, + a->location); } static Node * @@ -706,7 +727,8 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a) /* "row op row" */ return make_row_distinct_op(pstate, a->name, (RowExpr *) lexpr, - (RowExpr *) rexpr); + (RowExpr *) rexpr, + a->location); } else { @@ -714,7 +736,8 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a) return (Node *) make_distinct_op(pstate, a->name, lexpr, - rexpr); + rexpr, + a->location); } } @@ -728,11 +751,13 @@ transformAExprNullIf(ParseState *pstate, A_Expr *a) result = (Node *) make_op(pstate, a->name, lexpr, - rexpr); + rexpr, + a->location); if (((OpExpr *) result)->opresulttype != BOOLOID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("NULLIF requires = operator to yield boolean"))); + errmsg("NULLIF requires = operator to yield boolean"), + parser_errposition(pstate, a->location))); /* * We rely on NullIfExpr and OpExpr being the same struct @@ -758,7 +783,7 @@ transformAExprOf(ParseState *pstate, A_Expr *a) ltype = exprType(lexpr); foreach(telem, (List *) a->rexpr) { - rtype = LookupTypeName(lfirst(telem)); + rtype = typenameTypeId(pstate, lfirst(telem)); matched = (rtype == ltype); if (matched) break; @@ -864,7 +889,8 @@ transformAExprIn(ParseState *pstate, A_Expr *a) a->name, useOr, lexpr, - (Node *) newa); + (Node *) newa, + a->location); } } @@ -883,17 +909,20 @@ transformAExprIn(ParseState *pstate, A_Expr *a) !IsA(rexpr, RowExpr)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("arguments of row IN must all be row expressions"))); + errmsg("arguments of row IN must all be row expressions"), + parser_errposition(pstate, a->location))); cmp = make_row_comparison_op(pstate, a->name, (List *) copyObject(((RowExpr *) lexpr)->args), - ((RowExpr *) rexpr)->args); + ((RowExpr *) rexpr)->args, + a->location); } else cmp = (Node *) make_op(pstate, a->name, copyObject(lexpr), - rexpr); + rexpr, + a->location); cmp = coerce_to_boolean(pstate, cmp, "IN"); if (result == NULL) @@ -931,7 +960,8 @@ transformFuncCall(ParseState *pstate, FuncCall *fn) targs, fn->agg_star, fn->agg_distinct, - false); + false, + fn->location); } static Node * @@ -994,7 +1024,8 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c) /* shorthand form was specified, so expand... */ warg = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) placeholder, - warg); + warg, + -1); } neww->expr = (Expr *) transformExpr(pstate, warg); @@ -1173,7 +1204,8 @@ transformSubLink(ParseState *pstate, SubLink *sublink) sublink->testexpr = make_row_comparison_op(pstate, sublink->operName, left_list, - right_list); + right_list, + -1); } return result; @@ -1394,7 +1426,8 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b) * a rowtype; either a named composite type, or RECORD. */ static Node * -transformWholeRowRef(ParseState *pstate, char *schemaname, char *relname) +transformWholeRowRef(ParseState *pstate, char *schemaname, char *relname, + int location) { Node *result; RangeTblEntry *rte; @@ -1408,7 +1441,8 @@ transformWholeRowRef(ParseState *pstate, char *schemaname, char *relname) &sublevels_up); if (rte == NULL) - rte = addImplicitRTE(pstate, makeRangeVar(schemaname, relname)); + rte = addImplicitRTE(pstate, makeRangeVar(schemaname, relname), + location); vnum = RTERangeTablePosn(pstate, rte, &sublevels_up); @@ -1877,7 +1911,7 @@ typecast_expression(ParseState *pstate, Node *expr, TypeName *typename) Oid inputType = exprType(expr); Oid targetType; - targetType = typenameTypeId(typename); + targetType = typenameTypeId(pstate, typename); if (inputType == InvalidOid) return expr; /* do nothing if NULL input */ @@ -1891,7 +1925,8 @@ typecast_expression(ParseState *pstate, Node *expr, TypeName *typename) (errcode(ERRCODE_CANNOT_COERCE), errmsg("cannot cast type %s to %s", format_type_be(inputType), - format_type_be(targetType)))); + format_type_be(targetType)), + parser_errposition(pstate, typename->location))); return expr; } @@ -1910,7 +1945,7 @@ typecast_expression(ParseState *pstate, Node *expr, TypeName *typename) */ static Node * make_row_comparison_op(ParseState *pstate, List *opname, - List *largs, List *rargs) + List *largs, List *rargs, int location) { RowCompareExpr *rcexpr; RowCompareType rctype; @@ -1929,7 +1964,8 @@ make_row_comparison_op(ParseState *pstate, List *opname, if (nopers != list_length(rargs)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("unequal number of entries in row expressions"))); + errmsg("unequal number of entries in row expressions"), + parser_errposition(pstate, location))); /* * We can't compare zero-length rows because there is no principled @@ -1938,7 +1974,8 @@ make_row_comparison_op(ParseState *pstate, List *opname, if (nopers == 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot compare rows of zero length"))); + errmsg("cannot compare rows of zero length"), + parser_errposition(pstate, location))); /* * Identify all the pairwise operators, using make_op so that @@ -1951,7 +1988,7 @@ make_row_comparison_op(ParseState *pstate, List *opname, Node *rarg = (Node *) lfirst(r); OpExpr *cmp; - cmp = (OpExpr *) make_op(pstate, opname, larg, rarg); + cmp = (OpExpr *) make_op(pstate, opname, larg, rarg, location); Assert(IsA(cmp, OpExpr)); /* @@ -1964,11 +2001,13 @@ make_row_comparison_op(ParseState *pstate, List *opname, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("row comparison operator must yield type boolean, " "not type %s", - format_type_be(cmp->opresulttype)))); + format_type_be(cmp->opresulttype)), + parser_errposition(pstate, location))); if (expression_returns_set((Node *) cmp)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("row comparison operator must not return a set"))); + errmsg("row comparison operator must not return a set"), + parser_errposition(pstate, location))); opexprs = lappend(opexprs, cmp); } @@ -2021,7 +2060,8 @@ make_row_comparison_op(ParseState *pstate, List *opname, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("could not determine interpretation of row comparison operator %s", strVal(llast(opname))), - errhint("Row comparison operators must be associated with btree operator classes."))); + errhint("Row comparison operators must be associated with btree operator classes."), + parser_errposition(pstate, location))); rctype = 0; /* keep compiler quiet */ break; case BMS_SINGLETON: @@ -2069,7 +2109,8 @@ make_row_comparison_op(ParseState *pstate, List *opname, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("could not determine interpretation of row comparison operator %s", strVal(llast(opname))), - errdetail("There are multiple equally-plausible candidates."))); + errdetail("There are multiple equally-plausible candidates."), + parser_errposition(pstate, location))); break; } } @@ -2120,7 +2161,8 @@ make_row_comparison_op(ParseState *pstate, List *opname, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("could not determine interpretation of row comparison operator %s", strVal(llast(opname))), - errdetail("There are multiple equally-plausible candidates."))); + errdetail("There are multiple equally-plausible candidates."), + parser_errposition(pstate, location))); } /* @@ -2158,7 +2200,8 @@ make_row_comparison_op(ParseState *pstate, List *opname, */ static Node * make_row_distinct_op(ParseState *pstate, List *opname, - RowExpr *lrow, RowExpr *rrow) + RowExpr *lrow, RowExpr *rrow, + int location) { Node *result = NULL; List *largs = lrow->args; @@ -2169,7 +2212,8 @@ make_row_distinct_op(ParseState *pstate, List *opname, if (list_length(largs) != list_length(rargs)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("unequal number of entries in row expressions"))); + errmsg("unequal number of entries in row expressions"), + parser_errposition(pstate, location))); forboth(l, largs, r, rargs) { @@ -2177,7 +2221,7 @@ make_row_distinct_op(ParseState *pstate, List *opname, Node *rarg = (Node *) lfirst(r); Node *cmp; - cmp = (Node *) make_distinct_op(pstate, opname, larg, rarg); + cmp = (Node *) make_distinct_op(pstate, opname, larg, rarg, location); if (result == NULL) result = cmp; else @@ -2198,15 +2242,17 @@ make_row_distinct_op(ParseState *pstate, List *opname, * make the node for an IS DISTINCT FROM operator */ static Expr * -make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree) +make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree, + int location) { Expr *result; - result = make_op(pstate, opname, ltree, rtree); + result = make_op(pstate, opname, ltree, rtree, location); if (((OpExpr *) result)->opresulttype != BOOLOID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("IS DISTINCT FROM requires = operator to yield boolean"))); + errmsg("IS DISTINCT FROM requires = operator to yield boolean"), + parser_errposition(pstate, location))); /* * We rely on DistinctExpr and OpExpr being same struct diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index d6b4307a61..35e826881f 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.184 2006/03/05 15:58:33 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.185 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,8 +34,9 @@ static Node *ParseComplexProjection(ParseState *pstate, char *funcname, - Node *first_arg); -static void unknown_attribute(ParseState *pstate, Node *relref, char *attname); + Node *first_arg, int location); +static void unknown_attribute(ParseState *pstate, Node *relref, char *attname, + int location); /* @@ -59,7 +60,8 @@ static void unknown_attribute(ParseState *pstate, Node *relref, char *attname); */ Node * ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, - bool agg_star, bool agg_distinct, bool is_column) + bool agg_star, bool agg_distinct, bool is_column, + int location) { Oid rettype; Oid funcid; @@ -83,7 +85,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, ereport(ERROR, (errcode(ERRCODE_TOO_MANY_ARGUMENTS), errmsg("cannot pass more than %d arguments to a function", - FUNC_MAX_ARGS))); + FUNC_MAX_ARGS), + parser_errposition(pstate, location))); /* * Extract arg type info in preparation for function lookup. @@ -131,7 +134,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, { retval = ParseComplexProjection(pstate, strVal(linitial(funcname)), - first_arg); + first_arg, + location); if (retval) return retval; @@ -174,12 +178,14 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("%s(*) specified, but %s is not an aggregate function", NameListToString(funcname), - NameListToString(funcname)))); + NameListToString(funcname)), + parser_errposition(pstate, location))); if (agg_distinct) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("DISTINCT specified, but %s is not an aggregate function", - NameListToString(funcname)))); + NameListToString(funcname)), + parser_errposition(pstate, location))); } else if (fdresult != FUNCDETAIL_AGGREGATE) { @@ -193,7 +199,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, { Assert(nargs == 1); Assert(list_length(funcname) == 1); - unknown_attribute(pstate, first_arg, strVal(linitial(funcname))); + unknown_attribute(pstate, first_arg, strVal(linitial(funcname)), + location); } /* @@ -206,7 +213,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, func_signature_string(funcname, nargs, actual_arg_types)), errhint("Could not choose a best candidate function. " - "You may need to add explicit type casts."))); + "You may need to add explicit type casts."), + parser_errposition(pstate, location))); else ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), @@ -214,7 +222,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, func_signature_string(funcname, nargs, actual_arg_types)), errhint("No function matches the given name and argument types. " - "You may need to add explicit type casts."))); + "You may need to add explicit type casts."), + parser_errposition(pstate, location))); } /* @@ -262,7 +271,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, if (retset) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("aggregates may not return sets"))); + errmsg("aggregates may not return sets"), + parser_errposition(pstate, location))); } return retval; @@ -726,11 +736,9 @@ func_get_detail(List *funcname, if (nargs == 1 && fargs != NIL) { Oid targetType; - TypeName *tn = makeNode(TypeName); - tn->names = funcname; - tn->typmod = -1; - targetType = LookupTypeName(tn); + targetType = LookupTypeName(NULL, + makeTypeNameFromNameList(funcname)); if (OidIsValid(targetType) && !ISCOMPLEX(targetType)) { @@ -953,7 +961,8 @@ make_fn_arguments(ParseState *pstate, * transformed expression tree. If not, return NULL. */ static Node * -ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg) +ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg, + int location) { TupleDesc tupdesc; int i; @@ -977,7 +986,7 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg) ((Var *) first_arg)->varno, ((Var *) first_arg)->varlevelsup); /* Return a Var if funcname matches a column, else NULL */ - return scanRTEForColumn(pstate, rte, funcname); + return scanRTEForColumn(pstate, rte, funcname, location); } /* @@ -1019,7 +1028,8 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg) * helper routine for delivering "column does not exist" error message */ static void -unknown_attribute(ParseState *pstate, Node *relref, char *attname) +unknown_attribute(ParseState *pstate, Node *relref, char *attname, + int location) { RangeTblEntry *rte; @@ -1033,7 +1043,8 @@ unknown_attribute(ParseState *pstate, Node *relref, char *attname) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column %s.%s does not exist", - rte->eref->aliasname, attname))); + rte->eref->aliasname, attname), + parser_errposition(pstate, location))); } else { @@ -1044,18 +1055,21 @@ unknown_attribute(ParseState *pstate, Node *relref, char *attname) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" not found in data type %s", - attname, format_type_be(relTypeId)))); + attname, format_type_be(relTypeId)), + parser_errposition(pstate, location))); else if (relTypeId == RECORDOID) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("could not identify column \"%s\" in record data type", - attname))); + attname), + parser_errposition(pstate, location))); else ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("column notation .%s applied to type %s, " "which is not a composite type", - attname, format_type_be(relTypeId)))); + attname, format_type_be(relTypeId)), + parser_errposition(pstate, location))); } } @@ -1219,7 +1233,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError) { TypeName *t = (TypeName *) lfirst(args_item); - argoids[i] = LookupTypeName(t); + argoids[i] = LookupTypeName(NULL, t); if (!OidIsValid(argoids[i])) ereport(ERROR, diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index 2ac869c9fc..23d73a13f2 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -8,13 +8,14 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.91 2006/03/05 15:58:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.92 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "catalog/pg_type.h" +#include "mb/pg_wchar.h" #include "nodes/makefuncs.h" #include "parser/parsetree.h" #include "parser/parse_coerce.h" @@ -44,13 +45,47 @@ make_parsestate(ParseState *parentParseState) pstate->p_next_resno = 1; if (parentParseState) + { + pstate->p_sourcetext = parentParseState->p_sourcetext; pstate->p_variableparams = parentParseState->p_variableparams; + } return pstate; } /* + * parser_errposition + * Report a parse-analysis-time cursor position, if possible. + * + * This is expected to be used within an ereport() call. The return value + * is a dummy (always 0, in fact). + * + * The locations stored in raw parsetrees are byte offsets into the source + * string. We have to convert them to 1-based character indexes for reporting + * to clients. (We do things this way to avoid unnecessary overhead in the + * normal non-error case: computing character indexes would be much more + * expensive than storing token offsets.) + */ +int +parser_errposition(ParseState *pstate, int location) +{ + int pos; + + /* No-op if location was not provided */ + if (location < 0) + return 0; + /* Can't do anything if source text is not available */ + if (pstate == NULL || pstate->p_sourcetext == NULL) + return 0; + /* Convert offset to character number */ + pos = pg_mbstrlen_with_len(pstate->p_sourcetext, location) + 1; + /* And pass it to the ereport mechanism */ + return errposition(pos); +} + + +/* * make_var * Build a Var node for an attribute identified by RTE and attrno */ diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index 2bd65b2e12..e483372e85 100644 --- a/src/backend/parser/parse_oper.c +++ b/src/backend/parser/parse_oper.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.85 2006/03/05 15:58:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.86 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,8 +37,9 @@ static FuncDetailCode oper_select_candidate(int nargs, Oid *operOid); static const char *op_signature_string(List *op, char oprkind, Oid arg1, Oid arg2); -static void op_error(List *op, char oprkind, Oid arg1, Oid arg2, - FuncDetailCode fdresult); +static void op_error(ParseState *pstate, List *op, char oprkind, + Oid arg1, Oid arg2, + FuncDetailCode fdresult, int location); static Expr *make_op_expr(ParseState *pstate, Operator op, Node *ltree, Node *rtree, Oid ltypeId, Oid rtypeId); @@ -56,10 +57,12 @@ static Expr *make_op_expr(ParseState *pstate, Operator op, * namespace search path. * * If the operator is not found, we return InvalidOid if noError is true, - * else raise an error. + * else raise an error. pstate and location are used only to report the + * error position; pass NULL/-1 if not available. */ Oid -LookupOperName(List *opername, Oid oprleft, Oid oprright, bool noError) +LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, + bool noError, int location) { FuncCandidateList clist; char oprkind; @@ -86,7 +89,8 @@ LookupOperName(List *opername, Oid oprleft, Oid oprright, bool noError) (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("operator does not exist: %s", op_signature_string(opername, oprkind, - oprleft, oprright)))); + oprleft, oprright)), + parser_errposition(pstate, location))); return InvalidOid; } @@ -99,8 +103,9 @@ LookupOperName(List *opername, Oid oprleft, Oid oprright, bool noError) * Pass oprleft = NULL for a prefix op, oprright = NULL for a postfix op. */ Oid -LookupOperNameTypeNames(List *opername, TypeName *oprleft, - TypeName *oprright, bool noError) +LookupOperNameTypeNames(ParseState *pstate, List *opername, + TypeName *oprleft, TypeName *oprright, + bool noError, int location) { Oid leftoid, rightoid; @@ -108,27 +113,15 @@ LookupOperNameTypeNames(List *opername, TypeName *oprleft, if (oprleft == NULL) leftoid = InvalidOid; else - { - leftoid = LookupTypeName(oprleft); - if (!OidIsValid(leftoid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type %s does not exist", - TypeNameToString(oprleft)))); - } + leftoid = typenameTypeId(pstate, oprleft); + if (oprright == NULL) rightoid = InvalidOid; else - { - rightoid = LookupTypeName(oprright); - if (!OidIsValid(rightoid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type %s does not exist", - TypeNameToString(oprright)))); - } + rightoid = typenameTypeId(pstate, oprright); - return LookupOperName(opername, leftoid, rightoid, noError); + return LookupOperName(pstate, opername, leftoid, rightoid, + noError, location); } /* @@ -500,13 +493,15 @@ oper_select_candidate(int nargs, * you need an exact- or binary-compatible match; see compatible_oper. * * If no matching operator found, return NULL if noError is true, - * raise an error if it is false. + * raise an error if it is false. pstate and location are used only to report + * the error position; pass NULL/-1 if not available. * * NOTE: on success, the returned object is a syscache entry. The caller * must ReleaseSysCache() the entry when done with it. */ Operator -oper(List *opname, Oid ltypeId, Oid rtypeId, bool noError) +oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, + bool noError, int location) { FuncCandidateList clist; Oid inputOids[2]; @@ -549,7 +544,7 @@ oper(List *opname, Oid ltypeId, Oid rtypeId, bool noError) } if (!HeapTupleIsValid(tup) && !noError) - op_error(opname, 'b', ltypeId, rtypeId, fdresult); + op_error(pstate, opname, 'b', ltypeId, rtypeId, fdresult, location); return (Operator) tup; } @@ -562,13 +557,14 @@ oper(List *opname, Oid ltypeId, Oid rtypeId, bool noError) * are accepted). Otherwise, the semantics are the same. */ Operator -compatible_oper(List *op, Oid arg1, Oid arg2, bool noError) +compatible_oper(ParseState *pstate, List *op, Oid arg1, Oid arg2, + bool noError, int location) { Operator optup; Form_pg_operator opform; /* oper() will find the best available match */ - optup = oper(op, arg1, arg2, noError); + optup = oper(pstate, op, arg1, arg2, noError, location); if (optup == (Operator) NULL) return (Operator) NULL; /* must be noError case */ @@ -585,7 +581,8 @@ compatible_oper(List *op, Oid arg1, Oid arg2, bool noError) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("operator requires run-time type coercion: %s", - op_signature_string(op, 'b', arg1, arg2)))); + op_signature_string(op, 'b', arg1, arg2)), + parser_errposition(pstate, location))); return (Operator) NULL; } @@ -602,7 +599,7 @@ compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError) Operator optup; Oid result; - optup = compatible_oper(op, arg1, arg2, noError); + optup = compatible_oper(NULL, op, arg1, arg2, noError, -1); if (optup != NULL) { result = oprid(optup); @@ -621,13 +618,14 @@ compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError) * you need an exact- or binary-compatible match. * * If no matching operator found, return NULL if noError is true, - * raise an error if it is false. + * raise an error if it is false. pstate and location are used only to report + * the error position; pass NULL/-1 if not available. * * NOTE: on success, the returned object is a syscache entry. The caller * must ReleaseSysCache() the entry when done with it. */ Operator -right_oper(List *op, Oid arg, bool noError) +right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location) { FuncCandidateList clist; Oid operOid = InvalidOid; @@ -669,7 +667,7 @@ right_oper(List *op, Oid arg, bool noError) } if (!HeapTupleIsValid(tup) && !noError) - op_error(op, 'r', arg, InvalidOid, fdresult); + op_error(pstate, op, 'r', arg, InvalidOid, fdresult, location); return (Operator) tup; } @@ -683,13 +681,14 @@ right_oper(List *op, Oid arg, bool noError) * you need an exact- or binary-compatible match. * * If no matching operator found, return NULL if noError is true, - * raise an error if it is false. + * raise an error if it is false. pstate and location are used only to report + * the error position; pass NULL/-1 if not available. * * NOTE: on success, the returned object is a syscache entry. The caller * must ReleaseSysCache() the entry when done with it. */ Operator -left_oper(List *op, Oid arg, bool noError) +left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location) { FuncCandidateList clist; Oid operOid = InvalidOid; @@ -736,7 +735,7 @@ left_oper(List *op, Oid arg, bool noError) } if (!HeapTupleIsValid(tup) && !noError) - op_error(op, 'l', InvalidOid, arg, fdresult); + op_error(pstate, op, 'l', InvalidOid, arg, fdresult, location); return (Operator) tup; } @@ -771,7 +770,9 @@ op_signature_string(List *op, char oprkind, Oid arg1, Oid arg2) * op_error - utility routine to complain about an unresolvable operator */ static void -op_error(List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult) +op_error(ParseState *pstate, List *op, char oprkind, + Oid arg1, Oid arg2, + FuncDetailCode fdresult, int location) { if (fdresult == FUNCDETAIL_MULTIPLE) ereport(ERROR, @@ -779,14 +780,16 @@ op_error(List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult) errmsg("operator is not unique: %s", op_signature_string(op, oprkind, arg1, arg2)), errhint("Could not choose a best candidate operator. " - "You may need to add explicit type casts."))); + "You may need to add explicit type casts."), + parser_errposition(pstate, location))); else ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("operator does not exist: %s", op_signature_string(op, oprkind, arg1, arg2)), errhint("No operator matches the given name and argument type(s). " - "You may need to add explicit type casts."))); + "You may need to add explicit type casts."), + parser_errposition(pstate, location))); } /* @@ -800,7 +803,8 @@ op_error(List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult) * processing is wanted. */ Expr * -make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree) +make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree, + int location) { Oid ltypeId, rtypeId; @@ -813,21 +817,21 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree) /* right operator */ ltypeId = exprType(ltree); rtypeId = InvalidOid; - tup = right_oper(opname, ltypeId, false); + tup = right_oper(pstate, opname, ltypeId, false, location); } else if (ltree == NULL) { /* left operator */ rtypeId = exprType(rtree); ltypeId = InvalidOid; - tup = left_oper(opname, rtypeId, false); + tup = left_oper(pstate, opname, rtypeId, false, location); } else { /* otherwise, binary operator */ ltypeId = exprType(ltree); rtypeId = exprType(rtree); - tup = oper(opname, ltypeId, rtypeId, false); + tup = oper(pstate, opname, ltypeId, rtypeId, false, location); } /* Do typecasting and build the expression tree */ @@ -845,7 +849,8 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree) Expr * make_scalar_array_op(ParseState *pstate, List *opname, bool useOr, - Node *ltree, Node *rtree) + Node *ltree, Node *rtree, + int location) { Oid ltypeId, rtypeId, @@ -875,11 +880,12 @@ make_scalar_array_op(ParseState *pstate, List *opname, if (!OidIsValid(rtypeId)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("op ANY/ALL (array) requires array on right side"))); + errmsg("op ANY/ALL (array) requires array on right side"), + parser_errposition(pstate, location))); } /* Now resolve the operator */ - tup = oper(opname, ltypeId, rtypeId, false); + tup = oper(pstate, opname, ltypeId, rtypeId, false, location); opform = (Form_pg_operator) GETSTRUCT(tup); args = list_make2(ltree, rtree); @@ -904,11 +910,13 @@ make_scalar_array_op(ParseState *pstate, List *opname, if (rettype != BOOLOID) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("op ANY/ALL (array) requires operator to yield boolean"))); + errmsg("op ANY/ALL (array) requires operator to yield boolean"), + parser_errposition(pstate, location))); if (get_func_retset(opform->oprcode)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("op ANY/ALL (array) requires operator not to return a set"))); + errmsg("op ANY/ALL (array) requires operator not to return a set"), + parser_errposition(pstate, location))); /* * Now switch back to the array type on the right, arranging for any @@ -919,7 +927,8 @@ make_scalar_array_op(ParseState *pstate, List *opname, ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("could not find array type for data type %s", - format_type_be(declared_arg_types[1])))); + format_type_be(declared_arg_types[1])), + parser_errposition(pstate, location))); actual_arg_types[1] = atypeId; declared_arg_types[1] = res_atypeId; diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index af8086a81a..d0f78b119c 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.119 2006/03/05 15:58:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.120 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -47,7 +47,8 @@ static void expandTupleDesc(TupleDesc tupdesc, Alias *eref, bool include_dropped, List **colnames, List **colvars); static int specialAttNum(const char *attname); -static void warnAutoRange(ParseState *pstate, RangeVar *relation); +static void warnAutoRange(ParseState *pstate, RangeVar *relation, + int location); /* @@ -329,7 +330,8 @@ GetRTEByRangeTablePosn(ParseState *pstate, * FROM will be marked as requiring read access from the beginning. */ Node * -scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname) +scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname, + int location) { Node *result = NULL; int attnum = 0; @@ -357,7 +359,8 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname) ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_COLUMN), errmsg("column reference \"%s\" is ambiguous", - colname))); + colname), + parser_errposition(pstate, location))); result = (Node *) make_var(pstate, rte, attnum); /* Require read access */ rte->requiredPerms |= ACL_SELECT; @@ -404,7 +407,8 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname) * If localonly is true, only names in the innermost query are considered. */ Node * -colNameToVar(ParseState *pstate, char *colname, bool localonly) +colNameToVar(ParseState *pstate, char *colname, bool localonly, + int location) { Node *result = NULL; ParseState *orig_pstate = pstate; @@ -419,7 +423,7 @@ colNameToVar(ParseState *pstate, char *colname, bool localonly) Node *newresult; /* use orig_pstate here to get the right sublevels_up */ - newresult = scanRTEForColumn(orig_pstate, rte, colname); + newresult = scanRTEForColumn(orig_pstate, rte, colname, location); if (newresult) { @@ -427,7 +431,8 @@ colNameToVar(ParseState *pstate, char *colname, bool localonly) ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_COLUMN), errmsg("column reference \"%s\" is ambiguous", - colname))); + colname), + parser_errposition(orig_pstate, location))); result = newresult; } } @@ -454,7 +459,8 @@ qualifiedNameToVar(ParseState *pstate, char *schemaname, char *refname, char *colname, - bool implicitRTEOK) + bool implicitRTEOK, + int location) { RangeTblEntry *rte; int sublevels_up; @@ -465,10 +471,11 @@ qualifiedNameToVar(ParseState *pstate, { if (!implicitRTEOK) return NULL; - rte = addImplicitRTE(pstate, makeRangeVar(schemaname, refname)); + rte = addImplicitRTE(pstate, makeRangeVar(schemaname, refname), + location); } - return scanRTEForColumn(pstate, rte, colname); + return scanRTEForColumn(pstate, rte, colname, location); } /* @@ -1043,12 +1050,12 @@ addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, * a conflicting name. */ RangeTblEntry * -addImplicitRTE(ParseState *pstate, RangeVar *relation) +addImplicitRTE(ParseState *pstate, RangeVar *relation, int location) { RangeTblEntry *rte; /* issue warning or error as needed */ - warnAutoRange(pstate, relation); + warnAutoRange(pstate, relation, location); /* * Note that we set inFromCl true, so that the RTE will be listed * explicitly if the parsetree is ever decompiled by ruleutils.c. This @@ -1196,7 +1203,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, Var *varnode; Oid atttypid; - atttypid = typenameTypeId(colDef->typename); + atttypid = typenameTypeId(NULL, colDef->typename); varnode = makeVar(rtindex, attnum, @@ -1543,7 +1550,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum, { ColumnDef *colDef = list_nth(rte->coldeflist, attnum - 1); - *vartype = typenameTypeId(colDef->typename); + *vartype = typenameTypeId(NULL, colDef->typename); *vartypmod = colDef->typename->typmod; } else @@ -1802,7 +1809,7 @@ attnumTypeId(Relation rd, int attid) * a warning. */ static void -warnAutoRange(ParseState *pstate, RangeVar *relation) +warnAutoRange(ParseState *pstate, RangeVar *relation, int location) { RangeTblEntry *rte; int sublevels_up; @@ -1841,7 +1848,8 @@ warnAutoRange(ParseState *pstate, RangeVar *relation) errhint("Perhaps you meant to reference the table alias \"%s\".", badAlias) : errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.", - rte->eref->aliasname)))); + rte->eref->aliasname)), + parser_errposition(pstate, location))); else ereport(ERROR, (errcode(ERRCODE_UNDEFINED_TABLE), @@ -1849,7 +1857,8 @@ warnAutoRange(ParseState *pstate, RangeVar *relation) errmsg("missing FROM-clause entry in subquery for table \"%s\"", relation->relname) : errmsg("missing FROM-clause entry for table \"%s\"", - relation->relname)))); + relation->relname)), + parser_errposition(pstate, location))); } else { @@ -1866,6 +1875,7 @@ warnAutoRange(ParseState *pstate, RangeVar *relation) badAlias) : (rte ? errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.", - rte->eref->aliasname) : 0)))); + rte->eref->aliasname) : 0)), + parser_errposition(pstate, location))); } } diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 63ce087e71..300e02d90b 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.140 2006/03/05 15:58:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.141 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -718,7 +718,8 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cross-database references are not implemented: %s", - NameListToString(fields)))); + NameListToString(fields)), + parser_errposition(pstate, cref->location))); schemaname = strVal(lsecond(fields)); relname = strVal(lthird(fields)); break; @@ -727,7 +728,8 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper qualified name (too many dotted names): %s", - NameListToString(fields)))); + NameListToString(fields)), + parser_errposition(pstate, cref->location))); schemaname = NULL; /* keep compiler quiet */ relname = NULL; break; @@ -736,8 +738,8 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref) rte = refnameRangeTblEntry(pstate, schemaname, relname, &sublevels_up); if (rte == NULL) - rte = addImplicitRTE(pstate, makeRangeVar(schemaname, - relname)); + rte = addImplicitRTE(pstate, makeRangeVar(schemaname, relname), + cref->location); rtindex = RTERangeTablePosn(pstate, rte, &sublevels_up); diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c index 4114354057..e88e6c37c1 100644 --- a/src/backend/parser/parse_type.c +++ b/src/backend/parser/parse_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.78 2006/03/05 15:58:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.79 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -35,9 +35,11 @@ * * NB: even if the returned OID is not InvalidOid, the type might be * just a shell. Caller should check typisdefined before using the type. + * + * pstate is only used for error location info, and may be NULL. */ Oid -LookupTypeName(const TypeName *typename) +LookupTypeName(ParseState *pstate, const TypeName *typename) { Oid restype; @@ -60,7 +62,8 @@ LookupTypeName(const TypeName *typename) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper %%TYPE reference (too few dotted names): %s", - NameListToString(typename->names)))); + NameListToString(typename->names)), + parser_errposition(pstate, typename->location))); break; case 2: rel->relname = strVal(linitial(typename->names)); @@ -81,7 +84,8 @@ LookupTypeName(const TypeName *typename) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper %%TYPE reference (too many dotted names): %s", - NameListToString(typename->names)))); + NameListToString(typename->names)), + parser_errposition(pstate, typename->location))); break; } @@ -92,7 +96,8 @@ LookupTypeName(const TypeName *typename) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" of relation \"%s\" does not exist", - field, rel->relname))); + field, rel->relname), + parser_errposition(pstate, typename->location))); restype = get_atttype(relid, attnum); /* this construct should never have an array indicator */ @@ -190,21 +195,24 @@ TypeNameToString(const TypeName *typename) * a suitable error message if the type cannot be found or is not defined. */ Oid -typenameTypeId(const TypeName *typename) +typenameTypeId(ParseState *pstate, const TypeName *typename) { Oid typoid; - typoid = LookupTypeName(typename); + typoid = LookupTypeName(pstate, typename); if (!OidIsValid(typoid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type \"%s\" does not exist", - TypeNameToString(typename)))); + TypeNameToString(typename)), + parser_errposition(pstate, typename->location))); + if (!get_typisdefined(typoid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type \"%s\" is only a shell", - TypeNameToString(typename)))); + TypeNameToString(typename)), + parser_errposition(pstate, typename->location))); return typoid; } @@ -215,17 +223,18 @@ typenameTypeId(const TypeName *typename) * NB: caller must ReleaseSysCache the type tuple when done with it. */ Type -typenameType(const TypeName *typename) +typenameType(ParseState *pstate, const TypeName *typename) { Oid typoid; HeapTuple tup; - typoid = LookupTypeName(typename); + typoid = LookupTypeName(pstate, typename); if (!OidIsValid(typoid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type \"%s\" does not exist", - TypeNameToString(typename)))); + TypeNameToString(typename)), + parser_errposition(pstate, typename->location))); tup = SearchSysCache(TYPEOID, ObjectIdGetDatum(typoid), 0, 0, 0); @@ -235,7 +244,8 @@ typenameType(const TypeName *typename) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type \"%s\" is only a shell", - TypeNameToString(typename)))); + TypeNameToString(typename)), + parser_errposition(pstate, typename->location))); return (Type) tup; } @@ -447,7 +457,7 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod) if (typename->setof) goto fail; - *type_id = typenameTypeId(typename); + *type_id = typenameTypeId(NULL, typename); *typmod = typename->typmod; pfree(buf.data); diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index 3d63cb73c8..0ac8d346a7 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -24,7 +24,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.132 2006/03/07 01:00:17 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.133 2006/03/14 22:48:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -74,20 +74,19 @@ static int literalalloc; /* current allocated buffer size */ static void addlit(char *ytext, int yleng); static void addlitchar(unsigned char ychar); static char *litbufdup(void); -static int pg_err_position(void); + +static int lexer_errposition(void); static void check_escape_warning(void); static void check_string_escape_warning(unsigned char ychar); /* + * Each call to yylex must set yylloc to the location of the found token + * (expressed as a byte offset from the start of the input text). * When we parse a token that requires multiple lexer rules to process, - * we set token_start to point at the true start of the token, for use - * by yyerror(). yytext will point at just the text consumed by the last - * rule, so it's not very helpful (e.g., it might contain just the last - * quote mark of a quoted identifier). But to avoid cluttering every rule - * with setting token_start, we allow token_start = NULL to denote that - * it's okay to use yytext. + * this should be done in the first such rule, else yylloc will point + * into the middle of the token. */ -static char *token_start; +#define SET_YYLLOC() (yylloc = yytext - scanbuf) /* Handles to the buffer that the lexer uses internally */ static YY_BUFFER_STATE scanbufhandle; @@ -316,17 +315,13 @@ other . %% -%{ - /* code to execute during start of each call of yylex() */ - token_start = NULL; -%} - {whitespace} { /* ignore */ } {xcstart} { - token_start = yytext; + /* Set location in case of syntax error in comment */ + SET_YYLLOC(); xcdepth = 0; BEGIN(xc); /* Put back any characters past slash-star; see above */ @@ -341,11 +336,7 @@ other . <xc>{xcstop} { if (xcdepth <= 0) - { BEGIN(INITIAL); - /* reset token_start for next token */ - token_start = NULL; - } else xcdepth--; } @@ -371,7 +362,7 @@ other . * In the meantime, place a leading "b" on the string * to mark it for the input routine as a binary string. */ - token_start = yytext; + SET_YYLLOC(); BEGIN(xb); startlit(); addlitchar('b'); @@ -400,7 +391,7 @@ other . * In the meantime, place a leading "x" on the string * to mark it for the input routine as a hex string. */ - token_start = yytext; + SET_YYLLOC(); BEGIN(xh); startlit(); addlitchar('x'); @@ -421,6 +412,7 @@ other . */ const ScanKeyword *keyword; + SET_YYLLOC(); yyless(1); /* eat only 'n' this time */ /* nchar had better be a keyword! */ keyword = ScanKeywordLookup("nchar"); @@ -431,7 +423,7 @@ other . {xqstart} { warn_on_first_escape = true; - token_start = yytext; + SET_YYLLOC(); if (standard_conforming_strings) BEGIN(xq); else @@ -440,7 +432,7 @@ other . } {xestart} { warn_on_first_escape = false; - token_start = yytext; + SET_YYLLOC(); BEGIN(xe); startlit(); } @@ -490,7 +482,7 @@ other . <xq,xe><<EOF>> { yyerror("unterminated quoted string"); } {dolqdelim} { - token_start = yytext; + SET_YYLLOC(); dolqstart = pstrdup(yytext); BEGIN(xdolq); startlit(); @@ -533,7 +525,7 @@ other . <xdolq><<EOF>> { yyerror("unterminated dollar-quoted string"); } {xdstart} { - token_start = yytext; + SET_YYLLOC(); BEGIN(xd); startlit(); } @@ -558,10 +550,12 @@ other . <xd><<EOF>> { yyerror("unterminated quoted identifier"); } {typecast} { + SET_YYLLOC(); return TYPECAST; } {self} { + SET_YYLLOC(); return yytext[0]; } @@ -611,6 +605,8 @@ other . nchars--; /* else remove the +/-, and check again */ } + SET_YYLLOC(); + if (nchars < yyleng) { /* Strip the unwanted chars from the token */ @@ -644,6 +640,7 @@ other . } {param} { + SET_YYLLOC(); yylval.ival = atol(yytext + 1); return PARAM; } @@ -652,6 +649,7 @@ other . long val; char* endptr; + SET_YYLLOC(); errno = 0; val = strtol(yytext, &endptr, 10); if (*endptr != '\0' || errno == ERANGE @@ -669,10 +667,12 @@ other . return ICONST; } {decimal} { + SET_YYLLOC(); yylval.str = pstrdup(yytext); return FCONST; } {real} { + SET_YYLLOC(); yylval.str = pstrdup(yytext); return FCONST; } @@ -684,12 +684,14 @@ other . * syntax error anyway, we don't bother to distinguish. */ yyless(yyleng-1); + SET_YYLLOC(); yylval.str = pstrdup(yytext); return FCONST; } {realfail2} { /* throw back the [Ee][+-], and proceed as above */ yyless(yyleng-2); + SET_YYLLOC(); yylval.str = pstrdup(yytext); return FCONST; } @@ -699,6 +701,8 @@ other . const ScanKeyword *keyword; char *ident; + SET_YYLLOC(); + /* Is it a keyword? */ keyword = ScanKeywordLookup(yytext); if (keyword != NULL) @@ -717,25 +721,52 @@ other . } {other} { + SET_YYLLOC(); return yytext[0]; } +<<EOF>> { + SET_YYLLOC(); + yyterminate(); + } + %% +/* + * lexer_errposition + * Report a lexical-analysis-time cursor position, if possible. + * + * This is expected to be used within an ereport() call. The return value + * is a dummy (always 0, in fact). + * + * Note that this can only be used for messages from the lexer itself, + * since it depends on scanbuf to still be valid. + */ static int -pg_err_position(void) +lexer_errposition(void) { - const char *loc = token_start ? token_start : yytext; + int pos; - /* in multibyte encodings, return index in characters not bytes */ - return pg_mbstrlen_with_len(scanbuf, loc - scanbuf) + 1; + /* Convert byte offset to character number */ + pos = pg_mbstrlen_with_len(scanbuf, yylloc) + 1; + /* And pass it to the ereport mechanism */ + return errposition(pos); } +/* + * yyerror + * Report a lexer or grammar error. + * + * The message's cursor position identifies the most recently lexed token. + * This is OK for syntax error messages from the Bison parser, because Bison + * parsers report error as soon as the first unparsable token is reached. + * Beware of using yyerror for other purposes, as the cursor position might + * be misleading! + */ void yyerror(const char *message) { - const char *loc = token_start ? token_start : yytext; - int cursorpos = pg_err_position(); + const char *loc = scanbuf + yylloc; if (*loc == YY_END_OF_BUFFER_CHAR) { @@ -743,7 +774,7 @@ yyerror(const char *message) (errcode(ERRCODE_SYNTAX_ERROR), /* translator: %s is typically "syntax error" */ errmsg("%s at end of input", _(message)), - errposition(cursorpos))); + lexer_errposition())); } else { @@ -751,7 +782,7 @@ yyerror(const char *message) (errcode(ERRCODE_SYNTAX_ERROR), /* translator: first %s is typically "syntax error" */ errmsg("%s at or near \"%s\"", _(message), loc), - errposition(cursorpos))); + lexer_errposition())); } } @@ -878,7 +909,7 @@ check_string_escape_warning(unsigned char ychar) (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), errmsg("nonstandard use of \\' in a string literal"), errhint("Use '' to write quotes in strings, or use the escape string syntax (E'...')."), - errposition(pg_err_position()))); + lexer_errposition())); warn_on_first_escape = false; /* warn only once per string */ } else if (ychar == '\\') @@ -888,7 +919,7 @@ check_string_escape_warning(unsigned char ychar) (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), errmsg("nonstandard use of \\\\ in a string literal"), errhint("Use the escape string syntax for backslashes, e.g., E'\\\\'."), - errposition(pg_err_position()))); + lexer_errposition())); warn_on_first_escape = false; /* warn only once per string */ } else @@ -903,6 +934,6 @@ check_escape_warning(void) (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), errmsg("nonstandard use of escape in a string literal"), errhint("Use the escape string syntax for escapes, e.g., E'\\r\\n'."), - errposition(pg_err_position()))); + lexer_errposition())); warn_on_first_escape = false; /* warn only once per string */ } |
