require 'pact_broker/project_root' require 'pact_broker/db/migrate' require 'pact_broker/db/version' require 'sequel' require 'yaml' require_relative 'database/table_dependency_calculator' Sequel.extension :migration module PactBroker module Database extend self def migrate target = nil opts = target ? {target: target} : {} PactBroker::DB::Migrate.call(database, opts) end def version PactBroker::DB::Version.call(database) end def delete_database_file ensure_not_production FileUtils.rm_rf database_file_path end def ensure_database_dir_exists ensure_not_production FileUtils.mkdir_p File.dirname(database_file_path) end def drop_objects drop_views drop_tables end def drop_tables ordered_tables.each do | table_name | database.drop_table(table_name, cascade: psql?) end database.drop_table(:schema_migrations) if database.table_exists?(:schema_migrations) end def drop_views database.views.each do | view_name | begin # checking for existance using table_exists? doesn't work in sqlite database.drop_view(view_name, cascade: psql?) rescue Sequel::DatabaseError => e # Cascade will have deleted some views already with pg raise e unless e.cause.class.name == 'PG::UndefinedTable' end end end def create if psql? system('psql postgres -c "create database pact_broker"') system('psql postgres -c "CREATE USER pact_broker WITH PASSWORD \'pact_broker\'"') system('psql postgres -c "GRANT ALL PRIVILEGES ON DATABASE pact_broker to pact_broker"') elsif sqlite? ensure_database_dir_exists else raise "Unknown database adapter #{adapter}" end end def recreate drop_tables create end def truncate ordered_tables.each do | table_name | if database.table_exists?(table_name) begin database[table_name].delete rescue SQLite3::ConstraintException => e puts "Could not delete the following records from #{table_name}: #{database[table_name].select_all}" raise e end end end end def database= database @@database = database end def database @@database ||= begin require 'db' ::DB.connection_for_env env end end def wait_for_database tries = 0 begin database rescue StandardError => e tries += 1 sleep 1 retry if tries < 10 raise e end end private def ordered_tables TableDependencyCalculator.call(database) end def ensure_not_production raise "Cannot delete production database using this task" if env == 'production' end def psql? adapter == 'postgres' end def sqlite? adapter == 'sqlite' end def migrations_dir PactBroker.project_root.join('db','migrations') end def database_file_path configuration_for_env(env)['database'] end def adapter configuration_for_env(env)['adapter'] end def configuration_for_env env database_yml = PactBroker.project_root.join('config','database.yml') config = YAML.load(ERB.new(File.read(database_yml)).result) adapter = ENV.fetch('DATABASE_ADAPTER','default') config.fetch(env)[adapter] end def env ENV.fetch('RACK_ENV') end end end