【GaussDB】507内核新特性-PLSQL字节码(二)

【GaussDB】507内核新特性-PLSQL字节码(二)

前言

上一篇《【GaussDB】507内核新特性-PLSQL字节码(一)》讲了正常使用的情况,这篇来讲讲使用约束。

一般来说,一个功能在哪些场景下支持,哪些场景下不支持,往往要么写白名单,要么写黑名单,不会两个都写上。

白名单意味着:产品保证在这些场景下可用,如果试出了在白名单以外的场景也可用,官方不保证没问题,用出问题不算BUG,设计如此;

黑名单意味着:产品明确这些场景有问题,如果发现黑名单里的东西是支持的,那是BUG,官方不保证每次都能正常使用。黑名单以外的场景都支持,测出问题那是BUG,官方会负责修复或者改文档增加黑名单内容。

但这次GaussDB把黑白名单都放文档里了,对于PLSQL这一复杂的开发语言而言,不可能两个章节就能把所有的场景都描述进去,所以这个黑白双名单就有点耐人寻味了。

本文环境参数配置

bash 复制代码
gs_guc reload -I all -N all -c "ddl_invalid_mode='invalid'";
gs_guc reload -I all -N all -c "enable_force_create_obj=on";
gs_guc reload -I all -N all -c "a_format_dev_version='s6'"
gs_guc reload -I all -N all -c "behavior_compat_options='aformat_null_test,aformat_regexp_match,allow_procedure_compile_check,bind_procedure_searchpath,compat_cursor,convert_string_digit_to_numeric,correct_to_number,current_sysdate,display_leading_zero,dynamic_sql_compat,enable_bpcharlikebpchar_compare,enable_case_when_alias,enable_crosstype_integer_operator,enable_ora_joinop_in_updatestmt,enable_use_ora_timestamptz,end_month_calculate,forbid_package_function_with_prefix,forbid_skip_tableof_empty_str_elem,forbid_update_multi_same_tables,plsql_rollback_keep_user,plsql_security_definer,plstmt_implicit_savepoint,proc_implicit_for_loop_variable,proc_outparam_override,proc_outparam_transfer_length,rownum_type_compat,show_full_error_lineno,sys_function_without_brackets,tableof_elem_constraints,time_constexpr_compact,truncate_numeric_tail_zero,unbind_divide_bound,varray_compat'"
gs_guc reload -I all -N all -c "plsql_code_type='BYTECODE'"

注意当前版本的自治事务不会从主事务复制plsql_code_type参数,因此需要全局设置。

另外,为了方便从日志观察,全局打开了字节码的日志

bash 复制代码
gs_guc reload -I all -N all -c "logging_module = 'on(BYTECODE)'"

测试

下面开始根据官方文档所说的约束,逐条开始进行测试,但有些一眼看破的东西我就懒得写代码测了,写个说明完事。

  • 目前不支持的DFX功能:PLDEBUGGER(打开PLDEBUGGER时,函数或存储过程将通过传统引擎执行),PG_STAT_USER_FUNCTIONS视图(仅统计通过传统引擎执行存储过程或函数的时间)。

    这里应该是指 DBE_PLDEBUGGER 存储过程调试功能,以及自定义函数统计信息收集视图

  • 不支持PACKAGE实例化。

    字节码按照proc维度实例化,package里的procedure和function是可以实例化的,只是package本身不作为一个整体实例化

  • 不支持匿名块。

    直接执行的匿名块不是保存在数据库里的对象,没有pg_proc的oid,就不支持,但是通过匿名块执行的proc,或者proc里嵌套的匿名块是支持的。另外,包的初始化匿名块也不支持,但含有初始化匿名块的包内的proc是支持的。

sql 复制代码
gaussdb=> create or replace package pkg_test1 is
gaussdb$> x int;
gaussdb$> procedure a1 ;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE
gaussdb=> 
gaussdb=> create  or replace package body pkg_test1 is
gaussdb$> procedure a1 is
gaussdb$> begin
gaussdb$> x:=x+1;
gaussdb$> end;
gaussdb$> begin
gaussdb$> x:=0;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE BODY
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call pkg_test1.a1();
LOG:  [ByteCode] BC019 proc 177 isn't pllanguage.
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 32976.
LOG:  [ByteCode] Function: a1(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] loadn_pkg 0 
[26] iconst1 
[27] function func: int4pl 
[40] storen_pkg 0 
[45] exec_stmt_end 
[58] exec_stmt_begin 
[79] exec_stmt_end 
[92] return0 5 

LOG:  Start ByteCode!
-[ RECORD 1 ]
a1 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> 
gaussdb=> select bytecode from dump_plsql_bytecode('pkg_test1.a1'::regproc);
-[ RECORD 1 ]-------------------------
bytecode | [0] exec_stmt_begin 
         | [21] loadn_pkg 0 
         | [26] iconst1 
         | [27] function func: int4pl 
         | [40] storen_pkg 0 
         | [45] exec_stmt_end 
         | [58] exec_stmt_begin 
         | [79] exec_stmt_end 
         | [92] return0 5 
         | 

gaussdb=> 
  • 不支持TRIGGER。
    trigger本身不是pl对象,它需要关联一个proc,就算是使用O的匿名块语法,也会隐式创建一个同名的proc
sql 复制代码
gaussdb=> CREATE TABLE test_trigger_src_tbl(id1 INT, id2 INT, id3 INT);
CREATE TABLE
gaussdb=> CREATE TABLE test_trigger_des_tbl(id1 INT, id2 INT, id3 INT);
CREATE TABLE
gaussdb=> CREATE TRIGGER insert_trigger_with_anonyblock
gaussdb-> BEFORE INSERT ON test_trigger_src_tbl
gaussdb-> FOR EACH ROW
gaussdb-> DECLARE
gaussdb-> BEGIN
gaussdb$> INSERT INTO test_trigger_des_tbl VALUES(NEW.id1, NEW.id2, NEW.id3);
gaussdb$> RETURN NEW;
gaussdb$> END;
gaussdb$> /
CREATE TRIGGER
gaussdb=> select * from pg_trigger where tgname='insert_trigger_with_anonyblock';
-[ RECORD 1 ]--+-------------------------------
tgrelid        | 32977
tgname         | insert_trigger_with_anonyblock
tgfoid         | 32983
tgtype         | 7
tgenabled      | O
tgisinternal   | f
tgconstrrelid  | 0
tgconstrindid  | 0
tgconstraint   | 0
tgdeferrable   | f
tginitdeferred | f
tgnargs        | 0
tgattr         | 
tgargs         | \x
tgqual         | 
tgowner        | 16547

gaussdb=> select * from pg_proc where proname='insert_trigger_with_anonyblock';
-[ RECORD 1 ]-------+--------------------------------------------------------------------
proname             | insert_trigger_with_anonyblock
pronamespace        | 16550
proowner            | 16547
prolang             | 11442
procost             | 100
prorows             | 0
provariadic         | 0
protransform        | -
proisagg            | f
proiswindow         | f
prosecdef           | t
proleakproof        | f
proisstrict         | f
proretset           | f
provolatile         | v
pronargs            | 0
pronargdefaults     | 0
prorettype          | 2279
proargtypes         | 
proallargtypes      | 
proargmodes         | 
proargnames         | 
proargdefaults      | 
prosrc              | DECLARE 
                    | BEGIN
                    | INSERT INTO test_trigger_des_tbl VALUES(NEW.id1, NEW.id2, NEW.id3);
                    | RETURN NEW;
                    | END
probin              | 
proconfig           | 
proacl              | {admin=X/admin}
prodefaultargpos    | 
fencedmode          | f
proshippable        | f
propackage          | f
prokind             | t
proargsrc           | 
propackageid        | 0
proisprivate        | f
proargtypesext      | 
prodefaultargposext | 
allargtypes         | 
allargtypesext      | 

gaussdb=> 
gaussdb=> set client_min_messages = log;
SET
gaussdb=> insert into test_trigger_src_tbl values (1,2,3);
LOG:  [ByteCode] BC003 bytecode doesn't support trigger func.
LOG:  [ByteCode] BC053 bytecode only support select statement.
LOG:  [ByteCode] BC039 This function doesn't support bytecode, func_oid: 32983.
INSERT 0 1
gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('insert_trigger_with_anonyblock'::regproc);
-[ RECORD 1 ]-----------
bytecode | Not supported

gaussdb=> 

测试的确是 Not supported

  • 不支持返回集合的函数。
    这里就有点描述不清了,以下我分三个场景测试
  1. returns setof
sql 复制代码
gaussdb=> DROP TABLE if exists t1;
NOTICE:  table "t1" does not exist, skipping
DROP TABLE
gaussdb=> CREATE TABLE t1(a int);
CREATE TABLE
gaussdb=> INSERT INTO t1 VALUES(1),(10);
INSERT 0 2
gaussdb=> CREATE OR REPLACE FUNCTION fun_for_return_next() RETURNS SETOF t1 AS $$
gaussdb$> DECLARE
gaussdb$>    r t1%ROWTYPE;
gaussdb$> BEGIN
gaussdb$>    FOR r IN select * from t1
gaussdb$>    LOOP
gaussdb$>       RETURN NEXT r;
gaussdb$>    END LOOP;
gaussdb$>    RETURN;
gaussdb$> END;
gaussdb$> $$ LANGUAGE plpgsql;
CREATE FUNCTION
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call fun_for_return_next();
LOG:  [ByteCode] BC004 bytecode doesn't support func which returns set.
LOG:  [ByteCode] BC030 Stmt RETURN NEXT does not support with some error, lineno: 7.
LOG:  [ByteCode] BC039 This function doesn't support bytecode, func_oid: 32988.
-[ RECORD 1 ]
a | 1
-[ RECORD 2 ]
a | 10

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode((select oid from pg_proc where proname='fun_for_return_next'));
-[ RECORD 1 ]-----------
bytecode | Not supported

gaussdb=> 
  1. returns table
sql 复制代码
gaussdb=> CREATE OR REPLACE FUNCTION fun_for_return_next2() RETURNS table (a int) AS $$
gaussdb$> DECLARE
gaussdb$>    r t1%ROWTYPE;
gaussdb$> BEGIN
gaussdb$>    RETURN query select * from t1;
gaussdb$> END;
gaussdb$> $$ LANGUAGE plpgsql;
CREATE FUNCTION
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call fun_for_return_next2(null);
LOG:  [ByteCode] BC004 bytecode doesn't support func which returns set.
LOG:  [ByteCode] BC013 The bytecode does not allow parameters except in & out.
LOG:  [ByteCode] BC039 This function doesn't support bytecode, func_oid: 32991.
-[ RECORD 1 ]
a | 1
-[ RECORD 2 ]
a | 10

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode((select oid from pg_proc where proname='fun_for_return_next2'));
-[ RECORD 1 ]-----------
bytecode | Not supported

gaussdb=> 
  1. return type (is table of )
sql 复制代码
gaussdb=> create type ty_test5 as (a int,b int);
CREATE TYPE
gaussdb=> create type tyt_test5 is table of ty_test5;
CREATE TYPE
gaussdb=> create function f5 return tyt_test5 is
gaussdb$> v tyt_test5:=tyt_test5();
gaussdb$> begin
gaussdb$> v.extend;
gaussdb$> v(1):=ty_test5(1,2);
gaussdb$> return v;
gaussdb$> end;
gaussdb$> /
CREATE FUNCTION
gaussdb=> set client_min_messages = log;
SET
gaussdb=> select f5();
LOG:  [ByteCode] BC019 proc 6149 isn't pllanguage.
CONTEXT:  referenced column: f5
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 32997.
CONTEXT:  referenced column: f5
LOG:  [ByteCode] Function: f5(), InterpreterBytecode:
[0] create_nesttable tyt_test5 0 
[9] storen_nesttable 9 
[22] exec_stmt_begin 
[43] loadn_expand 9 
[48] iconst1 
[49] function func: nesttable_extend 
[62] storen_nesttable 9 
[75] exec_stmt_end 
[88] exec_stmt_begin 
[109] iconst1 
[110] iconst2 
[111] eval_rowexpr  
[120] expand_and_load_table 9 
[125] iconst1 
[126] store_nesttable_elem 2249 -1 
[135] exec_stmt_end 
[148] exec_stmt_begin 
[169] loadn_expand 9 
[174] transfer 
[179] exec_stmt_end 
[192] return 5 

