module ActiveRecord # :nodoc: module ConnectionAdapters # :nodoc: module PostGIS # :nodoc: class PostGISDatabaseTasks < ::ActiveRecord::Tasks::PostgreSQLDatabaseTasks # :nodoc: def initialize(config) super ensure_installation_configs end def setup_gis establish_su_connection if extension_names setup_gis_from_extension end establish_connection(configuration) end # Override to set the database owner and call setup_gis def create(master_established = false) establish_master_connection unless master_established extra_configs = { "encoding" => encoding } extra_configs["owner"] = username if has_su? connection.create_database(configuration["database"], configuration.merge(extra_configs)) setup_gis rescue ::ActiveRecord::StatementInvalid => error if /database .* already exists/ === error.message raise ::ActiveRecord::Tasks::DatabaseAlreadyExists else raise end end private # Override to use su_username and su_password def establish_master_connection establish_connection(configuration.merge( "database" => "postgres", "password" => su_password, "schema_search_path" => "public", "username" => su_username, )) end def establish_su_connection establish_connection(configuration.merge( "password" => su_password, "schema_search_path" => "public", "username" => su_username, )) end def username @username ||= configuration["username"] end def quoted_username @quoted_username ||= ::ActiveRecord::Base.connection.quote_column_name(username) end def password @password ||= configuration["password"] end def su_username @su_username ||= configuration["su_username"] || username end def su_password @su_password ||= configuration["su_password"] || password end def has_su? @has_su = configuration.include?("su_username") unless defined?(@has_su) @has_su end def search_path @search_path ||= configuration["schema_search_path"].to_s.strip.split(",").map(&:strip) end def extension_names @extension_names ||= begin extensions = configuration["postgis_extension"] case extensions when ::String extensions.split(",") when ::Array extensions else ["postgis"] end end end def ensure_installation_configs if configuration["setup"] == "default" && !configuration["postgis_extension"] share_dir = `pg_config --sharedir`.strip rescue "/usr/share" control_file = ::File.expand_path("extension/postgis.control", share_dir) if ::File.readable?(control_file) configuration["postgis_extension"] = "postgis" end end end def setup_gis_from_extension extension_names.each do |extname| if extname == "postgis_topology" raise ::ArgumentError, "'topology' must be in schema_search_path for postgis_topology" unless search_path.include?("topology") connection.execute("CREATE EXTENSION IF NOT EXISTS #{extname} SCHEMA topology") else if (postgis_schema = configuration["postgis_schema"]) schema_clause = "WITH SCHEMA #{postgis_schema}" unless schema_exists?(postgis_schema) connection.execute("CREATE SCHEMA #{postgis_schema}") connection.execute("GRANT ALL ON SCHEMA #{postgis_schema} TO PUBLIC") end else schema_clause = "" end connection.execute("CREATE EXTENSION IF NOT EXISTS #{extname} #{schema_clause}") end end end def schema_exists?(schema_name) connection.execute("SELECT schema_name FROM information_schema.schemata WHERE schema_name = '#{schema_name}'").any? end end ::ActiveRecord::Tasks::DatabaseTasks.register_task(/postgis/, PostGISDatabaseTasks) end end end