module PGTrunk::Operations::Statistics

@private Namespace for operations with functions

@!parse

class ActiveRecord::Migration
  # Create a custom statistics
  #
  # @param [#to_s] name (nil) The qualified name of the statistics
  # @option options [Boolean] :if_not_exists (false)
  #   Suppress the error when the statistics is already exist
  # @option options [#to_s] table (nil)
  #   The qualified name of the table whose statistics will be collected
  # @option options [Array<Symbol>] kinds ([:dependencies, :mcv, :ndistinct])
  #   The kinds of statistics to be collected (all by default).
  #   Supported values in the array: :dependencies, :mcv, :ndistinct
  # @option options [#to_s] :comment The description of the statistics
  # @yield [s] the block with the statistics' definition
  # @yieldparam Object receiver of methods specifying the statistics
  # @return [void]
  #
  # The statistics can be created with explicit name:
  #
  # ```ruby
  # create_statistics "users_stats" do |s|
  #   s.table "users"
  #   s.columns "family", "name"
  #   s.kinds :dependencies, :mcv, :ndistinct
  #   s.comment "Statistics for users' names and families"
  # SQL
  # ```
  #
  # The name can be generated as well:
  #
  # ```ruby
  # create_statistics do |s|
  #   s.table "users"
  #   s.columns "family", "name"
  #   s.kinds :dependencies, :mcv, :ndistinct
  #   s.comment "Statistics for users' names and families"
  # SQL
  # ```
  #
  # Since v14 PostgreSQL have supported expressions in addition to columns:
  #
  # ```ruby
  # create_statistics "users_stats" do |s|
  #   s.table "users"
  #   s.columns "family"
  #   s.expression "length(name)"
  #   s.kinds :dependencies, :mcv, :ndistinct
  #   s.comment "Statistics for users' name lengths and families"
  # SQL
  # ```
  #
  # as well as statistics for the sole expression (kinds must be blank)
  # by columns of some table.
  #
  # ```ruby
  # create_statistics "users_stats" do |s|
  #   s.table "users"
  #   s.expression "length(name || ' ' || family)"
  #   s.comment "Statistics for full name lengths"
  # SQL
  # ```
  #
  # Use `if_not_exists: true` to suppress error in case the statistics
  # has already been created. This option, though, makes the migration
  # irreversible due to uncertainty of the previous state of the database.
  def create_statistics(name, **options, &block); end
end

@!parse

class ActiveRecord::Migration
  # Drop a custom statistics
  #
  # @param [#to_s] name (nil) The qualified name of the statistics
  # @option options [Boolean] :if_exists (false) Suppress the error when the statistics is absent
  # @option options [Symbol] :force (:restrict) How to process dependent objects (`:cascade` or `:restrict`)
  # @option options [#to_s] table (nil)
  #   The qualified name of the table whose statistics will be collected
  # @option options [Array<Symbol>] kinds ([:dependencies, :mcv, :ndistinct])
  #   The kinds of statistics to be collected (all by default).
  #   Supported values in the array: :dependencies, :mcv, :ndistinct
  # @option options [#to_s] :comment The description of the statistics
  # @yield [s] the block with the statistics' definition
  # @yieldparam Object receiver of methods specifying the statistics
  # @return [void]
  #
  # A statistics can be dropped by its name only:
  #
  # ```ruby
  # drop_statistics "my_stats"
  # ```
  #
  # Such operation is irreversible. To make it inverted
  # you have to provide a full definition:
  #
  # ```ruby
  # drop_statistics "users_stat" do |s|
  #   s.table "users"
  #   s.columns "firstname", "name"
  #   s.expression <<~SQL
  #     round(age, 10)
  #   SQL
  #   s.kinds :dependency, :mcv, :ndistinct
  #   s.comment "Statistics for name, firstname, and rough age"
  # SQL
  # ```
  #
  # If the statistics was anonymous (used the generated name),
  # it can be dropped without defining the name as well:
  #
  # ```ruby
  # drop_statistics do |s|
  #   s.table "users"
  #   s.columns "firstname", "name"
  #   s.expression <<~SQL
  #     round(age, 10)
  #   SQL
  #   s.kinds :dependency, :mcv, :ndistinct
  #   s.comment "Statistics for name, firstname, and rough age"
  # SQL
  # ```
  #
  # The operation can be called with `if_exists` option. In this case
  # it would do nothing when no statistics existed.
  #
  # ```ruby
  # drop_statistics "unknown_statistics", if_exists: true
  # ```
  #
  # Notice, that this option make the operation irreversible because of
  # uncertainty about the previous state of the database.
  def drop_statistics(name, **options, &block); end
end

@!parse

class ActiveRecord::Migration
  # Change the name and/or schema of a statistics
  #
  # @param [#to_s] :name (nil) The qualified name of the statistics
  # @option options [#to_s] :to (nil) The new qualified name for the statistics
  # @return [void]
  #
  # A custom statistics can be renamed by changing both the name
  # and the schema (namespace) it belongs to.
  #
  # ```ruby
  # rename_statistics "math.my_stat", to: "public.my_stats"
  # ```
  #
  # The operation is always reversible.
  def rename_statistics(name, to:); end
end

Constants

SQL_V10

SQL snippet to fetch statistics in v10-13

SQL_V14

In version 14 statistics can be collected for expressions.