Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unsafe mode #367

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/database.js
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ function Database(filenameGiven, options) {
const readonly = util.getBooleanOption(options, 'readonly');
const fileMustExist = util.getBooleanOption(options, 'fileMustExist');
const timeout = 'timeout' in options ? options.timeout : 5000;
const unsafe = util.getBooleanOption(options, 'unsafe');
const verbose = 'verbose' in options ? options.verbose : null;

if (readonly && (memory || anonymous)) throw new TypeError('In-memory databases cannot be readonly');
@@ -43,7 +44,8 @@ function Database(filenameGiven, options) {
.replace(/\/\/+/g, '/')
+ '?mode=memory&cache=shared';
}
return new CPPDatabase(filename, filenameGiven, memory || anonymous, readonly, fileMustExist, timeout, verbose || null);

return new CPPDatabase(filename, filenameGiven, memory || anonymous, readonly, fileMustExist, timeout, unsafe, verbose || null);
}

util.wrap(CPPDatabase, 'pragma', require('./pragma'));
169 changes: 87 additions & 82 deletions src/better_sqlite3.cpp

Large diffs are not rendered by default.

150 changes: 78 additions & 72 deletions src/better_sqlite3.hpp
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@
#endif
#line 153 "./src/util/macros.lzz"
template <class T> using CopyablePersistent = v8::Persistent<T, v8::CopyablePersistentTraits<T>>;
#line 158 "./src/util/constants.lzz"
#line 160 "./src/util/constants.lzz"
typedef v8::Persistent<v8::String> ConstantString;
#define LZZ_INLINE inline
#line 18 "./src/util/macros.lzz"
@@ -80,46 +80,48 @@ class CS
#line 17 "./src/util/constants.lzz"
static ConstantString name;
#line 18 "./src/util/constants.lzz"
static ConstantString next;
static ConstantString unsafe;
#line 19 "./src/util/constants.lzz"
static ConstantString length;
static ConstantString next;
#line 20 "./src/util/constants.lzz"
static ConstantString done;
static ConstantString length;
#line 21 "./src/util/constants.lzz"
static ConstantString value;
static ConstantString done;
#line 22 "./src/util/constants.lzz"
static ConstantString changes;
static ConstantString value;
#line 23 "./src/util/constants.lzz"
static ConstantString lastInsertRowid;
static ConstantString changes;
#line 24 "./src/util/constants.lzz"
static ConstantString code;
static ConstantString lastInsertRowid;
#line 25 "./src/util/constants.lzz"
static ConstantString statement;
static ConstantString code;
#line 26 "./src/util/constants.lzz"
static ConstantString column;
static ConstantString statement;
#line 27 "./src/util/constants.lzz"
static ConstantString table;
static ConstantString column;
#line 28 "./src/util/constants.lzz"
static ConstantString type;
static ConstantString table;
#line 29 "./src/util/constants.lzz"
static ConstantString totalPages;
static ConstantString type;
#line 30 "./src/util/constants.lzz"
static ConstantString totalPages;
#line 31 "./src/util/constants.lzz"
static ConstantString remainingPages;
#line 32 "./src/util/constants.lzz"
private:
#line 33 "./src/util/constants.lzz"
private:
#line 34 "./src/util/constants.lzz"
friend void RegisterModule (v8::Local <v8 :: Object> exports, v8::Local <v8 :: Object> module);
#line 33 "./src/util/constants.lzz"
#line 34 "./src/util/constants.lzz"
static void Init (v8::Isolate * isolate, v8::Local <v8 :: Object> exports, v8::Local <v8 :: Object> module);
#line 143 "./src/util/constants.lzz"
#line 145 "./src/util/constants.lzz"
static v8::Local <v8::String> InternalizedFromLatin1 (v8::Isolate * isolate, char const * str);
#line 146 "./src/util/constants.lzz"
#line 148 "./src/util/constants.lzz"
static void AddString (v8::Isolate * isolate, ConstantString & constant, char const * str);
#line 149 "./src/util/constants.lzz"
#line 151 "./src/util/constants.lzz"
static void AddCode (v8::Isolate * isolate, int code, char const * str);
#line 152 "./src/util/constants.lzz"
explicit CS (char _);
#line 154 "./src/util/constants.lzz"
explicit CS (char _);
#line 156 "./src/util/constants.lzz"
static std::unordered_map <int, ConstantString> codes;
};
#line 1 "./src/util/bind-map.lzz"
@@ -248,104 +250,108 @@ class Database : public node::ObjectWrap
bool was_js_error;
#line 57 "./src/objects/database.lzz"
unsigned short int iterators;
#line 58 "./src/objects/database.lzz"
bool const unsafe_mode;
};
#line 60 "./src/objects/database.lzz"
#line 61 "./src/objects/database.lzz"
State * GetState ();
#line 63 "./src/objects/database.lzz"
#line 64 "./src/objects/database.lzz"
sqlite3 * GetHandle ();
#line 67 "./src/objects/database.lzz"
#line 68 "./src/objects/database.lzz"
~ Database ();
#line 72 "./src/objects/database.lzz"
#line 73 "./src/objects/database.lzz"
private:
#line 74 "./src/objects/database.lzz"
#line 75 "./src/objects/database.lzz"
class CompareDatabase
{
#line 74 "./src/objects/database.lzz"
public:
#line 75 "./src/objects/database.lzz"
public:
#line 76 "./src/objects/database.lzz"
bool operator () (Database const * const a, Database const * const b) const;
};
#line 80 "./src/objects/database.lzz"
#line 81 "./src/objects/database.lzz"
class CompareStatement
{
#line 80 "./src/objects/database.lzz"
public:
#line 81 "./src/objects/database.lzz"
public:
#line 82 "./src/objects/database.lzz"
bool operator () (Statement const * const a, Statement const * const b) const;
};
#line 86 "./src/objects/database.lzz"
#line 87 "./src/objects/database.lzz"
class CompareBackup
{
#line 86 "./src/objects/database.lzz"
public:
#line 87 "./src/objects/database.lzz"
public:
#line 88 "./src/objects/database.lzz"
bool operator () (Backup const * const a, Backup const * const b) const;
};
#line 92 "./src/objects/database.lzz"
explicit Database (sqlite3 * _db_handle, v8::Isolate * isolate, v8::Local <v8::Value> _logger);
#line 108 "./src/objects/database.lzz"
#line 93 "./src/objects/database.lzz"
explicit Database (sqlite3 * _db_handle, v8::Isolate * isolate, bool _unsafe, v8::Local <v8::Value> _logger);
#line 110 "./src/objects/database.lzz"
friend void RegisterModule (v8::Local <v8 :: Object> exports, v8::Local <v8 :: Object> module);
#line 108 "./src/objects/database.lzz"
#line 110 "./src/objects/database.lzz"
static void Init (v8::Isolate * isolate, v8::Local <v8 :: Object> exports, v8::Local <v8 :: Object> module);
#line 132 "./src/objects/database.lzz"
#line 134 "./src/objects/database.lzz"
static void JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 176 "./src/objects/database.lzz"
#line 180 "./src/objects/database.lzz"
static void JS_prepare (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 182 "./src/objects/database.lzz"
#line 186 "./src/objects/database.lzz"
static void JS_exec (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 202 "./src/objects/database.lzz"
static void JS_pragma (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 206 "./src/objects/database.lzz"
static void JS_pragma (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 210 "./src/objects/database.lzz"
static void JS_checkpoint (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 249 "./src/objects/database.lzz"
#line 253 "./src/objects/database.lzz"
static void JS_backup (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 258 "./src/objects/database.lzz"
#line 262 "./src/objects/database.lzz"
static void JS_function (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 280 "./src/objects/database.lzz"
#line 284 "./src/objects/database.lzz"
static void JS_aggregate (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 307 "./src/objects/database.lzz"
#line 311 "./src/objects/database.lzz"
static void JS_loadExtension (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 321 "./src/objects/database.lzz"
#line 325 "./src/objects/database.lzz"
static void JS_close (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 332 "./src/objects/database.lzz"
#line 336 "./src/objects/database.lzz"
static void JS_defaultSafeIntegers (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 339 "./src/objects/database.lzz"
static void JS_open (v8::Local <v8 :: String> _, v8::PropertyCallbackInfo <v8 :: Value> const & info);
#line 343 "./src/objects/database.lzz"
static void JS_open (v8::Local <v8 :: String> _, v8::PropertyCallbackInfo <v8 :: Value> const & info);
#line 347 "./src/objects/database.lzz"
static void JS_inTransaction (v8::Local <v8 :: String> _, v8::PropertyCallbackInfo <v8 :: Value> const & info);
#line 348 "./src/objects/database.lzz"
#line 352 "./src/objects/database.lzz"
void CloseHandles ();
#line 360 "./src/objects/database.lzz"
#line 364 "./src/objects/database.lzz"
static void AtExit (void * _);
#line 365 "./src/objects/database.lzz"
#line 369 "./src/objects/database.lzz"
static std::set <Database*, Database::CompareDatabase> dbs;
#line 366 "./src/objects/database.lzz"
#line 370 "./src/objects/database.lzz"
static v8::Persistent <v8::Function> SqliteError;
#line 367 "./src/objects/database.lzz"
#line 371 "./src/objects/database.lzz"
static int const MAX_BUFFER_SIZE = node::Buffer::kMaxLength > INT_MAX ? INT_MAX : static_cast<int>(node::Buffer::kMaxLength);
#line 368 "./src/objects/database.lzz"
#line 372 "./src/objects/database.lzz"
static int const MAX_STRING_SIZE = v8::String::kMaxLength > INT_MAX ? INT_MAX : static_cast<int>(v8::String::kMaxLength);
#line 370 "./src/objects/database.lzz"
#line 374 "./src/objects/database.lzz"
sqlite3 * const db_handle;
#line 371 "./src/objects/database.lzz"
#line 375 "./src/objects/database.lzz"
bool open;
#line 372 "./src/objects/database.lzz"
#line 376 "./src/objects/database.lzz"
bool busy;
#line 373 "./src/objects/database.lzz"
#line 377 "./src/objects/database.lzz"
bool pragma_mode;
#line 374 "./src/objects/database.lzz"
#line 378 "./src/objects/database.lzz"
bool safe_ints;
#line 375 "./src/objects/database.lzz"
#line 379 "./src/objects/database.lzz"
bool was_js_error;
#line 376 "./src/objects/database.lzz"
#line 380 "./src/objects/database.lzz"
bool const has_logger;
#line 377 "./src/objects/database.lzz"
#line 381 "./src/objects/database.lzz"
unsigned short int iterators;
#line 378 "./src/objects/database.lzz"
#line 382 "./src/objects/database.lzz"
bool const unsafe_mode;
#line 383 "./src/objects/database.lzz"
CopyablePersistent <v8::Value> const logger;
#line 379 "./src/objects/database.lzz"
#line 384 "./src/objects/database.lzz"
std::set <Statement*, Database::CompareStatement> stmts;
#line 380 "./src/objects/database.lzz"
#line 385 "./src/objects/database.lzz"
std::set <Backup*, Database::CompareBackup> backups;
};
#line 1 "./src/objects/statement.lzz"
@@ -839,15 +845,15 @@ LZZ_INLINE void Database::RemoveBackup (Backup * backup)
#line 47 "./src/objects/database.lzz"
{ backups.erase(backup);
}
#line 60 "./src/objects/database.lzz"
#line 61 "./src/objects/database.lzz"
LZZ_INLINE Database::State * Database::GetState ()
#line 60 "./src/objects/database.lzz"
#line 61 "./src/objects/database.lzz"
{
return reinterpret_cast<State*>(&open);
}
#line 63 "./src/objects/database.lzz"
#line 64 "./src/objects/database.lzz"
LZZ_INLINE sqlite3 * Database::GetHandle ()
#line 63 "./src/objects/database.lzz"
#line 64 "./src/objects/database.lzz"
{
return db_handle;
}
11 changes: 8 additions & 3 deletions src/objects/database.lzz
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@ public:
const bool safe_ints;
bool was_js_error;
unsigned short iterators;
const bool unsafe_mode;
};

inline State* GetState() {
@@ -89,7 +90,7 @@ private:
}
};

explicit Database(sqlite3* _db_handle, v8::Isolate* isolate, v8::Local<v8::Value> _logger) : node::ObjectWrap(),
explicit Database(sqlite3* _db_handle, v8::Isolate* isolate, bool _unsafe, v8::Local<v8::Value> _logger) : node::ObjectWrap(),
db_handle(_db_handle),
open(true),
busy(false),
@@ -98,6 +99,7 @@ private:
was_js_error(false),
has_logger(_logger->IsFunction()),
iterators(0),
unsafe_mode(_unsafe),
logger(isolate, _logger),
stmts(),
backups() {
@@ -137,7 +139,8 @@ private:
REQUIRE_ARGUMENT_BOOLEAN(fourth, bool readonly);
REQUIRE_ARGUMENT_BOOLEAN(fifth, bool must_exist);
REQUIRE_ARGUMENT_INT32(sixth, int timeout);
REQUIRE_ARGUMENT_ANY(seventh, v8::Local<v8::Value> logger);
REQUIRE_ARGUMENT_BOOLEAN(seventh, bool unsafe);
REQUIRE_ARGUMENT_ANY(eighth, v8::Local<v8::Value> logger);

UseIsolate;
sqlite3* db_handle;
@@ -164,11 +167,12 @@ private:
assert(status == SQLITE_OK);

UseContext;
Database* db = new Database(db_handle, isolate, logger);
Database* db = new Database(db_handle, isolate, unsafe, logger);
db->Wrap(info.This());
SetFrozen(isolate, ctx, info.This(), CS::memory, in_memory ? v8::True(isolate) : v8::False(isolate));
SetFrozen(isolate, ctx, info.This(), CS::readonly, readonly ? v8::True(isolate) : v8::False(isolate));
SetFrozen(isolate, ctx, info.This(), CS::name, filenameGiven);
SetFrozen(isolate, ctx, info.This(), CS::unsafe, unsafe ? v8::True(isolate) : v8::False(isolate));

info.GetReturnValue().Set(info.This());
}
@@ -375,6 +379,7 @@ private:
bool was_js_error;
const bool has_logger;
unsigned short iterators;
const bool unsafe_mode;
const CopyablePersistent<v8::Value> logger;
std::set<Statement*, Database::CompareStatement> stmts;
std::set<Backup*, Database::CompareBackup> backups;
2 changes: 2 additions & 0 deletions src/util/constants.lzz
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ public:
static ConstantString memory;
static ConstantString readonly;
static ConstantString name;
static ConstantString unsafe;
static ConstantString next;
static ConstantString length;
static ConstantString done;
@@ -37,6 +38,7 @@ private:
AddString(isolate, CS::memory, "memory");
AddString(isolate, CS::readonly, "readonly");
AddString(isolate, CS::name, "name");
AddString(isolate, CS::unsafe, "unsafe");
AddString(isolate, CS::next, "next");
AddString(isolate, CS::length, "length");
AddString(isolate, CS::done, "done");
2 changes: 1 addition & 1 deletion src/util/macros.lzz
Original file line number Diff line number Diff line change
@@ -64,7 +64,7 @@ void ThrowRangeError(const char* message) { EasyIsolate; isolate->ThrowException
if (db->busy) \
return ThrowTypeError("This database connection is busy executing a query")
#define REQUIRE_DATABASE_NO_ITERATORS(db) \
if (db->iterators) \
if (db->iterators && !db->unsafe_mode) \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense that unsafe also affects the case above, not just the iterators case. E.g. to allow things such as #338

And what about locked? Which use-case does that prevent and could this be disabled in unsafe mode as well?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide a test case which demonstrates the functionality and I'll include it.

return ThrowTypeError("This database connection is busy executing a query")
#define REQUIRE_STATEMENT_NOT_LOCKED(stmt) \
if (stmt->locked) \
Loading