diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
new file mode 100644
index 9786242..140c81f
*** a/doc/src/sgml/plpgsql.sgml
--- b/doc/src/sgml/plpgsql.sgml
*************** SELECT merge_fields(t.*) FROM table1 t W
*** 710,715 ****
--- 710,792 ----
+
+ Array Types
+
+
+ variable%ARRAYTYPE
+
+
+
+ %ARRAYTYPE provides the array type from a variable or
+ table column. %ARRAYTYPE is particularly valuable in
+ polymorphic functions, since the data types needed for internal variables can
+ change from one call to the next. Appropriate variables can be
+ created by applying %ARRAYTYPE to the function's
+ arguments or result placeholders:
+
+ CREATE OR REPLACE FUNCTION array_init(v anyelement, size integer)
+ RETURNS anyarray AS $$
+ DECLARE
+ result v%ARRAYTYPE DEFAULT '{}';
+ BEGIN
+ -- prefer builtin function array_fill
+ FOR i IN 1 .. size
+ LOOP
+ result := result || v;
+ END LOOP;
+ RETURN result;
+ END;
+ $$ LANGUAGE plpgsql;
+
+ SELECT array_init(0::numeric, 10);
+ SELECT array_init(''::varchar, 10);
+
+
+
+
+
+ Array Element Types
+
+
+ variable%ELEMENTTYPE
+
+
+
+ %ELEMENTTYPE provides the element type of a given
+ array. %ELEMENTTYPE is particularly valuable in polymorphic
+ functions, since the data types needed for internal variables can
+ change from one call to the next. Appropriate variables can be
+ created by applying %ELEMENTTYPE to the function's
+ arguments or result placeholders:
+
+ CREATE OR REPLACE FUNCTION bubble_sort(a anyarray)
+ RETURNS anyarray AS $$
+ DECLARE
+ aux a%ELEMENTTYPE;
+ repeat_again boolean DEFAULT true;
+ BEGIN
+ -- Don't use this code for large arrays!
+ -- use builtin sort
+ WHILE repeat_again
+ LOOP
+ repeat_again := false;
+ FOR i IN array_lower(a, 1) .. array_upper(a, 1)
+ LOOP
+ IF a[i] > a[i+1] THEN
+ aux := a[i+1];
+ a[i+1] := a[i]; a[i] := aux;
+ repeat_again := true;
+ END IF;
+ END LOOP;
+ END LOOP;
+ RETURN a;
+ END;
+ $$ LANGUAGE plpgsql;
+
+
+
+
Collation of PL/pgSQL Variables
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
new file mode 100644
index ebe152d..98f74c3
*** a/src/pl/plpgsql/src/pl_comp.c
--- b/src/pl/plpgsql/src/pl_comp.c
*************** plpgsql_parse_tripword(char *word1, char
*** 1617,1632 ****
return false;
}
/* ----------
! * plpgsql_parse_wordtype The scanner found word%TYPE. word can be
! * a variable name or a basetype.
*
* Returns datatype struct, or NULL if no match found for word.
* ----------
*/
PLpgSQL_type *
! plpgsql_parse_wordtype(char *ident)
{
PLpgSQL_type *dtype;
PLpgSQL_nsitem *nse;
--- 1617,1683 ----
return false;
}
+ /*
+ * Derive type from ny base type controlled by reftype.
+ *
+ * This routine allows to take array type from array variable. This behave
+ * is not consistent with enforce_generic_type_consistency, where same task
+ * fails on ERROR: 42704: could not find array type for data type xxxxxxx[].
+ */
+ static PLpgSQL_type *
+ derive_type(PLpgSQL_type *base_type, PLpgSQL_reftype reftype)
+ {
+ Oid typoid;
+
+ switch (reftype)
+ {
+ case PLPGSQL_REFTYPE_TYPE:
+ return base_type;
+
+ case PLPGSQL_REFTYPE_ELEMENT:
+ {
+ typoid = get_element_type(base_type->typoid);
+ if (!OidIsValid(typoid))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("referenced variable should be an array, not type %s",
+ format_type_be(base_type->typoid))));
+
+ return plpgsql_build_datatype(typoid, -1,
+ plpgsql_curr_compile->fn_input_collation);
+ }
+
+ case PLPGSQL_REFTYPE_ARRAY:
+ {
+ /* Return base_type, when it is a array already */
+ if (OidIsValid(get_element_type(base_type->typoid)))
+ return base_type;
+
+ typoid = get_array_type(base_type->typoid);
+ if (!OidIsValid(typoid))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("could not find array type for data type %s",
+ format_type_be(base_type->typoid))));
+
+ return plpgsql_build_datatype(typoid, -1,
+ plpgsql_curr_compile->fn_input_collation);
+ }
+
+ default:
+ return NULL; /* keep compiler quiet */
+ }
+ }
/* ----------
! * plpgsql_parse_wordreftype The scanner found word%TYPE or word%ARRAYTYPE
! * or word%ELEMENTTYPE. word can be a variable name or a basetype.
*
* Returns datatype struct, or NULL if no match found for word.
* ----------
*/
PLpgSQL_type *
! plpgsql_parse_wordreftype(char *ident, PLpgSQL_reftype reftype)
{
PLpgSQL_type *dtype;
PLpgSQL_nsitem *nse;
*************** plpgsql_parse_wordtype(char *ident)
*** 1644,1653 ****
switch (nse->itemtype)
{
case PLPGSQL_NSTYPE_VAR:
! return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
! /* XXX perhaps allow REC/ROW here? */
default:
return NULL;
}
--- 1695,1715 ----
switch (nse->itemtype)
{
case PLPGSQL_NSTYPE_VAR:
! {
! dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
! return derive_type(dtype, reftype);
! }
! case PLPGSQL_NSTYPE_ROW:
! {
! dtype = ((PLpgSQL_row *) (plpgsql_Datums[nse->itemno]))->datatype;
! return derive_type(dtype, reftype);
! }
+ /*
+ * PLpgSQL doesn't support REC parameters, so we should not to
+ * support REC here.
+ */
default:
return NULL;
}
*************** plpgsql_parse_wordtype(char *ident)
*** 1685,1695 ****
/* ----------
! * plpgsql_parse_cwordtype Same lookup for compositeword%TYPE
* ----------
*/
PLpgSQL_type *
! plpgsql_parse_cwordtype(List *idents)
{
PLpgSQL_type *dtype = NULL;
PLpgSQL_nsitem *nse;
--- 1747,1758 ----
/* ----------
! * plpgsql_parse_cwordreftype Same lookup for compositeword%TYPE
! * compositeword%ARRAYTYPE or compositeword%ELEMENTTYPE
* ----------
*/
PLpgSQL_type *
! plpgsql_parse_cwordreftype(List *idents, PLpgSQL_reftype reftype)
{
PLpgSQL_type *dtype = NULL;
PLpgSQL_nsitem *nse;
*************** plpgsql_parse_cwordtype(List *idents)
*** 1718,1727 ****
NULL,
NULL);
! if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
{
! dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
! goto done;
}
/*
--- 1781,1804 ----
NULL,
NULL);
! if (nse != NULL)
{
! PLpgSQL_type *ref_type;
!
! if (nse->itemtype == PLPGSQL_NSTYPE_VAR)
! {
! ref_type = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
! dtype = derive_type(ref_type, reftype);
!
! goto done;
! }
! else if (nse->itemtype == PLPGSQL_NSTYPE_ROW)
! {
! ref_type = ((PLpgSQL_row *) (plpgsql_Datums[nse->itemno]))->datatype;
! dtype = derive_type(ref_type, reftype);
!
! goto done;
! }
}
/*
*************** plpgsql_build_variable(const char *refna
*** 1903,1908 ****
--- 1980,1986 ----
row->dtype = PLPGSQL_DTYPE_ROW;
row->refname = pstrdup(refname);
row->lineno = lineno;
+ row->datatype = dtype;
plpgsql_adddatum((PLpgSQL_datum *) row);
if (add2namespace)
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
new file mode 100644
index b14c22d..5048f54
*** a/src/pl/plpgsql/src/pl_gram.y
--- b/src/pl/plpgsql/src/pl_gram.y
*************** static void check_raise_parameters(PLp
*** 248,253 ****
--- 248,254 ----
%token K_ALIAS
%token K_ALL
%token K_ARRAY
+ %token K_ARRAYTYPE
%token K_ASSERT
%token K_BACKWARD
%token K_BEGIN
*************** static void check_raise_parameters(PLp
*** 270,275 ****
--- 271,277 ----
%token K_DETAIL
%token K_DIAGNOSTICS
%token K_DUMP
+ %token K_ELEMENTTYPE
%token K_ELSE
%token K_ELSIF
%token K_END
*************** unreserved_keyword :
*** 2390,2395 ****
--- 2392,2398 ----
K_ABSOLUTE
| K_ALIAS
| K_ARRAY
+ | K_ARRAYTYPE
| K_ASSERT
| K_BACKWARD
| K_CLOSE
*************** unreserved_keyword :
*** 2408,2413 ****
--- 2411,2417 ----
| K_DETAIL
| K_DIAGNOSTICS
| K_DUMP
+ | K_ELEMENTTYPE
| K_ELSIF
| K_ERRCODE
| K_ERROR
*************** read_datatype(int tok)
*** 2690,2696 ****
StringInfoData ds;
char *type_name;
int startlocation;
! PLpgSQL_type *result;
int parenlevel = 0;
/* Should only be called while parsing DECLARE sections */
--- 2694,2700 ----
StringInfoData ds;
char *type_name;
int startlocation;
! PLpgSQL_type *result = 0;
int parenlevel = 0;
/* Should only be called while parsing DECLARE sections */
*************** read_datatype(int tok)
*** 2703,2710 ****
startlocation = yylloc;
/*
! * If we have a simple or composite identifier, check for %TYPE
! * and %ROWTYPE constructs.
*/
if (tok == T_WORD)
{
--- 2707,2714 ----
startlocation = yylloc;
/*
! * If we have a simple or composite identifier, check for %TYPE,
! * %ELEMENTTYPE, %ARRAYTYPE and %ROWTYPE constructs.
*/
if (tok == T_WORD)
{
*************** read_datatype(int tok)
*** 2716,2733 ****
tok = yylex();
if (tok_is_keyword(tok, &yylval,
K_TYPE, "type"))
! {
! result = plpgsql_parse_wordtype(dtname);
! if (result)
! return result;
! }
else if (tok_is_keyword(tok, &yylval,
K_ROWTYPE, "rowtype"))
- {
result = plpgsql_parse_wordrowtype(dtname);
! if (result)
! return result;
! }
}
}
else if (plpgsql_token_is_unreserved_keyword(tok))
--- 2720,2737 ----
tok = yylex();
if (tok_is_keyword(tok, &yylval,
K_TYPE, "type"))
! result = plpgsql_parse_wordreftype(dtname, PLPGSQL_REFTYPE_TYPE);
! else if (tok_is_keyword(tok, &yylval,
! K_ELEMENTTYPE, "elementtype"))
! result = plpgsql_parse_wordreftype(dtname, PLPGSQL_REFTYPE_ELEMENT);
! else if (tok_is_keyword(tok, &yylval,
! K_ARRAYTYPE, "arraytype"))
! result = plpgsql_parse_wordreftype(dtname, PLPGSQL_REFTYPE_ARRAY);
else if (tok_is_keyword(tok, &yylval,
K_ROWTYPE, "rowtype"))
result = plpgsql_parse_wordrowtype(dtname);
! if (result)
! return result;
}
}
else if (plpgsql_token_is_unreserved_keyword(tok))
*************** read_datatype(int tok)
*** 2740,2757 ****
tok = yylex();
if (tok_is_keyword(tok, &yylval,
K_TYPE, "type"))
! {
! result = plpgsql_parse_wordtype(dtname);
! if (result)
! return result;
! }
else if (tok_is_keyword(tok, &yylval,
K_ROWTYPE, "rowtype"))
- {
result = plpgsql_parse_wordrowtype(dtname);
! if (result)
! return result;
! }
}
}
else if (tok == T_CWORD)
--- 2744,2761 ----
tok = yylex();
if (tok_is_keyword(tok, &yylval,
K_TYPE, "type"))
! result = plpgsql_parse_wordreftype(dtname, PLPGSQL_REFTYPE_TYPE);
! else if (tok_is_keyword(tok, &yylval,
! K_ELEMENTTYPE, "elementtype"))
! result = plpgsql_parse_wordreftype(dtname, PLPGSQL_REFTYPE_ELEMENT);
! else if (tok_is_keyword(tok, &yylval,
! K_ARRAYTYPE, "arraytype"))
! result = plpgsql_parse_wordreftype(dtname, PLPGSQL_REFTYPE_ARRAY);
else if (tok_is_keyword(tok, &yylval,
K_ROWTYPE, "rowtype"))
result = plpgsql_parse_wordrowtype(dtname);
! if (result)
! return result;
}
}
else if (tok == T_CWORD)
*************** read_datatype(int tok)
*** 2764,2781 ****
tok = yylex();
if (tok_is_keyword(tok, &yylval,
K_TYPE, "type"))
! {
! result = plpgsql_parse_cwordtype(dtnames);
! if (result)
! return result;
! }
else if (tok_is_keyword(tok, &yylval,
K_ROWTYPE, "rowtype"))
- {
result = plpgsql_parse_cwordrowtype(dtnames);
! if (result)
! return result;
! }
}
}
--- 2768,2785 ----
tok = yylex();
if (tok_is_keyword(tok, &yylval,
K_TYPE, "type"))
! result = plpgsql_parse_cwordreftype(dtnames, PLPGSQL_REFTYPE_TYPE);
! else if (tok_is_keyword(tok, &yylval,
! K_ELEMENTTYPE, "elementtype"))
! result = plpgsql_parse_cwordreftype(dtnames, PLPGSQL_REFTYPE_ELEMENT);
! else if (tok_is_keyword(tok, &yylval,
! K_ARRAYTYPE, "arraytype"))
! result = plpgsql_parse_cwordreftype(dtnames, PLPGSQL_REFTYPE_ARRAY);
else if (tok_is_keyword(tok, &yylval,
K_ROWTYPE, "rowtype"))
result = plpgsql_parse_cwordrowtype(dtnames);
! if (result)
! return result;
}
}
diff --git a/src/pl/plpgsql/src/pl_scanner.c b/src/pl/plpgsql/src/pl_scanner.c
new file mode 100644
index bb0f25b..9a5c54a
*** a/src/pl/plpgsql/src/pl_scanner.c
--- b/src/pl/plpgsql/src/pl_scanner.c
*************** static const ScanKeyword unreserved_keyw
*** 98,103 ****
--- 98,104 ----
PG_KEYWORD("absolute", K_ABSOLUTE, UNRESERVED_KEYWORD)
PG_KEYWORD("alias", K_ALIAS, UNRESERVED_KEYWORD)
PG_KEYWORD("array", K_ARRAY, UNRESERVED_KEYWORD)
+ PG_KEYWORD("arraytype", K_ARRAYTYPE, UNRESERVED_KEYWORD)
PG_KEYWORD("assert", K_ASSERT, UNRESERVED_KEYWORD)
PG_KEYWORD("backward", K_BACKWARD, UNRESERVED_KEYWORD)
PG_KEYWORD("close", K_CLOSE, UNRESERVED_KEYWORD)
*************** static const ScanKeyword unreserved_keyw
*** 116,121 ****
--- 117,123 ----
PG_KEYWORD("detail", K_DETAIL, UNRESERVED_KEYWORD)
PG_KEYWORD("diagnostics", K_DIAGNOSTICS, UNRESERVED_KEYWORD)
PG_KEYWORD("dump", K_DUMP, UNRESERVED_KEYWORD)
+ PG_KEYWORD("elementtype", K_ELEMENTTYPE, UNRESERVED_KEYWORD)
PG_KEYWORD("elseif", K_ELSIF, UNRESERVED_KEYWORD)
PG_KEYWORD("elsif", K_ELSIF, UNRESERVED_KEYWORD)
PG_KEYWORD("errcode", K_ERRCODE, UNRESERVED_KEYWORD)
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
new file mode 100644
index f4e9f62..41c3d74
*** a/src/pl/plpgsql/src/plpgsql.h
--- b/src/pl/plpgsql/src/plpgsql.h
*************** enum
*** 84,89 ****
--- 84,100 ----
};
/* ----------
+ * Possible modes for type references
+ * ----------
+ */
+ typedef enum
+ {
+ PLPGSQL_REFTYPE_TYPE, /* use type of some variable */
+ PLPGSQL_REFTYPE_ELEMENT, /* use a element type of referenced variable */
+ PLPGSQL_REFTYPE_ARRAY /* use a array type of referenced variable */
+ } PLpgSQL_reftype;
+
+ /* ----------
* Execution tree node types
* ----------
*/
*************** typedef struct
*** 281,286 ****
--- 292,298 ----
char *refname;
int lineno;
+ PLpgSQL_type *datatype;
TupleDesc rowtupdesc;
/*
*************** extern bool plpgsql_parse_dblword(char *
*** 961,968 ****
PLwdatum *wdatum, PLcword *cword);
extern bool plpgsql_parse_tripword(char *word1, char *word2, char *word3,
PLwdatum *wdatum, PLcword *cword);
! extern PLpgSQL_type *plpgsql_parse_wordtype(char *ident);
! extern PLpgSQL_type *plpgsql_parse_cwordtype(List *idents);
extern PLpgSQL_type *plpgsql_parse_wordrowtype(char *ident);
extern PLpgSQL_type *plpgsql_parse_cwordrowtype(List *idents);
extern PLpgSQL_type *plpgsql_build_datatype(Oid typeOid, int32 typmod,
--- 973,980 ----
PLwdatum *wdatum, PLcword *cword);
extern bool plpgsql_parse_tripword(char *word1, char *word2, char *word3,
PLwdatum *wdatum, PLcword *cword);
! extern PLpgSQL_type *plpgsql_parse_wordreftype(char *ident, PLpgSQL_reftype reftype);
! extern PLpgSQL_type *plpgsql_parse_cwordreftype(List *idents, PLpgSQL_reftype reftype);
extern PLpgSQL_type *plpgsql_parse_wordrowtype(char *ident);
extern PLpgSQL_type *plpgsql_parse_cwordrowtype(List *idents);
extern PLpgSQL_type *plpgsql_build_datatype(Oid typeOid, int32 typmod,
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
new file mode 100644
index e30c579..1d6117e
*** a/src/test/regress/expected/plpgsql.out
--- b/src/test/regress/expected/plpgsql.out
*************** end;
*** 5573,5575 ****
--- 5573,5692 ----
$$;
ERROR: unhandled assertion
CONTEXT: PL/pgSQL function inline_code_block line 3 at ASSERT
+ -- test referenced types
+ create type test_composite_type as (x int, y int);
+ create or replace function test_simple(src anyelement)
+ returns anyelement as $$
+ declare dest src%type;
+ begin
+ dest := src;
+ return dest;
+ end;
+ $$ language plpgsql;
+ select test_simple(10);
+ test_simple
+ -------------
+ 10
+ (1 row)
+
+ select test_simple('hoj'::text);
+ test_simple
+ -------------
+ hoj
+ (1 row)
+
+ select test_simple((10,20)::test_composite_type);
+ test_simple
+ -------------
+ (10,20)
+ (1 row)
+
+ create or replace function test_poly_element(x anyelement)
+ returns anyarray as $$
+ declare result x%arraytype;
+ begin
+ result := ARRAY[x];
+ raise notice '% %', pg_typeof(result), result;
+ return result;
+ end;
+ $$ language plpgsql;
+ create or replace function test_array_init(v anyelement, size integer)
+ returns anyarray as $$
+ declare result v%arraytype default '{}';
+ begin
+ -- prefer builtin function array_fill
+ for i in 1 .. size
+ loop
+ result := result || v;
+ end loop;
+ return result;
+ end;
+ $$ language plpgsql;
+ select test_poly_element(1);
+ NOTICE: integer[] {1}
+ test_poly_element
+ -------------------
+ {1}
+ (1 row)
+
+ select test_poly_element('hoj'::text);
+ NOTICE: text[] {hoj}
+ test_poly_element
+ -------------------
+ {hoj}
+ (1 row)
+
+ select test_poly_element((10,20)::test_composite_type);
+ NOTICE: test_composite_type[] {"(10,20)"}
+ test_poly_element
+ -------------------
+ {"(10,20)"}
+ (1 row)
+
+ select test_array_init(1.0::numeric, 10);
+ test_array_init
+ -------------------------------------------
+ {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0}
+ (1 row)
+
+ select test_array_init(1::int, 10);
+ test_array_init
+ -----------------------
+ {1,1,1,1,1,1,1,1,1,1}
+ (1 row)
+
+ create or replace function test_poly_array(x anyarray)
+ returns anyelement as $$
+ declare result x%elementtype;
+ begin
+ result := x[1];
+ raise notice '% %', pg_typeof(result), result;
+ return result;
+ end;
+ $$ language plpgsql;
+ select test_poly_array(ARRAY[1]);
+ NOTICE: integer 1
+ test_poly_array
+ -----------------
+ 1
+ (1 row)
+
+ select test_poly_array(ARRAY['hoj'::text]);
+ NOTICE: text hoj
+ test_poly_array
+ -----------------
+ hoj
+ (1 row)
+
+ select test_poly_array(ARRAY[(10,20)::test_composite_type]);
+ NOTICE: test_composite_type (10,20)
+ test_poly_array
+ -----------------
+ (10,20)
+ (1 row)
+
+ drop function test_simple(anyelement);
+ drop type test_composite_type;
+ drop function test_poly_element(anyelement);
+ drop function test_array_init(anyelement, int);
+ drop function test_poly_array(anyarray);
diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql
new file mode 100644
index 7ffef89..85b8174
*** a/src/test/regress/sql/plpgsql.sql
--- b/src/test/regress/sql/plpgsql.sql
*************** exception when others then
*** 4386,4388 ****
--- 4386,4455 ----
null; -- do nothing
end;
$$;
+
+ -- test referenced types
+ create type test_composite_type as (x int, y int);
+
+ create or replace function test_simple(src anyelement)
+ returns anyelement as $$
+ declare dest src%type;
+ begin
+ dest := src;
+ return dest;
+ end;
+ $$ language plpgsql;
+
+ select test_simple(10);
+ select test_simple('hoj'::text);
+ select test_simple((10,20)::test_composite_type);
+
+ create or replace function test_poly_element(x anyelement)
+ returns anyarray as $$
+ declare result x%arraytype;
+ begin
+ result := ARRAY[x];
+ raise notice '% %', pg_typeof(result), result;
+ return result;
+ end;
+ $$ language plpgsql;
+
+ create or replace function test_array_init(v anyelement, size integer)
+ returns anyarray as $$
+ declare result v%arraytype default '{}';
+ begin
+ -- prefer builtin function array_fill
+ for i in 1 .. size
+ loop
+ result := result || v;
+ end loop;
+ return result;
+ end;
+ $$ language plpgsql;
+
+ select test_poly_element(1);
+ select test_poly_element('hoj'::text);
+ select test_poly_element((10,20)::test_composite_type);
+
+ select test_array_init(1.0::numeric, 10);
+ select test_array_init(1::int, 10);
+
+ create or replace function test_poly_array(x anyarray)
+ returns anyelement as $$
+ declare result x%elementtype;
+ begin
+ result := x[1];
+ raise notice '% %', pg_typeof(result), result;
+ return result;
+ end;
+ $$ language plpgsql;
+
+
+ select test_poly_array(ARRAY[1]);
+ select test_poly_array(ARRAY['hoj'::text]);
+ select test_poly_array(ARRAY[(10,20)::test_composite_type]);
+
+ drop function test_simple(anyelement);
+ drop type test_composite_type;
+ drop function test_poly_element(anyelement);
+ drop function test_array_init(anyelement, int);
+ drop function test_poly_array(anyarray);