fx-jets 0.6.3s
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 +7 -0
- data/.gitignore +10 -0
- data/.hound.yml +2 -0
- data/.rspec +2 -0
- data/.rubocop.yml +648 -0
- data/.travis.yml +60 -0
- data/.yardopts +4 -0
- data/Appraisals +45 -0
- data/CONTRIBUTING.md +15 -0
- data/Gemfile +4 -0
- data/LICENSE +18 -0
- data/README.md +1 -0
- data/Rakefile +23 -0
- data/bin/appraisal +17 -0
- data/bin/console +14 -0
- data/bin/rake +17 -0
- data/bin/rspec +17 -0
- data/bin/setup +13 -0
- data/bin/yard +17 -0
- data/fx.gemspec +39 -0
- data/gemfiles/rails42.gemfile +10 -0
- data/gemfiles/rails50.gemfile +8 -0
- data/gemfiles/rails51.gemfile +8 -0
- data/gemfiles/rails52.gemfile +8 -0
- data/gemfiles/rails60.gemfile +8 -0
- data/gemfiles/rails61.gemfile +8 -0
- data/gemfiles/rails_edge.gemfile +8 -0
- data/lib/fx/adapters/postgres/connection.rb +16 -0
- data/lib/fx/adapters/postgres/functions.rb +59 -0
- data/lib/fx/adapters/postgres/triggers.rb +57 -0
- data/lib/fx/adapters/postgres.rb +167 -0
- data/lib/fx/command_recorder/arguments.rb +43 -0
- data/lib/fx/command_recorder/function.rb +30 -0
- data/lib/fx/command_recorder/trigger.rb +30 -0
- data/lib/fx/command_recorder.rb +24 -0
- data/lib/fx/configuration.rb +48 -0
- data/lib/fx/definition.rb +46 -0
- data/lib/fx/function.rb +26 -0
- data/lib/fx/railtie.rb +15 -0
- data/lib/fx/schema_dumper/function.rb +38 -0
- data/lib/fx/schema_dumper/trigger.rb +29 -0
- data/lib/fx/schema_dumper.rb +10 -0
- data/lib/fx/statements/function.rb +115 -0
- data/lib/fx/statements/trigger.rb +146 -0
- data/lib/fx/statements.rb +11 -0
- data/lib/fx/trigger.rb +26 -0
- data/lib/fx/version.rb +4 -0
- data/lib/fx.rb +43 -0
- data/lib/generators/fx/function/USAGE +11 -0
- data/lib/generators/fx/function/function_generator.rb +120 -0
- data/lib/generators/fx/function/templates/db/migrate/create_function.erb +5 -0
- data/lib/generators/fx/function/templates/db/migrate/update_function.erb +5 -0
- data/lib/generators/fx/trigger/USAGE +20 -0
- data/lib/generators/fx/trigger/templates/db/migrate/create_trigger.erb +5 -0
- data/lib/generators/fx/trigger/templates/db/migrate/update_trigger.erb +5 -0
- data/lib/generators/fx/trigger/trigger_generator.rb +130 -0
- data/lib/generators.rb +11 -0
- data/spec/acceptance/user_manages_functions_spec.rb +57 -0
- data/spec/acceptance/user_manages_triggers_spec.rb +51 -0
- data/spec/acceptance_helper.rb +62 -0
- data/spec/dummy/.gitignore +16 -0
- data/spec/dummy/Rakefile +13 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +15 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +9 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/.keep +0 -0
- data/spec/features/functions/migrations_spec.rb +65 -0
- data/spec/features/functions/revert_spec.rb +75 -0
- data/spec/features/triggers/migrations_spec.rb +56 -0
- data/spec/features/triggers/revert_spec.rb +95 -0
- data/spec/fx/adapters/postgres/functions_spec.rb +37 -0
- data/spec/fx/adapters/postgres/triggers_spec.rb +45 -0
- data/spec/fx/adapters/postgres_spec.rb +146 -0
- data/spec/fx/command_recorder/arguments_spec.rb +41 -0
- data/spec/fx/command_recorder_spec.rb +171 -0
- data/spec/fx/configuration_spec.rb +21 -0
- data/spec/fx/definition_spec.rb +134 -0
- data/spec/fx/function_spec.rb +68 -0
- data/spec/fx/schema_dumper/function_spec.rb +80 -0
- data/spec/fx/schema_dumper/trigger_spec.rb +40 -0
- data/spec/fx/statements/function_spec.rb +103 -0
- data/spec/fx/statements/trigger_spec.rb +132 -0
- data/spec/fx/trigger_spec.rb +55 -0
- data/spec/generators/fx/function/function_generator_spec.rb +46 -0
- data/spec/generators/fx/trigger/trigger_generator_spec.rb +59 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/definition_helpers.rb +37 -0
- data/spec/support/generator_setup.rb +11 -0
- data/spec/support/migration_helpers.rb +25 -0
- metadata +357 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require "bundler"
|
|
2
|
+
|
|
3
|
+
ENV["RAILS_ENV"] = "test"
|
|
4
|
+
|
|
5
|
+
RSpec.configure do |config|
|
|
6
|
+
config.around(:each) do |example|
|
|
7
|
+
Dir.chdir("spec/dummy") do
|
|
8
|
+
example.run
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
config.before(:suite) do
|
|
13
|
+
Dir.chdir("spec/dummy") do
|
|
14
|
+
system <<-CMD
|
|
15
|
+
git init 1>/dev/null &&
|
|
16
|
+
git add -A &&
|
|
17
|
+
git commit --no-gpg-sign --message 'initial' 1>/dev/null
|
|
18
|
+
CMD
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
config.after(:suite) do
|
|
23
|
+
Dir.chdir("spec/dummy") do
|
|
24
|
+
ActiveRecord::Base.connection.disconnect!
|
|
25
|
+
system <<-CMD
|
|
26
|
+
echo &&
|
|
27
|
+
rake db:environment:set db:drop db:create &&
|
|
28
|
+
git add -A &&
|
|
29
|
+
git reset --hard HEAD 1>/dev/null &&
|
|
30
|
+
rm -rf .git/ 1>/dev/null
|
|
31
|
+
CMD
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def successfully(command)
|
|
36
|
+
`RAILS_ENV=test #{command}`
|
|
37
|
+
expect($?.exitstatus).to eq(0), "'#{command}' was unsuccessful"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def write_function_definition(file, contents)
|
|
41
|
+
write_definition(file, contents, "functions")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def write_trigger_definition(file, contents)
|
|
45
|
+
write_definition(file, contents, "triggers")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def write_definition(file, contents, directory)
|
|
49
|
+
File.open("db/#{directory}/#{file}.sql", File::WRONLY) do |definition|
|
|
50
|
+
definition.truncate(0)
|
|
51
|
+
definition.write(contents)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def verify_identical_definitions(def_a, def_b)
|
|
56
|
+
successfully "cmp #{def_a} #{def_b}"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def execute(command)
|
|
60
|
+
ActiveRecord::Base.connection.execute(command).first
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
|
2
|
+
#
|
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
|
5
|
+
# git config --global core.excludesfile '~/.gitignore_global'
|
|
6
|
+
|
|
7
|
+
# Ignore bundler config.
|
|
8
|
+
/.bundle
|
|
9
|
+
|
|
10
|
+
# Ignore the default SQLite database.
|
|
11
|
+
/db/*.sqlite3
|
|
12
|
+
/db/*.sqlite3-journal
|
|
13
|
+
|
|
14
|
+
# Ignore all logfiles and tempfiles.
|
|
15
|
+
/log/*.log
|
|
16
|
+
/tmp
|
data/spec/dummy/Rakefile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
|
2
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
|
3
|
+
|
|
4
|
+
require File.expand_path('../config/application', __FILE__)
|
|
5
|
+
|
|
6
|
+
Jets.application.load_tasks
|
|
7
|
+
|
|
8
|
+
unless Rake::Task.task_defined?('db:environment:set')
|
|
9
|
+
desc 'dummy task for rails versions where this task does not exist'
|
|
10
|
+
task 'db:environment:set' do
|
|
11
|
+
# no-op
|
|
12
|
+
end
|
|
13
|
+
end
|
data/spec/dummy/bin/rake
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require File.expand_path("../boot", __FILE__)
|
|
2
|
+
|
|
3
|
+
# Pick the frameworks you want:
|
|
4
|
+
require "active_record/railtie"
|
|
5
|
+
|
|
6
|
+
Bundler.require(*Jets.groups)
|
|
7
|
+
require "fx"
|
|
8
|
+
|
|
9
|
+
module Dummy
|
|
10
|
+
class Application < Rails::Application
|
|
11
|
+
config.cache_classes = true
|
|
12
|
+
config.eager_load = false
|
|
13
|
+
config.active_support.deprecation = :stderr
|
|
14
|
+
end
|
|
15
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe "Function migrations", :db do
|
|
4
|
+
around do |example|
|
|
5
|
+
sql_definition = <<-EOS
|
|
6
|
+
CREATE OR REPLACE FUNCTION test()
|
|
7
|
+
RETURNS text AS $$
|
|
8
|
+
BEGIN
|
|
9
|
+
RETURN 'test';
|
|
10
|
+
END;
|
|
11
|
+
$$ LANGUAGE plpgsql;
|
|
12
|
+
EOS
|
|
13
|
+
with_function_definition(name: :test, sql_definition: sql_definition) do
|
|
14
|
+
example.run
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "can run migrations that create functions" do
|
|
19
|
+
migration = Class.new(migration_class) do
|
|
20
|
+
def up
|
|
21
|
+
create_function :test
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
expect { run_migration(migration, :up) }.not_to raise_error
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "can run migrations that drop functions" do
|
|
29
|
+
connection.create_function(:test)
|
|
30
|
+
|
|
31
|
+
migration = Class.new(migration_class) do
|
|
32
|
+
def up
|
|
33
|
+
drop_function :test
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
expect { run_migration(migration, :up) }.not_to raise_error
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "can run migrations that updates functions" do
|
|
41
|
+
connection.create_function(:test)
|
|
42
|
+
|
|
43
|
+
sql_definition = <<-EOS
|
|
44
|
+
CREATE OR REPLACE FUNCTION test()
|
|
45
|
+
RETURNS text AS $$
|
|
46
|
+
BEGIN
|
|
47
|
+
RETURN 'testest';
|
|
48
|
+
END;
|
|
49
|
+
$$ LANGUAGE plpgsql;
|
|
50
|
+
EOS
|
|
51
|
+
with_function_definition(
|
|
52
|
+
name: :test,
|
|
53
|
+
version: 2,
|
|
54
|
+
sql_definition: sql_definition,
|
|
55
|
+
) do
|
|
56
|
+
migration = Class.new(migration_class) do
|
|
57
|
+
def change
|
|
58
|
+
update_function :test, version: 2, revert_to_version: 1
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
expect { run_migration(migration, :change) }.not_to raise_error
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe "Reverting migrations", :db do
|
|
4
|
+
around do |example|
|
|
5
|
+
sql_definition = <<-EOS
|
|
6
|
+
CREATE OR REPLACE FUNCTION test()
|
|
7
|
+
RETURNS text AS $$
|
|
8
|
+
BEGIN
|
|
9
|
+
RETURN 'test';
|
|
10
|
+
END;
|
|
11
|
+
$$ LANGUAGE plpgsql;
|
|
12
|
+
EOS
|
|
13
|
+
with_function_definition(name: :test, sql_definition: sql_definition) do
|
|
14
|
+
example.run
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "can run reversible migrations for creating functions" do
|
|
19
|
+
migration = Class.new(migration_class) do
|
|
20
|
+
def change
|
|
21
|
+
create_function :test
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
expect { run_migration(migration, [:up, :down]) }.not_to raise_error
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "can run reversible migrations for dropping functions" do
|
|
29
|
+
connection.create_function(:test)
|
|
30
|
+
|
|
31
|
+
good_migration = Class.new(migration_class) do
|
|
32
|
+
def change
|
|
33
|
+
drop_function :test, revert_to_version: 1
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
bad_migration = Class.new(migration_class) do
|
|
37
|
+
def change
|
|
38
|
+
drop_function :test
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
expect { run_migration(good_migration, [:up, :down]) }.not_to raise_error
|
|
43
|
+
expect { run_migration(bad_migration, [:up, :down]) }.
|
|
44
|
+
to raise_error(
|
|
45
|
+
ActiveRecord::IrreversibleMigration,
|
|
46
|
+
/`create_function` is reversible only if given a `revert_to_version`/,
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "can run reversible migrations for updating functions" do
|
|
51
|
+
connection.create_function(:test)
|
|
52
|
+
|
|
53
|
+
sql_definition = <<-EOS
|
|
54
|
+
CREATE OR REPLACE FUNCTION test()
|
|
55
|
+
RETURNS text AS $$
|
|
56
|
+
BEGIN
|
|
57
|
+
RETURN 'bar';
|
|
58
|
+
END;
|
|
59
|
+
$$ LANGUAGE plpgsql;
|
|
60
|
+
EOS
|
|
61
|
+
with_function_definition(
|
|
62
|
+
name: :test,
|
|
63
|
+
version: 2,
|
|
64
|
+
sql_definition: sql_definition,
|
|
65
|
+
) do
|
|
66
|
+
migration = Class.new(migration_class) do
|
|
67
|
+
def change
|
|
68
|
+
update_function :test, version: 2, revert_to_version: 1
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
expect { run_migration(migration, [:up, :down]) }.not_to raise_error
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe "Trigger migrations", :db do
|
|
4
|
+
around do |example|
|
|
5
|
+
connection.execute <<-EOS
|
|
6
|
+
CREATE TABLE users (
|
|
7
|
+
id int PRIMARY KEY,
|
|
8
|
+
name varchar(256),
|
|
9
|
+
upper_name varchar(256)
|
|
10
|
+
);
|
|
11
|
+
EOS
|
|
12
|
+
Fx.database.create_function <<-EOS
|
|
13
|
+
CREATE OR REPLACE FUNCTION uppercase_users_name()
|
|
14
|
+
RETURNS trigger AS $$
|
|
15
|
+
BEGIN
|
|
16
|
+
NEW.upper_name = UPPER(NEW.name);
|
|
17
|
+
RETURN NEW;
|
|
18
|
+
END;
|
|
19
|
+
$$ LANGUAGE plpgsql;
|
|
20
|
+
EOS
|
|
21
|
+
sql_definition = <<-EOS
|
|
22
|
+
CREATE TRIGGER uppercase_users_name
|
|
23
|
+
BEFORE INSERT ON users
|
|
24
|
+
FOR EACH ROW
|
|
25
|
+
EXECUTE PROCEDURE uppercase_users_name();
|
|
26
|
+
EOS
|
|
27
|
+
with_trigger_definition(
|
|
28
|
+
name: :uppercase_users_name,
|
|
29
|
+
sql_definition: sql_definition,
|
|
30
|
+
) do
|
|
31
|
+
example.run
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "can run migrations that create triggers" do
|
|
36
|
+
migration = Class.new(migration_class) do
|
|
37
|
+
def up
|
|
38
|
+
create_trigger :uppercase_users_name
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
expect { run_migration(migration, :up) }.not_to raise_error
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "can run migrations that drop triggers" do
|
|
46
|
+
connection.create_trigger(:uppercase_users_name)
|
|
47
|
+
|
|
48
|
+
migration = Class.new(migration_class) do
|
|
49
|
+
def up
|
|
50
|
+
drop_trigger :uppercase_users_name, on: :users
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
expect { run_migration(migration, :up) }.not_to raise_error
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe "Reverting migrations", :db do
|
|
4
|
+
around do |example|
|
|
5
|
+
connection.execute <<-EOS
|
|
6
|
+
CREATE TABLE users (
|
|
7
|
+
id int PRIMARY KEY,
|
|
8
|
+
name varchar(256),
|
|
9
|
+
upper_name varchar(256)
|
|
10
|
+
);
|
|
11
|
+
EOS
|
|
12
|
+
Fx.database.create_function <<-EOS
|
|
13
|
+
CREATE OR REPLACE FUNCTION uppercase_users_name()
|
|
14
|
+
RETURNS trigger AS $$
|
|
15
|
+
BEGIN
|
|
16
|
+
NEW.upper_name = UPPER(NEW.name);
|
|
17
|
+
RETURN NEW;
|
|
18
|
+
END;
|
|
19
|
+
$$ LANGUAGE plpgsql;
|
|
20
|
+
EOS
|
|
21
|
+
sql_definition = <<-EOS
|
|
22
|
+
CREATE TRIGGER uppercase_users_name
|
|
23
|
+
BEFORE INSERT ON users
|
|
24
|
+
FOR EACH ROW
|
|
25
|
+
EXECUTE PROCEDURE uppercase_users_name();
|
|
26
|
+
EOS
|
|
27
|
+
with_trigger_definition(
|
|
28
|
+
name: :uppercase_users_name,
|
|
29
|
+
sql_definition: sql_definition,
|
|
30
|
+
) do
|
|
31
|
+
example.run
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "can run reversible migrations for creating triggers" do
|
|
36
|
+
migration = Class.new(migration_class) do
|
|
37
|
+
def change
|
|
38
|
+
create_trigger :uppercase_users_name, on: :users
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
expect { run_migration(migration, [:up, :down]) }.not_to raise_error
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "can run reversible migrations for dropping triggers" do
|
|
46
|
+
connection.create_trigger(:uppercase_users_name, on: :users)
|
|
47
|
+
|
|
48
|
+
good_migration = Class.new(migration_class) do
|
|
49
|
+
def change
|
|
50
|
+
drop_trigger :uppercase_users_name, on: :users, revert_to_version: 1
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
bad_migration = Class.new(migration_class) do
|
|
54
|
+
def change
|
|
55
|
+
drop_trigger :uppercase_users_name, on: :users
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
expect { run_migration(good_migration, [:up, :down]) }.not_to raise_error
|
|
60
|
+
expect { run_migration(bad_migration, [:up, :down]) }.
|
|
61
|
+
to raise_error(
|
|
62
|
+
ActiveRecord::IrreversibleMigration,
|
|
63
|
+
/`create_trigger` is reversible only if given a `revert_to_version`/,
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "can run reversible migrations for updating triggers" do
|
|
68
|
+
connection.create_trigger(:uppercase_users_name)
|
|
69
|
+
|
|
70
|
+
sql_definition = <<-EOS
|
|
71
|
+
CREATE TRIGGER uppercase_users_name
|
|
72
|
+
BEFORE UPDATE ON users
|
|
73
|
+
FOR EACH ROW
|
|
74
|
+
EXECUTE PROCEDURE uppercase_users_name();
|
|
75
|
+
EOS
|
|
76
|
+
with_trigger_definition(
|
|
77
|
+
name: :uppercase_users_name,
|
|
78
|
+
sql_definition: sql_definition,
|
|
79
|
+
version: 2,
|
|
80
|
+
) do
|
|
81
|
+
migration = Class.new(migration_class) do
|
|
82
|
+
def change
|
|
83
|
+
update_trigger(
|
|
84
|
+
:uppercase_users_name,
|
|
85
|
+
on: :users,
|
|
86
|
+
version: 2,
|
|
87
|
+
revert_to_version: 1,
|
|
88
|
+
)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
expect { run_migration(migration, [:up, :down]) }.not_to raise_error
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
module Fx
|
|
4
|
+
module Adapters
|
|
5
|
+
describe Postgres::Functions, :db do
|
|
6
|
+
describe ".all" do
|
|
7
|
+
it "returns `Function` objects" do
|
|
8
|
+
connection = ActiveRecord::Base.connection
|
|
9
|
+
connection.execute <<-EOS.strip_heredoc
|
|
10
|
+
CREATE OR REPLACE FUNCTION test()
|
|
11
|
+
RETURNS text AS $$
|
|
12
|
+
BEGIN
|
|
13
|
+
RETURN 'test';
|
|
14
|
+
END;
|
|
15
|
+
$$ LANGUAGE plpgsql;
|
|
16
|
+
EOS
|
|
17
|
+
|
|
18
|
+
functions = Postgres::Functions.new(connection).all
|
|
19
|
+
|
|
20
|
+
first = functions.first
|
|
21
|
+
expect(functions.size).to eq 1
|
|
22
|
+
expect(first.name).to eq "test"
|
|
23
|
+
expect(first.definition).to eq <<-EOS.strip_heredoc
|
|
24
|
+
CREATE OR REPLACE FUNCTION public.test()
|
|
25
|
+
RETURNS text
|
|
26
|
+
LANGUAGE plpgsql
|
|
27
|
+
AS $function$
|
|
28
|
+
BEGIN
|
|
29
|
+
RETURN 'test';
|
|
30
|
+
END;
|
|
31
|
+
$function$
|
|
32
|
+
EOS
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
module Fx
|
|
4
|
+
module Adapters
|
|
5
|
+
describe Postgres::Triggers, :db do
|
|
6
|
+
describe ".all" do
|
|
7
|
+
it "returns `Trigger` objects" do
|
|
8
|
+
connection = ActiveRecord::Base.connection
|
|
9
|
+
connection.execute <<-EOS.strip_heredoc
|
|
10
|
+
CREATE TABLE users (
|
|
11
|
+
id int PRIMARY KEY,
|
|
12
|
+
name varchar(256),
|
|
13
|
+
upper_name varchar(256)
|
|
14
|
+
);
|
|
15
|
+
EOS
|
|
16
|
+
connection.execute <<-EOS.strip_heredoc
|
|
17
|
+
CREATE OR REPLACE FUNCTION uppercase_users_name()
|
|
18
|
+
RETURNS trigger AS $$
|
|
19
|
+
BEGIN
|
|
20
|
+
NEW.upper_name = UPPER(NEW.name);
|
|
21
|
+
RETURN NEW;
|
|
22
|
+
END;
|
|
23
|
+
$$ LANGUAGE plpgsql;
|
|
24
|
+
EOS
|
|
25
|
+
connection.execute <<-EOS.strip_heredoc
|
|
26
|
+
CREATE TRIGGER uppercase_users_name
|
|
27
|
+
BEFORE INSERT ON users
|
|
28
|
+
FOR EACH ROW
|
|
29
|
+
EXECUTE PROCEDURE uppercase_users_name();
|
|
30
|
+
EOS
|
|
31
|
+
|
|
32
|
+
triggers = Postgres::Triggers.new(connection).all
|
|
33
|
+
|
|
34
|
+
first = triggers.first
|
|
35
|
+
expect(triggers.size).to eq 1
|
|
36
|
+
expect(first.name).to eq "uppercase_users_name"
|
|
37
|
+
expect(first.definition).to include("BEFORE INSERT")
|
|
38
|
+
expect(first.definition).to match(/ON [public\.users|users]/)
|
|
39
|
+
expect(first.definition).to include("FOR EACH ROW")
|
|
40
|
+
expect(first.definition).to include("EXECUTE PROCEDURE uppercase_users_name()")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
module Fx::Adapters
|
|
4
|
+
describe Postgres, :db do
|
|
5
|
+
describe "#create_function" do
|
|
6
|
+
it "successfully creates a function" do
|
|
7
|
+
adapter = Postgres.new
|
|
8
|
+
adapter.create_function(
|
|
9
|
+
<<-EOS
|
|
10
|
+
CREATE OR REPLACE FUNCTION test()
|
|
11
|
+
RETURNS text AS $$
|
|
12
|
+
BEGIN
|
|
13
|
+
RETURN 'test';
|
|
14
|
+
END;
|
|
15
|
+
$$ LANGUAGE plpgsql;
|
|
16
|
+
EOS
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
expect(adapter.functions.map(&:name)).to include("test")
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe "#create_trigger" do
|
|
24
|
+
it "successfully creates a trigger" do
|
|
25
|
+
connection.execute <<-EOS
|
|
26
|
+
CREATE TABLE users (
|
|
27
|
+
id int PRIMARY KEY,
|
|
28
|
+
name varchar(256),
|
|
29
|
+
upper_name varchar(256)
|
|
30
|
+
);
|
|
31
|
+
EOS
|
|
32
|
+
adapter = Postgres.new
|
|
33
|
+
adapter.create_function <<-EOS
|
|
34
|
+
CREATE OR REPLACE FUNCTION uppercase_users_name()
|
|
35
|
+
RETURNS trigger AS $$
|
|
36
|
+
BEGIN
|
|
37
|
+
NEW.upper_name = UPPER(NEW.name);
|
|
38
|
+
RETURN NEW;
|
|
39
|
+
END;
|
|
40
|
+
$$ LANGUAGE plpgsql;
|
|
41
|
+
EOS
|
|
42
|
+
adapter.create_trigger(
|
|
43
|
+
<<-EOS
|
|
44
|
+
CREATE TRIGGER uppercase_users_name
|
|
45
|
+
BEFORE INSERT ON users
|
|
46
|
+
FOR EACH ROW
|
|
47
|
+
EXECUTE PROCEDURE uppercase_users_name();
|
|
48
|
+
EOS
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
expect(adapter.triggers.map(&:name)).to include("uppercase_users_name")
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe "#drop_function" do
|
|
56
|
+
context "when the function has arguments" do
|
|
57
|
+
it "successfully drops a function with the entire function signature" do
|
|
58
|
+
adapter = Postgres.new
|
|
59
|
+
adapter.create_function(
|
|
60
|
+
<<-EOS
|
|
61
|
+
CREATE FUNCTION adder(x int, y int)
|
|
62
|
+
RETURNS int AS $$
|
|
63
|
+
BEGIN
|
|
64
|
+
RETURN $1 + $2;
|
|
65
|
+
END;
|
|
66
|
+
$$ LANGUAGE plpgsql;
|
|
67
|
+
EOS
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
adapter.drop_function(:adder)
|
|
71
|
+
|
|
72
|
+
expect(adapter.functions.map(&:name)).not_to include("adder")
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context "when the function does not have arguments" do
|
|
77
|
+
it "successfully drops a function" do
|
|
78
|
+
adapter = Postgres.new
|
|
79
|
+
adapter.create_function(
|
|
80
|
+
<<-EOS
|
|
81
|
+
CREATE OR REPLACE FUNCTION test()
|
|
82
|
+
RETURNS text AS $$
|
|
83
|
+
BEGIN
|
|
84
|
+
RETURN 'test';
|
|
85
|
+
END;
|
|
86
|
+
$$ LANGUAGE plpgsql;
|
|
87
|
+
EOS
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
adapter.drop_function(:test)
|
|
91
|
+
|
|
92
|
+
expect(adapter.functions.map(&:name)).not_to include("test")
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe "#functions" do
|
|
98
|
+
it "finds functions and builds Fx::Function objects" do
|
|
99
|
+
adapter = Postgres.new
|
|
100
|
+
adapter.create_function(
|
|
101
|
+
<<-EOS
|
|
102
|
+
CREATE OR REPLACE FUNCTION test()
|
|
103
|
+
RETURNS text AS $$
|
|
104
|
+
BEGIN
|
|
105
|
+
RETURN 'test';
|
|
106
|
+
END;
|
|
107
|
+
$$ LANGUAGE plpgsql;
|
|
108
|
+
EOS
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
expect(adapter.functions.map(&:name)).to eq ["test"]
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
describe "#triggers" do
|
|
116
|
+
it "finds triggers and builds Fx::Trigger objects" do
|
|
117
|
+
connection.execute <<-EOS
|
|
118
|
+
CREATE TABLE users (
|
|
119
|
+
id int PRIMARY KEY,
|
|
120
|
+
name varchar(256),
|
|
121
|
+
upper_name varchar(256)
|
|
122
|
+
);
|
|
123
|
+
EOS
|
|
124
|
+
adapter = Postgres.new
|
|
125
|
+
adapter.create_function <<-EOS
|
|
126
|
+
CREATE OR REPLACE FUNCTION uppercase_users_name()
|
|
127
|
+
RETURNS trigger AS $$
|
|
128
|
+
BEGIN
|
|
129
|
+
NEW.upper_name = UPPER(NEW.name);
|
|
130
|
+
RETURN NEW;
|
|
131
|
+
END;
|
|
132
|
+
$$ LANGUAGE plpgsql;
|
|
133
|
+
EOS
|
|
134
|
+
sql_definition = <<-EOS
|
|
135
|
+
CREATE TRIGGER uppercase_users_name
|
|
136
|
+
BEFORE INSERT ON users
|
|
137
|
+
FOR EACH ROW
|
|
138
|
+
EXECUTE PROCEDURE uppercase_users_name()
|
|
139
|
+
EOS
|
|
140
|
+
adapter.create_trigger(sql_definition)
|
|
141
|
+
|
|
142
|
+
expect(adapter.triggers.map(&:name)).to eq ["uppercase_users_name"]
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|