diff --git a/dist/js-data-sql.js b/dist/js-data-sql.js index 6e69428..257543f 100644 --- a/dist/js-data-sql.js +++ b/dist/js-data-sql.js @@ -53,10 +53,10 @@ module.exports = function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - var knex = __webpack_require__(2); - var JSData = __webpack_require__(3); - var map = __webpack_require__(4); - var underscore = __webpack_require__(1); + var knex = __webpack_require__(1); + var JSData = __webpack_require__(2); + var map = __webpack_require__(3); + var underscore = __webpack_require__(4); var unique = __webpack_require__(5); var toString = __webpack_require__(6); var DSUtils = JSData.DSUtils; @@ -67,159 +67,6 @@ module.exports = return resourceConfig.table || underscore(resourceConfig.name); } - function filterQuery(resourceConfig, params, options) { - var table = getTable(resourceConfig); - var query = options && options.transaction || this.query; - query = query.select(table + '.*').from(table); - params = params || {}; - params.where = params.where || {}; - params.orderBy = params.orderBy || params.sort; - params.skip = params.skip || params.offset; - - var joinedTables = []; - - DSUtils.forEach(DSUtils.keys(params), function (k) { - var v = params[k]; - if (!DSUtils.contains(reserved, k)) { - if (DSUtils.isObject(v)) { - params.where[k] = v; - } else { - params.where[k] = { - '==': v - }; - } - delete params[k]; - } - }); - - if (!DSUtils.isEmpty(params.where)) { - DSUtils.forOwn(params.where, function (criteria, field) { - if (!DSUtils.isObject(criteria)) { - params.where[field] = { - '==': criteria - }; - } - - DSUtils.forOwn(criteria, function (v, op) { - if (DSUtils.contains(field, '.')) { - (function () { - var parts = field.split('.'); - var localResourceConfig = resourceConfig; - - var relationPath = []; - - var _loop = function () { - var relationName = parts.shift(); - var relationResourceConfig = resourceConfig.getResource(relationName); - relationPath.push(relationName); - - if (!joinedTables.some(function (t) { - return t === relationPath.join('.'); - })) { - var _localResourceConfig$relationList$filter = localResourceConfig.relationList.filter(function (r) { - return r.relation === relationName; - }); - - var _localResourceConfig$relationList$filter2 = _slicedToArray(_localResourceConfig$relationList$filter, 1); - - var relation = _localResourceConfig$relationList$filter2[0]; - - if (relation) { - var _table = getTable(localResourceConfig); - var localId = _table + '.' + relation.localKey; - - var relationTable = getTable(relationResourceConfig); - var foreignId = relationTable + '.' + relationResourceConfig.idAttribute; - - query = query.join(relationTable, localId, foreignId); - joinedTables.push(relationPath.join('.')); - } else { - // local column - } - } - localResourceConfig = relationResourceConfig; - }; - - while (parts.length >= 2) { - _loop(); - } - - field = getTable(localResourceConfig) + '.' + parts[0]; - })(); - } - - if (op === '==' || op === '===') { - query = query.where(field, v); - } else if (op === '!=' || op === '!==') { - query = query.where(field, '!=', v); - } else if (op === '>') { - query = query.where(field, '>', v); - } else if (op === '>=') { - query = query.where(field, '>=', v); - } else if (op === '<') { - query = query.where(field, '<', v); - } else if (op === '<=') { - query = query.where(field, '<=', v); - // } else if (op === 'isectEmpty') { - // subQuery = subQuery ? subQuery.and(row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0) - // } else if (op === 'isectNotEmpty') { - // subQuery = subQuery ? subQuery.and(row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0) - } else if (op === 'in') { - query = query.where(field, 'in', v); - } else if (op === 'notIn') { - query = query.whereNotIn(field, v); - } else if (op === 'like') { - query = query.where(field, 'like', v); - } else if (op === '|==' || op === '|===') { - query = query.orWhere(field, v); - } else if (op === '|!=' || op === '|!==') { - query = query.orWhere(field, '!=', v); - } else if (op === '|>') { - query = query.orWhere(field, '>', v); - } else if (op === '|>=') { - query = query.orWhere(field, '>=', v); - } else if (op === '|<') { - query = query.orWhere(field, '<', v); - } else if (op === '|<=') { - query = query.orWhere(field, '<=', v); - // } else if (op === '|isectEmpty') { - // subQuery = subQuery ? subQuery.or(row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0) - // } else if (op === '|isectNotEmpty') { - // subQuery = subQuery ? subQuery.or(row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0) - } else if (op === '|in') { - query = query.orWhere(field, 'in', v); - } else if (op === '|notIn') { - query = query.orWhereNotIn(field, v); - } else { - throw new Error('Operator not found'); - } - }); - }); - } - - if (params.orderBy) { - if (DSUtils.isString(params.orderBy)) { - params.orderBy = [[params.orderBy, 'asc']]; - } - for (var i = 0; i < params.orderBy.length; i++) { - if (DSUtils.isString(params.orderBy[i])) { - params.orderBy[i] = [params.orderBy[i], 'asc']; - } - query = DSUtils.upperCase(params.orderBy[i][1]) === 'DESC' ? query.orderBy(params.orderBy[i][0], 'desc') : query.orderBy(params.orderBy[i][0], 'asc'); - } - } - - if (params.skip) { - query = query.offset(+params.offset); - } - - if (params.limit) { - query = query.limit(+params.limit); - } - - return query; - } - function loadWithRelations(items, resourceConfig, options) { var _this = this; @@ -399,7 +246,7 @@ module.exports = var items = null; options = options || {}; options['with'] = options['with'] || []; - return filterQuery.call(this, resourceConfig, params, options).then(function (_items) { + return this.filterQuery(resourceConfig, params, options).then(function (_items) { items = _items; return loadWithRelations.call(_this3, _items, resourceConfig, options); }).then(function () { @@ -440,17 +287,17 @@ module.exports = var _this6 = this; attrs = DSUtils.removeCircular(DSUtils.omit(attrs, resourceConfig.relationFields || [])); - return filterQuery.call(this, resourceConfig, params, options).then(function (items) { + return this.filterQuery(resourceConfig, params, options).then(function (items) { return map(items, function (item) { return item[resourceConfig.idAttribute]; }); }).then(function (ids) { - return filterQuery.call(_this6, resourceConfig, params, options).update(attrs).then(function () { + return _this6.filterQuery(resourceConfig, params, options).update(attrs).then(function () { var _params = { where: {} }; _params.where[resourceConfig.idAttribute] = { 'in': ids }; - return filterQuery.call(_this6, resourceConfig, _params, options); + return _this6.filterQuery(resourceConfig, _params, options); }); }); } @@ -465,10 +312,174 @@ module.exports = }, { key: 'destroyAll', value: function destroyAll(resourceConfig, params, options) { - return filterQuery.call(this, resourceConfig, params, options).del().then(function () { + return this.filterQuery(resourceConfig, params, options).del().then(function () { return undefined; }); } + }, { + key: 'filterQuery', + value: function filterQuery(resourceConfig, params, options) { + var table = getTable(resourceConfig); + var query = undefined; + + if (params instanceof Object.getPrototypeOf(this.query.client).QueryBuilder) { + query = params; + params = {}; + } else if (options && options.query) { + query = options.query || this.query; + } else { + query = options && options.transaction || this.query; + query = query.select(table + '.*').from(table); + } + + params = params || {}; + params.where = params.where || {}; + params.orderBy = params.orderBy || params.sort; + params.skip = params.skip || params.offset; + + var joinedTables = []; + + DSUtils.forEach(DSUtils.keys(params), function (k) { + var v = params[k]; + if (!DSUtils.contains(reserved, k)) { + if (DSUtils.isObject(v)) { + params.where[k] = v; + } else { + params.where[k] = { + '==': v + }; + } + delete params[k]; + } + }); + + if (!DSUtils.isEmpty(params.where)) { + DSUtils.forOwn(params.where, function (criteria, field) { + if (!DSUtils.isObject(criteria)) { + params.where[field] = { + '==': criteria + }; + } + + DSUtils.forOwn(criteria, function (v, op) { + if (DSUtils.contains(field, '.')) { + (function () { + var parts = field.split('.'); + var localResourceConfig = resourceConfig; + + var relationPath = []; + + var _loop = function () { + var relationName = parts.shift(); + var relationResourceConfig = resourceConfig.getResource(relationName); + relationPath.push(relationName); + + if (!joinedTables.some(function (t) { + return t === relationPath.join('.'); + })) { + var _localResourceConfig$relationList$filter = localResourceConfig.relationList.filter(function (r) { + return r.relation === relationName; + }); + + var _localResourceConfig$relationList$filter2 = _slicedToArray(_localResourceConfig$relationList$filter, 1); + + var relation = _localResourceConfig$relationList$filter2[0]; + + if (relation) { + var _table = getTable(localResourceConfig); + var localId = _table + '.' + relation.localKey; + + var relationTable = getTable(relationResourceConfig); + var foreignId = relationTable + '.' + relationResourceConfig.idAttribute; + + query = query.join(relationTable, localId, foreignId); + joinedTables.push(relationPath.join('.')); + } else { + // local column + } + } + localResourceConfig = relationResourceConfig; + }; + + while (parts.length >= 2) { + _loop(); + } + + field = getTable(localResourceConfig) + '.' + parts[0]; + })(); + } + + if (op === '==' || op === '===') { + query = query.where(field, v); + } else if (op === '!=' || op === '!==') { + query = query.where(field, '!=', v); + } else if (op === '>') { + query = query.where(field, '>', v); + } else if (op === '>=') { + query = query.where(field, '>=', v); + } else if (op === '<') { + query = query.where(field, '<', v); + } else if (op === '<=') { + query = query.where(field, '<=', v); + // } else if (op === 'isectEmpty') { + // subQuery = subQuery ? subQuery.and(row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0) + // } else if (op === 'isectNotEmpty') { + // subQuery = subQuery ? subQuery.and(row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0) + } else if (op === 'in') { + query = query.where(field, 'in', v); + } else if (op === 'notIn') { + query = query.whereNotIn(field, v); + } else if (op === 'like') { + query = query.where(field, 'like', v); + } else if (op === '|==' || op === '|===') { + query = query.orWhere(field, v); + } else if (op === '|!=' || op === '|!==') { + query = query.orWhere(field, '!=', v); + } else if (op === '|>') { + query = query.orWhere(field, '>', v); + } else if (op === '|>=') { + query = query.orWhere(field, '>=', v); + } else if (op === '|<') { + query = query.orWhere(field, '<', v); + } else if (op === '|<=') { + query = query.orWhere(field, '<=', v); + // } else if (op === '|isectEmpty') { + // subQuery = subQuery ? subQuery.or(row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0) + // } else if (op === '|isectNotEmpty') { + // subQuery = subQuery ? subQuery.or(row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0) + } else if (op === '|in') { + query = query.orWhere(field, 'in', v); + } else if (op === '|notIn') { + query = query.orWhereNotIn(field, v); + } else { + throw new Error('Operator not found'); + } + }); + }); + } + + if (params.orderBy) { + if (DSUtils.isString(params.orderBy)) { + params.orderBy = [[params.orderBy, 'asc']]; + } + for (var i = 0; i < params.orderBy.length; i++) { + if (DSUtils.isString(params.orderBy[i])) { + params.orderBy[i] = [params.orderBy[i], 'asc']; + } + query = DSUtils.upperCase(params.orderBy[i][1]) === 'DESC' ? query.orderBy(params.orderBy[i][0], 'desc') : query.orderBy(params.orderBy[i][0], 'asc'); + } + } + + if (params.skip) { + query = query.offset(+params.offset); + } + + if (params.limit) { + query = query.limit(+params.limit); + } + + return query; + } }]); return DSSqlAdapter; @@ -480,25 +491,25 @@ module.exports = /* 1 */ /***/ function(module, exports) { - module.exports = require("mout/string/underscore"); + module.exports = require("knex"); /***/ }, /* 2 */ /***/ function(module, exports) { - module.exports = require("knex"); + module.exports = require("js-data"); /***/ }, /* 3 */ /***/ function(module, exports) { - module.exports = require("js-data"); + module.exports = require("mout/array/map"); /***/ }, /* 4 */ /***/ function(module, exports) { - module.exports = require("mout/array/map"); + module.exports = require("mout/string/underscore"); /***/ }, /* 5 */ diff --git a/package.json b/package.json index 6083fed..a63c603 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "js-data-sql", "description": "Postgres/MySQL/MariaDB/SQLite3 adapter for js-data.", - "version": "0.11.4", + "version": "0.11.5", "homepage": "http://www.js-data.io/docs/dssqladapter", "repository": { "type": "git", diff --git a/src/index.js b/src/index.js index e0e7642..da03cc9 100644 --- a/src/index.js +++ b/src/index.js @@ -242,8 +242,18 @@ class DSSqlAdapter { filterQuery (resourceConfig, params, options) { let table = getTable(resourceConfig) - let query = options && options.transaction || this.query - query = query.select(`${table}.*`).from(table) + let query + + if (params instanceof Object.getPrototypeOf(this.query.client).QueryBuilder) { + query = params + params = {} + } else if (options && options.query) { + query = options.query || this.query + } else { + query = options && options.transaction || this.query + query = query.select(`${table}.*`).from(table) + } + params = params || {} params.where = params.where || {} params.orderBy = params.orderBy || params.sort diff --git a/test/filterQuery.spec.js b/test/filterQuery.spec.js new file mode 100644 index 0000000..2018313 --- /dev/null +++ b/test/filterQuery.spec.js @@ -0,0 +1,37 @@ +describe('DSSqlAdapter#filterQuery', function () { + + it('should use built-in query if no custom query provided', function* () { + var filterQuery = adapter.filterQuery(User); + assert.equal(filterQuery.toString(), 'select `user`.* from `user`') + }); + + it('should use custom query if passed as params (second parameter)', function* () { + var query = adapter.query.from('test'); + var filterQuery = adapter.filterQuery(User, query); + assert.equal(filterQuery.toString(), 'select * from `test`') + }); + + it('should use custom query if passed as options.query', function* () { + var query = adapter.query.from('test'); + var filterQuery = adapter.filterQuery(User, null, { query }); + assert.equal(filterQuery.toString(), 'select * from `test`') + }); + + it('should apply where from params to custom query', function* () { + var query = adapter.query.from('test'); + var filterQuery = adapter.filterQuery(User, { name: 'Sean' }, { query }); + assert.equal(filterQuery.toString(), 'select * from `test` where `name` = \'Sean\'') + }); + + it('should apply limit from params to custom query', function* () { + var query = adapter.query.from('test'); + var filterQuery = adapter.filterQuery(User, { limit: 2 }, { query }); + assert.equal(filterQuery.toString(), 'select * from `test` limit 2') + }); + + it('should apply order from params to custom query', function* () { + var query = adapter.query.from('test'); + var filterQuery = adapter.filterQuery(User, { orderBy: 'name' }, { query }); + assert.equal(filterQuery.toString(), 'select * from `test` order by `name` asc') + }); +}); diff --git a/test/find.spec.js b/test/find.spec.js index 30ca726..a961a06 100644 --- a/test/find.spec.js +++ b/test/find.spec.js @@ -1,4 +1,3 @@ -var Promise = require('bluebird'); describe('DSSqlAdapter#find', function () { it('should find a user in a Sql db', function* () { var user = yield adapter.create(User, {name: 'John'}); diff --git a/test/findAll.spec.js b/test/findAll.spec.js index 33f9fa7..550534f 100644 --- a/test/findAll.spec.js +++ b/test/findAll.spec.js @@ -1,4 +1,3 @@ -var Promise = require('bluebird'); describe('DSSqlAdapter#findAll', function () { it('should filter users', function* () { var users = yield adapter.findAll(User, { age: 30 });