Skip to content

Commit

Permalink
Add a strict: true option.
Browse files Browse the repository at this point in the history
Ref: rails/rails#45101
Ref: rails/rails#27782
Ref: https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted

Sqlite has a really unfortunate behavior around double quotes. It first
tries to consider them as column names, but if they don't exist it then consider
them as string literals.

Because of this, typos can silently go unnoticed. It would be very useful
for Active Record if this behavior could be disabled.
  • Loading branch information
byroot committed May 25, 2022
1 parent 09f0276 commit 40fb6cc
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 0 deletions.
18 changes: 18 additions & 0 deletions ext/sqlite3/database.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,23 @@ static VALUE rb_sqlite3_open_v2(VALUE self, VALUE file, VALUE mode, VALUE zvfs)
return self;
}

static VALUE rb_sqlite3_disable_quirk_mode(VALUE self)
{
#if defined SQLITE_DBCONFIG_DQS_DDL
sqlite3RubyPtr ctx;
Data_Get_Struct(self, sqlite3Ruby, ctx);

if(!ctx->db) return Qfalse;

sqlite3_db_config(ctx->db, SQLITE_DBCONFIG_DQS_DDL, 0, (void*)0);
sqlite3_db_config(ctx->db, SQLITE_DBCONFIG_DQS_DML, 0, (void*)0);

return Qtrue;
#else
return Qfalse
#endif
}

/* call-seq: db.close
*
* Closes this database.
Expand Down Expand Up @@ -805,6 +822,7 @@ void init_sqlite3_database()
/* public "define_aggregator" is now a shim around define_aggregator2
* implemented in Ruby */
rb_define_private_method(cSqlite3Database, "define_aggregator2", rb_sqlite3_define_aggregator2, 2);
rb_define_private_method(cSqlite3Database, "disable_quirk_mode", rb_sqlite3_disable_quirk_mode, 0);
rb_define_method(cSqlite3Database, "interrupt", interrupt, 0);
rb_define_method(cSqlite3Database, "errmsg", errmsg, 0);
rb_define_method(cSqlite3Database, "errcode", errcode_, 0);
Expand Down
4 changes: 4 additions & 0 deletions lib/sqlite3/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ def initialize file, options = {}, zvfs = nil
end

open_v2 file.encode("utf-8"), mode, zvfs

if options[:strict]
disable_quirk_mode
end
end

@tracefunc = nil
Expand Down
13 changes: 13 additions & 0 deletions test/test_database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -510,5 +510,18 @@ def test_query_with_named_bind_params
def test_execute_with_named_bind_params
assert_equal [['foo']], @db.execute("select :n", {'n' => 'foo'})
end

def test_strict_mode
db = SQLite3::Database.new(':memory:')
db.execute('create table numbers (val int);')
db.execute('create index index_numbers_nope ON numbers ("nope");') # nothing raised

db = SQLite3::Database.new(':memory:', :strict => true)
db.execute('create table numbers (val int);')
error = assert_raises SQLite3::SQLException do
db.execute('create index index_numbers_nope ON numbers ("nope");')
end
assert_includes error.message, "no such column: nope"
end
end
end

0 comments on commit 40fb6cc

Please sign in to comment.