From 35fe30fec1692a4e329e9c9b1ed40863e3b970b2 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 2 May 2022 10:23:26 +0200 Subject: [PATCH] Add construct_array_builtin, deconstruct_array_builtin There were many calls to construct_array() and deconstruct_array() for built-in types, for example, when dealing with system catalog columns. These all hardcoded the type attributes necessary to pass to these functions. To simplify this a bit, add construct_array_builtin(), deconstruct_array_builtin() as wrappers that centralize this hardcoded knowledge. This simplifies many call sites and reduces the amount of hardcoded stuff that is spread around. --- contrib/hstore/hstore_gin.c | 4 +- contrib/hstore/hstore_gist.c | 8 +- contrib/hstore/hstore_io.c | 12 +- contrib/hstore/hstore_op.c | 11 +- contrib/pageinspect/btreefuncs.c | 6 +- contrib/pageinspect/ginfuncs.c | 10 +- contrib/pageinspect/gistfuncs.c | 4 +- contrib/pageinspect/hashfuncs.c | 14 +- contrib/pageinspect/heapfuncs.c | 4 +- contrib/pg_trgm/trgm_op.c | 7 +- contrib/pgcrypto/pgp-pgsql.c | 9 +- src/backend/access/common/reloptions.c | 9 +- src/backend/catalog/objectaddress.c | 12 +- src/backend/catalog/pg_constraint.c | 21 +-- src/backend/catalog/pg_proc.c | 5 +- src/backend/catalog/pg_subscription.c | 4 +- src/backend/commands/analyze.c | 5 +- src/backend/commands/event_trigger.c | 3 +- src/backend/commands/extension.c | 24 +-- src/backend/commands/functioncmds.c | 12 +- src/backend/commands/policy.c | 9 +- src/backend/commands/prepare.c | 4 +- src/backend/commands/statscmds.c | 2 +- src/backend/commands/subscriptioncmds.c | 3 +- src/backend/commands/typecmds.c | 7 +- src/backend/executor/nodeTidscan.c | 4 +- src/backend/parser/parse_type.c | 4 +- src/backend/parser/parse_utilcmd.c | 4 +- .../replication/logical/logicalfuncs.c | 3 +- src/backend/statistics/extended_stats.c | 5 +- src/backend/tsearch/dict.c | 7 +- src/backend/utils/adt/arrayfuncs.c | 153 +++++++++++++++++- src/backend/utils/adt/arrayutils.c | 5 +- src/backend/utils/adt/hbafuncs.c | 2 +- src/backend/utils/adt/json.c | 13 +- src/backend/utils/adt/jsonb.c | 13 +- src/backend/utils/adt/jsonb_gin.c | 4 +- src/backend/utils/adt/jsonb_op.c | 6 +- src/backend/utils/adt/jsonfuncs.c | 18 +-- src/backend/utils/adt/lockfuncs.c | 10 +- src/backend/utils/adt/name.c | 6 +- src/backend/utils/adt/orderedsetaggs.c | 20 +-- src/backend/utils/adt/pg_upgrade_support.c | 4 +- src/backend/utils/adt/ruleutils.c | 20 +-- src/backend/utils/adt/tsvector_op.c | 19 +-- src/backend/utils/adt/xml.c | 6 +- src/backend/utils/cache/evtcache.c | 3 +- src/backend/utils/fmgr/funcapi.c | 14 +- src/backend/utils/misc/guc.c | 14 +- src/include/utils/array.h | 4 + .../modules/test_rls_hooks/test_rls_hooks.c | 4 +- 51 files changed, 276 insertions(+), 298 deletions(-) diff --git a/contrib/hstore/hstore_gin.c b/contrib/hstore/hstore_gin.c index 908530261a..766c00bb6a 100644 --- a/contrib/hstore/hstore_gin.c +++ b/contrib/hstore/hstore_gin.c @@ -118,9 +118,7 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS) j; text *item; - deconstruct_array(query, - TEXTOID, -1, false, TYPALIGN_INT, - &key_datums, &key_nulls, &key_count); + deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count); entries = (Datum *) palloc(sizeof(Datum) * key_count); diff --git a/contrib/hstore/hstore_gist.c b/contrib/hstore/hstore_gist.c index 102c9cea72..0a95628837 100644 --- a/contrib/hstore/hstore_gist.c +++ b/contrib/hstore/hstore_gist.c @@ -560,9 +560,7 @@ ghstore_consistent(PG_FUNCTION_ARGS) int key_count; int i; - deconstruct_array(query, - TEXTOID, -1, false, TYPALIGN_INT, - &key_datums, &key_nulls, &key_count); + deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count); for (i = 0; res && i < key_count; ++i) { @@ -583,9 +581,7 @@ ghstore_consistent(PG_FUNCTION_ARGS) int key_count; int i; - deconstruct_array(query, - TEXTOID, -1, false, TYPALIGN_INT, - &key_datums, &key_nulls, &key_count); + deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count); res = false; diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c index b3304ff844..fb72bb6cfe 100644 --- a/contrib/hstore/hstore_io.c +++ b/contrib/hstore/hstore_io.c @@ -567,9 +567,7 @@ hstore_from_arrays(PG_FUNCTION_ARGS) (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); - deconstruct_array(key_array, - TEXTOID, -1, false, TYPALIGN_INT, - &key_datums, &key_nulls, &key_count); + deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count); /* see discussion in hstoreArrayToPairs() */ if (key_count > MaxAllocSize / sizeof(Pairs)) @@ -606,9 +604,7 @@ hstore_from_arrays(PG_FUNCTION_ARGS) (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("arrays must have same bounds"))); - deconstruct_array(value_array, - TEXTOID, -1, false, TYPALIGN_INT, - &value_datums, &value_nulls, &value_count); + deconstruct_array_builtin(value_array, TEXTOID, &value_datums, &value_nulls, &value_count); Assert(key_count == value_count); } @@ -696,9 +692,7 @@ hstore_from_array(PG_FUNCTION_ARGS) errmsg("wrong number of array subscripts"))); } - deconstruct_array(in_array, - TEXTOID, -1, false, TYPALIGN_INT, - &in_datums, &in_nulls, &in_count); + deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count); count = in_count / 2; diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c index dd79d01cac..2f540d7ed6 100644 --- a/contrib/hstore/hstore_op.c +++ b/contrib/hstore/hstore_op.c @@ -80,9 +80,7 @@ hstoreArrayToPairs(ArrayType *a, int *npairs) int i, j; - deconstruct_array(a, - TEXTOID, -1, false, TYPALIGN_INT, - &key_datums, &key_nulls, &key_count); + deconstruct_array_builtin(a, TEXTOID, &key_datums, &key_nulls, &key_count); if (key_count == 0) { @@ -582,9 +580,7 @@ hstore_slice_to_array(PG_FUNCTION_ARGS) int key_count; int i; - deconstruct_array(key_array, - TEXTOID, -1, false, TYPALIGN_INT, - &key_datums, &key_nulls, &key_count); + deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count); if (key_count == 0) { @@ -719,8 +715,7 @@ hstore_akeys(PG_FUNCTION_ARGS) d[i] = PointerGetDatum(t); } - a = construct_array(d, count, - TEXTOID, -1, false, TYPALIGN_INT); + a = construct_array_builtin(d, count, TEXTOID); PG_RETURN_POINTER(a); } diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c index 62f2c1b315..9375d55e14 100644 --- a/contrib/pageinspect/btreefuncs.c +++ b/contrib/pageinspect/btreefuncs.c @@ -425,11 +425,7 @@ bt_page_print_tuples(struct user_args *uargs) tids_datum = (Datum *) palloc(nposting * sizeof(Datum)); for (int i = 0; i < nposting; i++) tids_datum[i] = ItemPointerGetDatum(&tids[i]); - values[j++] = PointerGetDatum(construct_array(tids_datum, - nposting, - TIDOID, - sizeof(ItemPointerData), - false, TYPALIGN_SHORT)); + values[j++] = PointerGetDatum(construct_array_builtin(tids_datum, nposting, TIDOID)); pfree(tids_datum); } else diff --git a/contrib/pageinspect/ginfuncs.c b/contrib/pageinspect/ginfuncs.c index 31aca7b000..952e9d51a8 100644 --- a/contrib/pageinspect/ginfuncs.c +++ b/contrib/pageinspect/ginfuncs.c @@ -166,9 +166,7 @@ gin_page_opaque_info(PG_FUNCTION_ARGS) values[0] = Int64GetDatum(opaq->rightlink); values[1] = Int32GetDatum(opaq->maxoff); - values[2] = PointerGetDatum(construct_array(flags, nflags, - TEXTOID, - -1, false, TYPALIGN_INT)); + values[2] = PointerGetDatum(construct_array_builtin(flags, nflags, TEXTOID)); /* Build and return the result tuple. */ resultTuple = heap_form_tuple(tupdesc, values, nulls); @@ -273,11 +271,7 @@ gin_leafpage_items(PG_FUNCTION_ARGS) tids_datum = (Datum *) palloc(ndecoded * sizeof(Datum)); for (i = 0; i < ndecoded; i++) tids_datum[i] = ItemPointerGetDatum(&tids[i]); - values[2] = PointerGetDatum(construct_array(tids_datum, - ndecoded, - TIDOID, - sizeof(ItemPointerData), - false, TYPALIGN_SHORT)); + values[2] = PointerGetDatum(construct_array_builtin(tids_datum, ndecoded, TIDOID)); pfree(tids_datum); pfree(tids); diff --git a/contrib/pageinspect/gistfuncs.c b/contrib/pageinspect/gistfuncs.c index 9c29fbc7aa..fb48d6feca 100644 --- a/contrib/pageinspect/gistfuncs.c +++ b/contrib/pageinspect/gistfuncs.c @@ -104,9 +104,7 @@ gist_page_opaque_info(PG_FUNCTION_ARGS) values[0] = LSNGetDatum(PageGetLSN(page)); values[1] = LSNGetDatum(GistPageGetNSN(page)); values[2] = Int64GetDatum(opaq->rightlink); - values[3] = PointerGetDatum(construct_array(flags, nflags, - TEXTOID, - -1, false, TYPALIGN_INT)); + values[3] = PointerGetDatum(construct_array_builtin(flags, nflags, TEXTOID)); /* Build and return the result tuple. */ resultTuple = heap_form_tuple(tupdesc, values, nulls); diff --git a/contrib/pageinspect/hashfuncs.c b/contrib/pageinspect/hashfuncs.c index 69af7b962f..6e592e3770 100644 --- a/contrib/pageinspect/hashfuncs.c +++ b/contrib/pageinspect/hashfuncs.c @@ -564,21 +564,11 @@ hash_metapage_info(PG_FUNCTION_ARGS) for (i = 0; i < HASH_MAX_SPLITPOINTS; i++) spares[i] = Int64GetDatum((int64) metad->hashm_spares[i]); - values[j++] = PointerGetDatum(construct_array(spares, - HASH_MAX_SPLITPOINTS, - INT8OID, - sizeof(int64), - FLOAT8PASSBYVAL, - TYPALIGN_DOUBLE)); + values[j++] = PointerGetDatum(construct_array_builtin(spares, lengthof(spares), INT8OID)); for (i = 0; i < HASH_MAX_BITMAPS; i++) mapp[i] = Int64GetDatum((int64) metad->hashm_mapp[i]); - values[j++] = PointerGetDatum(construct_array(mapp, - HASH_MAX_BITMAPS, - INT8OID, - sizeof(int64), - FLOAT8PASSBYVAL, - TYPALIGN_DOUBLE)); + values[j++] = PointerGetDatum(construct_array_builtin(mapp, lengthof(mapp), INT8OID)); tuple = heap_form_tuple(tupleDesc, values, nulls); diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c index 3dd1a9bc2a..a654234c6b 100644 --- a/contrib/pageinspect/heapfuncs.c +++ b/contrib/pageinspect/heapfuncs.c @@ -590,7 +590,7 @@ heap_tuple_infomask_flags(PG_FUNCTION_ARGS) /* build value */ Assert(cnt <= bitcnt); - a = construct_array(flags, cnt, TEXTOID, -1, false, TYPALIGN_INT); + a = construct_array_builtin(flags, cnt, TEXTOID); values[0] = PointerGetDatum(a); /* @@ -612,7 +612,7 @@ heap_tuple_infomask_flags(PG_FUNCTION_ARGS) if (cnt == 0) a = construct_empty_array(TEXTOID); else - a = construct_array(flags, cnt, TEXTOID, -1, false, TYPALIGN_INT); + a = construct_array_builtin(flags, cnt, TEXTOID); pfree(flags); values[1] = PointerGetDatum(a); diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c index e9b7981619..cbcc481a17 100644 --- a/contrib/pg_trgm/trgm_op.c +++ b/contrib/pg_trgm/trgm_op.c @@ -977,12 +977,7 @@ show_trgm(PG_FUNCTION_ARGS) d[i] = PointerGetDatum(item); } - a = construct_array(d, - ARRNELEM(trg), - TEXTOID, - -1, - false, - TYPALIGN_INT); + a = construct_array_builtin(d, ARRNELEM(trg), TEXTOID); for (i = 0; i < ARRNELEM(trg); i++) pfree(DatumGetPointer(d[i])); diff --git a/contrib/pgcrypto/pgp-pgsql.c b/contrib/pgcrypto/pgp-pgsql.c index 0536bfb892..d9b15b07b0 100644 --- a/contrib/pgcrypto/pgp-pgsql.c +++ b/contrib/pgcrypto/pgp-pgsql.c @@ -774,13 +774,8 @@ parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array, if (nkdims == 0) return 0; - deconstruct_array(key_array, - TEXTOID, -1, false, TYPALIGN_INT, - &key_datums, &key_nulls, &key_count); - - deconstruct_array(val_array, - TEXTOID, -1, false, TYPALIGN_INT, - &val_datums, &val_nulls, &val_count); + deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count); + deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count); if (key_count != val_count) ereport(ERROR, diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index 599e160ca6..2b2ef63c35 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -1177,8 +1177,7 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace, int noldoptions; int i; - deconstruct_array(array, TEXTOID, -1, false, TYPALIGN_INT, - &oldoptions, NULL, &noldoptions); + deconstruct_array_builtin(array, TEXTOID, &oldoptions, NULL, &noldoptions); for (i = 0; i < noldoptions; i++) { @@ -1345,8 +1344,7 @@ untransformRelOptions(Datum options) array = DatumGetArrayTypeP(options); - deconstruct_array(array, TEXTOID, -1, false, TYPALIGN_INT, - &optiondatums, NULL, &noptions); + deconstruct_array_builtin(array, TEXTOID, &optiondatums, NULL, &noptions); for (i = 0; i < noptions; i++) { @@ -1436,8 +1434,7 @@ parseRelOptionsInternal(Datum options, bool validate, int noptions; int i; - deconstruct_array(array, TEXTOID, -1, false, TYPALIGN_INT, - &optiondatums, NULL, &noptions); + deconstruct_array_builtin(array, TEXTOID, &optiondatums, NULL, &noptions); for (i = 0; i < noptions; i++) { diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 8377b4f7d4..2d21db4690 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -2099,8 +2099,7 @@ textarray_to_strvaluelist(ArrayType *arr) List *list = NIL; int i; - deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT, - &elems, &nulls, &nelems); + deconstruct_array_builtin(arr, TEXTOID, &elems, &nulls, &nelems); for (i = 0; i < nelems; i++) { @@ -2156,8 +2155,7 @@ pg_get_object_address(PG_FUNCTION_ARGS) bool *nulls; int nelems; - deconstruct_array(namearr, TEXTOID, -1, false, TYPALIGN_INT, - &elems, &nulls, &nelems); + deconstruct_array_builtin(namearr, TEXTOID, &elems, &nulls, &nelems); if (nelems != 1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -2174,8 +2172,7 @@ pg_get_object_address(PG_FUNCTION_ARGS) bool *nulls; int nelems; - deconstruct_array(namearr, TEXTOID, -1, false, TYPALIGN_INT, - &elems, &nulls, &nelems); + deconstruct_array_builtin(namearr, TEXTOID, &elems, &nulls, &nelems); if (nelems != 1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -2213,8 +2210,7 @@ pg_get_object_address(PG_FUNCTION_ARGS) int nelems; int i; - deconstruct_array(argsarr, TEXTOID, -1, false, TYPALIGN_INT, - &elems, &nulls, &nelems); + deconstruct_array_builtin(argsarr, TEXTOID, &elems, &nulls, &nelems); args = NIL; for (i = 0; i < nelems; i++) diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 472dbda211..454367a852 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -112,8 +112,7 @@ CreateConstraintEntry(const char *constraintName, conkey = (Datum *) palloc(constraintNKeys * sizeof(Datum)); for (i = 0; i < constraintNKeys; i++) conkey[i] = Int16GetDatum(constraintKey[i]); - conkeyArray = construct_array(conkey, constraintNKeys, - INT2OID, 2, true, TYPALIGN_SHORT); + conkeyArray = construct_array_builtin(conkey, constraintNKeys, INT2OID); } else conkeyArray = NULL; @@ -125,27 +124,22 @@ CreateConstraintEntry(const char *constraintName, fkdatums = (Datum *) palloc(foreignNKeys * sizeof(Datum)); for (i = 0; i < foreignNKeys; i++) fkdatums[i] = Int16GetDatum(foreignKey[i]); - confkeyArray = construct_array(fkdatums, foreignNKeys, - INT2OID, 2, true, TYPALIGN_SHORT); + confkeyArray = construct_array_builtin(fkdatums, foreignNKeys, INT2OID); for (i = 0; i < foreignNKeys; i++) fkdatums[i] = ObjectIdGetDatum(pfEqOp[i]); - conpfeqopArray = construct_array(fkdatums, foreignNKeys, - OIDOID, sizeof(Oid), true, TYPALIGN_INT); + conpfeqopArray = construct_array_builtin(fkdatums, foreignNKeys, OIDOID); for (i = 0; i < foreignNKeys; i++) fkdatums[i] = ObjectIdGetDatum(ppEqOp[i]); - conppeqopArray = construct_array(fkdatums, foreignNKeys, - OIDOID, sizeof(Oid), true, TYPALIGN_INT); + conppeqopArray = construct_array_builtin(fkdatums, foreignNKeys, OIDOID); for (i = 0; i < foreignNKeys; i++) fkdatums[i] = ObjectIdGetDatum(ffEqOp[i]); - conffeqopArray = construct_array(fkdatums, foreignNKeys, - OIDOID, sizeof(Oid), true, TYPALIGN_INT); + conffeqopArray = construct_array_builtin(fkdatums, foreignNKeys, OIDOID); if (numFkDeleteSetCols > 0) { for (i = 0; i < numFkDeleteSetCols; i++) fkdatums[i] = Int16GetDatum(fkDeleteSetCols[i]); - confdelsetcolsArray = construct_array(fkdatums, numFkDeleteSetCols, - INT2OID, 2, true, TYPALIGN_SHORT); + confdelsetcolsArray = construct_array_builtin(fkdatums, numFkDeleteSetCols, INT2OID); } else confdelsetcolsArray = NULL; @@ -166,8 +160,7 @@ CreateConstraintEntry(const char *constraintName, opdatums = (Datum *) palloc(constraintNKeys * sizeof(Datum)); for (i = 0; i < constraintNKeys; i++) opdatums[i] = ObjectIdGetDatum(exclOp[i]); - conexclopArray = construct_array(opdatums, constraintNKeys, - OIDOID, sizeof(Oid), true, TYPALIGN_INT); + conexclopArray = construct_array_builtin(opdatums, constraintNKeys, OIDOID); } else conexclopArray = NULL; diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index d82221fdb8..a4a30bccf6 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -1193,10 +1193,7 @@ oid_array_to_list(Datum datum) int i; List *result = NIL; - deconstruct_array(array, - OIDOID, - sizeof(Oid), true, TYPALIGN_INT, - &values, NULL, &nelems); + deconstruct_array_builtin(array, OIDOID, &values, NULL, &nelems); for (i = 0; i < nelems; i++) result = lappend_oid(result, values[i]); return result; diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c index add51caadf..8856ce3b50 100644 --- a/src/backend/catalog/pg_subscription.c +++ b/src/backend/catalog/pg_subscription.c @@ -260,9 +260,7 @@ textarray_to_stringlist(ArrayType *textarray) i; List *res = NIL; - deconstruct_array(textarray, - TEXTOID, -1, false, TYPALIGN_INT, - &elems, NULL, &nelems); + deconstruct_array_builtin(textarray, TEXTOID, &elems, NULL, &nelems); if (nelems == 0) return NIL; diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 305226692a..7f8652013e 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -1688,10 +1688,7 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats) for (n = 0; n < nnum; n++) numdatums[n] = Float4GetDatum(stats->stanumbers[k][n]); - /* XXX knows more than it should about type float4: */ - arry = construct_array(numdatums, nnum, - FLOAT4OID, - sizeof(float4), true, TYPALIGN_INT); + arry = construct_array_builtin(numdatums, nnum, FLOAT4OID); values[i++] = PointerGetDatum(arry); /* stanumbersN */ } else diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 4642527881..f46f86474a 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -351,8 +351,7 @@ filter_list_to_array(List *filterlist) pfree(result); } - return PointerGetDatum(construct_array(data, l, TEXTOID, - -1, false, TYPALIGN_INT)); + return PointerGetDatum(construct_array_builtin(data, l, TEXTOID)); } /* diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 1013790dbb..117ed80246 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -2251,9 +2251,7 @@ convert_requires_to_datum(List *requires) datums[ndatums++] = DirectFunctionCall1(namein, CStringGetDatum(curreq)); } - a = construct_array(datums, ndatums, - NAMEOID, - NAMEDATALEN, false, TYPALIGN_CHAR); + a = construct_array_builtin(datums, ndatums, NAMEOID); return PointerGetDatum(a); } @@ -2433,9 +2431,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) arrayLength = 0; arrayIndex = 1; - a = construct_array(&elementDatum, 1, - OIDOID, - sizeof(Oid), true, TYPALIGN_INT); + a = construct_array_builtin(&elementDatum, 1, OIDOID); } else { @@ -2486,9 +2482,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) if (arrayLength != 0) elog(ERROR, "extconfig and extcondition arrays do not match"); - a = construct_array(&elementDatum, 1, - TEXTOID, - -1, false, TYPALIGN_INT); + a = construct_array_builtin(&elementDatum, 1, TEXTOID); } else { @@ -2630,14 +2624,12 @@ extension_config_remove(Oid extensionoid, Oid tableoid) int i; /* We already checked there are no nulls */ - deconstruct_array(a, OIDOID, sizeof(Oid), true, TYPALIGN_INT, - &dvalues, NULL, &nelems); + deconstruct_array_builtin(a, OIDOID, &dvalues, NULL, &nelems); for (i = arrayIndex; i < arrayLength - 1; i++) dvalues[i] = dvalues[i + 1]; - a = construct_array(dvalues, arrayLength - 1, - OIDOID, sizeof(Oid), true, TYPALIGN_INT); + a = construct_array_builtin(dvalues, arrayLength - 1, OIDOID); repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a); } @@ -2676,14 +2668,12 @@ extension_config_remove(Oid extensionoid, Oid tableoid) int i; /* We already checked there are no nulls */ - deconstruct_array(a, TEXTOID, -1, false, TYPALIGN_INT, - &dvalues, NULL, &nelems); + deconstruct_array_builtin(a, TEXTOID, &dvalues, NULL, &nelems); for (i = arrayIndex; i < arrayLength - 1; i++) dvalues[i] = dvalues[i + 1]; - a = construct_array(dvalues, arrayLength - 1, - TEXTOID, -1, false, TYPALIGN_INT); + a = construct_array_builtin(dvalues, arrayLength - 1, TEXTOID); repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a); } diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 00a6d282cf..b016eecb2c 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -468,10 +468,8 @@ interpret_function_parameter_list(ParseState *pstate, if (outCount > 0 || varCount > 0) { - *allParameterTypes = construct_array(allTypes, parameterCount, OIDOID, - sizeof(Oid), true, TYPALIGN_INT); - *parameterModes = construct_array(paramModes, parameterCount, CHAROID, - 1, true, TYPALIGN_CHAR); + *allParameterTypes = construct_array_builtin(allTypes, parameterCount, OIDOID); + *parameterModes = construct_array_builtin(paramModes, parameterCount, CHAROID); if (outCount > 1) *requiredResultType = RECORDOID; /* otherwise we set requiredResultType correctly above */ @@ -489,8 +487,7 @@ interpret_function_parameter_list(ParseState *pstate, if (paramNames[i] == PointerGetDatum(NULL)) paramNames[i] = CStringGetTextDatum(""); } - *parameterNames = construct_array(paramNames, parameterCount, TEXTOID, - -1, false, TYPALIGN_INT); + *parameterNames = construct_array_builtin(paramNames, parameterCount, TEXTOID); } else *parameterNames = NULL; @@ -1222,8 +1219,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt) i = 0; foreach(lc, trftypes_list) arr[i++] = ObjectIdGetDatum(lfirst_oid(lc)); - trftypes = construct_array(arr, list_length(trftypes_list), - OIDOID, sizeof(Oid), true, TYPALIGN_INT); + trftypes = construct_array_builtin(arr, list_length(trftypes_list), OIDOID); } else { diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c index a59ee3b947..d9dff9ecaa 100644 --- a/src/backend/commands/policy.c +++ b/src/backend/commands/policy.c @@ -500,8 +500,7 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id) memset(isnull, 0, sizeof(isnull)); /* This is the array for the new tuple */ - role_ids = construct_array(role_oids, num_roles, OIDOID, - sizeof(Oid), true, TYPALIGN_INT); + role_ids = construct_array_builtin(role_oids, num_roles, OIDOID); replaces[Anum_pg_policy_polroles - 1] = true; values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids); @@ -617,8 +616,7 @@ CreatePolicy(CreatePolicyStmt *stmt) /* Collect role ids */ role_oids = policy_role_list_to_array(stmt->roles, &nitems); - role_ids = construct_array(role_oids, nitems, OIDOID, - sizeof(Oid), true, TYPALIGN_INT); + role_ids = construct_array_builtin(role_oids, nitems, OIDOID); /* Parse the supplied clause */ qual_pstate = make_parsestate(NULL); @@ -801,8 +799,7 @@ AlterPolicy(AlterPolicyStmt *stmt) if (stmt->roles != NULL) { role_oids = policy_role_list_to_array(stmt->roles, &nitems); - role_ids = construct_array(role_oids, nitems, OIDOID, - sizeof(Oid), true, TYPALIGN_INT); + role_ids = construct_array_builtin(role_oids, nitems, OIDOID); } /* Get id of table. Also handles permissions checks. */ diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index 80738547ed..633c9a40bb 100644 --- a/src/backend/commands/prepare.c +++ b/src/backend/commands/prepare.c @@ -722,8 +722,6 @@ build_regtype_array(Oid *param_types, int num_params) for (i = 0; i < num_params; i++) tmp_ary[i] = ObjectIdGetDatum(param_types[i]); - /* XXX: this hardcodes assumptions about the regtype type */ - result = construct_array(tmp_ary, num_params, REGTYPEOID, - 4, true, TYPALIGN_INT); + result = construct_array_builtin(tmp_ary, num_params, REGTYPEOID); return PointerGetDatum(result); } diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c index 54a190722d..e54c2d90c9 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -466,7 +466,7 @@ CreateStatistics(CreateStatsStmt *stmt) if (build_expressions) types[ntypes++] = CharGetDatum(STATS_EXT_EXPRESSIONS); Assert(ntypes > 0 && ntypes <= lengthof(types)); - stxkind = construct_array(types, ntypes, CHAROID, 1, true, TYPALIGN_CHAR); + stxkind = construct_array_builtin(types, ntypes, CHAROID); /* convert the expressions (if any) to a text datum */ if (stxexprs != NIL) diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index b94236f74d..2e5f7b0b55 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -494,8 +494,7 @@ publicationListToArray(List *publist) MemoryContextSwitchTo(oldcxt); - arr = construct_array(datums, list_length(publist), - TEXTOID, -1, false, TYPALIGN_INT); + arr = construct_array_builtin(datums, list_length(publist), TEXTOID); MemoryContextDelete(memcxt); diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 9b92b04242..4f5e7c7ccb 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -1893,12 +1893,9 @@ makeMultirangeConstructors(const char *name, Oid namespace, /* n-arg constructor - vararg */ argtypes = buildoidvector(&rangeArrayOid, 1); allParamTypes = ObjectIdGetDatum(rangeArrayOid); - allParameterTypes = construct_array(&allParamTypes, - 1, OIDOID, - sizeof(Oid), true, TYPALIGN_INT); + allParameterTypes = construct_array_builtin(&allParamTypes, 1, OIDOID); paramModes = CharGetDatum(FUNC_PARAM_VARIADIC); - parameterModes = construct_array(¶mModes, 1, CHAROID, - 1, true, TYPALIGN_CHAR); + parameterModes = construct_array_builtin(¶mModes, 1, CHAROID); myself = ProcedureCreate(name, /* name: same as multirange type */ namespace, false, /* replace */ diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index 4116d1f3b5..a1c6325d64 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -206,9 +206,7 @@ TidListEval(TidScanState *tidstate) if (isNull) continue; itemarray = DatumGetArrayTypeP(arraydatum); - deconstruct_array(itemarray, - TIDOID, sizeof(ItemPointerData), false, TYPALIGN_SHORT, - &ipdatums, &ipnulls, &ndatums); + deconstruct_array_builtin(itemarray, TIDOID, &ipdatums, &ipnulls, &ndatums); if (numTids + ndatums > numAllocTids) { numAllocTids = numTids + ndatums; diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c index 307114a30d..f7ad689459 100644 --- a/src/backend/parser/parse_type.c +++ b/src/backend/parser/parse_type.c @@ -411,9 +411,7 @@ typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ) datums[n++] = CStringGetDatum(cstr); } - /* hardwired knowledge about cstring's representation details here */ - arrtypmod = construct_array(datums, n, CSTRINGOID, - -2, false, TYPALIGN_CHAR); + arrtypmod = construct_array_builtin(datums, n, CSTRINGOID); /* arrange to report location if type's typmodin function fails */ setup_parser_errposition_callback(&pcbstate, pstate, typeName->location); diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 1a64a52279..f889726a28 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -1642,9 +1642,7 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx, elog(ERROR, "null conexclop for constraint %u", constraintId); - deconstruct_array(DatumGetArrayTypeP(datum), - OIDOID, sizeof(Oid), true, TYPALIGN_INT, - &elems, NULL, &nElems); + deconstruct_array_builtin(DatumGetArrayTypeP(datum), OIDOID, &elems, NULL, &nElems); for (i = 0; i < nElems; i++) { diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c index 6058d36e0d..7fa2b2cba7 100644 --- a/src/backend/replication/logical/logicalfuncs.c +++ b/src/backend/replication/logical/logicalfuncs.c @@ -172,8 +172,7 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin Assert(ARR_ELEMTYPE(arr) == TEXTOID); - deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT, - &datum_opts, NULL, &nelems); + deconstruct_array_builtin(arr, TEXTOID, &datum_opts, NULL, &nelems); if (nelems % 2 != 0) ereport(ERROR, diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c index ca48395d5c..7c02fb279f 100644 --- a/src/backend/statistics/extended_stats.c +++ b/src/backend/statistics/extended_stats.c @@ -2345,10 +2345,7 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs) for (n = 0; n < nnum; n++) numdatums[n] = Float4GetDatum(stats->stanumbers[k][n]); - /* XXX knows more than it should about type float4: */ - arry = construct_array(numdatums, nnum, - FLOAT4OID, - sizeof(float4), true, TYPALIGN_INT); + arry = construct_array_builtin(numdatums, nnum, FLOAT4OID); values[i++] = PointerGetDatum(arry); /* stanumbersN */ } else diff --git a/src/backend/tsearch/dict.c b/src/backend/tsearch/dict.c index 8dae2b8e99..c6ea9f9269 100644 --- a/src/backend/tsearch/dict.c +++ b/src/backend/tsearch/dict.c @@ -68,12 +68,7 @@ ts_lexize(PG_FUNCTION_ARGS) ptr++; } - a = construct_array(da, - ptr - res, - TEXTOID, - -1, - false, - TYPALIGN_INT); + a = construct_array_builtin(da, ptr - res, TEXTOID); ptr = res; while (ptr->lexeme) diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 78e951a6bc..9f22349a0d 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -3330,6 +3330,88 @@ construct_array(Datum *elems, int nelems, elmtype, elmlen, elmbyval, elmalign); } +/* + * 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. + */ +ArrayType * +construct_array_builtin(Datum *elems, int nelems, Oid elmtype) +{ + int elmlen; + bool elmbyval; + char elmalign; + + switch (elmtype) + { + case CHAROID: + elmlen = 1; + elmbyval = true; + elmalign = TYPALIGN_CHAR; + break; + + case CSTRINGOID: + elmlen = -2; + elmbyval = false; + elmalign = TYPALIGN_CHAR; + break; + + case FLOAT4OID: + elmlen = sizeof(float4); + elmbyval = true; + elmalign = TYPALIGN_INT; + break; + + case INT2OID: + elmlen = sizeof(int16); + elmbyval = true; + elmalign = TYPALIGN_SHORT; + break; + + case INT4OID: + elmlen = sizeof(int32); + elmbyval = true; + elmalign = TYPALIGN_INT; + break; + + case INT8OID: + elmlen = sizeof(int64); + elmbyval = FLOAT8PASSBYVAL; + elmalign = TYPALIGN_DOUBLE; + break; + + case NAMEOID: + elmlen = NAMEDATALEN; + elmbyval = false; + elmalign = TYPALIGN_CHAR; + break; + + case OIDOID: + case REGTYPEOID: + elmlen = sizeof(Oid); + elmbyval = true; + elmalign = TYPALIGN_INT; + break; + + case TEXTOID: + elmlen = -1; + elmbyval = false; + elmalign = TYPALIGN_INT; + break; + + case TIDOID: + elmlen = sizeof(ItemPointerData); + elmbyval = false; + elmalign = TYPALIGN_SHORT; + break; + + default: + elog(ERROR, "type %u not supported here", elmtype); + } + + return construct_array(elems, nelems, elmtype, elmlen, elmbyval, elmalign); +} + /* * construct_md_array --- simple method for constructing an array object * with arbitrary dimensions and possible NULLs @@ -3483,9 +3565,9 @@ construct_empty_expanded_array(Oid element_type, * 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, in most current - * uses the type is hard-wired into the caller and so we can save a lookup - * cycle by hard-wiring the type info as well. + * 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, @@ -3548,6 +3630,71 @@ deconstruct_array(ArrayType *array, } } +/* + * Like deconstruct_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. + */ +void +deconstruct_array_builtin(ArrayType *array, + Oid elmtype, + Datum **elemsp, bool **nullsp, int *nelemsp) +{ + int elmlen; + bool elmbyval; + char elmalign; + + switch (elmtype) + { + case CHAROID: + elmlen = 1; + elmbyval = true; + elmalign = TYPALIGN_CHAR; + break; + + case CSTRINGOID: + elmlen = -2; + elmbyval = false; + elmalign = TYPALIGN_CHAR; + break; + + case FLOAT8OID: + elmlen = sizeof(float8); + elmbyval = FLOAT8PASSBYVAL; + elmalign = TYPALIGN_DOUBLE; + break; + + case INT2OID: + elmlen = sizeof(int16); + elmbyval = true; + elmalign = TYPALIGN_SHORT; + break; + + case OIDOID: + elmlen = sizeof(Oid); + elmbyval = true; + elmalign = TYPALIGN_INT; + break; + + case TEXTOID: + elmlen = -1; + elmbyval = false; + elmalign = TYPALIGN_INT; + break; + + case TIDOID: + elmlen = sizeof(ItemPointerData); + elmbyval = false; + elmalign = TYPALIGN_SHORT; + break; + + default: + elog(ERROR, "type %u not supported here", elmtype); + } + + deconstruct_array(array, elmtype, elmlen, elmbyval, elmalign, elemsp, nullsp, nelemsp); +} + /* * array_contains_nulls --- detect whether an array has any null elements * diff --git a/src/backend/utils/adt/arrayutils.c b/src/backend/utils/adt/arrayutils.c index 464a37641e..051169a149 100644 --- a/src/backend/utils/adt/arrayutils.c +++ b/src/backend/utils/adt/arrayutils.c @@ -249,10 +249,7 @@ ArrayGetIntegerTypmods(ArrayType *arr, int *n) (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("typmod array must not contain nulls"))); - /* hardwired knowledge about cstring's representation details here */ - deconstruct_array(arr, CSTRINGOID, - -2, false, TYPALIGN_CHAR, - &elem_values, NULL, n); + deconstruct_array_builtin(arr, CSTRINGOID, &elem_values, NULL, n); result = (int32 *) palloc(*n * sizeof(int32)); diff --git a/src/backend/utils/adt/hbafuncs.c b/src/backend/utils/adt/hbafuncs.c index 9fe7b62c9a..598259718c 100644 --- a/src/backend/utils/adt/hbafuncs.c +++ b/src/backend/utils/adt/hbafuncs.c @@ -151,7 +151,7 @@ get_hba_options(HbaLine *hba) Assert(noptions <= MAX_HBA_OPTIONS); if (noptions > 0) - return construct_array(options, noptions, TEXTOID, -1, false, TYPALIGN_INT); + return construct_array_builtin(options, noptions, TEXTOID); else return NULL; } diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c index 63649ba735..73dd35f6ec 100644 --- a/src/backend/utils/adt/json.c +++ b/src/backend/utils/adt/json.c @@ -1447,9 +1447,7 @@ json_object(PG_FUNCTION_ARGS) errmsg("wrong number of array subscripts"))); } - deconstruct_array(in_array, - TEXTOID, -1, false, TYPALIGN_INT, - &in_datums, &in_nulls, &in_count); + deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count); count = in_count / 2; @@ -1523,13 +1521,8 @@ json_object_two_arg(PG_FUNCTION_ARGS) if (nkdims == 0) PG_RETURN_DATUM(CStringGetTextDatum("{}")); - deconstruct_array(key_array, - TEXTOID, -1, false, TYPALIGN_INT, - &key_datums, &key_nulls, &key_count); - - deconstruct_array(val_array, - TEXTOID, -1, false, TYPALIGN_INT, - &val_datums, &val_nulls, &val_count); + deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count); + deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count); if (key_count != val_count) ereport(ERROR, diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c index 26d81366c9..f70576f1c0 100644 --- a/src/backend/utils/adt/jsonb.c +++ b/src/backend/utils/adt/jsonb.c @@ -1376,9 +1376,7 @@ jsonb_object(PG_FUNCTION_ARGS) errmsg("wrong number of array subscripts"))); } - deconstruct_array(in_array, - TEXTOID, -1, false, TYPALIGN_INT, - &in_datums, &in_nulls, &in_count); + deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count); count = in_count / 2; @@ -1464,13 +1462,8 @@ jsonb_object_two_arg(PG_FUNCTION_ARGS) if (nkdims == 0) goto close_object; - deconstruct_array(key_array, - TEXTOID, -1, false, TYPALIGN_INT, - &key_datums, &key_nulls, &key_count); - - deconstruct_array(val_array, - TEXTOID, -1, false, TYPALIGN_INT, - &val_datums, &val_nulls, &val_count); + deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count); + deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count); if (key_count != val_count) ereport(ERROR, diff --git a/src/backend/utils/adt/jsonb_gin.c b/src/backend/utils/adt/jsonb_gin.c index 5edf278cdb..c5325acde4 100644 --- a/src/backend/utils/adt/jsonb_gin.c +++ b/src/backend/utils/adt/jsonb_gin.c @@ -885,9 +885,7 @@ gin_extract_jsonb_query(PG_FUNCTION_ARGS) int i, j; - deconstruct_array(query, - TEXTOID, -1, false, TYPALIGN_INT, - &key_datums, &key_nulls, &key_count); + deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count); entries = (Datum *) palloc(sizeof(Datum) * key_count); diff --git a/src/backend/utils/adt/jsonb_op.c b/src/backend/utils/adt/jsonb_op.c index ed37252e7f..202367e996 100644 --- a/src/backend/utils/adt/jsonb_op.c +++ b/src/backend/utils/adt/jsonb_op.c @@ -53,8 +53,7 @@ jsonb_exists_any(PG_FUNCTION_ARGS) bool *key_nulls; int elem_count; - deconstruct_array(keys, TEXTOID, -1, false, TYPALIGN_INT, - &key_datums, &key_nulls, &elem_count); + deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count); for (i = 0; i < elem_count; i++) { @@ -86,8 +85,7 @@ jsonb_exists_all(PG_FUNCTION_ARGS) bool *key_nulls; int elem_count; - deconstruct_array(keys, TEXTOID, -1, false, TYPALIGN_INT, - &key_datums, &key_nulls, &elem_count); + deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count); for (i = 0; i < elem_count; i++) { diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index d1356d6416..2a3f656899 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -1000,8 +1000,7 @@ get_path_all(FunctionCallInfo fcinfo, bool as_text) if (array_contains_nulls(path)) PG_RETURN_NULL(); - deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT, - &pathtext, &pathnulls, &npath); + deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath); tpath = palloc(npath * sizeof(char *)); ipath = palloc(npath * sizeof(int)); @@ -1456,8 +1455,7 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text) if (array_contains_nulls(path)) PG_RETURN_NULL(); - deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT, - &pathtext, &pathnulls, &npath); + deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath); res = jsonb_get_element(jb, pathtext, npath, &isnull, as_text); @@ -4369,8 +4367,7 @@ jsonb_delete_array(PG_FUNCTION_ARGS) if (JB_ROOT_COUNT(in) == 0) PG_RETURN_JSONB_P(in); - deconstruct_array(keys, TEXTOID, -1, false, TYPALIGN_INT, - &keys_elems, &keys_nulls, &keys_len); + deconstruct_array_builtin(keys, TEXTOID, &keys_elems, &keys_nulls, &keys_len); if (keys_len == 0) PG_RETURN_JSONB_P(in); @@ -4522,8 +4519,7 @@ jsonb_set(PG_FUNCTION_ARGS) if (JB_ROOT_COUNT(in) == 0 && !create) PG_RETURN_JSONB_P(in); - deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT, - &path_elems, &path_nulls, &path_len); + deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len); if (path_len == 0) PG_RETURN_JSONB_P(in); @@ -4634,8 +4630,7 @@ jsonb_delete_path(PG_FUNCTION_ARGS) if (JB_ROOT_COUNT(in) == 0) PG_RETURN_JSONB_P(in); - deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT, - &path_elems, &path_nulls, &path_len); + deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len); if (path_len == 0) PG_RETURN_JSONB_P(in); @@ -4680,8 +4675,7 @@ jsonb_insert(PG_FUNCTION_ARGS) (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("cannot set path in scalar"))); - deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT, - &path_elems, &path_nulls, &path_len); + deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len); if (path_len == 0) PG_RETURN_JSONB_P(in); diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c index 023a004ac8..dedee7af5c 100644 --- a/src/backend/utils/adt/lockfuncs.c +++ b/src/backend/utils/adt/lockfuncs.c @@ -538,10 +538,7 @@ pg_blocking_pids(PG_FUNCTION_ARGS) /* Assert we didn't overrun arrayelems[] */ Assert(narrayelems <= lockData->nlocks); - /* Construct array, using hardwired knowledge about int4 type */ - PG_RETURN_ARRAYTYPE_P(construct_array(arrayelems, narrayelems, - INT4OID, - sizeof(int32), true, TYPALIGN_INT)); + PG_RETURN_ARRAYTYPE_P(construct_array_builtin(arrayelems, narrayelems, INT4OID)); } @@ -579,10 +576,7 @@ pg_safe_snapshot_blocking_pids(PG_FUNCTION_ARGS) else blocker_datums = NULL; - /* Construct array, using hardwired knowledge about int4 type */ - PG_RETURN_ARRAYTYPE_P(construct_array(blocker_datums, num_blockers, - INT4OID, - sizeof(int32), true, TYPALIGN_INT)); + PG_RETURN_ARRAYTYPE_P(construct_array_builtin(blocker_datums, num_blockers, INT4OID)); } diff --git a/src/backend/utils/adt/name.c b/src/backend/utils/adt/name.c index e8bba3670c..d22e1f277b 100644 --- a/src/backend/utils/adt/name.c +++ b/src/backend/utils/adt/name.c @@ -314,11 +314,7 @@ current_schemas(PG_FUNCTION_ARGS) } list_free(search_path); - array = construct_array(names, i, - NAMEOID, - NAMEDATALEN, /* sizeof(Name) */ - false, /* Name is not by-val */ - TYPALIGN_CHAR); /* alignment of Name */ + array = construct_array_builtin(names, i, NAMEOID); PG_RETURN_POINTER(array); } diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c index 6d4f6b7dca..185b2cb848 100644 --- a/src/backend/utils/adt/orderedsetaggs.c +++ b/src/backend/utils/adt/orderedsetaggs.c @@ -759,12 +759,10 @@ percentile_disc_multi_final(PG_FUNCTION_ARGS) PG_RETURN_NULL(); param = PG_GETARG_ARRAYTYPE_P(1); - deconstruct_array(param, FLOAT8OID, - /* hard-wired info on type float8 */ - sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE, - &percentiles_datum, - &percentiles_null, - &num_percentiles); + deconstruct_array_builtin(param, FLOAT8OID, + &percentiles_datum, + &percentiles_null, + &num_percentiles); if (num_percentiles == 0) PG_RETURN_POINTER(construct_empty_array(osastate->qstate->sortColType)); @@ -883,12 +881,10 @@ percentile_cont_multi_final_common(FunctionCallInfo fcinfo, PG_RETURN_NULL(); param = PG_GETARG_ARRAYTYPE_P(1); - deconstruct_array(param, FLOAT8OID, - /* hard-wired info on type float8 */ - sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE, - &percentiles_datum, - &percentiles_null, - &num_percentiles); + deconstruct_array_builtin(param, FLOAT8OID, + &percentiles_datum, + &percentiles_null, + &num_percentiles); if (num_percentiles == 0) PG_RETURN_POINTER(construct_empty_array(osastate->qstate->sortColType)); diff --git a/src/backend/utils/adt/pg_upgrade_support.c b/src/backend/utils/adt/pg_upgrade_support.c index 67b9675e92..65764d78a3 100644 --- a/src/backend/utils/adt/pg_upgrade_support.c +++ b/src/backend/utils/adt/pg_upgrade_support.c @@ -214,9 +214,7 @@ binary_upgrade_create_empty_extension(PG_FUNCTION_ARGS) int ndatums; int i; - deconstruct_array(textArray, - TEXTOID, -1, false, TYPALIGN_INT, - &textDatums, NULL, &ndatums); + deconstruct_array_builtin(textArray, TEXTOID, &textDatums, NULL, &ndatums); for (i = 0; i < ndatums; i++) { char *extName = TextDatumGetCString(textDatums[i]); diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 5d49f564a2..4d714666d5 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -2399,9 +2399,8 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, if (isnull) elog(ERROR, "null indkey for index %u", indexId); - deconstruct_array(DatumGetArrayTypeP(cols), - INT2OID, 2, true, TYPALIGN_SHORT, - &keys, NULL, &nKeys); + deconstruct_array_builtin(DatumGetArrayTypeP(cols), INT2OID, + &keys, NULL, &nKeys); for (j = keyatts; j < nKeys; j++) { @@ -2524,9 +2523,8 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, elog(ERROR, "null conexclop for constraint %u", constraintId); - deconstruct_array(DatumGetArrayTypeP(val), - OIDOID, sizeof(Oid), true, TYPALIGN_INT, - &elems, NULL, &nElems); + deconstruct_array_builtin(DatumGetArrayTypeP(val), OIDOID, + &elems, NULL, &nElems); operators = (Oid *) palloc(nElems * sizeof(Oid)); for (i = 0; i < nElems; i++) @@ -2580,9 +2578,8 @@ decompile_column_index_array(Datum column_index_array, Oid relId, int j; /* Extract data from array of int16 */ - deconstruct_array(DatumGetArrayTypeP(column_index_array), - INT2OID, 2, true, TYPALIGN_SHORT, - &keys, NULL, &nKeys); + deconstruct_array_builtin(DatumGetArrayTypeP(column_index_array), INT2OID, + &keys, NULL, &nKeys); for (j = 0; j < nKeys; j++) { @@ -12715,9 +12712,8 @@ get_reloptions(StringInfo buf, Datum reloptions) int noptions; int i; - deconstruct_array(DatumGetArrayTypeP(reloptions), - TEXTOID, -1, false, TYPALIGN_INT, - &options, NULL, &noptions); + deconstruct_array_builtin(DatumGetArrayTypeP(reloptions), TEXTOID, + &options, NULL, &noptions); for (i = 0; i < noptions; i++) { diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c index addc349151..1786c18f89 100644 --- a/src/backend/utils/adt/tsvector_op.c +++ b/src/backend/utils/adt/tsvector_op.c @@ -308,8 +308,7 @@ tsvector_setweight_by_filter(PG_FUNCTION_ARGS) memcpy(tsout, tsin, VARSIZE(tsin)); entry = ARRPTR(tsout); - deconstruct_array(lexemes, TEXTOID, -1, false, TYPALIGN_INT, - &dlexemes, &nulls, &nlexemes); + deconstruct_array_builtin(lexemes, TEXTOID, &dlexemes, &nulls, &nlexemes); /* * Assuming that lexemes array is significantly shorter than tsvector we @@ -586,8 +585,7 @@ tsvector_delete_arr(PG_FUNCTION_ARGS) Datum *dlexemes; bool *nulls; - deconstruct_array(lexemes, TEXTOID, -1, false, TYPALIGN_INT, - &dlexemes, &nulls, &nlex); + deconstruct_array_builtin(lexemes, TEXTOID, &dlexemes, &nulls, &nlex); /* * In typical use case array of lexemes to delete is relatively small. So @@ -694,10 +692,8 @@ tsvector_unnest(PG_FUNCTION_ARGS) 1)); } - values[1] = PointerGetDatum(construct_array(positions, posv->npos, - INT2OID, 2, true, TYPALIGN_SHORT)); - values[2] = PointerGetDatum(construct_array(weights, posv->npos, - TEXTOID, -1, false, TYPALIGN_INT)); + values[1] = PointerGetDatum(construct_array_builtin(positions, posv->npos, INT2OID)); + values[2] = PointerGetDatum(construct_array_builtin(weights, posv->npos, TEXTOID)); } else { @@ -733,7 +729,7 @@ tsvector_to_array(PG_FUNCTION_ARGS) arrin[i].len)); } - array = construct_array(elements, tsin->size, TEXTOID, -1, false, TYPALIGN_INT); + array = construct_array_builtin(elements, tsin->size, TEXTOID); pfree(elements); PG_FREE_IF_COPY(tsin, 0); @@ -757,7 +753,7 @@ array_to_tsvector(PG_FUNCTION_ARGS) datalen = 0; char *cur; - deconstruct_array(v, TEXTOID, -1, false, TYPALIGN_INT, &dlexemes, &nulls, &nitems); + deconstruct_array_builtin(v, TEXTOID, &dlexemes, &nulls, &nitems); /* * Reject nulls and zero length strings (maybe we should just ignore them, @@ -833,8 +829,7 @@ tsvector_filter(PG_FUNCTION_ARGS) int cur_pos = 0; char mask = 0; - deconstruct_array(weights, CHAROID, 1, true, TYPALIGN_CHAR, - &dweights, &nulls, &nweights); + deconstruct_array_builtin(weights, CHAROID, &dweights, &nulls, &nweights); for (i = 0; i < nweights; i++) { diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 1ec6f1c2fd..60a85c4697 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -4017,9 +4017,9 @@ xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces, Assert(ARR_ELEMTYPE(namespaces) == TEXTOID); - deconstruct_array(namespaces, TEXTOID, -1, false, TYPALIGN_INT, - &ns_names_uris, &ns_names_uris_nulls, - &ns_count); + deconstruct_array_builtin(namespaces, TEXTOID, + &ns_names_uris, &ns_names_uris_nulls, + &ns_count); Assert((ns_count % 2) == 0); /* checked above */ ns_count /= 2; /* count pairs only */ diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c index 3a9c9f0c50..f7f7165f7f 100644 --- a/src/backend/utils/cache/evtcache.c +++ b/src/backend/utils/cache/evtcache.c @@ -228,8 +228,7 @@ DecodeTextArrayToBitmapset(Datum array) if (ARR_NDIM(arr) != 1 || ARR_HASNULL(arr) || ARR_ELEMTYPE(arr) != TEXTOID) elog(ERROR, "expected 1-D text array"); - deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT, - &elems, NULL, &nelems); + deconstruct_array_builtin(arr, TEXTOID, &elems, NULL, &nelems); for (bms = NULL, i = 0; i < nelems; ++i) { diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c index 9197b0f1e2..a1fe50ffca 100644 --- a/src/backend/utils/fmgr/funcapi.c +++ b/src/backend/utils/fmgr/funcapi.c @@ -1390,9 +1390,8 @@ get_func_arg_info(HeapTuple procTup, *p_argnames = NULL; else { - deconstruct_array(DatumGetArrayTypeP(proargnames), - TEXTOID, -1, false, TYPALIGN_INT, - &elems, NULL, &nelems); + deconstruct_array_builtin(DatumGetArrayTypeP(proargnames), TEXTOID, + &elems, NULL, &nelems); if (nelems != numargs) /* should not happen */ elog(ERROR, "proargnames must have the same number of elements as the function has arguments"); *p_argnames = (char **) palloc(sizeof(char *) * numargs); @@ -1506,8 +1505,7 @@ get_func_input_arg_names(Datum proargnames, Datum proargmodes, ARR_HASNULL(arr) || ARR_ELEMTYPE(arr) != TEXTOID) elog(ERROR, "proargnames is not a 1-D text array or it contains nulls"); - deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT, - &argnames, NULL, &numargs); + deconstruct_array_builtin(arr, TEXTOID, &argnames, NULL, &numargs); if (proargmodes != PointerGetDatum(NULL)) { arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */ @@ -1621,8 +1619,7 @@ get_func_result_name(Oid functionId) ARR_ELEMTYPE(arr) != TEXTOID) elog(ERROR, "proargnames is not a 1-D text array of length %d or it contains nulls", numargs); - deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT, - &argnames, NULL, &nargnames); + deconstruct_array_builtin(arr, TEXTOID, &argnames, NULL, &nargnames); Assert(nargnames == numargs); /* scan for output argument(s) */ @@ -1770,8 +1767,7 @@ build_function_result_tupdesc_d(char prokind, ARR_ELEMTYPE(arr) != TEXTOID) elog(ERROR, "proargnames is not a 1-D text array of length %d or it contains nulls", numargs); - deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT, - &argnames, NULL, &nargnames); + deconstruct_array_builtin(arr, TEXTOID, &argnames, NULL, &nargnames); Assert(nargnames == numargs); } diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 8e9b71375c..23f2cb4f8e 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -9958,7 +9958,7 @@ pg_settings_get_flags(PG_FUNCTION_ARGS) Assert(cnt <= MAX_GUC_FLAGS); /* Returns the record as Datum */ - a = construct_array(flags, cnt, TEXTOID, -1, false, TYPALIGN_INT); + a = construct_array_builtin(flags, cnt, TEXTOID); PG_RETURN_ARRAYTYPE_P(a); } @@ -11491,9 +11491,7 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value) TYPALIGN_INT /* TEXT's typalign */ ); } else - a = construct_array(&datum, 1, - TEXTOID, - -1, false, TYPALIGN_INT); + a = construct_array_builtin(&datum, 1, TEXTOID); return a; } @@ -11560,9 +11558,7 @@ GUCArrayDelete(ArrayType *array, const char *name) false /* TEXT's typbyval */ , TYPALIGN_INT /* TEXT's typalign */ ); else - newarray = construct_array(&d, 1, - TEXTOID, - -1, false, TYPALIGN_INT); + newarray = construct_array_builtin(&d, 1, TEXTOID); index++; } @@ -11628,9 +11624,7 @@ GUCArrayReset(ArrayType *array) false /* TEXT's typbyval */ , TYPALIGN_INT /* TEXT's typalign */ ); else - newarray = construct_array(&d, 1, - TEXTOID, - -1, false, TYPALIGN_INT); + newarray = construct_array_builtin(&d, 1, TEXTOID); index++; pfree(val); diff --git a/src/include/utils/array.h b/src/include/utils/array.h index 656c766a9a..2f794d1168 100644 --- a/src/include/utils/array.h +++ b/src/include/utils/array.h @@ -387,6 +387,7 @@ 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); +extern ArrayType *construct_array_builtin(Datum *elems, int nelems, Oid elmtype); extern ArrayType *construct_md_array(Datum *elems, bool *nulls, int ndims, @@ -401,6 +402,9 @@ extern void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp); +extern void deconstruct_array_builtin(ArrayType *array, + Oid elmtype, + Datum **elemsp, bool **nullsp, int *nelemsp); extern bool array_contains_nulls(ArrayType *array); extern ArrayBuildState *initArrayResult(Oid element_type, diff --git a/src/test/modules/test_rls_hooks/test_rls_hooks.c b/src/test/modules/test_rls_hooks/test_rls_hooks.c index 4f862d081b..41bfc776ae 100644 --- a/src/test/modules/test_rls_hooks/test_rls_hooks.c +++ b/src/test/modules/test_rls_hooks/test_rls_hooks.c @@ -87,7 +87,7 @@ test_rls_hooks_permissive(CmdType cmdtype, Relation relation) policy->policy_name = pstrdup("extension policy"); policy->polcmd = '*'; - policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true, TYPALIGN_INT); + policy->roles = construct_array_builtin(&role, 1, OIDOID); /* * policy->qual = (Expr *) makeConst(BOOLOID, -1, InvalidOid, @@ -155,7 +155,7 @@ test_rls_hooks_restrictive(CmdType cmdtype, Relation relation) policy->policy_name = pstrdup("extension policy"); policy->polcmd = '*'; - policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true, TYPALIGN_INT); + policy->roles = construct_array_builtin(&role, 1, OIDOID); n = makeFuncCall(list_make2(makeString("pg_catalog"), makeString("current_user")), -- 2.35.1