CONTEXT:  referenced column: f5
LOG:  Start ByteCode!
CONTEXT:  referenced column: f5
-[ RECORD 1 ]-
f5 | {"(1,2)"}

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode((select oid from pg_proc where proname='f5'));
-[ RECORD 1 ]-----------------------------------
bytecode | [0] create_nesttable tyt_test5 0 
         | [9] storen_nesttable 9 
         | [22] exec_stmt_begin 
         | [43] loadn_expand 9 
         | [48] iconst1 
         | [49] function func: nesttable_extend 
         | [62] storen_nesttable 9 
         | [75] exec_stmt_end 
         | [88] exec_stmt_begin 
         | [109] iconst1 
         | [110] iconst2 
         | [111] eval_rowexpr  
         | [120] expand_and_load_table 9 
         | [125] iconst1 
         | [126] store_nesttable_elem 2249 -1 
         | [135] exec_stmt_end 
         | [148] exec_stmt_begin 
         | [169] loadn_expand 9 
         | [174] transfer 
         | [179] exec_stmt_end 
         | [192] return 5 
         | 

gaussdb=> 

return 嵌套表类型是支持的,returns setof/table 是不支持的。

  • 不支持高级包以及系统函数。
    自定义pl存储过程里使用系统函数不会导致自定义存储过程不支持字节码,像下面这种日志其实没有影响
sql 复制代码
LOG:  [ByteCode] BC019 proc 7752 isn't pllanguage.
LOG:  [ByteCode] BC019 proc 1724 isn't pllanguage.
  • 不支持带有出参的FUNCTION在表达式中嵌套调用。
    这个用法在GaussDB本来就是会报错的,与字节码无关
sql 复制代码
gaussdb=> create function f1(o out int) return varchar2 is
gaussdb$> begin
gaussdb$>     return 'a';
gaussdb$> end;
gaussdb$> /
CREATE FUNCTION
gaussdb=> set client_min_messages = log;
SET
gaussdb=> declare
gaussdb-> x text;
gaussdb-> o int;
gaussdb-> begin
gaussdb$> x:=x||f1(o);
gaussdb$> end;
gaussdb$> /
ERROR:  Function f1 with out parameters cannot be called by an expression.
CONTEXT:  PL/pgSQL function inline_code_block line 5 at assignment
gaussdb=> reset client_min_messages;
RESET
gaussdb=> 

不嵌套,直接x:=f1(o);是可以使用字节码的

  • 不支持RETURN复合类型的带有出参的FUNCTION。
sql 复制代码
gaussdb=> create type ty_test1 as (a int,b int);
CREATE TYPE
gaussdb=> create or replace function f2(o out int) return ty_test1 is
gaussdb$> x ty_test1:=ty_test1();
gaussdb$> begin
gaussdb$> return x;
gaussdb$> end;
gaussdb$> /
CREATE FUNCTION
gaussdb=> set client_min_messages = log;
SET
gaussdb=> declare
gaussdb-> x ty_test1;
gaussdb-> v int;
gaussdb-> begin
gaussdb$> x:=f2(v);
gaussdb$> end;
gaussdb$> /
LOG:  [ByteCode] BC057 bytecode doesn't support function with outparam return record.
CONTEXT:  SQL statement "CALL f2(v)"
PL/pgSQL function inline_code_block line 5 at assignment
LOG:  [ByteCode] BC059 bytecode does not support return var is not out param var.
CONTEXT:  SQL statement "CALL f2(v)"
PL/pgSQL function inline_code_block line 5 at assignment
LOG:  [ByteCode] BC030 Stmt RETURN does not support with some error, lineno: 4.
CONTEXT:  SQL statement "CALL f2(v)"
PL/pgSQL function inline_code_block line 5 at assignment
LOG:  [ByteCode] BC039 This function doesn't support bytecode, func_oid: 33002.
CONTEXT:  SQL statement "CALL f2(v)"
PL/pgSQL function inline_code_block line 5 at assignment
ANONYMOUS BLOCK EXECUTE
gaussdb=> reset client_min_messages;
RESET
gaussdb=> 

这里其实报了两个不支持,一是不支持带出参的函数返回record/复合类型,二是不支持返回值不是出参值("返回值是出参值"指的是PG风格带出参的function,out参数其实就是定义的return,但既然必须要开启proc_outparam_override,就肯定不会是PG风格的出参,不知该如何理解)

  • 不支持PROCEDURE显式指定RETURN值(正常用法PROCEDURE无需RETURN值)。
sql 复制代码
gaussdb=> create or replace procedure p1 is
gaussdb$> begin
gaussdb$> return '';
gaussdb$> end;
gaussdb$> /
WARNING:  RETURN cannot have a parameter in a function returning void.
DETAIL:  N/A
CONTEXT:  compilation of PL/pgSQL function "p1" near line 3
WARNING:  Procedure created with compilation errors.
CREATE PROCEDURE
gaussdb=> 

这玩意本身就会编译报错,无法执行的。

  • 不支持子程序
sql 复制代码
gaussdb=> create or replace procedure p2 is 
gaussdb$> a int;
gaussdb$> procedure p3 is
gaussdb$> begin
gaussdb$> null;
gaussdb$> end;
gaussdb$> begin
gaussdb$> p3();
gaussdb$> a:=a+1;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p2();
LOG:  [ByteCode] BC068 bytecode neither support nest sub procedure/function nor subtype.
-[ RECORD 1 ]
p2 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('p2'::regproc);
-[ RECORD 1 ]-----------
bytecode | Not supported

gaussdb=> 

的确不支持

  • 主事务不支持嵌套调用自治事务的表达式执行字节码(自治事务创建的新SESSION执行存储过程可以通过字节码框架执行)。
    这里需要注意,自治事务是新开连接,而且plsql_code_type这个参数的值不会从主事务复制到自治事务,因此自治事务如果要使用字节码,则需要在非会话级设置,比如database/role/instance级别
  1. 存储过程里嵌套了一个自治事务的匿名块
sql 复制代码
gaussdb=> create or replace procedure p_main2 is
gaussdb$> x int:=0;
gaussdb$> begin
gaussdb$> x:=x+1;
gaussdb$> declare
gaussdb$> PRAGMA AUTONOMOUS_TRANSACTION;
gaussdb$> begin
gaussdb$> x:=x+2;
gaussdb$> end;
gaussdb$> x:=x+3;
gaussdb$> end;
gaussdb$> /
ERROR:  Autonomous transactions do not support nested anonymous blocks.
DETAIL:  N/A
gaussdb=> 

创建就报错

  1. 自治事务里调用另一个非自治事务的存储过程
sql 复制代码
gaussdb=> create or replace procedure p_main2 is
gaussdb$> x int:=0;
gaussdb$> begin
gaussdb$> x:=x+1;
gaussdb$> x:=x+3;
gaussdb$> commit;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> create or replace procedure p_autom2 is
gaussdb$> x int;
gaussdb$> PRAGMA AUTONOMOUS_TRANSACTION;
gaussdb$> begin
gaussdb$> raise notice 'plsql_code_type:%',current_setting('plsql_code_type');
gaussdb$> raise notice 'client_min_messages:%',current_setting('client_min_messages');raise notice 'logging_module:%',current_setting('logging_module');
gaussdb$> x:=x+1;
gaussdb$> p_main2();
gaussdb$> commit;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> alter database postgres set client_min_messages = log;
NOTICE:  SET "client_min_messages" TO "log" will only take effect after restarting session.
ALTER DATABASE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p_autom2();
LOG:  [ByteCode] BC019 proc 177 isn't pllanguage.
CONTEXT:  referenced column: p_autom2
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33007.
CONTEXT:  referenced column: p_autom2
LOG:  [ByteCode] Function: p_autom2(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] exec_stmt_treebased  
[34] exec_stmt_end 
[47] exec_stmt_begin 
[68] exec_stmt_treebased  
[81] exec_stmt_end 
[94] exec_stmt_begin 
[115] exec_stmt_treebased  
[128] exec_stmt_end 
[141] exec_stmt_begin 
[162] loadn 9 
[167] iconst1 
[168] function func: int4pl 
[181] storen 9 
[186] exec_stmt_end 
[199] exec_stmt_begin 
[220] procedure expression expr: CALL p_main2() 
[257] exec_stmt_end 
[270] nop_pop 
[271] exec_stmt_begin 
[292] exec_stmt_treebased_transaction  
[305] exec_stmt_end 
[318] exec_stmt_begin 
[339] exec_stmt_end 
[352] return0 5 

CONTEXT:  referenced column: p_autom2
LOG:  Start ByteCode!
CONTEXT:  referenced column: p_autom2
NOTICE:  plsql_code_type:BYTECODE
CONTEXT:  referenced column: p_autom2
NOTICE:  client_min_messages:log
CONTEXT:  referenced column: p_autom2
NOTICE:  logging_module:ALL,on(BYTECODE),off(COMMAND,DFS,GUC,GSCLEAN,HDFS,ORC,SLRU,MEM_CTL,AUTOVAC,CACHE,ADIO,SSL,GDS,TBLSPC,WLM,OBS,INDEX,EXECUTOR,OPFUSION,GPC,GSC,VEC_EXECUTOR,STREAM,LLVM,OPT,OPT_REWRITE,CBOPT_REWRITE,OPT_JOIN,OPT_AGG,OPT_CHOICE,OPT_SUBPLAN,OPT_SETOP,OPT_SKEW,OPT_PLANNER,OPT_STAT_EXT,OPT_SHIPPING,OPT_DSL_REWRITE,SPM,SPM_BG,SPM_KEY_FLOW,UDF,COOP_ANALYZE,WLMCP,ACCELERATE,MOT,PLANHINT,PARQUET,PGSTAT,CARBONDATA,SNAPSHOT,XACT,HANDLE,CLOG,EC,REMOTE,CN_RETRY,PLSQL,PLSQL_COMPILE,PLSQL_TRANS,TEXTSEARCH,SEQ,REDO,FUNCTION,PARSER,INSTR,WDR_SNAPSHOT,GSMONITOR,WDR_REPORT,ASP_REPORT,BLACKBOX,INCRE_CKPT,INCRE_BG_WRITER,DBL_WRT,RTO_RPO,HEARTBEAT,COMM_IPC,COMM_PARAM,TIMESERIES,SCHEMA,GTT,SEGMENT_PAGE,LIGHTPROXY,HOTKEY,THREAD_POOL,OPT_AI,WALRECEIVER,USTORE,UPAGE,UBTREE,UNDO,TIMECAPSULE,GEN_COL,DCF,AI4DB,DB4AI,ABO,MOD_ABOFEEDBACK,ASCEND,PLDEBUGGER,ADVISOR,SEC,SEC_FE,SEC_LEGER,SEC_POLICY,SEC_SDD,SEC_TDE,COMM_FRAMEWORK,COMM_PROXY,COMM_POOLER,COMM_STATUS,VACUUM,JOB,SPI,NEST_COMPILE,RESOWNER,GSSTACK,LOGICAL_DECODE,GPRC,DISASTER_READ,STANDBY_READ,SQL_APPLY,REPSYNC,SQLPATCH,PARTITION,UBT_NEWPAGE,GS_DEPENDENCY,GPI,LWLOCK,LOCK,UNIQUE_SQL,GLC,SRF,DBLINK,BARRIER_CREATOR,EXRTO_PAGE_P,SEQ_TUP_P,BT_TUP_P,DISPATCH_VERIFY,HBKT,HBKT_CBI,DBE_STATS,DBE_XMLGEN,MESSAGE_QUEUE,DBE_ALERT,GS_ILM,GSPERF,PARAMETERIZE,EXEC_REMOTE,UBTREE_PARA,BTREE_PARA,ANTI_CACHE,ANTI_RECYCLER,VERIFYLOG,PARALLEL_BUILD,GS_REPAIR,AUTHID,CCINDEX,ONLINE_DDL,MTD,EXRTO_BUFFER,WAL,HTAP,UALT,GTM_LITE_READ_S,UGIN,LOCAL_CACHE,BIINDEX,ONDEMAND,DATEA,TURBO_COMPRESS,GS_SIGNAL,AUTOHINT,EXRTO_READ_RECY,CHARACTER,ABNORMAL_SQL,GAUSS_STOR,BUFFILE,BUFFER,PAGE,SELCACHE,UTIL,FUNC_DEPEND,MOD_DBE_LOB,EXEC_CACHE,ROWID,WAL_IMAGE_CHECK,CHECK_XLOG_GEN,SHARE_STORAGE,MOD_TOOLKIT)
CONTEXT:  referenced column: p_autom2
LOG:  [ByteCode] BC019 proc 177 isn't pllanguage.
CONTEXT:  SQL statement "CALL p_main2()"
PL/pgSQL function p_autom2() line 8 at PERFORM
referenced column: p_autom2
LOG:  [ByteCode] BC019 proc 177 isn't pllanguage.
CONTEXT:  SQL statement "CALL p_main2()"
PL/pgSQL function p_autom2() line 8 at PERFORM
referenced column: p_autom2
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33006.
CONTEXT:  SQL statement "CALL p_main2()"
PL/pgSQL function p_autom2() line 8 at PERFORM
referenced column: p_autom2
LOG:  [ByteCode] Function: p_main2(), InterpreterBytecode:
[0] iconst0 
[1] storen 9 
[6] exec_stmt_begin 
[27] loadn 9 
[32] iconst1 
[33] function func: int4pl 
[46] storen 9 
[51] exec_stmt_end 
[64] exec_stmt_begin 
[85] loadn 9 
[90] iconst3 
[91] function func: int4pl 
[104] storen 9 
[109] exec_stmt_end 
[122] exec_stmt_begin 
[143] exec_stmt_treebased_transaction  
[156] exec_stmt_end 
[169] exec_stmt_begin 
[190] exec_stmt_end 
[203] return0 5 

