mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
SQLite3 adapter supports expression indexes
This commit is contained in:
parent
b20762e56c
commit
3a36cb0868
5 changed files with 70 additions and 6 deletions
|
@ -1,3 +1,15 @@
|
||||||
|
* SQLite3 adapter supports expression indexes
|
||||||
|
|
||||||
|
```
|
||||||
|
create_table :users do |t|
|
||||||
|
t.string :email
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :users, 'lower(email)', name: 'index_users_on_email', unique: true
|
||||||
|
```
|
||||||
|
|
||||||
|
*Gray Kemmey*
|
||||||
|
|
||||||
* Allow subclasses to redefine autosave callbacks for associated records.
|
* Allow subclasses to redefine autosave callbacks for associated records.
|
||||||
|
|
||||||
Fixes #33305.
|
Fixes #33305.
|
||||||
|
|
|
@ -21,12 +21,16 @@ module ActiveRecord
|
||||||
WHERE name = #{quote(row['name'])} AND type = 'index'
|
WHERE name = #{quote(row['name'])} AND type = 'index'
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
/\sWHERE\s+(?<where>.+)$/i =~ index_sql
|
/\sON\s+"(\w+?)"\s+\((?<expressions>.+?)\)(\sWHERE\s+(?<where>.+))?$/i =~ index_sql
|
||||||
|
|
||||||
columns = exec_query("PRAGMA index_info(#{quote(row['name'])})", "SCHEMA").map do |col|
|
columns = exec_query("PRAGMA index_info(#{quote(row['name'])})", "SCHEMA").map do |col|
|
||||||
col["name"]
|
col["name"]
|
||||||
end
|
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
|
# Add info on sort order for columns (only desc order is explicitly specified, asc is
|
||||||
# the default)
|
# the default)
|
||||||
orders = {}
|
orders = {}
|
||||||
|
|
|
@ -125,6 +125,10 @@ module ActiveRecord
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def supports_expression_index?
|
||||||
|
sqlite_version >= "3.9.0"
|
||||||
|
end
|
||||||
|
|
||||||
def requires_reloading?
|
def requires_reloading?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
|
@ -345,6 +345,41 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if ActiveRecord::Base.connection.supports_expression_index?
|
||||||
|
def test_expression_index
|
||||||
|
with_example_table do
|
||||||
|
@conn.add_index "ex", "abs(number)", name: "expression"
|
||||||
|
index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
|
||||||
|
assert_equal %w{ abs(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"
|
||||||
|
index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
|
||||||
|
assert_equal ["id % 10", "abs(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"
|
||||||
|
index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
|
||||||
|
assert_equal ["id % 10", "(CASE WHEN number > 0 THEN abs(number) END)"], index.columns
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_not_everything_an_expression
|
||||||
|
with_example_table do
|
||||||
|
@conn.add_index "ex", %w{ id abs(number) }, name: "expression"
|
||||||
|
index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
|
||||||
|
assert_equal %w{ id abs(number) }.sort, index.columns.sort
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_primary_key
|
def test_primary_key
|
||||||
with_example_table do
|
with_example_table do
|
||||||
assert_equal "id", @conn.primary_key("ex")
|
assert_equal "id", @conn.primary_key("ex")
|
||||||
|
|
|
@ -226,6 +226,20 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
||||||
assert_match %r{t\.float\s+"temperature"$}, output
|
assert_match %r{t\.float\s+"temperature"$}, output
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if ActiveRecord::Base.connection.supports_expression_index?
|
||||||
|
def test_schema_dump_expression_indices
|
||||||
|
index_definition = dump_table_schema("companies").split(/\n/).grep(/t\.index.*company_expression_index/).first.strip
|
||||||
|
|
||||||
|
if current_adapter?(:PostgreSQLAdapter)
|
||||||
|
assert_match %r{CASE.+lower\(\(name\)::text\)}i, index_definition
|
||||||
|
elsif current_adapter?(:SQLite3Adapter)
|
||||||
|
assert_match %r{CASE.+lower\(name\)}i, index_definition
|
||||||
|
else
|
||||||
|
assert false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if current_adapter?(:Mysql2Adapter)
|
if current_adapter?(:Mysql2Adapter)
|
||||||
def test_schema_dump_includes_length_for_mysql_binary_fields
|
def test_schema_dump_includes_length_for_mysql_binary_fields
|
||||||
output = standard_dump
|
output = standard_dump
|
||||||
|
@ -278,11 +292,6 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
||||||
assert_match %r{t\.decimal\s+"decimal_array_default",\s+default: \["1.23", "3.45"\],\s+array: true}, output
|
assert_match %r{t\.decimal\s+"decimal_array_default",\s+default: \["1.23", "3.45"\],\s+array: true}, output
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_schema_dump_expression_indices
|
|
||||||
index_definition = dump_table_schema("companies").split(/\n/).grep(/t\.index.*company_expression_index/).first.strip
|
|
||||||
assert_match %r{CASE.+lower\(\(name\)::text\)}i, index_definition
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_schema_dump_interval_type
|
def test_schema_dump_interval_type
|
||||||
output = dump_table_schema "postgresql_times"
|
output = dump_table_schema "postgresql_times"
|
||||||
assert_match %r{t\.interval\s+"time_interval"$}, output
|
assert_match %r{t\.interval\s+"time_interval"$}, output
|
||||||
|
|
Loading…
Reference in a new issue