!5701 完善PL中的type、recor:包外使用包类型并继承默认值

Merge pull request !5701 from 雷紫薇/req129584_2_const
This commit is contained in:
opengauss_bot
2024-10-18 03:05:06 +00:00
committed by Gitee
8 changed files with 926 additions and 12 deletions

View File

@ -12777,10 +12777,11 @@ parse_datatype(const char *string, int location)
{
Oid type_id;
int32 typmod;
int expr_len = 0;
sql_error_callback_arg cbarg;
ErrorContextCallback syntax_errcontext;
MemoryContext oldCxt = NULL;
PLpgSQL_type* datatype = NULL;
cbarg.location = location;
cbarg.leaderlen = 0;
@ -12827,11 +12828,13 @@ parse_datatype(const char *string, int location)
/* Okay, build a PLpgSQL_type data structure for it */
if (u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile == NULL)
{
return plpgsql_build_datatype(type_id, typmod, 0, typeDependExtend);
}
return plpgsql_build_datatype(type_id, typmod,
datatype = plpgsql_build_datatype(type_id, typmod, 0, typeDependExtend);
} else {
datatype = plpgsql_build_datatype(type_id, typmod,
u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile->fn_input_collation, typeDependExtend);
}
datatype->defaultvalues = get_default_plpgsql_expr_from_typeoid(type_id, &expr_len);
return datatype;
}
/* Build a arrary_type by elem_type. */
@ -13546,7 +13549,7 @@ static Node* make_columnDef_from_attr(PLpgSQL_rec_attr* attr)
n->is_not_null = false;
n->is_from_type = false;
n->storage = 0;
n->raw_default = NULL;
n->raw_default = attr->defaultvalue ? get_default_node_from_plpgsql_expr(attr->defaultvalue) : NULL;
n->cooked_default = NULL;
n->collClause = NULL;
n->clientLogicColumnRef=NULL;

View File