CONTEXT:  SQL statement "CALL p_main2()"
PL/pgSQL function p_autom2() line 8 at PERFORM
referenced column: p_autom2
LOG:  [ByteCode] Function: CALL p_main2(), InterpreterBytecode:
[0] nop_push 
[1] invokemethod_definer func: p_main2 

CONTEXT:  PL/pgSQL function p_autom2() line 8 at PERFORM
referenced column: p_autom2
-[ RECORD 1 ]
p_autom2 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> alter database postgres reset client_min_messages;
NOTICE:  SET "client_min_messages" TO "(null)" will only take effect after restarting session.
ALTER DATABASE
gaussdb=> select bytecode from dump_plsql_bytecode('p_main2'::regproc);
-[ RECORD 1 ]-------------------------------------
bytecode | [0] iconst0 
         | [1] storen 9 
         | [6] exec_stmt_begin 
         | [27] loadn 9 
         | [32] iconst1 
         | [33] function func: int4pl 
         | [46] storen 9 
         | [51] exec_stmt_end 
         | [64] exec_stmt_begin 
         | [85] loadn 9 
         | [90] iconst3 
         | [91] function func: int4pl 
         | [104] storen 9 
         | [109] exec_stmt_end 
         | [122] exec_stmt_begin 
         | [143] exec_stmt_treebased_transaction  
         | [156] exec_stmt_end 
         | [169] exec_stmt_begin 
         | [190] exec_stmt_end 
         | [203] return0 5 
         | 

gaussdb=> select bytecode from dump_plsql_bytecode('p_autom2'::regproc);
-[ RECORD 1 ]----------------------------------------------
bytecode | [0] exec_stmt_begin 
         | [21] exec_stmt_treebased  
         | [34] exec_stmt_end 
         | [47] exec_stmt_begin 
         | [68] exec_stmt_treebased  
         | [81] exec_stmt_end 
         | [94] exec_stmt_begin 
         | [115] exec_stmt_treebased  
         | [128] exec_stmt_end 
         | [141] exec_stmt_begin 
         | [162] loadn 9 
         | [167] iconst1 
         | [168] function func: int4pl 
         | [181] storen 9 
         | [186] exec_stmt_end 
         | [199] exec_stmt_begin 
         | [220] procedure expression expr: CALL p_main2() 
         | [257] exec_stmt_end 
         | [270] nop_pop 
         | [271] exec_stmt_begin 
         | [292] exec_stmt_treebased_transaction  
         | [305] exec_stmt_end 
         | [318] exec_stmt_begin 
         | [339] exec_stmt_end 
         | [352] return0 5 
         | 

gaussdb=> 

两个存储过程都支持字节码。

这里注意,自治事务没有复制主事务的client_min_messages参数,所以额外在数据库级别上设置了一下,否则打不出这个日志

  1. 存储过程里调用了另一个自治事务的存储过程
sql 复制代码
gaussdb=> create or replace procedure p_autom1 is
gaussdb$> x int;
gaussdb$> PRAGMA AUTONOMOUS_TRANSACTION;
gaussdb$> begin
gaussdb$> x:=x+1;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> create or replace procedure p_main1 is
gaussdb$> begin
gaussdb$> p_autom1();
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> alter database postgres set client_min_messages = log;
NOTICE:  SET "client_min_messages" TO "log" will only take effect after restarting session.
ALTER DATABASE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p_main1();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33009.
LOG:  [ByteCode] Function: p_main1(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] procedure expression expr: CALL p_autom1() 
[58] exec_stmt_end 
[71] nop_pop 
[72] exec_stmt_begin 
[93] exec_stmt_end 
[106] return0 5 

LOG:  Start ByteCode!
LOG:  [ByteCode] BC072 Expression: CALL p_autom1() is degenerated.
CONTEXT:  PL/pgSQL function p_main1() line 3 at PERFORM
LOG:  [ByteCode] BC019 proc 177 isn't pllanguage.
CONTEXT:  referenced column: p_autom1
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33008.
CONTEXT:  referenced column: p_autom1
LOG:  [ByteCode] Function: p_autom1(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] loadn 9 
[26] iconst1 
[27] function func: int4pl 
[40] storen 9 
[45] exec_stmt_end 
[58] exec_stmt_begin 
[79] exec_stmt_end 
[92] return0 5 

CONTEXT:  referenced column: p_autom1
LOG:  Start ByteCode!
CONTEXT:  referenced column: p_autom1
-[ RECORD 1 ]
p_main1 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> alter database postgres reset client_min_messages;
NOTICE:  SET "client_min_messages" TO "(null)" will only take effect after restarting session.
ALTER DATABASE
gaussdb=> select bytecode from dump_plsql_bytecode('p_autom1'::regproc);
-[ RECORD 1 ]-------------------------
bytecode | [0] exec_stmt_begin 
         | [21] loadn 9 
         | [26] iconst1 
         | [27] function func: int4pl 
         | [40] storen 9 
         | [45] exec_stmt_end 
         | [58] exec_stmt_begin 
         | [79] exec_stmt_end 
         | [92] return0 5 
         | 

gaussdb=> select bytecode from dump_plsql_bytecode('p_main1'::regproc);
-[ RECORD 1 ]----------------------------------------------
bytecode | [0] exec_stmt_begin 
         | [21] procedure expression expr: CALL p_autom1() 
         | [58] exec_stmt_end 
         | [71] nop_pop 
         | [72] exec_stmt_begin 
         | [93] exec_stmt_end 
         | [106] return0 5 
         | 

gaussdb=> 

主事务和自治事务的存储过程都支持字节码

  1. 自治事务的双重嵌套
sql 复制代码
gaussdb=> create or replace procedure p_autom3 is
gaussdb$> x int;
gaussdb$> PRAGMA AUTONOMOUS_TRANSACTION;
gaussdb$> begin
gaussdb$> x:=x+1;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> create or replace procedure p_autom4 is
gaussdb$> x int;
gaussdb$> PRAGMA AUTONOMOUS_TRANSACTION;
gaussdb$> begin
gaussdb$> p_autom3();
gaussdb$> x:=x+1;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> create or replace procedure p_main3 is
gaussdb$> begin
gaussdb$> p_autom4();
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> alter database postgres set client_min_messages = log;
NOTICE:  SET "client_min_messages" TO "log" will only take effect after restarting session.
ALTER DATABASE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p_main3();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33012.
LOG:  [ByteCode] Function: p_main3(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] procedure expression expr: CALL p_autom4() 
[58] exec_stmt_end 
[71] nop_pop 
[72] exec_stmt_begin 
[93] exec_stmt_end 
[106] return0 5 

LOG:  Start ByteCode!
LOG:  [ByteCode] BC072 Expression: CALL p_autom4() is degenerated.
CONTEXT:  PL/pgSQL function p_main3() line 3 at PERFORM
LOG:  [ByteCode] BC019 proc 177 isn't pllanguage.
CONTEXT:  referenced column: p_autom4
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33011.
CONTEXT:  referenced column: p_autom4
LOG:  [ByteCode] Function: p_autom4(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] procedure expression expr: CALL p_autom3() 
[58] exec_stmt_end 
[71] nop_pop 
[72] exec_stmt_begin 
[93] loadn 9 
[98] iconst1 
[99] function func: int4pl 
[112] storen 9 
[117] exec_stmt_end 
[130] exec_stmt_begin 
[151] exec_stmt_end 
[164] return0 5 

CONTEXT:  referenced column: p_autom4
LOG:  Start ByteCode!
CONTEXT:  referenced column: p_autom4
LOG:  [ByteCode] BC072 Expression: CALL p_autom3() is degenerated.
CONTEXT:  PL/pgSQL function p_autom4() line 5 at PERFORM
referenced column: p_autom4
LOG:  [ByteCode] BC019 proc 177 isn't pllanguage.
CONTEXT:  referenced column: p_autom3
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33010.
CONTEXT:  referenced column: p_autom3
LOG:  [ByteCode] Function: p_autom3(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] loadn 9 
[26] iconst1 
[27] function func: int4pl 
[40] storen 9 
[45] exec_stmt_end 
[58] exec_stmt_begin 
[79] exec_stmt_end 
[92] return0 5 

CONTEXT:  referenced column: p_autom3
LOG:  Start ByteCode!
CONTEXT:  referenced column: p_autom3
-[ RECORD 1 ]
p_main3 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> alter database postgres reset client_min_messages;
NOTICE:  SET "client_min_messages" TO "(null)" will only take effect after restarting session.
ALTER DATABASE
gaussdb=> select bytecode from dump_plsql_bytecode('p_autom3'::regproc);
-[ RECORD 1 ]-------------------------
bytecode | [0] exec_stmt_begin 
         | [21] loadn 9 
         | [26] iconst1 
         | [27] function func: int4pl 
         | [40] storen 9 
         | [45] exec_stmt_end 
         | [58] exec_stmt_begin 
         | [79] exec_stmt_end 
         | [92] return0 5 
         | 

gaussdb=> select bytecode from dump_plsql_bytecode('p_autom4'::regproc);
-[ RECORD 1 ]----------------------------------------------
bytecode | [0] exec_stmt_begin 
         | [21] procedure expression expr: CALL p_autom3() 
         | [58] exec_stmt_end 
         | [71] nop_pop 
         | [72] exec_stmt_begin 
         | [93] loadn 9 
         | [98] iconst1 
         | [99] function func: int4pl 
         | [112] storen 9 
         | [117] exec_stmt_end 
         | [130] exec_stmt_begin 
         | [151] exec_stmt_end 
         | [164] return0 5 
         | 

gaussdb=> select bytecode from dump_plsql_bytecode('p_main3'::regproc);
-[ RECORD 1 ]----------------------------------------------
bytecode | [0] exec_stmt_begin 
         | [21] procedure expression expr: CALL p_autom4() 
         | [58] exec_stmt_end 
         | [71] nop_pop 
         | [72] exec_stmt_begin 
         | [93] exec_stmt_end 
         | [106] return0 5 
         | 

gaussdb=> 

