*** ./doc/src/sgml/func.sgml.orig	2010-07-03 19:21:48.000000000 +0200
--- ./doc/src/sgml/func.sgml	2010-07-20 08:44:59.267804371 +0200
***************
*** 4652,4658 ****
     </para>
  
     <para>
!     If case-independent matching is specified,
      the effect is much as if all case distinctions had vanished from the
      alphabet.
      When an alphabetic that exists in multiple cases appears as an
--- 4652,4658 ----
     </para>
  
     <para>
!      If case-independent matching is specified,
      the effect is much as if all case distinctions had vanished from the
      alphabet.
      When an alphabetic that exists in multiple cases appears as an
***************
*** 9544,9549 ****
--- 9544,9555 ----
      <primary>string_to_array</primary>
    </indexterm>
    <indexterm>
+     <primary>to_array</primary>
+   </indexterm>
+   <indexterm>
+     <primary>to_string</primary>
+   </indexterm>
+   <indexterm>
      <primary>unnest</primary>
    </indexterm>
  
***************
*** 9686,9691 ****
--- 9692,9719 ----
         <row>
          <entry>
           <literal>
+           <function>to_array</function>(<type>text</type>, <type>text</type> <optional>, <type>text</type></optional>)
+          </literal>
+         </entry>
+         <entry><type>text[]</type></entry>
+         <entry>splits string into array elements using supplied delimiter and null string</entry>
+         <entry><literal>to_array('1,2,3,,5', ',')</literal></entry>
+         <entry><literal>{1,2,3,4,NULL,5}</literal></entry>
+        </row>
+        <row>
+         <entry>
+          <literal>
+           <function>to_string</function>(<type>anyarray</type>, <type>text</type> <optional>, <type>text</type></optional>)
+          </literal>
+         </entry>
+         <entry><type>text</type></entry>
+         <entry>concatenates array elements using supplied delimiter and null string</entry>
+         <entry><literal>to_string(ARRAY[1, 2, 3, NULL, 5], ',', '*')</literal></entry>
+         <entry><literal>1,2,3,*,5</literal></entry>
+        </row>
+        <row>
+         <entry>
+          <literal>
            <function>unnest</function>(<type>anyarray</type>)
           </literal>
          </entry>
*** ./src/backend/catalog/system_views.sql.orig	2010-07-20 08:44:18.940804380 +0200
--- ./src/backend/catalog/system_views.sql	2010-07-20 11:20:20.415803330 +0200
***************
*** 487,489 ****
--- 487,497 ----
  CREATE OR REPLACE FUNCTION
    pg_start_backup(label text, fast boolean DEFAULT false)
    RETURNS text STRICT VOLATILE LANGUAGE internal AS 'pg_start_backup';
+ 
+ CREATE OR REPLACE FUNCTION
+   to_string(v anyarray, fldsep text, null_string text DEFAULT '')
+   RETURNS text STABLE LANGUAGE internal AS 'to_string';
+ 
+ CREATE OR REPLACE FUNCTION
+   to_array(inputstr text, fldsep text, null_string text DEFAULT '')
+   RETURNS text[] IMMUTABLE LANGUAGE internal AS 'to_array';
*** ./src/backend/utils/adt/array_userfuncs.c.orig	2010-07-20 08:44:18.941805977 +0200
--- ./src/backend/utils/adt/array_userfuncs.c	2010-07-20 08:44:59.271806788 +0200
***************
*** 407,415 ****
--- 407,417 ----
  create_singleton_array(FunctionCallInfo fcinfo,
  					   Oid element_type,
  					   Datum element,
+ 					   bool isNull,
  					   int ndims)
  {
  	Datum		dvalues[1];
+ 	bool		nulls[1];
  	int16		typlen;
  	bool		typbyval;
  	char		typalign;
***************
*** 429,434 ****
--- 431,437 ----
  						ndims, MAXDIM)));
  
  	dvalues[0] = element;
+ 	nulls[0] = isNull;
  
  	for (i = 0; i < ndims; i++)
  	{
***************
*** 462,468 ****
  	typbyval = my_extra->typbyval;
  	typalign = my_extra->typalign;
  
! 	return construct_md_array(dvalues, NULL, ndims, dims, lbs, element_type,
  							  typlen, typbyval, typalign);
  }
  
--- 465,471 ----
  	typbyval = my_extra->typbyval;
  	typalign = my_extra->typalign;
  
