pg_trunk 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +4 -15
  3. data/CHANGELOG.md +6 -0
  4. data/README.md +1 -0
  5. data/lib/pg_trunk/operations/check_constraints/add_check_constraint.rb +3 -3
  6. data/lib/pg_trunk/operations/check_constraints/drop_check_constraint.rb +4 -4
  7. data/lib/pg_trunk/operations/check_constraints/rename_check_constraint.rb +2 -2
  8. data/lib/pg_trunk/operations/check_constraints/validate_check_constraint.rb +1 -1
  9. data/lib/pg_trunk/operations/composite_types/change_composite_type.rb +2 -2
  10. data/lib/pg_trunk/operations/composite_types/create_composite_type.rb +1 -1
  11. data/lib/pg_trunk/operations/composite_types/drop_composite_type.rb +3 -3
  12. data/lib/pg_trunk/operations/composite_types/rename_composite_type.rb +1 -1
  13. data/lib/pg_trunk/operations/domains/create_domain.rb +5 -5
  14. data/lib/pg_trunk/operations/domains/drop_domain.rb +6 -6
  15. data/lib/pg_trunk/operations/domains/rename_domain.rb +1 -1
  16. data/lib/pg_trunk/operations/enums/create_enum.rb +2 -2
  17. data/lib/pg_trunk/operations/enums/drop_enum.rb +4 -4
  18. data/lib/pg_trunk/operations/enums/rename_enum.rb +1 -1
  19. data/lib/pg_trunk/operations/foreign_keys/add_foreign_key.rb +8 -8
  20. data/lib/pg_trunk/operations/foreign_keys/drop_foreign_key.rb +9 -9
  21. data/lib/pg_trunk/operations/foreign_keys/rename_foreign_key.rb +5 -5
  22. data/lib/pg_trunk/operations/functions/change_function.rb +1 -1
  23. data/lib/pg_trunk/operations/functions/create_function.rb +11 -11
  24. data/lib/pg_trunk/operations/functions/drop_function.rb +12 -12
  25. data/lib/pg_trunk/operations/functions/rename_function.rb +1 -1
  26. data/lib/pg_trunk/operations/materialized_views/change_materialized_view.rb +1 -1
  27. data/lib/pg_trunk/operations/materialized_views/create_materialized_view.rb +6 -6
  28. data/lib/pg_trunk/operations/materialized_views/drop_materialized_view.rb +7 -7
  29. data/lib/pg_trunk/operations/materialized_views/refresh_materialized_view.rb +2 -2
  30. data/lib/pg_trunk/operations/materialized_views/rename_materialized_view.rb +2 -2
  31. data/lib/pg_trunk/operations/procedures/change_procedure.rb +1 -1
  32. data/lib/pg_trunk/operations/procedures/create_procedure.rb +5 -5
  33. data/lib/pg_trunk/operations/procedures/drop_procedure.rb +5 -5
  34. data/lib/pg_trunk/operations/procedures/rename_procedure.rb +1 -1
  35. data/lib/pg_trunk/operations/rules/base.rb +77 -0
  36. data/lib/pg_trunk/operations/rules/create_rule.rb +155 -0
  37. data/lib/pg_trunk/operations/rules/drop_rule.rb +94 -0
  38. data/lib/pg_trunk/operations/rules/rename_rule.rb +62 -0
  39. data/lib/pg_trunk/operations/rules.rb +13 -0
  40. data/lib/pg_trunk/operations/statistics/create_statistics.rb +4 -4
  41. data/lib/pg_trunk/operations/statistics/drop_statistics.rb +5 -5
  42. data/lib/pg_trunk/operations/statistics/rename_statistics.rb +1 -1
  43. data/lib/pg_trunk/operations/triggers/change_trigger.rb +1 -1
  44. data/lib/pg_trunk/operations/triggers/create_trigger.rb +9 -9
  45. data/lib/pg_trunk/operations/triggers/drop_trigger.rb +9 -9
  46. data/lib/pg_trunk/operations/triggers/rename_trigger.rb +6 -6
  47. data/lib/pg_trunk/operations/views/change_view.rb +1 -1
  48. data/lib/pg_trunk/operations/views/create_view.rb +5 -5
  49. data/lib/pg_trunk/operations/views/drop_view.rb +7 -7
  50. data/lib/pg_trunk/operations/views/rename_view.rb +2 -2
  51. data/lib/pg_trunk/operations.rb +1 -0
  52. data/lib/pg_trunk/version.rb +1 -1
  53. data/pg_trunk.gemspec +0 -1
  54. data/spec/operations/rules/create_rule_spec.rb +119 -0
  55. data/spec/operations/rules/drop_rule_spec.rb +117 -0
  56. data/spec/operations/rules/rename_rule_spec.rb +148 -0
  57. metadata +12 -68
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: false
2
+
3
+ module PGTrunk::Operations::Rules
4
+ # @abstract
5
+ # @private
6
+ # Base class for operations with rules
7
+ class Base < PGTrunk::Operation
8
+ attribute :command, :string
9
+ attribute :event, :pg_trunk_symbol
10
+ attribute :kind, :pg_trunk_symbol
11
+ attribute :replace_existing, :boolean
12
+ attribute :table, :pg_trunk_qualified_name
13
+ attribute :where, :string
14
+
15
+ # Generate missed name from table & expression
16
+ after_initialize { self.name = generated_name if name.blank? }
17
+
18
+ # Ensure correctness of present values
19
+ # The table must be defined because the name only
20
+ # is not enough to identify the constraint.
21
+ validates :if_not_exists, absence: true
22
+ validates :table, :name, presence: true
23
+ validates :kind, inclusion: { in: %i[instead also] }, allow_nil: true
24
+ validates :event, inclusion: { in: %i[insert update delete] }, allow_nil: true
25
+
26
+ # By default foreign keys are sorted by tables and names.
27
+ def <=>(other)
28
+ return unless other.is_a?(self.class)
29
+
30
+ result = table <=> other.table
31
+ result.zero? ? super : result
32
+ end
33
+
34
+ # Support `table` and `name` in positional arguments
35
+ # @example
36
+ # create_rule :users, "_do_nothing"
37
+ ruby_params :table, :name
38
+
39
+ # Snippet to be used in all operations with rules
40
+ ruby_snippet do |s|
41
+ s.ruby_param(table.lean) if table.present?
42
+ s.ruby_param(name.name) if custom_name?
43
+ s.ruby_param(if_exists: true) if if_exists
44
+ s.ruby_param(replace_existing: true) if replace_existing
45
+ s.ruby_param(force: :cascade) if force == :cascade
46
+
47
+ s.ruby_line(:event, event) if event.present?
48
+ s.ruby_line(:kind, :instead) if kind == :instead
49
+ s.ruby_line(:where, where) if where.present?
50
+ s.ruby_line(:command, command) if command.present?
51
+ s.ruby_line(:comment, comment) if comment.present?
52
+ end
53
+
54
+ private
55
+
56
+ # *************************************************************************
57
+ # Helpers for operation definitions
58
+ # *************************************************************************
59
+
60
+ def generated_name
61
+ return @generated_name if instance_variable_defined?(:@generated_name)
62
+
63
+ @generated_name = begin
64
+ return if table.blank? || event.blank?
65
+
66
+ key_options = { event: event, kind: (kind || :also) }
67
+ identifier = "#{table.lean}_#{key_options}_rule"
68
+ hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
69
+ PGTrunk::QualifiedName.wrap("rule_rails_#{hashed_identifier}")
70
+ end
71
+ end
72
+
73
+ def custom_name?(qname = name)
74
+ qname&.differs_from?(/^rule_rails_\w+$/)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: false
2
+
3
+ # @!parse
4
+ # class ActiveRecord::Migration
5
+ # # Create a rule
6
+ # #
7
+ # # @param [#to_s] table (nil) The qualified name of the table
8
+ # # @param [#to_s] name (nil) The name of the rule (unique within the table)
9
+ # # @option options [Boolean] :replace_existing (false) If the rule should overwrite an existing one
10
+ # # @option options [Symbol] :event (nil) The type of the query the rule is applied to.
11
+ # # Supported values: :update, :insert, :delete
12
+ # # @option options [Symbol] :kind (:also) The kind of the rule (either :also or :instead).
13
+ # # In case of `instead` the original query wouldn't be executed, only the `command` is.
14
+ # # @option options [String] :where (nil) The condition (SQL) for the rule to be applied.
15
+ # # @option options [String] :command (nil) The SQL command to be added by the rule.
16
+ # # @yield [r] the block with the rule's definition
17
+ # # @yieldparam Object receiver of methods specifying the procedure
18
+ # # @return [void]
19
+ # #
20
+ # # @notice `SELECT` rules are not supported by the gem.
21
+ # #
22
+ # # To create a rule you must define table, and event (operation) for the rule.
23
+ # # Usually you also supposed to define a command, but in case the `kind` is set
24
+ # # to `:instead`, missing the command would provide `INSTEAD DO NOTHING` rule.
25
+ # #
26
+ # # ```ruby
27
+ # # create_rule "users" do |r|
28
+ # # r.event :insert
29
+ # # r.kind :instead
30
+ # # r.comment "Forbid insertion to the table"
31
+ # # SQL
32
+ # # ```
33
+ # #
34
+ # # By default the kind is set to `:also`, in this case the `command` is needed as well:
35
+ # #
36
+ # # ```ruby
37
+ # # create_rule "users", "_count_insertion" do |r|
38
+ # # r.event :insert
39
+ # # r.command <<~SQL
40
+ # # UPDATE counters SET user_inserts = user_inserts + 1
41
+ # # SQL
42
+ # # r.comment "Count insertion to the table"
43
+ # # SQL
44
+ # # ```
45
+ # #
46
+ # # With a `when` option you can also specify a condition:
47
+ # #
48
+ # # ```ruby
49
+ # # create_rule "users", "_forbid_grants" do |r|
50
+ # # r.event :update
51
+ # # r.kind :instead
52
+ # # r.where "NOT old.admin AND new.admin"
53
+ # # r.comment "Forbid granting admin rights"
54
+ # # SQL
55
+ # # ```
56
+ # #
57
+ # # With a `replace_existing: true` option,
58
+ # # the rule will be created using the `CREATE OR REPLACE` clause.
59
+ # # In this case the migration is irreversible because we
60
+ # # don't know if and how to restore the previous definition.
61
+ # #
62
+ # # ```ruby
63
+ # # create_rule "users", "_forbid_insertion", replace_existing: true do |r|
64
+ # # r.event :insert
65
+ # # r.kind :instead
66
+ # # r.comment "Forbid insertion to the table"
67
+ # # SQL
68
+ # # ```
69
+ # def create_rule(table, name = nil, **options, &block); end
70
+ # end
71
+ module PGTrunk::Operations::Rules
72
+ # @private
73
+ class CreateRule < Base
74
+ validates :if_exists, :force, :new_name, absence: true
75
+ validates :event, presence: true
76
+ validate do
77
+ errors.add :command, :blank if kind != :instead && command.blank?
78
+ end
79
+
80
+ from_sql do |_server_version|
81
+ <<~SQL
82
+ SELECT
83
+ r.oid,
84
+ (c.relnamespace::regnamespace || '.' || c.relname) AS table,
85
+ r.rulename AS name,
86
+ (
87
+ CASE
88
+ WHEN r.ev_type = '1' THEN 'select'
89
+ WHEN r.ev_type = '2' THEN 'update'
90
+ WHEN r.ev_type = '3' THEN 'insert'
91
+ WHEN r.ev_type = '4' THEN 'delete'
92
+ END
93
+ ) AS event,
94
+ ( CASE WHEN r.is_instead THEN 'instead' ELSE 'also' END ) AS kind,
95
+ pg_get_expr(r.ev_qual, r.oid, true) AS "where",
96
+ regexp_replace(
97
+ regexp_replace(
98
+ pg_get_ruledef(r.oid, true),
99
+ '.+ DO +(INSTEAD +)?(ALSO +)?(NOTHING *)?| *;',
100
+ '',
101
+ 'g'
102
+ ), '(\n|\s)+', ' ', 'g'
103
+ ) AS command,
104
+ d.description AS comment
105
+ FROM pg_rewrite r
106
+ JOIN pg_class c ON c.oid = r.ev_class
107
+ JOIN pg_trunk t ON t.oid = r.oid
108
+ AND t.classid = 'pg_rewrite'::regclass
109
+ LEFT JOIN pg_description d ON d.objoid = r.oid
110
+ AND d.classoid = 'pg_rewrite'::regclass
111
+ SQL
112
+ end
113
+
114
+ def to_sql(_server_version)
115
+ [create_rule, *comment_rule, register_rule].join(" ")
116
+ end
117
+
118
+ def invert
119
+ irreversible!("replace_existing: true") if replace_existing
120
+ DropRule.new(**to_h)
121
+ end
122
+
123
+ private
124
+
125
+ def create_rule
126
+ sql = "CREATE"
127
+ sql << " OR REPLACE" if replace_existing
128
+ sql << " RULE #{name.to_sql} AS ON #{event.to_s.upcase}"
129
+ sql << " TO #{table.to_sql}"
130
+ sql << " WHERE #{where}" if where.present?
131
+ sql << " DO #{kind == :instead ? 'INSTEAD' : 'ALSO'}"
132
+ sql << " #{command.presence || 'NOTHING'}"
133
+ sql << ";"
134
+ end
135
+
136
+ def comment_rule
137
+ <<~SQL.squish if comment.present?
138
+ COMMENT ON RULE #{name.to_sql} ON #{table.to_sql}#{' '}
139
+ IS $comment$#{comment}$comment$;
140
+ SQL
141
+ end
142
+
143
+ def register_rule
144
+ <<~SQL.squish
145
+ INSERT INTO pg_trunk (oid, classid)
146
+ SELECT r.oid, 'pg_rewrite'::regclass
147
+ FROM pg_rewrite r JOIN pg_class c ON c.oid = r.ev_class
148
+ WHERE r.rulename = #{name.quoted}
149
+ AND c.relname = '#{table.name}'
150
+ AND c.relnamespace = #{table.namespace}
151
+ ON CONFLICT DO NOTHING;
152
+ SQL
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: false
2
+
3
+ # @!parse
4
+ # class ActiveRecord::Migration
5
+ # # Drop a rule
6
+ # #
7
+ # # @param [#to_s] table (nil) The qualified name of the table
8
+ # # @param [#to_s] name (nil) The name of the rule (unique within the table)
9
+ # # @option options [Boolean] :if_exists (false) Suppress the error when the rule is absent.
10
+ # # @option options [Symbol] :force (:restrict) Define how to process dependent objects
11
+ # # Supported values: :restrict (default), :cascade (for cascade deletion)
12
+ # # @option options [Symbol] :event (nil) The type of the query the rule is applied to.
13
+ # # Supported values: :update, :insert, :delete
14
+ # # @option options [Symbol] :kind (:also) The kind of the rule (either :also or :instead).
15
+ # # In case of `instead` the original query wouldn't be executed, only the `command` is.
16
+ # # @option options [String] :where (nil) The condition (SQL) for the rule to be applied.
17
+ # # @option options [String] :command (nil) The SQL command to be added by the rule.
18
+ # # @yield [r] the block with the rule's definition
19
+ # # @yieldparam Object receiver of methods specifying the procedure
20
+ # # @return [void]
21
+ # #
22
+ # # The rule can be identified by the table and explicit name
23
+ # #
24
+ # # ```ruby
25
+ # # drop_rule :users, "_forbid_insertion"
26
+ # # ```
27
+ # #
28
+ # # Alternatively the name can be got from kind and event.
29
+ # #
30
+ # # ```ruby
31
+ # # drop_rule :users do |r|
32
+ # # r.event :insert
33
+ # # r.kind :instead
34
+ # # r.comment "Forbid insertion to the table"
35
+ # # end
36
+ # # ```
37
+ # #
38
+ # # To made operation reversible all the necessary parameters must be provided
39
+ # # like in the `create_rule` operation:
40
+ # #
41
+ # # ```ruby
42
+ # # drop_rule "users", "_count_insertion" do |r|
43
+ # # r.event :insert
44
+ # # r.command <<~SQL
45
+ # # UPDATE counters SET user_inserts = user_inserts + 1
46
+ # # SQL
47
+ # # r.comment "Count insertion to the table"
48
+ # # SQL
49
+ # # ```
50
+ # #
51
+ # # The operation can be called with `if_exists` option.
52
+ # #
53
+ # # ```ruby
54
+ # # drop_rule :users, if_exists: true do |r|
55
+ # # # event and kind here are used to define a name
56
+ # # r.event :insert
57
+ # # r.kind :instead
58
+ # # end
59
+ # # ```
60
+ # #
61
+ # # With the `force: :cascade` option the operation would remove
62
+ # # all the objects that use the type.
63
+ # #
64
+ # # ```ruby
65
+ # # drop_rule :users, force: :cascade do |r|
66
+ # # r.event :insert
67
+ # # r.kind :instead
68
+ # # end
69
+ # # ```
70
+ # #
71
+ # # In both cases the operation becomes irreversible due to
72
+ # # uncertainty of the previous state of the database.
73
+ # def drop_rule(table, name = nil, **options, &block); end
74
+ # end
75
+ module PGTrunk::Operations::Rules
76
+ # @private
77
+ class DropRule < Base
78
+ validates :replace_existing, :new_name, absence: true
79
+
80
+ def to_sql(_version)
81
+ sql = "DROP RULE"
82
+ sql << " IF EXISTS" if if_exists
83
+ sql << " #{name.name.inspect} ON #{table.to_sql}"
84
+ sql << " CASCADE" if force == :cascade
85
+ sql << ";"
86
+ end
87
+
88
+ def invert
89
+ irreversible!("if_exists: true") if if_exists
90
+ irreversible!("force: :cascade") if force == :cascade
91
+ CreateRule.new(**to_h.except(:force))
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: false
2
+
3
+ # @!parse
4
+ # class ActiveRecord::Migration
5
+ # # Rename a rule
6
+ # #
7
+ # # @param [#to_s] table (nil) The qualified name of the table
8
+ # # @param [#to_s] name (nil) The current name of the rule
9
+ # # @option options [#to_s] :to (nil) The new name for the rule
10
+ # # @yield [c] the block with the constraint's definition
11
+ # # @yieldparam Object receiver of methods specifying the constraint
12
+ # # @return [void]
13
+ # #
14
+ # # A constraint can be identified by the table and explicit name
15
+ # #
16
+ # # ```ruby
17
+ # # rename_rule :users, "_forbid_insertion", to: "_skip_insertion"
18
+ # # ```
19
+ # #
20
+ # # Alternatively the name can be got from the event and kind.
21
+ # #
22
+ # # ```ruby
23
+ # # rename_rule :users, to: "_skip_insertion" do |r|
24
+ # # r.event :insert
25
+ # # r.kind :instead
26
+ # # end
27
+ # # ```
28
+ # #
29
+ # # The name can be reset to auto-generated when
30
+ # # the `:to` option is missed or blank:
31
+ # #
32
+ # # ```ruby
33
+ # # rename_rule :users, "_skip_insertion" do |r|
34
+ # # r.event :insert
35
+ # # r.kind :instead
36
+ # # end
37
+ # # ```
38
+ # #
39
+ # # The operation is always reversible.
40
+ # def rename_rule(table, name = nil, **options, &block); end
41
+ # end
42
+ module PGTrunk::Operations::Rules
43
+ # @private
44
+ class RenameRule < Base
45
+ after_initialize { self.new_name = generated_name if new_name.blank? }
46
+
47
+ validates :new_name, presence: true
48
+ validates :where, :command, :replace_existing, :force, :if_exists,
49
+ absence: true
50
+
51
+ def to_sql(_version)
52
+ <<~SQL
53
+ ALTER RULE #{name.to_sql} ON #{table.to_sql}
54
+ RENAME TO #{new_name.to_sql};
55
+ SQL
56
+ end
57
+
58
+ def invert
59
+ self.class.new(**to_h, name: new_name, to: name)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # nodoc
4
+ module PGTrunk::Rules
5
+ # @private
6
+ # Namespace for operations with rules
7
+ module Rules
8
+ require_relative "rules/base"
9
+ require_relative "rules/create_rule"
10
+ require_relative "rules/drop_rule"
11
+ require_relative "rules/rename_rule"
12
+ end
13
+ end
@@ -5,14 +5,14 @@
5
5
  # # Create a custom statistics