主事务和两个自治事务都支持字节码

  1. 表达式是自治事务的函数

    gaussdb=> create function f6 return int is
    gaussdb> PRAGMA AUTONOMOUS_TRANSACTION; gaussdb> begin
    gaussdb> return 1; gaussdb> end;
    gaussdb> / CREATE FUNCTION gaussdb=> create procedure p6 is gaussdb> v int;
    gaussdb> begin gaussdb> v:=f6();
    gaussdb> end; gaussdb> /
    CREATE PROCEDURE
    gaussdb=> alter database postgres set client_min_messages = log;
    NOTICE: SET "client_min_messages" TO "log" will only take effect after restarting session.
    ALTER DATABASE
    gaussdb=> set client_min_messages = log;
    SET
    gaussdb=> call p6();
    LOG: [ByteCode] BC040 This function supports bytecode, func_oid: 33014.
    LOG: [ByteCode] Function: p6(), InterpreterBytecode:
    [0] exec_stmt_begin
    [21] expression expr: SELECT f6()
    [58] storen 9
    [63] exec_stmt_end
    [76] exec_stmt_begin
    [97] exec_stmt_end
    [110] return0 5

    LOG: Start ByteCode!
    LOG: [ByteCode] BC072 Expression: SELECT f6() is degenerated.
    CONTEXT: PL/pgSQL function p6() line 4 at assignment
    LOG: [ByteCode] BC040 This function supports bytecode, func_oid: 33013.
    CONTEXT: referenced column: f6
    LOG: [ByteCode] Function: f6(), InterpreterBytecode:
    [0] exec_stmt_begin
    [21] iconst1
    [22] exec_stmt_end
    [35] return 5

    CONTEXT: referenced column: f6
    LOG: Start ByteCode!
    CONTEXT: referenced column: f6
    -[ RECORD 1 ]
    p6 |

    gaussdb=> reset client_min_messages;
    RESET
    gaussdb=> alter database postgres reset client_min_messages;
    NOTICE: SET "client_min_messages" TO "(null)" will only take effect after restarting session.
    ALTER DATABASE
    gaussdb=> select bytecode from dump_plsql_bytecode('f6'::regproc);
    -[ RECORD 1 ]------------------
    bytecode | [0] exec_stmt_begin
    | [21] iconst1
    | [22] exec_stmt_end
    | [35] return 5
    |

    gaussdb=> select bytecode from dump_plsql_bytecode('p6'::regproc);
    -[ RECORD 1 ]--------------------------------
    bytecode | [0] exec_stmt_begin
    | [21] expression expr: SELECT f6()
    | [58] storen 9
    | [63] exec_stmt_end
    | [76] exec_stmt_begin
    | [97] exec_stmt_end
    | [110] return0 5
    |

    gaussdb=>

主事务和自治事务都支持字节码

上面测了5种场景,并没有测出不支持的情况。

  • 不支持SUBTYPE类型。
    GaussDB里有两个subtype的概念
  1. PG原生的RANGE类型里指定subtype ,不过这样应该叫不支持range类型
sql 复制代码
gaussdb=> CREATE TYPE float8_range AS RANGE (subtype = float8, subtype_diff = float8mi);
CREATE TYPE
gaussdb=> create procedure p5 is
gaussdb$> v float8_range;
gaussdb$> begin
gaussdb$> v:='[1,5]';
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p5();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33027.
LOG:  [ByteCode] Function: p5(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] const64 
[30] outputfunction func: textout 
[39] inputfunction func: range_in 
[56] storen_copy1 9 
[61] exec_stmt_end 
[74] exec_stmt_begin 
[95] exec_stmt_end 
[108] return0 5 

LOG:  Start ByteCode!
-[ RECORD 1 ]
p5 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('p5'::regproc);
-[ RECORD 1 ]--------------------------------
bytecode | [0] exec_stmt_begin 
         | [21] const64 
         | [30] outputfunction func: textout 
         | [39] inputfunction func: range_in 
         | [56] storen_copy1 9 
         | [61] exec_stmt_end 
         | [74] exec_stmt_begin 
         | [95] exec_stmt_end 
         | [108] return0 5 
         | 

gaussdb=> 

这种实测是支持的

  1. ORACLE风格package里的subtype
sql 复制代码
gaussdb=> create package pkg5 is
gaussdb$> subtype varchar8 is varchar2(8);
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE
gaussdb=> create package pkg6 is
gaussdb$> procedure p6 ;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE
gaussdb=> create package body pkg6 is
gaussdb$> procedure p6 is
gaussdb$> v pkg5.varchar8;
gaussdb$> begin
gaussdb$> v:=1;
gaussdb$> end;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE BODY
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call pkg6.p6();
LOG:  [ByteCode] BC036 bytecode does not support to cast subtype.
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33032.
LOG:  [ByteCode] Function: p6(), InterpreterBytecode:
[0] const_null 
[1] inputfunction func: subtype_in 
[18] storen_copy1 9 
[23] exec_stmt_begin 
[44] exec_stmt_treebased  
[57] exec_stmt_end 
[70] exec_stmt_begin 
[91] exec_stmt_end 
[104] return0 5 

LOG:  Start ByteCode!
-[ RECORD 1 ]
p6 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('pkg6.p6'::regproc);
-[ RECORD 1 ]---------------------------------
bytecode | [0] const_null 
         | [1] inputfunction func: subtype_in 
         | [18] storen_copy1 9 
         | [23] exec_stmt_begin 
         | [44] exec_stmt_treebased  
         | [57] exec_stmt_end 
         | [70] exec_stmt_begin 
         | [91] exec_stmt_end 
         | [104] return0 5 
         | 

gaussdb=> 

这个实测也是支持的

弄个subtype类型的参数

sql 复制代码
gaussdb=> create or replace package pkg6 is
gaussdb$> procedure p6 ;
gaussdb$> procedure p7(i pkg5.varchar8);
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE
gaussdb=> create or replace package body pkg6 is
gaussdb$> procedure p6 is
gaussdb$> v pkg5.varchar8;
gaussdb$> begin
gaussdb$> v:=1;
gaussdb$> end;
gaussdb$> procedure p7(i pkg5.varchar8) is
gaussdb$> v pkg5.varchar8;
gaussdb$> begin
gaussdb$> v:=i;
gaussdb$> end;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE BODY
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call pkg6.p7(1);
LOG:  [ByteCode] BC036 bytecode does not support to cast subtype.
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33033.
LOG:  [ByteCode] Function: p7(pkg5.varchar8), InterpreterBytecode:
[0] const_null 
[1] inputfunction func: subtype_in 
[18] storen_copy1 10 
[23] exec_stmt_begin 
[44] exec_stmt_treebased  
[57] exec_stmt_end 
[70] exec_stmt_begin 
[91] exec_stmt_end 
[104] return0 5 

LOG:  Start ByteCode!
-[ RECORD 1 ]
p7 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('pkg6.p7'::regproc);
-[ RECORD 1 ]---------------------------------
bytecode | [0] const_null 
         | [1] inputfunction func: subtype_in 
         | [18] storen_copy1 10 
         | [23] exec_stmt_begin 
         | [44] exec_stmt_treebased  
         | [57] exec_stmt_end 
         | [70] exec_stmt_begin 
         | [91] exec_stmt_end 
         | [104] return0 5 
         | 

gaussdb=> 

也是支持的,这说明文档不对

  • 不支持游标循环语句SELECT返回的列数与语句中的游标变量列数不一致。
    可能指的是fetch into ,ORACLE里需保证列对应,但GaussDB里支持源列和目标列数不一致
sql 复制代码
gaussdb=> create or replace procedure p7 is
gaussdb$> v1 int;
gaussdb$> v2 int;
gaussdb$> cursor c is
gaussdb$> select 1 c1,2 c2,3 c3 from dual  ;
gaussdb$> begin
gaussdb$> open c;
gaussdb$> fetch c into v1,v2;
gaussdb$> close c;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p7();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33034.
LOG:  [ByteCode] Function: p7(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] exec_stmt_treebased_open  
[34] exec_stmt_end 
[47] exec_stmt_begin 
[68] exec_stmt_treebased_fetch  
[81] exec_stmt_end 
[94] exec_stmt_begin 
[115] exec_stmt_treebased_close  
[128] exec_stmt_end 
[141] exec_stmt_begin 
[162] exec_stmt_end 
[175] return0 5 

LOG:  Start ByteCode!
-[ RECORD 1 ]
p7 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('p7'::regproc);
-[ RECORD 1 ]-------------------------------
bytecode | [0] exec_stmt_begin 
         | [21] exec_stmt_treebased_open  
         | [34] exec_stmt_end 
         | [47] exec_stmt_begin 
         | [68] exec_stmt_treebased_fetch  
         | [81] exec_stmt_end 
         | [94] exec_stmt_begin 
         | [115] exec_stmt_treebased_close  
         | [128] exec_stmt_end 
         | [141] exec_stmt_begin 
         | [162] exec_stmt_end 
         | [175] return0 5 
         | 

gaussdb=> 

这种情况是支持的

放循环里

sql 复制代码
gaussdb=> create or replace procedure p8 is
gaussdb$> v1 int;
gaussdb$> v2 int;
gaussdb$> cursor c is
gaussdb$> select 1 c1,2 c2,3 c3 from dual  ;
gaussdb$> begin
gaussdb$> open c;
gaussdb$> loop
gaussdb$> if c%notfound then exit;
gaussdb$> end if;
gaussdb$> fetch c into v1,v2;
gaussdb$> raise notice 'v1:%,v2:%',v1,v2;
gaussdb$> end loop;
gaussdb$> close c;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p8();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33038.
LOG:  [ByteCode] Function: p8(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] exec_stmt_treebased_open  
[34] exec_stmt_end 
[47] exec_stmt_begin 
[68] loopwhile 
[73] exec_stmt_begin 
[94] loadn_cursor_attributes 11 
[103] if_or_when 49 
[108] exec_stmt_begin 
[129] exec_stmt_end 
[142] goto 122 
[147] goto 5 
[152] exec_stmt_end 
[165] exec_stmt_begin 
[186] exec_stmt_treebased_fetch  
[199] exec_stmt_end 
[212] exec_stmt_begin 
[233] exec_stmt_treebased  
[246] exec_stmt_end 
[259] goto -191 
[264] exec_stmt_end 
[277] exec_stmt_begin 
[298] exec_stmt_treebased_close  
[311] exec_stmt_end 
[324] exec_stmt_begin 
[345] exec_stmt_end 
[358] return0 5 

LOG:  Start ByteCode!
NOTICE:  v1:1,v2:2
NOTICE:  v1:1,v2:2
-[ RECORD 1 ]
p8 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('p8'::regproc);
-[ RECORD 1 ]-------------------------------
bytecode | [0] exec_stmt_begin 
         | [21] exec_stmt_treebased_open  
         | [34] exec_stmt_end 
         | [47] exec_stmt_begin 
         | [68] loopwhile 
         | [73] exec_stmt_begin 
         | [94] loadn_cursor_attributes 11 
         | [103] if_or_when 49 
         | [108] exec_stmt_begin 
         | [129] exec_stmt_end 
         | [142] goto 122 
         | [147] goto 5 
         | [152] exec_stmt_end 
         | [165] exec_stmt_begin 
         | [186] exec_stmt_treebased_fetch  
         | [199] exec_stmt_end 
         | [212] exec_stmt_begin 
         | [233] exec_stmt_treebased  
         | [246] exec_stmt_end 
         | [259] goto -191 
         | [264] exec_stmt_end 
         | [277] exec_stmt_begin 
         | [298] exec_stmt_treebased_close  
         | [311] exec_stmt_end 
         | [324] exec_stmt_begin 
         | [345] exec_stmt_end 
         | [358] return0 5 
         | 

gaussdb=> 

也是支持的,

反过来,让游标列数比目标参数列少

sql 复制代码
gaussdb=> create or replace procedure p9 is
gaussdb$> v1 int;
gaussdb$> v2 int;
gaussdb$> v3 int;
gaussdb$> v4 int;
gaussdb$> cursor c is
gaussdb$> select 1 c1,2 c2,3 c3 from dual  ;
gaussdb$> begin
gaussdb$> open c;
gaussdb$> loop
gaussdb$> if c%notfound then exit;
gaussdb$> end if;
gaussdb$> fetch c into v1,v2,v3,v4;
gaussdb$> raise notice 'v1:%,v2:%,v3:%,v4:%',v1,v2,v3,v4;
gaussdb$> end loop;
gaussdb$> close c;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p9();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33042.
LOG:  [ByteCode] Function: p9(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] exec_stmt_treebased_open  
[34] exec_stmt_end 
[47] exec_stmt_begin 
[68] loopwhile 
[73] exec_stmt_begin 
[94] loadn_cursor_attributes 13 
[103] if_or_when 49 
[108] exec_stmt_begin 
[129] exec_stmt_end 
[142] goto 122 
[147] goto 5 
[152] exec_stmt_end 
[165] exec_stmt_begin 
[186] exec_stmt_treebased_fetch  
[199] exec_stmt_end 
[212] exec_stmt_begin 
[233] exec_stmt_treebased  
[246] exec_stmt_end 
[259] goto -191 
[264] exec_stmt_end 
[277] exec_stmt_begin 
[298] exec_stmt_treebased_close  
[311] exec_stmt_end 
[324] exec_stmt_begin 
[345] exec_stmt_end 
[358] return0 5 

