Talk About Network

Google


Register and Login
Nick
Password
Register create new account Sign up is FREE and you can post replies, new topics, bookmark posts and more!
Recover lost password


Data Bases > Pgsql Patches > Re: array_fill ...
Latest [ Topics | Posts ] Archive Post A New Topic Post a Reply
<< Topic < Post Post 1 of 1 Topic 3901 of 4088
Post > Topic >>

Re: array_fill function

by bruce@[EMAIL PROTECTED] (Bruce Momjian) Jul 15, 2008 at 08:49 PM

--ELM1216169375-24139-4_
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset="US-ASCII"


Patch applied, with minor adjustments in error message wording, with
do***ntation added;  committed patch attached.

---------------------------------------------------------------------------

Pavel Stehule wrote:
> Hello
> 
> Proposal:
http://archives.postgresql.org/pgsql-hackers/2008-06/msg00057.php
> 
> I changed name to array_fill and order of arguments.
> 
> postgres=# SELECT array_fill(0, ARRAY[2,3]);
>     array_fill
> -------------------
>  {{0,0,0},{0,0,0}}
> (1 row)
> 
> postgres=# SELECT array_fill(0, ARRAY[2,3], ARRAY[1,2]);
>           array_fill
> ------------------------------
>  [1:2][2:4]={{0,0,0},{0,0,0}}
> (1 row)
> 
> postgres=# SELECT array_fill(0, ARRAY[4], ARRAY[2]);
>    array_fill
> -----------------
>  [2:5]={0,0,0,0}
> (1 row)
> 
> postgres=# SELECT array_fill(NULL::int, ARRAY[4]);
>       array_fill
> -----------------------
>  {NULL,NULL,NULL,NULL}
> (1 row)
> 
> Regards
> Pavel Stehule

[ Attachment, skipping... ]

> 
> -- 
> Sent via pgsql-patches mailing list (pgsql-patches@[EMAIL PROTECTED]
)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-patches

-- 
  Bruce Momjian  <bruce@[EMAIL PROTECTED]
>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +

--ELM1216169375-24139-4_
Content-Transfer-Encoding: 7bit
Content-Type: text/x-diff
Content-Disposition: inline; filename="/rtmp/diff"

Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.440
diff -c -c -r1.440 func.sgml
*** doc/src/sgml/func.sgml	15 Jul 2008 18:24:59 -0000	1.440
--- doc/src/sgml/func.sgml	16 Jul 2008 00:42:25 -0000
***************
*** 9374,9379 ****
--- 9374,9392 ----
         <row>
          <entry>
           <literal>
+           <function>array_fill</function>(<type>anyelement</type>,
<type>anyarray</type>,
+           <optional>, <type>anyarray</type></optional>)
+          </literal>
+         </entry>
+         <entry><type>anyarray</type></entry>
+         <entry>returns an array initialized with supplied value,
+         dimensions, and lower bounds</entry>
+         <entry><literal>array_fill(7, ARRAY[3],
ARRAY[2])</literal></entry>
+         <entry><literal>[2:4]={7,7,7}</literal></entry>
+        </row>
+        <row>
+         <entry>
+          <literal>
            <function>array_lower</function>(<type>anyarray</type>,
<type>int</type>)
           </literal>
          </entry>
Index: src/backend/utils/adt/arrayfuncs.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v
retrieving revision 1.145
diff -c -c -r1.145 arrayfuncs.c
*** src/backend/utils/adt/arrayfuncs.c	12 May 2008 00:00:51 -0000	1.145
--- src/backend/utils/adt/arrayfuncs.c	16 Jul 2008 00:42:26 -0000
***************
*** 95,100 ****
--- 95,105 ----
  				   int *st, int *endp,
  				   int typlen, bool typbyval, char typalign);
  static int	array_cmp(FunctionCallInfo fcinfo);
+ static ArrayType *create_array_envelope(int ndims, int *dimv, int *lbv,
int nbytes,
+ 			    Oid elmtype, int dataoffset);
+ static ArrayType *array_fill_internal(ArrayType *dims, ArrayType *lbs,
Datum value, 
+ 					    Oid elmtype, bool isnull, 
+ 					    FunctionCallInfo fcinfo);
  
  
  /*
***************
*** 4314,4316 ****
--- 4319,4590 ----
  	/* just call the other one -- it can handle both cases */
  	return generate_subscripts(fcinfo);
  }
