From 86d3f251c802575fa1414a10f2981566002c19d4 Mon Sep 17 00:00:00 2001 From: Martin Schuster Date: Tue, 4 Jun 2019 15:47:21 +0200 Subject: Fix sqlite3 collation parsing when using decimal columns. If an sqlite3 table contains a decimal column behind columns with a collation definition, then parsing the collation of all preceeding columns will fail -- the collation will be missed without notice. --- activerecord/CHANGELOG.md | 4 ++++ .../lib/active_record/connection_adapters/sqlite3_adapter.rb | 4 ++-- activerecord/test/cases/adapters/sqlite3/collation_test.rb | 9 +++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 6f08b1b8fe..7cc9ee92c2 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +* Fix sqlite3 collation parsing when using decimal columns. + + *Martin R. Schuster* + * Fix invalid schema when primary key column has a comment Fixes #29966 diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index 7f3f32162e..9fc5ee3ab4 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -477,9 +477,9 @@ module ActiveRecord result = exec_query(sql, "SCHEMA").first if result - # Splitting with left parentheses and picking up last will return all + # Splitting with left parentheses and discarding the first part will return all # columns separated with comma(,). - columns_string = result["sql"].split("(").last + columns_string = result["sql"].split("(", 2).last columns_string.split(",").each do |column_string| # This regex will match the column name and collation type and will save diff --git a/activerecord/test/cases/adapters/sqlite3/collation_test.rb b/activerecord/test/cases/adapters/sqlite3/collation_test.rb index 76c8f7d8dd..d938b5ff2f 100644 --- a/activerecord/test/cases/adapters/sqlite3/collation_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/collation_test.rb @@ -11,6 +11,10 @@ class SQLite3CollationTest < ActiveRecord::SQLite3TestCase @connection.create_table :collation_table_sqlite3, force: true do |t| t.string :string_nocase, collation: "NOCASE" t.text :text_rtrim, collation: "RTRIM" + # The decimal column might interfere with collation parsing. + # Thus, add this column type and some other string column afterwards. + t.decimal :decimal_col, precision: 6, scale: 2 + t.string :string_after_decimal_nocase, collation: "NOCASE" end end @@ -22,6 +26,11 @@ class SQLite3CollationTest < ActiveRecord::SQLite3TestCase column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == "string_nocase" } assert_equal :string, column.type assert_equal "NOCASE", column.collation + + # Verify collation of a column behind the decimal column as well. + column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == "string_after_decimal_nocase" } + assert_equal :string, column.type + assert_equal "NOCASE", column.collation end test "text column with collation" do -- cgit v1.2.3