From 59a8cda049f39bdb770d69eb3acb3e3a57994c06 Mon Sep 17 00:00:00 2001 From: zhubin79 <18784715772@163.com> Date: Sat, 26 Oct 2024 14:12:52 +0800 Subject: [PATCH] =?UTF-8?q?gms=5Futility=E9=AB=98=E7=BA=A7=E5=8C=85?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0(PART1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GNUmakefile.in | 1 + build/script/aarch64_lite_list | 3 + build/script/aarch64_opengauss_list | 3 + build/script/loongarch64_lite_list | 3 + build/script/opengauss_release_list_mini | 3 + .../opengauss_release_list_ubuntu_single | 3 + build/script/x86_64_lite_list | 3 + build/script/x86_64_opengauss_list | 3 + contrib/CMakeLists.txt | 2 + contrib/Makefile | 1 + contrib/gms_utility/CMakeLists.txt | 21 + contrib/gms_utility/Makefile | 32 + contrib/gms_utility/data/dummy.txt | 1 + contrib/gms_utility/expected/gms_utility.out | 3315 +++++++++++++++++ contrib/gms_utility/gms_utility--1.0.sql | 309 ++ contrib/gms_utility/gms_utility.control | 5 + contrib/gms_utility/gms_utility.cpp | 1658 +++++++++ contrib/gms_utility/gms_utility.h | 115 + contrib/gms_utility/smartmatch.pl | 583 +++ contrib/gms_utility/sql/gms_utility.sql | 2411 ++++++++++++ src/common/backend/parser/parse_relation.cpp | 31 +- .../optimizer/commands/dropcmds.cpp | 1 + .../optimizer/commands/packagecmds.cpp | 2 +- src/include/parser/parse_relation.h | 1 + 24 files changed, 8504 insertions(+), 6 deletions(-) create mode 100644 contrib/gms_utility/CMakeLists.txt create mode 100644 contrib/gms_utility/Makefile create mode 100644 contrib/gms_utility/data/dummy.txt create mode 100644 contrib/gms_utility/expected/gms_utility.out create mode 100644 contrib/gms_utility/gms_utility--1.0.sql create mode 100644 contrib/gms_utility/gms_utility.control create mode 100644 contrib/gms_utility/gms_utility.cpp create mode 100644 contrib/gms_utility/gms_utility.h create mode 100644 contrib/gms_utility/smartmatch.pl create mode 100644 contrib/gms_utility/sql/gms_utility.sql diff --git a/GNUmakefile.in b/GNUmakefile.in index 075e9951f..ae841234a 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -105,6 +105,7 @@ install: @if test -d contrib/datavec; then $(MAKE) -C contrib/datavec clean; fi @if test -d contrib/datavec; then $(MAKE) -C contrib/datavec $@; fi @if test -d contrib/gms_compress; then $(MAKE) -C contrib/gms_compress $@; fi + @if test -d contrib/gms_utility; then $(MAKE) -C contrib/gms_utility $@; fi @if test -d contrib/gms_stats; then $(MAKE) -C contrib/gms_stats $@; fi @if test -d contrib/gms_tcp; then $(MAKE) -C contrib/gms_tcp $@; fi @if test -d contrib/gms_profiler; then $(MAKE) -C contrib/gms_profiler $@; fi diff --git a/build/script/aarch64_lite_list b/build/script/aarch64_lite_list index fd01590bc..1d1730bf8 100644 --- a/build/script/aarch64_lite_list +++ b/build/script/aarch64_lite_list @@ -63,6 +63,8 @@ ./share/postgresql/extension/hstore--1.0--1.1.sql ./share/postgresql/extension/log_fdw--1.0.sql ./share/postgresql/extension/log_fdw.control +./share/postgresql/extension/gms_utility--1.0.sql +./share/postgresql/extension/gms_utility.control ./share/postgresql/extension/gms_output--1.0.sql ./share/postgresql/extension/gms_output.control ./share/postgresql/extension/gms_stats--1.0.sql @@ -766,6 +768,7 @@ ./lib/postgresql/latin2_and_win1250.so ./lib/postgresql/euc2004_sjis2004.so ./lib/postgresql/pgoutput.so +./lib/postgresql/gms_utility.so ./lib/postgresql/gms_output.so ./lib/postgresql/gms_stats.so ./lib/postgresql/gms_profiler.so diff --git a/build/script/aarch64_opengauss_list b/build/script/aarch64_opengauss_list index 0c4ca97c4..90f057328 100644 --- a/build/script/aarch64_opengauss_list +++ b/build/script/aarch64_opengauss_list @@ -123,6 +123,8 @@ ./share/postgresql/extension/dblink.control ./share/postgresql/extension/gms_compress--1.0.sql ./share/postgresql/extension/gms_compress.control +./share/postgresql/extension/gms_utility--1.0.sql +./share/postgresql/extension/gms_utility.control ./share/postgresql/extension/gms_output--1.0.sql ./share/postgresql/extension/gms_output.control ./share/postgresql/extension/gms_inaddr--1.0.sql @@ -838,6 +840,7 @@ ./lib/postgresql/java/pljava.jar ./lib/postgresql/postgres_fdw.so ./lib/postgresql/dblink.so +./lib/postgresql/gms_utility.so ./lib/postgresql/pgoutput.so ./lib/postgresql/assessment.so ./lib/postgresql/gms_compress.so diff --git a/build/script/loongarch64_lite_list b/build/script/loongarch64_lite_list index 03168f684..3fe5776e9 100644 --- a/build/script/loongarch64_lite_list +++ b/build/script/loongarch64_lite_list @@ -68,6 +68,8 @@ ./share/postgresql/extension/gms_sql.control ./share/postgresql/extension/gms_i18n--1.0.sql ./share/postgresql/extension/gms_i18n.control +./share/postgresql/extension/gms_utility--1.0.sql +./share/postgresql/extension/gms_utility.control ./share/postgresql/timezone/GB-Eire ./share/postgresql/timezone/Turkey ./share/postgresql/timezone/Kwajalein @@ -762,6 +764,7 @@ ./lib/postgresql/gms_lob.so ./lib/postgresql/gms_sql.so ./lib/postgresql/gms_i18n.so +./lib/postgresql/gms_utility.so ./include/postgresql/server/postgres_ext.h ./include/postgresql/server/pg_config_os.h ./include/postgresql/server/pgtime.h diff --git a/build/script/opengauss_release_list_mini b/build/script/opengauss_release_list_mini index 5776d553c..c8271cb89 100644 --- a/build/script/opengauss_release_list_mini +++ b/build/script/opengauss_release_list_mini @@ -98,6 +98,8 @@ ./share/postgresql/extension/gms_sql.control ./share/postgresql/extension/gms_i18n--1.0.sql ./share/postgresql/extension/gms_i18n.control +./share/postgresql/extension/gms_utility--1.0.sql +./share/postgresql/extension/gms_utility.control ./share/postgresql/timezone/GB-Eire ./share/postgresql/timezone/Turkey ./share/postgresql/timezone/Kwajalein @@ -780,6 +782,7 @@ ./lib/postgresql/gms_lob.so ./lib/postgresql/gms_sql.so ./lib/postgresql/gms_i18n.so +./lib/postgresql/gms_utility.so ./lib/libpljava.so ./lib/libpq.a ./lib/libpq.so diff --git a/build/script/opengauss_release_list_ubuntu_single b/build/script/opengauss_release_list_ubuntu_single index 48e7a8433..306981363 100644 --- a/build/script/opengauss_release_list_ubuntu_single +++ b/build/script/opengauss_release_list_ubuntu_single @@ -119,6 +119,8 @@ ./share/postgresql/extension/gms_lob.control ./share/postgresql/extension/gms_stats--1.0.sql ./share/postgresql/extension/gms_stats.control +./share/postgresql/extension/gms_utility--1.0.sql +./share/postgresql/extension/gms_utility.control ./share/postgresql/extension/gms_profiler--1.0.sql ./share/postgresql/extension/gms_profiler.control ./share/postgresql/extension/gms_sql--1.0.sql @@ -815,6 +817,7 @@ ./lib/postgresql/gms_inaddr.so ./lib/postgresql/gms_lob.so ./lib/postgresql/gms_stats.so +./lib/postgresql/gms_utility.so ./lib/postgresql/gms_profiler.so ./lib/postgresql/gms_sql.so ./lib/postgresql/gms_tcp.so diff --git a/build/script/x86_64_lite_list b/build/script/x86_64_lite_list index 0cbf41d7e..037b477e5 100644 --- a/build/script/x86_64_lite_list +++ b/build/script/x86_64_lite_list @@ -63,6 +63,8 @@ ./share/postgresql/extension/hstore--1.0--1.1.sql ./share/postgresql/extension/log_fdw--1.0.sql ./share/postgresql/extension/log_fdw.control +./share/postgresql/extension/gms_utility--1.0.sql +./share/postgresql/extension/gms_utility.control ./share/postgresql/extension/gms_output--1.0.sql ./share/postgresql/extension/gms_output.control ./share/postgresql/extension/gms_stats--1.0.sql @@ -765,6 +767,7 @@ ./lib/postgresql/latin2_and_win1250.so ./lib/postgresql/euc2004_sjis2004.so ./lib/postgresql/pgoutput.so +./lib/postgresql/gms_utility.so ./lib/postgresql/gms_output.so ./lib/postgresql/gms_stats.so ./lib/postgresql/gms_profiler.so diff --git a/build/script/x86_64_opengauss_list b/build/script/x86_64_opengauss_list index df6868a4b..b7155fede 100644 --- a/build/script/x86_64_opengauss_list +++ b/build/script/x86_64_opengauss_list @@ -123,6 +123,8 @@ ./share/postgresql/extension/dblink.control ./share/postgresql/extension/gms_compress--1.0.sql ./share/postgresql/extension/gms_compress.control +./share/postgresql/extension/gms_utility--1.0.sql +./share/postgresql/extension/gms_utility.control ./share/postgresql/extension/gms_output--1.0.sql ./share/postgresql/extension/gms_output.control ./share/postgresql/extension/gms_inaddr--1.0.sql @@ -838,6 +840,7 @@ ./lib/postgresql/java/pljava.jar ./lib/postgresql/postgres_fdw.so ./lib/postgresql/dblink.so +./lib/postgresql/gms_utility.so ./lib/postgresql/gms_lob.so ./lib/postgresql/gms_stats.so ./lib/postgresql/gms_tcp.so diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 6d228b7a4..3802be761 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -29,6 +29,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/datavec ${CMAKE_CURRENT_SOURCE_DIR}/chparser ${CMAKE_CURRENT_SOURCE_DIR}/gms_stats + ${CMAKE_CURRENT_SOURCE_DIR}/gms_utility ${CMAKE_CURRENT_SOURCE_DIR}/gms_profiler ${CMAKE_CURRENT_SOURCE_DIR}/gms_lob ${CMAKE_CURRENT_SOURCE_DIR}/gms_sql @@ -60,6 +61,7 @@ add_subdirectory(pagehack) add_subdirectory(pg_xlogdump) add_subdirectory(file_fdw) add_subdirectory(log_fdw) +add_subdirectory(gms_utility) add_subdirectory(gms_stats) add_subdirectory(gms_sql) add_subdirectory(gms_tcp) diff --git a/contrib/Makefile b/contrib/Makefile index 533ff5c57..d2693e3e9 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -57,6 +57,7 @@ SUBDIRS = \ vacuumlo \ security_plugin \ ndpplugin \ + gms_utility \ gms_profiler \ gms_inaddr \ gms_output \ diff --git a/contrib/gms_utility/CMakeLists.txt b/contrib/gms_utility/CMakeLists.txt new file mode 100644 index 000000000..97be66b20 --- /dev/null +++ b/contrib/gms_utility/CMakeLists.txt @@ -0,0 +1,21 @@ +#This is the main CMAKE for build all gms_utility. +# gms_utility +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} TGT_gms_utility_SRC) +set(TGT_gms_utility_INC + ${PROJECT_OPENGS_DIR}/contrib/gms_utility + ${PROJECT_OPENGS_DIR}/contrib +) + +set(gms_utility_DEF_OPTIONS ${MACRO_OPTIONS}) +set(gms_utility_COMPILE_OPTIONS ${OPTIMIZE_OPTIONS} ${OS_OPTIONS} ${PROTECT_OPTIONS} ${WARNING_OPTIONS} ${LIB_SECURE_OPTIONS} ${CHECK_OPTIONS}) +set(gms_utility_LINK_OPTIONS ${LIB_LINK_OPTIONS}) +add_shared_libtarget(gms_utility TGT_gms_utility_SRC TGT_gms_utility_INC "${gms_utility_DEF_OPTIONS}" "${gms_utility_COMPILE_OPTIONS}" "${gms_utility_LINK_OPTIONS}") +set_target_properties(gms_utility PROPERTIES PREFIX "") + +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gms_utility.control + DESTINATION share/postgresql/extension/ +) +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gms_utility--1.0.sql + DESTINATION share/postgresql/extension/ +) +install(TARGETS gms_utility DESTINATION lib/postgresql) \ No newline at end of file diff --git a/contrib/gms_utility/Makefile b/contrib/gms_utility/Makefile new file mode 100644 index 000000000..6e2d103cc --- /dev/null +++ b/contrib/gms_utility/Makefile @@ -0,0 +1,32 @@ +# contrib/gms_utility/Makefile +MODULE_big = gms_utility +OBJS = gms_utility.o + +EXTENSION = gms_utility +DATA = gms_utility--1.0.sql + +exclude_option = -fPIE +override CPPFLAGS := -fstack-protector-strong $(filter-out $(exclude_option),$(CPPFLAGS)) + +REGRESS = gms_utility + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/gms_utility +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +regress_home = $(top_builddir)/src/test/regress +REGRESS_OPTS = -c 0 -d 1 -r 1 -p 36789 --single_node -w --keep_last_data=false \ + --regconf=$(regress_home)/regress.conf \ + --temp-config=$(regress_home)/make_fastcheck_postgresql.conf +include $(top_srcdir)/contrib/contrib-global.mk +endif + +gms_utility.o: gms_utility.cpp + +check_utility: + chmod +x ./smartmatch.pl + make check \ No newline at end of file diff --git a/contrib/gms_utility/data/dummy.txt b/contrib/gms_utility/data/dummy.txt new file mode 100644 index 000000000..7f015cede --- /dev/null +++ b/contrib/gms_utility/data/dummy.txt @@ -0,0 +1 @@ +The openGauss regression needs this file to run. \ No newline at end of file diff --git a/contrib/gms_utility/expected/gms_utility.out b/contrib/gms_utility/expected/gms_utility.out new file mode 100644 index 000000000..38cc9bf91 --- /dev/null +++ b/contrib/gms_utility/expected/gms_utility.out @@ -0,0 +1,3315 @@ +reset search_path; +create extension if not exists gms_utility; +-- start test db_version +declare + version varchar2(50); + compatibility varchar2(50); +begin + gms_utility.db_version(version, compatibility); + raise info 'version: %', version; + raise info 'compatibility: %', compatibility; +end; +/ +--?INFO: version: openGauss.* +--?INFO: compatibility: openGuass.* +declare + version varchar2(50); +begin + gms_utility.db_version(version); + raise info 'version: %', version; +end; -- error +/ +ERROR: function "db_version" with 1 parameters doesn't exist +CONTEXT: SQL statement "CALL gms_utility.db_version(version)" +PL/pgSQL function inline_code_block line 3 at SQL statement +call gms_utility.db_version(); -- error +ERROR: function "db_version" with 0 parameters doesn't exist +declare + version int; + compatibility int; +begin + gms_utility.db_version(version, compatibility); + raise info 'version: %', version; + raise info 'compatibility: %', compatibility; +end; -- error +/ +--?ERROR: invalid input syntax for integer:.* +CONTEXT: PL/pgSQL function inline_code_block line 4 at SQL statement +-- end test db_version +-- start test get_cpu_time +select gms_utility.get_cpu_time(); + get_cpu_time +-------------- +--?.* +(1 row) + +select gms_utility.get_cpu_time(100); -- error +ERROR: function gms_utility.get_cpu_time(integer) does not exist +LINE 1: select gms_utility.get_cpu_time(100); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +CONTEXT: referenced column: get_cpu_time +declare + cputime char(1); +begin + cputime := gms_utility.get_cpu_time(); + raise info 'cpuTimeDelta: %', cputime; +end; +/ +ERROR: value too long for type character(1) +CONTEXT: PL/pgSQL function inline_code_block line 3 at assignment +declare + cputime json; +begin + cputime := gms_utility.get_cpu_time(); + raise info 'cpuTimeDelta: %', cputime; +end; +/ +--?INFO: cpuTimeDelta:.* +declare + t1 number := 0; + t2 number := 0; + timeDelta number; + i integer; + sum integer; +begin + t1 := gms_utility.get_cpu_time(); + for i in 1..1000000 loop + sum := sum + i * 2 + i / 2; + end loop; + t2 := gms_utility.get_cpu_time(); + timeDelta = t2 - t1; + raise info 'cpuTimeDelta: %', timeDelta; +end; +/ +--?INFO: cpuTimeDelta:.* +declare + i number; + j number; + k number; +begin + i := gms_utility.get_cpu_time; + + select count(*) + into j + from pg_class t, pg_index i + where t.Oid = i.indexrelid; + + k := gms_utility.get_cpu_time; + raise info 'costtime: %', (k-i); +end; +/ +--?INFO: costtime:.* +-- end test get_cpu_time +-- start test get_endianness +select gms_utility.get_endianness(); + get_endianness +---------------- +--?.* +(1 row) + +select gms_utility.get_endianness(1000); +ERROR: function gms_utility.get_endianness(integer) does not exist +LINE 1: select gms_utility.get_endianness(1000); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +CONTEXT: referenced column: get_endianness +-- end test get_endianness +-- start test get_sql_hash +declare + hash raw(50); + l4b number; +begin + gms_utility.get_sql_hash('Today is a good day!', hash, l4b); + raise info 'hash: %', hash; + raise info 'last4byte: %', l4b; +end; +/ +INFO: hash: 834E5BE13C0240D4F1AEBB1BCE7205AF +INFO: last4byte: 2936369870 +declare + hash raw(50); + l4b number; +begin + gms_utility.get_sql_hash(NULL, hash, l4b); + raise info 'hash: %', hash; + raise info 'last4byte: %', l4b; +end; +/ +INFO: hash: +INFO: last4byte: +declare + hash raw(50); + l4b number; +begin + gms_utility.get_sql_hash('', hash, l4b); + raise info 'hash: %', hash; + raise info 'last4byte: %', l4b; +end; +/ +INFO: hash: +INFO: last4byte: +call gms_utility.get_sql_hash(); +ERROR: function "get_sql_hash" with 0 parameters doesn't exist +-- end test get_sql_hash +-- start test is_bit_set +declare + r raw(50) := '123456AF'; + result NUMBER; + pos NUMBER; +begin + for pos in 1..32 loop + result := gms_utility.is_bit_set(r, pos); + raise info 'position = %, result = %', pos, result; + end loop; +end; +/ +INFO: position = 1, result = 1 +INFO: position = 2, result = 1 +INFO: position = 3, result = 1 +INFO: position = 4, result = 1 +INFO: position = 5, result = 0 +INFO: position = 6, result = 1 +INFO: position = 7, result = 0 +INFO: position = 8, result = 1 +INFO: position = 9, result = 0 +INFO: position = 10, result = 1 +INFO: position = 11, result = 1 +INFO: position = 12, result = 0 +INFO: position = 13, result = 1 +INFO: position = 14, result = 0 +INFO: position = 15, result = 1 +INFO: position = 16, result = 0 +INFO: position = 17, result = 0 +INFO: position = 18, result = 0 +INFO: position = 19, result = 1 +INFO: position = 20, result = 0 +INFO: position = 21, result = 1 +INFO: position = 22, result = 1 +INFO: position = 23, result = 0 +INFO: position = 24, result = 0 +INFO: position = 25, result = 0 +INFO: position = 26, result = 1 +INFO: position = 27, result = 0 +INFO: position = 28, result = 0 +INFO: position = 29, result = 1 +INFO: position = 30, result = 0 +INFO: position = 31, result = 0 +INFO: position = 32, result = 0 +declare + r raw(50) := '123456AF'; + result NUMBER; + pos NUMBER; +begin + for pos in 33..64 loop + result := gms_utility.is_bit_set(r, pos); + raise info 'position = %, result = %', pos, result; + end loop; +end; +/ +INFO: position = 33, result = 1 +INFO: position = 34, result = 1 +INFO: position = 35, result = 1 +INFO: position = 36, result = 1 +INFO: position = 37, result = 0 +INFO: position = 38, result = 1 +INFO: position = 39, result = 0 +INFO: position = 40, result = 1 +INFO: position = 41, result = 0 +INFO: position = 42, result = 1 +INFO: position = 43, result = 1 +INFO: position = 44, result = 0 +INFO: position = 45, result = 1 +INFO: position = 46, result = 0 +INFO: position = 47, result = 1 +INFO: position = 48, result = 0 +INFO: position = 49, result = 0 +INFO: position = 50, result = 0 +INFO: position = 51, result = 1 +INFO: position = 52, result = 0 +INFO: position = 53, result = 1 +INFO: position = 54, result = 1 +INFO: position = 55, result = 0 +INFO: position = 56, result = 0 +INFO: position = 57, result = 0 +INFO: position = 58, result = 1 +INFO: position = 59, result = 0 +INFO: position = 60, result = 0 +INFO: position = 61, result = 1 +INFO: position = 62, result = 0 +INFO: position = 63, result = 0 +INFO: position = 64, result = 0 +select gms_utility.is_bit_set(); -- error +ERROR: function gms_utility.is_bit_set() does not exist +LINE 1: select gms_utility.is_bit_set(); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +CONTEXT: referenced column: is_bit_set +select gms_utility.is_bit_set(NULL, 10); -- error +ERROR: invalid input value +CONTEXT: referenced column: is_bit_set +select gms_utility.is_bit_set('', 10); -- error +ERROR: invalid input value +CONTEXT: referenced column: is_bit_set +select gms_utility.is_bit_set('123456'); -- error +ERROR: function gms_utility.is_bit_set(unknown) does not exist +LINE 1: select gms_utility.is_bit_set('123456'); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +CONTEXT: referenced column: is_bit_set +select gms_utility.is_bit_set('123456AF', 9); + is_bit_set +------------ + 0 +(1 row) + +select gms_utility.is_bit_set('12345678AF', 9); + is_bit_set +------------ + 0 +(1 row) + +select gms_utility.is_bit_set('123456TT', 9); -- error +ERROR: invalid hexadecimal digit: "T" +LINE 1: select gms_utility.is_bit_set('123456TT', 9); + ^ +CONTEXT: referenced column: is_bit_set +select gms_utility.is_bit_set('12345678TT', 9); -- error +ERROR: invalid hexadecimal digit: "T" +LINE 1: select gms_utility.is_bit_set('12345678TT', 9); + ^ +CONTEXT: referenced column: is_bit_set +select gms_utility.is_bit_set('1234', 9); + is_bit_set +------------ + 0 +(1 row) + +select gms_utility.is_bit_set('12345678', -10); -- error +ERROR: invalid second param value range +CONTEXT: referenced column: is_bit_set +select gms_utility.is_bit_set('12345678', 0); -- error +ERROR: invalid second param value range +CONTEXT: referenced column: is_bit_set +select gms_utility.is_bit_set('12345678', 100); + is_bit_set +------------ + 1 +(1 row) + +select gms_utility.is_bit_set('12345678', 3.14E100); -- error +ERROR: integer out of range +CONTEXT: referenced column: is_bit_set +select gms_utility.is_bit_set('团团又圆圆', 20); -- error +--?ERROR: invalid hexadecimal digit:.* +LINE 1: select gms_utility.is_bit_set('团团又圆圆', 20); + ^ +CONTEXT: referenced column: is_bit_set +-- end test is_bit_set +-- start test is_cluster_database +select gms_utility.is_cluster_database(); + is_cluster_database +--------------------- + f +(1 row) + +select gms_utility.is_cluster_database(1000); +ERROR: function gms_utility.is_cluster_database(integer) does not exist +LINE 1: select gms_utility.is_cluster_database(1000); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +CONTEXT: referenced column: is_cluster_database +begin + if gms_utility.is_cluster_database then + raise info 'true'; + else + raise info 'false'; + end if; +end; +/ +INFO: false +-- end test is_cluster_database +-- start test old_current_schema +select gms_utility.old_current_schema(); + old_current_schema +-------------------- +--?.* +(1 row) + +select gms_utility.old_current_schema(2000); +ERROR: function gms_utility.old_current_schema(integer) does not exist +LINE 1: select gms_utility.old_current_schema(2000); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +CONTEXT: referenced column: old_current_schema +-- end test old_current_schema +-- start test old_current_user +select gms_utility.old_current_user(); + old_current_user +------------------ +--?.* +(1 row) + +select gms_utility.old_current_user(2000); +ERROR: function gms_utility.old_current_user(integer) does not exist +LINE 1: select gms_utility.old_current_user(2000); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +CONTEXT: referenced column: old_current_user +-- end test old_current_user +--------------------------- +-- expand_sql_text +--------------------------- +create schema test_utility_est; +set search_path to test_utility_est; +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text(NULL, sqlTxt); + raise info 'output_sql_text: %', sqlTxt; +end; +/ +INFO: output_sql_text: +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text(NULL); + raise info 'output_sql_text: %', sqlTxt; +end; +/ +ERROR: function "expand_sql_text" with 1 parameters doesn't exist +CONTEXT: SQL statement "CALL gms_utility.expand_sql_text(NULL)" +PL/pgSQL function inline_code_block line 3 at SQL statement +create table test_dx(id int); +create view view1 as select * from test_dx; +create materialized view mv_dx as select * from test_dx; +declare + input_sql_text clob := 'select * from test_utility_est.view1'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +INFO: output_sql_text: SELECT id FROM (SELECT test_dx.id FROM test_utility_est.test_dx) view1 +declare + input_sql_text clob := 'select * from test_utility_est.view1;'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +INFO: output_sql_text: SELECT id FROM (SELECT test_dx.id FROM test_utility_est.test_dx) view1 +-- don't expand materialized view sql, just print +declare + input_sql_text clob := 'select * from test_utility_est.mv_dx'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +INFO: output_sql_text: SELECT id FROM test_utility_est.mv_dx +-- test multi sql, error +declare + input_sql_text clob := 'select * from test_utility_est.view1;select * from test_utility_est.view1'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +ERROR: Expand_sql_text only support one query +CONTEXT: PL/pgSQL function gms_utility.expand_sql_text(clob) line 2 at assignment +SQL statement "CALL gms_utility.expand_sql_text(input_sql_text,output_sql_text)" +PL/pgSQL function inline_code_block line 4 at SQL statement +-- test select into +insert into test_dx values (3); +declare + num int := 0; + input_sql_text clob := 'select * into t_into from test_utility_est.view1;'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +INFO: output_sql_text: INSERT INTO gms_utility.t_into (id) SELECT id FROM (SELECT test_dx.id FROM test_utility_est.test_dx) view1 +declare + num int := 0; + output_sql_text clob; +begin + gms_utility.expand_sql_text('select id into num from test_utility_est.view1', output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +INFO: output_sql_text: INSERT INTO gms_utility.num (id) SELECT id FROM (SELECT test_dx.id FROM test_utility_est.test_dx) view1 +--test with select +declare + num int := 0; + input_sql_text clob := 'with ws (id) AS (select id from test_utility_est.view1) select * from ws'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +INFO: output_sql_text: WITH ws(id) AS (SELECT view1.id FROM (SELECT test_dx.id FROM test_utility_est.test_dx) view1) SELECT id FROM ws +-- test select for update +declare + input_sql_text clob := 'select * from test_utility_est.test_dx for update'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +INFO: output_sql_text: SELECT id FROM test_utility_est.test_dx FOR UPDATE OF test_dx +declare + input_sql_text clob := 'select * from test_utility_est.view1 for update'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +INFO: output_sql_text: SELECT id FROM (SELECT test_dx.id FROM test_utility_est.test_dx) view1 FOR UPDATE OF view1 +create table test_1(id int, name varchar(20)); +create table test_2(id int, name varchar(20)); +create view view2 as select * from test_1; +create view view3 as select * from test_1 union select * from test_2; +create view view4 as select * from test_1 union select * from view3; +declare + input_sql_text1 clob := 'select * from test_utility_est.view3'; + output_sql_text1 clob; + input_sql_text2 clob := 'select * from test_utility_est.view4'; + output_sql_text2 clob; +begin + gms_utility.expand_sql_text(input_sql_text1, output_sql_text1); + raise info 'output_sql_text1: %', output_sql_text1; + gms_utility.expand_sql_text(input_sql_text2, output_sql_text2); + raise info 'output_sql_text2: %', output_sql_text2; +END; +/ +INFO: output_sql_text1: SELECT id, name FROM (SELECT test_1.id, test_1.name FROM test_utility_est.test_1 UNION SELECT test_2.id, test_2.name FROM test_utility_est.test_2) view3 +INFO: output_sql_text2: SELECT id, name FROM (SELECT test_1.id, test_1.name FROM test_utility_est.test_1 UNION SELECT view3.id, view3.name FROM (SELECT test_1.id, test_1.name FROM test_utility_est.test_1 UNION SELECT test_2.id, test_2.name FROM test_utility_est.test_2) view3) view4 +declare + input_sql_text1 clob := 'select * from test_utility_est.view3'; + output_sql_text1 clob; + input_sql_text2 clob := 'select * from test_utility_est.view4'; + output_sql_text2 clob; +begin + gms_utility.expand_sql_text(input_sql_text1, output_sql_text1); + raise info 'output_sql_text1: %', output_sql_text1; + gms_utility.expand_sql_text(input_sql_text2, output_sql_text2); + raise info 'output_sql_text2: %', output_sql_text2; +END; +/ +INFO: output_sql_text1: SELECT id, name FROM (SELECT test_1.id, test_1.name FROM test_utility_est.test_1 UNION SELECT test_2.id, test_2.name FROM test_utility_est.test_2) view3 +INFO: output_sql_text2: SELECT id, name FROM (SELECT test_1.id, test_1.name FROM test_utility_est.test_1 UNION SELECT view3.id, view3.name FROM (SELECT test_1.id, test_1.name FROM test_utility_est.test_1 UNION SELECT test_2.id, test_2.name FROM test_utility_est.test_2) view3) view4 +-- test not select query, error +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text('create table test(id int)', sqlTxt); + raise info 'output_sql_text: %', sqlTxt; +end; +/ +ERROR: Unsupported query type, only support SELECT query +CONTEXT: PL/pgSQL function gms_utility.expand_sql_text(clob) line 2 at assignment +SQL statement "CALL gms_utility.expand_sql_text('create table test(id int)',sqlTxt)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text('begin', sqlTxt); + raise info 'output_sql_text: %', sqlTxt; +end; +/ +ERROR: Unsupported query type, only support SELECT query +CONTEXT: PL/pgSQL function gms_utility.expand_sql_text(clob) line 2 at assignment +SQL statement "CALL gms_utility.expand_sql_text('begin',sqlTxt)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text('update test_1 set name = ''ggboom'' where id = 1', sqlTxt); + raise info 'output_sql_text: %', sqlTxt; +end; +/ +ERROR: Unsupported query type, only support SELECT query +CONTEXT: PL/pgSQL function gms_utility.expand_sql_text(clob) line 2 at assignment +SQL statement "CALL gms_utility.expand_sql_text('update test_1 set name = ''ggboom'' where id = 1',sqlTxt)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text('delete from test_1', sqlTxt); + raise info 'output_sql_text: %', sqlTxt; +end; +/ +ERROR: Unsupported query type, only support SELECT query +CONTEXT: PL/pgSQL function gms_utility.expand_sql_text(clob) line 2 at assignment +SQL statement "CALL gms_utility.expand_sql_text('delete from test_1',sqlTxt)" +PL/pgSQL function inline_code_block line 3 at SQL statement +-- test not valid query, error +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text('today is a good day', sqlTxt); + raise info 'output_sql_text: %', sqlTxt; +end; +/ +ERROR: syntax error at or near "today" +LINE 1: CALL gms_utility.expand_sql_text('today is a good day',sqlTx... + ^ +QUERY: CALL gms_utility.expand_sql_text('today is a good day',sqlTxt) +CONTEXT: PL/pgSQL function gms_utility.expand_sql_text(clob) line 2 at assignment +PL/pgSQL function inline_code_block line 3 at SQL statement +create table t1(srvr_id int); +create view expandv as select * from t1; +declare + vclobin clob := +'select distinct srvr_id +from public.expandv +where srvr_id not in +(select srvr_id +from public.expandv +minus +select srvr_id +from public.t1)'; + vclobout clob; +begin + gms_utility.expand_sql_text(vclobin, vclobout); + raise info 'output_sql_text: %', vclobout; +end; +/ +ERROR: relation "public.expandv" does not exist on datanode1 +LINE 1: CALL gms_utility.expand_sql_text(vclobin,vclobout) + ^ +QUERY: CALL gms_utility.expand_sql_text(vclobin,vclobout) +CONTEXT: PL/pgSQL function gms_utility.expand_sql_text(clob) line 2 at assignment +PL/pgSQL function inline_code_block line 12 at SQL statement +-- test privileges +create user user01 password 'utility@123'; +set session AUTHORIZATION user01 password 'utility@123'; +set search_path to test_utility_est; +declare + input_sql_text1 clob := 'select * from test_utility_est.view3'; + output_sql_text1 clob; +begin + gms_utility.expand_sql_text(input_sql_text1, output_sql_text1); + raise info 'output_sql_text1: %', output_sql_text1; +END; +/ +ERROR: permission denied for schema test_utility_est +LINE 1: CALL gms_utility.expand_sql_text(input_sql_text1,output_sql_... + ^ +DETAIL: N/A +QUERY: CALL gms_utility.expand_sql_text(input_sql_text1,output_sql_text1) +CONTEXT: PL/pgSQL function gms_utility.expand_sql_text(clob) line 2 at assignment +PL/pgSQL function inline_code_block line 4 at SQL statement +RESET SESSION AUTHORIZATION; +drop view view4; +drop view view3; +drop view view2; +drop view view1; +drop view expandv; +drop materialized view mv_dx; +drop table t1; +drop table if exists t_into; +NOTICE: table "t_into" does not exist, skipping +drop talbe if exists test_2; +ERROR: syntax error at or near "talbe" +LINE 1: drop talbe if exists test_2; + ^ +drop talbe if exists test_1; +ERROR: syntax error at or near "talbe" +LINE 1: drop talbe if exists test_1; + ^ +drop talbe if exists test_dx; +ERROR: syntax error at or near "talbe" +LINE 1: drop talbe if exists test_dx; + ^ +drop schema test_utility_est; +ERROR: cannot drop schema test_utility_est because other objects depend on it +DETAIL: table test_dx depends on schema test_utility_est +table test_1 depends on schema test_utility_est +table test_2 depends on schema test_utility_est +HINT: Use DROP ... CASCADE to drop the dependent objects too. +--------------------------- +-- analyze_schema|database +--------------------------- +create user test_utility_analyze password "test_utility_analyze@123"; +set search_path to test_utility_analyze; +create table t1 (id int, c2 text); +create unique index t1_id_uidx on t1 using btree(id); +insert into t1 values (generate_series(1, 100), 'aabbcc'); +insert into t1 values (generate_series(101, 200), '123dfg'); +insert into t1 values (generate_series(201, 300), '人面桃花相映红'); +insert into t1 values (generate_series(301, 400), 'fortunate'); +insert into t1 values (generate_series(401, 500), 'open@gauss'); +insert into t1 values (generate_series(501, 600), '127.0.0.1'); +insert into t1 values (generate_series(601, 700), '!@#$!%#!'); +insert into t1 values (generate_series(701, 800), '[1,2,3,4]'); +insert into t1 values (generate_series(801, 900), '{"name":"张三","age":18}'); +insert into t1 values (generate_series(901, 1000), ''); +create or replace function batch_insert(count INT) +returns int as $$ +declare + i INT; + start INT; +begin + select count(*) into start from t1; + for i in select generate_series(1, count) loop + insert into t1 values (start + i, left((pg_catalog.random() * i)::text, 6)); + end loop; + + return count; +end; +$$ language plpgsql; +select batch_insert(50000); + batch_insert +-------------- + 50000 +(1 row) + +-- analyze_schema +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=-100); -- error +ERROR: invalid value "-100" for "estimate_rows" +CONTEXT: SQL statement "CALL gms_utility.analyze_schema_c_fun(schema,method,estimate_rows,estimate_percent,method_opt)" +PL/pgSQL function gms_utility.analyze_schema(character varying,character varying,numeric,numeric,character varying) line 2 at PERFORM +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_percent:=20); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_percent:=0); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_percent:=101); -- error +ERROR: invalid value "101" for "estimate_percent" +CONTEXT: SQL statement "CALL gms_utility.analyze_schema_c_fun(schema,method,estimate_rows,estimate_percent,method_opt)" +PL/pgSQL function gms_utility.analyze_schema(character varying,character varying,numeric,numeric,character varying) line 2 at PERFORM +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR TABLE'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL INDEXES'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL COLUMNS'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL COLUMNS SIZE 100'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL INDEXED COLUMNS'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL INDEXED COLUMNS SIZE 100'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', estimate_rows:=10000); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', estimate_percent:=-100); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', estimate_rows:=10000, estimate_percent:=-100); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR TABLE'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL INDEXES'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL INDEXED COLUMNS'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL INDEXED COLUMNS SIZE 100'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL COLUMNS'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL COLUMNS SIZE 100'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR TABLE FOR ALL INDEXES'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR TABLE FOR ALL INDEXED COLUMNS'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR TABLE123'); -- error +ERROR: invalid input value for method_opt +CONTEXT: SQL statement "CALL gms_utility.analyze_schema_c_fun(schema,method,estimate_rows,estimate_percent,method_opt)" +PL/pgSQL function gms_utility.analyze_schema(character varying,character varying,numeric,numeric,character varying) line 2 at PERFORM +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='111FOR TABLE'); -- error +ERROR: unrecognized param value: "111FOR TABLE" +CONTEXT: SQL statement "CALL gms_utility.analyze_schema_c_fun(schema,method,estimate_rows,estimate_percent,method_opt)" +PL/pgSQL function gms_utility.analyze_schema(character varying,character varying,numeric,numeric,character varying) line 2 at PERFORM +call gms_utility.analyze_schema('test_utility_analyze', 'DELETE'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_schema('test_utility_analyze', 'DELETE', method_opt:='FOR TABLE'); -- error +ERROR: The Command did not end correctly +CONTEXT: SQL statement "CALL gms_utility.analyze_schema_c_fun(schema,method,estimate_rows,estimate_percent,method_opt)" +PL/pgSQL function gms_utility.analyze_schema(character varying,character varying,numeric,numeric,character varying) line 2 at PERFORM +DECLARE + res boolean; +BEGIN + gms_utility.analyze_schema('SYSTEM','ESTIMATE', NULL, 10); + EXCEPTION + WHEN OTHERS THEN + NULL; +END; +/ +-- test analyze database +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=-100); -- error +ERROR: invalid value "-100" for "estimate_rows" +CONTEXT: SQL statement "CALL gms_utility.analyze_schema_c_fun(schema_name,method,estimate_rows,estimate_percent,method_opt)" +PL/pgSQL function gms_utility.analyze_database(character varying,numeric,numeric,character varying) line 5 at PERFORM +call gms_utility.analyze_database('ESTIMATE', estimate_percent:=20); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('ESTIMATE', estimate_percent:=0); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('ESTIMATE', estimate_percent:=101); -- error +ERROR: invalid value "101" for "estimate_percent" +CONTEXT: SQL statement "CALL gms_utility.analyze_schema_c_fun(schema_name,method,estimate_rows,estimate_percent,method_opt)" +PL/pgSQL function gms_utility.analyze_database(character varying,numeric,numeric,character varying) line 5 at PERFORM +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR TABLE'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL INDEXES'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL COLUMNS'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL COLUMNS SIZE 100'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL INDEXED COLUMNS'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL INDEXED COLUMNS SIZE 100'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE', estimate_rows:=10000); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE', estimate_percent:=-100); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE', estimate_rows:=10000, estimate_percent:=-100); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR TABLE'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL INDEXES'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL INDEXED COLUMNS'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL INDEXED COLUMNS SIZE 100'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL COLUMNS'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL COLUMNS SIZE 100'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR TABLE FOR ALL INDEXES'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR TABLE FOR ALL INDEXED COLUMNS'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR TABLE123'); -- error +ERROR: invalid input value for method_opt +CONTEXT: SQL statement "CALL gms_utility.analyze_schema_c_fun(schema_name,method,estimate_rows,estimate_percent,method_opt)" +PL/pgSQL function gms_utility.analyze_database(character varying,numeric,numeric,character varying) line 5 at PERFORM +call gms_utility.analyze_database('COMPUTE', method_opt:='111FOR TABLE'); -- error +ERROR: unrecognized param value: "111FOR TABLE" +CONTEXT: SQL statement "CALL gms_utility.analyze_schema_c_fun(schema_name,method,estimate_rows,estimate_percent,method_opt)" +PL/pgSQL function gms_utility.analyze_database(character varying,numeric,numeric,character varying) line 5 at PERFORM +call gms_utility.analyze_database('DELETE'); + analyze_database +------------------ + +(1 row) + +call gms_utility.analyze_database('DELETE', method_opt:='FOR TABLE'); -- error +ERROR: The Command did not end correctly +CONTEXT: SQL statement "CALL gms_utility.analyze_schema_c_fun(schema_name,method,estimate_rows,estimate_percent,method_opt)" +PL/pgSQL function gms_utility.analyze_database(character varying,numeric,numeric,character varying) line 5 at PERFORM +ALTER INDEX t1_id_uidx UNUSABLE; +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL INDEXES'); +ERROR: index "t1_id_uidx" is not available +CONTEXT: SQL statement "CALL gms_utility.analyze_schema_c_fun(schema,method,estimate_rows,estimate_percent,method_opt)" +PL/pgSQL function gms_utility.analyze_schema(character varying,character varying,numeric,numeric,character varying) line 2 at PERFORM +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL INDEXES'); +ERROR: index "t1_id_uidx" is not available +CONTEXT: SQL statement "CALL gms_utility.analyze_schema_c_fun(schema_name,method,estimate_rows,estimate_percent,method_opt)" +PL/pgSQL function gms_utility.analyze_database(character varying,numeric,numeric,character varying) line 5 at PERFORM +ALTER INDEX t1_id_uidx REBUILD; +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL INDEXES'); + analyze_schema +---------------- + +(1 row) + +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL INDEXES'); + analyze_database +------------------ + +(1 row) + +drop table t1 cascade; +drop function batch_insert; +reset search_path; +drop user test_utility_analyze cascade; +--------------------------- +-- canonicalize +--------------------------- +create schema test_utility_canonicalize; +set search_path to test_utility_canonicalize; +-- canonicalize +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('uwclass.test', canon_name, 16); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: "UWCLASS"."TEST" +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: "KOLL"."ROOY"."NUUOP"."A" +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: function "canonicalize" with 2 parameters doesn't exist +CONTEXT: SQL statement "CALL gms_utility.canonicalize('koll.rooy.nuuop.a',canon_name)" +PL/pgSQL function inline_code_block line 3 at SQL statement +-- empty、space +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize(NULL, canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- NULL +/ +INFO: canon_name: +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('""', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Invalid paramter value """" with zero length +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('""',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize(' ', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize(' .abcd', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Invalid paramter value " .abcd" with special words +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize(' .abcd',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll..nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Invalid paramter value "koll..nuuop.a" with special words +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('koll..nuuop.a',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll."".nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Invalid paramter value "koll."".nuuop.a" with zero length +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('koll."".nuuop.a',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: KOLL +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('"koll"', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: koll +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize(' " koll.rooy" .nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: " koll.rooy"."NUUOP"."A" +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: "KOLL"."ROOY"."NUUOP"."A" +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('"~!#@@#$%)(#@(!@))<>?/*-+".nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: "~!#@@#$%)(#@(!@))<>?/*-+"."NUUOP"."A" +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy#_$nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: "KOLL"."ROOY#_$NUUOP"."A" +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll."rooy" abc.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Invalid parameter value "koll."rooy" abc.nuuop.a" after quotation +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('koll."rooy" abc.nuuop.a',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Invalid paramter value "koll.rooy.nuuop." +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('koll.rooy.nuuop.',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nu"uo"p', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Invalid parameter value "koll.rooy.nu"uo"p" before quotation +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('koll.rooy.nu"uo"p',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy."nu"u"o"p', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Invalid parameter value "koll.rooy."nu"u"o"p" after quotation +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('koll.rooy."nu"u"o"p',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll."rooy"."nuuop.', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Invalid paramter value "koll."rooy"."nuuop." with quotation not closed +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('koll."rooy"."nuuop.',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +-- identy +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.123rooy.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Invalid paramter value "koll.123rooy.nuuop.a" with special words +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('koll.123rooy.nuuop.a',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll._rooy.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- ok for og, error for A +/ +INFO: canon_name: "KOLL"."_ROOY"."NUUOP"."A" +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll."_rooy".nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: "KOLL"."_rooy"."NUUOP"."A" +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('table', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: TABLE +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.table.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Invalid paramter value "koll.rooy.table.a" with special words +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('koll.rooy.table.a',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('column', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: COLUMN +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.column.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Invalid paramter value "koll.column.nuuop.a" with special words +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('koll.column.nuuop.a',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +-- test indentifier overlength; og >= 64, A >= 128 +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.DoYouThinkCausalUnderstandingIsADefiningCharacteristicOfHumanCognition.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +ERROR: identifier too long, max length is 64 +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('koll.DoYouThinkCausalUnderstandingIsADefiningCharacteristicOfHumanCognition.nuuop.a',canon_name,100)" +PL/pgSQL function inline_code_block line 3 at SQL statement +-- param canon_len +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name, -10); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: Input parameter "canon_len" value "-10" is less than zero +CONTEXT: PL/pgSQL function gms_utility.canonicalize(character varying,integer) line 5 at assignment +SQL statement "CALL gms_utility.canonicalize('koll.rooy.nuuop.a',canon_name,-10)" +PL/pgSQL function inline_code_block line 3 at SQL statement +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name, 0); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name, 10); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: "KOLL"."RO +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('开车.rooy.nuuop.a', canon_name, 10); + raise info 'canon_name: %', canon_name; +end; +/ +INFO: canon_name: "开车"." +declare + canon_name varchar2(10); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name, 20); + raise info 'canon_name: %', canon_name; +end; -- error +/ +ERROR: value too long for type character varying(10) +CONTEXT: PL/pgSQL function inline_code_block line 3 at SQL statement +drop schema test_utility_canonicalize; +--------------------------- +-- compile schema +--------------------------- +create schema test_utility_compile; +set search_path to test_utility_compile; +create table classes ( + class_id int primary key, + class_name varchar(50) not null +) +with (orientation=row, compression=no); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "classes_pkey" for table "classes" + +create table students ( + student_id int primary key, + class_id int, + student_name varchar(50) not null +) +with (orientation=row, compression=no); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "students_pkey" for table "students" + +create table studentscores ( + score_id int primary key, + student_id int, + subject varchar(50), + score int +) +with (orientation=row, compression=no); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "studentscores_pkey" for table "studentscores" +create or replace procedure insertclass(in classname varchar(50)) +as + ct int; +begin + select count(class_id) into ct from classes; + insert into classes values (ct + 1, classname); +end; +/ + +create or replace procedure insertstudent(in classname varchar(50), in studentname varchar(50)) +as + classid int; + ct int; +begin + select class_id into classid from classes where class_name = classname; + select count(student_id) into ct from students; + insert into students values (ct + 1, classid, studentname); +end; +/ +create or replace function insertscore(studentid int, subject varchar(50), score int) +returns int +as $$ +declare + ct int; +begin + select count(score_id) into ct from studentscores; + insert into studentscores values (ct + 1, studentid, subject, score); + return ct + 1; +end; +$$ language plpgsql; +create or replace function getrank(score int) +returns text +as $$ +declare + rk text; +begin + if score = 100 then + rk := 'perfect'; + elsif score >= 80 then + rk := 'nice'; + elsif score >= 60 then + rk := 'ordinary'; + elsif score >= 0 then + rk := 'poor'; + else + raise notice 'error input'; + end if; + + return rk; +end; +$$ language plpgsql; +call insertclass('class a'); + insertclass +------------- + +(1 row) + +call insertclass('class b'); + insertclass +------------- + +(1 row) + + +call insertstudent('class a', 'alice'); + insertstudent +--------------- + +(1 row) + +call insertstudent('class a', 'bob'); + insertstudent +--------------- + +(1 row) + +call insertstudent('class b', 'charlie'); + insertstudent +--------------- + +(1 row) + +call insertstudent('class b', 'rose'); + insertstudent +--------------- + +(1 row) + +call insertstudent('class b', 'jack'); + insertstudent +--------------- + +(1 row) + + +select insertscore(1, 'math', 90); + insertscore +------------- + 1 +(1 row) + +select insertscore(1, 'science', 85); + insertscore +------------- + 2 +(1 row) + +select insertscore(2, 'math', 95); + insertscore +------------- + 3 +(1 row) + +select insertscore(2, 'science', 88); + insertscore +------------- + 4 +(1 row) + +select insertscore(3, 'math', 78); + insertscore +------------- + 5 +(1 row) + +select insertscore(3, 'science', 82); + insertscore +------------- + 6 +(1 row) + +select insertscore(4, 'math', 100); + insertscore +------------- + 7 +(1 row) + +select insertscore(4, 'science', 66); + insertscore +------------- + 8 +(1 row) + +select insertscore(5, 'math', 57); + insertscore +------------- + 9 +(1 row) + +select insertscore(5, 'science', 68); + insertscore +------------- + 10 +(1 row) + +create view stud_class as select s.student_name, c.class_name from students s join classes c on s.class_id = c.class_id; +create view stud_score as select b.student_name, a.subject, a.score, getrank(a.score) from studentscores a join students b on a.student_id = b.student_id; +create table t_pkg (c1 text); +create package p_batch as + procedure insertpkg(txt text); + function batchinsert(num int) return int; +end p_batch; +/ +create package body p_batch as + procedure insertpkg(txt text) + as + begin + insert into t_pkg values (txt); + end; + + function batchinsert(num int) + return int + is + start int := 0; + i int := 0; + begin + select count(*) into start from t_pkg; + for i in select generate_series(1, num) loop + insert into t1 values (start + i, left((pg_catalog.random() * i)::text, 6)); + end loop; + + return i; + end; +end p_batch; +/ +call gms_utility.compile_schema('test_utility_compile'); + compile_schema +---------------- + +(1 row) + +call gms_utility.compile_schema('test_utility_compile', false); + compile_schema +---------------- + +(1 row) + +call gms_utility.compile_schema('test_utility_compile', true, false); + compile_schema +---------------- + +(1 row) + +call gms_utility.compile_schema(); -- error +ERROR: function "compile_schema" with 0 parameters doesn't exist +call gms_utility.compile_schema(1); -- error +ERROR: schema "1" does not exists +CONTEXT: SQL statement "CALL gms_utility.compile_schema_c_func(schema,compile_all,reuse_settings)" +PL/pgSQL function gms_utility.compile_schema(character varying,boolean,boolean) line 2 at PERFORM +call gms_utility.compile_schema('no_schema'); -- error +ERROR: schema "no_schema" does not exists +CONTEXT: SQL statement "CALL gms_utility.compile_schema_c_func(schema,compile_all,reuse_settings)" +PL/pgSQL function gms_utility.compile_schema(character varying,boolean,boolean) line 2 at PERFORM +create or replace function getrank(score int) +returns text +as $$ +declare + rk text; +begin + if score = 100 then + rk := 'perfect'; + elsif score >= 80 then + rk := 'nice'; + elsif score >= 60 then + rk := 'ordinary'; + elsif score >= 0 then + rk := 'poor'; + else + rk := 'error'; + end if; + + return rk; +end; +$$ language plpgsql; +call gms_utility.compile_schema('test_utility_compile'); + compile_schema +---------------- + +(1 row) + +drop package body p_batch; +drop package p_batch; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to function test_utility_compile.insertpkg(text) +drop cascades to function test_utility_compile.batchinsert(integer) +drop table t_pkg; +drop view stud_score; +drop view stud_class; +drop function getrank; +drop function insertscore; +drop procedure insertstudent; +drop procedure insertclass; +drop table studentscores; +drop table students; +drop table classes; +-- test invalid object compile +set behavior_compat_options = 'plpgsql_dependency'; +create type s_type as ( + id integer, + name varchar, + addr text +); +create or replace procedure type_alter(a s_type) +is +begin + raise info 'call a: %', a; +end; +/ +select valid from pg_object where object_type='p' and object_oid in (select oid from pg_proc where propackageid = 0 and proname='type_alter' and pronamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- +(0 rows) + +alter type s_type add attribute a int; +select valid from pg_object where object_type='p' and object_oid in (select oid from pg_proc where propackageid = 0 and proname='type_alter' and pronamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- +(0 rows) + +call gms_utility.compile_schema('test_utility_compile', false); + compile_schema +---------------- + +(1 row) + +select valid from pg_object where object_type='p' and object_oid in (select oid from pg_proc where propackageid = 0 and proname='type_alter' and pronamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- +(0 rows) + +create table stu(sno int, name varchar, sex varchar, cno int); +create type r1 as (a int, c stu%rowtype); +create or replace package pkg +is + procedure proc1(p_in r1); +end pkg; +/ +create or replace package body pkg +is +declare + v1 r1; + v2 stu%rowtype; + procedure proc1(p_in r1) as + begin + raise info 'call p_in: %', p_in; + end; +end pkg; +/ +call pkg.proc1((1,(1,'zhang','m',1))); +INFO: call p_in: (1,"(1,zhang,m,1)") + proc1 +------- + +(1 row) + +select valid from pg_object where object_type='b' and object_oid in (select oid from gs_package where pkgname='pkg' and pkgnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- +(0 rows) + +alter table stu add column b int; +select valid from pg_object where object_type='b' and object_oid in (select oid from gs_package where pkgname='pkg' and pkgnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- +(0 rows) + +call gms_utility.compile_schema('test_utility_compile', false); + compile_schema +---------------- + +(1 row) + +select valid from pg_object where object_type='b' and object_oid in (select oid from gs_package where pkgname='pkg' and pkgnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- +(0 rows) + +create view v_stu as select * from stu; +select * from v_stu; + sno | name | sex | cno | b +-----+------+-----+-----+--- +(0 rows) + +select valid from pg_object where object_type='v' and object_oid in (select oid from pg_class where relname='v_stu' and relkind='v' and relnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- + t +(1 row) + +alter table stu drop column b; +select valid from pg_object where object_type='v' and object_oid in (select oid from pg_class where relname='v_stu' and relkind='v' and relnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- + f +(1 row) + +call gms_utility.compile_schema('test_utility_compile', false); +WARNING: Compile view "v_stu" failed +CONTEXT: SQL statement "CALL gms_utility.compile_schema_c_func(schema,compile_all,reuse_settings)" +PL/pgSQL function gms_utility.compile_schema(character varying,boolean,boolean) line 2 at PERFORM + compile_schema +---------------- + +(1 row) + +select valid from pg_object where object_type='v' and object_oid in (select oid from pg_class where relname='v_stu' and relkind='v' and relnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- + f +(1 row) + +select * from v_stu; +ERROR: The view v_stu is invalid, please make it valid before operation. +HINT: Please re-add missing table fields. +alter table stu add column b int; +select valid from pg_object where object_type='v' and object_oid in (select oid from pg_class where relname='v_stu' and relkind='v' and relnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- + f +(1 row) + +call gms_utility.compile_schema('test_utility_compile', false); + compile_schema +---------------- + +(1 row) + +select valid from pg_object where object_type='v' and object_oid in (select oid from pg_class where relname='v_stu' and relkind='v' and relnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- + t +(1 row) + +select * from v_stu; + sno | name | sex | cno | b +-----+------+-----+-----+--- +(0 rows) + +drop view v_stu; +drop package body pkg; +drop package pkg cascade; +ERROR: syntax error at or near "cascade" +LINE 1: drop package pkg cascade; + ^ +drop type r1; +drop table stu; +drop procedure type_alter; +-- test procedure compile error +set behavior_compat_options = 'plpgsql_dependency'; +create or replace procedure proc_err(p_in s_type) as +begin + raise info 'call p_in: %', p_in; +end; +/ +drop type s_type; +select valid from pg_object where object_type='p' and object_oid in (select oid from pg_proc where propackageid = 0 and proname='proc_err' and pronamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- +(0 rows) + +call gms_utility.compile_schema('test_utility_compile', false); +WARNING: "proc_err" header is undefined, you can try to recreate. +CONTEXT: SQL statement "CALL gms_utility.compile_schema_c_func(schema,compile_all,reuse_settings)" +PL/pgSQL function gms_utility.compile_schema(character varying,boolean,boolean) line 2 at PERFORM + compile_schema +---------------- + +(1 row) + +select valid from pg_object where object_type='p' and object_oid in (select oid from pg_proc where propackageid = 0 and proname='proc_err' and pronamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + valid +------- +(0 rows) + +drop procedure proc_err; +drop schema test_utility_compile cascade; +NOTICE: drop cascades to 2 other objects +--?DETAIL: drop cascades to package.* +drop cascades to function test_utility_compile.proc1(undefined) +--------------------------- +-- name tokenize +--------------------------- +create schema test_utility_tokenize; +set search_path to test_utility_tokenize; +declare + name varchar2(50) := 'peer.lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +INFO: a = PEER, b = LOKPPE, c = VUUMEE, dblink = OOKEYY, nextpos = 25 +-- test empty character +declare + name varchar2(50) := NULL; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := ''; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := '""'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value """" with zero length +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := ' . '; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value " . " with special words +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := '" . "'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +INFO: a = . , b = , c = , dblink = , nextpos = 7 +declare + name varchar2(50) := 'peer. lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +INFO: a = PEER, b = LOKPPE, c = VUUMEE, dblink = OOKEYY, nextpos = 28 +declare + name varchar2(50) := 'peer." lokppe.vuumee"@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +INFO: a = PEER, b = lokppe.vuumee, c = , dblink = OOKEYY, nextpos = 30 +-- test support special char +declare + name varchar2(50) := 'peer._lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- ok for og, error for A +/ +INFO: a = PEER, b = _LOKPPE, c = VUUMEE, dblink = OOKEYY, nextpos = 26 +declare + name varchar2(50) := 'peer.lokp_pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +INFO: a = PEER, b = LOKP_PE, c = VUUMEE, dblink = OOKEYY, nextpos = 26 +declare + name varchar2(50) := 'peer.$lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- ok for og, error for A +/ +INFO: a = PEER, b = $LOKPPE, c = VUUMEE, dblink = OOKEYY, nextpos = 26 +declare + name varchar2(50) := 'peer.lokp$pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +INFO: a = PEER, b = LOKP$PE, c = VUUMEE, dblink = OOKEYY, nextpos = 26 +declare + name varchar2(50) := 'peer.lokp233pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +INFO: a = PEER, b = LOKP233PE, c = VUUMEE, dblink = OOKEYY, nextpos = 28 +declare + name varchar2(50) := 'peer.233lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = , c = , dblink = , nextpos = 4 +/ +INFO: a = PEER, b = , c = , dblink = , nextpos = 4 +declare + name varchar2(50) := 'peer.-lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value "eer.-lokppe.vuumee@ookeyy" +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := 'peer."-lokppe".vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +INFO: a = PEER, b = -lokppe, c = VUUMEE, dblink = OOKEYY, nextpos = 28 +declare + name varchar2(50) := 'peer.lokp-pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = LOKP, c = , dblink = , nextpos = 9 +/ +INFO: a = PEER, b = LOKP, c = , dblink = , nextpos = 9 +declare + name varchar2(50) := 'peer.lokp=pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = LOKP, c = , dblink = , nextpos = 9 +/ +INFO: a = PEER, b = LOKP, c = , dblink = , nextpos = 9 +declare + name varchar2(50) := 'peer.=lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value "eer.=lokppe.vuumee@ookeyy" +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := 'peer.lokp`pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value "peer.lokp`pe.vuumee@ookeyy" with special character +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := 'peer.lokp~pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value "peer.lokp~pe.vuumee@ookeyy" with special character +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := 'peer.lokp%pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value "peer.lokp%pe.vuumee@ookeyy" with special character +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +-- test keyword +declare + name varchar2(50) := 'peer.table.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value "peer.table.vuumee@ookeyy" with special words +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +-- test @ +declare + name varchar2(50) := 'peer.lokppe.vuumee@'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value "peer.lokppe.vuumee@" with special words +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := 'peer.lokppe.vuumee@_ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- ok for og, error for A +/ +INFO: a = PEER, b = LOKPPE, c = VUUMEE, dblink = _OOKEYY, nextpos = 26 +declare + name varchar2(50) := 'peer.lokppe.vuumee@"_ookeyy"'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +INFO: a = PEER, b = LOKPPE, c = VUUMEE, dblink = _ookeyy, nextpos = 28 +declare + name varchar2(50) := 'peer.lokppe.vuumee@$ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- ok for og, error for A +/ +INFO: a = PEER, b = LOKPPE, c = VUUMEE, dblink = $OOKEYY, nextpos = 26 +declare + name varchar2(50) := 'peer.lokppe.vuumee@"$ookeyy"'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +INFO: a = PEER, b = LOKPPE, c = VUUMEE, dblink = $ookeyy, nextpos = 28 +declare + name varchar2(50) := 'peer.lokppe.vuumee@123ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid dblink value "peer.lokppe.vuumee@123ookeyy" +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := 'peer.lokppe.vuumee@ookeyy.zk'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +INFO: a = PEER, b = LOKPPE, c = VUUMEE, dblink = OOKEYY.ZK, nextpos = 28 +declare + name varchar2(50) := 'peer.lokppe.vuumee@'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value "peer.lokppe.vuumee@" with special words +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := '@vuumee'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value "@vuumee" with special words +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := 'peer.lokppe.vuumee@ook=eyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = LOKPPE, c = VUUMEE, dblink = OOK, nextpos = 22 +/ +INFO: a = PEER, b = LOKPPE, c = VUUMEE, dblink = OOK, nextpos = 22 +declare + name varchar2(50) := 'peer.lokppe.vuumee@=ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value "eer.lokppe.vuumee@=ookeyy" with special words +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +declare + name varchar2(50) := 'peer.lokppe.vuumee@ook%eyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value "peer.lokppe.vuumee@ook%eyy" with special character +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +-- test double quote +declare + name varchar2(50) := 'peer.lokppe.vuumee"@ookeyy"'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = LOKPPE, c = VUUMEE, dblink = , nextpos = 18 +/ +INFO: a = PEER, b = LOKPPE, c = VUUMEE, dblink = , nextpos = 18 +declare + name varchar2(50) := 'peer.lokppe.vu"ume"e@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = LOKPPE, c = VU, dblink = , nextpos = 14 +/ +INFO: a = PEER, b = LOKPPE, c = VU, dblink = , nextpos = 14 +declare + name varchar2(50) := 'peer.lokppe."vu"ume"e@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = LOKPPE, c = vu, dblink = , nextpos = 16 +/ +INFO: a = PEER, b = LOKPPE, c = vu, dblink = , nextpos = 16 +declare + name varchar2(50) := 'peer.lokppe.vuumee.aking@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: Invalid input value "peer.lokppe.vuumee.aking@ookeyy" +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +-- test idnetifier overlength. og >= 64, A >= 128 +declare + name varchar2(100) := 'peer.DoYouThinkCausalUnderstandingIsADefiningCharacteristicOfHumanCognition.vuumee.aking@ookeyy'; + a varchar2(100); + b varchar2(100); + c varchar2(100); + dblink varchar2(100); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +ERROR: identifier too long, max length is 64 +CONTEXT: PL/pgSQL function gms_utility.name_tokenize(character varying) line 4 at assignment +SQL statement "CALL gms_utility.name_tokenize(name,a,b,c,dblink,nextpos)" +PL/pgSQL function inline_code_block line 8 at SQL statement +drop schema test_utility_tokenize; +--------------------------- +-- name resolve +--------------------------- +reset search_path; +-- prepare data +CREATE TABLE public.t_resolve (c1 NUMBER, c2 VARCHAR2(100)); +CREATE UNIQUE INDEX IF NOT EXISTS public.t_resolve_c1_udx ON public.t_resolve(c1); +CREATE TABLE public.t_log (c1 NUMBER, c2 TIMESTAMP); +CREATE SEQUENCE IF NOT EXISTS public.t_seq + INCREMENT BY 1 + NOMINVALUE + NOMAXVALUE + START WITH 1 + NOCYCLE; +SELECT public.t_seq.NEXTVAL; + nextval +--------- + 1 +(1 row) + +CREATE OR REPLACE FUNCTION public.add_numbers ( + p_num1 IN INT, + p_num2 IN INT +) RETURN NUMBER IS + v_result INT; +BEGIN + v_result := p_num1 + p_num2; + RETURN v_result; +END; +/ +CREATE OR REPLACE PROCEDURE public.insert_val(name VARCHAR2(100)) IS + id INT := 0; +BEGIN + SELECT public.t_seq.NEXTVAL INTO id; + INSERT INTO public.t_resolve VALUES (id, name); +END; +/ +CREATE OR REPLACE FUNCTION public.tg_log() RETURNS TRIGGER AS +$$ +BEGIN + INSERT INTO public.t_log VALUES (NEW.c1, SYSDATE); + RETURN NEW; +END; +$$ LANGUAGE PLPGSQL; +CREATE TRIGGER log_resolve_after_insert +AFTER INSERT ON public.t_resolve +FOR EACH ROW +EXECUTE PROCEDURE public.tg_log(); +CREATE OR REPLACE PACKAGE public.t_pkg IS + FUNCTION multi_number(num1 IN INT, num2 IN INT) RETURN INT; + PROCEDURE delete_val(id IN INT); +END t_pkg; +/ +CREATE OR REPLACE PACKAGE BODY public.t_pkg IS + FUNCTION multi_number(num1 IN INT, num2 IN INT) RETURN INT IS + v_res INT; + BEGIN + v_res = num1 * num2; + return v_res; + END multi_number; + + PROCEDURE delete_val(id IN INT) AS + BEGIN + DELETE FROM t_resolve WHERE c1 = id; + END delete_val; +END t_pkg; +/ +CREATE TYPE public.t_typ AS (t1 INT, t2 TEXT); +CREATE OR REPLACE SYNONYM public.syn_tbl FOR t_resolve; +CREATE OR REPLACE SYNONYM public.syn_idx FOR t_resolve_c1_udx; +CREATE OR REPLACE SYNONYM public.syn_seq FOR t_seq; +CREATE OR REPLACE SYNONYM public.syn_fun FOR add_numbers; +CREATE OR REPLACE SYNONYM public.syn_pro FOR insert_val; +CREATE OR REPLACE SYNONYM public.syn_tg FOR log_resolve_after_insert; +CREATE OR REPLACE SYNONYM public.syn_pkg FOR t_pkg; +CREATE OR REPLACE SYNONYM public.syn_typ FOR t_typ; +-- test table +declare + name varchar2 := 'public.t_resolve'; + context number := 0; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_RESOLVE, part2 = , dblink = , part1_type = 2, object_number =.* +declare + name varchar2 := 't_resolve'; + context number := 0; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_RESOLVE, part2 = , dblink = , part1_type = 2, object_number =.* +declare + name varchar2 := 'public.syn_tbl'; + context number := 0; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_RESOLVE, part2 = , dblink = , part1_type = 2, object_number =.* +declare + name varchar2 := 'syn_tbl'; + context number := 0; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_RESOLVE, part2 = , dblink = , part1_type = 2, object_number =.* +-- test PL/SQL +declare + name varchar2 := 'public.add_numbers'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = , part2 = ADD_NUMBERS, dblink = , part1_type = 8, object_number =.* +declare + name varchar2 := 'add_numbers'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = , part2 = ADD_NUMBERS, dblink = , part1_type = 8, object_number =.* +declare + name varchar2 := 'public.syn_fun'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = , part2 = ADD_NUMBERS, dblink = , part1_type = 8, object_number =.* +declare + name varchar2 := 'syn_fun'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = , part2 = ADD_NUMBERS, dblink = , part1_type = 8, object_number =.* +declare + name varchar2 := 'public.insert_val'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = , part2 = INSERT_VAL, dblink = , part1_type = 7, object_number =.* +declare + name varchar2 := 'insert_val'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = , part2 = INSERT_VAL, dblink = , part1_type = 7, object_number =.* +declare + name varchar2 := 'public.syn_pro'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = , part2 = INSERT_VAL, dblink = , part1_type = 7, object_number =.* +declare + name varchar2 := 'syn_pro'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = , part2 = INSERT_VAL, dblink = , part1_type = 7, object_number =.* +-- test package +declare + name varchar2 := 'public.t_pkg.multi_number'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_PKG, part2 = MULTI_NUMBER, dblink = , part1_type = 9, object_number =.* +declare + name varchar2 := 'public.t_pkg.delete_val'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_PKG, part2 = DELETE_VAL, dblink = , part1_type = 9, object_number =.* +declare + name varchar2 := 'public.t_pkg.qwer'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_PKG, part2 = QWER, dblink = , part1_type = 9, object_number =.* +declare + name varchar2 := 't_pkg.multi_number'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_PKG, part2 = MULTI_NUMBER, dblink = , part1_type = 9, object_number =.* +declare + name varchar2 := 't_pkg.delete_val'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_PKG, part2 = DELETE_VAL, dblink = , part1_type = 9, object_number =.* +declare + name varchar2 := 't_pkg.qwer'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_PKG, part2 = QWER, dblink = , part1_type = 9, object_number =.* +declare + name varchar2 := 'public.syn_pkg.multi_number'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_PKG, part2 = MULTI_NUMBER, dblink = , part1_type = 9, object_number =.* +declare + name varchar2 := 'public.syn_pkg.delete_var'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_PKG, part2 = DELETE_VAR, dblink = , part1_type = 9, object_number =.* +declare + name varchar2 := 'public.syn_pkg.qwer'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_PKG, part2 = QWER, dblink = , part1_type = 9, object_number =.* +declare + name varchar2 := 'syn_pkg.multi_number'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_PKG, part2 = MULTI_NUMBER, dblink = , part1_type = 9, object_number =.* +declare + name varchar2 := 'syn_pkg.delete_var'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_PKG, part2 = DELETE_VAR, dblink = , part1_type = 9, object_number =.* +declare + name varchar2 := 'syn_pkg.qwer'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_PKG, part2 = QWER, dblink = , part1_type = 9, object_number =.* +-- test trigger +declare + name varchar2 := 'public.log_resolve_after_insert'; + context number := 3; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = LOG_RESOLVE_AFTER_INSERT, part2 = , dblink = , part1_type = 12, object_number =.* +declare + name varchar2 := 'public.syn_tg'; + context number := 3; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; -- error +/ +ERROR: The Object is not exists +CONTEXT: PL/pgSQL function gms_utility.name_resolve(character varying,numeric) line 4 at assignment +SQL statement "CALL gms_utility.name_resolve(name,context,schema,part1,part2,dblink,part1_type,object_number)" +PL/pgSQL function inline_code_block line 10 at SQL statement +declare + name varchar2 := 'log_resolve_after_insert'; + context number := 3; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = LOG_RESOLVE_AFTER_INSERT, part2 = , dblink = , part1_type = 12, object_number =.* +declare + name varchar2 := 'syn_tg'; + context number := 3; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; -- error +/ +ERROR: The Object is not exists +CONTEXT: PL/pgSQL function gms_utility.name_resolve(character varying,numeric) line 4 at assignment +SQL statement "CALL gms_utility.name_resolve(name,context,schema,part1,part2,dblink,part1_type,object_number)" +PL/pgSQL function inline_code_block line 10 at SQL statement +-- test sequence +declare + name varchar2 := 'public.t_seq'; + context number := 2; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_SEQ, part2 = , dblink = , part1_type = 6, object_number =.* +declare + name varchar2 := 'public.syn_seq'; + context number := 2; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_SEQ, part2 = , dblink = , part1_type = 6, object_number =.* +declare + name varchar2 := 't_seq'; + context number := 2; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_SEQ, part2 = , dblink = , part1_type = 6, object_number =.* +declare + name varchar2 := 'syn_seq'; + context number := 2; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_SEQ, part2 = , dblink = , part1_type = 6, object_number =.* +-- test type +declare + name varchar2 := 'public.t_typ'; + context number := 7; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_TYP, part2 = , dblink = , part1_type = 13, object_number =.* +declare + name varchar2 := 'public.syn_typ'; + context number := 7; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_TYP, part2 = , dblink = , part1_type = 13, object_number =.* +declare + name varchar2 := 't_typ'; + context number := 7; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_TYP, part2 = , dblink = , part1_type = 13, object_number =.* +declare + name varchar2 := 'syn_typ'; + context number := 7; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_TYP, part2 = , dblink = , part1_type = 13, object_number =.* +-- test index +declare + name varchar2 := 'public.t_resolve_c1_udx'; + context number := 9; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_RESOLVE_C1_UDX, part2 = , dblink = , part1_type = 1, object_number =.* +declare + name varchar2 := 'public.syn_idx'; + context number := 9; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; -- error +/ +ERROR: The Object is not exists +CONTEXT: PL/pgSQL function gms_utility.name_resolve(character varying,numeric) line 4 at assignment +SQL statement "CALL gms_utility.name_resolve(name,context,schema,part1,part2,dblink,part1_type,object_number)" +PL/pgSQL function inline_code_block line 10 at SQL statement +declare + name varchar2 := 't_resolve_c1_udx'; + context number := 9; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +--?INFO: schema = PUBLIC, part1 = T_RESOLVE_C1_UDX, part2 = , dblink = , part1_type = 1, object_number =.* +declare + name varchar2 := 'syn_idx'; + context number := 9; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; -- error +/ +ERROR: The Object is not exists +CONTEXT: PL/pgSQL function gms_utility.name_resolve(character varying,numeric) line 4 at assignment +SQL statement "CALL gms_utility.name_resolve(name,context,schema,part1,part2,dblink,part1_type,object_number)" +PL/pgSQL function inline_code_block line 10 at SQL statement +-- test java +declare + name varchar2 := 'public.java.class'; + context number := 4; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +ERROR: Unsupported context type: 4 +CONTEXT: PL/pgSQL function gms_utility.name_resolve(character varying,numeric) line 4 at assignment +SQL statement "CALL gms_utility.name_resolve(name,context,schema,part1,part2,dblink,part1_type,object_number)" +PL/pgSQL function inline_code_block line 10 at SQL statement +declare + name varchar2 := 'public.java.class'; + context number := 5; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +ERROR: Unsupported context type: 5 +CONTEXT: PL/pgSQL function gms_utility.name_resolve(character varying,numeric) line 4 at assignment +SQL statement "CALL gms_utility.name_resolve(name,context,schema,part1,part2,dblink,part1_type,object_number)" +PL/pgSQL function inline_code_block line 10 at SQL statement +declare + name varchar2 := 'public.java.class'; + context number := 6; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +ERROR: Unsupported context type: 6 +CONTEXT: PL/pgSQL function gms_utility.name_resolve(character varying,numeric) line 4 at assignment +SQL statement "CALL gms_utility.name_resolve(name,context,schema,part1,part2,dblink,part1_type,object_number)" +PL/pgSQL function inline_code_block line 10 at SQL statement +declare + name varchar2 := 'public.java.class'; + context number := 8; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +ERROR: Unsupported context type: 8 +CONTEXT: PL/pgSQL function gms_utility.name_resolve(character varying,numeric) line 4 at assignment +SQL statement "CALL gms_utility.name_resolve(name,context,schema,part1,part2,dblink,part1_type,object_number)" +PL/pgSQL function inline_code_block line 10 at SQL statement +-- test with dblink +declare + name varchar2 := 'peer.lokppe.vuumee@ookeyy'; + context number := 0; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +INFO: schema = PEER, part1 = LOKPPE, part2 = VUUMEE, dblink = OOKEYY, part1_type = 0, object_number = 0 +declare + name varchar2 := 'peer@ookeyy'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +INFO: schema = PEER, part1 = , part2 = , dblink = OOKEYY, part1_type = 0, object_number = 0 +declare + name varchar2 := 'peer@ookeyy'; + context number := 2; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +INFO: schema = PEER, part1 = , part2 = , dblink = OOKEYY, part1_type = 0, object_number = 0 +declare + name varchar2 := 'peer.@ookeyy'; + context number := 3; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; -- error +/ +ERROR: Invalid input value "peer.@ookeyy" with special words +CONTEXT: PL/pgSQL function gms_utility.name_resolve(character varying,numeric) line 4 at assignment +SQL statement "CALL gms_utility.name_resolve(name,context,schema,part1,part2,dblink,part1_type,object_number)" +PL/pgSQL function inline_code_block line 10 at SQL statement +declare + name varchar2 := 'peer.lokppe@ookeyy'; + context number := 7; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +INFO: schema = PEER, part1 = LOKPPE, part2 = , dblink = OOKEYY, part1_type = 0, object_number = 0 +declare + name varchar2 := 'peer.lokppe@ookeyy'; + context number := 9; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +INFO: schema = PEER, part1 = LOKPPE, part2 = , dblink = OOKEYY, part1_type = 0, object_number = 0 +declare + name varchar2 := 'peer.lokppe@ookeyy'; + context number := 10; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +INFO: schema = PEER, part1 = LOKPPE, part2 = , dblink = OOKEYY, part1_type = 0, object_number = 0 +DROP SYNONYM syn_tbl; +DROP SYNONYM syn_idx; +DROP SYNONYM syn_seq; +DROP SYNONYM syn_fun; +DROP SYNONYM syn_pro; +DROP SYNONYM syn_tg; +DROP SYNONYM syn_pkg; +DROP SYNONYM syn_typ; +DROP TYPE public.t_typ; +DROP PACKAGE BODY public.t_pkg; +DROP PACKAGE public.t_pkg; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to function public.multi_number(integer,integer) +drop cascades to function public.delete_val(integer) +DROP TRIGGER log_resolve_after_insert ON t_resolve; +DROP FUNCTION public.tg_log; +DROP FUNCTION public.add_numbers; +DROP PROCEDURE public.insert_val; +DROP INDEX public.t_resolve_c1_udx; +DROP TABLE public.t_log; +DROP TABLE public.t_resolve; +DROP SEQUENCE public.t_seq; +drop extension gms_utility cascade; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to table gms_utility.t_into +drop cascades to table gms_utility.num +reset search_path; diff --git a/contrib/gms_utility/gms_utility--1.0.sql b/contrib/gms_utility/gms_utility--1.0.sql new file mode 100644 index 000000000..7dc8ed6b4 --- /dev/null +++ b/contrib/gms_utility/gms_utility--1.0.sql @@ -0,0 +1,309 @@ +/* contrib/gms_utility/gms_utility--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION gms_utility" to load this file. \quit + +-- gms_utility package begin +-- gms_utility schema +CREATE SCHEMA gms_utility; +GRANT USAGE ON SCHEMA gms_utility TO PUBLIC; + + +/* + * ---------------------------- + * -- DB_VERSION + * ---------------------------- + */ +CREATE OR REPLACE PROCEDURE GMS_UTILITY.DB_VERSION( + version OUT varchar2, + compatibility OUT varchar2 +) +AS +BEGIN + version := 'openGauss ' || opengauss_version(); + compatibility := 'openGuass ' || opengauss_version(); +END; + + +/* +* ---------------------------- +* -- ANALYZE_SCHEMA +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.ANALYZE_SCHEMA_C_FUN ( + schema VARCHAR2, + method VARCHAR2, + estimate_rows NUMBER DEFAULT NULL, + estimate_percent NUMBER DEFAULT NULL, + method_opt VARCHAR2 DEFAULT NULL +) RETURNS void +AS 'MODULE_PATHNAME','gms_analyze_schema' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE OR REPLACE PROCEDURE GMS_UTILITY.ANALYZE_SCHEMA ( + schema IN VARCHAR2, + method IN VARCHAR2, + estimate_rows IN NUMBER DEFAULT NULL, + estimate_percent IN NUMBER DEFAULT NULL, + method_opt IN VARCHAR2 DEFAULT NULL +) +AS +BEGIN + GMS_UTILITY.ANALYZE_SCHEMA_C_FUN(schema, method, estimate_rows, estimate_percent, method_opt); +END; + +/* +* ---------------------------- +* -- ANALYZE_DATABASE +* ---------------------------- +*/ +CREATE OR REPLACE PROCEDURE GMS_UTILITY.ANALYZE_DATABASE ( + method IN VARCHAR2, + estimate_rows IN NUMBER DEFAULT NULL, + estimate_percent IN NUMBER DEFAULT NULL, + method_opt IN VARCHAR2 DEFAULT NULL +) +AS + schema_name text; +BEGIN + FOR schema_name IN SELECT nspname FROM pg_namespace + LOOP + GMS_UTILITY.ANALYZE_SCHEMA_C_FUN(schema_name, method, estimate_rows, estimate_percent, method_opt); + END LOOP; +END; + +/* +* ---------------------------- +* -- CANONICALIZE +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.CANONICALIZE_C_FUNC ( + name VARCHAR2, + canon_len INTEGER +) RETURNS VARCHAR2 +AS 'MODULE_PATHNAME','gms_canonicalize' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE OR REPLACE PROCEDURE GMS_UTILITY.CANONICALIZE ( + name IN VARCHAR2, + canon_name OUT VARCHAR2, + canon_len IN INTEGER +) +AS +BEGIN + if name IS NULL then + canon_name := NULL; + else + canon_name := GMS_UTILITY.CANONICALIZE_C_FUNC(name, canon_len); + end if; +END; + +/* +* ---------------------------- +* -- COMPILE_SCHEMA +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.COMPILE_SCHEMA_C_FUNC ( + schema VARCHAR2, + compile_all BOOLEAN DEFAULT TRUE, + reuse_settings BOOLEAN DEFAULT FALSE +) RETURNS void +AS 'MODULE_PATHNAME','gms_compile_schema' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE OR REPLACE PROCEDURE GMS_UTILITY.COMPILE_SCHEMA ( + schema IN VARCHAR2, + compile_all IN BOOLEAN DEFAULT TRUE, + reuse_settings IN BOOLEAN DEFAULT FALSE +) +AS +BEGIN + GMS_UTILITY.COMPILE_SCHEMA_C_FUNC(schema, compile_all, reuse_settings); +END; + +/* +* ---------------------------- +* -- EXPAND_SQL_TEXT +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.EXPAND_SQL_TEXT_C_FUNC ( + input_sql_text IN CLOB, + output_sql_text OUT CLOB +) +AS 'MODULE_PATHNAME','gms_expand_sql_text' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE OR REPLACE PROCEDURE GMS_UTILITY.EXPAND_SQL_TEXT ( + input_sql_text IN CLOB, + output_sql_text OUT CLOB +) +AS +BEGIN + output_sql_text := GMS_UTILITY.EXPAND_SQL_TEXT_C_FUNC(input_sql_text); +END; + +/* +* ---------------------------- +* -- GET_CPU_TIME +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.GET_CPU_TIME +RETURNS NUMBER +AS 'MODULE_PATHNAME','gms_get_cpu_time' +LANGUAGE C VOLATILE NOT FENCED; + +/* +* ---------------------------- +* -- GET_ENDIANNESS +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.GET_ENDIANNESS +RETURNS integer +AS 'MODULE_PATHNAME','gms_get_endianness' +LANGUAGE C VOLATILE NOT FENCED; + +/* +* ---------------------------- +* -- GET_SQL_HASH +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.GET_SQL_HASH_C_FUNC ( + name IN VARCHAR2, + hash OUT RAW, + pre10ihash OUT NUMBER +) +AS 'MODULE_PATHNAME','gms_get_sql_hash' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE OR REPLACE PROCEDURE GMS_UTILITY.GET_SQL_HASH ( + name IN VARCHAR2, + hash OUT RAW, + last4byte OUT NUMBER +) +AS + TYPE RET IS RECORD(hash RAW, last4byte NUMBER); + rec RET; +BEGIN + rec := GMS_UTILITY.GET_SQL_HASH_C_FUNC(name); + hash := rec.hash; + last4byte := rec.last4byte; +END; + +/* +* ---------------------------- +* -- NAME_TOKENIZE +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.NAME_TOKENIZE_C_FUNC ( + name IN VARCHAR2, + a OUT VARCHAR2, + b OUT VARCHAR2, + c OUT VARCHAR2, + dblink OUT VARCHAR2, + nextpos OUT BINARY_INTEGER +) +AS 'MODULE_PATHNAME','gms_name_tokenize' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE OR REPLACE PROCEDURE GMS_UTILITY.NAME_TOKENIZE ( + name IN VARCHAR2, + a OUT VARCHAR2, + b OUT VARCHAR2, + c OUT VARCHAR2, + dblink OUT VARCHAR2, + nextpos OUT BINARY_INTEGER +) +AS + TYPE RET IS RECORD(a VARCHAR2, b VARCHAR2, c VARCHAR2, dblink VARCHAR2, nextpos INT); + rec RET; +BEGIN + rec := GMS_UTILITY.NAME_TOKENIZE_C_FUNC(name); + a := rec.a; + b := rec.b; + c := rec.c; + dblink := rec.dblink; + nextpos := rec.nextpos; +END; + +/* +* ---------------------------- +* -- NAME_RESOLVE +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.NAME_RESOLVE_C_FUNC ( + name IN VARCHAR2, + context IN NUMBER, + schema OUT VARCHAR2, + part1 OUT VARCHAR2, + part2 OUT VARCHAR2, + dblink OUT VARCHAR2, + part1_type OUT NUMBER, + object_number OUT NUMBER +) +AS 'MODULE_PATHNAME','gms_name_resolve' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE OR REPLACE PROCEDURE GMS_UTILITY.NAME_RESOLVE ( + name IN VARCHAR2, + context IN NUMBER, + schema OUT VARCHAR2, + part1 OUT VARCHAR2, + part2 OUT VARCHAR2, + dblink OUT VARCHAR2, + part1_type OUT NUMBER, + object_number OUT NUMBER +) +AS + TYPE RET IS RECORD(s VARCHAR2, p1 VARCHAR2, p2 VARCHAR2, dblink VARCHAR2, p1_type NUMBER, obj_num NUMBER); + rec RET; +BEGIN + rec := GMS_UTILITY.NAME_RESOLVE_C_FUNC(name, context); + schema := rec.s; + part1 := rec.p1; + part2 := rec.p2; + dblink := rec.dblink; + part1_type := rec.p1_type; + object_number := rec.obj_num; +END; + +/* +* ---------------------------- +* -- IS_BIT_SET +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.IS_BIT_SET ( + r IN RAW, + n IN NUMBER +) RETURNS NUMBER +AS 'MODULE_PATHNAME','gms_is_bit_set' +LANGUAGE C VOLATILE NOT FENCED; + +/* +* ---------------------------- +* -- IS_CLUSTER_DATABASE +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.IS_CLUSTER_DATABASE () +RETURNS BOOLEAN +AS $$ SELECT FALSE::BOOLEAN $$ +LANGUAGE SQL IMMUTABLE STRICT; + +/* +* ---------------------------- +* -- OLD_CURRENT_SCHEMA +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.OLD_CURRENT_SCHEMA () +RETURNS VARCHAR2 +AS 'MODULE_PATHNAME','gms_old_current_schema' +LANGUAGE C VOLATILE NOT FENCED; + +/* +* ---------------------------- +* -- OLD_CURRENT_USER +* ---------------------------- +*/ +CREATE OR REPLACE FUNCTION GMS_UTILITY.OLD_CURRENT_USER () +RETURNS VARCHAR2 +AS $$ SELECT CURRENT_USER::VARCHAR2 $$ +LANGUAGE SQL IMMUTABLE STRICT; \ No newline at end of file diff --git a/contrib/gms_utility/gms_utility.control b/contrib/gms_utility/gms_utility.control new file mode 100644 index 000000000..2d08024b3 --- /dev/null +++ b/contrib/gms_utility/gms_utility.control @@ -0,0 +1,5 @@ +# gms_utility extension +comment = 'collection of gms_utility for PL/SQL applications' +default_version = '1.0' +module_pathname = '$libdir/gms_utility' +relocatable = true \ No newline at end of file diff --git a/contrib/gms_utility/gms_utility.cpp b/contrib/gms_utility/gms_utility.cpp new file mode 100644 index 000000000..89f0c24d3 --- /dev/null +++ b/contrib/gms_utility/gms_utility.cpp @@ -0,0 +1,1658 @@ +/* + * Copyright (c) 2024 Huawei Technologies Co.,Ltd. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * -------------------------------------------------------------------------------------- + * + * gms_utility.cpp + * gms_utility provides various utility subprograms. + * + * + * IDENTIFICATION + * contrib/gms_utility/gms_utility.cpp + * + * -------------------------------------------------------------------------------------- + */ +#include "postgres.h" +#include "funcapi.h" +#include "fmgr.h" + +#include "access/skey.h" +#include "access/heapam.h" +#include "catalog/indexing.h" +#include "catalog/heap.h" +#include "commands/sqladvisor.h" +#include "commands/vacuum.h" +#include "executor/spi.h" +#include "lib/stringinfo.h" +#include "libpq/md5.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" +#include "utils/numeric.h" +#include "utils/numeric_gs.h" +#include "tcop/tcopprot.h" +#include "parser/keywords.h" +#include "gms_utility.h" + +PG_MODULE_MAGIC; + +static const char CANON_INVALID_CHARS[] = + {'`', '~', '!', '@', '%', '^', '&', '*', '(', ')', '-', '=', '+', '[', ']', + '{', '}', '/', '\\', '|', ';', ':', '?', '<', '>'}; +static const char VALID_IDENT_CHARS[] = {'#', '$', '_'}; + +static const char TOKENIZE_DANGER_CHARS[] = {'`', '~', '%', '\\', ';', '?'}; +static const char TOKENIZE_TRUNCATE_CHARS[] = + {'!', '^', '&', '*', '(', ')', '-', '=', '+', '[', ']', '{', '}', '/', '|', ':', '<', '>'}; + +typedef Oid (*SearchOidByName)(Oid namespaceId, char* name, NameResolveVar* var); + +static List* GetRelationsInSchema(char *namespc); +static void DoAnalyzeSchemaStatistic(char* schema, AnalyzeVar* var, AnalyzeMethodOpt methodOpt); +static void DoDeleteSchemaStatistic(char* schema); +static bool DetectKeyword(char* words); +static bool CheckLegalIdenty(char* w, bool checkDigital, bool checkKeyword); +static TokenizeVar* MakeTokenizeVar(); +static void DestoryTokenizeVar(TokenizeVar* var); +static TokenizeVar* NameParseInternal(char* name, int len); +static void ResolveContextName(NameResolveContext context, Oid namespaceId, char* resolveName, + NameResolveVar* var, SearchOidByName searchmtd); + +PG_FUNCTION_INFO_V1(gms_analyze_schema); +PG_FUNCTION_INFO_V1(gms_canonicalize); +PG_FUNCTION_INFO_V1(gms_compile_schema); +PG_FUNCTION_INFO_V1(gms_expand_sql_text); +PG_FUNCTION_INFO_V1(gms_get_cpu_time); +PG_FUNCTION_INFO_V1(gms_get_endianness); +PG_FUNCTION_INFO_V1(gms_get_sql_hash); +PG_FUNCTION_INFO_V1(gms_name_tokenize); +PG_FUNCTION_INFO_V1(gms_name_resolve); +PG_FUNCTION_INFO_V1(gms_is_bit_set); +PG_FUNCTION_INFO_V1(gms_old_current_schema); + +static List* GetIndexColName(List* colnamesList, Oid relid, int2 attnum) +{ + if (attnum <= 0) { + /* Hidden columns */ + return colnamesList; + } + + char* colname = NULL; + Form_pg_attribute pgAttributeTuple = NULL; + HeapTuple attrTuple; + + attrTuple = SearchSysCache2(ATTNUM, ObjectIdGetDatum(relid), Int16GetDatum(attnum)); + if (!HeapTupleIsValid(attrTuple)) { + return colnamesList; + } + pgAttributeTuple = (Form_pg_attribute)GETSTRUCT(attrTuple); + colnamesList = lappend(colnamesList, pstrdup(pgAttributeTuple->attname.data)); + + ReleaseSysCache(attrTuple); + return colnamesList; +} + +static void VacuumTableAclCheck(Oid relid, char* relname) +{ + AclResult aclresult = pg_class_aclcheck(relid, GetUserId(), ACL_VACUUM); + HeapTuple tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + Form_pg_class rel = (Form_pg_class)GETSTRUCT(tuple); + + if (aclresult != ACLCHECK_OK && + !(pg_class_ownercheck(relid, GetUserId()) || + (pg_database_ownercheck(u_sess->proc_cxt.MyDatabaseId, GetUserId()) && !rel->relisshared) || + (isOperatoradmin(GetUserId()) && u_sess->attr.attr_security.operation_mode))) { + ReleaseSysCache(tuple); + aclcheck_error(aclresult, ACL_KIND_CLASS, relname); + } + + ReleaseSysCache(tuple); +} + +static List* GetRelationsInSchema(char *namespc) +{ + Relation pgClassRel = NULL; + ScanKeyData skey[1]; + SysScanDesc sysscan; + HeapTuple tuple; + List* tbl_relnames = NIL; + Oid nspid; + + nspid = get_namespace_oid(namespc, false); + + ScanKeyInit(&skey[0], Anum_pg_class_relnamespace, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(nspid)); + pgClassRel = heap_open(RelationRelationId, AccessShareLock); + sysscan = systable_beginscan(pgClassRel, InvalidOid, false, SnapshotNow, 1, skey); + while (HeapTupleIsValid(tuple = systable_getnext(sysscan))) { + Form_pg_class reltup = (Form_pg_class)GETSTRUCT(tuple); + if ((reltup->relkind == RELKIND_RELATION || reltup->relkind == RELKIND_MATVIEW) + && !(reltup->relpersistence == RELPERSISTENCE_TEMP + || reltup->relpersistence == RELPERSISTENCE_GLOBAL_TEMP)) { + VacuumTableAclCheck(HeapTupleGetOid(tuple), reltup->relname.data); + tbl_relnames = lappend(tbl_relnames, pstrdup(reltup->relname.data)); + } + } + systable_endscan(sysscan); + heap_close(pgClassRel, AccessShareLock); + return tbl_relnames; +} + +static char* GetIndexNameById(Oid indexoid) +{ + char* indexName = NULL; + HeapTuple idxRelTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(indexoid)); + if (!HeapTupleIsValid(idxRelTuple)) { + return NULL; + } + Form_pg_class reltup = (Form_pg_class)GETSTRUCT(idxRelTuple); + indexName = pstrdup(reltup->relname.data); + + ReleaseSysCache(idxRelTuple); + + return indexName; +} + +static List* GetAllIndexColumnNames(char* schemaname, char* relname) +{ + List* colnamesList = NIL; + Oid relid = InvalidOid; + Oid namespaceId = InvalidOid; + ScanKeyData skey[1]; + SysScanDesc sysscan; + Relation indexRel; + HeapTuple idxTuple; + Form_pg_index pgIndexTuple; + int n; + + namespaceId = LookupExplicitNamespace(schemaname); + relid = get_relname_relid(relname, namespaceId); + + ScanKeyInit(&skey[0], Anum_pg_index_indrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(relid)); + indexRel = heap_open(IndexRelationId, AccessShareLock); + sysscan = systable_beginscan(indexRel, IndexIndrelidIndexId, true, SnapshotNow, 1, skey); + while (HeapTupleIsValid(idxTuple = systable_getnext(sysscan))) { + pgIndexTuple = (Form_pg_index)GETSTRUCT(idxTuple); + if (!(IndexIsUsable(pgIndexTuple) && IndexIsValid(pgIndexTuple) + && GetIndexEnableStateByTuple(idxTuple))) { + systable_endscan(sysscan); + heap_close(indexRel, AccessShareLock); + ereport(ERROR, (errcode(ERRCODE_INVALID_STATUS), + errmsg("index \"%s\" is not available", GetIndexNameById(pgIndexTuple->indexrelid)))); + } + for (n = 0; n < pgIndexTuple->indnatts; n++) { + colnamesList = GetIndexColName(colnamesList, relid, pgIndexTuple->indkey.values[n]); + } + } + systable_endscan(sysscan); + heap_close(indexRel, AccessShareLock); + + return colnamesList; +} + +static void UpdateRelTuplesAndPages(Oid relid) +{ + Relation pgClassRel = NULL; + HeapTuple tuple; + HeapTuple newtuple; + Form_pg_class reltuple; + Datum values[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; + bool replaces[Natts_pg_class] = {false}; + + pgClassRel = heap_open(RelationRelationId, RowExclusiveLock); + tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid)); + if (!HeapTupleIsValid(tuple)) { + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("cache lookup failed for relation %u", relid))); + } + + reltuple = (Form_pg_class)GETSTRUCT(tuple); + values[Anum_pg_class_relpages - 1] = Float8GetDatum(0); + replaces[Anum_pg_class_relpages - 1] = true; + values[Anum_pg_class_reltuples - 1] = Float8GetDatum(0); + replaces[Anum_pg_class_reltuples - 1] = true; + + newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgClassRel), values, nulls, replaces); + simple_heap_update(pgClassRel, &newtuple->t_self, newtuple); + + CatalogUpdateIndexes(pgClassRel, newtuple); + + heap_freetuple_ext(tuple); + heap_freetuple_ext(newtuple); + + heap_close(pgClassRel, RowExclusiveLock); +} + +static AnalyzeMethodOpt GetMethodOpFromStr(char* val) +{ + bool canFollowSize = false; + int offsetSize = 0; + AnalyzeMethodOpt opt; + char* str = val; + + if (0 == strncasecmp(str, "FORTABLE", 8)) { + opt = METHOD_OPT_TABLE; + offsetSize = 8; + } else if (0 == strncasecmp(str, "FORALLINDEXES", 13)) { + opt = METHOD_OPT_ALL_INDEX; + offsetSize = 13; + } else if (0 == strncasecmp(str, "FORALLCOLUMNS", 13)) { + opt = METHOD_OPT_ALL_COLUMN; + canFollowSize = true; + offsetSize = 13; + } else if (0 == strncasecmp(str, "FORALLINDEXEDCOLUMNS", 20)) { + opt = METHOD_OPT_ALL_INDEX; + canFollowSize = true; + offsetSize = 20; + } else { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_KEY), errmsg("unrecognized param value"))); + } + + str += offsetSize; + + if (canFollowSize) { + if (*str == '\0') { + return opt; + } + + if (0 != strncasecmp(str, "SIZE", 4)) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_KEY), errmsg("unrecognized param value"))); + } + + str += 4; + if (1 != sscanf(str, "%d", &offsetSize) || offsetSize <= 0) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_KEY), errmsg("unrecognized param value"))); + } + } else { + if (*str != '\0') { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid input value for method_opt"))); + } + } + return opt; +} + +static char* GetNextTokenSplitBySpace(char* val, int* travelLen) +{ + int len = 0; + char* result; + char* str = val + *travelLen; + + while (*str != '\0' && isspace((unsigned char)*str)) { + str++; + (*travelLen)++; + } + while (*(str + len) != '\0' && !isspace((unsigned char)*(str + len))) { + len++; + } + (*travelLen) += len; + if (len == 0) return NULL; + + result = (char *) palloc0(len + 1); + errno_t rc = memcpy_s(result, len + 1, str, len); + securec_check(rc, "\0", "\0"); + + return result; +} + +static AnalyzeMethodOpt HandleMethodOpt(text* methodOpt) +{ + if (NULL == methodOpt) { + return METHOD_OPT_TABLE; + } + char* str = TextDatumGetCString(methodOpt); + char* token; + int travelLen; + StringInfo format; + AnalyzeMethodOpt tOpt; + AnalyzeMethodOpt opt = METHOD_OPT_ALL_INDEX; + + format = makeStringInfo(); + travelLen = 0; + + while ((token = GetNextTokenSplitBySpace(str, &travelLen)) != NULL) { + if (format->len == 0 && 0 != strcasecmp(token, "FOR")) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_KEY), + errmsg("unrecognized param value: \"%s\"", str))); + } + if (0 == strcasecmp(token, "FOR") && format->len > 0) { + tOpt = GetMethodOpFromStr(format->data); + opt = (int)tOpt < (int)opt ? tOpt : opt; + resetStringInfo(format); + } + appendStringInfo(format, "%s", token); + + pfree(token); + token = NULL; + } + pfree_ext(str); + + tOpt = GetMethodOpFromStr(format->data); + opt = (int)tOpt < (int)opt ? tOpt : opt; + + DestroyStringInfo(format); + + return opt; +} + +static AnalyzeVar* MakeAnalyzeVar(char* method, FunctionCallInfo fcinfo, int argOffset) +{ + Numeric estimateRows; + Numeric estimatePercent; + AnalyzeVar* result = (AnalyzeVar *) palloc(sizeof(AnalyzeVar)); + result->isEstimate = 0 == pg_strcasecmp(method, "ESTIMATE"); + if (!result->isEstimate) { + return result; + } + result->validRows = !PG_ARGISNULL(argOffset); + result->validPercent = !PG_ARGISNULL(argOffset + 1); + + if(result->validRows) { + estimateRows = PG_GETARG_NUMERIC(argOffset); + int64 rows = convert_short_numeric_to_int64_byscale(estimateRows, NUMERIC_DSCALE(estimateRows)); + if (rows < 0) { + pfree(result); + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("invalid value \"%ld\" for \"estimate_rows\"", rows))); + } + result->estimateRows = rows; + } + if (!result->validRows && result->validPercent) { + estimatePercent = PG_GETARG_NUMERIC(argOffset + 1); + int64 percent = convert_short_numeric_to_int64_byscale(estimatePercent, NUMERIC_DSCALE(estimatePercent)); + if (percent < 0 || percent > 100) { + pfree(result); + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("invalid value \"%ld\" for \"estimate_percent\"", percent))); + } + result->estimatePercent = percent; + } + + return result; +} + +Datum gms_analyze_schema(PG_FUNCTION_ARGS) +{ + char* schema; + char* method; + AnalyzeMethodOpt analyzeMethodOpt; + AnalyzeVar* var; + + if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Unsupported NULL input value"))); + } + + schema = TextDatumGetCString(PG_GETARG_TEXT_P(0)); + method = TextDatumGetCString(PG_GETARG_TEXT_P(1)); + if (PG_ARGISNULL(4)) { + analyzeMethodOpt = METHOD_OPT_TABLE; + } else { + analyzeMethodOpt = HandleMethodOpt(PG_GETARG_TEXT_P(4)); + } + + if (0 == pg_strcasecmp(method, "ESTIMATE") || 0 == pg_strcasecmp(method, "COMPUTE")) { + var = MakeAnalyzeVar(method, fcinfo, 2); + DoAnalyzeSchemaStatistic(schema, var, analyzeMethodOpt); + pfree(var); + } else if (0 == pg_strcasecmp(method, "DELETE")) { + if (!PG_ARGISNULL(4)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("The Command did not end correctly"))); + } + DoDeleteSchemaStatistic(schema); + } else { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_KEY), + errmsg("Unrecognized param value: \"%s\"", method))); + } + + PG_RETURN_VOID(); +} + +static void DoAnalyzeSchemaStatistic(char* schema, AnalyzeVar* var, AnalyzeMethodOpt methodOpt) +{ + List* relnamesList; + List* colnamesList; + ListCell* lcRel; + ListCell* lcCol; + StringInfo executeSql; + VacuumStmt* stmt; + int saveEstimate; + + relnamesList = GetRelationsInSchema(schema); + executeSql = makeStringInfo(); + + if (var->isEstimate) { + saveEstimate = default_statistics_target; + default_statistics_target = var->validRows ? var->estimateRows + : var->validPercent ? -(var->estimatePercent) + : default_statistics_target; + } + + foreach(lcRel, relnamesList) { + char* relname = (char*)lfirst(lcRel); + appendStringInfo(executeSql, "ANALYZE %s.%s", quote_identifier(schema), quote_identifier(relname)); + if (methodOpt == METHOD_OPT_ALL_INDEX) { + colnamesList = GetAllIndexColumnNames(schema, relname); + if (colnamesList != NIL && list_length(colnamesList) > 0) { + appendStringInfo(executeSql, "("); + + int n = 0, colSize = list_length(colnamesList); + foreach(lcCol, colnamesList) { + char* colname = (char*)lfirst(lcCol); + appendStringInfo(executeSql, "%s", quote_identifier(colname)); + if (++n < colSize) { + appendStringInfo(executeSql, ","); + } + pfree(colname); + } + appendStringInfo(executeSql, ")"); + } + list_free(colnamesList); + } + appendStringInfo(executeSql, ";"); + + List* parsetree_list = NULL; + ListCell* parsetree_item = NULL; + parsetree_list = raw_parser(executeSql->data, NULL); + foreach (parsetree_item, parsetree_list) { + Node* parsetree = (Node*)lfirst(parsetree_item); + stmt = (VacuumStmt*)parsetree; + } + vacuum(stmt, InvalidOid, true, NULL, true); + + pfree_ext(relname); + list_free(parsetree_list); + resetStringInfo(executeSql); + } + + default_statistics_target = saveEstimate; + + DestroyStringInfo(executeSql); + list_free(relnamesList); +} + +static void DoDeleteSchemaStatistic(char* schema) +{ + List* relnamesList; + ListCell* lcRel; + Oid relid = InvalidOid; + Oid namespaceId = InvalidOid; + + namespaceId = LookupExplicitNamespace(schema); + relnamesList = GetRelationsInSchema(schema); + foreach(lcRel, relnamesList) { + char* relname = (char*)lfirst(lcRel); + + relid = get_relname_relid(relname, namespaceId); + RemoveStatistics<'c'>(relid, 0); + UpdateRelTuplesAndPages(relid); + + pfree_ext(relname); + } + list_free(relnamesList); +} + +static bool InvalidCanonChars(char val) +{ + for (char c : CANON_INVALID_CHARS) { + if (c == val) return true; + } + return false; +} + +/* + * Check for keyword. return true except for unreserved ones. + */ +static bool DetectKeyword(char* w) +{ + int len = strlen(w); + if (len <= 0) { + return true; + } + + char* str = (char *) palloc0(len + 1); + errno_t rc = memcpy_s(str, len + 1, w, len); + securec_check(rc, "\0", "\0"); + str = pg_strtolower(str); + int kwnum = ScanKeywordLookup(str, &ScanKeywords); + pfree_ext(str); + + return kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD; +} + +static bool CheckLegalIdenty(char* w, bool checkDigital, bool checkKeyword) +{ + if (strlen(w) >= NAMEDATALEN) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("identifier too long, max length is %d", NAMEDATALEN))); + } + /* For gms_canonicalize, legual identy must not start with digit */ + if (checkDigital && isdigit(*w)) { + return false; + } + if (checkKeyword && DetectKeyword(w)) { + return false; + } + return true; +} + +Datum gms_canonicalize(PG_FUNCTION_ARGS) +{ + char* name; + int32 canonLen; + int len; + bool dotted = false; + StringInfo tmp; + StringInfo result; + bits8 quoteState = QUOTE_NONE; + char curChar = '\0'; + int traveLen = 0; + text* output; + + if (PG_ARGISNULL(0)) { + PG_RETURN_NULL(); + } + if (PG_ARGISNULL(1)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Input parameter \"canon_len\" is NULL"))); + } + + name = TextDatumGetCString(PG_GETARG_TEXT_P(0)); + len = VARSIZE_ANY_EXHDR(PG_GETARG_TEXT_P(0)); + canonLen = PG_GETARG_INT32(1); + + if (canonLen < 0) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Input parameter \"canon_len\" value \"%d\" is less than zero", canonLen))); + } + + tmp = makeStringInfo(); + result = makeStringInfo(); + + while (*name != '\0' && traveLen < len) { + curChar = *name; + traveLen++; + name++; + + if (!IS_QUOTE_STARTED(quoteState) && curChar == ' ') { + continue; + } else if (curChar == '"') { + if (BEFORE_QUOTE_STARTED(quoteState)) { + if (tmp->len != 0) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid parameter value \"%s\" before quotation", (name - traveLen)))); + } + quoteState = QUOTE_STARTED; + } else if (IS_QUOTE_STARTED(quoteState)) { + if (tmp->len == 0) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid paramter value \"%s\" with zero length", (name - traveLen)))); + } + quoteState = QUOTE_ENDED; + } else { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid parameter value \"%s\" after quotation", (name - traveLen)))); + } + } else if (curChar == '.') { + if (IS_QUOTE_STARTED(quoteState)) { + appendStringInfoChar(tmp, curChar); + } else { + dotted = true; + if (BEFORE_QUOTE_STARTED(quoteState) && !CheckLegalIdenty(tmp->data, true, dotted)) { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid paramter value \"%s\" with special words", (name - traveLen)))); + } + if (tmp->len == 0) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid paramter value \"%s\" with zero length", (name - traveLen)))); + } + appendStringInfo(result, dotted ? "\"%s\"." : "%s.", tmp->data); + resetStringInfo(tmp); + quoteState = QUOTE_NONE; + } + } else { + if (IS_QUOTE_STARTED(quoteState)) { + appendStringInfoChar(tmp, curChar); + } else if (IS_QUOTE_END(quoteState)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid parameter value \"%s\" after quotation", (name - traveLen)))); + } else { + if (InvalidCanonChars(curChar)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid paramter value \"%s\" with special character", (name - traveLen)))); + } + appendStringInfoChar(tmp, pg_toupper(curChar)); + } + } + } + + if (IS_QUOTE_STARTED(quoteState)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid paramter value \"%s\" with quotation not closed", (name - traveLen)))); + } + if (dotted && tmp->len == 0) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid paramter value \"%s\"", (name - traveLen)))); + } + if (tmp->len > 0) { + if (BEFORE_QUOTE_STARTED(quoteState) && !CheckLegalIdenty(tmp->data, true, dotted)) { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid paramter value \"%s\" with special words", (name - traveLen)))); + } + appendStringInfo(result, dotted ? "\"%s\"" : "%s", tmp->data); + } + + traveLen = strlen(result->data); + canonLen = canonLen < traveLen ? canonLen : traveLen; + output = cstring_to_text_with_len(result->data, canonLen); + + DestroyStringInfo(tmp); + DestroyStringInfo(result); + + PG_RETURN_TEXT_P(output); +} + +static void DoCompileFuncAndProcedure(Oid namespaceId, bool compileAll) +{ + Relation pgProcRel = NULL; + ScanKeyData skey[1]; + SysScanDesc sysscan; + HeapTuple tuple; + bool isNull = false; + Oid funcOid; + Oid pkgOid; + char pprokind; + + ScanKeyInit(&skey[0], Anum_pg_proc_pronamespace, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(namespaceId)); + pgProcRel = heap_open(ProcedureRelationId, AccessShareLock); + sysscan = systable_beginscan(pgProcRel, InvalidOid, false, SnapshotNow, 1, skey); + while (HeapTupleIsValid(tuple = systable_getnext(sysscan))) { + funcOid = HeapTupleGetOid(tuple); + if (!compileAll && GetPgObjectValid(funcOid, OBJECT_TYPE_PROC)) { + continue; + } + pprokind = CharGetDatum(SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prokind, &isNull)); + if (!isNull && (PROC_IS_FUNC(pprokind) || PROC_IS_PRO(pprokind))) { + pkgOid = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_packageid, &isNull); + /* If function or procedure is belong to a package, don't recompile here */ + if (!OidIsValid(pkgOid)) { + RecompileSingleFunction(funcOid, PROC_IS_PRO(pprokind)); + } + } + } + systable_endscan(sysscan); + heap_close(pgProcRel, AccessShareLock); +} + +static void DoCompilePackage(Oid namespaceId, bool compileAll) +{ + Relation pgPkgRel = NULL; + ScanKeyData skey[1]; + SysScanDesc sysscan; + HeapTuple tuple; + bool isNull = false; + Oid pkgOid; + + ScanKeyInit(&skey[0], Anum_gs_package_pkgnamespace, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(namespaceId)); + pgPkgRel = heap_open(PackageRelationId, AccessShareLock); + sysscan = systable_beginscan(pgPkgRel, InvalidOid, false, SnapshotNow, 1, skey); + while (HeapTupleIsValid(tuple = systable_getnext(sysscan))) { + SysCacheGetAttr(PACKAGEOID, tuple, Anum_gs_package_pkgbodydeclsrc, &isNull); + pkgOid = HeapTupleGetOid(tuple); + if (!compileAll && GetPgObjectValid(pkgOid, isNull ? OBJECT_TYPE_PKGSPEC : OBJECT_TYPE_PKGBODY)) { + continue; + } + if (OidIsValid(pkgOid)) { + RecompileSinglePackage(pkgOid, isNull); + } + } + systable_endscan(sysscan); + heap_close(pgPkgRel, AccessShareLock); +} + +static void DoCompileView(Oid namespaceId, bool compileAll) +{ + Relation pgClassRel = NULL; + ScanKeyData skey[2]; + SysScanDesc sysscan; + HeapTuple tuple; + List* records = NIL; + Oid viewOid; + + ScanKeyInit(&skey[0], Anum_pg_class_relnamespace, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(namespaceId)); + ScanKeyInit(&skey[1], Anum_pg_class_relkind, BTEqualStrategyNumber, F_CHAREQ, CharGetDatum(RELKIND_VIEW)); + pgClassRel = heap_open(RelationRelationId, AccessShareLock); + sysscan = systable_beginscan(pgClassRel, InvalidOid, false, SnapshotNow, 2, skey); + while (HeapTupleIsValid(tuple = systable_getnext(sysscan))) { + viewOid = HeapTupleGetOid(tuple); + if (!ValidateDependViewDetectRecursion(viewOid, OBJECT_TYPE_VIEW, compileAll, records)) { + Form_pg_class reltup = (Form_pg_class)GETSTRUCT(tuple); + ereport(WARNING, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("Compile view \"%s\" failed", reltup->relname.data))); + } + } + list_free(records); + systable_endscan(sysscan); + heap_close(pgClassRel, AccessShareLock); +} + +Datum gms_compile_schema(PG_FUNCTION_ARGS) +{ + char* nspname; + bool compileAll; + Oid namespaceId; + + if (PG_ARGISNULL(0)) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_SCHEMA), + errmsg("Input parameter \"schema\" is NULL"))); + } + + nspname = TextDatumGetCString(PG_GETARG_TEXT_P(0)); + compileAll = PG_GETARG_BOOL(1); + + namespaceId = get_namespace_oid(nspname, true); + if (!OidIsValid(namespaceId)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("schema \"%s\" does not exists", nspname))); + } + + DoCompileFuncAndProcedure(namespaceId, compileAll); + + DoCompilePackage(namespaceId, compileAll); + + DoCompileView(namespaceId, compileAll); + + /* Trigger compilation is not yet supported */ + PG_RETURN_VOID(); +} + +Datum gms_expand_sql_text(PG_FUNCTION_ARGS) +{ + text* inputSqlText; + char* inputSql = NULL; + text* result; + List* parsetreeList = NIL; + List* rewriteList = NIL; + Node* parseNode; + Query* query; + StringInfo buf; + + if (PG_ARGISNULL(0)) { + PG_RETURN_NULL(); + } + + inputSqlText = PG_GETARG_TEXT_P(0); + FUNC_CHECK_HUGE_POINTER(false, inputSqlText, "gms_expand_sql_text"); + + inputSql = TextDatumGetCString(inputSqlText); + parsetreeList = pg_parse_query(inputSql); + + if (list_length(parsetreeList) != 1) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Expand_sql_text only support one query"))); + } + parseNode = (Node*) linitial(parsetreeList); + if (!IsA(parseNode, SelectStmt)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Unsupported query type, only support SELECT query"))); + } + + rewriteList = pg_analyze_and_rewrite(parseNode, inputSql, NULL, 0); + query = (Query *) linitial(rewriteList); + buf = makeStringInfo(); +#ifdef PGXC + deparse_query(query, buf, NIL, false, false); +#else + get_query_def(query, buf, NIL, NULL, PRETTYFLAG_PAREN, WRAP_COLUMN_DEFAULT, 0); +#endif + + result = cstring_to_text(buf->data); + + list_free(parsetreeList); + list_free(rewriteList); + DestroyStringInfo(buf); + + PG_RETURN_TEXT_P(result); +} + +Datum gms_get_cpu_time(PG_FUNCTION_ARGS) +{ + int64 result; + + clock_t clk = clock(); + /* get_cpu_time returns the number of 100th's of a second */ + result = (int64) (clk / (CLOCKS_PER_SEC / 100)); + + return DirectFunctionCall1(int8_numeric, Int64GetDatum(result)); +} + +Datum gms_get_endianness(PG_FUNCTION_ARGS) +{ + int32 result; + /* 1 for big-endian or 2 for little-endian */ + union { + uint32_t num; + uint8_t bytes[4]; + } u_num; + u_num.num = 0x12345678; + if (u_num.bytes[0] == 0x12) { + result = 1; + } else if (u_num.bytes[0] == 0x78) { + result = 2; + } else { + ereport(ERROR, (errmsg("unkonwn endianness"))); + } + PG_RETURN_INT32(result); +} + +Datum gms_get_sql_hash(PG_FUNCTION_ARGS) +{ + text* sqlText; + int len; + char hexsum[MD5_HASH_LEN + 1] = "\0"; + StringInfo buf; + int64 result; + TupleDesc tupdesc; + Datum values[2]; + bool isnull[2]; + char last4Bytes[8 + 1] = "\0"; + + if (PG_ARGISNULL(0)) { + PG_RETURN_NULL(); + } + sqlText = PG_GETARG_TEXT_PP(0); + FUNC_CHECK_HUGE_POINTER(false, sqlText, "gms_get_sql_hash"); + + len = VARSIZE_ANY_EXHDR(sqlText); + buf = makeStringInfo(); + + tupdesc = CreateTemplateTupleDesc(2, false); + TupleDescInitEntry(tupdesc, (AttrNumber)1, "hash", RAWOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber)2, "pre10ihash", NUMERICOID, -1, 0); + BlessTupleDesc(tupdesc); + + if (!pg_md5_hash(VARDATA_ANY(sqlText), len, hexsum)) { + ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } + + values[0] = DirectFunctionCall1(rawin, CStringGetDatum(hexsum)); + isnull[0] = false; + + last4Bytes[0] = hexsum[MD5_HASH_LEN - 2]; + last4Bytes[1] = hexsum[MD5_HASH_LEN - 1]; + last4Bytes[2] = hexsum[MD5_HASH_LEN - 4]; + last4Bytes[3] = hexsum[MD5_HASH_LEN - 3]; + last4Bytes[4] = hexsum[MD5_HASH_LEN - 6]; + last4Bytes[5] = hexsum[MD5_HASH_LEN - 5]; + last4Bytes[6] = hexsum[MD5_HASH_LEN - 8]; + last4Bytes[7] = hexsum[MD5_HASH_LEN - 7]; + result = strtoll(last4Bytes, NULL, 16); + + /* pre10ihash is not support, returns last4bytes instead */ + values[1] = DirectFunctionCall1(int8_numeric, Int64GetDatum(result)); + isnull[1] = false; + + return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull)); +} + +static TokenizeVar* MakeTokenizeVar() +{ + TokenizeVar* var = (TokenizeVar *) palloc(sizeof(TokenizeVar)); + var->dblink = NULL; + var->list = NIL; + var->nextpos = 0; + return var; +} + +static void DestoryTokenizeVar(TokenizeVar* var) +{ + if (var != NULL) { + list_free(var->list); + pfree_ext(var->dblink); + pfree(var); + } +} + +static bool IsDangerousChars(char ch) +{ + for (char c : TOKENIZE_DANGER_CHARS) { + if (c == ch) return true; + } + return false; +} + +static bool IsTruncateChars(char ch) +{ + for (char c : TOKENIZE_TRUNCATE_CHARS) { + if (c == ch) return true; + } + return false; +} + +static TokenizeVar* NameParseInternal(char* name, int len) +{ + List* list = NIL; + int traveLen = 0; + bits8 quoteState = QUOTE_NONE; + char curChar = '\0'; + bool startLink = false; + char* token = NULL; + errno_t rc; + TokenizeVar* var; + StringInfo tmp = makeStringInfo(); + + var = MakeTokenizeVar(); + + while (*name != '\0' && traveLen < len) { + curChar = *name; + traveLen++; + name++; + + if (!IS_QUOTE_STARTED(quoteState) && curChar == ' ') { + continue; + } else if (curChar == '"') { + if (BEFORE_QUOTE_STARTED(quoteState)) { + if (tmp->len != 0) { + /* If there exists valid char before double quote, end read. */ + traveLen--; + break; + } + quoteState = QUOTE_STARTED; + } else if (IS_QUOTE_STARTED(quoteState)) { + if (tmp->len == 0) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid input value \"%s\" with zero length", (name - traveLen)))); + } + quoteState = QUOTE_ENDED; + } else { + /* If there are more than one pair of double quote, end read. */ + break; + } + } else if (curChar == '.' || curChar == '@') { + if (IS_QUOTE_STARTED(quoteState) || startLink) { + appendStringInfoChar(tmp, curChar); + } else { + if (BEFORE_QUOTE_STARTED(quoteState) && !CheckLegalIdenty(tmp->data, false, true)) { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid input value \"%s\" with special words", (name - traveLen)))); + } + if (tmp->len == 0) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid input value \"%s\" with zero length", (name - traveLen)))); + } + if (list_length(list) >= 3) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid input value \"%s\"", (name - traveLen)))); + } + if (isdigit(*(tmp->data))) { + /* If word start with digit, end read. */ + break; + } + token = (char *) palloc0(tmp->len + 1); + rc = strcpy_s(token, tmp->len + 1, tmp->data); + securec_check(rc, "\0", "\0"); + list = lappend(list, token); + resetStringInfo(tmp); + quoteState = QUOTE_NONE; + } + if (curChar == '@') { + startLink = true; + } + } else { + if (IS_QUOTE_STARTED(quoteState)) { + appendStringInfoChar(tmp, curChar); + } else if (IS_QUOTE_END(quoteState)) { + traveLen--; + break; + } else { + if (IsDangerousChars(curChar)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid input value \"%s\" with special character", (name - traveLen)))); + } + if (IsTruncateChars(curChar)) { + /* If meet special char, end read. */ + traveLen--; + break; + } + appendStringInfoChar(tmp, pg_toupper(curChar)); + } + } + } + + if (IS_QUOTE_STARTED(quoteState)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid input value \"%s\" with quotation not closed", (name - traveLen)))); + } + if (tmp->len == 0 && !startLink) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid input value \"%s\"", (name - traveLen)))); + } + if (BEFORE_QUOTE_STARTED(quoteState) && !CheckLegalIdenty(tmp->data, false, true)) { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid input value \"%s\" with special words", (name - traveLen)))); + } + if (startLink) { + if (tmp->len == 0) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("dblink is empty \"%s\"", (name - traveLen)))); + } else if (isdigit(*(tmp->data))) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid dblink value \"%s\"", (name - traveLen)))); + } else { + var->dblink = (char *) palloc0(tmp->len + 1); + errno_t rc = strcpy_s(var->dblink, tmp->len + 1, tmp->data); + securec_check(rc, "\0", "\0"); + } + } else { + if (list_length(list) >= 3) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid input value \"%s\"", (name - traveLen)))); + } + if (isdigit(*(tmp->data))) { + traveLen -= (tmp->len + 2); + } else { + token = (char *) palloc0(tmp->len + 1); + rc = strcpy_s(token, tmp->len + 1, tmp->data); + securec_check(rc, "\0", "\0"); + list = lappend(list, token); + } + } + + var->nextpos = traveLen; + var->list = list_copy(list); + + DestroyStringInfo(tmp); + list_free(list); + + return var; +} + +Datum gms_name_tokenize(PG_FUNCTION_ARGS) +{ + char* name = NULL; + int len; + ListCell* lc; + TupleDesc tupdesc; + Datum values[5]; + bool isnull[5]; + int tc = 0; + TokenizeVar* var; + + if (PG_ARGISNULL(0)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid input value"))); + } + name = TextDatumGetCString(PG_GETARG_TEXT_P(0)); + len = VARSIZE_ANY_EXHDR(PG_GETARG_TEXT_P(0)); + + var = NameParseInternal(name, len); + + if (var->list == NIL || list_length(var->list) == 0 || list_length(var->list) > 3) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("Invalid Input value \"%s\"", name))); + } + + tupdesc = CreateTemplateTupleDesc(5, false); + TupleDescInitEntry(tupdesc, (AttrNumber)1, "a", TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber)2, "b", TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber)3, "c", TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber)4, "dblink", TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber)5, "nextpos", INT4OID, -1, 0); + + BlessTupleDesc(tupdesc); + + errno_t rc = memset_s(isnull, 5, 1, 5); + securec_check(rc, "\0", "\0"); + foreach (lc, var->list) { + char* token = (char *) lfirst(lc); + values[tc] = CStringGetTextDatum(token); + isnull[tc++] = false; + } + if (var->dblink != NULL && strlen(var->dblink) > 0) { + values[3] = CStringGetTextDatum(var->dblink); + isnull[3] = false; + } + values[4] = Int32GetDatum(var->nextpos); + isnull[4] = false; + + DestoryTokenizeVar(var); + + return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull)); +} + +static NameResolveVar* MakeNameResolveVar(List* list, char* name) +{ + int c = 0; + ListCell* lc; + errno_t rc; + + NameResolveVar* var = (NameResolveVar *) palloc0(sizeof(NameResolveVar)); + /* identifier length can't greater than NAMEDATALEN */ + var->schema = (char *) palloc0(NAMEDATALEN); + var->part1 = (char *) palloc0(NAMEDATALEN); + var->part2 = (char *) palloc0(NAMEDATALEN); + var->part1Type = NAME_RESOLVE_TYPE_NONE; + var->objectId = InvalidOid; + + foreach (lc, list) { + char* token = (char *) lfirst(lc); + token = pg_strtolower(token); + if (c == 0) { + rc = strcpy_s(var->schema, NAMEDATALEN, token); + } else if (c == 1) { + rc = strcpy_s(var->part1, NAMEDATALEN, token); + } else { + rc = strcpy_s(var->part2, NAMEDATALEN, token); + } + securec_check(rc, "\0", "\0"); + c++; + } + var->len = list_length(list); + var->synonym = false; + + return var; +} + +static void DestoryNameResolveVar(NameResolveVar* var) +{ + if (var != NULL) { + pfree_ext(var->part2); + pfree_ext(var->part1); + pfree_ext(var->schema); + pfree(var); + } +} + +static void ReportNameResolveAclErr(NameResolveVar* var) +{ + DestoryNameResolveVar(var); + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("The Object is not exists"))); +} + +static List* GetFillSchemaList() +{ + List* list = NIL; + Oid namespaceId = InvalidOid; + + char* username = GetUserNameById(GetUserId()); + namespaceId = get_namespace_oid(username, true); + pfree_ext(username); + if (OidIsValid(namespaceId)) { + list = lappend_oid(list, namespaceId); + } + list = lappend_oid(list, PG_PUBLIC_NAMESPACE); + return list; +} + +static Oid GetSchemaOidWithErrHandled(char* schemaName, NameResolveVar* var, HeapTuple synTuple = NULL) +{ + Oid namespaceId = get_namespace_oid(schemaName, true); + if (!OidIsValid(namespaceId)) { + if (synTuple != NULL) { + ReleaseSysCache(synTuple); + } + ReportNameResolveAclErr(var); + } + AclResult aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE); + if (aclresult != ACLCHECK_OK) { + if (synTuple != NULL) { + ReleaseSysCache(synTuple); + } + ReportNameResolveAclErr(var); + } + return namespaceId; +} + +static Oid SearchPkgOidByName(Oid namespaceId, char* pkgName, NameResolveVar* var) +{ + Oid pkgOid = InvalidOid; + AclResult aclresult; + + pkgOid = GetSysCacheOid2(PKGNAMENSP, CStringGetDatum(pkgName), ObjectIdGetDatum(namespaceId)); + if (OidIsValid(pkgOid)) { + aclresult = pg_package_aclcheck(pkgOid, GetUserId(), ACL_EXECUTE); + if (aclresult != ACLCHECK_OK) { + ReportNameResolveAclErr(var); + } + var->part1Type = NAME_RESOLVE_TYPE_PACKAGE; + } + return pkgOid; +} + +static void ResolvePkgNameFillSchema(NameResolveVar* var) +{ + List* tempActiveSearchPath = NIL; + ListCell* lc; + errno_t rc; + char* part1 = pstrdup(var->part1); + + tempActiveSearchPath = GetFillSchemaList(); + foreach (lc, tempActiveSearchPath) { + Oid namespaceId = lfirst_oid(lc); + ResolveContextName(NR_CONTEXT_PLSQL, namespaceId, var->schema, var, SearchPkgOidByName); + if (OidIsValid(var->objectId)) { + /* Fill schema part1 -> part2, schema -> part1, selectSchema -> schema */ + rc = strcpy_s(var->part2, NAMEDATALEN, part1); + securec_check(rc, "\0", "\0"); + if (!var->synonym) { + /* not synonym object */ + rc = strcpy_s(var->part1, NAMEDATALEN, var->schema); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(var->schema, NAMEDATALEN, get_namespace_name(namespaceId)); + securec_check(rc, "\0", "\0"); + } + break; + } + } + pfree_ext(part1); + list_free(tempActiveSearchPath); +} + +static Oid SearchProcOidByName(Oid namespaceId, char* procName, NameResolveVar* var) +{ + CatCList* catlist = NULL; + HeapTuple tuple; + Form_pg_proc procform; + Oid procOid = InvalidOid; + bool isNull = true; + char pprokind = '\0'; + +#ifndef ENABLE_MULTIPLE_NODES + if (t_thrd.proc->workingVersionNum < 92470) { + catlist = SearchSysCacheList1(PROCNAMEARGSNSP, CStringGetDatum(procName)); + } else { + catlist = SearchSysCacheList1(PROCALLARGS, CStringGetDatum(procName)); + } +#else + catlist = SearchSysCacheList1(PROCNAMEARGSNSP, CStringGetDatum(procName)); +#endif + + for (int i = 0; i < catlist->n_members; i++) { + tuple = t_thrd.lsc_cxt.FetchTupleFromCatCList(catlist, i); + procform = (Form_pg_proc)GETSTRUCT(tuple); + if (procform->pronamespace != namespaceId) continue; + + pprokind = CharGetDatum(SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prokind, &isNull)); + if (!isNull && (PROC_IS_FUNC(pprokind) || PROC_IS_PRO(pprokind))) { + procOid = HeapTupleGetOid(tuple); + var->part1Type = PROC_IS_FUNC(pprokind) ? NAME_RESOLVE_TYPE_FUNCTION + : PROC_IS_PRO(pprokind) ? NAME_RESOLVE_TYPE_PROCEDURE + : NAME_RESOLVE_TYPE_NONE; + } + AclResult aclresult = pg_proc_aclcheck(procOid, GetUserId(), ACL_EXECUTE); + if (aclresult != ACLCHECK_OK) { + ReleaseSysCacheList(catlist); + ReportNameResolveAclErr(var); + } + break; + } + ReleaseSysCacheList(catlist); + + return procOid; +} + +static Oid SearchRelOidByName(Oid namespaceId, char* relName, NameResolveVar* var) +{ + Oid relOid = InvalidOid; + AclResult aclResult; + + relOid = get_relname_relid(relName, namespaceId); + if (OidIsValid(relOid)) { + aclResult = pg_class_aclcheck(relOid, GetUserId(), ACL_SELECT); + if (aclResult != ACLCHECK_OK) { + ReportNameResolveAclErr(var); + } + } + return relOid; +} + +static Oid SearchTriggerOidByName(Oid namespaceId, char* triggerName, NameResolveVar* var) +{ + Relation tgrel; + ScanKeyData keys[1]; + SysScanDesc tgscan; + HeapTuple tuple; + bool found = false; + Oid tgOid = InvalidOid; + + ScanKeyInit(&keys[0], Anum_pg_trigger_tgname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(triggerName)); + + tgrel = heap_open(TriggerRelationId, AccessShareLock); + tgscan = systable_beginscan(tgrel, TriggerNameIndexId, true, SnapshotNow, 1, keys); + while (HeapTupleIsValid(tuple = systable_getnext(tgscan))) { + if (found) { + systable_endscan(tgscan); + heap_close(tgrel, AccessShareLock); + DestoryNameResolveVar(var); + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("duplicate trigger found"))); + } + tgOid = HeapTupleGetOid(tuple); + found = true; + } + systable_endscan(tgscan); + heap_close(tgrel, AccessShareLock); + return tgOid; +} + +static Oid SearchTypeOidByName(Oid namespaceId, char* typName, NameResolveVar* var) +{ + HeapTuple tuple; + Oid typId = InvalidOid; + + tuple = SearchSysCache2(TYPENAMENSP, CStringGetDatum(typName), ObjectIdGetDatum(namespaceId)); + + if (!HeapTupleIsValid(tuple)) { + return InvalidOid; + } + typId = HeapTupleGetOid(tuple); + if (OidIsValid(typId)) { + AclResult aclResult = pg_type_aclcheck(typId, GetUserId(), ACL_USAGE); + if (aclResult != ACLCHECK_OK) { + ReleaseSysCache(tuple); + ReportNameResolveAclErr(var); + } + } + ReleaseSysCache(tuple); + return typId; +} + +static void ResolveContextName(NameResolveContext context, Oid namespaceId, char* resolveName, + NameResolveVar* var, SearchOidByName searchmtd) +{ + Oid id = InvalidOid; + HeapTuple synTuple; + Oid newNamespaceId = InvalidOid; + + id = searchmtd(namespaceId, resolveName, var); + if (OidIsValid(id)) { + var->objectId = id; + return; + } + + if (!(context == NR_CONTEXT_PLSQL || context == NR_CONTEXT_TABLE || context == NR_CONTEXT_SEQUENCES + || context == NR_CONTEXT_TYPE)) { + return; + } + /* Search synonym */ + synTuple = SearchSysCache2(SYNONYMNAMENSP, PointerGetDatum(resolveName), ObjectIdGetDatum(namespaceId)); + if (!HeapTupleIsValid(synTuple)) { + return; + } + Form_pg_synonym synForm = (Form_pg_synonym)GETSTRUCT(synTuple); + newNamespaceId = GetSchemaOidWithErrHandled(NameStr(synForm->synobjschema), var, synTuple); + id = searchmtd(newNamespaceId, NameStr(synForm->synobjname), var); + if (OidIsValid(id)) { + /* Replace synonym to real name, and do it for schema too. */ + errno_t rc = strcpy_s(var->schema, NAMEDATALEN, NameStr(synForm->synobjschema)); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(var->part1, NAMEDATALEN, NameStr(synForm->synobjname)); + securec_check(rc, "\0", "\0"); + var->objectId = id; + var->synonym = true; + } + ReleaseSysCache(synTuple); +} + +static void ResolveObjectNameByContext(NameResolveContext context, Oid namespaceId, char* resolveName, NameResolveVar* var) +{ + errno_t rc; + + switch (context) { + case NR_CONTEXT_PLSQL: + /* Search func、proc、package */ + ResolveContextName(context, namespaceId, resolveName, var, SearchProcOidByName); + break; + case NR_CONTEXT_TABLE: + case NR_CONTEXT_SEQUENCES: + case NR_CONTEXT_INDEX: + ResolveContextName(context, namespaceId, resolveName, var, SearchRelOidByName); + var->part1Type = context == NR_CONTEXT_TABLE ? NAME_RESOLVE_TYPE_TABLE + : context == NR_CONTEXT_INDEX ? NAME_RESOLVE_TYPE_INDEX + : NAME_RESOLVE_TYPE_SEQUENCE; + break; + case NR_CONTEXT_TRIGGER: + ResolveContextName(context, namespaceId, resolveName, var, SearchTriggerOidByName); + var->part1Type = NAME_RESOLVE_TYPE_TRIGGER; + break; + case NR_CONTEXT_TYPE: + ResolveContextName(context, namespaceId, resolveName, var, SearchTypeOidByName); + var->part1Type = NAME_RESOLVE_TYPE_TYPE; + break; + case NR_CONTEXT_UNKNOWN: + /* Only support for context value 10 */ + ReportNameResolveAclErr(var); + break; + default: + var->part1Type = NAME_RESOLVE_TYPE_NONE; + break; + } + + if (var->len == 1 && !var->synonym) { + rc = strcpy_s(var->part1, NAMEDATALEN, var->schema); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(var->schema, NAMEDATALEN, get_namespace_name(namespaceId)); + securec_check(rc, "\0", "\0"); + } + + /* top-level function | procedure, part1 is empty, part2 is real function | procedure name */ + if ((var->part1Type == NAME_RESOLVE_TYPE_FUNCTION || var->part1Type == NAME_RESOLVE_TYPE_PROCEDURE) + && (var->part2 == NULL || strlen(var->part2) == 0)) { + rc = strcpy_s(var->part2, NAMEDATALEN, var->part1); + securec_check(rc, "\0", "\0"); + rc = memset_s(var->part1, NAMEDATALEN, 0, NAMEDATALEN); + securec_check(rc, "\0", "\0"); + } +} + +static NameResolveContext GetNameResolveContext(Numeric num) +{ + int32 contextNumber = DatumGetInt32(DirectFunctionCall1(numeric_int4, NumericGetDatum(num))); + if (contextNumber < 0 || contextNumber > 10) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("context argument must be number 0 to 10"))); + } + NameResolveContext context = (NameResolveContext) contextNumber; + if (context == NR_CONTEXT_JAVA_SOURCE || context == NR_CONTEXT_JAVA_RESOURCE || context ==NR_CONTEXT_JAVA_CLASS + || context == NR_CONTEXT_JAVA_SHARED_DATA) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("Unsupported context type: %d", (int)context))); + } + return context; +} + +static void SetResultValues(Datum* values, bool* isnull, NameResolveVar* var) +{ + if (var->schema != NULL && strlen(var->schema) > 0) { + values[0] = CStringGetTextDatum(pg_strtoupper(var->schema)); + isnull[0] = false; + } + if (var->part1 != NULL && strlen(var->part1) > 0) { + values[1] = CStringGetTextDatum(pg_strtoupper(var->part1)); + isnull[1] = false; + } + if (var->part2 != NULL && strlen(var->part2) > 0) { + values[2] = CStringGetTextDatum(pg_strtoupper(var->part2)); + isnull[2] = false; + } +} + +Datum gms_name_resolve(PG_FUNCTION_ARGS) +{ + char* name = NULL; + NameResolveContext context; + int len; + TupleDesc tupdesc; + const int outputParamLen = 6; + Datum values[outputParamLen]; + bool isnull[outputParamLen]; + TokenizeVar* tokenizeVar; + NameResolveVar* var; + int listLen; + Oid namespaceId = InvalidOid; + + if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("Invalid input value"))); + } + name = TextDatumGetCString(PG_GETARG_TEXT_P(0)); + len = VARSIZE_ANY_EXHDR(PG_GETARG_TEXT_P(0)); + context = GetNameResolveContext(PG_GETARG_NUMERIC(1)); + + tokenizeVar = NameParseInternal(name, len); + listLen = list_length(tokenizeVar->list); + + if (tokenizeVar->list == NIL || listLen == 0 || listLen > 3) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("Invalid Input value \"%s\"", name))); + } + + tupdesc = CreateTemplateTupleDesc(outputParamLen, false); + TupleDescInitEntry(tupdesc, (AttrNumber)1, "schema", TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber)2, "part1", TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber)3, "part2", TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber)4, "dblink", TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber)5, "part1_type", NUMERICOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber)6, "object_number", NUMERICOID, -1, 0); + + BlessTupleDesc(tupdesc); + + errno_t rc = memset_s(isnull, outputParamLen, 1, outputParamLen); + securec_check(rc, "\0", "\0"); + + var = MakeNameResolveVar(tokenizeVar->list, name); + pfree_ext(name); + + /* Set part1_type and object_number default value */ + values[4] = DirectFunctionCall1(int4_numeric, Int32GetDatum(var->part1Type)); + isnull[4] = false; + values[5] = DirectFunctionCall1(int4_numeric, Int32GetDatum(0)); + isnull[5] = false; + + /* If dblink is not null, don't resolve */ + if (tokenizeVar->dblink != NULL && strlen(tokenizeVar->dblink) > 0) { + SetResultValues(values, isnull, var); + values[3] = CStringGetTextDatum(tokenizeVar->dblink); + isnull[3] = false; + DestoryTokenizeVar(tokenizeVar); + DestoryNameResolveVar(var); + return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull)); + } + DestoryTokenizeVar(tokenizeVar); + + if (listLen == 3) { + namespaceId = GetSchemaOidWithErrHandled(var->schema, var); + ResolveContextName(context, namespaceId, var->part1, var, SearchPkgOidByName); + } else if (listLen == 2) { + /* If is pkg.c, fill schema and search */ + if (context == NR_CONTEXT_PLSQL) { + ResolvePkgNameFillSchema(var); + } + if (!OidIsValid(var->objectId)) { + namespaceId = GetSchemaOidWithErrHandled(var->schema, var); + ResolveObjectNameByContext(context, namespaceId, var->part1, var); + } + } else { + ListCell* lc; + List* tempActiveSearchPath = GetFillSchemaList(); + foreach (lc, tempActiveSearchPath) { + namespaceId = lfirst_oid(lc); + ResolveObjectNameByContext(context, namespaceId, var->schema, var); + if (OidIsValid(var->objectId)) { + break; + } + } + list_free(tempActiveSearchPath); + } + + if (!OidIsValid(var->objectId)) { + ReportNameResolveAclErr(var); + } + SetResultValues(values, isnull, var); + values[4] = DirectFunctionCall1(int4_numeric, Int32GetDatum(var->part1Type)); + values[5] = DirectFunctionCall1(int4_numeric, Int32GetDatum(var->objectId)); + return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull)); +} + +static int HexCharToDec(char hexChar) { + char lowerHexChar = pg_tolower(hexChar); + + if (lowerHexChar >= '0' && lowerHexChar <= '9') { + return lowerHexChar - '0'; + } else if (lowerHexChar >= 'a' && lowerHexChar <= 'f') { + return lowerHexChar - 'a' + 10; + } else { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid hexadecimal digit: \"%d\"", hexChar))); + } + return -1; /* make compiler quiet */ +} + +/* + * Checks the bit setting for the given bit in the given RAW value. + * - raw: input raw value; + * - pos: bit in raw to check, start from 1. + */ +Datum gms_is_bit_set(PG_FUNCTION_ARGS) +{ + bytea* data; + char* hexStr = NULL; + int len; + int pos; + int chVal; + uint32 result; + + if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid input value"))); + } + + data = PG_GETARG_BYTEA_P(0); + len = VARSIZE_ANY_EXHDR(data); + + hexStr = (char *) palloc0(len * 2 + 1); + hex_encode(VARDATA_ANY(data), len, hexStr); + len = strlen(hexStr); + + pos = DirectFunctionCall1(numeric_int4, PG_GETARG_DATUM(1)); + + if (pos <= 0 || pos > INT32_MAX) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid second param value range"))); + } + + /* convert pos to cycle 0~(len * 4 - 1) */ + pos = (pos - 1) % (len * 4); + + /* + * Find binary position in chars with 'pos', + * from high to low with the lowest bit being + * bit number 1. + * for example: hex input: 124578AF, pos: 9 + * 0001 0010 0100 0101 0111 1000 1010 1111 + * ^ + * 9 8765 4321 + * and each hex char indicate 4 bits, find offset + * bit pos in single char from right, use pos % 4 + * get right offset. + */ + chVal = HexCharToDec(hexStr[len - 1 - pos / 4]); + result = (chVal >> (pos % 4)) & 0x01; + + pfree_ext(hexStr); + + return DirectFunctionCall1(int4_numeric, Int32GetDatum(result)); +} + +Datum gms_old_current_schema(PG_FUNCTION_ARGS) +{ + Name schemaName = DatumGetName(OidFunctionCall0(CURRENTSCHEMAFUNCOID)); + return CStringGetTextDatum(schemaName->data); +} \ No newline at end of file diff --git a/contrib/gms_utility/gms_utility.h b/contrib/gms_utility/gms_utility.h new file mode 100644 index 000000000..c2a39c086 --- /dev/null +++ b/contrib/gms_utility/gms_utility.h @@ -0,0 +1,115 @@ +/*---------------------------------------------------------------------------------------* + * gms_utility.h + * + * Definition about gms_utility package. + * + * IDENTIFICATION + * contrib/gms_utility/gms_utility.h + * + * --------------------------------------------------------------------------------------- + */ +#ifndef GMS_UTILITY_H +#define GMS_UTILITY_H + +#include "postgres.h" +#include "funcapi.h" +#include "fmgr.h" +#include "catalog/pg_proc.h" +#include "catalog/gs_package.h" +#include "catalog/pg_object.h" +#include "catalog/pg_trigger.h" +#include "catalog/pg_synonym.h" +#include "parser/parse_relation.h" + +typedef enum { + METHOD_OPT_TABLE, + METHOD_OPT_ALL_COLUMN, + METHOD_OPT_ALL_INDEX +} AnalyzeMethodOpt; + +typedef struct AnalyzeVar { + bool isEstimate; + bool validRows; + int64 estimateRows; + bool validPercent; + int64 estimatePercent; +} AnalyzeVar; + +typedef struct TokenizeVar { + List* list; + char* dblink; + int nextpos; +} TokenizeVar; + +typedef struct NameResolveVar { + char* schema; + char* part1; + char* part2; + int part1Type; + Oid objectId; + int len; + bool synonym; +} NameResolveVar; + +/* + * name resolve function input param context valid value: 0~9 + */ +typedef enum { + NR_CONTEXT_TABLE, + NR_CONTEXT_PLSQL, + NR_CONTEXT_SEQUENCES, + NR_CONTEXT_TRIGGER, + NR_CONTEXT_JAVA_SOURCE, + NR_CONTEXT_JAVA_RESOURCE, + NR_CONTEXT_JAVA_CLASS, + NR_CONTEXT_TYPE, + NR_CONTEXT_JAVA_SHARED_DATA, + NR_CONTEXT_INDEX, + NR_CONTEXT_UNKNOWN +} NameResolveContext; + +/* + * name resolve function output param part1_type valid value: + * 0、1、2、5、6、7、8、9、12、13 + */ +#define NAME_RESOLVE_TYPE_NONE 0 +#define NAME_RESOLVE_TYPE_INDEX 1 +#define NAME_RESOLVE_TYPE_TABLE 2 +#define NAME_RESOLVE_TYPE_SYNONYM 5 +#define NAME_RESOLVE_TYPE_SEQUENCE 6 +#define NAME_RESOLVE_TYPE_PROCEDURE 7 +#define NAME_RESOLVE_TYPE_FUNCTION 8 +#define NAME_RESOLVE_TYPE_PACKAGE 9 +#define NAME_RESOLVE_TYPE_TRIGGER 12 +#define NAME_RESOLVE_TYPE_TYPE 13 + +/* + * name parse double quote marks + */ +#define QUOTE_NONE 0x01 +#define QUOTE_STARTED 0x02 +#define QUOTE_ENDED 0x04 + +#define QUOTE_STATE(val, bits) (((val) & (bits)) == (val)) +#define IS_QUOTE_STARTED(val) QUOTE_STATE(val, QUOTE_STARTED) +#define BEFORE_QUOTE_STARTED(val) QUOTE_STATE(val, QUOTE_NONE) +#define IS_QUOTE_END(val) QUOTE_STATE(val, QUOTE_ENDED) + +#define NAME_TOKENIZE_MAX_ITEM_COUNT 3 + +extern "C" Datum gms_analyze_schema(PG_FUNCTION_ARGS); +extern "C" Datum gms_canonicalize(PG_FUNCTION_ARGS); +extern "C" Datum gms_compile_schema(PG_FUNCTION_ARGS); +extern "C" Datum gms_expand_sql_text(PG_FUNCTION_ARGS); +extern "C" Datum gms_get_cpu_time(PG_FUNCTION_ARGS); +extern "C" Datum gms_get_endianness(PG_FUNCTION_ARGS); +extern "C" Datum gms_get_sql_hash(PG_FUNCTION_ARGS); +extern "C" Datum gms_name_tokenize(PG_FUNCTION_ARGS); +extern "C" Datum gms_name_resolve(PG_FUNCTION_ARGS); +extern "C" Datum gms_is_bit_set(PG_FUNCTION_ARGS); +extern "C" Datum gms_old_current_schema(PG_FUNCTION_ARGS); + +extern void RecompileSingleFunction(Oid func_oid, bool is_procedure); +extern void RecompileSinglePackage(Oid package_oid, bool is_spec); + +#endif /* GMS_UTILITY_H */ \ No newline at end of file diff --git a/contrib/gms_utility/smartmatch.pl b/contrib/gms_utility/smartmatch.pl new file mode 100644 index 000000000..e99dc8113 --- /dev/null +++ b/contrib/gms_utility/smartmatch.pl @@ -0,0 +1,583 @@ +#!/usr/bin/perl + + +# smartmatch: +# +# This script is extracted from Gurjeet Singh ( singh.gurjeet@gmail.com ) NEUROdiff patch. +# +# 04 Apr 2013 : First implementation + +use strict; +use warnings; + +sub usage +{ + print "Usage: smartmatch.pl \n"; + return; +} + +# file handles for expected and results files +my $EXPECTED; +my $RESULT; +my $NEW_EXPECTED; + +my $expected; # line iterator for EXPECTED file +my $result; # line iterator for RESULT file + +my $re; # the Regular Expression part of a line which starts with ? + +my $insideuo; # boolean, representing if we are INSIDE an UnOrdered set of lines + +my $bFirstLine; # Indicates whether the line going to be printed is the first or not + +my $iuo; # counter I for counting lines within an UnOrdered set +my $seenspecialinuo; # Seen special marker inside unordered group +my $smartmatch; # seen any special match syntax + +my $rc = 0; # Return Code + +my @earr = ( [], [] ); # 2-dimensional ARRay to keep Expected file's unmatched lines from an unordered set +my @rarr = ( [], [] ); # 2-dimensional ARRay to keep Result file's unmatched lines from unordered set + +my @searr = ( [], [] ); # 2-dimensional ARRay to keep Expected file's sorted lines from an unordered set +my @srarr = ( [], [] ); # 2-dimensional ARRay to keep Result file's sorted lines from unordered set + +# we require exactly 3 arguments +if( @ARGV != 3 ) +{ + usage(); + exit(2); +} + +# initialize (almost) everything +open $EXPECTED , "<", $ARGV[0] or die $!; +open $RESULT , "<", $ARGV[1] or die $!; +open $NEW_EXPECTED , ">", $ARGV[2] or die $!; + +$insideuo = 0; +$iuo = 0; +$smartmatch = 0; + +$bFirstLine = 1; + +# process all lines from both the files +while( 1 ) +{ + undef $!; + + my $matched = 1; + + $expected = <$EXPECTED>; + + undef $!; + + $result = <$RESULT>; + + + # one file finished but not the other + if( ( !defined( $expected ) || !defined( $result ) ) + && ( defined( $expected ) || defined( $result ) ) ) + { + $rc = 2; + + if( defined( $expected ) ) + { + if( $bFirstLine ) + { + print $NEW_EXPECTED "$expected"; + $bFirstLine = 0; + } + else + { + print $NEW_EXPECTED "\n$expected"; + } + } + + last; # while( 1 ) + } + + # both files finished + if( !defined( $expected ) && !defined( $result ) ) + { + last; # while( 1 ) + } + + # chomp away... + # Apart from getting rid of extra newlines in messages, this will also help + # us be agnostic about platform specific newline sequences. + # + # Correction: Apparently the above assumption is not true (found the hard + # way :( ). + # If the file was generated on Windows (CRLF), the Linux version of chomp + # will trim only \n and leave \r. Had to use dos2unix on the out files to + # make this script work. + chomp( $expected ); + chomp( $result ); + + # if the line from expected file starts with a ?, treat it specially + if( $expected =~ /^--\?.*/ ) + { + $smartmatch=1; + + # extract the Regular Expression + $re = substr $expected, 3; + + # If this is the beginning of an UnOrdered set of lines + if( $re eq 'unordered: start' ) + { + if( $insideuo ) + { + + if( $bFirstLine ) + { + print $NEW_EXPECTED "Nesting of 'unordered: start' blocks is not allowed"; + $bFirstLine = 0; + } + else + { + print $NEW_EXPECTED "\nNesting of 'unordered: start' blocks is not allowed"; + } + + exit( 2 ); + } + + # reset the variables for the UO set. + $iuo = 0; + $insideuo = 1; + $seenspecialinuo = 0; + + if( $bFirstLine ) + { + print $NEW_EXPECTED "$expected"; + $bFirstLine = 0; + } + else + { + print $NEW_EXPECTED "\n$expected"; + } + + next; + } + + # end of an UnOrderd set of lines + if( $re eq 'unordered: end' ) + { + if( !$insideuo ) + { + print $NEW_EXPECTED "'unordered: end' line found without a matching 'unordered: start' line\n"; + exit( 2 ); + } + + $insideuo = 0; + + # If there were some lines containing RE, do comparison the hard way + if( $seenspecialinuo ) + { + # begin the (m*n) processing of the two arrays. These arrays + # contain the set of unmatched lines from respective files + foreach my $eelemref ( @earr ) + { + my $i = 0; + + my $eelem = $eelemref->[0]; + + foreach my $relemref ( @rarr ) + { + my $relem = $relemref->[0]; + + $matched = 1; + + # treat these lines the same as we threat the others; + # that is, if an 'expected' line starts with a '?', we + # perform Regular Expression match, else we perform + # normal comparison. + + if( $eelem =~ /^--\?.*/ ) + { + my $tmpre = substr $eelem, 3; + + if( $relem !~ /^$tmpre$/ ) + { + $matched = 0; + } + else + { + if( $bFirstLine ) + { + print $NEW_EXPECTED "$relem"; + $bFirstLine = 0; + } + else + { + print $NEW_EXPECTED "\n$relem"; + } + + last; + } + } + elsif( $eelem ne $relem ) + { + $matched = 0; + } + else + { + if( $bFirstLine ) + { + print $NEW_EXPECTED "$relem"; + $bFirstLine = 0; + } + else + { + print $NEW_EXPECTED "\n$relem"; + } + + last; + } + + ++$i; + } # foreach @rarr + + if( !$matched ) + { + $rc = 2; + if( $bFirstLine ) + { + print $NEW_EXPECTED "$eelem"; + $bFirstLine = 0; + } + else + { + print $NEW_EXPECTED "\n$eelem"; + } + + } + else + { + splice @rarr, $i, 0; + } + } # foreach @earr + } + else # if there's no line containing an RE in this UO group, + # do it efficiently + { + # sort both arrays based on the text. + @searr = sort { $a->[0] cmp $b->[0] } @earr; + @srarr = sort { $a->[0] cmp $b->[0] } @rarr; + + my $min_len = (scalar(@searr) <= scalar(@srarr) ? scalar(@searr) : scalar(@srarr) ); + my $i; + $matched = 1; + + for( $i = 0; $i < $min_len; ++$i ) + { + my $eelem = $searr[$i][0]; + my $relem = $srarr[$i][0]; + + # treat these lines the same as we threat the others; that is, if an + # 'expected' line starts with a '?', we perform Regular Expression + # match, else we perform normal comparison. + + if( $eelem =~ /^--\?.*/ ) + { + my $tmpre = substr $eelem, 3; + + if( $relem !~ /^$tmpre$/ ) + { + $matched = 0; + } + } + elsif( $eelem ne $relem ) + { + $matched = 0; + } + } + + if ((scalar(@searr) > $i) || (scalar(@srarr) > $i)) + { + $matched = 0; + } + + if ( !$matched ) + { + $rc = 2; + for( my $i = 0; $i < scalar(@earr); ++$i ) + { + if( $bFirstLine ) + { + print $NEW_EXPECTED "$earr[$i][0]"; + $bFirstLine = 0; + } + else + { + print $NEW_EXPECTED "\n$earr[$i][0]"; + } + } + } + else + { + for( my $i = 0; $i < scalar(@rarr); ++$i ) + { + if( $bFirstLine ) + { + print $NEW_EXPECTED "$rarr[$i][0]"; + $bFirstLine = 0; + } + else + { + print $NEW_EXPECTED "\n$rarr[$i][0]"; + } + } + } + + $matched = 0; + } # else part of if( $seenspecialinuo ) + + if( $bFirstLine ) + { + $bFirstLine = 0; + print $NEW_EXPECTED "$expected"; + } + else + { + print $NEW_EXPECTED "\n$expected"; + } + + # reset the array variables to reclaim memory + @searr = @srarr = (); + @earr = @rarr = (); + + next; # while( 1 ) + + } # if re == 'unordered: end' + + # it is not an 'unordered' marker, so do regular Regular Expression match + else + { + my $re_1; + + if ($result !~ /^$re/) + { + if ($re =~ /(.*)datanode.*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*)\(cost=.*/ ) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*)\(actual time=.*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*)\(CPU:.*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*)\(RoughCheck CU:.*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*)Buffers:.*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*).*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /[.*]/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*).*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*).*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*).*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*).*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*).*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*).*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*).*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /(.*).*/) + { + $re_1 = quotemeta($1); + if ($result !~ /$re_1.*/) + { + $matched = 0; + } + } + elsif ($re =~ /^\s*Sort\s+Method.*/) + { + if ($result !~ /^\s*Sort\s+Method.*/) + { + $matched = 0; + } + } + + + elsif ($re =~ /Total runtime:.*/) + { + if ($result !~ /^\s*Total runtime:.*/) + { + $matched = 0; + } + } + elsif ($re =~ /^\s*QUERY PLAN\s*$/) + { + if ($result !~ /^\s*QUERY PLAN\s*$/) + { + $matched = 0; + } + } + elsif ($re =~ /^\-+$/) + { + if ($result !~ /^\-+$/) + { + $matched = 0; + } + } + else + { + $matched = 0; + } + } + } + + } # if $expected like ?.* + + # $expected doesn't begin with the special marker, so do normal comparison + elsif( $expected ne $result ) + { + $matched = 0; + } + + if( !$matched || $insideuo ) + { + # if the lines did not match, and if we are comparing an unordered set of lines, + # then save the lines for processing later. + if( $insideuo ) + { + $earr[$iuo][0] = $expected; + $rarr[$iuo][0] = $result; + + + if( !$seenspecialinuo && $expected =~ /^--\?.*/ ) + { + $seenspecialinuo = 1; + } + + ++$iuo; + } + else # print out the difference + { + $rc = 2; + if( $bFirstLine ) + { + $bFirstLine = 0; + print $NEW_EXPECTED "$expected"; + } + else + { + print $NEW_EXPECTED "\n$expected"; + } + } + } + else + { + if( $bFirstLine ) + { + $bFirstLine = 0; + print $NEW_EXPECTED "$result"; + } + else + { + print $NEW_EXPECTED "\n$result"; + } + + } +} + +close $EXPECTED; +close $RESULT; +close $NEW_EXPECTED; + +exit( $rc + $smartmatch ); diff --git a/contrib/gms_utility/sql/gms_utility.sql b/contrib/gms_utility/sql/gms_utility.sql new file mode 100644 index 000000000..d74174e92 --- /dev/null +++ b/contrib/gms_utility/sql/gms_utility.sql @@ -0,0 +1,2411 @@ +reset search_path; +create extension if not exists gms_utility; + +-- start test db_version +declare + version varchar2(50); + compatibility varchar2(50); +begin + gms_utility.db_version(version, compatibility); + raise info 'version: %', version; + raise info 'compatibility: %', compatibility; +end; +/ +declare + version varchar2(50); +begin + gms_utility.db_version(version); + raise info 'version: %', version; +end; -- error +/ +call gms_utility.db_version(); -- error +declare + version int; + compatibility int; +begin + gms_utility.db_version(version, compatibility); + raise info 'version: %', version; + raise info 'compatibility: %', compatibility; +end; -- error +/ +-- end test db_version + +-- start test get_cpu_time +select gms_utility.get_cpu_time(); +select gms_utility.get_cpu_time(100); -- error +declare + cputime char(1); +begin + cputime := gms_utility.get_cpu_time(); + raise info 'cpuTimeDelta: %', cputime; +end; +/ +declare + cputime json; +begin + cputime := gms_utility.get_cpu_time(); + raise info 'cpuTimeDelta: %', cputime; +end; +/ +declare + t1 number := 0; + t2 number := 0; + timeDelta number; + i integer; + sum integer; +begin + t1 := gms_utility.get_cpu_time(); + for i in 1..1000000 loop + sum := sum + i * 2 + i / 2; + end loop; + t2 := gms_utility.get_cpu_time(); + timeDelta = t2 - t1; + raise info 'cpuTimeDelta: %', timeDelta; +end; +/ +declare + i number; + j number; + k number; +begin + i := gms_utility.get_cpu_time; + + select count(*) + into j + from pg_class t, pg_index i + where t.Oid = i.indexrelid; + + k := gms_utility.get_cpu_time; + raise info 'costtime: %', (k-i); +end; +/ +-- end test get_cpu_time + +-- start test get_endianness +select gms_utility.get_endianness(); +select gms_utility.get_endianness(1000); +-- end test get_endianness + +-- start test get_sql_hash +declare + hash raw(50); + l4b number; +begin + gms_utility.get_sql_hash('Today is a good day!', hash, l4b); + raise info 'hash: %', hash; + raise info 'last4byte: %', l4b; +end; +/ +declare + hash raw(50); + l4b number; +begin + gms_utility.get_sql_hash(NULL, hash, l4b); + raise info 'hash: %', hash; + raise info 'last4byte: %', l4b; +end; +/ +declare + hash raw(50); + l4b number; +begin + gms_utility.get_sql_hash('', hash, l4b); + raise info 'hash: %', hash; + raise info 'last4byte: %', l4b; +end; +/ +call gms_utility.get_sql_hash(); +-- end test get_sql_hash + +-- start test is_bit_set +declare + r raw(50) := '123456AF'; + result NUMBER; + pos NUMBER; +begin + for pos in 1..32 loop + result := gms_utility.is_bit_set(r, pos); + raise info 'position = %, result = %', pos, result; + end loop; +end; +/ +declare + r raw(50) := '123456AF'; + result NUMBER; + pos NUMBER; +begin + for pos in 33..64 loop + result := gms_utility.is_bit_set(r, pos); + raise info 'position = %, result = %', pos, result; + end loop; +end; +/ +select gms_utility.is_bit_set(); -- error +select gms_utility.is_bit_set(NULL, 10); -- error +select gms_utility.is_bit_set('', 10); -- error +select gms_utility.is_bit_set('123456'); -- error +select gms_utility.is_bit_set('123456AF', 9); +select gms_utility.is_bit_set('12345678AF', 9); +select gms_utility.is_bit_set('123456TT', 9); -- error +select gms_utility.is_bit_set('12345678TT', 9); -- error +select gms_utility.is_bit_set('1234', 9); +select gms_utility.is_bit_set('12345678', -10); -- error +select gms_utility.is_bit_set('12345678', 0); -- error +select gms_utility.is_bit_set('12345678', 100); +select gms_utility.is_bit_set('12345678', 3.14E100); -- error +select gms_utility.is_bit_set('团团又圆圆', 20); -- error +-- end test is_bit_set + +-- start test is_cluster_database +select gms_utility.is_cluster_database(); +select gms_utility.is_cluster_database(1000); +begin + if gms_utility.is_cluster_database then + raise info 'true'; + else + raise info 'false'; + end if; +end; +/ +-- end test is_cluster_database + +-- start test old_current_schema +select gms_utility.old_current_schema(); +select gms_utility.old_current_schema(2000); +-- end test old_current_schema + +-- start test old_current_user +select gms_utility.old_current_user(); +select gms_utility.old_current_user(2000); +-- end test old_current_user + +--------------------------- +-- expand_sql_text +--------------------------- +create schema test_utility_est; +set search_path to test_utility_est; + +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text(NULL, sqlTxt); + raise info 'output_sql_text: %', sqlTxt; +end; +/ +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text(NULL); + raise info 'output_sql_text: %', sqlTxt; +end; +/ + +create table test_dx(id int); +create view view1 as select * from test_dx; +create materialized view mv_dx as select * from test_dx; + +declare + input_sql_text clob := 'select * from test_utility_est.view1'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +declare + input_sql_text clob := 'select * from test_utility_est.view1;'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +-- don't expand materialized view sql, just print +declare + input_sql_text clob := 'select * from test_utility_est.mv_dx'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +-- test multi sql, error +declare + input_sql_text clob := 'select * from test_utility_est.view1;select * from test_utility_est.view1'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +-- test select into +insert into test_dx values (3); +declare + num int := 0; + input_sql_text clob := 'select * into t_into from test_utility_est.view1;'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +declare + num int := 0; + output_sql_text clob; +begin + gms_utility.expand_sql_text('select id into num from test_utility_est.view1', output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +--test with select +declare + num int := 0; + input_sql_text clob := 'with ws (id) AS (select id from test_utility_est.view1) select * from ws'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +-- test select for update +declare + input_sql_text clob := 'select * from test_utility_est.test_dx for update'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ +declare + input_sql_text clob := 'select * from test_utility_est.view1 for update'; + output_sql_text clob; +begin + gms_utility.expand_sql_text(input_sql_text, output_sql_text); + raise info 'output_sql_text: %', output_sql_text; +end; +/ + +create table test_1(id int, name varchar(20)); +create table test_2(id int, name varchar(20)); +create view view2 as select * from test_1; +create view view3 as select * from test_1 union select * from test_2; +create view view4 as select * from test_1 union select * from view3; + +declare + input_sql_text1 clob := 'select * from test_utility_est.view3'; + output_sql_text1 clob; + input_sql_text2 clob := 'select * from test_utility_est.view4'; + output_sql_text2 clob; +begin + gms_utility.expand_sql_text(input_sql_text1, output_sql_text1); + raise info 'output_sql_text1: %', output_sql_text1; + gms_utility.expand_sql_text(input_sql_text2, output_sql_text2); + raise info 'output_sql_text2: %', output_sql_text2; +END; +/ + +declare + input_sql_text1 clob := 'select * from test_utility_est.view3'; + output_sql_text1 clob; + input_sql_text2 clob := 'select * from test_utility_est.view4'; + output_sql_text2 clob; +begin + gms_utility.expand_sql_text(input_sql_text1, output_sql_text1); + raise info 'output_sql_text1: %', output_sql_text1; + gms_utility.expand_sql_text(input_sql_text2, output_sql_text2); + raise info 'output_sql_text2: %', output_sql_text2; +END; +/ + +-- test not select query, error +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text('create table test(id int)', sqlTxt); + raise info 'output_sql_text: %', sqlTxt; +end; +/ +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text('begin', sqlTxt); + raise info 'output_sql_text: %', sqlTxt; +end; +/ +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text('update test_1 set name = ''ggboom'' where id = 1', sqlTxt); + raise info 'output_sql_text: %', sqlTxt; +end; +/ +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text('delete from test_1', sqlTxt); + raise info 'output_sql_text: %', sqlTxt; +end; +/ + +-- test not valid query, error +declare + sqlTxt CLOB; +begin + gms_utility.expand_sql_text('today is a good day', sqlTxt); + raise info 'output_sql_text: %', sqlTxt; +end; +/ + +create table t1(srvr_id int); +create view expandv as select * from t1; + +declare + vclobin clob := +'select distinct srvr_id +from public.expandv +where srvr_id not in +(select srvr_id +from public.expandv +minus +select srvr_id +from public.t1)'; + vclobout clob; +begin + gms_utility.expand_sql_text(vclobin, vclobout); + raise info 'output_sql_text: %', vclobout; +end; +/ + +-- test privileges +create user user01 password 'utility@123'; +set session AUTHORIZATION user01 password 'utility@123'; +set search_path to test_utility_est; + +declare + input_sql_text1 clob := 'select * from test_utility_est.view3'; + output_sql_text1 clob; +begin + gms_utility.expand_sql_text(input_sql_text1, output_sql_text1); + raise info 'output_sql_text1: %', output_sql_text1; +END; +/ + +RESET SESSION AUTHORIZATION; + +drop view view4; +drop view view3; +drop view view2; +drop view view1; +drop view expandv; +drop materialized view mv_dx; +drop table t1; +drop table if exists t_into; +drop talbe if exists test_2; +drop talbe if exists test_1; +drop talbe if exists test_dx; + +drop schema test_utility_est; + +--------------------------- +-- analyze_schema|database +--------------------------- +create user test_utility_analyze password "test_utility_analyze@123"; +set search_path to test_utility_analyze; + +create table t1 (id int, c2 text); +create unique index t1_id_uidx on t1 using btree(id); +insert into t1 values (generate_series(1, 100), 'aabbcc'); +insert into t1 values (generate_series(101, 200), '123dfg'); +insert into t1 values (generate_series(201, 300), '人面桃花相映红'); +insert into t1 values (generate_series(301, 400), 'fortunate'); +insert into t1 values (generate_series(401, 500), 'open@gauss'); +insert into t1 values (generate_series(501, 600), '127.0.0.1'); +insert into t1 values (generate_series(601, 700), '!@#$!%#!'); +insert into t1 values (generate_series(701, 800), '[1,2,3,4]'); +insert into t1 values (generate_series(801, 900), '{"name":"张三","age":18}'); +insert into t1 values (generate_series(901, 1000), ''); + +create or replace function batch_insert(count INT) +returns int as $$ +declare + i INT; + start INT; +begin + select count(*) into start from t1; + for i in select generate_series(1, count) loop + insert into t1 values (start + i, left((pg_catalog.random() * i)::text, 6)); + end loop; + + return count; +end; +$$ language plpgsql; + +select batch_insert(50000); + +-- analyze_schema +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000); +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=-100); -- error +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_percent:=20); +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_percent:=0); +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_percent:=101); -- error +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101); +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR TABLE'); +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL INDEXES'); +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL COLUMNS'); +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL COLUMNS SIZE 100'); +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL INDEXED COLUMNS'); +call gms_utility.analyze_schema('test_utility_analyze', 'ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL INDEXED COLUMNS SIZE 100'); + +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE'); +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', estimate_rows:=10000); +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', estimate_percent:=-100); +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', estimate_rows:=10000, estimate_percent:=-100); +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR TABLE'); +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL INDEXES'); +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL INDEXED COLUMNS'); +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL INDEXED COLUMNS SIZE 100'); +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL COLUMNS'); +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL COLUMNS SIZE 100'); +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR TABLE FOR ALL INDEXES'); +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR TABLE FOR ALL INDEXED COLUMNS'); +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR TABLE123'); -- error +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='111FOR TABLE'); -- error + +call gms_utility.analyze_schema('test_utility_analyze', 'DELETE'); +call gms_utility.analyze_schema('test_utility_analyze', 'DELETE', method_opt:='FOR TABLE'); -- error +DECLARE + res boolean; +BEGIN + gms_utility.analyze_schema('SYSTEM','ESTIMATE', NULL, 10); + EXCEPTION + WHEN OTHERS THEN + NULL; +END; +/ + +-- test analyze database +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000); +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=-100); -- error +call gms_utility.analyze_database('ESTIMATE', estimate_percent:=20); +call gms_utility.analyze_database('ESTIMATE', estimate_percent:=0); +call gms_utility.analyze_database('ESTIMATE', estimate_percent:=101); -- error +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101); +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR TABLE'); +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL INDEXES'); +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL COLUMNS'); +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL COLUMNS SIZE 100'); +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL INDEXED COLUMNS'); +call gms_utility.analyze_database('ESTIMATE', estimate_rows:=10000, estimate_percent:=101, method_opt:='FOR ALL INDEXED COLUMNS SIZE 100'); + +call gms_utility.analyze_database('COMPUTE'); +call gms_utility.analyze_database('COMPUTE', estimate_rows:=10000); +call gms_utility.analyze_database('COMPUTE', estimate_percent:=-100); +call gms_utility.analyze_database('COMPUTE', estimate_rows:=10000, estimate_percent:=-100); +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR TABLE'); +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL INDEXES'); +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL INDEXED COLUMNS'); +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL INDEXED COLUMNS SIZE 100'); +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL COLUMNS'); +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL COLUMNS SIZE 100'); +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR TABLE FOR ALL INDEXES'); +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR TABLE FOR ALL INDEXED COLUMNS'); +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR TABLE123'); -- error +call gms_utility.analyze_database('COMPUTE', method_opt:='111FOR TABLE'); -- error + +call gms_utility.analyze_database('DELETE'); +call gms_utility.analyze_database('DELETE', method_opt:='FOR TABLE'); -- error + +ALTER INDEX t1_id_uidx UNUSABLE; +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL INDEXES'); +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL INDEXES'); + +ALTER INDEX t1_id_uidx REBUILD; +call gms_utility.analyze_schema('test_utility_analyze', 'COMPUTE', method_opt:='FOR ALL INDEXES'); +call gms_utility.analyze_database('COMPUTE', method_opt:='FOR ALL INDEXES'); + +drop table t1 cascade; +drop function batch_insert; + +reset search_path; +drop user test_utility_analyze cascade; + +--------------------------- +-- canonicalize +--------------------------- +create schema test_utility_canonicalize; +set search_path to test_utility_canonicalize; + +-- canonicalize +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('uwclass.test', canon_name, 16); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +-- empty、space +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize(NULL, canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- NULL +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('""', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize(' ', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize(' .abcd', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll..nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll."".nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('"koll"', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize(' " koll.rooy" .nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('"~!#@@#$%)(#@(!@))<>?/*-+".nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy#_$nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll."rooy" abc.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nu"uo"p', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy."nu"u"o"p', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll."rooy"."nuuop.', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +-- identy +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.123rooy.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll._rooy.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- ok for og, error for A +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll."_rooy".nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('table', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.table.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('column', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.column.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; -- error +/ +-- test indentifier overlength; og >= 64, A >= 128 +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.DoYouThinkCausalUnderstandingIsADefiningCharacteristicOfHumanCognition.nuuop.a', canon_name, 100); + raise info 'canon_name: %', canon_name; +end; +/ + +-- param canon_len +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name, -10); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name, 0); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name, 10); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(100); +begin + gms_utility.canonicalize('开车.rooy.nuuop.a', canon_name, 10); + raise info 'canon_name: %', canon_name; +end; +/ + +declare + canon_name varchar2(10); +begin + gms_utility.canonicalize('koll.rooy.nuuop.a', canon_name, 20); + raise info 'canon_name: %', canon_name; +end; -- error +/ + +drop schema test_utility_canonicalize; + +--------------------------- +-- compile schema +--------------------------- +create schema test_utility_compile; +set search_path to test_utility_compile; + +create table classes ( + class_id int primary key, + class_name varchar(50) not null +) +with (orientation=row, compression=no); + +create table students ( + student_id int primary key, + class_id int, + student_name varchar(50) not null +) +with (orientation=row, compression=no); + +create table studentscores ( + score_id int primary key, + student_id int, + subject varchar(50), + score int +) +with (orientation=row, compression=no); + +create or replace procedure insertclass(in classname varchar(50)) +as + ct int; +begin + select count(class_id) into ct from classes; + insert into classes values (ct + 1, classname); +end; +/ + +create or replace procedure insertstudent(in classname varchar(50), in studentname varchar(50)) +as + classid int; + ct int; +begin + select class_id into classid from classes where class_name = classname; + select count(student_id) into ct from students; + insert into students values (ct + 1, classid, studentname); +end; +/ + +create or replace function insertscore(studentid int, subject varchar(50), score int) +returns int +as $$ +declare + ct int; +begin + select count(score_id) into ct from studentscores; + insert into studentscores values (ct + 1, studentid, subject, score); + return ct + 1; +end; +$$ language plpgsql; + +create or replace function getrank(score int) +returns text +as $$ +declare + rk text; +begin + if score = 100 then + rk := 'perfect'; + elsif score >= 80 then + rk := 'nice'; + elsif score >= 60 then + rk := 'ordinary'; + elsif score >= 0 then + rk := 'poor'; + else + raise notice 'error input'; + end if; + + return rk; +end; +$$ language plpgsql; + +call insertclass('class a'); +call insertclass('class b'); + +call insertstudent('class a', 'alice'); +call insertstudent('class a', 'bob'); +call insertstudent('class b', 'charlie'); +call insertstudent('class b', 'rose'); +call insertstudent('class b', 'jack'); + +select insertscore(1, 'math', 90); +select insertscore(1, 'science', 85); +select insertscore(2, 'math', 95); +select insertscore(2, 'science', 88); +select insertscore(3, 'math', 78); +select insertscore(3, 'science', 82); +select insertscore(4, 'math', 100); +select insertscore(4, 'science', 66); +select insertscore(5, 'math', 57); +select insertscore(5, 'science', 68); + +create view stud_class as select s.student_name, c.class_name from students s join classes c on s.class_id = c.class_id; +create view stud_score as select b.student_name, a.subject, a.score, getrank(a.score) from studentscores a join students b on a.student_id = b.student_id; + +create table t_pkg (c1 text); + +create package p_batch as + procedure insertpkg(txt text); + function batchinsert(num int) return int; +end p_batch; +/ + +create package body p_batch as + procedure insertpkg(txt text) + as + begin + insert into t_pkg values (txt); + end; + + function batchinsert(num int) + return int + is + start int := 0; + i int := 0; + begin + select count(*) into start from t_pkg; + for i in select generate_series(1, num) loop + insert into t1 values (start + i, left((pg_catalog.random() * i)::text, 6)); + end loop; + + return i; + end; +end p_batch; +/ + +call gms_utility.compile_schema('test_utility_compile'); +call gms_utility.compile_schema('test_utility_compile', false); +call gms_utility.compile_schema('test_utility_compile', true, false); + +call gms_utility.compile_schema(); -- error +call gms_utility.compile_schema(1); -- error +call gms_utility.compile_schema('no_schema'); -- error + +create or replace function getrank(score int) +returns text +as $$ +declare + rk text; +begin + if score = 100 then + rk := 'perfect'; + elsif score >= 80 then + rk := 'nice'; + elsif score >= 60 then + rk := 'ordinary'; + elsif score >= 0 then + rk := 'poor'; + else + rk := 'error'; + end if; + + return rk; +end; +$$ language plpgsql; + +call gms_utility.compile_schema('test_utility_compile'); + +drop package body p_batch; +drop package p_batch; +drop table t_pkg; +drop view stud_score; +drop view stud_class; +drop function getrank; +drop function insertscore; +drop procedure insertstudent; +drop procedure insertclass; +drop table studentscores; +drop table students; +drop table classes; + +-- test invalid object compile +set behavior_compat_options = 'plpgsql_dependency'; +create type s_type as ( + id integer, + name varchar, + addr text +); +create or replace procedure type_alter(a s_type) +is +begin + raise info 'call a: %', a; +end; +/ +select valid from pg_object where object_type='p' and object_oid in (select oid from pg_proc where propackageid = 0 and proname='type_alter' and pronamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); +alter type s_type add attribute a int; +select valid from pg_object where object_type='p' and object_oid in (select oid from pg_proc where propackageid = 0 and proname='type_alter' and pronamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); +call gms_utility.compile_schema('test_utility_compile', false); +select valid from pg_object where object_type='p' and object_oid in (select oid from pg_proc where propackageid = 0 and proname='type_alter' and pronamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + +create table stu(sno int, name varchar, sex varchar, cno int); +create type r1 as (a int, c stu%rowtype); +create or replace package pkg +is + procedure proc1(p_in r1); +end pkg; +/ +create or replace package body pkg +is +declare + v1 r1; + v2 stu%rowtype; + procedure proc1(p_in r1) as + begin + raise info 'call p_in: %', p_in; + end; +end pkg; +/ +call pkg.proc1((1,(1,'zhang','m',1))); +select valid from pg_object where object_type='b' and object_oid in (select oid from gs_package where pkgname='pkg' and pkgnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); +alter table stu add column b int; +select valid from pg_object where object_type='b' and object_oid in (select oid from gs_package where pkgname='pkg' and pkgnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); +call gms_utility.compile_schema('test_utility_compile', false); +select valid from pg_object where object_type='b' and object_oid in (select oid from gs_package where pkgname='pkg' and pkgnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + +create view v_stu as select * from stu; +select * from v_stu; +select valid from pg_object where object_type='v' and object_oid in (select oid from pg_class where relname='v_stu' and relkind='v' and relnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); +alter table stu drop column b; +select valid from pg_object where object_type='v' and object_oid in (select oid from pg_class where relname='v_stu' and relkind='v' and relnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); +call gms_utility.compile_schema('test_utility_compile', false); +select valid from pg_object where object_type='v' and object_oid in (select oid from pg_class where relname='v_stu' and relkind='v' and relnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); +select * from v_stu; + +alter table stu add column b int; +select valid from pg_object where object_type='v' and object_oid in (select oid from pg_class where relname='v_stu' and relkind='v' and relnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); +call gms_utility.compile_schema('test_utility_compile', false); +select valid from pg_object where object_type='v' and object_oid in (select oid from pg_class where relname='v_stu' and relkind='v' and relnamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); +select * from v_stu; + +drop view v_stu; +drop package body pkg; +drop package pkg cascade; +drop type r1; +drop table stu; +drop procedure type_alter; + +-- test procedure compile error +set behavior_compat_options = 'plpgsql_dependency'; +create or replace procedure proc_err(p_in s_type) as +begin + raise info 'call p_in: %', p_in; +end; +/ +drop type s_type; +select valid from pg_object where object_type='p' and object_oid in (select oid from pg_proc where propackageid = 0 and proname='proc_err' and pronamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); +call gms_utility.compile_schema('test_utility_compile', false); +select valid from pg_object where object_type='p' and object_oid in (select oid from pg_proc where propackageid = 0 and proname='proc_err' and pronamespace = (select oid from pg_namespace where nspname = 'test_utility_compile')); + +drop procedure proc_err; + +drop schema test_utility_compile cascade; + +--------------------------- +-- name tokenize +--------------------------- +create schema test_utility_tokenize; +set search_path to test_utility_tokenize; + +declare + name varchar2(50) := 'peer.lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ + +-- test empty character +declare + name varchar2(50) := NULL; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := ''; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := '""'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := ' . '; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := '" . "'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +declare + name varchar2(50) := 'peer. lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +declare + name varchar2(50) := 'peer." lokppe.vuumee"@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ + +-- test support special char +declare + name varchar2(50) := 'peer._lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- ok for og, error for A +/ +declare + name varchar2(50) := 'peer.lokp_pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +declare + name varchar2(50) := 'peer.$lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- ok for og, error for A +/ +declare + name varchar2(50) := 'peer.lokp$pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +declare + name varchar2(50) := 'peer.lokp233pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +declare + name varchar2(50) := 'peer.233lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = , c = , dblink = , nextpos = 4 +/ +declare + name varchar2(50) := 'peer.-lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := 'peer."-lokppe".vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +declare + name varchar2(50) := 'peer.lokp-pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = LOKP, c = , dblink = , nextpos = 9 +/ +declare + name varchar2(50) := 'peer.lokp=pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = LOKP, c = , dblink = , nextpos = 9 +/ +declare + name varchar2(50) := 'peer.=lokppe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := 'peer.lokp`pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := 'peer.lokp~pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := 'peer.lokp%pe.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ + +-- test keyword +declare + name varchar2(50) := 'peer.table.vuumee@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ + +-- test @ +declare + name varchar2(50) := 'peer.lokppe.vuumee@'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := 'peer.lokppe.vuumee@_ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- ok for og, error for A +/ +declare + name varchar2(50) := 'peer.lokppe.vuumee@"_ookeyy"'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +declare + name varchar2(50) := 'peer.lokppe.vuumee@$ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- ok for og, error for A +/ +declare + name varchar2(50) := 'peer.lokppe.vuumee@"$ookeyy"'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +declare + name varchar2(50) := 'peer.lokppe.vuumee@123ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := 'peer.lokppe.vuumee@ookeyy.zk'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; +/ +declare + name varchar2(50) := 'peer.lokppe.vuumee@'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := '@vuumee'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := 'peer.lokppe.vuumee@ook=eyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = LOKPPE, c = VUUMEE, dblink = OOK, nextpos = 22 +/ +declare + name varchar2(50) := 'peer.lokppe.vuumee@=ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ +declare + name varchar2(50) := 'peer.lokppe.vuumee@ook%eyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ + +-- test double quote +declare + name varchar2(50) := 'peer.lokppe.vuumee"@ookeyy"'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = LOKPPE, c = VUUMEE, dblink = , nextpos = 18 +/ +declare + name varchar2(50) := 'peer.lokppe.vu"ume"e@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = LOKPPE, c = VU, dblink = , nextpos = 14 +/ +declare + name varchar2(50) := 'peer.lokppe."vu"ume"e@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- a = PEER, b = LOKPPE, c = vu, dblink = , nextpos = 16 +/ +declare + name varchar2(50) := 'peer.lokppe.vuumee.aking@ookeyy'; + a varchar2(50); + b varchar2(50); + c varchar2(50); + dblink varchar2(50); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ + +-- test idnetifier overlength. og >= 64, A >= 128 +declare + name varchar2(100) := 'peer.DoYouThinkCausalUnderstandingIsADefiningCharacteristicOfHumanCognition.vuumee.aking@ookeyy'; + a varchar2(100); + b varchar2(100); + c varchar2(100); + dblink varchar2(100); + nextpos integer; +begin + gms_utility.name_tokenize(name, a, b, c, dblink, nextpos); + raise info 'a = %, b = %, c = %, dblink = %, nextpos = %', a, b, c, dblink, nextpos; +end; -- error +/ + +drop schema test_utility_tokenize; + +--------------------------- +-- name resolve +--------------------------- +reset search_path; + +-- prepare data +CREATE TABLE public.t_resolve (c1 NUMBER, c2 VARCHAR2(100)); +CREATE UNIQUE INDEX IF NOT EXISTS public.t_resolve_c1_udx ON public.t_resolve(c1); +CREATE TABLE public.t_log (c1 NUMBER, c2 TIMESTAMP); + +CREATE SEQUENCE IF NOT EXISTS public.t_seq + INCREMENT BY 1 + NOMINVALUE + NOMAXVALUE + START WITH 1 + NOCYCLE; +SELECT public.t_seq.NEXTVAL; + +CREATE OR REPLACE FUNCTION public.add_numbers ( + p_num1 IN INT, + p_num2 IN INT +) RETURN NUMBER IS + v_result INT; +BEGIN + v_result := p_num1 + p_num2; + RETURN v_result; +END; +/ + +CREATE OR REPLACE PROCEDURE public.insert_val(name VARCHAR2(100)) IS + id INT := 0; +BEGIN + SELECT public.t_seq.NEXTVAL INTO id; + INSERT INTO public.t_resolve VALUES (id, name); +END; +/ + +CREATE OR REPLACE FUNCTION public.tg_log() RETURNS TRIGGER AS +$$ +BEGIN + INSERT INTO public.t_log VALUES (NEW.c1, SYSDATE); + RETURN NEW; +END; +$$ LANGUAGE PLPGSQL; + +CREATE TRIGGER log_resolve_after_insert +AFTER INSERT ON public.t_resolve +FOR EACH ROW +EXECUTE PROCEDURE public.tg_log(); + +CREATE OR REPLACE PACKAGE public.t_pkg IS + FUNCTION multi_number(num1 IN INT, num2 IN INT) RETURN INT; + PROCEDURE delete_val(id IN INT); +END t_pkg; +/ + +CREATE OR REPLACE PACKAGE BODY public.t_pkg IS + FUNCTION multi_number(num1 IN INT, num2 IN INT) RETURN INT IS + v_res INT; + BEGIN + v_res = num1 * num2; + return v_res; + END multi_number; + + PROCEDURE delete_val(id IN INT) AS + BEGIN + DELETE FROM t_resolve WHERE c1 = id; + END delete_val; +END t_pkg; +/ + +CREATE TYPE public.t_typ AS (t1 INT, t2 TEXT); + +CREATE OR REPLACE SYNONYM public.syn_tbl FOR t_resolve; +CREATE OR REPLACE SYNONYM public.syn_idx FOR t_resolve_c1_udx; +CREATE OR REPLACE SYNONYM public.syn_seq FOR t_seq; +CREATE OR REPLACE SYNONYM public.syn_fun FOR add_numbers; +CREATE OR REPLACE SYNONYM public.syn_pro FOR insert_val; +CREATE OR REPLACE SYNONYM public.syn_tg FOR log_resolve_after_insert; +CREATE OR REPLACE SYNONYM public.syn_pkg FOR t_pkg; +CREATE OR REPLACE SYNONYM public.syn_typ FOR t_typ; + + +-- test table +declare + name varchar2 := 'public.t_resolve'; + context number := 0; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 't_resolve'; + context number := 0; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.syn_tbl'; + context number := 0; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'syn_tbl'; + context number := 0; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +-- test PL/SQL +declare + name varchar2 := 'public.add_numbers'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'add_numbers'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.syn_fun'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'syn_fun'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.insert_val'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'insert_val'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.syn_pro'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'syn_pro'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +-- test package +declare + name varchar2 := 'public.t_pkg.multi_number'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.t_pkg.delete_val'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.t_pkg.qwer'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 't_pkg.multi_number'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 't_pkg.delete_val'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 't_pkg.qwer'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.syn_pkg.multi_number'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.syn_pkg.delete_var'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.syn_pkg.qwer'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'syn_pkg.multi_number'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'syn_pkg.delete_var'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'syn_pkg.qwer'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ + +-- test trigger +declare + name varchar2 := 'public.log_resolve_after_insert'; + context number := 3; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.syn_tg'; + context number := 3; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; -- error +/ +declare + name varchar2 := 'log_resolve_after_insert'; + context number := 3; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'syn_tg'; + context number := 3; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; -- error +/ + +-- test sequence +declare + name varchar2 := 'public.t_seq'; + context number := 2; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.syn_seq'; + context number := 2; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 't_seq'; + context number := 2; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'syn_seq'; + context number := 2; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ + +-- test type +declare + name varchar2 := 'public.t_typ'; + context number := 7; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.syn_typ'; + context number := 7; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 't_typ'; + context number := 7; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'syn_typ'; + context number := 7; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ + +-- test index +declare + name varchar2 := 'public.t_resolve_c1_udx'; + context number := 9; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.syn_idx'; + context number := 9; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; -- error +/ +declare + name varchar2 := 't_resolve_c1_udx'; + context number := 9; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'syn_idx'; + context number := 9; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; -- error +/ + +-- test java +declare + name varchar2 := 'public.java.class'; + context number := 4; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.java.class'; + context number := 5; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.java.class'; + context number := 6; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'public.java.class'; + context number := 8; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ + +-- test with dblink +declare + name varchar2 := 'peer.lokppe.vuumee@ookeyy'; + context number := 0; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'peer@ookeyy'; + context number := 1; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'peer@ookeyy'; + context number := 2; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'peer.@ookeyy'; + context number := 3; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; -- error +/ +declare + name varchar2 := 'peer.lokppe@ookeyy'; + context number := 7; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'peer.lokppe@ookeyy'; + context number := 9; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ +declare + name varchar2 := 'peer.lokppe@ookeyy'; + context number := 10; + schema varchar2; + part1 varchar2; + part2 varchar2; + dblink varchar2; + part1_type number; + object_number number; +begin + gms_utility.NAME_RESOLVE(name, context, schema, part1, part2, dblink, part1_type, object_number); + raise info 'schema = %, part1 = %, part2 = %, dblink = %, part1_type = %, object_number = %', schema, part1, part2, dblink, part1_type, object_number; +end; +/ + +DROP SYNONYM syn_tbl; +DROP SYNONYM syn_idx; +DROP SYNONYM syn_seq; +DROP SYNONYM syn_fun; +DROP SYNONYM syn_pro; +DROP SYNONYM syn_tg; +DROP SYNONYM syn_pkg; +DROP SYNONYM syn_typ; +DROP TYPE public.t_typ; +DROP PACKAGE BODY public.t_pkg; +DROP PACKAGE public.t_pkg; +DROP TRIGGER log_resolve_after_insert ON t_resolve; +DROP FUNCTION public.tg_log; +DROP FUNCTION public.add_numbers; +DROP PROCEDURE public.insert_val; +DROP INDEX public.t_resolve_c1_udx; +DROP TABLE public.t_log; +DROP TABLE public.t_resolve; +DROP SEQUENCE public.t_seq; + +drop extension gms_utility cascade; +reset search_path; \ No newline at end of file diff --git a/src/common/backend/parser/parse_relation.cpp b/src/common/backend/parser/parse_relation.cpp index 1e7660fe6..a35a73150 100755 --- a/src/common/backend/parser/parse_relation.cpp +++ b/src/common/backend/parser/parse_relation.cpp @@ -1069,7 +1069,7 @@ enum ValidateDependResult { }; -static ValidateDependResult ValidateDependView(Oid view_oid, char objType, List** list) +static ValidateDependResult ValidateDependView(Oid view_oid, char objType, List** list, bool force) { bool isValid = true; bool existTable = false; @@ -1078,7 +1078,7 @@ static ValidateDependResult ValidateDependView(Oid view_oid, char objType, List* List* originEvAction = NIL; List* freshedEvAction = NIL; // 1. filter the valid view - if (GetPgObjectValid(view_oid, objType)) { + if (!force && GetPgObjectValid(view_oid, objType)) { return ValidateDependValid; } @@ -1157,8 +1157,9 @@ static ValidateDependResult ValidateDependView(Oid view_oid, char objType, List* } } else if (relkind == RELKIND_VIEW || relkind == RELKIND_MATVIEW) { char type = relkind == RELKIND_VIEW ? OBJECT_TYPE_VIEW : OBJECT_TYPE_MATVIEW; - ValidateDependResult result = ValidateDependView(dep_objid, type, list); + ValidateDependResult result = ValidateDependView(dep_objid, type, list, force); if (result == ValidateDependCircularDepend) { + list_free(*list); ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg( @@ -1241,7 +1242,7 @@ static ValidateDependResult ValidateDependView(Oid view_oid, char objType, List* bool ValidateDependView(Oid view_oid, char objType) { List * list = NIL; - ValidateDependResult result = ValidateDependView(view_oid, objType, &list); + ValidateDependResult result = ValidateDependView(view_oid, objType, &list, false); list_free_ext(list); if (result == ValidateDependCircularDepend) { ereport(ERROR, @@ -1252,6 +1253,26 @@ bool ValidateDependView(Oid view_oid, char objType) { return result != ValidateDependInvalid; } +bool ValidateDependViewDetectRecursion(Oid viewOid, char objType, bool force, List* records) +{ + ListCell* lc; + List* list = NIL; + if (records != NIL && list_member_oid(records, viewOid)) { + return true; + } + ValidateDependResult result = ValidateDependView(viewOid, objType, &list, force); + if (result == ValidateDependCircularDepend) { + list_free(list); + ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("infinite recursion detected in rules for relation: \"%s\"", get_rel_name(viewOid)))); + } + foreach (lc, list) { + records = list_append_unique_oid(records, lfirst_oid(lc)); + } + list_free(list); + return result != ValidateDependInvalid; +} + /* * Open a table during parse analysis * @@ -1410,7 +1431,7 @@ Relation parserOpenTable(ParseState *pstate, const RangeVar *relation, int lockm if (RelationGetRelkind(rel) == RELKIND_VIEW && RelationGetRelid(rel) >= FirstNormalObjectId) { - if (ValidateDependView(RelationGetRelid(rel), OBJECT_TYPE_VIEW) == ValidateDependInvalid) { + if (!ValidateDependView(RelationGetRelid(rel), OBJECT_TYPE_VIEW)) { ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("The view %s is invalid, please make it valid before operation.", diff --git a/src/gausskernel/optimizer/commands/dropcmds.cpp b/src/gausskernel/optimizer/commands/dropcmds.cpp index 26cdd6256..b327297da 100644 --- a/src/gausskernel/optimizer/commands/dropcmds.cpp +++ b/src/gausskernel/optimizer/commands/dropcmds.cpp @@ -97,6 +97,7 @@ static void DropExtensionInListIsSupported(List* objname) "hdfs_fdw", "age", "gms_compress", + "gms_utility", "gms_stats", "gms_output", "gms_inaddr", diff --git a/src/gausskernel/optimizer/commands/packagecmds.cpp b/src/gausskernel/optimizer/commands/packagecmds.cpp index 9e5d16faa..e5022cc42 100644 --- a/src/gausskernel/optimizer/commands/packagecmds.cpp +++ b/src/gausskernel/optimizer/commands/packagecmds.cpp @@ -236,7 +236,7 @@ static inline void clear_plsql_ctx_line_info() u_sess->plsql_cxt.package_as_line = 0; } -static void RecompileSinglePackage(Oid package_oid, bool is_spec) +void RecompileSinglePackage(Oid package_oid, bool is_spec) { Oid* save_pseudo_current_user_id = u_sess->misc_cxt.Pseudo_CurrentUserId; _PG_init(); diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h index cd43b435a..71b1f84d0 100644 --- a/src/include/parser/parse_relation.h +++ b/src/include/parser/parse_relation.h @@ -59,6 +59,7 @@ extern Oid attnumCollationId(Relation rd, int attid); extern bool GetPartitionOidForRTE(RangeTblEntry *rte, RangeVar *relation, ParseState *pstate, Relation rel); extern bool GetSubPartitionOidForRTE(RangeTblEntry *rte, RangeVar *relation, ParseState *pstate, Relation rel); extern bool ValidateDependView(Oid view_oid, char obj_type); +extern bool ValidateDependViewDetectRecursion(Oid viewOid, char objType, bool force, List* records); #ifdef PGXC extern int specialAttNum(const char* attname); #endif