+ 
+ /*
+  * array_fill_with_lower_bounds
+  *		Create and fill array with defined lower bounds.
+  */
+ Datum
+ array_fill_with_lower_bounds(PG_FUNCTION_ARGS)
+ {
+ 	ArrayType	*dims;
+ 	ArrayType	*lbs;
+ 	ArrayType		*result;
+ 	Oid			elmtype;
+ 	Datum 	value;
+ 	bool	isnull;
+ 
+ 	if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
+ 		ere****t(ERROR, 
+ 			    (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ 			     errmsg("dimension array or low bound array cannot be NULL")));
+ 
+ 	dims = PG_GETARG_ARRAYTYPE_P(1);
+ 	lbs  = PG_GETARG_ARRAYTYPE_P(2);
+ 
+ 	if (!PG_ARGISNULL(0))
+ 	{
+ 		value = PG_GETARG_DATUM(0);
+ 		isnull = false;
+ 	}
+ 	else
+ 	{
+ 		value = 0;
+ 		isnull = true;
+ 	}
+ 
+ 	elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0); 
+ 	if (!OidIsValid(elmtype)) 
+ 		elog(ERROR, "could not determine data type of input"); 
+ 
+ 	result = array_fill_internal(dims, lbs, value, elmtype, isnull,
fcinfo);
+ 	PG_RETURN_ARRAYTYPE_P(result);
+ }
+ 
+ /*
+  * array_fill
+  *		Create and fill array with default lower bounds.
+  */
+ Datum
+ array_fill(PG_FUNCTION_ARGS)
+ {
+ 	ArrayType	*dims;
+ 	ArrayType		*result;
+ 	Oid			elmtype;
+ 	Datum 	value;
+ 	bool	isnull;
+ 
+ 	if (PG_ARGISNULL(1))
+ 		ere****t(ERROR, 
+ 			    (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ 			     errmsg("dimension array or low bound array cannot be NULL")));
+ 
+ 	dims = PG_GETARG_ARRAYTYPE_P(1);
+ 
+ 	if (!PG_ARGISNULL(0))
+ 	{
+ 		value = PG_GETARG_DATUM(0);
+ 		isnull = false;
+ 	}
+ 	else
+ 	{
+ 		value = 0;
+ 		isnull = true;
+ 	}
+ 
+ 	elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0); 
+ 	if (!OidIsValid(elmtype)) 
+ 		elog(ERROR, "could not determine data type of input"); 
+ 
+ 	result = array_fill_internal(dims, NULL, value, elmtype, isnull,
fcinfo);
+ 	PG_RETURN_ARRAYTYPE_P(result);
+ }
+ 
+ static ArrayType *
+ create_array_envelope(int ndims, int *dimv, int *lbsv, int nbytes,
+ 			    Oid elmtype, int dataoffset)
+ {
+ 	ArrayType *result;
+ 
+ 	result = (ArrayType *) palloc0(nbytes);
+ 	SET_VARSIZE(result, nbytes);
+ 	result->ndim = ndims;
+ 	result->dataoffset = dataoffset;
+ 	result->elemtype = elmtype;
+ 	memcpy(ARR_DIMS(result), dimv, ndims * sizeof(int));
+ 	memcpy(ARR_LBOUND(result), lbsv, ndims * sizeof(int));
+ 
+ 	return result;
+ }
+ 
+ static ArrayType *
+ array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, 
+ 					    Oid elmtype, bool isnull,
+ 					    FunctionCallInfo fcinfo)
+ {
+ 	ArrayType	*result;
+ 	int	*dimv;
+ 	int	*lbsv;
+ 	int	ndims;
+ 	int	nitems;
+ 	int 		deflbs[MAXDIM];
+ 	int16 elmlen; 
+ 	bool elmbyval; 
+ 	char elmalign;
+ 	ArrayMetaState 		*my_extra;
+ 
+ 	/* 
+ 	 * Params checks
+ 	 */
+ 	if (ARR_NDIM(dims) != 1)
+ 		ere****t(ERROR,
+ 			    (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
+ 			     errmsg("wrong number of array subscripts"),
+ 			     errhint("Dimension array must be one dimensional.")));
+ 
+ 	if (ARR_LBOUND(dims)[0] != 1)
+ 		ere****t(ERROR,
+ 			    (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
+ 			     errmsg("wrong range of array_subscripts"),
+ 			     errhint("Lower bound of dimension array must be one.")));
+ 	
+ 	if (ARR_HASNULL(dims))
+ 		ere****t(ERROR, 
+ 			    (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ 			     errmsg("dimension values cannot be null")));
+ 
+ 	dimv = (int *) ARR_DATA_PTR(dims);
+ 	ndims = ARR_DIMS(dims)[0];
+ 	
+ 	if (ndims < 0)				/* we do allow zero-dimension arrays */
+ 		ere****t(ERROR,
+ 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ 				 errmsg("invalid number of dimensions: %d", ndims)));
+ 	if (ndims > MAXDIM)
+ 		ere****t(ERROR,
+ 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ 				 errmsg("number of array dimensions (%d) exceeds the maximum allowed
(%d)",
+ 						ndims, MAXDIM)));
+ 	
+ 	if (lbs != NULL)
+ 	{
+ 		if (ARR_NDIM(lbs) != 1)
+ 			ere****t(ERROR,
+ 				    (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
+ 			    	     errmsg("wrong number of array subscripts"),
+ 			    	     errhint("Dimension array must be one dimensional.")));
+ 
+ 		if (ARR_LBOUND(lbs)[0] != 1)
+ 			ere****t(ERROR,
+ 				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
+ 			         errmsg("wrong range of array_subscripts"),
+ 			    	 errhint("Lower bound of dimension array must be one.")));
+ 	
+ 		if (ARR_HASNULL(lbs))
+ 			ere****t(ERROR, 
+ 				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ 				 errmsg("dimension values cannot be null")));
+ 
+ 		if (ARR_DIMS(lbs)[0] != ndims)
+ 			ere****t(ERROR,
+ 				    (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
+ 				     errmsg("wrong number of array_subscripts"),
+ 				     errhint("Low bound array has different size than dimensions
array.")));
+ 				     
+ 		lbsv = (int *) ARR_DATA_PTR(lbs);
+ 	}
+ 	else	
+ 	{
+ 		int	i;
+ 	
+ 		for (i = 0; i < MAXDIM; i++)
+ 			deflbs[i] = 1;
+ 
+ 		lbsv = deflbs;
+ 	}
+ 
+ 	/* fast track for empty array */
+ 	if (ndims == 0)
+ 		return construct_empty_array(elmtype);
+ 	
+ 	nitems = ArrayGetNItems(ndims, dimv);
+ 
+ 
+ 	/*
+ 	 * We arrange to look up info about element type only once per series
of
+ 	 * calls, assuming the element type doesn't change underneath us.
+ 	 */
+ 	my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
+ 	if (my_extra == NULL)
+ 	{
+ 		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
+ 													  sizeof(ArrayMetaState));
+ 		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
+ 		my_extra->element_type = InvalidOid;
+ 	}
+ 
+ 	if (my_extra->element_type != elmtype)
+ 	{
+ 		/* Get info about element type */
+ 		get_typlenbyvalalign(elmtype,
+ 							 &my_extra->typlen,
+ 							 &my_extra->typbyval,
+ 							 &my_extra->typalign);
+ 		my_extra->element_type = elmtype;
+ 	}
+ 
+ 	elmlen = my_extra->typlen;
+ 	elmbyval = my_extra->typbyval;
+ 	elmalign = my_extra->typalign;
+ 
+ 	/* compute required space */
+ 	if (!isnull)
+ 	{
+ 		int 	i;
+ 		char		*p;
+ 		int			nbytes;
+ 		Datum	aux_value = value;
+ 
+ 		/* make sure data is not toasted */
+ 		if (elmlen == -1)
+ 			value = PointerGetDatum(PG_DETOAST_DATUM(value));
+ 
+ 		nbytes = att_addlength_datum(0, elmlen, value);
+ 		nbytes = att_align_nominal(nbytes, elmalign);
+ 
+ 		nbytes *= nitems;
+ 		/* check for overflow of total request */
+ 		if (!AllocSizeIsValid(nbytes))
+ 			ere****t(ERROR,
+ 					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ 					 errmsg("array size exceeds the maximum allowed (%d)",
+ 							(int) MaxAllocSize)));
+ 
+ 		nbytes += ARR_OVERHEAD_NONULLS(ndims);
+ 		result = create_array_envelope(ndims, dimv, lbsv, nbytes,
+ 							elmtype, 0);
+ 		p = ARR_DATA_PTR(result);
+ 		for (i = 0; i < nitems; i++)
+ 			p += ArrayCastAndSet(value, elmlen, elmbyval, elmalign, p);
+ 
+ 		/* cleaning up detoasted copies of datum */
+ 		if (aux_value != value)
+ 			pfree((Pointer) value);
+ 	}
+ 	else
+ 	{
+ 		int	nbytes;
+ 		int	dataoffset;
+ 		bits8	*bitmap;
+ 
+ 		dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
+ 		nbytes = dataoffset;
+ 
+ 		result = create_array_envelope(ndims, dimv, lbsv, nbytes,
+ 							elmtype, dataoffset);
+ 		bitmap = ARR_NULLBITMAP(result);
+ 		MemSet(bitmap, 0, (nitems + 7) / 8);
+ 	}
+ 		
+ 	return result;
+ }
Index: src/include/catalog/catversion.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/catversion.h,v
retrieving revision 1.467
diff -c -c -r1.467 catversion.h
*** src/include/catalog/catversion.h	14 Jul 2008 00:51:45 -0000	1.467
--- src/include/catalog/catversion.h	16 Jul 2008 00:42:27 -0000
***************
*** 53,58 ****
   */
  
  /*							yyyymmddN */
! #define CATALOG_VERSION_NO	200807131
  
  #endif
--- 53,58 ----
   */
  
  /*							yyyymmddN */
! #define CATALOG_VERSION_NO	200807151
  
  #endif
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.505
diff -c -c -r1.505 pg_proc.h
*** src/include/catalog/pg_proc.h	14 Jul 2008 00:51:45 -0000	1.505
--- src/include/catalog/pg_proc.h	16 Jul 2008 00:42:27 -0000
***************
*** 1010,1017 ****
  DESCR("array subscripts generator");
  DATA(insert OID = 1192 (  generate_subscripts PGNSP PGUID 12 1 1000 f f
t t i 2 23 "2277 23" _null_ _null_ _null_ generate_subscripts_nodir -
_null_ _null_ ));
  DESCR("array subscripts generator");
! 
! 
  DATA(insert OID = 760 (  smgrin			   PGNSP PGUID 12 1 0 f f t f s 1 210
"2275" _null_ _null_ _null_  smgrin - _null_ _null_ ));
  DESCR("I/O");
  DATA(insert OID = 761 (  smgrout		   PGNSP PGUID 12 1 0 f f t f s 1 2275
"210" _null_ _null_ _null_  smgrout - _null_ _null_ ));
--- 1010,1019 ----
  DESCR("array subscripts generator");
  DATA(insert OID = 1192 (  generate_subscripts PGNSP PGUID 12 1 1000 f f
t t i 2 23 "2277 23" _null_ _null_ _null_ generate_subscripts_nodir -
_null_ _null_ ));
  DESCR("array subscripts generator");
