Module: ViewsSchema
- Defined in:
- lib/views_schema.rb
Overview
Provides the ability to create and manage views through ActiveRecord
Constant Summary collapse
- WARNING =
Warning displayed in the event that the views have been broken
<<~HEREDOC ╔════════════════════════════════════════════════════════════╗ ║ WARNING! ║ ║ The attempt to dump the view schema failed. ║ ║ It is likely that your migrations have broken one or more ║ ║ of the views. It is CRITICAL that this problem is ║ ║ addressed before you commit these migrations. ║ ║ To ensure that reporting is not affected please ensure ║ ║ that the updated view accurately reflects the data. ║ ║ DO NOT change the schema of the view, merely how it ║ ║ retrieves the data. Ensure the changes are thoroughly ║ ║ tested against production like data. ║ ║ ║ ║ Downstream users should be notified of potential ║ ║ disruption. ║ ╚════════════════════════════════════════════════════════════╝ HEREDOC
- ALGORITHMS =
Valid algorithm options, first option is default
%w[UNDEFINED MERGE TEMPTABLE].freeze
- SECURITIES =
Valid security options, first option is default
%w[DEFINER INVOKER].freeze
- VIEW_STATEMENT =
'%{action} ALGORITHM=%<algorithm>s SQL SECURITY %<security>s VIEW `%<name>s` AS %<statement>s'- REGEXP =
rubocop:todo Layout/LineLength
/\ACREATE ALGORITHM=(?<algorithm>\w*) DEFINER=`[^`]*`@`[^`]*` SQL SECURITY (?<security>\w*) VIEW `[^`]+` AS (?<statement>.*)\z/i
Class Method Summary collapse
- .all_views ⇒ Object
-
.create_view(name, statement, algorithm: ALGORITHMS.first, security: SECURITIES.first) ⇒ Void
Creates a new view.
-
.drop_view(name) ⇒ Void
Drops the view.
-
.each_view ⇒ Object
rubocop:enable Layout/LineLength.
-
.execute(args) ⇒ Object
Generates the SQL for view creation/updating.
-
.update_view(name, statement, algorithm: ALGORITHMS.first, security: SECURITIES.first) ⇒ Void
Updates an existing view, or creates a new view if it doesn't exist already.
Class Method Details
.all_views ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/views_schema.rb', line 50 def self.all_views ActiveRecord::Base.with_connection do |connection| view_names = <<~SQL.squish SELECT TABLE_NAME AS name FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '#{connection.current_database}'; SQL connection .execute(view_names) .map(&:first) end end |
.create_view(name, statement, algorithm: ALGORITHMS.first, security: SECURITIES.first) ⇒ Void
Creates a new view. Will fail if the view already exists.
71 72 73 |
# File 'lib/views_schema.rb', line 71 def self.create_view(name, statement, algorithm: ALGORITHMS.first, security: SECURITIES.first) execute(action: 'CREATE', name: name, statement: statement, algorithm: algorithm, security: security) end |
.drop_view(name) ⇒ Void
Drops the view
92 93 94 95 96 |
# File 'lib/views_schema.rb', line 92 def self.drop_view(name) raise "Invalid name: `#{args[:name]}`" unless /^[a-z0-9_]*$/.match?(args[:name]) ActiveRecord::Base.connection.execute("DROP VIEW IF EXISTS `#{name}`;") end |
.each_view ⇒ Object
rubocop:enable Layout/LineLength
39 40 41 42 43 44 45 46 47 48 |
# File 'lib/views_schema.rb', line 39 def self.each_view all_views.each do |name| query = ActiveRecord::Base.connection.exec_query("SHOW CREATE TABLE #{name}").first matched = REGEXP.match(query['Create View']) yield(name, matched[:statement], matched[:algorithm], matched[:security]) end rescue ActiveRecord::StatementInvalid => e puts Rainbow(WARNING).red.inverse raise e end |
.execute(args) ⇒ Object
Note:
Use create_view or update_view
Generates the SQL for view creation/updating
107 108 109 110 111 112 |
# File 'lib/views_schema.rb', line 107 def self.execute(args) raise "Invalid name: `#{args[:name]}`" unless /^[a-z0-9_]*$/.match?(args[:name]) args[:statement] = args[:statement].to_sql if args[:statement].respond_to?(:to_sql) ActiveRecord::Base.connection.execute(VIEW_STATEMENT % args) end |
.update_view(name, statement, algorithm: ALGORITHMS.first, security: SECURITIES.first) ⇒ Void
Updates an existing view, or creates a new view if it doesn't exist already.
83 84 85 |
# File 'lib/views_schema.rb', line 83 def self.update_view(name, statement, algorithm: ALGORITHMS.first, security: SECURITIES.first) execute(action: 'CREATE OR REPLACE', name: name, statement: statement, algorithm: algorithm, security: security) end |