module PGTrunk::Operations::MaterializedViews
@private Namespace for operations with materialized views
@!parse
class ActiveRecord::Migration # Modify a materialized view # # @param [#to_s] name (nil) The qualified name of the view # @option options [Boolean] :if_exists (false) Suppress the error when the view is absent # @yield [v] the block with the view's definition # @yieldparam Object receiver of methods specifying the view # @return [void] # # The operation enables to alter a view without recreating # its from scratch. You can rename columns, change their # storage settings (how the column is TOAST-ed), or customize their statistics. # # ```ruby # change_materialized_view "admin_users" do |v| # v.rename_column "name", to: "full_name" # v.column "name", storage: "extended", from_storage: "expanded" # v.column "admin", n_distinct: 2 # v.column "role", statistics: 100 # end # ``` # # Notice that renaming will be done AFTER all changes even # though the order of declarations can be different. # # As in the snippet above, to make the change invertible, # you have to define a previous storage via `from_storage` option. # The inversion would always reset statistics (set it to 0). # # In addition to changing columns, the operation enables # to set a default clustering by given index: # # ```ruby # change_materialized_view "admin_users" do |v| # v.cluster_on "admin_users_by_names_idx" # end # ``` # # The clustering is invertible, but its inversion does nothing, # keeping the clustering unchanged. # # The comment can also be changed: # # ```ruby # change_materialized_view "admin_users" do |v| # v.comment "Admin users", from: "Admin users only" # end # ``` # # Notice, that without `from` option the operation is still # invertible, but its inversion would delete the comment. # It can also be reset to the blank string explicitly: # # ```ruby # change_materialized_view "admin_users" do |v| # v.comment "", from: "Admin users only" # end # ``` # # With the `if_exists: true` option, the operation won't fail # even when the view wasn't existed. At the same time, # this option makes a migration irreversible due to uncertainty # of the previous state of the database. def change_materialized_view(name, **options, &block); end end
@!parse
class ActiveRecord::Migration # Create a materialized view # # @param [#to_s] name (nil) The qualified name of the view # @option options [Boolean] :if_not_exists (false) Suppress the error when a view has been already created # @option options [#to_s] :sql_definition (nil) The snippet containing the query # @option options [#to_i] :version (nil) # The alternative way to set sql_definition by referencing to a file containing the snippet # @option options [#to_s] :tablespace (nil) The tablespace for the view # @option options [Boolean] :with_data (true) If the view should be populated after creation # @option options [#to_s] :comment (nil) The comment describing the view # @yield [v] the block with the view's definition # @yieldparam Object receiver of methods specifying the view # @return [void] # # The operation creates the view using its `sql_definition`: # # ```ruby # create_materialized_view("views.admin_users", sql_definition: <<~SQL) # SELECT id, name FROM users WHERE admin; # SQL # ``` # # For compatibility to the `scenic` gem, we also support # adding a definition via its version: # # ```ruby # create_materialized_view "admin_users", version: 1 # ``` # # It is expected, that a `db/materialized_views/admin_users_v01.sql` # to contain the SQL snippet. # # The tablespace can be specified for the created view. # Notice that later it can't be changed (in PostgreSQL all rows # can be moved to another tablespace, but we don't support # this feature yet). # # ```ruby # create_materialized_view "admin_users" do |v| # v.tablespace "fast_ssd" # v.sql_definition <<~SQL # SELECT id, name, password, admin, on_duty # FROM users # WHERE admin # SQL # end # ``` # # You can also set a comment describing the view, # and redefine the storage options for some TOAST-ed columns, # as well as their custom statistics: # # ```ruby # create_materialized_view "admin_users" do |v| # v.sql_definition <<~SQL # SELECT id, name, password, admin, on_duty # FROM users # WHERE admin # SQL # v.column "password", storage: "external" # to avoid compression # v.column "password", n_distinct: -1 # linear dependency # v.column "admin", n_distinct: 1 # exact number of values # v.column "on_duty", statistics: 2 # the total number of values # v.comment "Admin users only" # end # ``` # # With the `replace_existing: true` option the operation # would use `CREATE OR REPLACE VIEW` command, so it # can be used to "update" (or reload) the existing view. # # ```ruby # create_materialized_view "admin_users", # version: 1, # replace_existing: true # ``` # # This option makes the migration irreversible due to uncertainty # of the previous state of the database. def create_materialized_view(name, **options, &block); end end
@!parse
class ActiveRecord::Migration # Drop a materialized view # # @param [#to_s] name (nil) The qualified name of the view # @option options [Boolean] :if_exists (false) Suppress the error when the view is absent # @option options [Symbol] :force (:restrict) How to process dependent objects (`:cascade` or `:restrict`) # @option options [#to_s] :sql_definition (nil) The snippet containing the query # @option options [#to_i] :revert_to_version (nil) # The alternative way to set sql_definition by referencing to a file containing the snippet # @option options [#to_s] :tablespace (nil) The tablespace for the view # @option options [Boolean] :with_data (true) If the view should be populated after creation # @option options [#to_s] :comment (nil) The comment describing the view # @yield [v] the block with the view's definition # @yieldparam Object receiver of methods specifying the view # @return [void] # # The operation drops a materialized view identified by its # qualified name (it can include a schema). # # ```ruby # drop_materialized_view "views.admin_users" # ``` # # To make the operation invertible, use the same options # as in the `create_view` operation. # # ```ruby # drop_materialized_view "views.admin_users" do |v| # v.sql_definition "SELECT name, password FROM users WHERE admin;" # v.column "password", storage: "external" # prevent compression # v.with_data false # v.comment "Admin users only" # end # ``` # # You can also use a version-base SQL definition like: # # ```ruby # drop_materialized_view "admin_users", revert_to_version: 1 # ``` # # With the `force: :cascade` option the operation would remove # all the objects which depend on the view. # # ```ruby # drop_materialized_view "admin_users", force: :cascade # ``` # # With the `if_exists: true` option the operation won't fail # even when the view was absent in the database. # # ```ruby # drop_materialized_view "admin_users", if_exists: true # ``` # # Both options make a migration irreversible due to uncertainty # of the previous state of the database. def drop_materialized_view(name, **options, &block); end end
@!parse
class ActiveRecord::Migration # Refresh a materialized view # # @param [#to_s] name (nil) The qualified name of the view # @option options [Boolean] :with_data (true) If the view should be populated after creation # @option options [Symbol] :algorithm (nil) Makes the operation concurrent when set to :concurrently # @return [void] # # The operation enables refreshing a materialized view # by reloading its underlying SQL query: # # ```ruby # refresh_materialized_view "admin_users" # ``` # # The option `algorithm: :concurrently` acts exactly # like in the `create_index` definition. You should # possibly add the `disable_ddl_transaction!` command # to the migration as well. # # With option `with_data: false` the command won't # update the data. This option can't be used along with # the `:algorithm`. # # The operation is always reversible, though its # inversion does nothing. def refresh_materialized_view(name, **options); end end
@!parse
class ActiveRecord::Migration # Change the name and/or schema of a materialized view # # @param [#to_s] :name (nil) The qualified name of the view # @option options [#to_s] :to (nil) The new qualified name for the view # @option options [Boolean] :if_exists (false) Suppress the error when the view is absent # @return [void] # # A materialized view can be renamed by changing both the name # and the schema (namespace) it belongs to. # # ```ruby # rename_materialized_view "views.admin_users", to: "admins" # ``` # # With the `if_exists: true` option, the operation won't fail # even when the view wasn't existed. # # ```ruby # rename_materialized_view "admin_users", # to: "admins", # if_exists: true # ``` # # At the same time, the option makes a migration irreversible # due to uncertainty of the previous state of the database. def rename_materialized_view(name, **options); end end