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

Commit352a56b

Browse files
committed
Allow assignment to array elements not contiguous with those already
present; intervening positions are filled with nulls. This behavioris required by SQL99 but was not implementable before 8.2 due to lackof support for nulls in arrays. I have only made it work for theone-dimensional case, which is all that SQL99 requires. It seems quitecomplex to get it right in higher dimensions, and since we never allowedextension at all in higher dimensions, I think that must count as afuture feature addition not a bug fix.
1 parent673a573 commit352a56b

File tree

4 files changed

+267
-91
lines changed

4 files changed

+267
-91
lines changed

‎doc/src/sgml/array.sgml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/array.sgml,v 1.51 2006/05/09 23:12:54 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/array.sgml,v 1.52 2006/09/29 21:22:21 tgl Exp $ -->
22

33
<sect1 id="arrays">
44
<title>Arrays</title>
@@ -350,11 +350,12 @@ UPDATE sal_emp SET pay_by_quarter[1:2] = '{27000,27000}'
350350
</para>
351351

352352
<para>
353-
A stored array value can be enlarged by assigning to an element adjacent to
354-
those already present, or by assigning to a slice that is adjacent
355-
to or overlaps the data already present. For example, if array
356-
<literal>myarray</> currently has 4 elements, it will have five
357-
elements after an update that assigns to <literal>myarray[5]</>.
353+
A stored array value can be enlarged by assigning to element(s) not already
354+
present. Any positions between those previously present and the newly
355+
assigned element(s) will be filled with nulls. For example, if array
356+
<literal>myarray</> currently has 4 elements, it will have six
357+
elements after an update that assigns to <literal>myarray[6]</>,
358+
and <literal>myarray[5]</> will contain a null.
358359
Currently, enlargement in this fashion is only allowed for one-dimensional
359360
arrays, not multidimensional arrays.
360361
</para>

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

Lines changed: 114 additions & 85 deletions
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.131 2006/09/10 20:14:20 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.132 2006/09/29 21:22:21 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1925,8 +1925,9 @@ array_get_slice(ArrayType *array,
19251925
* modified entry. The original array object is not changed.
19261926
*
19271927
* For one-dimensional arrays only, we allow the array to be extended
1928-
* by assigning to the position one above or one below the existing range.
1929-
* (XXX we could be more flexible: perhaps allow NULL fill?)
1928+
* by assigning to a position outside the existing subscript range; any
1929+
* positions between the existing elements and the new one are set to NULLs.
1930+
* (XXX TODO: allow a corresponding behavior for multidimensional arrays)
19301931
*
19311932
* NOTE: For assignments, we throw an error for invalid subscripts etc,
19321933
* rather than returning a NULL as the fetch operations do.
@@ -1949,17 +1950,18 @@ array_set(ArrayType *array,
19491950
lb[MAXDIM],
19501951
offset;
19511952
char*elt_ptr;
1952-
boolextendbefore= false;
1953-
boolextendafter= false;
19541953
boolnewhasnulls;
19551954
bits8*oldnullbitmap;
19561955
intoldnitems,
1956+
newnitems,
19571957
olddatasize,
19581958
newsize,
19591959
olditemlen,
19601960
newitemlen,
19611961
overheadlen,
19621962
oldoverheadlen,
1963+
addedbefore,
1964+
addedafter,
19631965
lenbefore,
19641966
lenafter;
19651967

@@ -1972,12 +1974,12 @@ array_set(ArrayType *array,
19721974
if (nSubscripts!=1)
19731975
ereport(ERROR,
19741976
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1975-
errmsg("invalid array subscripts")));
1977+
errmsg("wrong number of array subscripts")));
19761978

19771979
if (indx[0]<0||indx[0]*elmlen >=arraytyplen)
19781980
ereport(ERROR,
19791981
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1980-
errmsg("invalidarraysubscripts")));
1982+
errmsg("arraysubscript out of range")));
19811983

19821984
if (isNull)
19831985
ereport(ERROR,
@@ -1994,7 +1996,7 @@ array_set(ArrayType *array,
19941996
if (nSubscripts <=0||nSubscripts>MAXDIM)
19951997
ereport(ERROR,
19961998
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1997-
errmsg("invalid array subscripts")));
1999+
errmsg("wrong number of array subscripts")));
19982000

