lib/fx/statements.rb in fx-0.8.0 vs lib/fx/statements.rb in fx-0.9.0
- old
+ new
@@ -1,11 +1,233 @@
-require "rails"
-require "fx/statements/function"
-require "fx/statements/trigger"
-
module Fx
# @api private
module Statements
- include Function
- include Trigger
+ # Create a new database function.
+ #
+ # @param name [String, Symbol] The name of the database function.
+ # @param version [Fixnum] The version number of the function, used to
+ # find the definition file in `db/functions`. This defaults to `1` if
+ # not provided.
+ # @param sql_definition [String] The SQL query for the function schema.
+ # If both `sql_definition` and `version` are provided,
+ # `sql_definition` takes prescedence.
+ # @return The database response from executing the create statement.
+ #
+ # @example Create from `db/functions/uppercase_users_name_v02.sql`
+ # create_function(:uppercase_users_name, version: 2)
+ #
+ # @example Create from provided SQL string
+ # create_function(:uppercase_users_name, sql_definition: <<~SQL)
+ # CREATE OR REPLACE FUNCTION uppercase_users_name()
+ # RETURNS trigger AS $$
+ # BEGIN
+ # NEW.upper_name = UPPER(NEW.name);
+ # RETURN NEW;
+ # END;
+ # $$ LANGUAGE plpgsql;
+ # SQL
+ #
+ def create_function(name, options = {})
+ version = options.fetch(:version, 1)
+ sql_definition = options[:sql_definition]
+
+ if version.nil? && sql_definition.nil?
+ raise(
+ ArgumentError,
+ "version or sql_definition must be specified"
+ )
+ end
+ sql_definition = sql_definition.strip_heredoc if sql_definition
+ sql_definition ||= Fx::Definition.function(name: name, version: version).to_sql
+
+ Fx.database.create_function(sql_definition)
+ end
+
+ # Drop a database function by name.
+ #
+ # @param name [String, Symbol] The name of the database function.
+ # @param revert_to_version [Fixnum] Used to reverse the `drop_function`
+ # command on `rake db:rollback`. The provided version will be passed as
+ # the `version` argument to {#create_function}.
+ # @return The database response from executing the drop statement.
+ #
+ # @example Drop a function, rolling back to version 2 on rollback
+ # drop_function(:uppercase_users_name, revert_to_version: 2)
+ #
+ def drop_function(name, options = {})
+ Fx.database.drop_function(name)
+ end
+
+ # Update a database function.
+ #
+ # @param name [String, Symbol] The name of the database function.
+ # @param version [Fixnum] The version number of the function, used to
+ # find the definition file in `db/functions`. This defaults to `1` if
+ # not provided.
+ # @param sql_definition [String] The SQL query for the function schema.
+ # If both `sql_definition` and `version` are provided,
+ # `sql_definition` takes prescedence.
+ # @return The database response from executing the create statement.
+ #
+ # @example Update function to a given version
+ # update_function(
+ # :uppercase_users_name,
+ # version: 3,
+ # revert_to_version: 2,
+ # )
+ #
+ # @example Update function from provided SQL string
+ # update_function(:uppercase_users_name, sql_definition: <<~SQL)
+ # CREATE OR REPLACE FUNCTION uppercase_users_name()
+ # RETURNS trigger AS $$
+ # BEGIN
+ # NEW.upper_name = UPPER(NEW.name);
+ # RETURN NEW;
+ # END;
+ # $$ LANGUAGE plpgsql;
+ # SQL
+ #
+ def update_function(name, options = {})
+ version = options[:version]
+ sql_definition = options[:sql_definition]
+
+ if version.nil? && sql_definition.nil?
+ raise(
+ ArgumentError,
+ "version or sql_definition must be specified"
+ )
+ end
+
+ sql_definition = sql_definition.strip_heredoc if sql_definition
+ sql_definition ||= Fx::Definition.function(name: name, version: version).to_sql
+
+ Fx.database.update_function(name, sql_definition)
+ end
+
+ # Create a new database trigger.
+ #
+ # @param name [String, Symbol] The name of the database trigger.
+ # @param version [Fixnum] The version number of the trigger, used to
+ # find the definition file in `db/triggers`. This defaults to `1` if
+ # not provided.
+ # @param sql_definition [String] The SQL query for the function. An error
+ # will be raised if `sql_definition` and `version` are both set,
+ # as they are mutually exclusive.
+ # @return The database response from executing the create statement.
+ #
+ # @example Create trigger from `db/triggers/uppercase_users_name_v01.sql`
+ # create_trigger(:uppercase_users_name, version: 1)
+ #
+ # @example Create trigger from provided SQL string
+ # create_trigger(:uppercase_users_name, sql_definition: <<~SQL)
+ # CREATE TRIGGER uppercase_users_name
+ # BEFORE INSERT ON users
+ # FOR EACH ROW
+ # EXECUTE FUNCTION uppercase_users_name();
+ # SQL
+ #
+ def create_trigger(name, options = {})
+ version = options[:version]
+ _on = options[:on]
+ sql_definition = options[:sql_definition]
+
+ if version.present? && sql_definition.present?
+ raise(
+ ArgumentError,
+ "sql_definition and version cannot both be set"
+ )
+ end
+
+ if version.nil?
+ version = 1
+ end
+
+ sql_definition = sql_definition.strip_heredoc if sql_definition
+ sql_definition ||= Fx::Definition.trigger(name: name, version: version).to_sql
+
+ Fx.database.create_trigger(sql_definition)
+ end
+
+ # Drop a database trigger by name.
+ #
+ # @param name [String, Symbol] The name of the database trigger.
+ # @param on [String, Symbol] The name of the table the database trigger
+ # is associated with.
+ # @param revert_to_version [Fixnum] Used to reverse the `drop_trigger`
+ # command on `rake db:rollback`. The provided version will be passed as
+ # the `version` argument to {#create_trigger}.
+ # @return The database response from executing the drop statement.
+ #
+ # @example Drop a trigger, rolling back to version 3 on rollback
+ # drop_trigger(:log_inserts, on: :users, revert_to_version: 3)
+ #
+ def drop_trigger(name, options = {})
+ on = options.fetch(:on)
+ Fx.database.drop_trigger(name, on: on)
+ end
+
+ # Update a database trigger to a new version.
+ #
+ # The existing trigger is dropped and recreated using the supplied `on`
+ # and `version` parameter.
+ #
+ # @param name [String, Symbol] The name of the database trigger.
+ # @param version [Fixnum] The version number of the trigger.
+ # @param on [String, Symbol] The name of the table the database trigger
+ # is associated with.
+ # @param sql_definition [String] The SQL query for the function. An error
+ # will be raised if `sql_definition` and `version` are both set,
+ # as they are mutually exclusive.
+ # @param revert_to_version [Fixnum] The version number to rollback to on
+ # `rake db rollback`
+ # @return The database response from executing the create statement.
+ #
+ # @example Update trigger to a given version
+ # update_trigger(
+ # :log_inserts,
+ # on: :users,
+ # version: 3,
+ # revert_to_version: 2,
+ # )
+ #
+ # @example Update trigger from provided SQL string
+ # update_trigger(:uppercase_users_name, sql_definition: <<~SQL)
+ # CREATE TRIGGER uppercase_users_name
+ # BEFORE INSERT ON users
+ # FOR EACH ROW
+ # EXECUTE FUNCTION uppercase_users_name();
+ # SQL
+ #
+ def update_trigger(name, options = {})
+ version = options[:version]
+ on = options[:on]
+ sql_definition = options[:sql_definition]
+
+ if version.nil? && sql_definition.nil?
+ raise(
+ ArgumentError,
+ "version or sql_definition must be specified"
+ )
+ end
+
+ if version.present? && sql_definition.present?
+ raise(
+ ArgumentError,
+ "sql_definition and version cannot both be set"
+ )
+ end
+
+ if on.nil?
+ raise ArgumentError, "on is required"
+ end
+
+ sql_definition = sql_definition.strip_heredoc if sql_definition
+ sql_definition ||= Fx::Definition.trigger(name: name, version: version).to_sql
+
+ Fx.database.update_trigger(
+ name,
+ on: on,
+ sql_definition: sql_definition
+ )
+ end
end
end