auto-grow indices
This commit is contained in:
		
							parent
							
								
									8f0680826a
								
							
						
					
					
						commit
						65fe453ac6
					
				
							
								
								
									
										158
									
								
								lib/dbwrap.js
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								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,19 +508,25 @@ 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) {
 | 
				
			||||||
    promises.push(createTable(opts).then(function (dbw) {
 | 
					    promises.push(createTable(opts).then(function (dbw) {
 | 
				
			||||||
      var modelname = opts.modelname;
 | 
					      var modelname = opts.modelname; 
 | 
				
			||||||
      
 | 
					
 | 
				
			||||||
      if (!modelname) {
 | 
					      if (!modelname) {
 | 
				
			||||||
        modelname = (opts.tablename || 'data');
 | 
					        modelname = (opts.tablename || 'data');
 | 
				
			||||||
        modelname = upperCamelCase(modelname);
 | 
					        modelname = upperCamelCase(modelname);
 | 
				
			||||||
@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user