Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 11, 2025

Description

AlaSQL parsed CASCADE syntax but did not enforce it. Deleting or updating parent rows left child rows orphaned.

Changes

Parser (alasqlparser.jison)

  • Added grammar rules for ON DELETE/UPDATE actions: CASCADE, SET NULL, SET DEFAULT, RESTRICT, NO ACTION
  • Handle CASCADE/RESTRICT as non-reserved literals with runtime validation

Metadata Storage (23table.js, 60createtable.js)

  • Store foreign key relationships in table.foreignKeys[] with action metadata
  • Capture both column-level and table-level foreign key constraints

DELETE Handler (72delete.js)

  • Recursive applyCascadeDeletes() helper for multi-level cascades
  • CASCADE: Delete matching child rows (and grandchildren)
  • SET NULL: Set foreign key columns to NULL (validates NOT NULL constraints)
  • SET DEFAULT: Set to default values (validates NOT NULL without defaults)
  • RESTRICT/NO ACTION: Throw error if child rows exist
  • Use row references instead of indices to avoid invalidation during recursion

UPDATE Handler (74update.js)

  • Pre-check RESTRICT before modifying data
  • CASCADE: Update child foreign keys when parent primary key changes
  • SET NULL/SET DEFAULT: Same validation as DELETE
  • Only triggers when primary key columns are modified

Example

alasql('CREATE TABLE parent (id INT PRIMARY KEY)');
alasql('CREATE TABLE child (id INT, parent_id INT, ' +
       'FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE)');

alasql('INSERT INTO parent VALUES (1), (2)');
alasql('INSERT INTO child VALUES (10, 1), (11, 1), (20, 2)');

alasql('DELETE FROM parent WHERE id = 1');
// child rows 10 and 11 automatically deleted
alasql('SELECT * FROM child'); // Returns [{id: 20, parent_id: 2}]

Testing

Added test/test897.js with 12 test cases covering all CASCADE actions, recursive cascades, and constraint violations.

Original prompt

This section details on the original issue you should resolve

<issue_title>Implement CASCADE behavior enforcement for FOREIGN KEY constraints</issue_title>
<issue_description>AlaSQL currently parses CASCADE syntax but does not enforce the behavior. When a parent row is deleted or updated, child rows with ON DELETE CASCADE or ON UPDATE CASCADE are not automatically affected.

What needs to be implemented

ON DELETE actions:

  • CASCADE: When a row in the parent table is deleted, automatically delete all rows in child tables that reference it
  • SET NULL: Set foreign key columns to NULL in child tables when parent is deleted
  • SET DEFAULT: Set foreign key columns to their default value when parent is deleted
  • RESTRICT: Prevent deletion of parent row if child rows exist
  • NO ACTION: Same as RESTRICT per SQL-99 standard

ON UPDATE actions:

  • CASCADE: When parent key is updated, update matching foreign keys in child tables
  • SET NULL: Set foreign key to NULL when parent key is updated
  • SET DEFAULT: Set foreign key to default when parent key is updated
  • RESTRICT: Prevent update of parent key if child rows exist
  • NO ACTION: Same as RESTRICT per SQL-99 standard

Implementation areas

  • Modify DELETE statement handler (src/74delete.js) to check for child tables and apply CASCADE actions
  • Modify UPDATE statement handler (src/74update.js) to check for child tables and apply CASCADE actions
  • Store foreign key metadata including ondelete/onupdate actions in table definition during CREATE TABLE
  • Add validation for RESTRICT actions before allowing delete/update
  • Handle circular dependencies and prevent infinite loops

Related

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 4 commits December 11, 2025 02:30
- Updated parser to support ON DELETE/UPDATE CASCADE, SET NULL, SET DEFAULT, RESTRICT, NO ACTION
- Added foreignKeys array to Table structure to track relationships
- Implemented CASCADE delete in delete handler
- Implemented CASCADE update in update handler
- Added comprehensive test suite with 11 passing tests

Co-authored-by: mathiasrw <[email protected]>
- Refactor CASCADE delete into reusable helper function
- Implement recursive CASCADE for grandchild rows
- Add NOT NULL constraint checks for SET NULL and SET DEFAULT
- Remove unused circular dependency tracking code
- Add test for recursive CASCADE behavior

Co-authored-by: mathiasrw <[email protected]>
- Store row references instead of indices to avoid invalidation after recursive deletes
- Simplify delete operation to call table.delete before setting newtable
- Ensures correct behavior when CASCADE operations modify child arrays

Co-authored-by: mathiasrw <[email protected]>
Copilot AI changed the title [WIP] Enforce CASCADE behavior for foreign key constraints Implement CASCADE behavior enforcement for FOREIGN KEY constraints Dec 11, 2025
Copilot AI requested a review from mathiasrw December 11, 2025 02:46
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.

Implement CASCADE behavior enforcement for FOREIGN KEY constraints

2 participants