Skip to content

Commit

Permalink
Merge pull request #277 from imdrasil/make_some_on_action_tweaks
Browse files Browse the repository at this point in the history
Adjust migration ON ACTION functionality
  • Loading branch information
imdrasil committed Oct 19, 2019
2 parents 73a94a1 + fcde3db commit 6f392d7
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 27 deletions.
4 changes: 2 additions & 2 deletions spec/adapter/schema_processor_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ describe Jennifer::Adapter::SchemaProcessor do

describe "#add_foreign_key" do
it do
match_query_from_exception(/ALTER TABLE from_table ADD CONSTRAINT name FOREIGN KEY \(column\) REFERENCES to_table\(primary_key\)/) do
processor.add_foreign_key("from_table", "to_table", "column", "primary_key", "name")
match_query_from_exception(/ALTER TABLE from_table ADD CONSTRAINT name FOREIGN KEY \(column\) REFERENCES to_table\(primary_key\) ON UPDATE RESTRICT ON DELETE NO ACTION/) do
processor.add_foreign_key("from_table", "to_table", "column", "primary_key", "name", :restrict, :no_action)
end
end
end
Expand Down
23 changes: 19 additions & 4 deletions spec/migration/table_builder/create_foreign_key_spec.cr
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
require "./spec_helper"

module H
def self.create_foreign_key(table = DEFAULT_TABLE, to_table = "to_tables", column = nil, primary = nil,
name = nil, on_update = :restrict, on_delete = :restrict)
Jennifer::Migration::TableBuilder::CreateForeignKey.new(
Jennifer::Adapter.adapter,
table,
to_table,
column,
primary,
name,
on_update,
on_delete
)
end
end

describe Jennifer::Migration::TableBuilder::CreateForeignKey do
described_class = Jennifer::Migration::TableBuilder::CreateForeignKey
adapter = Jennifer::Adapter.adapter

describe ".new" do
context "with nil value of column" do
it do
command = described_class.new(adapter, DEFAULT_TABLE, "to_tables", nil, "primary", "name")
command = H.create_foreign_key(primary: "primary", name: "name")
command.primary_key.should eq("primary")
command.name.should eq("name")
command.column.should eq("to_table_id")
Expand All @@ -16,7 +31,7 @@ describe Jennifer::Migration::TableBuilder::CreateForeignKey do

context "with nil value of primary_key" do
it do
command = described_class.new(adapter, DEFAULT_TABLE, "to_tables", "column", nil, "name")
command = H.create_foreign_key(column: "column", name: "name")
command.primary_key.should eq("id")
command.name.should eq("name")
command.column.should eq("column")
Expand All @@ -25,7 +40,7 @@ describe Jennifer::Migration::TableBuilder::CreateForeignKey do

context "with nil value of name" do
it do
command = described_class.new(adapter, DEFAULT_TABLE, "to_tables", "column", "primary", nil)
command = H.create_foreign_key(column: "column", primary: "primary")
command.primary_key.should eq("primary")
command.name.should eq("fk_cr_81338c9f68")
command.column.should eq("column")
Expand Down
17 changes: 10 additions & 7 deletions src/jennifer/adapter/schema_processor.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ require "../migration/table_builder/*"
module Jennifer
module Adapter
abstract class SchemaProcessor
ON_EVENT_ACTIONS = {
:no_action => "NO ACTION",
:restrict => "RESTRICT",
:cascade => "CASCADE",
:set_null => "SET NULL"
}

# :nodoc:
macro unsupported_method(*names)
{% for name in names %}
Expand Down Expand Up @@ -104,18 +111,14 @@ module Jennifer
adapter.exec buff
end

def add_foreign_key(from_table, to_table, column, primary_key, name, *, on_update = nil, on_delete = nil)
def add_foreign_key(from_table, to_table, column, primary_key, name, on_update, on_delete)
query = String.build do |s|
s << "ALTER TABLE " << from_table
s << " ADD CONSTRAINT " << name
s << " FOREIGN KEY (" << column << ") REFERENCES "
s << to_table << "(" << primary_key << ")"
if on_update
s << " ON UPDATE " << on_update
end
if on_delete
s << " ON DELETE " << on_delete
end
s << " ON UPDATE " << ON_EVENT_ACTIONS[on_update]
s << " ON DELETE " << ON_EVENT_ACTIONS[on_delete]
end
adapter.exec query
end
Expand Down
31 changes: 26 additions & 5 deletions src/jennifer/migration/base.cr
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,16 @@ module Jennifer
# By default it is executed under a transaction.
abstract def down

# Specify whether `#up`, `#down`, `#after_up_failure` and `#after_up_failure` should be wrapped into a transaction.
# Specify whether `#up`, `#down`, `#after_up_failure` and `#after_up_failure`
# should be wrapped into a transaction.
#
# `true` by default.
def self.with_transaction(value : Bool)
@@with_transaction = value
end