19992001
/* make sure item to be inserted is not toasted */
20002002
if (elmlen==-1&& !isNull)
@@ -2028,70 +2030,72 @@ array_set(ArrayType *array,
20282030
if (ndim!=nSubscripts)
20292031
ereport(ERROR,
20302032
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2031-
errmsg("invalid array subscripts")));
2033+
errmsg("wrong number of array subscripts")));
20322034

20332035
/* copy dim/lb since we may modify them */
20342036
memcpy(dim,ARR_DIMS(array),ndim*sizeof(int));
20352037
memcpy(lb,ARR_LBOUND(array),ndim*sizeof(int));
20362038

2039+
newhasnulls= (ARR_HASNULL(array)||isNull);
2040+
addedbefore=addedafter=0;
2041+
20372042
/*
20382043
* Check subscripts
20392044
*/
2040-
for (i=0;i<ndim;i++)
2045+
if (ndim==1)
20412046
{
2042-
if (indx[i]<lb[i])
2047+
if (indx[0]<lb[0])
20432048
{
2044-
if (ndim==1&&indx[i]==lb[i]-1)
2045-
{
2046-
dim[i]++;
2047-
lb[i]--;
2048-
extendbefore= true;
2049-
}
2050-
else
2051-
ereport(ERROR,
2052-
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2053-
errmsg("invalid array subscripts")));
2049+
addedbefore=lb[0]-indx[0];
2050+
dim[0]+=addedbefore;
2051+
lb[0]=indx[0];
2052+
if (addedbefore>1)
2053+
newhasnulls= true;/* will insert nulls */
20542054
}
2055-
if (indx[i] >= (dim[i]+lb[i]))
2055+
if (indx[0] >= (dim[0]+lb[0]))
20562056
{
2057-
if (ndim==1&&indx[i]== (dim[i]+lb[i]))
2058-
{
2059-
dim[i]++;
2060-
extendafter= true;
2061-
}
2062-
else
2057+
addedafter=indx[0]- (dim[0]+lb[0])+1;
2058+
dim[0]+=addedafter;
2059+
if (addedafter>1)
2060+
newhasnulls= true;/* will insert nulls */
2061+
}
2062+
}
2063+
else
2064+
{
2065+
/*
2066+
* XXX currently we do not support extending multi-dimensional
2067+
* arrays during assignment
2068+
*/
2069+
for (i=0;i<ndim;i++)
2070+
{
2071+
if (indx[i]<lb[i]||
2072+
indx[i] >= (dim[i]+lb[i]))
20632073
ereport(ERROR,
20642074
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2065-
errmsg("invalidarraysubscripts")));
2075+
errmsg("arraysubscript out of range")));
20662076
}
20672077
}
20682078

