Skip to content
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

Postresql index with type casting using CAST AS is non-rollbackable #32621

Closed
tomash opened this issue Apr 18, 2018 · 4 comments
Closed

Postresql index with type casting using CAST AS is non-rollbackable #32621

tomash opened this issue Apr 18, 2018 · 4 comments

Comments

@tomash
Copy link
Contributor

tomash commented Apr 18, 2018

Steps to reproduce

The requirement: adding typecasted index, namely created_at typecasted to DATE type because we're calculating daily statistics and therefore choosing rows with WHERE payments.created_at::date='2018-03-01'.

Adding a migration with

add_index :payments, "CAST(created_at AS date)"

creates an index and the following entry in schema.rb:

t.index "((created_at)::date)", name: "index_payments_on_CAST_created_at_AS_date"

So the migration engine was smart enough to shorthand CAST AS syntax into :: syntax, BUT puts the wrong name of newly created index into schema.rb. The actual name of index in the database is also generated based on shorthand form (which is nice and consistent), it's index_payments_on_created_at_date in this case.

Unfortunately the naming inconsistency causes the migration to be non-rollbackable, because

$ rails db:rollback
== 20180418123502 AddIndexToCreatedAtAsDate: reverting ========================
-- remove_index(:payments, {:column=>"CAST(created_at AS date)"})
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

No indexes found on payments with the options provided.
/home/tomek/.rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/connection_adapters/abstract/schema_statements.rb:1236:in `index_name_for_remove'
/home/tomek/.rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/connection_adapters/postgresql/schema_statements.rb:502:in `remove_index'

Or to put it shortly, the index with given name does not exist.

WORKAROUND: use shorthand form in migration, in this case

add_index :payments, "((created_at)::date)"

which creates a proper entry in schema.rb:

t.index "((created_at)::date)", name: "index_payments_on_created_at_date"

and rolls back like a charm.

Expected behavior

CAST AS form should generate rollback-able migrations.

System configuration

Rails version: 5.1.5

Ruby version: 2.5.0

@tomash tomash changed the title Postresql index with type casting puts wrong name in schema.rb Postresql index with type casting using CAST AS is non-rollbackable Apr 18, 2018
@tomash
Copy link
Contributor Author

tomash commented Apr 18, 2018

Note: I'll make a reproducible test case with active_record_gem.rb asap.

@abaldwin88
Copy link
Contributor

abaldwin88 commented Apr 26, 2018

Reproduced case for 5.2: https://gist.github.com/abaldwin88/c24db432b7b351fafe56797b97ae6a54

Here's one against master: https://gist.github.com/abaldwin88/30be7716414315102a14d56bfb186721

I'm going to take a stab at opening a PR in the next couple days

abaldwin88 added a commit to abaldwin88/rails that referenced this issue Apr 29, 2018
When creating an index in Postgres `CAST(created_at AS date)` is converted to `((created_at)::date)`.
This difference causes the `index_name` method to return 'index_payments_on_CAST_created_at_AS_date' when the index is created with the CAST statement and 'index_payments_on_created_at_date' when the postgres shorthand syntax is passed in during removal.

By adding an additional check against the index name we are able to handle this scenario appropriately.

Fixes rails#32621
@rails-bot
Copy link

rails-bot bot commented Jul 25, 2018

This issue has been automatically marked as stale because it has not been commented on for at least three months.
The resources of the Rails team are limited, and so we are asking for your help.
If you can still reproduce this error on the 5-2-stable branch or on master, please reply with all of the information you have about it in order to keep the issue open.
Thank you for all your contributions.

@rails-bot rails-bot bot added the stale label Jul 25, 2018
@rails-bot rails-bot bot closed this as completed Aug 2, 2018
@abaldwin88
Copy link
Contributor

For posterity -- The reproduction script is passing against version 7.0.5 (And may potentially succeed for versions after 5.2)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants