Skip to content

Commit 40fb6cc

Browse files
committed
Add a strict: true option.
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.
1 parent 09f0276 commit 40fb6cc

3 files changed

Lines changed: 35 additions & 0 deletions

File tree

ext/sqlite3/database.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,23 @@ static VALUE rb_sqlite3_open_v2(VALUE self, VALUE file, VALUE mode, VALUE zvfs)
6666
return self;
6767
}
6868

69+
static VALUE rb_sqlite3_disable_quirk_mode(VALUE self)
70+
{
71+
#if defined SQLITE_DBCONFIG_DQS_DDL
72+
sqlite3RubyPtr ctx;
73+
Data_Get_Struct(self, sqlite3Ruby, ctx);
74+
75+
if(!ctx->db) return Qfalse;
76+
77+
sqlite3_db_config(ctx->db, SQLITE_DBCONFIG_DQS_DDL, 0, (void*)0);
78+
sqlite3_db_config(ctx->db, SQLITE_DBCONFIG_DQS_DML, 0, (void*)0);
79+
80+
return Qtrue;
81+
#else
82+
return Qfalse
83+
#endif
84+
}
85+
6986
/* call-seq: db.close
7087
*
7188
* Closes this database.
@@ -805,6 +822,7 @@ void init_sqlite3_database()
805822
/* public "define_aggregator" is now a shim around define_aggregator2
806823
* implemented in Ruby */
807824
rb_define_private_method(cSqlite3Database, "define_aggregator2", rb_sqlite3_define_aggregator2, 2);
825+
rb_define_private_method(cSqlite3Database, "disable_quirk_mode", rb_sqlite3_disable_quirk_mode, 0);
808826
rb_define_method(cSqlite3Database, "interrupt", interrupt, 0);
809827
rb_define_method(cSqlite3Database, "errmsg", errmsg, 0);
810828
rb_define_method(cSqlite3Database, "errcode", errcode_, 0);

lib/sqlite3/database.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ def initialize file, options = {}, zvfs = nil
8888
end
8989

9090
open_v2 file.encode("utf-8"), mode, zvfs
91+
92+
if options[:strict]
93+
disable_quirk_mode
94+
end
9195
end
9296

9397
@tracefunc = nil

test/test_database.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,5 +510,18 @@ def test_query_with_named_bind_params
510510
def test_execute_with_named_bind_params
511511
assert_equal [['foo']], @db.execute("select :n", {'n' => 'foo'})
512512
end
513+
514+
def test_strict_mode
515+
db = SQLite3::Database.new(':memory:')
516+
db.execute('create table numbers (val int);')
517+
db.execute('create index index_numbers_nope ON numbers ("nope");') # nothing raised
518+
519+
db = SQLite3::Database.new(':memory:', :strict => true)
520+
db.execute('create table numbers (val int);')
521+
error = assert_raises SQLite3::SQLException do
522+
db.execute('create index index_numbers_nope ON numbers ("nope");')
523+
end
524+
assert_includes error.message, "no such column: nope"
525+
end
513526
end
514527
end

0 commit comments

Comments
 (0)