20692079
/*
20702080
* Compute sizes of items and areas to copy
20712081
*/
2072-
if (ARR_HASNULL(array)||isNull)
2073-
{
2074-
newhasnulls= true;
2075-
overheadlen=ARR_OVERHEAD_WITHNULLS(ndim,
2076-
ArrayGetNItems(ndim,dim));
2077-
}
2082+
newnitems=ArrayGetNItems(ndim,dim);
2083+
if (newhasnulls)
2084+
overheadlen=ARR_OVERHEAD_WITHNULLS(ndim,newnitems);
20782085
else
2079-
{
2080-
newhasnulls= false;
20812086
overheadlen=ARR_OVERHEAD_NONULLS(ndim);
2082-
}
20832087
oldnitems=ArrayGetNItems(ndim,ARR_DIMS(array));
20842088
oldnullbitmap=ARR_NULLBITMAP(array);
20852089
oldoverheadlen=ARR_DATA_OFFSET(array);
20862090
olddatasize=ARR_SIZE(array)-oldoverheadlen;
2087-
if (extendbefore)
2091+
if (addedbefore)
20882092
{
20892093
offset=0;
20902094
lenbefore=0;
20912095
olditemlen=0;
20922096
lenafter=olddatasize;
20932097
}
2094-
elseif (extendafter)
2098+
elseif (addedafter)
20952099
{
20962100
offset=oldnitems;
20972101
lenbefore=olddatasize;
@@ -2158,17 +2162,24 @@ array_set(ArrayType *array,
21582162
{
21592163
bits8*newnullbitmap=ARR_NULLBITMAP(newarray);
21602164

2161-
array_set_isnull(newnullbitmap,offset,isNull);
2162-
if (extendbefore)
2163-
array_bitmap_copy(newnullbitmap,1,
2165+
/* Zero the bitmap to take care of marking inserted positions null */
2166+
MemSet(newnullbitmap,0, (newnitems+7) /8);
2167+
/* Fix the inserted value */
2168+
if (addedafter)
2169+
array_set_isnull(newnullbitmap,newnitems-1,isNull);
2170+
else
2171+
array_set_isnull(newnullbitmap,offset,isNull);
2172+
/* Fix the copied range(s) */
2173+
if (addedbefore)
2174+
array_bitmap_copy(newnullbitmap,addedbefore,
21642175
oldnullbitmap,0,
21652176
oldnitems);
21662177
else
21672178
{
21682179
array_bitmap_copy(newnullbitmap,0,
21692180
oldnullbitmap,0,
21702181
offset);
2171-
if (!extendafter)
2182+
if (addedafter==0)
21722183
array_bitmap_copy(newnullbitmap,offset+1,
21732184
oldnullbitmap,offset+1,
21742185
oldnitems-offset-1);
@@ -2202,6 +2213,11 @@ array_set(ArrayType *array,
22022213
* A new array is returned, just like the old except for the
22032214
* modified range. The original array object is not changed.
22042215
*
2216+
* For one-dimensional arrays only, we allow the array to be extended
2217+
* by assigning to positions outside the existing subscript range; any
2218+
* positions between the existing elements and the new ones are set to NULLs.
2219+
* (XXX TODO: allow a corresponding behavior for multidimensional arrays)
2220+
*
22052221
* NOTE: we assume it is OK to scribble on the provided index arrays
22062222
* lowerIndx[] and upperIndx[]. These are generally just temporaries.
22072223
*
@@ -2235,6 +2251,8 @@ array_set_slice(ArrayType *array,
22352251
newitemsize,
22362252
overheadlen,
22372253
oldoverheadlen,
2254+
addedbefore,
2255+
addedafter,
22382256
lenbefore,
22392257
lenafter,
22402258
itemsbefore,
@@ -2298,55 +2316,70 @@ array_set_slice(ArrayType *array,
22982316
if (ndim<nSubscripts||ndim <=0||ndim>MAXDIM)
22992317
ereport(ERROR,
23002318
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2301-
errmsg("invalid array subscripts")));
2319+
errmsg("wrong number of array subscripts")));
23022320

23032321
/* copy dim/lb since we may modify them */
23042322
memcpy(dim,ARR_DIMS(array),ndim*sizeof(int));
23052323
memcpy(lb,ARR_LBOUND(array),ndim*sizeof(int));
23062324

2325+
newhasnulls= (ARR_HASNULL(array)||ARR_HASNULL(srcArray));
2326+
addedbefore=addedafter=0;
2327+
23072328
/*
2308-
* Check provided subscripts. A slice exceeding the current array limits
2309-
* throws an error, *except* in the 1-D case where we will extend the
2310-
* array as long as no hole is created. An empty slice is an error, too.
2329+
* Check subscripts
23112330
*/
2312-
for (i=0;i<nSubscripts;i++)
2331+
if (ndim==1)
23132332
{
2314-
if (lowerIndx[i]>upperIndx[i])
2333+
Assert(nSubscripts==1);
2334+
if (lowerIndx[0]>upperIndx[0])
23152335
ereport(ERROR,
23162336
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2317-
errmsg("invalid array subscripts")));
2318-
if (lowerIndx[i]<lb[i])
2337+
errmsg("upper bound cannot be less than lower bound")));
2338+
if (lowerIndx[0]<lb[0])
23192339
{
2320-
if (ndim==1&&upperIndx[i] >=lb[i]-1)
2321-
{
2322-
dim[i]+=lb[i]-lowerIndx[i];
2323-
lb[i]=lowerIndx[i];
2324-
}
2325-
else
2340+
if (upperIndx[0]<lb[0]-1)
2341+
newhasnulls= true;/* will insert nulls */
2342+
addedbefore=lb[0]-lowerIndx[0];
2343+
dim[0]+=addedbefore;
2344+
lb[0]=lowerIndx[0];
2345+
}
2346+
if (upperIndx[0] >= (dim[0]+lb[0]))
2347+
{
2348+
if (lowerIndx[0]> (dim[0]+lb[0]))
2349+
newhasnulls= true;/* will insert nulls */
2350+
addedafter=upperIndx[0]- (dim[0]+lb[0])+1;
2351+
dim[0]+=addedafter;
2352+
}
2353+
}
2354+
else
2355+
{
2356+
/*
2357+
* XXX currently we do not support extending multi-dimensional
2358+
* arrays during assignment
2359+
*/
2360+
for (i=0;i<nSubscripts;i++)
2361+
{
2362+
if (lowerIndx[i]>upperIndx[i])
2363+
ereport(ERROR,
2364+
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2365+
errmsg("upper bound cannot be less than lower bound")));
2366+
if (lowerIndx[i]<lb[i]||
2367+
upperIndx[i] >= (dim[i]+lb[i]))
23262368
ereport(ERROR,
23272369
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2328-
errmsg("invalidarraysubscripts")));
2370+
errmsg("arraysubscript out of range")));
23292371
}
2330-
if (upperIndx[i] >= (dim[i]+lb[i]))
2372+
/* fill any missing subscript positions with full array range */
2373+
for (;i<ndim;i++)
23312374
{
2332-
if (ndim==1&&lowerIndx[i]<= (dim[i]+lb[i]))
2333-
dim[i]=upperIndx[i]-lb[i]+1;
2334-
else
2375+
lowerIndx[i]=lb[i];
2376+
upperIndx[i]=dim[i]+lb[i]-1;
2377+
if (lowerIndx[i]>upperIndx[i])
23352378
ereport(ERROR,
23362379
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2337-
errmsg("invalid array subscripts")));
2380+
errmsg("upper bound cannot be less than lower bound")));
23382381
}
23392382
}
2340-
/* fill any missing subscript positions with full array range */
2341-
for (;i<ndim;i++)
2342-
{
2343-
lowerIndx[i]=lb[i];
2344-
upperIndx[i]=dim[i]+lb[i]-1;
2345-
if (lowerIndx[i]>upperIndx[i])
2346-
ereport(ERROR,
2347-
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2348-
errmsg("invalid array subscripts")));
2349-
}
23502383

