stored short varlena in array
Hi
Now, the varlena type is stored directly in the array. Did not consider
short varlena. If it's like fill_val(), using short varlena saves memory
footprint and disk space.
In TODO, there is a requirement to be implemented:
Allow single-byte header storage for array elements
This patch modifies many files.
Based on 38da053463bef32adf563ddee5277d16d2b6c5af
Has passed the regression test.
But it can affect many contribs. The code needs to be adjusted. Like
hstore and ltree.
Disk space usage test
create table t1 (c1 varchar[]);
insert into t1
select '{a,b,c,d,e,f,g,h,i,j,k,l,m,n}'
from generate_series(1,100000);
select pg_relation_size('t1')/8192;
before
postgres=# select pg_relation_size('t1')/8192;
?column?
----------
2041
(1 row)
after
postgres=# select pg_relation_size('t1')/8192;
?column?
----------
1334
(1 row)
Memory usage
'{a,b,c,d,e,f,g,h,i,j,k,l,m,n}'::varchar[]
before
136 bytes
after
80 bytes
--
Zongliang Quan
On 2024/12/25 14:29, Quan Zongliang wrote:
Hi
Now, the varlena type is stored directly in the array. Did not consider
short varlena. If it's like fill_val(), using short varlena saves memory
footprint and disk space.
In TODO, there is a requirement to be implemented:
Allow single-byte header storage for array elementsThis patch modifies many files.
Based on 38da053463bef32adf563ddee5277d16d2b6c5af
Has passed the regression test.
But it can affect many contribs. The code needs to be adjusted. Like
hstore and ltree.
Sorry I forgot the patch attachment.
Attachments:
arrayelemhdr.patchtext/plain; charset=UTF-8; name=arrayelemhdr.patchDownload
diff --git a/contrib/hstore/hstore_gin.c b/contrib/hstore/hstore_gin.c
index 766c00bb6a7..b6bd617df45 100644
--- a/contrib/hstore/hstore_gin.c
+++ b/contrib/hstore/hstore_gin.c
@@ -127,7 +127,7 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
/* Nulls in the array are ignored, cf hstoreArrayToPairs */
if (key_nulls[i])
continue;
- item = makeitem(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ, KEYFLAG);
+ item = makeitem(VARDATA_ANY(key_datums[i]), VARSIZE_ANY_EXHDR(key_datums[i]), KEYFLAG);
entries[j++] = PointerGetDatum(item);
}
diff --git a/contrib/hstore/hstore_gist.c b/contrib/hstore/hstore_gist.c
index a3b08af3850..9e330d7be4f 100644
--- a/contrib/hstore/hstore_gist.c
+++ b/contrib/hstore/hstore_gist.c
@@ -576,7 +576,7 @@ ghstore_consistent(PG_FUNCTION_ARGS)
if (key_nulls[i])
continue;
- crc = crc32_sz(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
+ crc = crc32_sz(VARDATA_ANY(key_datums[i]), VARSIZE_ANY_EXHDR(key_datums[i]));
if (!(GETBIT(sign, HASHVAL(crc, siglen))))
res = false;
}
@@ -599,7 +599,7 @@ ghstore_consistent(PG_FUNCTION_ARGS)
if (key_nulls[i])
continue;
- crc = crc32_sz(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
+ crc = crc32_sz(VARDATA_ANY(key_datums[i]), VARSIZE_ANY_EXHDR(key_datums[i]));
if (GETBIT(sign, HASHVAL(crc, siglen)))
res = true;
}
diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c
index 2125436e40c..51461a6ec32 100644
--- a/contrib/hstore/hstore_io.c
+++ b/contrib/hstore/hstore_io.c
@@ -681,22 +681,22 @@ hstore_from_arrays(PG_FUNCTION_ARGS)
if (!value_nulls || value_nulls[i])
{
- pairs[i].key = VARDATA(key_datums[i]);
+ pairs[i].key = VARDATA_ANY(key_datums[i]);
pairs[i].val = NULL;
pairs[i].keylen =
- hstoreCheckKeyLen(VARSIZE(key_datums[i]) - VARHDRSZ);
+ hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(key_datums[i]));
pairs[i].vallen = 4;
pairs[i].isnull = true;
pairs[i].needfree = false;
}
else
{
- pairs[i].key = VARDATA(key_datums[i]);
- pairs[i].val = VARDATA(value_datums[i]);
+ pairs[i].key = VARDATA_ANY(key_datums[i]);
+ pairs[i].val = VARDATA_ANY(value_datums[i]);
pairs[i].keylen =
- hstoreCheckKeyLen(VARSIZE(key_datums[i]) - VARHDRSZ);
+ hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(key_datums[i]));
pairs[i].vallen =
- hstoreCheckValLen(VARSIZE(value_datums[i]) - VARHDRSZ);
+ hstoreCheckValLen(VARSIZE_ANY_EXHDR(value_datums[i]));
pairs[i].isnull = false;
pairs[i].needfree = false;
}
@@ -775,22 +775,22 @@ hstore_from_array(PG_FUNCTION_ARGS)
if (in_nulls[i * 2 + 1])
{
- pairs[i].key = VARDATA(in_datums[i * 2]);
+ pairs[i].key = VARDATA_ANY(in_datums[i * 2]);
pairs[i].val = NULL;
pairs[i].keylen =
- hstoreCheckKeyLen(VARSIZE(in_datums[i * 2]) - VARHDRSZ);
+ hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(in_datums[i * 2]));
pairs[i].vallen = 4;
pairs[i].isnull = true;
pairs[i].needfree = false;
}
else
{
- pairs[i].key = VARDATA(in_datums[i * 2]);
- pairs[i].val = VARDATA(in_datums[i * 2 + 1]);
+ pairs[i].key = VARDATA_ANY(in_datums[i * 2]);
+ pairs[i].val = VARDATA_ANY(in_datums[i * 2 + 1]);
pairs[i].keylen =
- hstoreCheckKeyLen(VARSIZE(in_datums[i * 2]) - VARHDRSZ);
+ hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(in_datums[i * 2]));
pairs[i].vallen =
- hstoreCheckValLen(VARSIZE(in_datums[i * 2 + 1]) - VARHDRSZ);
+ hstoreCheckValLen(VARSIZE_ANY_EXHDR(in_datums[i * 2 + 1]));
pairs[i].isnull = false;
pairs[i].needfree = false;
}
diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c
index 5e57eceffc8..da6aa12e8c4 100644
--- a/contrib/hstore/hstore_op.c
+++ b/contrib/hstore/hstore_op.c
@@ -107,8 +107,8 @@ hstoreArrayToPairs(ArrayType *a, int *npairs)
{
if (!key_nulls[i])
{
- key_pairs[j].key = VARDATA(key_datums[i]);
- key_pairs[j].keylen = VARSIZE(key_datums[i]) - VARHDRSZ;
+ key_pairs[j].key = VARDATA_ANY(key_datums[i]);
+ key_pairs[j].keylen = VARSIZE_ANY_EXHDR(key_datums[i]);
key_pairs[j].val = NULL;
key_pairs[j].vallen = 0;
key_pairs[j].needfree = 0;
@@ -599,7 +599,7 @@ hstore_slice_to_array(PG_FUNCTION_ARGS)
if (key_nulls[i])
idx = -1;
else
- idx = hstoreFindKey(hs, NULL, VARDATA(key), VARSIZE(key) - VARHDRSZ);
+ idx = hstoreFindKey(hs, NULL, VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
if (idx < 0 || HSTORE_VALISNULL(entries, idx))
{
@@ -619,7 +619,8 @@ hstore_slice_to_array(PG_FUNCTION_ARGS)
ARR_NDIM(key_array),
ARR_DIMS(key_array),
ARR_LBOUND(key_array),
- TEXTOID, -1, false, TYPALIGN_INT);
+ TEXTOID, -1, false,
+ TYPALIGN_INT, TYPSTORAGE_EXTENDED);
PG_RETURN_POINTER(aout);
}
@@ -762,7 +763,8 @@ hstore_avals(PG_FUNCTION_ARGS)
}
a = construct_md_array(d, nulls, 1, &count, &lb,
- TEXTOID, -1, false, TYPALIGN_INT);
+ TEXTOID, -1, false,
+ TYPALIGN_INT, TYPSTORAGE_EXTENDED);
PG_RETURN_POINTER(a);
}
@@ -814,7 +816,8 @@ hstore_to_array_internal(HStore *hs, int ndims)
return construct_md_array(out_datums, out_nulls,
ndims, out_size, lb,
- TEXTOID, -1, false, TYPALIGN_INT);
+ TEXTOID, -1, false,
+ TYPALIGN_INT, TYPSTORAGE_EXTENDED);
}
PG_FUNCTION_INFO_V1(hstore_to_array);
diff --git a/contrib/ltree/_ltree_gist.c b/contrib/ltree/_ltree_gist.c
index 286ad24fbe8..ce84ee89d8e 100644
--- a/contrib/ltree/_ltree_gist.c
+++ b/contrib/ltree/_ltree_gist.c
@@ -26,7 +26,7 @@ PG_FUNCTION_INFO_V1(_ltree_consistent);
PG_FUNCTION_INFO_V1(_ltree_gist_options);
#define GETENTRY(vec,pos) ((ltree_gist *) DatumGetPointer((vec)->vector[(pos)].key))
-#define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
+#define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE_ANY(x) ) ) )
#define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
@@ -60,6 +60,7 @@ _ltree_compress(PG_FUNCTION_ARGS)
ArrayType *val = DatumGetArrayTypeP(entry->key);
int num = ArrayGetNItems(ARR_NDIM(val), ARR_DIMS(val));
ltree *item = (ltree *) ARR_DATA_PTR(val);
+ ltree *newitem;
if (ARR_NDIM(val) > 1)
ereport(ERROR,
@@ -74,7 +75,10 @@ _ltree_compress(PG_FUNCTION_ARGS)
while (num > 0)
{
- hashing(LTG_SIGN(key), item, siglen);
+ newitem = (ltree *)ltree_norm_short_item((char *)item);
+
+ hashing(LTG_SIGN(key), newitem, siglen);
+ PFREE_IF_NEW(newitem, item);
num--;
item = NEXTVAL(item);
}
@@ -481,6 +485,7 @@ static bool
_arrq_cons(ltree_gist *key, ArrayType *_query, int siglen)
{
lquery *query = (lquery *) ARR_DATA_PTR(_query);
+ lquery *newqry;
int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
if (ARR_NDIM(_query) > 1)
@@ -494,8 +499,16 @@ _arrq_cons(ltree_gist *key, ArrayType *_query, int siglen)
while (num > 0)
{
- if (gist_qe(key, query, siglen))
+ newqry = (lquery *)ltree_norm_short_item((char *)query);
+
+ if (gist_qe(key, newqry, siglen))
+ {
+ PFREE_IF_NEW(newqry, query);
return true;
+ }
+
+ PFREE_IF_NEW(newqry, query);
+
num--;
query = (lquery *) NEXTVAL(query);
}
diff --git a/contrib/ltree/_ltree_op.c b/contrib/ltree/_ltree_op.c
index b4a8097328d..274f8c6bd79 100644
--- a/contrib/ltree/_ltree_op.c
+++ b/contrib/ltree/_ltree_op.c
@@ -32,13 +32,14 @@ PG_FUNCTION_INFO_V1(_lca);
typedef Datum (*PGCALL2) (PG_FUNCTION_ARGS);
-#define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
+#define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE_ANY(x) ) ) )
static bool
array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree **found)
{
int num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
ltree *item = (ltree *) ARR_DATA_PTR(la);
+ ltree *newitem;
if (ARR_NDIM(la) > 1)
ereport(ERROR,
@@ -53,14 +54,20 @@ array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree **found)
*found = NULL;
while (num > 0)
{
+ newitem = (ltree *)ltree_norm_short_item((char *)item);
+
if (DatumGetBool(DirectFunctionCall2(callback,
- PointerGetDatum(item), PointerGetDatum(param))))
+ PointerGetDatum(newitem), PointerGetDatum(param))))
{
+ PFREE_IF_NEW(newitem, item);
if (found)
*found = item;
return true;
}
+
+ PFREE_IF_NEW(newitem, item);
+
num--;
item = NEXTVAL(item);
}
@@ -137,6 +144,7 @@ _lt_q_regex(PG_FUNCTION_ARGS)
ArrayType *_tree = PG_GETARG_ARRAYTYPE_P(0);
ArrayType *_query = PG_GETARG_ARRAYTYPE_P(1);
lquery *query = (lquery *) ARR_DATA_PTR(_query);
+ lquery *newqry;
bool res = false;
int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
@@ -151,11 +159,18 @@ _lt_q_regex(PG_FUNCTION_ARGS)
while (num > 0)
{
- if (array_iterator(_tree, ltq_regex, query, NULL))
+ newqry = (lquery *)ltree_norm_short_item((char *)query);
+
+ if (array_iterator(_tree, ltq_regex, newqry, NULL))
{
+ PFREE_IF_NEW(newqry, query);
+
res = true;
break;
}
+
+ PFREE_IF_NEW(newqry, query);
+
num--;
query = (lquery *) NEXTVAL(query);
}
@@ -297,6 +312,8 @@ _lca(PG_FUNCTION_ARGS)
ltree *item = (ltree *) ARR_DATA_PTR(la);
ltree **a,
*res;
+ int i;
+ bool *copied;
if (ARR_NDIM(la) > 1)
ereport(ERROR,
@@ -308,14 +325,25 @@ _lca(PG_FUNCTION_ARGS)
errmsg("array must not contain nulls")));
a = (ltree **) palloc(sizeof(ltree *) * num);
- while (num > 0)
+ copied = (bool *)palloc(sizeof(bool) * num);
+
+ for (i = 0; i < num; i++)
{
- num--;
- a[num] = item;
+ a[i] = (ltree *)ltree_norm_short_item((char *)item);
+ copied[i] = (a[i] != item);
item = NEXTVAL(item);
}
+
res = lca_inner(a, ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la)));
+
+ for (i = 0; i < num; i++)
+ {
+ if (copied[i])
+ pfree(a[i]);
+ }
+
pfree(a);
+ pfree(copied);
PG_FREE_IF_COPY(la, 0);
diff --git a/contrib/ltree/lquery_op.c b/contrib/ltree/lquery_op.c
index a6466f575fd..a55ee51de04 100644
--- a/contrib/ltree/lquery_op.c
+++ b/contrib/ltree/lquery_op.c
@@ -19,7 +19,7 @@ PG_FUNCTION_INFO_V1(ltq_rregex);
PG_FUNCTION_INFO_V1(lt_q_regex);
PG_FUNCTION_INFO_V1(lt_q_rregex);
-#define NEXTVAL(x) ( (lquery*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
+#define NEXTVAL(x) ( (lquery*)( (char*)(x) + INTALIGN( VARSIZE_ANY(x) ) ) )
static char *
getlexeme(char *start, char *end, int *len)
@@ -241,6 +241,7 @@ lt_q_regex(PG_FUNCTION_ARGS)
ltree *tree = PG_GETARG_LTREE_P(0);
ArrayType *_query = PG_GETARG_ARRAYTYPE_P(1);
lquery *query = (lquery *) ARR_DATA_PTR(_query);
+ lquery *newqry;
bool res = false;
int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
@@ -255,13 +256,19 @@ lt_q_regex(PG_FUNCTION_ARGS)
while (num > 0)
{
+ newqry = (lquery *)ltree_norm_short_item((char *)query);
+
if (DatumGetBool(DirectFunctionCall2(ltq_regex,
- PointerGetDatum(tree), PointerGetDatum(query))))
+ PointerGetDatum(tree), PointerGetDatum(newqry))))
{
+ PFREE_IF_NEW(newqry, query);
res = true;
break;
}
+
+ PFREE_IF_NEW(newqry, query);
+
num--;
query = NEXTVAL(query);
}
diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h
index 5e0761641d3..28075bd3498 100644
--- a/contrib/ltree/ltree.h
+++ b/contrib/ltree/ltree.h
@@ -6,6 +6,7 @@
#include "fmgr.h"
#include "tsearch/ts_locale.h"
#include "utils/memutils.h"
+#include "varatt.h"
/* ltree */
@@ -212,6 +213,29 @@ bool compare_subnode(ltree_level *t, char *qn, int len,
ltree *lca_inner(ltree **a, int len);
int ltree_strncasecmp(const char *a, const char *b, size_t s);
+/* normalize ltree/lquery in array if it is short version. */
+static inline char*
+ltree_norm_short_item(char *item)
+{
+ if (VARATT_IS_SHORT(item))
+ {
+ /*
+ * This is a short-header varlena --- convert to 4-byte header format
+ */
+ char *newitem;
+ Size data_size = VARSIZE_SHORT(item) - VARHDRSZ_SHORT;
+ Size new_size = data_size + VARHDRSZ;
+
+ newitem = palloc(new_size);
+ SET_VARSIZE(newitem, new_size);
+ memcpy(VARDATA(newitem), VARDATA_SHORT(item), data_size);
+
+ return newitem;
+ }
+ else
+ return item;
+}
+
/* fmgr macros for ltree objects */
#define DatumGetLtreeP(X) ((ltree *) PG_DETOAST_DATUM(X))
#define DatumGetLtreePCopy(X) ((ltree *) PG_DETOAST_DATUM_COPY(X))
diff --git a/contrib/ltree/ltree_gist.c b/contrib/ltree/ltree_gist.c
index 932f69bff2d..5733d5a1c2d 100644
--- a/contrib/ltree/ltree_gist.c
+++ b/contrib/ltree/ltree_gist.c
@@ -12,7 +12,7 @@
#include "ltree.h"
#include "utils/array.h"
-#define NEXTVAL(x) ( (lquery*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
+#define NEXTVAL(x) ( (lquery*)( (char*)(x) + INTALIGN( VARSIZE_ANY(x) ) ) )
#define ISEQ(a,b) ( (a)->numlevel == (b)->numlevel && ltree_compare(a,b)==0 )
PG_FUNCTION_INFO_V1(ltree_gist_in);
@@ -592,6 +592,7 @@ static bool
arrq_cons(ltree_gist *key, ArrayType *_query, int siglen)
{
lquery *query = (lquery *) ARR_DATA_PTR(_query);
+ lquery *newqry;
int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
if (ARR_NDIM(_query) > 1)
@@ -605,11 +606,21 @@ arrq_cons(ltree_gist *key, ArrayType *_query, int siglen)
while (num > 0)
{
- if (gist_qe(key, query, siglen) && gist_between(key, query, siglen))
+ newqry = (lquery *)ltree_norm_short_item((char *)query);
+
+ if (gist_qe(key, newqry, siglen) && gist_between(key, newqry, siglen))
+ {
+ PFREE_IF_NEW(newqry, query);
+
return true;
+ }
+
+ PFREE_IF_NEW(newqry, query);
+
num--;
query = NEXTVAL(query);
}
+
return false;
}
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 49fd35bfc55..26e31a583a4 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1179,8 +1179,8 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
for (i = 0; i < noldoptions; i++)
{
- char *text_str = VARDATA(oldoptions[i]);
- int text_len = VARSIZE(oldoptions[i]) - VARHDRSZ;
+ char *text_str = VARDATA_ANY(oldoptions[i]);
+ int text_len = VARSIZE_ANY_EXHDR(oldoptions[i]);
/* Search for a match in defList */
foreach(cell, defList)
@@ -1436,8 +1436,8 @@ parseRelOptionsInternal(Datum options, bool validate,
for (i = 0; i < noptions; i++)
{
- char *text_str = VARDATA(optiondatums[i]);
- int text_len = VARSIZE(optiondatums[i]) - VARHDRSZ;
+ char *text_str = VARDATA_ANY(optiondatums[i]);
+ int text_len = VARSIZE_ANY_EXHDR(optiondatums[i]);
int j;
/* Search for a match in reloptions */
diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c
index 2373e76f77e..b8311d21858 100644
--- a/src/backend/access/gin/ginarrayproc.c
+++ b/src/backend/access/gin/ginarrayproc.c
@@ -39,16 +39,17 @@ ginarrayextract(PG_FUNCTION_ARGS)
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
Datum *elems;
bool *nulls;
int nelems;
- get_typlenbyvalalign(ARR_ELEMTYPE(array),
- &elmlen, &elmbyval, &elmalign);
+ get_type_stores(ARR_ELEMTYPE(array),
+ &elmlen, &elmbyval, &elmalign, &elmstor);
deconstruct_array(array,
ARR_ELEMTYPE(array),
- elmlen, elmbyval, elmalign,
+ elmlen, elmbyval, elmalign, elmstor,
&elems, &nulls, &nelems);
*nkeys = nelems;
@@ -90,16 +91,17 @@ ginqueryarrayextract(PG_FUNCTION_ARGS)
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
Datum *elems;
bool *nulls;
int nelems;
- get_typlenbyvalalign(ARR_ELEMTYPE(array),
- &elmlen, &elmbyval, &elmalign);
+ get_type_stores(ARR_ELEMTYPE(array),
+ &elmlen, &elmbyval, &elmalign, &elmstor);
deconstruct_array(array,
ARR_ELEMTYPE(array),
- elmlen, elmbyval, elmalign,
+ elmlen, elmbyval, elmalign, elmstor,
&elems, &nulls, &nelems);
*nkeys = nelems;
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index a531d37908a..c3aa979c572 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -340,6 +340,7 @@ _bt_preprocess_array_keys(IndexScanDesc scan, int *new_numberOfKeys)
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
int num_elems;
Datum *elem_values;
bool *elem_nulls;
@@ -364,11 +365,11 @@ _bt_preprocess_array_keys(IndexScanDesc scan, int *new_numberOfKeys)
*/
arrayval = DatumGetArrayTypeP(cur->sk_argument);
/* We could cache this data, but not clear it's worth it */
- get_typlenbyvalalign(ARR_ELEMTYPE(arrayval),
- &elmlen, &elmbyval, &elmalign);
+ get_type_stores(ARR_ELEMTYPE(arrayval),
+ &elmlen, &elmbyval, &elmalign, &elmstor);
deconstruct_array(arrayval,
ARR_ELEMTYPE(arrayval),
- elmlen, elmbyval, elmalign,
+ elmlen, elmbyval, elmalign, elmstor,
&elem_values, &elem_nulls, &num_elems);
/*
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index e0cb70ee9da..79ebac5b78c 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -903,6 +903,105 @@ boot_get_type_io_data(Oid typid,
}
}
+/* ----------------
+ * boot_array_type_metadata
+ *
+ * Obtain type metadata at bootstrap time. This intentionally has
+ * almost the same API as lsyscache.c's array_type_metadata, except that
+ * we only support obtaining the typinput and typoutput routines, not
+ * the binary I/O routines. It is exported so that array_in and array_out
+ * can be made to work during early bootstrap.
+ * ----------------
+ */
+void
+boot_array_type_metadata(Oid typid,
+ IOFuncSelector which_func,
+ ArrayMetaState *metadata)
+{
+ if (Typ != NIL)
+ {
+ /* We have the boot-time contents of pg_type, so use it */
+ struct typmap *ap = NULL;
+ ListCell *lc;
+
+ foreach(lc, Typ)
+ {
+ ap = lfirst(lc);
+ if (ap->am_oid == typid)
+ break;
+ }
+
+ if (!ap || ap->am_oid != typid)
+ elog(ERROR, "type OID %u not found in Typ list", typid);
+
+ metadata->typlen = ap->am_typ.typlen;
+ metadata->typbyval = ap->am_typ.typbyval;
+ metadata->typalign = ap->am_typ.typalign;
+ metadata->typstorage = ap->am_typ.typstorage;
+ metadata->typdelim = ap->am_typ.typdelim;
+
+ /* XXX this logic must match getTypeIOParam() */
+ if (OidIsValid(ap->am_typ.typelem))
+ metadata->typioparam = ap->am_typ.typelem;
+ else
+ metadata->typioparam = typid;
+
+ switch (which_func)
+ {
+ case IOFunc_input:
+ metadata->typiofunc = ap->am_typ.typinput;
+ break;
+ case IOFunc_output:
+ metadata->typiofunc = ap->am_typ.typoutput;
+ break;
+ default:
+ elog(ERROR, "binary I/O not supported during bootstrap");
+ break;
+ }
+
+ return;
+ }
+ else
+ {
+ /* We don't have pg_type yet, so use the hard-wired TypInfo array */
+ int typeindex;
+
+ for (typeindex = 0; typeindex < n_types; typeindex++)
+ {
+ if (TypInfo[typeindex].oid == typid)
+ break;
+ }
+ if (typeindex >= n_types)
+ elog(ERROR, "type OID %u not found in TypInfo", typid);
+
+ metadata->typlen = TypInfo[typeindex].len;
+ metadata->typbyval = TypInfo[typeindex].byval;
+ metadata->typalign = TypInfo[typeindex].align;
+ metadata->typstorage = TypInfo[typeindex].storage;
+ /* We assume typdelim is ',' for all boot-time types */
+ metadata->typdelim = ',';
+
+ /* XXX this logic must match getTypeIOParam() */
+ if (OidIsValid(TypInfo[typeindex].elem))
+ metadata->typioparam = TypInfo[typeindex].elem;
+ else
+ metadata->typioparam = typid;
+
+ switch (which_func)
+ {
+ case IOFunc_input:
+ metadata->typiofunc = TypInfo[typeindex].inproc;
+ break;
+ case IOFunc_output:
+ metadata->typiofunc = TypInfo[typeindex].outproc;
+ break;
+ default:
+ elog(ERROR, "binary I/O not supported during bootstrap");
+ break;
+ }
+ }
+}
+
/* ----------------
* AllocateAttribute
*
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index be7e4a5dd01..c9e6bf73872 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -6126,7 +6126,8 @@ strlist_to_textarray(List *list)
lb[0] = 1;
arr = construct_md_array(datums, nulls, 1, &j,
- lb, TEXTOID, -1, false, TYPALIGN_INT);
+ lb, TEXTOID, -1, false,
+ TYPALIGN_INT, TYPSTORAGE_EXTENDED);
MemoryContextDelete(memcxt);
diff --git a/src/backend/catalog/pg_attrdef.c b/src/backend/catalog/pg_attrdef.c
index 003ae70b4d2..ce73000e4c7 100644
--- a/src/backend/catalog/pg_attrdef.c
+++ b/src/backend/catalog/pg_attrdef.c
@@ -148,7 +148,8 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
defAttStruct->atttypid,
defAttStruct->attlen,
defAttStruct->attbyval,
- defAttStruct->attalign));
+ defAttStruct->attalign,
+ defAttStruct->attstorage));
}
valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull;
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 9a56de2282f..ba449b2c495 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -1721,7 +1721,8 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
stats->statypid[k],
stats->statyplen[k],
stats->statypbyval[k],
- stats->statypalign[k]);
+ stats->statypalign[k],
+ stats->statypstorage[k]);
values[i++] = PointerGetDatum(arry); /* stavaluesN */
}
else
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index e683c520a82..b51348d65ce 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -2654,7 +2654,8 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
-1 /* varlena array */ ,
sizeof(Oid) /* OID's typlen */ ,
true /* OID's typbyval */ ,
- TYPALIGN_INT /* OID's typalign */ );
+ TYPALIGN_INT /* OID's typalign */,
+ TYPSTORAGE_PLAIN /* OID's typstorage */ );
}
repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a);
repl_repl[Anum_pg_extension_extconfig - 1] = true;
@@ -2690,7 +2691,8 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
-1 /* varlena array */ ,
-1 /* TEXT's typlen */ ,
false /* TEXT's typbyval */ ,
- TYPALIGN_INT /* TEXT's typalign */ );
+ TYPALIGN_INT /* TEXT's typalign */ ,
+ TYPSTORAGE_EXTENDED /* TEXT's typstorage */ );
}
repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a);
repl_repl[Anum_pg_extension_extcondition - 1] = true;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 49374782625..b4840d60e0a 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -13750,13 +13750,15 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
attTup->attlen,
attTup->attbyval,
attTup->attalign,
+ attTup->attstorage,
&isNull);
missingval = PointerGetDatum(construct_array(&missingval,
1,
targettype,
tform->typlen,
tform->typbyval,
- tform->typalign));
+ tform->typalign,
+ tform->typstorage));
valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 3d01a90bd64..5d73e2b21b0 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -1886,10 +1886,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
scratch.d.arrayexpr.elemtype = arrayexpr->element_typeid;
/* do one-time catalog lookup for type info */
- get_typlenbyvalalign(arrayexpr->element_typeid,
- &scratch.d.arrayexpr.elemlength,
- &scratch.d.arrayexpr.elembyval,
- &scratch.d.arrayexpr.elemalign);
+ get_type_stores(arrayexpr->element_typeid,
+ &scratch.d.arrayexpr.elemlength,
+ &scratch.d.arrayexpr.elembyval,
+ &scratch.d.arrayexpr.elemalign,
+ &scratch.d.arrayexpr.elemstorage);
/* prepare to evaluate all arguments */
elemoff = 0;
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index d2987663e63..9de7f7b523b 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -3211,7 +3211,8 @@ ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op)
element_type,
op->d.arrayexpr.elemlength,
op->d.arrayexpr.elembyval,
- op->d.arrayexpr.elemalign);
+ op->d.arrayexpr.elemalign,
+ op->d.arrayexpr.elemstorage);
}
else
{
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 8000feff4c9..7a33d697c35 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -678,6 +678,7 @@ ExecIndexEvalArrayKeys(ExprContext *econtext,
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
int num_elems;
Datum *elem_values;
bool *elem_nulls;
@@ -696,11 +697,11 @@ ExecIndexEvalArrayKeys(ExprContext *econtext,
}
arrayval = DatumGetArrayTypeP(arraydatum);
/* We could cache this data, but not clear it's worth it */
- get_typlenbyvalalign(ARR_ELEMTYPE(arrayval),
- &elmlen, &elmbyval, &elmalign);
+ get_type_stores(ARR_ELEMTYPE(arrayval),
+ &elmlen, &elmbyval, &elmalign, &elmstor);
deconstruct_array(arrayval,
ARR_ELEMTYPE(arrayval),
- elmlen, elmbyval, elmalign,
+ elmlen, elmbyval, elmalign, elmstor,
&elem_values, &elem_nulls, &num_elems);
if (num_elems <= 0)
{
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 5d102a0d371..83ee95a2656 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -3428,11 +3428,12 @@ match_orclause_to_indexcol(PlannerInfo *root,
int16 typlen;
bool typbyval;
char typalign;
+ char typstor;
Datum *elems;
int i = 0;
ArrayType *arrayConst;
- get_typlenbyvalalign(consttype, &typlen, &typbyval, &typalign);
+ get_type_stores(consttype, &typlen, &typbyval, &typalign, &typstor);
elems = (Datum *) palloc(sizeof(Datum) * list_length(consts));
foreach_node(Const, value, consts)
@@ -3443,7 +3444,7 @@ match_orclause_to_indexcol(PlannerInfo *root,
}
arrayConst = construct_array(elems, i, consttype,
- typlen, typbyval, typalign);
+ typlen, typbyval, typalign, typstor);
arrayNode = (Node *) makeConst(arraytype, -1, inputcollid,
-1, PointerGetDatum(arrayConst),
false, false);
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index 0a132610140..20e7dd220f0 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -965,6 +965,7 @@ arrayconst_startup_fn(Node *clause, PredIterInfo info)
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
/* Create working state struct */
state = (ArrayConstIterState *) palloc(sizeof(ArrayConstIterState));
@@ -973,11 +974,11 @@ arrayconst_startup_fn(Node *clause, PredIterInfo info)
/* Deconstruct the array literal */
arrayconst = (Const *) lsecond(saop->args);
arrayval = DatumGetArrayTypeP(arrayconst->constvalue);
- get_typlenbyvalalign(ARR_ELEMTYPE(arrayval),
- &elmlen, &elmbyval, &elmalign);
+ get_type_stores(ARR_ELEMTYPE(arrayval),
+ &elmlen, &elmbyval, &elmalign, &elmstor);
deconstruct_array(arrayval,
ARR_ELEMTYPE(arrayval),
- elmlen, elmbyval, elmalign,
+ elmlen, elmbyval, elmalign, elmstor,
&state->elem_values, &state->elem_nulls,
&state->num_elems);
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index c28639d2e3f..3064c943254 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -4778,6 +4778,7 @@ satisfies_hash_partition(PG_FUNCTION_ARGS)
int16 variadic_typlen;
bool variadic_typbyval;
char variadic_typalign;
+ char variadic_typstorage;
Oid partcollid[PARTITION_MAX_KEYS];
FmgrInfo partsupfunc[FLEXIBLE_ARRAY_MEMBER];
} ColumnsHashData;
@@ -4881,10 +4882,11 @@ satisfies_hash_partition(PG_FUNCTION_ARGS)
my_extra->relid = parentId;
my_extra->nkeys = key->partnatts;
my_extra->variadic_type = ARR_ELEMTYPE(variadic_array);
- get_typlenbyvalalign(my_extra->variadic_type,
+ get_type_stores(my_extra->variadic_type,
&my_extra->variadic_typlen,
&my_extra->variadic_typbyval,
- &my_extra->variadic_typalign);
+ &my_extra->variadic_typalign,
+ &my_extra->variadic_typstorage);
my_extra->partcollid[0] = key->partcollation[0];
/* check argument types */
@@ -4949,6 +4951,7 @@ satisfies_hash_partition(PG_FUNCTION_ARGS)
my_extra->variadic_typlen,
my_extra->variadic_typbyval,
my_extra->variadic_typalign,
+ my_extra->variadic_typstorage,
&datum, &isnull, &nelems);
/* complain if wrong number of column values */
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 4e12ae5d1e3..faf825b9cd5 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -2280,6 +2280,7 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
int16 elemlen;
bool elembyval;
char elemalign;
+ char elemstor;
Datum *elem_values;
bool *elem_nulls;
int num_elems,
@@ -2290,11 +2291,11 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
return PARTCLAUSE_MATCH_CONTRADICT;
arrval = DatumGetArrayTypeP(arr->constvalue);
- get_typlenbyvalalign(ARR_ELEMTYPE(arrval),
- &elemlen, &elembyval, &elemalign);
+ get_type_stores(ARR_ELEMTYPE(arrval),
+ &elemlen, &elembyval, &elemalign, &elemstor);
deconstruct_array(arrval,
ARR_ELEMTYPE(arrval),
- elemlen, elembyval, elemalign,
+ elemlen, elembyval, elemalign, elemstor,
&elem_values, &elem_nulls,
&num_elems);
for (i = 0; i < num_elems; i++)
diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c
index 99fdf208dba..3c1335fd707 100644
--- a/src/backend/statistics/extended_stats.c
+++ b/src/backend/statistics/extended_stats.c
@@ -575,6 +575,7 @@ examine_attribute(Node *expr)
stats->statyplen[i] = stats->attrtype->typlen;
stats->statypbyval[i] = stats->attrtype->typbyval;
stats->statypalign[i] = stats->attrtype->typalign;
+ stats->statypstorage[i] = stats->attrtype->typstorage;
}
/*
@@ -660,6 +661,7 @@ examine_expression(Node *expr, int stattarget)
stats->statyplen[i] = stats->attrtype->typlen;
stats->statypbyval[i] = stats->attrtype->typbyval;
stats->statypalign[i] = stats->attrtype->typalign;
+ stats->statypstorage[i] = stats->attrtype->typstorage;
}
/*
@@ -2393,7 +2395,8 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs)
stats->statypid[k],
stats->statyplen[k],
stats->statypbyval[k],
- stats->statypalign[k]);
+ stats->statypalign[k],
+ stats->statypstorage[k]);
values[i++] = PointerGetDatum(arry); /* stavaluesN */
}
else
diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c
index b0e9aead84e..c2fddf69526 100644
--- a/src/backend/statistics/mcv.c
+++ b/src/backend/statistics/mcv.c
@@ -1724,6 +1724,7 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
int num_elems;
Datum *elem_values;
bool *elem_nulls;
@@ -1745,11 +1746,11 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
if (!cst->constisnull)
{
arrayval = DatumGetArrayTypeP(cst->constvalue);
- get_typlenbyvalalign(ARR_ELEMTYPE(arrayval),
- &elmlen, &elmbyval, &elmalign);
+ get_type_stores(ARR_ELEMTYPE(arrayval),
+ &elmlen, &elmbyval, &elmalign, &elmstor);
deconstruct_array(arrayval,
ARR_ELEMTYPE(arrayval),
- elmlen, elmbyval, elmalign,
+ elmlen, elmbyval, elmalign, elmstor,
&elem_values, &elem_nulls, &num_elems);
}
diff --git a/src/backend/utils/adt/array_expanded.c b/src/backend/utils/adt/array_expanded.c
index cc3713b97b7..9882f1e0df8 100644
--- a/src/backend/utils/adt/array_expanded.c
+++ b/src/backend/utils/adt/array_expanded.c
@@ -92,6 +92,7 @@ expand_array(Datum arraydatum, MemoryContext parentcontext,
metacache->typlen = oldeah->typlen;
metacache->typbyval = oldeah->typbyval;
metacache->typalign = oldeah->typalign;
+ metacache->typstorage = oldeah->typstorage;
/*
* If element type is pass-by-value and we have a Datum-array
@@ -144,14 +145,17 @@ expand_array(Datum arraydatum, MemoryContext parentcontext,
eah->typlen = metacache->typlen;
eah->typbyval = metacache->typbyval;
eah->typalign = metacache->typalign;
+ eah->typstorage = metacache->typstorage;
}
else
{
/* No, so look it up */
- get_typlenbyvalalign(eah->element_type,
+ get_type_stores(eah->element_type,
&eah->typlen,
&eah->typbyval,
- &eah->typalign);
+ &eah->typalign,
+ &eah->typstorage);
+
/* Update cache if provided */
if (metacache)
{
@@ -159,6 +163,7 @@ expand_array(Datum arraydatum, MemoryContext parentcontext,
metacache->typlen = eah->typlen;
metacache->typbyval = eah->typbyval;
metacache->typalign = eah->typalign;
+ metacache->typstorage = eah->typstorage;
}
}
@@ -203,6 +208,7 @@ copy_byval_expanded_array(ExpandedArrayHeader *eah,
eah->typlen = oldeah->typlen;
eah->typbyval = oldeah->typbyval;
eah->typalign = oldeah->typalign;
+ eah->typstorage = oldeah->typstorage;
/* Copy the deconstructed representation */
eah->dvalues = (Datum *) MemoryContextAlloc(objcxt,
@@ -333,7 +339,7 @@ EA_flatten_into(ExpandedObjectHeader *eohptr,
CopyArrayEls(aresult,
eah->dvalues, eah->dnulls, nelems,
- eah->typlen, eah->typbyval, eah->typalign,
+ eah->typlen, eah->typbyval, eah->typalign, eah->typstorage,
false);
}
@@ -384,6 +390,7 @@ DatumGetExpandedArrayX(Datum d, ArrayMetaState *metacache)
metacache->typlen = eah->typlen;
metacache->typbyval = eah->typbyval;
metacache->typalign = eah->typalign;
+ metacache->typstorage = eah->typstorage;
}
return eah;
}
@@ -433,7 +440,8 @@ deconstruct_expanded_array(ExpandedArrayHeader *eah)
dnulls = NULL;
deconstruct_array(eah->fvalue,
eah->element_type,
- eah->typlen, eah->typbyval, eah->typalign,
+ eah->typlen, eah->typbyval,
+ eah->typalign, eah->typstorage,
&dvalues,
ARR_HASNULL(eah->fvalue) ? &dnulls : NULL,
&nelems);
diff --git a/src/backend/utils/adt/array_selfuncs.c b/src/backend/utils/adt/array_selfuncs.c
index e2af89f5cc5..d1857fa66f3 100644
--- a/src/backend/utils/adt/array_selfuncs.c
+++ b/src/backend/utils/adt/array_selfuncs.c
@@ -448,6 +448,7 @@ mcelem_array_selec(ArrayType *array, TypeCacheEntry *typentry,
typentry->typlen,
typentry->typbyval,
typentry->typalign,
+ typentry->typstorage,
&elem_values, &elem_nulls, &num_elems);
/* Collapse out any null elements */
diff --git a/src/backend/utils/adt/array_typanalyze.c b/src/backend/utils/adt/array_typanalyze.c
index 2c633bee6b1..148197694b0 100644
--- a/src/backend/utils/adt/array_typanalyze.c
+++ b/src/backend/utils/adt/array_typanalyze.c
@@ -42,6 +42,7 @@ typedef struct
bool typbyval; /* physical properties of element type */
int16 typlen;
char typalign;
+ char typstorage;
/*
* Lookup data for element type's comparison and hash functions (these are
@@ -139,6 +140,7 @@ array_typanalyze(PG_FUNCTION_ARGS)
extra_data->typbyval = typentry->typbyval;
extra_data->typlen = typentry->typlen;
extra_data->typalign = typentry->typalign;
+ extra_data->typstorage = typentry->typstorage;
extra_data->cmp = &typentry->cmp_proc_finfo;
extra_data->hash = &typentry->hash_proc_finfo;
@@ -340,6 +342,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
extra_data->typlen,
extra_data->typbyval,
extra_data->typalign,
+ extra_data->typstorage,
&elem_values, &elem_nulls, &num_elems);
/*
@@ -568,6 +571,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
stats->statyplen[slot_idx] = extra_data->typlen;
stats->statypbyval[slot_idx] = extra_data->typbyval;
stats->statypalign[slot_idx] = extra_data->typalign;
+ stats->statypstorage[slot_idx] = extra_data->typstorage;
slot_idx++;
}
diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c
index 304a93112e2..2d533a59185 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -161,8 +161,9 @@ array_append(PG_FUNCTION_ARGS)
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
result = array_set_element(EOHPGetRWDatum(&eah->hdr),
- 1, &indx, newelem, isNull,
- -1, my_extra->typlen, my_extra->typbyval, my_extra->typalign);
+ 1, &indx, newelem, isNull, -1,
+ my_extra->typlen, my_extra->typbyval,
+ my_extra->typalign, my_extra->typstorage);
PG_RETURN_DATUM(result);
}
@@ -216,8 +217,9 @@ array_prepend(PG_FUNCTION_ARGS)
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
result = array_set_element(EOHPGetRWDatum(&eah->hdr),
- 1, &indx, newelem, isNull,
- -1, my_extra->typlen, my_extra->typbyval, my_extra->typalign);
+ 1, &indx, newelem, isNull, -1,
+ my_extra->typlen, my_extra->typbyval,
+ my_extra->typalign, my_extra->typstorage);
/* Readjust result's LB to match the input's, as expected for prepend */
Assert(result == EOHPGetRWDatum(&eah->hdr));
@@ -654,6 +656,9 @@ array_agg_serialize(PG_FUNCTION_ARGS)
/* typalign */
pq_sendbyte(&buf, state->typalign);
+ /* typstorage */
+ pq_sendbyte(&buf, state->typstorage);
+
/* dnulls */
pq_sendbytes(&buf, state->dnulls, sizeof(bool) * state->nelems);
@@ -749,6 +754,9 @@ array_agg_deserialize(PG_FUNCTION_ARGS)
/* typalign */
result->typalign = pq_getmsgbyte(&buf);
+ /* typstorage */
+ result->typstorage = pq_getmsgbyte(&buf);
+
/* dnulls */
temp = pq_getmsgbytes(&buf, sizeof(bool) * nelems);
memcpy(result->dnulls, temp, sizeof(bool) * nelems);
@@ -1321,10 +1329,11 @@ array_position_common(FunctionCallInfo fcinfo)
if (my_extra->element_type != element_type)
{
- get_typlenbyvalalign(element_type,
- &my_extra->typlen,
- &my_extra->typbyval,
- &my_extra->typalign);
+ get_type_stores(element_type,
+ &my_extra->typlen,
+ &my_extra->typbyval,
+ &my_extra->typalign,
+ &my_extra->typstorage);
typentry = lookup_type_cache(element_type, TYPECACHE_EQ_OPR_FINFO);
@@ -1464,10 +1473,12 @@ array_positions(PG_FUNCTION_ARGS)
if (my_extra->element_type != element_type)
{
- get_typlenbyvalalign(element_type,
- &my_extra->typlen,
- &my_extra->typbyval,
- &my_extra->typalign);
+ get_type_stores(element_type,
+ &my_extra->typlen,
+ &my_extra->typbyval,
+ &my_extra->typalign,
+ &my_extra->typstorage);
+
typentry = lookup_type_cache(element_type, TYPECACHE_EQ_OPR_FINFO);
@@ -1548,6 +1559,7 @@ array_shuffle_n(ArrayType *array, int n, bool keep_lb,
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
Datum *elms,
*ielms;
bool *nuls,
@@ -1560,12 +1572,13 @@ array_shuffle_n(ArrayType *array, int n, bool keep_lb,
elmlen = typentry->typlen;
elmbyval = typentry->typbyval;
elmalign = typentry->typalign;
+ elmstor = typentry->typstorage;
/* If the target array is empty, exit fast */
if (ndim < 1 || dims[0] < 1 || n < 1)
return construct_empty_array(elmtyp);
- deconstruct_array(array, elmtyp, elmlen, elmbyval, elmalign,
+ deconstruct_array(array, elmtyp, elmlen, elmbyval, elmalign, elmstor,
&elms, &nuls, &nelm);
nitem = dims[0]; /* total number of items */
@@ -1608,7 +1621,7 @@ array_shuffle_n(ArrayType *array, int n, bool keep_lb,
rlbs[0] = 1;
result = construct_md_array(elms, nuls, ndim, rdims, rlbs,
- elmtyp, elmlen, elmbyval, elmalign);
+ elmtyp, elmlen, elmbyval, elmalign, elmstor);
pfree(elms);
pfree(nuls);
@@ -1709,6 +1722,7 @@ array_reverse_n(ArrayType *array, Oid elmtyp, TypeCacheEntry *typentry)
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
Datum *elms,
*ielms;
bool *nuls,
@@ -1721,8 +1735,9 @@ array_reverse_n(ArrayType *array, Oid elmtyp, TypeCacheEntry *typentry)
elmlen = typentry->typlen;
elmbyval = typentry->typbyval;
elmalign = typentry->typalign;
+ elmstor = typentry->typstorage;
- deconstruct_array(array, elmtyp, elmlen, elmbyval, elmalign,
+ deconstruct_array(array, elmtyp, elmlen, elmbyval, elmalign, elmstor,
&elms, &nuls, &nelm);
nitem = dims[0]; /* total number of items */
@@ -1756,7 +1771,7 @@ array_reverse_n(ArrayType *array, Oid elmtyp, TypeCacheEntry *typentry)
rdims[0] = nitem;
result = construct_md_array(elms, nuls, ndim, rdims, rlbs,
- elmtyp, elmlen, elmbyval, elmalign);
+ elmtyp, elmlen, elmbyval, elmalign, elmstor);
pfree(elms);
pfree(nuls);
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 593775c27f3..f8dad59c27f 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -74,6 +74,7 @@ typedef struct ArrayIteratorData
int16 typlen; /* element type's length */
bool typbyval; /* element type's byval property */
char typalign; /* element type's align property */
+ char typstorage; /* element type's storage property */
/* information about the requested slice size */
int slice_ndim; /* slice dimension, or 0 if not slicing */
@@ -105,46 +106,51 @@ static ArrayToken ReadArrayToken(char **srcptr, StringInfo elembuf, char typdeli
const char *origStr, Node *escontext);
static void ReadArrayBinary(StringInfo buf, int nitems,
FmgrInfo *receiveproc, Oid typioparam, int32 typmod,
- int typlen, bool typbyval, char typalign,
+ int typlen, bool typbyval, char typalign, char typstor,
Datum *values, bool *nulls,
bool *hasnulls, int32 *nbytes);
static Datum array_get_element_expanded(Datum arraydatum,
int nSubscripts, int *indx,
int arraytyplen,
- int elmlen, bool elmbyval, char elmalign,
- bool *isNull);
+ int elmlen, bool elmbyval,
+ char elmalign, char typstor, bool *isNull);
static Datum array_set_element_expanded(Datum arraydatum,
int nSubscripts, int *indx,
Datum dataValue, bool isNull,
int arraytyplen,
- int elmlen, bool elmbyval, char elmalign);
+ int elmlen, bool elmbyval,
+ char elmalign, char typstor);
static bool array_get_isnull(const bits8 *nullbitmap, int offset);
static void array_set_isnull(bits8 *nullbitmap, int offset, bool isNull);
static Datum ArrayCast(char *value, bool byval, int len);
static int ArrayCastAndSet(Datum src,
- int typlen, bool typbyval, char typalign,
- char *dest);
+ int typlen, bool typbyval,
+ char typalign, char typstor, char *dest);
static char *array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems,
- int typlen, bool typbyval, char typalign);
+ int typlen, bool typbyval, char typalign, char typstor);
static int array_nelems_size(char *ptr, int offset, bits8 *nullbitmap,
- int nitems, int typlen, bool typbyval, char typalign);
+ int nitems, int typlen, bool typbyval,
+ char typalign, char typstor);
static int array_copy(char *destptr, int nitems,
char *srcptr, int offset, bits8 *nullbitmap,
- int typlen, bool typbyval, char typalign);
+ int typlen, bool typbyval, char typalign, char typstor);
static int array_slice_size(char *arraydataptr, bits8 *arraynullsptr,
int ndim, int *dim, int *lb,
int *st, int *endp,
- int typlen, bool typbyval, char typalign);
+ int typlen, bool typbyval,
+ char typalign, char typstor);
static void array_extract_slice(ArrayType *newarray,
int ndim, int *dim, int *lb,
char *arraydataptr, bits8 *arraynullsptr,
int *st, int *endp,
- int typlen, bool typbyval, char typalign);
+ int typlen, bool typbyval,
+ char typalign, char typstor);
static void array_insert_slice(ArrayType *destArray, ArrayType *origArray,
ArrayType *srcArray,
int ndim, int *dim, int *lb,
int *st, int *endp,
- int typlen, bool typbyval, char typalign);
+ int typlen, bool typbyval,
+ char typalign, char typstor);
static int array_cmp(FunctionCallInfo fcinfo);
static ArrayType *create_array_envelope(int ndims, int *dimv, int *lbsv, int nbytes,
Oid elmtype, int dataoffset);
@@ -187,6 +193,7 @@ array_in(PG_FUNCTION_ARGS)
bool typbyval;
char typalign;
char typdelim;
+ char typstor;
Oid typioparam;
char *p;
int nitems;
@@ -220,10 +227,7 @@ array_in(PG_FUNCTION_ARGS)
/*
* Get info about element type, including its input conversion proc
*/
- get_type_io_data(element_type, IOFunc_input,
- &my_extra->typlen, &my_extra->typbyval,
- &my_extra->typalign, &my_extra->typdelim,
- &my_extra->typioparam, &my_extra->typiofunc);
+ array_type_metadata(element_type, IOFunc_input, my_extra);
fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
fcinfo->flinfo->fn_mcxt);
my_extra->element_type = element_type;
@@ -231,6 +235,7 @@ array_in(PG_FUNCTION_ARGS)
typlen = my_extra->typlen;
typbyval = my_extra->typbyval;
typalign = my_extra->typalign;
+ typstor = my_extra->typstorage;
typdelim = my_extra->typdelim;
typioparam = my_extra->typioparam;
@@ -326,7 +331,7 @@ array_in(PG_FUNCTION_ARGS)
/* let's just make sure data is not toasted */
if (typlen == -1)
values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
- nbytes = att_addlength_datum(nbytes, typlen, values[i]);
+ nbytes = att_addvarsize_datum(nbytes, typlen, typstor, values[i]);
nbytes = att_align_nominal(nbytes, typalign);
/* check for overflow of total request */
if (!AllocSizeIsValid(nbytes))
@@ -366,7 +371,7 @@ array_in(PG_FUNCTION_ARGS)
CopyArrayEls(retval,
values, nulls, nitems,
- typlen, typbyval, typalign,
+ typlen, typbyval, typalign, typstor,
true);
pfree(values);
@@ -949,7 +954,7 @@ ending_error:
* values: array of Datums to be copied
* nulls: array of is-null flags (can be NULL if no nulls)
* nitems: number of Datums to be copied
- * typbyval, typlen, typalign: info about element datatype
+ * typbyval, typlen, typalign, typstor: info about element datatype
* freedata: if true and element type is pass-by-ref, pfree data values
* referenced by Datums after copying them.
*
@@ -965,6 +970,7 @@ CopyArrayEls(ArrayType *array,
int typlen,
bool typbyval,
char typalign,
+ char typstor,
bool freedata)
{
char *p = ARR_DATA_PTR(array);
@@ -987,7 +993,8 @@ CopyArrayEls(ArrayType *array,
else
{
bitval |= bitmask;
- p += ArrayCastAndSet(values[i], typlen, typbyval, typalign, p);
+ p += ArrayCastAndSet(values[i],
+ typlen, typbyval, typalign, typstor, p);
if (freedata)
pfree(DatumGetPointer(values[i]));
}
@@ -1065,10 +1072,7 @@ array_out(PG_FUNCTION_ARGS)
/*
* Get info about element type, including its output conversion proc
*/
- get_type_io_data(element_type, IOFunc_output,
- &my_extra->typlen, &my_extra->typbyval,
- &my_extra->typalign, &my_extra->typdelim,
- &my_extra->typioparam, &my_extra->typiofunc);
+ array_type_metadata(element_type, IOFunc_output, my_extra);
fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
fcinfo->flinfo->fn_mcxt);
my_extra->element_type = element_type;
@@ -1278,6 +1282,7 @@ array_recv(PG_FUNCTION_ARGS)
int typlen;
bool typbyval;
char typalign;
+ char typstor;
Oid typioparam;
int i,
nitems;
@@ -1368,10 +1373,7 @@ array_recv(PG_FUNCTION_ARGS)
if (my_extra->element_type != element_type)
{
/* Get info about element type, including its receive proc */
- get_type_io_data(element_type, IOFunc_receive,
- &my_extra->typlen, &my_extra->typbyval,
- &my_extra->typalign, &my_extra->typdelim,
- &my_extra->typioparam, &my_extra->typiofunc);
+ array_type_metadata(element_type, IOFunc_receive, my_extra);
if (!OidIsValid(my_extra->typiofunc))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
@@ -1391,13 +1393,14 @@ array_recv(PG_FUNCTION_ARGS)
typlen = my_extra->typlen;
typbyval = my_extra->typbyval;
typalign = my_extra->typalign;
+ typstor = my_extra->typstorage;
typioparam = my_extra->typioparam;
dataPtr = (Datum *) palloc(nitems * sizeof(Datum));
nullsPtr = (bool *) palloc(nitems * sizeof(bool));
ReadArrayBinary(buf, nitems,
&my_extra->proc, typioparam, typmod,
- typlen, typbyval, typalign,
+ typlen, typbyval, typalign, typstor,
dataPtr, nullsPtr,
&hasnulls, &nbytes);
if (hasnulls)
@@ -1420,7 +1423,7 @@ array_recv(PG_FUNCTION_ARGS)
CopyArrayEls(retval,
dataPtr, nullsPtr, nitems,
- typlen, typbyval, typalign,
+ typlen, typbyval, typalign, typstor,
true);
pfree(dataPtr);
@@ -1438,7 +1441,7 @@ array_recv(PG_FUNCTION_ARGS)
* nitems: total number of array elements (already read).
* receiveproc: type-specific receive procedure for element datatype.
* typioparam, typmod: auxiliary values to pass to receiveproc.
- * typlen, typbyval, typalign: storage parameters of element datatype.
+ * typlen, typbyval, typalign, typstor: storage parameters of element datatype.
*
* Outputs:
* values[]: filled with converted data values.
@@ -1459,6 +1462,7 @@ ReadArrayBinary(StringInfo buf,
int typlen,
bool typbyval,
char typalign,
+ char typstor,
Datum *values,
bool *nulls,
bool *hasnulls,
@@ -1524,7 +1528,7 @@ ReadArrayBinary(StringInfo buf,
/* let's just make sure data is not toasted */
if (typlen == -1)
values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
- totbytes = att_addlength_datum(totbytes, typlen, values[i]);
+ totbytes = att_addvarsize_datum(totbytes, typlen, typstor, values[i]);
totbytes = att_align_nominal(totbytes, typalign);
/* check for overflow of total request */
if (!AllocSizeIsValid(totbytes))
@@ -1578,10 +1582,7 @@ array_send(PG_FUNCTION_ARGS)
if (my_extra->element_type != element_type)
{
/* Get info about element type, including its send proc */
- get_type_io_data(element_type, IOFunc_send,
- &my_extra->typlen, &my_extra->typbyval,
- &my_extra->typalign, &my_extra->typdelim,
- &my_extra->typioparam, &my_extra->typiofunc);
+ array_type_metadata(element_type, IOFunc_send, my_extra);
if (!OidIsValid(my_extra->typiofunc))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
@@ -1811,6 +1812,7 @@ array_cardinality(PG_FUNCTION_ARGS)
* elmlen: pg_type.typlen for the array's element type
* elmbyval: pg_type.typbyval for the array's element type
* elmalign: pg_type.typalign for the array's element type
+ * elmstor: pg_type.typstorage for the array's element type
*
* Outputs:
* The return value is the element Datum.
@@ -1824,6 +1826,7 @@ array_get_element(Datum arraydatum,
int elmlen,
bool elmbyval,
char elmalign,
+ char elmstor,
bool *isNull)
{
int i,
@@ -1860,6 +1863,7 @@ array_get_element(Datum arraydatum,
elmlen,
elmbyval,
elmalign,
+ elmstor,
isNull);
}
else
@@ -1910,7 +1914,7 @@ array_get_element(Datum arraydatum,
*/
*isNull = false;
retptr = array_seek(arraydataptr, 0, arraynullsptr, offset,
- elmlen, elmbyval, elmalign);
+ elmlen, elmbyval, elmalign, elmstor);
return ArrayCast(retptr, elmbyval, elmlen);
}
@@ -1921,7 +1925,8 @@ static Datum
array_get_element_expanded(Datum arraydatum,
int nSubscripts, int *indx,
int arraytyplen,
- int elmlen, bool elmbyval, char elmalign,
+ int elmlen, bool elmbyval,
+ char elmalign, char typstor,
bool *isNull)
{
ExpandedArrayHeader *eah;
@@ -1941,6 +1946,7 @@ array_get_element_expanded(Datum arraydatum,
Assert(elmlen == eah->typlen);
Assert(elmbyval == eah->typbyval);
Assert(elmalign == eah->typalign);
+ Assert(typstor == eah->typstorage);
ndim = eah->ndims;
dim = eah->dims;
@@ -2015,6 +2021,7 @@ array_get_element_expanded(Datum arraydatum,
* elmlen: pg_type.typlen for the array's element type
* elmbyval: pg_type.typbyval for the array's element type
* elmalign: pg_type.typalign for the array's element type
+ * elmstor: pg_type.typstorage for the array's element type
*
* Outputs:
* The return value is the new array Datum (it's never NULL)
@@ -2036,7 +2043,8 @@ array_get_slice(Datum arraydatum,
int arraytyplen,
int elmlen,
bool elmbyval,
- char elmalign)
+ char elmalign,
+ char elmstor)
{
ArrayType *array;
ArrayType *newarray;
@@ -2124,7 +2132,7 @@ array_get_slice(Datum arraydatum,
bytes = array_slice_size(arraydataptr, arraynullsptr,
ndim, dim, lb,
lowerIndx, upperIndx,
- elmlen, elmbyval, elmalign);
+ elmlen, elmbyval, elmalign, elmstor);
/*
* Currently, we put a null bitmap in the result if the source has one;
@@ -2160,7 +2168,7 @@ array_get_slice(Datum arraydatum,
ndim, dim, lb,
arraydataptr, arraynullsptr,
lowerIndx, upperIndx,
- elmlen, elmbyval, elmalign);
+ elmlen, elmbyval, elmalign, elmstor);
return PointerGetDatum(newarray);
}
@@ -2182,6 +2190,7 @@ array_get_slice(Datum arraydatum,
* elmlen: pg_type.typlen for the array's element type
* elmbyval: pg_type.typbyval for the array's element type
* elmalign: pg_type.typalign for the array's element type
+ * elmstor: pg_type.typstorage for the array's element type
*
* Result:
* A new array is returned, just like the old except for the one
@@ -2206,7 +2215,8 @@ array_set_element(Datum arraydatum,
int arraytyplen,
int elmlen,
bool elmbyval,
- char elmalign)
+ char elmalign,
+ char elmstor)
{
ArrayType *array;
ArrayType *newarray;
@@ -2257,7 +2267,7 @@ array_set_element(Datum arraydatum,
resultarray = (char *) palloc(arraytyplen);
memcpy(resultarray, DatumGetPointer(arraydatum), arraytyplen);
elt_ptr = (char *) resultarray + indx[0] * elmlen;
- ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, elt_ptr);
+ ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, elmstor, elt_ptr);
return PointerGetDatum(resultarray);
}
@@ -2281,7 +2291,8 @@ array_set_element(Datum arraydatum,
arraytyplen,
elmlen,
elmbyval,
- elmalign);
+ elmalign,
+ elmstor);
}
/* detoast input array if necessary */
@@ -2307,7 +2318,8 @@ array_set_element(Datum arraydatum,
return PointerGetDatum(construct_md_array(&dataValue, &isNull,
nSubscripts, dim, lb,
elmtype,
- elmlen, elmbyval, elmalign));
+ elmlen, elmbyval,
+ elmalign, elmstor));
}
if (ndim != nSubscripts)
@@ -2408,13 +2420,13 @@ array_set_element(Datum arraydatum,
{
offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
elt_ptr = array_seek(ARR_DATA_PTR(array), 0, oldnullbitmap, offset,
- elmlen, elmbyval, elmalign);
+ elmlen, elmbyval, elmalign, elmstor);
lenbefore = (int) (elt_ptr - ARR_DATA_PTR(array));
if (array_get_isnull(oldnullbitmap, offset))
olditemlen = 0;
else
{
- olditemlen = att_addlength_pointer(0, elmlen, elt_ptr);
+ olditemlen = att_addvarsize_pointer(0, elmlen, elmstor, elt_ptr);
olditemlen = att_align_nominal(olditemlen, elmalign);
}
lenafter = (int) (olddatasize - lenbefore - olditemlen);
@@ -2424,7 +2436,7 @@ array_set_element(Datum arraydatum,
newitemlen = 0;
else
{
- newitemlen = att_addlength_datum(0, elmlen, dataValue);
+ newitemlen = att_addvarsize_datum(0, elmlen, elmstor, dataValue);
newitemlen = att_align_nominal(newitemlen, elmalign);
}
@@ -2448,7 +2460,7 @@ array_set_element(Datum arraydatum,
(char *) array + oldoverheadlen,
lenbefore);
if (!isNull)
- ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign,
+ ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, elmstor,
(char *) newarray + overheadlen + lenbefore);
memcpy((char *) newarray + overheadlen + lenbefore + newitemlen,
(char *) array + oldoverheadlen + lenbefore + olditemlen,
@@ -2502,7 +2514,8 @@ array_set_element_expanded(Datum arraydatum,
int nSubscripts, int *indx,
Datum dataValue, bool isNull,
int arraytyplen,
- int elmlen, bool elmbyval, char elmalign)
+ int elmlen, bool elmbyval,
+ char elmalign, char typstor)
{
ExpandedArrayHeader *eah;
Datum *dvalues;
@@ -2526,6 +2539,7 @@ array_set_element_expanded(Datum arraydatum,
Assert(elmlen == eah->typlen);
Assert(elmbyval == eah->typbyval);
Assert(elmalign == eah->typalign);
+ Assert(typstor == eah->typstorage);
/*
* Copy dimension info into local storage. This allows us to modify the
@@ -2782,6 +2796,7 @@ array_set_element_expanded(Datum arraydatum,
* elmlen: pg_type.typlen for the array's element type
* elmbyval: pg_type.typbyval for the array's element type
* elmalign: pg_type.typalign for the array's element type
+ * elmstor: pg_type.typstorage for the array's element type
*
* Result:
* A new array is returned, just like the old except for the
@@ -2814,7 +2829,8 @@ array_set_slice(Datum arraydatum,
int arraytyplen,
int elmlen,
bool elmbyval,
- char elmalign)
+ char elmalign,
+ char elmstor)
{
ArrayType *array;
ArrayType *srcArray;
@@ -2875,7 +2891,7 @@ array_set_slice(Datum arraydatum,
int nelems;
Oid elmtype = ARR_ELEMTYPE(array);
- deconstruct_array(srcArray, elmtype, elmlen, elmbyval, elmalign,
+ deconstruct_array(srcArray, elmtype, elmlen, elmbyval, elmalign, elmstor,
&dvalues, &dnulls, &nelems);
for (i = 0; i < nSubscripts; i++)
@@ -2906,7 +2922,8 @@ array_set_slice(Datum arraydatum,
return PointerGetDatum(construct_md_array(dvalues, dnulls, nSubscripts,
dim, lb, elmtype,
- elmlen, elmbyval, elmalign));
+ elmlen, elmbyval,
+ elmalign, elmstor));
}
if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)
@@ -3026,7 +3043,7 @@ array_set_slice(Datum arraydatum,
overheadlen = ARR_OVERHEAD_NONULLS(ndim);
newitemsize = array_nelems_size(ARR_DATA_PTR(srcArray), 0,
ARR_NULLBITMAP(srcArray), nsrcitems,
- elmlen, elmbyval, elmalign);
+ elmlen, elmbyval, elmalign, elmstor);
oldoverheadlen = ARR_DATA_OFFSET(array);
olddatasize = ARR_SIZE(array) - oldoverheadlen;
if (ndim > 1)
@@ -3039,7 +3056,7 @@ array_set_slice(Datum arraydatum,
ARR_NULLBITMAP(array),
ndim, dim, lb,
lowerIndx, upperIndx,
- elmlen, elmbyval, elmalign);
+ elmlen, elmbyval, elmalign, elmstor);
lenbefore = lenafter = 0; /* keep compiler quiet */
itemsbefore = itemsafter = nolditems = 0;
}
@@ -3060,7 +3077,7 @@ array_set_slice(Datum arraydatum,
itemsbefore = Min(slicelb, oldub + 1) - oldlb;
lenbefore = array_nelems_size(oldarraydata, 0, oldarraybitmap,
itemsbefore,
- elmlen, elmbyval, elmalign);
+ elmlen, elmbyval, elmalign, elmstor);
/* count/size of old array entries that will be replaced by slice */
if (slicelb > sliceub)
{
@@ -3073,7 +3090,7 @@ array_set_slice(Datum arraydatum,
olditemsize = array_nelems_size(oldarraydata + lenbefore,
itemsbefore, oldarraybitmap,
nolditems,
- elmlen, elmbyval, elmalign);
+ elmlen, elmbyval, elmalign, elmstor);
}
/* count/size of old array entries that will go after the slice */
itemsafter = oldub + 1 - Max(sliceub + 1, oldlb);
@@ -3099,7 +3116,7 @@ array_set_slice(Datum arraydatum,
array_insert_slice(newarray, array, srcArray,
ndim, dim, lb,
lowerIndx, upperIndx,
- elmlen, elmbyval, elmalign);
+ elmlen, elmbyval, elmalign, elmstor);
}
else
{
@@ -3144,11 +3161,11 @@ array_set_slice(Datum arraydatum,
*/
Datum
array_ref(ArrayType *array, int nSubscripts, int *indx,
- int arraytyplen, int elmlen, bool elmbyval, char elmalign,
- bool *isNull)
+ int arraytyplen, int elmlen, bool elmbyval,
+ char elmalign, char elmstor, bool *isNull)
{
return array_get_element(PointerGetDatum(array), nSubscripts, indx,
- arraytyplen, elmlen, elmbyval, elmalign,
+ arraytyplen, elmlen, elmbyval, elmalign, elmstor,
isNull);
}
@@ -3161,14 +3178,15 @@ array_ref(ArrayType *array, int nSubscripts, int *indx,
*/
ArrayType *
array_set(ArrayType *array, int nSubscripts, int *indx,
- Datum dataValue, bool isNull,
- int arraytyplen, int elmlen, bool elmbyval, char elmalign)
+ Datum dataValue, bool isNull, int arraytyplen,
+ int elmlen, bool elmbyval, char elmalign, char elmstor)
{
return DatumGetArrayTypeP(array_set_element(PointerGetDatum(array),
nSubscripts, indx,
dataValue, isNull,
arraytyplen,
- elmlen, elmbyval, elmalign));
+ elmlen, elmbyval,
+ elmalign, elmstor));
}
/*
@@ -3220,6 +3238,7 @@ array_map(Datum arrayd,
int typlen;
bool typbyval;
char typalign;
+ char typstor;
array_iter iter;
ArrayMetaState *inp_extra;
ArrayMetaState *ret_extra;
@@ -3260,15 +3279,17 @@ array_map(Datum arrayd,
if (ret_extra->element_type != retType)
{
- get_typlenbyvalalign(retType,
- &ret_extra->typlen,
- &ret_extra->typbyval,
- &ret_extra->typalign);
+ get_type_stores(retType,
+ &ret_extra->typlen,
+ &ret_extra->typbyval,
+ &ret_extra->typalign,
+ &ret_extra->typstorage);
ret_extra->element_type = retType;
}
typlen = ret_extra->typlen;
typbyval = ret_extra->typbyval;
typalign = ret_extra->typalign;
+ typstor = ret_extra->typstorage;
/* Allocate temporary arrays for new values */
values = (Datum *) palloc(nitems * sizeof(Datum));
@@ -3296,7 +3317,7 @@ array_map(Datum arrayd,
if (typlen == -1)
values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
/* Update total result size */
- nbytes = att_addlength_datum(nbytes, typlen, values[i]);
+ nbytes = att_addvarsize_datum(nbytes, typlen, typstor, values[i]);
nbytes = att_align_nominal(nbytes, typalign);
/* check for overflow of total request */
if (!AllocSizeIsValid(nbytes))
@@ -3328,7 +3349,7 @@ array_map(Datum arrayd,
CopyArrayEls(result,
values, nulls, nitems,
- typlen, typbyval, typalign,
+ typlen, typbyval, typalign, typstor,
false);
/*
@@ -3346,7 +3367,8 @@ array_map(Datum arrayd,
* elems: array of Datum items to become the array contents
* (NULL element values are not supported).
* nelems: number of items
- * elmtype, elmlen, elmbyval, elmalign: info for the datatype of the items
+ * elmtype, elmlen, elmbyval, elmalign, elmstor:
+ * info for the datatype of the items
*
* A palloc'd 1-D array object is constructed and returned. Note that
* elem values will be copied into the object even if pass-by-ref type.
@@ -3360,7 +3382,7 @@ array_map(Datum arrayd,
ArrayType *
construct_array(Datum *elems, int nelems,
Oid elmtype,
- int elmlen, bool elmbyval, char elmalign)
+ int elmlen, bool elmbyval, char elmalign, char elmstor)
{
int dims[1];
int lbs[1];
@@ -3369,13 +3391,13 @@ construct_array(Datum *elems, int nelems,
lbs[0] = 1;
return construct_md_array(elems, NULL, 1, dims, lbs,
- elmtype, elmlen, elmbyval, elmalign);
+ elmtype, elmlen, elmbyval, elmalign, elmstor);
}
/*
* Like construct_array(), where elmtype must be a built-in type, and
- * elmlen/elmbyval/elmalign is looked up from hardcoded data. This is often
- * useful when manipulating arrays from/for system catalogs.
+ * elmlen/elmbyval/elmalign/elmstor is looked up from hardcoded data.
+ * This is often useful when manipulating arrays from/for system catalogs.
*/
ArrayType *
construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
@@ -3383,6 +3405,7 @@ construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
int elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
switch (elmtype)
{
@@ -3390,48 +3413,56 @@ construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
elmlen = 1;
elmbyval = true;
elmalign = TYPALIGN_CHAR;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case CSTRINGOID:
elmlen = -2;
elmbyval = false;
elmalign = TYPALIGN_CHAR;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case FLOAT4OID:
elmlen = sizeof(float4);
elmbyval = true;
elmalign = TYPALIGN_INT;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case FLOAT8OID:
elmlen = sizeof(float8);
elmbyval = FLOAT8PASSBYVAL;
elmalign = TYPALIGN_DOUBLE;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case INT2OID:
elmlen = sizeof(int16);
elmbyval = true;
elmalign = TYPALIGN_SHORT;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case INT4OID:
elmlen = sizeof(int32);
elmbyval = true;
elmalign = TYPALIGN_INT;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case INT8OID:
elmlen = sizeof(int64);
elmbyval = FLOAT8PASSBYVAL;
elmalign = TYPALIGN_DOUBLE;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case NAMEOID:
elmlen = NAMEDATALEN;
elmbyval = false;
elmalign = TYPALIGN_CHAR;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case OIDOID:
@@ -3439,24 +3470,28 @@ construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
elmlen = sizeof(Oid);
elmbyval = true;
elmalign = TYPALIGN_INT;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case TEXTOID:
elmlen = -1;
elmbyval = false;
elmalign = TYPALIGN_INT;
+ elmstor = TYPSTORAGE_EXTENDED;
break;
case TIDOID:
elmlen = sizeof(ItemPointerData);
elmbyval = false;
elmalign = TYPALIGN_SHORT;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case XIDOID:
elmlen = sizeof(TransactionId);
elmbyval = true;
elmalign = TYPALIGN_INT;
+ elmstor = TYPSTORAGE_PLAIN;
break;
default:
@@ -3465,9 +3500,11 @@ construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
elmlen = 0;
elmbyval = false;
elmalign = 0;
+ elmstor = 0;
}
- return construct_array(elems, nelems, elmtype, elmlen, elmbyval, elmalign);
+ return construct_array(elems, nelems, elmtype, elmlen, elmbyval,
+ elmalign, elmstor);
}
/*
@@ -3479,7 +3516,8 @@ construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
* ndims: number of dimensions
* dims: integer array with size of each dimension
* lbs: integer array with lower bound of each dimension
- * elmtype, elmlen, elmbyval, elmalign: info for the datatype of the items
+ * elmtype, elmlen, elmbyval, elmalign, elmstor:
+ * info for the datatype of the items
*
* A palloc'd ndims-D array object is constructed and returned. Note that
* elem values will be copied into the object even if pass-by-ref type.
@@ -3496,7 +3534,8 @@ construct_md_array(Datum *elems,
int ndims,
int *dims,
int *lbs,
- Oid elmtype, int elmlen, bool elmbyval, char elmalign)
+ Oid elmtype, int elmlen, bool elmbyval,
+ char elmalign, char elmstor)
{
ArrayType *result;
bool hasnulls;
@@ -3536,7 +3575,7 @@ construct_md_array(Datum *elems,
/* make sure data is not toasted */
if (elmlen == -1)
elems[i] = PointerGetDatum(PG_DETOAST_DATUM(elems[i]));
- nbytes = att_addlength_datum(nbytes, elmlen, elems[i]);
+ nbytes = att_addvarsize_datum(nbytes, elmlen, elmstor, elems[i]);
nbytes = att_align_nominal(nbytes, elmalign);
/* check for overflow of total request */
if (!AllocSizeIsValid(nbytes))
@@ -3567,7 +3606,7 @@ construct_md_array(Datum *elems,
CopyArrayEls(result,
elems, nulls, nelems,
- elmlen, elmbyval, elmalign,
+ elmlen, elmbyval, elmalign, elmstor,
false);
return result;
@@ -3610,7 +3649,8 @@ construct_empty_expanded_array(Oid element_type,
* deconstruct_array --- simple method for extracting data from an array
*
* array: array object to examine (must not be NULL)
- * elmtype, elmlen, elmbyval, elmalign: info for the datatype of the items
+ * elmtype, elmlen, elmbyval, elmalign, elmstor:
+ * info for the datatype of the items
* elemsp: return value, set to point to palloc'd array of Datum values
* nullsp: return value, set to point to palloc'd array of isnull markers
* nelemsp: return value, set to number of extracted values
@@ -3622,15 +3662,15 @@ construct_empty_expanded_array(Oid element_type,
* If array elements are pass-by-ref data type, the returned Datums will
* be pointers into the array object.
*
- * NOTE: it would be cleaner to look up the elmlen/elmbval/elmalign info
- * from the system catalogs, given the elmtype. However, the caller is
+ * NOTE: it would be cleaner to look up the elmlen/elmbval/elmalign/elmstor
+ * info from the system catalogs, given the elmtype. However, the caller is
* in a better position to cache this info across multiple uses, or even
* to hard-wire values if the element type is hard-wired.
*/
void
deconstruct_array(ArrayType *array,
Oid elmtype,
- int elmlen, bool elmbyval, char elmalign,
+ int elmlen, bool elmbyval, char elmalign, char elmstor,
Datum **elemsp, bool **nullsp, int *nelemsp)
{
Datum *elems;
@@ -3701,6 +3741,7 @@ deconstruct_array_builtin(ArrayType *array,
int elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
switch (elmtype)
{
@@ -3708,42 +3749,49 @@ deconstruct_array_builtin(ArrayType *array,
elmlen = 1;
elmbyval = true;
elmalign = TYPALIGN_CHAR;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case CSTRINGOID:
elmlen = -2;
elmbyval = false;
elmalign = TYPALIGN_CHAR;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case FLOAT8OID:
elmlen = sizeof(float8);
elmbyval = FLOAT8PASSBYVAL;
elmalign = TYPALIGN_DOUBLE;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case INT2OID:
elmlen = sizeof(int16);
elmbyval = true;
elmalign = TYPALIGN_SHORT;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case OIDOID:
elmlen = sizeof(Oid);
elmbyval = true;
elmalign = TYPALIGN_INT;
+ elmstor = TYPSTORAGE_PLAIN;
break;
case TEXTOID:
elmlen = -1;
elmbyval = false;
elmalign = TYPALIGN_INT;
+ elmstor = TYPSTORAGE_EXTENDED;
break;
case TIDOID:
elmlen = sizeof(ItemPointerData);
elmbyval = false;
elmalign = TYPALIGN_SHORT;
+ elmstor = TYPSTORAGE_PLAIN;
break;
default:
@@ -3752,9 +3800,11 @@ deconstruct_array_builtin(ArrayType *array,
elmlen = 0;
elmbyval = false;
elmalign = 0;
+ elmstor = 0;
}
- deconstruct_array(array, elmtype, elmlen, elmbyval, elmalign, elemsp, nullsp, nelemsp);
+ deconstruct_array(array, elmtype, elmlen, elmbyval, elmalign, elmstor,
+ elemsp, nullsp, nelemsp);
}
/*
@@ -4215,6 +4265,7 @@ hash_array(PG_FUNCTION_ARGS)
record_typentry->typlen = typentry->typlen;
record_typentry->typbyval = typentry->typbyval;
record_typentry->typalign = typentry->typalign;
+ record_typentry->typstorage = typentry->typstorage;
fmgr_info(F_HASH_RECORD, &record_typentry->hash_proc_finfo);
MemoryContextSwitchTo(oldcontext);
@@ -4392,6 +4443,7 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation,
int typlen;
bool typbyval;
char typalign;
+ char typstor;
int i;
int j;
array_iter it1;
@@ -4423,6 +4475,7 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation,
typlen = typentry->typlen;
typbyval = typentry->typbyval;
typalign = typentry->typalign;
+ typstor = typentry->typstorage;
/*
* Since we probably will need to scan array2 multiple times, it's
@@ -4439,7 +4492,7 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation,
}
else
deconstruct_array((ArrayType *) array2,
- element_type, typlen, typbyval, typalign,
+ element_type, typlen, typbyval, typalign, typstor,
&values2, &nulls2, &nelems2);
/*
@@ -4619,12 +4672,14 @@ array_create_iterator(ArrayType *arr, int slice_ndim, ArrayMetaState *mstate)
iterator->typlen = mstate->typlen;
iterator->typbyval = mstate->typbyval;
iterator->typalign = mstate->typalign;
+ iterator->typstorage = mstate->typstorage;
}
else
- get_typlenbyvalalign(ARR_ELEMTYPE(arr),
- &iterator->typlen,
- &iterator->typbyval,
- &iterator->typalign);
+ get_type_stores(ARR_ELEMTYPE(arr),
+ &iterator->typlen,
+ &iterator->typbyval,
+ &iterator->typalign,
+ &iterator->typstorage);
/*
* Remember the slicing parameters.
@@ -4743,7 +4798,8 @@ array_iterate(ArrayIterator iterator, Datum *value, bool *isnull)
ARR_ELEMTYPE(iterator->arr),
iterator->typlen,
iterator->typbyval,
- iterator->typalign);
+ iterator->typalign,
+ iterator->typstorage);
*isnull = false;
*value = PointerGetDatum(result);
@@ -4828,6 +4884,7 @@ ArrayCastAndSet(Datum src,
int typlen,
bool typbyval,
char typalign,
+ char typstor,
char *dest)
{
int inc;
@@ -4840,6 +4897,14 @@ ArrayCastAndSet(Datum src,
memmove(dest, DatumGetPointer(src), typlen);
inc = att_align_nominal(typlen, typalign);
}
+ else if (TYPE_IS_PACKABLE(typlen, typstor) && VARATT_CAN_MAKE_SHORT(src))
+ {
+ Assert(!typbyval);
+ inc = VARATT_CONVERTED_SHORT_SIZE(src);
+ SET_VARSIZE_SHORT(dest, inc);
+ memcpy(dest + 1, VARDATA(DatumGetPointer(src)), inc - 1);
+ inc = att_align_nominal(inc, typalign);
+ }
else
{
Assert(!typbyval);
@@ -4858,13 +4923,14 @@ ArrayCastAndSet(Datum src,
* offset: 0-based linear element number of first element (the one at *ptr)
* nullbitmap: start of array's null bitmap, or NULL if none
* nitems: number of array elements to advance over (>= 0)
- * typlen, typbyval, typalign: storage parameters of array element datatype
+ * typlen, typbyval, typalign, typstor:
+ * storage parameters of array element datatype
*
* It is caller's responsibility to ensure that nitems is within range
*/
static char *
array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems,
- int typlen, bool typbyval, char typalign)
+ int typlen, bool typbyval, char typalign, char typstor)
{
int bitmask;
int i;
@@ -4883,7 +4949,7 @@ array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems,
{
if (*nullbitmap & bitmask)
{
- ptr = att_addlength_pointer(ptr, typlen, ptr);
+ ptr = att_addvarsize_pointer(ptr, typlen, typstor, ptr);
ptr = (char *) att_align_nominal(ptr, typalign);
}
bitmask <<= 1;
@@ -4898,7 +4964,7 @@ array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems,
{
for (i = 0; i < nitems; i++)
{
- ptr = att_addlength_pointer(ptr, typlen, ptr);
+ ptr = att_addvarsize_pointer(ptr, typlen, typstor, ptr);
ptr = (char *) att_align_nominal(ptr, typalign);
}
}
@@ -4912,10 +4978,10 @@ array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems,
*/
static int
array_nelems_size(char *ptr, int offset, bits8 *nullbitmap, int nitems,
- int typlen, bool typbyval, char typalign)
+ int typlen, bool typbyval, char typalign, char typstor)
{
return array_seek(ptr, offset, nullbitmap, nitems,
- typlen, typbyval, typalign) - ptr;
+ typlen, typbyval, typalign, typstor) - ptr;
}
/*
@@ -4926,7 +4992,8 @@ array_nelems_size(char *ptr, int offset, bits8 *nullbitmap, int nitems,
* srcptr: starting location in source array
* offset: 0-based linear element number of first element (the one at *srcptr)
* nullbitmap: start of source array's null bitmap, or NULL if none
- * typlen, typbyval, typalign: storage parameters of array element datatype
+ * typlen, typbyval, typalign, typstor:
+ * storage parameters of array element datatype
*
* Returns number of bytes copied
*
@@ -4935,12 +5002,12 @@ array_nelems_size(char *ptr, int offset, bits8 *nullbitmap, int nitems,
static int
array_copy(char *destptr, int nitems,
char *srcptr, int offset, bits8 *nullbitmap,
- int typlen, bool typbyval, char typalign)
+ int typlen, bool typbyval, char typalign, char typstor)
{
int numbytes;
numbytes = array_nelems_size(srcptr, offset, nullbitmap, nitems,
- typlen, typbyval, typalign);
+ typlen, typbyval, typalign, typstor);
memcpy(destptr, srcptr, numbytes);
return numbytes;
}
@@ -5037,7 +5104,7 @@ static int
array_slice_size(char *arraydataptr, bits8 *arraynullsptr,
int ndim, int *dim, int *lb,
int *st, int *endp,
- int typlen, bool typbyval, char typalign)
+ int typlen, bool typbyval, char typalign, char typstor)
{
int src_offset,
span[MAXDIM],
@@ -5059,7 +5126,7 @@ array_slice_size(char *arraydataptr, bits8 *arraynullsptr,
/* Else gotta do it the hard way */
src_offset = ArrayGetOffset(ndim, dim, lb, st);
ptr = array_seek(arraydataptr, 0, arraynullsptr, src_offset,
- typlen, typbyval, typalign);
+ typlen, typbyval, typalign, typstor);
mda_get_prod(ndim, dim, prod);
mda_get_offset_values(ndim, dist, prod, span);
for (i = 0; i < ndim; i++)
@@ -5070,12 +5137,12 @@ array_slice_size(char *arraydataptr, bits8 *arraynullsptr,
if (dist[j])
{
ptr = array_seek(ptr, src_offset, arraynullsptr, dist[j],
- typlen, typbyval, typalign);
+ typlen, typbyval, typalign, typstor);
src_offset += dist[j];
}
if (!array_get_isnull(arraynullsptr, src_offset))
{
- inc = att_addlength_pointer(0, typlen, ptr);
+ inc = att_addvarsize_pointer(0, typlen, typstor, ptr);
inc = att_align_nominal(inc, typalign);
ptr += inc;
count += inc;
@@ -5104,7 +5171,8 @@ array_extract_slice(ArrayType *newarray,
int *endp,
int typlen,
bool typbyval,
- char typalign)
+ char typalign,
+ char typstor)
{
char *destdataptr = ARR_DATA_PTR(newarray);
bits8 *destnullsptr = ARR_NULLBITMAP(newarray);
@@ -5121,7 +5189,7 @@ array_extract_slice(ArrayType *newarray,
src_offset = ArrayGetOffset(ndim, dim, lb, st);
srcdataptr = array_seek(arraydataptr, 0, arraynullsptr, src_offset,
- typlen, typbyval, typalign);
+ typlen, typbyval, typalign, typstor);
mda_get_prod(ndim, dim, prod);
mda_get_range(ndim, span, st, endp);
mda_get_offset_values(ndim, dist, prod, span);
@@ -5136,12 +5204,12 @@ array_extract_slice(ArrayType *newarray,
/* skip unwanted elements */
srcdataptr = array_seek(srcdataptr, src_offset, arraynullsptr,
dist[j],
- typlen, typbyval, typalign);
+ typlen, typbyval, typalign, typstor);
src_offset += dist[j];
}
inc = array_copy(destdataptr, 1,
srcdataptr, src_offset, arraynullsptr,
- typlen, typbyval, typalign);
+ typlen, typbyval, typalign, typstor);
if (destnullsptr)
array_bitmap_copy(destnullsptr, dest_offset,
arraynullsptr, src_offset,
@@ -5177,7 +5245,8 @@ array_insert_slice(ArrayType *destArray,
int *endp,
int typlen,
bool typbyval,
- char typalign)
+ char typalign,
+ char typstor)
{
char *destPtr = ARR_DATA_PTR(destArray);
char *origPtr = ARR_DATA_PTR(origArray);
@@ -5202,7 +5271,7 @@ array_insert_slice(ArrayType *destArray,
/* copy items before the slice start */
inc = array_copy(destPtr, dest_offset,
origPtr, 0, origBitmap,
- typlen, typbyval, typalign);
+ typlen, typbyval, typalign, typstor);
destPtr += inc;
origPtr += inc;
if (destBitmap)
@@ -5222,7 +5291,7 @@ array_insert_slice(ArrayType *destArray,
{
inc = array_copy(destPtr, dist[j],
origPtr, orig_offset, origBitmap,
- typlen, typbyval, typalign);
+ typlen, typbyval, typalign, typstor);
destPtr += inc;
origPtr += inc;
if (destBitmap)
@@ -5235,7 +5304,7 @@ array_insert_slice(ArrayType *destArray,
/* Copy new element at this slice position */
inc = array_copy(destPtr, 1,
srcPtr, src_offset, srcBitmap,
- typlen, typbyval, typalign);
+ typlen, typbyval, typalign, typstor);
if (destBitmap)
array_bitmap_copy(destBitmap, dest_offset,
srcBitmap, src_offset,
@@ -5246,14 +5315,14 @@ array_insert_slice(ArrayType *destArray,
src_offset++;
/* Advance over old element at this slice position */
origPtr = array_seek(origPtr, orig_offset, origBitmap, 1,
- typlen, typbyval, typalign);
+ typlen, typbyval, typalign, typstor);
orig_offset++;
} while ((j = mda_next_tuple(ndim, indx, span)) != -1);
/* don't miss any data at the end */
array_copy(destPtr, orignitems - orig_offset,
origPtr, orig_offset, origBitmap,
- typlen, typbyval, typalign);
+ typlen, typbyval, typalign, typstor);
if (destBitmap)
array_bitmap_copy(destBitmap, dest_offset,
origBitmap, orig_offset,
@@ -5330,10 +5399,11 @@ initArrayResultWithSize(Oid element_type, MemoryContext rcontext,
MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
astate->nelems = 0;
astate->element_type = element_type;
- get_typlenbyvalalign(element_type,
- &astate->typlen,
- &astate->typbyval,
- &astate->typalign);
+ get_type_stores(element_type,
+ &astate->typlen,
+ &astate->typbyval,
+ &astate->typalign,
+ &astate->typstorage);
return astate;
}
@@ -5470,7 +5540,8 @@ makeMdArrayResult(ArrayBuildState *astate,
astate->element_type,
astate->typlen,
astate->typbyval,
- astate->typalign);
+ astate->typalign,
+ astate->typstorage);
MemoryContextSwitchTo(oldcontext);
@@ -6093,6 +6164,7 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs,
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
ArrayMetaState *my_extra;
/*
@@ -6177,16 +6249,18 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs,
if (my_extra->element_type != elmtype)
{
/* Get info about element type */
- get_typlenbyvalalign(elmtype,
- &my_extra->typlen,
- &my_extra->typbyval,
- &my_extra->typalign);
+ get_type_stores(elmtype,
+ &my_extra->typlen,
+ &my_extra->typbyval,
+ &my_extra->typalign,
+ &my_extra->typstorage);
my_extra->element_type = elmtype;
}
elmlen = my_extra->typlen;
elmbyval = my_extra->typbyval;
elmalign = my_extra->typalign;
+ elmstor = my_extra->typstorage;
/* compute required space */
if (!isnull)
@@ -6225,7 +6299,7 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs,
p = ARR_DATA_PTR(result);
for (i = 0; i < nitems; i++)
- p += ArrayCastAndSet(value, elmlen, elmbyval, elmalign, p);
+ p += ArrayCastAndSet(value, elmlen, elmbyval, elmalign, elmstor, p);
}
else
{
@@ -6398,6 +6472,7 @@ array_replace_internal(ArrayType *array,
int typlen;
bool typbyval;
char typalign;
+ char typstor;
char *arraydataptr;
bits8 *bitmap;
int bitmask;
@@ -6442,6 +6517,7 @@ array_replace_internal(ArrayType *array,
typlen = typentry->typlen;
typbyval = typentry->typbyval;
typalign = typentry->typalign;
+ typstor = typentry->typstorage;
/*
* Detoast values if they are toasted. The replacement value must be
@@ -6502,7 +6578,7 @@ array_replace_internal(ArrayType *array,
{
isNull = false;
elt = fetch_att(arraydataptr, typbyval, typlen);
- arraydataptr = att_addlength_datum(arraydataptr, typlen, elt);
+ arraydataptr = att_addvarsize_datum(arraydataptr, typlen, typstor, elt);
arraydataptr = (char *) att_align_nominal(arraydataptr, typalign);
if (search_isnull)
@@ -6549,7 +6625,7 @@ array_replace_internal(ArrayType *array,
else
{
/* Update total result size */
- nbytes = att_addlength_datum(nbytes, typlen, values[nresult]);
+ nbytes = att_addvarsize_datum(nbytes, typlen, typstor, values[nresult]);
nbytes = att_align_nominal(nbytes, typalign);
/* check for overflow of total request */
if (!AllocSizeIsValid(nbytes))
@@ -6619,7 +6695,7 @@ array_replace_internal(ArrayType *array,
/* Insert data into result array */
CopyArrayEls(result,
values, nulls, nresult,
- typlen, typbyval, typalign,
+ typlen, typbyval, typalign, typstor,
false);
pfree(values);
@@ -6925,6 +7001,7 @@ trim_array(PG_FUNCTION_ARGS)
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
int lower[MAXDIM];
int upper[MAXDIM];
bool lowerProvided[MAXDIM];
@@ -6948,12 +7025,12 @@ trim_array(PG_FUNCTION_ARGS)
}
/* Fetch the needed information about the element type */
- get_typlenbyvalalign(ARR_ELEMTYPE(v), &elmlen, &elmbyval, &elmalign);
+ get_type_stores(ARR_ELEMTYPE(v), &elmlen, &elmbyval, &elmalign, &elmstor);
/* Get the slice */
result = array_get_slice(PointerGetDatum(v), 1,
upper, lower, upperProvided, lowerProvided,
- -1, elmlen, elmbyval, elmalign);
+ -1, elmlen, elmbyval, elmalign, elmstor);
PG_RETURN_DATUM(result);
}
diff --git a/src/backend/utils/adt/arraysubs.c b/src/backend/utils/adt/arraysubs.c
index 6f68dfa5b23..1af83eff70a 100644
--- a/src/backend/utils/adt/arraysubs.c
+++ b/src/backend/utils/adt/arraysubs.c
@@ -34,6 +34,7 @@ typedef struct ArraySubWorkspace
int16 refelemlength; /* typlen of the array element type */
bool refelembyval; /* is the element type pass-by-value? */
char refelemalign; /* typalign of the element type */
+ char refelemstorage; /* typstorage of the element type */
/*
* Subscript values converted to integers. Note that these arrays must be
@@ -250,6 +251,7 @@ array_subscript_fetch(ExprState *state,
workspace->refelemlength,
workspace->refelembyval,
workspace->refelemalign,
+ workspace->refelemstorage,
op->resnull);
}
@@ -280,7 +282,8 @@ array_subscript_fetch_slice(ExprState *state,
workspace->refattrlength,
workspace->refelemlength,
workspace->refelembyval,
- workspace->refelemalign);
+ workspace->refelemalign,
+ workspace->refelemstorage);
/* The slice is never NULL, so no need to change *op->resnull */
}
@@ -330,7 +333,8 @@ array_subscript_assign(ExprState *state,
workspace->refattrlength,
workspace->refelemlength,
workspace->refelembyval,
- workspace->refelemalign);
+ workspace->refelemalign,
+ workspace->refelemstorage);
/* The result is never NULL, so no need to change *op->resnull */
}
@@ -383,7 +387,8 @@ array_subscript_assign_slice(ExprState *state,
workspace->refattrlength,
workspace->refelemlength,
workspace->refelembyval,
- workspace->refelemalign);
+ workspace->refelemalign,
+ workspace->refelemstorage);
/* The result is never NULL, so no need to change *op->resnull */
}
@@ -417,6 +422,7 @@ array_subscript_fetch_old(ExprState *state,
workspace->refelemlength,
workspace->refelembyval,
workspace->refelemalign,
+ workspace->refelemstorage,
&sbsrefstate->prevnull);
}
@@ -460,7 +466,8 @@ array_subscript_fetch_old_slice(ExprState *state,
workspace->refattrlength,
workspace->refelemlength,
workspace->refelembyval,
- workspace->refelemalign);
+ workspace->refelemalign,
+ workspace->refelemstorage);
/* slices of non-null arrays are never null */
sbsrefstate->prevnull = false;
}
@@ -504,10 +511,11 @@ array_exec_setup(const SubscriptingRef *sbsref,
*/
workspace->refelemtype = sbsref->refelemtype;
workspace->refattrlength = get_typlen(sbsref->refcontainertype);
- get_typlenbyvalalign(sbsref->refelemtype,
- &workspace->refelemlength,
- &workspace->refelembyval,
- &workspace->refelemalign);
+ get_type_stores(sbsref->refelemtype,
+ &workspace->refelemlength,
+ &workspace->refelembyval,
+ &workspace->refelemalign,
+ &workspace->refelemstorage);
/*
* Pass back pointers to appropriate step execution functions.
diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c
index d4c2aa0e7e9..4d74ac90117 100644
--- a/src/backend/utils/adt/enum.c
+++ b/src/backend/utils/adt/enum.c
@@ -608,7 +608,7 @@ enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
/* and build the result array */
/* note this hardwires some details about the representation of Oid */
result = construct_array(elems, cnt, enumtypoid,
- sizeof(Oid), true, TYPALIGN_INT);
+ sizeof(Oid), true, TYPALIGN_INT, TYPSTORAGE_PLAIN);
pfree(elems);
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 058aade2af4..ef473cec622 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -484,6 +484,7 @@ array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
int16 typlen;
bool typbyval;
char typalign;
+ char typstor;
JsonTypeCategory tcategory;
Oid outfuncoid;
@@ -497,14 +498,14 @@ array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
return;
}
- get_typlenbyvalalign(element_type,
- &typlen, &typbyval, &typalign);
+ get_type_stores(element_type,
+ &typlen, &typbyval, &typalign, &typstor);
json_categorize_type(element_type, false,
&tcategory, &outfuncoid);
deconstruct_array(v, element_type, typlen, typbyval,
- typalign, &elements, &nulls,
+ typalign, typstor, &elements, &nulls,
&nitems);
array_dim_to_json(result, 0, ndim, dim, elements, nulls, &count, tcategory,
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index d602df4eeb5..4ccf4400ea7 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -904,6 +904,7 @@ array_to_jsonb_internal(Datum array, JsonbInState *result)
int16 typlen;
bool typbyval;
char typalign;
+ char typstor;
JsonTypeCategory tcategory;
Oid outfuncoid;
@@ -918,14 +919,14 @@ array_to_jsonb_internal(Datum array, JsonbInState *result)
return;
}
- get_typlenbyvalalign(element_type,
- &typlen, &typbyval, &typalign);
+ get_type_stores(element_type,
+ &typlen, &typbyval, &typalign, &typstor);
json_categorize_type(element_type, true,
&tcategory, &outfuncoid);
deconstruct_array(v, element_type, typlen, typbyval,
- typalign, &elements, &nulls,
+ typalign, typstor, &elements, &nulls,
&nitems);
array_dim_to_jsonb(result, 0, ndim, dim, elements, nulls, &count, tcategory,
diff --git a/src/backend/utils/adt/multirangetypes.c b/src/backend/utils/adt/multirangetypes.c
index 35fd825babe..a28f9735606 100644
--- a/src/backend/utils/adt/multirangetypes.c
+++ b/src/backend/utils/adt/multirangetypes.c
@@ -996,7 +996,8 @@ multirange_constructor2(PG_FUNCTION_ARGS)
else
{
deconstruct_array(rangeArray, rngtypid, rangetyp->typlen, rangetyp->typbyval,
- rangetyp->typalign, &elements, &nulls, &range_count);
+ rangetyp->typalign, rangetyp->typstorage,
+ &elements, &nulls, &range_count);
ranges = palloc0(range_count * sizeof(RangeType *));
for (i = 0; i < range_count; i++)
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index b8bdc667dbc..da63a04af31 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -80,6 +80,7 @@ typedef struct OSAPerQueryState
int16 typLen;
bool typByVal;
char typAlign;
+ char typStorage;
/* Info about sort ordering: */
Oid sortOperator;
Oid eqOperator;
@@ -264,10 +265,11 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
qstate->sortNullsFirst = sortcl->nulls_first;
/* Save datatype info */
- get_typlenbyvalalign(qstate->sortColType,
- &qstate->typLen,
- &qstate->typByVal,
- &qstate->typAlign);
+ get_type_stores(qstate->sortColType,
+ &qstate->typLen,
+ &qstate->typByVal,
+ &qstate->typAlign,
+ &qstate->typStorage);
}
fcinfo->flinfo->fn_extra = qstate;
@@ -838,7 +840,8 @@ percentile_disc_multi_final(PG_FUNCTION_ARGS)
osastate->qstate->sortColType,
osastate->qstate->typLen,
osastate->qstate->typByVal,
- osastate->qstate->typAlign));
+ osastate->qstate->typAlign,
+ osastate->qstate->typStorage));
}
/*
@@ -847,7 +850,8 @@ percentile_disc_multi_final(PG_FUNCTION_ARGS)
static Datum
percentile_cont_multi_final_common(FunctionCallInfo fcinfo,
Oid expect_type,
- int16 typLen, bool typByVal, char typAlign,
+ int16 typLen, bool typByVal,
+ char typAlign, char typStor,
LerpFunc lerpfunc)
{
OSAPerGroupState *osastate;
@@ -994,7 +998,7 @@ percentile_cont_multi_final_common(FunctionCallInfo fcinfo,
expect_type,
typLen,
typByVal,
- typAlign));
+ typAlign, typStor));
}
/*
@@ -1009,6 +1013,7 @@ percentile_cont_float8_multi_final(PG_FUNCTION_ARGS)
sizeof(float8),
FLOAT8PASSBYVAL,
TYPALIGN_DOUBLE,
+ TYPSTORAGE_PLAIN,
float8_lerp);
}
@@ -1022,6 +1027,7 @@ percentile_cont_interval_multi_final(PG_FUNCTION_ARGS)
INTERVALOID,
/* hard-wired info on type interval */
16, false, TYPALIGN_DOUBLE,
+ TYPSTORAGE_PLAIN,
interval_lerp);
}
diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c
index dc714345222..80b0a240251 100644
--- a/src/backend/utils/adt/rangetypes.c
+++ b/src/backend/utils/adt/rangetypes.c
@@ -30,6 +30,7 @@
*/
#include "postgres.h"
+#include "catalog/pg_type.h"
#include "common/hashfn.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
@@ -2671,10 +2672,6 @@ range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum
* details.
*/
-/* Does datatype allow packing into the 1-byte-header varlena format? */
-#define TYPE_IS_PACKABLE(typlen, typstorage) \
- ((typlen) == -1 && (typstorage) != TYPSTORAGE_PLAIN)
-
/*
* Increment data_length by the space needed by the datum, including any
* preceding alignment padding.
diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c
index 42aec95738d..d6589bd24be 100644
--- a/src/backend/utils/adt/regexp.c
+++ b/src/backend/utils/adt/regexp.c
@@ -1664,7 +1664,8 @@ build_regexp_match_result(regexp_matches_ctx *matchctx)
lbs[0] = 1;
/* XXX: this hardcodes assumptions about the text type */
return construct_md_array(elems, nulls, 1, dims, lbs,
- TEXTOID, -1, false, TYPALIGN_INT);
+ TEXTOID, -1, false,
+ TYPALIGN_INT, TYPSTORAGE_EXTENDED);
}
/*
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index be1f1f50b78..15d769f55b9 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3055,6 +3055,7 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
-1 /* TEXT's typlen */ ,
false /* TEXT's typbyval */ ,
TYPALIGN_INT /* TEXT's typalign */ ,
+ TYPSTORAGE_EXTENDED /* TEXT's typalign */ ,
&isnull);
if (!isnull)
{
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 08fa6774d9c..48e6212354c 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -1926,6 +1926,7 @@ scalararraysel(PlannerInfo *root,
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
int num_elems;
Datum *elem_values;
bool *elem_nulls;
@@ -1934,11 +1935,11 @@ scalararraysel(PlannerInfo *root,
if (arrayisnull) /* qual can't succeed if null array */
return (Selectivity) 0.0;
arrayval = DatumGetArrayTypeP(arraydatum);
- get_typlenbyvalalign(ARR_ELEMTYPE(arrayval),
- &elmlen, &elmbyval, &elmalign);
+ get_type_stores(ARR_ELEMTYPE(arrayval),
+ &elmlen, &elmbyval, &elmalign, &elmstor);
deconstruct_array(arrayval,
ARR_ELEMTYPE(arrayval),
- elmlen, elmbyval, elmalign,
+ elmlen, elmbyval, elmalign, elmstor,
&elem_values, &elem_nulls, &num_elems);
/*
@@ -7488,6 +7489,7 @@ gincost_scalararrayopexpr(PlannerInfo *root,
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
int numElems;
Datum *elemValues;
bool *elemNulls;
@@ -7523,11 +7525,11 @@ gincost_scalararrayopexpr(PlannerInfo *root,
/* Otherwise, extract the array elements and iterate over them */
arrayval = DatumGetArrayTypeP(((Const *) rightop)->constvalue);
- get_typlenbyvalalign(ARR_ELEMTYPE(arrayval),
- &elmlen, &elmbyval, &elmalign);
+ get_type_stores(ARR_ELEMTYPE(arrayval),
+ &elmlen, &elmbyval, &elmalign, &elmstor);
deconstruct_array(arrayval,
ARR_ELEMTYPE(arrayval),
- elmlen, elmbyval, elmalign,
+ elmlen, elmbyval, elmalign, elmstor,
&elemValues, &elemNulls, &numElems);
memset(&arraycounts, 0, sizeof(arraycounts));
diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c
index f75e25388ca..6c4c6c30163 100644
--- a/src/backend/utils/adt/tsvector_op.c
+++ b/src/backend/utils/adt/tsvector_op.c
@@ -329,8 +329,8 @@ tsvector_setweight_by_filter(PG_FUNCTION_ARGS)
if (nulls[i])
continue;
- lex = VARDATA(dlexemes[i]);
- lex_len = VARSIZE(dlexemes[i]) - VARHDRSZ;
+ lex = VARDATA_ANY(dlexemes[i]);
+ lex_len = VARSIZE_ANY_EXHDR(dlexemes[i]);
lex_pos = tsvector_bsearch(tsout, lex, lex_len);
if (lex_pos >= 0 && (j = POSDATALEN(tsout, entry + lex_pos)) != 0)
@@ -605,8 +605,8 @@ tsvector_delete_arr(PG_FUNCTION_ARGS)
if (nulls[i])
continue;
- lex = VARDATA(dlexemes[i]);
- lex_len = VARSIZE(dlexemes[i]) - VARHDRSZ;
+ lex = VARDATA_ANY(dlexemes[i]);
+ lex_len = VARSIZE_ANY_EXHDR(dlexemes[i]);
lex_pos = tsvector_bsearch(tsin, lex, lex_len);
if (lex_pos >= 0)
@@ -770,7 +770,7 @@ array_to_tsvector(PG_FUNCTION_ARGS)
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("lexeme array may not contain nulls")));
- if (VARSIZE(dlexemes[i]) - VARHDRSZ == 0)
+ if (VARSIZE_ANY_EXHDR(dlexemes[i]) == 0)
ereport(ERROR,
(errcode(ERRCODE_ZERO_LENGTH_CHARACTER_STRING),
errmsg("lexeme array may not contain empty strings")));
@@ -786,7 +786,7 @@ array_to_tsvector(PG_FUNCTION_ARGS)
/* Calculate space needed for surviving lexemes. */
for (i = 0; i < nitems; i++)
- datalen += VARSIZE(dlexemes[i]) - VARHDRSZ;
+ datalen += VARSIZE_ANY_EXHDR(dlexemes[i]);
tslen = CALCDATASIZE(nitems, datalen);
/* Allocate and fill tsvector. */
@@ -798,8 +798,8 @@ array_to_tsvector(PG_FUNCTION_ARGS)
cur = STRPTR(tsout);
for (i = 0; i < nitems; i++)
{
- char *lex = VARDATA(dlexemes[i]);
- int lex_len = VARSIZE(dlexemes[i]) - VARHDRSZ;
+ char *lex = VARDATA_ANY(dlexemes[i]);
+ int lex_len = VARSIZE_ANY_EXHDR(dlexemes[i]);
memcpy(cur, lex, lex_len);
arrout[i].haspos = 0;
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 533bebc1c7b..4b43f934c2a 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -4867,10 +4867,7 @@ array_to_text_internal(FunctionCallInfo fcinfo, ArrayType *v,
/*
* Get info about element type, including its output conversion proc
*/
- get_type_io_data(element_type, IOFunc_output,
- &my_extra->typlen, &my_extra->typbyval,
- &my_extra->typalign, &my_extra->typdelim,
- &my_extra->typioparam, &my_extra->typiofunc);
+ array_type_metadata(element_type, IOFunc_output, my_extra);
fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
fcinfo->flinfo->fn_mcxt);
my_extra->element_type = element_type;
@@ -5678,6 +5675,7 @@ text_format(PG_FUNCTION_ARGS)
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
int nitems;
/* Should have just the one argument */
@@ -5702,12 +5700,12 @@ text_format(PG_FUNCTION_ARGS)
/* Get info about array element type */
element_type = ARR_ELEMTYPE(arr);
- get_typlenbyvalalign(element_type,
- &elmlen, &elmbyval, &elmalign);
+ get_type_stores(element_type,
+ &elmlen, &elmbyval, &elmalign, &elmstor);
/* Extract all array elements */
deconstruct_array(arr, element_type, elmlen, elmbyval, elmalign,
- &elements, &nulls, &nitems);
+ elmstor, &elements, &nulls, &nitems);
}
nargs = nitems + 1;
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 0898cb1be4c..fd28af187ad 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -2482,6 +2482,7 @@ map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
int16 elmlen;
bool elmbyval;
char elmalign;
+ char elmstor;
int num_elems;
Datum *elem_values;
bool *elem_nulls;
@@ -2490,10 +2491,11 @@ map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
array = DatumGetArrayTypeP(value);
elmtype = ARR_ELEMTYPE(array);
- get_typlenbyvalalign(elmtype, &elmlen, &elmbyval, &elmalign);
+ get_type_stores(elmtype, &elmlen,
+ &elmbyval, &elmalign, &elmstor);
deconstruct_array(array, elmtype,
- elmlen, elmbyval, elmalign,
+ elmlen, elmbyval, elmalign, elmstor,
&elem_values, &elem_nulls,
&num_elems);
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index a85dc0d891f..ec2775918ba 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -2284,6 +2284,30 @@ get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
ReleaseSysCache(tp);
}
+/*
+ * get_type_stores
+ *
+ * A four-fer: given the type OID, return typlen,
+ * typbyval, typalign, typstorage.
+ */
+void
+get_type_stores(Oid typid, int16 *typlen, bool *typbyval,
+ char *typalign, char *typstor)
+{
+ HeapTuple tp;
+ Form_pg_type typtup;
+
+ tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
+ if (!HeapTupleIsValid(tp))
+ elog(ERROR, "cache lookup failed for type %u", typid);
+ typtup = (Form_pg_type) GETSTRUCT(tp);
+ *typlen = typtup->typlen;
+ *typbyval = typtup->typbyval;
+ *typalign = typtup->typalign;
+ *typstor = typtup->typstorage;
+ ReleaseSysCache(tp);
+}
+
/*
* getTypeIOParam
* Given a pg_type row, select the type OID to pass to I/O functions
@@ -2394,6 +2418,63 @@ get_type_io_data(Oid typid,
ReleaseSysCache(typeTuple);
}
+/*
+ * array_type_metadata
+ *
+ * A six-fer: given the type OID, return typlen, typbyval, typalign,
+ * typdelim, typioparam, and IO function OID. The IO function
+ * returned is controlled by IOFuncSelector
+ */
+void
+array_type_metadata(Oid typid,
+ IOFuncSelector which_func,
+ ArrayMetaState *metadata)
+{
+ HeapTuple typeTuple;
+ Form_pg_type typeStruct;
+
+ /*
+ * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
+ * use array_in and array_out during bootstrap.
+ */
+ if (unlikely(IsBootstrapProcessingMode()))
+ {
+ boot_array_type_metadata(typid,
+ which_func,
+ metadata);
+
+ return;
+ }
+
+ typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
+ if (!HeapTupleIsValid(typeTuple))
+ elog(ERROR, "cache lookup failed for type %u", typid);
+ typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
+
+ metadata->typlen = typeStruct->typlen;
+ metadata->typbyval = typeStruct->typbyval;
+ metadata->typalign = typeStruct->typalign;
+ metadata->typstorage = typeStruct->typstorage;
+ metadata->typdelim = typeStruct->typdelim;
+ metadata->typioparam = getTypeIOParam(typeTuple);
+ switch (which_func)
+ {
+ case IOFunc_input:
+ metadata->typiofunc = typeStruct->typinput;
+ break;
+ case IOFunc_output:
+ metadata->typiofunc = typeStruct->typoutput;
+ break;
+ case IOFunc_receive:
+ metadata->typiofunc = typeStruct->typreceive;
+ break;
+ case IOFunc_send:
+ metadata->typiofunc = typeStruct->typsend;
+ break;
+ }
+ ReleaseSysCache(typeTuple);
+}
+
#ifdef NOT_USED
char
get_typalign(Oid typid)
@@ -3287,6 +3368,7 @@ get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple,
typeForm->typlen,
typeForm->typbyval,
typeForm->typalign,
+ typeForm->typstorage,
&sslot->values, NULL, &sslot->nvalues);
/*
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 1ce7eb9da8f..f6483a6d02e 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -627,6 +627,7 @@ RelationBuildTupleDesc(Relation relation)
attp->attlen,
attp->attbyval,
attp->attalign,
+ attp->attstorage,
&is_null);
Assert(!is_null);
if (attp->attbyval)
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index 05d763fa06e..c85f6048029 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -2023,6 +2023,7 @@ extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start,
Oid element_type;
bool typbyval;
char typalign;
+ char typstor;
int16 typlen;
Assert(PG_NARGS() == variadic_start + 1);
@@ -2033,10 +2034,10 @@ extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start,
array_in = PG_GETARG_ARRAYTYPE_P(variadic_start);
element_type = ARR_ELEMTYPE(array_in);
- get_typlenbyvalalign(element_type,
- &typlen, &typbyval, &typalign);
+ get_type_stores(element_type,
+ &typlen, &typbyval, &typalign, &typstor);
deconstruct_array(array_in, element_type, typlen, typbyval,
- typalign, &args_res, &nulls_res,
+ typalign, typstor, &args_res, &nulls_res,
&nargs);
/* All the elements of the array have the same type */
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index c10c0844ab6..c79a04a3472 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -6420,6 +6420,7 @@ TransformGUCArray(ArrayType *array, List **names, List **values)
-1 /* TEXT's typlen */ ,
false /* TEXT's typbyval */ ,
TYPALIGN_INT /* TEXT's typalign */ ,
+ TYPSTORAGE_EXTENDED /* TEXT's typalign */ ,
&isnull);
if (isnull)
@@ -6529,6 +6530,7 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
-1 /* TEXT's typlen */ ,
false /* TEXT's typbyval */ ,
TYPALIGN_INT /* TEXT's typalign */ ,
+ TYPSTORAGE_EXTENDED /* TEXT's typalign */ ,
&isnull);
if (isnull)
continue;
@@ -6548,7 +6550,8 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
-1 /* varlena array */ ,
-1 /* TEXT's typlen */ ,
false /* TEXT's typbyval */ ,
- TYPALIGN_INT /* TEXT's typalign */ );
+ TYPALIGN_INT /* TEXT's typalign */ ,
+ TYPSTORAGE_EXTENDED /* TEXT's typstorage */ );
}
else
a = construct_array_builtin(&datum, 1, TEXTOID);
@@ -6598,6 +6601,7 @@ GUCArrayDelete(ArrayType *array, const char *name)
-1 /* TEXT's typlen */ ,
false /* TEXT's typbyval */ ,
TYPALIGN_INT /* TEXT's typalign */ ,
+ TYPSTORAGE_EXTENDED /* TEXT's typalign */ ,
&isnull);
if (isnull)
continue;
@@ -6616,7 +6620,8 @@ GUCArrayDelete(ArrayType *array, const char *name)
-1 /* varlenarray */ ,
-1 /* TEXT's typlen */ ,
false /* TEXT's typbyval */ ,
- TYPALIGN_INT /* TEXT's typalign */ );
+ TYPALIGN_INT /* TEXT's typalign */ ,
+ TYPSTORAGE_EXTENDED /* TEXT's typstorage */ );
else
newarray = construct_array_builtin(&d, 1, TEXTOID);
@@ -6662,6 +6667,7 @@ GUCArrayReset(ArrayType *array)
-1 /* TEXT's typlen */ ,
false /* TEXT's typbyval */ ,
TYPALIGN_INT /* TEXT's typalign */ ,
+ TYPSTORAGE_EXTENDED /* TEXT's typalign */ ,
&isnull);
if (isnull)
continue;
@@ -6682,7 +6688,8 @@ GUCArrayReset(ArrayType *array)
-1 /* varlenarray */ ,
-1 /* TEXT's typlen */ ,
false /* TEXT's typbyval */ ,
- TYPALIGN_INT /* TEXT's typalign */ );
+ TYPALIGN_INT /* TEXT's typalign */ ,
+ TYPSTORAGE_EXTENDED /* TEXT's typstorage */ );
else
newarray = construct_array_builtin(&d, 1, TEXTOID);
diff --git a/src/include/access/tupmacs.h b/src/include/access/tupmacs.h
index 0de67e3602a..f2264767fbb 100644
--- a/src/include/access/tupmacs.h
+++ b/src/include/access/tupmacs.h
@@ -199,6 +199,35 @@ fetch_att(const void *T, bool attbyval, int attlen)
)) \
)
+/*
+ * att_addvarsize_datum increments the given offset by the space needed for
+ * the given Datum variable to store it. attdatum is only accessed if we are
+ * dealing with a variable-length attribute.
+ */
+#define att_addvarsize_datum(cur_offset, typlen, typstor, datum) \
+ att_addvarsize_pointer(cur_offset, typlen, typstor, DatumGetPointer(datum))
+
+#define att_addvarsize_pointer(cur_offset, typlen, typstor, ptr) \
+( \
+ ((typlen) > 0) ? \
+ ( \
+ (cur_offset) + (typlen) \
+ ) \
+ : (((typlen) == -1) ? \
+ ( \
+ ((TYPE_IS_PACKABLE(typlen, typstor) && VARATT_CAN_MAKE_SHORT(ptr)) ? \
+ (cur_offset) + VARATT_CONVERTED_SHORT_SIZE(ptr) \
+ : \
+ (cur_offset) + VARSIZE_ANY(ptr) \
+ ) \
+ ) \
+ : \
+ ( \
+ AssertMacro((typlen) == -2), \
+ (cur_offset) + (strlen((char *) (ptr)) + 1) \
+ )) \
+)
+
#ifndef FRONTEND
/*
* store_att_byval is a partial inverse of fetch_att: store a given Datum
diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h
index 33035d4ed82..9d55dcc419e 100644
--- a/src/include/bootstrap/bootstrap.h
+++ b/src/include/bootstrap/bootstrap.h
@@ -16,6 +16,8 @@
#include "nodes/execnodes.h"
#include "nodes/parsenodes.h"
+#include "utils/array.h"
+#include "utils/lsyscache.h"
/*
@@ -61,6 +63,10 @@ union YYSTYPE;
typedef void *yyscan_t;
#endif
+extern void boot_array_type_metadata(Oid typid,
+ IOFuncSelector which_func,
+ ArrayMetaState *metadata);
+
extern int boot_yyparse(yyscan_t yyscanner);
extern int boot_yylex_init(yyscan_t *yyscannerp);
extern int boot_yylex(union YYSTYPE *yylval_param, yyscan_t yyscanner);
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index e9259697321..652e9467333 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -345,6 +345,10 @@ MAKE_SYSCACHE(TYPENAMENSP, pg_type_typname_nsp_index, 64);
#endif /* EXPOSE_TO_CLIENT_CODE */
+/* Does datatype allow packing into the 1-byte-header varlena format? */
+#define TYPE_IS_PACKABLE(typlen, typstorage) \
+ ((typlen) == -1 && (typstorage) != TYPSTORAGE_PLAIN)
+
extern ObjectAddress TypeShellMake(const char *typeName,
Oid typeNamespace,
Oid ownerId);
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index 759f9a87d38..84e2def31cb 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -163,6 +163,7 @@ typedef struct VacAttrStats
int16 statyplen[STATISTIC_NUM_SLOTS];
bool statypbyval[STATISTIC_NUM_SLOTS];
char statypalign[STATISTIC_NUM_SLOTS];
+ char statypstorage[STATISTIC_NUM_SLOTS];
/*
* These fields are private to the main ANALYZE code and should not be
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index 56fb0d0adbe..f17cedc26b0 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -458,6 +458,7 @@ typedef struct ExprEvalStep
int16 elemlength; /* typlen of the array element type */
bool elembyval; /* is the element type pass-by-value? */
char elemalign; /* typalign of the element type */
+ char elemstorage; /* typstorage of the element type */
bool multidims; /* is array expression multi-D? */
} arrayexpr;
diff --git a/src/include/utils/array.h b/src/include/utils/array.h
index 157cc0e4c6e..711b37f6714 100644
--- a/src/include/utils/array.h
+++ b/src/include/utils/array.h
@@ -130,6 +130,7 @@ typedef struct ExpandedArrayHeader
int16 typlen; /* needed info about element datatype */
bool typbyval;
char typalign;
+ char typstorage;
/*
* If we have a Datum-array representation of the array, it's kept here;
@@ -195,6 +196,7 @@ typedef struct ArrayBuildState
int16 typlen; /* needed info about datatype */
bool typbyval;
char typalign;
+ char typstorage;
bool private_cxt; /* use private memory context */
} ArrayBuildState;
@@ -240,6 +242,7 @@ typedef struct ArrayMetaState
bool typbyval;
char typalign;
char typdelim;
+ char typstorage;
Oid typioparam;
Oid typiofunc;
FmgrInfo proc;
@@ -358,30 +361,34 @@ extern void CopyArrayEls(ArrayType *array,
int typlen,
bool typbyval,
char typalign,
+ char typstor,
bool freedata);
extern Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx,
- int arraytyplen, int elmlen, bool elmbyval, char elmalign,
- bool *isNull);
+ int arraytyplen, int elmlen, bool elmbyval,
+ char elmalign, char elmstor, bool *isNull);
extern Datum array_set_element(Datum arraydatum, int nSubscripts, int *indx,
Datum dataValue, bool isNull,
- int arraytyplen, int elmlen, bool elmbyval, char elmalign);
+ int arraytyplen, int elmlen, bool elmbyval,
+ char elmalign, char elmstor);
extern Datum array_get_slice(Datum arraydatum, int nSubscripts,
int *upperIndx, int *lowerIndx,
bool *upperProvided, bool *lowerProvided,
- int arraytyplen, int elmlen, bool elmbyval, char elmalign);
+ int arraytyplen, int elmlen, bool elmbyval,
+ char elmalign, char typstor);
extern Datum array_set_slice(Datum arraydatum, int nSubscripts,
int *upperIndx, int *lowerIndx,
bool *upperProvided, bool *lowerProvided,
Datum srcArrayDatum, bool isNull,
- int arraytyplen, int elmlen, bool elmbyval, char elmalign);
+ int arraytyplen, int elmlen, bool elmbyval,
+ char elmalign, char elmstor);
extern Datum array_ref(ArrayType *array, int nSubscripts, int *indx,
int arraytyplen, int elmlen, bool elmbyval, char elmalign,
- bool *isNull);
+ char elmstor, bool *isNull);
extern ArrayType *array_set(ArrayType *array, int nSubscripts, int *indx,
- Datum dataValue, bool isNull,
- int arraytyplen, int elmlen, bool elmbyval, char elmalign);
+ Datum dataValue, bool isNull, int arraytyplen,
+ int elmlen, bool elmbyval, char elmalign, char elmstor);
extern Datum array_map(Datum arrayd,
struct ExprState *exprstate, struct ExprContext *econtext,
@@ -393,21 +400,23 @@ extern void array_bitmap_copy(bits8 *destbitmap, int destoffset,
extern ArrayType *construct_array(Datum *elems, int nelems,
Oid elmtype,
- int elmlen, bool elmbyval, char elmalign);
+ int elmlen, bool elmbyval,
+ char elmalign, char elmstor);
extern ArrayType *construct_array_builtin(Datum *elems, int nelems, Oid elmtype);
extern ArrayType *construct_md_array(Datum *elems,
bool *nulls,
int ndims,
int *dims,
int *lbs,
- Oid elmtype, int elmlen, bool elmbyval, char elmalign);
+ Oid elmtype, int elmlen, bool elmbyval,
+ char elmalign, char elmstor);
extern ArrayType *construct_empty_array(Oid elmtype);
extern ExpandedArrayHeader *construct_empty_expanded_array(Oid element_type,
MemoryContext parentcontext,
ArrayMetaState *metacache);
extern void deconstruct_array(ArrayType *array,
Oid elmtype,
- int elmlen, bool elmbyval, char elmalign,
+ int elmlen, bool elmbyval, char elmalign, char elmstor,
Datum **elemsp, bool **nullsp, int *nelemsp);
extern void deconstruct_array_builtin(ArrayType *array,
Oid elmtype,
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 20446f6f836..5ee3ab2cdb8 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -16,6 +16,7 @@
#include "access/attnum.h"
#include "access/htup.h"
#include "nodes/pg_list.h"
+#include "utils/array.h"
/* avoid including subscripting.h here */
struct SubscriptRoutines;
@@ -150,7 +151,12 @@ extern bool get_typbyval(Oid typid);
extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
extern void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
char *typalign);
+extern void get_type_stores(Oid typid, int16 *typlen,
+ bool *typbyval, char *typalign, char *typstor);
extern Oid getTypeIOParam(HeapTuple typeTuple);
+extern void array_type_metadata(Oid typid,
+ IOFuncSelector which_func,
+ ArrayMetaState *metadata);
extern void get_type_io_data(Oid typid,
IOFuncSelector which_func,
int16 *typlen,
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
index 773a5d2c347..339745f5081 100644
--- a/src/include/utils/palloc.h
+++ b/src/include/utils/palloc.h
@@ -85,6 +85,12 @@ extern pg_nodiscard void *repalloc_extended(void *pointer,
extern pg_nodiscard void *repalloc0(void *pointer, Size oldsize, Size size);
extern void pfree(void *pointer);
+#define PFREE_IF_NEW(newptr, oldptr) \
+ do { \
+ if ((Pointer)(newptr) != (Pointer)(oldptr)) \
+ pfree(newptr); \
+ } while (0)
+
/*
* Variants with easier notation and more type safety
*/
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 1b1677e333b..85b5b1be9f4 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -1484,6 +1484,7 @@ plperl_ref_from_pg_array(Datum arg, Oid typid)
int16 typlen;
bool typbyval;
char typalign,
+ typstor,
typdelim;
Oid typioparam;
Oid typoutputfunc;
@@ -1506,6 +1507,8 @@ plperl_ref_from_pg_array(Datum arg, Oid typid)
&typlen, &typbyval, &typalign,
&typdelim, &typioparam, &typoutputfunc);
+ typstor = get_typstorage(elementtype);
+
/* Check for a transform function */
transform_funcid = get_transform_fromsql(elementtype,
current_call_data->prodesc->lang_oid,
@@ -1531,8 +1534,8 @@ plperl_ref_from_pg_array(Datum arg, Oid typid)
else
{
deconstruct_array(ar, elementtype, typlen, typbyval,
- typalign, &info->elements, &info->nulls,
- &nitems);
+ typalign, typstor,
+ &info->elements, &info->nulls, &nitems);
/* Get total number of elements in each dimension */
info->nelems = palloc(sizeof(int) * info->ndims);
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index e31206e7f4c..067b82427d6 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -1491,7 +1491,9 @@ plpgsql_fulfill_promise(PLpgSQL_execstate *estate,
PointerGetDatum(construct_md_array(elems, NULL,
1, dims, lbs,
TEXTOID,
- -1, false, TYPALIGN_INT)),
+ -1, false,
+ TYPALIGN_INT,
+ TYPSTORAGE_EXTENDED)),
false, true);
}
else
diff --git a/src/test/modules/test_regex/test_regex.c b/src/test/modules/test_regex/test_regex.c
index a780c678fbc..b3e0564f6da 100644
--- a/src/test/modules/test_regex/test_regex.c
+++ b/src/test/modules/test_regex/test_regex.c
@@ -678,7 +678,8 @@ build_test_info_result(regex_t *cpattern, test_re_flags *flags)
lbs[0] = 1;
/* XXX: this hardcodes assumptions about the text type */
return construct_md_array(elems, NULL, 1, dims, lbs,
- TEXTOID, -1, false, TYPALIGN_INT);
+ TEXTOID, -1, false,
+ TYPALIGN_INT, TYPSTORAGE_EXTENDED);
}
/*
@@ -758,5 +759,6 @@ build_test_match_result(test_regex_ctx *matchctx)
lbs[0] = 1;
/* XXX: this hardcodes assumptions about the text type */
return construct_md_array(elems, nulls, 1, dims, lbs,
- TEXTOID, -1, false, TYPALIGN_INT);
+ TEXTOID, -1, false,
+ TYPALIGN_INT, TYPSTORAGE_EXTENDED);
}
Quan Zongliang <quanzongliang@yeah.net> writes:
Now, the varlena type is stored directly in the array. Did not consider
short varlena. If it's like fill_val(), using short varlena saves memory
footprint and disk space.
TBH, I think this is a bad idea and we should reject it. As you have
already discovered, the code footprint of such a change is enormous
(and I have little confidence that you found all the places to fix).
The consequences would be equally dire in extensions, which'd likely
be dealing with ensuing bugs for years to come.
The reason we didn't do this when we originally invented short varlena
headers is that we presumed that array-level compression would remove
most of the benefit. Of course that only happens if the array is big
enough to get the attention of the tuple toaster, which is why your
example with very small arrays shows a benefit. But I'm doubtful that
such use-cases justify the pain we'd endure getting to the point where
this'd work reliably. The percentage savings drops off drastically as
the length of the individual strings grows, so this example with
one-byte strings is very much a best-case scenario.
In short, I'm afraid this ship sailed a long time ago. Perhaps it
was a poor decision but I think we're stuck with it.
regards, tom lane