-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ActiveRecord Truncation does not work when using multiple schemas #6
Comments
I've come across a similar thing. For now doing
and then wrapping calls to |
Honestly, this is pretty awful. But the solution above works and can be improved by using select schema_name from information_schema.schemata where schema_name not like 'information_schema' and schema_name not like 'pg_%' to fetch all schemas in the active database for cleaning, which is the behavior I expected database_cleaner to exhibit. |
For me as I am using sequel was to use search_path as described here https://github.com/jeremyevans/sequel/blob/master/doc/opening_databases.rdoc#postgres |
My workaround was to just truncate the tables I need myself after each test example: config.after(:each) do
DatabaseCleaner.clean
['schema.tablename'].each do |table|
ActiveRecord::Base.connection.execute("TRUNCATE #{table}")
end
end |
Hi, so I'd love to help get this problem solved, but honestly I'm not familiar with with the concept of multiple schemas in PostgreSQL, so I'm going to need some help understanding. Can someone explain why an app might have more than one schema? Also, about the current clause that is causing the issue:
Can someone unpack this for me? Finally, in the OP @abhchand has suggested the possible solution of replacing the line with |
Hiya @botandrose . The reason we're using multiple schemata is to do close integration with a proprietary 3rd party application. There are some good reasons not to do it this way (it's a microservices sin and I feel a little bit ill about it) but amongst the advantages we find are...
I think a general solution which would ensure |
There are many reasons why some apps use several schemas, but for sure it is a thing. What Billy Watson was trying to solve is totally fine, but there is one piece in his solution select current_schemas(false);
current_schemas
-----------------
{public} While if you execute the query suggested by @deathwish you will indeed get all your schemas (excluding the Postgres' ones of course) SELECT schema_name FROM information_schema.schemata WHERE schema_name not like 'information_schema' AND schema_name not like 'pg_%';
schema_name
-------------
public
archive So, combining the query above with the current code, it will solve the issue while still addressing the concern that Billy Watson was trying to solve since it now lists the tables in all schemas and still appending the schema name. SELECT schemaname || '.' || tablename as table_name
FROM pg_tables
WHERE tablename !~ '_prt_'
AND tablename <> 'schema_migrations' AND tablename <> 'ar_internal_metadata'
AND schemaname = ANY (
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name not like 'information_schema'
AND schema_name not like 'pg_%'
);
table_name
-----------------------------------------
public.users
public.questions
public.responses
public.versions
archive.logs
archive.versions |
Or even simpler as @alejandro-falkowski-gelato suggested, setting up the test:
adapter: postgresql
host: localhost
database: db_test
...
schema_search_path: 'schema1,public' So it will worth at least mention in the docs that you should set the |
Thank you, @Adamantish, for the description of your use-case... I think I have a good handle on this now! And thank you, @erlinis, for your superb detective work and proposed solution, which appears to me to be solid. Is there any reason why one might not want to clean all tables outside of the public schema? Let's say we were to fold this change into a hypothetical v1.8.5 bugfix release of |
Hi @botandrose, This way current behavior won't be affected and the developer will have more control over what clean. |
@erlinis I like it! What do others in this thread think? Are you game for taking a stab at it in a PR? |
Like the original submitter's per-tenant schema use case, I'd definitely prefer to be able to clean all schemata rather than saying which ones should be cleaned. That said, I agree that being able to specify which schemata are cleaned is also important. We are in dynamic-language land here, so why not both? Something like The only other note I have immediately is that this should interact correctly with the |
@deathwish All great points! Like you, I think |
Is this issue still relevant with the latest version of this gem? |
@jherdman - I am on the latest version (2.0.1) and can confirm it's still an issue. @botandrose, anything in the works? |
This line seems to be the problem. @only = all_tables.map { |table| table.split(".").last } For me Is there a reason to remove the schema? Seems like a simple bug fix, change this: all_tables = cache_tables? ? connection.database_cleaner_table_cache : connection.database_tables
@only = all_tables.map { |table| table.split(".").last } To this: @only = cache_tables? ? connection.database_cleaner_table_cache : connection.database_tables |
Hello - thanks for putting together
database_cleaner
! I've been using the gem for a while and I know maintenance takes effort, so appreciate those who contribute to this project.I'm using the following setup -
Like many multi-tenant applications, my app utilizes postgres schemas which store parrallel, independent copies of my database tables.
So if I have two tenants (
earth
,mars
) and two tables (users
,companies
) I would have the following tables in my DB -When using
DatabaseCleaner.strategy = :truncation
, it looks for a list of tables in my DB to truncate (see here).When I run that query against my local test database -
As you can see, it only returns the public schemas, because of the
schemaname =
criteria. This effectively doesn't wipe my non-public schema tables, causing run-over between tests.I understand that there are options to use a transaction instead, or even the
only: [..]
parameter to list all my tables. But it seems like this should work as is without having to use one of those as a workaround (and if my DB is quite large, a whitelist can get messy and inefficient across thousands of tests).Would it make sense to update the query logic to something like
Thanks!
Related to: https://github.com/DatabaseCleaner/database_cleaner/issues/225
The text was updated successfully, but these errors were encountered: