aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2018-09-14 09:19:49 +0900
committerRyuta Kamizono <kamipo@gmail.com>2018-09-14 09:32:37 +0900
commitaf653ef72190c6cd3e6b2a86786a981ad4bdb44e (patch)
tree697b61556c11f64322e2b3dfca1e3b739fec43ca
parent7265b897805aee6b858fb72f5fc33e4622635dab (diff)
downloadrails-af653ef72190c6cd3e6b2a86786a981ad4bdb44e.tar.gz
rails-af653ef72190c6cd3e6b2a86786a981ad4bdb44e.tar.bz2
rails-af653ef72190c6cd3e6b2a86786a981ad4bdb44e.zip
SQLite3: Support multiple args function for expression indexes
Follow up #33874. Related #23393.
-rw-r--r--activerecord/CHANGELOG.md2
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb23
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb9
-rw-r--r--activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb17
4 files changed, 28 insertions, 23 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index fa230df993..477bc1b54a 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,4 +1,4 @@
-* SQLite3 adapter supports expression indexes
+* SQLite3 adapter supports expression indexes.
```
create_table :users do |t|
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb
index 0e254455b6..46ca7e07a9 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb
@@ -21,23 +21,24 @@ module ActiveRecord
WHERE name = #{quote(row['name'])} AND type = 'index'
SQL
- /\sON\s+"(\w+?)"\s+\((?<expressions>.+?)\)(\sWHERE\s+(?<where>.+))?$/i =~ index_sql
+ /\bON\b\s*"?(\w+?)"?\s*\((?<expressions>.+?)\)(?:\s*WHERE\b\s*(?<where>.+))?\z/i =~ index_sql
columns = exec_query("PRAGMA index_info(#{quote(row['name'])})", "SCHEMA").map do |col|
col["name"]
end
- if columns.any?(&:nil?) # index created with an expression
- columns = expressions.split(", ").map { |e| e.gsub(/^\"|\"?$/, "") }
- end
-
- # Add info on sort order for columns (only desc order is explicitly specified, asc is
- # the default)
orders = {}
- if index_sql # index_sql can be null in case of primary key indexes
- index_sql.scan(/"(\w+)" DESC/).flatten.each { |order_column|
- orders[order_column] = :desc
- }
+
+ if columns.any?(&:nil?) # index created with an expression
+ columns = expressions
+ else
+ # Add info on sort order for columns (only desc order is explicitly specified,
+ # asc is the default)
+ if index_sql # index_sql can be null in case of primary key indexes
+ index_sql.scan(/"(\w+)" DESC/).flatten.each { |order_column|
+ orders[order_column] = :desc
+ }
+ end
end
IndexDefinition.new(
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index 51f4944808..d32fd5ea09 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -487,9 +487,12 @@ module ActiveRecord
name = name[1..-1]
end
- to_column_names = columns(to).map(&:name)
- columns = index.columns.map { |c| rename[c] || c }.select do |column|
- to_column_names.include?(column)
+ columns = index.columns
+ if columns.is_a?(Array)
+ to_column_names = columns(to).map(&:name)
+ columns = columns.map { |c| rename[c] || c }.select do |column|
+ to_column_names.include?(column)
+ end
end
unless columns.empty?
diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
index 320f6efd56..7b73621ed9 100644
--- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
@@ -348,34 +348,35 @@ module ActiveRecord
if ActiveRecord::Base.connection.supports_expression_index?
def test_expression_index
with_example_table do
- @conn.add_index "ex", "abs(number)", name: "expression"
+ @conn.add_index "ex", "max(id, number)", name: "expression"
index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
- assert_equal %w{ abs(number) }, index.columns
+ assert_equal "max(id, number)", index.columns
end
end
def test_expression_index_with_where
with_example_table do
- @conn.add_index "ex", "id % 10, abs(number)", name: "expression", where: "id > 1000"
+ @conn.add_index "ex", "id % 10, max(id, number)", name: "expression", where: "id > 1000"
index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
- assert_equal ["id % 10", "abs(number)"], index.columns
+ assert_equal "id % 10, max(id, number)", index.columns
assert_equal "id > 1000", index.where
end
end
def test_complicated_expression
with_example_table do
- @conn.add_index "ex", "id % 10, (CASE WHEN number > 0 THEN abs(number) END)", name: "expression"
+ @conn.execute "CREATE INDEX expression ON ex (id % 10, (CASE WHEN number > 0 THEN max(id, number) END))WHERE(id > 1000)"
index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
- assert_equal ["id % 10", "(CASE WHEN number > 0 THEN abs(number) END)"], index.columns
+ assert_equal "id % 10, (CASE WHEN number > 0 THEN max(id, number) END)", index.columns
+ assert_equal "(id > 1000)", index.where
end
end
def test_not_everything_an_expression
with_example_table do
- @conn.add_index "ex", %w{ id abs(number) }, name: "expression"
+ @conn.add_index "ex", "id, max(id, number)", name: "expression"
index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
- assert_equal %w{ id abs(number) }.sort, index.columns.sort
+ assert_equal "id, max(id, number)", index.columns
end
end
end