Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2c77329

Browse files
committed
Add array_fill() to create arrays initialized with a value.
Pavel Stehule
1 parent2fa42cc commit2c77329

File tree

7 files changed

+371
-8
lines changed

7 files changed

+371
-8
lines changed

‎doc/src/sgml/func.sgml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.440 2008/07/15 18:24:59 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.441 2008/07/16 00:48:53 momjian Exp $ -->
22

33
<chapter id="functions">
44
<title>Functions and Operators</title>
@@ -9371,6 +9371,19 @@ SELECT NULLIF(value, '(none)') ...
93719371
<entry><literal>array_dims(ARRAY[[1,2,3], [4,5,6]])</literal></entry>
93729372
<entry><literal>[1:2][1:3]</literal></entry>
93739373
</row>
9374+
<row>
9375+
<entry>
9376+
<literal>
9377+
<function>array_fill</function>(<type>anyelement</type>, <type>anyarray</type>,
9378+
<optional>, <type>anyarray</type></optional>)
9379+
</literal>
9380+
</entry>
9381+
<entry><type>anyarray</type></entry>
9382+
<entry>returns an array initialized with supplied value,
9383+
dimensions, and lower bounds</entry>
9384+
<entry><literal>array_fill(7, ARRAY[3], ARRAY[2])</literal></entry>
9385+
<entry><literal>[2:4]={7,7,7}</literal></entry>
9386+
</row>
93749387
<row>
93759388
<entry>
93769389
<literal>

‎src/backend/utils/adt/arrayfuncs.c

Lines changed: 275 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.145 2008/05/12 00:00:51 alvherre Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.146 2008/07/16 00:48:53 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -95,6 +95,11 @@ static void array_insert_slice(ArrayType *destArray, ArrayType *origArray,
9595
int*st,int*endp,
9696
inttyplen,booltypbyval,chartypalign);
9797
staticintarray_cmp(FunctionCallInfofcinfo);
98+
staticArrayType*create_array_envelope(intndims,int*dimv,int*lbv,intnbytes,
99+
Oidelmtype,intdataoffset);
100+
staticArrayType*array_fill_internal(ArrayType*dims,ArrayType*lbs,Datumvalue,
101+
Oidelmtype,boolisnull,
102+
FunctionCallInfofcinfo);
98103

99104