! DATA(insert OID = 1193 (  array_fill PGNSP PGUID 12 1 0 f f f f i 2 2277
"2283 1007" _null_ _null_ _null_ array_fill - _null_ _null_ ));
! DESCR("array constructor with value");
! DATA(insert OID = 1286 (  array_fill PGNSP PGUID 12 1 0 f f f f i 3 2277
"2283 1007 1007" _null_ _null_ _null_ array_fill_with_lower_bounds - _null_
_null_ ));
! DESCR("array constructor with value");
  DATA(insert OID = 760 (  smgrin			   PGNSP PGUID 12 1 0 f f t f s 1 210
"2275" _null_ _null_ _null_  smgrin - _null_ _null_ ));
  DESCR("I/O");
  DATA(insert OID = 761 (  smgrout		   PGNSP PGUID 12 1 0 f f t f s 1 2275
"210" _null_ _null_ _null_  smgrout - _null_ _null_ ));
Index: src/include/utils/array.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/utils/array.h,v
retrieving revision 1.67
diff -c -c -r1.67 array.h
*** src/include/utils/array.h	28 Apr 2008 14:48:57 -0000	1.67
--- src/include/utils/array.h	16 Jul 2008 00:42:28 -0000
***************
*** 202,207 ****
--- 202,209 ----
  extern Datum array_smaller(PG_FUNCTION_ARGS);
  extern Datum generate_subscripts(PG_FUNCTION_ARGS);
  extern Datum generate_subscripts_nodir(PG_FUNCTION_ARGS);
