Closed joemsak closed 4 years ago
I have an SO question as well in case it helps with more context https://stackoverflow.com/questions/59668861/postgresql-9-6-with-multi-tenancy-inherit-says-child-table-has-column-with-dif
Rooting around the commit history of the apartment initializer, I realized we've also had this laying around
# frozen_string_literal: true
require 'apartment/adapters/postgresql_adapter'
# Monkey patching Apartment to fix this:
# https://github.com/influitive/apartment/issues/532
module Apartment
module Adapters
class PostgresqlSchemaFromSqlAdapter < PostgresqlSchemaAdapter
PSQL_DUMP_BLACKLISTED_STATEMENTS = [
/SET search_path/i, # overridden later
/SET lock_timeout/i, # new in postgresql 9.3
/SET row_security/i, # new in postgresql 9.5
/SET idle_in_transaction_session_timeout/i, # new in postgresql 9.6
/CREATE SCHEMA public/i # this schema already exists
].freeze
def import_database_schema
preserving_search_path do
clone_pg_schema
copy_schema_migrations
end
end
def clone_pg_schema
pg_schema_sql = patch_search_path(pg_dump_schema)
Apartment.connection.execute(pg_schema_sql)
end
def preserving_search_path
search_path = Apartment.connection.execute('show search_path').first['search_path']
yield
Apartment.connection.execute("set search_path = #{search_path}")
end
def patch_search_path(sql)
search_path = "SET search_path = \"#{current}\", #{default_tenant};"
swap_schema_qualifier(sql)
.split("\n")
.select { |line| check_input_against_regexps(line, PSQL_DUMP_BLACKLISTED_STATEMENTS).empty? }
.prepend(search_path)
.join("\n")
end
def swap_schema_qualifier(sql)
sql.gsub(/#{default_tenant}\.\w*/) do |match|
match.gsub(default_tenant, %("#{current}"))
end
end
end
end
end
This has been here seemingly not causing issues for a year or so, and I don't know what it's really doing or is for, I haven't messed with it
This one turned out to be totally my fault. Red herrings threw me off. It was a loading order dependency in my initializers. I was referencing Apartment::Tenant
in some custom domain code before all other initializers, meaning the adapter would load and memoize with the default config options, and the apartment config initializer would not take over and set the PostgresqlSchemaFromSqlAdapter
- once I fixed the ordering, and that adapter is set, the tenant inherits worked.
Steps to reproduce
Using Apartment 1.2 on existing postgresql database Have a model with a simple
t.string :name
column no other modifiers Run Apartment::Tenant.create("schema_name") Inspect ActiveRecord::Base.connection.columns("public.table_name") => name's sql_type is "character varying(255)" Inspect ActiveRecord::Base.connection.columns("schema_name.table_name")Expected behavior
=> name's sql_type is "character varying(255)"
Actual behavior
=> name's sql_type is "character varying"
System configuration
Rails 4.2 Ruby 2.3.8 Apartment 1.2
There is an INHERIT migration running which throws DatatypeMismatch error due to the new child schema's table not picking up the (255) character limit for the type
Postgresql 9.6 on AWS RDS
1.2
config/initializers/apartment.rb
or so):Require whichever elevator you're using below here...
#
require 'apartment/elevators/generic'
require 'apartment/elevators/domain'
require 'apartment/elevators/subdomain'
require 'apartment' unless Kannu.tenant.config.no_database? require 'apartment/elevators/host_hash' require 'apartment/adapters/postgresql_schema_from_sql_adapter' #
Apartment Configuration
# if Kadenze.kannu? && !Kadenze.config.no_database? Apartment.configure do |config|
These models will not be multi-tenanted,
end end
Elevator Configuration
NOTE: This is specified in the application config to keep all of our middleware declarations in one place
Rails.application.config.middleware.use 'Apartment::Elevators::Generic', lambda { |request|
TODO: supply generic implementation
}
Rails.application.config.middleware.use 'Apartment::Elevators::Domain'
Rails.application.config.middleware.use 'Apartment::Elevators::Subdomain'