Tom Lane escribió: > Alvaro Herrera <[EMAIL PROTECTED]> writes: > > Tom Lane escribió: > >> They're logically different things, and after I get done putting a parse > >> location field into A_Const, they'll still be physically different too. > > > Aha. Are you working from Brendan's patch? I was going to commit it. > > Sure, go ahead. I was going to add the parse location at the same time, > but it can perfectly well be done as a separate patch.
I came up with the attached patch. I added the location bits (although I am unsure if I got the locations right in the parser), but they are unused -- figuring out how to use them would take me longer than I can to spend on this. -- Alvaro Herrera http://www.CommandPrompt.com/ PostgreSQL Replication, Consulting, Custom Development, 24x7 support
Index: src/backend/nodes/copyfuncs.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/nodes/copyfuncs.c,v retrieving revision 1.392 diff -c -p -r1.392 copyfuncs.c *** src/backend/nodes/copyfuncs.c 14 Apr 2008 17:05:33 -0000 1.392 --- src/backend/nodes/copyfuncs.c 28 Apr 2008 20:20:44 -0000 *************** _copyAConst(A_Const *from) *** 1639,1645 **** break; } ! COPY_NODE_FIELD(typename); return newnode; } --- 1639,1645 ---- break; } ! COPY_SCALAR_FIELD(location); return newnode; } Index: src/backend/nodes/equalfuncs.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/nodes/equalfuncs.c,v retrieving revision 1.321 diff -c -p -r1.321 equalfuncs.c *** src/backend/nodes/equalfuncs.c 14 Apr 2008 17:05:33 -0000 1.321 --- src/backend/nodes/equalfuncs.c 28 Apr 2008 16:17:02 -0000 *************** _equalParamRef(ParamRef *a, ParamRef *b) *** 1691,1701 **** static bool _equalAConst(A_Const *a, A_Const *b) { ! if (!equal(&a->val, &b->val)) /* hack for in-line Value field */ ! return false; ! COMPARE_NODE_FIELD(typename); ! ! return true; } static bool --- 1691,1697 ---- static bool _equalAConst(A_Const *a, A_Const *b) { ! return equal(&a->val, &b->val); /* hack for in-line Value field */ } static bool Index: src/backend/nodes/outfuncs.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/nodes/outfuncs.c,v retrieving revision 1.325 diff -c -p -r1.325 outfuncs.c *** src/backend/nodes/outfuncs.c 13 Apr 2008 20:51:20 -0000 1.325 --- src/backend/nodes/outfuncs.c 28 Apr 2008 17:24:10 -0000 *************** _outAConst(StringInfo str, A_Const *node *** 1945,1951 **** appendStringInfo(str, " :val "); _outValue(str, &(node->val)); ! WRITE_NODE_FIELD(typename); } static void --- 1945,1951 ---- appendStringInfo(str, " :val "); _outValue(str, &(node->val)); ! WRITE_INT_FIELD(location); } static void Index: src/backend/parser/gram.y =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/parser/gram.y,v retrieving revision 2.612 diff -c -p -r2.612 gram.y *** src/backend/parser/gram.y 14 Apr 2008 17:05:33 -0000 2.612 --- src/backend/parser/gram.y 28 Apr 2008 19:48:16 -0000 *************** static bool QueryIsRule = FALSE; *** 91,101 **** 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); ! static Node *makeFloatConst(char *str); ! static Node *makeAConst(Value *v); ! static A_Const *makeBoolAConst(bool state); static FuncCall *makeOverlaps(List *largs, List *rargs, int location); static void check_qualified_name(List *names); static List *check_func_name(List *names); --- 91,102 ---- static Node *makeColumnRef(char *relname, List *indirection, int location); static Node *makeTypeCast(Node *arg, TypeName *typename); ! static Node *makeStringConst(char *str, int location); ! static Node *makeStringConstCast(char *str, TypeName *typename, int location); ! static Node *makeIntConst(int val, int location); ! static Node *makeFloatConst(char *str, int location); ! static Node *makeAConst(Value *v, int location); ! static Node *makeBoolAConst(bool state, int location); static FuncCall *makeOverlaps(List *largs, List *rargs, int location); static void check_qualified_name(List *names); static List *check_func_name(List *names); *************** set_rest: /* Generic SET syntaxes: */ *** 1112,1118 **** n->kind = VAR_SET_VALUE; n->name = "client_encoding"; if ($2 != NULL) ! n->args = list_make1(makeStringConst($2, NULL)); else n->kind = VAR_SET_DEFAULT; $$ = n; --- 1113,1119 ---- n->kind = VAR_SET_VALUE; n->name = "client_encoding"; if ($2 != NULL) ! n->args = list_make1(makeStringConst($2, @2)); else n->kind = VAR_SET_DEFAULT; $$ = n; *************** set_rest: /* Generic SET syntaxes: */ *** 1122,1128 **** VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_SET_VALUE; n->name = "role"; ! n->args = list_make1(makeStringConst($2, NULL)); $$ = n; } | SESSION AUTHORIZATION ColId_or_Sconst --- 1123,1129 ---- VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_SET_VALUE; n->name = "role"; ! n->args = list_make1(makeStringConst($2, @2)); $$ = n; } | SESSION AUTHORIZATION ColId_or_Sconst *************** set_rest: /* Generic SET syntaxes: */ *** 1130,1136 **** VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_SET_VALUE; n->name = "session_authorization"; ! n->args = list_make1(makeStringConst($3, NULL)); $$ = n; } | SESSION AUTHORIZATION DEFAULT --- 1131,1137 ---- VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_SET_VALUE; n->name = "session_authorization"; ! n->args = list_make1(makeStringConst($3, @3)); $$ = n; } | SESSION AUTHORIZATION DEFAULT *************** set_rest: /* Generic SET syntaxes: */ *** 1145,1151 **** VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_SET_VALUE; n->name = "xmloption"; ! n->args = list_make1(makeStringConst($3 == XMLOPTION_DOCUMENT ? "DOCUMENT" : "CONTENT", NULL)); $$ = n; } ; --- 1146,1153 ---- VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_SET_VALUE; n->name = "xmloption"; ! n->args = list_make1(makeStringConst($3 == XMLOPTION_DOCUMENT ? ! "DOCUMENT" : "CONTENT", @3)); $$ = n; } ; *************** var_list: var_value { $$ = list_m *** 1163,1173 **** ; var_value: opt_boolean ! { $$ = makeStringConst($1, NULL); } | ColId_or_Sconst ! { $$ = makeStringConst($1, NULL); } | NumericOnly ! { $$ = makeAConst($1); } ; iso_level: READ UNCOMMITTED { $$ = "read uncommitted"; } --- 1165,1175 ---- ; var_value: opt_boolean ! { $$ = makeStringConst($1, @1); } | ColId_or_Sconst ! { $$ = makeStringConst($1, @1); } | NumericOnly ! { $$ = makeAConst($1, @1); } ; iso_level: READ UNCOMMITTED { $$ = "read uncommitted"; } *************** opt_boolean: *** 1194,1231 **** zone_value: Sconst { ! $$ = makeStringConst($1, NULL); } | IDENT { ! $$ = makeStringConst($1, NULL); } | ConstInterval Sconst opt_interval { ! A_Const *n = (A_Const *) makeStringConst($2, $1); if ($3 != INTERVAL_FULL_RANGE) { 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"))); ! n->typename->typmods = list_make1(makeIntConst($3)); } ! $$ = (Node *)n; } | ConstInterval '(' Iconst ')' Sconst opt_interval { ! A_Const *n = (A_Const *) makeStringConst($5, $1); if (($6 != INTERVAL_FULL_RANGE) && (($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"))); ! n->typename->typmods = list_make2(makeIntConst($6), ! makeIntConst($3)); ! $$ = (Node *)n; } ! | NumericOnly { $$ = makeAConst($1); } | DEFAULT { $$ = NULL; } | LOCAL { $$ = NULL; } ; --- 1196,1233 ---- zone_value: Sconst { ! $$ = makeStringConst($1, @1); } | IDENT { ! $$ = makeStringConst($1, @1); } | ConstInterval Sconst opt_interval { ! TypeName *t = $1; if ($3 != INTERVAL_FULL_RANGE) { 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"))); ! t->typmods = list_make1(makeIntConst($3, @3)); } ! $$ = (Node *)makeStringConstCast($2, t, @2); } | ConstInterval '(' Iconst ')' Sconst opt_interval { ! TypeName *t = $1; if (($6 != INTERVAL_FULL_RANGE) && (($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"))); ! t->typmods = list_make2(makeIntConst($6, @6), ! makeIntConst($3, @3)); ! $$ = (Node *)makeStringConstCast($5, t, @5); } ! | NumericOnly { $$ = makeAConst($1, @1); } | DEFAULT { $$ = NULL; } | LOCAL { $$ = NULL; } ; *************** opt_transaction: WORK {} *** 5207,5219 **** transaction_mode_item: ISOLATION LEVEL iso_level { $$ = makeDefElem("transaction_isolation", ! makeStringConst($3, NULL)); } | READ ONLY { $$ = makeDefElem("transaction_read_only", ! makeIntConst(TRUE)); } | READ WRITE { $$ = makeDefElem("transaction_read_only", ! makeIntConst(FALSE)); } ; /* Syntax with commas is SQL-spec, without commas is Postgres historical */ --- 5209,5221 ---- transaction_mode_item: ISOLATION LEVEL iso_level { $$ = makeDefElem("transaction_isolation", ! makeStringConst($3, @3)); } | READ ONLY { $$ = makeDefElem("transaction_read_only", ! makeIntConst(TRUE, -1)); } | READ WRITE { $$ = makeDefElem("transaction_read_only", ! makeIntConst(FALSE, -1)); } ; /* Syntax with commas is SQL-spec, without commas is Postgres historical */ *************** select_limit_value: *** 6396,6401 **** --- 6398,6404 ---- /* LIMIT ALL is represented as a NULL constant */ A_Const *n = makeNode(A_Const); n->val.type = T_Null; + n->location = @1; $$ = (Node *)n; } ; *************** SimpleTypename: *** 6898,6910 **** { $$ = $1; if ($2 != INTERVAL_FULL_RANGE) ! $$->typmods = list_make1(makeIntConst($2)); } | ConstInterval '(' Iconst ')' opt_interval { $$ = $1; ! $$->typmods = list_make2(makeIntConst($5), ! makeIntConst($3)); } ; --- 6901,6913 ---- { $$ = $1; if ($2 != INTERVAL_FULL_RANGE) ! $$->typmods = list_make1(makeIntConst($2, @2)); } | ConstInterval '(' Iconst ')' opt_interval { $$ = $1; ! $$->typmods = list_make2(makeIntConst($5, @5), ! makeIntConst($3, @3)); } ; *************** BitWithoutLength: *** 7090,7096 **** else { $$ = SystemTypeName("bit"); ! $$->typmods = list_make1(makeIntConst(1)); } $$->location = @1; } --- 7093,7099 ---- else { $$ = SystemTypeName("bit"); ! $$->typmods = list_make1(makeIntConst(1, -1)); } $$->location = @1; } *************** CharacterWithLength: character '(' Icon *** 7142,7148 **** } $$ = SystemTypeName($1); ! $$->typmods = list_make1(makeIntConst($3)); $$->location = @1; } ; --- 7145,7151 ---- } $$ = SystemTypeName($1); ! $$->typmods = list_make1(makeIntConst($3, @3)); $$->location = @1; } ; *************** CharacterWithoutLength: character opt_c *** 7164,7170 **** /* char defaults to char(1), varchar to no limit */ if (strcmp($1, "bpchar") == 0) ! $$->typmods = list_make1(makeIntConst(1)); $$->location = @1; } --- 7167,7173 ---- /* char defaults to char(1), varchar to no limit */ if (strcmp($1, "bpchar") == 0) ! $$->typmods = list_make1(makeIntConst(1, -1)); $$->location = @1; } *************** ConstDatetime: *** 7204,7210 **** $$ = SystemTypeName("timestamptz"); else $$ = SystemTypeName("timestamp"); ! $$->typmods = list_make1(makeIntConst($3)); $$->location = @1; } | TIMESTAMP opt_timezone --- 7207,7213 ---- $$ = SystemTypeName("timestamptz"); else $$ = SystemTypeName("timestamp"); ! $$->typmods = list_make1(makeIntConst($3, @3)); $$->location = @1; } | TIMESTAMP opt_timezone *************** ConstDatetime: *** 7221,7227 **** $$ = SystemTypeName("timetz"); else $$ = SystemTypeName("time"); ! $$->typmods = list_make1(makeIntConst($3)); $$->location = @1; } | TIME opt_timezone --- 7224,7230 ---- $$ = SystemTypeName("timetz"); else $$ = SystemTypeName("time"); ! $$->typmods = list_make1(makeIntConst($3, @3)); $$->location = @1; } | TIME opt_timezone *************** a_expr: c_expr { $$ = $1; } *** 7411,7416 **** --- 7414,7420 ---- A_Const *c = makeNode(A_Const); FuncCall *n = makeNode(FuncCall); c->val.type = T_Null; + c->location = -1; n->funcname = SystemFuncName("similar_escape"); n->args = list_make2($4, (Node *) c); n->agg_star = FALSE; *************** a_expr: c_expr { $$ = $1; } *** 7433,7438 **** --- 7437,7443 ---- A_Const *c = makeNode(A_Const); FuncCall *n = makeNode(FuncCall); c->val.type = T_Null; + c->location = -1; n->funcname = SystemFuncName("similar_escape"); n->args = list_make2($5, (Node *) c); n->agg_star = FALSE; *************** func_expr: func_name '(' ')' *** 7912,7927 **** * that is actually possible, but not clear that we want * to rely on it.) */ ! A_Const *s = makeNode(A_Const); ! TypeName *d; ! ! s->val.type = T_String; ! s->val.val.str = "now"; ! s->typename = SystemTypeName("text"); ! d = SystemTypeName("date"); ! ! $$ = (Node *)makeTypeCast((Node *)s, d); } | CURRENT_TIME { --- 7917,7927 ---- * that is actually possible, but not clear that we want * to rely on it.) */ ! Node *n = makeStringConstCast("now", ! SystemTypeName("text"), @1); ! $$ = (Node *)makeTypeCast((Node *)n, ! SystemTypeName("date")); } | CURRENT_TIME { *************** func_expr: func_name '(' ')' *** 7929,7944 **** * Translate as "'now'::text::timetz". * See comments for CURRENT_DATE. */ ! A_Const *s = makeNode(A_Const); ! TypeName *d; ! ! s->val.type = T_String; ! s->val.val.str = "now"; ! s->typename = SystemTypeName("text"); ! ! d = SystemTypeName("timetz"); ! $$ = (Node *)makeTypeCast((Node *)s, d); } | CURRENT_TIME '(' Iconst ')' { --- 7929,7939 ---- * Translate as "'now'::text::timetz". * See comments for CURRENT_DATE. */ ! Node *n = makeStringConstCast("now", ! SystemTypeName("text"), @1); ! $$ = (Node *)makeTypeCast((Node *)n, ! SystemTypeName("timetz")); } | CURRENT_TIME '(' Iconst ')' { *************** func_expr: func_name '(' ')' *** 7946,7961 **** * Translate as "'now'::text::timetz(n)". * See comments for CURRENT_DATE. */ ! A_Const *s = makeNode(A_Const); ! TypeName *d; ! s->val.type = T_String; ! s->val.val.str = "now"; ! s->typename = SystemTypeName("text"); ! d = SystemTypeName("timetz"); ! d->typmods = list_make1(makeIntConst($3)); ! $$ = (Node *)makeTypeCast((Node *)s, d); } | CURRENT_TIMESTAMP { --- 7941,7953 ---- * Translate as "'now'::text::timetz(n)". * See comments for CURRENT_DATE. */ ! Node *n = makeStringConstCast("now", ! SystemTypeName("text"), @1); ! TypeName *d = SystemTypeName("timetz"); ! d->typmods = list_make1(makeIntConst($3, @3)); ! $$ = (Node *)makeTypeCast((Node *)n, d); } | CURRENT_TIMESTAMP { *************** func_expr: func_name '(' ')' *** 7977,7993 **** * Translate as "'now'::text::timestamptz(n)". * See comments for CURRENT_DATE. */ ! A_Const *s = makeNode(A_Const); ! TypeName *d; ! s->val.type = T_String; ! s->val.val.str = "now"; ! s->typename = SystemTypeName("text"); ! d = SystemTypeName("timestamptz"); ! d->typmods = list_make1(makeIntConst($3)); ! ! $$ = (Node *)makeTypeCast((Node *)s, d); } | LOCALTIME { --- 7969,7981 ---- * Translate as "'now'::text::timestamptz(n)". * See comments for CURRENT_DATE. */ ! Node *n = makeStringConstCast("now", ! SystemTypeName("text"), @1); ! TypeName *d = SystemTypeName("timestamptz"); ! d->typmods = list_make1(makeIntConst($3, @3)); ! $$ = (Node *)makeTypeCast((Node *)n, d); } | LOCALTIME { *************** func_expr: func_name '(' ')' *** 7995,8010 **** * Translate as "'now'::text::time". * See comments for CURRENT_DATE. */ ! A_Const *s = makeNode(A_Const); ! TypeName *d; ! ! s->val.type = T_String; ! s->val.val.str = "now"; ! s->typename = SystemTypeName("text"); ! ! d = SystemTypeName("time"); ! $$ = (Node *)makeTypeCast((Node *)s, d); } | LOCALTIME '(' Iconst ')' { --- 7983,7993 ---- * Translate as "'now'::text::time". * See comments for CURRENT_DATE. */ ! Node *n = makeStringConstCast("now", ! SystemTypeName("text"), @1); ! $$ = (Node *)makeTypeCast((Node *)n, ! SystemTypeName("time")); } | LOCALTIME '(' Iconst ')' { *************** func_expr: func_name '(' ')' *** 8012,8027 **** * Translate as "'now'::text::time(n)". * See comments for CURRENT_DATE. */ ! A_Const *s = makeNode(A_Const); ! TypeName *d; ! s->val.type = T_String; ! s->val.val.str = "now"; ! s->typename = SystemTypeName("text"); ! d = SystemTypeName("time"); ! d->typmods = list_make1(makeIntConst($3)); ! $$ = (Node *)makeTypeCast((Node *)s, d); } | LOCALTIMESTAMP { --- 7995,8007 ---- * Translate as "'now'::text::time(n)". * See comments for CURRENT_DATE. */ ! Node *n = makeStringConstCast("now", ! SystemTypeName("text"), @1); ! TypeName *d = SystemTypeName("time"); ! d->typmods = list_make1(makeIntConst($3, @3)); ! $$ = (Node *)makeTypeCast((Node *)n, d); } | LOCALTIMESTAMP { *************** func_expr: func_name '(' ')' *** 8029,8044 **** * Translate as "'now'::text::timestamp". * See comments for CURRENT_DATE. */ ! A_Const *s = makeNode(A_Const); ! TypeName *d; ! s->val.type = T_String; ! s->val.val.str = "now"; ! s->typename = SystemTypeName("text"); ! ! d = SystemTypeName("timestamp"); ! ! $$ = (Node *)makeTypeCast((Node *)s, d); } | LOCALTIMESTAMP '(' Iconst ')' { --- 8009,8019 ---- * Translate as "'now'::text::timestamp". * See comments for CURRENT_DATE. */ ! Node *n = makeStringConstCast("now", ! SystemTypeName("text"), @1); ! $$ = (Node *)makeTypeCast((Node *)n, ! SystemTypeName("timestamp")); } | LOCALTIMESTAMP '(' Iconst ')' { *************** func_expr: func_name '(' ')' *** 8046,8062 **** * Translate as "'now'::text::timestamp(n)". * See comments for CURRENT_DATE. */ ! A_Const *s = makeNode(A_Const); ! TypeName *d; ! ! s->val.type = T_String; ! s->val.val.str = "now"; ! s->typename = SystemTypeName("text"); ! d = SystemTypeName("timestamp"); ! d->typmods = list_make1(makeIntConst($3)); ! $$ = (Node *)makeTypeCast((Node *)s, d); } | CURRENT_ROLE { --- 8021,8033 ---- * Translate as "'now'::text::timestamp(n)". * See comments for CURRENT_DATE. */ ! Node *n = makeStringConstCast("now", ! SystemTypeName("text"), @1); ! TypeName *d = SystemTypeName("timestamp"); ! d->typmods = list_make1(makeIntConst($3, @3)); ! $$ = (Node *)makeTypeCast((Node *)n, d); } | CURRENT_ROLE { *************** func_expr: func_name '(' ')' *** 8263,8269 **** { XmlExpr *x = (XmlExpr *) makeXmlExpr(IS_XMLPARSE, NULL, NIL, list_make2($4, ! makeBoolAConst($5))); x->xmloption = $3; $$ = (Node *)x; } --- 8234,8240 ---- { XmlExpr *x = (XmlExpr *) makeXmlExpr(IS_XMLPARSE, NULL, NIL, list_make2($4, ! makeBoolAConst($5, @5))); x->xmloption = $3; $$ = (Node *)x; } *************** xml_root_version: VERSION_P a_expr *** 8299,8316 **** { A_Const *val = makeNode(A_Const); val->val.type = T_Null; $$ = (Node *) val; } ; opt_xml_root_standalone: ',' STANDALONE_P YES_P ! { $$ = (Node *) makeIntConst(XML_STANDALONE_YES); } | ',' STANDALONE_P NO ! { $$ = (Node *) makeIntConst(XML_STANDALONE_NO); } | ',' STANDALONE_P NO VALUE_P ! { $$ = (Node *) makeIntConst(XML_STANDALONE_NO_VALUE); } | /*EMPTY*/ ! { $$ = (Node *) makeIntConst(XML_STANDALONE_OMITTED); } ; xml_attributes: XMLATTRIBUTES '(' xml_attribute_list ')' { $$ = $3; } --- 8270,8288 ---- { A_Const *val = makeNode(A_Const); val->val.type = T_Null; + val->location = @1; $$ = (Node *) val; } ; opt_xml_root_standalone: ',' STANDALONE_P YES_P ! { $$ = (Node *) makeIntConst(XML_STANDALONE_YES, @2); } | ',' STANDALONE_P NO ! { $$ = (Node *) makeIntConst(XML_STANDALONE_NO, @2); } | ',' STANDALONE_P NO VALUE_P ! { $$ = (Node *) makeIntConst(XML_STANDALONE_NO_VALUE, @2); } | /*EMPTY*/ ! { $$ = (Node *) makeIntConst(XML_STANDALONE_OMITTED, -1); } ; xml_attributes: XMLATTRIBUTES '(' xml_attribute_list ')' { $$ = $3; } *************** extract_list: *** 8457,8462 **** --- 8429,8435 ---- A_Const *n = makeNode(A_Const); n->val.type = T_String; n->val.val.str = $1; + n->location = @1; $$ = list_make2((Node *) n, $3); } | /*EMPTY*/ { $$ = NIL; } *************** substr_list: *** 8544,8549 **** --- 8517,8523 ---- A_Const *n = makeNode(A_Const); n->val.type = T_Integer; n->val.val.ival = 1; + n->location = -1; $$ = list_make3($1, (Node *) n, makeTypeCast($2, SystemTypeName("int4"))); } *************** AexprConst: Iconst *** 8859,8864 **** --- 8833,8839 ---- A_Const *n = makeNode(A_Const); n->val.type = T_Integer; n->val.val.ival = $1; + n->location = @1; $$ = (Node *)n; } | FCONST *************** AexprConst: Iconst *** 8866,8871 **** --- 8841,8847 ---- A_Const *n = makeNode(A_Const); n->val.type = T_Float; n->val.val.str = $1; + n->location = @1; $$ = (Node *)n; } | Sconst *************** AexprConst: Iconst *** 8873,8878 **** --- 8849,8855 ---- A_Const *n = makeNode(A_Const); n->val.type = T_String; n->val.val.str = $1; + n->location = @1; $$ = (Node *)n; } | BCONST *************** AexprConst: Iconst *** 8880,8885 **** --- 8857,8863 ---- A_Const *n = makeNode(A_Const); n->val.type = T_BitString; n->val.val.str = $1; + n->location = @1; $$ = (Node *)n; } | XCONST *************** AexprConst: Iconst *** 8892,8961 **** A_Const *n = makeNode(A_Const); n->val.type = T_BitString; n->val.val.str = $1; $$ = (Node *)n; } | func_name Sconst { /* generic type 'literal' syntax */ ! A_Const *n = makeNode(A_Const); ! n->typename = makeTypeNameFromNameList($1); ! n->typename->location = @1; ! n->val.type = T_String; ! n->val.val.str = $2; ! $$ = (Node *)n; } | func_name '(' expr_list ')' Sconst { /* generic syntax with a type modifier */ ! A_Const *n = makeNode(A_Const); ! n->typename = makeTypeNameFromNameList($1); ! n->typename->typmods = $3; ! n->typename->location = @1; ! n->val.type = T_String; ! n->val.val.str = $5; ! $$ = (Node *)n; } | ConstTypename Sconst { ! A_Const *n = makeNode(A_Const); ! n->typename = $1; ! n->val.type = T_String; ! n->val.val.str = $2; ! $$ = (Node *)n; } | ConstInterval Sconst opt_interval { ! A_Const *n = makeNode(A_Const); ! n->typename = $1; ! n->val.type = T_String; ! n->val.val.str = $2; /* precision is not specified, but fields may be... */ if ($3 != INTERVAL_FULL_RANGE) ! n->typename->typmods = list_make1(makeIntConst($3)); ! $$ = (Node *)n; } | ConstInterval '(' Iconst ')' Sconst opt_interval { ! A_Const *n = makeNode(A_Const); ! n->typename = $1; ! n->val.type = T_String; ! n->val.val.str = $5; ! n->typename->typmods = list_make2(makeIntConst($6), ! makeIntConst($3)); ! $$ = (Node *)n; } | TRUE_P { ! $$ = (Node *)makeBoolAConst(TRUE); } | FALSE_P { ! $$ = (Node *)makeBoolAConst(FALSE); } | NULL_P { A_Const *n = makeNode(A_Const); n->val.type = T_Null; $$ = (Node *)n; } ; --- 8870,8926 ---- A_Const *n = makeNode(A_Const); n->val.type = T_BitString; n->val.val.str = $1; + n->location = @1; $$ = (Node *)n; } | func_name Sconst { /* generic type 'literal' syntax */ ! TypeName *t = makeTypeNameFromNameList($1); ! t->location = @1; ! ! $$ = (Node *)makeStringConstCast($2, t, @1); } | func_name '(' expr_list ')' Sconst { /* generic syntax with a type modifier */ ! TypeName *t = makeTypeNameFromNameList($1); ! t->typmods = $3; ! t->location = @1; ! $$ = (Node *)makeStringConstCast($5, t, @1); } | ConstTypename Sconst { ! $$ = (Node *)makeStringConstCast($2, $1, @1); } | ConstInterval Sconst opt_interval { ! TypeName *t = $1; /* precision is not specified, but fields may be... */ if ($3 != INTERVAL_FULL_RANGE) ! t->typmods = list_make1(makeIntConst($3, @3)); ! $$ = (Node *)makeStringConstCast($2, t, @1); } | ConstInterval '(' Iconst ')' Sconst opt_interval { ! TypeName *t = $1; ! t->typmods = list_make2(makeIntConst($6, @6), ! makeIntConst($3, @3)); ! $$ = (Node *)makeStringConstCast($5, t, @1); } | TRUE_P { ! $$ = (Node *)makeBoolAConst(TRUE, @1); } | FALSE_P { ! $$ = (Node *)makeBoolAConst(FALSE, @1); } | NULL_P { A_Const *n = makeNode(A_Const); n->val.type = T_Null; + n->location = @1; $$ = (Node *)n; } ; *************** makeTypeCast(Node *arg, TypeName *typena *** 9506,9563 **** } static Node * ! makeStringConst(char *str, TypeName *typename) { A_Const *n = makeNode(A_Const); n->val.type = T_String; n->val.val.str = str; ! n->typename = typename; return (Node *)n; } static Node * ! makeIntConst(int val) { A_Const *n = makeNode(A_Const); n->val.type = T_Integer; n->val.val.ival = val; ! n->typename = SystemTypeName("int4"); return (Node *)n; } static Node * ! makeFloatConst(char *str) { A_Const *n = makeNode(A_Const); n->val.type = T_Float; n->val.val.str = str; ! n->typename = SystemTypeName("float8"); ! return (Node *)n; } static Node * ! makeAConst(Value *v) { Node *n; switch (v->type) { case T_Float: ! n = makeFloatConst(v->val.str); break; case T_Integer: ! n = makeIntConst(v->val.ival); break; case T_String: default: ! n = makeStringConst(v->val.str, NULL); break; } --- 9471,9537 ---- } static Node * ! makeStringConst(char *str, int location) { A_Const *n = makeNode(A_Const); n->val.type = T_String; n->val.val.str = str; ! n->location = location; return (Node *)n; } static Node * ! makeStringConstCast(char *str, TypeName *typename, int location) ! { ! Node *s = makeStringConst(str, location); ! ! return makeTypeCast(s, typename); ! } ! ! static Node * ! makeIntConst(int val, int location) { A_Const *n = makeNode(A_Const); + n->val.type = T_Integer; n->val.val.ival = val; ! n->location = location; return (Node *)n; } static Node * ! makeFloatConst(char *str, int location) { A_Const *n = makeNode(A_Const); n->val.type = T_Float; n->val.val.str = str; ! n->location = location; ! return makeTypeCast((Node *)n, SystemTypeName("float8")); } static Node * ! makeAConst(Value *v, int location) { Node *n; switch (v->type) { case T_Float: ! n = makeFloatConst(v->val.str, location); break; case T_Integer: ! n = makeIntConst(v->val.ival, location); break; case T_String: default: ! n = makeStringConst(v->val.str, location); break; } *************** makeAConst(Value *v) *** 9565,9580 **** } /* makeBoolAConst() ! * Create an A_Const node and initialize to a boolean constant. */ ! static A_Const * ! makeBoolAConst(bool state) { A_Const *n = makeNode(A_Const); n->val.type = T_String; n->val.val.str = (state ? "t" : "f"); ! n->typename = SystemTypeName("bool"); ! return n; } /* makeOverlaps() --- 9539,9556 ---- } /* makeBoolAConst() ! * Create an A_Const string node and put it inside a boolean cast. */ ! static Node * ! makeBoolAConst(bool state, int location) { A_Const *n = makeNode(A_Const); + n->val.type = T_String; n->val.val.str = (state ? "t" : "f"); ! n->location = location; ! ! return makeTypeCast((Node *)n, SystemTypeName("bool")); } /* makeOverlaps() Index: src/backend/parser/parse_expr.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/parser/parse_expr.c,v retrieving revision 1.227 diff -c -p -r1.227 parse_expr.c *** src/backend/parser/parse_expr.c 20 Mar 2008 21:42:48 -0000 1.227 --- src/backend/parser/parse_expr.c 28 Apr 2008 16:17:02 -0000 *************** transformExpr(ParseState *pstate, Node * *** 127,135 **** Value *val = &con->val; result = (Node *) make_const(val); - if (con->typename != NULL) - result = typecast_expression(pstate, result, - con->typename); break; } --- 127,132 ---- *************** exprIsNullConstant(Node *arg) *** 649,656 **** { A_Const *con = (A_Const *) arg; ! if (con->val.type == T_Null && ! con->typename == NULL) return true; } return false; --- 646,652 ---- { A_Const *con = (A_Const *) arg; ! if (con->val.type == T_Null) return true; } return false; Index: src/backend/parser/parse_target.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/parser/parse_target.c,v retrieving revision 1.159 diff -c -p -r1.159 parse_target.c *** src/backend/parser/parse_target.c 20 Mar 2008 21:42:48 -0000 1.159 --- src/backend/parser/parse_target.c 28 Apr 2008 16:17:02 -0000 *************** FigureColnameInternal(Node *node, char * *** 1266,1278 **** return 2; } break; - case T_A_Const: - if (((A_Const *) node)->typename != NULL) - { - *name = strVal(llast(((A_Const *) node)->typename->names)); - return 1; - } - break; case T_TypeCast: strength = FigureColnameInternal(((TypeCast *) node)->arg, name); --- 1266,1271 ---- Index: src/backend/parser/parse_type.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/parser/parse_type.c,v retrieving revision 1.95 diff -c -p -r1.95 parse_type.c *** src/backend/parser/parse_type.c 11 Apr 2008 22:54:23 -0000 1.95 --- src/backend/parser/parse_type.c 28 Apr 2008 16:17:02 -0000 *************** typenameTypeMod(ParseState *pstate, cons *** 289,308 **** { A_Const *ac = (A_Const *) tm; - /* - * The grammar hands back some integers with ::int4 attached, so - * allow a cast decoration if it's an Integer value, but not - * otherwise. - */ if (IsA(&ac->val, Integer)) { cstr = (char *) palloc(32); snprintf(cstr, 32, "%ld", (long) ac->val.val.ival); } ! else if (ac->typename == NULL) /* no casts allowed */ ! { ! /* otherwise we can just use the str field directly. */ cstr = ac->val.val.str; } } else if (IsA(tm, ColumnRef)) --- 289,321 ---- { A_Const *ac = (A_Const *) tm; if (IsA(&ac->val, Integer)) { cstr = (char *) palloc(32); snprintf(cstr, 32, "%ld", (long) ac->val.val.ival); } ! else ! /* we can just use the str field directly. */ cstr = ac->val.val.str; + } + else if (IsA(tm, TypeCast)) + { + /* + * The grammar hands back some integers with ::int4 attached, so + * allow a cast decoration if it's an Integer value, but not + * otherwise. + */ + TypeCast *tc = (TypeCast *) tm; + + if (IsA(tc->arg, A_Const)) + { + A_Const *ac = (A_Const *) tc->arg; + + if (IsA(&ac->val, Integer)) + { + cstr = (char *) palloc(32); + snprintf(cstr, 32, "%ld", (long) ac->val.val.ival); + } } } else if (IsA(tm, ColumnRef)) Index: src/backend/parser/parse_utilcmd.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/parser/parse_utilcmd.c,v retrieving revision 2.12 diff -c -p -r2.12 parse_utilcmd.c *** src/backend/parser/parse_utilcmd.c 24 Apr 2008 20:46:49 -0000 2.12 --- src/backend/parser/parse_utilcmd.c 28 Apr 2008 16:17:02 -0000 *************** transformColumnDefinition(ParseState *ps *** 308,313 **** --- 308,314 ---- char *sname; char *qstring; A_Const *snamenode; + TypeCast *castnode; FuncCall *funccallnode; CreateSeqStmt *seqstmt; AlterSeqStmt *altseqstmt; *************** transformColumnDefinition(ParseState *ps *** 379,388 **** snamenode = makeNode(A_Const); snamenode->val.type = T_String; snamenode->val.val.str = qstring; ! snamenode->typename = SystemTypeName("regclass"); funccallnode = makeNode(FuncCall); funccallnode->funcname = SystemFuncName("nextval"); ! funccallnode->args = list_make1(snamenode); funccallnode->agg_star = false; funccallnode->agg_distinct = false; funccallnode->location = -1; --- 380,391 ---- snamenode = makeNode(A_Const); snamenode->val.type = T_String; snamenode->val.val.str = qstring; ! castnode = makeNode(TypeCast); ! castnode->typename = SystemTypeName("regclass"); ! castnode->arg = (Node *) snamenode; funccallnode = makeNode(FuncCall); funccallnode->funcname = SystemFuncName("nextval"); ! funccallnode->args = list_make1(castnode); funccallnode->agg_star = false; funccallnode->agg_distinct = false; funccallnode->location = -1; Index: src/backend/utils/misc/guc.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/utils/misc/guc.c,v retrieving revision 1.447 diff -c -p -r1.447 guc.c *** src/backend/utils/misc/guc.c 18 Apr 2008 01:42:17 -0000 1.447 --- src/backend/utils/misc/guc.c 28 Apr 2008 20:14:31 -0000 *************** flatten_set_variable_args(const char *na *** 5207,5235 **** initStringInfo(&buf); foreach(l, args) { ! A_Const *arg = (A_Const *) lfirst(l); char *val; if (l != list_head(args)) appendStringInfo(&buf, ", "); if (!IsA(arg, A_Const)) elog(ERROR, "unrecognized node type: %d", (int) nodeTag(arg)); ! switch (nodeTag(&arg->val)) { case T_Integer: ! appendStringInfo(&buf, "%ld", intVal(&arg->val)); break; case T_Float: /* represented as a string, so just copy it */ ! appendStringInfoString(&buf, strVal(&arg->val)); break; case T_String: ! val = strVal(&arg->val); ! if (arg->typename != NULL) { /* * Must be a ConstInterval argument for TIME ZONE. Coerce --- 5207,5254 ---- initStringInfo(&buf); + /* + * Each list member may be a plain A_Const node, or an A_Const within a + * TypeCast, as produced by makeFloatConst() et al in gram.y. + */ foreach(l, args) { ! Node *arg = (Node *) lfirst(l); char *val; + TypeName *typename = NULL; + A_Const *con; if (l != list_head(args)) appendStringInfo(&buf, ", "); + if (IsA(arg, TypeCast)) + { + TypeCast *tc = (TypeCast *) arg; + + arg = tc->arg; + typename = tc->typename; + } + if (!IsA(arg, A_Const)) elog(ERROR, "unrecognized node type: %d", (int) nodeTag(arg)); ! con = (A_Const *) arg; ! switch (nodeTag(&con->val)) { case T_Integer: ! appendStringInfo(&buf, "%ld", intVal(&con->val)); break; case T_Float: /* represented as a string, so just copy it */ ! appendStringInfoString(&buf, strVal(&con->val)); break; case T_String: ! /* ! * Plain string literal or identifier. For quote mode, ! * quote it if it's not a vanilla identifier. ! */ ! val = strVal(&con->val); ! if (typename != NULL) { /* * Must be a ConstInterval argument for TIME ZONE. Coerce *************** flatten_set_variable_args(const char *na *** 5241,5247 **** Datum interval; char *intervalout; ! typoid = typenameTypeId(NULL, arg->typename, &typmod); Assert(typoid == INTERVALOID); interval = --- 5260,5266 ---- Datum interval; char *intervalout; ! typoid = typenameTypeId(NULL, typename, &typmod); Assert(typoid == INTERVALOID); interval = *************** flatten_set_variable_args(const char *na *** 5254,5266 **** DatumGetCString(DirectFunctionCall1(interval_out, interval)); appendStringInfo(&buf, "INTERVAL '%s'", intervalout); } else { - /* - * Plain string literal or identifier. For quote mode, - * quote it if it's not a vanilla identifier. - */ if (flags & GUC_LIST_QUOTE) appendStringInfoString(&buf, quote_identifier(val)); else --- 5273,5284 ---- DatumGetCString(DirectFunctionCall1(interval_out, interval)); appendStringInfo(&buf, "INTERVAL '%s'", intervalout); + + /* don't leave this set */ + typename = NULL; } else { if (flags & GUC_LIST_QUOTE) appendStringInfoString(&buf, quote_identifier(val)); else *************** flatten_set_variable_args(const char *na *** 5269,5275 **** break; default: elog(ERROR, "unrecognized node type: %d", ! (int) nodeTag(&arg->val)); break; } } --- 5287,5293 ---- break; default: elog(ERROR, "unrecognized node type: %d", ! (int) nodeTag(&con->val)); break; } } Index: src/include/catalog/catversion.h =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/include/catalog/catversion.h,v retrieving revision 1.451 diff -c -p -r1.451 catversion.h *** src/include/catalog/catversion.h 28 Apr 2008 14:57:35 -0000 1.451 --- src/include/catalog/catversion.h 28 Apr 2008 16:17:17 -0000 *************** *** 53,58 **** */ /* yyyymmddN */ ! #define CATALOG_VERSION_NO 200804281 #endif --- 53,58 ---- */ /* yyyymmddN */ ! #define CATALOG_VERSION_NO 200804282 #endif Index: src/include/nodes/parsenodes.h =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/include/nodes/parsenodes.h,v retrieving revision 1.362 diff -c -p -r1.362 parsenodes.h *** src/include/nodes/parsenodes.h 14 Apr 2008 17:05:34 -0000 1.362 --- src/include/nodes/parsenodes.h 28 Apr 2008 19:16:49 -0000 *************** typedef struct A_Const *** 234,250 **** { NodeTag type; Value val; /* the value (with the tag) */ ! TypeName *typename; /* typecast, or NULL if none */ } A_Const; /* * TypeCast - a CAST expression - * - * NOTE: for mostly historical reasons, A_Const parsenodes contain - * room for a TypeName, allowing a constant to be marked as being of a given - * type without a separate TypeCast node. Either representation will work, - * but the combined representation saves a bit of code in many - * productions in gram.y. */ typedef struct TypeCast { --- 234,244 ---- { NodeTag type; Value val; /* the value (with the tag) */ ! int location; /* token location, or -1 if unknown */ } A_Const; /* * TypeCast - a CAST expression */ typedef struct TypeCast {
-- Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-patches