@ -28,6 +28,7 @@
#include "catalog/gs_package.h"
#include "catalog/gs_package_fn.h"
#include "catalog/pg_type.h"
#include "catalog/pg_attrdef.h"
#include "commands/sqladvisor.h"
#include "executor/spi.h"
#include "funcapi.h"
@ -90,7 +91,7 @@ static Node* plpgsql_post_column_ref(ParseState* pstate, ColumnRef* cref, Node*
static Node* plpgsql_param_ref(ParseState* pstate, ParamRef* pref);
static Node* resolve_column_ref(ParseState* pstate, PLpgSQL_expr* expr, ColumnRef* cref, bool error_if_no_field);
static Node* make_datum_param(PLpgSQL_expr* expr, int dno, int location);
extern PLpgSQL_row* build_row_from_class(Oid class_oid);
extern PLpgSQL_row* build_row_from_class(Oid class_oid, PLpgSQL_expr** defaultvalues);
static PLpgSQL_row* build_row_from_vars(PLpgSQL_variable** vars, int numvars);
static void compute_function_hashkey(HeapTuple proc_tup, FunctionCallInfo fcinfo, Form_pg_proc proc_struct,
PLpgSQL_func_hashkey* hashkey, bool for_validator);
@ -675,6 +676,28 @@ static bool CheckPipelinedResIsTuple(Form_pg_type type_struct) {
return pipelinedResIsTuple;
}
static void plpgsql_add_param_initdatums(int *newvarnos, int newnum, int** oldvarnos, int oldnum)
{
int i;
int n = 0;
int *varnos = NULL;
errno_t rc = 0;
varnos = (int*)palloc(sizeof(int) * (newnum + oldnum));
if (oldnum > 0) {
rc = memcpy_s(varnos, sizeof(int) * oldnum, (int*)(*oldvarnos), sizeof(int) * oldnum);
securec_check(rc, "", "");
}
if (newnum > 0) {
rc = memcpy_s(varnos + oldnum, sizeof(int) * newnum, newvarnos, sizeof(int) * newnum);
securec_check(rc, "", "");
}
if (*oldvarnos)
pfree(*oldvarnos);
*oldvarnos = varnos;
}
/*
* This is the slow part of plpgsql_compile().
*
@ -723,7 +746,8 @@ static PLpgSQL_function* do_compile(FunctionCallInfo fcinfo, HeapTuple proc_tup,
PLpgSQL_variable** out_arg_variables;
Oid pkgoid = InvalidOid;
Oid namespaceOid = InvalidOid;
int *allvarnos = NULL;
int n_varnos = 0;
Oid* saved_pseudo_current_userId = NULL;
char* signature = NULL;
@ -1006,6 +1030,7 @@ static PLpgSQL_function* do_compile(FunctionCallInfo fcinfo, HeapTuple proc_tup,
const int buf_size = 32;
char buf[buf_size];
Oid arg_type_id = arg_types[i];
int attrnum = 0;
char arg_mode = arg_modes ? arg_modes[i] : PROARGMODE_IN;
PLpgSQL_variable* argvariable = NULL;
int arg_item_type;
@ -1020,6 +1045,9 @@ static PLpgSQL_function* do_compile(FunctionCallInfo fcinfo, HeapTuple proc_tup,
/* Create datatype info */
PLpgSQL_type* argdtype = plpgsql_build_datatype(arg_type_id, -1, func->fn_input_collation);
if (arg_mode != PROARGMODE_IN && arg_mode != PROARGMODE_INOUT) {
argdtype->defaultvalues = get_default_plpgsql_expr_from_typeoid(arg_type_id, &attrnum);
}
/* Disallow pseudotype argument */
/* (note we already replaced polymorphic types) */
@ -1034,6 +1062,11 @@ static PLpgSQL_function* do_compile(FunctionCallInfo fcinfo, HeapTuple proc_tup,
} else {
argvariable = plpgsql_build_variable(buf, 0, argdtype, false);
}
if (argdtype->defaultvalues) {
PLpgSQL_row *row = (PLpgSQL_row *)argvariable;
plpgsql_add_param_initdatums(row->varnos, attrnum, &allvarnos, n_varnos);
n_varnos = n_varnos + attrnum;
}
if (argvariable->dtype == PLPGSQL_DTYPE_VAR) {
arg_item_type = PLPGSQL_NSTYPE_VAR;
@ -1421,6 +1454,10 @@ static PLpgSQL_function* do_compile(FunctionCallInfo fcinfo, HeapTuple proc_tup,
errmsg("Syntax parsing error, plpgsql parser returned %d", parse_rc)));
}
func->action = curr_compile->plpgsql_parse_result;
if (n_varnos > 0) {
plpgsql_add_param_initdatums(allvarnos, n_varnos, &func->action->initvarnos, func->action->n_initvars);
func->action->n_initvars = func->action->n_initvars + n_varnos;
}
if (is_dml_trigger && func->action->isAutonomous) {
ereport(ERROR,
@ -3929,7 +3966,7 @@ PLpgSQL_variable* plpgsql_build_variable(const char* refname, int lineno, PLpgSQ
/* Composite type -- build a row variable */
PLpgSQL_row* row = NULL;
row = build_row_from_class(dtype->typrelid);
row = build_row_from_class(dtype->typrelid, dtype->defaultvalues);
row->addNamespace = add2namespace;
row->customErrorCode = 0;
if (0 == strcmp(format_type_be(row->rowtupdesc->tdtypeid), "exception")) {
@ -4313,7 +4350,7 @@ void plpgsql_build_synonym(char* typname, char* basetypname)
/*
* Build a row-variable data structure given the pg_class OID.
*/
PLpgSQL_row* build_row_from_class(Oid class_oid)
PLpgSQL_row* build_row_from_class(Oid class_oid, PLpgSQL_expr** defaultvalues)
{
/*
* Open the relation to get info.
@ -4374,6 +4411,8 @@ PLpgSQL_row* build_row_from_class(Oid class_oid)
*/
var = plpgsql_build_variable(refname, 0, plpgsql_build_datatype(attr_struct->atttypid,
attr_struct->atttypmod, attr_struct->attcollation), false);
if (defaultvalues != NULL)
((PLpgSQL_var*)var)->default_val = defaultvalues[i];
/* Add the variable to the row */
row->fieldnames[i] = attname;
@ -4637,7 +4676,7 @@ PLpgSQL_type* build_datatype(HeapTuple type_tup, int32 typmod, Oid collation)
errmsg("type \"%s\" is only a shell when build data type in PLSQL.", NameStr(type_struct->typname))));
}
PLpgSQL_type* typ = (PLpgSQL_type*)palloc(sizeof(PLpgSQL_type));
typ->defaultvalues = NULL;
typ->typname = pstrdup(NameStr(type_struct->typname));
typ->typoid = HeapTupleGetOid(type_tup);
typ->collectionType = PLPGSQL_COLLECTION_NONE;
@ -5947,3 +5986,106 @@ void checkArrayTypeInsert(ParseState* pstate, Expr* expr)
}
}
}
Node* get_default_node_from_plpgsql_expr(PLpgSQL_expr *expr)
{
MemoryContext cur = CurrentMemoryContext;
MemoryContext temp = NULL;
CachedPlanSource* plansource = NULL;
SelectStmt* stmt = NULL;
Value *val = NULL;
_SPI_plan plan;
parse_query_func parser = GetRawParser();
if (expr->query == NULL) {
return NULL;
}
SPI_STACK_LOG("connect", NULL, NULL);
if (SPI_connect() != SPI_OK_CONNECT) {
ereport(ERROR, (errcode(ERRCODE_SPI_CONNECTION_FAILURE), errmsg("SPI_connect failed")));
}
SPI_STACK_LOG("begin", expr->query, NULL);
if (_SPI_begin_call(true) < 0) {
return NULL;
}
int rc = memset_s(&plan, sizeof(_SPI_plan), '\0', sizeof(_SPI_plan));
securec_check_c(rc, "\0", "\0");
plan.magic = _SPI_PLAN_MAGIC;
plan.cursor_options = 0;
plan.spi_key = INVALID_SPI_KEY;
_SPI_prepare_oneshot_plan(expr->query, &plan, parser);
plansource = (CachedPlanSource*)lfirst(plan.plancache_list->head);
stmt = (SelectStmt*)plansource->raw_parse_tree;
if (stmt->targetList) {
Node* node = (Node*)lfirst(stmt->targetList->head);
if (IsA(node, ResTarget)) {
ResTarget* resTarget = (ResTarget*)node;
temp = MemoryContextSwitchTo(cur);
val = (Value*)copyObject((void*)resTarget->val);
temp = MemoryContextSwitchTo(temp);
}
}
if (_SPI_end_call(true) < 0) {
return NULL;
}
SPI_STACK_LOG("finish", NULL, NULL);
if (SPI_finish() != SPI_OK_FINISH) {
ereport(ERROR, (errcode(ERRCODE_SPI_FINISH_FAILURE), errmsg("SPI_finish failed")));
}
return (Node*)val;
}
PLpgSQL_expr** get_default_plpgsql_expr_from_typeoid(Oid typeOid, int* attrnum)
{
PLpgSQL_expr** defaultvalues = NULL;
ScanKeyData skey;
HeapTuple htup;
bool isnull = false;
Datum typrelid = typeidTypeRelid(typeOid);
if (typrelid != InvalidOid) {
ScanKeyInit(&skey, Anum_pg_attrdef_adrelid, BTEqualStrategyNumber, F_OIDEQ, typrelid);
Relation adrel = heap_open(AttrDefaultRelationId, AccessShareLock);
SysScanDesc adscan = systable_beginscan(adrel, AttrDefaultIndexId, true, NULL, 1, &skey);
List* del_list = NIL;
ListCell *lc = NULL;
int i = 0, j = 0;
while (HeapTupleIsValid(htup = systable_getnext(adscan))) {
Form_pg_attrdef adform = (Form_pg_attrdef)GETSTRUCT(htup);
Datum val;
StringInfoData ds;
val = fastgetattr(htup, Anum_pg_attrdef_adsrc, adrel->rd_att, &isnull);
char *adsrc_str = isnull ? NULL : TextDatumGetCString(val);
initStringInfo(&ds);
appendStringInfoString(&ds, "SELECT ");
appendStringInfoString(&ds, adsrc_str);
del_list = lappend(del_list, ds.data);
j++;
}
*attrnum = j;
if (j > 0) {
defaultvalues = (PLpgSQL_expr **)palloc0(sizeof(PLpgSQL_expr *) * j);
PLpgSQL_expr *exprs = (PLpgSQL_expr *)palloc0(sizeof(PLpgSQL_expr) * j);
foreach (lc, del_list) {
char *query = (char *)lfirst(lc);
PLpgSQL_expr *expr = exprs + i;
expr->dtype = PLPGSQL_DTYPE_EXPR;
expr->query = pstrdup(query);
expr->plan = NULL;
expr->paramnos = NULL;
expr->isouttype = false;
expr->idx = UINT32_MAX;
expr->out_param_dno = -1;
expr->is_have_tableof_index_func = true;
defaultvalues[i] = expr;
i++;
}
}
systable_endscan(adscan);
heap_close(adrel, AccessShareLock);
}
return defaultvalues;
}

