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
Add support for partitioned indexes in PostgreSQL 11+ #37585
Add support for partitioned indexes in PostgreSQL 11+ #37585
Conversation
activerecord/test/schema/schema.rb
Outdated
@@ -503,6 +503,18 @@ | |||
t.column :weight, :integer | |||
end | |||
|
|||
create_table(:measurements, id: false, force: true, options: "PARTITION BY LIST (city_id)") do |t| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This (and following) measurements table definitions in schema are valid only for postgres adapter.
CI can't create those tables on mysql and sqlite.
https://buildkite.com/rails/rails/builds/64610#b993a2df-ea4f-45f4-a6f2-0dd8487e2237
https://buildkite.com/rails/rails/builds/64610#8112f1a1-8b9e-4cf0-9b48-49f8caf5fb24
Any chance to make this table conditional and load coresponding model only when currently used adapter supports_partitioned_indexes
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @simi, thanks for the feedback. And yes, I'm gonna take a look at that, didn't check before if they were adapter constrained.
@@ -93,7 +93,7 @@ def indexes(table_name) # :nodoc: | |||
INNER JOIN pg_index d ON t.oid = d.indrelid | |||
INNER JOIN pg_class i ON d.indexrelid = i.oid | |||
LEFT JOIN pg_namespace n ON n.oid = i.relnamespace | |||
WHERE i.relkind = 'i' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 We can hardcode IN ('i', 'I')
for all versions here since it will not break older versions AFAIK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm gonna try hardcoding the IN
clause and running the test suite with older PG versions. I used PostgreSQL 11 to test this.
@@ -774,6 +774,11 @@ def quoted_scope(name = nil, type: nil) | |||
scope | |||
end | |||
|
|||
def relkind |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 There's already space before interpolation at WHERE i.relkind #{relkind}
. There's no need to return string starting with space.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we hardcode the IN clause, we can get rid of this method 😉
activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
Outdated
Show resolved
Hide resolved
@@ -3,6 +3,7 @@ | |||
require "cases/helper" | |||
require "models/book" | |||
require "models/speedometer" | |||
require "models/measurement" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 Maybe we can require this only in test_upsert_all_works_with_partitioned_indexes
after the skip part since it will be used only there and for all other cases it will get loaded model having no real db table (since it is created conditionally).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a nice catch! And I think is a good idea, since there's only one test in the whole file making use of it.
BTW I tested the WHERE i.relkind IN ('i', 'I')
changes in PostgreSQL 9.4, 9.6 and 10 (plus 11) and the test suite passes without problems.
Hey @kamipo, could you take a look at this PR, please? I'm wondering if it can be merged in order to solve the problem stated in the description. |
Why? |
I thought it'd make the PR "non-atomic" by trying to solve two things at once. Should I go with those changes? |
@vnhnhm if you would like to add support for partitioned indexes of PostgreSQL adapter in general, you should fix all places needed. Your current change does fix only |
activerecord/test/schema/schema.rb
Outdated
@@ -503,6 +503,20 @@ | |||
t.column :weight, :integer | |||
end | |||
|
|||
if supports_partitioned_indexes? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 I think you can move this to test/schema/postgresql_specific_schema.rb
.
@vnhnhm I think you should update the changelog entry title as well. |
It seems I did something wrong while trying to update the changelog, no @simi? |
Try to rebase against latest master @vnhnhm. |
It looks better now, thanks @simi |
Looks ok now. @kamipo any chance to take another look at this? |
@@ -124,6 +124,10 @@ def supports_partial_index? | |||
true | |||
end | |||
|
|||
def supports_partitioned_indexes? | |||
false | |||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be necessary, since it's identical to the version in AbstractAdapter.
activerecord/CHANGELOG.md
Outdated
@@ -1,3 +1,7 @@ | |||
* Add support for PostgreSQL 11+ partitioned indexes when using `upsert-all`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Add support for PostgreSQL 11+ partitioned indexes when using `upsert-all`. | |
* Add support for PostgreSQL 11+ partitioned indexes when using `upsert_all`. |
Hey @eugeneius, just removed the changes from the SQLite3Adapter and updated the changelog as suggested, thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good to me
PS: rebase would be nice
Yes, also to me :-). Thanks @simi |
Can you squash your commits into one? |
indexes in a table. Currently the pg_class catalog is filtered out to retrieve the indexes in a table by its relkind value. Which in versions lower than 11 of PostgreSQL is always `i` (lower case). But since version 11, PostgreSQL supports partitioned indexes referenced with a relkind value of `I` (upper case). This makes any feature within the current code base to exclude those partitioned indexes. The solution proposed is to make use of the `IN` clause to filter those relkind values of `i` and/or `I` when retrieving a table indexes.
Sure, done @kamipo |
🎉 thanks everone involved! |
…-indexes Add support for partitioned indexes in PostgreSQL 11+
This PR adds support to retrieve partitioned indexes when asking for indexes in a table.
Currently, the
pg_class
catalog is filtered out to retrieve the indexes in atable by its
relkind
value. Which in versions lower than 11 of PostgreSQLis always
i
(lower case). But since version 11, PostgreSQLsupports partitioned indexes referenced with a
relkind
value ofI
(upper case). This makes any feature within the current code base to exclude those
partitioned indexes.
The solution proposed is to make use of the
IN
clause to filter thoserelkind
values ofi
and/orI
when retrieving table indexes.This adds the needed changes to cover the issue when performing an
upsert_all
with a partitioned table and a unique index in the parent table.As
index_name_exists?
also performs therelkind = 'i'
filter when asking for the indexes, it's been updated to reflect these changes.