From 13460f74b4fb3ebedcd8d1c21d8a21c0a19fefb2 Mon Sep 17 00:00:00 2001 From: simov Date: Tue, 9 Sep 2014 21:47:46 +0300 Subject: [PATCH] Query builder accepts xsql instance --- app.js | 6 +-- lib/data/list.js | 2 +- lib/data/mtm.js | 2 +- lib/data/otm.js | 2 +- lib/data/pagination.js | 2 +- lib/data/tbl.js | 2 +- lib/db/database.js | 4 +- lib/db/schema.js | 6 +-- lib/db/update.js | 2 +- lib/index.js | 5 --- lib/qb/index.js | 13 ++++--- lib/qb/lst.js | 33 ++++++++++------ lib/qb/mtm.js | 17 ++++++--- lib/qb/otm.js | 13 +++++-- lib/qb/partials.js | 87 ++++++++++++++++++++++++++++++++++++++---- lib/qb/tbl.js | 19 ++++++--- lib/sql/query.js | 60 ----------------------------- routes/listview.js | 2 +- test/db/client.js | 21 +++++++--- test/editview/data.js | 24 +++++------- 20 files changed, 184 insertions(+), 138 deletions(-) delete mode 100644 lib/index.js delete mode 100644 lib/sql/query.js diff --git a/app.js b/app.js index 8e3ee46..58f673a 100644 --- a/app.js +++ b/app.js @@ -24,7 +24,7 @@ var db = require('./lib/db/database'), routes = require('./lib/app/routes'); var Xsql = require('xsql'), - instance = require('./lib'); + qb = require('./lib/qb'); // creates project's config files @@ -46,8 +46,8 @@ function initDatabase (args, cb) { db.connect(args.config, function (err) { if (err) return cb(err); - instance.db = db; - instance.x = new Xsql({dialect:db.client.name, schema:db.client.config.schema}); + var x = new Xsql({dialect:db.client.name, schema:db.client.config.schema}); + qb(x); db.empty(db.client.config.schema, function (err, empty) { if (err) return cb(err); diff --git a/lib/data/list.js b/lib/data/list.js index 8169af0..70223e4 100644 --- a/lib/data/list.js +++ b/lib/data/list.js @@ -1,5 +1,5 @@ -var qb = require('../qb'), +var qb = require('../qb')(), format = require('../format'); diff --git a/lib/data/mtm.js b/lib/data/mtm.js index b828777..f5458c8 100644 --- a/lib/data/mtm.js +++ b/lib/data/mtm.js @@ -1,6 +1,6 @@ var async = require('async'); -var qb = require('../qb'); +var qb = require('../qb')(); // modifies `rows.columns` with manyToMany columns on select diff --git a/lib/data/otm.js b/lib/data/otm.js index 400fb2d..35ab336 100644 --- a/lib/data/otm.js +++ b/lib/data/otm.js @@ -1,6 +1,6 @@ var async = require('async'); -var qb = require('../qb'); +var qb = require('../qb')(); // modifies `args.config.columns` with `value` diff --git a/lib/data/pagination.js b/lib/data/pagination.js index 1281724..95598a5 100644 --- a/lib/data/pagination.js +++ b/lib/data/pagination.js @@ -1,6 +1,6 @@ var pagination = require('sr-pagination'); -var qb = require('../qb') +var qb = require('../qb')(); exports.get = function (args, done) { diff --git a/lib/data/tbl.js b/lib/data/tbl.js index 39732a9..4c99ebd 100644 --- a/lib/data/tbl.js +++ b/lib/data/tbl.js @@ -1,5 +1,5 @@ -var qb = require('../qb'); +var qb = require('../qb')(); // get table records diff --git a/lib/db/database.js b/lib/db/database.js index bd97d6c..b703fe4 100644 --- a/lib/db/database.js +++ b/lib/db/database.js @@ -1,6 +1,6 @@ var Client = require('./client'), - query = require('../sql/query'); + qb = require('../qb')(); function Database () { @@ -34,7 +34,7 @@ Database.prototype.connect = function (config, cb) { Database.prototype.empty = function (schema, cb) { if (!this.client.connection) return cb(new Error('Missing database connection!')); - var sql = query.replace('show-tables', schema); + var sql = qb.partials.tables(schema); this.client.query(sql, function (err, rows) { if (err) return cb(err); if (rows.length) return cb(null, false); diff --git a/lib/db/schema.js b/lib/db/schema.js index b92cc3b..83d3138 100644 --- a/lib/db/schema.js +++ b/lib/db/schema.js @@ -1,5 +1,5 @@ -var query = require('../sql/query'); +var qb = require('../qb')(); /** @@ -24,7 +24,7 @@ function Schema (db) { Schema.prototype.getTables = function (cb) { var schema = this.db.client.config.schema, - sql = query.replace('show-tables', schema); + sql = qb.partials.tables(schema); this.db.client.query(sql, function (err, rows) { if (err) return cb(err); var tables = []; @@ -48,7 +48,7 @@ Schema.prototype.getTables = function (cb) { Schema.prototype.getColumns = function (table, cb) { var schema = this.db.client.config.schema, - sql = query.replace('show-columns', table, schema); + sql = qb.partials.columns(table, schema); this.db.client.query(sql, function (err, columns) { if (err) return cb(err); cb(null, this.db.client.getColumnsInfo(columns)); diff --git a/lib/db/update.js b/lib/db/update.js index 49cbba7..f3d17f7 100644 --- a/lib/db/update.js +++ b/lib/db/update.js @@ -1,6 +1,6 @@ var async = require('async'); -var qb = require('../qb'); +var qb = require('../qb')(); exports.update = function (args, done) { diff --git a/lib/index.js b/lib/index.js deleted file mode 100644 index f608051..0000000 --- a/lib/index.js +++ /dev/null @@ -1,5 +0,0 @@ - -exports = module.exports = { - db: null, - x: null -} diff --git a/lib/qb/index.js b/lib/qb/index.js index 982c7fe..b12f75c 100644 --- a/lib/qb/index.js +++ b/lib/qb/index.js @@ -1,7 +1,10 @@ -exports = module.exports = { - lst: require('./lst'), - tbl: require('./tbl'), - otm: require('./otm'), - mtm: require('./mtm') +exports = module.exports = function (x) { + return { + lst: require('./lst')(x), + tbl: require('./tbl')(x), + otm: require('./otm')(x), + mtm: require('./mtm')(x), + partials: require('./partials')(x) + }; } diff --git a/lib/qb/lst.js b/lib/qb/lst.js index 052c9f7..f160c44 100644 --- a/lib/qb/lst.js +++ b/lib/qb/lst.js @@ -1,9 +1,9 @@ -var x = require('../').x, - z = require('./partials'); +var x = null, + z = require('./partials')(); -exports.join = function (table, column, index) { +function join (table, column, index) { if (column.oneToMany) { var ref = column.oneToMany, alias = {alias: ref.table+index}; @@ -33,7 +33,7 @@ exports.join = function (table, column, index) { } -exports.select = function (args) { +function select (args) { var view = args.config, table = view.table, columns = view.columns; @@ -44,7 +44,7 @@ exports.select = function (args) { if (!columns[i].listview.show) continue; if (columns[i].oneToMany || columns[i].manyToMany) { - var result = this.join(table, columns[i], i); + var result = join(table, columns[i], i); joins = joins.concat(result.joins); names.push(result.select); } @@ -54,7 +54,7 @@ exports.select = function (args) { } names.unshift(x.as(z.concat(table.pk,table.name,z.schema(table),','),x.name('__pk'))); - var where = this.statement(table, columns, args.filter, joins); + var where = statement(table, columns, args.filter, joins); // always group by pk inside the listview! var group = (function groupby () { @@ -100,7 +100,7 @@ exports.select = function (args) { } } -exports.create = function (args) { +function create (args) { var s = args.statements; var str = [ @@ -112,7 +112,7 @@ exports.create = function (args) { args.query = str; } -exports.statement = function (table, columns, filter, joins) { +function statement (table, columns, filter, joins) { var statements = []; for (var i=0; i < columns.length; i++) { var column = columns[i], @@ -125,7 +125,7 @@ exports.statement = function (table, columns, filter, joins) { } else if (column.manyToMany) { if (!column.listview.show) { - var result = this.join(table, columns[i], i); + var result = join(table, columns[i], i); joins.push(result.joins[0]); joins.push(result.joins[1]); } @@ -134,7 +134,7 @@ exports.statement = function (table, columns, filter, joins) { statements.push(z.in(ref.pk, value, alias)); } else { - var expr = this.expression(table, column.name, column.control, value); + var expr = expression(table, column.name, column.control, value); if (!expr) continue; statements.push(expr); } @@ -145,7 +145,7 @@ exports.statement = function (table, columns, filter, joins) { : ''; } -exports.expression = function (table, column, control, value) { +function expression (table, column, control, value) { var name = x.name(column,table.name,z.schema(table)); if (control.select && !!control.options) { @@ -177,7 +177,7 @@ exports.expression = function (table, column, control, value) { } } -exports.pagination = function (args) { +function pagination (args) { var table = args.config.table, s = args.statements; @@ -194,3 +194,12 @@ exports.pagination = function (args) { args.log && console.log('pgr'.cyan, str); return str; } + +exports = module.exports = function (instance) { + if (instance) x = instance; + return { + join:join, select:select, create:create, + statement:statement, expression:expression, + pagination:pagination + } +} diff --git a/lib/qb/mtm.js b/lib/qb/mtm.js index 2344441..c399ab6 100644 --- a/lib/qb/mtm.js +++ b/lib/qb/mtm.js @@ -1,9 +1,9 @@ -var x = require('../').x, - z = require('./partials'); +var x = null, + z = require('./partials')(); -exports.select = function (args, column, pk) { +function select (args, column, pk) { var link = column.manyToMany.link; var concat = z.concat(link.childPk, link.table, z.schema(link),','); @@ -19,7 +19,7 @@ exports.select = function (args, column, pk) { return str; } -exports.insert = function (args, ids, link, record) { +function insert (args, ids, link, record) { var parentPk = link.parentPk instanceof Array ? link.parentPk : [link.parentPk], childPk = link.childPk instanceof Array ? link.childPk : [link.childPk]; @@ -43,7 +43,7 @@ exports.insert = function (args, ids, link, record) { return str; } -exports.remove = function (args, ids, link, record) { +function remove (args, ids, link, record) { var str = [ x.delete(x.name(link.table,z.schema(link))), @@ -55,3 +55,10 @@ exports.remove = function (args, ids, link, record) { args.log && console.log('mtm'.red, str); return str; } + +exports = module.exports = function (instance) { + if (instance) x = instance; + return { + select:select, insert:insert, remove:remove + } +} diff --git a/lib/qb/otm.js b/lib/qb/otm.js index f96c9c1..1cacaaa 100644 --- a/lib/qb/otm.js +++ b/lib/qb/otm.js @@ -1,9 +1,9 @@ -var x = require('../').x, - z = require('./partials'); +var x = null, + z = require('./partials')(); -exports.select = function (args, ref) { +function select (args, ref) { var concat = z.concat(ref.columns,ref.table,undefined,' '); var pk = x.as(z.concat(ref.pk,ref.table,z.schema(ref),','),x.name('__pk')), @@ -18,3 +18,10 @@ exports.select = function (args, ref) { args.log && console.log('otm'.grey, str); return str; } + +exports = module.exports = function (instance) { + if (instance) x = instance; + return { + select:select + } +} diff --git a/lib/qb/partials.js b/lib/qb/partials.js index 7aabfb0..77733f6 100644 --- a/lib/qb/partials.js +++ b/lib/qb/partials.js @@ -1,13 +1,13 @@ -var x = require('../').x; +var x = null; -exports.schema = function (table) { +function schema (table) { if (x.dialect != 'pg') return; return table.schema||x._schema; } -exports.concat = function (columns, table, schema, sep) { +function concat (columns, table, schema, sep) { if (!(columns instanceof Array)) return x.name(columns,table,schema); @@ -29,14 +29,14 @@ exports.concat = function (columns, table, schema, sep) { : columns.join("||'"+sep+"'||"); } -exports.group = function (columns) { +function group (columns) { return (/mysql|sqlite/.test(x.dialect)) ? x.func('group_concat',['distinct',columns],' ') // pg : x.func('string_agg',['distinct',[columns,x.wrap(',')].join()],' ') } -exports.join = function (table, fk, ref, pk, alias) { +function join (table, fk, ref, pk, alias) { var tbl = table.name||table.table, tsch = this.schema(table), rsch = this.schema(ref), @@ -62,7 +62,7 @@ exports.join = function (table, fk, ref, pk, alias) { ); } -exports.eq = function (table, column, value) { +function eq (table, column, value) { var columns = column instanceof Array ? column : [column]; var values = @@ -96,7 +96,7 @@ function zip (columns, values) { } return result; } -exports.in = function (column, value, alias) { +function _in (column, value, alias) { var columns = column instanceof Array ? column : [column], values = value instanceof Array ? value : [value]; @@ -112,3 +112,76 @@ exports.in = function (column, value, alias) { return x.and(result); } + +function tables (db) { + if (x.dialect == 'mysql') { + return [ + 'show tables in', + x.name(db), + ';' + ].join(' '); + } + else if (x.dialect == 'sqlite') { + return [ + x.select('*'), + x.from('sqlite_master'), + x.where(x.eq('type',x.wrap('table'))), + ';' + ].join(' '); + } + else if (x.dialect == 'pg') { + return [ + x.select('table_name'), + x.from('information_schema.tables'), + x.where(x.eq('table_schema',x.wrap(db))), + ';' + ].join(' '); + } +} + +function columns (table, schema) { + if (x.dialect == 'mysql') { + return [ + 'show columns in', + x.name(table), + 'in', + x.name(schema), + ';' + ].join(' '); + } + else if (x.dialect == 'sqlite') { + return [ + 'pragma', + x.func('table_info', x.wrap(table)), + ';' + ].join(' '); + } + else if (x.dialect == 'pg') { + return 'SELECT cs.column_name AS "Field", cs.data_type AS "Type", '+ + 'cs.is_nullable AS "Null", tc.constraint_type AS "Key", '+ + 'cs.column_default AS "Default", '+ + 'cs.numeric_precision, cs.numeric_precision_radix, cs.numeric_scale, '+ + 'cs.character_maximum_length '+ + 'FROM "information_schema"."columns" cs '+ + 'LEFT JOIN "information_schema"."key_column_usage" kc '+ + ' ON cs.column_name = kc.column_name '+ + ' AND cs.table_schema = kc.table_schema '+ + ' AND cs.table_name = kc.table_name '+ + 'LEFT JOIN "information_schema"."table_constraints" tc '+ + ' ON kc.constraint_name = tc.constraint_name '+ + ' AND kc.table_schema = tc.table_schema '+ + ' AND kc.table_name = tc.table_name '+ + 'WHERE '+ + ' cs.table_name = \''+table+'\' '+ + ' AND cs.table_schema = \''+schema+'\' ;'; + } +} + +exports = module.exports = function (instance) { + if (instance) x = instance; + return { + schema:schema, concat:concat, group:group, + join:join, eq:eq, in:_in, + tables:tables, columns:columns + } +} diff --git a/lib/qb/tbl.js b/lib/qb/tbl.js index ee2ff20..f1fa579 100644 --- a/lib/qb/tbl.js +++ b/lib/qb/tbl.js @@ -1,9 +1,9 @@ -var x = require('../').x, - z = require('./partials'); +var x = null, + z = require('./partials')(); -exports.select = function (args) { +function select (args) { var table = args.config.table, columns = args.config.columns; @@ -34,7 +34,7 @@ exports.select = function (args) { return str; } -exports.insert = function (args, settings, record) { +function insert (args, settings, record) { var data = _kvp(args.name, record.columns, settings.columns); var result = [ @@ -57,7 +57,7 @@ exports.insert = function (args, settings, record) { return str; } -exports.update = function (args, settings, record) { +function update (args, settings, record) { var data = _kvp(args.name, record.columns, settings.columns); var str = [ @@ -74,7 +74,7 @@ exports.update = function (args, settings, record) { return str; } -exports.remove = function (args, settings, record) { +function remove (args, settings, record) { var pk = settings.table.pk; var str = [ @@ -135,3 +135,10 @@ function _escape (value, type) { } } +exports = module.exports = function (instance) { + if (instance) x = instance; + return { + select:select, insert:insert, update:update, + remove:remove + } +} diff --git a/lib/sql/query.js b/lib/sql/query.js deleted file mode 100644 index c58fcd0..0000000 --- a/lib/sql/query.js +++ /dev/null @@ -1,60 +0,0 @@ - -var instance = require('../'), - x = null; - - -exports.sql = function (name) { - switch (name) { - - case 'show-tables': - - return x.dialect == 'mysql' - ? "SHOW TABLES IN `{0}` ;" - : (x.dialect == 'pg' - ? "SELECT table_name FROM information_schema.tables WHERE table_schema = '{0}' ;" - // sqlite - : "SELECT * FROM sqlite_master WHERE type = 'table' ;" - ); - - case 'show-columns': - - return x.dialect == 'mysql' - ? "SHOW COLUMNS IN `{0}` IN `{1}` ;" - : (x.dialect == 'pg' - ? 'SELECT cs.column_name AS "Field", cs.data_type AS "Type", '+ - 'cs.is_nullable AS "Null", tc.constraint_type AS "Key", '+ - 'cs.column_default AS "Default", '+ - 'cs.numeric_precision, cs.numeric_precision_radix, cs.numeric_scale, '+ - 'cs.character_maximum_length '+ - 'FROM "information_schema"."columns" cs '+ - 'LEFT JOIN "information_schema"."key_column_usage" kc '+ - ' ON cs.column_name = kc.column_name '+ - ' AND cs.table_schema = kc.table_schema '+ - ' AND cs.table_name = kc.table_name '+ - 'LEFT JOIN "information_schema"."table_constraints" tc '+ - ' ON kc.constraint_name = tc.constraint_name '+ - ' AND kc.table_schema = tc.table_schema '+ - ' AND kc.table_name = tc.table_name '+ - 'WHERE '+ - ' cs.table_name = \'{0}\' '+ - ' AND cs.table_schema = \'{1}\' ;' - // sqlite - : "PRAGMA table_info('{0}') ;" - ); - } -} - -exports.replace = function () { - if (!arguments.length) return null; - - x = instance.x; - - var sql = this.sql(arguments[0]); - if (arguments.length > 1) { - [].splice.call(arguments, 0, 1); - for (var i=0; i < arguments.length; i++) { - sql = sql.replace('{'+i+'}', arguments[i]); - } - } - return sql; -} diff --git a/routes/listview.js b/routes/listview.js index 3b870c5..f03fe58 100644 --- a/routes/listview.js +++ b/routes/listview.js @@ -1,6 +1,6 @@ var dcopy = require('deep-copy'); -var qb = require('../lib/qb'), +var qb = require('../lib/qb')(), data = require('../lib/data'), format = require('../lib/format'); var filter = require('../lib/listview/filter'); diff --git a/test/db/client.js b/test/db/client.js index 2708a9c..6aca40d 100644 --- a/test/db/client.js +++ b/test/db/client.js @@ -1,8 +1,9 @@ var path = require('path'), - should = require('should'); + should = require('should'), + Xsql = require('xsql'); var Client = require('../../lib/db/client'), - query = require('../../lib/sql/query'); + qb = require('../../lib/qb'); describe.skip('client (db)', function () { @@ -136,7 +137,9 @@ describe.skip('client (db)', function () { var client = new Client(config); client.connect(config.mysql, function (err) { if (err) return done(err); - var sql = query.replace('show-columns', 'controls', 'express-admin-examples'); + var x = new Xsql({dialect:client.name, schema:client.config.schema}); + qb(x); + var sql = qb.partials.columns('controls', 'express-admin-examples'); client.query(sql, function (err, rows) { if (err) return done(err); @@ -171,7 +174,9 @@ describe.skip('client (db)', function () { var client = new Client(config); client.connect(config.pg, function (err) { if (err) return done(err); - var sql = query.replace('show-columns', 'controls', 'public'); + var x = new Xsql({dialect:client.name, schema:client.config.schema}); + qb(x); + var sql = qb.partials.columns('controls', 'public'); client.query(sql, function (err, rows) { if (err) return done(err); @@ -205,7 +210,9 @@ describe.skip('client (db)', function () { var client = new Client(config); client.connect(config.sqlite, function (err) { if (err) return done(err); - var sql = query.replace('show-columns', 'controls', ''); + var x = new Xsql({dialect:client.name, schema:client.config.schema}); + qb(x); + var sql = qb.partials.columns('controls', ''); client.query(sql, function (err, rows) { if (err) return done(err); @@ -239,7 +246,9 @@ describe.skip('client (db)', function () { var client = new Client(config); client.connect(config.pg, function (err) { if (err) return done(err); - var sql = query.replace('show-columns', 'controls', 'public'); + var x = new Xsql({dialect:client.name, schema:client.config.schema}); + qb(x); + var sql = qb.partials.columns('controls', 'public'); client.query(sql, function (err, rows) { if (err) return done(err); diff --git a/test/editview/data.js b/test/editview/data.js index 7ae2780..a1fa4fe 100644 --- a/test/editview/data.js +++ b/test/editview/data.js @@ -1,9 +1,11 @@ -var should = require('should'); -var db = require('../../lib/db/database'); -var Xsql = require('xsql'), - instance = require('../../lib'); -var data, editview, qb; +var should = require('should'), + Xsql = require('xsql'); +var db = require('../../lib/db/database'), + data = require('../../lib/data'), + editview = require('../../lib/editview/index'), + qb = require('../../lib/qb'); + describe('data (editview)', function () { @@ -17,15 +19,9 @@ describe('data (editview)', function () { }; db.connect(options, function (err) { if (err) return done(err); - instance.db = db; - instance.x = new Xsql({dialect:db.client.name, schema:db.client.config.schema}); - - setTimeout(function () { - data = require('../../lib/data'); - editview = require('../../lib/editview/index'); - qb = require('../../lib/qb'); - done(); - }, 100); + var x = new Xsql({dialect:db.client.name, schema:db.client.config.schema}); + qb = qb(x); + done(); }); });