23512384
/* Do this mainly to check for overflow */
23522385
nitems=ArrayGetNItems(ndim,dim);
@@ -2366,16 +2399,10 @@ array_set_slice(ArrayType *array,
23662399
* Compute space occupied by new entries, space occupied by replaced
23672400
* entries, and required space for new array.
23682401
*/
2369-
if (ARR_HASNULL(array)||ARR_HASNULL(srcArray))
2370-
{
2371-
newhasnulls= true;
2402+
if (newhasnulls)
23722403
overheadlen=ARR_OVERHEAD_WITHNULLS(ndim,nitems);
2373-
}
23742404
else
2375-
{
2376-
newhasnulls= false;
23772405
overheadlen=ARR_OVERHEAD_NONULLS(ndim);
2378-
}
23792406
newitemsize=array_nelems_size(ARR_DATA_PTR(srcArray),0,
23802407
ARR_NULLBITMAP(srcArray),nsrcitems,
23812408
elmlen,elmbyval,elmalign);
@@ -2407,7 +2434,7 @@ array_set_slice(ArrayType *array,
24072434
char*oldarraydata=ARR_DATA_PTR(array);
24082435
bits8*oldarraybitmap=ARR_NULLBITMAP(array);
24092436

2410-
itemsbefore=slicelb-oldlb;
2437+
itemsbefore=Min(slicelb,oldub+1)-oldlb;
24112438
lenbefore=array_nelems_size(oldarraydata,0,oldarraybitmap,
24122439
itemsbefore,
24132440
elmlen,elmbyval,elmalign);
@@ -2467,13 +2494,15 @@ array_set_slice(ArrayType *array,
24672494
bits8*newnullbitmap=ARR_NULLBITMAP(newarray);
24682495
bits8*oldnullbitmap=ARR_NULLBITMAP(array);
24692496

2470-
array_bitmap_copy(newnullbitmap,0,
2497+
/* Zero the bitmap to handle marking inserted positions null */
2498+
MemSet(newnullbitmap,0, (nitems+7) /8);
2499+
array_bitmap_copy(newnullbitmap,addedbefore,
24712500
oldnullbitmap,0,
24722501
itemsbefore);
2473-
array_bitmap_copy(newnullbitmap,itemsbefore,
2502+
array_bitmap_copy(newnullbitmap,lowerIndx[0]-lb[0],
24742503
ARR_NULLBITMAP(srcArray),0,
24752504
nsrcitems);
2476-
array_bitmap_copy(newnullbitmap,itemsbefore+nsrcitems,
2505+
array_bitmap_copy(newnullbitmap,addedbefore+itemsbefore+nolditems,
24772506
oldnullbitmap,itemsbefore+nolditems,
24782507
itemsafter);
24792508
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp