Skip to content

Add Auto Incrementing Primary Keys to tables with no PKs#13844

Open
dakshina99 wants to merge 1 commit into
wso2:masterfrom
dakshina99:master-db-PKs
Open

Add Auto Incrementing Primary Keys to tables with no PKs#13844
dakshina99 wants to merge 1 commit into
wso2:masterfrom
dakshina99:master-db-PKs

Conversation

@dakshina99

Copy link
Copy Markdown
Contributor

Description

This pull request updates the database schema scripts for multiple RDBMSs (MySQL, H2, MSSQL, Oracle, DB2) to add an auto-incrementing primary key column (ID) to several tables that previously lacked a simple integer primary key. For Oracle and Oracle 23c, it also adds the necessary sequences and triggers to support auto-increment behavior. These changes improve data integrity, support for ORM frameworks, and ease of referencing rows.

The most important changes are:

Schema enhancements:

Oracle-specific support:

  • For Oracle and Oracle 23c, created sequences and triggers to automatically populate the new ID columns for the affected tables, ensuring auto-increment behavior. [1] [2] [3] [4] [5]

These changes standardize primary key usage across the schema and ensure compatibility and consistency for all supported database platforms.

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Nine SQL dialect files are updated to add auto-generated integer ID columns and make PRIMARY KEY (ID) for four tables: IDN_OAUTH2_TOKEN_BINDING, AM_SCOPE_BINDING, AM_API_REVISION_METADATA, and AM_WEBHOOKS_UNSUBSCRIPTION, using dialect-specific auto-increment mechanisms.

Changes

Schema Normalization: Surrogate Key Migration

Layer / File(s) Summary
OAuth2 token binding surrogate key
features/apimgt/.../sql/db2.sql, h2.sql, mssql.sql, mysql.sql, oracle.sql, oracle_23c.sql, oracle_rac.sql, postgresql.sql
IDN_OAUTH2_TOKEN_BINDING adds an auto-generated ID primary key in each dialect; existing UNIQUE (TOKEN_ID, TOKEN_BINDING_TYPE, TOKEN_BINDING_VALUE) and FK to access token remain.
API scope binding surrogate key
features/apimgt/.../sql/db2.sql, h2.sql, mssql.sql, mysql.sql, mysql_cluster.sql, oracle.sql, oracle_23c.sql, oracle_rac.sql, postgresql.sql
AM_SCOPE_BINDING adds an auto-generated ID primary key in each dialect; SCOPE_ID foreign key to AM_SCOPE is preserved.
API revision metadata surrogate key
features/apimgt/.../sql/db2.sql, h2.sql, mssql.sql, mysql.sql, mysql_cluster.sql, oracle.sql, oracle_23c.sql, oracle_rac.sql, postgresql.sql
AM_API_REVISION_METADATA adds an auto-generated ID primary key while retaining UNIQUE (API_UUID, REVISION_UUID) and the REVISION_UUID FK to AM_REVISION.
Webhooks unsubscription surrogate key
features/apimgt/.../sql/db2.sql, h2.sql, mssql.sql, mysql.sql, mysql_cluster.sql, oracle.sql, oracle_23c.sql, oracle_rac.sql, postgresql.sql
AM_WEBHOOKS_UNSUBSCRIPTION switches to an auto-generated ID primary key in each dialect; webhook columns and ADDED_AT defaults remain unchanged.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • npamudika
  • pubudu538
  • dushaniw
  • RakhithaRR
  • PasanT9
  • Krishanx92
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding auto-incrementing primary keys to tables that previously lacked simple integer primary keys.
Description check ✅ Passed The description is well-detailed and directly related to the changeset, explaining the schema enhancements and database-specific implementations across multiple platforms.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copilot AI left a comment

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.

Pull request overview

This PR updates the API-M database initialization SQL scripts to introduce a surrogate, auto-incrementing integer primary key (ID) for several tables that previously lacked a simple PK, with Oracle-specific sequence/trigger support to emulate auto-increment behavior.

Changes:

  • Added ID auto-increment (or sequence/trigger) + PRIMARY KEY (ID) to: IDN_OAUTH2_TOKEN_BINDING, AM_SCOPE_BINDING, AM_API_REVISION_METADATA, AM_WEBHOOKS_UNSUBSCRIPTION across multiple RDBMS scripts.
  • Added PostgreSQL sequences for the new ID defaults.
  • Added Oracle/Oracle RAC/Oracle 23c sequences + triggers to populate the new ID columns.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/postgresql.sql Adds sequences and ID PKs for the affected tables in PostgreSQL.
features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql Adds ID PKs plus sequences/triggers for auto-increment behavior in Oracle.
features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_rac.sql Mirrors Oracle changes for RAC variant with sequences/triggers.
features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql Mirrors Oracle changes for Oracle 23c variant with sequences/triggers.
features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql Adds AUTO_INCREMENT ID PKs for the affected tables in MySQL.
features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql Adds AUTO_INCREMENT ID PKs for several tables in MySQL NDB cluster script (but currently incomplete for IDN_OAUTH2_TOKEN_BINDING).
features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mssql.sql Adds IDENTITY ID PKs for the affected tables in SQL Server.
features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql Adds AUTO_INCREMENT ID PKs for the affected tables in H2.
features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/db2.sql Adds IDENTITY ID PKs for the affected tables in DB2.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2494 to +2498
ID INTEGER NOT NULL AUTO_INCREMENT,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
PRIMARY KEY (ID),
Comment on lines 116 to +120
DROP TABLE IF EXISTS IDN_OAUTH2_TOKEN_BINDING;
DROP SEQUENCE IF EXISTS IDN_OAUTH2_TOKEN_BINDING_PK_SEQ;
CREATE SEQUENCE IDN_OAUTH2_TOKEN_BINDING_PK_SEQ;
CREATE TABLE IDN_OAUTH2_TOKEN_BINDING (
ID INTEGER DEFAULT NEXTVAL('IDN_OAUTH2_TOKEN_BINDING_PK_SEQ') NOT NULL,

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 15

🧹 Nitpick comments (2)
features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql (1)

3824-3835: 💤 Low value

Consider adding UNIQUE constraint if duplicate prevention is required.

If the previous composite primary key was on columns like (API_UUID, APPLICATION_ID, HUB_CALLBACK_URL, HUB_TOPIC), switching to a surrogate ID without a UNIQUE constraint allows duplicate unsubscription records. If this table is intended as an append-only log where duplicates are acceptable, this is fine. Otherwise, consider adding a unique constraint.

Please confirm whether duplicate unsubscription records for the same webhook are acceptable, or if a UNIQUE constraint should be added to preserve data integrity.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql`
around lines 3824 - 3835, The table AM_WEBHOOKS_UNSUBSCRIPTION was converted to
use a surrogate PK (ID) which allows duplicate unsubscription rows; decide
whether duplicates are acceptable and if not, add a UNIQUE constraint on the
composite columns (API_UUID, APPLICATION_ID, HUB_CALLBACK_URL, HUB_TOPIC) to
enforce uniqueness. Update the table definition for AM_WEBHOOKS_UNSUBSCRIPTION
to include a UNIQUE constraint referencing those columns (or restore the
previous composite PK) and ensure any insert logic (if present) handles unique
constraint violations appropriately. Be explicit about the constraint name when
adding it so it can be referenced/rolled back if needed.
features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql (1)

2639-2650: 💤 Low value

Verify if UNIQUE constraint on business columns is intentional.

The AM_WEBHOOKS_UNSUBSCRIPTION table now uses surrogate ID as the primary key but has no UNIQUE constraint on the natural key columns (e.g., API_UUID, APPLICATION_ID, TENANT_DOMAIN, HUB_CALLBACK_URL, HUB_TOPIC).

If the previous schema enforced uniqueness via a composite primary key, that guarantee is now lost. Please verify whether allowing duplicate unsubscription records is acceptable for the business logic. If not, add a UNIQUE constraint on the appropriate columns.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql`
around lines 2639 - 2650, The new AM_WEBHOOKS_UNSUBSCRIPTION table uses a
surrogate PK (ID) but dropped the previous uniqueness guarantee on the natural
key; confirm whether duplicates of (API_UUID, APPLICATION_ID, TENANT_DOMAIN,
HUB_CALLBACK_URL, HUB_TOPIC) are allowed and, if not, add a UNIQUE constraint on
those columns (or the correct subset) to restore the business-rule uniqueness
for AM_WEBHOOKS_UNSUBSCRIPTION; locate the CREATE TABLE for
AM_WEBHOOKS_UNSUBSCRIPTION and add a UNIQUE(...) clause referencing the
appropriate columns.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/db2.sql`:
- Around line 3250-3260: The table AM_WEBHOOKS_UNSUBSCRIPTION lost its previous
business-key uniqueness; add a UNIQUE constraint on the prior composite business
key (the columns used to identify an unsubscription) alongside the surrogate ID
to prevent duplicate unsubscriptions — for example, alter the CREATE TABLE for
AM_WEBHOOKS_UNSUBSCRIPTION to include a UNIQUE(...) clause referencing the
previous business-key columns (e.g., API_UUID, APPLICATION_ID, TENANT_DOMAIN,
HUB_TOPIC or the exact composite used previously) so the surrogate PRIMARY
KEY(ID) stays and the old composite uniqueness is preserved.
- Around line 3092-3098: The migration replaced the natural key by making
AM_SCOPE_BINDING PRIMARY KEY (ID) but removed the uniqueness of the previous
natural key; add back a UNIQUE constraint on (SCOPE_ID, SCOPE_BINDING,
BINDING_TYPE) to prevent duplicate bindings. Modify the AM_SCOPE_BINDING table
definition (the CREATE TABLE for AM_SCOPE_BINDING) to include UNIQUE (SCOPE_ID,
SCOPE_BINDING, BINDING_TYPE) alongside PRIMARY KEY (ID) so it matches the
uniqueness semantics used by IDN_OAUTH2_SCOPE_BINDING.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql`:
- Around line 2467-2477: The new AM_WEBHOOKS_UNSUBSCRIPTION table definition
removed the previous composite business key, allowing duplicate unsubscriptions;
add a UNIQUE constraint on the original composite columns to preserve that
uniqueness (e.g. add UNIQUE (API_UUID, APPLICATION_ID, TENANT_DOMAIN,
HUB_CALLBACK_URL, HUB_TOPIC) in the CREATE TABLE for AM_WEBHOOKS_UNSUBSCRIPTION,
optionally naming the constraint like
UNQ_AM_WEBHOOKS_UNSUBSCRIPTION_BUSINESSKEY) so the combination of those fields
cannot be inserted more than once.
- Around line 2303-2309: The new AM_SCOPE_BINDING table drops the previous
business-key uniqueness by only declaring PRIMARY KEY (ID); add a unique
constraint to preserve the natural/business key by declaring UNIQUE (SCOPE_ID,
SCOPE_BINDING, BINDING_TYPE) on the table definition so duplicates of that
triple cannot be inserted while keeping ID as the surrogate PK; modify the
CREATE TABLE for AM_SCOPE_BINDING to include this UNIQUE constraint referencing
the existing columns SCOPE_ID, SCOPE_BINDING and BINDING_TYPE.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mssql.sql`:
- Around line 2723-2732: The table AM_WEBHOOKS_UNSUBSCRIPTION was changed to use
PRIMARY KEY (ID) but lost the original business-key uniqueness; add a UNIQUE
constraint on the original unsubscribe key columns to restore idempotency by
declaring UNIQUE (API_UUID, APPLICATION_ID, TENANT_DOMAIN, HUB_CALLBACK_URL,
HUB_TOPIC) in the CREATE TABLE statement (while leaving PRIMARY KEY (ID) intact)
so duplicate logical unsubscribe records cannot be inserted.
- Around line 2564-2569: The AM_SCOPE_BINDING table lost its business-key
uniqueness when it was changed to PRIMARY KEY (ID), allowing duplicate
(SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) rows; restore data integrity by adding a
UNIQUE constraint or unique index on the triple (SCOPE_ID, SCOPE_BINDING,
BINDING_TYPE) for the AM_SCOPE_BINDING table (update the SQL in mssql.sql near
the table definition) so that inserts/updates cannot create duplicates while
keeping the surrogate ID primary key.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql`:
- Around line 2493-2500: The AM_SCOPE_BINDING table adds a surrogate primary key
ID but is missing a UNIQUE constraint on the natural key, so add a UNIQUE
constraint on (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) in the AM_SCOPE_BINDING
CREATE TABLE statement to prevent duplicate entries; modify the AM_SCOPE_BINDING
definition (the table with PRIMARY KEY (ID) and FOREIGN KEY (SCOPE_ID)
REFERENCES AM_SCOPE) to include UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE).

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql`:
- Around line 2508-2517: The table AM_WEBHOOKS_UNSUBSCRIPTION currently uses a
surrogate primary key (ID) but lost the previous composite business key; add a
UNIQUE constraint on the former composite columns to prevent duplicate logical
unsubscribe records by declaring UNIQUE(API_UUID, APPLICATION_ID, TENANT_DOMAIN,
HUB_CALLBACK_URL, HUB_TOPIC) in the table definition (alongside PRIMARY KEY
(ID)) so the business key is enforced while keeping the surrogate key.
- Around line 2343-2348: The AM_SCOPE_BINDING table currently only defines ID as
the primary key which allows duplicate natural-key rows; add a UNIQUE constraint
on (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) while keeping ID as the surrogate PK
and the existing FOREIGN KEY on SCOPE_ID. Locate the table definition for
AM_SCOPE_BINDING and add a UNIQUE clause (e.g., UNIQUE (SCOPE_ID, SCOPE_BINDING,
BINDING_TYPE) with an appropriate constraint name) alongside the PRIMARY KEY and
FOREIGN KEY declarations.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql`:
- Around line 3630-3648: The AM_SCOPE_BINDING table definition is missing a
UNIQUE constraint on the natural key, allowing duplicate bindings; update the
CREATE TABLE for AM_SCOPE_BINDING to include UNIQUE (SCOPE_ID, SCOPE_BINDING,
BINDING_TYPE) alongside the PRIMARY KEY and FOREIGN KEY so the combination of
SCOPE_ID, SCOPE_BINDING, and BINDING_TYPE is enforced as unique; ensure the
change is applied in the AM_SCOPE_BINDING CREATE TABLE statement (and mirrored
across other dialect files: db2.sql, mssql.sql, oracle.sql, oracle_rac.sql)
while leaving the AM_SCOPE_BINDING_SEQ and AM_SCOPE_BINDING_TRIG unchanged.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_rac.sql`:
- Around line 3576-3586: The table AM_WEBHOOKS_UNSUBSCRIPTION currently uses
only PRIMARY KEY (ID) which removes the previous business-key uniqueness; add
back a UNIQUE constraint on the composite business-key columns (API_UUID,
APPLICATION_ID, TENANT_DOMAIN, HUB_CALLBACK_URL, HUB_TOPIC) so duplicates cannot
be inserted while keeping the surrogate ID primary key (i.e., keep PRIMARY KEY
(ID) and add UNIQUE(...) on those columns), ensuring the constraint name is
descriptive and consistent with existing naming conventions.
- Around line 3392-3398: The CREATE TABLE for AM_SCOPE_BINDING replaced the
business key with a surrogate PK (ID) but removed uniqueness on the original
tuple; update the DDL to keep ID as PRIMARY KEY and add a UNIQUE constraint on
(SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) so duplicate bindings cannot be
inserted; modify the AM_SCOPE_BINDING definition to include a UNIQUE (SCOPE_ID,
SCOPE_BINDING, BINDING_TYPE) clause while retaining the FOREIGN KEY on SCOPE_ID
and PRIMARY KEY (ID).

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql`:
- Around line 3617-3624: The AM_SCOPE_BINDING table now uses a surrogate ID but
lacks a UNIQUE constraint on the former natural key, allowing duplicate entries;
update the AM_SCOPE_BINDING DDL to add a UNIQUE constraint on (SCOPE_ID,
SCOPE_BINDING, BINDING_TYPE) so those three columns remain unique (mirror the
constraint used by IDN_OAUTH2_SCOPE_BINDING), ensuring the UNIQUE is declared
for AM_SCOPE_BINDING alongside the PRIMARY KEY(ID).

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/postgresql.sql`:
- Around line 2829-2839: The CREATE TABLE for AM_WEBHOOKS_UNSUBSCRIPTION
replaced the previous composite business key with a surrogate ID and thus lost
uniqueness; restore the original composite uniqueness by adding a UNIQUE
constraint (or unique index) on the combination of API_UUID, APPLICATION_ID,
TENANT_DOMAIN, HUB_CALLBACK_URL and HUB_TOPIC in the AM_WEBHOOKS_UNSUBSCRIPTION
definition (or immediately after creation) so the table keeps the old
business-key uniqueness while still having the ID primary key.
- Around line 2665-2671: The table AM_SCOPE_BINDING currently only has a
surrogate primary key ID which allows duplicate logical bindings; add a
uniqueness constraint (or unique index) on the tuple (SCOPE_ID, SCOPE_BINDING,
BINDING_TYPE) to restore the original uniqueness semantics—modify the
AM_SCOPE_BINDING DDL to include a UNIQUE constraint on those three columns (or
create a UNIQUE INDEX on SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) and ensure the
constraint name is descriptive (e.g., AM_SCOPE_BINDING_UQ) so duplicate
(scope_id, scope_binding, binding_type) rows are rejected.

---

Nitpick comments:
In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql`:
- Around line 2639-2650: The new AM_WEBHOOKS_UNSUBSCRIPTION table uses a
surrogate PK (ID) but dropped the previous uniqueness guarantee on the natural
key; confirm whether duplicates of (API_UUID, APPLICATION_ID, TENANT_DOMAIN,
HUB_CALLBACK_URL, HUB_TOPIC) are allowed and, if not, add a UNIQUE constraint on
those columns (or the correct subset) to restore the business-rule uniqueness
for AM_WEBHOOKS_UNSUBSCRIPTION; locate the CREATE TABLE for
AM_WEBHOOKS_UNSUBSCRIPTION and add a UNIQUE(...) clause referencing the
appropriate columns.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql`:
- Around line 3824-3835: The table AM_WEBHOOKS_UNSUBSCRIPTION was converted to
use a surrogate PK (ID) which allows duplicate unsubscription rows; decide
whether duplicates are acceptable and if not, add a UNIQUE constraint on the
composite columns (API_UUID, APPLICATION_ID, HUB_CALLBACK_URL, HUB_TOPIC) to
enforce uniqueness. Update the table definition for AM_WEBHOOKS_UNSUBSCRIPTION
to include a UNIQUE constraint referencing those columns (or restore the
previous composite PK) and ensure any insert logic (if present) handles unique
constraint violations appropriately. Be explicit about the constraint name when
adding it so it can be referenced/rolled back if needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 19cc5d74-0237-45e3-a397-415724b3886d

📥 Commits

Reviewing files that changed from the base of the PR and between c32fbde and 7bfd004.

📒 Files selected for processing (9)
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/db2.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mssql.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_rac.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/postgresql.sql

Comment on lines 3092 to 3098
CREATE TABLE AM_SCOPE_BINDING (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep the natural key unique after adding ID.

Switching AM_SCOPE_BINDING to PRIMARY KEY (ID) without a replacement UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) now allows duplicate bindings for the same scope. That weakens the old key contract and also makes this table inconsistent with IDN_OAUTH2_SCOPE_BINDING earlier in the same script.

Suggested fix
 CREATE TABLE AM_SCOPE_BINDING (
             ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
             SCOPE_ID INTEGER NOT NULL,
             SCOPE_BINDING VARCHAR(255) NOT NULL,
             BINDING_TYPE VARCHAR(255) NOT NULL,
+            UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE),
             PRIMARY KEY (ID),
             FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE)
📝 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
CREATE TABLE AM_SCOPE_BINDING (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE)
CREATE TABLE AM_SCOPE_BINDING (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE),
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/db2.sql`
around lines 3092 - 3098, The migration replaced the natural key by making
AM_SCOPE_BINDING PRIMARY KEY (ID) but removed the uniqueness of the previous
natural key; add back a UNIQUE constraint on (SCOPE_ID, SCOPE_BINDING,
BINDING_TYPE) to prevent duplicate bindings. Modify the AM_SCOPE_BINDING table
definition (the CREATE TABLE for AM_SCOPE_BINDING) to include UNIQUE (SCOPE_ID,
SCOPE_BINDING, BINDING_TYPE) alongside PRIMARY KEY (ID) so it matches the
uniqueness semantics used by IDN_OAUTH2_SCOPE_BINDING.

Comment on lines 3250 to +3260
CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
API_UUID VARCHAR(255) NOT NULL,
APPLICATION_ID VARCHAR(20) NOT NULL,
TENANT_DOMAIN VARCHAR(255) NOT NULL,
HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
HUB_TOPIC VARCHAR(255) NOT NULL,
HUB_SECRET VARCHAR(2048),
HUB_LEASE_SECONDS INTEGER,
ADDED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
ADDED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ID)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve the previous webhook business key as UNIQUE.

After this change, the table no longer has any uniqueness on the old unsubscription identity, so duplicate unsubscribe rows become valid. Please keep the prior composite key as a UNIQUE constraint alongside the surrogate ID.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/db2.sql`
around lines 3250 - 3260, The table AM_WEBHOOKS_UNSUBSCRIPTION lost its previous
business-key uniqueness; add a UNIQUE constraint on the prior composite business
key (the columns used to identify an unsubscription) alongside the surrogate ID
to prevent duplicate unsubscriptions — for example, alter the CREATE TABLE for
AM_WEBHOOKS_UNSUBSCRIPTION to include a UNIQUE(...) clause referencing the
previous business-key columns (e.g., API_UUID, APPLICATION_ID, TENANT_DOMAIN,
HUB_TOPIC or the exact composite used previously) so the surrogate PRIMARY
KEY(ID) stays and the old composite uniqueness is preserved.

Comment on lines 2303 to 2309
CREATE TABLE IF NOT EXISTS AM_SCOPE_BINDING (
ID INTEGER NOT NULL AUTO_INCREMENT,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep the natural key unique after adding ID.

This change removes the old business-key protection from AM_SCOPE_BINDING. With only PRIMARY KEY (ID), duplicate (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) rows become possible.

Suggested fix
 CREATE TABLE IF NOT EXISTS AM_SCOPE_BINDING (
             ID INTEGER NOT NULL AUTO_INCREMENT,
             SCOPE_ID INTEGER NOT NULL,
             SCOPE_BINDING VARCHAR(255) NOT NULL,
             BINDING_TYPE VARCHAR(255) NOT NULL,
+            UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE),
             PRIMARY KEY (ID),
             FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE
 );
📝 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
CREATE TABLE IF NOT EXISTS AM_SCOPE_BINDING (
ID INTEGER NOT NULL AUTO_INCREMENT,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE
CREATE TABLE IF NOT EXISTS AM_SCOPE_BINDING (
ID INTEGER NOT NULL AUTO_INCREMENT,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE),
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql`
around lines 2303 - 2309, The new AM_SCOPE_BINDING table drops the previous
business-key uniqueness by only declaring PRIMARY KEY (ID); add a unique
constraint to preserve the natural/business key by declaring UNIQUE (SCOPE_ID,
SCOPE_BINDING, BINDING_TYPE) on the table definition so duplicates of that
triple cannot be inserted while keeping ID as the surrogate PK; modify the
CREATE TABLE for AM_SCOPE_BINDING to include this UNIQUE constraint referencing
the existing columns SCOPE_ID, SCOPE_BINDING and BINDING_TYPE.

Comment on lines 2467 to +2477
CREATE TABLE IF NOT EXISTS AM_WEBHOOKS_UNSUBSCRIPTION (
ID INTEGER NOT NULL AUTO_INCREMENT,
API_UUID VARCHAR(255) NOT NULL,
APPLICATION_ID VARCHAR(20) NOT NULL,
TENANT_DOMAIN VARCHAR(255) NOT NULL,
HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
HUB_TOPIC VARCHAR(255) NOT NULL,
HUB_SECRET VARCHAR(2048),
HUB_LEASE_SECONDS INTEGER,
ADDED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
ADDED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ID)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve the previous webhook business key as UNIQUE.

Using ID as the sole key here drops the old unsubscription uniqueness guarantee, so the same webhook unsubscribe can now be stored multiple times. Please retain the prior composite key as a UNIQUE constraint.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql`
around lines 2467 - 2477, The new AM_WEBHOOKS_UNSUBSCRIPTION table definition
removed the previous composite business key, allowing duplicate unsubscriptions;
add a UNIQUE constraint on the original composite columns to preserve that
uniqueness (e.g. add UNIQUE (API_UUID, APPLICATION_ID, TENANT_DOMAIN,
HUB_CALLBACK_URL, HUB_TOPIC) in the CREATE TABLE for AM_WEBHOOKS_UNSUBSCRIPTION,
optionally naming the constraint like
UNQ_AM_WEBHOOKS_UNSUBSCRIPTION_BUSINESSKEY) so the combination of those fields
cannot be inserted more than once.

Comment on lines +2564 to 2569
ID INTEGER NOT NULL IDENTITY,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Restore business-key uniqueness for AM_SCOPE_BINDING.

Switching this table to PRIMARY KEY (ID) without a replacement UNIQUE constraint now allows duplicate (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) rows. That weakens data integrity and changes the semantics of scope binding lookups.

Suggested fix
 CREATE TABLE AM_SCOPE_BINDING (
   ID INTEGER NOT NULL IDENTITY,
   SCOPE_ID INTEGER NOT NULL,
   SCOPE_BINDING VARCHAR(255) NOT NULL,
   BINDING_TYPE VARCHAR(255) NOT NULL,
+  UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE),
   PRIMARY KEY (ID),
   FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE
 );
📝 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
ID INTEGER NOT NULL IDENTITY,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE
ID INTEGER NOT NULL IDENTITY,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE),
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mssql.sql`
around lines 2564 - 2569, The AM_SCOPE_BINDING table lost its business-key
uniqueness when it was changed to PRIMARY KEY (ID), allowing duplicate
(SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) rows; restore data integrity by adding a
UNIQUE constraint or unique index on the triple (SCOPE_ID, SCOPE_BINDING,
BINDING_TYPE) for the AM_SCOPE_BINDING table (update the SQL in mssql.sql near
the table definition) so that inserts/updates cannot create duplicates while
keeping the surrogate ID primary key.

Comment on lines 3392 to 3398
CREATE TABLE AM_SCOPE_BINDING (
ID INTEGER NOT NULL,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR2(255) NOT NULL,
BINDING_TYPE VARCHAR2(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep the old binding tuple unique.

Switching AM_SCOPE_BINDING to PRIMARY KEY (ID) here drops the only uniqueness guarantee on (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE), so identical bindings can now be inserted multiple times. If the surrogate key is needed for ORM compatibility, keep the previous business key as a UNIQUE constraint alongside ID.

Suggested fix
 CREATE TABLE AM_SCOPE_BINDING (
             ID INTEGER NOT NULL,
             SCOPE_ID INTEGER NOT NULL,
             SCOPE_BINDING VARCHAR2(255) NOT NULL,
             BINDING_TYPE VARCHAR2(255) NOT NULL,
             PRIMARY KEY (ID),
+            UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE),
             FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE)
📝 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
CREATE TABLE AM_SCOPE_BINDING (
ID INTEGER NOT NULL,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR2(255) NOT NULL,
BINDING_TYPE VARCHAR2(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE)
CREATE TABLE AM_SCOPE_BINDING (
ID INTEGER NOT NULL,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR2(255) NOT NULL,
BINDING_TYPE VARCHAR2(255) NOT NULL,
PRIMARY KEY (ID),
UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_rac.sql`
around lines 3392 - 3398, The CREATE TABLE for AM_SCOPE_BINDING replaced the
business key with a surrogate PK (ID) but removed uniqueness on the original
tuple; update the DDL to keep ID as PRIMARY KEY and add a UNIQUE constraint on
(SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) so duplicate bindings cannot be
inserted; modify the AM_SCOPE_BINDING definition to include a UNIQUE (SCOPE_ID,
SCOPE_BINDING, BINDING_TYPE) clause while retaining the FOREIGN KEY on SCOPE_ID
and PRIMARY KEY (ID).

Comment on lines 3576 to +3586
CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION (
ID INTEGER NOT NULL,
API_UUID VARCHAR(255) NOT NULL,
APPLICATION_ID VARCHAR(20) NOT NULL,
TENANT_DOMAIN VARCHAR(255) NOT NULL,
HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
HUB_TOPIC VARCHAR(255) NOT NULL,
HUB_SECRET VARCHAR(2048),
HUB_LEASE_SECONDS INTEGER,
ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ID))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Retain the previous webhook business-key uniqueness.

Replacing the composite key with PRIMARY KEY (ID) alone changes the table semantics: duplicate unsubscribe rows for the same webhook can now be stored, and the old key index disappears. Please keep the previous composite key columns as a UNIQUE constraint in addition to the surrogate ID.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_rac.sql`
around lines 3576 - 3586, The table AM_WEBHOOKS_UNSUBSCRIPTION currently uses
only PRIMARY KEY (ID) which removes the previous business-key uniqueness; add
back a UNIQUE constraint on the composite business-key columns (API_UUID,
APPLICATION_ID, TENANT_DOMAIN, HUB_CALLBACK_URL, HUB_TOPIC) so duplicates cannot
be inserted while keeping the surrogate ID primary key (i.e., keep PRIMARY KEY
(ID) and add UNIQUE(...) on those columns), ensuring the constraint name is
descriptive and consistent with existing naming conventions.

Comment on lines 3617 to 3624
CREATE TABLE AM_SCOPE_BINDING (
ID INTEGER NOT NULL,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR2(255) NOT NULL,
BINDING_TYPE VARCHAR2(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE)
/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Missing UNIQUE constraint on natural key columns.

When switching from a composite primary key to a surrogate ID, a UNIQUE constraint should be added on the previous natural key columns to preserve data integrity. Without it, duplicate scope bindings (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) can now be inserted.

For consistency, note that the similar IDN_OAUTH2_SCOPE_BINDING table at line 289 includes UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE).

Proposed fix
 CREATE TABLE AM_SCOPE_BINDING (
             ID INTEGER NOT NULL,
             SCOPE_ID INTEGER NOT NULL,
             SCOPE_BINDING VARCHAR2(255) NOT NULL,
             BINDING_TYPE VARCHAR2(255) NOT NULL,
             PRIMARY KEY (ID),
+            UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE),
             FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE)
📝 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
CREATE TABLE AM_SCOPE_BINDING (
ID INTEGER NOT NULL,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR2(255) NOT NULL,
BINDING_TYPE VARCHAR2(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE)
/
CREATE TABLE AM_SCOPE_BINDING (
ID INTEGER NOT NULL,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR2(255) NOT NULL,
BINDING_TYPE VARCHAR2(255) NOT NULL,
PRIMARY KEY (ID),
UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE)
/
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql`
around lines 3617 - 3624, The AM_SCOPE_BINDING table now uses a surrogate ID but
lacks a UNIQUE constraint on the former natural key, allowing duplicate entries;
update the AM_SCOPE_BINDING DDL to add a UNIQUE constraint on (SCOPE_ID,
SCOPE_BINDING, BINDING_TYPE) so those three columns remain unique (mirror the
constraint used by IDN_OAUTH2_SCOPE_BINDING), ensuring the UNIQUE is declared
for AM_SCOPE_BINDING alongside the PRIMARY KEY(ID).

Comment on lines 2665 to 2671
CREATE TABLE IF NOT EXISTS AM_SCOPE_BINDING (
ID INTEGER DEFAULT NEXTVAL('AM_SCOPE_BINDING_PK_SEQ') NOT NULL,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve uniqueness on the original scope-binding key.

PRIMARY KEY (ID) is fine for the surrogate key, but without also keeping (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) unique, this table now accepts duplicate bindings that the old key structure would have rejected.

Suggested fix
 CREATE TABLE IF NOT EXISTS AM_SCOPE_BINDING (
             ID INTEGER DEFAULT NEXTVAL('AM_SCOPE_BINDING_PK_SEQ') NOT NULL,
             SCOPE_ID INTEGER NOT NULL,
             SCOPE_BINDING VARCHAR(255) NOT NULL,
             BINDING_TYPE VARCHAR(255) NOT NULL,
             PRIMARY KEY (ID),
+            UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE),
             FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE
 );
📝 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
CREATE TABLE IF NOT EXISTS AM_SCOPE_BINDING (
ID INTEGER DEFAULT NEXTVAL('AM_SCOPE_BINDING_PK_SEQ') NOT NULL,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE
CREATE TABLE IF NOT EXISTS AM_SCOPE_BINDING (
ID INTEGER DEFAULT NEXTVAL('AM_SCOPE_BINDING_PK_SEQ') NOT NULL,
SCOPE_ID INTEGER NOT NULL,
SCOPE_BINDING VARCHAR(255) NOT NULL,
BINDING_TYPE VARCHAR(255) NOT NULL,
PRIMARY KEY (ID),
UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE),
FOREIGN KEY (SCOPE_ID) REFERENCES AM_SCOPE(SCOPE_ID) ON DELETE CASCADE
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/postgresql.sql`
around lines 2665 - 2671, The table AM_SCOPE_BINDING currently only has a
surrogate primary key ID which allows duplicate logical bindings; add a
uniqueness constraint (or unique index) on the tuple (SCOPE_ID, SCOPE_BINDING,
BINDING_TYPE) to restore the original uniqueness semantics—modify the
AM_SCOPE_BINDING DDL to include a UNIQUE constraint on those three columns (or
create a UNIQUE INDEX on SCOPE_ID, SCOPE_BINDING, BINDING_TYPE) and ensure the
constraint name is descriptive (e.g., AM_SCOPE_BINDING_UQ) so duplicate
(scope_id, scope_binding, binding_type) rows are rejected.

Comment on lines 2829 to +2839
CREATE TABLE IF NOT EXISTS AM_WEBHOOKS_UNSUBSCRIPTION (
ID INTEGER DEFAULT NEXTVAL('AM_WEBHOOKS_UNSUBSCRIPTION_PK_SEQ') NOT NULL,
API_UUID VARCHAR(255) NOT NULL,
APPLICATION_ID VARCHAR(20) NOT NULL,
TENANT_DOMAIN VARCHAR(255) NOT NULL,
HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
HUB_TOPIC VARCHAR(255) NOT NULL,
HUB_SECRET VARCHAR(2048),
HUB_LEASE_SECONDS INTEGER,
ADDED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
ADDED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ID)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t drop the old webhook uniqueness when adding ID.

This changes AM_WEBHOOKS_UNSUBSCRIPTION from a composite-key table to an ID-only key, which means duplicate unsubscribe rows can now be recorded for the same logical webhook entry. Please retain the previous composite business key as a UNIQUE constraint.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/postgresql.sql`
around lines 2829 - 2839, The CREATE TABLE for AM_WEBHOOKS_UNSUBSCRIPTION
replaced the previous composite business key with a surrogate ID and thus lost
uniqueness; restore the original composite uniqueness by adding a UNIQUE
constraint (or unique index) on the combination of API_UUID, APPLICATION_ID,
TENANT_DOMAIN, HUB_CALLBACK_URL and HUB_TOPIC in the AM_WEBHOOKS_UNSUBSCRIPTION
definition (or immediately after creation) so the table keeps the old
business-key uniqueness while still having the ID primary key.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql`:
- Around line 2639-2650: Add a UNIQUE constraint on the natural key for
AM_WEBHOOKS_UNSUBSCRIPTION to prevent duplicate unsubscription rows; modify the
CREATE TABLE for AM_WEBHOOKS_UNSUBSCRIPTION to include a UNIQUE(...) index
covering (API_UUID, APPLICATION_ID, TENANT_DOMAIN, HUB_CALLBACK_URL, HUB_TOPIC)
and apply the same change to all dialect-specific SQL files (mysql, oracle,
postgresql, mssql) so updateUnSubscription() cannot insert duplicate requests
for the same webhook.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql`:
- Around line 3825-3836: The AM_WEBHOOKS_UNSUBSCRIPTION table lacks a UNIQUE
constraint on its natural key allowing duplicate unsubscription records; add a
UNIQUE constraint on the natural key columns (API_UUID, APPLICATION_ID,
HUB_CALLBACK_URL, HUB_TOPIC) in the CREATE TABLE definition for
AM_WEBHOOKS_UNSUBSCRIPTION so the DB enforces uniqueness for each unsubscription
event (ensure the constraint name is descriptive, e.g.,
UNQ_AM_WEBHOOKS_UNSUBSCRIPTION_API_APP_CALLBACK_TOPIC).

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql`:
- Around line 3824-3846: Add a UNIQUE constraint on the natural key for
AM_WEBHOOKS_UNSUBSCRIPTION to prevent duplicate unsubscriptions: alter the
AM_WEBHOOKS_UNSUBSCRIPTION table definition to include a UNIQUE constraint/index
over (API_UUID, APPLICATION_ID, HUB_CALLBACK_URL, HUB_TOPIC) so those four
columns are enforced as unique while keeping the surrogate ID (and existing
SEQUENCE/ TRIGGER) unchanged; apply the same change to the corresponding files
for other dialects (oracle_rac.sql, oracle_23c.sql, mysql.sql, postgresql.sql)
using the appropriate dialect-specific syntax for creating a unique
constraint/index.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 88a2e49a-e592-479a-a079-14420bfa1afc

📥 Commits

Reviewing files that changed from the base of the PR and between 7bfd004 and 080861b.

📒 Files selected for processing (9)
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/db2.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mssql.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_rac.sql
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/postgresql.sql

Comment on lines 2639 to 2650
CREATE TABLE IF NOT EXISTS AM_WEBHOOKS_UNSUBSCRIPTION (
ID INTEGER NOT NULL AUTO_INCREMENT,
API_UUID VARCHAR(255) NOT NULL,
APPLICATION_ID VARCHAR(20) NOT NULL,
TENANT_DOMAIN VARCHAR(255) NOT NULL,
HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
HUB_TOPIC VARCHAR(255) NOT NULL,
HUB_SECRET VARCHAR(2048),
HUB_LEASE_SECONDS INTEGER,
ADDED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
ADDED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ID)
)ENGINE=NDB;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the complete webhooks table structure in the SQL file
grep -n "AM_WEBHOOKS" features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql | head -20

Repository: wso2/carbon-apimgt

Length of output: 182


🏁 Script executed:

# Get more context around the webhooks tables
sed -n '2620,2660p' features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql

Repository: wso2/carbon-apimgt

Length of output: 1668


🏁 Script executed:

# Search for code that inserts into or queries AM_WEBHOOKS_UNSUBSCRIPTION
find . -type f \( -name "*.java" -o -name "*.js" -o -name "*.py" \) -exec grep -l "AM_WEBHOOKS_UNSUBSCRIPTION" {} \;

Repository: wso2/carbon-apimgt

Length of output: 184


🏁 Script executed:

# Search for references to webhooks unsubscription in the codebase
rg "WEBHOOKS_UNSUBSCRIPTION" --type java -C 3

Repository: wso2/carbon-apimgt

Length of output: 1492


🏁 Script executed:

# Look for all references to unsubscription processing
rg "WEBHOOKS_UNSUBSCRIPTION|unsubscription" --type java -B 2 -A 5 | head -100

Repository: wso2/carbon-apimgt

Length of output: 9040


🏁 Script executed:

# Check what SQL operations are performed on the unsubscription table
grep -r "AM_WEBHOOKS_UNSUBSCRIPTION" components/ --include="*.java" -B 2 -A 2

Repository: wso2/carbon-apimgt

Length of output: 1073


🏁 Script executed:

# Look for any webhook unsubscription logic or handlers
rg "unsubscribe|Unsubscribe" --type java -l | head -10

Repository: wso2/carbon-apimgt

Length of output: 1308


🏁 Script executed:

# Check for any SQL constraint definitions or indexes on webhook tables in other SQL dialects
find . -name "*.sql" -exec grep -l "WEBHOOKS_UNSUBSCRIPTION" {} \;

Repository: wso2/carbon-apimgt

Length of output: 1317


🏁 Script executed:

# Look at WebhooksDAO to see complete unsubscription processing logic
cat components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/WebhooksDAO.java | grep -A 20 "updateUnSubscription\|ADD_UNSUBSCRIPTION"

Repository: wso2/carbon-apimgt

Length of output: 2553


🏁 Script executed:

# Check for any SELECT queries on unsubscription table
grep -r "AM_WEBHOOKS_UNSUBSCRIPTION" components/ --include="*.java" | grep -i select

Repository: wso2/carbon-apimgt

Length of output: 44


🏁 Script executed:

# Check how unsubscription records are consumed/processed
grep -r "AM_WEBHOOKS_UNSUBSCRIPTION" components/ --include="*.java"

Repository: wso2/carbon-apimgt

Length of output: 284


🏁 Script executed:

# Check MySQL dialect to see if they're different
sed -n '2620,2660p' features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql

Repository: wso2/carbon-apimgt

Length of output: 1748


🏁 Script executed:

# Check Oracle dialect
grep -A 20 "CREATE TABLE.*AM_WEBHOOKS_UNSUBSCRIPTION" features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql

Repository: wso2/carbon-apimgt

Length of output: 927


🏁 Script executed:

# Check PostgreSQL dialect
grep -A 20 "CREATE TABLE.*AM_WEBHOOKS_UNSUBSCRIPTION" features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/postgresql.sql

Repository: wso2/carbon-apimgt

Length of output: 1002


Add a UNIQUE constraint on the natural key columns to prevent duplicate unsubscription requests.

The AM_WEBHOOKS_UNSUBSCRIPTION table stores pending unsubscription requests that are inserted via updateUnSubscription(). Without a UNIQUE constraint on the natural key (API_UUID, APPLICATION_ID, TENANT_DOMAIN, HUB_CALLBACK_URL, HUB_TOPIC), duplicate unsubscription requests can be inserted if the method is called multiple times for the same webhook.

This would lead to duplicate processing attempts being sent to webhook endpoints, causing data integrity issues in webhook lifecycle management. The pattern is consistent across all database dialects (MySQL, Oracle, PostgreSQL).

Proposed fix
 CREATE TABLE IF NOT EXISTS AM_WEBHOOKS_UNSUBSCRIPTION (
             ID INTEGER NOT NULL AUTO_INCREMENT,
             API_UUID VARCHAR(255) NOT NULL,
             APPLICATION_ID VARCHAR(20) NOT NULL,
             TENANT_DOMAIN VARCHAR(255) NOT NULL,
             HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
             HUB_TOPIC VARCHAR(255) NOT NULL,
             HUB_SECRET VARCHAR(2048),
             HUB_LEASE_SECONDS INTEGER,
             ADDED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-            PRIMARY KEY (ID)
+            PRIMARY KEY (ID),
+            UNIQUE (API_UUID, APPLICATION_ID, TENANT_DOMAIN, HUB_CALLBACK_URL, HUB_TOPIC)
 )ENGINE=NDB;

Apply the same fix to all SQL dialect files (mysql.sql, oracle.sql, postgresql.sql, mssql.sql, etc.).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql`
around lines 2639 - 2650, Add a UNIQUE constraint on the natural key for
AM_WEBHOOKS_UNSUBSCRIPTION to prevent duplicate unsubscription rows; modify the
CREATE TABLE for AM_WEBHOOKS_UNSUBSCRIPTION to include a UNIQUE(...) index
covering (API_UUID, APPLICATION_ID, TENANT_DOMAIN, HUB_CALLBACK_URL, HUB_TOPIC)
and apply the same change to all dialect-specific SQL files (mysql, oracle,
postgresql, mssql) so updateUnSubscription() cannot insert duplicate requests
for the same webhook.

Comment on lines 3825 to +3836
CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION (
ID INTEGER NOT NULL,
API_UUID VARCHAR(255) NOT NULL,
APPLICATION_ID VARCHAR(20) NOT NULL,
TENANT_DOMAIN VARCHAR(255) NOT NULL,
HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
HUB_TOPIC VARCHAR(255) NOT NULL,
HUB_SECRET VARCHAR(2048),
HUB_LEASE_SECONDS INTEGER,
ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ID))
/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check AM_WEBHOOKS_UNSUBSCRIPTION definition across all SQL dialect files for UNIQUE constraints
for f in $(fd -e sql . features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/); do
  echo "=== $f ==="
  awk '/CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION/,/^[\/;]/' "$f" | head -20
done

Repository: wso2/carbon-apimgt

Length of output: 3839


🏁 Script executed:

#!/bin/bash
# Check IDN_OAUTH2_TOKEN_BINDING and AM_API_REVISION_METADATA in oracle_23c.sql
echo "=== Checking IDN_OAUTH2_TOKEN_BINDING ==="
grep -A 20 "CREATE TABLE IDN_OAUTH2_TOKEN_BINDING" features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql

echo ""
echo "=== Checking AM_API_REVISION_METADATA ==="
grep -A 20 "CREATE TABLE AM_API_REVISION_METADATA" features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql

Repository: wso2/carbon-apimgt

Length of output: 1790


🏁 Script executed:

#!/bin/bash
# Search for any UNIQUE constraints in the AM_WEBHOOKS_UNSUBSCRIPTION region
echo "=== Full AM_WEBHOOKS_UNSUBSCRIPTION + surrounding context ==="
sed -n '3820,3850p' features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql

Repository: wso2/carbon-apimgt

Length of output: 1229


🏁 Script executed:

#!/bin/bash
# Check if other dialect files have UNIQUE constraints on AM_WEBHOOKS_UNSUBSCRIPTION
echo "=== Checking for UNIQUE constraints in AM_WEBHOOKS_UNSUBSCRIPTION across all dialects ==="
for f in features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/{oracle,mysql,postgresql,mssql}.sql; do
  if [ -f "$f" ]; then
    echo "File: $(basename $f)"
    awk '/CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION/,/^[\/;]/' "$f" | grep -i unique && echo "Found UNIQUE" || echo "No UNIQUE constraint"
  fi
done

Repository: wso2/carbon-apimgt

Length of output: 971


🏁 Script executed:

#!/bin/bash
# Check recent commits affecting oracle_23c.sql for AM_WEBHOOKS_UNSUBSCRIPTION
git log --oneline -20 -- features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql

echo ""
echo "=== Checking for recent changes to AM_WEBHOOKS_UNSUBSCRIPTION ==="
git log -p --follow -- features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql | grep -A 20 -B 5 "AM_WEBHOOKS_UNSUBSCRIPTION" | head -50

Repository: wso2/carbon-apimgt

Length of output: 211


🏁 Script executed:

#!/bin/bash
# Search for any mention of webhook unsubscription schema changes
git log --all --grep="webhook" --grep="unsubscription" --grep="composite.*key" -i --oneline | head -10

Repository: wso2/carbon-apimgt

Length of output: 842


🏁 Script executed:

#!/bin/bash
# Get the diff for the commit that added primary keys
git show 080861bb5f3 -- features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql | grep -A 30 -B 5 "AM_WEBHOOKS_UNSUBSCRIPTION"

Repository: wso2/carbon-apimgt

Length of output: 2019


🏁 Script executed:

#!/bin/bash
# Alternative: check if there's an older version without PRIMARY KEY
git show 080861bb5f3^:features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql 2>/dev/null | grep -A 15 "CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION"

Repository: wso2/carbon-apimgt

Length of output: 44


Missing UNIQUE constraint on natural key may allow duplicate unsubscription records.

While this table is newly created (not refactored from a previous composite key), it lacks a UNIQUE constraint on its natural key unlike similar tables in the same file (IDN_OAUTH2_TOKEN_BINDING has UNIQUE (TOKEN_ID, TOKEN_BINDING_TYPE, TOKEN_BINDING_VALUE) and AM_API_REVISION_METADATA has UNIQUE (API_UUID, REVISION_UUID)). Without such a constraint, the same unsubscription event (same API, application, callback URL, and topic) can be inserted multiple times, potentially causing duplicate processing.

Add a UNIQUE constraint on the columns that form the natural key—likely API_UUID, APPLICATION_ID, HUB_CALLBACK_URL, HUB_TOPIC—to maintain data integrity.

Proposed fix
 CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION (
             ID INTEGER NOT NULL,
             API_UUID VARCHAR(255) NOT NULL,
             APPLICATION_ID VARCHAR(20) NOT NULL,
             TENANT_DOMAIN VARCHAR(255) NOT NULL,
             HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
             HUB_TOPIC VARCHAR(255) NOT NULL,
             HUB_SECRET VARCHAR(2048),
             HUB_LEASE_SECONDS INTEGER,
             ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-            PRIMARY KEY (ID))
+            PRIMARY KEY (ID),
+            UNIQUE (API_UUID, APPLICATION_ID, HUB_CALLBACK_URL, HUB_TOPIC))
📝 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
CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION (
ID INTEGER NOT NULL,
API_UUID VARCHAR(255) NOT NULL,
APPLICATION_ID VARCHAR(20) NOT NULL,
TENANT_DOMAIN VARCHAR(255) NOT NULL,
HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
HUB_TOPIC VARCHAR(255) NOT NULL,
HUB_SECRET VARCHAR(2048),
HUB_LEASE_SECONDS INTEGER,
ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ID))
/
CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION (
ID INTEGER NOT NULL,
API_UUID VARCHAR(255) NOT NULL,
APPLICATION_ID VARCHAR(20) NOT NULL,
TENANT_DOMAIN VARCHAR(255) NOT NULL,
HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
HUB_TOPIC VARCHAR(255) NOT NULL,
HUB_SECRET VARCHAR(2048),
HUB_LEASE_SECONDS INTEGER,
ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ID),
UNIQUE (API_UUID, APPLICATION_ID, HUB_CALLBACK_URL, HUB_TOPIC))
/
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql`
around lines 3825 - 3836, The AM_WEBHOOKS_UNSUBSCRIPTION table lacks a UNIQUE
constraint on its natural key allowing duplicate unsubscription records; add a
UNIQUE constraint on the natural key columns (API_UUID, APPLICATION_ID,
HUB_CALLBACK_URL, HUB_TOPIC) in the CREATE TABLE definition for
AM_WEBHOOKS_UNSUBSCRIPTION so the DB enforces uniqueness for each unsubscription
event (ensure the constraint name is descriptive, e.g.,
UNQ_AM_WEBHOOKS_UNSUBSCRIPTION_API_APP_CALLBACK_TOPIC).

Comment on lines 3824 to 3846
CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION (
ID INTEGER NOT NULL,
API_UUID VARCHAR(255) NOT NULL,
APPLICATION_ID VARCHAR(20) NOT NULL,
TENANT_DOMAIN VARCHAR(255) NOT NULL,
HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
HUB_TOPIC VARCHAR(255) NOT NULL,
HUB_SECRET VARCHAR(2048),
HUB_LEASE_SECONDS INTEGER,
ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ID))
/
CREATE SEQUENCE AM_WEBHOOKS_UNSUBSCRIPTION_SEQ START WITH 1 INCREMENT BY 1 NOCACHE
/
CREATE OR REPLACE TRIGGER AM_WEBHOOKS_UNSUBSCRIPTION_TRIG
BEFORE INSERT
ON AM_WEBHOOKS_UNSUBSCRIPTION
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT AM_WEBHOOKS_UNSUBSCRIPTION_SEQ.nextval INTO :NEW.ID FROM dual;
END;
/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check other SQL dialect files for this table to see if any have UNIQUE constraints
rg -n "AM_WEBHOOKS_UNSUBSCRIPTION" --type sql -A 15 | head -100

Repository: wso2/carbon-apimgt

Length of output: 12967


Add UNIQUE constraint on natural key columns.

Across all database dialects (PostgreSQL, MySQL, Oracle), the surrogate ID replaces the composite key without preserving uniqueness on the natural key. This allows duplicate unsubscription records for the same webhook (API_UUID, APPLICATION_ID, HUB_CALLBACK_URL, HUB_TOPIC) to be inserted, compromising data integrity.

Proposed fix
 CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION (
             ID INTEGER NOT NULL,
             API_UUID VARCHAR(255) NOT NULL,
             APPLICATION_ID VARCHAR(20) NOT NULL,
             TENANT_DOMAIN VARCHAR(255) NOT NULL,
             HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
             HUB_TOPIC VARCHAR(255) NOT NULL,
             HUB_SECRET VARCHAR(2048),
             HUB_LEASE_SECONDS INTEGER,
             ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-            PRIMARY KEY (ID))
+            PRIMARY KEY (ID),
+            UNIQUE (API_UUID, APPLICATION_ID, HUB_CALLBACK_URL, HUB_TOPIC))