LOG:  Start ByteCode!
NOTICE:  v1:1,v2:2,v3:3,v4:<NULL>
NOTICE:  v1:1,v2:2,v3:3,v4:<NULL>
-[ RECORD 1 ]
p9 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('p9'::regproc);
-[ RECORD 1 ]-------------------------------
bytecode | [0] exec_stmt_begin 
         | [21] exec_stmt_treebased_open  
         | [34] exec_stmt_end 
         | [47] exec_stmt_begin 
         | [68] loopwhile 
         | [73] exec_stmt_begin 
         | [94] loadn_cursor_attributes 13 
         | [103] if_or_when 49 
         | [108] exec_stmt_begin 
         | [129] exec_stmt_end 
         | [142] goto 122 
         | [147] goto 5 
         | [152] exec_stmt_end 
         | [165] exec_stmt_begin 
         | [186] exec_stmt_treebased_fetch  
         | [199] exec_stmt_end 
         | [212] exec_stmt_begin 
         | [233] exec_stmt_treebased  
         | [246] exec_stmt_end 
         | [259] goto -191 
         | [264] exec_stmt_end 
         | [277] exec_stmt_begin 
         | [298] exec_stmt_treebased_close  
         | [311] exec_stmt_end 
         | [324] exec_stmt_begin 
         | [345] exec_stmt_end 
         | [358] return0 5 
         | 

gaussdb=> 

也是支持的,

让into 的是一个record变量

sql 复制代码
gaussdb=> create or replace procedure p99 is
gaussdb$> type t_r is record(v1 int,v2 int);
gaussdb$> r t_r;
gaussdb$> cursor c is
gaussdb$> select 1 c1,2 c2,3 c3 from dual  ;
gaussdb$> begin
gaussdb$> open c;
gaussdb$> loop
gaussdb$> if c%notfound then exit;
gaussdb$> end if;
gaussdb$> fetch c into r;
gaussdb$> raise notice 'r:%',r::text;
gaussdb$> end loop;
gaussdb$> close c;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p99();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33046.
LOG:  [ByteCode] Function: p99(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] exec_stmt_treebased_open  
[34] exec_stmt_end 
[47] exec_stmt_begin 
[68] loopwhile 
[73] exec_stmt_begin 
[94] loadn_cursor_attributes 13 
[103] if_or_when 49 
[108] exec_stmt_begin 
[129] exec_stmt_end 
[142] goto 122 
[147] goto 5 
[152] exec_stmt_end 
[165] exec_stmt_begin 
[186] exec_stmt_treebased_fetch  
[199] exec_stmt_end 
[212] exec_stmt_begin 
[233] exec_stmt_treebased  
[246] exec_stmt_end 
[259] goto -191 
[264] exec_stmt_end 
[277] exec_stmt_begin 
[298] exec_stmt_treebased_close  
[311] exec_stmt_end 
[324] exec_stmt_begin 
[345] exec_stmt_end 
[358] return0 5 

LOG:  Start ByteCode!
ERROR:  Assignment and variable field do not match.
CONTEXT:  PL/pgSQL function p99() line 11 at FETCH
gaussdb=> reset client_min_messages;
RESET

执行会报错 ERROR: Assignment and variable field do not match.

sql 复制代码
gaussdb=> create or replace procedure p98 is
gaussdb$> type t_r is record(v1 int,v2 int,v3 int);
gaussdb$> r t_r;
gaussdb$> cursor c is
gaussdb$> select 1 c1,2 c2 from dual  ;
gaussdb$> begin
gaussdb$> open c;
gaussdb$> loop
gaussdb$> if c%notfound then exit;
gaussdb$> end if;
gaussdb$> fetch c into r;
gaussdb$> raise notice 'r:%',r::text;
gaussdb$> end loop;
gaussdb$> close c;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p98();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33052.
LOG:  [ByteCode] Function: p98(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] exec_stmt_treebased_open  
[34] exec_stmt_end 
[47] exec_stmt_begin 
[68] loopwhile 
[73] exec_stmt_begin 
[94] loadn_cursor_attributes 14 
[103] if_or_when 49 
[108] exec_stmt_begin 
[129] exec_stmt_end 
[142] goto 122 
[147] goto 5 
[152] exec_stmt_end 
[165] exec_stmt_begin 
[186] exec_stmt_treebased_fetch  
[199] exec_stmt_end 
[212] exec_stmt_begin 
[233] exec_stmt_treebased  
[246] exec_stmt_end 
[259] goto -191 
[264] exec_stmt_end 
[277] exec_stmt_begin 
[298] exec_stmt_treebased_close  
[311] exec_stmt_end 
[324] exec_stmt_begin 
[345] exec_stmt_end 
[358] return0 5 

LOG:  Start ByteCode!
ERROR:  Assignment and variable field do not match.
CONTEXT:  PL/pgSQL function p98() line 11 at FETCH
gaussdb=> reset client_min_messages;
RESET
gaussdb=> 

这种反过来也会报错,ERROR: Assignment and variable field do not match.

所以没找到对应的不支持场景

  • 不支持RECORD变量的读取和赋值列值(如:va record; va.c1 := 1;)。
    游标的一行/row函数/复合类型不带参数名的构造,类型都是record,但复合类型带参数名的构造的类型则是复合类型自己。
sql 复制代码
gaussdb=> select pg_typeof(row(1,1));
-[ RECORD 1 ]-----
pg_typeof | record

gaussdb=> create type ty_test2 as (a int,b int);
CREATE TYPE
gaussdb=> select pg_typeof(ty_test2(1,1));
-[ RECORD 1 ]-----
pg_typeof | record

gaussdb=> select pg_typeof(ty_test2(a=>1,b=>1));
-[ RECORD 1 ]-------
pg_typeof | ty_test2

gaussdb=> 
sql 复制代码
gaussdb=> create procedure p10 is
gaussdb$> begin
gaussdb$> for rec in (select 1 a,2 b from dual) 
gaussdb$> loop
gaussdb$> raise notice '%',pg_typeof(rec);
gaussdb$> rec.a:=3;
gaussdb$> end loop;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p10();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33067.
LOG:  [ByteCode] Function: p10(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] fors_prepare 
[46] fors 105 
[59] exec_stmt_begin 
[80] exec_stmt_treebased  
[93] exec_stmt_end 
[106] exec_stmt_begin 
[127] iconst3 
[128] storen 9 
[133] exec_stmt_end 
[146] goto -100 
[151] exec_stmt_end 
[164] exec_stmt_begin 
[185] exec_stmt_end 
[198] return0 5 

LOG:  Start ByteCode!
NOTICE:  record
-[ RECORD 1 ]
p10 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('p10'::regproc);
-[ RECORD 1 ]------------------------
bytecode | [0] exec_stmt_begin 
         | [21] fors_prepare 
         | [46] fors 105 
         | [59] exec_stmt_begin 
         | [80] exec_stmt_treebased  
         | [93] exec_stmt_end 
         | [106] exec_stmt_begin 
         | [127] iconst3 
         | [128] storen 9 
         | [133] exec_stmt_end 
         | [146] goto -100 
         | [151] exec_stmt_end 
         | [164] exec_stmt_begin 
         | [185] exec_stmt_end 
         | [198] return0 5 
         | 

gaussdb=> 

测试下来其实是支持的

sql 复制代码
gaussdb=> create procedure p11 is
gaussdb$> type t_rec is record(a int,b int);
gaussdb$> v t_rec;
gaussdb$> begin
gaussdb$> v.a:=1;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p11();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33068.
LOG:  [ByteCode] Function: p11(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] iconst1 
[22] storen 10 
[27] exec_stmt_end 
[40] exec_stmt_begin 
[61] exec_stmt_end 
[74] return0 5 

LOG:  Start ByteCode!
-[ RECORD 1 ]
p11 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('p11'::regproc);
-[ RECORD 1 ]-------------------
bytecode | [0] exec_stmt_begin 
         | [21] iconst1 
         | [22] storen 10 
         | [27] exec_stmt_end 
         | [40] exec_stmt_begin 
         | [61] exec_stmt_end 
         | [74] return0 5 
         | 

gaussdb=> 

这种也支持

至于文档里说的那个例子,本身就是个错的,没有定义record的结构,c1列是哪里来的?

  • 不支持PACKAGE中RECORD变量的读取和复制。
    同上,没必要单独强调package,这里还有错别字,"复制"应该是"赋值"
sql 复制代码
gaussdb=> create or replace package pkg11 is
gaussdb$> type t_rec is record(a int,b int);
gaussdb$> procedure p11 ;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE
gaussdb=> create or replace package body pkg11 is
gaussdb$> procedure p11 is
gaussdb$> v t_rec;
gaussdb$> begin
gaussdb$> v.a:=1;
gaussdb$> raise notice '%',v.a;
gaussdb$> end;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE BODY
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call pkg11.p11();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33073.
LOG:  [ByteCode] Function: p11(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] iconst1 
[22] storen 11 
[27] exec_stmt_end 
[40] exec_stmt_begin 
[61] exec_stmt_treebased  
[74] exec_stmt_end 
[87] exec_stmt_begin 
[108] exec_stmt_end 
[121] return0 5 

LOG:  Start ByteCode!
NOTICE:  1
-[ RECORD 1 ]
p11 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('pkg11.p11'::regproc);
-[ RECORD 1 ]------------------------
bytecode | [0] exec_stmt_begin 
         | [21] iconst1 
         | [22] storen 11 
         | [27] exec_stmt_end 
         | [40] exec_stmt_begin 
         | [61] exec_stmt_treebased  
         | [74] exec_stmt_end 
         | [87] exec_stmt_begin 
         | [108] exec_stmt_end 
         | [121] return0 5 
         | 

gaussdb=> 

也是支持的

  • 不支持REFCURSOR类型的出入参转换为其他类型(例如:REFCURSOR转换为VARCHAR2,或进行拼接运算操作等)。
    游标类型的参数强转没什么意义 一个 "" 的字符串而已
sql 复制代码
gaussdb=> create or replace package pkg12 is
gaussdb$> procedure p1(o out sys_refcursor);
gaussdb$> procedure p2;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE
gaussdb=> create or replace package body pkg12 is
gaussdb$> procedure p1(o out sys_refcursor) is
gaussdb$> begin
gaussdb$> open o for select 1 a,2 b from dual;
gaussdb$> raise notice '%',o::text;
gaussdb$> end;
gaussdb$> procedure p2 is
gaussdb$> cr sys_refcursor;
gaussdb$> begin
gaussdb$> p1(cr);
gaussdb$> raise notice '%','aaaa'||cr::text;
gaussdb$> end;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE BODY
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call pkg12.p2();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33079.
LOG:  [ByteCode] Function: p2(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] procedure expression expr: CALL p1(cr) 
[58] nop_pop 
[59] exec_stmt_end 
[72] exec_stmt_begin 
[93] exec_stmt_treebased  
[106] exec_stmt_end 
[119] exec_stmt_begin 
[140] exec_stmt_end 
[153] return0 5 

LOG:  Start ByteCode!
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33078.
CONTEXT:  PL/pgSQL function p2() line 10 at SQL statement
LOG:  [ByteCode] Function: p1(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] exec_stmt_treebased_open  
[34] exec_stmt_end 
[47] exec_stmt_begin 
[68] exec_stmt_treebased  
[81] exec_stmt_end 
[94] exec_stmt_begin 
[115] loadn_return_cursor 0 
[120] transfer 
[125] exec_stmt_end 
[138] return 5 

CONTEXT:  PL/pgSQL function p2() line 10 at SQL statement
LOG:  [ByteCode] Function: CALL p1(cr), InterpreterBytecode:
[0] nop_push 
[1] invokemethod_definer func: p1 
[30] storen_copy_cursor 9 

CONTEXT:  PL/pgSQL function p2() line 10 at SQL statement
NOTICE:  <unnamed portal 9>
CONTEXT:  PL/pgSQL function p2() line 10 at SQL statement
NOTICE:  aaaa<unnamed portal 9>
-[ RECORD 1 ]
p2 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('pkg12.p2'::regproc);
-[ RECORD 1 ]------------------------------------------
bytecode | [0] exec_stmt_begin 
         | [21] procedure expression expr: CALL p1(cr) 
         | [58] nop_pop 
         | [59] exec_stmt_end 
         | [72] exec_stmt_begin 
         | [93] exec_stmt_treebased  
         | [106] exec_stmt_end 
         | [119] exec_stmt_begin 
         | [140] exec_stmt_end 
         | [153] return0 5 
         | 

