Skip to content

Commit d4f3a45

Browse files
flavorjonesbyroot
authored andcommitted
fix: sqlite3 adapter quotes Infinity and NaN
This is similar to the fix applied to the postgresql adapter in rails#3713 This isn't a problem if the value is provided as a parameter to a prepared statement, but is a problem where literal SQL is assembled, for example with `upsert`. Without quoting, the exception raised is: ``` >> Shirt.upsert({id: 1, size: Float::INFINITY}) sqlite3-2.6.0-x86_64-linux-gnu/lib/sqlite3/statement.rb:36:in 'SQLite3::Statement#prepare': no such column: Infinity: (SQLite3::SQLException) INSERT INTO "shirts" ("id","size","created_at","updated_at") VALUES (1, Infinity, STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW'), STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')) ON CONFLICT ("id") DO UPDATE SET updated_at=(CASE WHEN ("size" IS excluded."size") THEN "shirts".updated_at ELSE STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') END),"size"=excluded."size" RETURNING "id" ^ from sqlite3-2.6.0-x86_64-linux-gnu/lib/sqlite3/statement.rb:36:in 'SQLite3::Statement#initialize' from sqlite3-2.6.0-x86_64-linux-gnu/lib/sqlite3/database.rb:216:in 'Class#new' from sqlite3-2.6.0-x86_64-linux-gnu/lib/sqlite3/database.rb:216:in 'SQLite3::Database#prepare' from rails/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb:94:in 'ActiveRecord::ConnectionAdapters::SQLite3::DatabaseStatements#perform_query' ... from rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:558:in 'block in ActiveRecord::ConnectionAdapters::DatabaseStatements#raw_execute' ... from rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:557:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#raw_execute' from rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:601:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#internal_execute' from rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:550:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#internal_exec_query' from rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:180:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#exec_insert_all' from rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:27:in 'ActiveRecord::ConnectionAdapters::AbstractAdapter#exec_insert_all' from rails/activerecord/lib/active_record/insert_all.rb:54:in 'ActiveRecord::InsertAll#execute' from rails/activerecord/lib/active_record/insert_all.rb:13:in 'block in ActiveRecord::InsertAll.execute' ... ``` Quoting this value of "Infinity" (and also "NaN") does what's intended.
1 parent c356b42 commit d4f3a45

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@ def quote_table_name(name)
5050
end
5151
end
5252

53+
def quote(value) # :nodoc:
54+
case value
55+
when Numeric
56+
if value.finite?
57+
super
58+
else
59+
"'#{value}'"
60+
end
61+
else
62+
super
63+
end
64+
end
65+
5366
def quote_string(s)
5467
::SQLite3::Database.quote(s)
5568
end

activerecord/test/cases/adapters/sqlite3/quoting_test.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,16 @@ def test_quoted_time_dst_local
9595
end
9696
end
9797
end
98+
99+
def test_quote_numeric_infinity
100+
assert_equal "'Infinity'", @conn.quote(Float::INFINITY)
101+
assert_equal "'-Infinity'", @conn.quote(-Float::INFINITY)
102+
assert_equal "'Infinity'", @conn.quote(BigDecimal(Float::INFINITY))
103+
assert_equal "'-Infinity'", @conn.quote(BigDecimal(-Float::INFINITY))
104+
end
105+
106+
def test_quote_float_nan
107+
assert_equal "'NaN'", @conn.quote(Float::NAN)
108+
assert_equal "'NaN'", @conn.quote(BigDecimal(Float::NAN))
109+
end
98110
end

0 commit comments

Comments
 (0)