Apply the same fix to all database dialect files: oracle.sql, oracle_rac.sql, oracle_23c.sql, mysql.sql, and postgresql.sql.

📝 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
CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION (
ID INTEGER NOT NULL,
API_UUID VARCHAR(255) NOT NULL,
APPLICATION_ID VARCHAR(20) NOT NULL,
TENANT_DOMAIN VARCHAR(255) NOT NULL,
HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
HUB_TOPIC VARCHAR(255) NOT NULL,
HUB_SECRET VARCHAR(2048),
HUB_LEASE_SECONDS INTEGER,
ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ID))
/
CREATE SEQUENCE AM_WEBHOOKS_UNSUBSCRIPTION_SEQ START WITH 1 INCREMENT BY 1 NOCACHE
/
CREATE OR REPLACE TRIGGER AM_WEBHOOKS_UNSUBSCRIPTION_TRIG
BEFORE INSERT
ON AM_WEBHOOKS_UNSUBSCRIPTION
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT AM_WEBHOOKS_UNSUBSCRIPTION_SEQ.nextval INTO :NEW.ID FROM dual;
END;
/
CREATE TABLE AM_WEBHOOKS_UNSUBSCRIPTION (
ID INTEGER NOT NULL,
API_UUID VARCHAR(255) NOT NULL,
APPLICATION_ID VARCHAR(20) NOT NULL,
TENANT_DOMAIN VARCHAR(255) NOT NULL,
HUB_CALLBACK_URL VARCHAR(1024) NOT NULL,
HUB_TOPIC VARCHAR(255) NOT NULL,
HUB_SECRET VARCHAR(2048),
HUB_LEASE_SECONDS INTEGER,
ADDED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ID),
UNIQUE (API_UUID, APPLICATION_ID, HUB_CALLBACK_URL, HUB_TOPIC))
/
CREATE SEQUENCE AM_WEBHOOKS_UNSUBSCRIPTION_SEQ START WITH 1 INCREMENT BY 1 NOCACHE
/
CREATE OR REPLACE TRIGGER AM_WEBHOOKS_UNSUBSCRIPTION_TRIG
BEFORE INSERT
ON AM_WEBHOOKS_UNSUBSCRIPTION
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT AM_WEBHOOKS_UNSUBSCRIPTION_SEQ.nextval INTO :NEW.ID FROM dual;
END;
/
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql`
around lines 3824 - 3846, Add a UNIQUE constraint on the natural key for
AM_WEBHOOKS_UNSUBSCRIPTION to prevent duplicate unsubscriptions: alter the
AM_WEBHOOKS_UNSUBSCRIPTION table definition to include a UNIQUE constraint/index
over (API_UUID, APPLICATION_ID, HUB_CALLBACK_URL, HUB_TOPIC) so those four
columns are enforced as unique while keeping the surrogate ID (and existing
SEQUENCE/ TRIGGER) unchanged; apply the same change to the corresponding files
for other dialects (oracle_rac.sql, oracle_23c.sql, mysql.sql, postgresql.sql)
using the appropriate dialect-specific syntax for creating a unique
constraint/index.

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.

2 participants