# Returns whether `#up`, `#down`, `#after_up_failure` and `#after_up_failure` are wrapped into a transaction.
# Returns whether `#up`, `#down`, `#after_up_failure` and `#after_up_failure`
# are wrapped into a transaction.
def self.with_transaction?
@@with_transaction
end
Expand Down Expand Up @@ -381,7 +383,7 @@ module Jennifer
# * `nil` (default)
# * `:unique`
# * `:fulltext` (MySQL only)
# * ``spatial` (MySQL only)
# * `:spatial` (MySQL only)
#
# ```
# add_index(:contacts, :email)
Expand Down Expand Up @@ -488,10 +490,29 @@ module Jennifer
# ```
# add_foreign_key(:comments, :posts, name: "comments_posts_fk")
# ```
#
# Specify `ON DELETE` or `ON UPDATE` action:
#
# ```
# add_foreign_key(:comments, :posts, on_delete: :cascade)
# ```
#
# Supported values: `:no_action`, `:restrict` (default), `:cascade`, `:set_null`.
def add_foreign_key(from_table : String | Symbol, to_table : String | Symbol, column : String | Symbol? = nil,
primary_key : String | Symbol? = nil, name : String? = nil)
primary_key : String | Symbol? = nil, name : String? = nil,
on_update : Symbol = TableBuilder::Base::DEFAULT_ON_EVENT_ACTION,
on_delete : Symbol = TableBuilder::Base::DEFAULT_ON_EVENT_ACTION)
process_builder(
TableBuilder::CreateForeignKey.new(adapter, from_table.to_s, to_table.to_s, column, primary_key, name)
TableBuilder::CreateForeignKey.new(
adapter,
from_table.to_s,
to_table.to_s,
column,
primary_key,
name,
on_update,
on_delete
)
)
end

Expand Down
6 changes: 6 additions & 0 deletions src/jennifer/migration/table_builder/base.cr
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ module Jennifer
# Hash type for options argument
alias DB_OPTIONS = Hash(Symbol, EAllowedTypes | Array(EAllowedTypes))

DEFAULT_ON_EVENT_ACTION = :restrict

delegate schema_processor, table_exists?, index_exists?, column_exists?, to: adapter

getter adapter : Adapter::Base, name : String
Expand All @@ -20,9 +22,13 @@ module Jennifer
@commands = [] of Base
end

# Invokes current command.
abstract def process

# Returns string presentation of invoked changes.
abstract def explain

# Invokes underlying commands.
def process_commands
@commands.each(&.process)
end
Expand Down
14 changes: 12 additions & 2 deletions src/jennifer/migration/table_builder/change_table.cr
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,18 @@ module Jennifer
# Creates a foreign key constraint to `to_table` table.
#
# For more details see `Migration::Base#add_foreign_key`.
def add_foreign_key(to_table : String | Symbol, column = nil, primary_key = nil, name = nil)
@commands << CreateForeignKey.new(@adapter, @name, to_table.to_s, column, primary_key, name)
def add_foreign_key(to_table : String | Symbol, column = nil, primary_key = nil, name = nil, *,
on_update : Symbol = DEFAULT_ON_EVENT_ACTION, on_delete : Symbol = DEFAULT_ON_EVENT_ACTION)
@commands << CreateForeignKey.new(
@adapter,
@name,
to_table.to_s,
column,
primary_key,
name,
on_update,
on_delete
)
self
end

Expand Down
6 changes: 3 additions & 3 deletions src/jennifer/migration/table_builder/create_foreign_key.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ module Jennifer
module Migration
module TableBuilder
class CreateForeignKey < Base
getter from_table : String, to_table : String, column : String, primary_key : String, on_update : String?, on_delete : String?
getter from_table : String, to_table : String, column : String, primary_key : String, on_update : Symbol, on_delete : Symbol

def initialize(adapter, @from_table, @to_table, column, primary_key, name, *, @on_update = nil, @on_delete = nil)
def initialize(adapter, @from_table, @to_table, column, primary_key, name, @on_update, @on_delete)
@column = self.class.column_name(@to_table, column)
@primary_key = (primary_key || "id").to_s
super(adapter, self.class.foreign_key_name(@from_table, @column, name))
end

def process
schema_processor.add_foreign_key(from_table, to_table, column, primary_key, name, on_update: @on_update, on_delete: @on_delete)
schema_processor.add_foreign_key(from_table, to_table, column, primary_key, name, on_update, on_delete)
end

def explain
Expand Down
18 changes: 14 additions & 4 deletions src/jennifer/migration/table_builder/create_table.cr
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ module Jennifer
options[:column]?.as(String | Symbol?),
options[:primary_key]?.as(String | Symbol?),
options[:key_name]?.as(String?),
on_update: options[:on_update]?.as(String?),
on_delete: options[:on_delete]?.as(String?),
on_update: options[:on_update]?.as(Symbol?) || DEFAULT_ON_EVENT_ACTION,
on_delete: options[:on_delete]?.as(Symbol?) || DEFAULT_ON_EVENT_ACTION,
)
end
self
Expand Down Expand Up @@ -155,8 +155,18 @@ module Jennifer
# Creates a foreign key constraint to `to_table` table.
#
# For more details see `Migration::Base#add_foreign_key`.
def foreign_key(to_table : String | Symbol, column = nil, primary_key = nil, name = nil, *, on_update = nil, on_delete = nil)
@commands << CreateForeignKey.new(@adapter, @name, to_table.to_s, column, primary_key, name, on_update: on_update, on_delete: on_delete)
def foreign_key(to_table : String | Symbol, column = nil, primary_key = nil, name = nil, *,
on_update : Symbol = DEFAULT_ON_EVENT_ACTION, on_delete : Symbol = DEFAULT_ON_EVENT_ACTION)
@commands << CreateForeignKey.new(
@adapter,
@name,
to_table.to_s,
column,
primary_key,
name,
on_update,
on_delete
)
self
end
end
Expand Down

0 comments on commit 6f392d7

Please sign in to comment.