gaussdb=> select bytecode from dump_plsql_bytecode('pkg12.p1'::regproc);
-[ RECORD 1 ]-----------------------------
bytecode | [0] exec_stmt_begin 
         | [21] exec_stmt_treebased_open  
         | [34] exec_stmt_end 
         | [47] exec_stmt_begin 
         | [68] exec_stmt_treebased  
         | [81] exec_stmt_end 
         | [94] exec_stmt_begin 
         | [115] loadn_return_cursor 0 
         | [120] transfer 
         | [125] exec_stmt_end 
         | [138] return 5 
         | 

gaussdb=> 

不过这么测下来,竟然是支持的。

  • 不支持伪类型(具体请参见伪类型)作为函数或存储过程出入参。
名称 描述
any 表示函数接受任何输入数据类型。
anyelement 表示函数接受任何数据类型。
anyarray 表示函数接受任意数组数据类型。
anynonarray 表示函数接受任意非数组数据类型。
anyenum 表示函数接受任意枚举数据类型。
anyrange 表示函数接受任意范围数据类型。
cstring 表示函数接受或者返回一个空结尾的C字符串。
internal 表示函数接受或者返回一种服务器内部的数据类型。
language_handler 声明一个过程语言调用句柄返回language_handler。
fdw_handler 声明一个外部数据封装器返回fdw_handler。
record 标识函数返回一个未声明的行类型。
trigger 声明一个触发器函数返回trigger。
void 表示函数不返回值。
opaque 一个已经过时的类型,以前用于所有上面这些用途。

ORACLE里也没这些东西,直接迁移过来的不会用,但是自己写一些通用工具函数时要注意了。

sql 复制代码
gaussdb=> create or replace function f12(anyelement) return text as
gaussdb$> begin 
gaussdb$> return $1::text;
gaussdb$> end;
gaussdb$> /
CREATE FUNCTION
gaussdb=> set client_min_messages = log;
SET
gaussdb=> select f12(1);
LOG:  [ByteCode] BC070 Bytecode does not support parameter with pseudo type.
CONTEXT:  referenced column: f12
LOG:  [ByteCode] BC039 This function doesn't support bytecode, func_oid: 33080.
CONTEXT:  referenced column: f12
-[ RECORD 1 ]
f12 | 1

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('f12'::regproc);
-[ RECORD 1 ]-----------
bytecode | Not supported

gaussdb=> 
  • 不支持循环游标语句使用跨PACKAGE的CURSOR变量。
sql 复制代码
gaussdb=> create package  pkg13 is
gaussdb$> cursor c is select 1 a,2 b from dual;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE
gaussdb=> create package pkg14 is
gaussdb$> procedure p ;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE
gaussdb=> create or replace package body pkg14 is
gaussdb$> procedure p is
gaussdb$> r pkg13.c%rowtype;
gaussdb$> begin
gaussdb$> open pkg13.c;
gaussdb$> loop 
gaussdb$> if pkg13.c%notfound then exit;
gaussdb$> end if;
gaussdb$> fetch pkg13.c into r;
gaussdb$> raise notice '%',r;
gaussdb$> end loop;
gaussdb$> close pkg13.c;
gaussdb$> end;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE BODY
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call pkg14.p();
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33086.
LOG:  [ByteCode] Function: p(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] exec_stmt_treebased_open  
[34] exec_stmt_end 
[47] exec_stmt_begin 
[68] loopwhile 
[73] exec_stmt_begin 
[94] loadn_pkg_cursor_attributes 12 
[103] if_or_when 49 
[108] exec_stmt_begin 
[129] exec_stmt_end 
[142] goto 122 
[147] goto 5 
[152] exec_stmt_end 
[165] exec_stmt_begin 
[186] exec_stmt_treebased_fetch  
[199] exec_stmt_end 
[212] exec_stmt_begin 
[233] exec_stmt_treebased  
[246] exec_stmt_end 
[259] goto -191 
[264] exec_stmt_end 
[277] exec_stmt_begin 
[298] exec_stmt_treebased_close  
[311] exec_stmt_end 
[324] exec_stmt_begin 
[345] exec_stmt_end 
[358] return0 5 

LOG:  Start ByteCode!
NOTICE:  (1,2)
NOTICE:  (1,2)
-[ RECORD 1 ]
p | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('pkg14.p'::regproc);
-[ RECORD 1 ]----------------------------------
bytecode | [0] exec_stmt_begin 
         | [21] exec_stmt_treebased_open  
         | [34] exec_stmt_end 
         | [47] exec_stmt_begin 
         | [68] loopwhile 
         | [73] exec_stmt_begin 
         | [94] loadn_pkg_cursor_attributes 12 
         | [103] if_or_when 49 
         | [108] exec_stmt_begin 
         | [129] exec_stmt_end 
         | [142] goto 122 
         | [147] goto 5 
         | [152] exec_stmt_end 
         | [165] exec_stmt_begin 
         | [186] exec_stmt_treebased_fetch  
         | [199] exec_stmt_end 
         | [212] exec_stmt_begin 
         | [233] exec_stmt_treebased  
         | [246] exec_stmt_end 
         | [259] goto -191 
         | [264] exec_stmt_end 
         | [277] exec_stmt_begin 
         | [298] exec_stmt_treebased_close  
         | [311] exec_stmt_end 
         | [324] exec_stmt_begin 
         | [345] exec_stmt_end 
         | [358] return0 5 
         | 

gaussdb=> 

实测其实是支持的

  • 不支持包含对入参进行赋值的存储过程或函数。
    在ORACLE里,入参本身就不允许赋值,GaussDB没做强控制
sql 复制代码
gaussdb=> create procedure p15( a int) is 
gaussdb$> begin
gaussdb$> a:=1;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p15(1);
LOG:  [ByteCode] BC066 in-param can't be changed.
LOG:  [ByteCode] BC039 This function doesn't support bytecode, func_oid: 33087.
-[ RECORD 1 ]
p15 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('p15'::regproc);
-[ RECORD 1 ]-----------
bytecode | Not supported

这种不合规用法的确会导致该函数整个无法使用字节码

  • 不支持BULK COLLECT语句。
sql 复制代码
gaussdb=> CREATE TABLE customers(id int,name varchar);
CREATE TABLE
gaussdb=> INSERT INTO customers VALUES(1,'ab');
INSERT 0 1
gaussdb=> create procedure p16 is
gaussdb$> type id_list is varray(6) of customers.id%type;
gaussdb$> id_arr id_list;
gaussdb$> begin
gaussdb$> select id bulk collect into id_arr from customers;
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p16();
LOG:  [Bytecode] BC077 bulk collect does not support.
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33093.
LOG:  [ByteCode] Function: p16(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] exec_stmt_treebased  
[34] exec_stmt_end 
[47] exec_stmt_begin 
[68] exec_stmt_end 
[81] return0 5 

LOG:  Start ByteCode!
-[ RECORD 1 ]
p16 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('p16'::regproc);
-[ RECORD 1 ]------------------------
bytecode | [0] exec_stmt_begin 
         | [21] exec_stmt_treebased  
         | [34] exec_stmt_end 
         | [47] exec_stmt_begin 
         | [68] exec_stmt_end 
         | [81] return0 5 
         | 

gaussdb=> 

的确不支持,但是没有导致这个存储过程不支持字节码,这是个好消息

  • 不支持FORALL批量查询语句带有SAVE EXCEPTIONS。
