module PGTrunk::Operations::CompositeTypes

@private Definitions for composite types

@!parse

class ActiveRecord::Migration
  # Modify a composite type
  #
  # @param [#to_s] name (nil) The qualified name of the type
  # @option options [Symbol] :force (:restrict) How to process dependent objects (`:cascade` or `:restrict`)
  # @option options [#to_s] :comment (nil) The comment describing the constraint
  # @yield [t] the block with the type's definition
  # @yieldparam Object receiver of methods specifying the type
  # @return [void]
  #
  # The operation can be used to add, drop, rename or change columns.
  # The comment can be changed as well.
  #
  # Providing a type "paint.colored_point":
  #
  # ```ruby
  # create_composite_type "paint.colored_point" do |t|
  #   t.column "color", "text", collation: "en_US"
  #   t.column "x", "integer"
  #   t.column "z", "integer"
  # end
  # ```
  #
  # After the following change:
  #
  # ```ruby
  # change_composite_type "paint.colored_point" do |t|
  #   t.change_column "color", "text", collation: "ru_RU", from_collation: "en_US"
  #   t.change_column "x", "bigint", from_type: "integer"
  #   t.drop_column "z", "integer"
  #   t.add_column "Y", "bigint"
  #   t.rename_column "x", to: "X"
  #   t.comment "2D point with a color", from: "2D point"
  # end
  # ```
  #
  # The definition became:
  #
  # ```ruby
  # create_composite_type "paint.colored_point" do |t|
  #   t.column "color", "text", collation: "ru_RU"
  #   t.column "X", "bigint"
  #   t.column "Y", "integer"
  # end
  # ```
  #
  # Notice, that all renames will be done AFTER other changes,
  # so in `change_column` you should use the old names.
  #
  # In several cases the operation is not invertible:
  #
  # - when a column was dropped
  # - when `force: :cascade` option is used (to update
  #   objects that use the type)
  # - when `if_exists: true` is added to the `drop_column` clause
  # - when a previous state of the column type, collation or comment
  #   is not specified.
  def change_composite_type(name, **options, &block); end
end

@!parse

class ActiveRecord::Migration
  # Create a composite type
  #
  # @param [#to_s] name (nil) The qualified name of the type
  # @option options [#to_s] :comment (nil) The comment describing the constraint
  # @yield [t] the block with the type's definition
  # @yieldparam Object receiver of methods specifying the type
  # @return [void]
  #
  # ```ruby
  # create_composite_type "paint.colored_point" do |d|
  #   d.column "x", "integer"
  #   d.column "y", "integer"
  #   d.column "color", "text", collation: "en_US"
  #   d.comment <<~COMMENT
  #     2D point with color
  #   COMMENT
  # end
  # ```
  #
  # It is always reversible.
  def create_composite_type(name, **options, &block); end
end

@!parse

class ActiveRecord::Migration
  # Drop a composite type
  #
  # @param [#to_s] name (nil) The qualified name of the type
  # @option options [Boolean] :if_exists (false) Suppress the error when the type is absent
  # @option options [Symbol] :force (:restrict) How to process dependent objects (`:cascade` or `:restrict`)
  # @option options [#to_s] :comment (nil) The comment describing the constraint
  # @yield [t] the block with the type's definition
  # @yieldparam Object receiver of methods specifying the type
  # @return [void]
  #
  # The operation drops a composite_type type identified by its qualified name (it can include a schema).
  #
  # For inversion use the same options as in the `create_composite_type` operation.
  #
  # ```ruby
  # drop_composite_type "paint.colored_point" do |d|
  #   d.column "x", "integer"
  #   d.column "y", "integer"
  #   d.column "color", "text", collation: "en_US"
  #   d.comment <<~COMMENT
  #     2D point with color
  #   COMMENT
  # end
  # ```
  #
  # Notice, that the composite type creation can use no attributes.
  # That's why dropping it is always reversible; though the reversion provides a type without columns:
  #
  # ```ruby
  # drop_composite_type "paint.colored_point"
  # ```
  #
  # With the `force: :cascade` option the operation removes all objects using the type.
  #
  # ```ruby
  # drop_composite_type "paint.colored_point", force: :cascade
  # ```
  #
  # With the `if_exists: true` option the operation won't fail even when the view was absent.
  #
  # ```ruby
  # drop_composite_type "paint.colored_point", if_exists: true
  # ```
  #
  # Both options make a migration irreversible due to uncertainty of the previous state of the database.
  def drop_composite_type(name, **options, &block); end
end

@!parse

class ActiveRecord::Migration
  # Change the name and/or schema of a composite type
  #
  # @param [#to_s] name (nil) The qualified name of the type
  # @option options [#to_s] :to (nil) The new qualified name for the type
  # @return [void]
  #
  # ```ruby
  # rename_composite_type "point", to: "paint.colored_point"
  # ```
  #
  # The operation is always reversible.
  def rename_composite_type(name, to:); end
end