shard-crystal-sqlite3/spec/db_spec.cr

139 lines
4.5 KiB
Crystal

require "./spec_helper"
require "db/spec"
private class NotSupportedType
end
private def cast_if_blob(expr, sql_type)
case sql_type
when "blob"
"cast(#{expr} as blob)"
else
expr
end
end
DB::DriverSpecs(DB::Any).run do |ctx|
support_unprepared false
before do
File.delete(DB_FILENAME) if File.exists?(DB_FILENAME)
end
after do
File.delete(DB_FILENAME) if File.exists?(DB_FILENAME)
end
connection_string "sqlite3:#{DB_FILENAME}"
# ? can use many ... (:memory:)
sample_value true, "int", "1", type_safe_value: false
sample_value false, "int", "0", type_safe_value: false
sample_value 2, "int", "2", type_safe_value: false
sample_value 1_i64, "int", "1"
sample_value "hello", "text", "'hello'"
sample_value 1.5_f32, "float", "1.5", type_safe_value: false
sample_value 1.5, "float", "1.5"
sample_value Time.utc(2016, 2, 15), "text", "'2016-02-15 00:00:00.000'", type_safe_value: false
sample_value Time.utc(2016, 2, 15, 10, 15, 30), "text", "'2016-02-15 10:15:30'", type_safe_value: false
sample_value Time.utc(2016, 2, 15, 10, 15, 30), "text", "'2016-02-15 10:15:30.000'", type_safe_value: false
sample_value Time.utc(2016, 2, 15, 10, 15, 30, nanosecond: 123000000), "text", "'2016-02-15 10:15:30.123'", type_safe_value: false
sample_value Time.local(2016, 2, 15, 7, 15, 30, location: Time::Location.fixed("fixed", -3*3600)), "text", "'2016-02-15 10:15:30.000'", type_safe_value: false
ary = UInt8[0x53, 0x51, 0x4C, 0x69, 0x74, 0x65]
sample_value Bytes.new(ary.to_unsafe, ary.size), "blob", "X'53514C697465'" # , type_safe_value: false
binding_syntax do |index|
"?"
end
create_table_1column_syntax do |table_name, col1|
"create table #{table_name} (#{col1.name} #{col1.sql_type} #{col1.null ? "NULL" : "NOT NULL"})"
end
create_table_2columns_syntax do |table_name, col1, col2|
"create table #{table_name} (#{col1.name} #{col1.sql_type} #{col1.null ? "NULL" : "NOT NULL"}, #{col2.name} #{col2.sql_type} #{col2.null ? "NULL" : "NOT NULL"})"
end
select_1column_syntax do |table_name, col1|
"select #{cast_if_blob(col1.name, col1.sql_type)} from #{table_name}"
end
select_2columns_syntax do |table_name, col1, col2|
"select #{cast_if_blob(col1.name, col1.sql_type)}, #{cast_if_blob(col2.name, col2.sql_type)} from #{table_name}"
end
select_count_syntax do |table_name|
"select count(*) from #{table_name}"
end
select_scalar_syntax do |expression, sql_type|
"select #{cast_if_blob(expression, sql_type)}"
end
insert_1column_syntax do |table_name, col, expression|
"insert into #{table_name} (#{col.name}) values (#{expression})"
end
insert_2columns_syntax do |table_name, col1, expr1, col2, expr2|
"insert into #{table_name} (#{col1.name}, #{col2.name}) values (#{expr1}, #{expr2})"
end
drop_table_if_exists_syntax do |table_name|
"drop table if exists #{table_name}"
end
it "gets last insert row id", prepared: :both do |db|
db.exec "create table person (name text, age integer)"
db.exec %(insert into person values ("foo", 10))
res = db.exec %(insert into person values ("foo", 10))
res.last_insert_id.should eq(2)
res.rows_affected.should eq(1)
end
# TODO timestamp support
it "raises on unsupported param types" do |db|
expect_raises Exception, "SQLite3::Statement does not support NotSupportedType params" do
db.query "select ?", NotSupportedType.new
end
# TODO raising exception does not close the connection and pool is exhausted
end
it "ensures statements are closed" do |db|
db.exec %(create table if not exists a (i int not null, str text not null);)
db.exec %(insert into a (i, str) values (23, "bai bai");)
2.times do |i|
DB.open ctx.connection_string do |db|
begin
db.query("SELECT i, str FROM a WHERE i = ?", 23) do |rs|
rs.move_next
break
end
rescue e : SQLite3::Exception
fail("Expected no exception, but got \"#{e.message}\"")
end
begin
db.exec("UPDATE a SET i = ? WHERE i = ?", 23, 23)
rescue e : SQLite3::Exception
fail("Expected no exception, but got \"#{e.message}\"")
end
end
end
end
it "handles single-step pragma statements" do |db|
db.exec %(PRAGMA synchronous = OFF)
end
it "handles multi-step pragma statements" do |db|
db.exec %(PRAGMA journal_mode = memory)
end
it "handles REGEXP operator" do |db|
(db.scalar "select 'unmatching text' REGEXP '^m'").should eq 0
(db.scalar "select 'matching text' REGEXP '^m'").should eq 1
end
end