pg_trunk 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (196) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +87 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +4 -0
  5. data/.rubocop.yml +92 -0
  6. data/.yardopts +4 -0
  7. data/CHANGELOG.md +31 -0
  8. data/CONTRIBUTING.md +17 -0
  9. data/Gemfile +22 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +141 -0
  12. data/Rakefile +16 -0
  13. data/bin/console +8 -0
  14. data/bin/rake +19 -0
  15. data/bin/rspec +19 -0
  16. data/bin/setup +8 -0
  17. data/bin/yard +19 -0
  18. data/lib/pg_trunk/core/adapters/postgres.rb +80 -0
  19. data/lib/pg_trunk/core/dependencies_resolver.rb +101 -0
  20. data/lib/pg_trunk/core/generators.rb +140 -0
  21. data/lib/pg_trunk/core/operation/attributes.rb +78 -0
  22. data/lib/pg_trunk/core/operation/callbacks.rb +40 -0
  23. data/lib/pg_trunk/core/operation/generators.rb +51 -0
  24. data/lib/pg_trunk/core/operation/inversion.rb +70 -0
  25. data/lib/pg_trunk/core/operation/registration.rb +55 -0
  26. data/lib/pg_trunk/core/operation/ruby_builder.rb +112 -0
  27. data/lib/pg_trunk/core/operation/ruby_helpers.rb +99 -0
  28. data/lib/pg_trunk/core/operation/sql_helpers.rb +44 -0
  29. data/lib/pg_trunk/core/operation/validations.rb +21 -0
  30. data/lib/pg_trunk/core/operation.rb +78 -0
  31. data/lib/pg_trunk/core/qualified_name.rb +165 -0
  32. data/lib/pg_trunk/core/railtie/command_recorder.rb +30 -0
  33. data/lib/pg_trunk/core/railtie/custom_types.rb +37 -0
  34. data/lib/pg_trunk/core/railtie/migration.rb +50 -0
  35. data/lib/pg_trunk/core/railtie/migrator.rb +22 -0
  36. data/lib/pg_trunk/core/railtie/schema_dumper.rb +75 -0
  37. data/lib/pg_trunk/core/railtie/schema_migration.rb +22 -0
  38. data/lib/pg_trunk/core/railtie/statements.rb +21 -0
  39. data/lib/pg_trunk/core/railtie.rb +35 -0
  40. data/lib/pg_trunk/core/registry.rb +159 -0
  41. data/lib/pg_trunk/core/serializers/array_of_hashes_serializer.rb +28 -0
  42. data/lib/pg_trunk/core/serializers/array_of_strings_serializer.rb +29 -0
  43. data/lib/pg_trunk/core/serializers/array_of_symbols_serializer.rb +28 -0
  44. data/lib/pg_trunk/core/serializers/array_serializer.rb +22 -0
  45. data/lib/pg_trunk/core/serializers/lowercase_string_serializer.rb +21 -0
  46. data/lib/pg_trunk/core/serializers/multiline_text_serializer.rb +21 -0
  47. data/lib/pg_trunk/core/serializers/qualified_name_serializer.rb +27 -0
  48. data/lib/pg_trunk/core/serializers/symbol_serializer.rb +22 -0
  49. data/lib/pg_trunk/core/serializers.rb +16 -0
  50. data/lib/pg_trunk/core/validators/all_items_valid_validator.rb +15 -0
  51. data/lib/pg_trunk/core/validators/difference_validator.rb +19 -0
  52. data/lib/pg_trunk/core/validators.rb +10 -0
  53. data/lib/pg_trunk/core.rb +21 -0
  54. data/lib/pg_trunk/generators.rb +7 -0
  55. data/lib/pg_trunk/operations/check_constraints/add_check_constraint.rb +109 -0
  56. data/lib/pg_trunk/operations/check_constraints/base.rb +69 -0
  57. data/lib/pg_trunk/operations/check_constraints/drop_check_constraint.rb +60 -0
  58. data/lib/pg_trunk/operations/check_constraints/rename_check_constraint.rb +54 -0
  59. data/lib/pg_trunk/operations/check_constraints/validate_check_constraint.rb +39 -0
  60. data/lib/pg_trunk/operations/check_constraints.rb +14 -0
  61. data/lib/pg_trunk/operations/composite_types/base.rb +61 -0
  62. data/lib/pg_trunk/operations/composite_types/change_composite_type.rb +136 -0
  63. data/lib/pg_trunk/operations/composite_types/column.rb +118 -0
  64. data/lib/pg_trunk/operations/composite_types/create_composite_type.rb +99 -0
  65. data/lib/pg_trunk/operations/composite_types/drop_composite_type.rb +67 -0
  66. data/lib/pg_trunk/operations/composite_types/rename_composite_type.rb +44 -0
  67. data/lib/pg_trunk/operations/composite_types.rb +15 -0
  68. data/lib/pg_trunk/operations/domains/base.rb +46 -0
  69. data/lib/pg_trunk/operations/domains/change_domain.rb +140 -0
  70. data/lib/pg_trunk/operations/domains/constraint.rb +93 -0
  71. data/lib/pg_trunk/operations/domains/create_domain.rb +124 -0
  72. data/lib/pg_trunk/operations/domains/drop_domain.rb +65 -0
  73. data/lib/pg_trunk/operations/domains/rename_domain.rb +44 -0
  74. data/lib/pg_trunk/operations/domains.rb +15 -0
  75. data/lib/pg_trunk/operations/enums/base.rb +47 -0
  76. data/lib/pg_trunk/operations/enums/change.rb +55 -0
  77. data/lib/pg_trunk/operations/enums/change_enum.rb +119 -0
  78. data/lib/pg_trunk/operations/enums/create_enum.rb +83 -0
  79. data/lib/pg_trunk/operations/enums/drop_enum.rb +63 -0
  80. data/lib/pg_trunk/operations/enums/rename_enum.rb +44 -0
  81. data/lib/pg_trunk/operations/enums.rb +15 -0
  82. data/lib/pg_trunk/operations/foreign_keys/add_foreign_key.rb +174 -0
  83. data/lib/pg_trunk/operations/foreign_keys/base.rb +155 -0
  84. data/lib/pg_trunk/operations/foreign_keys/drop_foreign_key.rb +76 -0
  85. data/lib/pg_trunk/operations/foreign_keys/rename_foreign_key.rb +63 -0
  86. data/lib/pg_trunk/operations/foreign_keys.rb +16 -0
  87. data/lib/pg_trunk/operations/functions/base.rb +54 -0
  88. data/lib/pg_trunk/operations/functions/change_function.rb +108 -0
  89. data/lib/pg_trunk/operations/functions/create_function.rb +198 -0
  90. data/lib/pg_trunk/operations/functions/drop_function.rb +88 -0
  91. data/lib/pg_trunk/operations/functions/rename_function.rb +57 -0
  92. data/lib/pg_trunk/operations/functions.rb +14 -0
  93. data/lib/pg_trunk/operations/indexes/add_index.rb +68 -0
  94. data/lib/pg_trunk/operations/indexes.rb +10 -0
  95. data/lib/pg_trunk/operations/materialized_views/base.rb +79 -0
  96. data/lib/pg_trunk/operations/materialized_views/change_materialized_view.rb +139 -0
  97. data/lib/pg_trunk/operations/materialized_views/column.rb +94 -0
  98. data/lib/pg_trunk/operations/materialized_views/create_materialized_view.rb +170 -0
  99. data/lib/pg_trunk/operations/materialized_views/drop_materialized_view.rb +70 -0
  100. data/lib/pg_trunk/operations/materialized_views/refresh_materialized_view.rb +48 -0
  101. data/lib/pg_trunk/operations/materialized_views/rename_materialized_view.rb +61 -0
  102. data/lib/pg_trunk/operations/materialized_views.rb +17 -0
  103. data/lib/pg_trunk/operations/procedures/base.rb +42 -0
  104. data/lib/pg_trunk/operations/procedures/change_procedure.rb +107 -0
  105. data/lib/pg_trunk/operations/procedures/create_procedure.rb +146 -0
  106. data/lib/pg_trunk/operations/procedures/drop_procedure.rb +66 -0
  107. data/lib/pg_trunk/operations/procedures/rename_procedure.rb +57 -0
  108. data/lib/pg_trunk/operations/procedures.rb +14 -0
  109. data/lib/pg_trunk/operations/statistics/base.rb +94 -0
  110. data/lib/pg_trunk/operations/statistics/create_statistics.rb +181 -0
  111. data/lib/pg_trunk/operations/statistics/drop_statistics.rb +75 -0
  112. data/lib/pg_trunk/operations/statistics/rename_statistics.rb +48 -0
  113. data/lib/pg_trunk/operations/statistics.rb +13 -0
  114. data/lib/pg_trunk/operations/tables/create_table.rb +75 -0
  115. data/lib/pg_trunk/operations/tables.rb +10 -0
  116. data/lib/pg_trunk/operations/triggers/base.rb +119 -0
  117. data/lib/pg_trunk/operations/triggers/change_trigger.rb +82 -0
  118. data/lib/pg_trunk/operations/triggers/create_trigger.rb +208 -0
  119. data/lib/pg_trunk/operations/triggers/drop_trigger.rb +66 -0
  120. data/lib/pg_trunk/operations/triggers/rename_trigger.rb +71 -0
  121. data/lib/pg_trunk/operations/triggers.rb +14 -0
  122. data/lib/pg_trunk/operations/views/base.rb +38 -0
  123. data/lib/pg_trunk/operations/views/change_view.rb +90 -0
  124. data/lib/pg_trunk/operations/views/create_view.rb +115 -0
  125. data/lib/pg_trunk/operations/views/drop_view.rb +69 -0
  126. data/lib/pg_trunk/operations/views/rename_view.rb +58 -0
  127. data/lib/pg_trunk/operations/views.rb +14 -0
  128. data/lib/pg_trunk/operations.rb +23 -0
  129. data/lib/pg_trunk/version.rb +6 -0
  130. data/lib/pg_trunk.rb +27 -0
  131. data/pg_trunk.gemspec +34 -0
  132. data/spec/dummy/.gitignore +16 -0
  133. data/spec/dummy/Rakefile +15 -0
  134. data/spec/dummy/bin/bundle +6 -0
  135. data/spec/dummy/bin/rails +6 -0
  136. data/spec/dummy/bin/rake +6 -0
  137. data/spec/dummy/config/application.rb +18 -0
  138. data/spec/dummy/config/boot.rb +7 -0
  139. data/spec/dummy/config/database.yml +14 -0
  140. data/spec/dummy/config/environment.rb +7 -0
  141. data/spec/dummy/config.ru +6 -0
  142. data/spec/dummy/db/materialized_views/admin_users_v01.sql +1 -0
  143. data/spec/dummy/db/migrate/.keep +0 -0
  144. data/spec/dummy/db/schema.rb +18 -0
  145. data/spec/dummy/db/views/admin_users_v01.sql +1 -0
  146. data/spec/dummy/db/views/admin_users_v02.sql +1 -0
  147. data/spec/operations/check_constraints/add_check_constraint_spec.rb +85 -0
  148. data/spec/operations/check_constraints/drop_check_constraint_spec.rb +111 -0
  149. data/spec/operations/check_constraints/rename_check_constraint_spec.rb +90 -0
  150. data/spec/operations/composite_types/change_composite_type_spec.rb +257 -0
  151. data/spec/operations/composite_types/create_composite_type_spec.rb +55 -0
  152. data/spec/operations/composite_types/drop_composite_type_spec.rb +109 -0
  153. data/spec/operations/composite_types/rename_composite_type_spec.rb +74 -0
  154. data/spec/operations/dependency_resolver_spec.rb +177 -0
  155. data/spec/operations/domains/change_domain_spec.rb +287 -0
  156. data/spec/operations/domains/create_domain_spec.rb +69 -0
  157. data/spec/operations/domains/drop_domain_spec.rb +119 -0
  158. data/spec/operations/domains/rename_domain_spec.rb +70 -0
  159. data/spec/operations/enums/change_enum_spec.rb +157 -0
  160. data/spec/operations/enums/create_enum_spec.rb +40 -0
  161. data/spec/operations/enums/drop_enum_spec.rb +120 -0
  162. data/spec/operations/enums/rename_enum_spec.rb +72 -0
  163. data/spec/operations/foreign_keys/add_foreign_key_spec.rb +208 -0
  164. data/spec/operations/foreign_keys/drop_foreign_key_spec.rb +167 -0
  165. data/spec/operations/foreign_keys/rename_foreign_key_spec.rb +101 -0
  166. data/spec/operations/functions/change_function_spec.rb +166 -0
  167. data/spec/operations/functions/create_function_spec.rb +192 -0
  168. data/spec/operations/functions/drop_function_spec.rb +182 -0
  169. data/spec/operations/functions/rename_function_spec.rb +101 -0
  170. data/spec/operations/indexes/add_index_spec.rb +94 -0
  171. data/spec/operations/materialized_views/change_materialized_view_spec.rb +190 -0
  172. data/spec/operations/materialized_views/create_materialized_view_spec.rb +144 -0
  173. data/spec/operations/materialized_views/drop_materialized_view_spec.rb +145 -0
  174. data/spec/operations/materialized_views/refresh_materialized_view_spec.rb +79 -0
  175. data/spec/operations/materialized_views/rename_materialized_view_spec.rb +88 -0
  176. data/spec/operations/procedures/change_procedure_spec.rb +175 -0
  177. data/spec/operations/procedures/create_procedure_spec.rb +151 -0
  178. data/spec/operations/procedures/drop_procedure_spec.rb +159 -0
  179. data/spec/operations/procedures/rename_procedure_spec.rb +107 -0
  180. data/spec/operations/statistics/create_statistics_spec.rb +230 -0
  181. data/spec/operations/statistics/drop_statistics_spec.rb +106 -0
  182. data/spec/operations/statistics/rename_statistics_spec.rb +129 -0
  183. data/spec/operations/tables/create_table_spec.rb +53 -0
  184. data/spec/operations/tables/rename_table_spec.rb +37 -0
  185. data/spec/operations/triggers/change_trigger_spec.rb +195 -0
  186. data/spec/operations/triggers/create_trigger_spec.rb +104 -0
  187. data/spec/operations/triggers/drop_trigger_spec.rb +124 -0
  188. data/spec/operations/triggers/rename_trigger_spec.rb +160 -0
  189. data/spec/operations/views/change_view_spec.rb +144 -0
  190. data/spec/operations/views/create_view_spec.rb +134 -0
  191. data/spec/operations/views/drop_view_spec.rb +146 -0
  192. data/spec/operations/views/rename_view_spec.rb +85 -0
  193. data/spec/pg_trunk/dependencies_resolver_spec.rb +43 -0
  194. data/spec/spec_helper.rb +28 -0
  195. data/spec/support/migrations_helper.rb +376 -0
  196. metadata +348 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 98c9050bc62e8f9a33f87ff77a836189fca018a968ff1fd487f1e5b613b1278f
