module PGTrunk::Operations::Views

@private Namespace for operations with views

@!parse

class ActiveRecord::Migration
  # Modify a 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 replaces the view with a new definition(s):
  #
  # ```ruby
  # change_view "admin_users" do |v|
  #   v.sql_definition: <<~SQL, from: <<~SQL
  #     SELECT id, name FROM users WHERE admin;
  #   SQL
  #     SELECT * FROM users WHERE admin;
  #   SQL
  # end
  # ```
  #
  # For some compatibility to the `scenic` gem, we also support
  # adding a definition via its version:
  #
  # ```ruby
  # change_view "admin_users" do |v|
  #   v.version 2, from: 1
  # end
  # ```
  #
  # It is expected, that both `db/views/admin_users_v01.sql`
  # and `db/views/admin_users_v02.sql` to contain SQL snippets.
  #
  # Please, notice that neither deletion of columns,
  # nor changing their types is supported by the PostgreSQL.
  #
  # You can also (re)set a comment describing the view,
  # and the check option (either `:local` or `:cascaded`):
  #
  # ```ruby
  # change_view "admin_users" do |v|
  #   v.check :local, from: :cascaded
  #   v.comment "Admin users only", from: ""
  # end
  # ```
  def change_view(name, **options, &block); end
end

@!parse

class ActiveRecord::Migration
  # Create a view
  #
  # @param [#to_s] name (nil) The qualified name of the view
  # @option options [Boolean] :replace_existing (false) If the view should overwrite an existing one
  # @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] :check (nil) Controls the behavior of automatically updatable views
  #   Supported values: :local, :cascaded
  # @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_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_view "admin_users", version: 1
  # ```
  #
  # It is expected, that a `db/views/admin_users_v01.sql`
  # to contain the SQL snippet.
  #
  # You can also set a comment describing the view, and the check option
  # (either `:local` or `:cascaded`):
  #
  # ```ruby
  # create_view "admin_users" do |v|
  #   v.sql_definition "SELECT id, name FROM users WHERE admin;"
  #   v.check :local
  #   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_view "admin_users", version: 1, replace_existing: true
  # ```
  #
  # This option makes an operation irreversible due to uncertainty
  # of the previous state of the database.
  def create_view(name, **options, &block); end
end

@!parse

class ActiveRecord::Migration
  # Drop a view
  #
  # @param [#to_s] name (nil) The qualified name of the view
  # @option options [Boolean] :replace_existing (false) If the view should overwrite an existing one
  # @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] :check (nil) Controls the behavior of automatically updatable views
  #   Supported values: :local, :cascaded
  # @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 the existing view identified by its
  # qualified name (it can include a schema).
  #
  # ```ruby
  # drop_view "views.admin_users"
  # ```
  #
  # To make the operation invertible, use the same options
  # as in the `create_view` operation.
  #
  # ```ruby
  # drop_view "views.admin_users" do |v|
  #   v.sql_definition "SELECT name, email FROM users WHERE admin;"
  #   v.check :local
  #   v.comment "Admin users only"
  # end
  # ```
  #
  # You can also use a version-base SQL definition like:
  #
  # ```ruby
  # drop_view "views.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_view "views.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_view "views.admin_users", if_exists: true
  # ```
  #
  # Both options make an operation irreversible due to uncertainty
  # of the previous state of the database.
  def drop_view(name, **options, &block); end
end

@!parse

class ActiveRecord::Migration
  # Change the name and/or schema of a 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 view can be renamed by changing both the name
  # and the schema (namespace) it belongs to.
  #
  # ```ruby
  # rename_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_view "views.admin_users", to: "admins", if_exists: true
  # ```
  #
  # At the same time, the option makes a view irreversible
  # due to uncertainty of the previous state of the database.
  def rename_view(name, **options); end
end