arrdom1v1-polymorphism.patch
text/plain
Filename: arrdom1v1-polymorphism.patch
Type: text/plain
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/catalog/pg_aggregate.c | 0 | 0 |
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 86e8c6b..8194519 100644
*** a/src/backend/catalog/pg_aggregate.c
--- b/src/backend/catalog/pg_aggregate.c
***************
*** 305,310 **** lookup_agg_function(List *fnName,
--- 305,311 ----
Oid *rettype)
{
Oid fnOid;
+ Oid vartype;
bool retset;
int nvargs;
Oid *true_oid_array;
***************
*** 321,327 **** lookup_agg_function(List *fnName,
*/
fdresult = func_get_detail(fnName, NIL, NIL,
nargs, input_types, false, false,
! &fnOid, rettype, &retset, &nvargs,
&true_oid_array, NULL);
/* only valid case is a normal function not returning a set */
--- 322,328 ----
*/
fdresult = func_get_detail(fnName, NIL, NIL,
nargs, input_types, false, false,
! &fnOid, rettype, &vartype, &retset, &nvargs,
&true_oid_array, NULL);
/* only valid case is a normal function not returning a set */
diff --git a/src/backend/catalog/pg_proc.index 6250b07..8fdd88e 100644
*** a/src/backend/catalog/pg_proc.c
--- b/src/backend/catalog/pg_proc.c
***************
*** 272,278 **** ProcedureCreate(const char *procedureName,
variadicType = ANYELEMENTOID;
break;
default:
! variadicType = get_element_type(allParams[i]);
if (!OidIsValid(variadicType))
elog(ERROR, "variadic parameter is not an array");
break;
--- 272,278 ----
variadicType = ANYELEMENTOID;
break;
default:
! variadicType = get_base_element_type(allParams[i]);
if (!OidIsValid(variadicType))
elog(ERROR, "variadic parameter is not an array");
break;
diff --git a/src/backend/commands/fuindex 03da168..717c632 100644
*** a/src/backend/commands/functioncmds.c
--- b/src/backend/commands/functioncmds.c
***************
*** 273,279 **** examine_parameter_list(List *parameters, Oid languageOid,
/* okay */
break;
default:
! if (!OidIsValid(get_element_type(toid)))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("VARIADIC parameter must be an array")));
--- 273,279 ----
/* okay */
break;
default:
! if (!OidIsValid(get_base_element_type(toid)))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("VARIADIC parameter must be an array")));
diff --git a/src/backend/parser/parse_coerindex 0418972..990ee29 100644
*** a/src/backend/parser/parse_coerce.c
--- b/src/backend/parser/parse_coerce.c
***************
*** 1326,1332 **** check_generic_type_consistency(Oid *actual_arg_types,
return true;
}
! array_typelem = get_element_type(array_typeid);
if (!OidIsValid(array_typelem))
return false; /* should be an array, but isn't */
--- 1326,1332 ----
return true;
}
! array_typelem = get_base_element_type(array_typeid);
if (!OidIsValid(array_typelem))
return false; /* should be an array, but isn't */
***************
*** 1513,1519 **** enforce_generic_type_consistency(Oid *actual_arg_types,
}
else
{
! array_typelem = get_element_type(array_typeid);
if (!OidIsValid(array_typelem))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
--- 1513,1519 ----
}
else
{
! array_typelem = get_base_element_type(array_typeid);
if (!OidIsValid(array_typelem))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
***************
*** 1656,1662 **** resolve_generic_type(Oid declared_type,
if (context_declared_type == ANYARRAYOID)
{
/* Use actual type, but it must be an array */
! Oid array_typelem = get_element_type(context_actual_type);
if (!OidIsValid(array_typelem))
ereport(ERROR,
--- 1656,1662 ----
if (context_declared_type == ANYARRAYOID)
{
/* Use actual type, but it must be an array */
! Oid array_typelem = get_base_element_type(context_actual_type);
if (!OidIsValid(array_typelem))
ereport(ERROR,
***************
*** 1687,1693 **** resolve_generic_type(Oid declared_type,
if (context_declared_type == ANYARRAYOID)
{
/* Use the element type corresponding to actual type */
! Oid array_typelem = get_element_type(context_actual_type);
if (!OidIsValid(array_typelem))
ereport(ERROR,
--- 1687,1693 ----
if (context_declared_type == ANYARRAYOID)
{
/* Use the element type corresponding to actual type */
! Oid array_typelem = get_base_element_type(context_actual_type);
if (!OidIsValid(array_typelem))
ereport(ERROR,
diff --git a/src/backend/parser/parse_fuindex 75f1e20..acf9317 100644
*** a/src/backend/parser/parse_func.c
--- b/src/backend/parser/parse_func.c
***************
*** 64,69 **** ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
--- 64,70 ----
WindowDef *over, bool is_column, int location)
{
Oid rettype;
+ Oid vartype;
Oid funcid;
ListCell *l;
ListCell *nextl;
***************
*** 212,218 **** ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
fdresult = func_get_detail(funcname, fargs, argnames, nargs,
actual_arg_types,
!func_variadic, true,
! &funcid, &rettype, &retset, &nvargs,
&declared_arg_types, &argdefaults);
if (fdresult == FUNCDETAIL_COERCION)
{
--- 213,219 ----
fdresult = func_get_detail(funcname, fargs, argnames, nargs,
actual_arg_types,
!func_variadic, true,
! &funcid, &rettype, &vartype, &retset, &nvargs,
&declared_arg_types, &argdefaults);
if (fdresult == FUNCDETAIL_COERCION)
{
***************
*** 371,377 **** ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
newa->multidims = false;
newa->location = exprLocation((Node *) vargs);
! fargs = lappend(fargs, newa);
}
/* build the appropriate output structure */
--- 372,403 ----
newa->multidims = false;
newa->location = exprLocation((Node *) vargs);
! /*
! * If the VARIADIC parameter is anyarray, look for other anyarray
! * arguments that constrain its true type. If we don't find one, the
! * standard array type of the variadic element type fills in.
! */
! if (vartype == ANYARRAYOID)
! {
! int i;
!
! vartype = newa->array_typeid;
! for (i = 0; i < nargs; i++)
! if (declared_arg_types[i] == ANYARRAYOID)
! {
! vartype = actual_arg_types[i];
! break;
! }
! }
!
! /* VARIADIC parameter type may be a domain - coerce it */
! fargs = lappend(fargs, coerce_type(pstate,
! (Node *) newa,
! newa->array_typeid,
! vartype, -1,
! COERCION_IMPLICIT,
! COERCE_IMPLICIT_CAST,
! -1));
}
/* build the appropriate output structure */
***************
*** 929,934 **** func_get_detail(List *funcname,
--- 955,961 ----
bool expand_defaults,
Oid *funcid, /* return value */
Oid *rettype, /* return value */
+ Oid *vartype, /* return value */
bool *retset, /* return value */
int *nvargs, /* return value */
Oid **true_typeids, /* return value */
***************
*** 940,945 **** func_get_detail(List *funcname,
--- 967,973 ----
/* initialize output arguments to silence compiler warnings */
*funcid = InvalidOid;
*rettype = InvalidOid;
+ *vartype = InvalidOid;
*retset = false;
*nvargs = 0;
*true_typeids = NULL;
***************
*** 1050,1055 **** func_get_detail(List *funcname,
--- 1078,1084 ----
/* Treat it as a type coercion */
*funcid = InvalidOid;
*rettype = targetType;
+ *vartype = InvalidOid;
*retset = false;
*nvargs = 0;
*true_typeids = argtypes;
***************
*** 1148,1153 **** func_get_detail(List *funcname,
--- 1177,1186 ----
best_candidate->oid);
pform = (Form_pg_proc) GETSTRUCT(ftup);
*rettype = pform->prorettype;
+ if (*nvargs > 0)
+ *vartype = pform->proargtypes.values[pform->pronargs - 1];
+ else
+ *vartype = InvalidOid;
*retset = pform->proretset;
/* fetch default args if caller wants 'em */
if (argdefaults && best_candidate->ndargs > 0)
diff --git a/src/backend/utils/adt/arrindex 274e867..6f9824d 100644
*** a/src/backend/utils/adt/array_userfuncs.c
--- b/src/backend/utils/adt/array_userfuncs.c
***************
*** 32,37 **** array_push(PG_FUNCTION_ARGS)
--- 32,38 ----
*lb;
ArrayType *result;
int indx;
+ Oid array_type;
Oid element_type;
int16 typlen;
bool typbyval;
***************
*** 47,57 **** array_push(PG_FUNCTION_ARGS)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("could not determine input data types")));
! arg0_elemid = get_element_type(arg0_typeid);
! arg1_elemid = get_element_type(arg1_typeid);
if (arg0_elemid != InvalidOid)
{
if (PG_ARGISNULL(0))
v = construct_empty_array(arg0_elemid);
else
--- 48,59 ----
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("could not determine input data types")));
! arg0_elemid = get_base_element_type(arg0_typeid);
! arg1_elemid = get_base_element_type(arg1_typeid);
if (arg0_elemid != InvalidOid)
{
+ array_type = arg0_typeid;
if (PG_ARGISNULL(0))
v = construct_empty_array(arg0_elemid);
else
***************
*** 64,69 **** array_push(PG_FUNCTION_ARGS)
--- 66,72 ----
}
else if (arg1_elemid != InvalidOid)
{
+ array_type = arg1_typeid;
if (PG_ARGISNULL(1))
v = construct_empty_array(arg1_elemid);
else
***************
*** 156,161 **** array_push(PG_FUNCTION_ARGS)
--- 159,171 ----
if (ARR_NDIM(v) == 1)
ARR_LBOUND(result)[0] = ARR_LBOUND(v)[0];
+ /*
+ * If the input array type is a domain, our returned value must also
+ * conform to the constraints of that domain.
+ */
+ if (getBaseType(array_type) != array_type)
+ domain_check(PointerGetDatum(result), false, array_type, NULL, NULL);
+
PG_RETURN_ARRAYTYPE_P(result);
}
***************
*** 195,200 **** array_cat(PG_FUNCTION_ARGS)
--- 205,211 ----
Oid element_type;
Oid element_type1;
Oid element_type2;
+ Oid array_type;
int32 dataoffset;
/* Concatenating a null array is a no-op, just return the other input */
***************
*** 396,401 **** array_cat(PG_FUNCTION_ARGS)
--- 407,421 ----
nitems2);
}
+ /*
+ * If the input array type is a domain, our returned value must also
+ * conform to the constraints of that domain. Earlier exits did not need
+ * this check, because they merely returned input data unchanged.
+ */
+ array_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
+ if (getBaseType(array_type) != array_type)
+ domain_check(PointerGetDatum(result), false, array_type, NULL, NULL);
+
PG_RETURN_ARRAYTYPE_P(result);
}
diff --git a/src/backend/utils/adt/ruleutils.cindex 3ab90cb..b7bdd0b 100644
*** a/src/backend/utils/adt/ruleutils.c
--- b/src/backend/utils/adt/ruleutils.c
***************
*** 7001,7006 **** generate_function_name(Oid funcid, int nargs, List *argnames,
--- 7001,7007 ----
FuncDetailCode p_result;
Oid p_funcid;
Oid p_rettype;
+ Oid p_vartype;
bool p_retset;
int p_nvargs;
Oid *p_true_typeids;
***************
*** 7020,7026 **** generate_function_name(Oid funcid, int nargs, List *argnames,
p_result = func_get_detail(list_make1(makeString(proname)),
NIL, argnames, nargs, argtypes,
!OidIsValid(procform->provariadic), true,
! &p_funcid, &p_rettype,
&p_retset, &p_nvargs, &p_true_typeids, NULL);
if ((p_result == FUNCDETAIL_NORMAL ||
p_result == FUNCDETAIL_AGGREGATE ||
--- 7021,7027 ----
p_result = func_get_detail(list_make1(makeString(proname)),
NIL, argnames, nargs, argtypes,
!OidIsValid(procform->provariadic), true,
! &p_funcid, &p_rettype, &p_vartype,
&p_retset, &p_nvargs, &p_true_typeids, NULL);
if ((p_result == FUNCDETAIL_NORMAL ||
p_result == FUNCDETAIL_AGGREGATE ||
diff --git a/src/include/parser/parse_fuindex 2fe6f90..01f4954 100644
*** a/src/include/parser/parse_func.h
--- b/src/include/parser/parse_func.h
***************
*** 52,58 **** extern FuncDetailCode func_get_detail(List *funcname,
List *fargs, List *fargnames,
int nargs, Oid *argtypes,
bool expand_variadic, bool expand_defaults,
! Oid *funcid, Oid *rettype,
bool *retset, int *nvargs, Oid **true_typeids,
List **argdefaults);
--- 52,58 ----
List *fargs, List *fargnames,
int nargs, Oid *argtypes,
bool expand_variadic, bool expand_defaults,
! Oid *funcid, Oid *rettype, Oid *vartype,
bool *retset, int *nvargs, Oid **true_typeids,
List **argdefaults);
diff --git a/src/test/regress/expectedindex 7d72791..6c1d2ee 100644
*** a/src/test/regress/expected/domain.out
--- b/src/test/regress/expected/domain.out
***************
*** 595,597 **** select array_elem_check(-1);
--- 595,637 ----
ERROR: value for domain orderedpair violates check constraint "orderedpair_check"
CONTEXT: PL/pgSQL function "array_elem_check" line 5 at assignment
drop function array_elem_check(int);
+ select array_append('{1}'::orderedpair, 2);
+ array_append
+ --------------
+ {1,2}
+ (1 row)
+
+ select array_prepend(2, '{1}'::orderedpair); -- fail
+ ERROR: value for domain orderedpair violates check constraint "orderedpair_check"
+ select array_cat('{2}'::orderedpair, '{1}'); -- fail
+ ERROR: value for domain orderedpair violates check constraint "orderedpair_check"
+ create or replace function domain_variadic(variadic orderedpair)
+ returns int
+ as 'select $1[2] - $1[1]' language sql;
+ select domain_variadic(1, 2);
+ domain_variadic
+ -----------------
+ 1
+ (1 row)
+
+ select domain_variadic(2, 1); -- fail
+ ERROR: value for domain orderedpair violates check constraint "orderedpair_check"
+ select domain_variadic(variadic array[1,2]);
+ domain_variadic
+ -----------------
+ 1
+ (1 row)
+
+ select domain_variadic(variadic array[2,1]); -- fail
+ ERROR: value for domain orderedpair violates check constraint "orderedpair_check"
+ create or replace function domain_poly_variadic(anyarray, variadic anyarray)
+ returns int
+ as 'select array_length($1, 1) * array_length($2, 1)' language sql;
+ select domain_poly_variadic('{2}'::orderedpair, 3, 4);
+ domain_poly_variadic
+ ----------------------
+ 2
+ (1 row)
+
+ select domain_poly_variadic('{2}'::orderedpair, 3, 1); -- fail
+ ERROR: value for domain orderedpair violates check constraint "orderedpair_check"
diff --git a/src/test/regress/sql/domain.sqindex 545af62..180fdcf 100644
*** a/src/test/regress/sql/domain.sql
--- b/src/test/regress/sql/domain.sql
***************
*** 466,468 **** select array_elem_check(3);
--- 466,486 ----
select array_elem_check(-1);
drop function array_elem_check(int);
+
+ select array_append('{1}'::orderedpair, 2);
+ select array_prepend(2, '{1}'::orderedpair); -- fail
+ select array_cat('{2}'::orderedpair, '{1}'); -- fail
+
+ create or replace function domain_variadic(variadic orderedpair)
+ returns int
+ as 'select $1[2] - $1[1]' language sql;
+ select domain_variadic(1, 2);
+ select domain_variadic(2, 1); -- fail
+ select domain_variadic(variadic array[1,2]);
+ select domain_variadic(variadic array[2,1]); -- fail
+
+ create or replace function domain_poly_variadic(anyarray, variadic anyarray)
+ returns int
+ as 'select array_length($1, 1) * array_length($2, 1)' language sql;
+ select domain_poly_variadic('{2}'::orderedpair, 3, 4);
+ select domain_poly_variadic('{2}'::orderedpair, 3, 1); -- fail