morphismtech / squeal

Squeal, a deep embedding of SQL in Haskell
350 stars 32 forks source link

Tables referenced by Foreign Keys are not scoped by a Schema #222

Closed SamuelSchlesinger closed 4 years ago

SamuelSchlesinger commented 4 years ago
type BookCols = '[ "id" ::: 'NoDef :=> 'NotNull 'PGint8 ]

type BookCons = '[ "pk_book" ::: 'PrimaryKey '["id"] ]

type ReviewCols = '[ "book" ::: 'NoDef :=> 'NotNull 'PGint8 ]

type ReviewCons = '[ "fk_book" ::: 'ForeignKey '["book"] "books" '["id"] ]

type Schemas =
  '[ "public" ::: '[]
   , "bookstore" ::: '[ "books" ::: 'Table (BookCons :=> BookCols)
                      , "reviews" ::: 'Table (ReviewCons :=> ReviewCols)
                      ]
   ]

mig :: Migration (IsoQ Definition) '["public" ::: '[]] Schemas
mig = Migration "Bookstore" IsoQ{..} where
  up :: Definition '["public" ::: '[]] Schemas
  up = createSchema #bookstore
   >>> createTable (#bookstore ! #books)
       (notNullable int8 `as` #id)
       (primaryKey #id `as` #pk_book)
   >>> createTable (#bookstore ! #reviews)
       (notNullable int8 `as` #book)
       (foreignKey #book #books #id OnDeleteCascade OnUpdateRestrict `as` #fk_book)
  down = dropSchemaCascade #bookstore

When you run printSQL (up . migration $ mig) you get:

CREATE SCHEMA "bookstore";
CREATE TABLE "bookstore"."books" ("id" int8 NOT NULL, CONSTRAINT "pk_book" PRIMARY KEY ("id"));
CREATE TABLE "bookstore"."reviews" ("book" int8 NOT NULL, CONSTRAINT "fk_book" FOREIGN KEY ("book") REFERENCES "books" ("id") ON DELETE CASCADE ON UPDATE RESTRICT);

This is expected behavior, but not valid, because "books" does not exist, only "bookstore"."books". The expected fix is for ForeignKey constraints to have the tables they reference scoped by schemas at the type level and the term level.

echatav commented 4 years ago

Hopefully #223 addressed this. Want to check?