discourse/migrations/lib/database/schema
Selase Krakani 99ace1be12
Some checks failed
Tests / core system (push) Has been cancelled
Tests / plugins system (push) Has been cancelled
Licenses / run (push) Has been cancelled
Linting / run (push) Has been cancelled
Migration Tests / Tests (push) Has been cancelled
Publish Assets / publish-assets (push) Has been cancelled
Tests / core backend (push) Has been cancelled
Tests / plugins backend (push) Has been cancelled
Tests / core frontend (Chrome) (push) Has been cancelled
Tests / plugins frontend (push) Has been cancelled
Tests / themes frontend (push) Has been cancelled
Tests / themes system (push) Has been cancelled
Tests / core frontend (Firefox ESR) (push) Has been cancelled
Tests / core frontend (Firefox Evergreen) (push) Has been cancelled
Tests / chat system (push) Has been cancelled
Tests / merge (push) Has been cancelled
DEV: Add support for table-level constraints (#34739)
Allow table-level check constraints in the Intermediate DB


In https://github.com/discourse/discourse/pull/34339, I’ve worked on
distinguishing between `user_custom_fields` tied to `user_fields` and
arbitrary `user_custom_fields` entries.

To support this, I’ve made both `field_id` and `name` nullable, which
requires a table-level constraint to ensure each entry has either a
`field_id` (referencing `user_fields`) or an arbitrary `name` for the
value.

This first pass supports only named  table-level `CHECK` constraints.

## Usage

```yaml
user_custom_fields:
      columns:
        exclude:
          - "id"
        modify:
          - name: "name"
            nullable: true
        add:
          - name: "field_id"
            datatype: numeric
          - name: "is_multiselect_field"
            datatype: boolean
      indexes:
      # ...
      constraints:
        - name: "require_field_id_or_name"
          condition: "field_id IS NOT NULL OR name IS NOT NULL"
        - name: "disallow_both_field_id_and_name"
          type: check      # default, only `check` supported for now
          condition: "NOT (field_id IS NOT NULL AND name IS NOT NULL)"
```



```sql
CREATE TABLE user_custom_fields
(
    created_at           DATETIME,
    field_id             NUMERIC,
    is_multiselect_field BOOLEAN,
    name                 TEXT,
    user_id              NUMERIC  NOT NULL,
    value                TEXT,
    CONSTRAINT require_field_id_or_name CHECK (field_id IS NOT NULL OR name IS NOT NULL),
    CONSTRAINT disallow_both_field_id_and_name CHECK (NOT (field_id IS NOT NULL AND name IS NOT NULL))
);
```
2025-09-12 20:14:51 +00:00
..
validation
config_validator.rb
global_config.rb DEV: Support nullable column property modification (#32978) 2025-06-01 22:39:18 +00:00
loader.rb DEV: Add support for table-level constraints (#34739) 2025-09-12 20:14:51 +00:00
model_writer.rb DEV: Make SQL constant in IntermediateDB models private (#34610) 2025-08-28 18:12:01 +02:00
table_writer.rb DEV: Add support for table-level constraints (#34739) 2025-09-12 20:14:51 +00:00