100105
/*
@@ -4314,3 +4319,272 @@ generate_subscripts_nodir(PG_FUNCTION_ARGS)
43144319
/* just call the other one -- it can handle both cases */
43154320
returngenerate_subscripts(fcinfo);
43164321
}
4322+
4323+
/*
4324+
* array_fill_with_lower_bounds
4325+
*Create and fill array with defined lower bounds.
4326+
*/
4327+
Datum
4328+
array_fill_with_lower_bounds(PG_FUNCTION_ARGS)
4329+
{
4330+
ArrayType*dims;
4331+
ArrayType*lbs;
4332+
ArrayType*result;
4333+
Oidelmtype;
4334+
Datumvalue;
4335+
boolisnull;
4336+
4337+
if (PG_ARGISNULL(1)||PG_ARGISNULL(2))
4338+
ereport(ERROR,
4339+
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4340+
errmsg("dimension array or low bound array cannot be NULL")));
4341+
4342+
dims=PG_GETARG_ARRAYTYPE_P(1);
4343+
lbs=PG_GETARG_ARRAYTYPE_P(2);
4344+
4345+
if (!PG_ARGISNULL(0))
4346+
{
4347+
value=PG_GETARG_DATUM(0);
4348+
isnull= false;
4349+
}
4350+
else
4351+
{
4352+
value=0;
4353+
isnull= true;
4354+
}
4355+
4356+
elmtype=get_fn_expr_argtype(fcinfo->flinfo,0);
4357+
if (!OidIsValid(elmtype))
4358+
elog(ERROR,"could not determine data type of input");
4359+
4360+
result=array_fill_internal(dims,lbs,value,elmtype,isnull,fcinfo);
4361+
PG_RETURN_ARRAYTYPE_P(result);
4362+
}
4363+
4364+
/*
4365+
* array_fill
4366+
*Create and fill array with default lower bounds.
4367+
*/
4368+
Datum
4369+
array_fill(PG_FUNCTION_ARGS)
4370+
{
4371+
ArrayType*dims;
4372+
ArrayType*result;
4373+
Oidelmtype;
4374+
Datumvalue;
4375+
boolisnull;
4376+
4377+
if (PG_ARGISNULL(1))
4378+
ereport(ERROR,
4379+
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4380+
errmsg("dimension array or low bound array cannot be NULL")));
4381+
4382+
dims=PG_GETARG_ARRAYTYPE_P(1);
4383+
4384+
if (!PG_ARGISNULL(0))
4385+
{
4386+
value=PG_GETARG_DATUM(0);
4387+
isnull= false;
4388+
}
4389+
else
4390+
{
4391+
value=0;
4392+
isnull= true;
4393+
}
4394+
4395+
elmtype=get_fn_expr_argtype(fcinfo->flinfo,0);
4396+
if (!OidIsValid(elmtype))
4397+
elog(ERROR,"could not determine data type of input");
4398+
4399+
result=array_fill_internal(dims,NULL,value,elmtype,isnull,fcinfo);
4400+
PG_RETURN_ARRAYTYPE_P(result);
4401+
}
4402+
4403+
staticArrayType*
4404+
create_array_envelope(intndims,int*dimv,int*lbsv,intnbytes,
4405+
Oidelmtype,intdataoffset)
4406+
{
4407+
ArrayType*result;
4408+
4409+
result= (ArrayType*)palloc0(nbytes);
4410+
SET_VARSIZE(result,nbytes);
4411+
result->ndim=ndims;
4412+
result->dataoffset=dataoffset;
4413+
result->elemtype=elmtype;
4414+
memcpy(ARR_DIMS(result),dimv,ndims*sizeof(int));
4415+
memcpy(ARR_LBOUND(result),lbsv,ndims*sizeof(int));
4416+
4417+
returnresult;
4418+
}
4419+
4420+
staticArrayType*
4421+
array_fill_internal(ArrayType*dims,ArrayType*lbs,Datumvalue,
4422+
Oidelmtype,boolisnull,
4423+
FunctionCallInfofcinfo)
4424+
{
4425+
ArrayType*result;
4426+
int*dimv;
4427+
int*lbsv;
4428+
intndims;
4429+
intnitems;
4430+
intdeflbs[MAXDIM];
4431+
int16elmlen;
4432+
boolelmbyval;
4433+
charelmalign;
4434+
ArrayMetaState*my_extra;
4435+
4436+
/*
4437+
* Params checks
4438+
*/
4439+
if (ARR_NDIM(dims)!=1)
4440+
ereport(ERROR,
4441+
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4442+
errmsg("wrong number of array subscripts"),
4443+
errhint("Dimension array must be one dimensional.")));
4444+
4445+
if (ARR_LBOUND(dims)[0]!=1)
4446+
ereport(ERROR,
4447+
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4448+
errmsg("wrong range of array_subscripts"),
4449+
errhint("Lower bound of dimension array must be one.")));
4450+
4451+
if (ARR_HASNULL(dims))
4452+
ereport(ERROR,
4453+
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4454+
errmsg("dimension values cannot be null")));
4455+
4456+
dimv= (int*)ARR_DATA_PTR(dims);
4457+
ndims=ARR_DIMS(dims)[0];
4458+
4459+
if (ndims<0)/* we do allow zero-dimension arrays */
4460+
ereport(ERROR,
4461+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4462+
errmsg("invalid number of dimensions: %d",ndims)));
4463+
if (ndims>MAXDIM)
4464+
ereport(ERROR,
4465+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
4466+
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
4467+
ndims,MAXDIM)));
4468+
4469+
if (lbs!=NULL)
4470+
{
4471+
if (ARR_NDIM(lbs)!=1)
4472+
ereport(ERROR,
4473+
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4474+
errmsg("wrong number of array subscripts"),
4475+
errhint("Dimension array must be one dimensional.")));
4476+
4477+
if (ARR_LBOUND(lbs)[0]!=1)
4478+
ereport(ERROR,
4479+
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4480+
errmsg("wrong range of array_subscripts"),
4481+
errhint("Lower bound of dimension array must be one.")));
4482+
4483+
if (ARR_HASNULL(lbs))
4484+
ereport(ERROR,
4485+
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4486+
errmsg("dimension values cannot be null")));
4487+
4488+
if (ARR_DIMS(lbs)[0]!=ndims)
4489+
ereport(ERROR,
4490+
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4491+
errmsg("wrong number of array_subscripts"),
4492+
errhint("Low bound array has different size than dimensions array.")));
4493+
4494+
lbsv= (int*)ARR_DATA_PTR(lbs);
4495+
}
4496+
else
4497+
{
4498+
inti;
4499+
4500+
for (i=0;i<MAXDIM;i++)
4501+
deflbs[i]=1;
4502+
4503+
lbsv=deflbs;
4504+
}
4505+
4506+
/* fast track for empty array */
4507+
if (ndims==0)
4508+
returnconstruct_empty_array(elmtype);
4509+
4510+
nitems=ArrayGetNItems(ndims,dimv);
4511+
4512+
4513+
/*
4514+
* We arrange to look up info about element type only once per series of
4515+
* calls, assuming the element type doesn't change underneath us.
4516+
*/
4517+
my_extra= (ArrayMetaState*)fcinfo->flinfo->fn_extra;
4518+
if (my_extra==NULL)
4519+
{
4520+
fcinfo->flinfo->fn_extra=MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
4521+
sizeof(ArrayMetaState));
4522+
my_extra= (ArrayMetaState*)fcinfo->flinfo->fn_extra;
4523+
my_extra->element_type=InvalidOid;
4524+
}
4525+
4526+
if (my_extra->element_type!=elmtype)
4527+
{
4528+
/* Get info about element type */
4529+
get_typlenbyvalalign(elmtype,
4530+
&my_extra->typlen,
4531+
&my_extra->typbyval,
4532+
&my_extra->typalign);
4533+
my_extra->element_type=elmtype;
4534+
}
4535+
4536+
elmlen=my_extra->typlen;
4537+
elmbyval=my_extra->typbyval;
4538+
elmalign=my_extra->typalign;
4539+
4540+
/* compute required space */
4541+
if (!isnull)
4542+
{
4543+
inti;
4544+
char*p;
4545+
intnbytes;
4546+
Datumaux_value=value;
4547+
4548+
/* make sure data is not toasted */
4549+
if (elmlen==-1)
4550+
value=PointerGetDatum(PG_DETOAST_DATUM(value));
4551+
4552+
nbytes=att_addlength_datum(0,elmlen,value);
4553+
nbytes=att_align_nominal(nbytes,elmalign);
4554+
4555+
nbytes *=nitems;
4556+
/* check for overflow of total request */
4557+
if (!AllocSizeIsValid(nbytes))
4558+
ereport(ERROR,
4559+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
4560+
errmsg("array size exceeds the maximum allowed (%d)",
4561+
(int)MaxAllocSize)));
4562+
4563+
nbytes+=ARR_OVERHEAD_NONULLS(ndims);
4564+
result=create_array_envelope(ndims,dimv,lbsv,nbytes,
4565+
elmtype,0);
4566+
p=ARR_DATA_PTR(result);
4567+
for (i=0;i<nitems;i++)
4568+
p+=ArrayCastAndSet(value,elmlen,elmbyval,elmalign,p);
4569+
4570+
/* cleaning up detoasted copies of datum */
4571+
if (aux_value!=value)
4572+
pfree((Pointer)value);
4573+
}
4574+
else
4575+
{
4576+
intnbytes;
4577+
intdataoffset;
4578+
bits8*bitmap;
4579+
4580+
dataoffset=ARR_OVERHEAD_WITHNULLS(ndims,nitems);
4581+
nbytes=dataoffset;
4582+
4583+
result=create_array_envelope(ndims,dimv,lbsv,nbytes,
4584+
elmtype,dataoffset);
4585+
bitmap=ARR_NULLBITMAP(result);
4586+
MemSet(bitmap,0, (nitems+7) /8);
4587+
}
4588+
4589+
returnresult;
4590+
}

