Skip to content

Commit

Permalink
Composite primary key migration (#616)
Browse files Browse the repository at this point in the history
  • Loading branch information
Whaxion authored Jan 21, 2021
1 parent 68d73ea commit fa1ba00
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
51 changes: 51 additions & 0 deletions spec/migrator/create_table_statement_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions src/avram/migrator/create_table_statement.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit fa1ba00

Please sign in to comment.