! 	return construct_md_array(dvalues, nulls, ndims, dims, lbs, element_type,
  							  typlen, typbyval, typalign);
  }
  
*** ./src/backend/utils/adt/varlena.c.orig	2010-07-20 08:44:18.943806309 +0200
--- ./src/backend/utils/adt/varlena.c	2010-07-20 13:19:45.006803452 +0200
***************
*** 75,80 ****
--- 75,83 ----
  static bytea *bytea_overlay(bytea *t1, bytea *t2, int sp, int sl);
  static StringInfo makeStringAggState(FunctionCallInfo fcinfo);
  
+ static Datum _to_array(PG_FUNCTION_ARGS);
+ static Datum _to_text(PG_FUNCTION_ARGS);
+ 
  
  /*****************************************************************************
   *	 CONVERSION ROUTINES EXPORTED FOR USE BY C CODE							 *
***************
*** 2965,2970 ****
--- 2968,2984 ----
  }
  
  /*
+  * Returns true when two text params are same.
+  */
+ static 
+ bool text_isequal(text *txt1, text *txt2)
+ {
+ 	return DatumGetBool(DirectFunctionCall2(texteq,
+ 							PointerGetDatum(txt1),
+ 							PointerGetDatum(txt2)));
+ }
+ 
+ /*
   * text_to_array
   * parse input string
   * return text array of elements
***************
*** 2973,3076 ****
  Datum
  text_to_array(PG_FUNCTION_ARGS)
  {
! 	text	   *inputstring = PG_GETARG_TEXT_PP(0);
! 	text	   *fldsep = PG_GETARG_TEXT_PP(1);
  	int			inputstring_len;
- 	int			fldsep_len;
- 	TextPositionState state;
- 	int			fldnum;
- 	int			start_posn;
- 	int			end_posn;
- 	int			chunk_len;
  	char	   *start_ptr;
  	text	   *result_text;
  	ArrayBuildState *astate = NULL;
  
! 	text_position_setup(inputstring, fldsep, &state);
! 
! 	/*
! 	 * Note: we check the converted string length, not the original, because
! 	 * they could be different if the input contained invalid encoding.
! 	 */
! 	inputstring_len = state.len1;
! 	fldsep_len = state.len2;
! 
! 	/* return NULL for empty input string */
! 	if (inputstring_len < 1)
! 	{
! 		text_position_cleanup(&state);
  		PG_RETURN_NULL();
! 	}
  
! 	/*
! 	 * empty field separator return one element, 1D, array using the input
! 	 * string
  	 */
! 	if (fldsep_len < 1)
! 	{
! 		text_position_cleanup(&state);
! 		PG_RETURN_ARRAYTYPE_P(create_singleton_array(fcinfo, TEXTOID,
! 										   PointerGetDatum(inputstring), 1));
! 	}
! 
! 	start_posn = 1;
! 	/* start_ptr points to the start_posn'th character of inputstring */
! 	start_ptr = VARDATA_ANY(inputstring);
! 
! 	for (fldnum = 1;; fldnum++) /* field number is 1 based */
  	{
! 		CHECK_FOR_INTERRUPTS();
! 
! 		end_posn = text_position_next(start_posn, &state);
  
! 		if (end_posn == 0)
  		{
! 			/* fetch last field */
! 			chunk_len = ((char *) inputstring + VARSIZE_ANY(inputstring)) - start_ptr;
  		}
! 		else
  		{
! 			/* fetch non-last field */
! 			chunk_len = charlen_to_bytelen(start_ptr, end_posn - start_posn);
  		}
  
! 		/* must build a temp text datum to pass to accumArrayResult */
! 		result_text = cstring_to_text_with_len(start_ptr, chunk_len);
  
! 		/* stash away this field */
! 		astate = accumArrayResult(astate,
  								  PointerGetDatum(result_text),
! 								  false,
! 								  TEXTOID,
! 								  CurrentMemoryContext);
  
! 		pfree(result_text);
  
! 		if (end_posn == 0)
! 			break;
  
! 		start_posn = end_posn;
! 		start_ptr += chunk_len;
! 		start_posn += fldsep_len;
! 		start_ptr += charlen_to_bytelen(start_ptr, fldsep_len);
  	}
  
! 	text_position_cleanup(&state);
  