6
6
  # #
7
7
  # # @param [#to_s] name (nil) The qualified name of the statistics
8
- # # @option [Boolean] :if_not_exists (false)
8
+ # # @option options [Boolean] :if_not_exists (false)
9
9
  # # Suppress the error when the statistics is already exist
10
- # # @option [#to_s] table (nil)
10
+ # # @option options [#to_s] table (nil)
11
11
  # # The qualified name of the table whose statistics will be collected
12
- # # @option [Array<Symbol>] kinds ([:dependencies, :mcv, :ndistinct])
12
+ # # @option options [Array<Symbol>] kinds ([:dependencies, :mcv, :ndistinct])
13
13
  # # The kinds of statistics to be collected (all by default).
14
14
  # # Supported values in the array: :dependencies, :mcv, :ndistinct
15
- # # @option [#to_s] :comment The description of the statistics
15
+ # # @option options [#to_s] :comment The description of the statistics
16
16
  # # @yield [s] the block with the statistics' definition
17
17
  # # @yieldparam Object receiver of methods specifying the statistics
18
18
  # # @return [void]
@@ -5,14 +5,14 @@
5
5
  # # Drop a custom statistics
6
6
  # #
7
7
  # # @param [#to_s] name (nil) The qualified name of the statistics
8
- # # @option [Boolean] :if_exists (false) Suppress the error when the statistics is absent
9
- # # @option [Symbol] :force (:restrict) How to process dependent objects (`:cascade` or `:restrict`)
10
- # # @option [#to_s] table (nil)
8
+ # # @option options [Boolean] :if_exists (false) Suppress the error when the statistics is absent
9
+ # # @option options [Symbol] :force (:restrict) How to process dependent objects (`:cascade` or `:restrict`)
10
+ # # @option options [#to_s] table (nil)
11
11
  # # The qualified name of the table whose statistics will be collected
12
- # # @option [Array<Symbol>] kinds ([:dependencies, :mcv, :ndistinct])
12
+ # # @option options [Array<Symbol>] kinds ([:dependencies, :mcv, :ndistinct])
13
13
  # # The kinds of statistics to be collected (all by default).
14
14
  # # Supported values in the array: :dependencies, :mcv, :ndistinct
15
- # # @option [#to_s] :comment The description of the statistics
15
+ # # @option options [#to_s] :comment The description of the statistics
16
16
  # # @yield [s] the block with the statistics' definition
17
17
  # # @yieldparam Object receiver of methods specifying the statistics
18
18
  # # @return [void]
@@ -5,7 +5,7 @@
5
5
  # # Change the name and/or schema of a statistics
6
6
  # #
7
7
  # # @param [#to_s] :name (nil) The qualified name of the statistics
8
- # # @option [#to_s] :to (nil) The new qualified name for the statistics
8
+ # # @option options [#to_s] :to (nil) The new qualified name for the statistics
9
9
  # # @return [void]
10
10
  # #
11
11
  # # A custom statistics can be renamed by changing both the name
@@ -6,7 +6,7 @@
6
6
  # #
7
7
  # # @param [#to_s] table (nil) The qualified name of the table
8
8
  # # @param [#to_s] name (nil) The name of the trigger
9
- # # @option [Boolean] :if_exists (false) Suppress the error when the trigger is absent
9
+ # # @option options [Boolean] :if_exists (false) Suppress the error when the trigger is absent
10
10
  # # @yield [t] the block with the trigger's definition
11
11
  # # @yieldparam Object receiver of methods specifying the trigger
12
12
  # # @return [void]
@@ -6,19 +6,19 @@
6
6
  # #
7
7
  # # @param [#to_s] table (nil) The qualified name of the table
8
8
  # # @param [#to_s] name (nil) The name of the trigger
9
- # # @option [Boolean] :replace_existing (false) If the trigger should overwrite an existing one
10
- # # @option [#to_s] :function (nil) The qualified name of the function to be called
11
- # # @option [Symbol] :type (nil) When the trigger should be run
9
+ # # @option options [Boolean] :replace_existing (false) If the trigger should overwrite an existing one
10
+ # # @option options [#to_s] :function (nil) The qualified name of the function to be called
11
+ # # @option options [Symbol] :type (nil) When the trigger should be run
12
12
  # # Supported values: :before, :after, :instead_of
13
- # # @option [Array<Symbol>] :events List of events running the trigger
13
+ # # @option options [Array<Symbol>] :events List of events running the trigger
14
14
  # # Supported values in the array: :insert, :update, :delete, :truncate
