fx 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +2 -7
- data/CHANGELOG.md +124 -0
- data/CONTRIBUTING.md +3 -3
- data/Gemfile +12 -1
- data/README.md +2 -0
- data/bin/standardrb +27 -0
- data/fx.gemspec +10 -15
- data/lib/fx/adapters/postgres/connection.rb +12 -0
- data/lib/fx/adapters/postgres/functions.rb +3 -3
- data/lib/fx/adapters/postgres/triggers.rb +3 -3
- data/lib/fx/adapters/postgres.rb +6 -14
- data/lib/fx/command_recorder.rb +87 -6
- data/lib/fx/configuration.rb +0 -25
- data/lib/fx/definition.rb +16 -6
- data/lib/fx/function.rb +3 -3
- data/lib/fx/schema_dumper.rb +45 -5
- data/lib/fx/statements.rb +228 -6
- data/lib/fx/trigger.rb +3 -3
- data/lib/fx/version.rb +1 -1
- data/lib/fx.rb +30 -12
- data/lib/generators/fx/function/function_generator.rb +2 -2
- data/lib/generators/fx/trigger/trigger_generator.rb +1 -5
- data/spec/acceptance/user_manages_functions_spec.rb +4 -4
- data/spec/acceptance/user_manages_triggers_spec.rb +6 -6
- data/spec/acceptance_helper.rb +2 -2
- data/spec/dummy/config/application.rb +5 -1
- data/spec/features/functions/migrations_spec.rb +3 -3
- data/spec/features/functions/revert_spec.rb +3 -3
- data/spec/features/triggers/migrations_spec.rb +4 -4
- data/spec/features/triggers/revert_spec.rb +5 -5
- data/spec/fx/adapters/postgres/functions_spec.rb +26 -30
- data/spec/fx/adapters/postgres/triggers_spec.rb +34 -38
- data/spec/fx/adapters/postgres_spec.rb +107 -109
- data/spec/fx/command_recorder_spec.rb +27 -25
- data/spec/fx/configuration_spec.rb +20 -9
- data/spec/fx/definition_spec.rb +27 -35
- data/spec/fx/function_spec.rb +45 -48
- data/spec/fx/schema_dumper_spec.rb +123 -0
- data/spec/fx/statements_spec.rb +217 -0
- data/spec/fx/trigger_spec.rb +37 -40
- data/spec/fx_spec.rb +28 -0
- data/spec/generators/fx/function/function_generator_spec.rb +3 -3
- data/spec/generators/fx/trigger/trigger_generator_spec.rb +10 -10
- data/spec/spec_helper.rb +5 -0
- data/spec/support/definition_helpers.rb +2 -6
- data/spec/support/warning_helper.rb +5 -0
- metadata +21 -163
- data/lib/fx/command_recorder/arguments.rb +0 -43
- data/lib/fx/command_recorder/function.rb +0 -30
- data/lib/fx/command_recorder/trigger.rb +0 -30
- data/lib/fx/schema_dumper/function.rb +0 -38
- data/lib/fx/schema_dumper/trigger.rb +0 -29
- data/lib/fx/statements/function.rb +0 -113
- data/lib/fx/statements/trigger.rb +0 -144
- data/spec/fx/command_recorder/arguments_spec.rb +0 -41
- data/spec/fx/schema_dumper/function_spec.rb +0 -78
- data/spec/fx/schema_dumper/trigger_spec.rb +0 -40
- data/spec/fx/statements/function_spec.rb +0 -103
- data/spec/fx/statements/trigger_spec.rb +0 -132
data/spec/fx/definition_spec.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
|
|
3
|
-
describe Fx::Definition do
|
|
3
|
+
RSpec.describe Fx::Definition do
|
|
4
4
|
describe "#to_sql" do
|
|
5
5
|
context "representing a function definition" do
|
|
6
6
|
it "returns the content of a function definition" do
|
|
@@ -14,16 +14,18 @@ describe Fx::Definition do
|
|
|
14
14
|
EOS
|
|
15
15
|
allow(File).to receive(:read).and_return(sql_definition)
|
|
16
16
|
|
|
17
|
-
definition = Fx::Definition.
|
|
17
|
+
definition = Fx::Definition.function(name: "test", version: 1)
|
|
18
18
|
|
|
19
|
-
expect(definition.to_sql).to eq
|
|
19
|
+
expect(definition.to_sql).to eq(sql_definition)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
it "raises an error if the file is empty" do
|
|
23
23
|
allow(File).to receive(:read).and_return("")
|
|
24
|
-
definition = Fx::Definition.
|
|
24
|
+
definition = Fx::Definition.function(name: "test", version: 1)
|
|
25
25
|
|
|
26
|
-
expect
|
|
26
|
+
expect do
|
|
27
|
+
definition.to_sql
|
|
28
|
+
end.to raise_error(
|
|
27
29
|
RuntimeError,
|
|
28
30
|
%r{Define function in db/functions/test_v01.sql before migrating}
|
|
29
31
|
)
|
|
@@ -31,7 +33,7 @@ describe Fx::Definition do
|
|
|
31
33
|
|
|
32
34
|
context "when definition is at Rails engine" do
|
|
33
35
|
it "returns the content of a function definition" do
|
|
34
|
-
sql_definition =
|
|
36
|
+
sql_definition = <<~EOS
|
|
35
37
|
CREATE OR REPLACE FUNCTION test()
|
|
36
38
|
RETURNS text AS $$
|
|
37
39
|
BEGIN
|
|
@@ -44,9 +46,9 @@ describe Fx::Definition do
|
|
|
44
46
|
File.write(engine_path.join("db", "functions", "custom_test_v01.sql"), sql_definition)
|
|
45
47
|
Rails.application.config.paths["db/migrate"].push(engine_path.join("db", "migrate"))
|
|
46
48
|
|
|
47
|
-
definition = Fx::Definition.
|
|
49
|
+
definition = Fx::Definition.function(name: "custom_test", version: 1)
|
|
48
50
|
|
|
49
|
-
expect(definition.to_sql).to eq
|
|
51
|
+
expect(definition.to_sql).to eq(sql_definition)
|
|
50
52
|
|
|
51
53
|
FileUtils.rm_rf(engine_path)
|
|
52
54
|
end
|
|
@@ -55,7 +57,7 @@ describe Fx::Definition do
|
|
|
55
57
|
|
|
56
58
|
context "representing a trigger definition" do
|
|
57
59
|
it "returns the content of a trigger definition" do
|
|
58
|
-
sql_definition =
|
|
60
|
+
sql_definition = <<~EOS
|
|
59
61
|
CREATE TRIGGER check_update
|
|
60
62
|
BEFORE UPDATE ON accounts
|
|
61
63
|
FOR EACH ROW
|
|
@@ -63,24 +65,18 @@ describe Fx::Definition do
|
|
|
63
65
|
EOS
|
|
64
66
|
allow(File).to receive(:read).and_return(sql_definition)
|
|
65
67
|
|
|
66
|
-
definition = Fx::Definition.
|
|
67
|
-
name: "test",
|
|
68
|
-
version: 1,
|
|
69
|
-
type: "trigger"
|
|
70
|
-
)
|
|
68
|
+
definition = Fx::Definition.trigger(name: "test", version: 1)
|
|
71
69
|
|
|
72
|
-
expect(definition.to_sql).to eq
|
|
70
|
+
expect(definition.to_sql).to eq(sql_definition)
|
|
73
71
|
end
|
|
74
72
|
|
|
75
73
|
it "raises an error if the file is empty" do
|
|
76
74
|
allow(File).to receive(:read).and_return("")
|
|
77
|
-
definition = Fx::Definition.
|
|
78
|
-
name: "test",
|
|
79
|
-
version: 1,
|
|
80
|
-
type: "trigger"
|
|
81
|
-
)
|
|
75
|
+
definition = Fx::Definition.trigger(name: "test", version: 1)
|
|
82
76
|
|
|
83
|
-
expect
|
|
77
|
+
expect do
|
|
78
|
+
definition.to_sql
|
|
79
|
+
end.to raise_error(
|
|
84
80
|
RuntimeError,
|
|
85
81
|
%r{Define trigger in db/triggers/test_v01.sql before migrating}
|
|
86
82
|
)
|
|
@@ -91,44 +87,40 @@ describe Fx::Definition do
|
|
|
91
87
|
describe "#path" do
|
|
92
88
|
context "representing a function definition" do
|
|
93
89
|
it "returns a sql file with padded version and function name" do
|
|
94
|
-
definition = Fx::Definition.
|
|
90
|
+
definition = Fx::Definition.function(name: "test", version: 1)
|
|
95
91
|
|
|
96
|
-
expect(definition.path).to eq
|
|
92
|
+
expect(definition.path).to eq("db/functions/test_v01.sql")
|
|
97
93
|
end
|
|
98
94
|
end
|
|
99
95
|
|
|
100
96
|
context "representing a trigger definition" do
|
|
101
97
|
it "returns a sql file with padded version and trigger name" do
|
|
102
|
-
definition = Fx::Definition.
|
|
103
|
-
name: "test",
|
|
104
|
-
version: 1,
|
|
105
|
-
type: "trigger"
|
|
106
|
-
)
|
|
98
|
+
definition = Fx::Definition.trigger(name: "test", version: 1)
|
|
107
99
|
|
|
108
|
-
expect(definition.path).to eq
|
|
100
|
+
expect(definition.path).to eq("db/triggers/test_v01.sql")
|
|
109
101
|
end
|
|
110
102
|
end
|
|
111
103
|
end
|
|
112
104
|
|
|
113
105
|
describe "#full_path" do
|
|
114
106
|
it "joins the path with Rails.root" do
|
|
115
|
-
definition = Fx::Definition.
|
|
107
|
+
definition = Fx::Definition.function(name: "test", version: 15)
|
|
116
108
|
|
|
117
|
-
expect(definition.full_path).to eq
|
|
109
|
+
expect(definition.full_path).to eq(Rails.root.join(definition.path))
|
|
118
110
|
end
|
|
119
111
|
end
|
|
120
112
|
|
|
121
113
|
describe "#version" do
|
|
122
114
|
it "pads the version number with 0" do
|
|
123
|
-
definition = Fx::Definition.
|
|
115
|
+
definition = Fx::Definition.function(name: :_, version: 1)
|
|
124
116
|
|
|
125
|
-
expect(definition.version).to eq
|
|
117
|
+
expect(definition.version).to eq("01")
|
|
126
118
|
end
|
|
127
119
|
|
|
128
120
|
it "does not pad more than 2 characters" do
|
|
129
|
-
definition = Fx::Definition.
|
|
121
|
+
definition = Fx::Definition.function(name: :_, version: 15)
|
|
130
122
|
|
|
131
|
-
expect(definition.version).to eq
|
|
123
|
+
expect(definition.version).to eq("15")
|
|
132
124
|
end
|
|
133
125
|
end
|
|
134
126
|
end
|
data/spec/fx/function_spec.rb
CHANGED
|
@@ -1,68 +1,65 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
|
-
require "fx/function"
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
describe
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
)
|
|
3
|
+
RSpec.describe Fx::Function do
|
|
4
|
+
describe "#<=>" do
|
|
5
|
+
it "delegates to `name`" do
|
|
6
|
+
function_a = Fx::Function.new(
|
|
7
|
+
"name" => "name_a",
|
|
8
|
+
"definition" => "some definition"
|
|
9
|
+
)
|
|
10
|
+
function_b = Fx::Function.new(
|
|
11
|
+
"name" => "name_b",
|
|
12
|
+
"definition" => "some definition"
|
|
13
|
+
)
|
|
14
|
+
function_c = Fx::Function.new(
|
|
15
|
+
"name" => "name_c",
|
|
16
|
+
"definition" => "some definition"
|
|
17
|
+
)
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
end
|
|
19
|
+
expect(function_b).to be_between(function_a, function_c)
|
|
23
20
|
end
|
|
21
|
+
end
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
describe "#==" do
|
|
24
|
+
it "compares `name` and `definition`" do
|
|
25
|
+
function_a = Fx::Function.new(
|
|
26
|
+
"name" => "name_a",
|
|
27
|
+
"definition" => "some definition"
|
|
28
|
+
)
|
|
29
|
+
function_b = Fx::Function.new(
|
|
30
|
+
"name" => "name_b",
|
|
31
|
+
"definition" => "some other definition"
|
|
32
|
+
)
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
end
|
|
34
|
+
expect(function_a).not_to eq(function_b)
|
|
38
35
|
end
|
|
36
|
+
end
|
|
39
37
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
describe "#to_schema" do
|
|
39
|
+
it "returns a schema compatible version of the function" do
|
|
40
|
+
function = Fx::Function.new(
|
|
41
|
+
"name" => "uppercase_users_name",
|
|
42
|
+
"definition" => "CREATE OR REPLACE TRIGGER uppercase_users_name ..."
|
|
43
|
+
)
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
expect(function.to_schema).to eq(<<-EOS)
|
|
48
46
|
create_function :uppercase_users_name, sql_definition: <<-'SQL'
|
|
49
47
|
CREATE OR REPLACE TRIGGER uppercase_users_name ...
|
|
50
48
|
SQL
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
EOS
|
|
50
|
+
end
|
|
53
51
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
it "maintains backslashes" do
|
|
53
|
+
function = Fx::Function.new(
|
|
54
|
+
"name" => "regex",
|
|
55
|
+
"definition" => "CREATE OR REPLACE FUNCTION regex \\1"
|
|
56
|
+
)
|
|
59
57
|
|
|
60
|
-
|
|
58
|
+
expect(function.to_schema).to eq(<<-'EOS')
|
|
61
59
|
create_function :regex, sql_definition: <<-'SQL'
|
|
62
60
|
CREATE OR REPLACE FUNCTION regex \1
|
|
63
61
|
SQL
|
|
64
|
-
|
|
65
|
-
end
|
|
62
|
+
EOS
|
|
66
63
|
end
|
|
67
64
|
end
|
|
68
65
|
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
RSpec.describe Fx::SchemaDumper, :db do
|
|
4
|
+
it "dumps a create_function for a function in the database" do
|
|
5
|
+
sql_definition = <<~EOS
|
|
6
|
+
CREATE OR REPLACE FUNCTION my_function()
|
|
7
|
+
RETURNS text AS $$
|
|
8
|
+
BEGIN
|
|
9
|
+
RETURN 'test';
|
|
10
|
+
END;
|
|
11
|
+
$$ LANGUAGE plpgsql;
|
|
12
|
+
EOS
|
|
13
|
+
connection.create_function :my_function, sql_definition: sql_definition
|
|
14
|
+
connection.create_table :my_table
|
|
15
|
+
stream = StringIO.new
|
|
16
|
+
output = stream.string
|
|
17
|
+
|
|
18
|
+
dump(connection: connection, stream: stream)
|
|
19
|
+
|
|
20
|
+
expect(output).to match(
|
|
21
|
+
/table "my_table".*function :my_function.*RETURN 'test';/m
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "dumps a create_function for a function in the database" do
|
|
26
|
+
Fx.configuration.dump_functions_at_beginning_of_schema = true
|
|
27
|
+
sql_definition = <<~EOS
|
|
28
|
+
CREATE OR REPLACE FUNCTION my_function()
|
|
29
|
+
RETURNS text AS $$
|
|
30
|
+
BEGIN
|
|
31
|
+
RETURN 'test';
|
|
32
|
+
END;
|
|
33
|
+
$$ LANGUAGE plpgsql;
|
|
34
|
+
EOS
|
|
35
|
+
connection.create_function :my_function, sql_definition: sql_definition
|
|
36
|
+
connection.create_table :my_table
|
|
37
|
+
stream = StringIO.new
|
|
38
|
+
output = stream.string
|
|
39
|
+
|
|
40
|
+
dump(connection: connection, stream: stream)
|
|
41
|
+
|
|
42
|
+
expect(output).to(
|
|
43
|
+
match(/function :my_function.*RETURN 'test';.*table "my_table"/m)
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
Fx.configuration.dump_functions_at_beginning_of_schema = false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "does not dump a create_function for aggregates in the database" do
|
|
50
|
+
sql_definition = <<~EOS
|
|
51
|
+
CREATE OR REPLACE FUNCTION test(text, text)
|
|
52
|
+
RETURNS text AS $$
|
|
53
|
+
BEGIN
|
|
54
|
+
RETURN 'test';
|
|
55
|
+
END;
|
|
56
|
+
$$ LANGUAGE plpgsql;
|
|
57
|
+
EOS
|
|
58
|
+
|
|
59
|
+
aggregate_sql_definition = <<~EOS
|
|
60
|
+
CREATE AGGREGATE aggregate_test(text)
|
|
61
|
+
(
|
|
62
|
+
sfunc = test,
|
|
63
|
+
stype = text
|
|
64
|
+
);
|
|
65
|
+
EOS
|
|
66
|
+
|
|
67
|
+
connection.create_function :test, sql_definition: sql_definition
|
|
68
|
+
connection.execute aggregate_sql_definition
|
|
69
|
+
stream = StringIO.new
|
|
70
|
+
|
|
71
|
+
dump(connection: connection, stream: stream)
|
|
72
|
+
|
|
73
|
+
output = stream.string
|
|
74
|
+
expect(output).to include("create_function :test, sql_definition: <<-'SQL'")
|
|
75
|
+
expect(output).to include("RETURN 'test';")
|
|
76
|
+
expect(output).not_to include("aggregate_test")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "dumps a create_trigger for a trigger in the database" do
|
|
80
|
+
connection.execute <<~EOS
|
|
81
|
+
CREATE TABLE users (
|
|
82
|
+
id int PRIMARY KEY,
|
|
83
|
+
name varchar(256),
|
|
84
|
+
upper_name varchar(256)
|
|
85
|
+
);
|
|
86
|
+
EOS
|
|
87
|
+
Fx.database.create_function <<~EOS
|
|
88
|
+
CREATE OR REPLACE FUNCTION uppercase_users_name()
|
|
89
|
+
RETURNS trigger AS $$
|
|
90
|
+
BEGIN
|
|
91
|
+
NEW.upper_name = UPPER(NEW.name);
|
|
92
|
+
RETURN NEW;
|
|
93
|
+
END;
|
|
94
|
+
$$ LANGUAGE plpgsql;
|
|
95
|
+
EOS
|
|
96
|
+
sql_definition = <<~EOS
|
|
97
|
+
CREATE TRIGGER uppercase_users_name
|
|
98
|
+
BEFORE INSERT ON users
|
|
99
|
+
FOR EACH ROW
|
|
100
|
+
EXECUTE FUNCTION uppercase_users_name();
|
|
101
|
+
EOS
|
|
102
|
+
connection.create_trigger(
|
|
103
|
+
:uppercase_users_name,
|
|
104
|
+
sql_definition: sql_definition
|
|
105
|
+
)
|
|
106
|
+
stream = StringIO.new
|
|
107
|
+
|
|
108
|
+
dump(connection: connection, stream: stream)
|
|
109
|
+
|
|
110
|
+
output = stream.string
|
|
111
|
+
expect(output).to include("create_trigger :uppercase_users_name")
|
|
112
|
+
expect(output).to include("sql_definition: <<-SQL")
|
|
113
|
+
expect(output).to include("EXECUTE FUNCTION uppercase_users_name()")
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def dump(connection:, stream:)
|
|
117
|
+
if Rails.version >= "7.2"
|
|
118
|
+
ActiveRecord::SchemaDumper.dump(connection.pool, stream)
|
|
119
|
+
else
|
|
120
|
+
ActiveRecord::SchemaDumper.dump(connection, stream)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
RSpec.describe Fx::Statements, :db do
|
|
4
|
+
describe "#create_function" do
|
|
5
|
+
it "creates a function from a file" do
|
|
6
|
+
database = stubbed_database
|
|
7
|
+
definition = stubbed_definition
|
|
8
|
+
|
|
9
|
+
connection.create_function(:test)
|
|
10
|
+
|
|
11
|
+
expect(database).to have_received(:create_function)
|
|
12
|
+
.with(definition.to_sql)
|
|
13
|
+
expect(Fx::Definition).to have_received(:function)
|
|
14
|
+
.with(name: :test, version: 1)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "allows creating a function with a specific version" do
|
|
18
|
+
database = stubbed_database
|
|
19
|
+
definition = stubbed_definition
|
|
20
|
+
|
|
21
|
+
connection.create_function(:test, version: 2)
|
|
22
|
+
|
|
23
|
+
expect(database).to have_received(:create_function)
|
|
24
|
+
.with(definition.to_sql)
|
|
25
|
+
expect(Fx::Definition).to have_received(:function)
|
|
26
|
+
.with(name: :test, version: 2)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "raises an error if both arguments are nil" do
|
|
30
|
+
expect do
|
|
31
|
+
connection.create_function(
|
|
32
|
+
:whatever,
|
|
33
|
+
version: nil,
|
|
34
|
+
sql_definition: nil
|
|
35
|
+
)
|
|
36
|
+
end.to raise_error(
|
|
37
|
+
ArgumentError,
|
|
38
|
+
/version or sql_definition must be specified/
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "#drop_function" do
|
|
44
|
+
it "drops the function" do
|
|
45
|
+
database = stubbed_database
|
|
46
|
+
|
|
47
|
+
connection.drop_function(:test)
|
|
48
|
+
|
|
49
|
+
expect(database).to have_received(:drop_function).with(:test)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe "#update_function" do
|
|
54
|
+
it "updates the function" do
|
|
55
|
+
database = stubbed_database
|
|
56
|
+
definition = stubbed_definition
|
|
57
|
+
|
|
58
|
+
connection.update_function(:test, version: 3)
|
|
59
|
+
|
|
60
|
+
expect(database).to have_received(:update_function)
|
|
61
|
+
.with(:test, definition.to_sql)
|
|
62
|
+
expect(Fx::Definition).to have_received(:function)
|
|
63
|
+
.with(name: :test, version: 3)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "updates a function from a text definition" do
|
|
67
|
+
database = stubbed_database
|
|
68
|
+
|
|
69
|
+
connection.update_function(:test, sql_definition: "a definition")
|
|
70
|
+
|
|
71
|
+
expect(database).to have_received(:update_function)
|
|
72
|
+
.with(:test, "a definition")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "raises an error if not supplied a version" do
|
|
76
|
+
expect do
|
|
77
|
+
connection.update_function(
|
|
78
|
+
:whatever,
|
|
79
|
+
version: nil,
|
|
80
|
+
sql_definition: nil
|
|
81
|
+
)
|
|
82
|
+
end.to raise_error(
|
|
83
|
+
ArgumentError,
|
|
84
|
+
/version or sql_definition must be specified/
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe "#create_trigger" do
|
|
90
|
+
it "creates a trigger from a file" do
|
|
91
|
+
database = stubbed_database
|
|
92
|
+
definition = stubbed_definition
|
|
93
|
+
|
|
94
|
+
connection.create_trigger(:test)
|
|
95
|
+
|
|
96
|
+
expect(database).to have_received(:create_trigger)
|
|
97
|
+
.with(definition.to_sql)
|
|
98
|
+
expect(Fx::Definition).to have_received(:trigger)
|
|
99
|
+
.with(name: :test, version: 1)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "allows creating a trigger with a specific version" do
|
|
103
|
+
database = stubbed_database
|
|
104
|
+
definition = stubbed_definition
|
|
105
|
+
|
|
106
|
+
connection.create_trigger(:test, version: 2)
|
|
107
|
+
|
|
108
|
+
expect(database).to have_received(:create_trigger)
|
|
109
|
+
.with(definition.to_sql)
|
|
110
|
+
expect(Fx::Definition).to have_received(:trigger)
|
|
111
|
+
.with(name: :test, version: 2)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "raises an error if both arguments are set" do
|
|
115
|
+
stubbed_database
|
|
116
|
+
|
|
117
|
+
expect do
|
|
118
|
+
connection.create_trigger(
|
|
119
|
+
:whatever,
|
|
120
|
+
version: 1,
|
|
121
|
+
sql_definition: "a definition"
|
|
122
|
+
)
|
|
123
|
+
end.to raise_error(
|
|
124
|
+
ArgumentError,
|
|
125
|
+
/cannot both be set/
|
|
126
|
+
)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe "#drop_trigger" do
|
|
131
|
+
it "drops the trigger" do
|
|
132
|
+
database = stubbed_database
|
|
133
|
+
|
|
134
|
+
connection.drop_trigger(:test, on: :users)
|
|
135
|
+
|
|
136
|
+
expect(database).to have_received(:drop_trigger)
|
|
137
|
+
.with(:test, on: :users)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
describe "#update_trigger" do
|
|
142
|
+
it "updates the trigger" do
|
|
143
|
+
database = stubbed_database
|
|
144
|
+
definition = stubbed_definition
|
|
145
|
+
|
|
146
|
+
connection.update_trigger(:test, on: :users, version: 3)
|
|
147
|
+
|
|
148
|
+
expect(database).to have_received(:update_trigger).with(
|
|
149
|
+
:test,
|
|
150
|
+
on: :users,
|
|
151
|
+
sql_definition: definition.to_sql
|
|
152
|
+
)
|
|
153
|
+
expect(Fx::Definition).to have_received(:trigger).with(
|
|
154
|
+
name: :test,
|
|
155
|
+
version: 3
|
|
156
|
+
)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "updates a trigger from a text definition" do
|
|
160
|
+
database = stubbed_database
|
|
161
|
+
|
|
162
|
+
connection.update_trigger(
|
|
163
|
+
:test,
|
|
164
|
+
on: :users,
|
|
165
|
+
sql_definition: "a definition"
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
expect(database).to have_received(:update_trigger).with(
|
|
169
|
+
:test,
|
|
170
|
+
on: :users,
|
|
171
|
+
sql_definition: "a definition"
|
|
172
|
+
)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "raises an error if not supplied a version" do
|
|
176
|
+
expect do
|
|
177
|
+
connection.update_trigger(
|
|
178
|
+
:whatever,
|
|
179
|
+
version: nil,
|
|
180
|
+
sql_definition: nil
|
|
181
|
+
)
|
|
182
|
+
end.to raise_error(
|
|
183
|
+
ArgumentError,
|
|
184
|
+
/version or sql_definition must be specified/
|
|
185
|
+
)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
it "raises an error if both arguments are set" do
|
|
189
|
+
stubbed_database
|
|
190
|
+
|
|
191
|
+
expect do
|
|
192
|
+
connection.update_trigger(
|
|
193
|
+
:whatever,
|
|
194
|
+
version: 1,
|
|
195
|
+
sql_definition: "a definition"
|
|
196
|
+
)
|
|
197
|
+
end.to raise_error(
|
|
198
|
+
ArgumentError,
|
|
199
|
+
/cannot both be set/
|
|
200
|
+
)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def stubbed_definition
|
|
205
|
+
instance_double("Fx::Definition", to_sql: nil).tap do |stubbed_definition|
|
|
206
|
+
allow(Fx::Definition).to receive(:function).and_return(stubbed_definition)
|
|
207
|
+
allow(Fx::Definition).to receive(:trigger).and_return(stubbed_definition)
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def stubbed_database
|
|
212
|
+
database = instance_spy("StubbedDatabase")
|
|
213
|
+
allow(Fx).to receive(:database).and_return(database)
|
|
214
|
+
|
|
215
|
+
database
|
|
216
|
+
end
|
|
217
|
+
end
|
data/spec/fx/trigger_spec.rb
CHANGED
|
@@ -1,55 +1,52 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
|
-
require "fx/trigger"
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
describe
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
)
|
|
3
|
+
RSpec.describe Fx::Trigger do
|
|
4
|
+
describe "#<=>" do
|
|
5
|
+
it "delegates to `name`" do
|
|
6
|
+
trigger_a = Fx::Trigger.new(
|
|
7
|
+
"name" => "name_a",
|
|
8
|
+
"definition" => "some definition"
|
|
9
|
+
)
|
|
10
|
+
trigger_b = Fx::Trigger.new(
|
|
11
|
+
"name" => "name_b",
|
|
12
|
+
"definition" => "some definition"
|
|
13
|
+
)
|
|
14
|
+
trigger_c = Fx::Trigger.new(
|
|
15
|
+
"name" => "name_c",
|
|
16
|
+
"definition" => "some definition"
|
|
17
|
+
)
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
end
|
|
19
|
+
expect(trigger_b).to be_between(trigger_a, trigger_c)
|
|
23
20
|
end
|
|
21
|
+
end
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
describe "#==" do
|
|
24
|
+
it "compares `name` and `definition`" do
|
|
25
|
+
trigger_a = Fx::Trigger.new(
|
|
26
|
+
"name" => "name_a",
|
|
27
|
+
"definition" => "some definition"
|
|
28
|
+
)
|
|
29
|
+
trigger_b = Fx::Trigger.new(
|
|
30
|
+
"name" => "name_b",
|
|
31
|
+
"definition" => "some other definition"
|
|
32
|
+
)
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
end
|
|
34
|
+
expect(trigger_a).not_to eq(trigger_b)
|
|
38
35
|
end
|
|
36
|
+
end
|
|
39
37
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
describe "#to_schema" do
|
|
39
|
+
it "returns a schema compatible version of the trigger" do
|
|
40
|
+
trigger = Fx::Trigger.new(
|
|
41
|
+
"name" => "uppercase_users_name",
|
|
42
|
+
"definition" => "CREATE TRIGGER uppercase_users_name ..."
|
|
43
|
+
)
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
expect(trigger.to_schema).to eq(<<-EOS)
|
|
48
46
|
create_trigger :uppercase_users_name, sql_definition: <<-\SQL
|
|
49
47
|
CREATE TRIGGER uppercase_users_name ...
|
|
50
48
|
SQL
|
|
51
|
-
|
|
52
|
-
end
|
|
49
|
+
EOS
|
|
53
50
|
end
|
|
54
51
|
end
|
|
55
52
|
end
|