Skip to content

Fix the issue where upgrading from PostgreSQL to IvorySQL fails.#1157

Merged
gaoxueyu merged 1 commit intoIvorySQL:IVORY_REL_5_STABLEfrom
jiaoshuntian:ivy5_fix_upgrade
Jan 29, 2026
Merged

Fix the issue where upgrading from PostgreSQL to IvorySQL fails.#1157
gaoxueyu merged 1 commit intoIvorySQL:IVORY_REL_5_STABLEfrom
jiaoshuntian:ivy5_fix_upgrade

Conversation

@jiaoshuntian
Copy link
Copy Markdown
Collaborator

@jiaoshuntian jiaoshuntian commented Jan 22, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added -g command-line option for database mode configuration.
  • Bug Fixes

    • Improved compatibility during database upgrades between PostgreSQL and IvorySQL systems.
    • Enhanced runtime detection of database-specific features.
    • Relaxed database mode matching requirements for upgrade processes.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 22, 2026

📝 Walkthrough

Walkthrough

The PR replaces version-based feature detection with runtime column existence probes in pg_dump for IvorySQL compatibility, removes database mode validation in pg_upgrade, and adds short option support for Oracle mode configuration in pg_upgrade.

Changes

Cohort / File(s) Summary
Runtime column detection in pg_dump
src/bin/pg_dump/pg_dump.c
Three functions now use runtime probes instead of remoteVersion checks: getPackages queries pg_package existence before fetching packages; getTables detects relhasrowid column availability; getTableAttrs detects attisinvisible column availability. Enables compatibility across PostgreSQL/IvorySQL versions with varying schema.
Database mode validation removal
src/bin/pg_upgrade/controldata.c
Disables mandatory database_mode_is_oracle checks in both data collection and compatibility validation. Permits upgrading between clusters with different database mode values.
Oracle mode command-line support
src/bin/pg_upgrade/option.c
Adds 'g' to getopt_long short-options string, enabling -g flag as alias for --using-ora-pg long option. Existing case handler for 'g' already present.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • NotHimmel

Poem

🐰 A rabbit hops through schemas bright,
Runtime checks replace version's plight,
No Oracle mode gates need hold,
IvorySQL tales now boldly told! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective of the pull request—fixing upgrade failures from PostgreSQL to IvorySQL—which is directly reflected in the changeset across three files implementing runtime compatibility checks.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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