15
- # # @option [Boolean] :constraint (false) If the trigger is a constraint
16
- # # @option [Symbol] :initially (:immediate) If the constraint check should be deferred
15
+ # # @option options [Boolean] :constraint (false) If the trigger is a constraint
16
+ # # @option options [Symbol] :initially (:immediate) If the constraint check should be deferred
17
17
  # # Supported values: :immediate (default), :deferred
18
- # # @option [#to_s] :when (nil) The SQL snippet definiing a condition for the trigger
19
- # # @option [Symbol] :for_each (:statement) Define if a trigger should be run for every row
18
+ # # @option options [#to_s] :when (nil) The SQL snippet definiing a condition for the trigger
19
+ # # @option options [Symbol] :for_each (:statement) Define if a trigger should be run for every row
20
20
  # # Supported values: :statement (default), :row
21
- # # @option [#to_s] :comment (nil) The commend describing the trigger
21
+ # # @option options [#to_s] :comment (nil) The commend describing the trigger
22
22
  # # @yield [t] the block with the trigger's definition
23
23
  # # @yieldparam Object receiver of methods specifying the trigger
24
24
  # # @return [void]
@@ -6,19 +6,19 @@
6
6
  # #
7
7
  # # @param [#to_s] table (nil) The qualified name of the table
8
8
  # # @param [#to_s] name (nil) The name of the trigger
9
- # # @option [Boolean] :if_exists (false) Suppress the error when the trigger is absent
10
- # # @option [#to_s] :function (nil) The qualified name of the function to be called
11
- # # @option [Symbol] :type (nil) When the trigger should be run
9
+ # # @option options [Boolean] :if_exists (false) Suppress the error when the trigger is absent
10
+ # # @option options [#to_s] :function (nil) The qualified name of the function to be called
11
+ # # @option options [Symbol] :type (nil) When the trigger should be run
12
12
  # # Supported values: :before, :after, :instead_of
13
- # # @option [Array<Symbol>] :events List of events running the trigger
13
+ # # @option options [Array<Symbol>] :events List of events running the trigger
14
14
  # # Supported values in the array: :insert, :update, :delete, :truncate
15
- # # @option [Boolean] :constraint (false) If the trigger is a constraint
16
- # # @option [Symbol] :initially (:immediate) If the constraint check should be deferred
15
+ # # @option options [Boolean] :constraint (false) If the trigger is a constraint
16
+ # # @option options [Symbol] :initially (:immediate) If the constraint check should be deferred
17
17
  # # Supported values: :immediate (default), :deferred
18
- # # @option [#to_s] :when (nil) The SQL snippet definiing a condition for the trigger
19
- # # @option [Symbol] :for_each (:statement) Define if a trigger should be run for every row
18
+ # # @option options [#to_s] :when (nil) The SQL snippet definiing a condition for the trigger
19
+ # # @option options [Symbol] :for_each (:statement) Define if a trigger should be run for every row
20
20
  # # Supported values: :statement (default), :row
21
- # # @option [#to_s] :comment (nil) The commend describing the trigger
21
+ # # @option options [#to_s] :comment (nil) The commend describing the trigger
22
22
  # # @yield [t] the block with the trigger's definition
23
23
  # # @yieldparam Object receiver of methods specifying the trigger
24
24
  # # @return [void]
@@ -6,16 +6,16 @@
6
6
  # #
7
7
  # # @param [#to_s] table (nil) The qualified name of the table
8
8
  # # @param [#to_s] name (nil) The name of the trigger
9
- # # @option [#to_s] :to (nil) The new name of the trigger
9
+ # # @option options [#to_s] :to (nil) The new name of the trigger
10
10
  # # @param [#to_s] table (nil) The qualified name of the table
11
11
  # # @param [#to_s] name (nil) The current name of the trigger
12
- # # @option [#to_s] :to (nil) The new name for the trigger
13
- # # @option [#to_s] :function (nil) The qualified name of the function to be called
14
- # # @option [Symbol] :type (nil) When the trigger should be run
12
+ # # @option options [#to_s] :to (nil) The new name for the trigger
13
+ # # @option options [#to_s] :function (nil) The qualified name of the function to be called
14
+ # # @option options [Symbol] :type (nil) When the trigger should be run
15
15
  # # Supported values: :before, :after, :instead_of
16
- # # @option [Array<Symbol>] :events List of events running the trigger
16
+ # # @option options [Array<Symbol>] :events List of events running the trigger
17
17
  # # Supported values in the array: :insert, :update, :delete, :truncate
18
- # # @option [Symbol] :for_each (:statement) Define if a trigger should be run for every row
18
+ # # @option options [Symbol] :for_each (:statement) Define if a trigger should be run for every row
19
19
  # # Supported values: :statement (default), :row
20
20
  # # @yield [t] the block with the trigger's definition
21
21
  # # @yieldparam Object receiver of methods specifying the trigger
@@ -5,7 +5,7 @@
5
5
  # # Modify a view
6
6
  # #
7
7
  # # @param [#to_s] name (nil) The qualified name of the view
8
- # # @option [Boolean] :if_exists (false) Suppress the error when the view is absent
8
+ # # @option options [Boolean] :if_exists (false) Suppress the error when the view is absent
9
9
  # # @yield [v] the block with the view's definition
10
10
  # # @yieldparam Object receiver of methods specifying the view
11
11
  # # @return [void]
