made Database class extendable, and fixed importing into jest environments

This commit is contained in:
Joshua Wise
2021-03-30 12:31:07 -05:00
parent 00a6f85dc1
commit bb8f2d0dbc
19 changed files with 493 additions and 440 deletions
-40
View File
@@ -1,40 +0,0 @@
'use strict';
const { getBooleanOption } = require('./util');
module.exports = (createAggregate) => {
return function defineAggregate(name, options) {
if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof options !== 'object' || options === null) throw new TypeError('Expected second argument to be an options object');
if (!name) throw new TypeError('User-defined function name cannot be an empty string');
const start = 'start' in options ? options.start : null;
const step = getFunctionOption(options, 'step', true);
const inverse = getFunctionOption(options, 'inverse', false);
const result = getFunctionOption(options, 'result', false);
const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;
const deterministic = getBooleanOption(options, 'deterministic');
const varargs = getBooleanOption(options, 'varargs');
let argCount = -1;
if (!varargs) {
argCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);
if (argCount > 0) argCount -= 1;
if (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');
}
return createAggregate.call(this, start, step, inverse, result, name, argCount, safeIntegers, deterministic);
};
};
const getFunctionOption = (options, key, required) => {
const value = key in options ? options[key] : null;
if (typeof value === 'function') return value;
if (value != null) throw new TypeError(`Expected the "${key}" option to be a function`);
if (required) throw new TypeError(`Missing required option "${key}"`);
return null;
};
const getLength = ({ length }) => {
if (Number.isInteger(length) && length >= 0) return length;
throw new TypeError('Expected function.length to be a positive integer');
};
-65
View File
@@ -1,65 +0,0 @@
'use strict';
const fs = require('fs');
const path = require('path');
const { promisify } = require('util');
const fsAccess = promisify(fs.access);
module.exports = (createBackup) => {
return async function backup(filename, options) {
if (options == null) options = {};
if (typeof filename !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
filename = filename.trim();
if (!filename) throw new TypeError('Backup filename cannot be an empty string');
if (filename === ':memory:') throw new TypeError('Invalid backup filename ":memory:"');
const attachedName = 'attached' in options ? options.attached : 'main';
const handler = 'progress' in options ? options.progress : null;
if (typeof attachedName !== 'string') throw new TypeError('Expected the "attached" option to be a string');
if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
if (handler != null && typeof handler !== 'function') throw new TypeError('Expected the "progress" option to be a function');
await fsAccess(path.dirname(filename)).catch(() => {
throw new TypeError('Cannot save backup because the directory does not exist');
});
const newFile = await fsAccess(filename).then(() => false, () => true);
return runBackup(createBackup.call(this, attachedName, filename, newFile), handler || null);
};
};
const runBackup = (backup, handler) => {
let rate = 0;
let useDefault = true;
return new Promise((resolve, reject) => {
setImmediate(function step() {
try {
const progress = backup.transfer(rate);
if (!progress.remainingPages) {
backup.close();
resolve(progress);
return;
}
if (useDefault) {
useDefault = false;
rate = 100;
}
if (handler) {
const ret = handler(progress);
if (ret !== undefined) {
if (typeof ret === 'number' && ret === ret) rate = Math.max(0, Math.min(0x7fffffff, Math.round(ret)));
else throw new TypeError('Expected progress callback to return a number or undefined');
}
}
setImmediate(step);
} catch (err) {
backup.close();
reject(err);
}
});
});
}
+30 -9
View File
@@ -9,13 +9,21 @@ const {
} = require('bindings')('better_sqlite3.node');
function Database(filenameGiven, options) {
if (new.target !== Database) {
return new Database(filenameGiven, options);
}
// Apply defaults
if (filenameGiven == null) filenameGiven = '';
if (options == null) options = {};
// Validate arguments
if (typeof filenameGiven !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
if ('readOnly' in options) throw new TypeError('Misspelled option "readOnly" should be "readonly"');
if ('memory' in options) throw new TypeError('Option "memory" was removed in v7.0.0 (use ":memory:" filename instead)');
// Interpret options
const filename = filenameGiven.trim();
const anonymous = filename === '' || filename === ':memory:';
const readonly = util.getBooleanOption(options, 'readonly');
@@ -23,23 +31,36 @@ function Database(filenameGiven, options) {
const timeout = 'timeout' in options ? options.timeout : 5000;
const verbose = 'verbose' in options ? options.verbose : null;
// Validate interpreted options
if (readonly && anonymous) throw new TypeError('In-memory/temporary databases cannot be readonly');
if (!Number.isInteger(timeout) || timeout < 0) throw new TypeError('Expected the "timeout" option to be a positive integer');
if (timeout > 0x7fffffff) throw new RangeError('Option "timeout" cannot be greater than 2147483647');
if (verbose != null && typeof verbose !== 'function') throw new TypeError('Expected the "verbose" option to be a function');
// Make sure the specified directory exists
if (!anonymous && !fs.existsSync(path.dirname(filename))) {
throw new TypeError('Cannot open database because the directory does not exist');
}
return new CPPDatabase(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null);
Object.defineProperties(this, {
[util.cppdb]: { value: new CPPDatabase(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null) },
...wrappers.getters,
});
}
setErrorConstructor(require('./sqlite-error'));
util.wrap(CPPDatabase, 'pragma', require('./pragma'));
util.wrap(CPPDatabase, 'function', require('./function'));
util.wrap(CPPDatabase, 'aggregate', require('./aggregate'));
util.wrap(CPPDatabase, 'backup', require('./backup'));
CPPDatabase.prototype.transaction = require('./transaction');
CPPDatabase.prototype.constructor = Database;
Database.prototype = CPPDatabase.prototype;
const wrappers = require('./methods/wrappers');
Database.prototype.prepare = wrappers.prepare;
Database.prototype.transaction = require('./methods/transaction');
Database.prototype.pragma = require('./methods/pragma');
Database.prototype.backup = require('./methods/backup');
Database.prototype.function = require('./methods/function');
Database.prototype.aggregate = require('./methods/aggregate');
Database.prototype.loadExtension = wrappers.loadExtension;
Database.prototype.exec = wrappers.exec;
Database.prototype.close = wrappers.close;
Database.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers;
Database.prototype.unsafeMode = wrappers.unsafeMode;
Database.prototype[util.inspect] = require('./methods/inspect');
module.exports = Database;
setErrorConstructor(require('./sqlite-error'));
-26
View File
@@ -1,26 +0,0 @@
'use strict';
const { getBooleanOption } = require('./util');
module.exports = (createFunction) => {
return function defineFunction(name, options, fn) {
if (options == null) options = {};
if (typeof options === 'function') { fn = options; options = {}; }
if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof fn !== 'function') throw new TypeError('Expected last argument to be a function');
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
if (!name) throw new TypeError('User-defined function name cannot be an empty string');
const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;
const deterministic = getBooleanOption(options, 'deterministic');
const varargs = getBooleanOption(options, 'varargs');
let argCount = -1;
if (!varargs) {
argCount = fn.length;
if (!Number.isInteger(argCount) || argCount < 0) throw new TypeError('Expected function.length to be a positive integer');
if (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');
}
return createFunction.call(this, fn, name, argCount, safeIntegers, deterministic);
};
};
+42
View File
@@ -0,0 +1,42 @@
'use strict';
const { getBooleanOption, cppdb } = require('../util');
module.exports = function defineAggregate(name, options) {
// Validate arguments
if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof options !== 'object' || options === null) throw new TypeError('Expected second argument to be an options object');
if (!name) throw new TypeError('User-defined function name cannot be an empty string');
// Interpret options
const start = 'start' in options ? options.start : null;
const step = getFunctionOption(options, 'step', true);
const inverse = getFunctionOption(options, 'inverse', false);
const result = getFunctionOption(options, 'result', false);
const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;
const deterministic = getBooleanOption(options, 'deterministic');
const varargs = getBooleanOption(options, 'varargs');
let argCount = -1;
// Determine argument count
if (!varargs) {
argCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);
if (argCount > 0) argCount -= 1;
if (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');
}
this[cppdb].aggregate(start, step, inverse, result, name, argCount, safeIntegers, deterministic);
return this;
};
const getFunctionOption = (options, key, required) => {
const value = key in options ? options[key] : null;
if (typeof value === 'function') return value;
if (value != null) throw new TypeError(`Expected the "${key}" option to be a function`);
if (required) throw new TypeError(`Missing required option "${key}"`);
return null;
};
const getLength = ({ length }) => {
if (Number.isInteger(length) && length >= 0) return length;
throw new TypeError('Expected function.length to be a positive integer');
};
+67
View File
@@ -0,0 +1,67 @@
'use strict';
const fs = require('fs');
const path = require('path');
const { promisify } = require('util');
const { cppdb } = require('../util');
const fsAccess = promisify(fs.access);
module.exports = async function backup(filename, options) {
if (options == null) options = {};
// Validate arguments
if (typeof filename !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
// Interpret options
filename = filename.trim();
const attachedName = 'attached' in options ? options.attached : 'main';
const handler = 'progress' in options ? options.progress : null;
// Validate interpreted options
if (!filename) throw new TypeError('Backup filename cannot be an empty string');
if (filename === ':memory:') throw new TypeError('Invalid backup filename ":memory:"');
if (typeof attachedName !== 'string') throw new TypeError('Expected the "attached" option to be a string');
if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
if (handler != null && typeof handler !== 'function') throw new TypeError('Expected the "progress" option to be a function');
// Make sure the specified directory exists
await fsAccess(path.dirname(filename)).catch(() => {
throw new TypeError('Cannot save backup because the directory does not exist');
});
const isNewFile = await fsAccess(filename).then(() => false, () => true);
return runBackup(this[cppdb].backup(this, attachedName, filename, isNewFile), handler || null);
};
const runBackup = (backup, handler) => {
let rate = 0;
let useDefault = true;
return new Promise((resolve, reject) => {
setImmediate(function step() {
try {
const progress = backup.transfer(rate);
if (!progress.remainingPages) {
backup.close();
resolve(progress);
return;
}
if (useDefault) {
useDefault = false;
rate = 100;
}
if (handler) {
const ret = handler(progress);
if (ret !== undefined) {
if (typeof ret === 'number' && ret === ret) rate = Math.max(0, Math.min(0x7fffffff, Math.round(ret)));
else throw new TypeError('Expected progress callback to return a number or undefined');
}
}
setImmediate(step);
} catch (err) {
backup.close();
reject(err);
}
});
});
};
+30
View File
@@ -0,0 +1,30 @@
'use strict';
const { getBooleanOption, cppdb } = require('../util');
module.exports = function defineFunction(name, options, fn) {
// Apply defaults
if (options == null) options = {};
if (typeof options === 'function') { fn = options; options = {}; }
// Validate arguments
if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof fn !== 'function') throw new TypeError('Expected last argument to be a function');
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
if (!name) throw new TypeError('User-defined function name cannot be an empty string');
// Interpret options
const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;
const deterministic = getBooleanOption(options, 'deterministic');
const varargs = getBooleanOption(options, 'varargs');
let argCount = -1;
// Determine argument count
if (!varargs) {
argCount = fn.length;
if (!Number.isInteger(argCount) || argCount < 0) throw new TypeError('Expected function.length to be a positive integer');
if (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');
}
this[cppdb].function(fn, name, argCount, safeIntegers, deterministic);
return this;
};
+7
View File
@@ -0,0 +1,7 @@
'use strict';
const DatabaseInspection = function Database() {};
module.exports = function inspect(depth, opts) {
return Object.assign(new DatabaseInspection(), this);
};
+12
View File
@@ -0,0 +1,12 @@
'use strict';
const { getBooleanOption, cppdb } = require('../util');
module.exports = function pragma(source, options) {
if (options == null) options = {};
if (typeof source !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
const simple = getBooleanOption(options, 'simple');
const stmt = this[cppdb].prepare(`PRAGMA ${source}`, this, true);
return simple ? stmt.pluck().get() : stmt.all();
};
@@ -1,16 +1,20 @@
'use strict';
const controllers = new WeakMap;
const { cppdb } = require('../util');
const controllers = new WeakMap();
module.exports = function transaction(fn) {
if (typeof fn !== 'function') throw new TypeError('Expected first argument to be a function');
const controller = getController(this);
const db = this[cppdb];
const controller = getController(db, this);
const { apply } = Function.prototype;
// Each version of the transaction function has these same properties
const properties = {
default: { value: wrapTransaction(apply, fn, this, controller.default) },
deferred: { value: wrapTransaction(apply, fn, this, controller.deferred) },
immediate: { value: wrapTransaction(apply, fn, this, controller.immediate) },
exclusive: { value: wrapTransaction(apply, fn, this, controller.exclusive) },
default: { value: wrapTransaction(apply, fn, db, controller.default) },
deferred: { value: wrapTransaction(apply, fn, db, controller.deferred) },
immediate: { value: wrapTransaction(apply, fn, db, controller.immediate) },
exclusive: { value: wrapTransaction(apply, fn, db, controller.exclusive) },
database: { value: this, enumerable: true },
};
@@ -19,29 +23,32 @@ module.exports = function transaction(fn) {
Object.defineProperties(properties.immediate.value, properties);
Object.defineProperties(properties.exclusive.value, properties);
// Return the default version of the transaction function
return properties.default.value;
};
const getController = (db) => {
// Return the database's cached transaction controller, or create a new one
const getController = (db, self) => {
let controller = controllers.get(db);
if (!controller) {
const shared = {
commit: db.prepare('COMMIT'),
rollback: db.prepare('ROLLBACK'),
savepoint: db.prepare('SAVEPOINT `\t_bs3.\t`'),
release: db.prepare('RELEASE `\t_bs3.\t`'),
rollbackTo: db.prepare('ROLLBACK TO `\t_bs3.\t`'),
commit: db.prepare('COMMIT', self, false),
rollback: db.prepare('ROLLBACK', self, false),
savepoint: db.prepare('SAVEPOINT `\t_bs3.\t`', self, false),
release: db.prepare('RELEASE `\t_bs3.\t`', self, false),
rollbackTo: db.prepare('ROLLBACK TO `\t_bs3.\t`', self, false),
};
controllers.set(db, controller = {
default: Object.assign({ begin: db.prepare('BEGIN') }, shared),
deferred: Object.assign({ begin: db.prepare('BEGIN DEFERRED') }, shared),
immediate: Object.assign({ begin: db.prepare('BEGIN IMMEDIATE') }, shared),
exclusive: Object.assign({ begin: db.prepare('BEGIN EXCLUSIVE') }, shared),
default: Object.assign({ begin: db.prepare('BEGIN', self, false) }, shared),
deferred: Object.assign({ begin: db.prepare('BEGIN DEFERRED', self, false) }, shared),
immediate: Object.assign({ begin: db.prepare('BEGIN IMMEDIATE', self, false) }, shared),
exclusive: Object.assign({ begin: db.prepare('BEGIN EXCLUSIVE', self, false) }, shared),
});
}
return controller;
};
// Return a new transaction function by wrapping the given function
const wrapTransaction = (apply, fn, db, { begin, commit, rollback, savepoint, release, rollbackTo }) => function sqliteTransaction() {
let before, after, undo;
if (db.inTransaction) {
+54
View File
@@ -0,0 +1,54 @@
'use strict';
const { cppdb } = require('../util');
exports.prepare = function prepare(sql) {
return this[cppdb].prepare(sql, this, false);
};
exports.exec = function exec(sql) {
this[cppdb].exec(sql);
return this;
};
exports.close = function close() {
this[cppdb].close();
return this;
};
exports.loadExtension = function loadExtension(...args) {
this[cppdb].loadExtension(...args);
return this;
};
exports.defaultSafeIntegers = function defaultSafeIntegers(...args) {
this[cppdb].defaultSafeIntegers(...args);
return this;
};
exports.unsafeMode = function unsafeMode(...args) {
this[cppdb].unsafeMode(...args);
return this;
};
exports.getters = {
name: {
get: function name() { return this[cppdb].name; },
enumerable: true,
},
open: {
get: function open() { return this[cppdb].open; },
enumerable: true,
},
inTransaction: {
get: function inTransaction() { return this[cppdb].inTransaction; },
enumerable: true,
},
readonly: {
get: function readonly() { return this[cppdb].readonly; },
enumerable: true,
},
memory: {
get: function memory() { return this[cppdb].memory; },
enumerable: true,
},
};
-20
View File
@@ -1,20 +0,0 @@
'use strict';
const { getBooleanOption } = require('./util');
module.exports = (setPragmaMode) => {
return function pragma(source, options) {
if (options == null) options = {};
if (typeof source !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
const simple = getBooleanOption(options, 'simple');
let stmt;
setPragmaMode.call(this, true);
try {
stmt = this.prepare(`PRAGMA ${source}`);
} finally {
setPragmaMode.call(this, false);
}
return simple ? stmt.pluck().get() : stmt.all();
};
};
+2 -12
View File
@@ -1,5 +1,4 @@
'use strict';
const wrappedMethods = new WeakSet();
exports.getBooleanOption = (options, key) => {
let value = false;
@@ -9,14 +8,5 @@ exports.getBooleanOption = (options, key) => {
return value;
};
exports.wrap = (Class, methodName, wrapper) => {
const originalMethod = Class.prototype[methodName];
if (typeof originalMethod !== 'function') {
throw new TypeError(`Missing method ${methodName}`);
}
if (!wrappedMethods.has(originalMethod)) {
const wrapped = wrapper(originalMethod);
wrappedMethods.add(wrapped);
Class.prototype[methodName] = wrapped;
}
};
exports.cppdb = Symbol();
exports.inspect = Symbol.for('nodejs.util.inspect.custom');
+97 -99
View File
@@ -2,7 +2,7 @@
//
#include "better_sqlite3.hpp"
#line 67 "./src/better_sqlite3.lzz"
#line 61 "./src/better_sqlite3.lzz"
NODE_MODULE_INIT(/* exports, context */) {
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope scope(isolate);
@@ -314,7 +314,6 @@ v8::Local <v8 :: Function> Database::Init (v8::Isolate * isolate, v8::Local <v8
v8::Local<v8::FunctionTemplate> t = NewConstructorTemplate(isolate, data, JS_new, "Database");
SetPrototypeMethod(isolate, data, t, "prepare", JS_prepare);
SetPrototypeMethod(isolate, data, t, "exec", JS_exec);
SetPrototypeMethod(isolate, data, t, "pragma", JS_pragma);
SetPrototypeMethod(isolate, data, t, "backup", JS_backup);
SetPrototypeMethod(isolate, data, t, "function", JS_function);
SetPrototypeMethod(isolate, data, t, "aggregate", JS_aggregate);
@@ -326,41 +325,41 @@ v8::Local <v8 :: Function> Database::Init (v8::Isolate * isolate, v8::Local <v8
SetPrototypeGetter(isolate, data, t, "inTransaction", JS_inTransaction);
return t->GetFunction( isolate -> GetCurrentContext ( ) ).ToLocalChecked();
}
#line 23 "./src/objects/database.lzz"
#line 22 "./src/objects/database.lzz"
bool Database::CompareDatabase::operator () (Database const * const a, Database const * const b) const
#line 23 "./src/objects/database.lzz"
#line 22 "./src/objects/database.lzz"
{
return a < b;
}
#line 28 "./src/objects/database.lzz"
#line 27 "./src/objects/database.lzz"
bool Database::CompareStatement::operator () (Statement const * const a, Statement const * const b) const
#line 28 "./src/objects/database.lzz"
#line 27 "./src/objects/database.lzz"
{
return Statement::Compare(a, b);
}
#line 33 "./src/objects/database.lzz"
#line 32 "./src/objects/database.lzz"
bool Database::CompareBackup::operator () (Backup const * const a, Backup const * const b) const
#line 33 "./src/objects/database.lzz"
#line 32 "./src/objects/database.lzz"
{
return Backup::Compare(a, b);
}
#line 39 "./src/objects/database.lzz"
#line 38 "./src/objects/database.lzz"
void Database::ThrowDatabaseError ()
#line 39 "./src/objects/database.lzz"
#line 38 "./src/objects/database.lzz"
{
if (was_js_error) was_js_error = false;
else ThrowSqliteError(addon, db_handle);
}
#line 43 "./src/objects/database.lzz"
#line 42 "./src/objects/database.lzz"
void Database::ThrowSqliteError (Addon * addon, sqlite3 * db_handle)
#line 43 "./src/objects/database.lzz"
#line 42 "./src/objects/database.lzz"
{
assert(db_handle != NULL);
ThrowSqliteError(addon, sqlite3_errmsg(db_handle), sqlite3_extended_errcode(db_handle));
}
#line 47 "./src/objects/database.lzz"
#line 46 "./src/objects/database.lzz"
void Database::ThrowSqliteError (Addon * addon, char const * message, int code)
#line 47 "./src/objects/database.lzz"
#line 46 "./src/objects/database.lzz"
{
assert(message != NULL);
assert((code & 0xff) != SQLITE_OK);
@@ -375,9 +374,9 @@ void Database::ThrowSqliteError (Addon * addon, char const * message, int code)
->NewInstance( isolate -> GetCurrentContext ( ) , 2, args)
.ToLocalChecked());
}
#line 63 "./src/objects/database.lzz"
#line 62 "./src/objects/database.lzz"
bool Database::Log (v8::Isolate * isolate, sqlite3_stmt * handle)
#line 63 "./src/objects/database.lzz"
#line 62 "./src/objects/database.lzz"
{
assert(was_js_error == false);
if (!has_logger) return false;
@@ -389,9 +388,9 @@ bool Database::Log (v8::Isolate * isolate, sqlite3_stmt * handle)
if (expanded) sqlite3_free(expanded);
return was_js_error;
}
#line 106 "./src/objects/database.lzz"
#line 105 "./src/objects/database.lzz"
void Database::CloseHandles ()
#line 106 "./src/objects/database.lzz"
#line 105 "./src/objects/database.lzz"
{
if (open) {
open = false;
@@ -403,25 +402,25 @@ void Database::CloseHandles ()
assert(status == SQLITE_OK); ((void)status);
}
}
#line 118 "./src/objects/database.lzz"
#line 117 "./src/objects/database.lzz"
Database::~ Database ()
#line 118 "./src/objects/database.lzz"
#line 117 "./src/objects/database.lzz"
{
if (open) addon->dbs.erase(this);
CloseHandles();
}
#line 125 "./src/objects/database.lzz"
#line 124 "./src/objects/database.lzz"
Database::Database (sqlite3 * _db_handle, v8::Isolate * isolate, Addon * _addon, v8::Local <v8::Value> _logger)
#line 125 "./src/objects/database.lzz"
#line 124 "./src/objects/database.lzz"
: node::ObjectWrap (), db_handle (_db_handle), open (true), busy (false), safe_ints (false), unsafe_mode (false), was_js_error (false), has_logger (_logger->IsFunction()), iterators (0), addon (_addon), logger (isolate, _logger), stmts (), backups ()
#line 137 "./src/objects/database.lzz"
#line 136 "./src/objects/database.lzz"
{
assert(_db_handle != NULL);
addon->dbs.insert(this);
}
#line 142 "./src/objects/database.lzz"
#line 141 "./src/objects/database.lzz"
void Database::JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 142 "./src/objects/database.lzz"
#line 141 "./src/objects/database.lzz"
{
assert(info.IsConstructCall());
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > filename = v8 :: Local < v8 :: String > :: Cast ( info [ 0 ] ) ;
@@ -466,12 +465,16 @@ void Database::JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info)
info.GetReturnValue().Set(info.This());
}
#line 187 "./src/objects/database.lzz"
#line 186 "./src/objects/database.lzz"
void Database::JS_prepare (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 187 "./src/objects/database.lzz"
#line 186 "./src/objects/database.lzz"
{
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > source = v8 :: Local < v8 :: String > :: Cast ( info [ 0 ] ) ;
if ( info . Length ( ) <= ( 1 ) || ! info [ 1 ] -> IsObject ( ) ) return ThrowTypeError ( "Expected " "second" " argument to be " "an object" ) ; v8 :: Local < v8 :: Object > database = v8 :: Local < v8 :: Object > :: Cast ( info [ 1 ] ) ;
if ( info . Length ( ) <= ( 2 ) || ! info [ 2 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "third" " argument to be " "a boolean" ) ; bool pragmaMode = v8 :: Local < v8 :: Boolean > :: Cast ( info [ 2 ] ) -> Value ( ) ;
(void)source;
(void)database;
(void)pragmaMode;
Addon * addon = static_cast < Addon * > ( v8 :: Local < v8 :: External > :: Cast ( info . Data ( ) ) -> Value ( ) ) ;
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
v8::Local<v8::Function> c = v8::Local<v8::Function>::New(isolate, addon->Statement);
@@ -480,9 +483,9 @@ void Database::JS_prepare (v8::FunctionCallbackInfo <v8 :: Value> const & info)
addon->privileged_info = NULL;
if (!maybe_statement.IsEmpty()) info.GetReturnValue().Set(maybe_statement.ToLocalChecked());
}
#line 199 "./src/objects/database.lzz"
#line 202 "./src/objects/database.lzz"
void Database::JS_exec (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 199 "./src/objects/database.lzz"
#line 202 "./src/objects/database.lzz"
{
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > source = v8 :: Local < v8 :: String > :: Cast ( info [ 0 ] ) ;
@@ -518,23 +521,19 @@ void Database::JS_exec (v8::FunctionCallbackInfo <v8 :: Value> const & info)
}
db->busy = false;
if (status == SQLITE_OK) info.GetReturnValue().Set(info.This());
else db->ThrowDatabaseError();
if (status != SQLITE_OK) {
db->ThrowDatabaseError();
}
}
#line 238 "./src/objects/database.lzz"
void Database::JS_pragma (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 238 "./src/objects/database.lzz"
{
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a boolean" ) ; bool active = v8 :: Local < v8 :: Boolean > :: Cast ( info [ 0 ] ) -> Value ( ) ;
static_cast < Addon * > ( v8 :: Local < v8 :: External > :: Cast ( info . Data ( ) ) -> Value ( ) ) ->SetPragmaMode(active);
}
#line 243 "./src/objects/database.lzz"
#line 242 "./src/objects/database.lzz"
void Database::JS_backup (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 243 "./src/objects/database.lzz"
#line 242 "./src/objects/database.lzz"
{
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > attachedName = v8 :: Local < v8 :: String > :: Cast ( info [ 0 ] ) ;
if ( info . Length ( ) <= ( 1 ) || ! info [ 1 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "second" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > destFile = v8 :: Local < v8 :: String > :: Cast ( info [ 1 ] ) ;
if ( info . Length ( ) <= ( 2 ) || ! info [ 2 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "third" " argument to be " "a boolean" ) ; bool unlink = v8 :: Local < v8 :: Boolean > :: Cast ( info [ 2 ] ) -> Value ( ) ;
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsObject ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "an object" ) ; v8 :: Local < v8 :: Object > database = v8 :: Local < v8 :: Object > :: Cast ( info [ 0 ] ) ;
if ( info . Length ( ) <= ( 1 ) || ! info [ 1 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "second" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > attachedName = v8 :: Local < v8 :: String > :: Cast ( info [ 1 ] ) ;
if ( info . Length ( ) <= ( 2 ) || ! info [ 2 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "third" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > destFile = v8 :: Local < v8 :: String > :: Cast ( info [ 2 ] ) ;
if ( info . Length ( ) <= ( 3 ) || ! info [ 3 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "fourth" " argument to be " "a boolean" ) ; bool unlink = v8 :: Local < v8 :: Boolean > :: Cast ( info [ 3 ] ) -> Value ( ) ;
(void)database;
(void)attachedName;
(void)destFile;
(void)unlink;
@@ -546,9 +545,9 @@ void Database::JS_backup (v8::FunctionCallbackInfo <v8 :: Value> const & info)
addon->privileged_info = NULL;
if (!maybe_backup.IsEmpty()) info.GetReturnValue().Set(maybe_backup.ToLocalChecked());
}
#line 259 "./src/objects/database.lzz"
#line 260 "./src/objects/database.lzz"
void Database::JS_function (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 259 "./src/objects/database.lzz"
#line 260 "./src/objects/database.lzz"
{
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsFunction ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a function" ) ; v8 :: Local < v8 :: Function > fn = v8 :: Local < v8 :: Function > :: Cast ( info [ 0 ] ) ;
@@ -566,9 +565,8 @@ void Database::JS_function (v8::FunctionCallbackInfo <v8 :: Value> const & info)
safe_ints = safe_ints < 2 ? safe_ints : static_cast<int>(db->safe_ints);
if (sqlite3_create_function_v2(db->db_handle, *name, argc, mask, new CustomFunction(isolate, db, fn, *name, safe_ints), CustomFunction::xFunc, NULL, NULL, CustomFunction::xDestroy) != SQLITE_OK) {
return db->ThrowDatabaseError();
db->ThrowDatabaseError();
}
info.GetReturnValue().Set(info.This());
}
#line 281 "./src/objects/database.lzz"
void Database::JS_aggregate (v8::FunctionCallbackInfo <v8 :: Value> const & info)
@@ -595,13 +593,12 @@ void Database::JS_aggregate (v8::FunctionCallbackInfo <v8 :: Value> const & info
safe_ints = safe_ints < 2 ? safe_ints : static_cast<int>(db->safe_ints);
if (sqlite3_create_window_function(db->db_handle, *name, argc, mask, new CustomAggregate(isolate, db, start, step, inverse, result, *name, safe_ints), CustomAggregate::xStep, CustomAggregate::xFinal, xValue, xInverse, CustomAggregate::xDestroy) != SQLITE_OK) {
return db->ThrowDatabaseError();
db->ThrowDatabaseError();
}
info.GetReturnValue().Set(info.This());
}
#line 308 "./src/objects/database.lzz"
#line 307 "./src/objects/database.lzz"
void Database::JS_loadExtension (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 308 "./src/objects/database.lzz"
#line 307 "./src/objects/database.lzz"
{
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
v8::Local<v8::String> entryPoint;
@@ -618,8 +615,9 @@ void Database::JS_loadExtension (v8::FunctionCallbackInfo <v8 :: Value> const &
entryPoint.IsEmpty() ? NULL : *v8::String::Utf8Value(isolate, entryPoint),
&error
);
if (status == SQLITE_OK) info.GetReturnValue().Set(info.This());
else ThrowSqliteError(db->addon, error, status);
if (status != SQLITE_OK) {
ThrowSqliteError(db->addon, error, status);
}
sqlite3_free(error);
}
#line 329 "./src/objects/database.lzz"
@@ -633,43 +631,40 @@ void Database::JS_close (v8::FunctionCallbackInfo <v8 :: Value> const & info)
db->addon->dbs.erase(db);
db->CloseHandles();
}
info.GetReturnValue().Set(info.This());
}
#line 340 "./src/objects/database.lzz"
#line 339 "./src/objects/database.lzz"
void Database::JS_defaultSafeIntegers (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 340 "./src/objects/database.lzz"
#line 339 "./src/objects/database.lzz"
{
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
if (info.Length() == 0) db->safe_ints = true;
else { if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a boolean" ) ; db -> safe_ints = v8 :: Local < v8 :: Boolean > :: Cast ( info [ 0 ] ) -> Value ( ) ; }
info.GetReturnValue().Set(info.This());
}
#line 347 "./src/objects/database.lzz"
#line 345 "./src/objects/database.lzz"
void Database::JS_unsafeMode (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 347 "./src/objects/database.lzz"
#line 345 "./src/objects/database.lzz"
{
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
if (info.Length() == 0) db->unsafe_mode = true;
else { if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a boolean" ) ; db -> unsafe_mode = v8 :: Local < v8 :: Boolean > :: Cast ( info [ 0 ] ) -> Value ( ) ; }
sqlite3_db_config(db->db_handle, SQLITE_DBCONFIG_DEFENSIVE, static_cast<int>(!db->unsafe_mode), NULL);
info.GetReturnValue().Set(info.This());
}
#line 355 "./src/objects/database.lzz"
#line 352 "./src/objects/database.lzz"
void Database::JS_open (v8::Local <v8 :: String> _, v8::PropertyCallbackInfo <v8 :: Value> const & info)
#line 355 "./src/objects/database.lzz"
#line 352 "./src/objects/database.lzz"
{
info.GetReturnValue().Set( node :: ObjectWrap :: Unwrap <Database>(info.This())->open);
}
#line 359 "./src/objects/database.lzz"
#line 356 "./src/objects/database.lzz"
void Database::JS_inTransaction (v8::Local <v8 :: String> _, v8::PropertyCallbackInfo <v8 :: Value> const & info)
#line 359 "./src/objects/database.lzz"
#line 356 "./src/objects/database.lzz"
{
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
info.GetReturnValue().Set(db->open && !static_cast<bool>(sqlite3_get_autocommit(db->db_handle)));
}
#line 364 "./src/objects/database.lzz"
#line 361 "./src/objects/database.lzz"
int const Database::MAX_BUFFER_SIZE;
#line 365 "./src/objects/database.lzz"
#line 362 "./src/objects/database.lzz"
int const Database::MAX_STRING_SIZE;
#line 5 "./src/objects/statement.lzz"
v8::Local <v8 :: Function> Statement::Init (v8::Isolate * isolate, v8::Local <v8 :: External> data)
@@ -746,18 +741,21 @@ void Statement::JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info)
return ThrowTypeError("Statements can only be constructed by the db.prepare() method");
}
assert(info.IsConstructCall());
v8::Local<v8::Object> database = addon->privileged_info->This();
Database* db = node :: ObjectWrap :: Unwrap <Database>(database);
int flags = SQLITE_PREPARE_PERSISTENT;
Database* db = node :: ObjectWrap :: Unwrap <Database>(addon->privileged_info->This());
if ( ! db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ;
if ( db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
if (addon->PragmaMode()) {
v8::Local<v8::String> source = v8::Local<v8::String>::Cast((*addon->privileged_info)[0]);
v8::Local<v8::Object> database = v8::Local<v8::Object>::Cast((*addon->privileged_info)[1]);
bool pragmaMode = v8::Local<v8::Boolean>::Cast((*addon->privileged_info)[2])->Value();
int flags = SQLITE_PREPARE_PERSISTENT;
if (pragmaMode) {
if ( ! db -> GetState ( ) -> unsafe_mode ) { if ( db -> GetState ( ) -> iterators ) return ThrowTypeError ( "This database connection is busy executing a query" ) ; } ( ( void ) 0 ) ;
flags = 0;
}
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
v8::Local<v8::String> source = v8::Local<v8::String>::Cast((*addon->privileged_info)[0]);
v8::String::Utf8Value utf8(isolate, source);
sqlite3_stmt* handle;
const char* tail;
@@ -790,7 +788,7 @@ void Statement::JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info)
}
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
bool returns_data = (sqlite3_stmt_readonly(handle) && sqlite3_column_count(handle) >= 1) || addon->PragmaMode();
bool returns_data = (sqlite3_stmt_readonly(handle) && sqlite3_column_count(handle) >= 1) || pragmaMode;
Statement* stmt = new Statement(db, handle, addon->NextId(), returns_data);
stmt->Wrap(info.This());
SetFrozen(isolate, ctx, info.This(), addon->cs.reader, v8::Boolean::New(isolate, returns_data));
@@ -799,9 +797,9 @@ void Statement::JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info)
info.GetReturnValue().Set(info.This());
}
#line 139 "./src/objects/statement.lzz"
#line 142 "./src/objects/statement.lzz"
void Statement::JS_run (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 139 "./src/objects/statement.lzz"
#line 142 "./src/objects/statement.lzz"
{
Statement * stmt = node :: ObjectWrap :: Unwrap < Statement > ( info . This ( ) ) ; if ( stmt -> returns_data ) return ThrowTypeError ( "This statement returns data. Use get(), all(), or iterate() instead" ) ; sqlite3_stmt * handle = stmt -> handle ; Database * db = stmt -> db ; if ( ! db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ; if ( db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ; assert ( ! stmt -> locked ) ; if ( ! db -> GetState ( ) -> unsafe_mode ) { if ( db -> GetState ( ) -> iterators ) return ThrowTypeError ( "This database connection is busy executing a query" ) ; } ( ( void ) 0 ) ; const bool bound = stmt -> bound ; if ( ! bound ) { Binder binder ( handle ) ; if ( ! binder . Bind ( info , info . Length ( ) , stmt ) ) { sqlite3_clear_bindings ( handle ) ; return ; } ( ( void ) 0 ) ; } else if ( info . Length ( ) > 0 ) { return ThrowTypeError ( "This statement already has bound parameters" ) ; } ( ( void ) 0 ) ; db -> GetState ( ) -> busy = true ; v8 :: Isolate * isolate = info . GetIsolate ( ) ; if ( db -> Log ( isolate , handle ) ) { db -> GetState ( ) -> busy = false ; db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ; } ( ( void ) 0 ) ;
sqlite3* db_handle = db->GetHandle();
@@ -824,9 +822,9 @@ void Statement::JS_run (v8::FunctionCallbackInfo <v8 :: Value> const & info)
}
db -> GetState ( ) -> busy = false ; db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ;
}
#line 162 "./src/objects/statement.lzz"
#line 165 "./src/objects/statement.lzz"
void Statement::JS_get (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 162 "./src/objects/statement.lzz"
#line 165 "./src/objects/statement.lzz"
{
Statement * stmt = node :: ObjectWrap :: Unwrap < Statement > ( info . This ( ) ) ; if ( ! stmt -> returns_data ) return ThrowTypeError ( "This statement does not return data. Use run() instead" ) ; sqlite3_stmt * handle = stmt -> handle ; Database * db = stmt -> db ; if ( ! db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ; if ( db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ; if ( stmt -> locked ) return ThrowTypeError ( "This statement is busy executing a query" ) ; const bool bound = stmt -> bound ; if ( ! bound ) { Binder binder ( handle ) ; if ( ! binder . Bind ( info , info . Length ( ) , stmt ) ) { sqlite3_clear_bindings ( handle ) ; return ; } ( ( void ) 0 ) ; } else if ( info . Length ( ) > 0 ) { return ThrowTypeError ( "This statement already has bound parameters" ) ; } ( ( void ) 0 ) ; db -> GetState ( ) -> busy = true ; v8 :: Isolate * isolate = info . GetIsolate ( ) ; if ( db -> Log ( isolate , handle ) ) { db -> GetState ( ) -> busy = false ; db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ; } ( ( void ) 0 ) ;
int status = sqlite3_step(handle);
@@ -841,9 +839,9 @@ void Statement::JS_get (v8::FunctionCallbackInfo <v8 :: Value> const & info)
sqlite3_reset(handle);
db -> GetState ( ) -> busy = false ; db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ;
}
#line 177 "./src/objects/statement.lzz"
#line 180 "./src/objects/statement.lzz"
void Statement::JS_all (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 177 "./src/objects/statement.lzz"
#line 180 "./src/objects/statement.lzz"
{
Statement * stmt = node :: ObjectWrap :: Unwrap < Statement > ( info . This ( ) ) ; if ( ! stmt -> returns_data ) return ThrowTypeError ( "This statement does not return data. Use run() instead" ) ; sqlite3_stmt * handle = stmt -> handle ; Database * db = stmt -> db ; if ( ! db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ; if ( db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ; if ( stmt -> locked ) return ThrowTypeError ( "This statement is busy executing a query" ) ; const bool bound = stmt -> bound ; if ( ! bound ) { Binder binder ( handle ) ; if ( ! binder . Bind ( info , info . Length ( ) , stmt ) ) { sqlite3_clear_bindings ( handle ) ; return ; } ( ( void ) 0 ) ; } else if ( info . Length ( ) > 0 ) { return ThrowTypeError ( "This statement already has bound parameters" ) ; } ( ( void ) 0 ) ; db -> GetState ( ) -> busy = true ; v8 :: Isolate * isolate = info . GetIsolate ( ) ; if ( db -> Log ( isolate , handle ) ) { db -> GetState ( ) -> busy = false ; db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ; } ( ( void ) 0 ) ;
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
@@ -864,9 +862,9 @@ void Statement::JS_all (v8::FunctionCallbackInfo <v8 :: Value> const & info)
if (js_error) db->GetState()->was_js_error = true;
db -> GetState ( ) -> busy = false ; db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ;
}
#line 198 "./src/objects/statement.lzz"
#line 201 "./src/objects/statement.lzz"
void Statement::JS_iterate (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 198 "./src/objects/statement.lzz"
#line 201 "./src/objects/statement.lzz"
{
Addon * addon = static_cast < Addon * > ( v8 :: Local < v8 :: External > :: Cast ( info . Data ( ) ) -> Value ( ) ) ;
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
@@ -876,9 +874,9 @@ void Statement::JS_iterate (v8::FunctionCallbackInfo <v8 :: Value> const & info)
addon->privileged_info = NULL;
if (!maybe_iter.IsEmpty()) info.GetReturnValue().Set(maybe_iter.ToLocalChecked());
}
#line 208 "./src/objects/statement.lzz"
#line 211 "./src/objects/statement.lzz"
void Statement::JS_bind (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 208 "./src/objects/statement.lzz"
#line 211 "./src/objects/statement.lzz"
{
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
if (stmt->bound) return ThrowTypeError("The bind() method can only be invoked once per statement object");
@@ -889,9 +887,9 @@ void Statement::JS_bind (v8::FunctionCallbackInfo <v8 :: Value> const & info)
stmt->bound = true;
info.GetReturnValue().Set(info.This());
}
#line 219 "./src/objects/statement.lzz"
#line 222 "./src/objects/statement.lzz"
void Statement::JS_pluck (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 219 "./src/objects/statement.lzz"
#line 222 "./src/objects/statement.lzz"
{
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
if (!stmt->returns_data) return ThrowTypeError("The pluck() method is only for statements that return data");
@@ -902,9 +900,9 @@ void Statement::JS_pluck (v8::FunctionCallbackInfo <v8 :: Value> const & info)
stmt->mode = use ? Data::PLUCK : stmt->mode == Data::PLUCK ? Data::FLAT : stmt->mode;
info.GetReturnValue().Set(info.This());
}
#line 230 "./src/objects/statement.lzz"
#line 233 "./src/objects/statement.lzz"
void Statement::JS_expand (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 230 "./src/objects/statement.lzz"
#line 233 "./src/objects/statement.lzz"
{
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
if (!stmt->returns_data) return ThrowTypeError("The expand() method is only for statements that return data");
@@ -915,9 +913,9 @@ void Statement::JS_expand (v8::FunctionCallbackInfo <v8 :: Value> const & info)
stmt->mode = use ? Data::EXPAND : stmt->mode == Data::EXPAND ? Data::FLAT : stmt->mode;
info.GetReturnValue().Set(info.This());
}
#line 241 "./src/objects/statement.lzz"
#line 244 "./src/objects/statement.lzz"
void Statement::JS_raw (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 241 "./src/objects/statement.lzz"
#line 244 "./src/objects/statement.lzz"
{
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
if (!stmt->returns_data) return ThrowTypeError("The raw() method is only for statements that return data");
@@ -928,9 +926,9 @@ void Statement::JS_raw (v8::FunctionCallbackInfo <v8 :: Value> const & info)
stmt->mode = use ? Data::RAW : stmt->mode == Data::RAW ? Data::FLAT : stmt->mode;
info.GetReturnValue().Set(info.This());
}
#line 252 "./src/objects/statement.lzz"
#line 255 "./src/objects/statement.lzz"
void Statement::JS_safeIntegers (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 252 "./src/objects/statement.lzz"
#line 255 "./src/objects/statement.lzz"
{
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
if ( stmt -> db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
@@ -939,9 +937,9 @@ void Statement::JS_safeIntegers (v8::FunctionCallbackInfo <v8 :: Value> const &
else { if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a boolean" ) ; stmt -> safe_ints = v8 :: Local < v8 :: Boolean > :: Cast ( info [ 0 ] ) -> Value ( ) ; }
info.GetReturnValue().Set(info.This());
}
#line 261 "./src/objects/statement.lzz"
#line 264 "./src/objects/statement.lzz"
void Statement::JS_columns (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 261 "./src/objects/statement.lzz"
#line 264 "./src/objects/statement.lzz"
{
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
if (!stmt->returns_data) return ThrowTypeError("The columns() method is only for statements that return data");
@@ -1157,14 +1155,14 @@ void Backup::JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info)
Addon * addon = static_cast < Addon * > ( v8 :: Local < v8 :: External > :: Cast ( info . Data ( ) ) -> Value ( ) ) ;
if (!addon->privileged_info) return ThrowTypeError("Disabled constructor");
assert(info.IsConstructCall());
v8::Local<v8::Object> database = addon->privileged_info->This();
Database* db = node :: ObjectWrap :: Unwrap <Database>(database);
Database* db = node :: ObjectWrap :: Unwrap <Database>(addon->privileged_info->This());
if ( ! db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ;
if ( db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
v8::Local<v8::String> attachedName = v8::Local<v8::String>::Cast((*addon->privileged_info)[0]);
v8::Local<v8::String> destFile = v8::Local<v8::String>::Cast((*addon->privileged_info)[1]);
bool unlink = v8::Local<v8::Boolean>::Cast((*addon->privileged_info)[2])->Value();
v8::Local<v8::Object> database = v8::Local<v8::Object>::Cast((*addon->privileged_info)[0]);
v8::Local<v8::String> attachedName = v8::Local<v8::String>::Cast((*addon->privileged_info)[1]);
v8::Local<v8::String> destFile = v8::Local<v8::String>::Cast((*addon->privileged_info)[2]);
bool unlink = v8::Local<v8::Boolean>::Cast((*addon->privileged_info)[3])->Value();
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
sqlite3* dest_handle;
@@ -1661,9 +1659,9 @@ Binder::Result Binder::BindArgs (v8::FunctionCallbackInfo <v8 :: Value> const &
#line 32 "./src/better_sqlite3.lzz"
Addon::Addon (v8::Isolate * isolate)
#line 32 "./src/better_sqlite3.lzz"
: privileged_info (NULL), bit_field (0), cs (isolate)
: privileged_info (NULL), next_id (0), cs (isolate)
#line 32 "./src/better_sqlite3.lzz"
{}
{}
#line 43 "./src/better_sqlite3.lzz"
void Addon::JS_setErrorConstructor (v8::FunctionCallbackInfo <v8 :: Value> const & info)
#line 43 "./src/better_sqlite3.lzz"
+95 -113
View File
@@ -173,133 +173,131 @@ class Database : public node::ObjectWrap
public:
#line 4 "./src/objects/database.lzz"
static v8::Local <v8 :: Function> Init (v8::Isolate * isolate, v8::Local <v8 :: External> data);
#line 22 "./src/objects/database.lzz"
#line 21 "./src/objects/database.lzz"
class CompareDatabase
{
#line 22 "./src/objects/database.lzz"
#line 21 "./src/objects/database.lzz"
public:
#line 23 "./src/objects/database.lzz"
#line 22 "./src/objects/database.lzz"
bool operator () (Database const * const a, Database const * const b) const;
};
#line 27 "./src/objects/database.lzz"
#line 26 "./src/objects/database.lzz"
class CompareStatement
{
#line 27 "./src/objects/database.lzz"
#line 26 "./src/objects/database.lzz"
public:
#line 28 "./src/objects/database.lzz"
#line 27 "./src/objects/database.lzz"
bool operator () (Statement const * const a, Statement const * const b) const;
};
#line 32 "./src/objects/database.lzz"
#line 31 "./src/objects/database.lzz"
class CompareBackup
{
#line 32 "./src/objects/database.lzz"
#line 31 "./src/objects/database.lzz"
public:
#line 33 "./src/objects/database.lzz"
#line 32 "./src/objects/database.lzz"
bool operator () (Backup const * const a, Backup const * const b) const;
};
#line 39 "./src/objects/database.lzz"
#line 38 "./src/objects/database.lzz"
void ThrowDatabaseError ();
#line 43 "./src/objects/database.lzz"
#line 42 "./src/objects/database.lzz"
static void ThrowSqliteError (Addon * addon, sqlite3 * db_handle);
#line 47 "./src/objects/database.lzz"
#line 46 "./src/objects/database.lzz"
static void ThrowSqliteError (Addon * addon, char const * message, int code);
#line 63 "./src/objects/database.lzz"
#line 62 "./src/objects/database.lzz"
bool Log (v8::Isolate * isolate, sqlite3_stmt * handle);
#line 76 "./src/objects/database.lzz"
#line 75 "./src/objects/database.lzz"
void AddStatement (Statement * stmt);
#line 77 "./src/objects/database.lzz"
#line 76 "./src/objects/database.lzz"
void RemoveStatement (Statement * stmt);
#line 80 "./src/objects/database.lzz"
#line 79 "./src/objects/database.lzz"
void AddBackup (Backup * backup);
#line 81 "./src/objects/database.lzz"
#line 80 "./src/objects/database.lzz"
void RemoveBackup (Backup * backup);
#line 85 "./src/objects/database.lzz"
#line 84 "./src/objects/database.lzz"
struct State
{
#line 86 "./src/objects/database.lzz"
#line 85 "./src/objects/database.lzz"
bool const open;
#line 87 "./src/objects/database.lzz"
#line 86 "./src/objects/database.lzz"
bool busy;
#line 88 "./src/objects/database.lzz"
#line 87 "./src/objects/database.lzz"
bool const safe_ints;
#line 89 "./src/objects/database.lzz"
#line 88 "./src/objects/database.lzz"
bool const unsafe_mode;
#line 90 "./src/objects/database.lzz"
#line 89 "./src/objects/database.lzz"
bool was_js_error;
#line 91 "./src/objects/database.lzz"
#line 90 "./src/objects/database.lzz"
bool const has_logger;
#line 92 "./src/objects/database.lzz"
#line 91 "./src/objects/database.lzz"
unsigned short int iterators;
#line 93 "./src/objects/database.lzz"
#line 92 "./src/objects/database.lzz"
Addon * const addon;
};
#line 95 "./src/objects/database.lzz"
#line 94 "./src/objects/database.lzz"
State * GetState ();
#line 98 "./src/objects/database.lzz"
#line 97 "./src/objects/database.lzz"
sqlite3 * GetHandle ();
#line 101 "./src/objects/database.lzz"
#line 100 "./src/objects/database.lzz"
Addon * GetAddon ();
#line 106 "./src/objects/database.lzz"
#line 105 "./src/objects/database.lzz"
void CloseHandles ();
#line 118 "./src/objects/database.lzz"
#line 117 "./src/objects/database.lzz"
~ Database ();
#line 123 "./src/objects/database.lzz"
#line 122 "./src/objects/database.lzz"
private:
#line 125 "./src/objects/database.lzz"
#line 124 "./src/objects/database.lzz"
explicit Database (sqlite3 * _db_handle, v8::Isolate * isolate, Addon * _addon, v8::Local <v8::Value> _logger);
#line 142 "./src/objects/database.lzz"
#line 141 "./src/objects/database.lzz"
static void JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 187 "./src/objects/database.lzz"
#line 186 "./src/objects/database.lzz"
static void JS_prepare (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 199 "./src/objects/database.lzz"
#line 202 "./src/objects/database.lzz"
static void JS_exec (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 238 "./src/objects/database.lzz"
static void JS_pragma (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 243 "./src/objects/database.lzz"
#line 242 "./src/objects/database.lzz"
static void JS_backup (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 259 "./src/objects/database.lzz"
#line 260 "./src/objects/database.lzz"
static void JS_function (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 281 "./src/objects/database.lzz"
static void JS_aggregate (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 308 "./src/objects/database.lzz"
#line 307 "./src/objects/database.lzz"
static void JS_loadExtension (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 329 "./src/objects/database.lzz"
static void JS_close (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 340 "./src/objects/database.lzz"
#line 339 "./src/objects/database.lzz"
static void JS_defaultSafeIntegers (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 347 "./src/objects/database.lzz"
#line 345 "./src/objects/database.lzz"
static void JS_unsafeMode (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 355 "./src/objects/database.lzz"
#line 352 "./src/objects/database.lzz"
static void JS_open (v8::Local <v8 :: String> _, v8::PropertyCallbackInfo <v8 :: Value> const & info);
#line 359 "./src/objects/database.lzz"
#line 356 "./src/objects/database.lzz"
static void JS_inTransaction (v8::Local <v8 :: String> _, v8::PropertyCallbackInfo <v8 :: Value> const & info);
#line 364 "./src/objects/database.lzz"
#line 361 "./src/objects/database.lzz"
static int const MAX_BUFFER_SIZE = node::Buffer::kMaxLength > INT_MAX ? INT_MAX : static_cast<int>(node::Buffer::kMaxLength);
#line 365 "./src/objects/database.lzz"
#line 362 "./src/objects/database.lzz"
static int const MAX_STRING_SIZE = v8::String::kMaxLength > INT_MAX ? INT_MAX : static_cast<int>(v8::String::kMaxLength);
#line 367 "./src/objects/database.lzz"
#line 364 "./src/objects/database.lzz"
sqlite3 * const db_handle;
#line 368 "./src/objects/database.lzz"
#line 365 "./src/objects/database.lzz"
bool open;
#line 369 "./src/objects/database.lzz"
#line 366 "./src/objects/database.lzz"
bool busy;
#line 370 "./src/objects/database.lzz"
#line 367 "./src/objects/database.lzz"
bool safe_ints;
#line 371 "./src/objects/database.lzz"
#line 368 "./src/objects/database.lzz"
bool unsafe_mode;
#line 372 "./src/objects/database.lzz"
#line 369 "./src/objects/database.lzz"
bool was_js_error;
#line 373 "./src/objects/database.lzz"
#line 370 "./src/objects/database.lzz"
bool const has_logger;
#line 374 "./src/objects/database.lzz"
#line 371 "./src/objects/database.lzz"
unsigned short int iterators;
#line 375 "./src/objects/database.lzz"
#line 372 "./src/objects/database.lzz"
Addon * const addon;
#line 376 "./src/objects/database.lzz"
#line 373 "./src/objects/database.lzz"
CopyablePersistent <v8::Value> const logger;
#line 377 "./src/objects/database.lzz"
#line 374 "./src/objects/database.lzz"
std::set <Statement*, CompareStatement> stmts;
#line 378 "./src/objects/database.lzz"
#line 375 "./src/objects/database.lzz"
std::set <Backup*, CompareBackup> backups;
};
#line 1 "./src/objects/statement.lzz"
@@ -337,45 +335,45 @@ private:
explicit Statement (Database * _db, sqlite3_stmt * _handle, sqlite3_uint64 _id, bool _returns_data);
#line 79 "./src/objects/statement.lzz"
static void JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 139 "./src/objects/statement.lzz"
#line 142 "./src/objects/statement.lzz"
static void JS_run (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 162 "./src/objects/statement.lzz"
#line 165 "./src/objects/statement.lzz"
static void JS_get (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 177 "./src/objects/statement.lzz"
#line 180 "./src/objects/statement.lzz"
static void JS_all (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 198 "./src/objects/statement.lzz"
#line 201 "./src/objects/statement.lzz"
static void JS_iterate (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 208 "./src/objects/statement.lzz"
#line 211 "./src/objects/statement.lzz"
static void JS_bind (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 219 "./src/objects/statement.lzz"
#line 222 "./src/objects/statement.lzz"
static void JS_pluck (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 230 "./src/objects/statement.lzz"
#line 233 "./src/objects/statement.lzz"
static void JS_expand (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 241 "./src/objects/statement.lzz"
#line 244 "./src/objects/statement.lzz"
static void JS_raw (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 252 "./src/objects/statement.lzz"
#line 255 "./src/objects/statement.lzz"
static void JS_safeIntegers (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 261 "./src/objects/statement.lzz"
#line 264 "./src/objects/statement.lzz"
static void JS_columns (v8::FunctionCallbackInfo <v8 :: Value> const & info);
#line 304 "./src/objects/statement.lzz"
Database * const db;
#line 305 "./src/objects/statement.lzz"
sqlite3_stmt * const handle;
#line 306 "./src/objects/statement.lzz"
Extras * const extras;
#line 307 "./src/objects/statement.lzz"
bool alive;
Database * const db;
#line 308 "./src/objects/statement.lzz"
bool locked;
sqlite3_stmt * const handle;
#line 309 "./src/objects/statement.lzz"
bool bound;
Extras * const extras;
#line 310 "./src/objects/statement.lzz"
bool has_bind_map;
bool alive;
#line 311 "./src/objects/statement.lzz"
bool safe_ints;
bool locked;
#line 312 "./src/objects/statement.lzz"
char mode;
bool bound;
#line 313 "./src/objects/statement.lzz"
bool has_bind_map;
#line 314 "./src/objects/statement.lzz"
bool safe_ints;
#line 315 "./src/objects/statement.lzz"
char mode;
#line 316 "./src/objects/statement.lzz"
bool const returns_data;
};
#line 1 "./src/objects/statement-iterator.lzz"
@@ -660,7 +658,7 @@ struct Addon
#line 38 "./src/better_sqlite3.lzz"
v8::FunctionCallbackInfo <v8 :: Value> const * privileged_info;
#line 39 "./src/better_sqlite3.lzz"
sqlite3_uint64 bit_field;
sqlite3_uint64 next_id;
#line 40 "./src/better_sqlite3.lzz"
CS cs;
#line 41 "./src/better_sqlite3.lzz"
@@ -671,10 +669,6 @@ struct Addon
static void Cleanup (void * ptr);
#line 55 "./src/better_sqlite3.lzz"
sqlite3_uint64 NextId ();
#line 58 "./src/better_sqlite3.lzz"
bool PragmaMode ();
#line 61 "./src/better_sqlite3.lzz"
void SetPragmaMode (bool active);
};
#line 16 "./src/util/macros.lzz"
LZZ_INLINE v8::Local <v8::String> StringFromUtf8 (v8::Isolate * isolate, char const * data, int length)
@@ -757,41 +751,41 @@ LZZ_INLINE int BindMap::GetSize ()
#line 42 "./src/util/bind-map.lzz"
{ return length;
}
#line 76 "./src/objects/database.lzz"
#line 75 "./src/objects/database.lzz"
LZZ_INLINE void Database::AddStatement (Statement * stmt)
#line 76 "./src/objects/database.lzz"
#line 75 "./src/objects/database.lzz"
{ stmts.insert(stmts.end(), stmt);
}
#line 77 "./src/objects/database.lzz"
#line 76 "./src/objects/database.lzz"
LZZ_INLINE void Database::RemoveStatement (Statement * stmt)
#line 77 "./src/objects/database.lzz"
#line 76 "./src/objects/database.lzz"
{ stmts.erase(stmt);
}
#line 80 "./src/objects/database.lzz"
#line 79 "./src/objects/database.lzz"
LZZ_INLINE void Database::AddBackup (Backup * backup)
#line 80 "./src/objects/database.lzz"
#line 79 "./src/objects/database.lzz"
{ backups.insert(backups.end(), backup);
}
#line 81 "./src/objects/database.lzz"
#line 80 "./src/objects/database.lzz"
LZZ_INLINE void Database::RemoveBackup (Backup * backup)
#line 81 "./src/objects/database.lzz"
#line 80 "./src/objects/database.lzz"
{ backups.erase(backup);
}
#line 95 "./src/objects/database.lzz"
#line 94 "./src/objects/database.lzz"
LZZ_INLINE Database::State * Database::GetState ()
#line 95 "./src/objects/database.lzz"
#line 94 "./src/objects/database.lzz"
{
return reinterpret_cast<State*>(&open);
}
#line 98 "./src/objects/database.lzz"
#line 97 "./src/objects/database.lzz"
LZZ_INLINE sqlite3 * Database::GetHandle ()
#line 98 "./src/objects/database.lzz"
#line 97 "./src/objects/database.lzz"
{
return db_handle;
}
#line 101 "./src/objects/database.lzz"
#line 100 "./src/objects/database.lzz"
LZZ_INLINE Addon * Database::GetAddon ()
#line 101 "./src/objects/database.lzz"
#line 100 "./src/objects/database.lzz"
{
return addon;
}
@@ -873,19 +867,7 @@ LZZ_INLINE void CustomAggregate::xValueBase (sqlite3_context * invocation, bool
LZZ_INLINE sqlite3_uint64 Addon::NextId ()
#line 55 "./src/better_sqlite3.lzz"
{
return (bit_field++ << 1) >> 1;
}
#line 58 "./src/better_sqlite3.lzz"
LZZ_INLINE bool Addon::PragmaMode ()
#line 58 "./src/better_sqlite3.lzz"
{
return bit_field >> 63 != 0;
}
#line 61 "./src/better_sqlite3.lzz"
LZZ_INLINE void Addon::SetPragmaMode (bool active)
#line 61 "./src/better_sqlite3.lzz"
{
bit_field = (bit_field << 1) >> 1 | static_cast<sqlite3_uint64>(active) << 63;
return next_id++;
}
#undef LZZ_INLINE
#endif
+3 -9
View File
@@ -29,14 +29,14 @@ class Backup;
#insert "util/binder.lzz"
struct Addon {
Addon(v8::Isolate* isolate) : privileged_info(NULL), bit_field(0), cs(isolate) {}
Addon(v8::Isolate* isolate) : privileged_info(NULL), next_id(0), cs(isolate) {}
CopyablePersistent<v8::Function> Statement;
CopyablePersistent<v8::Function> StatementIterator;
CopyablePersistent<v8::Function> Backup;
CopyablePersistent<v8::Function> SqliteError;
NODE_ARGUMENTS_POINTER privileged_info;
sqlite3_uint64 bit_field;
sqlite3_uint64 next_id;
CS cs;
std::set<Database*, Database::CompareDatabase> dbs;
@@ -53,13 +53,7 @@ struct Addon {
}
inline sqlite3_uint64 NextId() {
return (bit_field++ << 1) >> 1;
}
inline bool PragmaMode() {
return bit_field >> 63 != 0;
}
inline void SetPragmaMode(bool active) {
bit_field = (bit_field << 1) >> 1 | static_cast<sqlite3_uint64>(active) << 63;
return next_id++;
}
};
+5 -5
View File
@@ -50,14 +50,14 @@ private:
UseAddon;
if (!addon->privileged_info) return ThrowTypeError("Disabled constructor");
assert(info.IsConstructCall());
v8::Local<v8::Object> database = addon->privileged_info->This();
Database* db = Unwrap<Database>(database);
Database* db = Unwrap<Database>(addon->privileged_info->This());
REQUIRE_DATABASE_OPEN(db->GetState());
REQUIRE_DATABASE_NOT_BUSY(db->GetState());
v8::Local<v8::String> attachedName = v8::Local<v8::String>::Cast((*addon->privileged_info)[0]);
v8::Local<v8::String> destFile = v8::Local<v8::String>::Cast((*addon->privileged_info)[1]);
bool unlink = v8::Local<v8::Boolean>::Cast((*addon->privileged_info)[2])->Value();
v8::Local<v8::Object> database = v8::Local<v8::Object>::Cast((*addon->privileged_info)[0]);
v8::Local<v8::String> attachedName = v8::Local<v8::String>::Cast((*addon->privileged_info)[1]);
v8::Local<v8::String> destFile = v8::Local<v8::String>::Cast((*addon->privileged_info)[2]);
bool unlink = v8::Local<v8::Boolean>::Cast((*addon->privileged_info)[3])->Value();
UseIsolate;
sqlite3* dest_handle;
+17 -20
View File
@@ -5,7 +5,6 @@ public:
v8::Local<v8::FunctionTemplate> t = NewConstructorTemplate(isolate, data, JS_new, "Database");
SetPrototypeMethod(isolate, data, t, "prepare", JS_prepare);
SetPrototypeMethod(isolate, data, t, "exec", JS_exec);
SetPrototypeMethod(isolate, data, t, "pragma", JS_pragma);
SetPrototypeMethod(isolate, data, t, "backup", JS_backup);
SetPrototypeMethod(isolate, data, t, "function", JS_function);
SetPrototypeMethod(isolate, data, t, "aggregate", JS_aggregate);
@@ -186,7 +185,11 @@ private:
NODE_METHOD(JS_prepare) {
REQUIRE_ARGUMENT_STRING(first, v8::Local<v8::String> source);
REQUIRE_ARGUMENT_OBJECT(second, v8::Local<v8::Object> database);
REQUIRE_ARGUMENT_BOOLEAN(third, bool pragmaMode);
(void)source;
(void)database;
(void)pragmaMode;
UseAddon;
UseIsolate;
v8::Local<v8::Function> c = v8::Local<v8::Function>::New(isolate, addon->Statement);
@@ -231,19 +234,17 @@ private:
}
db->busy = false;
if (status == SQLITE_OK) info.GetReturnValue().Set(info.This());
else db->ThrowDatabaseError();
}
NODE_METHOD(JS_pragma) {
REQUIRE_ARGUMENT_BOOLEAN(first, bool active);
OnlyAddon->SetPragmaMode(active);
if (status != SQLITE_OK) {
db->ThrowDatabaseError();
}
}
NODE_METHOD(JS_backup) {
REQUIRE_ARGUMENT_STRING(first, v8::Local<v8::String> attachedName);
REQUIRE_ARGUMENT_STRING(second, v8::Local<v8::String> destFile);
REQUIRE_ARGUMENT_BOOLEAN(third, bool unlink);
REQUIRE_ARGUMENT_OBJECT(first, v8::Local<v8::Object> database);
REQUIRE_ARGUMENT_STRING(second, v8::Local<v8::String> attachedName);
REQUIRE_ARGUMENT_STRING(third, v8::Local<v8::String> destFile);
REQUIRE_ARGUMENT_BOOLEAN(fourth, bool unlink);
(void)database;
(void)attachedName;
(void)destFile;
(void)unlink;
@@ -273,9 +274,8 @@ private:
safe_ints = safe_ints < 2 ? safe_ints : static_cast<int>(db->safe_ints);
if (sqlite3_create_function_v2(db->db_handle, *name, argc, mask, new CustomFunction(isolate, db, fn, *name, safe_ints), CustomFunction::xFunc, NULL, NULL, CustomFunction::xDestroy) != SQLITE_OK) {
return db->ThrowDatabaseError();
db->ThrowDatabaseError();
}
info.GetReturnValue().Set(info.This());
}
NODE_METHOD(JS_aggregate) {
@@ -300,9 +300,8 @@ private:
safe_ints = safe_ints < 2 ? safe_ints : static_cast<int>(db->safe_ints);
if (sqlite3_create_window_function(db->db_handle, *name, argc, mask, new CustomAggregate(isolate, db, start, step, inverse, result, *name, safe_ints), CustomAggregate::xStep, CustomAggregate::xFinal, xValue, xInverse, CustomAggregate::xDestroy) != SQLITE_OK) {
return db->ThrowDatabaseError();
db->ThrowDatabaseError();
}
info.GetReturnValue().Set(info.This());
}
NODE_METHOD(JS_loadExtension) {
@@ -321,8 +320,9 @@ private:
entryPoint.IsEmpty() ? NULL : *v8::String::Utf8Value(isolate, entryPoint),
&error
);
if (status == SQLITE_OK) info.GetReturnValue().Set(info.This());
else ThrowSqliteError(db->addon, error, status);
if (status != SQLITE_OK) {
ThrowSqliteError(db->addon, error, status);
}
sqlite3_free(error);
}
@@ -334,14 +334,12 @@ private:
db->addon->dbs.erase(db);
db->CloseHandles();
}
info.GetReturnValue().Set(info.This());
}
NODE_METHOD(JS_defaultSafeIntegers) {
Database* db = Unwrap<Database>(info.This());
if (info.Length() == 0) db->safe_ints = true;
else { REQUIRE_ARGUMENT_BOOLEAN(first, db->safe_ints); }
info.GetReturnValue().Set(info.This());
}
NODE_METHOD(JS_unsafeMode) {
@@ -349,7 +347,6 @@ private:
if (info.Length() == 0) db->unsafe_mode = true;
else { REQUIRE_ARGUMENT_BOOLEAN(first, db->unsafe_mode); }
sqlite3_db_config(db->db_handle, SQLITE_DBCONFIG_DEFENSIVE, static_cast<int>(!db->unsafe_mode), NULL);
info.GetReturnValue().Set(info.This());
}
NODE_GETTER(JS_open) {
+9 -6
View File
@@ -82,18 +82,21 @@ private:
return ThrowTypeError("Statements can only be constructed by the db.prepare() method");
}
assert(info.IsConstructCall());
v8::Local<v8::Object> database = addon->privileged_info->This();
Database* db = Unwrap<Database>(database);
int flags = SQLITE_PREPARE_PERSISTENT;
Database* db = Unwrap<Database>(addon->privileged_info->This());
REQUIRE_DATABASE_OPEN(db->GetState());
REQUIRE_DATABASE_NOT_BUSY(db->GetState());
if (addon->PragmaMode()) {
v8::Local<v8::String> source = v8::Local<v8::String>::Cast((*addon->privileged_info)[0]);
v8::Local<v8::Object> database = v8::Local<v8::Object>::Cast((*addon->privileged_info)[1]);
bool pragmaMode = v8::Local<v8::Boolean>::Cast((*addon->privileged_info)[2])->Value();
int flags = SQLITE_PREPARE_PERSISTENT;
if (pragmaMode) {
REQUIRE_DATABASE_NO_ITERATORS_UNLESS_UNSAFE(db->GetState());
flags = 0;
}
UseIsolate;
v8::Local<v8::String> source = v8::Local<v8::String>::Cast((*addon->privileged_info)[0]);
v8::String::Utf8Value utf8(isolate, source);
sqlite3_stmt* handle;
const char* tail;
@@ -126,7 +129,7 @@ private:
}
UseContext;
bool returns_data = (sqlite3_stmt_readonly(handle) && sqlite3_column_count(handle) >= 1) || addon->PragmaMode();
bool returns_data = (sqlite3_stmt_readonly(handle) && sqlite3_column_count(handle) >= 1) || pragmaMode;
Statement* stmt = new Statement(db, handle, addon->NextId(), returns_data);
stmt->Wrap(info.This());
SetFrozen(isolate, ctx, info.This(), addon->cs.reader, v8::Boolean::New(isolate, returns_data));