! 	PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate,
! 										  CurrentMemoryContext));
  }
  
  /*
   * array_to_text
   * concatenate Cstring representation of input array elements
!  * using provided field separator
   */
  Datum
  array_to_text(PG_FUNCTION_ARGS)
  {
! 	ArrayType  *v = PG_GETARG_ARRAYTYPE_P(0);
! 	char	   *fldsep = text_to_cstring(PG_GETARG_TEXT_PP(1));
  	int			nitems,
  			   *dims,
  				ndims;
--- 2987,3197 ----
  Datum
  text_to_array(PG_FUNCTION_ARGS)
  {
! 	text *inputstr = PG_GETARG_TEXT_PP(0);
! 
! 	/* function string_to_array returns a NULL for empty string */
! 	if (VARSIZE_ANY_EXHDR(inputstr) < 1)
! 		PG_RETURN_NULL();
! 
! 	return _to_array(fcinfo);
! }
! 
! /*
!  * just only outer wrapper
!  */
! Datum
! to_array(PG_FUNCTION_ARGS)
! {
! 	return _to_array(fcinfo);
! }
! 
! /*
!  * _to_array - common code for to_array and text_to_array functions
!  */
! static Datum 
! _to_array(PG_FUNCTION_ARGS)
! {
  	int			inputstring_len;
  	char	   *start_ptr;
  	text	   *result_text;
  	ArrayBuildState *astate = NULL;
+ 	bool		is_null;
+ 	text	   *inputstring;
+ 	text	   *fldsep;
+ 	text	   *null_string;
  
! 	/* when input string is NULL, then result is NULL too */
! 	if (PG_ARGISNULL(0))
  		PG_RETURN_NULL();
! 		
! 	inputstring = PG_GETARG_TEXT_PP(0);
  
! 	/* 
! 	 * when null string is NULL, there are not string representation for NULL,
! 	 * the behave is compatible old text_to_array function. to_array function has
! 	 * three arguments - last argument has default value. text_to_array function 
! 	 * has two arguments. When null_string is NULL, then behave is same like
! 	 * old text_to_array (string_to_array) function. 
  	 */
! 	if (PG_NARGS() > 2)
! 		null_string = (!PG_ARGISNULL(2)) ? PG_GETARG_TEXT_PP(2) : NULL;
! 	else
! 		null_string = NULL;
! 	
! 	/* 
! 	 * when separator is NULL, then returns every character as field,
! 	 * there are no any character used as separator - etc separator is
! 	 * space between chars.
! 	 */
! 	if (!PG_ARGISNULL(1))
  	{
! 		TextPositionState state;
! 		int			fldnum;
! 		int			start_posn;
! 		int			end_posn;
! 		int			chunk_len;
! 	
! 		fldsep = PG_GETARG_TEXT_PP(1);
! 		
! 		text_position_setup(inputstring, fldsep, &state);
  
! 		/* return empty array for empty input string */
! 		if (state.len1 < 1)
  		{
! 			text_position_cleanup(&state);
! 			PG_RETURN_ARRAYTYPE_P(construct_empty_array(TEXTOID));
  		}
! 
! 		/*
! 		 * empty field separator return one element, 1D, array using the input
! 		 * string
! 		 */
! 		if (state.len2 < 1)
  		{
! 			text_position_cleanup(&state);
! 			/* single element can be a NULL too */
! 			is_null = (null_string != NULL) ? text_isequal(null_string, inputstring) : false;
! 			PG_RETURN_ARRAYTYPE_P(create_singleton_array(fcinfo, TEXTOID,
! 											PointerGetDatum(inputstring),
! 											is_null, 1));
  		}
+ 		
+ 		start_posn = 1;
+ 		/* start_ptr points to the start_posn'th character of inputstring */
+ 		start_ptr = VARDATA_ANY(inputstring);
+ 
+ 		for (fldnum = 1;; fldnum++) /* field number is 1 based */
+ 		{
+ 			CHECK_FOR_INTERRUPTS();
  
! 			end_posn = text_position_next(start_posn, &state);
! 
! 			if (end_posn == 0)
! 			{
! 				/* fetch last field */
! 				chunk_len = ((char *) inputstring + VARSIZE_ANY(inputstring)) - start_ptr;
! 			}
! 			else
! 			{
! 				/* fetch non-last field */
! 				chunk_len = charlen_to_bytelen(start_ptr, end_posn - start_posn);
! 			}
  
! 			/* must build a temp text datum to pass to accumArrayResult */
! 			result_text = cstring_to_text_with_len(start_ptr, chunk_len);
! 			is_null = (null_string != NULL) ? text_isequal(null_string, result_text) : false;
! 		
! 			/* stash away this field */
! 			astate = accumArrayResult(astate,
  								  PointerGetDatum(result_text),
! 												is_null,
! 												TEXTOID,
! 												CurrentMemoryContext);
  
! 			pfree(result_text);
  
! 			if (end_posn == 0)
! 				break;
  
! 			start_posn = end_posn;
! 			start_ptr += chunk_len;
! 			start_posn += state.len2;
! 			start_ptr += charlen_to_bytelen(start_ptr, state.len2);
! 		}
! 
! 		text_position_cleanup(&state);
  	}
+ 	else
+ 	{
+ 		/* 
+ 		 * simple mode 
+ 		 *  when field separator is NULL, then divide chars from string.
+ 		 */
+ 		inputstring_len = VARSIZE_ANY_EXHDR(inputstring);
+ 		
+ 		/* returns empty array for empty string */
+ 		if (inputstring_len < 1)
+ 			PG_RETURN_ARRAYTYPE_P(construct_empty_array(TEXTOID));
+ 		
+ 		start_ptr = VARDATA_ANY(inputstring);
+ 		
+ 		while (inputstring_len > 0)
+ 		{
+ 			int	chunk_len;
+ 			
+ 			chunk_len = pg_mblen(start_ptr);
+ 			result_text = cstring_to_text_with_len(start_ptr, chunk_len);
+ 			
+ 			is_null = (null_string != NULL) ? text_isequal(null_string, result_text) : false;
+ 		
+ 			/* stash away this field */
+ 			astate = accumArrayResult(astate,
+ 								  PointerGetDatum(result_text),
+ 												is_null,
+ 												TEXTOID,
+ 												CurrentMemoryContext);
  
! 			pfree(result_text);
! 			start_ptr += chunk_len;
! 			inputstring_len -= chunk_len;
! 		}
! 	}
  
! 	PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, CurrentMemoryContext));
  }
  
  /*
   * array_to_text
   * concatenate Cstring representation of input array elements
!  * using provided field separator - just only wrapper for 
!  * strict version of function.
   */
  Datum
  array_to_text(PG_FUNCTION_ARGS)
  {
! 	return _to_text(fcinfo);
! }
! 
! /*
!  * to_string
!  * concatenate Cstring representation of input array elements
!  * using provided field separator and null string - just only 
!  * wrapper for non strict three params function.
!  */
! Datum
! to_string(PG_FUNCTION_ARGS)
! {
! 	return _to_text(fcinfo);
! }
! 
! /*
!  * common code for array_to_text and to_string function. null_string can be
!  * NULL (only for array_to_text function).
!  */
! static Datum
! _to_text(PG_FUNCTION_ARGS)
! {
! 	ArrayType *v;
  	int			nitems,
  			   *dims,
  				ndims;
***************
*** 3085,3090 ****
--- 3206,3241 ----
  	int			bitmask;
  	int			i;
  	ArrayMetaState *my_extra;
+ 	char	*fieldsep;
+ 	char	*null_string;
+ 	text		*result;
+ 	
+ 	
+ 	/* returns NULL when input parameter is NULL */
+ 	if (PG_ARGISNULL(0))
+ 		PG_RETURN_NULL();
+ 	
+ 	v = PG_GETARG_ARRAYTYPE_P(0);
+ 		
+ 	
+ 	/* field separator cannot be a NULL */
+ 	if (PG_ARGISNULL(1))
+ 		ereport(ERROR, 
+ 				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ 				 errmsg("field separator cannot be NULL")));
+ 	
+ 	fieldsep = text_to_cstring(PG_GETARG_TEXT_PP(1));
+ 	
+ 	/* get a NULL string */
+ 	if (PG_NARGS() > 2)
+ 	{
+ 		if (!PG_ARGISNULL(2))
+ 			null_string = text_to_cstring(PG_GETARG_TEXT_PP(2));
+ 		else
+ 			null_string = NULL;
+ 	}
+ 	else
+ 		null_string = NULL;
  
  	ndims = ARR_NDIM(v);
  	dims = ARR_DIMS(v);
***************
*** 3092,3098 ****
  
  	/* if there are no elements, return an empty string */
  	if (nitems == 0)
! 		PG_RETURN_TEXT_P(cstring_to_text(""));
  
  	element_type = ARR_ELEMTYPE(v);
  	initStringInfo(&buf);
--- 3243,3249 ----
  
  	/* if there are no elements, return an empty string */
  	if (nitems == 0)
! 		PG_RETURN_TEXT_P(cstring_to_text_with_len("", 0));
  
  	element_type = ARR_ELEMTYPE(v);
  	initStringInfo(&buf);
***************
*** 3140,3146 ****
  		/* Get source element, checking for NULL */
  		if (bitmap && (*bitmap & bitmask) == 0)
  		{
! 			/* we ignore nulls */
  		}
  		else
  		{
--- 3291,3305 ----
  		/* Get source element, checking for NULL */
  		if (bitmap && (*bitmap & bitmask) == 0)
  		{
! 			/* we ignore nulls, when null_string isn't defined (is NULL) */
! 			if (null_string != NULL)
! 			{
! 				if (printed)
! 					appendStringInfo(&buf, "%s%s", fieldsep, null_string);
! 				else
! 					appendStringInfoString(&buf, null_string);
! 				printed = true;
! 			}
  		}
  		else
  		{
***************
*** 3149,3155 ****
  			value = OutputFunctionCall(&my_extra->proc, itemvalue);
  
  			if (printed)
! 				appendStringInfo(&buf, "%s%s", fldsep, value);
  			else
  				appendStringInfoString(&buf, value);
  			printed = true;
--- 3308,3314 ----
  			value = OutputFunctionCall(&my_extra->proc, itemvalue);
  
  			if (printed)
! 				appendStringInfo(&buf, "%s%s", fieldsep, value);
  			else
  				appendStringInfoString(&buf, value);
  			printed = true;
***************
*** 3169,3176 ****
  			}
  		}
  	}
  
