Removing typename from A_Const (was: Empty arrays with ARRAY[])

Started by Brendan Jurdover 17 years ago10 messages
#1Brendan Jurd
direvus@gmail.com
1 attachment(s)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, Mar 21, 2008 at 7:47 AM, Tom Lane wrote:

I didn't do anything about removing A_Const's typename field, but I'm
thinking that would be a good cleanup patch.

Here's my attempt to remove the typename field from A_Const. There
were a few places (notably flatten_set_variable_args() in guc.c, and
typenameTypeMod() in parse_type.c) where the code expected to see an
A_Const with a typename, and I had to adjust for an A_Const within a
TypeCast. Nonetheless, there was an overall net reduction of 34 lines
of code, so I think this was a win.

All regression tests passed on x86_64 gentoo.

Added to May CommitFest.

Cheers,
BJ
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.7 (GNU/Linux)
Comment: http://getfiregpg.org

iD8DBQFIA8s/5YBsbHkuyV0RAlMdAJ0dWdoZd5cypvInAR2msO8XA8qqxACeILSw
bCI2TGAQI3m3TBoJspvV4OQ=
=dGP9
-----END PGP SIGNATURE-----

Attachments:

aconst-no-typename_0.diff.bz2application/x-bzip2; name=aconst-no-typename_0.diff.bz2Download
BZh91AY&SY�<y�9_��w�����������`�}��ji���S�]��mK@��P������
����lh(�

{4@�"j��#MM�4� �Bji4�zx��=M��h�Q�@���M4����F@& 4i%����S�M'���@h	�L)(!�hM�I��`&�&`&�*(��@LF���L�S�iF�zG�d��4�z��jy��Ts��-BI"��� �&��@`O�"*�uRR�J �Q@QF1I�YJ����hN4���@��b3��CI��`��@�){BH��Y$J$�AQ%dE�T(�$$Db�7����Z7C������[[[m����c�I��UUW�-�h�`�8��t���uZC�aD���:���M�:$e��[x���
kD����� 0"Qr��HN`
f��#i���@CC�jh�,��Z6L!�bPU�:�f��d��UT�l����#T7%d���Z��KeY�����q���<x��ea3�sFV�2�8E�d�)� C�L2~�Z��Tx|��[:I�{l1)��������/Bc
6���d
��P���M��os��������p9���-b�^�9`����[
������mk8�^2Oc������,�~n[���5��=7wN�����=�l���)f.r�� c!A$
�H��UE�bEJ1F��(R3D��*���dR�XP
2����`�P�"Zf6����T�#�d���(��E(�D�3*���HLj�+I���QT��b��UT�h$�v������v
}�.+��I�<���d���X�w�������j�&0{�����,�z���I�����t�_��>o�]�^T����'�x�����������Y�l3����N���(	%���`����UJ��
�	d��vv�Qh=�-�dH�*���X�����_.����� ���=wK�
	�b5,RvF@@�aa�`��dp�����������>��'��qQ���<~������f���e��"����g������:�$������?����I2���7U��K"���qD�V��S�Fp��h5N-8�n�����v����oB�?���I�c��-����3��p��59G����G[�t5����S��,����9��
��HE�l\��p��l[8��qp�*��`��p����D)\�p)6�	t���O)� U�K��=c���9��r�Fl4{��27������F�vf��7foc� ��>��:|^C��6�/&�	0����|7i�����'��h4xo�k���4����2d�b}��q���$�60w;^�Nze2�h�~W�Y��y.�,�z����>���
4:��7�~���^��:
��x$�o�s����Sb����`v���������:��vJ��8��u����>����=������;��z4��L�9-��s�P�_r<F��K�%���g^W���Jo������a%\�������`�����c�������N�����k��������<�i�D1�4�6[-D<����qN�UX�UJ���BO�I,�""�2FFA�H�%�1�����.��!g4�B�w;�"9$�	<N�`T:���2����
qa���{�1&������Z�_t�4Y��#z�0a���-�����4D��J8�>W�mf�^*c��csS�3�0�����F�?��������H�@�S	Y��}�����4���������>#����u#��?�����!<��*��cM�8�q�;
?Q�:;]m�k����s:��z���77��
)��h�#�p��NA��$����l�n&|���S%,�nk3��!Y�.N=�R�:���2�6b���9``��1��'�@ZP8I��F������)�����=EYV��DRUYW�X�ar#��O�o��F�����-�.�y��4���������y)����������r��i3���3(��G�T�"<\��F�I!!���Q���,jN�y%���'�"a�J$�`F*y�q�DfD�1�n�~5���JM"L"0��=�c�,������2���Z��u��#�~;n��3��[O{&��M&�@��3�f���xp71G����=l���5�]u{$#�|"G�w����0VK���1�C��
d��o����A�=����5����K)�:{��F�h�c��)��9���-(��J:��������"\�;\T8�Y���o��!zl�I�n+kn8��\D��:���3��+�l��`CN�u��E-jw��w��4��E�]��U�d�qe���|��N���gU+!�E�/{���h�;���_a�:���j���i��fG.lM��r�g���I!$$�����_rD��I!$�y���QN%e��5k:������;�{��iL:t�JK��p7pD{�R��e
��6@g{��I���$���!�b��`��=S�����I������y�B���"���%��M���lLcoA1��q&�I�)����!��?�+�	���g����`�()]:2���������I�e�t�����:3����a�.
�m�H��T��%T�,IU0��{�DQ������2d�?���H�x�8O(jX)�h�.WC�`���f,\`Xf#�a��rh����_�n�����`����$4B	QG�Z����E�YK2��\A�=�����Y�-�4+�0�xxqK�z������EZ�s�e�EI����}/j{���R:�����*Nm��qd�Q������;�:�.�����&_k�z�f�y�a�����O�j:^/�#���!�����<6GL|�=�.}c���������C��`nx.R��RoMc�+��=h�T���M��~�)[�y���8!��$8,���A�X����K$��gT��}��Q�=�t��x���#���-�jO�/3�I�����/)�z�5l��7w��Q5&S��R=}���	�6H���
���a��sQ�6�0��=k��{���?�-L?�=����0�����������e0xE;Rc$v�t�m��c���ht,�����EK��&��+�Vo��4I!t;k���O�u�����0����u
��;��gg��nk��MZ8�n���j�n�(u�GT���_-VR�Q���C��wLt}��2���e�`l��q�H�6'���8y8�.F�A�!�
��o����Y�p`�d���D����Y��x���L]h\���~)��D�fR��w���'�N&�����c�����O����T��Q-%*�:����p�
������Z�1tYc{��(D$�Id��K���Pr��"��"�����s����'GWI��(����b�al������d����6MXj���z���x����z!����d;���}�,����$��'S�#�13h��T;����R/�'7M�a�����J8D�rtt�;>NS����s�R������VzL63$�8q��e8����L�.b�.I���/����r�����^U�ml�J�U�Vr[�Fc�����d�c�����&v�	���6phx��M� �T��<:�rk$���e��p�s������@�M	D��	4,�7IF$����R�3z�s�f���d0�\[M�	����]8Yl����JY{tYb��(�b�h����F	���>�0�
�*�T���3X�0�����!��q�IIR7Jkuj���osP�J�
�M�5:88����U��I�:>&
�s����&�?����>��<#��H���C?����������I�{���>����+)�:���~g�u����88��}w����<z��<^#���Y
�������vW���b0��k+�%7�ML%rx���0��u����t0L������c��9I��	U�a�����YbZ�����t�F�L�=lhF�0�~W�s�kyR1��s)����^�$�b�X���*���l}��G����X����gL1�t6}��j�� �}<&L<�_Z=No���=L ��^������S�k�S������v�c��w���EY>���l|]������q-*I���<�=.
��G��'�>�������M}�0T��dz�����)VL�V�	XC
XJ2( `��b0�}�����7y�po��g������X��<��a������I�+�0���sru��|�'�r7���7Z�����q��	�>��e������Y��Mfd�l���U)R��~��)M@��YU���m
!$�?�N���0�F"ET��GKd��hG�~�[$�=�{�XB�Ngj2��F�3:U,%�R���Y�����v
v*a��[J��8J�beX��Fb*cU��9e����s��R<�z�:����}c��>���#m�GJ�T��)�$�xT�>��
$����b>��5b��p7�1����31�+Y&v�����$���7Z:�LI$J��C4�����VZ���4U�UT4Y�2�l�{k
{��#����I#i<��F&U0�+*��������]�n9���EI�eG�,N_�NS��n;B��E�UQRB�ImW�G�K��h��;�f,�V}nf��>��3�����89�W%W���%o����b�2D<�s�����'�2a�e��=����q�r��,&�������)C�9Q�b�	Q��he���1+T~��l�#g��h������K�������`�8�_�OdeI���:�D'	���#����WC��9���n&\��4I���IaN�i%��J&�3vIb��s>���9�G��OrnO�G�&�;�����yY���I�����;^V�����y,�N�m�����o+��W��;R4��7(����U"	"
 X��3
���&���b���T:e�"E�ji���$�3:�.'�)t#g/���<�����,�4�i�p�N��o��2;���W��9����d0�Il�tn��M7��L)���Mb�t����s
���I&���8���)�Nk�^w���$�4�}�
�8��n�������u&��80����3����wN���~�H�;�]���H�*J�-�{2hH��&'[G��R/tW"�&���*�NMI����I�t�S�&���Q'gUfMR�
�$�K�'W	�Q�!��y�,����M�$�,S����a��h��v6�7�X�"�
�C��$�����~�HJD��O��\����:�f�#�~��6�oGS���Y�y�S?/_������p�K.1WV�V�C�!Bw���E�<!'��X��vk;AR��{:k}�=������;z��>g���ZtW@�I>�,�%�J�$�B);���4y�3%d�
d
�[���M����N�� �D
��� ���������)������
#2Alvaro Herrera
alvherre@commandprompt.com
In reply to: Brendan Jurd (#1)
Re: Removing typename from A_Const (was: Empty arrays with ARRAY[])

Brendan Jurd escribi�:

Here's my attempt to remove the typename field from A_Const. There
were a few places (notably flatten_set_variable_args() in guc.c, and
typenameTypeMod() in parse_type.c) where the code expected to see an
A_Const with a typename, and I had to adjust for an A_Const within a
TypeCast. Nonetheless, there was an overall net reduction of 34 lines
of code, so I think this was a win.

Do say ... why don't we do away with A_Const altogether and just replace
it with Value? After this patch, I don't see what's the difference.

--
Alvaro Herrera http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alvaro Herrera (#2)
Re: Removing typename from A_Const (was: Empty arrays with ARRAY[])

Alvaro Herrera <alvherre@commandprompt.com> writes:

Brendan Jurd escribi�:

Here's my attempt to remove the typename field from A_Const. There
were a few places (notably flatten_set_variable_args() in guc.c, and
typenameTypeMod() in parse_type.c) where the code expected to see an
A_Const with a typename, and I had to adjust for an A_Const within a
TypeCast. Nonetheless, there was an overall net reduction of 34 lines
of code, so I think this was a win.

Do say ... why don't we do away with A_Const altogether and just replace
it with Value? After this patch, I don't see what's the difference.

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.

regards, tom lane

#4Alvaro Herrera
alvherre@commandprompt.com
In reply to: Tom Lane (#3)
Re: [HACKERS] Removing typename from A_Const (was: Empty arrays with ARRAY[])

Tom Lane escribió:

Alvaro Herrera <alvherre@commandprompt.com> writes:

Brendan Jurd escribi�:

Here's my attempt to remove the typename field from A_Const. There
were a few places (notably flatten_set_variable_args() in guc.c, and
typenameTypeMod() in parse_type.c) where the code expected to see an
A_Const with a typename, and I had to adjust for an A_Const within a
TypeCast. Nonetheless, there was an overall net reduction of 34 lines
of code, so I think this was a win.

Do say ... why don't we do away with A_Const altogether and just replace
it with Value? After this patch, I don't see what's the difference.

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.

--
Alvaro Herrera http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alvaro Herrera (#4)
Re: [HACKERS] Removing typename from A_Const (was: Empty arrays with ARRAY[])

Alvaro Herrera <alvherre@commandprompt.com> 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.

regards, tom lane

#6Alvaro Herrera
alvherre@commandprompt.com
In reply to: Tom Lane (#5)
1 attachment(s)
Re: [HACKERS] Removing typename from A_Const (was: Empty arrays with ARRAY[])

Tom Lane escribi�:

Alvaro Herrera <alvherre@commandprompt.com> 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

Attachments:

aconst-no-typename-1.patchtext/x-diff; charset=us-asciiDownload
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
  {
#7Alvaro Herrera
alvherre@commandprompt.com
In reply to: Alvaro Herrera (#6)
Re: [HACKERS] Removing typename from A_Const (was: Empty arrays with ARRAY[])

Alvaro Herrera escribi�:

Tom Lane escribi�:

Alvaro Herrera <alvherre@commandprompt.com> 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.

Hmm, I'm now wondering if the location should be added to Value as well,
so that it can be passed down to Const?

--
Alvaro Herrera http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.

#8Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alvaro Herrera (#6)
Re: [HACKERS] Removing typename from A_Const (was: Empty arrays with ARRAY[])

Alvaro Herrera <alvherre@commandprompt.com> writes:

I came up with the attached patch.

I wasn't envisioning anything anywhere near this invasive. We only
need locations on constants in a few contexts, I think.

BTW, you broke _equalAConst() ... it was a bad idea anyway to recast
it on the assumption that there would never again be more than one
field.

regards, tom lane

#9Alvaro Herrera
alvherre@commandprompt.com
In reply to: Tom Lane (#8)
Re: [HACKERS] Removing typename from A_Const (was: Empty arrays with ARRAY[])

Tom Lane escribi�:

Alvaro Herrera <alvherre@commandprompt.com> writes:

I came up with the attached patch.

I wasn't envisioning anything anywhere near this invasive. We only
need locations on constants in a few contexts, I think.

Aha. OK, I'll commit the original patch and let you deal with the rest
of it :-)

BTW, you broke _equalAConst() ... it was a bad idea anyway to recast
it on the assumption that there would never again be more than one
field.

Oops, sorry, I had intended to revert that part and forgot.

--
Alvaro Herrera http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

#10Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alvaro Herrera (#7)
Re: [HACKERS] Removing typename from A_Const (was: Empty arrays with ARRAY[])

Alvaro Herrera <alvherre@commandprompt.com> writes:

Hmm, I'm now wondering if the location should be added to Value as well,
so that it can be passed down to Const?

Just for the record, we don't want it in Const. Parse locations are
only useful in the "raw grammar" output, mainly because they aren't
helpful unless you still have the original query string laying about.

regards, tom lane