pg_trunk 0.1.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 +7 -0
- data/.github/workflows/ci.yml +87 -0
- data/.gitignore +9 -0
- data/.rspec +4 -0
- data/.rubocop.yml +92 -0
- data/.yardopts +4 -0
- data/CHANGELOG.md +31 -0
- data/CONTRIBUTING.md +17 -0
- data/Gemfile +22 -0
- data/LICENSE.txt +21 -0
- data/README.md +141 -0
- data/Rakefile +16 -0
- data/bin/console +8 -0
- data/bin/rake +19 -0
- data/bin/rspec +19 -0
- data/bin/setup +8 -0
- data/bin/yard +19 -0
- data/lib/pg_trunk/core/adapters/postgres.rb +80 -0
- data/lib/pg_trunk/core/dependencies_resolver.rb +101 -0
- data/lib/pg_trunk/core/generators.rb +140 -0
- data/lib/pg_trunk/core/operation/attributes.rb +78 -0
- data/lib/pg_trunk/core/operation/callbacks.rb +40 -0
- data/lib/pg_trunk/core/operation/generators.rb +51 -0
- data/lib/pg_trunk/core/operation/inversion.rb +70 -0
- data/lib/pg_trunk/core/operation/registration.rb +55 -0
- data/lib/pg_trunk/core/operation/ruby_builder.rb +112 -0
- data/lib/pg_trunk/core/operation/ruby_helpers.rb +99 -0
- data/lib/pg_trunk/core/operation/sql_helpers.rb +44 -0
- data/lib/pg_trunk/core/operation/validations.rb +21 -0
- data/lib/pg_trunk/core/operation.rb +78 -0
- data/lib/pg_trunk/core/qualified_name.rb +165 -0
- data/lib/pg_trunk/core/railtie/command_recorder.rb +30 -0
- data/lib/pg_trunk/core/railtie/custom_types.rb +37 -0
- data/lib/pg_trunk/core/railtie/migration.rb +50 -0
- data/lib/pg_trunk/core/railtie/migrator.rb +22 -0
- data/lib/pg_trunk/core/railtie/schema_dumper.rb +75 -0
- data/lib/pg_trunk/core/railtie/schema_migration.rb +22 -0
- data/lib/pg_trunk/core/railtie/statements.rb +21 -0
- data/lib/pg_trunk/core/railtie.rb +35 -0
- data/lib/pg_trunk/core/registry.rb +159 -0
- data/lib/pg_trunk/core/serializers/array_of_hashes_serializer.rb +28 -0
- data/lib/pg_trunk/core/serializers/array_of_strings_serializer.rb +29 -0
- data/lib/pg_trunk/core/serializers/array_of_symbols_serializer.rb +28 -0
- data/lib/pg_trunk/core/serializers/array_serializer.rb +22 -0
- data/lib/pg_trunk/core/serializers/lowercase_string_serializer.rb +21 -0
- data/lib/pg_trunk/core/serializers/multiline_text_serializer.rb +21 -0
- data/lib/pg_trunk/core/serializers/qualified_name_serializer.rb +27 -0
- data/lib/pg_trunk/core/serializers/symbol_serializer.rb +22 -0
- data/lib/pg_trunk/core/serializers.rb +16 -0
- data/lib/pg_trunk/core/validators/all_items_valid_validator.rb +15 -0
- data/lib/pg_trunk/core/validators/difference_validator.rb +19 -0
- data/lib/pg_trunk/core/validators.rb +10 -0
- data/lib/pg_trunk/core.rb +21 -0
- data/lib/pg_trunk/generators.rb +7 -0
- data/lib/pg_trunk/operations/check_constraints/add_check_constraint.rb +109 -0
- data/lib/pg_trunk/operations/check_constraints/base.rb +69 -0
- data/lib/pg_trunk/operations/check_constraints/drop_check_constraint.rb +60 -0
- data/lib/pg_trunk/operations/check_constraints/rename_check_constraint.rb +54 -0
- data/lib/pg_trunk/operations/check_constraints/validate_check_constraint.rb +39 -0
- data/lib/pg_trunk/operations/check_constraints.rb +14 -0
- data/lib/pg_trunk/operations/composite_types/base.rb +61 -0
- data/lib/pg_trunk/operations/composite_types/change_composite_type.rb +136 -0
- data/lib/pg_trunk/operations/composite_types/column.rb +118 -0
- data/lib/pg_trunk/operations/composite_types/create_composite_type.rb +99 -0
- data/lib/pg_trunk/operations/composite_types/drop_composite_type.rb +67 -0
- data/lib/pg_trunk/operations/composite_types/rename_composite_type.rb +44 -0
- data/lib/pg_trunk/operations/composite_types.rb +15 -0
- data/lib/pg_trunk/operations/domains/base.rb +46 -0
- data/lib/pg_trunk/operations/domains/change_domain.rb +140 -0
- data/lib/pg_trunk/operations/domains/constraint.rb +93 -0
- data/lib/pg_trunk/operations/domains/create_domain.rb +124 -0
- data/lib/pg_trunk/operations/domains/drop_domain.rb +65 -0
- data/lib/pg_trunk/operations/domains/rename_domain.rb +44 -0
- data/lib/pg_trunk/operations/domains.rb +15 -0
- data/lib/pg_trunk/operations/enums/base.rb +47 -0
- data/lib/pg_trunk/operations/enums/change.rb +55 -0
- data/lib/pg_trunk/operations/enums/change_enum.rb +119 -0
- data/lib/pg_trunk/operations/enums/create_enum.rb +83 -0
- data/lib/pg_trunk/operations/enums/drop_enum.rb +63 -0
- data/lib/pg_trunk/operations/enums/rename_enum.rb +44 -0
- data/lib/pg_trunk/operations/enums.rb +15 -0
- data/lib/pg_trunk/operations/foreign_keys/add_foreign_key.rb +174 -0
- data/lib/pg_trunk/operations/foreign_keys/base.rb +155 -0
- data/lib/pg_trunk/operations/foreign_keys/drop_foreign_key.rb +76 -0
- data/lib/pg_trunk/operations/foreign_keys/rename_foreign_key.rb +63 -0
- data/lib/pg_trunk/operations/foreign_keys.rb +16 -0
- data/lib/pg_trunk/operations/functions/base.rb +54 -0
- data/lib/pg_trunk/operations/functions/change_function.rb +108 -0
- data/lib/pg_trunk/operations/functions/create_function.rb +198 -0
- data/lib/pg_trunk/operations/functions/drop_function.rb +88 -0
- data/lib/pg_trunk/operations/functions/rename_function.rb +57 -0
- data/lib/pg_trunk/operations/functions.rb +14 -0
- data/lib/pg_trunk/operations/indexes/add_index.rb +68 -0
- data/lib/pg_trunk/operations/indexes.rb +10 -0
- data/lib/pg_trunk/operations/materialized_views/base.rb +79 -0
- data/lib/pg_trunk/operations/materialized_views/change_materialized_view.rb +139 -0
- data/lib/pg_trunk/operations/materialized_views/column.rb +94 -0
- data/lib/pg_trunk/operations/materialized_views/create_materialized_view.rb +170 -0
- data/lib/pg_trunk/operations/materialized_views/drop_materialized_view.rb +70 -0
- data/lib/pg_trunk/operations/materialized_views/refresh_materialized_view.rb +48 -0
- data/lib/pg_trunk/operations/materialized_views/rename_materialized_view.rb +61 -0
- data/lib/pg_trunk/operations/materialized_views.rb +17 -0
- data/lib/pg_trunk/operations/procedures/base.rb +42 -0
- data/lib/pg_trunk/operations/procedures/change_procedure.rb +107 -0
- data/lib/pg_trunk/operations/procedures/create_procedure.rb +146 -0
- data/lib/pg_trunk/operations/procedures/drop_procedure.rb +66 -0
- data/lib/pg_trunk/operations/procedures/rename_procedure.rb +57 -0
- data/lib/pg_trunk/operations/procedures.rb +14 -0
- data/lib/pg_trunk/operations/statistics/base.rb +94 -0
- data/lib/pg_trunk/operations/statistics/create_statistics.rb +181 -0
- data/lib/pg_trunk/operations/statistics/drop_statistics.rb +75 -0
- data/lib/pg_trunk/operations/statistics/rename_statistics.rb +48 -0
- data/lib/pg_trunk/operations/statistics.rb +13 -0
- data/lib/pg_trunk/operations/tables/create_table.rb +75 -0
- data/lib/pg_trunk/operations/tables.rb +10 -0
- data/lib/pg_trunk/operations/triggers/base.rb +119 -0
- data/lib/pg_trunk/operations/triggers/change_trigger.rb +82 -0
- data/lib/pg_trunk/operations/triggers/create_trigger.rb +208 -0
- data/lib/pg_trunk/operations/triggers/drop_trigger.rb +66 -0
- data/lib/pg_trunk/operations/triggers/rename_trigger.rb +71 -0
- data/lib/pg_trunk/operations/triggers.rb +14 -0
- data/lib/pg_trunk/operations/views/base.rb +38 -0
- data/lib/pg_trunk/operations/views/change_view.rb +90 -0
- data/lib/pg_trunk/operations/views/create_view.rb +115 -0
- data/lib/pg_trunk/operations/views/drop_view.rb +69 -0
- data/lib/pg_trunk/operations/views/rename_view.rb +58 -0
- data/lib/pg_trunk/operations/views.rb +14 -0
- data/lib/pg_trunk/operations.rb +23 -0
- data/lib/pg_trunk/version.rb +6 -0
- data/lib/pg_trunk.rb +27 -0
- data/pg_trunk.gemspec +34 -0
- data/spec/dummy/.gitignore +16 -0
- data/spec/dummy/Rakefile +15 -0
- data/spec/dummy/bin/bundle +6 -0
- data/spec/dummy/bin/rails +6 -0
- data/spec/dummy/bin/rake +6 -0
- data/spec/dummy/config/application.rb +18 -0
- data/spec/dummy/config/boot.rb +7 -0
- data/spec/dummy/config/database.yml +14 -0
- data/spec/dummy/config/environment.rb +7 -0
- data/spec/dummy/config.ru +6 -0
- data/spec/dummy/db/materialized_views/admin_users_v01.sql +1 -0
- data/spec/dummy/db/migrate/.keep +0 -0
- data/spec/dummy/db/schema.rb +18 -0
- data/spec/dummy/db/views/admin_users_v01.sql +1 -0
- data/spec/dummy/db/views/admin_users_v02.sql +1 -0
- data/spec/operations/check_constraints/add_check_constraint_spec.rb +85 -0
- data/spec/operations/check_constraints/drop_check_constraint_spec.rb +111 -0
- data/spec/operations/check_constraints/rename_check_constraint_spec.rb +90 -0
- data/spec/operations/composite_types/change_composite_type_spec.rb +257 -0
- data/spec/operations/composite_types/create_composite_type_spec.rb +55 -0
- data/spec/operations/composite_types/drop_composite_type_spec.rb +109 -0
- data/spec/operations/composite_types/rename_composite_type_spec.rb +74 -0
- data/spec/operations/dependency_resolver_spec.rb +177 -0
- data/spec/operations/domains/change_domain_spec.rb +287 -0
- data/spec/operations/domains/create_domain_spec.rb +69 -0
- data/spec/operations/domains/drop_domain_spec.rb +119 -0
- data/spec/operations/domains/rename_domain_spec.rb +70 -0
- data/spec/operations/enums/change_enum_spec.rb +157 -0
- data/spec/operations/enums/create_enum_spec.rb +40 -0
- data/spec/operations/enums/drop_enum_spec.rb +120 -0
- data/spec/operations/enums/rename_enum_spec.rb +72 -0
- data/spec/operations/foreign_keys/add_foreign_key_spec.rb +208 -0
- data/spec/operations/foreign_keys/drop_foreign_key_spec.rb +167 -0
- data/spec/operations/foreign_keys/rename_foreign_key_spec.rb +101 -0
- data/spec/operations/functions/change_function_spec.rb +166 -0
- data/spec/operations/functions/create_function_spec.rb +192 -0
- data/spec/operations/functions/drop_function_spec.rb +182 -0
- data/spec/operations/functions/rename_function_spec.rb +101 -0
- data/spec/operations/indexes/add_index_spec.rb +94 -0
- data/spec/operations/materialized_views/change_materialized_view_spec.rb +190 -0
- data/spec/operations/materialized_views/create_materialized_view_spec.rb +144 -0
- data/spec/operations/materialized_views/drop_materialized_view_spec.rb +145 -0
- data/spec/operations/materialized_views/refresh_materialized_view_spec.rb +79 -0
- data/spec/operations/materialized_views/rename_materialized_view_spec.rb +88 -0
- data/spec/operations/procedures/change_procedure_spec.rb +175 -0
- data/spec/operations/procedures/create_procedure_spec.rb +151 -0
- data/spec/operations/procedures/drop_procedure_spec.rb +159 -0
- data/spec/operations/procedures/rename_procedure_spec.rb +107 -0
- data/spec/operations/statistics/create_statistics_spec.rb +230 -0
- data/spec/operations/statistics/drop_statistics_spec.rb +106 -0
- data/spec/operations/statistics/rename_statistics_spec.rb +129 -0
- data/spec/operations/tables/create_table_spec.rb +53 -0
- data/spec/operations/tables/rename_table_spec.rb +37 -0
- data/spec/operations/triggers/change_trigger_spec.rb +195 -0
- data/spec/operations/triggers/create_trigger_spec.rb +104 -0
- data/spec/operations/triggers/drop_trigger_spec.rb +124 -0
- data/spec/operations/triggers/rename_trigger_spec.rb +160 -0
- data/spec/operations/views/change_view_spec.rb +144 -0
- data/spec/operations/views/create_view_spec.rb +134 -0
- data/spec/operations/views/drop_view_spec.rb +146 -0
- data/spec/operations/views/rename_view_spec.rb +85 -0
- data/spec/pg_trunk/dependencies_resolver_spec.rb +43 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/support/migrations_helper.rb +376 -0
- metadata +348 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: false
|
|
2
|
+
|
|
3
|
+
# @!method ActiveRecord::Migration#rename_view(name, **options)
|
|
4
|
+
# Change the name and/or schema of a view
|
|
5
|
+
#
|
|
6
|
+
# @param [#to_s] :name (nil) The qualified name of the view
|
|
7
|
+
# @option [#to_s] :to (nil) The new qualified name for the view
|
|
8
|
+
# @option [Boolean] :if_exists (false) Suppress the error when the view is absent
|
|
9
|
+
#
|
|
10
|
+
# A view can be renamed by changing both the name
|
|
11
|
+
# and the schema (namespace) it belongs to.
|
|
12
|
+
#
|
|
13
|
+
# rename_view "views.admin_users", to: "admins"
|
|
14
|
+
#
|
|
15
|
+
# With the `if_exists: true` option, the operation won't fail
|
|
16
|
+
# even when the view wasn't existed.
|
|
17
|
+
#
|
|
18
|
+
# rename_view "views.admin_users", to: "admins", if_exists: true
|
|
19
|
+
#
|
|
20
|
+
# At the same time, the option makes a view irreversible
|
|
21
|
+
# due to uncertainty of the previous state of the database.
|
|
22
|
+
|
|
23
|
+
module PGTrunk::Operations::Views
|
|
24
|
+
# @private
|
|
25
|
+
class RenameView < Base
|
|
26
|
+
validates :new_name, presence: true
|
|
27
|
+
validates :replace_existing, :sql_definition, :check, :force, :version,
|
|
28
|
+
absence: true
|
|
29
|
+
|
|
30
|
+
def to_sql(_version)
|
|
31
|
+
[*change_schema, *change_name].join("; ")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def invert
|
|
35
|
+
irreversible!("if_exists: true") if if_exists
|
|
36
|
+
self.class.new(**to_h, name: new_name, to: name)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def change_schema
|
|
42
|
+
return if name.schema == new_name.schema
|
|
43
|
+
|
|
44
|
+
sql = "ALTER VIEW"
|
|
45
|
+
sql << " IF EXISTS" if if_exists
|
|
46
|
+
sql << " #{name.to_sql} SET SCHEMA #{new_name.schema.inspect};"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def change_name
|
|
50
|
+
return if new_name.name == name.name
|
|
51
|
+
|
|
52
|
+
moved = name.merge(schema: new_name.schema)
|
|
53
|
+
sql = "ALTER VIEW"
|
|
54
|
+
sql << " IF EXISTS" if if_exists
|
|
55
|
+
sql << " #{moved.to_sql} RENAME TO #{new_name.name.inspect};"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# nodoc
|
|
4
|
+
module PGTrunk::Operations
|
|
5
|
+
# @private
|
|
6
|
+
# Namespace for operations with views
|
|
7
|
+
module Views
|
|
8
|
+
require_relative "views/base"
|
|
9
|
+
require_relative "views/change_view"
|
|
10
|
+
require_relative "views/create_view"
|
|
11
|
+
require_relative "views/drop_view"
|
|
12
|
+
require_relative "views/rename_view"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @private
|
|
4
|
+
module PGTrunk
|
|
5
|
+
# Namespace for creator definitions and their fetchers
|
|
6
|
+
module Operations
|
|
7
|
+
# The order of requirements is essential:
|
|
8
|
+
# in this order independent objects will be dumped to the schema.
|
|
9
|
+
require_relative "operations/enums"
|
|
10
|
+
require_relative "operations/composite_types"
|
|
11
|
+
require_relative "operations/domains"
|
|
12
|
+
require_relative "operations/tables"
|
|
13
|
+
require_relative "operations/views"
|
|
14
|
+
require_relative "operations/materialized_views"
|
|
15
|
+
require_relative "operations/functions"
|
|
16
|
+
require_relative "operations/indexes"
|
|
17
|
+
require_relative "operations/check_constraints"
|
|
18
|
+
require_relative "operations/foreign_keys"
|
|
19
|
+
require_relative "operations/procedures"
|
|
20
|
+
require_relative "operations/triggers"
|
|
21
|
+
require_relative "operations/statistics"
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/pg_trunk.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_record"
|
|
4
|
+
require "active_record/connection_adapters/postgresql_adapter"
|
|
5
|
+
require "active_record/migration"
|
|
6
|
+
require "pg"
|
|
7
|
+
require "rails/railtie"
|
|
8
|
+
|
|
9
|
+
# @private
|
|
10
|
+
# PGTrunk adds methods to `ActiveRecord::Migration`
|
|
11
|
+
# to create and manage PostgreSQL objects
|
|
12
|
+
# in Rails applications.
|
|
13
|
+
module PGTrunk
|
|
14
|
+
require_relative "pg_trunk/version"
|
|
15
|
+
require_relative "pg_trunk/core"
|
|
16
|
+
require_relative "pg_trunk/operations"
|
|
17
|
+
|
|
18
|
+
# @private
|
|
19
|
+
def self.database
|
|
20
|
+
@database ||= Adapters::Postgres.new
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @private
|
|
24
|
+
def self.dumper
|
|
25
|
+
@dumper ||= database.dumper
|
|
26
|
+
end
|
|
27
|
+
end
|
data/pg_trunk.gemspec
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
|
+
require "pg_trunk/version"
|
|
6
|
+
|
|
7
|
+
Gem::Specification.new do |spec|
|
|
8
|
+
spec.name = "pg_trunk"
|
|
9
|
+
spec.version = PGTrunk::VERSION
|
|
10
|
+
spec.authors = ["Andrew Kozin"]
|
|
11
|
+
spec.email = ["andrew.kozin@gmail.com"]
|
|
12
|
+
|
|
13
|
+
spec.summary = "Empower PostgreSQL migrations in Rails app"
|
|
14
|
+
spec.description = <<-DESCRIPTION
|
|
15
|
+
Adds methods to ActiveRecord::Migration to create and manage PostgreSQL objects in Rails
|
|
16
|
+
DESCRIPTION
|
|
17
|
+
spec.homepage = "https://github.com/nepalez/pg_trunk"
|
|
18
|
+
spec.license = "MIT"
|
|
19
|
+
|
|
20
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
21
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
|
22
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/CHANGELOG.md"
|
|
23
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
|
24
|
+
|
|
25
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
26
|
+
spec.test_files = spec.files.grep(%r{^spec/})
|
|
27
|
+
spec.require_paths = ["lib"]
|
|
28
|
+
|
|
29
|
+
spec.add_dependency "activerecord", ">= 4.0.0"
|
|
30
|
+
spec.add_dependency "pg"
|
|
31
|
+
spec.add_dependency "railties", ">= 4.0.0"
|
|
32
|
+
|
|
33
|
+
spec.required_ruby_version = ">= 2.7.0"
|
|
34
|
+
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,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
|
4
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
|
5
|
+
|
|
6
|
+
require File.expand_path("config/application", __dir__)
|
|
7
|
+
|
|
8
|
+
Rails.application.load_tasks
|
|
9
|
+
|
|
10
|
+
unless Rake::Task.task_defined?("db:environment:set")
|
|
11
|
+
desc "dummy task for rails versions where this task does not exist"
|
|
12
|
+
task "db:environment:set" do
|
|
13
|
+
# no op
|
|
14
|
+
end
|
|
15
|
+
end
|
data/spec/dummy/bin/rake
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path("boot", __dir__)
|
|
4
|
+
|
|
5
|
+
# Pick the frameworks you want:
|
|
6
|
+
require "active_record/railtie"
|
|
7
|
+
|
|
8
|
+
# noinspection RubyResolve
|
|
9
|
+
Bundler.require(*Rails.groups)
|
|
10
|
+
|
|
11
|
+
module Dummy
|
|
12
|
+
# noinspection RubyResolve
|
|
13
|
+
class Application < Rails::Application
|
|
14
|
+
config.cache_classes = true
|
|
15
|
+
config.eager_load = false
|
|
16
|
+
config.active_support.deprecation = :stderr
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Set up gems listed in the Gemfile.
|
|
4
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", __dir__)
|
|
5
|
+
|
|
6
|
+
require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
|
|
7
|
+
$LOAD_PATH.unshift File.expand_path("../../../lib", __dir__)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
development: &default
|
|
2
|
+
adapter: postgresql
|
|
3
|
+
database: pg_trunk_dummy_dev
|
|
4
|
+
encoding: unicode
|
|
5
|
+
pool: 5
|
|
6
|
+
<% if ENV.fetch("GITHUB_ACTIONS", false) %>
|
|
7
|
+
host: localhost
|
|
8
|
+
username: <%= ENV.fetch("POSTGRES_USER") %>
|
|
9
|
+
password: <%= ENV.fetch("POSTGRES_PASSWORD") %>
|
|
10
|
+
<% end %>
|
|
11
|
+
|
|
12
|
+
test:
|
|
13
|
+
<<: *default
|
|
14
|
+
database: pg_trunk_dummy_test
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SELECT id, name FROM users WHERE admin;
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is auto-generated from the current state of the database. Instead
|
|
4
|
+
# of editing this file, please use the operations feature of Active Record to
|
|
5
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
|
6
|
+
#
|
|
7
|
+
# This file is the source Rails uses to define your schema when running `bin/rails
|
|
8
|
+
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
|
9
|
+
# be faster and is potentially less error prone than running all of your
|
|
10
|
+
# operations from scratch. Old operations may fail to apply correctly if those
|
|
11
|
+
# operations use external dependencies or application code.
|
|
12
|
+
#
|
|
13
|
+
# It's strongly recommended that you check this file into your version control system.
|
|
14
|
+
|
|
15
|
+
ActiveRecord::Schema.define(version: 0) do
|
|
16
|
+
# These are extensions that must be enabled in order to support this database
|
|
17
|
+
enable_extension "plpgsql"
|
|
18
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SELECT id, name FROM users WHERE admin;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SELECT NULL::bigint AS id, name FROM users WHERE admin;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveRecord::Migration, "#add_check_constraint" do
|
|
4
|
+
before_all do
|
|
5
|
+
run_migration <<~RUBY
|
|
6
|
+
create_table "users" do |t|
|
|
7
|
+
t.string :name
|
|
8
|
+
end
|
|
9
|
+
RUBY
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:valid_query) { "INSERT INTO users (name) VALUES ('xx');" }
|
|
13
|
+
# breaks the constraint 'length(name) > 1'
|
|
14
|
+
let(:invalid_query) { "INSERT INTO users (name) VALUES ('x');" }
|
|
15
|
+
|
|
16
|
+
context "when added separately" do
|
|
17
|
+
let(:migration) do
|
|
18
|
+
<<~RUBY.squish
|
|
19
|
+
add_check_constraint "users", "length((name)::text) > 1"
|
|
20
|
+
RUBY
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
its(:execution) { is_expected.to enable_sql_request(valid_query) }
|
|
24
|
+
its(:execution) { is_expected.to disable_sql_request(invalid_query) }
|
|
25
|
+
its(:execution) { is_expected.to insert(migration).into_schema }
|
|
26
|
+
|
|
27
|
+
its(:inversion) { is_expected.to enable_sql_request(valid_query) }
|
|
28
|
+
its(:inversion) { is_expected.not_to change_schema }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context "when added inside the table definition" do
|
|
32
|
+
let(:migration) do
|
|
33
|
+
<<~RUBY
|
|
34
|
+
change_table "users" do |t|
|
|
35
|
+
t.check_constraint "length(name) > 1"
|
|
36
|
+
end
|
|
37
|
+
RUBY
|
|
38
|
+
end
|
|
39
|
+
let(:snippet) do
|
|
40
|
+
<<~RUBY.squish
|
|
41
|
+
add_check_constraint "users", "length((name)::text) > 1"
|
|
42
|
+
RUBY
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
its(:execution) { is_expected.to disable_sql_request(invalid_query) }
|
|
46
|
+
its(:execution) { is_expected.to enable_sql_request(valid_query) }
|
|
47
|
+
its(:execution) { is_expected.to insert(snippet).into_schema }
|
|
48
|
+
|
|
49
|
+
its(:inversion) { is_expected.not_to change_schema }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context "with a comment" do
|
|
53
|
+
let(:migration) do
|
|
54
|
+
<<~RUBY.squish
|
|
55
|
+
add_check_constraint "users", "length((name)::text) > 1",
|
|
56
|
+
comment: "Name is long enough"
|
|
57
|
+
RUBY
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
its(:execution) { is_expected.to insert(migration).into_schema }
|
|
61
|
+
its(:inversion) { is_expected.not_to change_schema }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
context "with an explicit name" do
|
|
65
|
+
let(:migration) do
|
|
66
|
+
<<~RUBY.squish
|
|
67
|
+
add_check_constraint "users", "length((name)::text) > 1",
|
|
68
|
+
name: "name_is_long_enough"
|
|
69
|
+
RUBY
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
its(:execution) { is_expected.to insert(migration).into_schema }
|
|
73
|
+
its(:inversion) { is_expected.not_to change_schema }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context "without an expression" do
|
|
77
|
+
let(:migration) do
|
|
78
|
+
<<~RUBY
|
|
79
|
+
add_check_constraint "users"
|
|
80
|
+
RUBY
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it { is_expected.to fail_validation.because(/expression can't be blank/i) }
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveRecord::Migration, "#drop_check_constraint" do
|
|
4
|
+
before_all do
|
|
5
|
+
run_migration <<~RUBY
|
|
6
|
+
create_table "users" do |t|
|
|
7
|
+
t.string :name
|
|
8
|
+
end
|
|
9
|
+
RUBY
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# satisfy the constraint 'length(name) > 1'
|
|
13
|
+
let(:valid_query) { "INSERT INTO users (name) VALUES ('xx');" }
|
|
14
|
+
# breaks the constraint 'length(name) > 1'
|
|
15
|
+
let(:invalid_query) { "INSERT INTO users (name) VALUES ('x');" }
|
|
16
|
+
|
|
17
|
+
context "when the constraint was named explicitly" do
|
|
18
|
+
before { run_migration(snippet) }
|
|
19
|
+
|
|
20
|
+
let(:snippet) do
|
|
21
|
+
<<~RUBY.squish
|
|
22
|
+
add_check_constraint "users", "length((name)::text) > 1",
|
|
23
|
+
name: "name_is_long_enough"
|
|
24
|
+
RUBY
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "with an expression" do
|
|
28
|
+
let(:migration) do
|
|
29
|
+
<<~RUBY.squish
|
|
30
|
+
drop_check_constraint "users", "length((name)::text) > 1",
|
|
31
|
+
name: "name_is_long_enough"
|
|
32
|
+
RUBY
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
its(:execution) { is_expected.to enable_sql_request(invalid_query) }
|
|
36
|
+
its(:execution) { is_expected.to remove(snippet).from_schema }
|
|
37
|
+
|
|
38
|
+
its(:inversion) { is_expected.to disable_sql_request(invalid_query) }
|
|
39
|
+
its(:inversion) { is_expected.to enable_sql_request(valid_query) }
|
|
40
|
+
its(:inversion) { is_expected.not_to change_schema }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context "without an expression" do
|
|
44
|
+
let(:migration) do
|
|
45
|
+
<<~RUBY
|
|
46
|
+
drop_check_constraint "users", name: "name_is_long_enough"
|
|
47
|
+
RUBY
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
its(:execution) { is_expected.to enable_sql_request(invalid_query) }
|
|
51
|
+
its(:execution) { is_expected.to remove(snippet).from_schema }
|
|
52
|
+
|
|
53
|
+
it { is_expected.to be_irreversible.because(/expression can't be blank/i) }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "without table name" do
|
|
57
|
+
let(:migration) do
|
|
58
|
+
<<~RUBY
|
|
59
|
+
drop_check_constraint
|
|
60
|
+
RUBY
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it { is_expected.to fail_validation.because(/table can't be blank/i) }
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "when the constraint was anonymous" do
|
|
68
|
+
before { run_migration(snippet) }
|
|
69
|
+
|
|
70
|
+
let(:snippet) do
|
|
71
|
+
<<~RUBY.squish
|
|
72
|
+
add_check_constraint "users", "length((name)::text) > 1"
|
|
73
|
+
RUBY
|
|
74
|
+
end
|
|
75
|
+
let(:migration) do
|
|
76
|
+
<<~RUBY
|
|
77
|
+
drop_check_constraint "users", "length((name)::text) > 1"
|
|
78
|
+
RUBY
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
its(:execution) { is_expected.to enable_sql_request(invalid_query) }
|
|
82
|
+
its(:execution) { is_expected.to remove(snippet).from_schema }
|
|
83
|
+
|
|
84
|
+
its(:inversion) { is_expected.to disable_sql_request(invalid_query) }
|
|
85
|
+
its(:inversion) { is_expected.to enable_sql_request(valid_query) }
|
|
86
|
+
its(:inversion) { is_expected.not_to change_schema }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context "when a constraint not existed" do
|
|
90
|
+
context "without the `it_exists: true` option" do
|
|
91
|
+
let(:migration) do
|
|
92
|
+
<<~RUBY
|
|
93
|
+
drop_check_constraint :users, name: "id_positive"
|
|
94
|
+
RUBY
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
its(:execution) { is_expected.to raise_error(StandardError) }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context "with the `it_exists: true` option" do
|
|
101
|
+
let(:migration) do
|
|
102
|
+
<<~RUBY
|
|
103
|
+
drop_check_constraint :users, "id_positive", if_exists: true
|
|
104
|
+
RUBY
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
its(:execution) { is_expected.not_to raise_error }
|
|
108
|
+
it { is_expected.to be_irreversible.because_of(/if_exists: true/i) }
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveRecord::Migration, "#rename_check_constraint" do
|
|
4
|
+
before_all do
|
|
5
|
+
run_migration <<~RUBY
|
|
6
|
+
create_table :users do |t|
|
|
7
|
+
t.string :name
|
|
8
|
+
end
|
|
9
|
+
RUBY
|
|
10
|
+
end
|
|
11
|
+
before { run_migration(old_snippet) }
|
|
12
|
+
|
|
13
|
+
context "when the constraint was anonymous" do
|
|
14
|
+
let(:old_snippet) do
|
|
15
|
+
<<~RUBY.squish
|
|
16
|
+
add_check_constraint "users", "length(name) > 1"
|
|
17
|
+
RUBY
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "with a new name" do
|
|
21
|
+
let(:migration) do
|
|
22
|
+
<<~RUBY.squish
|
|
23
|
+
rename_check_constraint "users", "length(name) > 1", to: "my_new_key"
|
|
24
|
+
RUBY
|
|
25
|
+
end
|
|
26
|
+
let(:new_snippet) do
|
|
27
|
+
<<~RUBY.squish
|
|
28
|
+
add_check_constraint "users", "length((name)::text) > 1",
|
|
29
|
+
name: "my_new_key"
|
|
30
|
+
RUBY
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
its(:execution) { is_expected.to insert(new_snippet).into_schema }
|
|
34
|
+
its(:reversion) { is_expected.not_to change_schema }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context "without a new name" do
|
|
38
|
+
let(:migration) do
|
|
39
|
+
<<~RUBY.squish
|
|
40
|
+
rename_check_constraint "users", "length((name)::text) > 1"
|
|
41
|
+
RUBY
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it { is_expected.to fail_validation.because(/new name must be different/i) }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context "when the constraint was named explicitly" do
|
|
49
|
+
let(:old_snippet) do
|
|
50
|
+
<<~RUBY.squish
|
|
51
|
+
add_check_constraint "users", "length(name) > 1", name: "my_key"
|
|
52
|
+
RUBY
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context "without new name" do
|
|
56
|
+
let(:migration) do
|
|
57
|
+
<<~RUBY
|
|
58
|
+
rename_check_constraint "users", "length((name)::text) > 1",
|
|
59
|
+
name: "my_key"
|
|
60
|
+
RUBY
|
|
61
|
+
end
|
|
62
|
+
let(:new_snippet) do
|
|
63
|
+
<<~RUBY
|
|
64
|
+
add_check_constraint "users", "length((name)::text) > 1"
|
|
65
|
+
RUBY
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
its(:execution) { is_expected.to insert(new_snippet).into_schema }
|
|
69
|
+
its(:reversion) { is_expected.not_to change_schema }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context "with a new name" do
|
|
73
|
+
let(:migration) do
|
|
74
|
+
<<~RUBY
|
|
75
|
+
rename_check_constraint "users", "length((name)::text) > 1",
|
|
76
|
+
name: "my_key",
|
|
77
|
+
to: "new_key"
|
|
78
|
+
RUBY
|
|
79
|
+
end
|
|
80
|
+
let(:snippet) do
|
|
81
|
+
<<~RUBY.squish
|
|
82
|
+
add_check_constraint "users", "length((name)::text) > 1", name: "new_key"
|
|
83
|
+
RUBY
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
its(:execution) { is_expected.to insert(snippet).into_schema }
|
|
87
|
+
its(:reversion) { is_expected.not_to change_schema }
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|