View File

@ -49,7 +49,7 @@ extern Oid findPackageParameter(const char* objname);
extern int plpgsql_getCustomErrorCode(void);
extern PLpgSQL_row* build_row_from_class(Oid class_oid);
extern PLpgSQL_row* build_row_from_class(Oid class_oid, PLpgSQL_expr** defaultvalues);
extern int GetLineNumber(const char* procedureStr, int loc);

View File

@ -489,6 +489,7 @@ typedef struct { /* openGauss data type */
PLpgSQL_expr* cursorExpr;
int cursorDno;
char typtyp;
PLpgSQL_expr** defaultvalues;
} PLpgSQL_type;
typedef struct {
@ -1858,6 +1859,8 @@ extern PLpgSQL_datum* plpgsql_lookup_datum(
extern PLpgSQL_type* plpgsql_get_row_field_type(int dno, const char* fieldname, MemoryContext old_cxt);
extern PLpgSQL_resolve_option GetResolveOption();
extern Node* plpgsql_check_match_var(Node* node, ParseState* pstate, ColumnRef* cref);
extern Node* get_default_node_from_plpgsql_expr(PLpgSQL_expr *expr);
extern PLpgSQL_expr** get_default_plpgsql_expr_from_typeoid(Oid typeOid, int* attrnum);
/* ----------
* Functions in pl_handler.c

View File

@ -0,0 +1,446 @@
create schema test_pkg_default_value;
set current_schema = test_pkg_default_value;
-- test default expr
CREATE FUNCTION func1(num2 inout int,num3 inout int) RETURNS int
AS $$
DECLARE
BEGIN
num2 := num2 + 9 + num3;
return num2;
END
$$
LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION func3(num2 inout int) RETURNS int
AS $$
DECLARE
BEGIN
num2 := num2 + 2;
return num2;
END
$$
LANGUAGE plpgsql;
CREATE FUNCTION func2(num1 inout int, st1 inout varchar(10), num2 inout int) RETURNS int
AS $$
DECLARE
BEGIN
num2 := num2 + 9;
raise info 'str1 is %', NVL(str1,'NULL');
raise info 'str2 is %', NVL(str2,'NULL');
raise info 'num1 is %', num1;
raise info 'num2 is %', num2;
return num2;
END
$$
LANGUAGE plpgsql;
CREATE FUNCTION func4(num2 inout int,num3 inout bool) RETURNS int
AS $$
DECLARE
BEGIN
num2 := num2 + 1;
return num2;
END
$$
LANGUAGE plpgsql;
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := (+1));
END r_types;
/
select adsrc from PG_ATTRDEF where adrelid in (select typrelid from PG_TYPE where typname ilike '%r_type_1%' limit 1);
adsrc
-------
(+ 1)
(1 row)
DECLARE
r1 r_types.r_type_1;
BEGIN
raise info 'r1.f is %', r1.f;
END;
/
INFO: r1.f is 1
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := 1+-9+8*(-7)+1*-2);
END r_types;
/
select adsrc from PG_ATTRDEF where adrelid in (select typrelid from PG_TYPE where typname ilike '%r_type_1%' limit 1);
adsrc
------------------------------------------
(((1 + (-9)) + (8 * (-7))) + (1 * (-2)))
(1 row)
DECLARE
r1 r_types.r_type_1;
BEGIN
raise info 'r1.f is %', r1.f;
END;
/
INFO: r1.f is -66
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := 1+-9+8/-11*(-7)+1*-2*2/5);
END r_types;
/
select adsrc from PG_ATTRDEF where adrelid in (select typrelid from PG_TYPE where typname ilike '%r_type_1%' limit 1);
adsrc
--------------------------------------------------------------------------------------------------------
((((1 + (-9)))::double precision + ((8 / (-11)) * ((-7))::double precision)) + (((1 * (-2)) * 2) / 5))
(1 row)
DECLARE
r1 r_types.r_type_1;
BEGIN
raise info 'r1.f is %', r1.f;
END;
/
INFO: r1.f is -4
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := 8*-11*(-7)+1*-2*2/5+9);
END r_types;
/
select adsrc from PG_ATTRDEF where adrelid in (select typrelid from PG_TYPE where typname ilike '%r_type_1%' limit 1);
adsrc
-----------------------------------------------------------------------------------------------
(((((8 * (-11)) * (-7)))::double precision + (((1 * (-2)) * 2) / 5)) + (9)::double precision)
(1 row)
DECLARE
r1 r_types.r_type_1;
BEGIN
raise info 'r1.f is %', r1.f;
END;
/
INFO: r1.f is 624
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := -1);
END r_types;
/
select adsrc from PG_ATTRDEF where adrelid in (select typrelid from PG_TYPE where typname ilike '%r_type_1%' limit 1);
adsrc
-------
(-1)
(1 row)
DECLARE
r1 r_types.r_type_1;
BEGIN
raise info 'r1.f is %', r1.f;
END;
/
INFO: r1.f is -1
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f VARCHAR2(5) := 'abus');
END r_types;
/
select adsrc from PG_ATTRDEF where adrelid in (select typrelid from PG_TYPE where typname ilike '%r_type_1%' limit 1);
adsrc
---------------------------
'abus'::character varying
(1 row)
DECLARE
r1 r_types.r_type_1;
BEGIN
raise info 'r1.f is %', NVL(r1.f,'NULL');
END;
/
INFO: r1.f is abus
-- test expr error
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := (1+));
END r_types;
/
ERROR: syntax error at or near ")"
LINE 1: SELECT (1+)
^
QUERY: SELECT (1+)
CONTEXT: compilation of PL/pgSQL package near line 1
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := +);
END r_types;
/
ERROR: syntax error at end of input
LINE 1: SELECT +
^
QUERY: SELECT +
CONTEXT: compilation of PL/pgSQL package near line 1
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := (+));
END r_types;
/
ERROR: syntax error at or near "(+)"
LINE 1: SELECT (+)
^
QUERY: SELECT (+)
CONTEXT: compilation of PL/pgSQL package near line 1
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := (a+b));
END r_types;
/
ERROR: column "a" does not exist
CONTEXT: compilation of PL/pgSQL package near line 1
-- normal default
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f VARCHAR2(5) := 'abcde', f2 VARCHAR2(5) := 'waxtr');
END r_types;
/
DECLARE
TYPE r_type_2 IS RECORD (f VARCHAR2(5) := 'a1c2e', f2 VARCHAR2(5) := 'w5x3r');
r1 r_types.r_type_1;
r2 r_type_2;
BEGIN
raise info 'r1.f is %', NVL(r1.f,'NULL');
raise info 'r1.f2 is %', NVL(r1.f2,'NULL');
raise info 'r2.f is %', NVL(r2.f,'NULL');
raise info 'r1.f2 is %', NVL(r2.f2,'NULL');
END;
/
INFO: r1.f is abcde
INFO: r1.f2 is waxtr
INFO: r2.f is a1c2e
INFO: r1.f2 is w5x3r
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f date := '2001-9-28', f2 timestamp := '1957-06-13');
END r_types;
/
DECLARE
TYPE r_type_2 IS RECORD (f date := '2000-7-28', f2 timestamp := '1987-06-03');
r1 r_types.r_type_1;
r2 r_type_2;
BEGIN
raise info 'r1.f is %', r1.f;
raise info 'r1.f2 is %', r1.f2;
raise info 'r1.f is %', r2.f;
raise info 'r1.f2 is %', r2.f2;
END;
/
INFO: r1.f is Fri Sep 28 00:00:00 2001
INFO: r1.f2 is Thu Jun 13 00:00:00 1957
INFO: r1.f is Fri Jul 28 00:00:00 2000
INFO: r1.f2 is Wed Jun 03 00:00:00 1987
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f boolean := true, f2 numeric := 19.578);
END r_types;
/
DECLARE
TYPE r_type_2 IS RECORD (f boolean := false, f2 numeric := 13.278);
r1 r_types.r_type_1;
r2 r_type_2;
BEGIN
raise info 'r1.f is %', r1.f;
raise info 'r1.f2 is %', r1.f2;
raise info 'r1.f is %', r2.f;
raise info 'r1.f2 is %', r2.f2;
END;
/
INFO: r1.f is t
INFO: r1.f2 is 19.578
INFO: r1.f is f
INFO: r1.f2 is 13.278
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f money := 10.5, f2 int := 15);
END r_types;
/
DECLARE
TYPE r_type_2 IS RECORD (f money := 9.6, f2 int := 13);
r1 r_types.r_type_1;
r2 r_type_2;
BEGIN
raise info 'r1.f is %', r1.f;
raise info 'r1.f2 is %', r1.f2;
raise info 'r1.f is %', r2.f;
raise info 'r1.f2 is %', r2.f2;
END;
/
INFO: r1.f is $10.50
INFO: r1.f2 is 15
INFO: r1.f is $9.60
INFO: r1.f2 is 13
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f integer := 10, f2 oid := 15);
END r_types;
/
DECLARE
TYPE r_type_2 IS RECORD (f integer := 9, f2 oid := 13);
r1 r_types.r_type_1;
r2 r_type_2;
BEGIN
raise info 'r1.f is %', r1.f;
raise info 'r1.f2 is %', r1.f2;
raise info 'r1.f is %', r2.f;
raise info 'r1.f2 is %', r2.f2;
END;
/
INFO: r1.f is 10
INFO: r1.f2 is 15
INFO: r1.f is 9
INFO: r1.f2 is 13
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f name := 'abcde', f2 text := 'waxtr');
END r_types;
/
DECLARE
TYPE r_type_2 IS RECORD (f name := 'a1c2e', f2 text := 'w5x3r');
r1 r_types.r_type_1;
r2 r_type_2;
BEGIN
raise info 'r1.f is %', NVL(r1.f,'NULL');
raise info 'r1.f2 is %', NVL(r1.f2,'NULL');
raise info 'r2.f is %', NVL(r2.f,'NULL');
raise info 'r1.f2 is %', NVL(r2.f2,'NULL');
END;
/
INFO: r1.f is abcde
INFO: r1.f2 is waxtr
INFO: r2.f is a1c2e
INFO: r1.f2 is w5x3r
-- pkg param default
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f VARCHAR2(5) := 'abcde', f2 VARCHAR2(5) := 'syutw');
TYPE r_type_2 IS RECORD (f VARCHAR2(5));
END r_types;
/
CREATE OR REPLACE PROCEDURE p1 (
x OUT r_types.r_type_1,
y OUT r_types.r_type_2,
z OUT VARCHAR2)
AUTHID CURRENT_USER IS
BEGIN
raise info 'x.f is %', NVL(x.f,'NULL');
raise info 'x.f2 is %', NVL(x.f2,'NULL');
raise info 'y.f is %', NVL(y.f,'NULL');
raise info 'z is %', NVL(z,'NULL');
END;
/
CREATE OR REPLACE PROCEDURE p2 (
x IN r_types.r_type_1,
y IN r_types.r_type_2,
z IN VARCHAR2)
AUTHID CURRENT_USER IS
BEGIN
raise info 'x.f is %', NVL(x.f,'NULL');
raise info 'x.f2 is %', NVL(x.f2,'NULL');
raise info 'y.f is %', NVL(y.f,'NULL');
raise info 'z is %', NVL(z,'NULL');
END;
/
CREATE OR REPLACE PROCEDURE p3 (
x INOUT r_types.r_type_1,
y INOUT r_types.r_type_2,
z INOUT VARCHAR2)
AUTHID CURRENT_USER IS
BEGIN
raise info 'x.f is %', NVL(x.f,'NULL');
raise info 'x.f2 is %', NVL(x.f2,'NULL');
raise info 'y.f is %', NVL(y.f,'NULL');
raise info 'z is %', NVL(z,'NULL');
END;
/
DECLARE
r1 r_types.r_type_1;
r2 r_types.r_type_2;
s VARCHAR2(5) := 'fghij';
BEGIN
raise info '===============p1===================';
p1 (r1, r2, s);
raise info '===============p2===================';
p2 (r1, r2, s);
raise info '===============p3===================';
p3 (r1, r2, s);
r1.f:='waqrt';
r1.f2:='bfgrf';
r2.f:='nuytg';
raise info '===============p1===================';
p1 (r1, r2, s);
raise info '===============p2===================';
p2 (r1, r2, s);
raise info '===============p3===================';
p3 (r1, r2, s);
END;
/
INFO: ===============p1===================
INFO: x.f is abcde
CONTEXT: SQL statement "CALL p1(r1,r2,s)"
PL/pgSQL function inline_code_block line 6 at SQL statement
INFO: x.f2 is syutw
CONTEXT: SQL statement "CALL p1(r1,r2,s)"
PL/pgSQL function inline_code_block line 6 at SQL statement
INFO: y.f is NULL
CONTEXT: SQL statement "CALL p1(r1,r2,s)"
PL/pgSQL function inline_code_block line 6 at SQL statement
INFO: z is NULL
CONTEXT: SQL statement "CALL p1(r1,r2,s)"
PL/pgSQL function inline_code_block line 6 at SQL statement
INFO: ===============p2===================
INFO: x.f is abcde
CONTEXT: SQL statement "CALL p2(r1,r2,s)"
PL/pgSQL function inline_code_block line 8 at PERFORM
INFO: x.f2 is syutw
CONTEXT: SQL statement "CALL p2(r1,r2,s)"
PL/pgSQL function inline_code_block line 8 at PERFORM
INFO: y.f is NULL
CONTEXT: SQL statement "CALL p2(r1,r2,s)"
PL/pgSQL function inline_code_block line 8 at PERFORM
INFO: z is NULL
CONTEXT: SQL statement "CALL p2(r1,r2,s)"
PL/pgSQL function inline_code_block line 8 at PERFORM
INFO: ===============p3===================
INFO: x.f is abcde
CONTEXT: SQL statement "CALL p3(r1,r2,s)"
PL/pgSQL function inline_code_block line 10 at SQL statement
INFO: x.f2 is syutw
CONTEXT: SQL statement "CALL p3(r1,r2,s)"
PL/pgSQL function inline_code_block line 10 at SQL statement
INFO: y.f is NULL
CONTEXT: SQL statement "CALL p3(r1,r2,s)"
PL/pgSQL function inline_code_block line 10 at SQL statement
INFO: z is NULL
CONTEXT: SQL statement "CALL p3(r1,r2,s)"
PL/pgSQL function inline_code_block line 10 at SQL statement
INFO: ===============p1===================
INFO: x.f is abcde
CONTEXT: SQL statement "CALL p1(r1,r2,s)"
PL/pgSQL function inline_code_block line 15 at SQL statement
INFO: x.f2 is syutw
CONTEXT: SQL statement "CALL p1(r1,r2,s)"
PL/pgSQL function inline_code_block line 15 at SQL statement
INFO: y.f is NULL
CONTEXT: SQL statement "CALL p1(r1,r2,s)"
PL/pgSQL function inline_code_block line 15 at SQL statement
INFO: z is NULL
CONTEXT: SQL statement "CALL p1(r1,r2,s)"
PL/pgSQL function inline_code_block line 15 at SQL statement
INFO: ===============p2===================
INFO: x.f is abcde
CONTEXT: SQL statement "CALL p2(r1,r2,s)"
PL/pgSQL function inline_code_block line 17 at PERFORM
INFO: x.f2 is syutw
CONTEXT: SQL statement "CALL p2(r1,r2,s)"
PL/pgSQL function inline_code_block line 17 at PERFORM
INFO: y.f is NULL
CONTEXT: SQL statement "CALL p2(r1,r2,s)"
PL/pgSQL function inline_code_block line 17 at PERFORM
INFO: z is NULL
CONTEXT: SQL statement "CALL p2(r1,r2,s)"
PL/pgSQL function inline_code_block line 17 at PERFORM
INFO: ===============p3===================
INFO: x.f is abcde
CONTEXT: SQL statement "CALL p3(r1,r2,s)"
PL/pgSQL function inline_code_block line 19 at SQL statement
INFO: x.f2 is syutw
CONTEXT: SQL statement "CALL p3(r1,r2,s)"
PL/pgSQL function inline_code_block line 19 at SQL statement
INFO: y.f is NULL
CONTEXT: SQL statement "CALL p3(r1,r2,s)"
PL/pgSQL function inline_code_block line 19 at SQL statement
INFO: z is NULL
CONTEXT: SQL statement "CALL p3(r1,r2,s)"
PL/pgSQL function inline_code_block line 19 at SQL statement
DROP FUNCTION func1;
DROP FUNCTION func2;
DROP FUNCTION func3;
DROP FUNCTION func4;
DROP PACKAGE r_types;
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to function p1()
--?.*
--?.*
DROP SCHEMA test_pkg_default_value;

View File

@ -783,6 +783,7 @@ test: plpgsql_array_of_record
test: arrayinterface_ted
test: function_default_test plpgsql_inout_param record_slow_sql_in_proc
test: plpgsql_cursor_rowtype
test: plpgsql_default_value_various_type
test: plpgsql_assign_list
test: plpgsql_package_type plpgsql_package_param
test: plpgsql_record_attrname

View File

@ -285,6 +285,7 @@ test: plpgsql_array_of_record
test: arrayinterface_ted
test: function_default_test plpgsql_inout_param
test: plpgsql_cursor_rowtype
test: plpgsql_default_value_various_type
test: plpgsql_assign_list
test: plpgsql_package_type plpgsql_package_param
test: plpgsql_record_attrname

View File

@ -0,0 +1,318 @@
create schema test_pkg_default_value;
set current_schema = test_pkg_default_value;
-- test default expr
CREATE FUNCTION func1(num2 inout int,num3 inout int) RETURNS int
AS $$
DECLARE
BEGIN
num2 := num2 + 9 + num3;
return num2;
END
$$
LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION func3(num2 inout int) RETURNS int
AS $$
DECLARE
BEGIN
num2 := num2 + 2;
return num2;
END
$$
LANGUAGE plpgsql;
CREATE FUNCTION func2(num1 inout int, st1 inout varchar(10), num2 inout int) RETURNS int
AS $$
DECLARE
BEGIN
num2 := num2 + 9;
raise info 'str1 is %', NVL(str1,'NULL');
raise info 'str2 is %', NVL(str2,'NULL');
raise info 'num1 is %', num1;
raise info 'num2 is %', num2;
return num2;
END
$$
LANGUAGE plpgsql;
CREATE FUNCTION func4(num2 inout int,num3 inout bool) RETURNS int
AS $$
DECLARE
BEGIN
num2 := num2 + 1;
return num2;
END
$$
LANGUAGE plpgsql;
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := (+1));
END r_types;
/
select adsrc from PG_ATTRDEF where adrelid in (select typrelid from PG_TYPE where typname ilike '%r_type_1%' limit 1);
DECLARE
r1 r_types.r_type_1;
BEGIN
raise info 'r1.f is %', r1.f;
END;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := 1+-9+8*(-7)+1*-2);
END r_types;
/
select adsrc from PG_ATTRDEF where adrelid in (select typrelid from PG_TYPE where typname ilike '%r_type_1%' limit 1);
DECLARE
r1 r_types.r_type_1;
BEGIN
raise info 'r1.f is %', r1.f;
END;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := 1+-9+8/-11*(-7)+1*-2*2/5);
END r_types;
/
select adsrc from PG_ATTRDEF where adrelid in (select typrelid from PG_TYPE where typname ilike '%r_type_1%' limit 1);
DECLARE
r1 r_types.r_type_1;
BEGIN
raise info 'r1.f is %', r1.f;
END;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := 8*-11*(-7)+1*-2*2/5+9);
END r_types;
/
select adsrc from PG_ATTRDEF where adrelid in (select typrelid from PG_TYPE where typname ilike '%r_type_1%' limit 1);
DECLARE
r1 r_types.r_type_1;
BEGIN
raise info 'r1.f is %', r1.f;
END;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := -1);
END r_types;
/
select adsrc from PG_ATTRDEF where adrelid in (select typrelid from PG_TYPE where typname ilike '%r_type_1%' limit 1);
DECLARE
r1 r_types.r_type_1;
BEGIN
raise info 'r1.f is %', r1.f;
END;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f VARCHAR2(5) := 'abus');
END r_types;
/
select adsrc from PG_ATTRDEF where adrelid in (select typrelid from PG_TYPE where typname ilike '%r_type_1%' limit 1);
DECLARE
r1 r_types.r_type_1;
BEGIN
raise info 'r1.f is %', NVL(r1.f,'NULL');
END;
/
-- test expr error
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := (1+));
END r_types;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := +);
END r_types;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := (+));
END r_types;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f int := (a+b));
END r_types;
/
-- normal default
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f VARCHAR2(5) := 'abcde', f2 VARCHAR2(5) := 'waxtr');
END r_types;
/
DECLARE
TYPE r_type_2 IS RECORD (f VARCHAR2(5) := 'a1c2e', f2 VARCHAR2(5) := 'w5x3r');
r1 r_types.r_type_1;
r2 r_type_2;
BEGIN
raise info 'r1.f is %', NVL(r1.f,'NULL');
raise info 'r1.f2 is %', NVL(r1.f2,'NULL');
raise info 'r2.f is %', NVL(r2.f,'NULL');
raise info 'r1.f2 is %', NVL(r2.f2,'NULL');
END;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f date := '2001-9-28', f2 timestamp := '1957-06-13');
END r_types;
/
DECLARE
TYPE r_type_2 IS RECORD (f date := '2000-7-28', f2 timestamp := '1987-06-03');
r1 r_types.r_type_1;
r2 r_type_2;
BEGIN
raise info 'r1.f is %', r1.f;
raise info 'r1.f2 is %', r1.f2;
raise info 'r1.f is %', r2.f;
raise info 'r1.f2 is %', r2.f2;
END;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f boolean := true, f2 numeric := 19.578);
END r_types;
/
DECLARE
TYPE r_type_2 IS RECORD (f boolean := false, f2 numeric := 13.278);
r1 r_types.r_type_1;
r2 r_type_2;
BEGIN
raise info 'r1.f is %', r1.f;
raise info 'r1.f2 is %', r1.f2;
raise info 'r1.f is %', r2.f;
raise info 'r1.f2 is %', r2.f2;
END;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f money := 10.5, f2 int := 15);
END r_types;
/
DECLARE
TYPE r_type_2 IS RECORD (f money := 9.6, f2 int := 13);
r1 r_types.r_type_1;
r2 r_type_2;
BEGIN
raise info 'r1.f is %', r1.f;
raise info 'r1.f2 is %', r1.f2;
raise info 'r1.f is %', r2.f;
raise info 'r1.f2 is %', r2.f2;
END;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f integer := 10, f2 oid := 15);
END r_types;
/
DECLARE
TYPE r_type_2 IS RECORD (f integer := 9, f2 oid := 13);
r1 r_types.r_type_1;
r2 r_type_2;
BEGIN
raise info 'r1.f is %', r1.f;
raise info 'r1.f2 is %', r1.f2;
raise info 'r1.f is %', r2.f;
raise info 'r1.f2 is %', r2.f2;
END;
/
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f name := 'abcde', f2 text := 'waxtr');
END r_types;
/
DECLARE
TYPE r_type_2 IS RECORD (f name := 'a1c2e', f2 text := 'w5x3r');
r1 r_types.r_type_1;
r2 r_type_2;
BEGIN
raise info 'r1.f is %', NVL(r1.f,'NULL');
raise info 'r1.f2 is %', NVL(r1.f2,'NULL');
raise info 'r2.f is %', NVL(r2.f,'NULL');
raise info 'r1.f2 is %', NVL(r2.f2,'NULL');
END;
/
-- pkg param default
CREATE OR REPLACE PACKAGE r_types IS
TYPE r_type_1 IS RECORD (f VARCHAR2(5) := 'abcde', f2 VARCHAR2(5) := 'syutw');
TYPE r_type_2 IS RECORD (f VARCHAR2(5));
END r_types;
/
CREATE OR REPLACE PROCEDURE p1 (
x OUT r_types.r_type_1,
y OUT r_types.r_type_2,
z OUT VARCHAR2)
AUTHID CURRENT_USER IS
BEGIN
raise info 'x.f is %', NVL(x.f,'NULL');
raise info 'x.f2 is %', NVL(x.f2,'NULL');
raise info 'y.f is %', NVL(y.f,'NULL');
raise info 'z is %', NVL(z,'NULL');
END;
/
CREATE OR REPLACE PROCEDURE p2 (
x IN r_types.r_type_1,
y IN r_types.r_type_2,
z IN VARCHAR2)
AUTHID CURRENT_USER IS
BEGIN
raise info 'x.f is %', NVL(x.f,'NULL');
raise info 'x.f2 is %', NVL(x.f2,'NULL');
raise info 'y.f is %', NVL(y.f,'NULL');
raise info 'z is %', NVL(z,'NULL');
END;
/
CREATE OR REPLACE PROCEDURE p3 (
x INOUT r_types.r_type_1,
y INOUT r_types.r_type_2,
z INOUT VARCHAR2)
AUTHID CURRENT_USER IS
BEGIN
raise info 'x.f is %', NVL(x.f,'NULL');
raise info 'x.f2 is %', NVL(x.f2,'NULL');
raise info 'y.f is %', NVL(y.f,'NULL');
raise info 'z is %', NVL(z,'NULL');
END;
/
DECLARE
r1 r_types.r_type_1;
r2 r_types.r_type_2;
s VARCHAR2(5) := 'fghij';
BEGIN
raise info '===============p1===================';
p1 (r1, r2, s);
raise info '===============p2===================';
p2 (r1, r2, s);
raise info '===============p3===================';
p3 (r1, r2, s);
r1.f:='waqrt';
r1.f2:='bfgrf';
r2.f:='nuytg';
raise info '===============p1===================';
p1 (r1, r2, s);
raise info '===============p2===================';
p2 (r1, r2, s);
raise info '===============p3===================';
p3 (r1, r2, s);
END;
/
DROP FUNCTION func1;
DROP FUNCTION func2;
DROP FUNCTION func3;
DROP FUNCTION func4;
DROP PACKAGE r_types;
DROP SCHEMA test_pkg_default_value;