Skip to content

Bug fix pg dump cannot duplicate null pointer#870

Merged
gaoxueyu merged 8 commits intoIvorySQL:masterfrom
yasir-hussain-shah:bug-fix-pg_dump-cannot-duplicate-null-pointer
Sep 3, 2025
Merged

Bug fix pg dump cannot duplicate null pointer#870
gaoxueyu merged 8 commits intoIvorySQL:masterfrom
yasir-hussain-shah:bug-fix-pg_dump-cannot-duplicate-null-pointer

Conversation

@yasir-hussain-shah
Copy link
Copy Markdown
Contributor

@yasir-hussain-shah yasir-hussain-shah commented Sep 2, 2025

  • Fix the pg_dump bug throwing error "cannot duplicate null pointer" if DB to be dumped contain packages

  • Add TAP tests to pg_dump utility to cover the packages in dump

    • New test file added for oracle compatible packages pg_dump/t/oracle/001_pg_dump_ora_specific.pl
    • TAP tests can be executed as:
  • Add support for connection to ivorysql.port for oracle specific TAP tests execution

Fixes Bug#857

Summary by CodeRabbit

  • New Features

    • Added support for configuring and using a separate IvorySQL port for test clusters.
  • Bug Fixes

    • Corrected package owner extraction for dumps to use the proper owner field.
  • Tests

    • Added Oracle-specific pg_dump regression tests covering package dumping and cleanup/restore scenarios.
  • Chores

    • Expanded default Oracle test discovery to include all t/oracle/*.pl files when no explicit test list is provided.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 2, 2025

Walkthrough

Adds Oracle-specific test coverage for pg_dump packages, updates pg_dump to read package owner from pkgowner, extends test cluster to support an alternate IvorySQL port (oraport) with new accessor and connection flag, and broadens Makefile prove targets to include t/oracle/*.pl when PROVE_TESTS is unset.

Changes

Cohort / File(s) Summary
Build/Test Orchestration
src/Makefile.global.in
PROVE invocations now include t/oracle/*.pl by default for Oracle tests across oracle_prove_installcheck (PGXS/non-PGXS) and oracle_prove_check when PROVE_TESTS is not set.
pg_dump Package Owner Source
src/bin/pg_dump/pg_dump.c
In getPackages, package owner is read from the pkgowner column (via PQfnumber(..., "pkgowner")) instead of rolname; assignment uses that column.
Oracle pg_dump Tests
src/bin/pg_dump/t/oracle/001_pg_dump_ora_specific.pl
New Perl regression test that seeds package objects, runs two pg_dump scenarios (packages and clean_if_exists), optionally compresses/restores, and verifies dump output via regex with shared like/unlike test keys.
Test Cluster Oraport Support
src/oracle_test/perl/PostgreSQL/Test/Cluster.pm
Adds _oraport field and public oraport() accessor; connstr($dbname, $connect_to_oraport) and psql(..., connect_to_oraport) can target oraport. ivorysql.port in init and init_from_backup flows is set from oraport.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant T as Test Script (001_pg_dump_ora_specific.pl)
  participant C as Test Cluster
  participant P as pg_dump
  participant DB as Server

  rect rgba(200,220,255,0.3)
    note over C: Node creation/init
    T->>C: new()/init()
    C->>C: select and store oraport
    C->>C: configure postgresql.conf (ivorysql.port=oraport)
    T->>C: start()
    C->>DB: Launch cluster (listening on port & oraport)
  end

  rect rgba(220,255,220,0.3)
    note over T: Seed objects via oraport
    T->>C: psql(..., connect_to_oraport=true)
    C->>DB: Connect via oraport and execute CREATE PACKAGE/BODY
  end

  rect rgba(255,240,200,0.4)
    note over T,P: Dump & verify
    T->>P: Invoke pg_dump against test DB
    P->>DB: Query metadata (reads pkgowner)
    P-->>T: Emit dump output
    T->>T: Match regex expectations (like/unlike)
  end
Loading
sequenceDiagram
  autonumber
  participant Caller as Test/Utility
  participant C as Test Cluster
  participant DB as Server

  note over Caller,C: Connection selection
  Caller->>C: connstr(dbname, connect_to_oraport=false)
  C-->>Caller: host=..., port=<main port>

  Caller->>C: connstr(dbname, connect_to_oraport=true)
  C-->>Caller: host=..., port=<oraport>

  Caller->>C: psql(cmd, connect_to_oraport=true)
  C->>DB: Connect via oraport and run cmd
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Poem

In burrows of code where packages hop,
I twitch my whiskers at the oraport stop.
pg_dump peeks where the owner hides,
Tests hop through tunnels with regex guides.
Makefiles gather oracle trails — thump! 🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/bin/pg_dump/pg_dump.c (1)

6911-6951: Fix owner handling and ACL logic in getPackages()

  • You’re copying p.pkgowner (an OID) directly into pkginfo[i].rolname as a string. This should be resolved to an actual role name, like the rest of pg_dump does, using getRoleName(...). Otherwise, ArchiveEntry “owner” fields (and ACL emission) will be incorrect.

  • The ACL check is inverted. You currently clear ACL dumping when pkgacl is NOT NULL. We should skip ACLs only when pkgacl IS NULL.

Apply this diff:

@@
-    i_rolname = PQfnumber(res, "pkgowner");
+    int i_pkgowner = PQfnumber(res, "pkgowner");
@@
-    pkginfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+    pkginfo[i].rolname = getRoleName(PQgetvalue(res, i, i_pkgowner));
@@
-    /* Do not try to dump ACL if no ACL exists. */
-    if (!PQgetisnull(res, i, i_pkgacl))
-      pkginfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+    /* Do not try to dump ACL if no ACL exists. */
+    if (PQgetisnull(res, i, i_pkgacl))
+      pkginfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+    else
+      pkginfo[i].dobj.components |= DUMP_COMPONENT_ACL;
🧹 Nitpick comments (4)
src/Makefile.global.in (1)