‎src/include/catalog/catversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.467 2008/07/14 00:51:45 tgl Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.468 2008/07/16 00:48:53 momjian Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/*yyyymmddN */
56-
#defineCATALOG_VERSION_NO200807131
56+
#defineCATALOG_VERSION_NO200807151
5757

5858
#endif

‎src/include/catalog/pg_proc.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.505 2008/07/14 00:51:45 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.506 2008/07/16 00:48:53 momjian Exp $
1111
*
1212
* NOTES
1313
* The script catalog/genbki.sh reads this file and generates .bki
@@ -1010,8 +1010,10 @@ DATA(insert OID = 1191 ( generate_subscripts PGNSP PGUID 12 1 1000 f f t t i 3
10101010
DESCR("array subscripts generator");
10111011
DATA(insertOID=1192 (generate_subscriptsPGNSPPGUID1211000fftti223"2277 23"_null__null__null_generate_subscripts_nodir-_null__null_ ));
10121012
DESCR("array subscripts generator");
1013-
1014-
1013+
DATA(insertOID=1193 (array_fillPGNSPPGUID1210ffffi22277"2283 1007"_null__null__null_array_fill-_null__null_ ));
1014+
DESCR("array constructor with value");
1015+
DATA(insertOID=1286 (array_fillPGNSPPGUID1210ffffi32277"2283 1007 1007"_null__null__null_array_fill_with_lower_bounds-_null__null_ ));
1016+
DESCR("array constructor with value");
10151017
DATA(insertOID=760 (smgrinPGNSPPGUID1210fftfs1210"2275"_null__null__null_smgrin-_null__null_ ));
10161018
DESCR("I/O");
10171019
DATA(insertOID=761 (smgroutPGNSPPGUID1210fftfs12275"210"_null__null__null_smgrout-_null__null_ ));

‎src/include/utils/array.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
5050
* Portions Copyright (c) 1994, Regents of the University of California
5151
*
52-
* $PostgreSQL: pgsql/src/include/utils/array.h,v 1.67 2008/04/28 14:48:57 alvherre Exp $
52+
* $PostgreSQL: pgsql/src/include/utils/array.h,v 1.68 2008/07/16 00:48:54 momjian Exp $
5353
*
5454
*-------------------------------------------------------------------------
5555
*/
@@ -202,6 +202,8 @@ extern Datum array_larger(PG_FUNCTION_ARGS);
202202
externDatumarray_smaller(PG_FUNCTION_ARGS);
203203
externDatumgenerate_subscripts(PG_FUNCTION_ARGS);
204204
externDatumgenerate_subscripts_nodir(PG_FUNCTION_ARGS);
205+
externDatumarray_fill(PG_FUNCTION_ARGS);
206+
externDatumarray_fill_with_lower_bounds(PG_FUNCTION_ARGS);
205207

206208
externDatumarray_ref(ArrayType*array,intnSubscripts,int*indx,
207209
intarraytyplen,intelmlen,boolelmbyval,charelmalign,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp