SQLite3: Support multiple args function for expression indexes
Follow up #33874. Related #23393.
This commit is contained in:
parent
7265b89780
commit
af653ef721
@ -1,4 +1,4 @@
|
|||||||
* SQLite3 adapter supports expression indexes
|
* SQLite3 adapter supports expression indexes.
|
||||||
|
|
||||||
```
|
```
|
||||||
create_table :users do |t|
|
create_table :users do |t|
|
||||||
|
@ -21,23 +21,24 @@ def indexes(table_name)
|
|||||||
WHERE name = #{quote(row['name'])} AND type = 'index'
|
WHERE name = #{quote(row['name'])} AND type = 'index'
|
||||||
SQL
|
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|
|
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
|
|
||||||
# the default)
|
|
||||||
orders = {}
|
orders = {}
|
||||||
if index_sql # index_sql can be null in case of primary key indexes
|
|
||||||
index_sql.scan(/"(\w+)" DESC/).flatten.each { |order_column|
|
if columns.any?(&:nil?) # index created with an expression
|
||||||
orders[order_column] = :desc
|
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
|
end
|
||||||
|
|
||||||
IndexDefinition.new(
|
IndexDefinition.new(
|
||||||
|
@ -487,9 +487,12 @@ def copy_table_indexes(from, to, rename = {})
|
|||||||
name = name[1..-1]
|
name = name[1..-1]
|
||||||
end
|
end
|
||||||
|
|
||||||
to_column_names = columns(to).map(&:name)
|
columns = index.columns
|
||||||
columns = index.columns.map { |c| rename[c] || c }.select do |column|
|
if columns.is_a?(Array)
|
||||||
to_column_names.include?(column)
|
to_column_names = columns(to).map(&:name)
|
||||||
|
columns = columns.map { |c| rename[c] || c }.select do |column|
|
||||||
|
to_column_names.include?(column)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
unless columns.empty?
|
unless columns.empty?
|
||||||
|
@ -348,34 +348,35 @@ def test_compound_index
|
|||||||
if ActiveRecord::Base.connection.supports_expression_index?
|
if ActiveRecord::Base.connection.supports_expression_index?
|
||||||
def test_expression_index
|
def test_expression_index
|
||||||
with_example_table do
|
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" }
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_expression_index_with_where
|
def test_expression_index_with_where
|
||||||
with_example_table do
|
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" }
|
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
|
assert_equal "id > 1000", index.where
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_complicated_expression
|
def test_complicated_expression
|
||||||
with_example_table do
|
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" }
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_not_everything_an_expression
|
def test_not_everything_an_expression
|
||||||
with_example_table do
|
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" }
|
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
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user