! 	PG_RETURN_TEXT_P(cstring_to_text_with_len(buf.data, buf.len));
  }
  
  #define HEXBASE 16
--- 3328,3338 ----
  			}
  		}
  	}
+ 	
+ 	result = cstring_to_text_with_len(buf.data, buf.len);
+ 	pfree(buf.data);
  
! 	PG_RETURN_TEXT_P(result);
  }
  
  #define HEXBASE 16
*** ./src/include/catalog/pg_proc.h.orig	2010-07-20 08:44:18.944804554 +0200
--- ./src/include/catalog/pg_proc.h	2010-07-20 11:17:39.173804133 +0200
***************
*** 1022,1027 ****
--- 1022,1031 ----
  DESCR("split delimited text into text[]");
  DATA(insert OID = 395 (  array_to_string   PGNSP PGUID 12 1 0 0 f f f t f i 2 0 25 "2277 25" _null_ _null_ _null_ _null_ array_to_text _null_ _null_ _null_ ));
  DESCR("concatenate array elements, using delimiter, into text");
+ DATA(insert OID = 950 (  to_array   PGNSP PGUID 12 1 0 0 f f f f f i 3 0 1009 "25 25 25" _null_ _null_ _null_ _null_ to_array _null_ _null_ _null_ ));
+ DESCR("split delimited text into text[], possible to set null string");
+ DATA(insert OID = 951 (  to_string   PGNSP PGUID 12 1 0 0 f f f f f i 3 0 25 "2277 25 25" _null_ _null_ _null_ _null_ to_string _null_ _null_ _null_ ));
+ DESCR("concatenate array elements, using delimiter, into text, possible to set null string");
  DATA(insert OID = 515 (  array_larger	   PGNSP PGUID 12 1 0 0 f f f t f i 2 0 2277 "2277 2277" _null_ _null_ _null_ _null_ array_larger _null_ _null_ _null_ ));
  DESCR("larger of two");
  DATA(insert OID = 516 (  array_smaller	   PGNSP PGUID 12 1 0 0 f f f t f i 2 0 2277 "2277 2277" _null_ _null_ _null_ _null_ array_smaller _null_ _null_ _null_ ));
*** ./src/include/utils/array.h.orig	2010-07-20 08:44:18.946806422 +0200
--- ./src/include/utils/array.h	2010-07-20 08:44:59.279804706 +0200
***************
*** 274,279 ****
--- 274,280 ----
  extern ArrayType *create_singleton_array(FunctionCallInfo fcinfo,
  					   Oid element_type,
  					   Datum element,
+ 					   bool isNull,
  					   int ndims);
  
  extern Datum array_agg_transfn(PG_FUNCTION_ARGS);
