auto-grow indices
This commit is contained in:
parent
8f0680826a
commit
65fe453ac6
154
lib/dbwrap.js
154
lib/dbwrap.js
|
@ -5,8 +5,12 @@ function wrap(db, dir) {
|
||||||
// why doesn't the unhandled promise rejection fire?
|
// why doesn't the unhandled promise rejection fire?
|
||||||
var PromiseA = require('bluebird');
|
var PromiseA = require('bluebird');
|
||||||
var promises = [];
|
var promises = [];
|
||||||
|
var earr = [];
|
||||||
var dbsMap = {};
|
var dbsMap = {};
|
||||||
var arr = true;
|
|
||||||
|
db.escape = function (str) {
|
||||||
|
return (str||'').replace(/'/g, "''");
|
||||||
|
};
|
||||||
|
|
||||||
function lowerFirst(str) {
|
function lowerFirst(str) {
|
||||||
return str.charAt(0).toLowerCase() + str.slice(1);
|
return str.charAt(0).toLowerCase() + str.slice(1);
|
||||||
|
@ -36,11 +40,98 @@ function wrap(db, dir) {
|
||||||
return str.charAt(0).toUpperCase() + camelCase(str).slice(1);
|
return str.charAt(0).toUpperCase() + camelCase(str).slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PRAGMA schema.table_info(table-name);
|
||||||
|
//
|
||||||
|
function sqlite3GetColumns(tablename, columns, cb) {
|
||||||
|
var sql = "PRAGMA table_info(" + db.escape(tablename) + ")";
|
||||||
|
|
||||||
|
db.all(sql, earr, function (err, result) {
|
||||||
|
if (err) {
|
||||||
|
console.error('[Error] query columns');
|
||||||
|
console.error(err.stack);
|
||||||
|
cb(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('sqlite3 rows 0');
|
||||||
|
console.log(result);
|
||||||
|
|
||||||
|
function alterTable() {
|
||||||
|
var column = columns.pop();
|
||||||
|
var sql;
|
||||||
|
|
||||||
|
if (!column) {
|
||||||
|
cb(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((result.rows||result).some(function (row) {
|
||||||
|
return (row.column_name || row.name) === snakeCase(column.name);
|
||||||
|
})) {
|
||||||
|
alterTable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = "ALTER TABLE " + db.escape(tablename)
|
||||||
|
+ " ADD COLUMN "
|
||||||
|
+ db.escape(column.name) + " " + db.escape(column.type)
|
||||||
|
+ " DEFAULT null"
|
||||||
|
;
|
||||||
|
console.log('sqlite3 1');
|
||||||
|
console.log(sql);
|
||||||
|
|
||||||
|
db.all(sql, earr, function (err, results) {
|
||||||
|
if (err) {
|
||||||
|
console.error("[Error] add column '" + tablename + "'");
|
||||||
|
console.error(err.stack);
|
||||||
|
cb(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('sqlite3 rows 1');
|
||||||
|
console.log(results);
|
||||||
|
|
||||||
|
alterTable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
alterTable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeColumn(col, i, arr) {
|
||||||
|
if ('string' === typeof col) {
|
||||||
|
col = arr[i] = { name: col, type: 'text' };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!col.type) {
|
||||||
|
col.type = 'text';
|
||||||
|
}
|
||||||
|
|
||||||
|
col.type = col.type.toLowerCase(); // oh postgres...
|
||||||
|
col.name = snakeCase(col.name);
|
||||||
|
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
function createTable(opts) {
|
function createTable(opts) {
|
||||||
|
if (!opts.modelname && !opts.tablename) {
|
||||||
|
throw new Error('Please specify opts.modelname');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opts.tablename) {
|
||||||
|
opts.tablename = snakeCase(opts.modelname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opts.indices) {
|
||||||
|
opts.indices = [];
|
||||||
|
}
|
||||||
|
|
||||||
var DB = {};
|
var DB = {};
|
||||||
var tablename = db.escape(snakeCase(opts.tablename) || 'data');
|
var tablename = db.escape(snakeCase(opts.tablename) || 'data');
|
||||||
var idname = db.escape(snakeCase(opts.idname) || 'id');
|
var idname = db.escape(snakeCase(opts.idname || 'id'));
|
||||||
var idnameCased = (camelCase(opts.idname) || 'id');
|
var idnameCased = (camelCase(opts.idname || 'id'));
|
||||||
|
|
||||||
|
opts.indices.forEach(normalizeColumn);
|
||||||
|
|
||||||
db = PromiseA.promisifyAll(db);
|
db = PromiseA.promisifyAll(db);
|
||||||
|
|
||||||
|
@ -98,6 +189,21 @@ function wrap(db, dir) {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DB.migrate = function (columns) {
|
||||||
|
columns.forEach(normalizeColumn);
|
||||||
|
|
||||||
|
return new PromiseA(function (resolve, reject) {
|
||||||
|
sqlite3GetColumns(tablename, columns, function (err) {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
DB.find = function (opts, params) {
|
DB.find = function (opts, params) {
|
||||||
var sql = 'SELECT * FROM \'' + tablename + '\' ';
|
var sql = 'SELECT * FROM \'' + tablename + '\' ';
|
||||||
var keys = opts && Object.keys(opts);
|
var keys = opts && Object.keys(opts);
|
||||||
|
@ -109,7 +215,12 @@ function wrap(db, dir) {
|
||||||
if (i !== 0) {
|
if (i !== 0) {
|
||||||
sql += 'AND ';
|
sql += 'AND ';
|
||||||
}
|
}
|
||||||
sql += db.escape(snakeCase(key)) + " = '" + db.escape(opts[key]) + "'";
|
if (null === opts[key]) {
|
||||||
|
sql += db.escape(snakeCase(key)) + " IS '" + db.escape(opts[key]) + "'";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sql += db.escape(snakeCase(key)) + " = '" + db.escape(opts[key]) + "'";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (null !== opts || (params && !params.limit)) {
|
else if (null !== opts || (params && !params.limit)) {
|
||||||
|
@ -264,14 +375,7 @@ function wrap(db, dir) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
(opts.indices || []).forEach(function (col) {
|
opts.indices.forEach(function (col) {
|
||||||
if ('string' === typeof col) {
|
|
||||||
col = { name: col, type: 'TEXT' };
|
|
||||||
}
|
|
||||||
if (!col.type) {
|
|
||||||
col.type = 'TEXT';
|
|
||||||
}
|
|
||||||
|
|
||||||
var val = data[camelCase(col.name)];
|
var val = data[camelCase(col.name)];
|
||||||
|
|
||||||
//if (col.name in data)
|
//if (col.name in data)
|
||||||
|
@ -386,7 +490,7 @@ function wrap(db, dir) {
|
||||||
var indexable = [idname + ' TEXT'];
|
var indexable = [idname + ' TEXT'];
|
||||||
var sql;
|
var sql;
|
||||||
|
|
||||||
(opts.indices || []).forEach(function (col) {
|
opts.indices.forEach(function (col) {
|
||||||
if ('string' === typeof col) {
|
if ('string' === typeof col) {
|
||||||
col = { name: col, type: 'TEXT' };
|
col = { name: col, type: 'TEXT' };
|
||||||
}
|
}
|
||||||
|
@ -404,13 +508,19 @@ function wrap(db, dir) {
|
||||||
+ "(" + indexable.join(', ') + ", PRIMARY KEY(" + idname + "))"
|
+ "(" + indexable.join(', ') + ", PRIMARY KEY(" + idname + "))"
|
||||||
;
|
;
|
||||||
|
|
||||||
db.runAsync(sql).then(function () { resolve(DB); }, reject);
|
db.runAsync(sql).then(function () {
|
||||||
});
|
sqlite3GetColumns(tablename, opts.indices, function (err) {
|
||||||
}
|
if (err) {
|
||||||
|
console.error('[Error] dbwrap get columns');
|
||||||
|
console.error(err.stack);
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Array.isArray(dir)) {
|
resolve(DB);
|
||||||
arr = false;
|
});
|
||||||
dir = [dir];
|
}, reject);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
dir.forEach(function (opts) {
|
dir.forEach(function (opts) {
|
||||||
|
@ -430,11 +540,7 @@ function wrap(db, dir) {
|
||||||
|
|
||||||
dbsMap.sql = db;
|
dbsMap.sql = db;
|
||||||
|
|
||||||
return PromiseA.all(promises).then(function (dbs) {
|
return PromiseA.all(promises).then(function (/*dbs*/) {
|
||||||
if (!arr) {
|
|
||||||
return dbs[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbsMap;
|
return dbsMap;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
var PromiseA = require('bluebird').Promise;
|
var PromiseA = require('bluebird').Promise;
|
||||||
|
|
||||||
function testDb(DB) {
|
function testDb(DB) {
|
||||||
|
DB = DB.Data;
|
||||||
return PromiseA.resolve(DB).then(function (DB) {
|
return PromiseA.resolve(DB).then(function (DB) {
|
||||||
var data = { secret: 'super secret', verifiedAt: 1437207288791 };
|
var data = { secret: 'super secret', verifiedAt: 1437207288791 };
|
||||||
//return DB.set('aj@the.dj', data)
|
//return DB.set('aj@the.dj', data)
|
||||||
|
@ -43,7 +44,7 @@ function testDb(DB) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function run(/*isMaster*/) {
|
function run(/*isMaster*/) {
|
||||||
require('./setup').run().then(testDb);
|
require('./setup').run([{ modelname: 'Data', indices: ['data'] }]).then(testDb);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
function run(opts) {
|
function run(opts) {
|
||||||
var config = require('../config.test.js');
|
var config = require('../config.test.js');
|
||||||
var sqlite3 = require('sqlite3-cluster');
|
|
||||||
var wrap = require('../lib/dbwrap');
|
var wrap = require('../lib/dbwrap');
|
||||||
|
var sqlite3 = require('sqlite3');
|
||||||
|
|
||||||
|
var db = new sqlite3.Database(config.filename);
|
||||||
|
return wrap.wrap(db, opts);
|
||||||
|
|
||||||
|
/*
|
||||||
|
var sqlite3 = require('sqlite3-cluster');
|
||||||
var promise = sqlite3.create({
|
var promise = sqlite3.create({
|
||||||
standalone: true
|
standalone: true
|
||||||
, bits: 128
|
, bits: 128
|
||||||
|
@ -13,8 +20,9 @@ function run(opts) {
|
||||||
return promise.then(function (db) {
|
return promise.then(function (db) {
|
||||||
return db.init({ bits: 128, key: config.key });
|
return db.init({ bits: 128, key: config.key });
|
||||||
}).then(function (db) {
|
}).then(function (db) {
|
||||||
return wrap.wrap(db, Array.isArray(opts) && opts || { idname: 'uuid', tablename: opts && opts.tablename || 'authn' });
|
return wrap.wrap(db, opts);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
|
|
Loading…
Reference in New Issue