4
+ data.tar.gz: 30bcc2a1d61cc3343a95e752d8307c20b1326b57969ac0479a3e4ef161026747
5
+ SHA512:
6
+ metadata.gz: a4ba64e08cb9a12ce958e1a4a13a88370e4a20e8fe25cf9da19731c5e77ea8d952decabaebd89c6c0af545f34e955f274a768ad28282345e0365ef57f314d69b
7
+ data.tar.gz: 62289de65886d00d28a979149909839f237afdd9e1144f61710306f4da4258e9487da36e07ef21f46e90b86f63cd6b18a17db59317728eac56ce37524cdbc60a
@@ -0,0 +1,87 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+ branches:
9
+ - "*"
10
+
11
+ jobs:
12
+ build:
13
+ name: Ruby ${{ matrix.ruby }}, Rails ${{ matrix.rails }}, PostgreSQL ${{ matrix.postgres }}
14
+
15
+ strategy:
16
+ fail-fast: true
17
+ matrix:
18
+ ruby:
19
+ - "3.0"
20
+ rails:
21
+ - "7.0"
22
+ postgres:
23
+ - 10
24
+ - 11
25
+ - 12
26
+ - 13
27
+ - 14
28
+ include: # for backward-compatibility
29
+ - ruby: "2.7"
30
+ rails: "5.2"
31
+ postgres: 10
32
+ - ruby: "3.0"
33
+ rails: "6.1"
34
+ postgres: 10
35
+
36
+ runs-on: ubuntu-latest
37
+
38
+ services:
39
+ postgres:
40
+ image: postgres:${{ matrix.postgres }}
41
+ env:
42
+ POSTGRES_USER: postgres
43
+ POSTGRES_PASSWORD: postgres
44
+ ports:
45
+ - 5432:5432
46
+ options: >-
47
+ --health-cmd pg_isready
48
+ --health-interval 10s
49
+ --health-timeout 5s
50
+ --health-retries 5
51
+
52
+ env:
53
+ RAILS_VERSION: ${{ matrix.rails }}
54
+ POSTGRES_USER: "postgres"
55
+ POSTGRES_PASSWORD: "postgres"
56
+
57
+ steps:
58
+ - name: Checkout
59
+ uses: actions/checkout@v2
60
+
61
+ - name: Install Ruby ${{ matrix.ruby }}
62
+ uses: ruby/setup-ruby@v1.61.1
63
+ with:
64
+ ruby-version: ${{ matrix.ruby }}
65
+
66
+ - name: Install dependent libraries
67
+ run: sudo apt-get install libpq-dev
68
+
69
+ - name: Generate lockfile
70
+ run: bundle lock
71
+
72
+ - name: Cache dependencies
73
+ uses: actions/cache@v1
74
+ with:
75
+ path: vendor/bundle
76
+ key: bundle-${{ hashFiles('Gemfile.lock') }}
77
+
78
+ - name: Set up PGTrunk
79
+ run: bin/setup
80
+
81
+ - name: Check code style
82
+ run: bundle exec rubocop
83
+ continue-on-error: false
84
+
85
+ - name: Run tests
86
+ run: bundle exec rake --trace
87
+ continue-on-error: false
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /gemfiles/*.gemfile.lock
7
+ /Gemfile.lock
8
+ /tmp/
9
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --require spec_helper
3
+ --order random
4
+ --warning
data/.rubocop.yml ADDED
@@ -0,0 +1,92 @@
1
+ ---
2
+ AllCops:
3
+ NewCops: enable
4
+ TargetRubyVersion: 2.7
5
+
6
+ Lint/AmbiguousBlockAssociation:
7
+ IgnoredMethods:
8
+ - change
9
+
10
+ # Enable long'n'complex methods in operations
11
+ # because we made those definitions using a DSL
12
+ # which 'regularizes' a code, so we can afford that complexity.
13
+
14
+ Metrics/BlockLength:
15
+ # these methods should wrap a lot of definitions by design
16
+ IgnoredMethods:
17
+ - class_methods
18
+ - configure
19
+ - context
20
+ - describe
21
+ - define
22
+ Exclude:
23
+ - lib/pg_trunk/operations/**/*.rb
24
+
25
+ Metrics/AbcSize:
26
+ Exclude:
27
+ - lib/pg_trunk/operations/**/*.rb
28
+
29
+ Metrics/ClassLength:
30
+ Exclude:
31
+ - spec/**/*_spec.rb
32
+ - lib/pg_trunk/operations/**/*.rb
33
+
34
+ Metrics/CyclomaticComplexity:
35
+ Exclude:
36
+ - lib/pg_trunk/operations/**/*.rb
37
+
38
+ Metrics/MethodLength:
39
+ Exclude:
40
+ - lib/pg_trunk/operations/**/*.rb
41
+
42
+ Metrics/PerceivedComplexity:
43
+ Exclude:
44
+ - lib/pg_trunk/operations/**/*.rb
45
+
46
+ # Enable long modules in specs
47
+ Metrics/ModuleLength:
48
+ Exclude:
49
+ - spec/**/*_spec.rb
50
+
51
+ # Start class definitions from inline
52
+ # private def initialize(...)
53
+ Style/AccessModifierDeclarations:
54
+ Enabled: false
55
+
56
+ # Prefer the following style:
57
+ #
58
+ # module Foo:Bar # directly accessible from Baz
59
+ # class Baz
60
+ # # ...
61
+ Style/ClassAndModuleChildren:
62
+ Enabled: false
63
+
64
+ # The convention is too opinionated
65
+ Style/DocumentDynamicEvalDefinition:
66
+ Enabled: false
67
+
68
+ # The convention is too opinionated
69
+ Style/EmptyCaseCondition:
70
+ Enabled: false
71
+
72
+ Style/EmptyMethod:
73
+ EnforcedStyle: compact
74
+
75
+ Style/ModuleFunction:
76
+ EnforcedStyle: extend_self
77
+
78
+ Style/StringLiterals:
79
+ EnforcedStyle: double_quotes
80
+
81
+ Style/TrailingCommaInArguments:
82
+ EnforcedStyleForMultiline: consistent_comma
83
+
84
+ Style/TrailingCommaInArrayLiteral:
85
+ EnforcedStyleForMultiline: consistent_comma
86
+
87
+ Style/TrailingCommaInHashLiteral:
88
+ EnforcedStyleForMultiline: consistent_comma
89
+
90
+ Style/WordArray:
91
+ Exclude:
92
+ - spec/features/**/*
data/.yardopts ADDED
@@ -0,0 +1,4 @@
1
+ --hide-api private
2
+ --exclude templates
3
+ --markup markdown
4
+ --markup-provider redcarpet
data/CHANGELOG.md ADDED
@@ -0,0 +1,31 @@
1
+ # Changelog
2
+
3
+ The noteworthy changes for each PGTrunk version are included here.
4
+ The format is based on [Keep a Changelog] and this project adheres to [Semantic Versioning].
5
+ For a complete changelog, see the [commits] for each version via the version links.
6
+
7
+ ## [0.1.0] (2022-01-14)
8
+
9
+ This is a first public release (nepalez)
10
+
11
+ Supported features:
12
+
13
+ - tables
14
+ - indexes (separated from tables)
15
+ - check constraints (separated from tables)
16
+ - foreign keys (including multi-column ones)
17
+ - views
18
+ - materialized views
19
+ - functions
20
+ - procedures
21
+ - triggers
22
+ - custom statistics
23
+ - enumerable types
24
+ - composite types
25
+ - domains types
26
+
27
+ [0.1.0]: https://github.com/nepalez/pg_trunk/releases/tag/v0.1.0
28
+
29
+ [Keep a Changelog]: http://keepachangelog.com/
30
+ [Semantic Versioning]: http://semver.org/
31
+ [commits]: https://github.com/nepalez/pg_trunk/commits/master
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,17 @@
1
+ # Contributing
2
+
3
+ 1. Fork the repository.
4
+ 2. Run `bin/setup`, which will install dependencies and create the dummy
5
+ application database.
6
+ 3. Run `rake` to verify that the tests pass against the version of Rails you are
7
+ running locally, and that the code is styled properly.
8
+ 4. Make your change with new passing tests, following the existing style.
9
+ 5. Write a [good commit message], push your fork, and submit a pull request.
10
+ 6. CI will run the test suite on all configured versions of Ruby and Rails.
11
+ Address any failures.
12
+
13
+ [good commit message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
14
+
15
+ Others will give constructive feedback. This is a time for discussion and
16
+ improvements, and making the necessary changes will be required before we can
17
+ merge the contribution.
data/Gemfile ADDED
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in pg_trunk.gemspec
6
+ gemspec
7
+
8
+ gem "appraisal", "~> 2.3.0"
9
+ gem "bundler", ">= 1.5"
10
+ gem "database_cleaner"
11
+ gem "pg"
12
+ gem "pry"
13
+ gem "pry-byebug"
14
+ gem "rake"
15
+ gem "redcarpet"
16
+ gem "rspec", ">= 3.3"
17
+ gem "rspec-its"
18
+ gem "rubocop"
19
+ gem "rubocop-rake"
20
+ gem "rubocop-rspec"
21
+ gem "test-prof"
22
+ gem "yard"
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Andrew Kozin (nepalez)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,141 @@
1
+ # PGTrunk
2
+
3
+ Empower PostgreSQL migrations in Rails app
4
+
5
+ <a href="https://evilmartians.com/">
6
+ <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
7
+
8
+ [![Gem Version][gem-badger]][gem]
9
+ [![Build Status][build-badger]][build]
10
+
11
+ PGTrunk adds methods to `ActiveRecord::Migration` to create and manage
12
+ various PostgreSQL objects (like views, functions, triggers, statistics, types etc.)
13
+ in Rails.
14
+
15
+ This gem is greatly influenced by the [Scenic], [F(x)] and [ActiveRecord::PostgtresEnum] projects
16
+ but takes some steps further.
17
+
18
+ In addition to support of different objects, we are solving a problem of interdependency between them.
19
+ For example, you can create a table, then a function using its type as an argument,
20
+ then check constraint and index using the function:
21
+
22
+ ```ruby
23
+ create_table "users" do |t|
24
+ t.text "first_name"
25
+ t.text "last_name"
26
+ end
27
+
28
+ # depends on the `users` table
29
+ create_function "full_name(u users) text" do |f|
30
+ f.volatility :immutable
31
+ f.strict true
32
+ f.parallel :safe
33
+ f.body <<~SQL.strip
34
+ string_trim(
35
+ SELECT COALESCE(u.first_name, '') + '.' + COALESCE(u.second_name, ''),
36
+ '.'
37
+ )
38
+ SQL
39
+ end
40
+
41
+ # both objects below depend on the `users` and `full_name(users)`
42
+ # so they couldn't be placed inside the `create_table` definition in the schema.
43
+
44
+ create_index "users", "full_name(users.*)", unique: true
45
+
46
+ # users.full_name is the PostgreSQL alternative syntax for the `full_name(users.*)`
47
+ create_check_constraint "users", "length(users.full_name) > 0", name: "full_name_present"
48
+ ```
49
+
50
+ Notice, that we had to separate definitions of indexes and check constraints from tables,
51
+ because there can be other objects (like functions or types) squeezing between them.
52
+
53
+ Another difference from aforementioned gems is that we explicitly register
54
+ all objects created by migrations in the special table (`pg_trunk`).
55
+ This let us distinct objects created by "regular" migration from temporary ones
56
+ added manually and exclude the latter from the schema. We bind any object
57
+ to a particular version of migration which added it. That's how only those
58
+ objects that belong to the current branch are dumped into the `schema.rb`.
59
+
60
+ As of today we support creation, modification and dropping the following objects:
61
+
62
+ - tables
63
+ - indexes
64
+ - foreign keys (including multi-column ones)
65
+ - check constraints
66
+ - views
67
+ - materialized views
68
+ - functions
69
+ - procedures
70
+ - triggers
71
+ - custom statistics
72
+ - enumerable types
73
+ - composite types
74
+ - domains types
75
+
76
+ For `tables` and `indexes` we reuse the ActiveRecord's native methods.
77
+ For `check constraints` and `foreign keys` we support both the native definitions inside the table
78
+ and standalone methods (like `create_foreign_key`) with additional features.
79
+ The other methods are implemented from scratch.
80
+
81
+ In the future other objects like aggregate functions, range types, operators, collations, and more
82
+ will be supported.
83
+
84
+ From now and on we support all versions of PostgreSQL since v10.
85
+
86
+ The gem is targeted to support PostgreSQL-specific features, that's why we won't provide adapters to other databases like [Scenic] does.
87
+
88
+ ## Documentation
89
+
90
+ The gem provides a lot of additional methods to create, rename, change a drop various objects.
91
+ You can find the necessary details in the gem's [wiki].
92
+
93
+ ## Installation
94
+
95
+ Add this line to your application's Gemfile:
96
+
97
+ ```ruby
98
+ gem 'pg_trunk'
99
+ ```
100
+
101
+ And then execute:
102
+
103
+ ```shell
104
+ $ bundle install
105
+ ```
106
+
107
+ Or install it yourself as:
108
+
109
+ ```shell
110
+ $ gem install pg_trunk
111
+ ```
112
+
113
+ Add the line somewhere in your ruby code:
114
+
115
+ ```ruby
116
+ require "pg_trunk"
117
+ ```
118
+
119
+ ## Development
120
+
121
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
122
+
123
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
124
+
125
+ ## Contributing
126
+
127
+ Bug reports and pull requests are welcome on GitHub at `https://github.com/nepalez/pg_trunk`.
128
+
129
+ ## License
130
+
131
+ The gem is available as open source under the terms of the [MIT License].
132
+
133
+ [build-badger]: https://github.com/nepalez/pg_trunk/workflows/CI/badge.svg
134
+ [build]: https://github.com/nepalez/pg_trunk/actions?query=workflow%3ACI+branch%3Amaster
135
+ [gem-badger]: https://img.shields.io/gem/v/pg_trunk.svg?style=flat
136
+ [gem]: https://rubygems.org/gems/pg_trunk
137
+ [MIT License]: https://opensource.org/licenses/MIT
138
+ [Scenic]: https://github.com/scenic-views/scenic
139
+ [F(x)]: https://github.com/teoljungberg/fx
140
+ [ActiveRecord::PostgtresEnum]: https://github.com/bibendi/activerecord-postgres_enum
141
+ [wiki]: https://github.com/nepalez/pg_trunk/wiki
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ namespace :dummy do
7
+ require_relative "spec/dummy/config/application"
8
+ Dummy::Application.load_tasks
9
+ end
10
+
11
+ task(:spec).clear
12
+ desc "Run specs"
13
+ RSpec::Core::RakeTask.new(:spec) { |task| task.verbose = false }
14
+
15
+ desc "Run the specs on the dummy database"
16
+ task default: %w[dummy:db:reset spec]
data/bin/console ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "pg_trunk"
6
+ require "pry"
7
+
8
+ Pry.start
data/bin/rake ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rake' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||=
13
+ File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath)
14
+
15
+ require "rubygems"
16
+ require "bundler/setup"
17
+
18
+ # noinspection RubyResolve
19
+ load Gem.bin_path("rake", "rake")
data/bin/rspec ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rspec' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||=
13
+ File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath)
14
+
15
+ require "rubygems"
16
+ require "bundler/setup"
17
+
18
+ # noinspection RubyResolve
19
+ load Gem.bin_path("rspec-core", "rspec")
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/bin/yard ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'yard' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||=
13
+ File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath)
14
+
15
+ require "rubygems"
16
+ require "bundler/setup"
17
+
18
+ # noinspection RubyResolve
19
+ load Gem.bin_path("yard", "yard")
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PGTrunk
4
+ # @private
5
+ # PGTrunk database adapters.
6
+ #
7
+ # PGTrunk ships with a Postgres adapter only,
8
+ # with interface implemented as +PGTrunk::Adapters::Postgres+.
9
+ #
10
+ module Adapters
11
+ # Creates an instance of the PGTrunk Postgres adapter.
12
+ # This is the only supported adapter for PGTrunk.
13
+ #
14
+ # @param [#connection] connectable An object that returns the connection
15
+ # for PGTrunk to use. Defaults to `ActiveRecord::Base`.
16
+ #
17
+ class Postgres
18
+ # Decorates an ActiveRecord connection with methods that help determine
19
+ # the connections capabilities.
20
+ #
21
+ # Every attempt is made to use the versions of these methods defined by
22
+ # Rails where they are available and public before falling back to our own
23
+ # implementations for older Rails versions.
24
+ #
25
+ # @private
26
+ class Connection < SimpleDelegator
27
+ def server_version
28
+ raw_connection.server_version.to_s
29
+ end
30
+
31
+ # Expose private method helpers
32
+
33
+ def check_constraint_name(table, expression)
34
+ __getobj__.send(
35
+ :check_constraint_name,
36
+ table,
37
+ expression: expression,
38
+ )
39
+ end
40
+
41
+ def strip_table_name(table)
42
+ __getobj__.send(:strip_table_name_prefix_and_suffix, table)
43
+ end
44
+ end
45
+
46
+ # Execute operation by its definition
47
+ # @param [Class < PgExtra::Operation] operation
48
+ def execute_operation(operation)
49
+ query = operation.to_sql(server_version)
50
+ connection.execute(query) if query
51
+ end
52
+
53
+ def dumper
54
+ # This instance is used to dump the table
55
+ # using its name extracted from the database.
56
+ # That's why we can skip prefix/suffix definitions
57
+ # in the parameters of the constructor.
58
+ @dumper ||= connection.create_schema_dumper({})
59
+ end
60
+
61
+ private
62
+
63
+ attr_reader :connectable
64
+
65
+ def connection
66
+ @connection ||= Connection.new(ActiveRecord::Base.connection)
67
+ end
68
+
69
+ def respond_to_missing?(symbol, *)
70
+ connection.respond_to?(symbol, true)
71
+ end
72
+
73
+ def method_missing(symbol, *args, **opts, &block)
74
+ super unless connection.respond_to?(symbol, true)
75
+
76
+ connection.send(symbol, *args, **opts, &block)
77
+ end
78
+ end
79
+ end
80
+ end