392-394: Fix typo in marker comment (IvoryrSQL → IvorySQL).

Minor but worth correcting for consistency/searchability.

-#IvoryrSQL:END - SQL oracle_test
+#IvorySQL:END - SQL oracle_test
src/oracle_test/perl/PostgreSQL/Test/Cluster.pm (2)

1591-1604: Accept a more ergonomic parameter name for oraport.

Supporting oraport => alongside 'ivorysql.port' improves call-site ergonomics and avoids dotted hash keys.

-	# Select a oraport.
-	my $oraport;
-	if (defined $params{'ivorysql.port'})
-	{
-		$oraport = $params{'ivorysql.port'};
-	}
-	else
-	{
-		# When selecting a port, we look for an unassigned TCP port number,
-		# even if we intend to use only Unix-domain sockets.  This is clearly
-		# necessary on $use_tcp (Windows) configurations, and it seems like a
-		# good idea on Unixen as well.
-		$oraport = get_free_port();
-	}
+	# Select an IvorySQL port (oraport).
+	my $oraport_param = defined $params{oraport} ? $params{oraport} : $params{'ivorysql.port'};
+	my $oraport = defined $oraport_param ? $oraport_param : get_free_port();

2361-2380: Optional: allow background_psql to target oraport.

For parity with psql/safe_psql, accept connect_to_oraport.

 sub background_psql
 {
 	my ($self, $dbname, %params) = @_;
@@
-	else
-	{
-		$psql_connstr = $self->connstr($dbname);
-	}
+	else
+	{
+		$psql_connstr = $self->connstr($dbname, $params{connect_to_oraport} ? 1 : 0);
+	}
src/bin/pg_dump/t/oracle/001_pg_dump_ora_specific.pl (1)

163-167: Drop unused variables.

$connect_to_oraport (declared) and $encoding (assigned but unused) add noise and an extra query.

-my ($connect_to_oraport);
-
-# ICU doesn't work with some encodings
-my $encoding = $node->safe_psql('postgres', 'show server_encoding', connect_to_oraport => 1);
+# (optional) If needed later, detect server encoding via connect_to_oraport.
+# my $encoding = $node->safe_psql('postgres', 'show server_encoding', connect_to_oraport => 1);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 48d5abf and 5ae9e19.

📒 Files selected for processing (4)
  • src/Makefile.global.in (3 hunks)
  • src/bin/pg_dump/pg_dump.c (1 hunks)
  • src/bin/pg_dump/t/oracle/001_pg_dump_ora_specific.pl (1 hunks)
  • src/oracle_test/perl/PostgreSQL/Test/Cluster.pm (10 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-02T10:43:25.242Z
Learnt from: syasirs
PR: IvorySQL/IvorySQL#858
File: src/Makefile.global.in:513-514
Timestamp: 2025-09-02T10:43:25.242Z
Learning: In IvorySQL Makefile.global.in, $(wildcard t/oracle/*.pl) is used instead of t/oracle/*.pl in Oracle TAP test discovery because the t/oracle directory is optional and may not exist in most builds. The wildcard function safely returns empty string when the directory is missing, preventing shell expansion errors.

Applied to files:

  • src/Makefile.global.in
🧬 Code graph analysis (1)
src/bin/pg_dump/pg_dump.c (1)
src/interfaces/libpq/fe-exec.c (1)
  • PQfnumber (3585-3680)
🔇 Additional comments (5)
src/Makefile.global.in (3)

513-514: Good use of $(wildcard) to make Oracle TAP test discovery robust.

Using $(wildcard t/oracle/*.pl) avoids shell expansion errors when t/oracle is absent. This aligns with prior guidance.


540-541: Good use of $(wildcard) in PGXS oracle_prove_installcheck.

Consistent with non-PGXS macro; safe when t/oracle is missing.


569-570: Good use of $(wildcard) in oracle_prove_check.

Keeps Oracle tests optional and non-failing when directory isn’t present.

src/oracle_test/perl/PostgreSQL/Test/Cluster.pm (1)

733-735: LGTM: ivorysql.port propagation is consistent.

Printing ivorysql.port in postgresql.conf during init and init_from_backup, and storing _oraport on creation, looks correct.

Also applies to: 1075-1077, 615-616, 933-934

src/bin/pg_dump/t/oracle/001_pg_dump_ora_specific.pl (1)

218-219: LGTM: seed objects via oraport to match Oracle path.

Seeding with connect_to_oraport ensures objects exist when dumping via the PG port.

Comment thread src/bin/pg_dump/t/oracle/001_pg_dump_ora_specific.pl
Comment thread src/oracle_test/perl/PostgreSQL/Test/Cluster.pm
Comment thread src/bin/pg_dump/t/oracle/001_pg_dump_ora_specific.pl
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
src/bin/pg_dump/t/oracle/001_pg_dump_ora_specific.pl (2)

134-136: Harden regex: escape dot and allow flexible whitespace

Make the match resilient across formatting changes.

-       regexp       => qr/^CREATE EDITIONABLE PACKAGE public.test_pkg AUTHID DEFINER  AS/m,
+       regexp       => qr/^CREATE\s+EDITIONABLE\s+PACKAGE\s+public\.test_pkg\s+AUTHID\s+DEFINER\s+AS\b/m,

147-149: Harden regex for PACKAGE BODY

Same robustness tweak as above.

-       regexp       => qr/^CREATE PACKAGE BODY public.test_pkg  AS/m,
+       regexp       => qr/^CREATE\s+PACKAGE\s+BODY\s+public\.test_pkg\s+AS\b/m,
🧹 Nitpick comments (3)
src/bin/pg_dump/t/oracle/001_pg_dump_ora_specific.pl (3)

151-154: Tighten DROP regex (escape dot, tolerate spaces)

Prevents false negatives due to spacing differences.

-       regexp => qr/^DROP PACKAGE IF EXISTS public.test_pkg;/m,
+       regexp => qr/^DROP\s+PACKAGE\s+IF\s+EXISTS\s+public\.test_pkg;/m,

164-169: Remove unused variables

$connect_to_oraport and $encoding are unused; keep the connect check without binding to a variable.

-my ($connect_to_oraport);
-
-# ICU doesn't work with some encodings
-my $encoding = $node->safe_psql('postgres', 'show server_encoding', connect_to_oraport => 1);
+# Exercise oraport connectivity
+$node->safe_psql('postgres', 'show server_encoding', connect_to_oraport => 1);

57-77: Optional: Add an owner-aware run to cover pkgowner fix

Since the PR mentions reading package owner from pkgowner, consider a third run without --no-owner and assert the emitted ALTER PACKAGE ... OWNER TO ... (or equivalent) to prevent regressions.

I can draft the additional run and assertion if you want.

Also applies to: 120-156

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5ae9e19 and 24b1814.

📒 Files selected for processing (1)
  • src/bin/pg_dump/t/oracle/001_pg_dump_ora_specific.pl (1 hunks)
🔇 Additional comments (1)
src/bin/pg_dump/t/oracle/001_pg_dump_ora_specific.pl (1)

2-4: License header looks good

Acknowledgements are present and correct.

Comment thread src/bin/pg_dump/t/oracle/001_pg_dump_ora_specific.pl
@gaoxueyu gaoxueyu merged commit 6d3dbf1 into IvorySQL:master Sep 3, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug - pg dump throws error "cannot duplicate null pointer" if the database to be dumped contain packages

5 participants