v19-0002-Subscripting-for-array.patch
application/octet-stream
Filename: v19-0002-Subscripting-for-array.patch
Type: application/octet-stream
Part: 3
Patch
Format: format-patch
Series: patch v19-0002
Subject: Subscripting for array
| File | + | − |
|---|---|---|
| src/backend/catalog/Catalog.pm | 1 | 0 |
| src/backend/catalog/heap.c | 1 | 1 |
| src/backend/commands/typecmds.c | 4 | 4 |
| src/backend/executor/execExprInterp.c | 13 | 2 |
| src/backend/nodes/nodeFuncs.c | 1 | 1 |
| src/backend/parser/parse_node.c | 0 | 11 |
| src/backend/parser/parse_target.c | 3 | 1 |
| src/backend/utils/adt/arrayfuncs.c | 289 | 0 |
| src/include/catalog/pg_proc.dat | 7 | 0 |
| src/include/catalog/pg_type.dat | 19 | 11 |
| src/test/regress/expected/arrays.out | 6 | 6 |
| src/test/regress/sql/arrays.sql | 2 | 2 |
From 1ab5d44aa22c24a36034501cdba6977ec63b1282 Mon Sep 17 00:00:00 2001
From: erthalion <9erthalion6@gmail.com>
Date: Fri, 1 Feb 2019 11:38:52 +0100
Subject: [PATCH v19 2/4] Subscripting for array
Subscripting implementation for array data types. It includes all array
specific parts, that were removed from the generalized code. Note, that
for some array-like data types it's not necessary to assign
array_subscript_handler explicitely, since it's done in Catalog.pm
Reviewed-by: Tom Lane, Arthur Zakirov
---
src/backend/catalog/Catalog.pm | 1 +
src/backend/catalog/heap.c | 2 +-
src/backend/commands/typecmds.c | 8 +-
src/backend/executor/execExprInterp.c | 15 +-
src/backend/nodes/nodeFuncs.c | 2 +-
src/backend/parser/parse_node.c | 11 --
src/backend/parser/parse_target.c | 4 +-
src/backend/utils/adt/arrayfuncs.c | 289 ++++++++++++++++++++++++++++++++++
src/include/catalog/pg_proc.dat | 7 +
src/include/catalog/pg_type.dat | 30 ++--
src/test/regress/expected/arrays.out | 12 +-
src/test/regress/sql/arrays.sql | 4 +-
12 files changed, 346 insertions(+), 39 deletions(-)
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index 3bf308fe3b..830c5bd557 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -385,6 +385,7 @@ sub GenerateArrayTypes
# Arrays require INT alignment, unless the element type requires
# DOUBLE alignment.
$array_type{typalign} = $elem_type->{typalign} eq 'd' ? 'd' : 'i';
+ $array_type{typsubshandler} = 'array_subscript_handler';
# Fill in the rest of the array entry's fields.
foreach my $column (@$pgtype_schema)
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index e945bb566a..28ab9d9d8a 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -1296,7 +1296,7 @@ heap_create_with_catalog(const char *relname,
0, /* array dimensions for typBaseType */
false, /* Type NOT NULL */
InvalidOid, /* rowtypes never have a collation */
- 0); /* array implementation */
+ F_ARRAY_SUBSCRIPT_HANDLER); /* array implementation */
pfree(relarrayname);
}
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 7b0046aea5..39eb3e8ab9 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -689,7 +689,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
0, /* Array dimensions of typbasetype */
false, /* Type NOT NULL */
collation, /* type's collation */
- 0);
+ F_ARRAY_SUBSCRIPT_HANDLER);
pfree(array_type);
@@ -1129,7 +1129,7 @@ DefineDomain(CreateDomainStmt *stmt)
0, /* Array dimensions of typbasetype */
false, /* Type NOT NULL */
domaincoll, /* type's collation */
- 0); /* array subscripting implementation */
+ F_ARRAY_SUBSCRIPT_HANDLER); /* array subscripting implementation */
pfree(domainArrayName);
@@ -1286,7 +1286,7 @@ DefineEnum(CreateEnumStmt *stmt)
0, /* Array dimensions of typbasetype */
false, /* Type NOT NULL */
InvalidOid, /* type's collation */
- 0); /* array subscripting implementation */
+ F_ARRAY_SUBSCRIPT_HANDLER); /* array subscripting implementation */
pfree(enumArrayName);
@@ -1618,7 +1618,7 @@ DefineRange(CreateRangeStmt *stmt)
0, /* Array dimensions of typbasetype */
false, /* Type NOT NULL */
InvalidOid, /* typcollation */
- 0); /* array subscripting implementation */
+ F_ARRAY_SUBSCRIPT_HANDLER); /* array subscripting implementation */
pfree(rangeArrayName);
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index f90145fe52..1c47ceff2f 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -3067,7 +3067,7 @@ ExecEvalSubscriptingRef(ExprState *state, ExprEvalStep *op)
if (sbsrefstate->isassignment)
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
- errmsg("array subscript in assignment must not be null")));
+ errmsg("subscript in assignment must not be null")));
*op->resnull = true;
return false;
}
@@ -3139,9 +3139,20 @@ ExecEvalSubscriptingRefOld(ExprState *state, ExprEvalStep *op)
void
ExecEvalSubscriptingRefAssign(ExprState *state, ExprEvalStep *op)
{
- SubscriptingRefState *sbsrefstate = op->d.sbsref_subscript.state;
+ SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
SubscriptRoutines *sbsroutines = sbsrefstate->sbsroutines;
+ /*
+ * For an assignment to a fixed-length container type, both the original
+ * container and the value to be assigned into it must be non-NULL, else we
+ * punt and return the original container.
+ */
+ if (sbsrefstate->refattrlength > 0)
+ {
+ if (*op->resnull || sbsrefstate->replacenull)
+ return;
+ }
+
sbsrefstate->resnull = *op->resnull;
*op->resvalue = sbsroutines->assign(*op->resvalue, sbsrefstate);
*op->resnull = sbsrefstate->resnull;
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index 8ed30c011a..a5c41bbbd8 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -71,7 +71,7 @@ exprType(const Node *expr)
const SubscriptingRef *sbsref = (const SubscriptingRef *) expr;
/* slice and/or store operations yield the container type */
- if (sbsref->reflowerindexpr || sbsref->refassgnexpr)
+ if (IsAssignment(sbsref) || sbsref->reflowerindexpr)
type = sbsref->refcontainertype;
else
type = sbsref->refelemtype;
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index ba2b93440b..fa717c53a0 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -331,17 +331,6 @@ transformContainerSubscripts(ParseState *pstate,
lowerIndexpr = lappend(lowerIndexpr, subexpr);
indexprSlice = lappend(indexprSlice, ai);
}
- else
- Assert(ai->lidx == NULL && !ai->is_slice);
-
- if (ai->uidx)
- subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind);
- else
- {
- /* Slice with omitted upper bound, put NULL into the list */
- Assert(isSlice && ai->is_slice);
- subexpr = NULL;
- }
subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind);
upperIndexpr = lappend(upperIndexpr, subexpr);
}
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 8fd8604794..bcf4f89291 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -685,7 +685,7 @@ transformAssignmentIndirection(ParseState *pstate,
Node *rhs,
int location)
{
- Node *result = NULL;
+ Node *result;
List *subscripts = NIL;
bool isSlice = false;
ListCell *i;
@@ -870,6 +870,8 @@ transformAssignmentIndirection(ParseState *pstate,
errhint("You will need to rewrite or cast the expression."),
parser_errposition(pstate, location)));
}
+ else
+ result = rhs;
return result;
}
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 5b2917d159..01a52c7e6c 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -25,14 +25,20 @@
#include "nodes/nodeFuncs.h"
#include "nodes/supportnodes.h"
#include "optimizer/optimizer.h"
+#include "nodes/makefuncs.h"
+#include "executor/execExpr.h"
#include "utils/array.h"
#include "utils/arrayaccess.h"
#include "utils/builtins.h"
#include "utils/datum.h"
+#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/selfuncs.h"
+#include "utils/syscache.h"
#include "utils/typcache.h"
+#include "parser/parse_node.h"
+#include "parser/parse_coerce.h"
/*
@@ -159,7 +165,14 @@ static int width_bucket_array_variable(Datum operand,
ArrayType *thresholds,
Oid collation,
TypeCacheEntry *typentry);
+static SubscriptingRef *array_subscript_prepare(bool isAssignment, SubscriptingRef *sbsref);
+static SubscriptingRef *array_subscript_validate(bool isAssignment, SubscriptingRef *sbsref,
+ ParseState *pstate);
+static Datum array_subscript_fetch(Datum containerSource,
+ SubscriptingRefState *sbstate);
+static Datum array_subscript_assign(Datum containerSource,
+ SubscriptingRefState *sbstate);
/*
* array_in :
@@ -6599,3 +6612,279 @@ width_bucket_array_variable(Datum operand,
return left;
}
+
+/*
+ * Perform an actual data extraction or modification for the array
+ * subscripting. As a result the extracted Datum or the modified containers
+ * value will be returned.
+ */
+Datum
+array_subscript_assign(Datum containerSource, SubscriptingRefState *sbstate)
+{
+ bool is_slice = (sbstate->numlower != 0);
+ IntArray u_index, l_index;
+ bool eisnull = sbstate->resnull;
+ int i = 0;
+
+ if (sbstate->refelemlength == 0)
+ {
+ /* do one-time catalog lookups for type info */
+ get_typlenbyvalalign(sbstate->refelemtype,
+ &sbstate->refelemlength,
+ &sbstate->refelembyval,
+ &sbstate->refelemalign);
+ }
+
+ for(i = 0; i < sbstate->numupper; i++)
+ u_index.indx[i] = DatumGetInt32(sbstate->upperindex[i]);
+
+ if (is_slice)
+ {
+ for(i = 0; i < sbstate->numlower; i++)
+ l_index.indx[i] = DatumGetInt32(sbstate->lowerindex[i]);
+ }
+
+ /*
+ * For assignment to varlena arrays, we handle a NULL original array
+ * by substituting an empty (zero-dimensional) array; insertion of the
+ * new element will result in a singleton array value. It does not
+ * matter whether the new element is NULL.
+ */
+ if (eisnull)
+ {
+ containerSource = PointerGetDatum(construct_empty_array(sbstate->refelemtype));
+ sbstate->resnull = false;
+ eisnull = false;
+ }
+
+ if (!is_slice)
+ return array_set_element(containerSource, sbstate->numupper,
+ u_index.indx,
+ sbstate->replacevalue,
+ sbstate->replacenull,
+ sbstate->refattrlength,
+ sbstate->refelemlength,
+ sbstate->refelembyval,
+ sbstate->refelemalign);
+ else
+ return array_set_slice(containerSource, sbstate->numupper,
+ u_index.indx, l_index.indx,
+ sbstate->upperprovided,
+ sbstate->lowerprovided,
+ sbstate->replacevalue,
+ sbstate->replacenull,
+ sbstate->refattrlength,
+ sbstate->refelemlength,
+ sbstate->refelembyval,
+ sbstate->refelemalign);
+}
+
+Datum
+array_subscript_fetch(Datum containerSource, SubscriptingRefState *sbstate)
+{
+ bool is_slice = (sbstate->numlower != 0);
+ IntArray u_index, l_index;
+ int i = 0;
+
+ if (sbstate->refelemlength == 0)
+ {
+ /* do one-time catalog lookups for type info */
+ get_typlenbyvalalign(sbstate->refelemtype,
+ &sbstate->refelemlength,
+ &sbstate->refelembyval,
+ &sbstate->refelemalign);
+ }
+
+ for(i = 0; i < sbstate->numupper; i++)
+ u_index.indx[i] = DatumGetInt32(sbstate->upperindex[i]);
+
+ if (is_slice)
+ {
+ for(i = 0; i < sbstate->numlower; i++)
+ l_index.indx[i] = DatumGetInt32(sbstate->lowerindex[i]);
+ }
+
+ if (!is_slice)
+ return array_get_element(containerSource, sbstate->numupper,
+ u_index.indx,
+ sbstate->refattrlength,
+ sbstate->refelemlength,
+ sbstate->refelembyval,
+ sbstate->refelemalign,
+ &sbstate->resnull);
+ else
+ return array_get_slice(containerSource, sbstate->numupper,
+ u_index.indx, l_index.indx,
+ sbstate->upperprovided,
+ sbstate->lowerprovided,
+ sbstate->refattrlength,
+ sbstate->refelemlength,
+ sbstate->refelembyval,
+ sbstate->refelemalign);
+}
+
+/*
+ * Handle array-type subscripting logic.
+ */
+Datum
+array_subscript_handler(PG_FUNCTION_ARGS)
+{
+ SubscriptRoutines *sbsroutines = (SubscriptRoutines *)
+ palloc(sizeof(SubscriptRoutines));
+
+ sbsroutines->prepare = array_subscript_prepare;
+ sbsroutines->validate = array_subscript_validate;
+ sbsroutines->fetch = array_subscript_fetch;
+ sbsroutines->assign = array_subscript_assign;
+
+ PG_RETURN_POINTER(sbsroutines);
+}
+
+SubscriptingRef *
+array_subscript_prepare(bool isAssignment, SubscriptingRef *sbsref)
+{
+ Oid array_type = sbsref->refcontainertype;
+ HeapTuple type_tuple_container;
+ Form_pg_type type_struct_container;
+ bool is_slice = sbsref->reflowerindexpr != NIL;
+
+ /* Get the type tuple for the container */
+ type_tuple_container = SearchSysCache1(TYPEOID, ObjectIdGetDatum(array_type));
+ if (!HeapTupleIsValid(type_tuple_container))
+ elog(ERROR, "cache lookup failed for type %u", array_type);
+ type_struct_container = (Form_pg_type) GETSTRUCT(type_tuple_container);
+
+ /* needn't check typisdefined since this will fail anyway */
+ sbsref->refelemtype = type_struct_container->typelem;
+
+ /* Identify type that RHS must provide */
+ if (isAssignment)
+ sbsref->refassgntype = is_slice ? sbsref->refcontainertype : sbsref->refelemtype;
+
+ ReleaseSysCache(type_tuple_container);
+
+ return sbsref;
+}
+
+SubscriptingRef *
+array_subscript_validate(bool isAssignment, SubscriptingRef *sbsref,
+ ParseState *pstate)
+{
+ bool is_slice = sbsref->reflowerindexpr != NIL;
+ Oid typeneeded = InvalidOid,
+ typesource = InvalidOid;
+ Node *new_from;
+ Node *subexpr;
+ List *upperIndexpr = NIL;
+ List *lowerIndexpr = NIL;
+ ListCell *u, *l, *s;
+
+ foreach(u, sbsref->refupperindexpr)
+ {
+ subexpr = (Node *) lfirst(u);
+
+ if (subexpr == NULL)
+ {
+ upperIndexpr = lappend(upperIndexpr, subexpr);
+ continue;
+ }
+
+ subexpr = coerce_to_target_type(pstate,
+ subexpr, exprType(subexpr),
+ INT4OID, -1,
+ COERCION_ASSIGNMENT,
+ COERCE_IMPLICIT_CAST,
+ -1);
+ if (subexpr == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("array subscript must have type integer"),
+ parser_errposition(pstate, exprLocation(subexpr))));
+
+ upperIndexpr = lappend(upperIndexpr, subexpr);
+ }
+
+ sbsref->refupperindexpr = upperIndexpr;
+
+ forboth(l, sbsref->reflowerindexpr, s, sbsref->refindexprslice)
+ {
+ A_Indices *ai = (A_Indices *) lfirst(s);
+ subexpr = (Node *) lfirst(l);
+
+ if (subexpr == NULL && !ai->is_slice)
+ {
+ /* Make a constant 1 */
+ subexpr = (Node *) makeConst(INT4OID,
+ -1,
+ InvalidOid,
+ sizeof(int32),
+ Int32GetDatum(1),
+ false,
+ true); /* pass by value */
+ }
+
+ if (subexpr == NULL)
+ {
+ lowerIndexpr = lappend(lowerIndexpr, subexpr);
+ continue;
+ }
+
+ subexpr = coerce_to_target_type(pstate,
+ subexpr, exprType(subexpr),
+ INT4OID, -1,
+ COERCION_ASSIGNMENT,
+ COERCE_IMPLICIT_CAST,
+ -1);
+ if (subexpr == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("array subscript must have type integer"),
+ parser_errposition(pstate, exprLocation(subexpr))));
+
+ lowerIndexpr = lappend(lowerIndexpr, subexpr);
+ }
+
+ sbsref->reflowerindexpr = lowerIndexpr;
+
+ if (isAssignment)
+ {
+ SubscriptingRef *assignRef = (SubscriptingRef *) sbsref;
+ Node *assignExpr = (Node *) assignRef->refassgnexpr;
+
+ typesource = exprType(assignExpr);
+ typeneeded = is_slice ? sbsref->refcontainertype : sbsref->refelemtype;
+ new_from = coerce_to_target_type(pstate,
+ assignExpr, typesource,
+ typeneeded, sbsref->reftypmod,
+ COERCION_ASSIGNMENT,
+ COERCE_IMPLICIT_CAST,
+ -1);
+ if (new_from == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("array assignment requires type %s"
+ " but expression is of type %s",
+ format_type_be(sbsref->refelemtype),
+ format_type_be(typesource)),
+ errhint("You will need to rewrite or cast the expression."),
+ parser_errposition(pstate, exprLocation(assignExpr))));
+ assignRef->refassgnexpr = (Expr *) new_from;
+ }
+
+ sbsref->refnestedfunc = F_ARRAY_SUBSCRIPT_HANDLER;
+
+ /* Verify subscript list lengths are within limit */
+ if (list_length(sbsref->refupperindexpr) > MAXDIM)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
+ list_length(sbsref->refupperindexpr), MAXDIM)));
+
+ if (list_length(sbsref->reflowerindexpr) > MAXDIM)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
+ list_length(sbsref->reflowerindexpr), MAXDIM)));
+
+ return sbsref;
+}
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index a4e173b484..af0dc692bd 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -10473,6 +10473,13 @@
proargnames => '{max_data_alignment,database_block_size,blocks_per_segment,wal_block_size,bytes_per_wal_segment,max_identifier_length,max_index_columns,max_toast_chunk_size,large_object_chunk_size,float4_pass_by_value,float8_pass_by_value,data_page_checksum_version}',
prosrc => 'pg_control_init' },
+{ oid => '4004',
+ descr => 'Array subscripting logic',
+ proname => 'array_subscript_handler',
+ prorettype => 'internal',
+ proargtypes => 'internal',
+ prosrc => 'array_subscript_handler' },
+
# collation management functions
{ oid => '3445', descr => 'import collations from operating system',
proname => 'pg_import_system_collations', procost => '100',
diff --git a/src/include/catalog/pg_type.dat b/src/include/catalog/pg_type.dat
index 4b7750d439..71b21a8a14 100644
--- a/src/include/catalog/pg_type.dat
+++ b/src/include/catalog/pg_type.dat
@@ -54,7 +54,8 @@
typname => 'name', typlen => 'NAMEDATALEN', typbyval => 'f',
typcategory => 'S', typelem => 'char', typinput => 'namein',
typoutput => 'nameout', typreceive => 'namerecv', typsend => 'namesend',
- typalign => 'c', typcollation => '950' },
+ typalign => 'c', typcollation => '950',
+ typsubshandler => 'array_subscript_handler' },
{ oid => '20', array_type_oid => '1016',
descr => '~18 digit integer, 8-byte storage',
typname => 'int8', typlen => '8', typbyval => 'FLOAT8PASSBYVAL',
@@ -70,7 +71,7 @@
typname => 'int2vector', typlen => '-1', typbyval => 'f', typcategory => 'A',
typelem => 'int2', typinput => 'int2vectorin', typoutput => 'int2vectorout',
typreceive => 'int2vectorrecv', typsend => 'int2vectorsend',
- typalign => 'i' },
+ typalign => 'i', typsubshandler => 'array_subscript_handler' },
{ oid => '23', array_type_oid => '1007',
descr => '-2 billion to 2 billion integer, 4-byte storage',
typname => 'int4', typlen => '4', typbyval => 't', typcategory => 'N',
@@ -109,7 +110,8 @@
descr => 'array of oids, used in system tables',
typname => 'oidvector', typlen => '-1', typbyval => 'f', typcategory => 'A',
typelem => 'oid', typinput => 'oidvectorin', typoutput => 'oidvectorout',
- typreceive => 'oidvectorrecv', typsend => 'oidvectorsend', typalign => 'i' },
+ typreceive => 'oidvectorrecv', typsend => 'oidvectorsend', typalign => 'i',
+ typsubshandler => 'array_subscript_handler' },
# hand-built rowtype entries for bootstrapped catalogs
# NB: OIDs assigned here must match the BKI_ROWTYPE_OID declarations
@@ -185,32 +187,37 @@
descr => 'geometric point \'(x, y)\'',
typname => 'point', typlen => '16', typbyval => 'f', typcategory => 'G',
typelem => 'float8', typinput => 'point_in', typoutput => 'point_out',
- typreceive => 'point_recv', typsend => 'point_send', typalign => 'd' },
+ typreceive => 'point_recv', typsend => 'point_send', typalign => 'd',
+ typsubshandler => 'array_subscript_handler' },
{ oid => '601', array_type_oid => '1018',
descr => 'geometric line segment \'(pt1,pt2)\'',
typname => 'lseg', typlen => '32', typbyval => 'f', typcategory => 'G',
typelem => 'point', typinput => 'lseg_in', typoutput => 'lseg_out',
- typreceive => 'lseg_recv', typsend => 'lseg_send', typalign => 'd' },
+ typreceive => 'lseg_recv', typsend => 'lseg_send', typalign => 'd',
+ typsubshandler => 'array_subscript_handler' },
{ oid => '602', array_type_oid => '1019',
descr => 'geometric path \'(pt1,...)\'',
typname => 'path', typlen => '-1', typbyval => 'f', typcategory => 'G',
typinput => 'path_in', typoutput => 'path_out', typreceive => 'path_recv',
- typsend => 'path_send', typalign => 'd', typstorage => 'x' },
+ typsend => 'path_send', typalign => 'd', typstorage => 'x',
+ typsubshandler => 'array_subscript_handler' },
{ oid => '603', array_type_oid => '1020',
descr => 'geometric box \'(lower left,upper right)\'',
typname => 'box', typlen => '32', typbyval => 'f', typcategory => 'G',
typdelim => ';', typelem => 'point', typinput => 'box_in',
typoutput => 'box_out', typreceive => 'box_recv', typsend => 'box_send',
- typalign => 'd' },
+ typalign => 'd', typsubshandler => 'array_subscript_handler' },
{ oid => '604', array_type_oid => '1027',
descr => 'geometric polygon \'(pt1,...)\'',
typname => 'polygon', typlen => '-1', typbyval => 'f', typcategory => 'G',
typinput => 'poly_in', typoutput => 'poly_out', typreceive => 'poly_recv',
- typsend => 'poly_send', typalign => 'd', typstorage => 'x' },
+ typsend => 'poly_send', typalign => 'd', typstorage => 'x',
+ typsubshandler => 'array_subscript_handler' },
{ oid => '628', array_type_oid => '629', descr => 'geometric line',
typname => 'line', typlen => '24', typbyval => 'f', typcategory => 'G',
typelem => 'float8', typinput => 'line_in', typoutput => 'line_out',
- typreceive => 'line_recv', typsend => 'line_send', typalign => 'd' },
+ typreceive => 'line_recv', typsend => 'line_send', typalign => 'd',
+ typsubshandler => 'array_subscript_handler' },
# OIDS 700 - 799
@@ -269,7 +276,7 @@
{ oid => '1033', array_type_oid => '1034', descr => 'access control list',
typname => 'aclitem', typlen => '12', typbyval => 'f', typcategory => 'U',
typinput => 'aclitemin', typoutput => 'aclitemout', typreceive => '-',
- typsend => '-', typalign => 'i' },
+ typsend => '-', typalign => 'i', typsubshandler => 'array_subscript_handler' },
{ oid => '1042', array_type_oid => '1014',
descr => 'char(length), blank-padded string, fixed storage length',
typname => 'bpchar', typlen => '-1', typbyval => 'f', typcategory => 'S',
@@ -308,7 +315,8 @@
typcategory => 'D', typispreferred => 't', typinput => 'timestamptz_in',
typoutput => 'timestamptz_out', typreceive => 'timestamptz_recv',
typsend => 'timestamptz_send', typmodin => 'timestamptztypmodin',
- typmodout => 'timestamptztypmodout', typalign => 'd' },
+ typmodout => 'timestamptztypmodout', typalign => 'd',
+ typsubshandler => 'array_subscript_handler' },
{ oid => '1186', array_type_oid => '1187',
descr => '@ <number> <units>, time interval',
typname => 'interval', typlen => '16', typbyval => 'f', typcategory => 'T',
diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out
index c730563f03..f54b73c9da 100644
--- a/src/test/regress/expected/arrays.out
+++ b/src/test/regress/expected/arrays.out
@@ -190,9 +190,9 @@ select ('[0:2][0:2]={{1,2,3},{4,5,6},{7,8,9}}'::int[])[1:2][2];
--
-- check subscription corner cases
--
--- More subscripts than MAXDIMS(6)
-SELECT ('{}'::int[])[1][2][3][4][5][6][7];
-ERROR: number of array dimensions (7) exceeds the maximum allowed (6)
+-- More subscripts than MAXDIMS(12)
+SELECT ('{}'::int[])[1][2][3][4][5][6][7][8][9][10][11][12][13];
+ERROR: number of array dimensions (13) exceeds the maximum allowed (6)
-- NULL index yields NULL when selecting
SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][NULL][1];
int4
@@ -216,15 +216,15 @@ SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][1:NULL][1];
UPDATE arrtest
SET c[NULL] = '{"can''t assign"}'
WHERE array_dims(c) is not null;
-ERROR: array subscript in assignment must not be null
+ERROR: subscript in assignment must not be null
UPDATE arrtest
SET c[NULL:1] = '{"can''t assign"}'
WHERE array_dims(c) is not null;
-ERROR: array subscript in assignment must not be null
+ERROR: subscript in assignment must not be null
UPDATE arrtest
SET c[1:NULL] = '{"can''t assign"}'
WHERE array_dims(c) is not null;
-ERROR: array subscript in assignment must not be null
+ERROR: subscript in assignment must not be null
-- test slices with empty lower and/or upper index
CREATE TEMP TABLE arrtest_s (
a int2[],
diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql
index 25dd4e2c6d..fb7a319118 100644
--- a/src/test/regress/sql/arrays.sql
+++ b/src/test/regress/sql/arrays.sql
@@ -106,8 +106,8 @@ select ('[0:2][0:2]={{1,2,3},{4,5,6},{7,8,9}}'::int[])[1:2][2];
--
-- check subscription corner cases
--
--- More subscripts than MAXDIMS(6)
-SELECT ('{}'::int[])[1][2][3][4][5][6][7];
+-- More subscripts than MAXDIMS(12)
+SELECT ('{}'::int[])[1][2][3][4][5][6][7][8][9][10][11][12][13];
-- NULL index yields NULL when selecting
SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][NULL][1];
SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][NULL:1][1];
--
2.16.4