Joe Conway wrote:
Markus Bertheau wrote:

Is there a reason the array_in parser accepts additional closing braces
at the end?

oocms=# SELECT '{}}'::text[];
 text
------
 {}
(1 ÐÐÐÐÑÑ)


Hmmm, I was *about* to say that this is fixed in cvs (and indeed, the array_in parser is significantly tightened up compared to previous releases), but unfortunately, there is still work to be done :(

The attached patch takes care of the above issue:

regression=# SELECT '{}}'::text[];
ERROR:  malformed array literal: "{}}"

If there are no objections, I'll apply in about 24 hours.

Joe
Index: src/backend/utils/adt/arrayfuncs.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/adt/arrayfuncs.c,v
retrieving revision 1.107
diff -c -r1.107 arrayfuncs.c
*** src/backend/utils/adt/arrayfuncs.c	8 Aug 2004 05:01:55 -0000	1.107
--- src/backend/utils/adt/arrayfuncs.c	27 Aug 2004 20:31:46 -0000
***************
*** 183,190 ****
  	typioparam = my_extra->typioparam;
  
  	/* Make a modifiable copy of the input */
! 	/* XXX why are we allocating an extra 2 bytes here? */
! 	string_save = (char *) palloc(strlen(string) + 3);
  	strcpy(string_save, string);
  
  	/*
--- 183,189 ----
  	typioparam = my_extra->typioparam;
  
  	/* Make a modifiable copy of the input */
! 	string_save = (char *) palloc0(strlen(string) + 1);
  	strcpy(string_save, string);
  
  	/*
***************
*** 375,380 ****
--- 374,380 ----
  					nelems_last[MAXDIM];
  	bool			scanning_string = false;
  	bool			eoArray = false;
+ 	bool			empty_array = true;
  	char		   *ptr;
  	ArrayParseState	parse_state = ARRAY_NO_LEVEL;
  
***************
*** 385,391 ****
  	}
  
  	/* special case for an empty array */
! 	if (strncmp(str, "{}", 2) == 0)
  		return 0;
  
  	ptr = str;
--- 385,391 ----
  	}
  
  	/* special case for an empty array */
! 	if (strlen(str) == 2 && strncmp(str, "{}", 2) == 0)
  		return 0;
  
  	ptr = str;
***************
*** 395,400 ****
--- 395,404 ----
  
  		while (!itemdone)
  		{
+ 			if (parse_state == ARRAY_ELEM_STARTED ||
+ 				parse_state == ARRAY_QUOTED_ELEM_STARTED)
+ 				empty_array = false;
+ 			
  			switch (*ptr)
  			{
  				case '\0':
***************
*** 481,487 ****
  						if (parse_state != ARRAY_ELEM_STARTED &&
  							parse_state != ARRAY_ELEM_COMPLETED &&
  							parse_state != ARRAY_QUOTED_ELEM_COMPLETED &&
! 							parse_state != ARRAY_LEVEL_COMPLETED)
  							ereport(ERROR,
  								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
  								errmsg("malformed array literal: \"%s\"", str)));
--- 485,492 ----
  						if (parse_state != ARRAY_ELEM_STARTED &&
  							parse_state != ARRAY_ELEM_COMPLETED &&
  							parse_state != ARRAY_QUOTED_ELEM_COMPLETED &&
! 							parse_state != ARRAY_LEVEL_COMPLETED &&
! 							!(nest_level == 1 &&  parse_state == ARRAY_LEVEL_STARTED))
  							ereport(ERROR,
  								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
  								errmsg("malformed array literal: \"%s\"", str)));
***************
*** 562,567 ****
--- 567,586 ----
  		temp[ndim - 1]++;
  		ptr++;
  	}
+ 	
+ 	/* only whitespace is allowed after the closing brace */
+ 	while (*ptr)
+ 	{
+ 		if (!isspace(*ptr++))
+ 			ereport(ERROR,
+ 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ 				errmsg("malformed array literal: \"%s\"", str)));
+ 	}
+ 	
+ 	/* special case for an empty array */
+ 	if (empty_array)
+ 		return 0;
+ 		
  	for (i = 0; i < ndim; ++i)
  		dim[i] = temp[i];
  