+ extern Datum array_fill(PG_FUNCTION_ARGS);
+ extern Datum array_fill_with_lower_bounds(PG_FUNCTION_ARGS);
  
  extern Datum array_ref(ArrayType *array, int nSubscripts, int *indx,
  		  int arraytyplen, int elmlen, bool elmbyval, char elmalign,
Index: src/test/regress/expected/arrays.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/arrays.out,v
retrieving revision 1.36
diff -c -c -r1.36 arrays.out
*** src/test/regress/expected/arrays.out	28 Apr 2008 14:48:57 -0000	1.36
--- src/test/regress/expected/arrays.out	16 Jul 2008 00:42:28 -0000
***************
*** 933,935 ****
--- 933,993 ----
  
  drop function unnest1(anyarray);
  drop function unnest2(anyarray);
+ select array_fill(null::integer, array[3,3],array[2,2]);
+                            array_fill                            
+ -----------------------------------------------------------------
+  [2:4][2:4]={{NULL,NULL,NULL},{NULL,NULL,NULL},{NULL,NULL,NULL}}
+ (1 row)
+ 
+ select array_fill(null::integer, array[3,3]);
+                       array_fill                      
+ ------------------------------------------------------
+  {{NULL,NULL,NULL},{NULL,NULL,NULL},{NULL,NULL,NULL}}
+ (1 row)
+ 
+ select array_fill(null::text, array[3,3],array[2,2]);
+                            array_fill                            
+ -----------------------------------------------------------------
+  [2:4][2:4]={{NULL,NULL,NULL},{NULL,NULL,NULL},{NULL,NULL,NULL}}
+ (1 row)
+ 
+ select array_fill(null::text, array[3,3]);
+                       array_fill                      
+ ------------------------------------------------------
+  {{NULL,NULL,NULL},{NULL,NULL,NULL},{NULL,NULL,NULL}}
+ (1 row)
+ 
+ select array_fill(7, array[3,3],array[2,2]);
+               array_fill              
+ --------------------------------------
+  [2:4][2:4]={{7,7,7},{7,7,7},{7,7,7}}
+ (1 row)
+ 
+ select array_fill(7, array[3,3]);
+         array_fill         
+ ---------------------------
+  {{7,7,7},{7,7,7},{7,7,7}}
+ (1 row)
+ 
+ select array_fill('juhu'::text, array[3,3],array[2,2]);
+                            array_fill                            
+ -----------------------------------------------------------------
+  [2:4][2:4]={{juhu,juhu,juhu},{juhu,juhu,juhu},{juhu,juhu,juhu}}
+ (1 row)
+ 
+ select array_fill('juhu'::text, array[3,3]);
+                       array_fill                      
+ ------------------------------------------------------
+  {{juhu,juhu,juhu},{juhu,juhu,juhu},{juhu,juhu,juhu}}
+ (1 row)
+ 
+ -- raise exception
+ select array_fill(1, null, array[2,2]);
+ ERROR:  dimension array or low bound array cannot be NULL
+ select array_fill(1, array[2,2], null);
+ ERROR:  dimension array or low bound array cannot be NULL
+ select array_fill(1, array[3,3], array[1,1,1]);
+ ERROR:  wrong number of array_subscripts
+ HINT:  Low bound array has different size than dimensions array.
+ select array_fill(1, array[1,2,null]);
+ ERROR:  dimension values cannot be null
Index: src/test/regress/sql/arrays.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/arrays.sql,v
retrieving revision 1.28
diff -c -c -r1.28 arrays.sql
*** src/test/regress/sql/arrays.sql	28 Apr 2008 14:48:58 -0000	1.28
--- src/test/regress/sql/arrays.sql	16 Jul 2008 00:42:28 -0000
***************
*** 357,359 ****
--- 357,373 ----
  
  drop function unnest1(anyarray);
  drop function unnest2(anyarray);
+ 
+ select array_fill(null::integer, array[3,3],array[2,2]);
+ select array_fill(null::integer, array[3,3]);
+ select array_fill(null::text, array[3,3],array[2,2]);
+ select array_fill(null::text, array[3,3]);
+ select array_fill(7, array[3,3],array[2,2]);
+ select array_fill(7, array[3,3]);
+ select array_fill('juhu'::text, array[3,3],array[2,2]);
+ select array_fill('juhu'::text, array[3,3]);
+ -- raise exception
+ select array_fill(1, null, array[2,2]);
+ select array_fill(1, array[2,2], null);
+ select array_fill(1, array[3,3], array[1,1,1]);
+ select array_fill(1, array[1,2,null]);

--ELM1216169375-24139-4_
Content-Type: text/plain
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
MIME-Version: 1.0


-- 
Sent via pgsql-patches mailing list (pgsql-patches@[EMAIL PROTECTED]
)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches

--ELM1216169375-24139-4_--
 




 1 Posts in Topic:
Re: array_fill function
bruce@[EMAIL PROTECTED]   2008-07-15 20:49:35 

Post A Reply:
  Go here to Signup

AddThis Feed Button


About - Advertising - Contact - Frequently Asked Questions - Privacy Policy - Terms of Use - Signup

Contact
tan12V112 Sun Oct 12 14:25:21 CDT 2008.