*** ./src/include/utils/builtins.h.orig	2010-07-13 22:57:19.000000000 +0200
--- ./src/include/utils/builtins.h	2010-07-20 08:44:59.279804706 +0200
***************
*** 715,720 ****
--- 715,722 ----
  extern Datum split_text(PG_FUNCTION_ARGS);
  extern Datum text_to_array(PG_FUNCTION_ARGS);
  extern Datum array_to_text(PG_FUNCTION_ARGS);
+ extern Datum to_array(PG_FUNCTION_ARGS);
+ extern Datum to_string(PG_FUNCTION_ARGS);
  extern Datum to_hex32(PG_FUNCTION_ARGS);
  extern Datum to_hex64(PG_FUNCTION_ARGS);
  extern Datum md5_text(PG_FUNCTION_ARGS);
*** ./src/test/regress/expected/arrays.out.orig	2010-07-20 08:44:18.948805776 +0200
--- ./src/test/regress/expected/arrays.out	2010-07-20 13:31:41.000000000 +0200
***************
*** 1208,1210 ****
--- 1208,1297 ----
   [5:5]={"(42,43)"}
  (1 row)
  
+ -- check to_string and to_array functions
+ select to_array('abc','');
+  to_array 
+ ----------
+  {abc}
+ (1 row)
+ 
+ select to_array('abc','','abc');
+  to_array 
+ ----------
+  {NULL}
+ (1 row)
+ 
+ select to_array('abc',',');
+  to_array 
+ ----------
+  {abc}
+ (1 row)
+ 
+ select to_array('abc',',','abc');
+  to_array 
+ ----------
+  {NULL}
+ (1 row)
+ 
+ select to_array('1,2,3,4,,6',',');
+      to_array     
+ ------------------
+  {1,2,3,4,NULL,6}
+ (1 row)
+ 
+ select to_array('1,2,3,4,,6',',','');
+      to_array     
+ ------------------
+  {1,2,3,4,NULL,6}
+ (1 row)
+ 
+ select to_array('1,2,3,4,*,6',',','*');
+      to_array     
+ ------------------
+  {1,2,3,4,NULL,6}
+ (1 row)
+ 
+ select to_array(NULL, ',') is NULL;
+  ?column? 
+ ----------
+  t
+ (1 row)
+ 
+ select to_array('', ',');
+  to_array 
+ ----------
+  {}
+ (1 row)
+ 
+ select to_string(NULL::int4[], ',') is NULL;
+  ?column? 
+ ----------
+  t
+ (1 row)
+ 
+ select to_string('{}'::int4[], ',');
+  to_string 
+ -----------
+  
+ (1 row)
+ 
+ select to_string(array[1,2,3,4,NULL,6],',');
+  to_string  
+ ------------
+  1,2,3,4,,6
+ (1 row)
+ 
+ select to_string(array[1,2,3,4,NULL,6],',','*');
+   to_string  
+ -------------
+  1,2,3,4,*,6
+ (1 row)
+ 
+ select to_string(array[1,2,3,4,NULL,6],NULL); -- should fail
+ ERROR:  field separator cannot be NULL
+ select to_string(array[1,2,3,4,NULL,6],',', NULL); -- ignore NULL value
+  to_string 
+ -----------
+  1,2,3,4,6
+ (1 row)
+ 
*** ./src/test/regress/sql/arrays.sql.orig	2010-07-20 08:44:18.949804300 +0200
--- ./src/test/regress/sql/arrays.sql	2010-07-20 13:31:25.789928470 +0200
***************
*** 412,414 ****
--- 412,432 ----
  select * from t1;
  update t1 set f1[5].q2 = 43;
  select * from t1;
+ 
+ -- check to_string and to_array functions
+ 
+ select to_array('abc','');
+ select to_array('abc','','abc');
+ select to_array('abc',',');
+ select to_array('abc',',','abc');
+ select to_array('1,2,3,4,,6',',');
+ select to_array('1,2,3,4,,6',',','');
+ select to_array('1,2,3,4,*,6',',','*');
+ select to_array(NULL, ',') is NULL;
+ select to_array('', ',');
+ select to_string(NULL::int4[], ',') is NULL;
+ select to_string('{}'::int4[], ',');
+ select to_string(array[1,2,3,4,NULL,6],',');
+ select to_string(array[1,2,3,4,NULL,6],',','*');
+ select to_string(array[1,2,3,4,NULL,6],NULL); -- should fail
+ select to_string(array[1,2,3,4,NULL,6],',', NULL); -- ignore NULL value