Index: src/test/regress/expected/arrays.out
===================================================================
RCS file: /cvsroot/pgsql-server/src/test/regress/expected/arrays.out,v
retrieving revision 1.22
diff -c -r1.22 arrays.out
*** src/test/regress/expected/arrays.out	5 Aug 2004 03:30:03 -0000	1.22
--- src/test/regress/expected/arrays.out	27 Aug 2004 20:31:46 -0000
***************
*** 425,427 ****
--- 425,485 ----
   t
  (1 row)
  
+ --
+ -- General array parser tests
+ --
+ -- none of the following should be accepted
+ select '{{1,{2}},{2,3}}'::text[];
+ ERROR:  malformed array literal: "{{1,{2}},{2,3}}"
+ select '{{},{}}'::text[];
+ ERROR:  malformed array literal: "{{},{}}"
+ select '{{1,2},\\{2,3}}'::text[];
+ ERROR:  malformed array literal: "{{1,2},\{2,3}}"
+ select '{{"1 2" x},{3}}'::text[];
+ ERROR:  malformed array literal: "{{"1 2" x},{3}}"
+ select '{}}'::text[];
+ ERROR:  malformed array literal: "{}}"
+ select '{ }}'::text[];
+ ERROR:  malformed array literal: "{ }}"
+ -- none of the above should be accepted
+ -- all of the following should be accepted
+ select '{}'::text[];
+  text 
+ ------
+  {}
+ (1 row)
+ 
+ select '{{{1,2,3,4},{2,3,4,5}},{{3,4,5,6},{4,5,6,7}}}'::text[];
+                      text                      
+ -----------------------------------------------
+  {{{1,2,3,4},{2,3,4,5}},{{3,4,5,6},{4,5,6,7}}}
+ (1 row)
+ 
+ select '{0 second  ,0 second}'::interval[];
+    interval    
+ ---------------
+  {"@ 0","@ 0"}
+ (1 row)
+ 
+ select '{ { "," } , { 3 } }'::text[];
+     text     
+ -------------
+  {{","},{3}}
+ (1 row)
+ 
+ select '  {   {  "  0 second  "   ,  0 second  }   }'::text[];
+              text              
+ -------------------------------
+  {{"  0 second  ","0 second"}}
+ (1 row)
+ 
+ select '{
+            0 second,
+            @ 1 hour @ 42 minutes @ 20 seconds
+          }'::interval[];
+               interval              
+ ------------------------------------
+  {"@ 0","@ 1 hour 42 mins 20 secs"}
+ (1 row)
+ 
+ -- all of the above should be accepted
Index: src/test/regress/sql/arrays.sql
===================================================================
RCS file: /cvsroot/pgsql-server/src/test/regress/sql/arrays.sql,v
retrieving revision 1.17
diff -c -r1.17 arrays.sql
*** src/test/regress/sql/arrays.sql	9 Jun 2004 19:08:20 -0000	1.17
--- src/test/regress/sql/arrays.sql	27 Aug 2004 20:31:46 -0000
***************
*** 192,194 ****
--- 192,219 ----
  select 'foo' not like all (array['%a', '%o']); -- f
  select 'foo' ilike any (array['%A', '%O']); -- t
  select 'foo' ilike all (array['F%', '%O']); -- t
+ 
+ --
+ -- General array parser tests
+ --
+ 
+ -- none of the following should be accepted
+ select '{{1,{2}},{2,3}}'::text[];
+ select '{{},{}}'::text[];
+ select '{{1,2},\\{2,3}}'::text[];
+ select '{{"1 2" x},{3}}'::text[];
+ select '{}}'::text[];
+ select '{ }}'::text[];
+ -- none of the above should be accepted
+ 
+ -- all of the following should be accepted
+ select '{}'::text[];
+ select '{{{1,2,3,4},{2,3,4,5}},{{3,4,5,6},{4,5,6,7}}}'::text[];
+ select '{0 second  ,0 second}'::interval[];
+ select '{ { "," } , { 3 } }'::text[];
+ select '  {   {  "  0 second  "   ,  0 second  }   }'::text[];
+ select '{
+            0 second,
+            @ 1 hour @ 42 minutes @ 20 seconds
+          }'::interval[];
+ -- all of the above should be accepted
---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faqs/FAQ.html

Reply via email to