sql 复制代码
gaussdb=> CREATE TABLE hdfs_t1 (
gaussdb(>   title NUMBER(6),
gaussdb(>   did VARCHAR2(20),
gaussdb(>   data_period VARCHAR2(25),
gaussdb(>   kind VARCHAR2(25),
gaussdb(>   interval VARCHAR2(20),
gaussdb(>   time DATE,
gaussdb(>   isModified VARCHAR2(10)
gaussdb(> );
CREATE TABLE
gaussdb=> INSERT INTO hdfs_t1 VALUES( 8, 'Donald', 'OConnell', 'DOCONNEL', '650.507.9833', to_date('21-06-1999', 'dd-mm-yyyy'), 'SH_CLERK' );
INSERT 0 1
gaussdb=> CREATE OR REPLACE PROCEDURE proc_forall()
gaussdb-> AS 
gaussdb$> BEGIN 
gaussdb$> FORALL i IN 100..120 save exceptions
gaussdb$> update hdfs_t1 set title = title + 100*i;
gaussdb$> END; 
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> CALL proc_forall();
LOG:  [ByteCode] BC027 Stmtfori is not support save_exceptions, plsql: FORALL i IN 100..120 save exceptions.
LOG:  [ByteCode] BC030 Stmt FOR with integer loop variable does not support with some error, lineno: 3.
LOG:  [ByteCode] BC039 This function doesn't support bytecode, func_oid: 33098.
-[ RECORD 1 ]-
proc_forall | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('proc_forall'::regproc);
-[ RECORD 1 ]-----------
bytecode | Not supported

gaussdb=> 

的确不支持,不过这个用得少

  • 不支持函数或存储过程的参数默认值为PACKAGE变量。
sql 复制代码
gaussdb=> create or replace package test_pkg is 
gaussdb$> xx int:=10000;
gaussdb$> PROCEDURE bc_loop2(i int default xx);
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE
gaussdb=> create or replace package body test_pkg is 
gaussdb$> PROCEDURE bc_loop2(i int default xx) is
gaussdb$> L_COUNT NUMBER:=0;
gaussdb$> BEGIN
gaussdb$>   LOOP
gaussdb$>     IF L_COUNT > i THEN
gaussdb$>       RAISE INFO 'count is %',L_COUNT;
gaussdb$>       EXIT;
gaussdb$>     END IF;
gaussdb$>    L_COUNT:=L_COUNT+1;
gaussdb$>   END LOOP;
gaussdb$> END;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE BODY
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call test_pkg.bc_loop2(20);
LOG:  [ByteCode] BC007 bytecode doesn't support parameters with package default value.
LOG:  [ByteCode] BC019 proc 7752 isn't pllanguage.
LOG:  [ByteCode] BC019 proc 1724 isn't pllanguage.
LOG:  [ByteCode] BC039 This function doesn't support bytecode, func_oid: 33100.
INFO:  count is 21
-[ RECORD 1 ]
bc_loop2 | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('test_pkg.bc_loop2'::regproc);
-[ RECORD 1 ]-----------
bytecode | Not supported

gaussdb=> 

这种用得还挺多,只要用了就整个存储过程不支持了。

  • 不支持存储过程或函数OUT出参具有多个列或带有数组下标的复杂变量(如:type arrayInt is varray(16) of int; val arrayInt; val(1) = 1;)
    可能是指out出参不能为复合类型或者数组类型?
sql 复制代码
gaussdb=> create type ty_test3 as (a int,b int);
CREATE TYPE
gaussdb=> create type tyt_test3 is table of ty_test3;
CREATE TYPE
gaussdb=> create type tyt_test4 is table of ty_test3 index by binary_integer ;
ERROR:  Creation outside PL/SQL is not supported.
gaussdb=> create type tyt_test5 is varray(16) of int;
ERROR:  syntax error at or near "varray"
LINE 1: create type tyt_test5 is varray(16) of int;
                                 ^
gaussdb=> 

后两种类型不能单独创建

sql 复制代码
gaussdb=> create or replace procedure p17( o out ty_test3) is
gaussdb$> begin
gaussdb$> o:=ty_test3();
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p17(null);
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33118.
LOG:  [ByteCode] Function: p17(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] eval_rowexpr  
[30] store_row  
[47] storen 0 
[52] storen 1 
[57] exec_stmt_end 
[70] exec_stmt_begin 
[91] loadn 0 
[96] loadn 1 
[101] eval_rowexpr  
[110] transfer 
[115] exec_stmt_end 
[128] return 5 

LOG:  Start ByteCode!
-[ RECORD 1 ]
a | 
b | 

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('p17'::regproc);
-[ RECORD 1 ]-------------------
bytecode | [0] exec_stmt_begin 
         | [21] eval_rowexpr  
         | [30] store_row  
         | [47] storen 0 
         | [52] storen 1 
         | [57] exec_stmt_end 
         | [70] exec_stmt_begin 
         | [91] loadn 0 
         | [96] loadn 1 
         | [101] eval_rowexpr  
         | [110] transfer 
         | [115] exec_stmt_end 
         | [128] return 5 
         | 

gaussdb=> 

这个是支持的

sql 复制代码
gaussdb=> create or replace procedure p18( o out tyt_test3,o2 out ty_test3) is
gaussdb$> begin
gaussdb$> o:=tyt_test3();
gaussdb$> o.extend;
gaussdb$> o(1):=ty_test3(1,2);
gaussdb$> o2:=o(1);
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p18(null,null);
LOG:  [ByteCode] BC019 proc 6149 isn't pllanguage.
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33119.
LOG:  [ByteCode] Function: p18(), InterpreterBytecode:
[0] exec_stmt_begin 
[21] create_nesttable tyt_test3 0 
[30] storen_nesttable 0 
[43] exec_stmt_end 
[56] exec_stmt_begin 
[77] loadn_expand 0 
[82] iconst1 
[83] function func: nesttable_extend 
[96] storen_nesttable 0 
[109] exec_stmt_end 
[122] exec_stmt_begin 
[143] iconst1 
[144] iconst2 
[145] eval_rowexpr  
[154] expand_and_load_table 0 
[159] iconst1 
[160] store_nesttable_elem 2249 -1 
[169] exec_stmt_end 
[182] exec_stmt_begin 
[203] loadn_expand 0 
[208] iconst1 
[209] tableofelem 33117 
[214] store_row  
[231] storen 1 
[236] storen 2 
[241] exec_stmt_end 
[254] exec_stmt_begin 
[275] loadn_expand 0 
[280] loadn 1 
[285] loadn 2 
[290] eval_rowexpr  
[299] eval_rowexpr  
[308] transfer 
[313] exec_stmt_end 
[326] return 5 

LOG:  Start ByteCode!
-[ RECORD 1 ]-
o  | {"(1,2)"}
o2 | (1,2)

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('p18'::regproc);
-[ RECORD 1 ]-----------------------------------
bytecode | [0] exec_stmt_begin 
         | [21] create_nesttable tyt_test3 0 
         | [30] storen_nesttable 0 
         | [43] exec_stmt_end 
         | [56] exec_stmt_begin 
         | [77] loadn_expand 0 
         | [82] iconst1 
         | [83] function func: nesttable_extend 
         | [96] storen_nesttable 0 
         | [109] exec_stmt_end 
         | [122] exec_stmt_begin 
         | [143] iconst1 
         | [144] iconst2 
         | [145] eval_rowexpr  
         | [154] expand_and_load_table 0 
         | [159] iconst1 
         | [160] store_nesttable_elem 2249 -1 
         | [169] exec_stmt_end 
         | [182] exec_stmt_begin 
         | [203] loadn_expand 0 
         | [208] iconst1 
         | [209] tableofelem 33117 
         | [214] store_row  
         | [231] storen 1 
         | [236] storen 2 
         | [241] exec_stmt_end 
         | [254] exec_stmt_begin 
         | [275] loadn_expand 0 
         | [280] loadn 1 
         | [285] loadn 2 
         | [290] eval_rowexpr  
         | [299] eval_rowexpr  
         | [308] transfer 
         | [313] exec_stmt_end 
         | [326] return 5 
         | 

gaussdb=> 

也是支持的

sql 复制代码
gaussdb=> create package pkg19 is
gaussdb$>  type tyt_test4 is table of ty_test3 index by binary_integer ;
gaussdb$>  type tyt_test5 is varray(16) of int;
gaussdb$> procedure p(o1 out tyt_test4 ,o2 out tyt_test5);
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE
gaussdb=> create or replace package body pkg19 is
gaussdb$> procedure p(o1 out tyt_test4 ,o2 out tyt_test5) is
gaussdb$> i int:=1;
gaussdb$> begin
gaussdb$> o1(i):=ty_test3(1,2);
gaussdb$> o2:=tyt_test5();
gaussdb$> o2.extend;
gaussdb$> o2(i):=1;
gaussdb$> end;
gaussdb$> end;
gaussdb$> /
CREATE PACKAGE BODY
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call pkg19.p(null,null);
LOG:  [ByteCode] BC019 proc 6014 isn't pllanguage.
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33134.
LOG:  [ByteCode] Function: p(), InterpreterBytecode:
[0] create_tableofindex pkg19.tyt_test4 integer 0 
[13] storen_tableofindex 2 
[26] iconst1 
[27] storen 14 
[32] exec_stmt_begin 
[53] iconst1 
[54] iconst2 
[55] eval_rowexpr  
[64] expand_and_load_table 2 
[69] loadn 14 
[74] store_tableofindex_elem 2249 -1 
[83] exec_stmt_end 
[96] exec_stmt_begin 
[117] const64 
[126] storen_array 3 integer[] -1 
[139] exec_stmt_end 
[152] exec_stmt_begin 
[173] loadn_expand 3 
[178] iconst1 
[179] function func: array_extendnull 
[192] storen_array 3 integer[] -1 
[205] exec_stmt_end 
[218] exec_stmt_begin 
[239] iconst1 
[240] op_check_and_load_array integer[] -1 3 
[253] loadn 14 
[258] store_array_elem integer -1 1 
[271] exec_stmt_end 
[284] exec_stmt_begin 
[305] loadn_expand 2 
[310] loadn_expand 3 
[315] eval_rowexpr  
[324] transfer 
[329] exec_stmt_end 
[342] return 5 

LOG:  Start ByteCode!
-[ RECORD 1 ]--------------------
o1 | {indexbyType:int,1=>"(1,2)"}
o2 | {1}

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('pkg19.p'::regproc);
-[ RECORD 1 ]------------------------------------------------
bytecode | [0] create_tableofindex pkg19.tyt_test4 integer 0 
         | [13] storen_tableofindex 2 
         | [26] iconst1 
         | [27] storen 14 
         | [32] exec_stmt_begin 
         | [53] iconst1 
         | [54] iconst2 
         | [55] eval_rowexpr  
         | [64] expand_and_load_table 2 
         | [69] loadn 14 
         | [74] store_tableofindex_elem 2249 -1 
         | [83] exec_stmt_end 
         | [96] exec_stmt_begin 
         | [117] const64 
         | [126] storen_array 3 integer[] -1 
         | [139] exec_stmt_end 
         | [152] exec_stmt_begin 
         | [173] loadn_expand 3 
         | [178] iconst1 
         | [179] function func: array_extendnull 
         | [192] storen_array 3 integer[] -1 
         | [205] exec_stmt_end 
         | [218] exec_stmt_begin 
         | [239] iconst1 
         | [240] op_check_and_load_array integer[] -1 3 
         | [253] loadn 14 
         | [258] store_array_elem integer -1 1 
         | [271] exec_stmt_end 
         | [284] exec_stmt_begin 
         | [305] loadn_expand 2 
         | [310] loadn_expand 3 
         | [315] eval_rowexpr  
         | [324] transfer 
         | [329] exec_stmt_end 
         | [342] return 5 
         | 

gaussdb=> 

也是支持的,没测出不支持的场景

  • 对于存储过程或函数INOUT参数,仅不包含运算的单一参数类型变量支持字节码框架。
    可能是指inout参数不能被赋值
sql 复制代码
gaussdb=> create procedure p20(io1 inout int,io2 inout varchar2) is
gaussdb$> begin
gaussdb$> io1:=1;
gaussdb$> io1:=io1+1;
gaussdb$> io2:='a';
gaussdb$> io2:=io2||'a';
gaussdb$> end;
gaussdb$> /
CREATE PROCEDURE
gaussdb=> set client_min_messages = log;
SET
gaussdb=> call p20(null,null);
LOG:  [ByteCode] BC019 proc 177 isn't pllanguage.
LOG:  [ByteCode] BC019 proc 1258 isn't pllanguage.
LOG:  [ByteCode] BC040 This function supports bytecode, func_oid: 33135.
LOG:  [ByteCode] Function: p20(integer,character varying), InterpreterBytecode:
[0] exec_stmt_begin 
[21] iconst1 
[22] storen 0 
[27] exec_stmt_end 
[40] exec_stmt_begin 
[61] loadn 0 
[66] iconst1 
[67] function func: int4pl 
[80] storen 0 
[85] exec_stmt_end 
[98] exec_stmt_begin 
[119] const64 
[128] storen_outparam 1043 1
[137] exec_stmt_end 
[150] exec_stmt_begin 
[171] loadn 1 
[176] const64 
[185] function func: textcat 
[198] storen_outparam 1043 1
[207] exec_stmt_end 
[220] exec_stmt_begin 
[241] loadn 0 
[246] loadn 1 
[251] eval_rowexpr  
[260] transfer 
[265] exec_stmt_end 
[278] return 5 

LOG:  Start ByteCode!
-[ RECORD 1 ]
io1 | 2
io2 | aa

gaussdb=> reset client_min_messages;
RESET
gaussdb=> select bytecode from dump_plsql_bytecode('p20'::regproc);
-[ RECORD 1 ]---------------------------
bytecode | [0] exec_stmt_begin 
         | [21] iconst1 
         | [22] storen 0 
         | [27] exec_stmt_end 
         | [40] exec_stmt_begin 
         | [61] loadn 0 
         | [66] iconst1 
         | [67] function func: int4pl 
         | [80] storen 0 
         | [85] exec_stmt_end 
         | [98] exec_stmt_begin 
         | [119] const64 
         | [128] storen_outparam 1043 1
         | [137] exec_stmt_end 
         | [150] exec_stmt_begin 
         | [171] loadn 1 
         | [176] const64 
         | [185] function func: textcat 
         | [198] storen_outparam 1043 1
         | [207] exec_stmt_end 
         | [220] exec_stmt_begin 
         | [241] loadn 0 
         | [246] loadn 1 
         | [251] eval_rowexpr  
         | [260] transfer 
         | [265] exec_stmt_end 
         | [278] return 5 
         | 

gaussdb=> 

也支持

非常规分析

官方文档描述有限,估计有些不支持的场景都没试出来。

观察字节码模块的日志,可以得出一个规律,字节码的日志都带了[ByteCode],所以可以尝试在二进制里搜索所有有关的日志。

strings gaussdb |grep "\[ByteCode\]"

复制代码
[ByteCode] Function: %s, InterpreterBytecode:
[ByteCode] BC017 can't find valid proc %u.
[ByteCode] BC018 can't find valid languageTuple.
[ByteCode] BC019 proc %u isn't pllanguage.
[ByteCode] BC070 Bytecode does not support parameter with pseudo type.
[ByteCode] BC013 The bytecode does not allow parameters except in & out.
[ByteCode] BC073 Bytecode is invalid, because the expr in Function: %s (func oid: %u) is changed to complex expr.Expr: %s
[ByteCode] BC071 Bytecode is invalid, because the type of expr in Function: %s (func oid: %u) is changed.
[ByteCode] BC076 occurs error: %s during bytecode processExpr
[ByteCode] BC072 Expression: %s is degenerated.
[ByteCode] BC065 assign outparam Failed
[ByteCode] outparam only supports var type & row type.
[ByteCode] BC079 func %u doesn't support bytecode because of permission error.
[ByteCode] BC064 Statements that ignore output parameters contain output parameters
[ByteCode] BC020 This expr type %d does not support.
[ByteCode] BC022 Param kind is PARAM_EXTERN.
[ByteCode] BC055 function(%u) with outparam called in simple expr does not support.
[ByteCode] BC023 FieldSelect input expression is null or fieldnum less 1.
[ByteCode] BC025 MinMaxExpr op is invalid.
[ByteCode] BC045 This xml type is not support, xml type: %d.
[ByteCode] BC024 CompositeExpr node has incorrect type.
[ByteCode] BC032 bytecode row type param includes column except var & row.
[ByteCode] BC036 bytecode does not support to cast subtype.
[ByteCode] BC037 bytecode does not support to cast tableof type.
[ByteCode] BC038 Typecast hashentry is NULL, valtype: %u, valtypmod: %d, reqtype: %u, reqtypmod: %d.
[ByteCode] BC052 bytecode only support independent statement.
[ByteCode] BC053 bytecode only support select statement.
[ByteCode] BC054 Simple expr check occurs exeception. Failed to eval simple expr.
[ByteCode] BC062 bytecode doesn't support query returning more row fields than the row variable has in loop stmt.
[ByteCode] BC066 in-param can't be changed.
[ByteCode] BC074 This function can not supports bytecode, func_oid: %u.Please check the GUC parameter behavior_compat_flags.
[ByteCode] BC002 bytecode doesn't support during package instantiation.
[ByteCode] BC067 bytecode doesn't support system functions.
[ByteCode] BC001 only support bytecode in A_FORMAT.
[ByteCode] BC003 bytecode doesn't support trigger func.
[ByteCode] BC004 bytecode doesn't support func which returns set.
[ByteCode] BC056 bytecode doesn't support function with outparam                 when proc_outparam_override is off.
[ByteCode] BC057 bytecode doesn't support function with outparam return record.
[ByteCode] BC007 bytecode doesn't support parameters with package default value.
[ByteCode] BC008 exists invalid parameter type %d.
[ByteCode] BC039 This function doesn't support bytecode, func_oid: %u.
[ByteCode] BC068 bytecode neither support nest sub procedure/function nor subtype.
[ByteCode] BC016 occurs exception during bytecode processStatement
[ByteCode] BC031 proc exists in unsupported namespace, it's in %s.
[ByteCode] BC040 This function supports bytecode, func_oid: %u.
[ByteCode] BC048 Bytecode does not support invalid typeoid. typeoid is %u
[ByteCode] exit or continue stmt label not match.
[ByteCode] BC044 Node type is not A_Indices, node type: %d.
[ByteCode] BC042 Node type is A_Indices.
[ByteCode] BC043 Attname %s's num is invalid.
[ByteCode] BC078 stack size is unexpected.
[ByteCode] BC041 Node type is not A_Indices, node type: %d.
[ByteCode] BC046 Neither GSPLSQL_COLLECTION_ARAY nor GSPLSQL_COLLECTION_TABLE are not supported.
[ByteCode] BC047 This datumtype %d is not support in assigntarget.
[ByteCode] BC049 unknown assign target.
[ByteCode] BC033 non-scalar variables are not supported in get_diag statement.
[ByteCode] BC034 This diagnostic type %d does not support.
[ByteCode] BC075 Assignment and variable field do not match in execsql statement, sql is :%s
[ByteCode] BC061 not spport func with out param used in execsql statement, sql is :%s
[ByteCode] BC058 bytecode does not support funtion with out paramter don't have return value.
[ByteCode] BC059 bytecode does not support return var is not out param var.
[ByteCode] BC060 bytecode does not support procedure return a value.
[ByteCode] BC028 bytecode doesn't support tuple return.
[ByteCode] BC029 This stmt type %s does not support, lineno: %d.
[ByteCode] BC030 Stmt %s does not support with some error, lineno: %d.
[ByteCode] BC063 bytecode doesn't support diff pkg cursor in loop stmt.
[ByteCode] BC027 Stmtfori is not support save_exceptions, plsql: %s.

不过这里面并非所有的日志都是不支持的,有些正常输出的日志也在里面,而且无法区分像BC019那种局部不支持但存储过程整体支持的有哪些,甚至还有一些重复的,比如BC044和BC041,都是Node type is not A_Indices, node type: %d.A_Indices是数组的下标访问,是或不是会怎样?)。

另外,还有一部分不支持字节码的情况,在非字节码运行时也是不支持的,创建就报错了,正确的代码不会遇到。

但仅从二进制里捞出来的这些不支持日志的场景数量上来说,明显是比官方文档里的要多的,有些日志我也没测出对应的场景,所以不能仅从官方文档上去看,还是得使用实际的存储过程代码去测试,才能准确知道字节码的支持情况。

略微有点力竭,官方文档不完善,而且没有源码,面对字节码这样一个新功能,或者说新的执行框架,个人盲测无法穷尽所有场景。我暂时先把本次测试汇总成一个表格吧,究竟这个功能能不能在生产环境上使用,建议以华为官方口径为准。

日志 是否约束 对应文档 是否有命中日志 自测是否支持字节码 备注
BC001 only support bytecode in A_FORMAT. Y 只有ORACLE兼容模式支持
BC002 bytecode doesn't support during package instantiation. Y 不支持PACKAGE实例化。
BC003 bytecode doesn't support trigger func. Y 不支持TRIGGER Y N
BC004 bytecode doesn't support func which returns set. Y 不支持返回集合的函数 Y N
BC007 bytecode doesn't support parameters with package default value. Y 不支持函数或存储过程的参数默认值为PACKAGE变量 Y N
BC008 exists invalid parameter type %d. Y 存在无效的参数类型
BC013 The bytecode does not allow parameters except in & out. Y Y N 不允许in和out之外的参数,RETURNS TABLE时会报
BC016 occurs exception during bytecode processStatement Y 处理语句时遇到错误
BC017 can't find valid proc %u. Y 不能发现有效的proc
BC018 can't find valid languageTuple. Y 不能发现有效的语言元组
BC019 proc %u isn't pllanguage. Y Y proc不是pl语言
BC020 This expr type %d does not support. Y 这种表达式类型不支持
BC022 Param kind is PARAM_EXTERN. 参数类型是PARAM_EXTERN
BC023 FieldSelect input expression is null or fieldnum less 1. Y FieldSelect输入表达式是空或者fieldnum小于1
BC024 CompositeExpr node has incorrect type. Y 复合类型表达式节点有不正确的类型
BC025 MinMaxExpr op is invalid. Y MinMaxExpr操作无效
BC027 Stmtfori is not support save_exceptions, plsql: %s. Y 不支持FORALL批量查询语句带有SAVE EXCEPTIONS Y N
BC028 bytecode doesn't support tuple return. Y 不支持返回行
BC029 This stmt type %s does not support, lineno: %d. Y 特定的语句类型不支持
BC030 Stmt %s does not support with some error, lineno: %d. Y Y N 由于一些错误,语句XXX不支持
BC031 proc exists in unsupported namespace, it's in %s. Y 不支持高级包以及系统函数。
BC032 bytecode row type param includes column except var & row. Y 行类型参数含有不是var和row的列
BC033 non-scalar variables are not supported in get_diag statement. Y 非标量变量不支持在get_diag语句里
BC034 This diagnostic type %d does not support. Y 这个诊断类型不支持
BC036 bytecode does not support to cast subtype. Y 不支持转换subtype
BC037 bytecode does not support to cast tableof type. Y 不支持转换tableof类型
BC038 Typecast hashentry is NULL, valtype: %u, valtypmod: %d, reqtype: %u, reqtypmod: %d. Y 类型转换hashentry是null
BC039 This function doesn't support bytecode, func_oid: %u. Y N 首次执行,该函数不支持字节码时会输出此日志
BC040 This function supports bytecode, func_oid: %u. 首次执行,该函数支持字节码时会输出此日志
BC041 Node type is not A_Indices, node type: %d. 不是数组下标节点
BC042 Node type is A_Indices. ? 是数组下标节点
BC043 Attname %s's num is invalid. 列名的列号是无效的
BC044 Node type is not A_Indices, node type: %d. ? 不是数组下标节点
BC045 This xml type is not support, xml type: %d. Y 这种xml类型不支持
BC046 Neither GSPLSQL_COLLECTION_ARAY nor GSPLSQL_COLLECTION_TABLE are not supported. Y 集合数组和集合表都不支持
BC047 This datumtype %d is not support in assigntarget. Y 这个datumtype不支持用于赋值目标
BC048 Bytecode does not support invalid typeoid. typeoid is %u Y 不支持无效的类型oid
BC049 unknown assign target. 未知的赋值目标
BC052 bytecode only support independent statement. Y 只支持独立语句
BC053 bytecode only support select statement. Y 只支持select语句
BC054 Simple expr check occurs exeception. Failed to eval simple expr. Y 简单表达式遇到错误,计算简单表达式失败
BC055 function(%u) with outparam called in simple expr does not support. Y 被简单表达式调用的带出参的函数不支持
BC056 bytecode doesn't support function with outparam when proc_outparam_override is off. Y 该特性仅在兼容性参数behavior_compat_options设置中包含compat_cursor、allow_procedure_compile_check、proc_outparam_override、dynamic_sql_compat、proc_outparam_transfer_length以及varray_compat参数选项时,支持执行字节码 O兼容一般都会打开proc_outparam_override
BC057 bytecode doesn't support function with outparam return record. Y 不支持RETURN复合类型的带有出参的FUNCTION Y N
BC058 bytecode does not support funtion with out paramter don't have return value. Y 函数没有返回值
BC059 bytecode does not support return var is not out param var. Y 函数不支持返回值不是出参
BC060 bytecode does not support procedure return a value. Y 不支持PROCEDURE显式指定RETURN值
BC061 not spport func with out param used in execsql statement, sql is :%s 执行SQL里不支持使用带出参的函数
BC062 bytecode doesn't support query returning more row fields than the row variable has in loop stmt. Y 不支持游标循环语句SELECT返回的列数与语句中的游标变量列数不一致。 Y
BC063 bytecode doesn't support diff pkg cursor in loop stmt. Y 不支持循环游标语句使用跨PACKAGE的CURSOR变量 Y
BC064 Statements that ignore output parameters contain output parameters Y 忽略了出参的语句包含有出参
BC065 assign outparam Failed Y 赋值出参失败
BC066 in-param can't be changed. Y 不支持包含对入参进行赋值的存储过程或函数 Y N
BC067 bytecode doesn't support system functions. Y 不支持高级包以及系统函数
BC068 bytecode neither support nest sub procedure/function nor subtype. Y 不支持子程序。 Y N
BC070 Bytecode does not support parameter with pseudo type. Y 不支持伪类型(具体请参见伪类型)作为函数或存储过程出入参。 Y N
BC071 Bytecode is invalid, because the type of expr in Function: %s (func oid: %u) is changed. Y 函数中表达式的类型被改成
BC072 Expression: %s is degenerated. ? Y 表达式被退化 (自治事务会出现)
BC073 Bytecode is invalid, because the expr in Function: %s (func oid: %u) is changed to complex expr.Expr: %s Y 函数中的表达式被改变成复杂表达式
BC074 This function can not supports bytecode, func_oid: %u.Please check the GUC parameter behavior_compat_flags. Y 该特性仅在兼容性参数behavior_compat_options设置中包含compat_cursor、allow_procedure_compile_check、proc_outparam_override、dynamic_sql_compat、proc_outparam_transfer_length以及varray_compat参数选项时,支持执行字节码 O兼容这些一般都要打开
BC075 Assignment and variable field do not match in execsql statement, sql is :%s 执行SQL的赋值和变量个数不匹配
BC076 occurs error: %s during bytecode processExpr Y 处理表达式遇到错误
BC078 stack size is unexpected. 栈大小非预期
BC079 func %u doesn't support bytecode because of permission error. Y 权限错误
exit or continue stmt label not match. Y exit 或 continue 后面的语句标签在前面找不到
Function: %s, InterpreterBytecode: Y Y 在这一行日志下开始输出字节码序列
outparam only supports var type & row type. Y 出参只支持var类型和row类型

关于这个字节码特性,我写了两篇了,后续我打算把这两篇内容喂给AI,让AI继续写第三篇。

未完待续~


相关推荐
DarkAthena2 天前
【GaussDB】分析一个使用子查询进行update导致的coredump
gaussdb
hh真是个慢性子13 天前
GaussDB Inside 2.23.01.280 集中式一主一备安装
数据库·database·gaussdb·国产数据库·高斯
Gauss松鼠会19 天前
【GaussDB】GaussDB性能调优分析思路
java·前端·数据库·经验分享·算法·gaussdb
不剪发的Tony老师1 个月前
国产数据库之GaussDB:固若金汤
数据库·gaussdb
DarkAthena1 个月前
【GaussDB】分析GaussDB在coredump后,部分应用连接假死的问题
gaussdb
Gauss松鼠会1 个月前
【GaussDB】GaussDB重要通信参数汇总
服务器·网络·数据库·sql·性能优化·gaussdb·经验总结
Gauss松鼠会1 个月前
【GaussDB】GaussDB SMP特性调优详解
java·服务器·前端·数据库·sql·算法·gaussdb
纬领网络1 个月前
安装diff-gaussian-rasterization模块技巧方法
gaussdb·diff·rasterization
DarkAthena2 个月前
【GaussDB】会话里出现大量idle in transaction状态的问题排查
gaussdb