[ActiveRecord] Schema Dumper Columns Order#32111
[ActiveRecord] Schema Dumper Columns Order#32111Tensho wants to merge 2 commits intorails:masterfrom
Conversation
fcc0c54 to
0732289
Compare
I agree that strongly supports the assumption that SHOW is ordered. Does your newly added test fail without the adapter change? 😕 I don't recall ever hearing a claim that the schema dump doesn't match the database column order. |
|
IME that happens when the |
|
🤔 Hmmn, maybe the problem arises from the input side, for example @matthewd, thank you for your time 🙇 P.S. Does the test for tables alphabetical order is still acceptable? |

Summary
From project to project written with Rails I spectate the similar snag, when column definition rows in the schema are shuffled from time to time (only for
schema.rbin:rubymode). It's annoying to see the changes in the git index, despite I haven't touched any of them. It's really hard for me to define the steps to reproduce for this bug, but let me put here my thoughts and proposed changes. First consider the next example for better clarity:Here "country_code" column definition changed position even though there was no any related migration code.
First of all I thought this behaviour is connected somehow with database engine version or operating system version divergence between developers in our team. So we setup the same version of Rails 4.2 (later checked on 5.2) and MySQL 5.7.20 on macOS Sierra 10.12.6 at MacBook Pro. But there was no luck – I still spectate schema shuffling.
Then I decided to dig into the schema dumper code to understand how ActiveRecord retrieves columns information and dumps it to the
schema.rbfile. Inside I noticed expected alphabetical table names sorting:Then I found table columns info retrievement:
So there is no specific ordering. "Hmmn" 🤔 , – was sparkled in my – "Maybe it's desirable to show columns definition in the same manera as database holds them and don't sort in alphabetical order. But how different databases return schema info and do they comply the result order?". I moved to connection adapters:
• MySQL (
ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter)I haven't found any proof in the
SHOW COLUMNS(synonym toSHOW FIELDS) MySQL official documentation that ordering is present. But I found the next interesting discussions – "SHOW DATABASES does not order infomation_schema correct" and "Return order of MySQL SHOW COLUMNS" – where people argue how MySQL handles position of columns info. Unfortunately, I'm not able to trace MySQL server source code to find the pure evidence. Let's assume all this means
column_definitionsdoesn't gauranty the order. Do we have alternatives? Yes!DESCRIBE(the clone ofSHOW COLUMNS, that leads me to the idea MySQL follows the same "There is more than one way to do it" principle as Ruby/Perl 😄 )INFORMATION_SCHEMA.COLUMNSMySQL has ORDINAL POSITION of the columns and provides it in
INFORMATION_SCHEMA.COLUMNS. But there is one note, that makes me confused:Seems like thoeretically
SHOWshould keep the order according to what I see in the note, but practically I see the opposite. Unlike Postgres, MySQL allows to insert column before or after specific one.I'd be very pleasant to hear any thoughts and get any references regarding the columns positioning (logical, physical, virtual, etc.) here.
• Postgres (
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)Schema info retrievement is pretty straightforward from
pg_attributesystem table. We have explicitORDER BY a.attnum(a.attnum – the number of the column), which should guarantee the order of attributes I guess. Unlike MySQL, Postgres doesn't allow to insert column before or after specific one.• SQlite3 (
ActiveRecord::ConnectionAdapters::SQLite3Adapter)PRAGMA table_infolacks the required knowledge, that's why ActiveRecord usessqlite_masterreadonly table to get and parse initial table creation SQL. As far as we parse the SQL statements all the time, it could be considered as columns order guarantee. Here is an excerpt from theALTER TABLEofficial documentation regarding column position specification:Alternatives
Any sorting, especially if it's not supported in the database, could be performed at schema dumper level. For example, dumper sorts table names in the alphabetical order right now. The same approach could be applied to the columns. Moreover we may enforce ordering at both levels – database query and schema dumper table info processing.
Considertations
How do different databases consider the columns order? AFAIK, there are 2 points:
Proposed changes
Does all this make sense? Please shout out if I have to cover provided changes with specs somewhere else. Also I'm happy for any critics 🙇