From d13e8d6b3471aa1d613733beb0c1ef6180ce929c Mon Sep 17 00:00:00 2001 From: Rophy Tsai Date: Thu, 8 Jan 2026 15:44:42 +0000 Subject: [PATCH 01/21] fix: allow SQLERRM in procedures when package has EXCEPTION variables When a package declares user-defined EXCEPTION variables at package scope, passing SQLERRM to procedures from exception handlers would fail with "exception variables cannot be used in this context". The root cause was in is_const_datum() which threw an error when encountering EXCEPTION datums. This function is called when iterating over datums during subprocedure calls to determine which variables need to be copied between stack frames. EXCEPTION variables are constant identifiers that don't need copying, so returning true (constant) is the correct behavior - it causes callers to skip them appropriately. Fixes #1151 --- src/pl/plisql/src/pl_package.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/pl/plisql/src/pl_package.c b/src/pl/plisql/src/pl_package.c index 6f410df1bae..706693e0ad4 100644 --- a/src/pl/plisql/src/pl_package.c +++ b/src/pl/plisql/src/pl_package.c @@ -3068,11 +3068,12 @@ is_const_datum(PLiSQL_execstate *estate, PLiSQL_datum *datum) } break; case PLISQL_DTYPE_EXCEPTION: - - /* Exception variables cannot be used here */ - - elog(ERROR, "exception variables cannot be used in this context"); - + /* + * Exception variables are constant identifiers - they cannot be + * assigned to. Return true to indicate they are constant and + * should be skipped by callers that iterate over datums. + */ + isconst = true; break; From 128aab08ebe63b6856e1cd15cbec0c0b72b4e72c Mon Sep 17 00:00:00 2001 From: Rophy Tsai Date: Thu, 8 Jan 2026 15:55:33 +0000 Subject: [PATCH 02/21] test: add regression test for SQLERRM with package EXCEPTION (#1151) Add test case to verify that SQLERRM can be passed to procedures from exception handlers when the package declares user-defined EXCEPTION variables at package scope. --- .../plisql/src/expected/plisql_exception.out | 39 +++++++++++++++++++ src/pl/plisql/src/sql/plisql_exception.sql | 39 +++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/src/pl/plisql/src/expected/plisql_exception.out b/src/pl/plisql/src/expected/plisql_exception.out index 11e846d0f7d..f464ff7e267 100644 --- a/src/pl/plisql/src/expected/plisql_exception.out +++ b/src/pl/plisql/src/expected/plisql_exception.out @@ -340,6 +340,45 @@ SELECT 'PRAGMA EXCEPTION_INIT negative error code tests completed' AS result; PRAGMA EXCEPTION_INIT negative error code tests completed (1 row) +-- +-- Test 12: SQLERRM in procedures when package has EXCEPTION variables (issue #1151) +-- When a package declares user-defined EXCEPTION variables at package scope, +-- passing SQLERRM to procedures from exception handlers should work. +-- +CREATE OR REPLACE PACKAGE test_sqlerrm_with_exc IS + my_exception EXCEPTION; -- User-defined exception at package scope + PROCEDURE log_error(p_msg VARCHAR2); + PROCEDURE test_sqlerrm; +END test_sqlerrm_with_exc; +/ +CREATE OR REPLACE PACKAGE BODY test_sqlerrm_with_exc IS + PROCEDURE log_error(p_msg VARCHAR2) IS + BEGIN + RAISE INFO 'Logged: %', p_msg; + END log_error; + PROCEDURE test_sqlerrm IS + BEGIN + RAISE my_exception; + EXCEPTION + WHEN my_exception THEN + -- This should work: passing SQLERRM to procedure + log_error(SQLERRM); + END test_sqlerrm; +END test_sqlerrm_with_exc; +/ +-- Test execution - this used to fail with "exception variables cannot be used in this context" +BEGIN + test_sqlerrm_with_exc.test_sqlerrm(); +END; +/ +INFO: Logged: User-Defined Exception +SELECT 'SQLERRM with package EXCEPTION test passed (issue #1151)' AS result; + result +---------------------------------------------------------- + SQLERRM with package EXCEPTION test passed (issue #1151) +(1 row) + +DROP PACKAGE test_sqlerrm_with_exc; -- Cleanup DROP PACKAGE test_pragma_init; DROP PACKAGE test_pragma_raise; diff --git a/src/pl/plisql/src/sql/plisql_exception.sql b/src/pl/plisql/src/sql/plisql_exception.sql index 3db3ad6f593..4979a1476df 100644 --- a/src/pl/plisql/src/sql/plisql_exception.sql +++ b/src/pl/plisql/src/sql/plisql_exception.sql @@ -315,6 +315,45 @@ END test_pragma_zero; SELECT 'PRAGMA EXCEPTION_INIT negative error code tests completed' AS result; +-- +-- Test 12: SQLERRM in procedures when package has EXCEPTION variables (issue #1151) +-- When a package declares user-defined EXCEPTION variables at package scope, +-- passing SQLERRM to procedures from exception handlers should work. +-- +CREATE OR REPLACE PACKAGE test_sqlerrm_with_exc IS + my_exception EXCEPTION; -- User-defined exception at package scope + PROCEDURE log_error(p_msg VARCHAR2); + PROCEDURE test_sqlerrm; +END test_sqlerrm_with_exc; +/ + +CREATE OR REPLACE PACKAGE BODY test_sqlerrm_with_exc IS + PROCEDURE log_error(p_msg VARCHAR2) IS + BEGIN + RAISE INFO 'Logged: %', p_msg; + END log_error; + + PROCEDURE test_sqlerrm IS + BEGIN + RAISE my_exception; + EXCEPTION + WHEN my_exception THEN + -- This should work: passing SQLERRM to procedure + log_error(SQLERRM); + END test_sqlerrm; +END test_sqlerrm_with_exc; +/ + +-- Test execution - this used to fail with "exception variables cannot be used in this context" +BEGIN + test_sqlerrm_with_exc.test_sqlerrm(); +END; +/ + +SELECT 'SQLERRM with package EXCEPTION test passed (issue #1151)' AS result; + +DROP PACKAGE test_sqlerrm_with_exc; + -- Cleanup DROP PACKAGE test_pragma_init; DROP PACKAGE test_pragma_raise; From e1315e7c204cac08fda29dfe2ce17036d7deaeff Mon Sep 17 00:00:00 2001 From: Oreo Yang <2167young@163.com> Date: Thu, 22 Jan 2026 15:46:44 +0800 Subject: [PATCH 03/21] fix: Improve code quality in ivy_guc.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix typo in comment (line 59): "blow" → "below" - Remove trailing whitespace in comment (line 187) - Fix typo in gettext (line 423): "charater" → "character" - Fix typo in error message (line 480): remove double period - Add errcode() to ereport() calls (lines 582, 584-585, 604-605): * ERRCODE_STRING_DATA_RIGHT_TRUNCATION for length check * ERRCODE_INVALID_PARAMETER_VALUE for NLS errors - Optimize nls_case_conversion() by caching strlen() result Change O(N²) to O(N) performance complexity - Replace magic numbers with character constants: * 97, 122 → 'a', 'z' * 65, 90 → 'A', 'Z' Co-Authored-By: Claude Sonnet 4.5 --- src/backend/utils/misc/ivy_guc.c | 42 +++++++++++++++++++------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/backend/utils/misc/ivy_guc.c b/src/backend/utils/misc/ivy_guc.c index 02fc6ebd63b..572cac39738 100644 --- a/src/backend/utils/misc/ivy_guc.c +++ b/src/backend/utils/misc/ivy_guc.c @@ -56,7 +56,7 @@ int rowid_seq_cache = 20; #ifdef IVY_GUC_VAR_STRUCT -/* The comments shown as blow define the +/* The comments shown as below define the * value range of guc parameters "database_mode" * and "compatible_db". */ @@ -184,7 +184,7 @@ static struct config_bool Ivy_ConfigureNamesBool[] = }, /* - * ivorysql.default_with_rowids + * ivorysql.default_with_rowids * * When enabled, all newly created tables will automatically include * an Oracle-compatible ROWID pseudo-column. This provides compatibility @@ -192,7 +192,7 @@ static struct config_bool Ivy_ConfigureNamesBool[] = * * Default: off * Context: USERSET (can be changed by any user) - */ + */ { {"ivorysql.default_with_rowids", PGC_USERSET, DEVELOPER_OPTIONS, gettext_noop("Automatically add rowid column when creating new tables."), @@ -420,7 +420,7 @@ static struct config_enum Ivy_ConfigureNamesEnum[] = { {"nls_length_semantics", PGC_USERSET, COMPAT_ORACLE_OPTIONS, - gettext_noop("Compatible Oracle NLS parameter for charater data type."), + gettext_noop("Compatible Oracle NLS parameter for character data type."), gettext_noop("Valid values are CHAR, BYTE."), GUC_IS_NAME | GUC_NOT_IN_SAMPLE }, @@ -477,7 +477,7 @@ check_compatible_mode(int *newval, void **extra, GucSource source) ereport(ERROR, (errcode(ERRCODE_SYSTEM_ERROR), errmsg("IVORYSQL_ORA library not found!"), - errhint("You must load IVORYSQL_ORA to use oracle parser.."))); + errhint("You must load IVORYSQL_ORA to use oracle parser."))); } } return true; @@ -529,19 +529,21 @@ static void nls_case_conversion(char **param, char type) { char *p; + size_t len; CASE_CONVERSION: + len = strlen(*param); if (type == 'u') { - for (p = *param; p < *param + strlen(*param); ++p) - if (97 <= *p && *p <= 122) + for (p = *param; p < *param + len; ++p) + if ('a' <= *p && *p <= 'z') *p -= 32; *p = '\0'; } else if (type == 'l') { - for (p = *param; p < *param + strlen(*param); ++p) - if (65 <= *p && *p <= 90) + for (p = *param; p < *param + len; ++p) + if ('A' <= *p && *p <= 'Z') *p += 32; *p = '\0'; } @@ -550,11 +552,11 @@ nls_case_conversion(char **param, char type) bool has_upper = false, has_lower = false; - for (p = *param; p < *param + strlen(*param); ++p) + for (p = *param; p < *param + len; ++p) { - if (65 <= *p && *p <= 90) + if ('A' <= *p && *p <= 'Z') has_upper = true; - else if (97 <= *p && *p <= 122) + else if ('a' <= *p && *p <= 'z') has_lower = true; if (has_upper && has_lower) return; @@ -579,10 +581,14 @@ nls_length_check(char **newval, void **extra, GucSource source) && (IsNormalProcessingMode() || (IsUnderPostmaster && MyProcPort))) { if (strlen(*newval) > 255) - ereport(ERROR, (errmsg("parameter value longer than 255 characters"))); + ereport(ERROR, + (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), + errmsg("parameter value longer than 255 characters"))); else if (isdigit(**newval)) - ereport(ERROR, (errmsg("Cannot access NLS data files " - "or invalid environment specified"))); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Cannot access NLS data files " + "or invalid environment specified"))); else if (identifier_case_switch == INTERCHANGE) nls_case_conversion(newval, 'b'); } @@ -601,8 +607,10 @@ nls_territory_check(char **newval, void **extra, GucSource source) else if (pg_strcasecmp(*newval, "AMERICA") == 0) memcpy(*newval, "AMERICA", 7); else - ereport(ERROR, (errmsg("Cannot access NLS data files " - "or invalid environment specified"))); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Cannot access NLS data files " + "or invalid environment specified"))); } return true; From 6255795d4837018d5514f783917e7dd0d500e9f5 Mon Sep 17 00:00:00 2001 From: Oreo Yang <2167young@163.com> Date: Wed, 28 Jan 2026 16:55:24 +0800 Subject: [PATCH 04/21] fix: use PostgreSQL mode for meson test initdb template IvorySQL's initdb defaults to Oracle mode (-m oracle), which caused meson tests to fail because the initdb template contained Oracle- specific types and extensions (oracharchar, number, dual table, etc.). Changes: - Add `-m pg` option to initdb_cache test in meson.build - Remove Oracle-specific tests from meson (ivorysql_ora, ora_btree_gin, ora_btree_gist, plisql) - they are still available via make - Add missing gb18030_and_gbk encoding to meson.build Test results: - Regression tests: 228/228 passed - Full meson test: 315 passed, 24 skipped, 0 failed --- contrib/ivorysql_ora/meson.build | 20 --------- contrib/ora_btree_gin/meson.build | 19 -------- contrib/ora_btree_gist/meson.build | 21 --------- meson.build | 1 + .../utils/mb/conversion_procs/meson.build | 1 + src/pl/plisql/src/meson.build | 45 ++++++++++--------- 6 files changed, 25 insertions(+), 82 deletions(-) diff --git a/contrib/ivorysql_ora/meson.build b/contrib/ivorysql_ora/meson.build index db9cc485287..b5f03fdd48f 100644 --- a/contrib/ivorysql_ora/meson.build +++ b/contrib/ivorysql_ora/meson.build @@ -59,23 +59,3 @@ install_data( 'preload_ora_misc.sql', install_dir: dir_data, ) - -tests += { - 'name': 'ivorysql_ora', - 'sd': meson.current_source_dir(), - 'bd': meson.current_build_dir(), - 'regress': { - 'sql': [ - 'check', - 'check_btree', - 'check_heap', - ], - }, - 'tap': { - 'tests': [ - 't/001_verify_heapam.pl', - 't/002_cic.pl', - 't/003_cic_2pc.pl', - ], - }, -} diff --git a/contrib/ora_btree_gin/meson.build b/contrib/ora_btree_gin/meson.build index 7f843018c07..6b48de74ea0 100644 --- a/contrib/ora_btree_gin/meson.build +++ b/contrib/ora_btree_gin/meson.build @@ -22,22 +22,3 @@ install_data( 'ora_btree_gin--1.0.sql', kwargs: contrib_data_args, ) - -tests += { - 'name': 'ora_btree_gin', - 'sd': meson.current_source_dir(), - 'bd': meson.current_build_dir(), - 'regress': { - 'sql': [ - 'init', - 'number', - 'varchar2', - 'binary_float', - 'binary_double', - 'date', - 'timestamp', - 'timestamptz', - 'timestampltz', - ], - }, -} diff --git a/contrib/ora_btree_gist/meson.build b/contrib/ora_btree_gist/meson.build index 2976ceff019..b38c4ad1d61 100644 --- a/contrib/ora_btree_gist/meson.build +++ b/contrib/ora_btree_gist/meson.build @@ -33,24 +33,3 @@ install_data( 'ora_btree_gist--1.0.sql', kwargs: contrib_data_args, ) - -tests += { - 'name': 'ora_btree_gist', - 'sd': meson.current_source_dir(), - 'bd': meson.current_build_dir(), - 'regress': { - 'sql': [ - 'init', - 'number', - 'varchar2', - 'binary_float', - 'binary_double', - 'date', - 'timestamp', - 'timestamptz', - 'timestampltz', - 'yminterval', - 'dsinterval', - ], - }, -} diff --git a/meson.build b/meson.build index 31356a90400..4b15c0e8b92 100644 --- a/meson.build +++ b/meson.build @@ -3595,6 +3595,7 @@ sys.exit(sp.returncode) ''', test_initdb_template, temp_install_bindir / 'initdb', + '-m', 'pg', '--auth', 'trust', '--no-sync', '--no-instructions', '--lc-messages=C', '--no-clean' ], diff --git a/src/backend/utils/mb/conversion_procs/meson.build b/src/backend/utils/mb/conversion_procs/meson.build index 0e8273e0b61..436e2dd34ec 100644 --- a/src/backend/utils/mb/conversion_procs/meson.build +++ b/src/backend/utils/mb/conversion_procs/meson.build @@ -10,6 +10,7 @@ encodings = { 'euc_tw_and_big5/euc_tw_and_big5.c', 'euc_tw_and_big5/big5.c', ], + 'gb18030_and_gbk': ['gb18030_and_gbk/gb18030_and_gbk.c'], 'latin2_and_win1250': ['latin2_and_win1250/latin2_and_win1250.c'], 'latin_and_mic': ['latin_and_mic/latin_and_mic.c'], 'utf8_and_big5': ['utf8_and_big5/utf8_and_big5.c'], diff --git a/src/pl/plisql/src/meson.build b/src/pl/plisql/src/meson.build index f4b610d780f..3ca054ee3e7 100644 --- a/src/pl/plisql/src/meson.build +++ b/src/pl/plisql/src/meson.build @@ -73,27 +73,28 @@ install_headers( install_dir: dir_include_server ) - -tests += { - 'name': 'plisql', - 'sd': meson.current_source_dir(), - 'bd': meson.current_build_dir(), - 'regress': { - 'sql': [ - 'plisql_array', - 'plisql_call', - 'plisql_control', - 'plisql_copy', - 'plisql_domain', - 'plisql_record', - 'plisql_cache', - 'plisql_simple', - 'plisql_transaction', - 'plisql_trap', - 'plisql_trigger', - 'plisql_varprops', - ], - }, -} +# IvorySQL: plisql is Oracle-compatible procedural language, not needed in meson test +# Use 'make oracle-check' to run plisql tests +# tests += { +# 'name': 'plisql', +# 'sd': meson.current_source_dir(), +# 'bd': meson.current_build_dir(), +# 'regress': { +# 'sql': [ +# 'plisql_array', +# 'plisql_call', +# 'plisql_control', +# 'plisql_copy', +# 'plisql_domain', +# 'plisql_record', +# 'plisql_cache', +# 'plisql_simple', +# 'plisql_transaction', +# 'plisql_trap', +# 'plisql_trigger', +# 'plisql_varprops', +# ], +# }, +# } subdir('po', if_found: libintl) From e708b23447a97231e7486677af6b9da65aee8988 Mon Sep 17 00:00:00 2001 From: Oreo Yang <2167young@163.com> Date: Wed, 28 Jan 2026 17:46:35 +0800 Subject: [PATCH 05/21] add meson test for pg --- .../workflows/{meson_build.yml => meson_build_pg_test.yml} | 7 +++++++ 1 file changed, 7 insertions(+) rename .github/workflows/{meson_build.yml => meson_build_pg_test.yml} (90%) diff --git a/.github/workflows/meson_build.yml b/.github/workflows/meson_build_pg_test.yml similarity index 90% rename from .github/workflows/meson_build.yml rename to .github/workflows/meson_build_pg_test.yml index fe13e1dbccb..dc9ab650a0e 100644 --- a/.github/workflows/meson_build.yml +++ b/.github/workflows/meson_build_pg_test.yml @@ -42,3 +42,10 @@ jobs: - name: compile run: | cd build && ninja -j1 + + - name: run postgres test + run: | + cd build + meson test || true + continue-on-error: true + timeout-minutes: 90 From 0d950ed5b12553bd0c995c749d15e647a8497b23 Mon Sep 17 00:00:00 2001 From: Oreo Yang <2167young@163.com> Date: Fri, 30 Jan 2026 13:44:28 +0800 Subject: [PATCH 06/21] add meson test for pg --- .github/workflows/meson_build_pg_test.yml | 56 +++++++++++++++++++++-- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/.github/workflows/meson_build_pg_test.yml b/.github/workflows/meson_build_pg_test.yml index dc9ab650a0e..136a0601053 100644 --- a/.github/workflows/meson_build_pg_test.yml +++ b/.github/workflows/meson_build_pg_test.yml @@ -41,11 +41,59 @@ jobs: - name: compile run: | - cd build && ninja -j1 + cd build && ninja - name: run postgres test + id: test_postgres run: | cd build - meson test || true - continue-on-error: true - timeout-minutes: 90 + meson test -j1 --verbose --no-rebuild + timeout-minutes: 30 + + - name: collect test logs + if: always() + run: | + mkdir -p ${{ github.workspace }}/test-logs + + # Collect Meson test logs + if [ -d build/meson-logs ] && [ "$(ls -A build/meson-logs 2>/dev/null)" ]; then + cp build/meson-logs/* ${{ github.workspace }}/test-logs/ 2>/dev/null || true + echo "Copied meson log" + else + echo "No meson log found" + fi + + # test results + if [ -d build/testrun ]; then + find build/testrun -type f \( -name "*.log" -o -name "*.diff" -o -name "regression.diffs" \) -exec cp {} ${{ github.workspace }}/test-logs/ \; 2>/dev/null || true + echo "Collected test run logs" + fi + + # create summary + { + echo "IvorySQL Meson Test Summary" + echo "==========================" + echo "Workflow: ${{ github.workflow }}" + echo "Run ID: ${{ github.run_id }}" + echo "Run Number: ${{ github.run_number }}" + echo "Commit: ${{ github.sha }}" + echo "Branch: ${{ github.ref }}" + echo "Event: ${{ github.event_name }}" + echo "Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC')" + } > ${{ github.workspace }}/test-logs/SUMMARY.txt + + # Compress logs + cd ${{ github.workspace }} + tar -czf test-logs.tar.gz test-logs/ + echo "Compressed test logs: $(du -h test-logs.tar.gz | cut -f1)" + + - name: upload failure logs (raw directories for deep debugging) + if: failure() + uses: actions/upload-artifact@v4 + with: + name: postgres-test-failures-${{ github.sha }}.raw + path: | + build/meson-logs/ + build/testrun/ + retention-days: 30 + compression-level: 6 From 09d80be2dc44f2a165bea5f02f766872bc98231f Mon Sep 17 00:00:00 2001 From: Oreo Yang <2167young@163.com> Date: Fri, 30 Jan 2026 14:08:35 +0800 Subject: [PATCH 07/21] fix meson: error: unrecognized arguments: -j1 --- .github/workflows/meson_build_pg_test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/meson_build_pg_test.yml b/.github/workflows/meson_build_pg_test.yml index 136a0601053..57cac08dd51 100644 --- a/.github/workflows/meson_build_pg_test.yml +++ b/.github/workflows/meson_build_pg_test.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v3 - - name: dependancy - linux + - name: dependency - linux run: | sudo apt-get update sudo apt-get install -y build-essential git lcov bison flex \ @@ -47,7 +47,7 @@ jobs: id: test_postgres run: | cd build - meson test -j1 --verbose --no-rebuild + meson test --verbose --no-rebuild timeout-minutes: 30 - name: collect test logs From 7a827cceb2e8890521fd5bbf6f66e727b0b7bbb6 Mon Sep 17 00:00:00 2001 From: Oreo Yang <2167young@163.com> Date: Fri, 30 Jan 2026 17:38:54 +0800 Subject: [PATCH 08/21] fix: ensure meson build generates non-empty ivorysql_ora--1.0.sql In meson mode, the script was opening the output file with truncate mode (>), which created an empty file before meson could capture the STDOUT output. This resulted in an empty extension file. Now in meson mode: - Do not open the output file (avoiding the truncate) - Output all content to STDOUT, which meson captures via --capture Make mode remains unchanged - it opens and writes to the file directly. This aligns with the pattern used by other scripts like generate-plerrcodes.pl and gb18030_2022's generation. --- contrib/ivorysql_ora/gensql.pl | 55 ++++++++++++---------------------- 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/contrib/ivorysql_ora/gensql.pl b/contrib/ivorysql_ora/gensql.pl index c987e31bb48..6bd61cd3fa1 100755 --- a/contrib/ivorysql_ora/gensql.pl +++ b/contrib/ivorysql_ora/gensql.pl @@ -80,46 +80,31 @@ sub sql_merge shift @ARGV; foreach my $v (@ARGV) { - # Delete ivorysql_ora--x.x(--x.x).sql files generated before. - unlink(File::Spec->rel2abs("ivorysql_ora--$v.sql")) - if (-e File::Spec->rel2abs("ivorysql_ora--$v.sql")); + # For Make mode, delete the old file first. + if ($first_arg ne 'meson') { + unlink(File::Spec->rel2abs("ivorysql_ora--$v.sql")) + if (-e File::Spec->rel2abs("ivorysql_ora--$v.sql")); - # Open(create if necessary) ivorysql_ora--x.x(--x.x).sql. - if ($first_arg eq 'meson'){ - open(OUTFILE, ">contrib/ivorysql_ora/ivorysql_ora--$v.sql") - || croak "Could not open ivorysql_ora--$v.sql : $!"; - } - else { + # Open output file for Make mode (meson mode uses STDOUT captured by meson) open(OUTFILE, ">ivorysql_ora--$v.sql") - || croak "Could not open ivorysql_ora--$v.sql : $!"; + || croak "Could not open ivorysql_ora--$v.sql : $!"; } - # Write "extension file loading information" into it. + # Write "extension file loading information". # Create extension when this version is "x.x". if ($v =~ /^\d+\.\d+$/) { - if ($first_arg eq 'meson'){ - print STDOUT '\echo Use "CREATE EXTENSION ivorysql_ora"'; - print STDOUT " to load this file. \\quit\n"; - } - else - { - print OUTFILE '\echo Use "CREATE EXTENSION ivorysql_ora"'; - print OUTFILE " to load this file. \\quit\n"; - } + my $fh = ($first_arg eq 'meson') ? *STDOUT : *OUTFILE; + print $fh '\echo Use "CREATE EXTENSION ivorysql_ora"'; + print $fh " to load this file. \\quit\n"; } # Update extension when this version is "x.x--x.x". elsif ($v =~ /^\d+\.\d+\-\-\d+\.\d+$/) { my $up2ver = (split("--", $v))[1]; - if ($first_arg eq 'meson'){ - print STDOUT '\echo Use "ALTER EXTENSION ivorysql_ora UPDATE'; - print STDOUT " TO \'$up2ver\'\" to load this file. \\quit\n"; - } - else{ - print OUTFILE '\echo Use "ALTER EXTENSION ivorysql_ora UPDATE'; - print OUTFILE " TO \'$up2ver\'\" to load this file. \\quit\n"; - } + my $fh = ($first_arg eq 'meson') ? *STDOUT : *OUTFILE; + print $fh '\echo Use "ALTER EXTENSION ivorysql_ora UPDATE'; + print $fh " TO \'$up2ver\'\" to load this file. \\quit\n"; } else { @@ -135,7 +120,9 @@ sub sql_merge if (-e "$set--$v.sql") { # Add a newline. - print OUTFILE "\n"; + my $fh = ($first_arg eq 'meson') ? *STDOUT : *OUTFILE; + print $fh "\n"; + # Open a sql file. open(INFILE, "<", File::Spec->rel2abs("$set--$v.sql")); while (my $line = ) @@ -143,17 +130,13 @@ sub sql_merge # Delete the last tailing "\n" of this line. chomp($line); # Write. - if ($first_arg eq 'meson'){ - print STDOUT "$line\n"; - } - else{ - print OUTFILE "$line\n"; - } + print $fh "$line\n"; } close INFILE; } } - close OUTFILE; + # Close OUTFILE for Make mode (meson mode doesn't open it) + close OUTFILE if ($first_arg ne 'meson'); } } From 5ba02de4fe274a5b232467cf8771112b75358bb6 Mon Sep 17 00:00:00 2001 From: yuan li Date: Tue, 3 Feb 2026 17:42:47 +0800 Subject: [PATCH 09/21] Fix raw_expression_tree_walker for ColumnRefOrFuncCall (issue #1182) --- src/backend/nodes/nodeFuncs.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index f4791df7531..bacebbb2813 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -4483,17 +4483,12 @@ raw_expression_tree_walker_impl(Node *node, break; case T_ColumnRefOrFuncCall: { - FuncCall *fcall = ((ColumnRefOrFuncCall *) node)->func; + ColumnRefOrFuncCall *colf = (ColumnRefOrFuncCall *) node; - if (WALK(fcall->args)) - return true; - if (WALK(fcall->agg_order)) + if (colf->cref && WALK(colf->cref)) return true; - if (WALK(fcall->agg_filter)) + if (colf->func && WALK(colf->func)) return true; - if (WALK(fcall->over)) - return true; - /* function name is deemed uninteresting */ } break; case T_NamedArgExpr: From f62f99843ebc1ad574774a9c2da5d7b7357a7e59 Mon Sep 17 00:00:00 2001 From: Pierre Forstmann Date: Sat, 7 Feb 2026 14:27:54 +0100 Subject: [PATCH 10/21] fix typo in ivorysql_ora comment --- contrib/ivorysql_ora/ivorysql_ora.control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/ivorysql_ora/ivorysql_ora.control b/contrib/ivorysql_ora/ivorysql_ora.control index 1bba3da4882..3c74258e5fa 100644 --- a/contrib/ivorysql_ora/ivorysql_ora.control +++ b/contrib/ivorysql_ora/ivorysql_ora.control @@ -1,5 +1,5 @@ # ivorysql_ora extension -comment = 'Oracle Compatible extenison on Postgres Database' +comment = 'Oracle Compatible extension on Postgres Database' default_version = '1.0' module_pathname = '$libdir/ivorysql_ora' superuser = true From a72b7c39117ef990fa0ceea1fdb035de32b765a5 Mon Sep 17 00:00:00 2001 From: Rophy Tsai Date: Sun, 8 Feb 2026 02:17:26 +0000 Subject: [PATCH 11/21] chore: add gdb debugging support to dev container - Add gdb package to Dockerfile - Enable SYS_PTRACE and seccomp:unconfined in docker-compose - Fix .gitignore for tmp_install --- .devcontainer/Dockerfile | 2 ++ .gitignore | 2 +- docker-compose.yaml | 7 +++++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index f5ef8cfdee1..fff0b3c47e3 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -34,6 +34,8 @@ RUN apt-get update && apt-get install -y \ locales \ # For dev containers sudo tini \ + # Debugging tools + gdb \ && rm -rf /var/lib/apt/lists/* # Install meson and ninja from source (matching workflow versions) diff --git a/.gitignore b/.gitignore index 794e35b73cb..bac11f33086 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,4 @@ lib*.pc /pgsql.sln.cache /Debug/ /Release/ -/tmp_install/ +/tmp_install diff --git a/docker-compose.yaml b/docker-compose.yaml index 35d265de3e3..1b0414aca7c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -3,12 +3,15 @@ services: build: context: . dockerfile: .devcontainer/Dockerfile - image: ivorysql-dev - container_name: ivorysql-dev volumes: - .:/home/ivorysql/IvorySQL:rw working_dir: /home/ivorysql/IvorySQL command: ["sleep", "infinity"] + # Enable ptrace for gdb debugging + cap_add: + - SYS_PTRACE + security_opt: + - seccomp:unconfined # docker compose --profile ora up -d oracle: From 39ffc1166bc9d03090e61ab812b57ea31b61e1b3 Mon Sep 17 00:00:00 2001 From: yuan li Date: Mon, 9 Feb 2026 14:39:40 +0800 Subject: [PATCH 12/21] fix: allow COMMIT in nested procedure calls for Oracle compatibility fixes plancache resource leak from issue #1007 by setting requires_procedure_resowner for Oracle-style calls in pl_gram.y codes by Rophy Tsai --- .../regress/expected/ora_package.out | 38 +++++ src/oracle_test/regress/sql/ora_package.sql | 36 ++++ .../src/expected/plisql_transaction.out | 160 +++++++++++++++++- src/pl/plisql/src/pl_gram.y | 6 + src/pl/plisql/src/sql/plisql_transaction.sql | 137 +++++++++++++++ 5 files changed, 375 insertions(+), 2 deletions(-) diff --git a/src/oracle_test/regress/expected/ora_package.out b/src/oracle_test/regress/expected/ora_package.out index 8c5f9bdfbc0..a9d5f33362a 100644 --- a/src/oracle_test/regress/expected/ora_package.out +++ b/src/oracle_test/regress/expected/ora_package.out @@ -6278,6 +6278,44 @@ call test_pkg.test_p1(NULL, 23); (1 row) DROP package test_pkg; +-- Test COMMIT in nested package procedure calls (Issue #1007) +CREATE TABLE test_nested_commit (id int); +CREATE OR REPLACE PACKAGE pkg_commit_test IS + PROCEDURE do_commit; + PROCEDURE main; +END; +/ +CREATE OR REPLACE PACKAGE BODY pkg_commit_test IS + PROCEDURE do_commit IS + BEGIN + INSERT INTO test_nested_commit VALUES (1); + COMMIT; + INSERT INTO test_nested_commit VALUES (2); + END; + PROCEDURE main IS + BEGIN + INSERT INTO test_nested_commit VALUES (0); + do_commit(); + INSERT INTO test_nested_commit VALUES (3); + END; +END; +/ +TRUNCATE test_nested_commit; +BEGIN + pkg_commit_test.main(); +END; +/ +SELECT * FROM test_nested_commit ORDER BY id; + id +---- + 0 + 1 + 2 + 3 +(4 rows) + +DROP PACKAGE pkg_commit_test; +DROP TABLE test_nested_commit; --clean data RESET ivorysql.allow_out_parameter_const; DROP FUNCTION test_event_trigger; diff --git a/src/oracle_test/regress/sql/ora_package.sql b/src/oracle_test/regress/sql/ora_package.sql index 6bb5a9b403f..2e947f2d0e3 100644 --- a/src/oracle_test/regress/sql/ora_package.sql +++ b/src/oracle_test/regress/sql/ora_package.sql @@ -6094,6 +6094,42 @@ call test_pkg.test_p1(NULL, 23); DROP package test_pkg; +-- Test COMMIT in nested package procedure calls (Issue #1007) +CREATE TABLE test_nested_commit (id int); + +CREATE OR REPLACE PACKAGE pkg_commit_test IS + PROCEDURE do_commit; + PROCEDURE main; +END; +/ + +CREATE OR REPLACE PACKAGE BODY pkg_commit_test IS + PROCEDURE do_commit IS + BEGIN + INSERT INTO test_nested_commit VALUES (1); + COMMIT; + INSERT INTO test_nested_commit VALUES (2); + END; + + PROCEDURE main IS + BEGIN + INSERT INTO test_nested_commit VALUES (0); + do_commit(); + INSERT INTO test_nested_commit VALUES (3); + END; +END; +/ + +TRUNCATE test_nested_commit; +BEGIN + pkg_commit_test.main(); +END; +/ +SELECT * FROM test_nested_commit ORDER BY id; + +DROP PACKAGE pkg_commit_test; +DROP TABLE test_nested_commit; + --clean data RESET ivorysql.allow_out_parameter_const; DROP FUNCTION test_event_trigger; diff --git a/src/pl/plisql/src/expected/plisql_transaction.out b/src/pl/plisql/src/expected/plisql_transaction.out index cbac81d5d3c..2ebe4fd2d17 100755 --- a/src/pl/plisql/src/expected/plisql_transaction.out +++ b/src/pl/plisql/src/expected/plisql_transaction.out @@ -472,6 +472,7 @@ INSERT INTO test4 SELECT repeat('xyzzy', 2000); -- that will return a still-toasted value CREATE FUNCTION data_source(i int) RETURNS TEXT LANGUAGE sql AS 'select f1 from test4' IMMUTABLE; +/ DO $$ declare x text; begin @@ -481,9 +482,8 @@ begin end loop; raise notice 'length(x) = %', length(x); end $$; +NOTICE: length(x) = 10000 / -ERROR: invalid transaction termination -CONTEXT: PL/iSQL function inline_code_block line 6 at COMMIT -- operations on composite types vs. internal transactions DO LANGUAGE plisql $$ declare @@ -748,6 +748,162 @@ SELECT * FROM test1; 2 | (2 rows) +-- Test nested procedure calls with COMMIT/ROLLBACK (Issue #1007) +-- +-- Note: Oracle-syntax procedures (CREATE PROCEDURE ... IS) default to +-- AUTHID DEFINER (prosecdef=true), which forces atomic mode and blocks +-- COMMIT/ROLLBACK. Use AUTHID CURRENT_USER to allow transaction control. +-- This matches Oracle behavior where COMMIT is allowed regardless of AUTHID. +-- Tests below verify COMMIT/ROLLBACK in nested procedure calls +-- using AUTHID CURRENT_USER (Oracle-compatible syntax). +-- Without AUTHID CURRENT_USER, Oracle-syntax procedures default to +-- SECURITY DEFINER (prosecdef=true), which forces atomic mode and +-- blocks COMMIT/ROLLBACK. This is a known limitation (see Test 0). +CREATE TABLE test_nested_commit (id int); +-- Inner procedure with COMMIT +CREATE OR REPLACE PROCEDURE nested_inner_commit AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (1); + COMMIT; + INSERT INTO test_nested_commit VALUES (2); +END; +/ +-- Outer procedure calling inner with CALL keyword +CREATE OR REPLACE PROCEDURE nested_outer_commit AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (0); + CALL nested_inner_commit(); + INSERT INTO test_nested_commit VALUES (3); +END; +/ +-- Test 1: Basic nested call with COMMIT +TRUNCATE test_nested_commit; +CALL nested_outer_commit(); +SELECT * FROM test_nested_commit ORDER BY id; + id +---- + 0 + 1 + 2 + 3 +(4 rows) + +-- Test 2: Oracle-style call (without CALL keyword) with COMMIT +CREATE OR REPLACE PROCEDURE nested_outer_oracle_style AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (10); + nested_inner_commit(); -- Oracle-style call + INSERT INTO test_nested_commit VALUES (13); +END; +/ +TRUNCATE test_nested_commit; +CALL nested_outer_oracle_style(); +SELECT * FROM test_nested_commit ORDER BY id; + id +---- + 1 + 2 + 10 + 13 +(4 rows) + +-- Test 3: Deeply nested Oracle-style calls (4 levels) with COMMIT +CREATE OR REPLACE PROCEDURE nested_level4 AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (104); + COMMIT; + INSERT INTO test_nested_commit VALUES (105); +END; +/ +CREATE OR REPLACE PROCEDURE nested_level3 AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (103); + nested_level4(); -- Oracle-style call + INSERT INTO test_nested_commit VALUES (106); +END; +/ +CREATE OR REPLACE PROCEDURE nested_level2 AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (102); + nested_level3(); -- Oracle-style call + INSERT INTO test_nested_commit VALUES (107); +END; +/ +CREATE OR REPLACE PROCEDURE nested_level1 AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (101); + nested_level2(); -- Oracle-style call + INSERT INTO test_nested_commit VALUES (108); +END; +/ +TRUNCATE test_nested_commit; +CALL nested_level1(); +SELECT * FROM test_nested_commit ORDER BY id; + id +----- + 101 + 102 + 103 + 104 + 105 + 106 + 107 + 108 +(8 rows) + +-- Test 4: ROLLBACK in nested procedure with CALL keyword +CREATE OR REPLACE PROCEDURE nested_inner_rollback AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (201); + ROLLBACK; + INSERT INTO test_nested_commit VALUES (202); +END; +/ +CREATE OR REPLACE PROCEDURE nested_outer_rollback AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (200); + CALL nested_inner_rollback(); + INSERT INTO test_nested_commit VALUES (203); +END; +/ +TRUNCATE test_nested_commit; +CALL nested_outer_rollback(); +SELECT * FROM test_nested_commit ORDER BY id; + id +----- + 202 + 203 +(2 rows) + +-- Test 5: Oracle-style call (without CALL keyword) with ROLLBACK +CREATE OR REPLACE PROCEDURE nested_outer_rollback_oracle_style AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (300); + nested_inner_rollback(); -- Oracle-style call + INSERT INTO test_nested_commit VALUES (303); +END; +/ +TRUNCATE test_nested_commit; +CALL nested_outer_rollback_oracle_style(); +SELECT * FROM test_nested_commit ORDER BY id; + id +----- + 202 + 303 +(2 rows) + +-- Clean up nested commit tests +DROP PROCEDURE nested_inner_commit; +DROP PROCEDURE nested_outer_commit; +DROP PROCEDURE nested_outer_oracle_style; +DROP PROCEDURE nested_level1; +DROP PROCEDURE nested_level2; +DROP PROCEDURE nested_level3; +DROP PROCEDURE nested_level4; +DROP PROCEDURE nested_inner_rollback; +DROP PROCEDURE nested_outer_rollback; +DROP PROCEDURE nested_outer_rollback_oracle_style; +DROP TABLE test_nested_commit; DROP TABLE test1; DROP TABLE test2; DROP TABLE test3; diff --git a/src/pl/plisql/src/pl_gram.y b/src/pl/plisql/src/pl_gram.y index 447b63615d7..73735251744 100644 --- a/src/pl/plisql/src/pl_gram.y +++ b/src/pl/plisql/src/pl_gram.y @@ -2737,6 +2737,9 @@ stmt_execsql : K_IMPORT new->expr = build_call_expr(T_WORD, @1, &yylval, &yylloc, yyscanner); new->is_call = true; + /* Remember we may need a procedure resource owner */ + plisql_curr_compile->requires_procedure_resowner = true; + $$ = (PLiSQL_stmt *)new; } else @@ -2764,6 +2767,9 @@ stmt_execsql : K_IMPORT new->expr = build_call_expr(T_CWORD, @1, &yylval, &yylloc, yyscanner); new->is_call = true; + /* Remember we may need a procedure resource owner */ + plisql_curr_compile->requires_procedure_resowner = true; + $$ = (PLiSQL_stmt *)new; } else diff --git a/src/pl/plisql/src/sql/plisql_transaction.sql b/src/pl/plisql/src/sql/plisql_transaction.sql index 56985ac2e91..7f4b7d2b37a 100755 --- a/src/pl/plisql/src/sql/plisql_transaction.sql +++ b/src/pl/plisql/src/sql/plisql_transaction.sql @@ -393,6 +393,7 @@ INSERT INTO test4 SELECT repeat('xyzzy', 2000); -- that will return a still-toasted value CREATE FUNCTION data_source(i int) RETURNS TEXT LANGUAGE sql AS 'select f1 from test4' IMMUTABLE; +/ DO $$ declare x text; @@ -649,6 +650,142 @@ $$; SELECT * FROM test1; +-- Test nested procedure calls with COMMIT/ROLLBACK (Issue #1007) +-- +-- Note: Oracle-syntax procedures (CREATE PROCEDURE ... IS) default to +-- AUTHID DEFINER (prosecdef=true), which forces atomic mode and blocks +-- COMMIT/ROLLBACK. Use AUTHID CURRENT_USER to allow transaction control. +-- This matches Oracle behavior where COMMIT is allowed regardless of AUTHID. + +-- Tests below verify COMMIT/ROLLBACK in nested procedure calls +-- using AUTHID CURRENT_USER (Oracle-compatible syntax). +-- Without AUTHID CURRENT_USER, Oracle-syntax procedures default to +-- SECURITY DEFINER (prosecdef=true), which forces atomic mode and +-- blocks COMMIT/ROLLBACK. This is a known limitation (see Test 0). + +CREATE TABLE test_nested_commit (id int); + +-- Inner procedure with COMMIT +CREATE OR REPLACE PROCEDURE nested_inner_commit AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (1); + COMMIT; + INSERT INTO test_nested_commit VALUES (2); +END; +/ + +-- Outer procedure calling inner with CALL keyword +CREATE OR REPLACE PROCEDURE nested_outer_commit AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (0); + CALL nested_inner_commit(); + INSERT INTO test_nested_commit VALUES (3); +END; +/ + +-- Test 1: Basic nested call with COMMIT +TRUNCATE test_nested_commit; +CALL nested_outer_commit(); +SELECT * FROM test_nested_commit ORDER BY id; + +-- Test 2: Oracle-style call (without CALL keyword) with COMMIT +CREATE OR REPLACE PROCEDURE nested_outer_oracle_style AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (10); + nested_inner_commit(); -- Oracle-style call + INSERT INTO test_nested_commit VALUES (13); +END; +/ + +TRUNCATE test_nested_commit; +CALL nested_outer_oracle_style(); +SELECT * FROM test_nested_commit ORDER BY id; + +-- Test 3: Deeply nested Oracle-style calls (4 levels) with COMMIT +CREATE OR REPLACE PROCEDURE nested_level4 AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (104); + COMMIT; + INSERT INTO test_nested_commit VALUES (105); +END; +/ + +CREATE OR REPLACE PROCEDURE nested_level3 AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (103); + nested_level4(); -- Oracle-style call + INSERT INTO test_nested_commit VALUES (106); +END; +/ + +CREATE OR REPLACE PROCEDURE nested_level2 AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (102); + nested_level3(); -- Oracle-style call + INSERT INTO test_nested_commit VALUES (107); +END; +/ + +CREATE OR REPLACE PROCEDURE nested_level1 AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (101); + nested_level2(); -- Oracle-style call + INSERT INTO test_nested_commit VALUES (108); +END; +/ + +TRUNCATE test_nested_commit; +CALL nested_level1(); +SELECT * FROM test_nested_commit ORDER BY id; + +-- Test 4: ROLLBACK in nested procedure with CALL keyword +CREATE OR REPLACE PROCEDURE nested_inner_rollback AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (201); + ROLLBACK; + INSERT INTO test_nested_commit VALUES (202); +END; +/ + +CREATE OR REPLACE PROCEDURE nested_outer_rollback AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (200); + CALL nested_inner_rollback(); + INSERT INTO test_nested_commit VALUES (203); +END; +/ + +TRUNCATE test_nested_commit; +CALL nested_outer_rollback(); +SELECT * FROM test_nested_commit ORDER BY id; + +-- Test 5: Oracle-style call (without CALL keyword) with ROLLBACK +CREATE OR REPLACE PROCEDURE nested_outer_rollback_oracle_style AUTHID CURRENT_USER IS +BEGIN + INSERT INTO test_nested_commit VALUES (300); + nested_inner_rollback(); -- Oracle-style call + INSERT INTO test_nested_commit VALUES (303); +END; +/ + +TRUNCATE test_nested_commit; +CALL nested_outer_rollback_oracle_style(); +SELECT * FROM test_nested_commit ORDER BY id; + +-- Clean up nested commit tests +DROP PROCEDURE nested_inner_commit; +DROP PROCEDURE nested_outer_commit; +DROP PROCEDURE nested_outer_oracle_style; +DROP PROCEDURE nested_level1; +DROP PROCEDURE nested_level2; +DROP PROCEDURE nested_level3; +DROP PROCEDURE nested_level4; +DROP PROCEDURE nested_inner_rollback; +DROP PROCEDURE nested_outer_rollback; +DROP PROCEDURE nested_outer_rollback_oracle_style; +DROP TABLE test_nested_commit; + + DROP TABLE test1; DROP TABLE test2; DROP TABLE test3; From 209f5e0040b5186fb7db18fdb5973825b732e65b Mon Sep 17 00:00:00 2001 From: yasirmashwani Date: Tue, 10 Feb 2026 17:01:19 +0500 Subject: [PATCH 13/21] =?UTF-8?q?fix=20warnings:=20variable=20=E2=80=98mat?= =?UTF-8?q?ch=E2=80=99=20set=20but=20not=20used?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pl/plisql/src/pl_subproc_function.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/pl/plisql/src/pl_subproc_function.c b/src/pl/plisql/src/pl_subproc_function.c index 2c74509e699..853a78d91c3 100644 --- a/src/pl/plisql/src/pl_subproc_function.c +++ b/src/pl/plisql/src/pl_subproc_function.c @@ -3024,7 +3024,6 @@ plisql_dynamic_compile_subproc(FunctionCallInfo fcinfo, static void plsql_init_glovalvar_from_stack(PLiSQL_execstate * estate, int dno, int *start_level) { - bool match = false; int connected; PLiSQL_execstate *parestate; PLiSQL_function *func; @@ -3042,11 +3041,11 @@ plsql_init_glovalvar_from_stack(PLiSQL_execstate * estate, int dno, int *start_l if (dno >= parestate->ndatums) continue; plisql_assign_in_global_var(estate, parestate, dno); - match = true; *start_level = connected; - break; + + return; } - Assert(match); + Assert(false); return; } @@ -3056,7 +3055,6 @@ plsql_init_glovalvar_from_stack(PLiSQL_execstate * estate, int dno, int *start_l static void plsql_assign_out_glovalvar_from_stack(PLiSQL_execstate * estate, int dno, int *start_level) { - bool match = false; int connected; PLiSQL_execstate *parestate; PLiSQL_function *func; @@ -3075,10 +3073,10 @@ plsql_assign_out_glovalvar_from_stack(PLiSQL_execstate * estate, int dno, int *s continue; plisql_assign_out_global_var(estate, parestate, dno, connected); *start_level = connected; - match = true; - break; + + return; } - Assert(match); + Assert(false); return; } From 6c21cfad7a207b416088cb98b34ec86e4484d9ea Mon Sep 17 00:00:00 2001 From: yasirmashwani Date: Tue, 10 Feb 2026 17:35:59 +0500 Subject: [PATCH 14/21] fix warning: unused variable pre_len --- src/pl/plisql/src/pl_package.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pl/plisql/src/pl_package.c b/src/pl/plisql/src/pl_package.c index caabd21bcbc..852d80844f9 100644 --- a/src/pl/plisql/src/pl_package.c +++ b/src/pl/plisql/src/pl_package.c @@ -2730,12 +2730,10 @@ static void plisql_remove_function_references(PLiSQL_function *func, PackageCacheItem *item) { PLiSQL_package *psource = (PLiSQL_package *) item->source; - int pre_len = list_length(psource->source.funclist); - psource->source.funclist = list_delete_ptr(psource->source.funclist, (void *) func); - - Assert(pre_len == list_length(psource->source.funclist) + 1); + Assert(list_member_ptr(psource->source.funclist, func)); + psource->source.funclist = list_delete_ptr(psource->source.funclist, (void *) func); psource->source.use_count--; /* From f549c096b412632f59abf71b00f8c4392e5723b4 Mon Sep 17 00:00:00 2001 From: yasirmashwani Date: Tue, 10 Feb 2026 17:44:17 +0500 Subject: [PATCH 15/21] =?UTF-8?q?fix=20warning:=20variable=20=E2=80=98foun?= =?UTF-8?q?d=E2=80=99=20set=20but=20not=20used?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pl/plisql/src/pl_package.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pl/plisql/src/pl_package.c b/src/pl/plisql/src/pl_package.c index 852d80844f9..af726ee2ba5 100644 --- a/src/pl/plisql/src/pl_package.c +++ b/src/pl/plisql/src/pl_package.c @@ -3636,7 +3636,6 @@ plisql_subproc_should_change_return_type(FuncExpr *fexpr, { /* only one out-parameter, change the rettype to be out-parameter type */ ListCell *lc; - bool found = false; foreach (lc, subprocfunc->arg) { @@ -3645,7 +3644,6 @@ plisql_subproc_should_change_return_type(FuncExpr *fexpr, if (argitem->argmode == ARGMODE_OUT || argitem->argmode == ARGMODE_INOUT) { - found = true; result = true; *rettype = argitem->type->typoid; *typmod = argitem->type->atttypmod; @@ -3653,7 +3651,7 @@ plisql_subproc_should_change_return_type(FuncExpr *fexpr, break; } } - Assert(found); + Assert(result); } return result; } From 8299ba0ae4fdc28c7793dedeaaaa14a0d3e9214c Mon Sep 17 00:00:00 2001 From: yasirmashwani Date: Tue, 10 Feb 2026 18:52:08 +0500 Subject: [PATCH 16/21] =?UTF-8?q?fix=20warning:=20=E2=80=98before.ticks?= =?UTF-8?q?=E2=80=99=20may=20be=20used=20uninitialized?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bin/psql/common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index 063e9537d05..4626acca072 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -2860,6 +2860,7 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec) int flush_error; *elapsed_msec = 0; + before.ticks = 0; /* initialize print options for partial table output */ my_popt.topt.start_table = true; From c397e8dd1e98e6c71ca7f72fb0ce54a5c180328c Mon Sep 17 00:00:00 2001 From: yasirmashwani Date: Tue, 10 Feb 2026 21:04:58 +0500 Subject: [PATCH 17/21] fix warning: ISO C90 forbids mixed declarations and code --- src/backend/executor/nodeResult.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c index 79933095a9e..7a6faaf7aec 100644 --- a/src/backend/executor/nodeResult.c +++ b/src/backend/executor/nodeResult.c @@ -104,6 +104,7 @@ ExecResult(PlanState *pstate) */ if (!node->rs_done) { + TupleTableSlot *result; outerPlan = outerPlanState(node); if (outerPlan != NULL) @@ -132,7 +133,7 @@ ExecResult(PlanState *pstate) } /* form the result tuple using ExecProject(), and return it */ - TupleTableSlot *result = ExecProject(node->ps.ps_ProjInfo); + result = ExecProject(node->ps.ps_ProjInfo); /* * If the projection contains ROWNUM expressions, materialize From a10bcb742f4bdbb5429792a9f15992a681be3903 Mon Sep 17 00:00:00 2001 From: yasirmashwani Date: Tue, 10 Feb 2026 21:34:42 +0500 Subject: [PATCH 18/21] fix warning: ISO C90 forbids mixed declarations and code --- .../src/builtin_packages/dbms_utility/dbms_utility.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contrib/ivorysql_ora/src/builtin_packages/dbms_utility/dbms_utility.c b/contrib/ivorysql_ora/src/builtin_packages/dbms_utility/dbms_utility.c index f572c697338..d61c03e8e42 100644 --- a/contrib/ivorysql_ora/src/builtin_packages/dbms_utility/dbms_utility.c +++ b/contrib/ivorysql_ora/src/builtin_packages/dbms_utility/dbms_utility.c @@ -66,6 +66,7 @@ static bool lookup_attempted = false; static void lookup_plisql_functions(void) { + void *fn; if (lookup_attempted) return; @@ -77,8 +78,6 @@ lookup_plisql_functions(void) * plisql.so should already be loaded when these functions are called * from within a PL/iSQL context. */ - void *fn; - fn = dlsym(RTLD_DEFAULT, "plisql_get_current_exception_context"); if (fn != NULL) get_exception_context_fn = (plisql_get_context_fn) fn; From 5eb0d90d3f43e83186767dad2f4ec510a4597dc6 Mon Sep 17 00:00:00 2001 From: yasirmashwani Date: Tue, 10 Feb 2026 22:53:39 +0500 Subject: [PATCH 19/21] use INSTR_TIME_SET_ZERO instead of direct updating .ticks --- src/bin/psql/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index 4626acca072..66a015a3ef0 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -2860,7 +2860,7 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec) int flush_error; *elapsed_msec = 0; - before.ticks = 0; + INSTR_TIME_SET_ZERO(before); /* initialize print options for partial table output */ my_popt.topt.start_table = true; From ca0cfe714c0ae7a23575a1b063ae35a819a8c84f Mon Sep 17 00:00:00 2001 From: yasirmashwani Date: Tue, 10 Feb 2026 22:58:09 +0500 Subject: [PATCH 20/21] fix potential unused-variable warning --- .../dbms_utility/dbms_utility.c | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/contrib/ivorysql_ora/src/builtin_packages/dbms_utility/dbms_utility.c b/contrib/ivorysql_ora/src/builtin_packages/dbms_utility/dbms_utility.c index d61c03e8e42..9a17de014d9 100644 --- a/contrib/ivorysql_ora/src/builtin_packages/dbms_utility/dbms_utility.c +++ b/contrib/ivorysql_ora/src/builtin_packages/dbms_utility/dbms_utility.c @@ -66,33 +66,34 @@ static bool lookup_attempted = false; static void lookup_plisql_functions(void) { - void *fn; if (lookup_attempted) return; lookup_attempted = true; #ifndef WIN32 - /* - * Use RTLD_DEFAULT to search all loaded shared objects. - * plisql.so should already be loaded when these functions are called - * from within a PL/iSQL context. - */ - fn = dlsym(RTLD_DEFAULT, "plisql_get_current_exception_context"); - if (fn != NULL) - get_exception_context_fn = (plisql_get_context_fn) fn; - - fn = dlsym(RTLD_DEFAULT, "plisql_get_current_exception_message"); - if (fn != NULL) - get_exception_message_fn = (plisql_get_message_fn) fn; - - fn = dlsym(RTLD_DEFAULT, "plisql_get_current_exception_sqlerrcode"); - if (fn != NULL) - get_exception_sqlerrcode_fn = (plisql_get_sqlerrcode_fn) fn; - - fn = dlsym(RTLD_DEFAULT, "plisql_get_call_stack"); - if (fn != NULL) - get_call_stack_fn = (plisql_get_call_stack_fn) fn; + { + /* + * Use RTLD_DEFAULT to search all loaded shared objects. + * plisql.so should already be loaded when these functions are called + * from within a PL/iSQL context. + */ + void *fn = dlsym(RTLD_DEFAULT, "plisql_get_current_exception_context"); + if (fn != NULL) + get_exception_context_fn = (plisql_get_context_fn) fn; + + fn = dlsym(RTLD_DEFAULT, "plisql_get_current_exception_message"); + if (fn != NULL) + get_exception_message_fn = (plisql_get_message_fn) fn; + + fn = dlsym(RTLD_DEFAULT, "plisql_get_current_exception_sqlerrcode"); + if (fn != NULL) + get_exception_sqlerrcode_fn = (plisql_get_sqlerrcode_fn) fn; + + fn = dlsym(RTLD_DEFAULT, "plisql_get_call_stack"); + if (fn != NULL) + get_call_stack_fn = (plisql_get_call_stack_fn) fn; + } #endif /* On Windows, function pointers remain NULL - features require plisql */ } From 63315114b7e7e5d4f73b2e1998ce859b9f1a641f Mon Sep 17 00:00:00 2001 From: yasirmashwani Date: Fri, 13 Feb 2026 15:05:01 +0500 Subject: [PATCH 21/21] =?UTF-8?q?fix=20warning:=20=E2=80=98=5F=5Fbuiltin?= =?UTF-8?q?=5Fstrncpy=E2=80=99=20specified=20bound=20depends=20on=20the=20?= =?UTF-8?q?length=20of=20the=20source=20argument?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/utils/adt/varlena.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 723a82b989f..6425e37f091 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -3994,7 +3994,8 @@ SplitGUCList(char *rawstring, char separator, char *new_name; new_name = identifier_case_transform(curname, strlen(curname)); - strncpy(curname, new_name, strlen(new_name)); + memcpy(curname, new_name, strlen(new_name)); + curname[strlen(new_name)] = '\0'; pfree(new_name); }