volatiletech/sqlboiler-sqlite3

Unique partial indexes not handled correctly

vortura opened this issue · 0 comments

Hi,

I believe there is a problem with code generation for tables that have unique partial indexes defined. Where such an index is defined, the whole column is treated as being unique when it is really just the contents of the index that are unique. Because the column is considered unique, if that column is a foreign key, the referenced table will have a one-to-one relation to the table with the index, not a one-to-many relationship.

Consider the following schema:

CREATE TABLE team(
    team_id INTEGER PRIMARY KEY,
    name    TEXT
);

CREATE TABLE person(
      person_id       INTEGER PRIMARY KEY,
      team_id         INTEGER REFERENCES team(team_id),
      is_team_leader  BOOLEAN
);

CREATE UNIQUE INDEX team_leader ON person(team_id) WHERE is_team_leader;

So there's a one to many relationship betwen team and person, but there's also a unique partial index allowing for exactly one team leader per team determined by the is_team_leader column on person. The generated code however, treats the relationship between team and person as one-to-one:

○ sqlboiler --wipe sqlite3 -d | jq .tables
using driver: /Users/richard/working/go/bin/sqlboiler-sqlite3
[
  {
    "name": "person",
    "schema_name": "",
    "columns": [
      {
        "name": "person_id",
        "type": "null.Int64",
        "db_type": "INTEGER",
        "default": "auto_increment",
        "comment": "",
        "nullable": true,
        "unique": false,
        "validated": false,
        "arr_type": null,
        "udt_name": "",
        "domain_name": null,
        "full_db_type": "INTEGER",
        "auto_generated": false
      },
      {
        "name": "team_id",
        "type": "null.Int64",
        "db_type": "INTEGER",
        "default": "",
        "comment": "",
        "nullable": true,
        "unique": true,
        "validated": false,
        "arr_type": null,
        "udt_name": "",
        "domain_name": null,
        "full_db_type": "INTEGER",
        "auto_generated": false
      },
      {
        "name": "is_team_leader",
        "type": "null.Bool",
        "db_type": "BOOLEAN",
        "default": "",
        "comment": "",
        "nullable": true,
        "unique": false,
        "validated": false,
        "arr_type": null,
        "udt_name": "",
        "domain_name": null,
        "full_db_type": "BOOLEAN",
        "auto_generated": false
      }
    ],
    "p_key": {
      "name": "",
      "columns": [
        "person_id"
      ]
    },
    "f_keys": [
      {
        "table": "person",
        "name": "FK_0",
        "column": "team_id",
        "nullable": true,
        "unique": true,
        "foreign_table": "team",
        "foreign_column": "team_id",
        "foreign_column_nullable": true,
        "foreign_column_unique": false
      }
    ],
    "is_join_table": false,
    "to_one_relationships": null,
    "to_many_relationships": null
  },
  {
    "name": "team",
    "schema_name": "",
    "columns": [
      {
        "name": "team_id",
        "type": "null.Int64",
        "db_type": "INTEGER",
        "default": "auto_increment",
        "comment": "",
        "nullable": true,
        "unique": false,
        "validated": false,
        "arr_type": null,
        "udt_name": "",
        "domain_name": null,
        "full_db_type": "INTEGER",
        "auto_generated": false
      },
      {
        "name": "name",
        "type": "null.String",
        "db_type": "TEXT",
        "default": "",
        "comment": "",
        "nullable": true,
        "unique": false,
        "validated": false,
        "arr_type": null,
        "udt_name": "",
        "domain_name": null,
        "full_db_type": "TEXT",
        "auto_generated": false
      }
    ],
    "p_key": {
      "name": "",
      "columns": [
        "team_id"
      ]
    },
    "f_keys": null,
    "is_join_table": false,
    "to_one_relationships": [
      {
        "name": "FK_0",
        "table": "team",
        "column": "team_id",
        "nullable": true,
        "unique": false,
        "foreign_table": "person",
        "foreign_column": "team_id",
        "foreign_column_nullable": true,
        "foreign_column_unique": true
      }
    ],
    "to_many_relationships": null
  }
]

This means the generated model for Team has no Persons() method to return the members of the team, only a Person() method.

This is on SQLBoiler 4.6.0. I'm not sure if the sqlite driver has a version, but I'm happy to provide that if I can.