fx 0.8.0 → 0.10.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 +150 -0
- data/CONTRIBUTING.md +3 -3
- data/Gemfile +11 -1
- data/README.md +2 -0
- data/bin/rake +2 -3
- data/bin/rspec +13 -3
- data/bin/standardrb +27 -0
- data/bin/yard +13 -3
- data/fx.gemspec +10 -15
- data/lib/fx/adapters/postgres/connection.rb +20 -0
- data/lib/fx/adapters/postgres/functions.rb +11 -28
- data/lib/fx/adapters/postgres/query_executor.rb +34 -0
- data/lib/fx/adapters/postgres/triggers.rb +14 -29
- data/lib/fx/adapters/postgres.rb +16 -24
- data/lib/fx/command_recorder.rb +87 -6
- data/lib/fx/configuration.rb +2 -27
- data/lib/fx/definition.rb +16 -6
- data/lib/fx/function.rb +3 -3
- data/lib/fx/schema_dumper.rb +37 -5
- data/lib/fx/statements.rb +231 -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 +50 -53
- data/lib/generators/fx/function/templates/db/migrate/create_function.erb +1 -1
- data/lib/generators/fx/function/templates/db/migrate/update_function.erb +1 -1
- data/lib/generators/fx/migration_helper.rb +53 -0
- data/lib/generators/fx/name_helper.rb +33 -0
- data/lib/generators/fx/trigger/templates/db/migrate/create_trigger.erb +1 -1
- data/lib/generators/fx/trigger/templates/db/migrate/update_trigger.erb +1 -1
- data/lib/generators/fx/trigger/trigger_generator.rb +44 -67
- data/lib/generators/fx/version_helper.rb +55 -0
- data/spec/acceptance/user_manages_functions_spec.rb +7 -7
- data/spec/acceptance/user_manages_triggers_spec.rb +11 -11
- data/spec/acceptance_helper.rb +4 -4
- data/spec/dummy/config/application.rb +5 -1
- data/spec/features/functions/migrations_spec.rb +5 -5
- data/spec/features/functions/revert_spec.rb +5 -5
- data/spec/features/triggers/migrations_spec.rb +7 -7
- data/spec/features/triggers/revert_spec.rb +9 -9
- data/spec/fx/adapters/postgres/functions_spec.rb +33 -30
- data/spec/fx/adapters/postgres/query_executor_spec.rb +75 -0
- data/spec/fx/adapters/postgres/triggers_spec.rb +41 -38
- data/spec/fx/adapters/postgres_spec.rb +155 -115
- data/spec/fx/command_recorder_spec.rb +27 -25
- data/spec/fx/configuration_spec.rb +20 -9
- data/spec/fx/definition_spec.rb +31 -39
- data/spec/fx/function_spec.rb +45 -48
- data/spec/fx/schema_dumper_spec.rb +169 -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 +11 -11
- data/spec/generators/fx/migration_helper_spec.rb +133 -0
- data/spec/generators/fx/name_helper_spec.rb +114 -0
- data/spec/generators/fx/trigger/trigger_generator_spec.rb +45 -22
- data/spec/generators/fx/version_helper_spec.rb +157 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/support/definition_helpers.rb +2 -6
- data/spec/support/generator_setup.rb +46 -5
- data/spec/support/warning_helper.rb +5 -0
- metadata +40 -165
- 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/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,169 @@
|
|
|
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 = <<~SQL
|
|
6
|
+
CREATE OR REPLACE FUNCTION my_function()
|
|
7
|
+
RETURNS text AS $$
|
|
8
|
+
BEGIN
|
|
9
|
+
RETURN 'test';
|
|
10
|
+
END;
|
|
11
|
+
$$ LANGUAGE plpgsql;
|
|
12
|
+
SQL
|
|
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 = <<~SQL
|
|
28
|
+
CREATE OR REPLACE FUNCTION my_function()
|
|
29
|
+
RETURNS text AS $$
|
|
30
|
+
BEGIN
|
|
31
|
+
RETURN 'test';
|
|
32
|
+
END;
|
|
33
|
+
$$ LANGUAGE plpgsql;
|
|
34
|
+
SQL
|
|
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 = <<~SQL
|
|
51
|
+
CREATE OR REPLACE FUNCTION test(text, text)
|
|
52
|
+
RETURNS text AS $$
|
|
53
|
+
BEGIN
|
|
54
|
+
RETURN 'test';
|
|
55
|
+
END;
|
|
56
|
+
$$ LANGUAGE plpgsql;
|
|
57
|
+
SQL
|
|
58
|
+
|
|
59
|
+
aggregate_sql_definition = <<~SQL
|
|
60
|
+
CREATE AGGREGATE aggregate_test(text)
|
|
61
|
+
(
|
|
62
|
+
sfunc = test,
|
|
63
|
+
stype = text
|
|
64
|
+
);
|
|
65
|
+
SQL
|
|
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 <<~SQL
|
|
81
|
+
CREATE TABLE users (
|
|
82
|
+
id int PRIMARY KEY,
|
|
83
|
+
name varchar(256),
|
|
84
|
+
upper_name varchar(256)
|
|
85
|
+
);
|
|
86
|
+
SQL
|
|
87
|
+
Fx.database.create_function <<~SQL
|
|
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
|
+
SQL
|
|
96
|
+
sql_definition = <<~SQL
|
|
97
|
+
CREATE TRIGGER uppercase_users_name
|
|
98
|
+
BEFORE INSERT ON users
|
|
99
|
+
FOR EACH ROW
|
|
100
|
+
EXECUTE FUNCTION uppercase_users_name();
|
|
101
|
+
SQL
|
|
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
|
+
it "dumps functions and triggers for multiple schemas" do
|
|
117
|
+
connection.schema_search_path = "public,test_schema"
|
|
118
|
+
connection.create_table :my_table
|
|
119
|
+
connection.create_function :test1, sql_definition: <<~SQL
|
|
120
|
+
CREATE OR REPLACE FUNCTION test_public_func()
|
|
121
|
+
RETURNS TRIGGER AS $$
|
|
122
|
+
BEGIN
|
|
123
|
+
RETURN 1;
|
|
124
|
+
END;
|
|
125
|
+
$$ LANGUAGE plpgsql;
|
|
126
|
+
SQL
|
|
127
|
+
connection.create_trigger :test1_trigger, sql_definition: <<~SQL
|
|
128
|
+
CREATE TRIGGER test_public_trigger
|
|
129
|
+
BEFORE INSERT ON my_table
|
|
130
|
+
FOR EACH ROW
|
|
131
|
+
EXECUTE FUNCTION test_public_func();
|
|
132
|
+
SQL
|
|
133
|
+
connection.execute("CREATE SCHEMA test_schema;")
|
|
134
|
+
connection.create_table "test_schema.my_table2"
|
|
135
|
+
connection.execute <<~SQL
|
|
136
|
+
CREATE OR REPLACE FUNCTION test_schema.test_schema_func()
|
|
137
|
+
RETURNS TRIGGER AS $$
|
|
138
|
+
BEGIN
|
|
139
|
+
RETURN 'test_schema';
|
|
140
|
+
END;
|
|
141
|
+
$$ LANGUAGE plpgsql;
|
|
142
|
+
SQL
|
|
143
|
+
connection.execute <<~SQL
|
|
144
|
+
CREATE TRIGGER test_schema_trigger
|
|
145
|
+
BEFORE INSERT ON test_schema.my_table2
|
|
146
|
+
FOR EACH ROW
|
|
147
|
+
EXECUTE FUNCTION test_schema.test_schema_func();
|
|
148
|
+
SQL
|
|
149
|
+
stream = StringIO.new
|
|
150
|
+
output = stream.string
|
|
151
|
+
|
|
152
|
+
dump(connection: connection, stream: stream)
|
|
153
|
+
|
|
154
|
+
expect(output.scan("create_function :test_public_func").size).to eq(1)
|
|
155
|
+
expect(output.scan("create_trigger :test_public_trigger").size).to eq(1)
|
|
156
|
+
expect(output.scan("create_function :test_schema_func").size).to eq(1)
|
|
157
|
+
expect(output.scan("create_trigger :test_schema_trigger").size).to eq(1)
|
|
158
|
+
|
|
159
|
+
connection.schema_search_path = "public"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def dump(connection:, stream:)
|
|
163
|
+
if Rails.version >= "7.2"
|
|
164
|
+
ActiveRecord::SchemaDumper.dump(connection.pool, stream)
|
|
165
|
+
else
|
|
166
|
+
ActiveRecord::SchemaDumper.dump(connection, stream)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
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
|
data/spec/fx_spec.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
RSpec.describe Fx do
|
|
4
|
+
it "has a version number" do
|
|
5
|
+
expect(Fx::VERSION).to be_present
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "loads fx into ActiveRecord" do
|
|
9
|
+
expect(Fx.load).to eq(true)
|
|
10
|
+
expect(ActiveRecord::Migration::CommandRecorder).to include(Fx::CommandRecorder)
|
|
11
|
+
expect(ActiveRecord::ConnectionAdapters::AbstractAdapter).to include(Fx::Statements)
|
|
12
|
+
expect(ActiveRecord::SchemaDumper).to include(Fx::SchemaDumper)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "allows configuration" do
|
|
16
|
+
adapter = double("Fx Adapter")
|
|
17
|
+
|
|
18
|
+
Fx.configure do |config|
|
|
19
|
+
config.database = adapter
|
|
20
|
+
config.dump_functions_at_beginning_of_schema = true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
expect(Fx.configuration.database).to eq(adapter)
|
|
24
|
+
expect(Fx.configuration.dump_functions_at_beginning_of_schema).to eq(true)
|
|
25
|
+
|
|
26
|
+
Fx.configuration = nil
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
require "generators/fx/function/function_generator"
|
|
3
3
|
|
|
4
|
-
describe Fx::Generators::FunctionGenerator, :generator do
|
|
4
|
+
RSpec.describe Fx::Generators::FunctionGenerator, :generator do
|
|
5
5
|
it "creates a function definition file, and a migration" do
|
|
6
6
|
migration = file("db/migrate/create_function_test.rb")
|
|
7
7
|
function_definition = file("db/functions/test_v01.sql")
|
|
8
8
|
|
|
9
|
-
run_generator ["test"]
|
|
9
|
+
run_generator(described_class, ["test"])
|
|
10
10
|
|
|
11
11
|
expect(function_definition).to exist
|
|
12
|
-
|
|
13
|
-
expect(
|
|
12
|
+
expect_to_be_a_migration(migration)
|
|
13
|
+
expect(migration_content(migration)).to include("CreateFunctionTest")
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
context "when passed --no-migration" do
|
|
@@ -18,10 +18,10 @@ describe Fx::Generators::FunctionGenerator, :generator do
|
|
|
18
18
|
migration = file("db/migrate/create_function_test.rb")
|
|
19
19
|
function_definition = file("db/functions/test_v01.sql")
|
|
20
20
|
|
|
21
|
-
run_generator ["test",
|
|
21
|
+
run_generator(described_class, ["test"], {migration: false})
|
|
22
22
|
|
|
23
23
|
expect(function_definition).to exist
|
|
24
|
-
expect(
|
|
24
|
+
expect(migration).not_to exist
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -31,16 +31,16 @@ describe Fx::Generators::FunctionGenerator, :generator do
|
|
|
31
31
|
version: 1,
|
|
32
32
|
sql_definition: "hello"
|
|
33
33
|
) do
|
|
34
|
-
allow(Dir).to receive(:entries).and_return(["test_v01.sql"])
|
|
35
34
|
migration = file("db/migrate/update_function_test_to_version_2.rb")
|
|
36
35
|
function_definition = file("db/functions/test_v02.sql")
|
|
37
36
|
|
|
38
|
-
run_generator ["test"]
|
|
37
|
+
run_generator(described_class, ["test"])
|
|
39
38
|
|
|
40
39
|
expect(function_definition).to exist
|
|
41
|
-
|
|
42
|
-
expect(
|
|
43
|
-
|
|
40
|
+
expect_to_be_a_migration(migration)
|
|
41
|
+
expect(migration_content(migration)).to include(
|
|
42
|
+
"UpdateFunctionTestToVersion2"
|
|
43
|
+
)
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
end
|