@@ -5,13 +5,13 @@
5
5
  # # Create a view
6
6
  # #
7
7
  # # @param [#to_s] name (nil) The qualified name of the view
8
- # # @option [Boolean] :replace_existing (false) If the view should overwrite an existing one
9
- # # @option [#to_s] :sql_definition (nil) The snippet containing the query
10
- # # @option [#to_i] :version (nil)
8
+ # # @option options [Boolean] :replace_existing (false) If the view should overwrite an existing one
9
+ # # @option options [#to_s] :sql_definition (nil) The snippet containing the query
10
+ # # @option options [#to_i] :version (nil)
11
11
  # # The alternative way to set sql_definition by referencing to a file containing the snippet
12
- # # @option [#to_s] :check (nil) Controls the behavior of automatically updatable views
12
+ # # @option options [#to_s] :check (nil) Controls the behavior of automatically updatable views
13
13
  # # Supported values: :local, :cascaded
14
- # # @option [#to_s] :comment (nil) The comment describing the view
14
+ # # @option options [#to_s] :comment (nil) The comment describing the view
15
15
  # # @yield [v] the block with the view's definition
16
16
  # # @yieldparam Object receiver of methods specifying the view
17
17
  # # @return [void]
@@ -5,15 +5,15 @@
5
5
  # # Drop a view
6
6
  # #
7
7
  # # @param [#to_s] name (nil) The qualified name of the view
8
- # # @option [Boolean] :replace_existing (false) If the view should overwrite an existing one
9
- # # @option [Boolean] :if_exists (false) Suppress the error when the view is absent
10
- # # @option [Symbol] :force (:restrict) How to process dependent objects (`:cascade` or `:restrict`)
11
- # # @option [#to_s] :sql_definition (nil) The snippet containing the query
12
- # # @option [#to_i] :revert_to_version (nil)
8
+ # # @option options [Boolean] :replace_existing (false) If the view should overwrite an existing one
9
+ # # @option options [Boolean] :if_exists (false) Suppress the error when the view is absent
10
+ # # @option options [Symbol] :force (:restrict) How to process dependent objects (`:cascade` or `:restrict`)
11
+ # # @option options [#to_s] :sql_definition (nil) The snippet containing the query
12
+ # # @option options [#to_i] :revert_to_version (nil)
13
13
  # # The alternative way to set sql_definition by referencing to a file containing the snippet
14
- # # @option [#to_s] :check (nil) Controls the behavior of automatically updatable views
14
+ # # @option options [#to_s] :check (nil) Controls the behavior of automatically updatable views
15
15
  # # Supported values: :local, :cascaded
16
- # # @option [#to_s] :comment (nil) The comment describing the view
16
+ # # @option options [#to_s] :comment (nil) The comment describing the view
17
17
  # # @yield [v] the block with the view's definition
18
18
  # # @yieldparam Object receiver of methods specifying the view
19
19
  # # @return [void]
@@ -5,8 +5,8 @@
5
5
  # # Change the name and/or schema of a view
6
6
  # #
7
7
  # # @param [#to_s] :name (nil) The qualified name of the view
8
- # # @option [#to_s] :to (nil) The new qualified name for the view
9
- # # @option [Boolean] :if_exists (false) Suppress the error when the view is absent
8
+ # # @option options [#to_s] :to (nil) The new qualified name for the view
9
+ # # @option options [Boolean] :if_exists (false) Suppress the error when the view is absent
10
10
  # # @return [void]
11
11
  # #
12
12
  # # A view can be renamed by changing both the name
@@ -18,6 +18,7 @@ module PGTrunk
18
18
  require_relative "operations/foreign_keys"
19
19
  require_relative "operations/procedures"
20
20
  require_relative "operations/triggers"
21
+ require_relative "operations/rules"
21
22
  require_relative "operations/statistics"
22
23
  end
23
24
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module PGTrunk
4
4
  # @private
5
- VERSION = "0.1.2"
5
+ VERSION = "0.1.3"
6
6
  end
data/pg_trunk.gemspec CHANGED
@@ -23,7 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.metadata["rubygems_mfa_required"] = "true"
24
24
 
25
25
  spec.files = `git ls-files -z`.split("\x0")
26
- spec.test_files = spec.files.grep(%r{^spec/})
27
26
  spec.require_paths = ["lib"]
28
27
 
29
28
  spec.add_dependency "activerecord", ">= 4.0.0"