!5703 完善PL中的type、record:赋值时检测自定义类型名称是否正确

Merge pull request !5703 from 雷紫薇/req129584_1_nest
This commit is contained in:
opengauss_bot
2024-10-18 07:39:45 +00:00
committed by Gitee
9 changed files with 1792 additions and 16 deletions

View File

@ -134,6 +134,7 @@ connection_alarm_rate|real|0,1|NULL|NULL|
constraint_exclusion|enum|partition,on,off,true,false,yes,no,1,0|NULL|NULL|
enable_union_all_subquery_orderby|bool|0,0|NULL|NULL|
enable_ignore_case_in_dquotes|bool|0,0|NULL|NULL|
enable_pltype_name_check|bool|0,0|NULL|NULL|
instr_unique_sql_track_type|enum|all,top|NULL|NULL|
transform_to_numeric_operators|bool|0,0|NULL|NULL|
convert_string_to_digit|bool|0,0|NULL|Please don't modify this parameter which will change the type conversion rule and may lead to unpredictable behavior!|

View File

@ -1782,6 +1782,17 @@ static void InitSqlConfigureNamesBool()
check_enable_ignore_case_in_dquotes,
NULL,
NULL},
{{"enable_pltype_name_check",
PGC_USERSET,
NODE_ALL,
QUERY_TUNING_METHOD,
gettext_noop("Enable PL type check, if the types are different, throw an error."),
NULL},
&u_sess->attr.attr_sql.enable_pltype_name_check,
false,
NULL,
NULL,
NULL},
{{"enable_streaming",
PGC_POSTMASTER,
NODE_DISTRIBUTE,

View File

@ -828,7 +828,7 @@ job_queue_processes = 10 # Number of concurrent jobs, optional: [0..1000]
#enable_seqscan_fusion = off
#enable_cachedplan_mgr=on
#enable_ignore_case_in_dquotes=off
#enable_pltype_name_check=off
#------------------------------------------------------------------------------
# SHARED STORAGE OPTIONS
#------------------------------------------------------------------------------

View File

@ -54,7 +54,7 @@
#include <limits.h>
#define MAX_LAYER 256
#define LENGTH_OF_BRACKETS_AND_DOT 4
#define LENGTH_OF_QUOTATION_MARKS 2
#define IS_ANONYMOUS_BLOCK \
@ -228,6 +228,8 @@ static char* get_attrname(int tok);
static AttrNumber get_assign_attrno(PLpgSQL_datum* target, char* attrname);
static void raw_parse_package_function(char* proc_str, int location, int leaderlen);
static void checkFuncName(List* funcname);
static void checkTypeName(List* nest_typnames, List* target_typnames);
static List* get_current_type_nest_type(List* old_nest_typenames, char* typname, bool add_current_type);
static void IsInPublicNamespace(char* varname);
static void CheckDuplicateCondition (char* name);
static void SetErrorState();
@ -1222,6 +1224,7 @@ as_is : K_IS
decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_notnull decl_defval
{
ListCell *lc = NULL;
PLpgSQL_row* row = NULL;
if ((list_length($1) > 1) && ($3 && $3->typoid == REFCURSOROID))
ereport(errstate,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@ -1283,6 +1286,14 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no
var = plpgsql_build_variable(varname->name, varname->lineno,
$3, true);
if (var->dtype == PLPGSQL_DTYPE_ROW || var->dtype == PLPGSQL_DTYPE_RECORD)
{
row = (PLpgSQL_row*)var;
PLpgSQL_nest_type* ntype = (PLpgSQL_nest_type *)palloc(sizeof(PLpgSQL_nest_type));
ntype->index = 1;
List* nest_typnames = NIL;
row->nest_typnames = search_external_nest_type($3->typname, $3->typoid, -1, nest_typnames, ntype);
}
if ($2)
{
if (var->dtype == PLPGSQL_DTYPE_VAR)
@ -1315,8 +1326,10 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no
((PLpgSQL_var *) var)->default_val = $6;
else if (var->dtype == PLPGSQL_DTYPE_ROW || var->dtype == PLPGSQL_DTYPE_RECORD) {
PLpgSQL_row * row = (PLpgSQL_row *) var;
if (!(row->atomically_null_object && pg_strcasecmp($6->query, "select null") == 0))
if (!(row->atomically_null_object && pg_strcasecmp($6->query, "select null") == 0)) {
row->default_val = $6;
checkTypeName($6->nest_typnames, row->nest_typnames);
}
} else if (var->dtype == PLPGSQL_DTYPE_CURSORROW) {
((PLpgSQL_rec *) var)->default_val = $6;
}
@ -1477,7 +1490,8 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no
u_sess->plsql_cxt.have_error = true;
}
plpgsql_build_varrayType($2->name, $2->lineno, $9, true);
PLpgSQL_var* var = (PLpgSQL_var*)plpgsql_build_varrayType($2->name, $2->lineno, $9, true);
var->nest_typnames = get_current_type_nest_type(var->nest_typnames, var->refname, true);
if (IS_PACKAGE) {
plpgsql_build_package_array_type($2->name, $9->typoid, TYPCATEGORY_ARRAY, $9->dependExtend);
} else if (enable_plpgsql_gsdependency()) {
@ -1514,11 +1528,12 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no
newp = build_type_from_record_var($9, @9);
newp->collectionType = PLPGSQL_COLLECTION_ARRAY;
newp->tableOfIndexType = InvalidOid;
plpgsql_build_varrayType($2->name, $2->lineno, newp, true);
PLpgSQL_var* var = (PLpgSQL_var*)plpgsql_build_varrayType($2->name, $2->lineno, newp, true);
PLpgSQL_rec_type* rec_var = (PLpgSQL_rec_type*)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$9];
var->nest_typnames = get_current_type_nest_type(rec_var->nest_typnames, var->refname, true);
if (IS_PACKAGE) {
plpgsql_build_package_array_type($2->name, newp->typoid, TYPCATEGORY_ARRAY);
} else if (enable_plpgsql_gsdependency()) {
PLpgSQL_rec_type* rec_var = (PLpgSQL_rec_type*)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$9];
int i;
for (i = 0; i < rec_var->attrnum; i++) {
gsplsql_build_gs_type_in_body_dependency(rec_var->types[i]);
@ -1540,6 +1555,8 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no
PLpgSQL_var* var = (PLpgSQL_var*)plpgsql_build_varrayType($2->name, $2->lineno, nest_type, true);
/* nested table type */
var->nest_table = (PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$9];
List *old_nest_typenames = var->nest_table && var->nest_table->nest_typnames ? var->nest_table->nest_typnames : NULL;
var->nest_typnames = get_current_type_nest_type(old_nest_typenames, var->refname, true);
var->nest_layers = depth;
var->isIndexByTblOf = false;
pfree_ext($2->name);
@ -1581,17 +1598,19 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no
PLpgSQL_type *var_type = ((PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$3])->datatype;
PLpgSQL_var *varray_type = (PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$3];
PLpgSQL_var *newp;
PLpgSQL_type *new_var_type;
new_var_type = build_array_type_from_elemtype(var_type);
new_var_type->collectionType = var_type->collectionType;
new_var_type->tableOfIndexType = var_type->tableOfIndexType;
newp = (PLpgSQL_var *)plpgsql_build_variable(varname->name, varname->lineno, new_var_type, true);
newp->isconst = $2;
newp->default_val = $4;
newp->nest_typnames = varray_type->nest_typnames;
if (newp->default_val != NULL) {
checkTypeName(newp->default_val->nest_typnames, varray_type->nest_typnames);
}
if (NULL == newp) {
const char* message = "build variable failed";
@ -1651,7 +1670,8 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no
erraction("check define of table type")));
u_sess->plsql_cxt.have_error = true;
}
plpgsql_build_tableType($2->name, $2->lineno, $6, true);
PLpgSQL_var* var = (PLpgSQL_var*)plpgsql_build_tableType($2->name, $2->lineno, $6, true);
var->nest_typnames = get_current_type_nest_type(var->nest_typnames, var->refname, true);
if (IS_PACKAGE) {
plpgsql_build_package_array_type($2->name, $6->typoid, TYPCATEGORY_TABLEOF, $6->dependExtend);
} else if (enable_plpgsql_gsdependency()) {
@ -1672,6 +1692,8 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no
PLpgSQL_var* var = (PLpgSQL_var*)plpgsql_build_tableType($2->name, $2->lineno, nest_type, true);
/* nested table type */
var->nest_table = (PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$6];
List *old_nest_typenames = var->nest_table && var->nest_table->nest_typnames ? var->nest_table->nest_typnames : NULL;
var->nest_typnames = get_current_type_nest_type(old_nest_typenames, var->refname, true);
var->nest_layers = depth;
var->isIndexByTblOf = false;
pfree_ext($2->name);
@ -1715,11 +1737,12 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no
newp = build_type_from_record_var($6, @6);
newp->collectionType = PLPGSQL_COLLECTION_TABLE;
newp->tableOfIndexType = InvalidOid;
plpgsql_build_tableType($2->name, $2->lineno, newp, true);
PLpgSQL_var* var = (PLpgSQL_var*)plpgsql_build_tableType($2->name, $2->lineno, newp, true);
PLpgSQL_rec_type* rec_var = (PLpgSQL_rec_type*)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$6];
var->nest_typnames = get_current_type_nest_type(rec_var->nest_typnames, var->refname, true);
if (IS_PACKAGE) {
plpgsql_build_package_array_type($2->name, newp->typoid, TYPCATEGORY_TABLEOF);
} else if (enable_plpgsql_gsdependency()) {
PLpgSQL_rec_type* rec_var = (PLpgSQL_rec_type*)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$6];
int i;
for (i = 0; i < rec_var->attrnum; i++) {
gsplsql_build_gs_type_in_body_dependency(rec_var->types[i]);
@ -1962,7 +1985,10 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no
}
newp->isconst = $2;
newp->default_val = $4;
newp->nest_typnames = table_type->nest_typnames;
if (newp->default_val != NULL) {
checkTypeName(newp->default_val->nest_typnames, table_type->nest_typnames);
}
if (table_type->nest_table != NULL) {
newp->nest_table = plpgsql_build_nested_variable(table_type->nest_table, $2, varname->name, varname->lineno);
newp->nest_layers = table_type->nest_layers;
@ -1977,6 +2003,13 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no
PLpgSQL_rec_type *newp = NULL;
newp = plpgsql_build_rec_type($2->name, $2->lineno, $6, true);
PLpgSQL_nest_type *new_ntype = (PLpgSQL_nest_type *)palloc(sizeof(PLpgSQL_nest_type));
new_ntype->typname = pstrdup(newp->typname);
new_ntype->layer = 0;
new_ntype->index = 1;
newp->nest_typnames = lappend(newp->nest_typnames, new_ntype);
if (NULL == newp) {
const char* message = "build variable failed";
InsertErrorMessage(message, plpgsql_yylloc);
@ -2018,7 +2051,9 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no
u_sess->plsql_cxt.have_error = true;
}
if ($3 != NULL) {
((PLpgSQL_row *) newp)->default_val = $3;
PLpgSQL_row* row = (PLpgSQL_row*)newp;
row->default_val = $3;
checkTypeName($3->nest_typnames, row->nest_typnames);
}
pfree_ext(varname->name);
}
@ -2220,10 +2255,18 @@ opt_subtype_range :
record_attr_list : record_attr
{
$$ = list_make1($1);
if ($1->cur_ntype) {
$1->cur_ntype->index = $$->length;
$1->nest_typnames = lappend($1->nest_typnames, $1->cur_ntype);
}
}
| record_attr_list ',' record_attr
{
$$ = lappend($1, $3);
if ($3->cur_ntype) {
$3->cur_ntype->index = $$->length;
$3->nest_typnames = lappend($3->nest_typnames, $3->cur_ntype);
}
}
;
@ -2247,6 +2290,10 @@ record_attr : attr_name decl_datatype decl_notnull decl_rec_defval
attr->type = $2;
attr->notnull = $3;
attr->cur_ntype = (PLpgSQL_nest_type *)palloc(sizeof(PLpgSQL_nest_type));
attr->cur_ntype->index = -1;
List* nest_typnames = NIL;
attr->nest_typnames = search_external_nest_type(attr->type->typname, attr->type->typoid, 0, nest_typnames, attr->cur_ntype);
if ($4 != NULL)
{
if (attr->type->ttype == PLPGSQL_TTYPE_SCALAR)
@ -2301,7 +2348,14 @@ record_attr : attr_name decl_datatype decl_notnull decl_rec_defval
attr->attrname = $1;
attr->type = build_type_from_record_var($2, @2);
PLpgSQL_rec_type *var_type = (PLpgSQL_rec_type *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$2];
attr->cur_ntype = (PLpgSQL_nest_type *)palloc(sizeof(PLpgSQL_nest_type));
attr->cur_ntype->typname = pstrdup(var_type->typname);
attr->cur_ntype->layer = 1;
if (var_type->nest_typnames != NIL) {
attr->nest_typnames = get_current_type_nest_type(var_type->nest_typnames, NULL, false);
}
attr->notnull = $3;
if ($4 != NULL)
{
@ -2360,6 +2414,13 @@ record_attr : attr_name decl_datatype decl_notnull decl_rec_defval
new_var_type->tableOfIndexType = var_type->tableOfIndexType;
attr->type = new_var_type;
attr->notnull = $3;
attr->cur_ntype = (PLpgSQL_nest_type *)palloc(sizeof(PLpgSQL_nest_type));
attr->cur_ntype->typname = pstrdup(varray_type->refname);
attr->cur_ntype->layer = 1;
if (varray_type->nest_typnames != NIL) {
attr->nest_typnames = get_current_type_nest_type(varray_type->nest_typnames, NULL, false);
}
if ($4 != NULL)
{
if (attr->type->ttype == PLPGSQL_TTYPE_SCALAR)
@ -2406,6 +2467,13 @@ record_attr : attr_name decl_datatype decl_notnull decl_rec_defval
new_var_type->tableOfIndexType = var_type->tableOfIndexType;
attr->type = new_var_type;
attr->notnull = $3;
attr->cur_ntype = (PLpgSQL_nest_type *)palloc(sizeof(PLpgSQL_nest_type));
attr->cur_ntype->typname = pstrdup(table_type->refname);
attr->cur_ntype->layer = 1;
if (table_type->nest_typnames != NIL) {
attr->nest_typnames = get_current_type_nest_type(table_type->nest_typnames, NULL, false);
}
if ($4 != NULL)
{
if (attr->type->ttype == PLPGSQL_TTYPE_SCALAR)
@ -2970,6 +3038,16 @@ stmt_assign : assign_var assign_operator expr_until_semi
newp->varno = $1;
newp->expr = $3;
newp->sqlString = plpgsql_get_curline_query();
if (newp->expr) {
PLpgSQL_var* target = (PLpgSQL_var*)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[newp->varno];
List* nest_typnames = NIL;
if (target->dtype == PLPGSQL_DTYPE_RECORD || target->dtype == PLPGSQL_DTYPE_ROW) {
nest_typnames = ((PLpgSQL_row*)target)->nest_typnames;
} else if (target->dtype == PLPGSQL_DTYPE_VAR) {
nest_typnames = target->nest_typnames;
}
checkTypeName(newp->expr->nest_typnames, nest_typnames);
}
$$ = (PLpgSQL_stmt *)newp;
}
@ -8629,6 +8707,92 @@ static bool oid_is_function(Oid funcid, bool* isSystemObj)
return false;
}
static void checkTypeName(List* nest_typnames, List* target_nest_typnames)
{
if (!u_sess->attr.attr_sql.enable_pltype_name_check ||
nest_typnames == NIL || target_nest_typnames == NIL)
return;
ListCell* lc = NULL;
int i = 0;
foreach (lc, nest_typnames) {
PLpgSQL_nest_type* ntype = (PLpgSQL_nest_type*)lfirst(lc);
ListCell* target_typnames = target_nest_typnames->head;
PLpgSQL_nest_type* target_ntype = (PLpgSQL_nest_type*)lfirst(target_typnames);
char* functypname = NULL;
char* pkgtypname = NULL;
List* found_list = NIL;
bool found = false;
for (i = 0; i < target_nest_typnames->length; i++) {
if (target_ntype->layer == ntype->layer &&
(target_ntype->index == -1 || target_ntype->index == ntype->index)) {
found_list = lappend(found_list, target_ntype);
}
if (target_typnames) {
target_typnames = target_typnames->next;
if (target_typnames) {
target_ntype = (PLpgSQL_nest_type*)lfirst(target_typnames);
}
}
}
if (strchr(ntype->typname, '.') == NULL) {
getPkgFuncTypeName(ntype->typname, &functypname, &pkgtypname);
}
if (found_list != NIL) {
ListCell* lcf = NULL;
foreach(lcf, found_list) {
target_ntype = (PLpgSQL_nest_type*)lfirst(lcf);
bool is_row = strcasecmp(ntype->typname, "ROW") == 0;
bool is_equal = strcmp(ntype->typname, target_ntype->typname) == 0;
bool func_name_equal = functypname ? strcmp(functypname, target_ntype->typname) == 0 : false;
bool pkg_name_equal = pkgtypname ? strcmp(pkgtypname, target_ntype->typname) == 0 : false;
if (is_row || is_equal || func_name_equal || pkg_name_equal) {
found = true;
}
}
}
if (!found) {
char *mes = NULL;
char *report_mes = "Wrong type of expression, should not use type ";
int length = strlen(ntype->typname) + strlen(report_mes) + 3;
mes = (char*)palloc0(length);
errno_t rc = snprintf_s(mes, length, length -1, "%s\"%s\"", report_mes, ntype->typname);
securec_check_ss(rc, "", "");
InsertErrorMessage(mes, plpgsql_yylloc);
ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg(mes)));
}
}
}
static List* get_current_type_nest_type(List* old_nest_typenames, char* typname, bool add_current_type)
{
List* nest_typnames = NIL;
ListCell* lc = NULL;
if (old_nest_typenames != NIL) {
int i = 0;
PLpgSQL_nest_type *new_ntypes = (PLpgSQL_nest_type *)palloc(sizeof(PLpgSQL_nest_type) * old_nest_typenames->length);
foreach (lc, old_nest_typenames) {
PLpgSQL_nest_type *old_ntype = (PLpgSQL_nest_type *)lfirst(lc);
PLpgSQL_nest_type *new_ntype = new_ntypes + i;
new_ntype->typname = pstrdup(old_ntype->typname);
new_ntype->layer = old_ntype->layer + 1;
new_ntype->index = old_ntype->index;
nest_typnames = lappend(nest_typnames, new_ntype);
i++;
}
}
if (add_current_type) {
PLpgSQL_nest_type *ntype = (PLpgSQL_nest_type *)palloc(sizeof(PLpgSQL_nest_type));
ntype->typname = pstrdup(typname);
ntype->layer = 0;
ntype->index = -1;
nest_typnames = lappend(nest_typnames, ntype);
}
return nest_typnames;
}
/*
* @brief is_datatype
* check if a given type is a datatype
@ -8997,6 +9161,9 @@ read_sql_construct6(int until,
bool ds_changed = false;
ArrayParseContext context;
List *idents = 0;
List* nest_typnames = NIL;
int comma_cnt = 0;
int typname_indexs[MAX_LAYER] = {0};
const char left_bracket[2] = "[";
const char right_bracket[2] = "]";
const char left_parentheses[2] = "(";
@ -9009,7 +9176,7 @@ read_sql_construct6(int until,
int right_brace_count = 0;
bool stop_count = false;
int stop_tok;
/* mark if there are 2 table of index by var call functions in an expr */
/* mark if there are 2 table of index by var call functions in an expr */
int tableof_func_dno = -1;
int tableof_var_dno = -1;
bool is_have_tableof_index_var = false;
@ -9037,6 +9204,10 @@ read_sql_construct6(int until,
{
prev_tok = tok;
tok = yylex();
if (tok == ',' && (left_brace_count - right_brace_count) > 0 &&
(left_brace_count - right_brace_count) < MAX_LAYER) {
typname_indexs[left_brace_count - right_brace_count] = typname_indexs[left_brace_count - right_brace_count] + 1;
}
if (tok == '\"' || tok == '\'') {
if (stop_count && stop_tok == tok) {
stop_count = false;
@ -9617,6 +9788,11 @@ read_sql_construct6(int until,
{
nest_layers = var->nest_layers;
}
PLpgSQL_nest_type* ntype = (PLpgSQL_nest_type*)palloc(sizeof(PLpgSQL_nest_type));
ntype->typname = pstrdup(var->refname);
ntype->layer = left_brace_count - right_brace_count;
ntype->index = typname_indexs[ntype->layer] + 1;
nest_typnames = lappend(nest_typnames, ntype);
ds_changed = construct_array_start(&ds, &context, var->datatype, &tok, parenlevel, loc);
break;
}
@ -9642,9 +9818,25 @@ read_sql_construct6(int until,
{
nest_layers = var->nest_layers;
}
PLpgSQL_nest_type* ntype = (PLpgSQL_nest_type*)palloc(sizeof(PLpgSQL_nest_type));
ntype->typname = pstrdup(var->refname);
ntype->layer = left_brace_count - right_brace_count;
ntype->index = typname_indexs[ntype->layer] + 1;
nest_typnames = lappend(nest_typnames, ntype);
ds_changed = construct_array_start(&ds, &context, var->datatype, &tok, parenlevel, loc);
break;
}
case T_RECORD:
{
int dno = yylval.wdatum.datum->dno;
PLpgSQL_rec_type* rec_type = (PLpgSQL_rec_type *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[dno];
PLpgSQL_nest_type* ntype = (PLpgSQL_nest_type*)palloc(sizeof(PLpgSQL_nest_type));
ntype->typname = pstrdup(rec_type->typname);
ntype->layer = left_brace_count - right_brace_count;
ntype->index = typname_indexs[ntype->layer] + 1;
nest_typnames = lappend(nest_typnames, ntype);
break;
}
case T_DATUM:
{
idents = yylval.wdatum.idents;
@ -9669,12 +9861,64 @@ read_sql_construct6(int until,
}
}
case T_WORD:
{
char *name = yylval.word.ident;
PLpgSQL_nest_type* ntype = (PLpgSQL_nest_type*)palloc(sizeof(PLpgSQL_nest_type));
ntype->typname = pstrdup(name);
ntype->layer = left_brace_count - right_brace_count;
ntype->index = typname_indexs[ntype->layer] + 1;
nest_typnames = lappend(nest_typnames, ntype);
AddNamespaceIfPkgVar(yylval.word.ident, save_IdentifierLookup);
ds_changed = construct_word(&ds, &context, &tok, parenlevel, loc);
break;
}
case T_CWORD:
{
List* name_list = yylval.cword.idents;
switch(name_list->length) {
case 2:
{
char* packageName = strVal(linitial(name_list));
char* typeName = strVal(lsecond(name_list));
Oid namespaceOid = getCurrentNamespace();
Oid pkgOid = packageName ? PackageNameGetOid(packageName, namespaceOid) : InvalidOid;
if (pkgOid != InvalidOid && namespaceOid != InvalidOid) {
Oid type_oid = LookupTypeInPackage(name_list, typeName, pkgOid, namespaceOid);
if (type_oid != InvalidOid) {
char* castTypeName = CastPackageTypeName(typeName, pkgOid, pkgOid != InvalidOid, true);
PLpgSQL_nest_type* ntype = (PLpgSQL_nest_type*)palloc(sizeof(PLpgSQL_nest_type));
ntype->typname = pstrdup(castTypeName);
ntype->layer = left_brace_count - right_brace_count;
ntype->index = typname_indexs[ntype->layer] + 1;
nest_typnames = lappend(nest_typnames, ntype);
}
}
break;
}
case 3:
{
char* namesapceName = strVal(linitial(name_list));
char* packageName = strVal(lsecond(name_list));
char* typeName = strVal(lthird(name_list));
Oid namespaceOid = namesapceName ? get_namespace_oid(namesapceName, true) : InvalidOid;
Oid pkgOid = packageName ? PackageNameGetOid(packageName, namespaceOid) : InvalidOid;
if (pkgOid != InvalidOid && namespaceOid != InvalidOid) {
Oid type_oid = LookupTypeInPackage(name_list, typeName, pkgOid, namespaceOid);
if (type_oid != InvalidOid) {
char* castTypeName = CastPackageTypeName(typeName, pkgOid, pkgOid != InvalidOid, true);
PLpgSQL_nest_type* ntype = (PLpgSQL_nest_type*)palloc(sizeof(PLpgSQL_nest_type));
ntype->typname = pstrdup(castTypeName);
ntype->layer = left_brace_count - right_brace_count;
ntype->index = typname_indexs[ntype->layer] + 1;
nest_typnames = lappend(nest_typnames, ntype);
}
}
break;
}
}
ds_changed = construct_cword(&ds, &context, &tok, parenlevel, loc);
break;
}
case T_OBJECT_TYPE_VAR_METHOD:
{
appendStringInfo(&ds, " %s(", yylval.wdatum.ident);
@ -9810,6 +10054,7 @@ read_sql_construct6(int until,
expr->tableof_var_dno = tableof_var_dno;
expr->is_have_tableof_index_func = tableof_func_dno != -1 ? true : false;
expr->tableof_func_dno = tableof_func_dno;
expr->nest_typnames = nest_typnames ? nest_typnames : NIL;
pfree_ext(ds.data);
@ -15158,4 +15403,4 @@ yylex_object_type_selfparam(char ** fieldnames,
varnos[nfields] = -1;
}
pfree_ext(ds.data);
}
}

View File

@ -49,6 +49,7 @@
#include "utils/rel.h"
#include "utils/rel_gs.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
#include "miscadmin.h"
#include "tcop/tcopprot.h"
#include "commands/event_trigger.h"
@ -4222,6 +4223,7 @@ PLpgSQL_rec_type* plpgsql_build_rec_type(const char* typname, int lineno, List*
ListCell* cell = NULL;
PLpgSQL_rec_attr* attr = NULL;
PLpgSQL_rec_type* result = NULL;
List* nest_typnames = NIL;
result = (PLpgSQL_rec_type*)palloc0(sizeof(PLpgSQL_rec_type));
@ -4241,10 +4243,12 @@ PLpgSQL_rec_type* plpgsql_build_rec_type(const char* typname, int lineno, List*
result->attrnames[idx] = pstrdup(attr->attrname);
result->types[idx] = attr->type;
nest_typnames = lappend3(nest_typnames, attr->nest_typnames);
result->notnulls[idx] = attr->notnull;
result->defaultvalues[idx] = attr->defaultvalue;
idx++;
}
result->nest_typnames = nest_typnames;
varno = plpgsql_adddatum((PLpgSQL_datum*)result);
@ -4254,6 +4258,38 @@ PLpgSQL_rec_type* plpgsql_build_rec_type(const char* typname, int lineno, List*
return result;
}
List* search_external_nest_type(char* name, Oid typeOid, int layer, List* nest_typnames, PLpgSQL_nest_type* cur_ntype)
{
HeapTuple tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
PLpgSQL_nest_type* nntype = NULL;
int typmod = -1;
int natts = 1;
layer++;
if (tuple) {
cur_ntype->typname = pstrdup(name);
cur_ntype->layer = layer;
if (cur_ntype->index != -1) {
nest_typnames = lappend(nest_typnames, cur_ntype);
}
TupleDesc tuple_desc = lookup_rowtype_tupdesc_noerror(typeOid, typmod, true);
if (tuple_desc) {
natts = tuple_desc->natts;
for (int i = 0; i < natts; i++) {
Form_pg_attribute attr = TupleDescAttr(tuple_desc, i);
if (!attr->attisdropped && attr->atttypid != InvalidOid) {
char* typname = get_typename(attr->atttypid);
PLpgSQL_nest_type* new_ntype = (PLpgSQL_nest_type *)palloc(sizeof(PLpgSQL_nest_type));
new_ntype->index = i + 1;
nest_typnames = search_external_nest_type(typname, attr->atttypid, layer, nest_typnames, new_ntype);
}
}
ReleaseTupleDesc(tuple_desc);
}
ReleaseSysCache(tuple);
}
return nest_typnames;
}
/*
* typname: SUBTYPE name
* basetypname: base type name
@ -4557,6 +4593,7 @@ PLpgSQL_row* build_row_from_rec_type(const char* rowname, int lineno, PLpgSQL_re
row->default_val = NULL;
row->recordVarTypOid = type->typoid;
row->atomically_null_object = false;
row->nest_typnames = type->nest_typnames;
for (int i = 0; i < row->nfields; i++) {
PLpgSQL_variable* var = NULL;

View File

@ -251,6 +251,7 @@ typedef struct knl_session_attr_sql {
char* db4ai_snapshot_version_delimiter;
char* db4ai_snapshot_version_separator;
bool enable_ignore_case_in_dquotes;
bool enable_pltype_name_check;
int pldebugger_timeout;
bool partition_page_estimation;
bool enable_opfusion_reuse;

View File

@ -323,6 +323,11 @@ typedef enum {
/**********************************************************************
* Node and structure definitions
**********************************************************************/
typedef struct PLpgSQL_nest_type { /* Generic datum array item */
char* typname;
int layer;
int index;
} PLpgSQL_nest_type;
/*
* PLpgSQL_datum is the common supertype for PLpgSQL_expr, PLpgSQL_var,
* PLpgSQL_row, PLpgSQL_rec, PLpgSQL_recfield, and PLpgSQL_arrayelem
@ -400,6 +405,7 @@ typedef struct PLpgSQL_expr { /* SQpL Query to plan and execute */
int dno;
bool ispkg;
char* query;
List* nest_typnames;
SPIPlanPtr plan;
Bitmapset* paramnos; /* all dnos referenced by this query */
@ -530,6 +536,7 @@ typedef struct PLpgSQL_var { /* Scalar variable */
struct PLpgSQL_var* nest_table; /* origin nest table type, copy from it when add new nest table */
HTAB* tableOfIndex = NULL; /* mapping of table of index */
int nest_layers = 0;
List* nest_typnames;
} PLpgSQL_var;
typedef struct { /* Row variable */
@ -566,6 +573,7 @@ typedef struct { /* Row variable */
Oid recordVarTypOid; /* package record var's composite type oid */
bool hasExceptionInit;
bool atomically_null_object;
List* nest_typnames;
} PLpgSQL_row;
typedef struct {
@ -573,6 +581,8 @@ typedef struct {
PLpgSQL_type* type;
bool notnull;
PLpgSQL_expr* defaultvalue;
List* nest_typnames;
PLpgSQL_nest_type* cur_ntype;
} PLpgSQL_rec_attr;
typedef struct {
@ -595,6 +605,7 @@ typedef struct {
bool* notnulls;
bool addNamespace;
PLpgSQL_expr** defaultvalues;
List* nest_typnames;
} PLpgSQL_rec_type;
typedef struct { /* Record variable (non-fixed structure) */
@ -1825,6 +1836,8 @@ extern PLpgSQL_variable* plpgsql_build_variable(const char* refname, int lineno,
PLpgSQL_variable* plpgsql_build_varrayType(const char* refname, int lineno, PLpgSQL_type* dtype, bool add2namespace);
PLpgSQL_variable* plpgsql_build_tableType(const char* refname, int lineno, PLpgSQL_type* dtype, bool add2namespace);
extern PLpgSQL_rec_type* plpgsql_build_rec_type(const char* typname, int lineno, List* list, bool add2namespace);
extern List* search_external_nest_type(char* name, Oid typeOid,
int layer, List* nest_typnames, PLpgSQL_nest_type* cur_ntype);
extern PLpgSQL_rec* plpgsql_build_record(const char* refname, int lineno, bool add2namespace, TupleDesc tupleDesc);
extern void plpgsql_build_synonym(char* typname, char* basetypname);
extern int plpgsql_recognize_err_condition(const char* condname, bool allow_sqlstate);

View File

@ -236,6 +236,776 @@ CONTEXT: referenced column: get_age
456
(1 row)
--test assign a value to a variable with a custom type
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
TYPE t_rec2 IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec:= t_rec2(1, ',', 'TWO', 'THREE');
BEGIN
raise info 'team.LIMIT = %', l_rec.val1;
END;
/
INFO: team.LIMIT = ,
set enable_pltype_name_check = on;
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
TYPE t_rec2 IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec:= t_rec(1, 'ONE', 'TWO', 'THREE');
BEGIN
raise info 'team.LIMIT = %', l_rec.val1;
END;
/
INFO: team.LIMIT = ONE
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
TYPE t_rec2 IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec:= t_rec2(1, ',', 'TWO', 'THREE');
BEGIN
raise info 'team.LIMIT = %', l_rec.val1;
END;
/
ERROR: Wrong type of expression, should not use type "t_rec2"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 11
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
TYPE t_rec2 IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec:= t_rec2(1, 'ONE', 'TWO', 'THREE');
BEGIN
raise info 'team.LIMIT = %', l_rec.val1;
END;
/
ERROR: Wrong type of expression, should not use type "t_rec2"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 11
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
TYPE t_rec2 IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec;
BEGIN
l_rec := t_rec2(1, 'ONE', 'TWO', 'THREE');
END;
/
ERROR: Wrong type of expression, should not use type "t_rec2"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 13
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec;
BEGIN
l_rec := t_rec(1, 'ONE', 'TWO', 'THREE');
END;
/
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec;
BEGIN
l_rec := ROW(1, 'ONE', 'TWO', 'THREE');
END;
/
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec;
BEGIN
l_rec := row(1, 'ONE', 'TWO', 'THREE');
END;
/
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec;
BEGIN
l_rec := t_rec2(1, 'ONE', 'TWO', 'THREE');
END;
/
ERROR: Wrong type of expression, should not use type "t_rec2"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 8
DECLARE
TYPE nt_type IS TABLE OF INTEGER;
TYPE va_type IS VARRAY(4) OF INTEGER;
nt nt_type;
BEGIN
nt := va_type(1,3,5);
raise info 'nt(1) = %', nt(1);
raise info 'nt(3) = %', nt(3);
END;
/
ERROR: Wrong type of expression, should not use type "va_type"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 5
DECLARE
TYPE nt_type IS TABLE OF INTEGER;
TYPE va_type IS VARRAY(4) OF INTEGER;
nt nt_type;
BEGIN
nt := nt_type(1,3,5);
raise info 'team.LIMIT = %', nt(2);
END;
/
INFO: team.LIMIT = 3
DECLARE
TYPE nt_type IS TABLE OF INTEGER;
TYPE va_type IS VARRAY(4) OF INTEGER;
nt nt_type:= va_type(1,3,5);
BEGIN
raise info 'nt(3) = %', nt(1);
END;
/
ERROR: Wrong type of expression, should not use type "va_type"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 3
DECLARE
TYPE nt_type IS TABLE OF INTEGER;
TYPE va_type IS VARRAY(4) OF INTEGER;
nt nt_type:= nt_type(1,3,5);
BEGIN
raise info 'nt(3) = %', nt(1);
END;
/
INFO: nt(3) = 1
DECLARE
TYPE va_type IS VARRAY(4) OF INTEGER;
nt va_type := va_type(1,3,5);
BEGIN
raise info 'nt(1) = %', nt(1);
raise info 'nt(3) = %', nt(3);
END;
/
INFO: nt(1) = 1
INFO: nt(3) = 5
DECLARE
TYPE va_type IS VARRAY(4) OF INTEGER;
nt va_type;
BEGIN
nt := va_type(1,3,5);
raise info 'nt(1) = %', nt(1);
raise info 'nt(3) = %', nt(3);
END;
/
INFO: nt(1) = 1
INFO: nt(3) = 5
DECLARE
TYPE nt_type IS TABLE OF INTEGER;
nt nt_type := nt_type(1,3,5);
BEGIN
raise info 'nt(1) = %', nt(1);
raise info 'nt(3) = %', nt(3);
END;
/
INFO: nt(1) = 1
INFO: nt(3) = 5
DECLARE
TYPE nt_type IS TABLE OF INTEGER;
nt nt_type;
BEGIN
nt := nt_type(1,3,5);
raise info 'nt(1) = %', nt(1);
raise info 'nt(3) = %', nt(3);
END;
/
INFO: nt(1) = 1
INFO: nt(3) = 5
--test nest record
create type to1 as (val1 VARCHAR2(10), val2 VARCHAR2(10));
create type to2 as (val3 VARCHAR2(10), val4 to1);
create type to3 as (val5 VARCHAR2(10), val6 to2, val7 to1);
DECLARE
l_rec to3:= ('ONE', to2('TWO',to2(',', 'FOUR')),to1('FIVE','SIX'));
BEGIN
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
ERROR: Wrong type of expression, should not use type "to2"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 1
DECLARE
l_rec to3;
BEGIN
l_rec := ('ONE', to2('TWO',to3(',', 'FOUR')),to1('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
ERROR: Wrong type of expression, should not use type "to3"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 3
CREATE OR REPLACE PACKAGE r_types IS
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val4 t_rec0, val3 VARCHAR2(10));
END r_types;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val6 r_types.t_rec1, val7 r_types.t_rec0, val5 VARCHAR2(10));
l_rec t_rec2;
BEGIN
l_rec := t_rec2(r_types.t_rec1(r_types.t_rec0(',', 'FOUR'), 'TWO'), r_types.t_rec0('FIVE','SIX'), 'ONE');
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val6 r_types.t_rec1, val7 r_types.t_rec0, val5 VARCHAR2(10));
l_rec t_rec2;
BEGIN
l_rec := t_rec2(r_types.t_rec1(r_types.t_rec1(',', 'FOUR'), 'TWO'), r_types.t_rec0('FIVE','SIX'), 'ONE');
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
--?.*
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 5
CREATE OR REPLACE PACKAGE r_types IS
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 t_rec0);
END r_types;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 r_types.t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 r_types.t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',r_types.t_rec1(',', 'FOUR')),r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
--?.*
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 5
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 r_types.t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),t_rec2('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
ERROR: Wrong type of expression, should not use type "t_rec2"
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 5
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 r_types.t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
--?.*
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 6
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 r_types.t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 r_types.t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),t_rec2('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
--?.*
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 6
DROP PACKAGE r_types;
--?.*
CREATE OR REPLACE PACKAGE plpgsql_assignlist.r_types IS
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val4 t_rec0, val3 VARCHAR2(10));
END r_types;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val6 plpgsql_assignlist.r_types.t_rec1, val7 plpgsql_assignlist.r_types.t_rec0, val5 VARCHAR2(10));
l_rec t_rec2;
BEGIN
l_rec := t_rec2(r_types.t_rec1(r_types.t_rec0(',', 'FOUR'), 'TWO'),plpgsql_assignlist.r_types.t_rec0('FIVE','SIX'), 'ONE');
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val6 plpgsql_assignlist.r_types.t_rec1, val7 r_types.t_rec0, val5 VARCHAR2(10));
l_rec t_rec2;
BEGIN
l_rec := t_rec2(r_types.t_rec1(plpgsql_assignlist.r_types.t_rec1(',', 'FOUR'), 'TWO'),r_types.t_rec0('FIVE','SIX'), 'ONE');
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
--?.*
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 5
CREATE OR REPLACE PACKAGE plpgsql_assignlist.r_types IS
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 t_rec0);
END r_types;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 plpgsql_assignlist.r_types.t_rec1, val7 plpgsql_assignlist.r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),plpgsql_assignlist.r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 plpgsql_assignlist.r_types.t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',plpgsql_assignlist.r_types.t_rec1(',', 'FOUR')),r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
--?.*
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 5
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 r_types.t_rec1, val7 plpgsql_assignlist.r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', plpgsql_assignlist.r_types.t_rec1('TWO',plpgsql_assignlist.r_types.t_rec0(',', 'FOUR')),t_rec2('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
ERROR: Wrong type of expression, should not use type "t_rec2"
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 5
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 plpgsql_assignlist.r_types.t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 plpgsql_assignlist.r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', plpgsql_assignlist.r_types.t_rec1('TWO',plpgsql_assignlist.r_types.t_rec0(',', 'FOUR')),plpgsql_assignlist.r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
--?.*
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 6
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 r_types.t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', t_rec1('TWO',plpgsql_assignlist.r_types.t_rec0(',', 'FOUR')),r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 plpgsql_assignlist.r_types.t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', plpgsql_assignlist.r_types.t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),t_rec2('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
--?.*
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 6
DROP PACKAGE r_types;
--?.*
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE arr2 IS VARRAY(5) OF INTEGER;
TYPE arr1 IS VARRAY(5) OF INTEGER;
TYPE nt1 IS VARRAY(10) OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1:=rec1(7, nt1(arr2(1,2,4,5),arr1(1,3)));
BEGIN
RAISE NOTICE 'ID: %', arr_rec.id;
END;
/
ERROR: nested table of type is not supported as record type attribute
LINE 5: TYPE rec1 IS RECORD(id int, arrarg nt1);
^
QUERY: DECLARE
TYPE arr2 IS VARRAY(5) OF INTEGER;
TYPE arr1 IS VARRAY(5) OF INTEGER;
TYPE nt1 IS VARRAY(10) OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1:=rec1(7, nt1(arr2(1,2,4,5),arr1(1,3)));
BEGIN
RAISE NOTICE 'ID: %', arr_rec.id;
END
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE arr2 IS VARRAY(5) OF INTEGER;
TYPE arr1 IS VARRAY(5) OF INTEGER;
TYPE nt1 IS VARRAY(10) OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1:=rec1(7, nt1(arr1(1,2,4,5),arr1(1,3)));
BEGIN
RAISE NOTICE 'ID: %', arr_rec.id;
END;
/
ERROR: nested table of type is not supported as record type attribute
LINE 5: TYPE rec1 IS RECORD(id int, arrarg nt1);
^
QUERY: DECLARE
TYPE arr2 IS VARRAY(5) OF INTEGER;
TYPE arr1 IS VARRAY(5) OF INTEGER;
TYPE nt1 IS VARRAY(10) OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1:=rec1(7, nt1(arr1(1,2,4,5),arr1(1,3)));
BEGIN
RAISE NOTICE 'ID: %', arr_rec.id;
END
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE arr2 IS VARRAY(5) OF INTEGER;
TYPE arr1 IS VARRAY(5) OF INTEGER;
TYPE nt1 IS VARRAY(10) OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1;
BEGIN
arr_rec:=rec1(7, nt1(arr2(1,2,4,5),arr1(1,3)))
RAISE NOTICE 'ID: %', arr_rec.id;
END;
/
ERROR: nested table of type is not supported as record type attribute
LINE 5: TYPE rec1 IS RECORD(id int, arrarg nt1);
^
QUERY: DECLARE
TYPE arr2 IS VARRAY(5) OF INTEGER;
TYPE arr1 IS VARRAY(5) OF INTEGER;
TYPE nt1 IS VARRAY(10) OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1;
BEGIN
arr_rec:=rec1(7, nt1(arr2(1,2,4,5),arr1(1,3)))
RAISE NOTICE 'ID: %', arr_rec.id;
END
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE arr2 IS TABLE OF INTEGER;
TYPE arr1 IS TABLE OF INTEGER;
TYPE nt1 IS TABLE OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1:=rec1(7, nt1(arr2(1,2,4,5),arr1(1,3)));
BEGIN
RAISE NOTICE 'ID: %', arr_rec.id;
END;
/
ERROR: nested table of type is not supported as record type attribute
LINE 5: TYPE rec1 IS RECORD(id int, arrarg nt1);
^
QUERY: DECLARE
TYPE arr2 IS TABLE OF INTEGER;
TYPE arr1 IS TABLE OF INTEGER;
TYPE nt1 IS TABLE OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1:=rec1(7, nt1(arr2(1,2,4,5),arr1(1,3)));
BEGIN
RAISE NOTICE 'ID: %', arr_rec.id;
END
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE arr2 IS TABLE OF INTEGER;
TYPE arr1 IS TABLE OF INTEGER;
TYPE nt1 IS TABLE OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1:=rec1(7, nt1(arr1(1,2,4,5),arr1(1,3)));
BEGIN
RAISE NOTICE 'ID: %', arr_rec.id;
END;
/
ERROR: nested table of type is not supported as record type attribute
LINE 5: TYPE rec1 IS RECORD(id int, arrarg nt1);
^
QUERY: DECLARE
TYPE arr2 IS TABLE OF INTEGER;
TYPE arr1 IS TABLE OF INTEGER;
TYPE nt1 IS TABLE OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1:=rec1(7, nt1(arr1(1,2,4,5),arr1(1,3)));
BEGIN
RAISE NOTICE 'ID: %', arr_rec.id;
END
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE arr2 IS TABLE OF INTEGER;
TYPE arr1 IS TABLE OF INTEGER;
TYPE nt1 IS TABLE OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1;
BEGIN
arr_rec:=rec1(7, nt1(arr2(1,2,4,5),arr1(1,3)))
RAISE NOTICE 'ID: %', arr_rec.id;
END;
/
ERROR: nested table of type is not supported as record type attribute
LINE 5: TYPE rec1 IS RECORD(id int, arrarg nt1);
^
QUERY: DECLARE
TYPE arr2 IS TABLE OF INTEGER;
TYPE arr1 IS TABLE OF INTEGER;
TYPE nt1 IS TABLE OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1;
BEGIN
arr_rec:=rec1(7, nt1(arr2(1,2,4,5),arr1(1,3)))
RAISE NOTICE 'ID: %', arr_rec.id;
END
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 to2, val7 to1);
l_rec t_rec2;
BEGIN
l_rec := ('ONE', to2('TWO',to2(',', 'FOUR')),to1('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
ERROR: Wrong type of expression, should not use type "to2"
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 5
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 to2, val7 to1);
l_rec t_rec2;
BEGIN
l_rec := ('ONE', to2('TWO',to1(',', 'FOUR')),to1('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 to2, val7 t_rec0);
l_rec t_rec2;
BEGIN
l_rec := ('ONE', to2('TWO',to1(',', 'FOUR')),to1('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
ERROR: Wrong type of expression, should not use type "to1"
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 7
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 to1);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 to2, val7 t_rec1);
l_rec t_rec2;
BEGIN
l_rec := ('ONE', to2('TWO',to1(',', 'FOUR')),t_rec2('A', to1('FIVE','SIX')));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val4.val1;
END;
/
ERROR: Wrong type of expression, should not use type "t_rec2"
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 7
DECLARE
l_rec to3;
BEGIN
l_rec := to2('ONE', to2('TWO',to1(',', 'FOUR')),to1('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
ERROR: Wrong type of expression, should not use type "to2"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 3
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 t_rec0);
l_rec t_rec2;
BEGIN
l_rec := ('ONE', t_rec1('TWO',t_rec2(',', 'FOUR')),t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
ERROR: Wrong type of expression, should not use type "t_rec2"
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 7
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 t_rec0);
l_rec t_rec2 := ('ONE', t_rec1(',',t_rec2('THREE', 'FOUR')),t_rec0('FIVE','SIX'));
BEGIN
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
ERROR: Wrong type of expression, should not use type "t_rec2"
CONTEXT: compilation of PL/pgSQL function "test_nested" near line 5
--test nest table
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE t2 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE nt2 IS VARRAY(10) OF t2; -- varray of varray of integer
TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer
TYPE nt22 IS VARRAY(10) OF nt2; -- varray of varray of integer
TYPE nt11 IS VARRAY(10) OF nt1; -- varray of varray of integer
nva nt11;
BEGIN
nva := nt11(nt1(t1(4,5,6), t2(55,6,73), t1(2,4), t1(2,5,6)),nt1(t1(2,4),t1(2,8)));
END;
/
ERROR: Wrong type of expression, should not use type "t2"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 9
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE t2 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE nt2 IS VARRAY(10) OF t2; -- varray of varray of integer
TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer
TYPE nt22 IS VARRAY(10) OF nt2; -- varray of varray of integer
TYPE nt11 IS VARRAY(10) OF nt1; -- varray of varray of integer
nva nt11;
BEGIN
nva := nt22(nt1(t1(4,5,6), t1(55,6,73), t1(2,4), t1(2,5,6)),nt1(t1(2,4),t1(2,8)));
END;
/
ERROR: Wrong type of expression, should not use type "nt22"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 9
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE t2 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE nt2 IS VARRAY(10) OF t2; -- varray of varray of integer
TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer
TYPE nt22 IS VARRAY(10) OF nt2; -- varray of varray of integer
TYPE nt11 IS VARRAY(10) OF nt1; -- varray of varray of integer
nva nt11;
BEGIN
nva := nt11(nt1(t1(4,5,6), t1(55,6,73), t1(2,4), t1(2,5,6)),nt2(t1(2,4),t1(2,8)));
END;
/
ERROR: Wrong type of expression, should not use type "nt2"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 9
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE t2 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE nt2 IS VARRAY(10) OF t2; -- varray of varray of integer
TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer
TYPE nt22 IS VARRAY(10) OF nt2; -- varray of varray of integer
TYPE nt11 IS VARRAY(10) OF nt1; -- varray of varray of integer
nva nt11 := nt11(nt1(t1(4,5,6), t2(55,6,73), t1(2,4), t1(2,5,6)),nt1(t1(2,4),t1(2,8)));
va2 t2;
BEGIN
va2(1):=9;
END;
/
ERROR: Wrong type of expression, should not use type "t2"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 7
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE t2 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE nt2 IS VARRAY(10) OF t2; -- varray of varray of integer
TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer
TYPE nt22 IS VARRAY(10) OF nt2; -- varray of varray of integer
TYPE nt11 IS VARRAY(10) OF nt1; -- varray of varray of integer
nva nt11 := nt22(nt1(t1(4,5,6), t1(55,6,73), t1(2,4), t1(2,5,6)),nt1(t1(2,4),t1(2,8)));
va2 t2;
BEGIN
va2(1):=9;
END;
/
ERROR: Wrong type of expression, should not use type "nt22"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 7
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE t2 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE nt2 IS VARRAY(10) OF t2; -- varray of varray of integer
TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer
TYPE nt22 IS VARRAY(10) OF nt2; -- varray of varray of integer
TYPE nt11 IS VARRAY(10) OF nt1; -- varray of varray of integer
nva nt11 := nt11(nt1(t1(4,5,6), t1(55,6,73), t1(2,4), t1(2,5,6)),nt2(t1(2,4),t1(2,8)));
va2 t2;
BEGIN
va2(1):=9;
END;
/
ERROR: Wrong type of expression, should not use type "nt2"
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 7
set enable_pltype_name_check = off;
--test o1.col1.col2 ref
create type ct as (num int,info text);
create type ct1 as (num int,info ct);
@ -306,3 +1076,8 @@ drop type if exists o2;
drop type if exists o1;
-- clean up --
drop schema if exists plpgsql_assignlist cascade;
NOTICE: drop cascades to 4 other objects
DETAIL: drop cascades to type to1
drop cascades to type to2
drop cascades to type to3
drop cascades to function test_nested()

View File

@ -158,6 +158,699 @@ end;
$$ language plpgsql;
select get_age();
--test assign a value to a variable with a custom type
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
TYPE t_rec2 IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec:= t_rec2(1, ',', 'TWO', 'THREE');
BEGIN
raise info 'team.LIMIT = %', l_rec.val1;
END;
/
set enable_pltype_name_check = on;
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
TYPE t_rec2 IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec:= t_rec(1, 'ONE', 'TWO', 'THREE');
BEGIN
raise info 'team.LIMIT = %', l_rec.val1;
END;
/
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
TYPE t_rec2 IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec:= t_rec2(1, ',', 'TWO', 'THREE');
BEGIN
raise info 'team.LIMIT = %', l_rec.val1;
END;
/
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
TYPE t_rec2 IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec:= t_rec2(1, 'ONE', 'TWO', 'THREE');
BEGIN
raise info 'team.LIMIT = %', l_rec.val1;
END;
/
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
TYPE t_rec2 IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec;
BEGIN
l_rec := t_rec2(1, 'ONE', 'TWO', 'THREE');
END;
/
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec;
BEGIN
l_rec := t_rec(1, 'ONE', 'TWO', 'THREE');
END;
/
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec;
BEGIN
l_rec := ROW(1, 'ONE', 'TWO', 'THREE');
END;
/
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec;
BEGIN
l_rec := row(1, 'ONE', 'TWO', 'THREE');
END;
/
DECLARE
TYPE t_rec IS RECORD (
id NUMBER,
val1 VARCHAR2(10),
val2 VARCHAR2(10),
val3 VARCHAR2(10) );
l_rec t_rec;
BEGIN
l_rec := t_rec2(1, 'ONE', 'TWO', 'THREE');
END;
/
DECLARE
TYPE nt_type IS TABLE OF INTEGER;
TYPE va_type IS VARRAY(4) OF INTEGER;
nt nt_type;
BEGIN
nt := va_type(1,3,5);
raise info 'nt(1) = %', nt(1);
raise info 'nt(3) = %', nt(3);
END;
/
DECLARE
TYPE nt_type IS TABLE OF INTEGER;
TYPE va_type IS VARRAY(4) OF INTEGER;
nt nt_type;
BEGIN
nt := nt_type(1,3,5);
raise info 'team.LIMIT = %', nt(2);
END;
/
DECLARE
TYPE nt_type IS TABLE OF INTEGER;
TYPE va_type IS VARRAY(4) OF INTEGER;
nt nt_type:= va_type(1,3,5);
BEGIN
raise info 'nt(3) = %', nt(1);
END;
/
DECLARE
TYPE nt_type IS TABLE OF INTEGER;
TYPE va_type IS VARRAY(4) OF INTEGER;
nt nt_type:= nt_type(1,3,5);
BEGIN
raise info 'nt(3) = %', nt(1);
END;
/
DECLARE
TYPE va_type IS VARRAY(4) OF INTEGER;
nt va_type := va_type(1,3,5);
BEGIN
raise info 'nt(1) = %', nt(1);
raise info 'nt(3) = %', nt(3);
END;
/
DECLARE
TYPE va_type IS VARRAY(4) OF INTEGER;
nt va_type;
BEGIN
nt := va_type(1,3,5);
raise info 'nt(1) = %', nt(1);
raise info 'nt(3) = %', nt(3);
END;
/
DECLARE
TYPE nt_type IS TABLE OF INTEGER;
nt nt_type := nt_type(1,3,5);
BEGIN
raise info 'nt(1) = %', nt(1);
raise info 'nt(3) = %', nt(3);
END;
/
DECLARE
TYPE nt_type IS TABLE OF INTEGER;
nt nt_type;
BEGIN
nt := nt_type(1,3,5);
raise info 'nt(1) = %', nt(1);
raise info 'nt(3) = %', nt(3);
END;
/
--test nest record
create type to1 as (val1 VARCHAR2(10), val2 VARCHAR2(10));
create type to2 as (val3 VARCHAR2(10), val4 to1);
create type to3 as (val5 VARCHAR2(10), val6 to2, val7 to1);
DECLARE
l_rec to3:= ('ONE', to2('TWO',to2(',', 'FOUR')),to1('FIVE','SIX'));
BEGIN
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
DECLARE
l_rec to3;
BEGIN
l_rec := ('ONE', to2('TWO',to3(',', 'FOUR')),to1('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val4 t_rec0, val3 VARCHAR2(10));
END r_types;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val6 r_types.t_rec1, val7 r_types.t_rec0, val5 VARCHAR2(10));
l_rec t_rec2;
BEGIN
l_rec := t_rec2(r_types.t_rec1(r_types.t_rec0(',', 'FOUR'), 'TWO'), r_types.t_rec0('FIVE','SIX'), 'ONE');
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val6 r_types.t_rec1, val7 r_types.t_rec0, val5 VARCHAR2(10));
l_rec t_rec2;
BEGIN
l_rec := t_rec2(r_types.t_rec1(r_types.t_rec1(',', 'FOUR'), 'TWO'), r_types.t_rec0('FIVE','SIX'), 'ONE');
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 t_rec0);
END r_types;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 r_types.t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 r_types.t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',r_types.t_rec1(',', 'FOUR')),r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 r_types.t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),t_rec2('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 r_types.t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 r_types.t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 r_types.t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),t_rec2('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
DROP PACKAGE r_types;
CREATE OR REPLACE PACKAGE plpgsql_assignlist.r_types IS
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val4 t_rec0, val3 VARCHAR2(10));
END r_types;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val6 plpgsql_assignlist.r_types.t_rec1, val7 plpgsql_assignlist.r_types.t_rec0, val5 VARCHAR2(10));
l_rec t_rec2;
BEGIN
l_rec := t_rec2(r_types.t_rec1(r_types.t_rec0(',', 'FOUR'), 'TWO'),plpgsql_assignlist.r_types.t_rec0('FIVE','SIX'), 'ONE');
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val6 plpgsql_assignlist.r_types.t_rec1, val7 r_types.t_rec0, val5 VARCHAR2(10));
l_rec t_rec2;
BEGIN
l_rec := t_rec2(r_types.t_rec1(plpgsql_assignlist.r_types.t_rec1(',', 'FOUR'), 'TWO'),r_types.t_rec0('FIVE','SIX'), 'ONE');
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PACKAGE plpgsql_assignlist.r_types IS
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 t_rec0);
END r_types;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 plpgsql_assignlist.r_types.t_rec1, val7 plpgsql_assignlist.r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),plpgsql_assignlist.r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 plpgsql_assignlist.r_types.t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', r_types.t_rec1('TWO',plpgsql_assignlist.r_types.t_rec1(',', 'FOUR')),r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 r_types.t_rec1, val7 plpgsql_assignlist.r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', plpgsql_assignlist.r_types.t_rec1('TWO',plpgsql_assignlist.r_types.t_rec0(',', 'FOUR')),t_rec2('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 plpgsql_assignlist.r_types.t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 plpgsql_assignlist.r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', plpgsql_assignlist.r_types.t_rec1('TWO',plpgsql_assignlist.r_types.t_rec0(',', 'FOUR')),plpgsql_assignlist.r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 r_types.t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', t_rec1('TWO',plpgsql_assignlist.r_types.t_rec0(',', 'FOUR')),r_types.t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 plpgsql_assignlist.r_types.t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 r_types.t_rec0);
l_rec t_rec2;
BEGIN
l_rec := t_rec2('ONE', plpgsql_assignlist.r_types.t_rec1('TWO',r_types.t_rec0(',', 'FOUR')),t_rec2('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
DROP PACKAGE r_types;
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE arr2 IS VARRAY(5) OF INTEGER;
TYPE arr1 IS VARRAY(5) OF INTEGER;
TYPE nt1 IS VARRAY(10) OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1:=rec1(7, nt1(arr2(1,2,4,5),arr1(1,3)));
BEGIN
RAISE NOTICE 'ID: %', arr_rec.id;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE arr2 IS VARRAY(5) OF INTEGER;
TYPE arr1 IS VARRAY(5) OF INTEGER;
TYPE nt1 IS VARRAY(10) OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1:=rec1(7, nt1(arr1(1,2,4,5),arr1(1,3)));
BEGIN
RAISE NOTICE 'ID: %', arr_rec.id;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE arr2 IS VARRAY(5) OF INTEGER;
TYPE arr1 IS VARRAY(5) OF INTEGER;
TYPE nt1 IS VARRAY(10) OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1;
BEGIN
arr_rec:=rec1(7, nt1(arr2(1,2,4,5),arr1(1,3)))
RAISE NOTICE 'ID: %', arr_rec.id;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE arr2 IS TABLE OF INTEGER;
TYPE arr1 IS TABLE OF INTEGER;
TYPE nt1 IS TABLE OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1:=rec1(7, nt1(arr2(1,2,4,5),arr1(1,3)));
BEGIN
RAISE NOTICE 'ID: %', arr_rec.id;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE arr2 IS TABLE OF INTEGER;
TYPE arr1 IS TABLE OF INTEGER;
TYPE nt1 IS TABLE OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1:=rec1(7, nt1(arr1(1,2,4,5),arr1(1,3)));
BEGIN
RAISE NOTICE 'ID: %', arr_rec.id;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE arr2 IS TABLE OF INTEGER;
TYPE arr1 IS TABLE OF INTEGER;
TYPE nt1 IS TABLE OF arr1;
TYPE rec1 IS RECORD(id int, arrarg nt1);
arr_rec rec1;
BEGIN
arr_rec:=rec1(7, nt1(arr2(1,2,4,5),arr1(1,3)))
RAISE NOTICE 'ID: %', arr_rec.id;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 to2, val7 to1);
l_rec t_rec2;
BEGIN
l_rec := ('ONE', to2('TWO',to2(',', 'FOUR')),to1('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 to2, val7 to1);
l_rec t_rec2;
BEGIN
l_rec := ('ONE', to2('TWO',to1(',', 'FOUR')),to1('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 to2, val7 t_rec0);
l_rec t_rec2;
BEGIN
l_rec := ('ONE', to2('TWO',to1(',', 'FOUR')),to1('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 to1);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 to2, val7 t_rec1);
l_rec t_rec2;
BEGIN
l_rec := ('ONE', to2('TWO',to1(',', 'FOUR')),t_rec2('A', to1('FIVE','SIX')));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val4.val1;
END;
/
DECLARE
l_rec to3;
BEGIN
l_rec := to2('ONE', to2('TWO',to1(',', 'FOUR')),to1('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 t_rec0);
l_rec t_rec2;
BEGIN
l_rec := ('ONE', t_rec1('TWO',t_rec2(',', 'FOUR')),t_rec0('FIVE','SIX'));
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
CREATE OR REPLACE PROCEDURE test_nested AS
DECLARE
TYPE t_rec0 IS RECORD (val1 VARCHAR2(10), val2 VARCHAR2(10));
TYPE t_rec1 IS RECORD (val3 VARCHAR2(10), val4 t_rec0);
TYPE t_rec2 IS RECORD (val5 VARCHAR2(10), val6 t_rec1, val7 t_rec0);
l_rec t_rec2 := ('ONE', t_rec1(',',t_rec2('THREE', 'FOUR')),t_rec0('FIVE','SIX'));
BEGIN
RAISE NOTICE 'ID: %, NAME: %', l_rec.val5, l_rec.val6.val3;
RAISE NOTICE 'ID: %, NAME: %', l_rec.val6.val4.val1, l_rec.val7.val2;
END;
/
--test nest table
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE t2 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE nt2 IS VARRAY(10) OF t2; -- varray of varray of integer
TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer
TYPE nt22 IS VARRAY(10) OF nt2; -- varray of varray of integer
TYPE nt11 IS VARRAY(10) OF nt1; -- varray of varray of integer
nva nt11;
BEGIN
nva := nt11(nt1(t1(4,5,6), t2(55,6,73), t1(2,4), t1(2,5,6)),nt1(t1(2,4),t1(2,8)));
END;
/
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE t2 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE nt2 IS VARRAY(10) OF t2; -- varray of varray of integer
TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer
TYPE nt22 IS VARRAY(10) OF nt2; -- varray of varray of integer
TYPE nt11 IS VARRAY(10) OF nt1; -- varray of varray of integer
nva nt11;
BEGIN
nva := nt22(nt1(t1(4,5,6), t1(55,6,73), t1(2,4), t1(2,5,6)),nt1(t1(2,4),t1(2,8)));
END;
/
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE t2 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE nt2 IS VARRAY(10) OF t2; -- varray of varray of integer
TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer
TYPE nt22 IS VARRAY(10) OF nt2; -- varray of varray of integer
TYPE nt11 IS VARRAY(10) OF nt1; -- varray of varray of integer
nva nt11;
BEGIN
nva := nt11(nt1(t1(4,5,6), t1(55,6,73), t1(2,4), t1(2,5,6)),nt2(t1(2,4),t1(2,8)));
END;
/
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE t2 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE nt2 IS VARRAY(10) OF t2; -- varray of varray of integer
TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer
TYPE nt22 IS VARRAY(10) OF nt2; -- varray of varray of integer
TYPE nt11 IS VARRAY(10) OF nt1; -- varray of varray of integer
nva nt11 := nt11(nt1(t1(4,5,6), t2(55,6,73), t1(2,4), t1(2,5,6)),nt1(t1(2,4),t1(2,8)));
va2 t2;
BEGIN
va2(1):=9;
END;
/
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE t2 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE nt2 IS VARRAY(10) OF t2; -- varray of varray of integer
TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer
TYPE nt22 IS VARRAY(10) OF nt2; -- varray of varray of integer
TYPE nt11 IS VARRAY(10) OF nt1; -- varray of varray of integer
nva nt11 := nt22(nt1(t1(4,5,6), t1(55,6,73), t1(2,4), t1(2,5,6)),nt1(t1(2,4),t1(2,8)));
va2 t2;
BEGIN
va2(1):=9;
END;
/
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE t2 IS VARRAY(10) OF INTEGER; -- varray of integer
TYPE nt2 IS VARRAY(10) OF t2; -- varray of varray of integer
TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer
TYPE nt22 IS VARRAY(10) OF nt2; -- varray of varray of integer
TYPE nt11 IS VARRAY(10) OF nt1; -- varray of varray of integer
nva nt11 := nt11(nt1(t1(4,5,6), t1(55,6,73), t1(2,4), t1(2,5,6)),nt2(t1(2,4),t1(2,8)));
va2 t2;
BEGIN
va2(1):=9;
END;
/
set enable_pltype_name_check = off;
--test o1.col1.col2 ref
create type ct as (num int,info text);
create type ct1 as (num int,info ct);