🤖 Fix all issues with AI agents
In `@src/bin/pg_dump/pg_dump.c`:
- Around line 9353-9377: The runtime probe for attisinvisible can return a false
positive if the pg_attribute row is marked dropped; update the ExecuteSqlQuery
used to detect attisinvisible (res_invisible) to include "AND NOT attisdropped"
in its WHERE clause so the check only considers non-dropped attributes, leaving
the surrounding logic that sets attisinvisible_exists and appends to q
(appendPQExpBufferStr) unchanged.
- Around line 7220-7244: The runtime probe for the relhasrowid column can return
a false positive if the attribute exists but is marked dropped; update the
pg_attribute query used in ExecuteSqlQuery (res_rowid) to exclude dropped
attributes by adding a condition like "AND NOT attisdropped" (or "AND
attisdropped = false") so relhasrowid_exists only becomes true for live columns,
leaving the rest of the logic using query/appendPQExpBufferStr and
res_rowid/PQclear unchanged.
🧹 Nitpick comments (1)
src/bin/pg_upgrade/controldata.c (1)

627-629: Consider a non-fatal warning when database modes differ.
Now that the hard check is removed (Line 627, Line 770), a warning would help users notice a mode mismatch without blocking the upgrade.

💡 Suggested warning (non-fatal)
-// if (oldctrl->database_mode_is_oracle != newctrl->database_mode_is_oracle)
-//     pg_fatal("old and new pg_controldata database mode do not match\n");
+if (oldctrl->database_mode_is_oracle != newctrl->database_mode_is_oracle)
+    pg_log(PG_WARNING,
+           "old and new pg_controldata database modes differ; proceeding for compatibility");

Also applies to: 770-772

Comment thread src/bin/pg_dump/pg_dump.c
Comment on lines +7220 to +7244
/*
* Check if relhasrowid column exists. This column is IvorySQL-specific
* for Oracle ROWID compatibility, and doesn't exist in native PostgreSQL.
* We need to check at runtime rather than relying on remoteVersion because
* when upgrading from PostgreSQL to IvorySQL, the source database is
* PostgreSQL which may have the same version number but lacks this column.
*/
{
PGresult *res_rowid;
bool relhasrowid_exists = false;

res_rowid = ExecuteSqlQuery(fout,
"SELECT 1 FROM pg_catalog.pg_attribute "
"WHERE attrelid = 'pg_class'::regclass "
"AND attname = 'relhasrowid' "
"AND attnum > 0 LIMIT 1",
PGRES_TUPLES_OK);
relhasrowid_exists = (PQntuples(res_rowid) > 0);
PQclear(res_rowid);

if (relhasrowid_exists)
appendPQExpBufferStr(query, "c.relhasrowid, ");
else
appendPQExpBufferStr(query, "false AS relhasrowid, ");
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid false positives if the catalog column was dropped.
If relhasrowid is later removed (left as attisdropped), this probe still returns a row and the subsequent SELECT c.relhasrowid will fail. Filter out dropped attributes.

🩹 Proposed fix
-							  "AND attnum > 0 LIMIT 1",
+							  "AND attnum > 0 AND NOT attisdropped LIMIT 1",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/*
* Check if relhasrowid column exists. This column is IvorySQL-specific
* for Oracle ROWID compatibility, and doesn't exist in native PostgreSQL.
* We need to check at runtime rather than relying on remoteVersion because
* when upgrading from PostgreSQL to IvorySQL, the source database is
* PostgreSQL which may have the same version number but lacks this column.
*/
{
PGresult *res_rowid;
bool relhasrowid_exists = false;
res_rowid = ExecuteSqlQuery(fout,
"SELECT 1 FROM pg_catalog.pg_attribute "
"WHERE attrelid = 'pg_class'::regclass "
"AND attname = 'relhasrowid' "
"AND attnum > 0 LIMIT 1",
PGRES_TUPLES_OK);
relhasrowid_exists = (PQntuples(res_rowid) > 0);
PQclear(res_rowid);
if (relhasrowid_exists)
appendPQExpBufferStr(query, "c.relhasrowid, ");
else
appendPQExpBufferStr(query, "false AS relhasrowid, ");
}
/*
* Check if relhasrowid column exists. This column is IvorySQL-specific
* for Oracle ROWID compatibility, and doesn't exist in native PostgreSQL.
* We need to check at runtime rather than relying on remoteVersion because
* when upgrading from PostgreSQL to IvorySQL, the source database is
* PostgreSQL which may have the same version number but lacks this column.
*/
{
PGresult *res_rowid;
bool relhasrowid_exists = false;
res_rowid = ExecuteSqlQuery(fout,
"SELECT 1 FROM pg_catalog.pg_attribute "
"WHERE attrelid = 'pg_class'::regclass "
"AND attname = 'relhasrowid' "
"AND attnum > 0 AND NOT attisdropped LIMIT 1",
PGRES_TUPLES_OK);
relhasrowid_exists = (PQntuples(res_rowid) > 0);
PQclear(res_rowid);
if (relhasrowid_exists)
appendPQExpBufferStr(query, "c.relhasrowid, ");
else
appendPQExpBufferStr(query, "false AS relhasrowid, ");
}
🤖 Prompt for AI Agents
In `@src/bin/pg_dump/pg_dump.c` around lines 7220 - 7244, The runtime probe for
the relhasrowid column can return a false positive if the attribute exists but
is marked dropped; update the pg_attribute query used in ExecuteSqlQuery
(res_rowid) to exclude dropped attributes by adding a condition like "AND NOT
attisdropped" (or "AND attisdropped = false") so relhasrowid_exists only becomes
true for live columns, leaving the rest of the logic using
query/appendPQExpBufferStr and res_rowid/PQclear unchanged.

Comment thread src/bin/pg_dump/pg_dump.c
Comment on lines +9353 to +9377
/*
* Check if attisinvisible column exists. This column is IvorySQL-specific
* for Oracle compatibility, and doesn't exist in native PostgreSQL.
* We need to check at runtime rather than relying on remoteVersion because
* when upgrading from PostgreSQL to IvorySQL, the source database is
* PostgreSQL which may have the same version number but lacks this column.
*/
{
PGresult *res_invisible;
bool attisinvisible_exists = false;

res_invisible = ExecuteSqlQuery(fout,
"SELECT 1 FROM pg_catalog.pg_attribute "
"WHERE attrelid = 'pg_attribute'::regclass "
"AND attname = 'attisinvisible' "
"AND attnum > 0 LIMIT 1",
PGRES_TUPLES_OK);
attisinvisible_exists = (PQntuples(res_invisible) > 0);
PQclear(res_invisible);

if (attisinvisible_exists)
appendPQExpBufferStr(q, "a.attisinvisible,\n");
else
appendPQExpBufferStr(q, "'f' AS attisinvisible,\n");
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid false positives if the catalog column was dropped.
Same risk as above for attisinvisible; add NOT attisdropped to the probe.

🩹 Proposed fix
-							  "AND attnum > 0 LIMIT 1",
+							  "AND attnum > 0 AND NOT attisdropped LIMIT 1",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/*
* Check if attisinvisible column exists. This column is IvorySQL-specific
* for Oracle compatibility, and doesn't exist in native PostgreSQL.
* We need to check at runtime rather than relying on remoteVersion because
* when upgrading from PostgreSQL to IvorySQL, the source database is
* PostgreSQL which may have the same version number but lacks this column.
*/
{
PGresult *res_invisible;
bool attisinvisible_exists = false;
res_invisible = ExecuteSqlQuery(fout,
"SELECT 1 FROM pg_catalog.pg_attribute "
"WHERE attrelid = 'pg_attribute'::regclass "
"AND attname = 'attisinvisible' "
"AND attnum > 0 LIMIT 1",
PGRES_TUPLES_OK);
attisinvisible_exists = (PQntuples(res_invisible) > 0);
PQclear(res_invisible);
if (attisinvisible_exists)
appendPQExpBufferStr(q, "a.attisinvisible,\n");
else
appendPQExpBufferStr(q, "'f' AS attisinvisible,\n");
}
/*
* Check if attisinvisible column exists. This column is IvorySQL-specific
* for Oracle compatibility, and doesn't exist in native PostgreSQL.
* We need to check at runtime rather than relying on remoteVersion because
* when upgrading from PostgreSQL to IvorySQL, the source database is
* PostgreSQL which may have the same version number but lacks this column.
*/
{
PGresult *res_invisible;
bool attisinvisible_exists = false;
res_invisible = ExecuteSqlQuery(fout,
"SELECT 1 FROM pg_catalog.pg_attribute "
"WHERE attrelid = 'pg_attribute'::regclass "
"AND attname = 'attisinvisible' "
"AND attnum > 0 AND NOT attisdropped LIMIT 1",
PGRES_TUPLES_OK);
attisinvisible_exists = (PQntuples(res_invisible) > 0);
PQclear(res_invisible);
if (attisinvisible_exists)
appendPQExpBufferStr(q, "a.attisinvisible,\n");
else
appendPQExpBufferStr(q, "'f' AS attisinvisible,\n");
}
🤖 Prompt for AI Agents
In `@src/bin/pg_dump/pg_dump.c` around lines 9353 - 9377, The runtime probe for
attisinvisible can return a false positive if the pg_attribute row is marked
dropped; update the ExecuteSqlQuery used to detect attisinvisible
(res_invisible) to include "AND NOT attisdropped" in its WHERE clause so the
check only considers non-dropped attributes, leaving the surrounding logic that
sets attisinvisible_exists and appends to q (appendPQExpBufferStr) unchanged.

@gaoxueyu gaoxueyu merged commit c04e74d into IvorySQL:IVORY_REL_5_STABLE Jan 29, 2026
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.

Use the pg_upgrade tool to upgrade a lower version of PG to the new version of IvorySQL.

2 participants