diff --git a/spec/migrator/create_table_statement_spec.cr b/spec/migrator/create_table_statement_spec.cr index 93a1b35db..c11471f1b 100644 --- a/spec/migrator/create_table_statement_spec.cr +++ b/spec/migrator/create_table_statement_spec.cr @@ -74,6 +74,41 @@ describe Avram::Migrator::CreateTableStatement do SQL end + it "can create tables with composite primary keys" do + built = Avram::Migrator::CreateTableStatement.new(:users).build do + add id1 : Int64 + add id2 : UUID + composite_primary_key :id1, :id2 + end + + built.statements.size.should eq 1 + built.statements.first.should eq <<-SQL + CREATE TABLE users ( + id1 bigint NOT NULL, + id2 uuid NOT NULL, + PRIMARY KEY (id1, id2)); + SQL + end + + it "can create tables with composite primary keys with primary key constraint at end" do + built = Avram::Migrator::CreateTableStatement.new(:users).build do + add id1 : Int64 + add id2 : UUID + composite_primary_key :id1, :id2 + + add example : String + end + + built.statements.size.should eq 1 + built.statements.first.should eq <<-SQL + CREATE TABLE users ( + id1 bigint NOT NULL, + id2 uuid NOT NULL, + example text NOT NULL, + PRIMARY KEY (id1, id2)); + SQL + end + it "sets default values" do built = Avram::Migrator::CreateTableStatement.new(:users).build do add name : String, default: "name" @@ -174,6 +209,22 @@ describe Avram::Migrator::CreateTableStatement do built.statements[5].should eq "CREATE INDEX comments_line_item_id_index ON comments USING btree (line_item_id);" end + it "can create tables with association on composite primary keys" do + built = Avram::Migrator::CreateTableStatement.new(:comments).build do + add_belongs_to user : User, on_delete: :cascade + add id2 : Int64 + composite_primary_key :user_id, :id2 + end + + built.statements.size.should eq 2 + built.statements.first.should eq <<-SQL + CREATE TABLE comments ( + user_id bigint NOT NULL REFERENCES users ON DELETE CASCADE, + id2 bigint NOT NULL, + PRIMARY KEY (user_id, id2)); + SQL + end + it "raises error when on_delete strategy is invalid or nil" do expect_raises Exception, "on_delete: :cascad is not supported. Please use :do_nothing, :cascade, :restrict, or :nullify" do Avram::Migrator::CreateTableStatement.new(:users).build do diff --git a/src/avram/migrator/create_table_statement.cr b/src/avram/migrator/create_table_statement.cr index f7dd8957f..7d606bb0c 100644 --- a/src/avram/migrator/create_table_statement.cr +++ b/src/avram/migrator/create_table_statement.cr @@ -6,6 +6,7 @@ class Avram::Migrator::CreateTableStatement include Avram::Migrator::MissingOnDeleteWithBelongsToError private getter rows = [] of String + private getter constraints = [] of String def initialize(@table_name : Symbol) end @@ -55,6 +56,8 @@ class Avram::Migrator::CreateTableStatement String.build do |statement| statement << initial_table_statement statement << rows.join(",\n") + statement << ",\n" if !constraints.empty? + statement << constraints.join(", \n") statement << ");" end end @@ -71,6 +74,13 @@ class Avram::Migrator::CreateTableStatement .build end + macro composite_primary_key(*columns) + {% if columns.size < 2 %} + {% raise "composite_primary_key expected at least two primary keys, instead got #{columns.size}" %} + {% end %} + constraints << " PRIMARY KEY ({{columns.join(", ").id}})" + end + macro add_timestamps add created_at : Time add updated_at : Time