diff --git a/.eslintrc b/.eslintrc index d230c37..bace5dd 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,39 +1,43 @@ { "env": { - "node": true, - "es6": true + "commonjs": true, + "es6": true, + "jest": true, + "node": true }, + "extends": ["eslint:recommended", "happiness"], "rules": { - "arrow-parens": [2, "as-needed"], - "no-console": [1], - "no-constant-condition": [1], - "no-extra-semi": [1], - "no-func-assign": [1], - "no-obj-calls": [2], - "no-unexpected-multiline" : [2], - "no-unneeded-ternary": [2], - "radix": [2], - "no-with": [2], - "no-eval": [2], - "no-unreachable": [1], - "no-irregular-whitespace": [1], - "no-new-wrappers": [2], - "no-new-func": [2], - "curly" : [2, "multi-line"], - "no-implied-eval": [2], - "no-invalid-this": [2], - "constructor-super": [2], - "no-dupe-args": [2], - "no-dupe-keys": [2], - "no-dupe-class-members": [2], - "no-this-before-super": [2], - "prefer-arrow-callback": [1], - "no-var": [2], - "valid-jsdoc": [1], - "strict": [2, "global"], - "callback-return": [1], - "object-shorthand": [1, "methods"], - "prefer-template": [1] + "arrow-parens": ["error", "as-needed"], + "callback-return": ["warn"], + "constructor-super": ["error"], + "curly" : ["error", "multi-line"], + "no-case-declarations": "off", + "no-console": ["warn"], + "no-constant-condition": ["warn"], + "no-dupe-args": ["error"], + "no-dupe-class-members": ["error"], + "no-dupe-keys": ["error"], + "no-eval": ["error"], + "no-extra-semi": ["warn"], + "no-func-assign": ["warn"], + "no-implied-eval": ["error"], + "no-invalid-this": ["error"], + "no-irregular-whitespace": ["warn"], + "no-new-func": ["error"], + "no-new-wrappers": ["error"], + "no-obj-calls": ["error"], + "no-this-before-super": ["error"], + "no-unexpected-multiline" : ["error"], + "no-unneeded-ternary": ["error"], + "no-unreachable": ["warn"], + "no-var": ["error"], + "no-with": ["error"], + "object-shorthand": ["warn", "methods"], + "prefer-arrow-callback": ["warn"], + "prefer-template": ["warn"], + "radix": ["error"], + "strict": ["error", "global"], + "valid-jsdoc": ["warn"] }, "parser": "babel-eslint" } diff --git a/lib/Driver.js b/lib/Driver.js index 19ac734..a348c09 100755 --- a/lib/Driver.js +++ b/lib/Driver.js @@ -1,3 +1,4 @@ +const array = require('locutus/php/array'); const Helpers = require('./Helpers'); /** @@ -64,36 +65,38 @@ const Driver = { * @return {String|Array} - Quoted identifier(s) */ quoteIdentifiers (str) { - let hiers, raw; - let pattern = new RegExp( + const pattern = new RegExp( `${Driver.identifierStartChar}(` + '([a-zA-Z0-9_]+)' + '(((.*?)))' + `)${Driver.identifierEndChar}`, 'ig'); - // Recurse for arrays of identifiiers + // Recurse for arrays of identifiers if (Array.isArray(str)) { return str.map(Driver.quoteIdentifiers); } + // cast to string so that you don't have undefined method errors with junk data + str = String(str); + // Handle commas if (str.includes(',')) { - let parts = str.split(',').map(Helpers.stringTrim); + const parts = str.split(',').map(Helpers.stringTrim); str = parts.map(Driver.quoteIdentifiers).join(','); } // Split identifiers by period - hiers = str.split('.').map(Driver._quote); - raw = hiers.join('.'); + const hierarchies = str.split('.').map(Driver._quote); + let raw = hierarchies.join('.'); // Fix functions if (raw.includes('(') && raw.includes(')')) { - let funcs = pattern.exec(raw); + const functionCalls = pattern.exec(raw); // Unquote the function - raw = raw.replace(funcs[0], funcs[1]); + raw = raw.replace(functionCalls[0], functionCalls[1]); // Quote the identifiers inside of the parens - let inParens = funcs[3].substring(1, funcs[3].length - 1); + const inParens = functionCalls[3].substring(1, functionCalls[3].length - 1); raw = raw.replace(inParens, Driver.quoteIdentifiers(inParens)); } @@ -126,7 +129,7 @@ const Driver = { * @return {String} - Query and data to insert */ insertBatch (table, data) { - const vals = []; + const values = []; const fields = Object.keys(data[0]); let sql = ''; @@ -134,7 +137,7 @@ const Driver = { // be parameterized data.forEach(obj => { Object.keys(obj).forEach(key => { - vals.push(obj[key]); + values.push(obj[key]); }); }); @@ -145,16 +148,79 @@ const Driver = { sql += `INSERT INTO ${table} (${Driver.quoteIdentifiers(fields).join(',')}) VALUES `; // Create placeholder groups - let params = Array(fields.length).fill('?'); - let paramString = `(${params.join(',')})`; - let paramList = Array(data.length).fill(paramString); + const params = Array(fields.length).fill('?'); + const paramString = `(${params.join(',')})`; + const paramList = Array(data.length).fill(paramString); sql += paramList.join(','); return { sql: sql, - values: vals + values: values }; + }, + + /** + * Creates a batch update sql statement + * + * @private + * @param {String} table + * @param {Array} data + * @param {String} updateKey + * @return {Array} array + */ + updateBatch (table, data, updateKey) { + let affectedRows = 0; + let insertData = []; + const fieldLines = []; + + let sql = `UPDATE ${Driver.quoteTable(table)} SET `; + + // get the keys of the current set of data, except the one used to + // set the update condition + const fields = data.reduce((previous, current) => { + affectedRows++; + const keys = Object.keys(current).filter(key => { + return key !== updateKey && !previous.includes(key); + }); + return previous.concat(keys); + }, []); + + // Create the CASE blocks for each data set + fields.forEach(field => { + let line = `${Driver.quoteIdentifiers(field)} = CASE\n`; + const cases = []; + data.forEach(currentCase => { + insertData.push(currentCase[updateKey]); + insertData.push(currentCase[field]); + + const newCase = `WHEN ${Driver.quoteIdentifiers(updateKey)} =? THEN ? `; + cases.push(newCase); + }); + + line += `${cases.join('\n')}\n`; + line += `ELSE ${Driver.quoteIdentifiers(field)} END`; + + fieldLines.push(line); + }); + + sql += `${fieldLines.join(',\n')}\n`; + + const whereValues = []; + data.forEach(entry => { + const insertValue = entry[updateKey]; + whereValues.push(insertValue); + insertData.push(insertValue); + }); + + // Create the placeholders for the WHERE IN clause + const placeholders = Array(whereValues.length); + placeholders.fill('?'); + + sql += `WHERE ${Driver.quoteIdentifiers(updateKey)} IN `; + sql += `( ${placeholders.join(',')} )`; + + return [sql, insertData, affectedRows]; } }; diff --git a/lib/Helpers.js b/lib/Helpers.js index 627babf..48edaa8 100755 --- a/lib/Helpers.js +++ b/lib/Helpers.js @@ -42,7 +42,7 @@ class Helpers { * @return {String} - Type of the object */ static type (o) { - let type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase(); + const type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase(); // handle NaN and Infinity if (type === 'number') { @@ -62,11 +62,10 @@ class Helpers { * Determine whether an object is scalar * * @param {mixed} obj - Object to test - * @return {bool} - Is object scalar + * @return {boolean} - Is object scalar */ static isScalar (obj) { - let scalar = ['string', 'number', 'boolean']; - return scalar.indexOf(Helpers.type(obj)) !== -1; + return ['string', 'number', 'boolean'].includes(Helpers.type(obj)); } /** @@ -77,7 +76,7 @@ class Helpers { * @return {Array} - The new array of plucked values */ static arrayPluck (arr, key) { - let output = []; + const output = []; // Empty case if (arr.length === 0) { @@ -119,20 +118,20 @@ class Helpers { } /** - * Make the first letter of the string uppercase + * Make the first constter of the string uppercase * * @param {String} str - The string to modify * @return {String} - The modified string */ static upperCaseFirst (str) { str += ''; - let first = str.charAt(0).toUpperCase(); + const first = str.charAt(0).toUpperCase(); return first + str.substr(1); } } // Define an 'is' method for each type -let types = [ +const types = [ 'Null', 'Undefined', 'Object', diff --git a/lib/NodeQuery.js b/lib/NodeQuery.js index 54086b0..71bb7de 100755 --- a/lib/NodeQuery.js +++ b/lib/NodeQuery.js @@ -50,17 +50,16 @@ class NodeQuery { this.instance = null; if (config !== undefined) { - let drivername = dbDriverMap.get(config.driver); + const driverName = dbDriverMap.get(config.driver); - if (!drivername) { + if (!driverName) { throw new Error(`Selected driver (${config.driver}) does not exist!`); } - const driver = require(`./drivers/${drivername}`); - const Adapter = require(`./adapters/${drivername}`); + const driver = require(`./drivers/${driverName}`); + const Adapter = require(`./adapters/${driverName}`); - let adapter = Adapter(config); - this.instance = new QueryBuilder(driver, adapter); + this.instance = new QueryBuilder(driver, Adapter(config)); } } diff --git a/lib/QueryBuilder.js b/lib/QueryBuilder.js index da3a8a6..3a56113 100755 --- a/lib/QueryBuilder.js +++ b/lib/QueryBuilder.js @@ -107,7 +107,7 @@ class QueryBuilder extends QueryBuilderBase { } }); - let safeArray = this.driver.quoteIdentifiers(fields); + const safeArray = this.driver.quoteIdentifiers(fields); // Join the strings back together safeArray.forEach((field, index) => { @@ -378,8 +378,8 @@ class QueryBuilder extends QueryBuilderBase { table = table.join(' '); // Parse out the join condition - let parsedCondition = this.parser.compileJoin(cond); - let condition = `${table} ON ${parsedCondition}`; + const parsedCondition = this.parser.compileJoin(cond); + const condition = `${table} ON ${parsedCondition}`; // Append the join condition to the query map this._appendMap(`\n${type.toUpperCase()} JOIN `, condition, 'join'); @@ -395,7 +395,7 @@ class QueryBuilder extends QueryBuilderBase { */ groupBy (field) { if (!Helpers.isScalar(field)) { - let newGroupArray = field.map(this.driver.quoteIdentifiers); + const newGroupArray = field.map(this.driver.quoteIdentifiers); this.state.groupArray = this.state.groupArray.concat(newGroupArray); } else { this.state.groupArray.push(this.driver.quoteIdentifiers(field)); @@ -421,7 +421,7 @@ class QueryBuilder extends QueryBuilderBase { this.state.orderArray[field] = type; - let orderClauses = []; + const orderClauses = []; // Flatten key/val pairs into an array of space-separated pairs Object.keys(this.state.orderArray).forEach(key => { @@ -454,7 +454,7 @@ class QueryBuilder extends QueryBuilderBase { * @return {QueryBuilder} - The Query Builder object, for chaining */ groupStart () { - let conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ' AND '; + const conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ' AND '; this._appendMap(conj, '(', 'groupStart'); return this; @@ -549,7 +549,7 @@ class QueryBuilder extends QueryBuilderBase { * @return {Promise} - Promise containing the result of the query */ insertBatch (table, data) { - let batch = this.driver.insertBatch(table, data); + const batch = this.driver.insertBatch(table, data); // Run the query return this.query(batch.sql, batch.values); @@ -571,6 +571,20 @@ class QueryBuilder extends QueryBuilderBase { return this._run('update', this.driver.quoteTable(table)); } + /** + * Creates a batch update sql statement + * + * @param {String} table - The table to update + * @param {Object} data - Batch insert data + * @param {String} updateKey - The field in the table to compare against for updating + * @return {Number} Number of rows updated + */ + updateBatch (table, data, updateKey) { + const [sql, insertData, affectedRows] = this.driver.updateBatch(table, data, updateKey); + this._run('', table, sql, insertData); + return affectedRows; + } + /** * Run the generated delete query * @@ -613,7 +627,7 @@ class QueryBuilder extends QueryBuilderBase { * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built * @return {String} - The compiled sql statement */ - getCompiledInsert (table, reset) { + getCompiledInsert (table, reset = true) { return this._getCompile('insert', this.driver.quoteTable(table), reset); } @@ -624,7 +638,7 @@ class QueryBuilder extends QueryBuilderBase { * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built * @return {String} - The compiled sql statement */ - getCompiledUpdate (table, reset) { + getCompiledUpdate (table, reset = true) { return this._getCompile('update', this.driver.quoteTable(table), reset); } @@ -635,7 +649,7 @@ class QueryBuilder extends QueryBuilderBase { * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built * @return {String} - The compiled sql statement */ - getCompiledDelete (table, reset) { + getCompiledDelete (table, reset = true) { return this._getCompile('delete', this.driver.quoteTable(table), reset); } } diff --git a/lib/QueryBuilderBase.js b/lib/QueryBuilderBase.js index c4e9d7f..9e23ab8 100644 --- a/lib/QueryBuilderBase.js +++ b/lib/QueryBuilderBase.js @@ -16,74 +16,6 @@ class QueryBuilderBase { this.state = new State(); } - /** - * Complete the sql building based on the type provided - * - * @private - * @param {String} type - Type of SQL query - * @param {String} table - The table to run the query on - * @return {String} - The compiled sql - */ - _compile (type, table) { - // Put together the basic query - let sql = this._compileType(type, table); - - // Set each subClause - ['queryMap', 'groupString', 'orderString', 'havingMap'].forEach(clause => { - let param = this.state[clause]; - - if (!Helpers.isScalar(param)) { - Object.keys(param).forEach(part => { - sql += param[part].conjunction + param[part].string; - }); - } else { - sql += param; - } - }); - - // Append the limit, if it exists - if (Helpers.isNumber(this.state.limit)) { - sql = this.driver.limit(sql, this.state.limit, this.state.offset); - } - - return sql; - } - - _compileType (type, table) { - let sql = ''; - - switch (type) { - case 'insert': - let params = Array(this.state.setArrayKeys.length).fill('?'); - - sql = `INSERT INTO ${table} (`; - sql += this.state.setArrayKeys.join(','); - sql += `) VALUES (${params.join(',')})`; - break; - - case 'update': - sql = `UPDATE ${table} SET ${this.state.setString}`; - break; - - case 'delete': - sql = `DELETE FROM ${table}`; - break; - - default: - sql = `SELECT * FROM ${this.state.fromString}`; - - // Set the select string - if (this.state.selectString.length > 0) { - // Replace the star with the selected fields - sql = sql.replace('*', this.state.selectString); - } - - break; - } - - return sql; - } - _like (field, val, pos, like, conj) { field = this.driver.quoteIdentifiers(field); @@ -147,7 +79,7 @@ class QueryBuilderBase { Object.keys(obj).forEach(k => { // If a single value for the return if (['key', 'value'].indexOf(valType) !== -1) { - let pushVal = (valType === 'key') ? k : obj[k]; + const pushVal = (valType === 'key') ? k : obj[k]; this.state[letName].push(pushVal); } else { this.state[letName][k] = obj[k]; @@ -166,8 +98,8 @@ class QueryBuilderBase { } _fixConjunction (conj) { - let lastItem = this.state.queryMap[this.state.queryMap.length - 1]; - let conjunctionList = Helpers.arrayPluck(this.state.queryMap, 'conjunction'); + const lastItem = this.state.queryMap[this.state.queryMap.length - 1]; + const conjunctionList = Helpers.arrayPluck(this.state.queryMap, 'conjunction'); if (this.state.queryMap.length === 0 || (!Helpers.regexInArray(conjunctionList, /^ ?WHERE/i))) { conj = ' WHERE '; @@ -189,7 +121,7 @@ class QueryBuilderBase { this.state = this.parser.parseWhere(this.driver, this.state); this.state.whereMap.forEach(clause => { - let conj = this._fixConjunction(defaultConj); + const conj = this._fixConjunction(defaultConj); this._appendMap(conj, clause, 'where'); }); @@ -198,7 +130,7 @@ class QueryBuilderBase { _whereNull (field, stmt, conj) { field = this.driver.quoteIdentifiers(field); - let item = `${field} ${stmt}`; + const item = `${field} ${stmt}`; this._appendMap(this._fixConjunction(conj), item, 'whereNull'); } @@ -225,7 +157,7 @@ class QueryBuilderBase { _whereIn (key, val, inClause, conj) { key = this.driver.quoteIdentifiers(key); - let params = Array(val.length); + const params = Array(val.length); params.fill('?'); val.forEach(value => { @@ -233,7 +165,7 @@ class QueryBuilderBase { }); conj = (this.state.queryMap.length > 0) ? ` ${conj} ` : ' WHERE '; - let str = `${key} ${inClause} (${params.join(',')}) `; + const str = `${key} ${inClause} (${params.join(',')}) `; this._appendMap(conj, str, 'whereIn'); } @@ -257,7 +189,7 @@ class QueryBuilderBase { _getCompile (type, table, reset) { reset = reset || false; - let sql = this._compile(type, table); + const sql = this._compile(type, table); if (reset) { this._resetState(); @@ -266,6 +198,74 @@ class QueryBuilderBase { return sql; } + /** + * Complete the sql building based on the type provided + * + * @private + * @param {String} type - Type of SQL query + * @param {String} table - The table to run the query on + * @return {String} - The compiled sql + */ + _compile (type, table) { + // Put together the basic query + let sql = this._compileType(type, table); + + // Set each subClause + ['queryMap', 'groupString', 'orderString', 'havingMap'].forEach(clause => { + const param = this.state[clause]; + + if (!Helpers.isScalar(param)) { + Object.keys(param).forEach(part => { + sql += param[part].conjunction + param[part].string; + }); + } else { + sql += param; + } + }); + + // Append the limit, if it exists + if (Helpers.isNumber(this.state.limit)) { + sql = this.driver.limit(sql, this.state.limit, this.state.offset); + } + + return sql; + } + + _compileType (type, table) { + let sql = ''; + + switch (type) { + case 'insert': + const params = Array(this.state.setArrayKeys.length).fill('?'); + + sql = `INSERT INTO ${table} (`; + sql += this.state.setArrayKeys.join(','); + sql += `) VALUES (${params.join(',')})`; + break; + + case 'update': + sql = `UPDATE ${table} SET ${this.state.setString}`; + break; + + case 'delete': + sql = `DELETE FROM ${table}`; + break; + + default: + sql = `SELECT * FROM ${this.state.fromString}`; + + // Set the select string + if (this.state.selectString.length > 0) { + // Replace the star with the selected fields + sql = sql.replace('*', this.state.selectString); + } + + break; + } + + return sql; + } + _resetState () { this.state = new State(); } diff --git a/lib/QueryParser.js b/lib/QueryParser.js index b59c044..ed70c27 100644 --- a/lib/QueryParser.js +++ b/lib/QueryParser.js @@ -54,7 +54,7 @@ class QueryParser { * @return {Array|null} - Filtered set of possible matches */ filterMatches (array) { - let output = []; + const output = []; // Return non-array matches if (Helpers.isNull(array)) { @@ -85,8 +85,8 @@ class QueryParser { * @return {Object} - Join condition components */ parseJoin (sql) { - let matches = {}; - let output = { + const matches = {}; + const output = { functions: [], identifiers: [], operators: [], @@ -117,7 +117,7 @@ class QueryParser { * @return {String} - The parsed/escaped join condition */ compileJoin (condition) { - let parts = this.parseJoin(condition); + const parts = this.parseJoin(condition); // Quote the identifiers parts.combined.forEach((part, i) => { @@ -137,11 +137,11 @@ class QueryParser { * @return {String} - The parsed/escaped where condition */ parseWhere (driver, state) { - let whereMap = state.whereMap; + const whereMap = state.whereMap; let whereValues = state.rawWhereValues; - let outputMap = []; - let outputValues = []; + const outputMap = []; + const outputValues = []; Object.keys(whereMap).forEach(key => { // Combine fields, operators, functions and values into a full clause @@ -158,16 +158,16 @@ class QueryParser { } // Separate the clause into separate pieces - let parts = this.parseJoin(fullClause); + const parts = this.parseJoin(fullClause); // Filter explicit literals from lists of matches if (whereValues.indexOf(whereMap[key]) !== -1) { - let value = whereMap[key]; - let identIndex = parts.identifiers.indexOf(value); - let litIndex = (Helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1; - let combIndex = parts.combined.indexOf(value); - let funcIndex = (Helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1; - let inOutputArray = outputValues.indexOf(value) !== -1; + const value = whereMap[key]; + const identIndex = parts.identifiers.indexOf(value); + const litIndex = (Helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1; + const combIndex = parts.combined.indexOf(value); + const funcIndex = (Helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1; + let inOutputArray = outputValues.includes(value); // Remove the identifier in question, // and add to the output values array @@ -201,8 +201,8 @@ class QueryParser { // Filter false positive identifiers parts.identifiers = parts.identifiers.filter(item => { - let isInCombinedMatches = parts.combined.indexOf(item) !== -1; - let isNotInBlackList = this.identifierBlacklist.indexOf(item.toLowerCase()) === -1; + const isInCombinedMatches = parts.combined.indexOf(item) !== -1; + const isNotInBlackList = this.identifierBlacklist.indexOf(item.toLowerCase()) === -1; return isInCombinedMatches && isNotInBlackList; }, this); @@ -210,7 +210,7 @@ class QueryParser { // Quote identifiers if (Helpers.isArray(parts.identifiers)) { parts.identifiers.forEach(ident => { - let index = parts.combined.indexOf(ident); + const index = parts.combined.indexOf(ident); if (index !== -1) { parts.combined[index] = driver.quoteIdentifiers(ident); } @@ -224,7 +224,7 @@ class QueryParser { // a where condition, if (Helpers.isArray(parts.literals)) { parts.literals.forEach(lit => { - let litIndex = parts.combined.indexOf(lit); + const litIndex = parts.combined.indexOf(lit); if (litIndex !== -1) { parts.combined[litIndex] = '?'; diff --git a/lib/adapters/MSSQLServer/index.js b/lib/adapters/MSSQLServer/index.js index 5c41b25..d3ab816 100644 --- a/lib/adapters/MSSQLServer/index.js +++ b/lib/adapters/MSSQLServer/index.js @@ -1,5 +1,3 @@ -'use strict'; - module.exports = config => { }; diff --git a/lib/adapters/Mysql/mysql2.js b/lib/adapters/Mysql/mysql2.js index b86d01e..d1d5e23 100644 --- a/lib/adapters/Mysql/mysql2.js +++ b/lib/adapters/Mysql/mysql2.js @@ -36,7 +36,7 @@ class Mysql extends Adapter { * Run the sql query as a prepared statement * * @param {String} sql - The sql with placeholders - * @param {Array|undefined} params - The values to insert into the query + * @param {Array} params - The values to insert into the query * @return {Promise} Result of query */ execute (sql, params) { diff --git a/lib/adapters/Pg/Pg.js b/lib/adapters/Pg/Pg.js index 4a9803b..7c0597c 100644 --- a/lib/adapters/Pg/Pg.js +++ b/lib/adapters/Pg/Pg.js @@ -7,28 +7,10 @@ const url = require('url'); class Pg extends Adapter { constructor (config) { let instance = null; - let connectionString = ''; - if (Helpers.isObject(config)) { - let host = config.host || 'localhost'; - let user = config.user || 'postgres'; - let password = `:${config.password}` || ''; - let port = config.port || 5432; - - let conn = { - protocol: 'postgres', - slashes: true, - host: `${host}:${port}`, - auth: `${user}${password}`, - pathname: config.database - }; - - connectionString = url.format(conn); - } else if (Helpers.isString(config)) { - connectionString = config; - } + let connectionString = Pg.formatConnectionString(config); if (connectionString !== '') { - let conn = new pg.Client(connectionString); + const conn = new pg.Client(connectionString); conn.connect(err => { if (err) { throw new Error(err); @@ -41,6 +23,37 @@ class Pg extends Adapter { super(instance); } + /** + * Convert the connection object to a connection string + * + * @param {Object} config - the configuration object + * @return {String} - the connection string + */ + static formatConnectionString (config) { + let connectionString = ''; + + if (Helpers.isObject(config)) { + const host = config.host || 'localhost'; + const user = config.user || 'postgres'; + const password = `:${config.password}` || ''; + const port = config.port || 5432; + + const conn = { + protocol: 'postgres', + slashes: true, + host: `${host}:${port}`, + auth: `${user}${password}`, + pathname: config.database + }; + + connectionString = url.format(conn); + } else if (Helpers.isString(config)) { + connectionString = config; + } + + return connectionString; + } + /** * Transform the adapter's result into a standard format * @@ -52,9 +65,9 @@ class Pg extends Adapter { return new Result(); } - let cols = []; + const cols = []; result.fields.forEach(field => { - cols = field.name; + cols.push(field.name); }); return new Result(result.rows, cols); diff --git a/lib/adapters/Pg/PgNative.js b/lib/adapters/Pg/PgNative.js deleted file mode 100644 index 906dbe0..0000000 --- a/lib/adapters/Pg/PgNative.js +++ /dev/null @@ -1,25 +0,0 @@ -const Pg = require('./Pg'); -const pg = require('pg').native; - -class PgNative extends Pg { - constructor (config) { - super(config); - let instance = null; - let connectionString = Pg._formatConnectionString(config); - - if (connectionString !== '') { - let conn = new pg.Client(connectionString); - conn.connect(err => { - if (err) { - throw new Error(err); - } - }); - - instance = Promise.resolve(conn); - } - - super.instance = instance; - } -} - -module.exports = PgNative; diff --git a/lib/adapters/Pg/index.js b/lib/adapters/Pg/index.js index a7d7d22..d021904 100644 --- a/lib/adapters/Pg/index.js +++ b/lib/adapters/Pg/index.js @@ -1,8 +1,2 @@ const Pg = require('./Pg'); -const PgNative = require('./PgNative'); - -module.exports = config => { - return (config.native) - ? new PgNative(config.connection) - : new Pg(config.connection); -}; +module.exports = config => new Pg(config.connection); diff --git a/lib/adapters/Sqlite/dblite.js b/lib/adapters/Sqlite/dblite.js index 0629151..cd7c1bc 100644 --- a/lib/adapters/Sqlite/dblite.js +++ b/lib/adapters/Sqlite/dblite.js @@ -5,10 +5,10 @@ const dbliteAdapter = require('dblite'); class SqliteDblite extends Adapter { constructor (config) { - let file = (Helpers.isString(config)) ? config : config.file; + const file = (Helpers.isString(config)) ? config : config.file; const instance = new Promise((resolve, reject) => { - let conn = dbliteAdapter(file); + const conn = dbliteAdapter(file); // Stop the stupid 'bye bye' message being output conn.on('close', () => {}); diff --git a/lib/adapters/Sqlite/sqlite3.js b/lib/adapters/Sqlite/sqlite3.js index 6fe1391..860633b 100644 --- a/lib/adapters/Sqlite/sqlite3.js +++ b/lib/adapters/Sqlite/sqlite3.js @@ -5,10 +5,10 @@ const sqlite3 = require('sqlite3').verbose(); class SqliteSqlite3 extends Adapter { constructor (config) { - let file = (Helpers.isString(config)) ? config : config.file; + const file = (Helpers.isString(config)) ? config : config.file; const instance = new Promise((resolve, reject) => { - let conn = new sqlite3.Database(file, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, err => { + const conn = new sqlite3.Database(file, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, err => { if (err) { reject(err); } diff --git a/lib/drivers/MSSQLDriver.js b/lib/drivers/MSSQLDriver.js index 19ec4f5..57fc06c 100644 --- a/lib/drivers/MSSQLDriver.js +++ b/lib/drivers/MSSQLDriver.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Driver for Microsoft SQL Server databases * @@ -8,7 +6,6 @@ module.exports = (() => { delete require.cache[require.resolve('../Driver')]; const driver = require('../Driver'); - const Helpers = require('../Helpers'); driver.identifierStartChar = '['; driver.identifierEndChar = ']'; diff --git a/lib/drivers/Pg.js b/lib/drivers/Pg.js index 3ec19cb..18d396a 100755 --- a/lib/drivers/Pg.js +++ b/lib/drivers/Pg.js @@ -5,7 +5,5 @@ */ module.exports = (() => { delete require.cache[require.resolve('../Driver')]; - let driver = require('../Driver'); - - return driver; + return require('../Driver'); })(); diff --git a/lib/drivers/Sqlite.js b/lib/drivers/Sqlite.js index cd69ab2..0da4ea5 100644 --- a/lib/drivers/Sqlite.js +++ b/lib/drivers/Sqlite.js @@ -5,7 +5,7 @@ */ module.exports = (() => { delete require.cache[require.resolve('../Driver')]; - let driver = require('../Driver'); + const driver = require('../Driver'); // Sqlite doesn't have a truncate command driver.hasTruncate = false; @@ -22,11 +22,11 @@ module.exports = (() => { // Get the data values to insert, so they can // be parameterized let sql = ''; - let first = data.shift(); + const first = data.shift(); - let vals = []; + const vals = []; data.forEach(obj => { - let row = []; + const row = []; Object.keys(obj).forEach(key => { row.push(obj[key]); }); @@ -37,8 +37,8 @@ module.exports = (() => { // Get the field names from the keys of the first // object to be inserted - let fields = Object.keys(first); - let cols = []; + const fields = Object.keys(first); + const cols = []; fields.forEach(key => { cols.push(`'${driver._quote(first[key])}' AS ${driver.quoteIdentifiers(key)}`); }); @@ -46,7 +46,7 @@ module.exports = (() => { sql += `SELECT ${cols.join(', ')}\n`; vals.forEach(rowValues => { - let quoted = rowValues.map(value => String(value).replace('\'', '\'\'')); + const quoted = rowValues.map(value => String(value).replace('\'', '\'\'')); sql += `UNION ALL SELECT '${quoted.join('\', \'')}'\n`; }); diff --git a/package.json b/package.json index 4fcfafc..78c446b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ci-node-query", - "version": "6.0.0", + "version": "5.0.0", "description": "A query builder for node based on the one in CodeIgniter", "author": "Timothy J Warren ", "engines": { @@ -42,27 +42,31 @@ "glob": "^7.0.3", "mysql2": "^1.2.0", "pg": "^7.4", - "require-reload": "~0.2.2", "sqlite3": "^3.1.8", "tedious": "^2.0.0", "xregexp": "^4.0.0" }, "devDependencies": { "babel-eslint": "^8.2.1", - "chai": "^4.1", - "chai-as-promised": "^7.1", "documentation": "latest", "eslint": "^4.16.0", + "eslint-config-happiness": "^10.2.1", + "eslint-plugin-import": "^2.8.0", + "eslint-plugin-node": "^5.2.1", + "eslint-plugin-promise": "^3.6.0", + "eslint-plugin-standard": "^3.0.1", "globstar": "^1.0.0", - "happiness": "^10.0", "jest": "^22.0.0", "jsdoc": "^3.4.3", "npm-run-all": "^4.0.2", "nsp": "^3.1", - "pg-native": "^2.2" + "require-reload": "~0.2.2" }, "license": "MIT", "jest": { + "collectCoverageFrom": [ + "lib/**/*.js" + ], "coverageDirectory": "coverage", "coverageReporters": [ "html", @@ -82,21 +86,11 @@ "default": "npm-run-all --parallel audit lint:src lint:tests && npm run test", "predocs": "globstar -- documentation build -f md -o API.md \"lib/*.js\"", "docs": "globstar -- documentation build -f html -o docs \"lib/*.js\"", - "fix": "happiness --fix \"lib/**/*.js\" \"test/**/*.js\"", + "fix": "eslint --fix ./lib ./test", "postdocs": "jsdoc lib -r -d documentation", - "happy": "happiness \"lib/**/*.js\" \"test/**/*.js\"", - "happy:src": "happiness \"lib/**/*.js\"", - "happy:tests": "happiness \"test/**/*.js\"", - "lint": "npm-run-all lint:tests lint:src happy", + "lint": "npm-run-all lint:src lint:tests", "lint:src": "eslint ./lib", "lint:tests": "eslint ./test", "test": "jest" - }, - "happiness": { - "env": { - "es6": true, - "jest": true - }, - "parser": "babel-eslint" } } diff --git a/test/adapters/__snapshots__/dblite_test.js.snap b/test/adapters/__snapshots__/dblite_test.js.snap new file mode 100644 index 0000000..bc327b2 --- /dev/null +++ b/test/adapters/__snapshots__/dblite_test.js.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Dblite adapter tests - Get compiled - getCompiledDelete 1`] = `"DELETE FROM \\"create_test\\" WHERE \\"id\\" = ?"`; + +exports[`Dblite adapter tests - Get compiled - getCompiledInsert 1`] = `"INSERT INTO \\"create_test\\" (\\"id\\",\\"key\\",\\"val\\") VALUES (?,?,?)"`; + +exports[`Dblite adapter tests - Get compiled - getCompiledSelect 1`] = `"SELECT \\"id\\", \\"key\\" AS \\"k\\", \\"val\\" FROM \\"create_test\\" WHERE (\\"id\\" > ? AND \\"id\\" < ?) LIMIT 2 OFFSET 1"`; + +exports[`Dblite adapter tests - Get compiled - getCompiledSelect 2 1`] = `"SELECT \\"id\\", \\"key\\" AS \\"k\\", \\"val\\" FROM \\"create_test\\" WHERE (\\"id\\" > ? AND \\"id\\" < ?) LIMIT 2 OFFSET 1"`; + +exports[`Dblite adapter tests - Get compiled - getCompiledUpdate 1`] = `"UPDATE \\"create_test\\" SET \\"id\\"=?,\\"key\\"=?,\\"val\\"=? WHERE \\"id\\" = ?"`; diff --git a/test/adapters/__snapshots__/mysql2_test.js.snap b/test/adapters/__snapshots__/mysql2_test.js.snap new file mode 100644 index 0000000..585b123 --- /dev/null +++ b/test/adapters/__snapshots__/mysql2_test.js.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Mysql2 adapter tests - Get compiled - getCompiledDelete 1`] = `"DELETE FROM \`create_test\` WHERE \`id\` = ?"`; + +exports[`Mysql2 adapter tests - Get compiled - getCompiledInsert 1`] = `"INSERT INTO \`create_test\` (\`id\`,\`key\`,\`val\`) VALUES (?,?,?)"`; + +exports[`Mysql2 adapter tests - Get compiled - getCompiledSelect 1`] = `"SELECT \`id\`, \`key\` AS \`k\`, \`val\` FROM \`create_test\` WHERE (\`id\` > ? AND \`id\` < ?) LIMIT 1,2"`; + +exports[`Mysql2 adapter tests - Get compiled - getCompiledSelect 2 1`] = `"SELECT \`id\`, \`key\` AS \`k\`, \`val\` FROM \`create_test\` WHERE (\`id\` > ? AND \`id\` < ?) LIMIT 1,2"`; + +exports[`Mysql2 adapter tests - Get compiled - getCompiledUpdate 1`] = `"UPDATE \`create_test\` SET \`id\`=?,\`key\`=?,\`val\`=? WHERE \`id\` = ?"`; diff --git a/test/adapters/__snapshots__/pg_test.js.snap b/test/adapters/__snapshots__/pg_test.js.snap new file mode 100644 index 0000000..e3a3b9a --- /dev/null +++ b/test/adapters/__snapshots__/pg_test.js.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Pg adapter tests - Get compiled - getCompiledDelete 1`] = `"DELETE FROM \\"create_test\\" WHERE \\"id\\" = ?"`; + +exports[`Pg adapter tests - Get compiled - getCompiledInsert 1`] = `"INSERT INTO \\"create_test\\" (\\"id\\",\\"key\\",\\"val\\") VALUES (?,?,?)"`; + +exports[`Pg adapter tests - Get compiled - getCompiledSelect 1`] = `"SELECT \\"id\\", \\"key\\" AS \\"k\\", \\"val\\" FROM \\"create_test\\" WHERE (\\"id\\" > ? AND \\"id\\" < ?) LIMIT 2 OFFSET 1"`; + +exports[`Pg adapter tests - Get compiled - getCompiledSelect 2 1`] = `"SELECT \\"id\\", \\"key\\" AS \\"k\\", \\"val\\" FROM \\"create_test\\" WHERE (\\"id\\" > ? AND \\"id\\" < ?) LIMIT 2 OFFSET 1"`; + +exports[`Pg adapter tests - Get compiled - getCompiledUpdate 1`] = `"UPDATE \\"create_test\\" SET \\"id\\"=?,\\"key\\"=?,\\"val\\"=? WHERE \\"id\\" = ?"`; diff --git a/test/adapters/__snapshots__/sqlite3_test.js.snap b/test/adapters/__snapshots__/sqlite3_test.js.snap new file mode 100644 index 0000000..f33c3ef --- /dev/null +++ b/test/adapters/__snapshots__/sqlite3_test.js.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Sqlite3 adapter tests - Get compiled - getCompiledDelete 1`] = `"DELETE FROM \\"create_test\\" WHERE \\"id\\" = ?"`; + +exports[`Sqlite3 adapter tests - Get compiled - getCompiledInsert 1`] = `"INSERT INTO \\"create_test\\" (\\"id\\",\\"key\\",\\"val\\") VALUES (?,?,?)"`; + +exports[`Sqlite3 adapter tests - Get compiled - getCompiledSelect 1`] = `"SELECT \\"id\\", \\"key\\" AS \\"k\\", \\"val\\" FROM \\"create_test\\" WHERE (\\"id\\" > ? AND \\"id\\" < ?) LIMIT 2 OFFSET 1"`; + +exports[`Sqlite3 adapter tests - Get compiled - getCompiledSelect 2 1`] = `"SELECT \\"id\\", \\"key\\" AS \\"k\\", \\"val\\" FROM \\"create_test\\" WHERE (\\"id\\" > ? AND \\"id\\" < ?) LIMIT 2 OFFSET 1"`; + +exports[`Sqlite3 adapter tests - Get compiled - getCompiledUpdate 1`] = `"UPDATE \\"create_test\\" SET \\"id\\"=?,\\"key\\"=?,\\"val\\"=? WHERE \\"id\\" = ?"`; diff --git a/test/adapters/dblite_test.js b/test/adapters/dblite_test.js index 2aae4ab..f4d1710 100644 --- a/test/adapters/dblite_test.js +++ b/test/adapters/dblite_test.js @@ -19,7 +19,7 @@ describe('Dblite adapter tests -', () => { }); testRunner(qb); - it('Promise - Select with function and argument in WHERE clause', async () => { + it('Select with function and argument in WHERE clause', async () => { let promise = await qb.select('id') .from('create_test') .where('id', 'ABS(-88)') @@ -27,26 +27,6 @@ describe('Dblite adapter tests -', () => { expect(promise).toEqual(expect.anything()); }); - it('Promise - Test Insert Batch', async () => { - let data = [ - { - id: 544, - key: 3, - val: Buffer.from('7') - }, { - id: 89, - key: 34, - val: Buffer.from('10 o\'clock') - }, { - id: 48, - key: 403, - val: Buffer.from('97') - } - ]; - - let promise = await qb.insertBatch('create_test', data); - expect(promise).toEqual(expect.anything()); - }); afterAll(() => { qb.end(); }); diff --git a/test/adapters/mysql2_test.js b/test/adapters/mysql2_test.js index 32058e3..1956585 100644 --- a/test/adapters/mysql2_test.js +++ b/test/adapters/mysql2_test.js @@ -24,7 +24,7 @@ describe('Mysql2 adapter tests -', () => { }); testRunner(qb); - it('Promise - Select with function and argument in WHERE clause', async () => { + it('Select with function and argument in WHERE clause', async () => { let promise = await qb.select('id') .from('create_test') .where('id', 'CEILING(SQRT(88))') @@ -36,28 +36,7 @@ describe('Mysql2 adapter tests -', () => { let promise = await qb.truncate('create_test'); expect(promise).toEqual(expect.anything()); }); - it('Test Insert Batch', async () => { - let data = [ - { - id: 5442, - key: 4, - val: Buffer.from('7') - }, { - id: 892, - key: 35, - val: Buffer.from('10 o\'clock') - }, { - id: 482, - key: 404, - val: 97 - } - ]; - - const promise = await qb.insertBatch('create_test', data); - expect(promise).toEqual(expect.anything()); - }); - - /* describeTeardown(() => { + afterAll(() => { qb.end(); - }); */ + }); }); diff --git a/test/adapters/pg_test.js b/test/adapters/pg_test.js index b1d1fb7..a87efa5 100644 --- a/test/adapters/pg_test.js +++ b/test/adapters/pg_test.js @@ -45,36 +45,16 @@ describe('Pg adapter tests -', () => { }); testRunner(qb); - it('Promise - Select with function and argument in WHERE clause', async () => { - let promise = await qb.select('id') + it('Select with function and argument in WHERE clause', async () => { + const promise = await qb.select('id') .from('create_test') .where('id', 'CEILING(SQRT(88))') .get(); expect(promise).toEqual(expect.anything()); }); - it('Promise - Test Truncate', async () => { - let promise = await qb.truncate('create_test'); - expect(promise).toEqual(expect.anything()); - }); - it('Promise - Test Insert Batch', async () => { - let data = [ - { - id: 544, - key: 3, - val: Buffer.from('7') - }, { - id: 89, - key: 34, - val: Buffer.from('10 o\'clock') - }, { - id: 48, - key: 403, - val: Buffer.from('97') - } - ]; - - let promise = await qb.insertBatch('create_test', data); + it('Test Truncate', async () => { + const promise = await qb.truncate('create_test'); expect(promise).toEqual(expect.anything()); }); afterAll(() => { diff --git a/test/adapters/sqlite3_test.js b/test/adapters/sqlite3_test.js index 491dece..be02cfa 100644 --- a/test/adapters/sqlite3_test.js +++ b/test/adapters/sqlite3_test.js @@ -20,7 +20,7 @@ describe('Sqlite3 adapter tests -', () => { }); testRunner(qb); - it('Promise - Select with function and argument in WHERE clause', async () => { + it('Select with function and argument in WHERE clause', async () => { let promise = await qb.select('id') .from('create_test') .where('id', 'ABS(-88)') @@ -28,26 +28,6 @@ describe('Sqlite3 adapter tests -', () => { expect(promise).toEqual(expect.anything()); }); - it('Promise - Test Insert Batch', async () => { - let data = [ - { - id: 544, - key: 3, - val: Buffer.from('7') - }, { - id: 89, - key: 34, - val: Buffer.from('10 o\'clock') - }, { - id: 48, - key: 403, - val: Buffer.from('97') - } - ]; - - let promise = await qb.insertBatch('create_test', data); - expect(promise).toEqual(expect.anything()); - }); afterAll(() => { qb.end(); }); diff --git a/test/base.js b/test/base.js index c4c4d40..b915c3a 100644 --- a/test/base.js +++ b/test/base.js @@ -1,13 +1,8 @@ -const chai = require('chai'); -const chaiAsPromised = require('chai-as-promised'); -chai.use(chaiAsPromised); - // Load the test config file const configFile = './config.json'; module.exports = { config: require(configFile), - expect: chai.expect, tests: require('./base/tests'), promiseTestRunner: require('./base/adapterPromiseTestRunner') }; diff --git a/test/base/adapterPromiseTestRunner.js b/test/base/adapterPromiseTestRunner.js index 64d93d1..cbb86e1 100644 --- a/test/base/adapterPromiseTestRunner.js +++ b/test/base/adapterPromiseTestRunner.js @@ -37,13 +37,14 @@ module.exports = function promiseTestRunner (qb) { }); }); }); - describe('DB update tests -', async () => { + + describe('DB update tests -', () => { beforeAll(done => { let sql = qb.driver.truncate('create_test'); - qb.query(sql).then(res => done()) + qb.query(sql).then(() => done()) .catch(err => done(err)); }); - it('Promise - Test Insert', async () => { + it('Test Insert', async () => { const promise = await qb.set('id', 98) .set('key', '84') .set('val', Buffer.from('120')) @@ -51,7 +52,7 @@ module.exports = function promiseTestRunner (qb) { expect(promise).toEqual(expect.anything()); }); - it('Promise - Test Insert Object', async () => { + it('Test Insert Object', async () => { const promise = await qb.insert('create_test', { id: 587, key: 1, @@ -60,7 +61,7 @@ module.exports = function promiseTestRunner (qb) { expect(promise).toEqual(expect.anything()); }); - it('Promise - Test Update', async () => { + it('Test Update', async () => { const promise = await qb.where('id', 7) .update('create_test', { id: 7, @@ -70,7 +71,7 @@ module.exports = function promiseTestRunner (qb) { expect(promise).toEqual(expect.anything()); }); - it('Promise - Test set Array Update', async () => { + it('Test set Array Update', async () => { let object = { id: 22, key: 'gogle', @@ -83,7 +84,7 @@ module.exports = function promiseTestRunner (qb) { expect(promise).toEqual(expect.anything()); }); - it('Promise - Test where set update', async () => { + it('Test where set update', async () => { const promise = await qb.where('id', 36) .set('id', 36) .set('key', 'gogle') @@ -92,17 +93,17 @@ module.exports = function promiseTestRunner (qb) { expect(promise).toEqual(expect.anything()); }); - it('Promise - Test delete', async () => { + it('Test delete', async () => { const promise = await qb.delete('create_test', {id: 5}); expect(promise).toEqual(expect.anything()); }); - it('Promise - Delete with where', async () => { + it('Delete with where', async () => { const promise = await qb.where('id', 5) .delete('create_test'); expect(promise).toEqual(expect.anything()); }); - it('Promise - Delete multiple where values', async () => { + it('Delete multiple where values', async () => { const promise = await qb.delete('create_test', { id: 5, key: 'gogle' @@ -111,8 +112,46 @@ module.exports = function promiseTestRunner (qb) { expect(promise).toEqual(expect.anything()); }); }); - describe('Grouping tests -', async () => { - it('Promise - Using grouping method', async () => { + + describe('Batch tests -', () => { + it('Test Insert Batch', async () => { + const data = [ + { + id: 544, + key: 3, + val: Buffer.from('7') + }, { + id: 89, + key: 34, + val: Buffer.from('10 o\'clock') + }, { + id: 48, + key: 403, + val: Buffer.from('97') + } + ]; + + const promise = await qb.insertBatch('create_test', data); + expect(promise).toEqual(expect.anything()); + }); + it('Test Update Batch', async () => { + const data = [{ + id: 480, + key: 49, + val: '7x7' + }, { + id: 890, + key: 100, + val: '10x10' + }]; + + const affectedRows = qb.updateBatch('create_test', data, 'id'); + expect(affectedRows).toBe(2); + }); + }); + + describe('Grouping tests -', () => { + it('Using grouping method', async () => { const promise = await qb.select('id, key as k, val') .from('create_test') .groupStart() @@ -124,7 +163,7 @@ module.exports = function promiseTestRunner (qb) { expect(promise).toEqual(expect.anything()); }); - it('Promise - Using where first grouping', async () => { + it('Using where first grouping', async () => { const promise = await qb.select('id, key as k, val') .from('create_test') .where('id !=', 5) @@ -137,7 +176,7 @@ module.exports = function promiseTestRunner (qb) { expect(promise).toEqual(expect.anything()); }); - it('Promise - Using or grouping method', async () => { + it('Using or grouping method', async () => { const promise = await qb.select('id, key as k, val') .from('create_test') .groupStart() @@ -152,7 +191,7 @@ module.exports = function promiseTestRunner (qb) { expect(promise).toEqual(expect.anything()); }); - it('Promise - Using or not grouping method', async () => { + it('Using or not grouping method', async () => { const promise = await qb.select('id, key as k, val') .from('create_test') .groupStart() @@ -168,4 +207,51 @@ module.exports = function promiseTestRunner (qb) { expect(promise).toEqual(expect.anything()); }); }); + describe('Get compiled - ', () => { + it('getCompiledSelect', () => { + const sql = qb.select('id, key as k, val') + .from('create_test') + .groupStart() + .where('id >', 1) + .where('id <', 900) + .groupEnd() + .limit(2, 1) + .getCompiledSelect(); + + expect(sql).toMatchSnapshot(); + }); + it('getCompiledSelect 2', () => { + const sql = qb.select('id, key as k, val') + .groupStart() + .where('id >', 1) + .where('id <', 900) + .groupEnd() + .limit(2, 1) + .getCompiledSelect('create_test'); + + expect(sql).toMatchSnapshot(); + }); + it('getCompiledInsert', () => { + const sql = qb.set({ + id: 587, + key: 1, + val: Buffer.from('2') + }).getCompiledInsert('create_test'); + + expect(sql).toMatchSnapshot(); + }); + it('getCompiledUpdate', () => { + const sql = qb.where('id', 36) + .set('id', 36) + .set('key', 'gogle') + .set('val', Buffer.from('non-word')) + .getCompiledUpdate('create_test'); + + expect(sql).toMatchSnapshot(); + }); + it('getCompiledDelete', () => { + const sql = qb.where({id: 5}).getCompiledDelete('create_test'); + expect(sql).toMatchSnapshot(); + }); + }); }; diff --git a/test/config-ci.json b/test/config-ci.json index 398a4fe..97e09fd 100644 --- a/test/config-ci.json +++ b/test/config-ci.json @@ -18,6 +18,18 @@ "database": "test" } }, + "pg-native": { + "driver": "pg", + "native": true, + "connection": "postgres://test:test@posgres/test" + }, + "pg-object-native": { + "driver": "pg", + "native": true, + "connection": { + "database": "test" + } + }, "dblite": { "adapter": "dblite", "driver": "sqlite", @@ -26,14 +38,5 @@ "sqlite3": { "driver": "sqlite", "connection": ":memory:" - }, - "node-firebird": { - "driver": "firebird", - "connection": { - "host": "127.0.0.1", - "database": "/../FB_TEST_DB.FDB", - "user": "SYSDBA", - "password": "masterkey" - } } }