diff --git a/.travis.yml b/.travis.yml index 2ceb35c2..07becfb2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,11 @@ language: node_js node_js: - - "0.8" + - "5.0" + - "4.2" - "0.10" - "0.11" matrix: allow_failures: - - node_js: "0.11" + - node_js: "0.10" + - node_js: "0.11" \ No newline at end of file diff --git a/Makefile b/Makefile index 6cde1304..4d56d98a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,17 @@ -.PHONY: jshint test - -jshint: - ./node_modules/.bin/jshint lib test +.PHONY: jshint test publish-patch test test: npm test + +patch: test + npm version patch -m "Bump version" + git push origin master --tags + npm publish + +minor: test + npm version minor -m "Bump version" + git push origin master --tags + npm publish + +jshint: + ./node_modules/.bin/jshint lib diff --git a/README.md b/README.md index 5b16559e..e1a3af8c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # node-sql -_sql string builder for node_ - supports PostgreSQL, mysql, and sqlite dialects. +_sql string builder for node_ - supports PostgreSQL, mysql, Microsoft SQL Server, Oracle and sqlite dialects. Building SQL statements by hand is no fun, especially in a language which has clumsy support for multi-line strings. @@ -9,12 +9,22 @@ Maybe it's still not fun, but at least it's _less not fun_. [![Build Status](https://secure.travis-ci.org/brianc/node-sql.png)](http://travis-ci.org/brianc/node-sql) -## examples +## install + +```sh +$ npm install sql +``` + +## use ```js //require the module var sql = require('sql'); +//(optionally) set the SQL dialect +sql.setDialect('postgres'); +//possible dialects: mssql, mysql, postgres (default), sqlite + //first we define our tables var user = sql.define({ name: 'user', @@ -98,7 +108,7 @@ console.log(user.select().where(user.state.equals('WA')).toQuery().text); // "SELECT "user".* FROM "user" WHERE ("user"."state_or_province" = $1)" ``` -There are a __lot__ more examples included in the `test/dialects` folder. +There are a __lot__ more examples included in the [test/dialects](https://github.com/brianc/node-sql/tree/master/test/dialects) folder. We encourage you to read through them if you have any questions on usage! ## from the command line You can use the [sql-generate module](https://github.com/tmont/node-sql-generate) @@ -173,5 +183,5 @@ Usually after a few high-quality pull requests and friendly interactions we will After all, open source belongs to everyone. -##license +## license MIT diff --git a/lib/column.js b/lib/column.js index 3c5e70f5..55a3da18 100644 --- a/lib/column.js +++ b/lib/column.js @@ -20,6 +20,7 @@ var Column = function(config) { direction : new TextNode('DESC') }); this.dataType = config.dataType; + this.defaultValue = config.defaultValue; }; // mix in value expression diff --git a/lib/dialect/index.js b/lib/dialect/index.js index 06dbd8c6..c26f15de 100644 --- a/lib/dialect/index.js +++ b/lib/dialect/index.js @@ -9,6 +9,10 @@ var getDialect = function(dialect) { return require('./mysql'); case 'sqlite': return require('./sqlite'); + case 'mssql': + return require('./mssql'); + case 'oracle': + return require('./oracle'); default: throw new Error(dialect + ' is unsupported'); } diff --git a/lib/dialect/mssql.js b/lib/dialect/mssql.js new file mode 100644 index 00000000..6e71f2e1 --- /dev/null +++ b/lib/dialect/mssql.js @@ -0,0 +1,481 @@ +// TODO: visitCreate needs to support schemas +// TODO: visitDrop needs to support schemas + +'use strict'; + +var util = require('util'); +var assert = require('assert'); + +/** + * Config can contain: + * + * questionMarkParameterPlaceholder:true which will use a "?" for the parameter placeholder instead of the @index. + * + * @param config + * @constructor + */ +var Mssql = function(config) { + this.output = []; + this.params = []; + this.config = config || {}; +}; + +var Postgres = require('./postgres'); + +util.inherits(Mssql, Postgres); + +Mssql.prototype._myClass = Mssql; + +Mssql.prototype._quoteCharacter = '['; + +Mssql.prototype._arrayAggFunctionName = ''; + +Mssql.prototype.visitReplace = function(replace) { + throw new Error('Mssql does not support REPLACE.'); +}; + +Mssql.prototype._getParameterPlaceholder = function(index, value) { + if (this.config.questionMarkParameterPlaceholder) return '?'; + return '@' + index; +}; + +Mssql.prototype.visitBinary = function(binary) { + if(binary.operator === '@@'){ + var self = this; + var text = '(CONTAINS (' + this.visit(binary.left) + ', '; + text += this.visit(binary.right); + text += '))'; + return [text]; + } + + if(binary.operator === '||'){ + return ['(' + this.visit(binary.left) + ' + ' + this.visit(binary.right) + ')']; + } + + if (!isRightSideArray(binary)){ + return Mssql.super_.prototype.visitBinary.call(this, binary); + } + if (binary.operator=='IN' || binary.operator=='NOT IN'){ + return Mssql.super_.prototype.visitBinary.call(this, binary); + } + throw new Error('SQL Sever does not support arrays in this type of expression.'); +}; + +Mssql.prototype.visitAlter = function(alter) { + var self=this; + var errMsg='ALTER TABLE cannot be used to perform multiple different operations in the same statement.'; + + // Implement our own add column: + // PostgreSQL: ALTER TABLE "name" ADD COLUMN "col1", ADD COLUMN "col2" + // Mssql: ALTER TABLE [name] ADD [col1], [col2] + function _addColumn(){ + self._visitingAlter = true; + var table = self._queryNode.table; + self._visitingAddColumn = true; + var result='ALTER TABLE '+self.visit(table.toNode())+' ADD '+self.visit(alter.nodes[0].nodes[0]); + for (var i= 1,len=alter.nodes.length; i= 0) txt = _extract(); + // Override CURRENT_TIMESTAMP function to remove parens + else if ('CURRENT_TIMESTAMP' == functionCall.name) txt = functionCall.name; + else { + var name = functionCall.name; + // override the LENGTH function since mssql calls it LEN + if (name == "LENGTH") name = "LEN"; + txt = name + '(' + functionCall.nodes.map(this.visit.bind(this)).join(', ') + ')'; + } + this._visitingFunctionCall = false; + return [txt]; +}; + +Mssql.prototype.visitJoin = function(join) { + if (join.subType !== 'LEFT LATERAL') return Mssql.super_.prototype.visitJoin.call(this, join); + var result = []; + this._visitingJoin = true; + result = result.concat(this.visit(join.from)); + result = result.concat('OUTER APPLY'); + result = result.concat(this.visit(join.to)); + return result; +}; + +Mssql.prototype.visitOrderBy = function(orderBy) { + var result=Mssql.super_.prototype.visitOrderBy.call(this, orderBy); + var offsetNode=orderBy.msSQLOffsetNode; + var limitNode=orderBy.msSQLLimitNode; + if (!offsetNode && !limitNode) return result; + assert(offsetNode,"Something bad happened, should have had an msSQLOffsetNode here."); + result.push("OFFSET "+getModifierValue(this,offsetNode)+" ROWS"); + if (!limitNode) return result; + result.push("FETCH NEXT "+getModifierValue(this,limitNode)+" ROWS ONLY"); + return result; +}; + +/** + * We override this so that we can deal with the LIMIT and OFFSET clauses specially since they have to become + * part of the SELECT and ORDER BY clauses. + * + * Basically if there's an ORDER BY clause we attach OFFSET and LIMIT to it so that it can be processed by the + * ORDER BY handler later. + * + * If there's a LIMIT clause without OFFSET, we attach it to the SELECT clause so we can process it later. + * + * @param {Node[]} actions + * @param {Node[]} targets + * @param {Node[]} filters + * @returns {String[]} + */ +Mssql.prototype.visitQueryHelper=function(actions,targets,filters){ + function _handleLimitAndOffset(){ + var limitInfo=Mssql.super_.prototype.findNode.call(this, filters, "LIMIT"); // jshint ignore:line + var offsetInfo=Mssql.super_.prototype.findNode.call(this, filters, "OFFSET"); // jshint ignore:line + var orderByInfo=Mssql.super_.prototype.findNode.call(this, filters, "ORDER BY"); // jshint ignore:line + + // no OFFSET or LIMIT then there's nothing special to do + if (!offsetInfo && !limitInfo) return; + // ORDER BY with OFFSET we have work to do, may consume LIMIT as well + if (orderByInfo && offsetInfo) _processOrderByOffsetLimit(orderByInfo,offsetInfo,limitInfo); + else if (offsetInfo) throw new Error("MS SQL Server does not allow OFFSET without ORDER BY"); + else if (limitInfo) _processLimit(limitInfo); + } + + /** + * We need to turn LIMIT into a TOP clause on the SELECT STATEMENT + * + * @param limitInfo + * @private + */ + function _processLimit(limitInfo){ + var selectInfo=Mssql.super_.prototype.findNode.call(this, actions, "SELECT"); // jshint ignore:line + assert(selectInfo!==undefined,"MS SQL Server requires a SELECT clause when using LIMIT"); + // save the LIMIT node with the SELECT node + selectInfo.node.msSQLLimitNode=limitInfo.node; + // remove the LIMIT node from the filters so it doesn't get processed later. + filters.splice(limitInfo.index,1); + } + + /** + * We need to turn LIMIT into a TOP clause on the SELECT STATEMENT + * + * @param orderByInfo + * @param offsetInfo + * @param limitInfo + * @private + */ + function _processOrderByOffsetLimit(orderByInfo,offsetInfo,limitInfo){ + // save the OFFSET AND LIMIT nodes with the ORDER BY node + orderByInfo.node.msSQLOffsetNode=offsetInfo.node; + if (limitInfo) orderByInfo.node.msSQLLimitNode=limitInfo.node; + // remove the OFFSET and LIMIT nodes from the filters so they don't get processed later. + filters.splice(offsetInfo.index,1); + if (limitInfo) filters.splice(limitInfo.index,1); + } + + // MAIN + + Mssql.super_.prototype.handleDistinct.call(this, actions, filters); + _handleLimitAndOffset(); + + // lazy-man sorting + var sortedNodes = actions.concat(targets).concat(filters); + for(var i = 0; i < sortedNodes.length; i++) { + var res = this.visit(sortedNodes[i]); + this.output = this.output.concat(res); + } + return this.output; +}; + +//Mysql.prototype.visitRenameColumn = function(renameColumn) { +// var dataType = renameColumn.nodes[1].dataType || renameColumn.nodes[0].dataType; +// assert(dataType, 'dataType missing for column ' + (renameColumn.nodes[1].name || renameColumn.nodes[0].name || '') + +// ' (CHANGE COLUMN statements require a dataType)'); +// return ['CHANGE COLUMN ' + this.visit(renameColumn.nodes[0]) + ' ' + this.visit(renameColumn.nodes[1]) + ' ' + dataType]; +//}; +// +//Mysql.prototype.visitInsert = function(insert) { +// var result = Postgres.prototype.visitInsert.call(this, insert); +// if (result[2] === 'DEFAULT VALUES') { +// result[2] = '() VALUES ()'; +// } +// return result; +//}; +// +//Mysql.prototype.visitIndexes = function(node) { +// var tableName = this.visit(this._queryNode.table.toNode()); +// +// return "SHOW INDEX FROM " + tableName; +//}; + +Mssql.prototype.visitOnDuplicate = function(onDuplicate) { + throw new Error('MSSQL does not allow onDuplicate clause.'); +}; + +Mssql.prototype.visitOnConflict = function(onConflict) { + throw new Error('MSSQL does not allow onConflict clause.'); +}; + +Mssql.prototype.visitReturning = function() { + // TODO: need to add some code to the INSERT clause to support this since its the equivalent of the OUTPUT clause + // in MS SQL which appears before the values, not at the end of the statement. + throw new Error('Returning clause is not yet supported for MS SQL.'); +}; + +// We deal with SELECT specially so we can add the TOP clause if needed +Mssql.prototype.visitSelect = function(select) { + if (!select.msSQLLimitNode) return Mssql.super_.prototype.visitSelect.call(this, select); + var result=[ + 'SELECT', + 'TOP('+getModifierValue(this,select.msSQLLimitNode)+')', + select.nodes.map(this.visit.bind(this)).join(', ') + ]; + this._selectOrDeleteEndIndex = this.output.length + result.length; + return result; +}; + +// Node is either an OFFSET or LIMIT node +function getModifierValue(dialect,node){ + return node.count.type ? dialect.visit(node.count) : node.count; +} + +function isAlterAddColumn(alter){ + if (alter.nodes.length===0) return false; + if (alter.nodes[0].type!='ADD COLUMN') return false; + return true; +} + +function isAlterDropColumn(alter){ + if (alter.nodes.length===0) return false; + if (alter.nodes[0].type!='DROP COLUMN') return false; + return true; +} + +function isAlterRename(alter){ + if (alter.nodes.length===0) return false; + if (alter.nodes[0].type!='RENAME') return false; + return true; +} + +function isAlterRenameColumn(alter){ + if (alter.nodes.length===0) return false; + if (alter.nodes[0].type!='RENAME COLUMN') return false; + return true; +} + +function isCountStarExpression(columnNode){ + if (!columnNode.aggregator) return false; + if (columnNode.aggregator.toLowerCase()!='count') return false; + if (!columnNode.star) return false; + return true; +} + +function isCreateIfNotExists(create){ + if (create.nodes.length===0) return false; + if (create.nodes[0].type!='IF NOT EXISTS') return false; + return true; +} + +function isCreateTemporary(create){ + return create.options.isTemporary; +} + +function isDropIfExists(drop){ + if (drop.nodes.length===0) return false; + if (drop.nodes[0].type!='IF EXISTS') return false; + return true; +} + +// SQL Server does not support array expressions except in the IN clause. +function isRightSideArray(binary){ + return Array.isArray(binary.right); +} + +module.exports = Mssql; diff --git a/lib/dialect/mysql.js b/lib/dialect/mysql.js index f8d31890..0a63f3be 100644 --- a/lib/dialect/mysql.js +++ b/lib/dialect/mysql.js @@ -2,13 +2,15 @@ var util = require('util'); var assert = require('assert'); +var _ = require('lodash'); -var Mysql = function() { +var Mysql = function(config) { this.output = []; this.params = []; + this.config = config || {}; }; -var Postgres = require(__dirname + '/postgres'); +var Postgres = require('./postgres'); util.inherits(Mysql, Postgres); @@ -18,6 +20,42 @@ Mysql.prototype._quoteCharacter = '`'; Mysql.prototype._arrayAggFunctionName = 'GROUP_CONCAT'; +Mysql.prototype.visitReplace = function(replace) { + var self = this; + // don't use table.column for replaces + this._visitedReplace = true; + + var result = ['REPLACE']; + result = result.concat(replace.nodes.map(this.visit.bind(this))); + result.push('INTO ' + this.visit(this._queryNode.table.toNode())); + result.push('(' + replace.columns.map(this.visit.bind(this)).join(', ') + ')'); + + var paramNodes = replace.getParameters(); + + if (paramNodes.length > 0) { + var paramText = paramNodes.map(function (paramSet) { + return paramSet.map(function (param) { + return self.visit(param); + }).join(', '); + }).map(function (param) { + return '('+param+')'; + }).join(', '); + + result.push('VALUES', paramText); + + if (result.slice(2, 5).join(' ') === '() VALUES ()') { + result.splice(2, 3, 'DEFAULT VALUES'); + } + } + + this._visitedReplace = false; + + if (result[2] === 'DEFAULT VALUES') { + result[2] = '() VALUES ()'; + } + return result; +}; + Mysql.prototype._getParameterPlaceholder = function() { return '?'; }; @@ -31,6 +69,24 @@ Mysql.prototype._getParameterValue = function(value) { return value; }; +Mysql.prototype.visitOnDuplicate = function(onDuplicate) { + var params = []; + /* jshint boss: true */ + for(var i = 0, node; node = onDuplicate.nodes[i]; i++) { + var target_col = this.visit(node); + params = params.concat(target_col + ' = ' + this.visit(node.value)); + } + var result = [ + 'ON DUPLICATE KEY UPDATE', + params.join(', ') + ]; + return result; +}; + +Mysql.prototype.visitOnConflict = function(onConflict) { + throw new Error('Mysql does not allow onConflict clause.'); +}; + Mysql.prototype.visitReturning = function() { throw new Error('MySQL does not allow returning clause.'); }; @@ -76,4 +132,90 @@ Mysql.prototype.visitIndexes = function(node) { return "SHOW INDEX FROM " + tableName; }; +Mysql.prototype.visitBinary = function(binary) { + if (binary.operator === '@@') { + var self = this; + var text = '(MATCH ' + this.visit(binary.left) + ' AGAINST '; + text += this.visit(binary.right); + text += ')'; + return [text]; + } + return Mysql.super_.prototype.visitBinary.call(this, binary); +}; + +Mysql.prototype.visitFunctionCall = function(functionCall) { + var _this=this; + + this._visitingFunctionCall = true; + + function _extract() { + var nodes = functionCall.nodes.map(_this.visit.bind(_this)); + if (nodes.length != 1) throw new Error('Not enough parameters passed to ' + functionCall.name + ' function'); + var txt = functionCall.name + '(' + (nodes[0]+'') + ')'; + return txt; + } + + var txt=""; + var name = functionCall.name; + // Override date functions since mysql is different than postgres + if (['YEAR', 'MONTH', 'DAY', 'HOUR'].indexOf(functionCall.name) >= 0) txt = _extract(); + // Override CURRENT_TIMESTAMP function to remove parens + else if ('CURRENT_TIMESTAMP' == functionCall.name) txt = functionCall.name; + else txt = name + '(' + functionCall.nodes.map(this.visit.bind(this)).join(', ') + ')'; + + this._visitingFunctionCall = false; + return [txt]; +}; + +Mysql.prototype.visitColumn = function(columnNode) { + var self = this; + var inSelectClause; + + function isCountStarExpression(columnNode){ + if (!columnNode.aggregator) return false; + if (columnNode.aggregator.toLowerCase()!='count') return false; + if (!columnNode.star) return false; + return true; + } + + function _countStar(){ + // Implement our own since count(table.*) is invalid in Mysql + var result='COUNT(*)'; + if(inSelectClause && columnNode.alias) { + result += ' AS ' + self.quote(columnNode.alias); + } + return result; + } + + inSelectClause = !this._selectOrDeleteEndIndex; + if(isCountStarExpression(columnNode)) return _countStar(); + return Mysql.super_.prototype.visitColumn.call(this, columnNode); +}; + +Mysql.prototype.visitInterval = function(interval) { + var parameter; + if(_.isNumber(interval.years)) { + if(_.isNumber(interval.months)) { + parameter = "'" + interval.years + '-' + interval.months + "' YEAR_MONTH"; + } else { + parameter = interval.years + ' YEAR'; + } + } else if(_.isNumber(interval.months)) { + parameter = interval.months + ' MONTH'; + } else if(_.isNumber(interval.days)) { + parameter = "'" + interval.days + ' ' + + (_.isNumber(interval.hours)?interval.hours:0) + ':' + + (_.isNumber(interval.minutes)?interval.minutes:0) + ':' + + (_.isNumber(interval.seconds)?interval.seconds:0) + "' DAY_SECOND"; + } else { + parameter = "'" + (_.isNumber(interval.hours)?interval.hours:0) + ':' + + (_.isNumber(interval.minutes)?interval.minutes:0) + ':' + + (_.isNumber(interval.seconds)?interval.seconds:0) + "' HOUR_SECOND"; + } + var result = "INTERVAL " + parameter; + return result; +}; + + + module.exports = Mysql; diff --git a/lib/dialect/oracle.js b/lib/dialect/oracle.js new file mode 100644 index 00000000..a55e7aca --- /dev/null +++ b/lib/dialect/oracle.js @@ -0,0 +1,330 @@ +'use strict'; + +var util = require('util'); +var assert = require('assert'); + +var Oracle = function(config) { + this.output = []; + this.params = []; + this.config = config || {}; +}; + +var Postgres = require('./postgres'); + +var Mssql = require('./mssql'); + +util.inherits(Oracle, Postgres); + +Oracle.prototype._myClass = Oracle; + +Oracle.prototype.visitReplace = function(replace) { + throw new Error('Oracle does not support REPLACE.'); +}; + +Oracle.prototype._aliasText = ' '; +Oracle.prototype._getParameterPlaceholder = function(index, value) { + /* jshint unused: false */ + return ':' + index; +}; + +Oracle.prototype.visitAlias = function(alias) { + var result = [this.visit(alias.value) + ' ' + this.quote(alias.alias)]; + return result; +}; + +Oracle.prototype.visitAlter = function(alter) { + var self=this; + var errMsg='ALTER TABLE cannot be used to perform multiple different operations in the same statement.'; + + // Implement our own add column: + // PostgreSQL: ALTER TABLE "name" ADD COLUMN "col1", ADD COLUMN "col2" + // Oracle: ALTER TABLE "name" ADD ("col1", "col2") + function _addColumn(){ + self._visitingAlter = true; + var table = self._queryNode.table; + self._visitingAddColumn = true; + var result='ALTER TABLE '+self.visit(table.toNode())+' ADD ('+self.visit(alter.nodes[0].nodes[0]); + for (var i= 1,len=alter.nodes.length; i= 0) { + ret.push('ROWS'); + } + if (ret.indexOf('LIMIT') >= 0) { + ret[0] = 'FETCH NEXT'; + ret.push('ROWS ONLY'); + } + return ret; +}; + +Oracle.prototype.visitQueryHelper=function(actions,targets,filters){ + var output = Oracle.super_.prototype.visitQueryHelper.call(this,actions,targets,filters); + + //In Oracle, OFFSET must come before FETCH NEXT (limit) + //Change positions, if both are present and not done already + var offset = output.indexOf('OFFSET'); + var limit = output.indexOf('FETCH NEXT'); + if (offset != -1 && limit != -1 && offset > limit){ + var temp = [output[offset], output[offset+1], output[offset+2]]; + output[offset] = output[limit]; + output[offset+1] = output[limit+1]; + output[offset+2] = output[limit+2]; + output[limit] = temp[0]; + output[limit+1] = temp[1]; + output[limit+2] = temp[2]; + } + + return this.output; +}; + +Oracle.prototype.visitColumn = function(columnNode) { + var self=this; + var table; + var inSelectClause; + + function _arrayAgg(){ + throw new Error("Oracle does not support array_agg."); + } + + function _countStar(){ + // Implement our own since count(table.*) is invalid in Oracle + var result='COUNT(*)'; + if(inSelectClause && columnNode.alias) { + result += self._aliasText + self.quote(columnNode.alias); + } + return result; + } + + table = columnNode.table; + inSelectClause = !this._selectOrDeleteEndIndex; + if (isCountStarExpression(columnNode)) return _countStar(); + if (inSelectClause && table && !table.alias && columnNode.asArray) return _arrayAgg(); + return Oracle.super_.prototype.visitColumn.call(this, columnNode); +}; + + +Oracle.prototype.visitReturning = function() { + // TODO: need to add some code to the INSERT clause to support this since its the equivalent of the OUTPUT clause + // in MS SQL which appears before the values, not at the end of the statement. + throw new Error('Returning clause is not yet supported for Oracle.'); +}; + + +Oracle.prototype._getParameterValue = function(value) { + if (Buffer.isBuffer(value)) { + value = "utl_raw.cast_to_varchar2(hextoraw('" + value.toString('hex') + "'))"; + } else { + value = Oracle.super_.prototype._getParameterValue.call(this, value); + //value = Postgres.prototype._getParameterValue.call(this, value); + } + return value; +}; + + +Oracle.prototype.visitIndexes = function(node) { + + var tableName = this._queryNode.table.getName(); + var schemaName = this._queryNode.table.getSchema(); + + var indexes = "SELECT * FROM USER_INDEXES WHERE TABLE_NAME = '" + tableName + "'"; + + if (schemaName) { + indexes += " AND TABLE_OWNER = '" + schemaName + "'"; + } + + return indexes; +}; + + +Oracle.prototype.visitDropIndex = function(node) { + var result = [ 'DROP INDEX' ]; + var schemaName = node.table.getSchema(); + if (schemaName) { + result.push(this.quote(schemaName) + "."); + } + + result.push(this.quote(node.options.indexName)); + + return result; +}; + +// Using same CASE implementation as MSSQL +Oracle.prototype.visitCase = function(caseExp) { + + return Mssql.prototype.visitCase.call(this, caseExp); +}; + +// Using same JOIN implementation as MSSQL +Oracle.prototype.visitJoin = function(joinExp) { + return Mssql.prototype.visitJoin.call(this, joinExp); +}; + +Oracle.prototype.visitOnConflict = function(onConflict) { + throw new Error('Oracle does not allow onConflict clause.'); +}; + +function isCreateIfNotExists(create){ + if (create.nodes.length===0) return false; + if (create.nodes[0].type!='IF NOT EXISTS') return false; + return true; +} + +function isCreateTemporary(create){ + return create.options.isTemporary; +} + +function isDropIfExists(drop){ + if (drop.nodes.length===0) return false; + if (drop.nodes[0].type!='IF EXISTS') return false; + return true; +} + +// SQL Server does not support array expressions except in the IN clause. +function isRightSideArray(binary){ + return Array.isArray(binary.right); +} + +function isCountStarExpression(columnNode){ + if (!columnNode.aggregator) return false; + if (columnNode.aggregator.toLowerCase()!='count') return false; + if (!columnNode.star) return false; + return true; +} + +function isAlterAddColumn(alter){ + if (alter.nodes.length===0) return false; + if (alter.nodes[0].type!='ADD COLUMN') return false; + return true; +} + +function isAlterDropColumn(alter){ + if (alter.nodes.length===0) return false; + if (alter.nodes[0].type!='DROP COLUMN') return false; + return true; +} + +module.exports = Oracle; diff --git a/lib/dialect/postgres.js b/lib/dialect/postgres.js index 7ba997b5..9b81af25 100644 --- a/lib/dialect/postgres.js +++ b/lib/dialect/postgres.js @@ -6,9 +6,10 @@ var From = require('../node/from'); var Select = require('../node/select'); var Table = require('../table'); -var Postgres = function() { +var Postgres = function(config) { this.output = []; this.params = []; + this.config = config || {}; }; Postgres.prototype._myClass = Postgres; @@ -25,7 +26,7 @@ Postgres.prototype._getParameterText = function(index, value) { } }; -Postgres.prototype._getParameterValue = function(value) { +Postgres.prototype._getParameterValue = function(value, quoteChar) { // handle primitives if (null === value) { value = 'NULL'; @@ -35,22 +36,39 @@ Postgres.prototype._getParameterValue = function(value) { // number is just number value = value; } else if ('string' === typeof value) { - // string uses single quote - value = this.quote(value, "'"); + // string uses single quote by default + value = this.quote(value, quoteChar || "'"); } else if ('object' === typeof value) { - if (_.isArray(value)) { - // convert each element of the array - value = _.map(value, this._getParameterValue, this); - value = '(' + value.join(', ') + ')'; - } else if (_.isFunction(value.toISOString)) { + if (Array.isArray(value)) { + if (this._myClass === Postgres) { + // naive check to see if this is an array of objects, which + // is handled differently than an array of primitives + if (value.length && 'object' === typeof value[0] && + !_.isFunction(value[0].toISOString) && + !Array.isArray(value[0])) { + value = "'" + JSON.stringify(value) + "'"; + } else { + var self = this; + value = value.map(function (item) { + // In a Postgres array, strings must be double-quoted + return self._getParameterValue(item, '"'); + }); + value = '\'{' + value.join(',') + '}\''; + } + } else { + value = _.map(value, this._getParameterValue.bind(this)); + value = '(' + value.join(', ') + ')'; + } + } else if (value instanceof Date) { // Date object's default toString format does not get parsed well - // Handle date like objects using toISOString + // Handle dates using toISOString value = this._getParameterValue(value.toISOString()); } else if (Buffer.isBuffer(value)) { value = this._getParameterValue('\\x' + value.toString('hex')); } else { // rich object represent with string - value = this._getParameterValue(value.toString()); + var strValue = value.toString(); + value = strValue === '[object Object]' ? this._getParameterValue(JSON.stringify(value)) : this._getParameterValue(strValue); } } else { throw new Error('Unable to use ' + value + ' in query'); @@ -72,6 +90,16 @@ Postgres.prototype.getQuery = function(queryNode) { } this.output = this.visit(queryNode); + //if is a create view, must replace paramaters with values + if (this.output.indexOf('CREATE VIEW') > -1) { + var previousFlagStatus = this._disableParameterPlaceholders; + this._disableParameterPlaceholders = true; + this.output = []; + this.output = this.visit(queryNode); + this.params = []; + this._disableParameterPlaceholders = previousFlagStatus; + } + // create the query object var query = { text: this.output.join(' '), values: this.params }; @@ -103,10 +131,14 @@ Postgres.prototype.visit = function(node) { case 'SUBQUERY' : return this.visitSubquery(node); case 'SELECT' : return this.visitSelect(node); case 'INSERT' : return this.visitInsert(node); + case 'REPLACE' : return this.visitReplace(node); case 'UPDATE' : return this.visitUpdate(node); case 'DELETE' : return this.visitDelete(node); case 'CREATE' : return this.visitCreate(node); case 'DROP' : return this.visitDrop(node); + case 'TRUNCATE' : return this.visitTruncate(node); + case 'DISTINCT' : return this.visitDistinct(node); + case 'DISTINCT ON' : return this.visitDistinctOn(node); case 'ALIAS' : return this.visitAlias(node); case 'ALTER' : return this.visitAlter(node); case 'CAST' : return this.visitCast(node); @@ -117,10 +149,13 @@ Postgres.prototype.visit = function(node) { case 'GROUP BY' : return this.visitGroupBy(node); case 'HAVING' : return this.visitHaving(node); case 'RETURNING' : return this.visitReturning(node); + case 'ONDUPLICATE' : return this.visitOnDuplicate(node); + case 'ONCONFLICT' : return this.visitOnConflict(node); case 'FOR UPDATE' : return this.visitForUpdate(); case 'FOR SHARE' : return this.visitForShare(); case 'TABLE' : return this.visitTable(node); case 'COLUMN' : return this.visitColumn(node); + case 'FOREIGN KEY' : return this.visitForeignKey(node); case 'JOIN' : return this.visitJoin(node); case 'LITERAL' : return this.visitLiteral(node); case 'TEXT' : return node.text; @@ -128,6 +163,7 @@ Postgres.prototype.visit = function(node) { case 'DEFAULT' : return this.visitDefault(node); case 'IF EXISTS' : return this.visitIfExists(); case 'IF NOT EXISTS' : return this.visitIfNotExists(); + case 'OR IGNORE' : return this.visitOrIgnore(); case 'CASCADE' : return this.visitCascade(); case 'RESTRICT' : return this.visitRestrict(); case 'RENAME' : return this.visitRename(node); @@ -139,6 +175,8 @@ Postgres.prototype.visit = function(node) { case 'DROP INDEX' : return this.visitDropIndex(node); case 'FUNCTION CALL' : return this.visitFunctionCall(node); case 'ARRAY CALL' : return this.visitArrayCall(node); + case 'CREATE VIEW' : return this.visitCreateView(node); + case 'INTERVAL' : return this.visitInterval(node); case 'POSTFIX UNARY' : return this.visitPostfixUnary(node); case 'PREFIX UNARY' : return this.visitPrefixUnary(node); @@ -159,6 +197,8 @@ Postgres.prototype.visit = function(node) { }; Postgres.prototype._quoteCharacter = '"'; +Postgres.prototype._aliasText = ' AS '; + Postgres.prototype.quote = function(word, quoteCharacter) { var q; if (quoteCharacter) { @@ -167,13 +207,30 @@ Postgres.prototype.quote = function(word, quoteCharacter) { } else { q = this._quoteCharacter; } - - return q + word.replace(new RegExp(q,'g'),q+q) + q; + // handle square brackets specially + if (q=='['){ + return '['+word+']'; + } else { + return q + word.replace(new RegExp(q,'g'),q+q) + q; + } }; Postgres.prototype.visitSelect = function(select) { - var result = ['SELECT', select.nodes.map(this.visit.bind(this)).join(', ')]; + var result = ['SELECT']; + + if (select.isDistinct) result.push('DISTINCT'); + + var distinctOnNode = select.nodes.filter(function (node) {return node.type === 'DISTINCT ON';}).shift(); + var nonDistinctOnNodes = select.nodes.filter(function (node) {return node.type !== 'DISTINCT ON';}); + + if (distinctOnNode) { + result.push(this.visit(distinctOnNode)); + } + + result.push(nonDistinctOnNodes.map(this.visit.bind(this)).join(', ')); + this._selectOrDeleteEndIndex = this.output.length + result.length; + return result; }; @@ -182,11 +239,10 @@ Postgres.prototype.visitInsert = function(insert) { // don't use table.column for inserts this._visitedInsert = true; - var result = [ - 'INSERT INTO', - this.visit(this._queryNode.table.toNode()), - '(' + insert.columns.map(this.visit.bind(this)).join(', ') + ')' - ]; + var result = ['INSERT']; + result = result.concat(insert.nodes.map(this.visit.bind(this))); + result.push('INTO ' + this.visit(this._queryNode.table.toNode())); + result.push('(' + insert.columns.map(this.visit.bind(this)).join(', ') + ')'); var paramNodes = insert.getParameters(); @@ -206,9 +262,15 @@ Postgres.prototype.visitInsert = function(insert) { } } + this._visitedInsert = false; + return result; }; +Postgres.prototype.visitReplace = function(replace) { + throw new Error('Postgres does not support REPLACE.'); +}; + Postgres.prototype.visitUpdate = function(update) { // don't auto-generate from clause var params = []; @@ -242,11 +304,30 @@ Postgres.prototype.visitCreate = function(create) { // don't auto-generate from clause var table = this._queryNode.table; var col_nodes = table.columns.map(function(col) { return col.toNode(); }); + var foreign_key_nodes = table.foreignKeys; - var result = ['CREATE TABLE']; + var result = ['CREATE TABLE']; + if (create.options.isTemporary) result=['CREATE TEMPORARY TABLE']; result = result.concat(create.nodes.map(this.visit.bind(this))); result.push(this.visit(table.toNode())); - result.push('(' + col_nodes.map(this.visit.bind(this)).join(', ') + ')'); + var primary_col_nodes = col_nodes.filter(function(n) { + return n.primaryKey; + }); + this._visitCreateCompoundPrimaryKey = primary_col_nodes.length > 1; + var colspec = '(' + col_nodes.map(this.visit.bind(this)).join(', '); + if (this._visitCreateCompoundPrimaryKey) { + colspec += ', PRIMARY KEY ('; + colspec += primary_col_nodes.map(function(node) { + return this.quote(node.name); + }.bind(this)).join(', '); + colspec += ')'; + } + if(foreign_key_nodes.length > 0) { + colspec += ', ' + foreign_key_nodes.map(this.visit.bind(this)).join(', '); + } + colspec += ')'; + result.push(colspec); + this._visitCreateCompoundPrimaryKey = false; this._visitingCreate = false; return result; }; @@ -258,8 +339,23 @@ Postgres.prototype.visitDrop = function(drop) { return result; }; +Postgres.prototype.visitTruncate = function(truncate) { + var result = ['TRUNCATE TABLE']; + result = result.concat(truncate.nodes.map(this.visit.bind(this))); + return result; +}; + +Postgres.prototype.visitDistinct = function(truncate) { + // Nothing to do here since it's handled in the SELECT clause + return []; +}; + +Postgres.prototype.visitDistinctOn = function(distinctOn) { + return ['DISTINCT ON('+distinctOn.nodes.map(this.visit.bind(this)).join(', ')+')']; +}; + Postgres.prototype.visitAlias = function(alias) { - var result = [this.visit(alias.value) + ' AS ' + this.quote(alias.alias)]; + var result = [this.visit(alias.value) + this._aliasText + this.quote(alias.alias)]; return result; }; @@ -277,7 +373,9 @@ Postgres.prototype.visitAlter = function(alter) { }; Postgres.prototype.visitCast = function(cast) { + this._visitingCast = true; var result = ['CAST(' + this.visit(cast.value) + ' AS ' + cast.dataType + ')']; + this._visitingCast = false; return result; }; @@ -303,6 +401,9 @@ Postgres.prototype.visitWhere = function(where) { Postgres.prototype.visitOrderBy = function(orderBy) { var result = ['ORDER BY', orderBy.nodes.map(this.visit.bind(this)).join(', ')]; + if (this._myClass === Postgres && this.config.nullOrder) { + result.push('NULLS ' + this.config.nullOrder.toUpperCase()); + } return result; }; @@ -336,6 +437,10 @@ Postgres.prototype.visitPostfixUnary = function(unary) { Postgres.prototype.visitBinary = function(binary) { var self = this; + + binary.left.property = binary.left.name; + binary.right.property = binary.right.name; + var text = '(' + this.visit(binary.left) + ' ' + binary.operator + ' '; if (Array.isArray(binary.right)) { text += '(' + binary.right.map(function (node) { @@ -463,7 +568,7 @@ Postgres.prototype.visitCase = function(caseExp) { text += whenExp + thenExp; } - if (null != caseExp.else && undefined != caseExp.else) { + if (null !== caseExp.else && undefined !== caseExp.else) { text += ' ELSE ' + this.visit(caseExp.else); } @@ -471,7 +576,7 @@ Postgres.prototype.visitCase = function(caseExp) { text += ' END)'; return [text]; -} +}; Postgres.prototype.visitAt = function(at) { var text = '(' + this.visit(at.value) + ')[' + this.visit(at.index) + ']'; @@ -503,12 +608,14 @@ Postgres.prototype.visitOverlap = function(overlap) { }; Postgres.prototype.visitQuery = function(queryNode) { + if (this._queryNode) return this.visitSubquery(queryNode,dontParenthesizeSubQuery(this._queryNode)); this._queryNode = queryNode; // need to sort the top level query nodes on visitation priority // so select/insert/update/delete comes before from comes before where - var sortedNodes = []; var missingFrom = true; var hasFrom = false; + var createView; + var isSelect = false; var actions = []; var targets = []; var filters = []; @@ -516,14 +623,17 @@ Postgres.prototype.visitQuery = function(queryNode) { var node = queryNode.nodes[i]; switch(node.type) { case "SELECT": + isSelect = true; // jshint ignore:line case "DELETE": actions.push(node); break; case "INDEXES": case "INSERT": + case "REPLACE": case "UPDATE": case "CREATE": case "DROP": + case "TRUNCATE": case "ALTER": actions.push(node); missingFrom = false; @@ -534,6 +644,9 @@ Postgres.prototype.visitQuery = function(queryNode) { missingFrom = false; targets.push(node); break; + case "CREATE VIEW": + createView = node; + break; default: filters.push(node); break; @@ -542,13 +655,35 @@ Postgres.prototype.visitQuery = function(queryNode) { if(!actions.length) { // if no actions are given, guess it's a select actions.push(new Select().add('*')); + isSelect = true; } - if(missingFrom) { + if(missingFrom && queryNode.table instanceof Table) { + // the instanceof handles the situation where a sql.select(some expression) is used and there should be no FROM clause targets.push(new From().add(queryNode.table)); } + if (createView) { + if (isSelect) { + actions.unshift(createView); + } else { + throw new Error('Create View requires a Select.'); + } + } + return this.visitQueryHelper(actions,targets,filters); +}; + +/** + * We separate out this part of query building so it can be overridden by other implementations. + * + * @param {Node[]} actions + * @param {Node[]} targets + * @param {Node[]} filters + * @returns {String[]} + */ +Postgres.prototype.visitQueryHelper=function(actions,targets,filters){ + this.handleDistinct(actions, filters); // lazy-man sorting - sortedNodes = actions.concat(targets).concat(filters); - for(i = 0; i < sortedNodes.length; i++) { + var sortedNodes = actions.concat(targets).concat(filters); + for(var i = 0; i < sortedNodes.length; i++) { var res = this.visit(sortedNodes[i]); this.output = this.output.concat(res); } @@ -556,9 +691,9 @@ Postgres.prototype.visitQuery = function(queryNode) { return this.output; }; -Postgres.prototype.visitSubquery = function(queryNode) { +Postgres.prototype.visitSubquery = function(queryNode,dontParenthesize) { // create another query builder of the current class to build the subquery - var subQuery = new this._myClass(); + var subQuery = new this._myClass(this.config); // let the subquery modify this instance's params array subQuery.params = this.params; @@ -574,7 +709,10 @@ Postgres.prototype.visitSubquery = function(queryNode) { } var alias = queryNode.alias; - return ['(' + subQuery.output.join(' ') + ')' + (alias ? ' ' + alias : '')]; + if (dontParenthesize) { + return [subQuery.output.join(' ') + (alias ? ' ' + this.quote(alias) : '')]; + } + return ['(' + subQuery.output.join(' ') + ')' + (alias ? ' ' + this.quote(alias) : '')]; }; Postgres.prototype.visitTable = function(tableNode) { @@ -585,27 +723,30 @@ Postgres.prototype.visitTable = function(tableNode) { txt += '.'; } txt += this.quote(table.getName()); - if(table.alias) { - txt += ' AS ' + this.quote(table.alias); + if(typeof table.alias === 'string') { + txt += this._aliasText + this.quote(table.alias); } return [txt]; }; Postgres.prototype.visitColumn = function(columnNode) { var table = columnNode.table; - var inInsertUpdateClause = this._visitedInsert || this._visitingUpdateTargetColumn; + var inInsertUpdateClause = this._visitedInsert || this._visitedReplace || this._visitingUpdateTargetColumn; var inDdlClause = this._visitingAddColumn || this._visitingAlter || this._visitingCreate; var inSelectClause = this.visitingReturning || (!this._selectOrDeleteEndIndex - && !this._visitingWhere - && !inInsertUpdateClause - && !inDdlClause - && !this.visitingCase + && !this._visitingWhere // jshint ignore:line + && !inInsertUpdateClause // jshint ignore:line + && !inDdlClause // jshint ignore:line + && !this.visitingCase // jshint ignore:line + && !this._visitingJoin // jshint ignore:line ); + var inFunctionCall = this._visitingFunctionCall; + var inCast = this._visitingCast; var txt = []; var closeParen = 0; - if(inSelectClause && (!table.alias || !!columnNode.alias)) { + if(inSelectClause && (table && !table.alias || !!columnNode.alias)) { if (columnNode.asArray) { closeParen++; txt.push(this._arrayAggFunctionName+'('); @@ -621,55 +762,198 @@ Postgres.prototype.visitColumn = function(columnNode) { txt.push('DISTINCT('); } } - if(!inInsertUpdateClause && !this._visitingCreate && !this._visitingAlter) { - if(table.alias) { - txt.push(this.quote(table.alias)); - } else { - if(table.getSchema()) { - txt.push(this.quote(table.getSchema())); - txt.push('.'); + if(!inInsertUpdateClause && !this.visitingReturning && !this._visitingCreate && !this._visitingAlter && !columnNode.subfieldContainer) { + if (table) { + if (typeof table.alias === 'string') { + txt.push(this.quote(table.alias)); + } else { + if (table.getSchema()) { + txt.push(this.quote(table.getSchema())); + txt.push('.'); + } + txt.push(this.quote(table.getName())); } - txt.push(this.quote(table.getName())); + txt.push('.'); } - txt.push('.'); } if (columnNode.star) { var allCols = []; var hasAliases = false; - for(var i = 0; i < table.columns.length; ++i){ - var col = table.columns[i]; - var aliased = col.name !== (col.alias || col.property); - hasAliases = hasAliases || aliased; - allCols.push(this.quote(col.name) + (aliased ? ' AS ' + this.quote(col.alias || col.property) : '')); + if(columnNode.aggregator !== 'COUNT') { + var tableName = txt.join(''); + for (var i = 0; i < table.columns.length; ++i) { + var col = table.columns[i]; + var aliased = col.name !== (col.alias || col.property); + hasAliases = hasAliases || aliased; + allCols.push(tableName + this.quote(col.name) + (aliased ? this._aliasText + this.quote(col.alias || col.property) : '')); + } + } + if(hasAliases) { + txt = [allCols.join(', ')]; } - txt.push(hasAliases ? allCols.join(', ') : '*'); + else { + txt.push('*'); + } + } + else if (columnNode.isConstant) { + // this injects directly into SELECT statement rather than creating a parameter + // txt.push(this._getParameterValue(columnNode.literalValue)) + // currently thinking it is better to generate a parameter + var value = columnNode.constantValue; + this.params.push(value); + txt.push(this._getParameterText(this.params.length, value)); } else { + if (columnNode.subfieldContainer) { + txt.push('(' + this.visitColumn(columnNode.subfieldContainer) + ').'); + } txt.push(this.quote(columnNode.name)); } if(closeParen) { - for(var i = 0; i < closeParen; i++) { + for(var j = 0; j < closeParen; j++) { txt.push(')'); } } - if(inSelectClause && (columnNode.alias || columnNode.property !== columnNode.name)) { - txt.push(' AS ' + this.quote(columnNode.alias || columnNode.property)); + if(inSelectClause && !inFunctionCall && !inCast && (columnNode.alias || columnNode.property !== columnNode.name)) { + txt.push(this._aliasText + this.quote(columnNode.alias || columnNode.property)); } if(this._visitingCreate || this._visitingAddColumn) { assert(columnNode.dataType, 'dataType missing for column ' + columnNode.name + ' (CREATE TABLE and ADD COLUMN statements require a dataType)'); txt.push(' ' + columnNode.dataType); - if (this._visitingCreate && columnNode.primaryKey) { - // creating a column as a primary key - txt.push(' PRIMARY KEY'); + if (this._visitingCreate) { + if (columnNode.primaryKey && !this._visitCreateCompoundPrimaryKey) { + // creating a column as a primary key + txt.push(' PRIMARY KEY'); + } else if (columnNode.notNull) { + txt.push(' NOT NULL'); + } + if (!columnNode.primaryKey && columnNode.unique) { + txt.push(' UNIQUE'); + } + if (columnNode.defaultValue !== undefined) { + txt.push(' DEFAULT ' + this._getParameterValue(columnNode.defaultValue)); + } + } + + if (!!columnNode.references) { + assert.equal(typeof (columnNode.references), 'object', + 'references is not a object for column ' + columnNode.name + + ' (REFERENCES statements within CREATE TABLE and ADD COLUMN statements' + + ' require refrences to be expressed as an object)'); + + //Empty refrence objects are ok + if (Object.keys(columnNode.references).length > 0){ + assert(columnNode.references.table, 'reference.table missing for column ' + + columnNode.name + + ' (REFERENCES statements within CREATE TABLE and ADD COLUMN statements' + + ' require a table and column)'); + assert(columnNode.references.column, 'reference.column missing for column ' + + columnNode.name + + ' (REFERENCES statements within CREATE TABLE and ADD COLUMN statements' + + ' require a table and column)'); + txt.push(' REFERENCES '); + if(columnNode.references.schema) { + txt.push(this.quote(columnNode.references.schema) + '.'); + } + txt.push(this.quote(columnNode.references.table) + '(' + + this.quote(columnNode.references.column) + ')'); + + var onDelete = columnNode.references.onDelete; + if (onDelete) onDelete = onDelete.toUpperCase(); + if (onDelete === 'CASCADE' || onDelete === 'RESTRICT' || onDelete === 'SET NULL' || onDelete === 'SET DEFAULT' || onDelete === 'NO ACTION') { + txt.push(' ON DELETE ' + onDelete); + } + var onUpdate = columnNode.references.onUpdate; + if (onUpdate) onUpdate = onUpdate.toUpperCase(); + if (onUpdate === 'CASCADE' || onUpdate === 'RESTRICT' || onUpdate === 'SET NULL' || onUpdate === 'SET DEFAULT' || onUpdate === 'NO ACTION') { + txt.push(' ON UPDATE ' + onUpdate); + } + var constraint = columnNode.references.constraint; + if (constraint) { + constraint = ' ' + constraint.toUpperCase(); + txt.push(constraint); + } + } + } + } + return [txt.join('')]; +}; + +Postgres.prototype.visitForeignKey = function(foreignKeyNode) +{ + var txt = []; + if(this._visitingCreate) { + assert(foreignKeyNode.table, 'Foreign table missing for table reference'); + assert(foreignKeyNode.columns, 'Columns missing for table reference'); + if(foreignKeyNode.refColumns !== undefined) { + assert.equal(foreignKeyNode.columns.length, foreignKeyNode.refColumns.length, 'Number of local columns and foreign columns differ in table reference'); + } + if(foreignKeyNode.name !== undefined) { + txt.push('CONSTRAINT ' + this.quote(foreignKeyNode.name) + ' '); + } + txt.push('FOREIGN KEY ( '); + for(var i = 0; i < foreignKeyNode.columns.length; i++) { + if(i>0) { + txt.push(', '); + } + txt.push(this.quote(foreignKeyNode.columns[i])); + } + txt.push(' ) REFERENCES '); + if(foreignKeyNode.schema !== undefined) { + txt.push(this.quote(foreignKeyNode.schema) + '.'); + } + txt.push(this.quote(foreignKeyNode.table)); + if(foreignKeyNode.refColumns !== undefined) { + txt.push(' ( '); + for(i = 0; i < foreignKeyNode.refColumns.length; i++) { + if(i>0) { + txt.push(', '); + } + txt.push(this.quote(foreignKeyNode.refColumns[i])); + } + txt.push(' )'); + } + var onDelete = foreignKeyNode.onDelete; + if(onDelete) { + onDelete = onDelete.toUpperCase(); + if(onDelete === 'CASCADE' || onDelete === 'RESTRICT' || onDelete === 'SET NULL' || onDelete === 'SET DEFAULT' || onDelete === 'NO ACTION') { + txt.push(' ON DELETE ' + onDelete); + } + } + var onUpdate = foreignKeyNode.onUpdate; + if(onUpdate) { + onUpdate = onUpdate.toUpperCase(); + if(onUpdate === 'CASCADE' || onUpdate === 'RESTRICT' || onUpdate === 'SET NULL' || onUpdate === 'SET DEFAULT' || onUpdate === 'NO ACTION') { + txt.push(' ON UPDATE ' + onUpdate); + } + } + if(foreignKeyNode.constraint) { + txt.push(' ' + foreignKeyNode.constraint.toUpperCase()); } } return [txt.join('')]; }; Postgres.prototype.visitFunctionCall = function(functionCall) { - var txt = functionCall.name + '(' + functionCall.nodes.map(this.visit.bind(this)).join(', ') + ')'; + this._visitingFunctionCall = true; + var _this = this; + + function _extract() { + var nodes = functionCall.nodes.map(_this.visit.bind(_this)); + if (nodes.length != 1) throw new Error('Not enough parameters passed to ' + functionCall.name + ' function'); + var txt = 'EXTRACT(' + functionCall.name + ' FROM ' + (nodes[0]+'') + ')'; + return txt; + } + + var txt = ""; + // Override date functions since postgres (and others) uses extract + if (['YEAR', 'MONTH', 'DAY', 'HOUR'].indexOf(functionCall.name) >= 0) txt = _extract(); + // Override CURRENT_TIMESTAMP function to remove parens + else if ('CURRENT_TIMESTAMP' == functionCall.name) txt = functionCall.name; + else txt = functionCall.name + '(' + functionCall.nodes.map(this.visit.bind(this)).join(', ') + ')'; + this._visitingFunctionCall = false; return [txt]; }; @@ -717,6 +1001,10 @@ Postgres.prototype.visitIfNotExists = function() { return ['IF NOT EXISTS']; }; +Postgres.prototype.visitOrIgnore = function() { + throw new Error('PostgreSQL does not allow orIgnore clause.'); +}; + Postgres.prototype.visitCascade = function() { return ['CASCADE']; }; @@ -734,7 +1022,9 @@ Postgres.prototype.visitForShare = function() { }; Postgres.prototype.visitJoin = function(join) { + if (join.subType === 'LEFT LATERAL') return this.visitLeftJoinLateral(join); var result = []; + this._visitingJoin = true; result = result.concat(this.visit(join.from)); result = result.concat(join.subType + ' JOIN'); result = result.concat(this.visit(join.to)); @@ -743,10 +1033,20 @@ Postgres.prototype.visitJoin = function(join) { return result; }; +Postgres.prototype.visitLeftJoinLateral = function(join) { + var result = []; + this._visitingJoin = true; + result = result.concat(this.visit(join.from)); + result = result.concat('LEFT JOIN LATERAL'); + result = result.concat(this.visit(join.to)); + result = result.concat('ON true'); + return result; +}; + Postgres.prototype.visitLiteral = function(node) { var txt = [node.literal]; if(node.alias) { - txt.push(' AS ' + this.quote(node.alias)); + txt.push(this._aliasText + this.quote(node.alias)); } return [txt.join('')]; }; @@ -759,20 +1059,57 @@ Postgres.prototype.visitReturning = function(returning) { return r; }; +Postgres.prototype.visitOnDuplicate = function(onDuplicate) { + throw new Error('PostgreSQL does not allow onDuplicate clause.'); +}; + +Postgres.prototype.visitOnConflict = function(onConflict) { + var result = ['ON CONFLICT']; + var columns = []; + var updateClause = [], i, col; + var table = this._queryNode.table; + if(onConflict.constraint) + result.push(['ON CONSTRAINT', this.quote(onConflict.constraint)].join(' ')); + else if(onConflict.columns) { + for(i=0; i < onConflict.columns.length; i++) { + columns.push(this.quote(table.getColumn(onConflict.columns[i]).name)); + } + result.push( '(' + columns.join(', ') + ')' ); + } + + if(onConflict.update){ + updateClause.push("DO UPDATE SET"); + var update = onConflict.update; + var setClause = []; + for(i=0; i 0) { + var paramText = paramNodes.map(function (paramSet) { + return paramSet.map(function (param) { + return self.visit(param); + }).join(', '); + }).map(function (param) { + return '('+param+')'; + }).join(', '); + + result.push('VALUES', paramText); + + if (result.slice(2, 5).join(' ') === '() VALUES ()') { + result.splice(2, 3, 'DEFAULT VALUES'); + } + } + + this._visitedReplace = false; + + return result; +}; + Sqlite.prototype._getParameterValue = function(value) { if (Buffer.isBuffer(value)) { value = 'x' + this._getParameterValue(value.toString('hex')); + } else if (value instanceof Date && this.config.dateTimeMillis) { + value = value.getTime(); + } else if('boolean' === typeof value) { + value = value ? 1 : 0; + } else if(_.isArray(value)) { + value = Postgres.prototype._getParameterValue.call(this, JSON.stringify(value)); } else { value = Postgres.prototype._getParameterValue.call(this, value); } @@ -34,10 +75,87 @@ Sqlite.prototype.visitDropColumn = function() { throw new Error('SQLite does not allow dropping columns.'); }; +Sqlite.prototype.visitFunctionCall = function (functionCall) { + var _this = this; + + this._visitingFunctionCall = true; + + function _left() { + // convert LEFT(column,4) to SUBSTR(column,1,4) + var nodes = functionCall.nodes.map(_this.visit.bind(_this)); + if (nodes.length != 2) throw new Error('Not enough parameters passed to LEFT function.'); + var txt = "SUBSTR(" + (nodes[0] + '') + ', 1, ' + (nodes[1] + '') + ')'; + return txt; + } + + function _right() { + // convert RIGHT(column,4) to SUBSTR(column,-4) + var nodes = functionCall.nodes.map(_this.visit.bind(_this)); + if (nodes.length != 2) throw new Error('Not enough parameters passed to RIGHT function.'); + var txt = "SUBSTR(" + (nodes[0] + '') + ', -' + (nodes[1] + '') + ')'; + return txt; + } + + function _extract() { + var nodes = functionCall.nodes.map(_this.visit.bind(_this)); + if (nodes.length != 1) throw new Error('Not enough parameters passed to ' + functionCall.name + ' function'); + var format; + switch (functionCall.name) { + case 'YEAR': + format = "'%Y'"; + break; + case 'MONTH': + format = "'%m'"; + break; + case 'DAY': + format = "'%d'"; + break; + case 'HOUR': + format = "'%H'"; + break; + } + var col = (nodes[0] + ''); + if (_this.config.dateTimeMillis) { + // Convert to a datetime before running the strftime function + // Sqlite unix epoch is in seconds, but javascript is milliseconds. + col = 'datetime(' + col + '/1000, "unixepoch")'; + } + var txt = 'strftime(' + format + ', ' + col + ')'; + return txt; + } + + var txt = ""; + var name = functionCall.name; + // Override LEFT and RIGHT and convert to SUBSTR + if (name == "LEFT") txt = _left(); + else if (name == "RIGHT") txt = _right(); + // Override date functions since sqlite uses strftime + else if (['YEAR', 'MONTH', 'DAY', 'HOUR'].indexOf(functionCall.name) >= 0) txt = _extract(); + else if ('CURRENT_TIMESTAMP' == functionCall.name) txt = functionCall.name; + else txt = name + '(' + functionCall.nodes.map(this.visit.bind(this)).join(', ') + ')'; + + this._visitingFunctionCall = false; + return [txt]; +}; + +Sqlite.prototype.visitTruncate = function(truncate) { + var result = ['DELETE FROM']; + result = result.concat(truncate.nodes.map(this.visit.bind(this))); + return result; +}; + Sqlite.prototype.visitRenameColumn = function() { throw new Error('SQLite does not allow renaming columns.'); }; +Sqlite.prototype.visitOnDuplicate = function() { + throw new Error('SQLite does not allow onDuplicate clause.'); +}; + +Sqlite.prototype.visitOnConflict = function(onConflict) { + throw new Error('Sqlite does not allow onConflict clause.'); +}; + Sqlite.prototype.visitReturning = function() { throw new Error('SQLite does not allow returning clause.'); }; @@ -70,4 +188,18 @@ Sqlite.prototype.visitRestrict = function() { throw new Error('Sqlite do not support RESTRICT in DROP TABLE'); }; +Sqlite.prototype.visitBinary = function(binary) { + if(binary.operator === '@@'){ + binary.operator = 'MATCH'; + var ret = Sqlite.super_.prototype.visitBinary.call(this, binary); + binary.operator = '@@'; + return ret; + } + return Sqlite.super_.prototype.visitBinary.call(this, binary); +}; + +Sqlite.prototype.visitOrIgnore = function() { + return ['OR IGNORE']; +}; + module.exports = Sqlite; diff --git a/lib/functions.js b/lib/functions.js index 8186161a..fe9cdaaf 100644 --- a/lib/functions.js +++ b/lib/functions.js @@ -1,22 +1,23 @@ 'use strict'; var _ = require('lodash'); var sliced = require('sliced'); -var FunctionCall = require(__dirname + '/node/functionCall'); +var FunctionCall = require('./node/functionCall'); // create a function that creates a function call of the specific name, using the specified sql instance -var getFunctionCallCreator = function(name, sql) { +var getFunctionCallCreator = function(name) { return function() { // turn array-like arguments object into a true array - var functionCall = new FunctionCall(name, sliced(arguments)); - functionCall.sql = sql; - return functionCall; + return new FunctionCall(name, sliced(arguments)); }; }; // creates a hash of functions for a sql instance -var getFunctions = function(functionNames, sql) { +var getFunctions = function(functionNames) { + if (typeof functionNames === 'string') + return getFunctionCallCreator(functionNames); + var functions = _.reduce(functionNames, function(reducer, name) { - reducer[name] = getFunctionCallCreator(name, sql); + reducer[name] = getFunctionCallCreator(name); return reducer; }, {}); return functions; @@ -35,11 +36,13 @@ var aggregateFunctions = [ // common scalar functions available to most databases var scalarFunctions = [ 'ABS', - 'COALESC', + 'COALESCE', + 'LEFT', 'LENGTH', 'LOWER', 'LTRIM', 'RANDOM', + 'RIGHT', 'ROUND', 'RTRIM', 'SUBSTR', @@ -47,14 +50,26 @@ var scalarFunctions = [ 'UPPER' ]; +var dateFunctions = [ + 'YEAR', + 'MONTH', + 'DAY', + 'HOUR', + 'CURRENT_TIMESTAMP' +]; + // hstore function available to Postgres var hstoreFunction = 'HSTORE'; -var standardFunctionNames = aggregateFunctions.concat(scalarFunctions).concat(hstoreFunction); +//text search functions available to Postgres +var textsearchFunctions = ['TS_RANK','TS_RANK_CD', 'PLAINTO_TSQUERY', 'TO_TSQUERY', 'TO_TSVECTOR', 'SETWEIGHT']; + +var standardFunctionNames = aggregateFunctions.concat(scalarFunctions).concat(hstoreFunction).concat(textsearchFunctions).concat(dateFunctions); // creates a hash of standard functions for a sql instance -var getStandardFunctions = function(sql) { - return getFunctions(standardFunctionNames, sql); +var getStandardFunctions = function() { + return getFunctions(standardFunctionNames); }; +module.exports.getFunctions = getFunctions; module.exports.getStandardFunctions = getStandardFunctions; diff --git a/lib/index.js b/lib/index.js index 75d1c2e7..f26ad827 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,22 +1,26 @@ 'use strict'; var _ = require('lodash'); +var Column = require("./column"); var FunctionCall = require('./node/functionCall'); var ArrayCall = require('./node/arrayCall'); var functions = require('./functions'); var getDialect = require('./dialect'); +var JoinNode = require('./node/join'); var Query = require('./node/query'); var sliced = require('sliced'); var Table = require('./table'); +var Interval = require('./node/interval'); // default dialect is postgres var DEFAULT_DIALECT = 'postgres'; -var Sql = function(dialect) { - this.setDialect(dialect || DEFAULT_DIALECT); +var Sql = function(dialect, config) { + this.setDialect(dialect || DEFAULT_DIALECT, config); // attach the standard SQL functions to this instance - this.functions = functions.getStandardFunctions(this); + this.functions = functions.getStandardFunctions(); + this.function = functions.getFunctions; }; // Define a table @@ -30,11 +34,8 @@ Sql.prototype.define = function(def) { // Returns a function call creator Sql.prototype.functionCallCreator = function(name) { - var sql = this; return function() { - var functionCall = new FunctionCall(name, sliced(arguments)); - functionCall.sql = sql; - return functionCall; + return new FunctionCall(name, sliced(arguments)); }; }; @@ -52,20 +53,52 @@ Sql.prototype.select = function() { return query; }; +// Returns a subQuery clause +Sql.prototype.subQuery = function(alias) { + // create the query and pass it off + var query = new Query(this); + query.type = 'SUBQUERY'; + query.alias = alias; + query.join = function(other) { + return new JoinNode('INNER', this.toNode(), other.toNode(), other); + }; + return query; +}; + +// Returns an interval clause +Sql.prototype.interval = function() { + var interval = new Interval(sliced(arguments)); + return interval; +}; + // Set the dialect -Sql.prototype.setDialect = function(dialect) { +Sql.prototype.setDialect = function(dialect, config) { this.dialect = getDialect(dialect); this.dialectName = dialect; + this.config = config; return this; }; +// Create a constant Column (for use in SELECT) +Sql.prototype.constant = function(value) { + var config={ + name:"constant", + property:"constant", + isConstant:true, + constantValue:value, + }; + var cn = new Column(config); + return cn; +}; + + // back compat shim for the Sql class constructor -var create = function(dialect) { - return new Sql(dialect); +var create = function(dialect, config) { + return new Sql(dialect, {}); }; -module.exports = new Sql(DEFAULT_DIALECT); +module.exports = new Sql(DEFAULT_DIALECT, {}); module.exports.create = create; module.exports.Sql = Sql; module.exports.Table = Table; diff --git a/lib/node/addColumn.js b/lib/node/addColumn.js index 273d8836..3d7d4066 100644 --- a/lib/node/addColumn.js +++ b/lib/node/addColumn.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'ADD COLUMN' diff --git a/lib/node/alias.js b/lib/node/alias.js index 78f01323..9f9855f5 100644 --- a/lib/node/alias.js +++ b/lib/node/alias.js @@ -1,7 +1,7 @@ 'use strict'; var _ = require('lodash'); -var Node = require(__dirname); +var Node = require('./index'); var AliasNode = Node.define({ type: 'ALIAS', diff --git a/lib/node/alter.js b/lib/node/alter.js index ce53623c..4aae4d83 100644 --- a/lib/node/alter.js +++ b/lib/node/alter.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'ALTER' diff --git a/lib/node/arrayCall.js b/lib/node/arrayCall.js index 4f2f657b..7533190d 100644 --- a/lib/node/arrayCall.js +++ b/lib/node/arrayCall.js @@ -1,9 +1,9 @@ 'use strict'; var _ = require('lodash'); -var Node = require(__dirname); -var ParameterNode = require(__dirname + '/parameter'); -var valueExpressionMixin = require(__dirname + '/valueExpression'); +var Node = require('./index'); +var ParameterNode = require('./parameter'); +var valueExpressionMixin = require('./valueExpression'); var ArrayCallNode = Node.define({ type: 'ARRAY CALL', @@ -18,7 +18,7 @@ var ArrayCallNode = Node.define({ _.extend(ArrayCallNode.prototype, valueExpressionMixin()); // allow aliasing -var AliasNode = require(__dirname + '/alias'); +var AliasNode = require('./alias'); _.extend(ArrayCallNode.prototype, AliasNode.AliasMixin); module.exports = ArrayCallNode; diff --git a/lib/node/at.js b/lib/node/at.js index 2ded9362..5e8ca47b 100644 --- a/lib/node/at.js +++ b/lib/node/at.js @@ -1,8 +1,8 @@ 'use strict'; var _ = require('lodash'); -var Node = require(__dirname); -var valueExpressionMixin = require(__dirname + '/valueExpression'); +var Node = require('./index'); +var valueExpressionMixin = require('./valueExpression'); var valueExpressionMixed = false; var AtNode = Node.define({ @@ -21,7 +21,7 @@ var AtNode = Node.define({ }); // allow aliasing -var AliasNode = require(__dirname + '/alias'); +var AliasNode = require('./alias'); _.extend(AtNode.prototype, AliasNode.AliasMixin); module.exports = AtNode; diff --git a/lib/node/binary.js b/lib/node/binary.js index 7b721650..da8eb8bd 100644 --- a/lib/node/binary.js +++ b/lib/node/binary.js @@ -1,8 +1,8 @@ 'use strict'; var _ = require('lodash'); -var Node = require(__dirname); -var valueExpressionMixin = require(__dirname + '/valueExpression'); +var Node = require('./index'); +var valueExpressionMixin = require('./valueExpression'); var valueExpressionMixed = false; var BinaryNode = Node.define(_.extend({ @@ -23,7 +23,7 @@ var BinaryNode = Node.define(_.extend({ })); // allow aliasing -var AliasNode = require(__dirname + '/alias'); +var AliasNode = require('./alias'); _.extend(BinaryNode.prototype, AliasNode.AliasMixin); module.exports = BinaryNode; diff --git a/lib/node/cascade.js b/lib/node/cascade.js index 1dea1eef..4b6646fd 100644 --- a/lib/node/cascade.js +++ b/lib/node/cascade.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'CASCADE' diff --git a/lib/node/case.js b/lib/node/case.js index b8729314..ac3bf214 100644 --- a/lib/node/case.js +++ b/lib/node/case.js @@ -1,8 +1,8 @@ 'use strict'; var _ = require('lodash'); -var Node = require(__dirname); -var valueExpressionMixin = require(__dirname + '/valueExpression'); +var Node = require('./index'); +var valueExpressionMixin = require('./valueExpression'); var valueExpressionMixed = false; var CaseNode = Node.define(_.extend({ @@ -23,7 +23,7 @@ var CaseNode = Node.define(_.extend({ })); // allow aliasing -var AliasNode = require(__dirname + '/alias'); +var AliasNode = require('./alias'); _.extend(CaseNode.prototype, AliasNode.AliasMixin); module.exports = CaseNode; diff --git a/lib/node/cast.js b/lib/node/cast.js index 60966ea9..be915b1e 100644 --- a/lib/node/cast.js +++ b/lib/node/cast.js @@ -1,8 +1,8 @@ 'use strict'; var _ = require('lodash'); -var Node = require(__dirname); -var valueExpressionMixin = require(__dirname + '/valueExpression'); +var Node = require('./index'); +var valueExpressionMixin = require('./valueExpression'); var valueExpressionMixed = false; var CastNode = Node.define({ @@ -21,7 +21,7 @@ var CastNode = Node.define({ }); // allow aliasing -var AliasNode = require(__dirname + '/alias'); +var AliasNode = require('./alias'); _.extend(CastNode.prototype, AliasNode.AliasMixin); module.exports = CastNode; diff --git a/lib/node/column.js b/lib/node/column.js index 98baa363..6b145d74 100644 --- a/lib/node/column.js +++ b/lib/node/column.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'COLUMN', @@ -10,6 +10,8 @@ module.exports = Node.define({ this.property = config.property || config.name; this.alias = config.alias; this.star = config.star; + this.isConstant = config.isConstant; + this.constantValue = config.constantValue; this.asArray = config.asArray; this.aggregator = config.aggregator; this.table = config.table; @@ -17,7 +19,15 @@ module.exports = Node.define({ this.dataType = config.dataType; this.distinct = config.distinct; this.primaryKey = config.primaryKey; + this.notNull = config.notNull; + this.defaultValue = config.defaultValue; + this.references = config.references; + // If subfieldContainer is present, this is a subfield and subfieldContainer + // is the parent Column + this.subfieldContainer = config.subfieldContainer; + this.subfields = config.subfields; this.autoGenerated = !!config.autoGenerated; + this.unique = !!config.unique; }, as: function(alias) { this.alias = alias; diff --git a/lib/node/create.js b/lib/node/create.js index bf535f6a..67cd9b3d 100644 --- a/lib/node/create.js +++ b/lib/node/create.js @@ -1,7 +1,14 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ - type: 'CREATE' + type: 'CREATE', + + constructor: function(isTemporary) { + Node.call(this); + + this.options = { isTemporary: isTemporary}; + }, + }); diff --git a/lib/node/createIndex.js b/lib/node/createIndex.js index 2384ab8e..8f8f0d04 100644 --- a/lib/node/createIndex.js +++ b/lib/node/createIndex.js @@ -49,7 +49,8 @@ module.exports = Node.define({ if (!result) { var columns = this.options.columns.map(function(col) { - return col.name; + var column = col.name ? col.name : col.value.name; + return column; }).sort(); result = [this.table._name]; diff --git a/lib/node/createView.js b/lib/node/createView.js new file mode 100644 index 00000000..7d456d90 --- /dev/null +++ b/lib/node/createView.js @@ -0,0 +1,13 @@ +'use strict'; + +var Node = require('./index'); + +module.exports = Node.define({ + type: 'CREATE VIEW', + + constructor: function(viewName) { + Node.call(this); + + this.options = { viewName: viewName}; + } +}); diff --git a/lib/node/default.js b/lib/node/default.js index 49bd7ebd..b5adc894 100644 --- a/lib/node/default.js +++ b/lib/node/default.js @@ -1,6 +1,6 @@ 'use strict'; -module.exports = require(__dirname).define({ +module.exports = require('./index').define({ type: 'DEFAULT', value: function() { return; diff --git a/lib/node/delete.js b/lib/node/delete.js index 2acb5872..0d02ebab 100644 --- a/lib/node/delete.js +++ b/lib/node/delete.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'DELETE' diff --git a/lib/node/distinct.js b/lib/node/distinct.js new file mode 100644 index 00000000..8c681551 --- /dev/null +++ b/lib/node/distinct.js @@ -0,0 +1,7 @@ +'use strict'; + +var Node = require('./index'); + +module.exports = Node.define({ + type: 'DISTINCT', +}); diff --git a/lib/node/distinctOn.js b/lib/node/distinctOn.js new file mode 100644 index 00000000..72c430e8 --- /dev/null +++ b/lib/node/distinctOn.js @@ -0,0 +1,7 @@ +'use strict'; + +var Node = require('./index'); + +module.exports = Node.define({ + type: 'DISTINCT ON', +}); diff --git a/lib/node/drop.js b/lib/node/drop.js index aa37b3ed..b0428347 100644 --- a/lib/node/drop.js +++ b/lib/node/drop.js @@ -1,12 +1,12 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'DROP', constructor: function(table) { - Node.call(this); - this.add(table); + Node.call(this); + this.add(table); } }); diff --git a/lib/node/dropColumn.js b/lib/node/dropColumn.js index 60ad4219..01fe36c5 100644 --- a/lib/node/dropColumn.js +++ b/lib/node/dropColumn.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'DROP COLUMN' diff --git a/lib/node/forShare.js b/lib/node/forShare.js index 328a4ebe..68a83678 100644 --- a/lib/node/forShare.js +++ b/lib/node/forShare.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'FOR SHARE' diff --git a/lib/node/forUpdate.js b/lib/node/forUpdate.js index c869f981..da4a2518 100644 --- a/lib/node/forUpdate.js +++ b/lib/node/forUpdate.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'FOR UPDATE' diff --git a/lib/node/foreignKey.js b/lib/node/foreignKey.js new file mode 100644 index 00000000..a0ad99c1 --- /dev/null +++ b/lib/node/foreignKey.js @@ -0,0 +1,19 @@ +'use strict'; + +var Node = require('./index'); + +module.exports = Node.define({ + type: 'FOREIGN KEY', + constructor: function(config) { + Node.call(this); + this.name = config.name; + this.columns = config.columns; + this.schema = config.schema; + this.table = config.table; + this.refColumns = config.refColumns; + this.onUpdate = config.onUpdate; + this.onDelete = config.onDelete; + this.constraint = config.constraint; + } +}); + diff --git a/lib/node/from.js b/lib/node/from.js index 84a6010f..12b54565 100644 --- a/lib/node/from.js +++ b/lib/node/from.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); var From = Node.define({ type: 'FROM' diff --git a/lib/node/functionCall.js b/lib/node/functionCall.js index 6d43c279..608a3c1e 100644 --- a/lib/node/functionCall.js +++ b/lib/node/functionCall.js @@ -1,9 +1,9 @@ 'use strict'; var _ = require('lodash'); -var Node = require(__dirname); -var ParameterNode = require(__dirname + '/parameter'); -var valueExpressionMixin = require(__dirname + '/valueExpression'); +var Node = require('./index'); +var ParameterNode = require('./parameter'); +var valueExpressionMixin = require('./valueExpression'); var FunctionCallNode = Node.define({ type: 'FUNCTION CALL', @@ -18,7 +18,7 @@ var FunctionCallNode = Node.define({ _.extend(FunctionCallNode.prototype, valueExpressionMixin()); // allow aliasing -var AliasNode = require(__dirname + '/alias'); +var AliasNode = require('./alias'); _.extend(FunctionCallNode.prototype, AliasNode.AliasMixin); module.exports = FunctionCallNode; diff --git a/lib/node/groupBy.js b/lib/node/groupBy.js index 6e5888d1..53f63e94 100644 --- a/lib/node/groupBy.js +++ b/lib/node/groupBy.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'GROUP BY' diff --git a/lib/node/having.js b/lib/node/having.js index 7dcf3434..6f1523ac 100644 --- a/lib/node/having.js +++ b/lib/node/having.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'HAVING' diff --git a/lib/node/ifExists.js b/lib/node/ifExists.js index 9b759779..c26df660 100644 --- a/lib/node/ifExists.js +++ b/lib/node/ifExists.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'IF EXISTS' diff --git a/lib/node/ifNotExists.js b/lib/node/ifNotExists.js index ef414551..d731ccb2 100644 --- a/lib/node/ifNotExists.js +++ b/lib/node/ifNotExists.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'IF NOT EXISTS' diff --git a/lib/node/in.js b/lib/node/in.js index 4c807331..233b7c28 100644 --- a/lib/node/in.js +++ b/lib/node/in.js @@ -1,8 +1,8 @@ 'use strict'; var _ = require('lodash'); -var Node = require(__dirname); -var valueExpressionMixin = require(__dirname + '/valueExpression'); +var Node = require('./index'); +var valueExpressionMixin = require('./valueExpression'); var valueExpressionMixed = false; var InNode = Node.define(_.extend({ @@ -22,7 +22,7 @@ var InNode = Node.define(_.extend({ })); // allow aliasing -var AliasNode = require(__dirname + '/alias'); +var AliasNode = require('./alias'); _.extend(InNode.prototype, AliasNode.AliasMixin); module.exports = InNode; diff --git a/lib/node/index.js b/lib/node/index.js index e0dabff5..66c0e481 100644 --- a/lib/node/index.js +++ b/lib/node/index.js @@ -15,7 +15,11 @@ Node.prototype.toNode = function() { Node.prototype.add = function(node) { assert(node, 'Error while trying to add a non-existant node to a query'); - this.nodes.push(typeof node === 'string' ? new TextNode(node) : node.toNode()); + var newNode; + if (typeof node === 'string') newNode = new TextNode(node); + else if (node.toNode) newNode = node.toNode(); + else newNode = node; + this.nodes.push(newNode); return this; }; @@ -45,9 +49,14 @@ var determineDialect = function(query, dialect) { return Dialect; }; +var initializeDialect = function(Dialect, query) { + var config = query.sql ? query.sql.config : {}; + return new Dialect(config); +}; + Node.prototype.toQuery = function(dialect) { var Dialect = determineDialect(this, dialect); - return new Dialect().getQuery(this); + return initializeDialect(Dialect, this).getQuery(this); }; Node.prototype.toNamedQuery = function(name, dialect) { @@ -61,7 +70,7 @@ Node.prototype.toNamedQuery = function(name, dialect) { Node.prototype.toString = function(dialect) { var Dialect = determineDialect(this, dialect); - return new Dialect().getString(this); + return initializeDialect(Dialect, this).getString(this); }; Node.prototype.addAll = function(nodes) { @@ -89,4 +98,4 @@ Node.define = function(def) { }; module.exports = Node; -var TextNode = require(__dirname + '/text'); +var TextNode = require('./text'); diff --git a/lib/node/interval.js b/lib/node/interval.js new file mode 100644 index 00000000..9f46f9ab --- /dev/null +++ b/lib/node/interval.js @@ -0,0 +1,21 @@ +'use strict'; + +var Node = require('./index'); +var ParameterNode = require('./parameter'); + +var IntervalNode = Node.define({ + type: 'INTERVAL', + constructor: function(args) { + Node.call(this); + var interval = args[0] || {}; + this.years = interval.years; + this.months = interval.months; + this.days = interval.days; + this.hours = interval.hours; + this.minutes = interval.minutes; + this.seconds = interval.seconds; + } +}); + +module.exports = IntervalNode; + diff --git a/lib/node/join.js b/lib/node/join.js index 7186f694..f569997e 100644 --- a/lib/node/join.js +++ b/lib/node/join.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); var JoinNode = module.exports = Node.define({ type: 'JOIN', constructor: function(subType, from, to) { @@ -19,5 +19,8 @@ var JoinNode = module.exports = Node.define({ }, leftJoin: function(other) { return new JoinNode('LEFT', this, other); + }, + leftJoinLateral: function(other) { + return new JoinNode('LEFT LATERAL', this, other); } }); diff --git a/lib/node/literal.js b/lib/node/literal.js index c4f539bb..f5a1ea58 100644 --- a/lib/node/literal.js +++ b/lib/node/literal.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'LITERAL', diff --git a/lib/node/notIn.js b/lib/node/notIn.js index e363f7f3..c50976c3 100644 --- a/lib/node/notIn.js +++ b/lib/node/notIn.js @@ -1,8 +1,8 @@ 'use strict'; var _ = require('lodash'); -var Node = require(__dirname); -var valueExpressionMixin = require(__dirname + '/valueExpression'); +var Node = require('./index'); +var valueExpressionMixin = require('./valueExpression'); var valueExpressionMixed = false; var NotInNode = Node.define(_.extend({ @@ -22,7 +22,7 @@ var NotInNode = Node.define(_.extend({ })); // allow aliasing -var AliasNode = require(__dirname + '/alias'); +var AliasNode = require('./alias'); _.extend(NotInNode.prototype, AliasNode.AliasMixin); module.exports = NotInNode; diff --git a/lib/node/onConflict.js b/lib/node/onConflict.js new file mode 100644 index 00000000..cc71ac47 --- /dev/null +++ b/lib/node/onConflict.js @@ -0,0 +1,7 @@ +'use strict'; + +var Node = require('./index'); + +module.exports = Node.define({ + type: 'ONCONFLICT' +}); diff --git a/lib/node/onDuplicate.js b/lib/node/onDuplicate.js new file mode 100644 index 00000000..cd653cb3 --- /dev/null +++ b/lib/node/onDuplicate.js @@ -0,0 +1,7 @@ +'use strict'; + +var Node = require('./index'); + +module.exports = Node.define({ + type: 'ONDUPLICATE' +}); diff --git a/lib/node/orIgnore.js b/lib/node/orIgnore.js new file mode 100644 index 00000000..e23c9d6d --- /dev/null +++ b/lib/node/orIgnore.js @@ -0,0 +1,7 @@ +'use strict'; + +var Node = require('./index'); + +module.exports = Node.define({ + type: 'OR IGNORE' +}); diff --git a/lib/node/orderBy.js b/lib/node/orderBy.js index 6db2a978..b97fb891 100644 --- a/lib/node/orderBy.js +++ b/lib/node/orderBy.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); module.exports = Node.define({ type: 'ORDER BY' diff --git a/lib/node/orderByValue.js b/lib/node/orderByValue.js index 4ac7fd8a..47a8d5c0 100644 --- a/lib/node/orderByValue.js +++ b/lib/node/orderByValue.js @@ -1,6 +1,6 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); var OrderByColumn = Node.define({ type: 'ORDER BY VALUE', @@ -8,6 +8,9 @@ var OrderByColumn = Node.define({ Node.call(this); this.value = config.value; this.direction = config.direction; + // used when processing OFFSET and LIMIT clauses in MSSQL + this.msSQLOffsetNode=undefined; + this.msSQLLimitNode=undefined; } }); diff --git a/lib/node/parameter.js b/lib/node/parameter.js index 9d825d42..051ed852 100644 --- a/lib/node/parameter.js +++ b/lib/node/parameter.js @@ -1,13 +1,13 @@ 'use strict'; -var Node = require(__dirname); +var Node = require('./index'); var ParameterNode = module.exports = Node.define({ type: 'PARAMETER', constructor: function(val) { Node.call(this); this._val = val; - this.isExplicit = false; + this.isExplicit = false; }, value: function() { return this._val; diff --git a/lib/node/postfixUnary.js b/lib/node/postfixUnary.js index 0c132f8a..8c66b89f 100644 --- a/lib/node/postfixUnary.js +++ b/lib/node/postfixUnary.js @@ -1,8 +1,8 @@ 'use strict'; var _ = require('lodash'); -var Node = require(__dirname); -var valueExpressionMixin = require(__dirname + '/valueExpression'); +var Node = require('./index'); +var valueExpressionMixin = require('./valueExpression'); var valueExpressionMixed = false; var PostfixUnaryNode = Node.define({ @@ -22,7 +22,7 @@ var PostfixUnaryNode = Node.define({ }); // allow aliasing -var AliasNode = require(__dirname + '/alias'); +var AliasNode = require('./alias'); _.extend(PostfixUnaryNode.prototype, AliasNode.AliasMixin); module.exports = PostfixUnaryNode; diff --git a/lib/node/prefixUnary.js b/lib/node/prefixUnary.js index 67a59fa1..fbde69c0 100644 --- a/lib/node/prefixUnary.js +++ b/lib/node/prefixUnary.js @@ -1,8 +1,8 @@ 'use strict'; var _ = require('lodash'); -var Node = require(__dirname); -var valueExpressionMixin = require(__dirname + '/valueExpression'); +var Node = require('./index'); +var valueExpressionMixin = require('./valueExpression'); var valueExpressionMixed = false; var PrefixUnaryNode = Node.define({ @@ -22,7 +22,7 @@ var PrefixUnaryNode = Node.define({ }); // allow aliasing -var AliasNode = require(__dirname + '/alias'); +var AliasNode = require('./alias'); _.extend(PrefixUnaryNode.prototype, AliasNode.AliasMixin); module.exports = PrefixUnaryNode; diff --git a/lib/node/query.js b/lib/node/query.js index 0613d1a3..ebb3ecfa 100644 --- a/lib/node/query.js +++ b/lib/node/query.js @@ -1,8 +1,11 @@ 'use strict'; +var _ = require('lodash'); +var alias = require('./alias'); var assert = require('assert'); var sliced = require('sliced'); var util = require('util'); +var valueExpressionMixin = require('./valueExpression'); var Node = require('./'); var Select = require('./select'); @@ -12,13 +15,19 @@ var OrderBy = require('./orderBy'); var GroupBy = require('./groupBy'); var Having = require('./having'); var Insert = require('./insert'); +var Replace = require('./replace'); var Update = require('./update'); var Delete = require('./delete'); var Returning = require('./returning'); +var OnDuplicate = require('./onDuplicate'); +var OnConflict = require('./onConflict'); var ForUpdate = require('./forUpdate'); var ForShare = require('./forShare'); var Create = require('./create'); var Drop = require('./drop'); +var Truncate = require('./truncate'); +var Distinct = require('./distinct'); +var DistinctOn = require('./distinctOn'); var Alter = require('./alter'); var AddColumn = require('./addColumn'); var DropColumn = require('./dropColumn'); @@ -29,12 +38,15 @@ var ParameterNode = require('./parameter'); var PrefixUnaryNode = require('./prefixUnary'); var IfExists = require('./ifExists'); var IfNotExists = require('./ifNotExists'); +var OrIgnore = require('./orIgnore'); var Cascade = require('./cascade'); var Restrict = require('./restrict'); var Indexes = require('./indexes'); var CreateIndex = require('./createIndex'); var DropIndex = require('./dropIndex'); var Table = require('./table'); +var CreateView = require('./createView'); +var JoinNode = require('./join'); var Modifier = Node.define({ constructor: function(table, type, count) { @@ -109,9 +121,23 @@ var Query = Node.define({ }); }, - from: function(tableNode) { - var from = new From().add(tableNode); - return this.add(from); + from: function() { + var tableNodes = arguments; + + if (Array.isArray(arguments[0])) { + tableNodes = arguments[0]; + } + + for (var i=0; i'), keyText : binaryMethod('->>'), path : binaryMethod('#>'), pathText : binaryMethod('#>>'), like : binaryMethod('LIKE'), + rlike : binaryMethod('RLIKE'), notLike : binaryMethod('NOT LIKE'), + ilike : binaryMethod('ILIKE'), + notIlike : binaryMethod('NOT ILIKE'), + match : binaryMethod('@@'), in : inMethod, notIn : notInMethod, between : ternaryMethod('BETWEEN', 'AND'), + notBetween : ternaryMethod('NOT BETWEEN', 'AND'), at : atMethod, contains : binaryMethod('@>'), containedBy : binaryMethod('<@'), + containsKey : binaryMethod('?'), overlap : binaryMethod('&&'), slice : sliceMethod, cast : castMethod, diff --git a/lib/node/where.js b/lib/node/where.js index b7f2be1b..5c0465fc 100644 --- a/lib/node/where.js +++ b/lib/node/where.js @@ -1,14 +1,29 @@ 'use strict'; -var Node = require(__dirname); -var BinaryNode = require(__dirname + '/binary'); -var TextNode = require(__dirname + '/text'); +var Node = require('./index'); +var BinaryNode = require('./binary'); +var TextNode = require('./text'); var normalizeNode = function(table, node) { var result = node; if(typeof node === 'string') { result = new TextNode('(' + node + ')'); } + else if (Array.isArray(node)) { + result = false; + + if (node.length === 0) { + result = new TextNode('(1 = 1)'); + } else { + node.forEach(function (subNode) { + if (!result) { + result = subNode; + } else { + result = result.and(subNode); + } + }); + } + } else if (!node.toNode && typeof node === 'object'){ result = false; for (var colName in node) { diff --git a/lib/table.js b/lib/table.js index 1a7338f7..1408542b 100644 --- a/lib/table.js +++ b/lib/table.js @@ -3,20 +3,23 @@ var util = require('util'); var lodash = require('lodash'); -var Query = require(__dirname + '/node/query'); -var Column = require(__dirname + '/column'); -var TableNode = require(__dirname + '/node/table'); -var JoinNode = require(__dirname + '/node/join'); -var LiteralNode = require(__dirname + '/node/literal'); -var Joiner = require(__dirname + '/joiner'); +var Query = require('./node/query'); +var Column = require('./column'); +var TableNode = require('./node/table'); +var JoinNode = require('./node/join'); +var LiteralNode = require('./node/literal'); +var Joiner = require('./joiner'); +var ForeignKeyNode = require('./node/foreignKey'); var Table = function(config) { this._schema = config.schema; this._name = config.name; this._initialConfig = config; this.columnWhiteList = !!config.columnWhiteList; + this.isTemporary=!!config.isTemporary; this.snakeToCamel = !!config.snakeToCamel; this.columns = []; + this.foreignKeys = []; this.table = this; if (!config.sql) { config.sql = require('./index'); @@ -44,9 +47,31 @@ Table.define = function(config) { for (var i = 0; i < config.columns.length; i++) { table.addColumn(config.columns[i]); } + + if(config.foreignKeys !== undefined) { + if(util.isArray(config.foreignKeys)) { + for(i = 0; i < config.foreignKeys.length; i++) { + table.foreignKeys.push(new ForeignKeyNode(config.foreignKeys[i])); + } + } else { + table.foreignKeys.push(new ForeignKeyNode(config.foreignKeys)); + } + } return table; }; +Table.prototype.clone = function(config) { + return Table.define(lodash.extend({ + schema: this._schema, + name: this._name, + sql: this.sql, + columnWhiteList: !!this.columnWhiteList, + snakeToCamel: !!this.snakeToCamel, + columns: this.columns, + foreignKeys: this.foreignKeys + }, config || {})); +}; + Table.prototype.createColumn = function(col) { if(!(col instanceof Column)) { if(typeof col === 'string') { @@ -55,6 +80,20 @@ Table.prototype.createColumn = function(col) { col.table = this; col = new Column(col); + + // Load subfields from array into an object of form name: Column + if(util.isArray(col.subfields)) { + col.subfields = lodash.chain(col.subfields) + .map(lodash.bind(function (subfield) { + return [subfield, new Column({ + table: this, + subfieldContainer: col, + name: subfield + })]; + }, this)) + .fromPairs() + .value(); + } } return col; @@ -72,7 +111,7 @@ Table.prototype.addColumn = function(col, options) { } else { return this; } - } else if(!!this[col.name] && (process.env.NODE_ENV !== 'test')) { + } else if(!!this[col.name] && (process.env.NODE_ENV === 'debug')) { console.log('Please notice that you have just defined the column "' + col.name + '". In order to access it, you need to use "table.getColumn(\'' + col.name + '\');"!'); } this.columns.push(col); @@ -87,13 +126,10 @@ Table.prototype.addColumn = function(col, options) { }; Table.prototype.hasColumn = function(col) { - col = this.createColumn(col); - - var cols = this.columns.filter(function(column) { - return column.property === col.property || column.name === col.name; + var columnName = col instanceof Column ? col.name : col; + return this.columns.some(function(column) { + return column.property === columnName || column.name === columnName; }); - - return cols.length > 0; }; Table.prototype.getColumn = @@ -119,6 +155,7 @@ Table.prototype.setSchema = function(schema) { }; Table.prototype.getName = function() { + if (this.sql && this.sql.dialectName=="mssql" && this.isTemporary) return "#"+this._name; return this._name; }; @@ -135,7 +172,7 @@ Table.prototype.star = function(options) { Table.prototype.literal = function(literal) { return new LiteralNode(literal); -} +}; Table.prototype.count = function(alias) { var name = this.alias || this._name, @@ -155,56 +192,36 @@ Table.prototype.select = function() { return query; }; -Table.prototype.from = function() { - var query = new Query(this); - query.from.apply(query, arguments); - return query; -}; - Table.prototype.subQuery = function(alias) { // create the query and pass it off var query = new Query(this); query.type = 'SUBQUERY'; query.alias = alias; - query.join = function(other) { - return new JoinNode('INNER', this.toNode(), other.toNode(), other); - } + query.join = function(other) { + return new JoinNode('INNER', this.toNode(), other.toNode(), other); + }; return query; }; Table.prototype.insert = function() { var query = new Query(this); - query.insert.apply(query, arguments); - return query; -}; - -Table.prototype.update = function() { - var query = new Query(this); - query.update.apply(query, arguments); - return query; -}; - -Table.prototype['delete'] = function() { - var query = new Query(this); - query['delete'].apply(query, arguments); - return query; -}; - -Table.prototype.create = function() { - var query = new Query(this); - query.create.apply(query, arguments); - return query; -}; - -Table.prototype.drop = function() { - var query = new Query(this); - query.drop.apply(query, arguments); + if(!arguments[0] || (util.isArray(arguments[0]) && arguments[0].length === 0)){ + query.select.call(query, this.star()); + query.where.apply(query,["1=2"]); + } else { + query.insert.apply(query, arguments); + } return query; }; -Table.prototype.alter = function() { +Table.prototype.replace = function() { var query = new Query(this); - query.alter.apply(query, arguments); + if(!arguments[0] || (util.isArray(arguments[0]) && arguments[0].length === 0)){ + query.select.call(query, this.star()); + query.where.apply(query,["1=2"]); + } else { + query.replace.apply(query, arguments); + } return query; }; @@ -220,6 +237,10 @@ Table.prototype.leftJoin = function(other) { return new JoinNode('LEFT', this.toNode(), other.toNode()); }; +Table.prototype.leftJoinLateral = function(other) { + return new JoinNode('LEFT LATERAL', this.toNode(), other.toNode()); +}; + // auto-join tables based on column intropsection Table.prototype.joinTo = function(other) { return Joiner.leftJoin(this, other); @@ -237,26 +258,37 @@ Table.prototype.__defineGetter__("nodes", function() { return this.select(this.star()).nodes; }); -Table.prototype.where = function() { - var query = new Query(this); - query.where.apply(query, arguments); - return query; -}; - Table.prototype.and = function() { var query = new Query(this); query.where.apply(query, arguments); return query; }; -Table.prototype.or = function() { - var query = new Query(this); - query.or.apply(query, arguments); - return query; -}; - Table.prototype.indexes = function() { return new Query(this).indexes(); }; +var queryMethods = [ + 'alter', + 'create', + 'delete', + 'drop', + 'from', + 'limit', + 'offset', + 'or', + 'order', + 'truncate', + 'update', + 'where' +]; + +queryMethods.forEach(function (method) { + Table.prototype[method] = function () { + var query = new Query(this); + query[method].apply(query, arguments); + return query; + }; +}); + module.exports = Table; diff --git a/lib/types.d.ts b/lib/types.d.ts new file mode 100644 index 00000000..a7011f99 --- /dev/null +++ b/lib/types.d.ts @@ -0,0 +1,221 @@ + +/** + * This is an adaptation of https://github.com/doxout/anydb-sql/blob/4e4c0ff4a7f2efb7f820baaafea1f624f1ae0399/d.ts/anydb-sql.d.ts + * Whole project is MIT licensed, so, we can use it. We also feed back any + * improvements, questions, concerns. + */ +declare module "sql" { + + type SQLDialects = + | "mssql" + | "mysql" + | "oracle" + | "postgres" + | "sqlite" + ; + + interface OrderByValueNode {} + + interface Named { + name?: Name; + } + interface ColumnDefinition extends Named { + jsType?: Type; + dataType: string; + primaryKey?: boolean; + references?: { + table:string; + column: string; + onDelete?: 'restrict' | 'cascade' | 'no action' | 'set null' | 'set default'; + onUpdate?: 'restrict' | 'cascade' | 'no action' | 'set null' | 'set default'; + }; + notNull?: boolean; + unique?: boolean; + defaultValue?: Type; + } + + interface TableDefinition { + name: Name; + schema: string; + columns: {[CName in ((keyof Row) & string)]: ColumnDefinition}; + dialect?: SQLDialects; + isTemporary?: boolean; + foreignKeys?: { + table: string, + columns: (keyof Row)[], + refColumns: string[], + onDelete?: 'restrict' | 'cascade' | 'no action' | 'set null' | 'set default'; + onUpdate?: 'restrict' | 'cascade' | 'no action' | 'set null' | 'set default'; + } + } + + interface QueryLike { + values: any[] + text:string + } + + interface Executable { + toQuery():QueryLike; + } + + interface Queryable extends Executable { + where(...nodes:any[]):Query + delete():ModifyingQuery + select(star: Column): Query; + select(n1: Column):Query<{[N in N1]: T1}>; + select( + n1: Column, + n2: Column):Query<{[N in N1]: T1} & {[N in N2]: T2}> + select( + n1: Column, + n2: Column, + n3: Column):Query<{[N in N1]: T1} & {[N in N2]: T2} & {[N in N3]: T3}> + select(...nodesOrTables:any[]):Query + + } + + interface Query extends Executable, Queryable { + resultType: T; + + from(table:TableNode):Query + from(statement:string):Query + update(o:{[key: string]:any}):ModifyingQuery + update(o:{}):ModifyingQuery + group(...nodes:any[]):Query + order(...criteria:OrderByValueNode[]):Query + limit(l:number):Query + offset(o:number):Query + } + + interface SubQuery { + select(node:Column):SubQuery + select(...nodes: any[]):SubQuery + where(...nodes:any[]):SubQuery + from(table:TableNode):SubQuery + from(statement:string):SubQuery + group(...nodes:any[]):SubQuery + order(criteria:OrderByValueNode):SubQuery + exists():BinaryNode + notExists(): BinaryNode; + notExists(subQuery:SubQuery):BinaryNode + } + + + interface ModifyingQuery extends Executable { + returning(...nodes:any[]):Query + where(...nodes:any[]):ModifyingQuery + } + + interface TableNode { + join(table:TableNode):JoinTableNode + leftJoin(table:TableNode):JoinTableNode + } + + interface JoinTableNode extends TableNode { + on(filter:BinaryNode):TableNode + on(filter:string):TableNode + } + + interface CreateQuery extends Executable { + ifNotExists():Executable + } + interface DropQuery extends Executable { + ifExists():Executable + } + + type Columns = { + [Name in keyof T]: Column + } + type Table = TableNode & Queryable & Named & Columns & { + getName(): string; + getSchema(): string; + + literal(statement: string): any; + + create():CreateQuery + drop():DropQuery + as(name:OtherName):Table + update(o: Partial):ModifyingQuery + insert(row:T):ModifyingQuery + insert(rows:T[]):ModifyingQuery + select():Query + select(...nodes:any[]):Query + from(table:TableNode):Query + from(statement:string):Query + star():Column + subQuery():SubQuery + columns:Column[] + sql: SQL; + alter():AlterQuery; + indexes(): IndexQuery; + } + + interface AlterQuery extends Executable { + addColumn(column:Column): AlterQuery; + addColumn(name: string, options:string): AlterQuery; + dropColumn(column: Column|string): AlterQuery; + renameColumn(column: Column, newColumn: Column):AlterQuery; + renameColumn(column: Column, newName: string):AlterQuery; + renameColumn(name: string, newName: string):AlterQuery; + rename(newName: string): AlterQuery + } + interface IndexQuery { + create(): IndexCreationQuery; + create(indexName: string): IndexCreationQuery; + drop(indexName: string): Executable; + drop(...columns: Column[]): Executable + } + interface IndexCreationQuery extends Executable { + unique(): IndexCreationQuery; + using(name: string): IndexCreationQuery; + on(...columns: (Column|OrderByValueNode)[]): IndexCreationQuery; + withParser(parserName: string): IndexCreationQuery; + fulltext(): IndexCreationQuery; + spatial(): IndexCreationQuery; + } + + interface SQL { + functions: { + LOWER(c:Column):Column + } + } + + interface BinaryNode { + and(node:BinaryNode):BinaryNode + or(node:BinaryNode):BinaryNode + } + + interface Column { + name: Name + in(arr:T[]):BinaryNode + in(subQuery:SubQuery):BinaryNode + notIn(arr:T[]):BinaryNode + equals(node: T|Column):BinaryNode + notEquals(node: T|Column):BinaryNode + gte(node: T|Column):BinaryNode + lte(node: T|Column):BinaryNode + gt(node:T|Column):BinaryNode + lt(node: T|Column):BinaryNode + like(str:string):BinaryNode + multiply:{ + (node:Column):Column + (n:number):Column //todo check column names + } + isNull():BinaryNode + isNotNull():BinaryNode + //todo check column names + sum():Column + count():Column + count(name:string):Column + distinct():Column + as(name:OtherName):Column + ascending:OrderByValueNode + descending:OrderByValueNode + asc:OrderByValueNode + desc:OrderByValueNode + } + + function define(map:TableDefinition): Table; + function setDialect(dialect: SQLDialects): void; + +} diff --git a/package.json b/package.json index e344a719..dc250c01 100644 --- a/package.json +++ b/package.json @@ -2,22 +2,26 @@ "author": "brianc ", "name": "sql", "description": "sql builder", - "version": "0.38.0", + "version": "0.78.0", "homepage": "https://github.com/brianc/node-sql", + "license": "MIT", "repository": { "type": "git", "url": "git://github.com/brianc/node-sql.git" }, "main": "lib/", + "types": "lib/types.d.ts", "scripts": { - "test": "NODE_ENV=test ./node_modules/.bin/mocha" + "test": "node_modules/.bin/mocha", + "lint": "jshint lib test", + "posttest": "jshint lib test" }, "engines": { "node": "*" }, "dependencies": { "sliced": "0.0.x", - "lodash": "1.3.x" + "lodash": "4.1.x" }, "devDependencies": { "jshint": "*", diff --git a/runtests.js b/runtests.js new file mode 100644 index 00000000..ac89769b --- /dev/null +++ b/runtests.js @@ -0,0 +1,18 @@ +var childProcess = require("child_process"); +var path = require("path"); + +var env = process.env; +env.NODE_ENV = "test"; + +var options = { + env: env +}; + +var command = path.join(".", "node_modules", ".bin", "mocha"); +if (process.platform == "win32") command += ".cmd"; +var run = childProcess.spawn(command, [], options); +run.stdout.pipe(process.stdout); +run.stderr.pipe(process.stderr); +run.on('close', function(code) { + process.exit(code); +}); diff --git a/test/binary-clause-tests.js b/test/binary-clause-tests.js index 438a3761..10c50737 100644 --- a/test/binary-clause-tests.js +++ b/test/binary-clause-tests.js @@ -33,5 +33,12 @@ test('operators', function() { assert.equal(Foo.baz.divide(1).operator, '/'); assert.equal(Foo.baz.modulo(1).operator, '%'); assert.equal(Foo.baz.regex(1).operator, '~'); + assert.equal(Foo.baz.iregex(1).operator, '~*'); assert.equal(Foo.baz.notRegex(1).operator, '!~'); + assert.equal(Foo.baz.notIregex(1).operator, '!~*'); + assert.equal(Foo.baz.regexp(1).operator, 'REGEXP'); + assert.equal(Foo.baz.rlike(1).operator, 'RLIKE'); + assert.equal(Foo.baz.ilike('asdf').operator, 'ILIKE'); + assert.equal(Foo.baz.notIlike('asdf').operator, 'NOT ILIKE'); + assert.equal(Foo.baz.match('asdf').operator, '@@'); }); diff --git a/test/column-tests.js b/test/column-tests.js index f8b47d12..d0b95a14 100644 --- a/test/column-tests.js +++ b/test/column-tests.js @@ -6,7 +6,7 @@ var sql = require(__dirname + '/../lib'); describe('column', function() { var table = sql.define({ name: 'user', - columns: ['id', 'created'] + columns: ['id', 'created', 'alias'] }); it('can be accessed by property and array', function() { @@ -18,6 +18,10 @@ describe('column', function() { assert.equal(table.id.toQuery().text, '"user"."id"'); }); + it('works with a column name of "alias"', function() { + assert.equal(table.alias.toQuery().text, '"user"."alias"'); + }); + it('respects AS rename', function() { assert.equal(table.id.as('userId').toQuery().text, '"user"."id" AS "userId"'); }); @@ -32,29 +36,29 @@ describe('column', function() { assert.equal(col, '"subTable"."subId"'); }); - describe('property', function() { - var table = sql.define({ - name: 'roundtrip', - columns: { - column_name: { property: 'propertyName' } - } - }); - it('used as alias when !== column name', function() { - assert.equal(table.propertyName.toQuery().text, '"roundtrip"."column_name" AS "propertyName"'); - }); - it('uses explicit alias when !== column name', function() { - assert.equal(table.propertyName.as('alias').toQuery().text, '"roundtrip"."column_name" AS "alias"'); - }); - it('maps to column name in insert', function() { - assert.equal(table.insert({propertyName:'propVal'}).toQuery().text, 'INSERT INTO "roundtrip" ("column_name") VALUES ($1)'); - }); - it('maps to column name in update', function() { - assert.equal(table.update({propertyName:'propVal'}).toQuery().text, 'UPDATE "roundtrip" SET "column_name" = $1'); - }); - it('explicitly selected by *', function() { - assert.equal(table.select(table.star()).from(table).toQuery().text, 'SELECT "roundtrip"."column_name" AS "propertyName" FROM "roundtrip"'); - }); - }); + describe('property', function() { + var table = sql.define({ + name: 'roundtrip', + columns: { + column_name: { property: 'propertyName' } + } + }); + it('used as alias when !== column name', function() { + assert.equal(table.propertyName.toQuery().text, '"roundtrip"."column_name" AS "propertyName"'); + }); + it('uses explicit alias when !== column name', function() { + assert.equal(table.propertyName.as('alias').toQuery().text, '"roundtrip"."column_name" AS "alias"'); + }); + it('maps to column name in insert', function() { + assert.equal(table.insert({propertyName:'propVal'}).toQuery().text, 'INSERT INTO "roundtrip" ("column_name") VALUES ($1)'); + }); + it('maps to column name in update', function() { + assert.equal(table.update({propertyName:'propVal'}).toQuery().text, 'UPDATE "roundtrip" SET "column_name" = $1'); + }); + it('explicitly selected by *', function() { + assert.equal(table.select(table.star()).from(table).toQuery().text, 'SELECT "roundtrip"."column_name" AS "propertyName" FROM "roundtrip"'); + }); + }); describe('autoGenerate', function() { var table = sql.define({ @@ -92,10 +96,10 @@ describe('column', function() { columns: ['id', 'name'] }); it('throws for insert properties that are not a column', function() { - assert.throws(function() { table.insert({id:0, _private:'_private', name:'name'}) }, Error); + assert.throws(function() { table.insert({id:0, _private:'_private', name:'name'}); }, Error); }); it('throws for update properties that are not a column', function() { - assert.throws(function() { table.update({id:0, _private:'_private', name:'name'}) }, Error); + assert.throws(function() { table.update({id:0, _private:'_private', name:'name'}); }, Error); }); }); @@ -120,7 +124,7 @@ describe('column', function() { }); it('respects AS rename in RETURNING clause', function() { assert.equal(table.update({makeMeCamel:0}).returning(table.makeMeCamel.as('rename')).toQuery().text, - 'UPDATE "sc" SET "make_me_camel" = $1 RETURNING "sc"."make_me_camel" AS "rename"'); + 'UPDATE "sc" SET "make_me_camel" = $1 RETURNING "make_me_camel" AS "rename"'); }); }); }); diff --git a/test/dialects/aggregate-tests.js b/test/dialects/aggregate-tests.js index 4eff37b3..59d48d57 100644 --- a/test/dialects/aggregate-tests.js +++ b/test/dialects/aggregate-tests.js @@ -2,6 +2,8 @@ var Harness = require('./support'); var post = Harness.definePostTable(); +var customerAlias = Harness.defineCustomerAliasTable(); + Harness.test({ query: post.select(post.count()), @@ -14,8 +16,16 @@ Harness.test({ string: 'SELECT COUNT("post".*) AS "post_count" FROM "post"' }, mysql: { - text : 'SELECT COUNT(`post`.*) AS `post_count` FROM `post`', - string: 'SELECT COUNT(`post`.*) AS `post_count` FROM `post`' + text : 'SELECT COUNT(*) AS `post_count` FROM `post`', + string: 'SELECT COUNT(*) AS `post_count` FROM `post`' + }, + mssql: { + text : 'SELECT COUNT(*) AS [post_count] FROM [post]', + string: 'SELECT COUNT(*) AS [post_count] FROM [post]' + }, + oracle: { + text : 'SELECT COUNT(*) "post_count" FROM "post"', + string: 'SELECT COUNT(*) "post_count" FROM "post"' }, params: [] }); @@ -31,8 +41,16 @@ Harness.test({ string: 'SELECT COUNT("post".*) AS "post_count" FROM "post"' }, msyql: { - text : 'SELECT COUNT(`post`.*) AS `post_count` FROM `post`', - string: 'SELECT COUNT(`post`.*) AS `post_count` FROM `post`' + text : 'SELECT COUNT(*) AS `post_count` FROM `post`', + string: 'SELECT COUNT(*) AS `post_count` FROM `post`' + }, + mssql: { + text : 'SELECT COUNT(*) AS [post_count] FROM [post]', + string: 'SELECT COUNT(*) AS [post_count] FROM [post]' + }, + oracle: { + text : 'SELECT COUNT(*) "post_count" FROM "post"', + string: 'SELECT COUNT(*) "post_count" FROM "post"' }, params: [] }); @@ -48,8 +66,16 @@ Harness.test({ string: 'SELECT COUNT("post".*) AS "post_amount" FROM "post"' }, mysql: { - text : 'SELECT COUNT(`post`.*) AS `post_amount` FROM `post`', - string: 'SELECT COUNT(`post`.*) AS `post_amount` FROM `post`' + text : 'SELECT COUNT(*) AS `post_amount` FROM `post`', + string: 'SELECT COUNT(*) AS `post_amount` FROM `post`' + }, + mssql: { + text : 'SELECT COUNT(*) AS [post_amount] FROM [post]', + string: 'SELECT COUNT(*) AS [post_amount] FROM [post]' + }, + oracle: { + text : 'SELECT COUNT(*) "post_amount" FROM "post"', + string: 'SELECT COUNT(*) "post_amount" FROM "post"' }, params: [] }); @@ -68,6 +94,14 @@ Harness.test({ text : 'SELECT COUNT(`post`.`content`) AS `content_count` FROM `post`', string: 'SELECT COUNT(`post`.`content`) AS `content_count` FROM `post`' }, + mssql: { + text : 'SELECT COUNT([post].[content]) AS [content_count] FROM [post]', + string: 'SELECT COUNT([post].[content]) AS [content_count] FROM [post]' + }, + oracle: { + text : 'SELECT COUNT("post"."content") "content_count" FROM "post"', + string: 'SELECT COUNT("post"."content") "content_count" FROM "post"' + }, params: [] }); @@ -85,6 +119,14 @@ Harness.test({ text : 'SELECT COUNT(`post`.`content`) AS `content_count` FROM `post`', string: 'SELECT COUNT(`post`.`content`) AS `content_count` FROM `post`' }, + mssql: { + text : 'SELECT COUNT([post].[content]) AS [content_count] FROM [post]', + string: 'SELECT COUNT([post].[content]) AS [content_count] FROM [post]' + }, + oracle: { + text : 'SELECT COUNT("post"."content") "content_count" FROM "post"', + string: 'SELECT COUNT("post"."content") "content_count" FROM "post"' + }, params: [] }); @@ -102,6 +144,35 @@ Harness.test({ text : 'SELECT COUNT(`post`.`content`) AS `content_count` FROM `post`', string: 'SELECT COUNT(`post`.`content`) AS `content_count` FROM `post`' }, + mssql: { + text : 'SELECT COUNT([post].[content]) AS [content_count] FROM [post]', + string: 'SELECT COUNT([post].[content]) AS [content_count] FROM [post]' + }, + oracle: { + text : 'SELECT COUNT("post"."content") "content_count" FROM "post"', + string: 'SELECT COUNT("post"."content") "content_count" FROM "post"' + }, + params: [] +}); + +Harness.test({ + query: customerAlias.select(customerAlias.count()), + pg: { + text : 'SELECT COUNT("customer".*) AS "customer_count" FROM "customer"', + string: 'SELECT COUNT("customer".*) AS "customer_count" FROM "customer"' + }, + sqlite: { + text : 'SELECT COUNT("customer".*) AS "customer_count" FROM "customer"', + string: 'SELECT COUNT("customer".*) AS "customer_count" FROM "customer"' + }, + mysql: { + text : 'SELECT COUNT(*) AS `customer_count` FROM `customer`', + string: 'SELECT COUNT(*) AS `customer_count` FROM `customer`' + }, + oracle: { + text : 'SELECT COUNT(*) "customer_count" FROM "customer"', + string: 'SELECT COUNT(*) "customer_count" FROM "customer"' + }, params: [] }); @@ -119,6 +190,14 @@ Harness.test({ text : 'SELECT MIN(`post`.`id`) AS `id_min` FROM `post`', string: 'SELECT MIN(`post`.`id`) AS `id_min` FROM `post`' }, + mssql: { + text : 'SELECT MIN([post].[id]) AS [id_min] FROM [post]', + string: 'SELECT MIN([post].[id]) AS [id_min] FROM [post]' + }, + oracle: { + text : 'SELECT MIN("post"."id") "id_min" FROM "post"', + string: 'SELECT MIN("post"."id") "id_min" FROM "post"' + }, params: [] }); @@ -136,6 +215,14 @@ Harness.test({ text : 'SELECT MIN(`post`.`id`) AS `min_id` FROM `post`', string: 'SELECT MIN(`post`.`id`) AS `min_id` FROM `post`' }, + mssql: { + text : 'SELECT MIN([post].[id]) AS [min_id] FROM [post]', + string: 'SELECT MIN([post].[id]) AS [min_id] FROM [post]' + }, + oracle: { + text : 'SELECT MIN("post"."id") "min_id" FROM "post"', + string: 'SELECT MIN("post"."id") "min_id" FROM "post"' + }, params: [] }); @@ -153,6 +240,14 @@ Harness.test({ text : 'SELECT MIN(`post`.`id`) AS `min_id` FROM `post`', string: 'SELECT MIN(`post`.`id`) AS `min_id` FROM `post`' }, + mssql: { + text : 'SELECT MIN([post].[id]) AS [min_id] FROM [post]', + string: 'SELECT MIN([post].[id]) AS [min_id] FROM [post]' + }, + oracle: { + text : 'SELECT MIN("post"."id") "min_id" FROM "post"', + string: 'SELECT MIN("post"."id") "min_id" FROM "post"' + }, params: [] }); @@ -170,6 +265,14 @@ Harness.test({ text : 'SELECT MAX(`post`.`id`) AS `id_max` FROM `post`', string: 'SELECT MAX(`post`.`id`) AS `id_max` FROM `post`' }, + mssql: { + text : 'SELECT MAX([post].[id]) AS [id_max] FROM [post]', + string: 'SELECT MAX([post].[id]) AS [id_max] FROM [post]' + }, + oracle: { + text : 'SELECT MAX("post"."id") "id_max" FROM "post"', + string: 'SELECT MAX("post"."id") "id_max" FROM "post"' + }, params: [] }); @@ -187,6 +290,14 @@ Harness.test({ text : 'SELECT MAX(`post`.`id`) AS `max_id` FROM `post`', string: 'SELECT MAX(`post`.`id`) AS `max_id` FROM `post`' }, + mssql: { + text : 'SELECT MAX([post].[id]) AS [max_id] FROM [post]', + string: 'SELECT MAX([post].[id]) AS [max_id] FROM [post]' + }, + oracle: { + text : 'SELECT MAX("post"."id") "max_id" FROM "post"', + string: 'SELECT MAX("post"."id") "max_id" FROM "post"' + }, params: [] }); @@ -204,6 +315,14 @@ Harness.test({ text : 'SELECT MAX(`post`.`id`) AS `max_id` FROM `post`', string: 'SELECT MAX(`post`.`id`) AS `max_id` FROM `post`' }, + mssql: { + text : 'SELECT MAX([post].[id]) AS [max_id] FROM [post]', + string: 'SELECT MAX([post].[id]) AS [max_id] FROM [post]' + }, + oracle: { + text : 'SELECT MAX("post"."id") "max_id" FROM "post"', + string: 'SELECT MAX("post"."id") "max_id" FROM "post"' + }, params: [] }); @@ -221,6 +340,15 @@ Harness.test({ text : 'SELECT SUM(`post`.`id`) AS `id_sum` FROM `post`', string: 'SELECT SUM(`post`.`id`) AS `id_sum` FROM `post`' }, + mssql: { + text : 'SELECT SUM([post].[id]) AS [id_sum] FROM [post]', + string: 'SELECT SUM([post].[id]) AS [id_sum] FROM [post]' + }, + oracle: { + text : 'SELECT SUM("post"."id") "id_sum" FROM "post"', + string: 'SELECT SUM("post"."id") "id_sum" FROM "post"' + }, + params: [] }); Harness.test({ @@ -237,6 +365,15 @@ Harness.test({ text : 'SELECT SUM(`post`.`id`) AS `sum_id` FROM `post`', string: 'SELECT SUM(`post`.`id`) AS `sum_id` FROM `post`' }, + mssql: { + text : 'SELECT SUM([post].[id]) AS [sum_id] FROM [post]', + string: 'SELECT SUM([post].[id]) AS [sum_id] FROM [post]' + }, + oracle: { + text : 'SELECT SUM("post"."id") "sum_id" FROM "post"', + string: 'SELECT SUM("post"."id") "sum_id" FROM "post"' + }, + params: [] }); Harness.test({ @@ -253,6 +390,15 @@ Harness.test({ text : 'SELECT SUM(`post`.`id`) AS `sum_id` FROM `post`', string: 'SELECT SUM(`post`.`id`) AS `sum_id` FROM `post`' }, + mssql: { + text : 'SELECT SUM([post].[id]) AS [sum_id] FROM [post]', + string: 'SELECT SUM([post].[id]) AS [sum_id] FROM [post]' + }, + oracle: { + text : 'SELECT SUM("post"."id") "sum_id" FROM "post"', + string: 'SELECT SUM("post"."id") "sum_id" FROM "post"' + }, + params: [] }); Harness.test({ @@ -269,6 +415,15 @@ Harness.test({ text : 'SELECT AVG(`post`.`id`) AS `id_avg` FROM `post`', string: 'SELECT AVG(`post`.`id`) AS `id_avg` FROM `post`' }, + mssql: { + text : 'SELECT AVG([post].[id]) AS [id_avg] FROM [post]', + string: 'SELECT AVG([post].[id]) AS [id_avg] FROM [post]' + }, + oracle: { + text : 'SELECT AVG("post"."id") "id_avg" FROM "post"', + string: 'SELECT AVG("post"."id") "id_avg" FROM "post"' + }, + params: [] }); Harness.test({ @@ -285,6 +440,15 @@ Harness.test({ text : 'SELECT AVG(`post`.`id`) AS `avg_id` FROM `post`', string: 'SELECT AVG(`post`.`id`) AS `avg_id` FROM `post`' }, + mssql: { + text : 'SELECT AVG([post].[id]) AS [avg_id] FROM [post]', + string: 'SELECT AVG([post].[id]) AS [avg_id] FROM [post]' + }, + oracle: { + text : 'SELECT AVG("post"."id") "avg_id" FROM "post"', + string: 'SELECT AVG("post"."id") "avg_id" FROM "post"' + }, + params: [] }); Harness.test({ @@ -301,4 +465,13 @@ Harness.test({ text : 'SELECT AVG(`post`.`id`) AS `avg_id` FROM `post`', string: 'SELECT AVG(`post`.`id`) AS `avg_id` FROM `post`' }, + mssql: { + text : 'SELECT AVG([post].[id]) AS [avg_id] FROM [post]', + string: 'SELECT AVG([post].[id]) AS [avg_id] FROM [post]' + }, + oracle: { + text : 'SELECT AVG("post"."id") "avg_id" FROM "post"', + string: 'SELECT AVG("post"."id") "avg_id" FROM "post"' + }, + params: [] }); diff --git a/test/dialects/alias-tests.js b/test/dialects/alias-tests.js index 6981aaa6..32db9308 100644 --- a/test/dialects/alias-tests.js +++ b/test/dialects/alias-tests.js @@ -2,6 +2,7 @@ var Harness = require('./support'); var customer = Harness.defineCustomerTable(); +var Sql = require('../../lib').setDialect('postgres'); Harness.test({ query: customer.select(customer.name.isNull().as('nameIsNull')), @@ -17,6 +18,14 @@ Harness.test({ text : 'SELECT (`customer`.`name` IS NULL) AS `nameIsNull` FROM `customer`', string: 'SELECT (`customer`.`name` IS NULL) AS `nameIsNull` FROM `customer`' }, + mssql: { + text : 'SELECT ([customer].[name] IS NULL) AS [nameIsNull] FROM [customer]', + string: 'SELECT ([customer].[name] IS NULL) AS [nameIsNull] FROM [customer]' + }, + oracle: { + text : 'SELECT ("customer"."name" IS NULL) "nameIsNull" FROM "customer"', + string: 'SELECT ("customer"."name" IS NULL) "nameIsNull" FROM "customer"' + }, params: [] }); @@ -34,6 +43,14 @@ Harness.test({ text : 'SELECT (`customer`.`name` + `customer`.`age`) AS `nameAndAge` FROM `customer` WHERE ((`customer`.`age` > ?) AND (`customer`.`age` < ?))', string: 'SELECT (`customer`.`name` + `customer`.`age`) AS `nameAndAge` FROM `customer` WHERE ((`customer`.`age` > 10) AND (`customer`.`age` < 20))' }, + mssql: { + text : 'SELECT ([customer].[name] + [customer].[age]) AS [nameAndAge] FROM [customer] WHERE (([customer].[age] > @1) AND ([customer].[age] < @2))', + string: 'SELECT ([customer].[name] + [customer].[age]) AS [nameAndAge] FROM [customer] WHERE (([customer].[age] > 10) AND ([customer].[age] < 20))' + }, + oracle: { + text : 'SELECT ("customer"."name" + "customer"."age") "nameAndAge" FROM "customer" WHERE (("customer"."age" > :1) AND ("customer"."age" < :2))', + string: 'SELECT ("customer"."name" + "customer"."age") "nameAndAge" FROM "customer" WHERE (("customer"."age" > 10) AND ("customer"."age" < 20))' + }, params: [10, 20] }); @@ -51,5 +68,55 @@ Harness.test({ text : 'SELECT (`customer`.`age` BETWEEN ? AND ?) AS `ageBetween` FROM `customer`', string: 'SELECT (`customer`.`age` BETWEEN 10 AND 20) AS `ageBetween` FROM `customer`' }, + mssql: { + text : 'SELECT ([customer].[age] BETWEEN @1 AND @2) AS [ageBetween] FROM [customer]', + string: 'SELECT ([customer].[age] BETWEEN 10 AND 20) AS [ageBetween] FROM [customer]' + }, + oracle: { + text : 'SELECT ("customer"."age" BETWEEN :1 AND :2) "ageBetween" FROM "customer"', + string: 'SELECT ("customer"."age" BETWEEN 10 AND 20) "ageBetween" FROM "customer"' + }, + params: [10, 20] +}); + +Harness.test({ + query: customer.select(Sql.functions.ROUND(customer.age.as('ageBetween'), 2)), + pg: { + text : 'SELECT ROUND("customer"."age", $1) FROM "customer"', + string: 'SELECT ROUND("customer"."age", 2) FROM "customer"' + }, + sqlite: { + text : 'SELECT ROUND("customer"."age", $1) FROM "customer"', + string: 'SELECT ROUND("customer"."age", 2) FROM "customer"' + }, + mysql: { + text : 'SELECT ROUND(`customer`.`age`, ?) FROM `customer`', + string: 'SELECT ROUND(`customer`.`age`, 2) FROM `customer`' + }, + mssql: { + text : 'SELECT ROUND([customer].[age], @1) FROM [customer]', + string: 'SELECT ROUND([customer].[age], 2) FROM [customer]' + }, + oracle: { + text : 'SELECT ROUND("customer"."age", :1) FROM "customer"', + string: 'SELECT ROUND("customer"."age", 2) FROM "customer"' + }, + params: [2] +}); + +Harness.test({ + query: customer.select(customer.age.notBetween(10, 20).as('ageNotBetween')), + pg: { + text : 'SELECT ("customer"."age" NOT BETWEEN $1 AND $2) AS "ageNotBetween" FROM "customer"', + string: 'SELECT ("customer"."age" NOT BETWEEN 10 AND 20) AS "ageNotBetween" FROM "customer"' + }, + sqlite: { + text : 'SELECT ("customer"."age" NOT BETWEEN $1 AND $2) AS "ageNotBetween" FROM "customer"', + string: 'SELECT ("customer"."age" NOT BETWEEN 10 AND 20) AS "ageNotBetween" FROM "customer"' + }, + mysql: { + text : 'SELECT (`customer`.`age` NOT BETWEEN ? AND ?) AS `ageNotBetween` FROM `customer`', + string: 'SELECT (`customer`.`age` NOT BETWEEN 10 AND 20) AS `ageNotBetween` FROM `customer`' + }, params: [10, 20] }); diff --git a/test/dialects/alter-table-tests.js b/test/dialects/alter-table-tests.js index 71a5c396..d050da3d 100644 --- a/test/dialects/alter-table-tests.js +++ b/test/dialects/alter-table-tests.js @@ -18,6 +18,14 @@ Harness.test({ text : 'ALTER TABLE `post` DROP COLUMN `content`', string: 'ALTER TABLE `post` DROP COLUMN `content`' }, + mssql: { + text : 'ALTER TABLE [post] DROP COLUMN [content]', + string: 'ALTER TABLE [post] DROP COLUMN [content]' + }, + oracle: { + text : 'ALTER TABLE "post" DROP ("content")', + string: 'ALTER TABLE "post" DROP ("content")' + }, params: [] }); @@ -35,6 +43,14 @@ Harness.test({ text : 'ALTER TABLE `post` DROP COLUMN `content`, DROP COLUMN `userId`', string: 'ALTER TABLE `post` DROP COLUMN `content`, DROP COLUMN `userId`' }, + mssql: { + text : 'ALTER TABLE [post] DROP COLUMN [content], [userId]', + string: 'ALTER TABLE [post] DROP COLUMN [content], [userId]' + }, + oracle: { + text : 'ALTER TABLE "post" DROP ("content", "userId")', + string: 'ALTER TABLE "post" DROP ("content", "userId")' + }, params: [] }); @@ -52,6 +68,14 @@ Harness.test({ text : 'ALTER TABLE `post` DROP COLUMN `content`, DROP COLUMN `userId`', string: 'ALTER TABLE `post` DROP COLUMN `content`, DROP COLUMN `userId`' }, + mssql: { + text : 'ALTER TABLE [post] DROP COLUMN [content], [userId]', + string: 'ALTER TABLE [post] DROP COLUMN [content], [userId]' + }, + oracle: { + text : 'ALTER TABLE "post" DROP ("content", "userId")', + string: 'ALTER TABLE "post" DROP ("content", "userId")' + }, params: [] }); @@ -69,6 +93,10 @@ Harness.test({ text : 'ALTER TABLE `post` RENAME TO `posts`', string: 'ALTER TABLE `post` RENAME TO `posts`' }, + mssql: { + text : 'EXEC sp_rename [post], [posts]', + string: 'EXEC sp_rename [post], [posts]' + }, params: [] }); @@ -98,6 +126,14 @@ Harness.test({ text : 'ALTER TABLE `group` ADD COLUMN `id` varchar(100)', string: 'ALTER TABLE `group` ADD COLUMN `id` varchar(100)' }, + mssql: { + text : 'ALTER TABLE [group] ADD [id] varchar(100)', + string: 'ALTER TABLE [group] ADD [id] varchar(100)' + }, + oracle: { + text : 'ALTER TABLE "group" ADD ("id" varchar(100))', + string: 'ALTER TABLE "group" ADD ("id" varchar(100))' + }, params: [] }); @@ -115,6 +151,14 @@ Harness.test({ text : 'ALTER TABLE `group` ADD COLUMN `id` varchar(100), ADD COLUMN `userId` varchar(100)', string: 'ALTER TABLE `group` ADD COLUMN `id` varchar(100), ADD COLUMN `userId` varchar(100)' }, + mssql: { + text : 'ALTER TABLE [group] ADD [id] varchar(100), [userId] varchar(100)', + string: 'ALTER TABLE [group] ADD [id] varchar(100), [userId] varchar(100)' + }, + oracle: { + text : 'ALTER TABLE "group" ADD ("id" varchar(100), "userId" varchar(100))', + string: 'ALTER TABLE "group" ADD ("id" varchar(100), "userId" varchar(100))' + }, params: [] }); @@ -132,6 +176,14 @@ Harness.test({ text : 'ALTER TABLE `group` ADD COLUMN `id` varchar(100), ADD COLUMN `userId` varchar(100)', string: 'ALTER TABLE `group` ADD COLUMN `id` varchar(100), ADD COLUMN `userId` varchar(100)' }, + mssql: { + text : 'ALTER TABLE [group] ADD [id] varchar(100), [userId] varchar(100)', + string: 'ALTER TABLE [group] ADD [id] varchar(100), [userId] varchar(100)' + }, + oracle: { + text : 'ALTER TABLE "group" ADD ("id" varchar(100), "userId" varchar(100))', + string: 'ALTER TABLE "group" ADD ("id" varchar(100), "userId" varchar(100))' + }, params: [] }); @@ -149,6 +201,10 @@ Harness.test({ text : 'Sqlite cannot rename columns', throws: true }, + mssql: { + text : 'EXEC sp_rename \'[group].[userId]\', [newUserId], \'COLUMN\'', + string: 'EXEC sp_rename \'[group].[userId]\', [newUserId], \'COLUMN\'' + }, params: [] }); @@ -166,6 +222,10 @@ Harness.test({ text : 'ALTER TABLE `group` CHANGE COLUMN `userId` `newUserId` varchar(100)', string: 'ALTER TABLE `group` CHANGE COLUMN `userId` `newUserId` varchar(100)' }, + mssql: { + text : 'EXEC sp_rename \'[group].[userId]\', [newUserId], \'COLUMN\'', + string: 'EXEC sp_rename \'[group].[userId]\', [newUserId], \'COLUMN\'' + }, params: [] }); @@ -183,6 +243,10 @@ Harness.test({ text : 'ALTER TABLE `group` CHANGE COLUMN `userId` `id` varchar(100)', string: 'ALTER TABLE `group` CHANGE COLUMN `userId` `id` varchar(100)' }, + mssql: { + text : 'EXEC sp_rename \'[group].[userId]\', [id], \'COLUMN\'', + string: 'EXEC sp_rename \'[group].[userId]\', [id], \'COLUMN\'' + }, params: [] }); @@ -208,5 +272,67 @@ Harness.test({ sqlite: { text : 'Sqlite cannot rename columns', throws: true + }, + mssql: { + text : 'EXEC sp_rename \'[UserWithSignature].[Signature]\', [sig], \'COLUMN\'', + string: 'EXEC sp_rename \'[UserWithSignature].[Signature]\', [sig], \'COLUMN\'' } }); + +var post = Table.define({ + name: 'post', + columns: [{ + name: 'userId', + dataType: 'int', + references: { + table: 'user', + column: 'id' + } + }, { + name: 'picture', + dataType: 'varchar(100)', + references: {} + }] +}); + +Harness.test({ + query: post.alter().addColumn(post.userId), + pg: { + text : 'ALTER TABLE "post" ADD COLUMN "userId" int REFERENCES "user"("id")', + string: 'ALTER TABLE "post" ADD COLUMN "userId" int REFERENCES "user"("id")' + }, + sqlite: { + text : 'ALTER TABLE "post" ADD COLUMN "userId" int REFERENCES "user"("id")', + string: 'ALTER TABLE "post" ADD COLUMN "userId" int REFERENCES "user"("id")' + }, + mysql: { + text : 'ALTER TABLE `post` ADD COLUMN `userId` int REFERENCES `user`(`id`)', + string: 'ALTER TABLE `post` ADD COLUMN `userId` int REFERENCES `user`(`id`)' + }, + oracle: { + text : 'ALTER TABLE "post" ADD ("userId" int REFERENCES "user"("id"))', + string: 'ALTER TABLE "post" ADD ("userId" int REFERENCES "user"("id"))' + }, + params: [] +}); + +Harness.test({ + query: post.alter().addColumn(post.picture), + pg: { + text : 'ALTER TABLE "post" ADD COLUMN "picture" varchar(100)', + string: 'ALTER TABLE "post" ADD COLUMN "picture" varchar(100)' + }, + sqlite: { + text : 'ALTER TABLE "post" ADD COLUMN "picture" varchar(100)', + string: 'ALTER TABLE "post" ADD COLUMN "picture" varchar(100)' + }, + mysql: { + text : 'ALTER TABLE `post` ADD COLUMN `picture` varchar(100)', + string: 'ALTER TABLE `post` ADD COLUMN `picture` varchar(100)' + }, + oracle: { + text : 'ALTER TABLE "post" ADD ("picture" varchar(100))', + string: 'ALTER TABLE "post" ADD ("picture" varchar(100))' + }, + params: [] +}); diff --git a/test/dialects/binary-clause-tests.js b/test/dialects/binary-clause-tests.js index 23c299c5..69c355fe 100644 --- a/test/dialects/binary-clause-tests.js +++ b/test/dialects/binary-clause-tests.js @@ -2,8 +2,10 @@ var Harness = require('./support'); var customer = Harness.defineCustomerTable(); +var customerAlias = Harness.defineCustomerAliasTable(); var post = Harness.definePostTable(); + Harness.test({ query: customer.select(customer.name.plus(customer.age)), pg: { @@ -18,6 +20,35 @@ Harness.test({ text : 'SELECT (`customer`.`name` + `customer`.`age`) FROM `customer`', string: 'SELECT (`customer`.`name` + `customer`.`age`) FROM `customer`' }, + mssql: { + text : 'SELECT ([customer].[name] + [customer].[age]) FROM [customer]', + string: 'SELECT ([customer].[name] + [customer].[age]) FROM [customer]' + }, + oracle: { + text : 'SELECT ("customer"."name" + "customer"."age") FROM "customer"', + string: 'SELECT ("customer"."name" + "customer"."age") FROM "customer"' + }, + params: [] +}); + +Harness.test({ + query: customerAlias.select(customerAlias.name_alias.plus(customerAlias.age_alias)), + pg: { + text : 'SELECT ("customer"."name" + "customer"."age") FROM "customer"', + string: 'SELECT ("customer"."name" + "customer"."age") FROM "customer"' + }, + sqlite: { + text : 'SELECT ("customer"."name" + "customer"."age") FROM "customer"', + string: 'SELECT ("customer"."name" + "customer"."age") FROM "customer"' + }, + mysql: { + text : 'SELECT (`customer`.`name` + `customer`.`age`) FROM `customer`', + string: 'SELECT (`customer`.`name` + `customer`.`age`) FROM `customer`' + }, + mssql: { + text : 'SELECT ([customer].[name] + [customer].[age]) FROM [customer]', + string: 'SELECT ([customer].[name] + [customer].[age]) FROM [customer]' + }, params: [] }); @@ -35,6 +66,14 @@ Harness.test({ text : 'SELECT (`post`.`content` + ?) FROM `post` WHERE (`post`.`userId` IN (SELECT `customer`.`id` FROM `customer`))', string: 'SELECT (`post`.`content` + \'!\') FROM `post` WHERE (`post`.`userId` IN (SELECT `customer`.`id` FROM `customer`))' }, + mssql: { + text : 'SELECT ([post].[content] + @1) FROM [post] WHERE ([post].[userId] IN (SELECT [customer].[id] FROM [customer]))', + string: 'SELECT ([post].[content] + \'!\') FROM [post] WHERE ([post].[userId] IN (SELECT [customer].[id] FROM [customer]))' + }, + oracle: { + text : 'SELECT ("post"."content" + :1) FROM "post" WHERE ("post"."userId" IN (SELECT "customer"."id" FROM "customer"))', + string: 'SELECT ("post"."content" + \'!\') FROM "post" WHERE ("post"."userId" IN (SELECT "customer"."id" FROM "customer"))' + }, params: ['!'] }); @@ -52,5 +91,13 @@ Harness.test({ text : 'SELECT ((`post`.`id` + ?) + `post`.`content`) FROM `post` WHERE (`post`.`userId` NOT IN (SELECT `customer`.`id` FROM `customer`))', string: 'SELECT ((`post`.`id` + \': \') + `post`.`content`) FROM `post` WHERE (`post`.`userId` NOT IN (SELECT `customer`.`id` FROM `customer`))' }, + mssql: { + text : 'SELECT (([post].[id] + @1) + [post].[content]) FROM [post] WHERE ([post].[userId] NOT IN (SELECT [customer].[id] FROM [customer]))', + string: 'SELECT (([post].[id] + \': \') + [post].[content]) FROM [post] WHERE ([post].[userId] NOT IN (SELECT [customer].[id] FROM [customer]))' + }, + oracle: { + text : 'SELECT (("post"."id" + :1) + "post"."content") FROM "post" WHERE ("post"."userId" NOT IN (SELECT "customer"."id" FROM "customer"))', + string: 'SELECT (("post"."id" + \': \') + "post"."content") FROM "post" WHERE ("post"."userId" NOT IN (SELECT "customer"."id" FROM "customer"))' + }, params: [': '] }); diff --git a/test/dialects/case-tests.js b/test/dialects/case-tests.js index 61f193ec..f492a4f5 100644 --- a/test/dialects/case-tests.js +++ b/test/dialects/case-tests.js @@ -8,15 +8,25 @@ Harness.test({ query: customer.select(customer.age.case([true, false], [0, 1], 2)), pg: { text : 'SELECT (CASE WHEN $1 THEN $2 WHEN $3 THEN $4 ELSE $5 END) FROM "customer"', - string: 'SELECT (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END) FROM "customer"', + string: 'SELECT (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END) FROM "customer"' }, sqlite: { text : 'SELECT (CASE WHEN $1 THEN $2 WHEN $3 THEN $4 ELSE $5 END) FROM "customer"', - string: 'SELECT (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END) FROM "customer"', + string: 'SELECT (CASE WHEN 1 THEN 0 WHEN 0 THEN 1 ELSE 2 END) FROM "customer"' }, mysql: { text : 'SELECT (CASE WHEN ? THEN ? WHEN ? THEN ? ELSE ? END) FROM `customer`', - string: 'SELECT (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END) FROM `customer`', + string: 'SELECT (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END) FROM `customer`' + }, + mssql: { + text : 'SELECT (CASE WHEN 1=1 THEN @1 WHEN 0=1 THEN @2 ELSE @3 END) FROM [customer]', + string: 'SELECT (CASE WHEN 1=1 THEN 0 WHEN 0=1 THEN 1 ELSE 2 END) FROM [customer]', + params: [0, 1, 2] + }, + oracle: { + text : 'SELECT (CASE WHEN 1=1 THEN :1 WHEN 0=1 THEN :2 ELSE :3 END) FROM "customer"', + string: 'SELECT (CASE WHEN 1=1 THEN 0 WHEN 0=1 THEN 1 ELSE 2 END) FROM "customer"', + params: [0, 1, 2] }, params: [true, 0, false, 1, 2] }); @@ -26,15 +36,25 @@ Harness.test({ query: customer.select(customer.age.plus(customer.age.case([true, false], [0, 1], 2))), pg: { text : 'SELECT ("customer"."age" + (CASE WHEN $1 THEN $2 WHEN $3 THEN $4 ELSE $5 END)) FROM "customer"', - string: 'SELECT ("customer"."age" + (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END)) FROM "customer"', + string: 'SELECT ("customer"."age" + (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END)) FROM "customer"' }, sqlite: { text : 'SELECT ("customer"."age" + (CASE WHEN $1 THEN $2 WHEN $3 THEN $4 ELSE $5 END)) FROM "customer"', - string: 'SELECT ("customer"."age" + (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END)) FROM "customer"', + string: 'SELECT ("customer"."age" + (CASE WHEN 1 THEN 0 WHEN 0 THEN 1 ELSE 2 END)) FROM "customer"' }, mysql: { text : 'SELECT (`customer`.`age` + (CASE WHEN ? THEN ? WHEN ? THEN ? ELSE ? END)) FROM `customer`', - string: 'SELECT (`customer`.`age` + (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END)) FROM `customer`', + string: 'SELECT (`customer`.`age` + (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END)) FROM `customer`' + }, + mssql: { + text : 'SELECT ([customer].[age] + (CASE WHEN 1=1 THEN @1 WHEN 0=1 THEN @2 ELSE @3 END)) FROM [customer]', + string: 'SELECT ([customer].[age] + (CASE WHEN 1=1 THEN 0 WHEN 0=1 THEN 1 ELSE 2 END)) FROM [customer]', + params: [0, 1, 2] + }, + oracle: { + text : 'SELECT ("customer"."age" + (CASE WHEN 1=1 THEN :1 WHEN 0=1 THEN :2 ELSE :3 END)) FROM "customer"', + string: 'SELECT ("customer"."age" + (CASE WHEN 1=1 THEN 0 WHEN 0=1 THEN 1 ELSE 2 END)) FROM "customer"', + params: [0, 1, 2] }, params: [true, 0, false, 1, 2] }); @@ -48,11 +68,21 @@ Harness.test({ }, sqlite: { text : 'SELECT ((CASE WHEN $1 THEN $2 WHEN $3 THEN $4 ELSE $5 END) + $6) FROM "customer"', - string: 'SELECT ((CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END) + 3) FROM "customer"', + string: 'SELECT ((CASE WHEN 1 THEN 0 WHEN 0 THEN 1 ELSE 2 END) + 3) FROM "customer"' }, mysql: { text : 'SELECT ((CASE WHEN ? THEN ? WHEN ? THEN ? ELSE ? END) + ?) FROM `customer`', - string: 'SELECT ((CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END) + 3) FROM `customer`', + string: 'SELECT ((CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE 2 END) + 3) FROM `customer`' + }, + mssql: { + text : 'SELECT ((CASE WHEN 1=1 THEN @1 WHEN 0=1 THEN @2 ELSE @3 END) + @4) FROM [customer]', + string: 'SELECT ((CASE WHEN 1=1 THEN 0 WHEN 0=1 THEN 1 ELSE 2 END) + 3) FROM [customer]', + params: [0, 1, 2, 3] + }, + oracle: { + text : 'SELECT ((CASE WHEN 1=1 THEN :1 WHEN 0=1 THEN :2 ELSE :3 END) + :4) FROM "customer"', + string: 'SELECT ((CASE WHEN 1=1 THEN 0 WHEN 0=1 THEN 1 ELSE 2 END) + 3) FROM "customer"', + params: [0, 1, 2, 3] }, params: [true, 0, false, 1, 2, 3] }); @@ -66,11 +96,21 @@ Harness.test({ }, sqlite: { text : 'SELECT (CASE WHEN $1 THEN $2 WHEN $3 THEN $4 ELSE ("customer"."age" BETWEEN $5 AND $6) END) FROM "customer"', - string: 'SELECT (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE ("customer"."age" BETWEEN 10 AND 20) END) FROM "customer"', + string: 'SELECT (CASE WHEN 1 THEN 0 WHEN 0 THEN 1 ELSE ("customer"."age" BETWEEN 10 AND 20) END) FROM "customer"' }, mysql: { text : 'SELECT (CASE WHEN ? THEN ? WHEN ? THEN ? ELSE (`customer`.`age` BETWEEN ? AND ?) END) FROM `customer`', - string: 'SELECT (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE (`customer`.`age` BETWEEN 10 AND 20) END) FROM `customer`', + string: 'SELECT (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 ELSE (`customer`.`age` BETWEEN 10 AND 20) END) FROM `customer`' + }, + mssql: { + text : 'SELECT (CASE WHEN 1=1 THEN @1 WHEN 0=1 THEN @2 ELSE ([customer].[age] BETWEEN @3 AND @4) END) FROM [customer]', + string: 'SELECT (CASE WHEN 1=1 THEN 0 WHEN 0=1 THEN 1 ELSE ([customer].[age] BETWEEN 10 AND 20) END) FROM [customer]', + params: [0, 1, 10, 20] + }, + oracle: { + text : 'SELECT (CASE WHEN 1=1 THEN :1 WHEN 0=1 THEN :2 ELSE ("customer"."age" BETWEEN :3 AND :4) END) FROM "customer"', + string: 'SELECT (CASE WHEN 1=1 THEN 0 WHEN 0=1 THEN 1 ELSE ("customer"."age" BETWEEN 10 AND 20) END) FROM "customer"', + params: [0, 1, 10, 20] }, params: [true, 0, false, 1, 10, 20] }); @@ -84,11 +124,21 @@ Harness.test({ }, sqlite: { text : 'SELECT (CASE WHEN $1 THEN $2 WHEN $3 THEN $4 END) FROM "customer"', - string: 'SELECT (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 END) FROM "customer"', + string: 'SELECT (CASE WHEN 1 THEN 0 WHEN 0 THEN 1 END) FROM "customer"' }, mysql: { text : 'SELECT (CASE WHEN ? THEN ? WHEN ? THEN ? END) FROM `customer`', - string: 'SELECT (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 END) FROM `customer`', + string: 'SELECT (CASE WHEN TRUE THEN 0 WHEN FALSE THEN 1 END) FROM `customer`' + }, + mssql: { + text : 'SELECT (CASE WHEN 1=1 THEN @1 WHEN 0=1 THEN @2 END) FROM [customer]', + string: 'SELECT (CASE WHEN 1=1 THEN 0 WHEN 0=1 THEN 1 END) FROM [customer]', + params: [0, 1] + }, + oracle: { + text : 'SELECT (CASE WHEN 1=1 THEN :1 WHEN 0=1 THEN :2 END) FROM "customer"', + string: 'SELECT (CASE WHEN 1=1 THEN 0 WHEN 0=1 THEN 1 END) FROM "customer"', + params: [0, 1] }, params: [true, 0, false, 1] }); @@ -98,15 +148,23 @@ Harness.test({ query: customer.select(customer.age.case([customer.age.in([10, 20, 30]), customer.age.lte(60)], [0, 1], 2)), pg: { text : 'SELECT (CASE WHEN ("customer"."age" IN ($1, $2, $3)) THEN $4 WHEN ("customer"."age" <= $5) THEN $6 ELSE $7 END) FROM "customer"', - string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN 0 WHEN ("customer"."age" <= 60) THEN 1 ELSE 2 END) FROM "customer"', + string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN 0 WHEN ("customer"."age" <= 60) THEN 1 ELSE 2 END) FROM "customer"' }, sqlite: { text : 'SELECT (CASE WHEN ("customer"."age" IN ($1, $2, $3)) THEN $4 WHEN ("customer"."age" <= $5) THEN $6 ELSE $7 END) FROM "customer"', - string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN 0 WHEN ("customer"."age" <= 60) THEN 1 ELSE 2 END) FROM "customer"', + string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN 0 WHEN ("customer"."age" <= 60) THEN 1 ELSE 2 END) FROM "customer"' }, mysql: { text : 'SELECT (CASE WHEN (`customer`.`age` IN (?, ?, ?)) THEN ? WHEN (`customer`.`age` <= ?) THEN ? ELSE ? END) FROM `customer`', - string: 'SELECT (CASE WHEN (`customer`.`age` IN (10, 20, 30)) THEN 0 WHEN (`customer`.`age` <= 60) THEN 1 ELSE 2 END) FROM `customer`', + string: 'SELECT (CASE WHEN (`customer`.`age` IN (10, 20, 30)) THEN 0 WHEN (`customer`.`age` <= 60) THEN 1 ELSE 2 END) FROM `customer`' + }, + mssql: { + text : 'SELECT (CASE WHEN ([customer].[age] IN (@1, @2, @3)) THEN @4 WHEN ([customer].[age] <= @5) THEN @6 ELSE @7 END) FROM [customer]', + string: 'SELECT (CASE WHEN ([customer].[age] IN (10, 20, 30)) THEN 0 WHEN ([customer].[age] <= 60) THEN 1 ELSE 2 END) FROM [customer]' + }, + oracle: { + text : 'SELECT (CASE WHEN ("customer"."age" IN (:1, :2, :3)) THEN :4 WHEN ("customer"."age" <= :5) THEN :6 ELSE :7 END) FROM "customer"', + string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN 0 WHEN ("customer"."age" <= 60) THEN 1 ELSE 2 END) FROM "customer"' }, params: [10, 20, 30, 0, 60, 1, 2] }); @@ -116,15 +174,23 @@ Harness.test({ query: customer.select(customer.age.case([customer.age.in([10, 20, 30]), customer.age.lte(60)], [0, 1])), pg: { text : 'SELECT (CASE WHEN ("customer"."age" IN ($1, $2, $3)) THEN $4 WHEN ("customer"."age" <= $5) THEN $6 END) FROM "customer"', - string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN 0 WHEN ("customer"."age" <= 60) THEN 1 END) FROM "customer"', + string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN 0 WHEN ("customer"."age" <= 60) THEN 1 END) FROM "customer"' }, sqlite: { text : 'SELECT (CASE WHEN ("customer"."age" IN ($1, $2, $3)) THEN $4 WHEN ("customer"."age" <= $5) THEN $6 END) FROM "customer"', - string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN 0 WHEN ("customer"."age" <= 60) THEN 1 END) FROM "customer"', + string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN 0 WHEN ("customer"."age" <= 60) THEN 1 END) FROM "customer"' }, mysql: { text : 'SELECT (CASE WHEN (`customer`.`age` IN (?, ?, ?)) THEN ? WHEN (`customer`.`age` <= ?) THEN ? END) FROM `customer`', - string: 'SELECT (CASE WHEN (`customer`.`age` IN (10, 20, 30)) THEN 0 WHEN (`customer`.`age` <= 60) THEN 1 END) FROM `customer`', + string: 'SELECT (CASE WHEN (`customer`.`age` IN (10, 20, 30)) THEN 0 WHEN (`customer`.`age` <= 60) THEN 1 END) FROM `customer`' + }, + mssql: { + text : 'SELECT (CASE WHEN ([customer].[age] IN (@1, @2, @3)) THEN @4 WHEN ([customer].[age] <= @5) THEN @6 END) FROM [customer]', + string: 'SELECT (CASE WHEN ([customer].[age] IN (10, 20, 30)) THEN 0 WHEN ([customer].[age] <= 60) THEN 1 END) FROM [customer]' + }, + oracle: { + text : 'SELECT (CASE WHEN ("customer"."age" IN (:1, :2, :3)) THEN :4 WHEN ("customer"."age" <= :5) THEN :6 END) FROM "customer"', + string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN 0 WHEN ("customer"."age" <= 60) THEN 1 END) FROM "customer"' }, params: [10, 20, 30, 0, 60, 1] }); @@ -134,15 +200,23 @@ Harness.test({ query: customer.select(customer.age.case([customer.age.in([10, 20, 30]), customer.age.lte(60)], [customer.age.plus(5), customer.age.minus(1)])), pg: { text : 'SELECT (CASE WHEN ("customer"."age" IN ($1, $2, $3)) THEN ("customer"."age" + $4) WHEN ("customer"."age" <= $5) THEN ("customer"."age" - $6) END) FROM "customer"', - string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN ("customer"."age" + 5) WHEN ("customer"."age" <= 60) THEN ("customer"."age" - 1) END) FROM "customer"', + string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN ("customer"."age" + 5) WHEN ("customer"."age" <= 60) THEN ("customer"."age" - 1) END) FROM "customer"' }, sqlite: { text : 'SELECT (CASE WHEN ("customer"."age" IN ($1, $2, $3)) THEN ("customer"."age" + $4) WHEN ("customer"."age" <= $5) THEN ("customer"."age" - $6) END) FROM "customer"', - string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN ("customer"."age" + 5) WHEN ("customer"."age" <= 60) THEN ("customer"."age" - 1) END) FROM "customer"', + string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN ("customer"."age" + 5) WHEN ("customer"."age" <= 60) THEN ("customer"."age" - 1) END) FROM "customer"' }, mysql: { text : 'SELECT (CASE WHEN (`customer`.`age` IN (?, ?, ?)) THEN (`customer`.`age` + ?) WHEN (`customer`.`age` <= ?) THEN (`customer`.`age` - ?) END) FROM `customer`', - string: 'SELECT (CASE WHEN (`customer`.`age` IN (10, 20, 30)) THEN (`customer`.`age` + 5) WHEN (`customer`.`age` <= 60) THEN (`customer`.`age` - 1) END) FROM `customer`', + string: 'SELECT (CASE WHEN (`customer`.`age` IN (10, 20, 30)) THEN (`customer`.`age` + 5) WHEN (`customer`.`age` <= 60) THEN (`customer`.`age` - 1) END) FROM `customer`' + }, + mssql: { + text : 'SELECT (CASE WHEN ([customer].[age] IN (@1, @2, @3)) THEN ([customer].[age] + @4) WHEN ([customer].[age] <= @5) THEN ([customer].[age] - @6) END) FROM [customer]', + string: 'SELECT (CASE WHEN ([customer].[age] IN (10, 20, 30)) THEN ([customer].[age] + 5) WHEN ([customer].[age] <= 60) THEN ([customer].[age] - 1) END) FROM [customer]' + }, + oracle: { + text : 'SELECT (CASE WHEN ("customer"."age" IN (:1, :2, :3)) THEN ("customer"."age" + :4) WHEN ("customer"."age" <= :5) THEN ("customer"."age" - :6) END) FROM "customer"', + string: 'SELECT (CASE WHEN ("customer"."age" IN (10, 20, 30)) THEN ("customer"."age" + 5) WHEN ("customer"."age" <= 60) THEN ("customer"."age" - 1) END) FROM "customer"' }, params: [10, 20, 30, 5, 60, 1] }); diff --git a/test/dialects/cast-tests.js b/test/dialects/cast-tests.js index 90e913e4..2295d720 100644 --- a/test/dialects/cast-tests.js +++ b/test/dialects/cast-tests.js @@ -2,6 +2,7 @@ var Harness = require('./support'); var customer = Harness.defineCustomerTable(); +var customerAlias = Harness.defineCustomerAliasTable(); // Cast columns. Harness.test({ @@ -18,6 +19,14 @@ Harness.test({ text : 'SELECT CAST(`customer`.`age` AS int) FROM `customer`', string: 'SELECT CAST(`customer`.`age` AS int) FROM `customer`' }, + mssql: { + text : 'SELECT CAST([customer].[age] AS int) FROM [customer]', + string: 'SELECT CAST([customer].[age] AS int) FROM [customer]' + }, + oracle: { + text : 'SELECT CAST("customer"."age" AS int) FROM "customer"', + string: 'SELECT CAST("customer"."age" AS int) FROM "customer"' + }, params: [] }); @@ -35,6 +44,14 @@ Harness.test({ text : 'SELECT CAST(`customer`.`name` AS varchar(10)) FROM `customer`', string: 'SELECT CAST(`customer`.`name` AS varchar(10)) FROM `customer`' }, + mssql: { + text : 'SELECT CAST([customer].[name] AS varchar(10)) FROM [customer]', + string: 'SELECT CAST([customer].[name] AS varchar(10)) FROM [customer]' + }, + oracle: { + text : 'SELECT CAST("customer"."name" AS varchar(10)) FROM "customer"', + string: 'SELECT CAST("customer"."name" AS varchar(10)) FROM "customer"' + }, params: [] }); @@ -43,15 +60,23 @@ Harness.test({ query: customer.select(customer.name.plus(customer.age).cast('varchar(15)')), pg: { text : 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"', - string: 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"', + string: 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"' }, sqlite: { text : 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"', - string: 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"', + string: 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"' }, mysql: { text : 'SELECT CAST((`customer`.`name` + `customer`.`age`) AS varchar(15)) FROM `customer`', - string: 'SELECT CAST((`customer`.`name` + `customer`.`age`) AS varchar(15)) FROM `customer`', + string: 'SELECT CAST((`customer`.`name` + `customer`.`age`) AS varchar(15)) FROM `customer`' + }, + mssql: { + text : 'SELECT CAST(([customer].[name] + [customer].[age]) AS varchar(15)) FROM [customer]', + string: 'SELECT CAST(([customer].[name] + [customer].[age]) AS varchar(15)) FROM [customer]' + }, + oracle: { + text : 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"', + string: 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"' }, params: [] }); @@ -71,6 +96,14 @@ Harness.test({ text : 'SELECT CAST(CAST(`customer`.`name` AS varchar(15)) AS varchar(10)) FROM `customer`', string: 'SELECT CAST(CAST(`customer`.`name` AS varchar(15)) AS varchar(10)) FROM `customer`' }, + mssql: { + text : 'SELECT CAST(CAST([customer].[name] AS varchar(15)) AS varchar(10)) FROM [customer]', + string: 'SELECT CAST(CAST([customer].[name] AS varchar(15)) AS varchar(10)) FROM [customer]' + }, + oracle: { + text : 'SELECT CAST(CAST("customer"."name" AS varchar(15)) AS varchar(10)) FROM "customer"', + string: 'SELECT CAST(CAST("customer"."name" AS varchar(15)) AS varchar(10)) FROM "customer"' + }, params: [] }); @@ -89,6 +122,14 @@ Harness.test({ text : 'SELECT `customer`.`name` FROM `customer` WHERE ((CAST(`customer`.`age` AS int) + ?) = ?)', string: 'SELECT `customer`.`name` FROM `customer` WHERE ((CAST(`customer`.`age` AS int) + 100) = 150)' }, + mssql: { + text : 'SELECT [customer].[name] FROM [customer] WHERE ((CAST([customer].[age] AS int) + @1) = @2)', + string: 'SELECT [customer].[name] FROM [customer] WHERE ((CAST([customer].[age] AS int) + 100) = 150)' + }, + oracle: { + text : 'SELECT "customer"."name" FROM "customer" WHERE ((CAST("customer"."age" AS int) + :1) = :2)', + string: 'SELECT "customer"."name" FROM "customer" WHERE ((CAST("customer"."age" AS int) + 100) = 150)' + }, params: [100, 150] }); @@ -107,5 +148,167 @@ Harness.test({ text : 'SELECT CAST(`customer`.`age` AS int) AS `age_int` FROM `customer`', string: 'SELECT CAST(`customer`.`age` AS int) AS `age_int` FROM `customer`' }, + mssql: { + text : 'SELECT CAST([customer].[age] AS int) AS [age_int] FROM [customer]', + string: 'SELECT CAST([customer].[age] AS int) AS [age_int] FROM [customer]' + }, + oracle: { + text : 'SELECT CAST("customer"."age" AS int) "age_int" FROM "customer"', + string: 'SELECT CAST("customer"."age" AS int) "age_int" FROM "customer"' + }, + params: [] +}); + +// Cast Aliased columns. +Harness.test({ + query: customerAlias.select(customerAlias.age_alias.cast('int')), + pg: { + text : 'SELECT CAST("customer"."age" AS int) FROM "customer"', + string: 'SELECT CAST("customer"."age" AS int) FROM "customer"' + }, + sqlite: { + text : 'SELECT CAST("customer"."age" AS int) FROM "customer"', + string: 'SELECT CAST("customer"."age" AS int) FROM "customer"' + }, + mysql: { + text : 'SELECT CAST(`customer`.`age` AS int) FROM `customer`', + string: 'SELECT CAST(`customer`.`age` AS int) FROM `customer`' + }, + mssql: { + text : 'SELECT CAST([customer].[age] AS int) FROM [customer]', + string: 'SELECT CAST([customer].[age] AS int) FROM [customer]' + }, + oracle: { + text : 'SELECT CAST("customer"."age" AS int) FROM "customer"', + string: 'SELECT CAST("customer"."age" AS int) FROM "customer"' + }, + params: [] +}); + +Harness.test({ + query: customerAlias.select(customerAlias.name_alias.cast('varchar(10)')), + pg: { + text : 'SELECT CAST("customer"."name" AS varchar(10)) FROM "customer"', + string: 'SELECT CAST("customer"."name" AS varchar(10)) FROM "customer"' + }, + sqlite: { + text : 'SELECT CAST("customer"."name" AS varchar(10)) FROM "customer"', + string: 'SELECT CAST("customer"."name" AS varchar(10)) FROM "customer"' + }, + mysql: { + text : 'SELECT CAST(`customer`.`name` AS varchar(10)) FROM `customer`', + string: 'SELECT CAST(`customer`.`name` AS varchar(10)) FROM `customer`' + }, + mssql: { + text : 'SELECT CAST([customer].[name] AS varchar(10)) FROM [customer]', + string: 'SELECT CAST([customer].[name] AS varchar(10)) FROM [customer]' + }, + oracle: { + text : 'SELECT CAST("customer"."name" AS varchar(10)) FROM "customer"', + string: 'SELECT CAST("customer"."name" AS varchar(10)) FROM "customer"' + }, + params: [] +}); +// Cast binary expressions for Aliased Column. +Harness.test({ + query: customerAlias.select(customerAlias.name_alias.plus(customerAlias.age_alias).cast('varchar(15)')), + pg: { + text : 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"', + string: 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"' + }, + sqlite: { + text : 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"', + string: 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"' + }, + mysql: { + text : 'SELECT CAST((`customer`.`name` + `customer`.`age`) AS varchar(15)) FROM `customer`', + string: 'SELECT CAST((`customer`.`name` + `customer`.`age`) AS varchar(15)) FROM `customer`' + }, + mssql: { + text : 'SELECT CAST(([customer].[name] + [customer].[age]) AS varchar(15)) FROM [customer]', + string: 'SELECT CAST(([customer].[name] + [customer].[age]) AS varchar(15)) FROM [customer]' + }, + oracle: { + text : 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"', + string: 'SELECT CAST(("customer"."name" + "customer"."age") AS varchar(15)) FROM "customer"' + }, + params: [] +}); + +// Cast cast expressions for aliased columns. +Harness.test({ + query: customerAlias.select(customerAlias.name_alias.cast('varchar(15)').cast('varchar(10)')), + pg: { + text : 'SELECT CAST(CAST("customer"."name" AS varchar(15)) AS varchar(10)) FROM "customer"', + string: 'SELECT CAST(CAST("customer"."name" AS varchar(15)) AS varchar(10)) FROM "customer"' + }, + sqlite: { + text : 'SELECT CAST(CAST("customer"."name" AS varchar(15)) AS varchar(10)) FROM "customer"', + string: 'SELECT CAST(CAST("customer"."name" AS varchar(15)) AS varchar(10)) FROM "customer"' + }, + mysql: { + text : 'SELECT CAST(CAST(`customer`.`name` AS varchar(15)) AS varchar(10)) FROM `customer`', + string: 'SELECT CAST(CAST(`customer`.`name` AS varchar(15)) AS varchar(10)) FROM `customer`' + }, + mssql: { + text : 'SELECT CAST(CAST([customer].[name] AS varchar(15)) AS varchar(10)) FROM [customer]', + string: 'SELECT CAST(CAST([customer].[name] AS varchar(15)) AS varchar(10)) FROM [customer]' + }, + oracle: { + text : 'SELECT CAST(CAST("customer"."name" AS varchar(15)) AS varchar(10)) FROM "customer"', + string: 'SELECT CAST(CAST("customer"."name" AS varchar(15)) AS varchar(10)) FROM "customer"' + }, + params: [] +}); + +// Cast in WHERE for aliased columns. +Harness.test({ + query: customerAlias.select(customerAlias.name_alias).where(customerAlias.age_alias.cast('int').plus(100).equals(150)), + pg: { + text : 'SELECT "customer"."name" AS "name_alias" FROM "customer" WHERE ((CAST("customer"."age" AS int) + $1) = $2)', + string: 'SELECT "customer"."name" AS "name_alias" FROM "customer" WHERE ((CAST("customer"."age" AS int) + 100) = 150)' + }, + sqlite: { + text : 'SELECT "customer"."name" AS "name_alias" FROM "customer" WHERE ((CAST("customer"."age" AS int) + $1) = $2)', + string: 'SELECT "customer"."name" AS "name_alias" FROM "customer" WHERE ((CAST("customer"."age" AS int) + 100) = 150)' + }, + mysql: { + text : 'SELECT `customer`.`name` AS `name_alias` FROM `customer` WHERE ((CAST(`customer`.`age` AS int) + ?) = ?)', + string: 'SELECT `customer`.`name` AS `name_alias` FROM `customer` WHERE ((CAST(`customer`.`age` AS int) + 100) = 150)' + }, + mssql: { + text : 'SELECT [customer].[name] AS [name_alias] FROM [customer] WHERE ((CAST([customer].[age] AS int) + @1) = @2)', + string: 'SELECT [customer].[name] AS [name_alias] FROM [customer] WHERE ((CAST([customer].[age] AS int) + 100) = 150)' + }, + oracle: { + text : 'SELECT "customer"."name" "name_alias" FROM "customer" WHERE ((CAST("customer"."age" AS int) + :1) = :2)', + string: 'SELECT "customer"."name" "name_alias" FROM "customer" WHERE ((CAST("customer"."age" AS int) + 100) = 150)' + }, + params: [100, 150] +}); + +// Alias cast. +Harness.test({ + query: customerAlias.select(customerAlias.age_alias.cast('int').as('age_int')), + pg: { + text : 'SELECT CAST("customer"."age" AS int) AS "age_int" FROM "customer"', + string: 'SELECT CAST("customer"."age" AS int) AS "age_int" FROM "customer"' + }, + sqlite: { + text : 'SELECT CAST("customer"."age" AS int) AS "age_int" FROM "customer"', + string: 'SELECT CAST("customer"."age" AS int) AS "age_int" FROM "customer"' + }, + mysql: { + text : 'SELECT CAST(`customer`.`age` AS int) AS `age_int` FROM `customer`', + string: 'SELECT CAST(`customer`.`age` AS int) AS `age_int` FROM `customer`' + }, + mssql: { + text : 'SELECT CAST([customer].[age] AS int) AS [age_int] FROM [customer]', + string: 'SELECT CAST([customer].[age] AS int) AS [age_int] FROM [customer]' + }, + oracle: { + text : 'SELECT CAST("customer"."age" AS int) "age_int" FROM "customer"', + string: 'SELECT CAST("customer"."age" AS int) "age_int" FROM "customer"' + }, params: [] }); diff --git a/test/dialects/clause-ordering-tests.js b/test/dialects/clause-ordering-tests.js index 8d957471..83d2d28e 100644 --- a/test/dialects/clause-ordering-tests.js +++ b/test/dialects/clause-ordering-tests.js @@ -9,7 +9,7 @@ Harness.test({ query: user.from(user.join(post).on(user.id.equals(post.userId))).select(user.name, post.content), pg: { text : 'SELECT "user"."name", "post"."content" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId")', - string: 'SELECT "user"."name", "post"."content" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId")', + string: 'SELECT "user"."name", "post"."content" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId")' }, sqlite: { text : 'SELECT "user"."name", "post"."content" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId")', @@ -19,6 +19,15 @@ Harness.test({ text : 'SELECT `user`.`name`, `post`.`content` FROM `user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`)', string: 'SELECT `user`.`name`, `post`.`content` FROM `user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`)' }, + mssql: { + text : 'SELECT [user].[name], [post].[content] FROM [user] INNER JOIN [post] ON ([user].[id] = [post].[userId])', + string: 'SELECT [user].[name], [post].[content] FROM [user] INNER JOIN [post] ON ([user].[id] = [post].[userId])' + }, + oracle: { + text : 'SELECT "user"."name", "post"."content" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId")', + string: 'SELECT "user"."name", "post"."content" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId")' + }, + params: [] }); // WHERE - FROM - SELECT @@ -38,6 +47,14 @@ Harness.test({ text : 'SELECT `user`.`id` FROM `user` WHERE (`user`.`name` = ?)', string: 'SELECT `user`.`id` FROM `user` WHERE (`user`.`name` = \'\')' }, + mssql: { + text : 'SELECT [user].[id] FROM [user] WHERE ([user].[name] = @1)', + string: 'SELECT [user].[id] FROM [user] WHERE ([user].[name] = \'\')' + }, + oracle: { + text : 'SELECT "user"."id" FROM "user" WHERE ("user"."name" = :1)', + string: 'SELECT "user"."id" FROM "user" WHERE ("user"."name" = \'\')' + }, params: [''] }); @@ -61,6 +78,14 @@ Harness.test({ text : 'SELECT `user`.`name`, `post`.`content` FROM `user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`) WHERE (`user`.`name` = ?)', string: 'SELECT `user`.`name`, `post`.`content` FROM `user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`) WHERE (`user`.`name` = \'\')' }, + mssql: { + text : 'SELECT [user].[name], [post].[content] FROM [user] INNER JOIN [post] ON ([user].[id] = [post].[userId]) WHERE ([user].[name] = @1)', + string: 'SELECT [user].[name], [post].[content] FROM [user] INNER JOIN [post] ON ([user].[id] = [post].[userId]) WHERE ([user].[name] = \'\')' + }, + oracle: { + text : 'SELECT "user"."name", "post"."content" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId") WHERE ("user"."name" = :1)', + string: 'SELECT "user"."name", "post"."content" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId") WHERE ("user"."name" = \'\')' + }, params: [''] }); @@ -81,5 +106,13 @@ Harness.test({ text : 'SELECT `user`.`id` FROM `user` WHERE (`user`.`name` = ?)', string: 'SELECT `user`.`id` FROM `user` WHERE (`user`.`name` = \'\')' }, + mssql: { + text : 'SELECT [user].[id] FROM [user] WHERE ([user].[name] = @1)', + string: 'SELECT [user].[id] FROM [user] WHERE ([user].[name] = \'\')' + }, + oracle: { + text : 'SELECT "user"."id" FROM "user" WHERE ("user"."name" = :1)', + string: 'SELECT "user"."id" FROM "user" WHERE ("user"."name" = \'\')' + }, params: [''] }); diff --git a/test/dialects/create-table-tests.js b/test/dialects/create-table-tests.js index d6d9d45f..b1150617 100644 --- a/test/dialects/create-table-tests.js +++ b/test/dialects/create-table-tests.js @@ -29,6 +29,14 @@ Harness.test({ text : 'CREATE TABLE `group` (`id` varchar(100), `user_id` varchar(100))', string: 'CREATE TABLE `group` (`id` varchar(100), `user_id` varchar(100))' }, + mssql: { + text : 'CREATE TABLE [group] ([id] varchar(100), [user_id] varchar(100))', + string: 'CREATE TABLE [group] ([id] varchar(100), [user_id] varchar(100))' + }, + oracle: { + text : 'CREATE TABLE "group" ("id" varchar(100), "user_id" varchar(100))', + string: 'CREATE TABLE "group" ("id" varchar(100), "user_id" varchar(100))' + }, params: [] }); @@ -46,6 +54,14 @@ Harness.test({ text : 'CREATE TABLE IF NOT EXISTS `group` (`id` varchar(100), `user_id` varchar(100))', string: 'CREATE TABLE IF NOT EXISTS `group` (`id` varchar(100), `user_id` varchar(100))' }, + mssql: { + text : 'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = \'group\') BEGIN CREATE TABLE [group] ([id] varchar(100), [user_id] varchar(100)) END', + string: 'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = \'group\') BEGIN CREATE TABLE [group] ([id] varchar(100), [user_id] varchar(100)) END' + }, + oracle: { + text : 'BEGIN EXECUTE IMMEDIATE \'CREATE TABLE "group" ("id" varchar(100), "user_id" varchar(100))\'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;', + string: 'BEGIN EXECUTE IMMEDIATE \'CREATE TABLE "group" ("id" varchar(100), "user_id" varchar(100))\'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;' + }, params: [] }); @@ -70,6 +86,14 @@ Harness.test({ mysql: { text : 'CREATE TABLE `user` (`id` varchar(100)) ENGINE=InnoDB', string: 'CREATE TABLE `user` (`id` varchar(100)) ENGINE=InnoDB' + }, + mssql: { + text : 'CREATE TABLE [user] ([id] varchar(100))', + string: 'CREATE TABLE [user] ([id] varchar(100))' + }, + oracle: { + text : 'CREATE TABLE "user" ("id" varchar(100))', + string: 'CREATE TABLE "user" ("id" varchar(100))' } }); @@ -94,6 +118,14 @@ Harness.test({ mysql: { text : 'CREATE TABLE `user` (`id` varchar(100)) DEFAULT CHARSET=latin1', string: 'CREATE TABLE `user` (`id` varchar(100)) DEFAULT CHARSET=latin1' + }, + mssql: { + text : 'CREATE TABLE [user] ([id] varchar(100))', + string: 'CREATE TABLE [user] ([id] varchar(100))' + }, + oracle: { + text : 'CREATE TABLE "user" ("id" varchar(100))', + string: 'CREATE TABLE "user" ("id" varchar(100))' } }); @@ -119,6 +151,14 @@ Harness.test({ mysql: { text : 'CREATE TABLE `user` (`id` varchar(100)) ENGINE=MyISAM DEFAULT CHARSET=latin1', string: 'CREATE TABLE `user` (`id` varchar(100)) ENGINE=MyISAM DEFAULT CHARSET=latin1' + }, + mssql: { + text : 'CREATE TABLE [user] ([id] varchar(100))', + string: 'CREATE TABLE [user] ([id] varchar(100))' + }, + oracle: { + text : 'CREATE TABLE "user" ("id" varchar(100))', + string: 'CREATE TABLE "user" ("id" varchar(100))' } }); @@ -142,5 +182,580 @@ Harness.test({ mysql: { text : 'CREATE TABLE `user` (`id` int PRIMARY KEY)', string: 'CREATE TABLE `user` (`id` int PRIMARY KEY)' + }, + mssql: { + text : 'CREATE TABLE [user] ([id] int PRIMARY KEY)', + string: 'CREATE TABLE [user] ([id] int PRIMARY KEY)' + }, + oracle: { + text : 'CREATE TABLE "user" ("id" int PRIMARY KEY)', + string: 'CREATE TABLE "user" ("id" int PRIMARY KEY)' + } +}); + +Harness.test({ + query: Table.define({ + name: 'user', + columns: [{ + name: 'id', + dataType: 'int', + notNull: true + }] + }).create(), + pg: { + text : 'CREATE TABLE "user" ("id" int NOT NULL)', + string: 'CREATE TABLE "user" ("id" int NOT NULL)' + }, + sqlite: { + text : 'CREATE TABLE "user" ("id" int NOT NULL)', + string: 'CREATE TABLE "user" ("id" int NOT NULL)' + }, + mysql: { + text : 'CREATE TABLE `user` (`id` int NOT NULL)', + string: 'CREATE TABLE `user` (`id` int NOT NULL)' + }, + oracle: { + text : 'CREATE TABLE "user" ("id" int NOT NULL)', + string: 'CREATE TABLE "user" ("id" int NOT NULL)' + } +}); + +Harness.test({ + query: Table.define({ + name: 'user', + columns: [{ + name: 'id', + dataType: 'int', + primaryKey: true, + notNull: true + }] + }).create(), + pg: { + text : 'CREATE TABLE "user" ("id" int PRIMARY KEY)', + string: 'CREATE TABLE "user" ("id" int PRIMARY KEY)' + }, + sqlite: { + text : 'CREATE TABLE "user" ("id" int PRIMARY KEY)', + string: 'CREATE TABLE "user" ("id" int PRIMARY KEY)' + }, + mysql: { + text : 'CREATE TABLE `user` (`id` int PRIMARY KEY)', + string: 'CREATE TABLE `user` (`id` int PRIMARY KEY)' + }, + oracle: { + text : 'CREATE TABLE "user" ("id" int PRIMARY KEY)', + string: 'CREATE TABLE "user" ("id" int PRIMARY KEY)' } }); + +Harness.test({ + query: Table.define({ + name: 'user', + columns: [{ + name: 'id', + dataType: 'int', + primaryKey: true, + notNull: true + }, { + name: 'posts', + dataType: 'int', + notNull: true, + defaultValue: 0 + }] + }).create(), + pg: { + text : 'CREATE TABLE "user" ("id" int PRIMARY KEY, "posts" int NOT NULL DEFAULT 0)', + string: 'CREATE TABLE "user" ("id" int PRIMARY KEY, "posts" int NOT NULL DEFAULT 0)' + }, + sqlite: { + text : 'CREATE TABLE "user" ("id" int PRIMARY KEY, "posts" int NOT NULL DEFAULT 0)', + string: 'CREATE TABLE "user" ("id" int PRIMARY KEY, "posts" int NOT NULL DEFAULT 0)' + }, + mysql: { + text : 'CREATE TABLE `user` (`id` int PRIMARY KEY, `posts` int NOT NULL DEFAULT 0)', + string: 'CREATE TABLE `user` (`id` int PRIMARY KEY, `posts` int NOT NULL DEFAULT 0)' + }, + oracle: { + text : 'CREATE TABLE "user" ("id" int PRIMARY KEY, "posts" int NOT NULL DEFAULT 0)', + string: 'CREATE TABLE "user" ("id" int PRIMARY KEY, "posts" int NOT NULL DEFAULT 0)' + } +}); + +Harness.test({ + query: Table.define({ + name: 'post', + columns: [{ + name: 'userId', + dataType: 'int', + references: { + table: 'user', + column: 'id', + onDelete: 'restrict', + onUpdate: 'set null' + } + }] + }).create(), + pg: { + text : 'CREATE TABLE "post" ("userId" int REFERENCES "user"("id") ON DELETE RESTRICT ON UPDATE SET NULL)', + string: 'CREATE TABLE "post" ("userId" int REFERENCES "user"("id") ON DELETE RESTRICT ON UPDATE SET NULL)' + }, + sqlite: { + text : 'CREATE TABLE "post" ("userId" int REFERENCES "user"("id") ON DELETE RESTRICT ON UPDATE SET NULL)', + string: 'CREATE TABLE "post" ("userId" int REFERENCES "user"("id") ON DELETE RESTRICT ON UPDATE SET NULL)' + }, + mysql: { + text : 'CREATE TABLE `post` (`userId` int REFERENCES `user`(`id`) ON DELETE RESTRICT ON UPDATE SET NULL)', + string: 'CREATE TABLE `post` (`userId` int REFERENCES `user`(`id`) ON DELETE RESTRICT ON UPDATE SET NULL)' + }, + oracle: { + text : 'CREATE TABLE "post" ("userId" int REFERENCES "user"("id") ON DELETE RESTRICT ON UPDATE SET NULL)', + string: 'CREATE TABLE "post" ("userId" int REFERENCES "user"("id") ON DELETE RESTRICT ON UPDATE SET NULL)' + }, + params: [] +}); + +Harness.test({ + query: Table.define({ + name: 'picture', + columns: [{ + name: 'userId', + dataType: 'int', + references: { + table: 'user', + column: 'id' + } + }, { + name: 'caption', + dataType: 'varchar(100)', + references: {} + }] + }).create(), + pg: { + text : 'CREATE TABLE "picture" ("userId" int REFERENCES "user"("id"), "caption" varchar(100))', + string: 'CREATE TABLE "picture" ("userId" int REFERENCES "user"("id"), "caption" varchar(100))' + }, + sqlite: { + text : 'CREATE TABLE "picture" ("userId" int REFERENCES "user"("id"), "caption" varchar(100))', + string: 'CREATE TABLE "picture" ("userId" int REFERENCES "user"("id"), "caption" varchar(100))' + }, + mysql: { + text : 'CREATE TABLE `picture` (`userId` int REFERENCES `user`(`id`), `caption` varchar(100))', + string: 'CREATE TABLE `picture` (`userId` int REFERENCES `user`(`id`), `caption` varchar(100))' + }, + oracle: { + text : 'CREATE TABLE "picture" ("userId" int REFERENCES "user"("id"), "caption" varchar(100))', + string: 'CREATE TABLE "picture" ("userId" int REFERENCES "user"("id"), "caption" varchar(100))' + }, + params: [] +}); + +Harness.test({ + query: Table.define({ + name: 'picture', + columns: [{ + name: 'userId', + dataType: 'int', + references: { + table: 'user', + column: 'id', + onDelete: 'cascade' + } + }] + }).create(), + pg: { + text : 'CREATE TABLE "picture" ("userId" int REFERENCES "user"("id") ON DELETE CASCADE)', + string: 'CREATE TABLE "picture" ("userId" int REFERENCES "user"("id") ON DELETE CASCADE)' + }, + sqlite: { + text : 'CREATE TABLE "picture" ("userId" int REFERENCES "user"("id") ON DELETE CASCADE)', + string: 'CREATE TABLE "picture" ("userId" int REFERENCES "user"("id") ON DELETE CASCADE)' + }, + mysql: { + text : 'CREATE TABLE `picture` (`userId` int REFERENCES `user`(`id`) ON DELETE CASCADE)', + string: 'CREATE TABLE `picture` (`userId` int REFERENCES `user`(`id`) ON DELETE CASCADE)' + }, + oracle: { + text : 'CREATE TABLE "picture" ("userId" int REFERENCES "user"("id") ON DELETE CASCADE)', + string: 'CREATE TABLE "picture" ("userId" int REFERENCES "user"("id") ON DELETE CASCADE)' + }, + params: [] +}); + +Harness.test({ + query: Table.define({ + name: 'post', + columns: [{ + name: 'userId', + dataType: 'int', + references: 'user' + }] + }).create(), + pg: { + text : 'references is not a object for column userId (REFERENCES statements within CREATE TABLE and ADD COLUMN statements require refrences to be expressed as an object)', + throws: true + }, + sqlite: { + text : 'references is not a object for column userId (REFERENCES statements within CREATE TABLE and ADD COLUMN statements require refrences to be expressed as an object)', + throws: true + }, + mysql: { + text : 'references is not a object for column userId (REFERENCES statements within CREATE TABLE and ADD COLUMN statements require refrences to be expressed as an object)', + throws: true + }, + oracle: { + text : 'references is not a object for column userId (REFERENCES statements within CREATE TABLE and ADD COLUMN statements require refrences to be expressed as an object)', + throws: true + }, + params: [] +}); + +Harness.test({ + query: Table.define({ + name: 'membership', + columns: { + group_id: { dataType: 'int', primaryKey: true}, + user_id: { dataType: 'int', primaryKey: true}, + desc: { dataType: 'varchar'} + } + }).create(), + pg: { + text : 'CREATE TABLE "membership" ("group_id" int, "user_id" int, "desc" varchar, PRIMARY KEY ("group_id", "user_id"))', + string: 'CREATE TABLE "membership" ("group_id" int, "user_id" int, "desc" varchar, PRIMARY KEY ("group_id", "user_id"))', + }, + sqlite: { + text : 'CREATE TABLE "membership" ("group_id" int, "user_id" int, "desc" varchar, PRIMARY KEY ("group_id", "user_id"))', + string: 'CREATE TABLE "membership" ("group_id" int, "user_id" int, "desc" varchar, PRIMARY KEY ("group_id", "user_id"))', + }, + mysql: { + text : 'CREATE TABLE `membership` (`group_id` int, `user_id` int, `desc` varchar, PRIMARY KEY (`group_id`, `user_id`))', + string: 'CREATE TABLE `membership` (`group_id` int, `user_id` int, `desc` varchar, PRIMARY KEY (`group_id`, `user_id`))', + } +}); + +// TEMPORARY TABLE TESTS + +// This tests explicitly setting the isTemporary flag to false, as opposed to all the test above here which have it +// as undefined. +Harness.test({ + query: Table.define({ + name: 'post', + columns: [{ + name: 'id', + dataType: 'int' + }], + isTemporary:false + }).create(), + pg: { + text : 'CREATE TABLE "post" ("id" int)', + string: 'CREATE TABLE "post" ("id" int)' + }, + sqlite: { + text : 'CREATE TABLE "post" ("id" int)', + string: 'CREATE TABLE "post" ("id" int)' + }, + mysql: { + text : 'CREATE TABLE `post` (`id` int)', + string: 'CREATE TABLE `post` (`id` int)' + }, + mssql: { + text : 'CREATE TABLE [post] ([id] int)', + string: 'CREATE TABLE [post] ([id] int)' + }, + oracle: { + text : 'CREATE TABLE "post" ("id" int)', + string: 'CREATE TABLE "post" ("id" int)' + }, + params: [] +}); + +Harness.test({ + query: Table.define({ + name: 'post', + columns: [{ + name: 'id', + dataType: 'int' + }], + isTemporary:true + }).create(), + pg: { + text : 'CREATE TEMPORARY TABLE "post" ("id" int)', + string: 'CREATE TEMPORARY TABLE "post" ("id" int)' + }, + sqlite: { + text : 'CREATE TEMPORARY TABLE "post" ("id" int)', + string: 'CREATE TEMPORARY TABLE "post" ("id" int)' + }, + mysql: { + text : 'CREATE TEMPORARY TABLE `post` (`id` int)', + string: 'CREATE TEMPORARY TABLE `post` (`id` int)' + }, + //mssql: { + // text : 'CREATE TABLE [#post] ([id] int)', + // string: 'CREATE TABLE [#post] ([id] int)' + //}, + params: [] +}); + +var users = Table.define({ + name: 'users', + columns: { + id: { + primaryKey: true, + dataType: 'int', + references: { + table: "entity", + column: "id", + constraint: "DEFERRABLE INITIALLY DEFERRED" + } + } + } +}); + +Harness.test({ + query: users.create(), + pg: { + text: 'CREATE TABLE "users" ("id" int PRIMARY KEY REFERENCES "entity"("id") DEFERRABLE INITIALLY DEFERRED)', + string: 'CREATE TABLE "users" ("id" int PRIMARY KEY REFERENCES "entity"("id") DEFERRABLE INITIALLY DEFERRED)' + }, + sqlite: { + text: 'CREATE TABLE "users" ("id" int PRIMARY KEY REFERENCES "entity"("id") DEFERRABLE INITIALLY DEFERRED)', + string: 'CREATE TABLE "users" ("id" int PRIMARY KEY REFERENCES "entity"("id") DEFERRABLE INITIALLY DEFERRED)' + }, + mysql: { + text: 'CREATE TABLE `users` (`id` int PRIMARY KEY REFERENCES `entity`(`id`) DEFERRABLE INITIALLY DEFERRED)', + string: 'CREATE TABLE `users` (`id` int PRIMARY KEY REFERENCES `entity`(`id`) DEFERRABLE INITIALLY DEFERRED)' + }, + mssql: { + text: 'CREATE TABLE [users] ([id] int PRIMARY KEY REFERENCES [entity]([id]) DEFERRABLE INITIALLY DEFERRED)', + string: 'CREATE TABLE [users] ([id] int PRIMARY KEY REFERENCES [entity]([id]) DEFERRABLE INITIALLY DEFERRED)' + }, + oracle: { + text: 'CREATE TABLE "users" ("id" int PRIMARY KEY REFERENCES "entity"("id") DEFERRABLE INITIALLY DEFERRED)', + string: 'CREATE TABLE "users" ("id" int PRIMARY KEY REFERENCES "entity"("id") DEFERRABLE INITIALLY DEFERRED)' + }, + params: [] +}); + +// UNIQUE COLUMN TESTS +Harness.test({ + query: Table.define({ + name: 'post', + columns: [{ + name: 'id', + dataType: 'int', + //primaryKey: true, + //notNull: true, + unique: true + }] + }).create(), + pg: { + text : 'CREATE TABLE "post" ("id" int UNIQUE)', + string: 'CREATE TABLE "post" ("id" int UNIQUE)' + }, + sqlite: { + text : 'CREATE TABLE "post" ("id" int UNIQUE)', + string: 'CREATE TABLE "post" ("id" int UNIQUE)' + }, + mysql: { + text : 'CREATE TABLE `post` (`id` int UNIQUE)', + string: 'CREATE TABLE `post` (`id` int UNIQUE)' + }, + mssql: { + text : 'CREATE TABLE [post] ([id] int UNIQUE)', + string: 'CREATE TABLE [post] ([id] int UNIQUE)' + }, + oracle: { + text : 'CREATE TABLE "post" ("id" int UNIQUE)', + string: 'CREATE TABLE "post" ("id" int UNIQUE)' + }, + params: [] +}); + + +var noUsers = Table.define({ + name: 'no_users', + columns: { + id: { + primaryKey: true, + dataType: 'int', + references: { + table: "entity", + column: "id", + constraint: "" + } + } + } +}); + +Harness.test({ + query: noUsers.create(), + pg: { + text : 'CREATE TABLE "no_users" ("id" int PRIMARY KEY REFERENCES "entity"("id"))', + string: 'CREATE TABLE "no_users" ("id" int PRIMARY KEY REFERENCES "entity"("id"))' + }, + sqlite: { + text : 'CREATE TABLE "no_users" ("id" int PRIMARY KEY REFERENCES "entity"("id"))', + string: 'CREATE TABLE "no_users" ("id" int PRIMARY KEY REFERENCES "entity"("id"))' + }, + mysql: { + text : 'CREATE TABLE `no_users` (`id` int PRIMARY KEY REFERENCES `entity`(`id`))', + string: 'CREATE TABLE `no_users` (`id` int PRIMARY KEY REFERENCES `entity`(`id`))' + }, + mssql: { + text : 'CREATE TABLE [no_users] ([id] int PRIMARY KEY REFERENCES [entity]([id]))', + string: 'CREATE TABLE [no_users] ([id] int PRIMARY KEY REFERENCES [entity]([id]))' + }, + oracle: { + text : 'CREATE TABLE "no_users" ("id" int PRIMARY KEY REFERENCES "entity"("id"))', + string: 'CREATE TABLE "no_users" ("id" int PRIMARY KEY REFERENCES "entity"("id"))' + }, + params: [] +}); + +Harness.test({ + query: Table.define({ + name: 'post', + columns: [{ + name: 'id', + dataType: 'int', + //primaryKey: true, + notNull: true, + unique: true + }] + }).create(), + pg: { + text : 'CREATE TABLE "post" ("id" int NOT NULL UNIQUE)', + string: 'CREATE TABLE "post" ("id" int NOT NULL UNIQUE)' + }, + sqlite: { + text : 'CREATE TABLE "post" ("id" int NOT NULL UNIQUE)', + string: 'CREATE TABLE "post" ("id" int NOT NULL UNIQUE)' + }, + mysql: { + text : 'CREATE TABLE `post` (`id` int NOT NULL UNIQUE)', + string: 'CREATE TABLE `post` (`id` int NOT NULL UNIQUE)' + }, + mssql: { + text : 'CREATE TABLE [post] ([id] int NOT NULL UNIQUE)', + string: 'CREATE TABLE [post] ([id] int NOT NULL UNIQUE)' + }, + oracle: { + text : 'CREATE TABLE "post" ("id" int NOT NULL UNIQUE)', + string: 'CREATE TABLE "post" ("id" int NOT NULL UNIQUE)' + }, + params: [] +}); + +Harness.test({ + query: Table.define({ + name: 'post', + columns: [{ + name: 'id', + dataType: 'int', + primaryKey: true, + //notNull: true, + unique: true + }] + }).create(), + pg: { + text : 'CREATE TABLE "post" ("id" int PRIMARY KEY)', + string: 'CREATE TABLE "post" ("id" int PRIMARY KEY)' + }, + sqlite: { + text : 'CREATE TABLE "post" ("id" int PRIMARY KEY)', + string: 'CREATE TABLE "post" ("id" int PRIMARY KEY)' + }, + mysql: { + text : 'CREATE TABLE `post` (`id` int PRIMARY KEY)', + string: 'CREATE TABLE `post` (`id` int PRIMARY KEY)' + }, + mssql: { + text : 'CREATE TABLE [post] ([id] int PRIMARY KEY)', + string: 'CREATE TABLE [post] ([id] int PRIMARY KEY)' + }, + oracle: { + text : 'CREATE TABLE "post" ("id" int PRIMARY KEY)', + string: 'CREATE TABLE "post" ("id" int PRIMARY KEY)' + }, + params: [] +}); + +Harness.test({ + query: Table.define({ + name: 'post', + columns: [{ + name: 'id', + dataType: 'int', + primaryKey: true + }, { + name: 'blog_id', + dataType: 'int' + }, { + name: 'user_id', + dataType: 'int' + }], + foreignKeys: { + table: 'users', + columns: [ 'blog_id', 'user_id' ], + refColumns: [ 'id', 'user_id' ] + } + }).create(), + pg: { + text : 'CREATE TABLE "post" ("id" int PRIMARY KEY, "blog_id" int, "user_id" int, FOREIGN KEY ( "blog_id", "user_id" ) REFERENCES "users" ( "id", "user_id" ))', + string: 'CREATE TABLE "post" ("id" int PRIMARY KEY, "blog_id" int, "user_id" int, FOREIGN KEY ( "blog_id", "user_id" ) REFERENCES "users" ( "id", "user_id" ))' + }, + sqlite: { + text : 'CREATE TABLE "post" ("id" int PRIMARY KEY, "blog_id" int, "user_id" int, FOREIGN KEY ( "blog_id", "user_id" ) REFERENCES "users" ( "id", "user_id" ))', + string: 'CREATE TABLE "post" ("id" int PRIMARY KEY, "blog_id" int, "user_id" int, FOREIGN KEY ( "blog_id", "user_id" ) REFERENCES "users" ( "id", "user_id" ))' + }, + mysql: { + text : 'CREATE TABLE `post` (`id` int PRIMARY KEY, `blog_id` int, `user_id` int, FOREIGN KEY ( `blog_id`, `user_id` ) REFERENCES `users` ( `id`, `user_id` ))', + string: 'CREATE TABLE `post` (`id` int PRIMARY KEY, `blog_id` int, `user_id` int, FOREIGN KEY ( `blog_id`, `user_id` ) REFERENCES `users` ( `id`, `user_id` ))' + }, + params: [] +}); + +Harness.test({ + query: Table.define({ + name: 'replies', + columns: [{ + name: 'id', + dataType: 'int', + primaryKey: true + }, { + name: 'blog_id', + dataType: 'int' + }, { + name: 'post_id', + dataType: 'int' + }, { + name: 'user_id', + dataType: 'int' + }], + foreignKeys: [{ + table: 'users', + columns: [ 'blog_id', 'user_id' ], + onDelete: 'no action' + }, { + name: 'posts_idx', + table: 'posts', + columns: [ 'blog_id', 'post_id' ], + refColumns: [ 'blog_id', 'id' ], + onDelete: 'cascade', + onUpdate: 'set default' + }] + }).create(), + pg: { + text : 'CREATE TABLE "replies" ("id" int PRIMARY KEY, "blog_id" int, "post_id" int, "user_id" int, FOREIGN KEY ( "blog_id", "user_id" ) REFERENCES "users" ON DELETE NO ACTION, CONSTRAINT "posts_idx" FOREIGN KEY ( "blog_id", "post_id" ) REFERENCES "posts" ( "blog_id", "id" ) ON DELETE CASCADE ON UPDATE SET DEFAULT)', + string: 'CREATE TABLE "replies" ("id" int PRIMARY KEY, "blog_id" int, "post_id" int, "user_id" int, FOREIGN KEY ( "blog_id", "user_id" ) REFERENCES "users" ON DELETE NO ACTION, CONSTRAINT "posts_idx" FOREIGN KEY ( "blog_id", "post_id" ) REFERENCES "posts" ( "blog_id", "id" ) ON DELETE CASCADE ON UPDATE SET DEFAULT)' + }, + sqlite: { + text : 'CREATE TABLE "replies" ("id" int PRIMARY KEY, "blog_id" int, "post_id" int, "user_id" int, FOREIGN KEY ( "blog_id", "user_id" ) REFERENCES "users" ON DELETE NO ACTION, CONSTRAINT "posts_idx" FOREIGN KEY ( "blog_id", "post_id" ) REFERENCES "posts" ( "blog_id", "id" ) ON DELETE CASCADE ON UPDATE SET DEFAULT)', + string: 'CREATE TABLE "replies" ("id" int PRIMARY KEY, "blog_id" int, "post_id" int, "user_id" int, FOREIGN KEY ( "blog_id", "user_id" ) REFERENCES "users" ON DELETE NO ACTION, CONSTRAINT "posts_idx" FOREIGN KEY ( "blog_id", "post_id" ) REFERENCES "posts" ( "blog_id", "id" ) ON DELETE CASCADE ON UPDATE SET DEFAULT)' + }, + mysql: { + text : 'CREATE TABLE `replies` (`id` int PRIMARY KEY, `blog_id` int, `post_id` int, `user_id` int, FOREIGN KEY ( `blog_id`, `user_id` ) REFERENCES `users` ON DELETE NO ACTION, CONSTRAINT `posts_idx` FOREIGN KEY ( `blog_id`, `post_id` ) REFERENCES `posts` ( `blog_id`, `id` ) ON DELETE CASCADE ON UPDATE SET DEFAULT)', + string: 'CREATE TABLE `replies` (`id` int PRIMARY KEY, `blog_id` int, `post_id` int, `user_id` int, FOREIGN KEY ( `blog_id`, `user_id` ) REFERENCES `users` ON DELETE NO ACTION, CONSTRAINT `posts_idx` FOREIGN KEY ( `blog_id`, `post_id` ) REFERENCES `posts` ( `blog_id`, `id` ) ON DELETE CASCADE ON UPDATE SET DEFAULT)' + }, + params: [] +}); diff --git a/test/dialects/create-view-tests.js b/test/dialects/create-view-tests.js new file mode 100644 index 00000000..977f540a --- /dev/null +++ b/test/dialects/create-view-tests.js @@ -0,0 +1,80 @@ +'use strict'; + +var Harness = require('./support'); +var user = Harness.defineUserTable(); + +//simple view create +Harness.test({ + query: user.select(user.star()).createView('allUsersView'), + pg: { + text : '(CREATE VIEW "allUsersView" AS SELECT "user".* FROM "user")', + string: '(CREATE VIEW "allUsersView" AS SELECT "user".* FROM "user")' + }, + sqlite: { + text : '(CREATE VIEW "allUsersView" AS SELECT "user".* FROM "user")', + string: '(CREATE VIEW "allUsersView" AS SELECT "user".* FROM "user")' + }, + mysql: { + text : '(CREATE VIEW `allUsersView` AS SELECT `user`.* FROM `user`)', + string: '(CREATE VIEW `allUsersView` AS SELECT `user`.* FROM `user`)' + }, + mssql: { + text : '(CREATE VIEW [allUsersView] AS SELECT [user].* FROM [user])', + string: '(CREATE VIEW [allUsersView] AS SELECT [user].* FROM [user])' + }, + oracle: { + text : '(CREATE VIEW "allUsersView" AS SELECT "user".* FROM "user")', + string: '(CREATE VIEW "allUsersView" AS SELECT "user".* FROM "user")' + } +}); + +//create view with parameters +Harness.test({ + query: user.select(user.star()).where(user.id.equals(1)).createView('oneUserView'), + pg: { + text : '(CREATE VIEW "oneUserView" AS SELECT "user".* FROM "user" WHERE ("user"."id" = 1))', + string: '(CREATE VIEW "oneUserView" AS SELECT "user".* FROM "user" WHERE ("user"."id" = 1))' + }, + sqlite: { + text : '(CREATE VIEW "oneUserView" AS SELECT "user".* FROM "user" WHERE ("user"."id" = 1))', + string: '(CREATE VIEW "oneUserView" AS SELECT "user".* FROM "user" WHERE ("user"."id" = 1))' + }, + mysql: { + text : '(CREATE VIEW `oneUserView` AS SELECT `user`.* FROM `user` WHERE (`user`.`id` = 1))', + string: '(CREATE VIEW `oneUserView` AS SELECT `user`.* FROM `user` WHERE (`user`.`id` = 1))' + }, + mssql: { + text : '(CREATE VIEW [oneUserView] AS SELECT [user].* FROM [user] WHERE ([user].[id] = 1))', + string: '(CREATE VIEW [oneUserView] AS SELECT [user].* FROM [user] WHERE ([user].[id] = 1))' + }, + oracle: { + text : '(CREATE VIEW "oneUserView" AS SELECT "user".* FROM "user" WHERE ("user"."id" = 1))', + string: '(CREATE VIEW "oneUserView" AS SELECT "user".* FROM "user" WHERE ("user"."id" = 1))' + } +}); + +//Tests error raised for non-SELECT create view attempts +Harness.test({ + query: user.delete().where(user.id.equals(1)).createView('oneUserView'), + pg: { + text : 'Create View requires a Select.', + throws: true + }, + sqlite: { + text : 'Create View requires a Select.', + throws: true + }, + mysql: { + text : 'Create View requires a Select.', + throws: true + }, + mssql: { + text : 'Create View requires a Select.', + throws: true + }, + oracle: { + text : 'Create View requires a Select.', + throws: true + }, + params: [] +}); diff --git a/test/dialects/date-tests.js b/test/dialects/date-tests.js new file mode 100644 index 00000000..dd2c4d64 --- /dev/null +++ b/test/dialects/date-tests.js @@ -0,0 +1,228 @@ +'use strict'; + +var Harness = require('./support'); +var customer = Harness.defineCustomerTable(); +var Sql = require('../../lib'); + +Harness.test({ + query: customer.select(Sql.functions.YEAR(customer.metadata)), + pg: { + text : 'SELECT EXTRACT(YEAR FROM "customer"."metadata") FROM "customer"', + string: 'SELECT EXTRACT(YEAR FROM "customer"."metadata") FROM "customer"' + }, + sqlite: { + text : 'SELECT strftime(\'%Y\', "customer"."metadata") FROM "customer"', + string: 'SELECT strftime(\'%Y\', "customer"."metadata") FROM "customer"' + }, + mysql: { + text : 'SELECT YEAR(`customer`.`metadata`) FROM `customer`', + string: 'SELECT YEAR(`customer`.`metadata`) FROM `customer`' + }, + mssql: { + text : 'SELECT DATEPART(year, [customer].[metadata]) FROM [customer]', + string: 'SELECT DATEPART(year, [customer].[metadata]) FROM [customer]' + }, + oracle: { + text : 'SELECT EXTRACT(YEAR FROM "customer"."metadata") FROM "customer"', + string: 'SELECT EXTRACT(YEAR FROM "customer"."metadata") FROM "customer"' + }, + params: [] +}); + +Harness.test({ + query: customer.select(Sql.functions.MONTH(customer.metadata)), + pg: { + text : 'SELECT EXTRACT(MONTH FROM "customer"."metadata") FROM "customer"', + string: 'SELECT EXTRACT(MONTH FROM "customer"."metadata") FROM "customer"' + }, + sqlite: { + text: 'SELECT strftime(\'%m\', datetime("customer"."metadata"/1000, "unixepoch")) FROM "customer"', + string: 'SELECT strftime(\'%m\', datetime("customer"."metadata"/1000, "unixepoch")) FROM "customer"', + config: { + dateTimeMillis: true + } + }, + mysql: { + text : 'SELECT MONTH(`customer`.`metadata`) FROM `customer`', + string: 'SELECT MONTH(`customer`.`metadata`) FROM `customer`' + }, + mssql: { + text : 'SELECT DATEPART(month, [customer].[metadata]) FROM [customer]', + string: 'SELECT DATEPART(month, [customer].[metadata]) FROM [customer]' + }, + oracle: { + text : 'SELECT EXTRACT(MONTH FROM "customer"."metadata") FROM "customer"', + string: 'SELECT EXTRACT(MONTH FROM "customer"."metadata") FROM "customer"' + }, + params: [] +}); + +Harness.test({ + query: customer.select(Sql.functions.DAY(customer.metadata)), + pg: { + text : 'SELECT EXTRACT(DAY FROM "customer"."metadata") FROM "customer"', + string: 'SELECT EXTRACT(DAY FROM "customer"."metadata") FROM "customer"' + }, + sqlite: { + text : 'SELECT strftime(\'%d\', "customer"."metadata") FROM "customer"', + string: 'SELECT strftime(\'%d\', "customer"."metadata") FROM "customer"' + }, + mysql: { + text : 'SELECT DAY(`customer`.`metadata`) FROM `customer`', + string: 'SELECT DAY(`customer`.`metadata`) FROM `customer`' + }, + mssql: { + text : 'SELECT DATEPART(day, [customer].[metadata]) FROM [customer]', + string: 'SELECT DATEPART(day, [customer].[metadata]) FROM [customer]' + }, + oracle: { + text : 'SELECT EXTRACT(DAY FROM "customer"."metadata") FROM "customer"', + string: 'SELECT EXTRACT(DAY FROM "customer"."metadata") FROM "customer"' + }, + params: [] +}); + +Harness.test({ + query: customer.select(Sql.functions.HOUR(customer.metadata)), + pg: { + text : 'SELECT EXTRACT(HOUR FROM "customer"."metadata") FROM "customer"', + string: 'SELECT EXTRACT(HOUR FROM "customer"."metadata") FROM "customer"' + }, + sqlite: { + text: 'SELECT strftime(\'%H\', datetime("customer"."metadata"/1000, "unixepoch")) FROM "customer"', + string: 'SELECT strftime(\'%H\', datetime("customer"."metadata"/1000, "unixepoch")) FROM "customer"', + config: { + dateTimeMillis: true + } + }, + mysql: { + text : 'SELECT HOUR(`customer`.`metadata`) FROM `customer`', + string: 'SELECT HOUR(`customer`.`metadata`) FROM `customer`' + }, + mssql: { + text : 'SELECT DATEPART(hour, [customer].[metadata]) FROM [customer]', + string: 'SELECT DATEPART(hour, [customer].[metadata]) FROM [customer]' + }, + oracle: { + text : 'SELECT EXTRACT(HOUR FROM "customer"."metadata") FROM "customer"', + string: 'SELECT EXTRACT(HOUR FROM "customer"."metadata") FROM "customer"' + }, + params: [] +}); + +Harness.test({ + query: customer.select(Sql.functions.CURRENT_TIMESTAMP()), + pg: { + text : 'SELECT CURRENT_TIMESTAMP FROM "customer"', + string: 'SELECT CURRENT_TIMESTAMP FROM "customer"' + }, + sqlite: { + text : 'SELECT CURRENT_TIMESTAMP FROM "customer"', + string: 'SELECT CURRENT_TIMESTAMP FROM "customer"' + }, + mysql: { + text : 'SELECT CURRENT_TIMESTAMP FROM `customer`', + string: 'SELECT CURRENT_TIMESTAMP FROM `customer`' + }, + mssql: { + text : 'SELECT CURRENT_TIMESTAMP FROM [customer]', + string: 'SELECT CURRENT_TIMESTAMP FROM [customer]' + }, + oracle: { + text : 'SELECT CURRENT_TIMESTAMP FROM "customer"', + string: 'SELECT CURRENT_TIMESTAMP FROM "customer"' + }, + params: [] +}); + +Harness.test({ + query: Sql.select(Sql.functions.CURRENT_TIMESTAMP().plus(Sql.interval({hours:1}))), + pg: { + text : 'SELECT (CURRENT_TIMESTAMP + INTERVAL \'1 HOUR\')', + string: 'SELECT (CURRENT_TIMESTAMP + INTERVAL \'1 HOUR\')' + }, + mysql: { + text : 'SELECT (CURRENT_TIMESTAMP + INTERVAL \'1:0:0\' HOUR_SECOND)', + string: 'SELECT (CURRENT_TIMESTAMP + INTERVAL \'1:0:0\' HOUR_SECOND)' + }, + params: [] +}); + +Harness.test({ + query: Sql.select(Sql.functions.CURRENT_TIMESTAMP().minus(Sql.interval({years:3}))), + pg: { + text : 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'3 YEAR\')', + string: 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'3 YEAR\')' + }, + mysql: { + text : 'SELECT (CURRENT_TIMESTAMP - INTERVAL 3 YEAR)', + string: 'SELECT (CURRENT_TIMESTAMP - INTERVAL 3 YEAR)' + }, + params: [] +}); + +Harness.test({ + query: Sql.select(Sql.functions.CURRENT_TIMESTAMP().minus(Sql.interval({years:3, months:2}))), + pg: { + text : 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'3 YEAR 2 MONTH\')', + string: 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'3 YEAR 2 MONTH\')' + }, + mysql: { + text : 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'3-2\' YEAR_MONTH)', + string: 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'3-2\' YEAR_MONTH)' + }, + params: [] +}); + +Harness.test({ + query: Sql.select(Sql.functions.CURRENT_TIMESTAMP().plus(Sql.interval({hours:1, minutes:20}))), + pg: { + text : 'SELECT (CURRENT_TIMESTAMP + INTERVAL \'1 HOUR 20 MINUTE\')', + string: 'SELECT (CURRENT_TIMESTAMP + INTERVAL \'1 HOUR 20 MINUTE\')' + }, + mysql: { + text : 'SELECT (CURRENT_TIMESTAMP + INTERVAL \'1:20:0\' HOUR_SECOND)', + string: 'SELECT (CURRENT_TIMESTAMP + INTERVAL \'1:20:0\' HOUR_SECOND)' + }, + params: [] +}); + +Harness.test({ + query: Sql.select(Sql.functions.CURRENT_TIMESTAMP().plus(Sql.interval({hours:'sql\'injection', minutes:20}))), + pg: { + text : 'SELECT (CURRENT_TIMESTAMP + INTERVAL \'20 MINUTE\')', + string: 'SELECT (CURRENT_TIMESTAMP + INTERVAL \'20 MINUTE\')' + }, + mysql: { + text : 'SELECT (CURRENT_TIMESTAMP + INTERVAL \'0:20:0\' HOUR_SECOND)', + string: 'SELECT (CURRENT_TIMESTAMP + INTERVAL \'0:20:0\' HOUR_SECOND)' + }, + params: [] +}); + +Harness.test({ + query: Sql.select(Sql.functions.CURRENT_TIMESTAMP().minus(Sql.interval({days: 1, hours:5, minutes: 'sql\'injection'}))), + pg: { + text : 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'1 DAY 5 HOUR\')', + string: 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'1 DAY 5 HOUR\')' + }, + mysql: { + text : 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'1 5:0:0\' DAY_SECOND)', + string: 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'1 5:0:0\' DAY_SECOND)' + }, + params: [] +}); + +Harness.test({ + query: Sql.select(Sql.functions.CURRENT_TIMESTAMP().minus(Sql.interval({years: 2, months: 5}))), + pg: { + text : 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'2 YEAR 5 MONTH\')', + string: 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'2 YEAR 5 MONTH\')' + }, + mysql: { + text : 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'2-5\' YEAR_MONTH)', + string: 'SELECT (CURRENT_TIMESTAMP - INTERVAL \'2-5\' YEAR_MONTH)' + }, + params: [] +}); + diff --git a/test/dialects/delete-tests.js b/test/dialects/delete-tests.js index 58e6d0d6..51fe3026 100644 --- a/test/dialects/delete-tests.js +++ b/test/dialects/delete-tests.js @@ -18,6 +18,14 @@ Harness.test({ text : 'DELETE FROM `post` WHERE (`post`.`content` = ?)', string: 'DELETE FROM `post` WHERE (`post`.`content` = \'hello\'\'s world\')' }, + mssql: { + text : 'DELETE FROM [post] WHERE ([post].[content] = @1)', + string: "DELETE FROM [post] WHERE ([post].[content] = 'hello''s world')" + }, + oracle: { + text : 'DELETE FROM "post" WHERE ("post"."content" = :1)', + string: 'DELETE FROM "post" WHERE ("post"."content" = \'hello\'\'s world\')' + }, params: ["hello's world"] }); @@ -72,6 +80,10 @@ Harness.test({ text: 'DELETE `user` FROM `user` INNER JOIN `post` ON (`post`.`userId` = `user`.`id`) WHERE (`post`.`content` = ?)', string: 'DELETE `user` FROM `user` INNER JOIN `post` ON (`post`.`userId` = `user`.`id`) WHERE (`post`.`content` = \'foo\')' }, + oracle: { + text: 'DELETE "user" FROM "user" INNER JOIN "post" ON ("post"."userId" = "user"."id") WHERE ("post"."content" = :1)', + string: 'DELETE "user" FROM "user" INNER JOIN "post" ON ("post"."userId" = "user"."id") WHERE ("post"."content" = \'foo\')' + }, params: [ 'foo' ] }); @@ -91,6 +103,14 @@ Harness.test({ text : 'DELETE FROM `post` WHERE (`post`.`content` = ?)', string: 'DELETE FROM `post` WHERE (`post`.`content` = \'\')' }, + mssql: { + text : 'DELETE FROM [post] WHERE ([post].[content] = @1)', + string: "DELETE FROM [post] WHERE ([post].[content] = '')" + }, + oracle: { + text : 'DELETE FROM "post" WHERE ("post"."content" = :1)', + string: 'DELETE FROM "post" WHERE ("post"."content" = \'\')' + }, params: [''] }); @@ -110,6 +130,14 @@ Harness.test({ text : 'DELETE FROM `post` WHERE (`post`.`content` = ?)', string: 'DELETE FROM `post` WHERE (`post`.`content` = \'\')' }, + mssql: { + text : 'DELETE FROM [post] WHERE ([post].[content] = @1)', + string: "DELETE FROM [post] WHERE ([post].[content] = '')" + }, + oracle: { + text : 'DELETE FROM "post" WHERE ("post"."content" = :1)', + string: 'DELETE FROM "post" WHERE ("post"."content" = \'\')' + }, params: [''] }); @@ -129,5 +157,13 @@ Harness.test({ text : 'DELETE FROM `post` WHERE ((`post`.`content` = ?) OR (`post`.`content` IS NULL))', string: 'DELETE FROM `post` WHERE ((`post`.`content` = \'\') OR (`post`.`content` IS NULL))' }, + mssql: { + text : 'DELETE FROM [post] WHERE (([post].[content] = @1) OR ([post].[content] IS NULL))', + string: "DELETE FROM [post] WHERE (([post].[content] = '') OR ([post].[content] IS NULL))" + }, + oracle: { + text : 'DELETE FROM "post" WHERE (("post"."content" = :1) OR ("post"."content" IS NULL))', + string: 'DELETE FROM "post" WHERE (("post"."content" = \'\') OR ("post"."content" IS NULL))' + }, params: [''] }); diff --git a/test/dialects/distinct-on-tests.js b/test/dialects/distinct-on-tests.js new file mode 100644 index 00000000..d238f928 --- /dev/null +++ b/test/dialects/distinct-on-tests.js @@ -0,0 +1,24 @@ +'use strict'; + +var Harness = require('./support'); +var user = Harness.defineUserTable(); +var Sql = require('../../lib').setDialect('postgres'); + +Harness.test({ + query: user.select().distinctOn(user.id), + pg: { + text : 'SELECT DISTINCT ON("user"."id") "user".* FROM "user"', + string: 'SELECT DISTINCT ON("user"."id") "user".* FROM "user"' + }, + params: [] +}); + +Harness.test({ + query: user.select(user.id,user.name).distinctOn(user.id), + pg: { + text : 'SELECT DISTINCT ON("user"."id") "user"."id", "user"."name" FROM "user"', + string: 'SELECT DISTINCT ON("user"."id") "user"."id", "user"."name" FROM "user"' + }, + params: [] +}); + diff --git a/test/dialects/distinct-tests.js b/test/dialects/distinct-tests.js index 5a767183..9f922bff 100644 --- a/test/dialects/distinct-tests.js +++ b/test/dialects/distinct-tests.js @@ -17,6 +17,14 @@ Harness.test({ text : 'SELECT DISTINCT(`user`.`id`) FROM `user`', string: 'SELECT DISTINCT(`user`.`id`) FROM `user`' }, + mssql: { + text : 'SELECT DISTINCT([user].[id]) FROM [user]', + string: 'SELECT DISTINCT([user].[id]) FROM [user]' + }, + oracle: { + text : 'SELECT DISTINCT("user"."id") FROM "user"', + string: 'SELECT DISTINCT("user"."id") FROM "user"' + }, params: [] }); @@ -34,5 +42,91 @@ Harness.test({ text : 'SELECT COUNT(DISTINCT(`user`.`id`)) AS `count` FROM `user`', string: 'SELECT COUNT(DISTINCT(`user`.`id`)) AS `count` FROM `user`' }, + mssql: { + text : 'SELECT COUNT(DISTINCT([user].[id])) AS [count] FROM [user]', + string: 'SELECT COUNT(DISTINCT([user].[id])) AS [count] FROM [user]' + }, + oracle: { + text : 'SELECT COUNT(DISTINCT("user"."id")) "count" FROM "user"', + string: 'SELECT COUNT(DISTINCT("user"."id")) "count" FROM "user"' + }, + params: [] +}); + +// BELOW HERE TEST DISTINCT ON THE ENTIRE RESULTS SET, NOT JUST ONE COLUMN + +Harness.test({ + query: user.select().distinct(), + pg: { + text : 'SELECT DISTINCT "user".* FROM "user"', + string: 'SELECT DISTINCT "user".* FROM "user"' + }, + sqlite: { + text : 'SELECT DISTINCT "user".* FROM "user"', + string: 'SELECT DISTINCT "user".* FROM "user"' + }, + mysql: { + text : 'SELECT DISTINCT `user`.* FROM `user`', + string: 'SELECT DISTINCT `user`.* FROM `user`' + }, + mssql: { + text : 'SELECT DISTINCT [user].* FROM [user]', + string: 'SELECT DISTINCT [user].* FROM [user]' + }, + oracle: { + text : 'SELECT DISTINCT "user".* FROM "user"', + string: 'SELECT DISTINCT "user".* FROM "user"' + }, + params: [] +}); + +Harness.test({ + query: user.select(user.id).distinct(), + pg: { + text : 'SELECT DISTINCT "user"."id" FROM "user"', + string: 'SELECT DISTINCT "user"."id" FROM "user"' + }, + sqlite: { + text : 'SELECT DISTINCT "user"."id" FROM "user"', + string: 'SELECT DISTINCT "user"."id" FROM "user"' + }, + mysql: { + text : 'SELECT DISTINCT `user`.`id` FROM `user`', + string: 'SELECT DISTINCT `user`.`id` FROM `user`' + }, + mssql: { + text : 'SELECT DISTINCT [user].[id] FROM [user]', + string: 'SELECT DISTINCT [user].[id] FROM [user]' + }, + oracle: { + text : 'SELECT DISTINCT "user"."id" FROM "user"', + string: 'SELECT DISTINCT "user"."id" FROM "user"' + }, + params: [] +}); + +Harness.test({ + query: user.select(user.id,user.name).distinct(), + pg: { + text : 'SELECT DISTINCT "user"."id", "user"."name" FROM "user"', + string: 'SELECT DISTINCT "user"."id", "user"."name" FROM "user"' + }, + sqlite: { + text : 'SELECT DISTINCT "user"."id", "user"."name" FROM "user"', + string: 'SELECT DISTINCT "user"."id", "user"."name" FROM "user"' + }, + mysql: { + text : 'SELECT DISTINCT `user`.`id`, `user`.`name` FROM `user`', + string: 'SELECT DISTINCT `user`.`id`, `user`.`name` FROM `user`' + }, + mssql: { + text : 'SELECT DISTINCT [user].[id], [user].[name] FROM [user]', + string: 'SELECT DISTINCT [user].[id], [user].[name] FROM [user]' + }, + oracle: { + text : 'SELECT DISTINCT "user"."id", "user"."name" FROM "user"', + string: 'SELECT DISTINCT "user"."id", "user"."name" FROM "user"' + }, params: [] }); + diff --git a/test/dialects/drop-table-tests.js b/test/dialects/drop-table-tests.js index e44a989b..eb183e64 100644 --- a/test/dialects/drop-table-tests.js +++ b/test/dialects/drop-table-tests.js @@ -17,6 +17,14 @@ Harness.test({ text : 'DROP TABLE `post`', string: 'DROP TABLE `post`' }, + mssql: { + text : 'DROP TABLE [post]', + string: 'DROP TABLE [post]' + }, + oracle: { + text : 'DROP TABLE "post"', + string: 'DROP TABLE "post"' + }, params: [] }); @@ -34,6 +42,14 @@ Harness.test({ text : 'DROP TABLE IF EXISTS `post`', string: 'DROP TABLE IF EXISTS `post`' }, + mssql: { + text : 'IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = [post]) BEGIN DROP TABLE [post] END', + string: 'IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = [post]) BEGIN DROP TABLE [post] END' + }, + oracle: { + text : 'BEGIN EXECUTE IMMEDIATE \'DROP TABLE "post"\'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;', + string: 'BEGIN EXECUTE IMMEDIATE \'DROP TABLE "post"\'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;' + }, params: [] }); @@ -51,6 +67,10 @@ Harness.test({ text : 'DROP TABLE `post` CASCADE', string: 'DROP TABLE `post` CASCADE' }, + oracle: { + text : 'DROP TABLE "post" CASCADE CONSTRAINTS', + string: 'DROP TABLE "post" CASCADE CONSTRAINTS' + }, params: [] }); @@ -68,5 +88,9 @@ Harness.test({ text : 'DROP TABLE `post` RESTRICT', string: 'DROP TABLE `post` RESTRICT' }, + oracle: { + text : 'Oracle do not support RESTRICT in DROP TABLE', + throws: true + }, params: [] }); diff --git a/test/dialects/from-clause-tests.js b/test/dialects/from-clause-tests.js index d0d8fc01..673087db 100644 --- a/test/dialects/from-clause-tests.js +++ b/test/dialects/from-clause-tests.js @@ -17,6 +17,14 @@ Harness.test({ mysql: { text : 'SELECT `user`.* FROM `user` , `post`', string: 'SELECT `user`.* FROM `user` , `post`' + }, + mssql: { + text : 'SELECT [user].* FROM [user] , [post]', + string: 'SELECT [user].* FROM [user] , [post]' + }, + oracle: { + text : 'SELECT "user".* FROM "user" , "post"', + string: 'SELECT "user".* FROM "user" , "post"' } }); @@ -33,5 +41,53 @@ Harness.test({ mysql: { text : 'SELECT `user`.*, `post`.* FROM `user` , `post`', string: 'SELECT `user`.*, `post`.* FROM `user` , `post`' + }, + mssql: { + text : 'SELECT [user].*, [post].* FROM [user] , [post]', + string: 'SELECT [user].*, [post].* FROM [user] , [post]' + }, + oracle: { + text : 'SELECT "user".*, "post".* FROM "user" , "post"', + string: 'SELECT "user".*, "post".* FROM "user" , "post"' } }); + +Harness.test({ + query: user.select(user.star()).from(user, post), + pg: { + text : 'SELECT "user".* FROM "user" , "post"', + string: 'SELECT "user".* FROM "user" , "post"' + }, + sqlite: { + text : 'SELECT "user".* FROM "user" , "post"', + string: 'SELECT "user".* FROM "user" , "post"' + }, + mysql: { + text : 'SELECT `user`.* FROM `user` , `post`', + string: 'SELECT `user`.* FROM `user` , `post`' + }, + oracle: { + text : 'SELECT "user".* FROM "user" , "post"', + string: 'SELECT "user".* FROM "user" , "post"' + } +}); + +Harness.test({ + query: user.select(user.star()).from([user, post]), + pg: { + text : 'SELECT "user".* FROM "user" , "post"', + string: 'SELECT "user".* FROM "user" , "post"' + }, + sqlite: { + text : 'SELECT "user".* FROM "user" , "post"', + string: 'SELECT "user".* FROM "user" , "post"' + }, + mysql: { + text : 'SELECT `user`.* FROM `user` , `post`', + string: 'SELECT `user`.* FROM `user` , `post`' + }, + oracle: { + text : 'SELECT "user".* FROM "user" , "post"', + string: 'SELECT "user".* FROM "user" , "post"' + } +}); \ No newline at end of file diff --git a/test/dialects/function-tests.js b/test/dialects/function-tests.js new file mode 100644 index 00000000..702d8c63 --- /dev/null +++ b/test/dialects/function-tests.js @@ -0,0 +1,82 @@ +'use strict'; + +var Harness = require('./support'); +var Sql = require('../../lib'); + +var post = Harness.definePostTable(); + +Harness.test({ + query: post.select(Sql.functions.LENGTH(post.content)), + pg: { + text : 'SELECT LENGTH("post"."content") FROM "post"', + string: 'SELECT LENGTH("post"."content") FROM "post"' + }, + sqlite: { + text : 'SELECT LENGTH("post"."content") FROM "post"', + string: 'SELECT LENGTH("post"."content") FROM "post"' + }, + mysql: { + text : 'SELECT LENGTH(`post`.`content`) FROM `post`', + string: 'SELECT LENGTH(`post`.`content`) FROM `post`' + }, + mssql: { + text : 'SELECT LEN([post].[content]) FROM [post]', + string: 'SELECT LEN([post].[content]) FROM [post]' + }, + oracle: { + text : 'SELECT LENGTH("post"."content") FROM "post"', + string: 'SELECT LENGTH("post"."content") FROM "post"' + }, + params: [] +}); + +Harness.test({ + query: post.select(Sql.functions.LEFT(post.content,4)), + pg: { + text : 'SELECT LEFT("post"."content", $1) FROM "post"', + string: 'SELECT LEFT("post"."content", 4) FROM "post"' + }, + sqlite: { + text : 'SELECT SUBSTR("post"."content", 1, $1) FROM "post"', + string: 'SELECT SUBSTR("post"."content", 1, 4) FROM "post"' + }, + mysql: { + text : 'SELECT LEFT(`post`.`content`, ?) FROM `post`', + string: 'SELECT LEFT(`post`.`content`, 4) FROM `post`' + }, + mssql: { + text : 'SELECT LEFT([post].[content], @1) FROM [post]', + string: 'SELECT LEFT([post].[content], 4) FROM [post]' + }, + oracle: { + text : 'SELECT LEFT("post"."content", :1) FROM "post"', + string: 'SELECT LEFT("post"."content", 4) FROM "post"' + }, + params: [4] +}); + +Harness.test({ + query: post.select(Sql.functions.RIGHT(post.content,4)), + pg: { + text : 'SELECT RIGHT("post"."content", $1) FROM "post"', + string: 'SELECT RIGHT("post"."content", 4) FROM "post"' + }, + sqlite: { + text : 'SELECT SUBSTR("post"."content", -$1) FROM "post"', + string: 'SELECT SUBSTR("post"."content", -4) FROM "post"' + }, + mysql: { + text : 'SELECT RIGHT(`post`.`content`, ?) FROM `post`', + string: 'SELECT RIGHT(`post`.`content`, 4) FROM `post`' + }, + mssql: { + text : 'SELECT RIGHT([post].[content], @1) FROM [post]', + string: 'SELECT RIGHT([post].[content], 4) FROM [post]' + }, + oracle: { + text : 'SELECT RIGHT("post"."content", :1) FROM "post"', + string: 'SELECT RIGHT("post"."content", 4) FROM "post"' + }, + params: [4] +}); + diff --git a/test/dialects/group-by-tests.js b/test/dialects/group-by-tests.js index c9db48ed..673b5639 100644 --- a/test/dialects/group-by-tests.js +++ b/test/dialects/group-by-tests.js @@ -17,6 +17,14 @@ Harness.test({ text : 'SELECT `post`.`content` FROM `post` GROUP BY `post`.`userId`', string: 'SELECT `post`.`content` FROM `post` GROUP BY `post`.`userId`' }, + mssql: { + text : 'SELECT [post].[content] FROM [post] GROUP BY [post].[userId]', + string: 'SELECT [post].[content] FROM [post] GROUP BY [post].[userId]' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post" GROUP BY "post"."userId"', + string: 'SELECT "post"."content" FROM "post" GROUP BY "post"."userId"' + }, params: [] }); @@ -34,6 +42,14 @@ Harness.test({ text : 'SELECT `post`.`content` FROM `post` GROUP BY `post`.`userId`, `post`.`id`', string: 'SELECT `post`.`content` FROM `post` GROUP BY `post`.`userId`, `post`.`id`' }, + mssql: { + text : 'SELECT [post].[content] FROM [post] GROUP BY [post].[userId], [post].[id]', + string: 'SELECT [post].[content] FROM [post] GROUP BY [post].[userId], [post].[id]' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post" GROUP BY "post"."userId", "post"."id"', + string: 'SELECT "post"."content" FROM "post" GROUP BY "post"."userId", "post"."id"' + }, params: [] }); @@ -51,6 +67,14 @@ Harness.test({ text : 'SELECT GROUP_CONCAT(`post`.`content`) AS `contents` FROM `post` GROUP BY `post`.`userId`', string: 'SELECT GROUP_CONCAT(`post`.`content`) AS `contents` FROM `post` GROUP BY `post`.`userId`' }, + mssql: { + text : 'SQL Server does not support array_agg.', + throws: true + }, + oracle: { + text : 'Oracle does not support array_agg.', + throws: true + }, params: [] }); @@ -68,6 +92,14 @@ Harness.test({ text : 'SELECT GROUP_CONCAT(`post`.`content`) AS `post contents` FROM `post` GROUP BY `post`.`userId`', string: 'SELECT GROUP_CONCAT(`post`.`content`) AS `post contents` FROM `post` GROUP BY `post`.`userId`' }, + mssql: { + text : 'SQL Server does not support array_agg.', + throws: true + }, + oracle: { + text : 'Oracle does not support array_agg.', + throws: true + }, params: [] }); @@ -85,5 +117,13 @@ Harness.test({ text : 'SELECT `post`.`content` FROM `post` GROUP BY `post`.`userId`, `post`.`id`', string: 'SELECT `post`.`content` FROM `post` GROUP BY `post`.`userId`, `post`.`id`' }, + mssql: { + text : 'SELECT [post].[content] FROM [post] GROUP BY [post].[userId], [post].[id]', + string: 'SELECT [post].[content] FROM [post] GROUP BY [post].[userId], [post].[id]' + }, + oracel: { + text : 'SELECT "post"."content" FROM "post" GROUP BY "post"."userId", "post"."id"', + string: 'SELECT "post"."content" FROM "post" GROUP BY "post"."userId", "post"."id"' + }, params: [] }); diff --git a/test/dialects/having-tests.js b/test/dialects/having-tests.js index b06190e3..5f8f9cc7 100644 --- a/test/dialects/having-tests.js +++ b/test/dialects/having-tests.js @@ -17,6 +17,14 @@ Harness.test({ text : 'SELECT `post`.`userId`, COUNT(`post`.`content`) AS `content_count` FROM `post` GROUP BY `post`.`userId` HAVING (`post`.`userId` > ?)', string: 'SELECT `post`.`userId`, COUNT(`post`.`content`) AS `content_count` FROM `post` GROUP BY `post`.`userId` HAVING (`post`.`userId` > 10)' }, + mssql : { + text : 'SELECT [post].[userId], COUNT([post].[content]) AS [content_count] FROM [post] GROUP BY [post].[userId] HAVING ([post].[userId] > @1)', + string: 'SELECT [post].[userId], COUNT([post].[content]) AS [content_count] FROM [post] GROUP BY [post].[userId] HAVING ([post].[userId] > 10)' + }, + oracle: { + text : 'SELECT "post"."userId", COUNT("post"."content") "content_count" FROM "post" GROUP BY "post"."userId" HAVING ("post"."userId" > :1)', + string: 'SELECT "post"."userId", COUNT("post"."content") "content_count" FROM "post" GROUP BY "post"."userId" HAVING ("post"."userId" > 10)' + }, params: [10] }); @@ -34,6 +42,14 @@ Harness.test({ text : 'SELECT `post`.`userId`, COUNT(`post`.`content`) AS `content_count` FROM `post` GROUP BY `post`.`userId` HAVING (`post`.`userId` > ?) AND (`post`.`userId` < ?)', string: 'SELECT `post`.`userId`, COUNT(`post`.`content`) AS `content_count` FROM `post` GROUP BY `post`.`userId` HAVING (`post`.`userId` > 10) AND (`post`.`userId` < 100)' }, + mssql : { + text : 'SELECT [post].[userId], COUNT([post].[content]) AS [content_count] FROM [post] GROUP BY [post].[userId] HAVING ([post].[userId] > @1) AND ([post].[userId] < @2)', + string: 'SELECT [post].[userId], COUNT([post].[content]) AS [content_count] FROM [post] GROUP BY [post].[userId] HAVING ([post].[userId] > 10) AND ([post].[userId] < 100)' + }, + oracle: { + text : 'SELECT "post"."userId", COUNT("post"."content") "content_count" FROM "post" GROUP BY "post"."userId" HAVING ("post"."userId" > :1) AND ("post"."userId" < :2)', + string: 'SELECT "post"."userId", COUNT("post"."content") "content_count" FROM "post" GROUP BY "post"."userId" HAVING ("post"."userId" > 10) AND ("post"."userId" < 100)' + }, params: [10, 100] }); @@ -51,5 +67,13 @@ Harness.test({ text : 'SELECT `post`.`userId`, COUNT(`post`.`content`) AS `content_count` FROM `post` GROUP BY `post`.`userId` HAVING (`post`.`userId` > ?) AND (`post`.`userId` < ?)', string: 'SELECT `post`.`userId`, COUNT(`post`.`content`) AS `content_count` FROM `post` GROUP BY `post`.`userId` HAVING (`post`.`userId` > 10) AND (`post`.`userId` < 100)' }, + mssql : { + text : 'SELECT [post].[userId], COUNT([post].[content]) AS [content_count] FROM [post] GROUP BY [post].[userId] HAVING ([post].[userId] > @1) AND ([post].[userId] < @2)', + string: 'SELECT [post].[userId], COUNT([post].[content]) AS [content_count] FROM [post] GROUP BY [post].[userId] HAVING ([post].[userId] > 10) AND ([post].[userId] < 100)' + }, + oracle: { + text : 'SELECT "post"."userId", COUNT("post"."content") "content_count" FROM "post" GROUP BY "post"."userId" HAVING ("post"."userId" > :1) AND ("post"."userId" < :2)', + string: 'SELECT "post"."userId", COUNT("post"."content") "content_count" FROM "post" GROUP BY "post"."userId" HAVING ("post"."userId" > 10) AND ("post"."userId" < 100)' + }, params: [10, 100] }); diff --git a/test/dialects/ilike-tests.js b/test/dialects/ilike-tests.js new file mode 100644 index 00000000..aba487ee --- /dev/null +++ b/test/dialects/ilike-tests.js @@ -0,0 +1,45 @@ +'use strict'; + +var Harness = require('./support'); +var post = Harness.definePostTable(); +var user = Harness.defineUserTable(); +var Sql = require('../../lib').setDialect('postgres'); + +Harness.test({ + query: post.select(post.content, post.userId).where(post.content.ilike('A%')), + pg: { + text : 'SELECT "post"."content", "post"."userId" FROM "post" WHERE ("post"."content" ILIKE $1)', + string: 'SELECT "post"."content", "post"."userId" FROM "post" WHERE ("post"."content" ILIKE \'A%\')' + }, + params: ['A%'] +}); + +Harness.test({ + query: post.insert(post.content, post.userId) + .select('\'test\'', user.id).from(user).where(user.name.ilike('A%')), + pg: { + text : 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" ILIKE $1)', + string: 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" ILIKE \'A%\')' + }, + params: ['A%'] +}); + +Harness.test({ + query: post.insert([post.content, post.userId]) + .select('\'test\'', user.id).from(user).where(user.name.ilike('A%')), + pg: { + text : 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" ILIKE $1)', + string: 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" ILIKE \'A%\')' + }, + params: ['A%'] +}); + +Harness.test({ + query: post.insert(post.userId) + .select(user.id).from(user).where(user.name.ilike('A%')), + pg: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" WHERE ("user"."name" ILIKE $1)', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" WHERE ("user"."name" ILIKE \'A%\')' + }, + params: ['A%'] +}); diff --git a/test/dialects/in-clause-tests.js b/test/dialects/in-clause-tests.js index a8410e14..513c7243 100644 --- a/test/dialects/in-clause-tests.js +++ b/test/dialects/in-clause-tests.js @@ -17,6 +17,14 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (1=0)', string: 'SELECT `post`.* FROM `post` WHERE (1=0)' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE (1=0)', + string: 'SELECT [post].* FROM [post] WHERE (1=0)' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE (1=0)', + string: 'SELECT "post".* FROM "post" WHERE (1=0)' + }, params: [] }); @@ -34,6 +42,14 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IN (?))', string: 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IN (1))' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE ([post].[id] IN (@1))', + string: 'SELECT [post].* FROM [post] WHERE ([post].[id] IN (1))' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."id" IN (:1))', + string: 'SELECT "post".* FROM "post" WHERE ("post"."id" IN (1))' + }, params: [1] }); @@ -51,6 +67,14 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IS NULL)', string: 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IS NULL)' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE ([post].[id] IS NULL)', + string: 'SELECT [post].* FROM [post] WHERE ([post].[id] IS NULL)' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."id" IS NULL)', + string: 'SELECT "post".* FROM "post" WHERE ("post"."id" IS NULL)' + }, params: [] }); @@ -68,6 +92,14 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IN (?, ?))', string: 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IN (1, 2))' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE ([post].[id] IN (@1, @2))', + string: 'SELECT [post].* FROM [post] WHERE ([post].[id] IN (1, 2))' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."id" IN (:1, :2))', + string: 'SELECT "post".* FROM "post" WHERE ("post"."id" IN (1, 2))' + }, params: [1, 2] }); @@ -85,6 +117,14 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IS NULL)', string: 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IS NULL)' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE ([post].[id] IS NULL)', + string: 'SELECT [post].* FROM [post] WHERE ([post].[id] IS NULL)' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."id" IS NULL)', + string: 'SELECT "post".* FROM "post" WHERE ("post"."id" IS NULL)' + }, params: [] }); @@ -102,6 +142,14 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IN (?, ?) OR `post`.`id` IS NULL)', string: 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IN (1, 2) OR `post`.`id` IS NULL)' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE ([post].[id] IN (@1, @2) OR [post].[id] IS NULL)', + string: 'SELECT [post].* FROM [post] WHERE ([post].[id] IN (1, 2) OR [post].[id] IS NULL)' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."id" IN (:1, :2) OR "post"."id" IS NULL)', + string: 'SELECT "post".* FROM "post" WHERE ("post"."id" IN (1, 2) OR "post"."id" IS NULL)' + }, params: [1, 2] }); @@ -119,5 +167,13 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IN (?, ?) OR `post`.`id` IS NULL)', string: 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IN (1, 2) OR `post`.`id` IS NULL)' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE ([post].[id] IN (@1, @2) OR [post].[id] IS NULL)', + string: 'SELECT [post].* FROM [post] WHERE ([post].[id] IN (1, 2) OR [post].[id] IS NULL)' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."id" IN (:1, :2) OR "post"."id" IS NULL)', + string: 'SELECT "post".* FROM "post" WHERE ("post"."id" IN (1, 2) OR "post"."id" IS NULL)' + }, params: [1, 2] }); diff --git a/test/dialects/indexes-tests.js b/test/dialects/indexes-tests.js index 132c01fb..86b50449 100644 --- a/test/dialects/indexes-tests.js +++ b/test/dialects/indexes-tests.js @@ -6,8 +6,8 @@ var post = Harness.definePostTable(); Harness.test({ query: post.indexes(), pg: { - text : 'SELECT relname FROM pg_class WHERE oid IN ( SELECT indexrelid FROM pg_index, pg_class WHERE pg_class.relname=\'post\' AND pg_class.oid=pg_index.indrelid)', - string: 'SELECT relname FROM pg_class WHERE oid IN ( SELECT indexrelid FROM pg_index, pg_class WHERE pg_class.relname=\'post\' AND pg_class.oid=pg_index.indrelid)' + text : 'SELECT relname FROM pg_class WHERE oid IN ( SELECT indexrelid FROM pg_index, pg_class WHERE pg_class.relname=\'post\' AND pg_class.relnamespace IN (SELECT pg_namespace.oid FROM pg_namespace WHERE nspname = \'public\') AND pg_class.oid=pg_index.indrelid)', + string: 'SELECT relname FROM pg_class WHERE oid IN ( SELECT indexrelid FROM pg_index, pg_class WHERE pg_class.relname=\'post\' AND pg_class.relnamespace IN (SELECT pg_namespace.oid FROM pg_namespace WHERE nspname = \'public\') AND pg_class.oid=pg_index.indrelid)' }, mysql: { text : 'SHOW INDEX FROM `post`', @@ -17,6 +17,10 @@ Harness.test({ text : 'PRAGMA INDEX_LIST("post")', string: 'PRAGMA INDEX_LIST("post")' }, + oracle: { + text : 'SELECT * FROM USER_INDEXES WHERE TABLE_NAME = \'post\'', + string: 'SELECT * FROM USER_INDEXES WHERE TABLE_NAME = \'post\'' + }, params: [] }); @@ -34,6 +38,10 @@ Harness.test({ text : 'CREATE UNIQUE INDEX "index_name" USING BTREE ON "post" ("id","userId") WITH PARSER foo', string: 'CREATE UNIQUE INDEX "index_name" USING BTREE ON "post" ("id","userId") WITH PARSER foo' }, + oracle: { + text : 'CREATE UNIQUE INDEX "index_name" USING BTREE ON "post" ("id","userId") WITH PARSER foo', + string: 'CREATE UNIQUE INDEX "index_name" USING BTREE ON "post" ("id","userId") WITH PARSER foo' + }, params: [] }); @@ -85,6 +93,10 @@ Harness.test({ text : 'CREATE INDEX "post_id_userId" ON "post" ("userId","id")', string: 'CREATE INDEX "post_id_userId" ON "post" ("userId","id")' }, + oracle: { + text : 'CREATE INDEX "post_id_userId" ON "post" ("userId","id")', + string: 'CREATE INDEX "post_id_userId" ON "post" ("userId","id")' + }, params: [] }); @@ -102,9 +114,64 @@ Harness.test({ text : 'CREATE INDEX "post_id_userId" ON "post" ("userId","id")', string: 'CREATE INDEX "post_id_userId" ON "post" ("userId","id")' }, + oracle: { + text : 'CREATE INDEX "post_id_userId" ON "post" ("userId","id")', + string: 'CREATE INDEX "post_id_userId" ON "post" ("userId","id")' + }, + params: [] +}); + +Harness.test({ + query: post.indexes().create().on(post.userId, post.id.desc), + pg: { + text : 'CREATE INDEX "post_id_userId" ON "post" ("userId","id" DESC)', + string: 'CREATE INDEX "post_id_userId" ON "post" ("userId","id" DESC)' + }, + mysql: { + text : 'CREATE INDEX `post_id_userId` ON `post` (`userId`,`id` DESC)', + string: 'CREATE INDEX `post_id_userId` ON `post` (`userId`,`id` DESC)' + }, + sqlite: { + text : 'CREATE INDEX "post_id_userId" ON "post" ("userId","id" DESC)', + string: 'CREATE INDEX "post_id_userId" ON "post" ("userId","id" DESC)' + }, + mssql: { + text : 'CREATE INDEX [post_id_userId] ON [post] ([userId],[id] DESC)', + string: 'CREATE INDEX [post_id_userId] ON [post] ([userId],[id] DESC)' + }, + oracle: { + text : 'CREATE INDEX "post_id_userId" ON "post" ("userId","id" DESC)', + string: 'CREATE INDEX "post_id_userId" ON "post" ("userId","id" DESC)' + }, + params: [] +}); + +Harness.test({ + query: post.indexes().create().on(post.userId).on(post.id.descending), + pg: { + text : 'CREATE INDEX "post_id_userId" ON "post" ("userId","id" DESC)', + string: 'CREATE INDEX "post_id_userId" ON "post" ("userId","id" DESC)' + }, + mysql: { + text : 'CREATE INDEX `post_id_userId` ON `post` (`userId`,`id` DESC)', + string: 'CREATE INDEX `post_id_userId` ON `post` (`userId`,`id` DESC)' + }, + sqlite: { + text : 'CREATE INDEX "post_id_userId" ON "post" ("userId","id" DESC)', + string: 'CREATE INDEX "post_id_userId" ON "post" ("userId","id" DESC)' + }, + mssql: { + text : 'CREATE INDEX [post_id_userId] ON [post] ([userId],[id] DESC)', + string: 'CREATE INDEX [post_id_userId] ON [post] ([userId],[id] DESC)' + }, + oracle: { + text : 'CREATE INDEX "post_id_userId" ON "post" ("userId","id" DESC)', + string: 'CREATE INDEX "post_id_userId" ON "post" ("userId","id" DESC)' + }, params: [] }); + Harness.test({ query: post.indexes().create(), pg: { @@ -118,22 +185,30 @@ Harness.test({ sqlite: { text : 'No columns defined!', throws: true + }, + oracle: { + text : 'No columns defined!', + throws: true } }); Harness.test({ query: post.indexes().drop('index_name'), pg: { - text : 'DROP INDEX "index_name" ON "post"', - string: 'DROP INDEX "index_name" ON "post"' + text : 'DROP INDEX "public"."index_name"', + string: 'DROP INDEX "public"."index_name"' }, mysql: { - text : 'DROP INDEX `index_name` ON `post`', - string: 'DROP INDEX `index_name` ON `post`' + text : 'DROP INDEX `public`.`index_name`', + string: 'DROP INDEX `public`.`index_name`' }, sqlite: { - text : 'DROP INDEX "index_name" ON "post"', - string: 'DROP INDEX "index_name" ON "post"' + text : 'DROP INDEX "public"."index_name"', + string: 'DROP INDEX "public"."index_name"' + }, + oracle: { + text : 'DROP INDEX "index_name"', + string: 'DROP INDEX "index_name"' }, params: [] }); @@ -141,16 +216,20 @@ Harness.test({ Harness.test({ query: post.indexes().drop(post.userId, post.id), pg: { - text : 'DROP INDEX "post_id_userId" ON "post"', - string: 'DROP INDEX "post_id_userId" ON "post"' + text : 'DROP INDEX "public"."post_id_userId"', + string: 'DROP INDEX "public"."post_id_userId"' }, mysql: { - text : 'DROP INDEX `post_id_userId` ON `post`', - string: 'DROP INDEX `post_id_userId` ON `post`' + text : 'DROP INDEX `public`.`post_id_userId`', + string: 'DROP INDEX `public`.`post_id_userId`' }, sqlite: { - text : 'DROP INDEX "post_id_userId" ON "post"', - string: 'DROP INDEX "post_id_userId" ON "post"' + text : 'DROP INDEX "public"."post_id_userId"', + string: 'DROP INDEX "public"."post_id_userId"' + }, + oracle: { + text : 'DROP INDEX "post_id_userId"', + string: 'DROP INDEX "post_id_userId"' }, params: [] }); diff --git a/test/dialects/insert-tests.js b/test/dialects/insert-tests.js index 69daa9f8..60ba6a62 100644 --- a/test/dialects/insert-tests.js +++ b/test/dialects/insert-tests.js @@ -3,6 +3,13 @@ var Harness = require('./support'); var post = Harness.definePostTable(); var user = Harness.defineUserTable(); +var contentTable = Harness.defineContentTable(); +var customerAliasTable = Harness.defineCustomerAliasTable(); + +var arrayTable = require('../../lib/table').define({ + name: 'arraytest', + columns: ['id', 'numbers'] +}); Harness.test({ query: post.insert(post.content.value('test'), post.userId.value(1)), @@ -18,6 +25,10 @@ Harness.test({ text : 'INSERT INTO `post` (`content`, `userId`) VALUES (?, ?)', string: 'INSERT INTO `post` (`content`, `userId`) VALUES (\'test\', 1)' }, + oracle: { + text : 'INSERT INTO "post" ("content", "userId") VALUES (:1, :2)', + string: 'INSERT INTO "post" ("content", "userId") VALUES (\'test\', 1)' + }, params: ['test', 1] }); @@ -35,9 +46,42 @@ Harness.test({ text : 'INSERT INTO `post` (`content`) VALUES (?)', string: 'INSERT INTO `post` (`content`) VALUES (\'whoah\')' }, + mssql: { + text : 'INSERT INTO [post] ([content]) VALUES (@1)', + string: 'INSERT INTO [post] ([content]) VALUES (\'whoah\')' + }, + oracle: { + text : 'INSERT INTO "post" ("content") VALUES (:1)', + string: 'INSERT INTO "post" ("content") VALUES (\'whoah\')' + }, params: ['whoah'] }); +Harness.test({ + query: post.insert({length: 0}), + pg: { + text : 'INSERT INTO "post" ("length") VALUES ($1)', + string: 'INSERT INTO "post" ("length") VALUES (0)' + }, + sqlite: { + text : 'INSERT INTO "post" ("length") VALUES ($1)', + string: 'INSERT INTO "post" ("length") VALUES (0)' + }, + mysql: { + text : 'INSERT INTO `post` (`length`) VALUES (?)', + string: 'INSERT INTO `post` (`length`) VALUES (0)' + }, + mssql: { + text : 'INSERT INTO [post] ([length]) VALUES (@1)', + string: 'INSERT INTO [post] ([length]) VALUES (0)' + }, + oracle: { + text : 'INSERT INTO "post" ("length") VALUES (:1)', + string: 'INSERT INTO "post" ("length") VALUES (0)' + }, + params: [0] +}); + Harness.test({ query: post.insert({ content: 'test', @@ -55,6 +99,10 @@ Harness.test({ text : 'INSERT INTO `post` (`content`, `userId`) VALUES (?, ?)', string: 'INSERT INTO `post` (`content`, `userId`) VALUES (\'test\', 2)' }, + oracle: { + text : 'INSERT INTO "post" ("content", "userId") VALUES (:1, :2)', + string: 'INSERT INTO "post" ("content", "userId") VALUES (\'test\', 2)' + }, params: ['test', 2] }); @@ -75,6 +123,10 @@ Harness.test({ text : 'INSERT INTO `post` (`content`, `userId`) VALUES (LOWER(?), ?)', string: 'INSERT INTO `post` (`content`, `userId`) VALUES (LOWER(\'TEST\'), 2)' }, + oracle: { + text : 'INSERT INTO "post" ("content", "userId") VALUES (LOWER(:1), :2)', + string: 'INSERT INTO "post" ("content", "userId") VALUES (LOWER(\'TEST\'), 2)' + }, params: ['TEST', 2] }); @@ -98,6 +150,10 @@ Harness.test({ text : 'INSERT INTO `post` (`content`) VALUES (?), (?)', string: 'INSERT INTO `post` (`content`) VALUES (\'whoah\'), (\'hey\')' }, + oracle: { + text : 'INSERT INTO "post" ("content") VALUES (:1), (:2)', + string: 'INSERT INTO "post" ("content") VALUES (\'whoah\'), (\'hey\')' + }, params: ['whoah', 'hey'] }); @@ -122,6 +178,10 @@ Harness.test({ text : 'INSERT INTO `post` (`content`, `userId`) VALUES (?, ?), (?, ?)', string: 'INSERT INTO `post` (`content`, `userId`) VALUES (\'whoah\', 1), (\'hey\', 2)' }, + oracle: { + text : 'INSERT INTO "post" ("content", "userId") VALUES (:1, :2), (:3, :4)', + string: 'INSERT INTO "post" ("content", "userId") VALUES (\'whoah\', 1), (\'hey\', 2)' + }, params: ['whoah', 1, 'hey', 2] }); @@ -147,6 +207,14 @@ Harness.test({ text : 'INSERT INTO `post` (`content`, `userId`) VALUES (?, ?), (?, ?)', string: 'INSERT INTO `post` (`content`, `userId`) VALUES (\'whoah\', 1), (\'hey\', 2)' }, + mssql: { + text : 'INSERT INTO [post] ([content], [userId]) VALUES (@1, @2), (@3, @4)', + string: 'INSERT INTO [post] ([content], [userId]) VALUES (\'whoah\', 1), (\'hey\', 2)' + }, + oracle: { + text : 'INSERT INTO "post" ("content", "userId") VALUES (:1, :2), (:3, :4)', + string: 'INSERT INTO "post" ("content", "userId") VALUES (\'whoah\', 1), (\'hey\', 2)' + }, params: ['whoah', 1, 'hey', 2] }); @@ -164,6 +232,14 @@ Harness.test({ text : 'INSERT INTO `post` () VALUES ()', string: 'INSERT INTO `post` () VALUES ()' }, + mssql: { + text : 'INSERT INTO [post] DEFAULT VALUES', + string: 'INSERT INTO [post] DEFAULT VALUES' + }, + oracle: { + text : 'INSERT INTO "post" DEFAULT VALUES', + string: 'INSERT INTO "post" DEFAULT VALUES' + }, params: [] }); @@ -179,6 +255,12 @@ Harness.test({ mysql: { throws: true }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, params: [] }); @@ -194,6 +276,12 @@ Harness.test({ mysql: { throws: true }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, params: [] }); @@ -209,6 +297,12 @@ Harness.test({ mysql: { throws: true }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, params: [] }); @@ -224,6 +318,12 @@ Harness.test({ mysql: { throws: true }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, params: [] }); @@ -239,6 +339,12 @@ Harness.test({ mysql: { throws: true }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, params: [] }); @@ -264,7 +370,17 @@ Harness.test({ text : 'INSERT INTO `post` (`content`, `userId`) VALUES (?, ?), (?, DEFAULT)', string: 'INSERT INTO `post` (`content`, `userId`) VALUES (\'whoah\', 1), (\'hey\', DEFAULT)', params: ['whoah', 1, 'hey'] - } + }, + mssql: { + text : 'INSERT INTO [post] ([content], [userId]) VALUES (@1, @2), (@3, DEFAULT)', + string: 'INSERT INTO [post] ([content], [userId]) VALUES (\'whoah\', 1), (\'hey\', DEFAULT)', + params: ['whoah', 1, 'hey'] + }, + oracle: { + text : 'INSERT INTO "post" ("content", "userId") VALUES (:1, :2), (:3, DEFAULT)', + string: 'INSERT INTO "post" ("content", "userId") VALUES (\'whoah\', 1), (\'hey\', DEFAULT)', + params: ['whoah', 1, 'hey'] + }, }); Harness.test({ @@ -288,6 +404,16 @@ Harness.test({ text : 'INSERT INTO `post` (`userId`, `content`) VALUES (?, DEFAULT), (?, ?)', string: 'INSERT INTO `post` (`userId`, `content`) VALUES (1, DEFAULT), (2, \'hey\')', params: [1, 2, 'hey'] + }, + mssql: { + text : 'INSERT INTO [post] ([userId], [content]) VALUES (@1, DEFAULT), (@2, @3)', + string: 'INSERT INTO [post] ([userId], [content]) VALUES (1, DEFAULT), (2, \'hey\')', + params: [1, 2, 'hey'] + }, + oracle: { + text : 'INSERT INTO "post" ("userId", "content") VALUES (:1, DEFAULT), (:2, :3)', + string: 'INSERT INTO "post" ("userId", "content") VALUES (1, DEFAULT), (2, \'hey\')', + params: [1, 2, 'hey'] } }); @@ -295,16 +421,24 @@ Harness.test({ query: post.insert(post.content, post.userId) .select('\'test\'', user.id).from(user).where(user.name.like('A%')), pg: { - text : 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "id" FROM "user" WHERE ("name" LIKE $1)', - string: 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "id" FROM "user" WHERE ("name" LIKE \'A%\')' + text : 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE $1)', + string: 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE \'A%\')' }, sqlite: { - text : 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "id" FROM "user" WHERE ("name" LIKE $1)', - string: 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "id" FROM "user" WHERE ("name" LIKE \'A%\')' + text : 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE $1)', + string: 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE \'A%\')' }, mysql: { - text : 'INSERT INTO `post` (`content`, `userId`) SELECT \'test\', `id` FROM `user` WHERE (`name` LIKE ?)', - string: 'INSERT INTO `post` (`content`, `userId`) SELECT \'test\', `id` FROM `user` WHERE (`name` LIKE \'A%\')' + text : 'INSERT INTO `post` (`content`, `userId`) SELECT \'test\', `user`.`id` FROM `user` WHERE (`user`.`name` LIKE ?)', + string: 'INSERT INTO `post` (`content`, `userId`) SELECT \'test\', `user`.`id` FROM `user` WHERE (`user`.`name` LIKE \'A%\')' + }, + mssql: { + text : 'INSERT INTO [post] ([content], [userId]) SELECT \'test\', [user].[id] FROM [user] WHERE ([user].[name] LIKE @1)', + string: 'INSERT INTO [post] ([content], [userId]) SELECT \'test\', [user].[id] FROM [user] WHERE ([user].[name] LIKE \'A%\')' + }, + oracle: { + text : 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE :1)', + string: 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE \'A%\')' }, params: ['A%'] }); @@ -313,16 +447,24 @@ Harness.test({ query: post.insert([post.content, post.userId]) .select('\'test\'', user.id).from(user).where(user.name.like('A%')), pg: { - text : 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "id" FROM "user" WHERE ("name" LIKE $1)', - string: 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "id" FROM "user" WHERE ("name" LIKE \'A%\')' + text : 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE $1)', + string: 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE \'A%\')' }, sqlite: { - text : 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "id" FROM "user" WHERE ("name" LIKE $1)', - string: 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "id" FROM "user" WHERE ("name" LIKE \'A%\')' + text : 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE $1)', + string: 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE \'A%\')' }, mysql: { - text : 'INSERT INTO `post` (`content`, `userId`) SELECT \'test\', `id` FROM `user` WHERE (`name` LIKE ?)', - string: 'INSERT INTO `post` (`content`, `userId`) SELECT \'test\', `id` FROM `user` WHERE (`name` LIKE \'A%\')' + text : 'INSERT INTO `post` (`content`, `userId`) SELECT \'test\', `user`.`id` FROM `user` WHERE (`user`.`name` LIKE ?)', + string: 'INSERT INTO `post` (`content`, `userId`) SELECT \'test\', `user`.`id` FROM `user` WHERE (`user`.`name` LIKE \'A%\')' + }, + mssql: { + text : 'INSERT INTO [post] ([content], [userId]) SELECT \'test\', [user].[id] FROM [user] WHERE ([user].[name] LIKE @1)', + string: 'INSERT INTO [post] ([content], [userId]) SELECT \'test\', [user].[id] FROM [user] WHERE ([user].[name] LIKE \'A%\')' + }, + oracle: { + text : 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE :1)', + string: 'INSERT INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE \'A%\')' }, params: ['A%'] }); @@ -331,20 +473,75 @@ Harness.test({ query: post.insert(post.userId) .select(user.id).from(user).where(user.name.like('A%')), pg: { - text : 'INSERT INTO "post" ("userId") SELECT "id" FROM "user" WHERE ("name" LIKE $1)', - string: 'INSERT INTO "post" ("userId") SELECT "id" FROM "user" WHERE ("name" LIKE \'A%\')' + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" WHERE ("user"."name" LIKE $1)', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" WHERE ("user"."name" LIKE \'A%\')' }, sqlite: { - text : 'INSERT INTO "post" ("userId") SELECT "id" FROM "user" WHERE ("name" LIKE $1)', - string: 'INSERT INTO "post" ("userId") SELECT "id" FROM "user" WHERE ("name" LIKE \'A%\')' + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" WHERE ("user"."name" LIKE $1)', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" WHERE ("user"."name" LIKE \'A%\')' }, mysql: { - text : 'INSERT INTO `post` (`userId`) SELECT `id` FROM `user` WHERE (`name` LIKE ?)', - string: 'INSERT INTO `post` (`userId`) SELECT `id` FROM `user` WHERE (`name` LIKE \'A%\')' + text : 'INSERT INTO `post` (`userId`) SELECT `user`.`id` FROM `user` WHERE (`user`.`name` LIKE ?)', + string: 'INSERT INTO `post` (`userId`) SELECT `user`.`id` FROM `user` WHERE (`user`.`name` LIKE \'A%\')' + }, + oracle: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" WHERE ("user"."name" LIKE :1)', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" WHERE ("user"."name" LIKE \'A%\')' }, params: ['A%'] }); +Harness.test({ + query: post.insert(post.userId) + .select(post.userId).from(user.join(post).on(user.id.equals(post.userId))).where(post.tags.like('A%')), + pg: { + text : 'INSERT INTO "post" ("userId") SELECT "post"."userId" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId") WHERE ("post"."tags" LIKE $1)', + string: 'INSERT INTO "post" ("userId") SELECT "post"."userId" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId") WHERE ("post"."tags" LIKE \'A%\')' + }, + sqlite: { + text : 'INSERT INTO "post" ("userId") SELECT "post"."userId" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId") WHERE ("post"."tags" LIKE $1)', + string: 'INSERT INTO "post" ("userId") SELECT "post"."userId" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId") WHERE ("post"."tags" LIKE \'A%\')' + }, + mysql: { + text : 'INSERT INTO `post` (`userId`) SELECT `post`.`userId` FROM `user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`) WHERE (`post`.`tags` LIKE ?)', + string: 'INSERT INTO `post` (`userId`) SELECT `post`.`userId` FROM `user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`) WHERE (`post`.`tags` LIKE \'A%\')' + }, + mssql: { + text : 'INSERT INTO [post] ([userId]) SELECT [post].[userId] FROM [user] INNER JOIN [post] ON ([user].[id] = [post].[userId]) WHERE ([post].[tags] LIKE @1)', + string: 'INSERT INTO [post] ([userId]) SELECT [post].[userId] FROM [user] INNER JOIN [post] ON ([user].[id] = [post].[userId]) WHERE ([post].[tags] LIKE \'A%\')' + }, + oracle: { + text : 'INSERT INTO "post" ("userId") SELECT "post"."userId" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId") WHERE ("post"."tags" LIKE :1)', + string: 'INSERT INTO "post" ("userId") SELECT "post"."userId" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId") WHERE ("post"."tags" LIKE \'A%\')' + }, + params: ['A%'] +}); + +Harness.test({ + query: post.insert(post.userId).select(user.id).distinct().from(user), + pg: { + text : 'INSERT INTO "post" ("userId") SELECT DISTINCT "user"."id" FROM "user"', + string: 'INSERT INTO "post" ("userId") SELECT DISTINCT "user"."id" FROM "user"' + }, + sqlite: { + text : 'INSERT INTO "post" ("userId") SELECT DISTINCT "user"."id" FROM "user"', + string: 'INSERT INTO "post" ("userId") SELECT DISTINCT "user"."id" FROM "user"' + }, + mysql: { + text : 'INSERT INTO `post` (`userId`) SELECT DISTINCT `user`.`id` FROM `user`', + string: 'INSERT INTO `post` (`userId`) SELECT DISTINCT `user`.`id` FROM `user`' + }, + mssql: { + text : 'INSERT INTO [post] ([userId]) SELECT DISTINCT [user].[id] FROM [user]', + string: 'INSERT INTO [post] ([userId]) SELECT DISTINCT [user].[id] FROM [user]' + }, + oracle: { + text : 'INSERT INTO "post" ("userId") SELECT DISTINCT "user"."id" FROM "user"', + string: 'INSERT INTO "post" ("userId") SELECT DISTINCT "user"."id" FROM "user"' + }, + params: [] +}); + // Binary inserts Harness.test({ query: post.insert(post.content.value(new Buffer('test')), post.userId.value(2)), @@ -360,6 +557,14 @@ Harness.test({ text : 'INSERT INTO `post` (`content`, `userId`) VALUES (?, ?)', string: 'INSERT INTO `post` (`content`, `userId`) VALUES (x\'74657374\', 2)' }, + mssql: { + text : 'INSERT INTO [post] ([content], [userId]) VALUES (@1, @2)', + string: 'INSERT INTO [post] ([content], [userId]) VALUES (\'\\x74657374\', 2)' + }, + oracle: { + text : 'INSERT INTO "post" ("content", "userId") VALUES (:1, :2)', + string: 'INSERT INTO "post" ("content", "userId") VALUES (utl_raw.cast_to_varchar2(hextoraw(\'74657374\')), 2)' + }, params: [new Buffer('test'), 2] }); @@ -380,6 +585,14 @@ Harness.test({ text : 'INSERT INTO `post` (`content`, `userId`) VALUES (?, ?)', string: 'INSERT INTO `post` (`content`, `userId`) VALUES (x\'74657374\', 2)' }, + mssql: { + text : 'INSERT INTO [post] ([content], [userId]) VALUES (@1, @2)', + string: 'INSERT INTO [post] ([content], [userId]) VALUES (\'\\x74657374\', 2)' + }, + oracle: { + text : 'INSERT INTO "post" ("content", "userId") VALUES (:1, :2)', + string: 'INSERT INTO "post" ("content", "userId") VALUES (utl_raw.cast_to_varchar2(hextoraw(\'74657374\')), 2)' + }, params: [new Buffer('test'), 2] }); @@ -403,5 +616,479 @@ Harness.test({ text : 'INSERT INTO `post` (`content`) VALUES (?), (?)', string: 'INSERT INTO `post` (`content`) VALUES (x\'77686f6168\'), (x\'686579\')' }, + mssql: { + text : 'INSERT INTO [post] ([content]) VALUES (@1), (@2)', + string: 'INSERT INTO [post] ([content]) VALUES (\'\\x77686f6168\'), (\'\\x686579\')' + }, + oracle: { + text : 'INSERT INTO "post" ("content") VALUES (:1), (:2)', + string: 'INSERT INTO "post" ("content") VALUES (utl_raw.cast_to_varchar2(hextoraw(\'77686f6168\'))), (utl_raw.cast_to_varchar2(hextoraw(\'686579\')))' + }, params: [new Buffer('whoah'), new Buffer('hey')] }); + +Harness.test({ + query: post.insert({ + content: 'test', + userId: 2 + }).onDuplicate({ + content: 'testupdate', + }), + pg: { + throws: true + }, + sqlite: { + throws: true + }, + mysql: { + text : 'INSERT INTO `post` (`content`, `userId`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `post`.`content` = ?', + string: 'INSERT INTO `post` (`content`, `userId`) VALUES (\'test\', 2) ON DUPLICATE KEY UPDATE `post`.`content` = \'testupdate\'' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2, 'testupdate'] +}); + +Harness.test({ + query: customerAliasTable.insert({ + id : 2, + name : 'test' + }).onConflict({ + columns: ['id'], + update: ['name'] + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + text : 'INSERT INTO "customer" ("id", "name") VALUES ($1, $2) ON CONFLICT ("id") DO UPDATE SET "name" = EXCLUDED."name"', + string: 'INSERT INTO "customer" ("id", "name") VALUES (2, \'test\') ON CONFLICT ("id") DO UPDATE SET "name" = EXCLUDED."name"' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [2, 'test'] +}); + +Harness.test({ + query: customerAliasTable.insert({ + id : 2, + name : 'test' + }).orIgnore(), + mysql: { + throws: true + }, + sqlite: { + text : 'INSERT OR IGNORE INTO "customer" ("id", "name") VALUES ($1, $2)', + string: 'INSERT OR IGNORE INTO "customer" ("id", "name") VALUES (2, \'test\')' + }, + pg: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [2, 'test'] +}); + +Harness.test({ + query: post.insert({ + content: 'test', + userId: 2 + }).onConflict({ + columns: ['userId'], + update: ['content'] + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + text : 'INSERT INTO "post" ("content", "userId") VALUES ($1, $2) ON CONFLICT ("userId") DO UPDATE SET "content" = EXCLUDED."content"', + string: 'INSERT INTO "post" ("content", "userId") VALUES (\'test\', 2) ON CONFLICT ("userId") DO UPDATE SET "content" = EXCLUDED."content"' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2] +}); + +Harness.test({ + query: post.insert({ + content: 'test', + userId: 2 + }).onConflict({ + columns: ['userId','content'], + update: ['content','userId'] + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + text : 'INSERT INTO "post" ("content", "userId") VALUES ($1, $2) ON CONFLICT ("userId", "content") DO UPDATE SET "content" = EXCLUDED."content", "userId" = EXCLUDED."userId"', + string: 'INSERT INTO "post" ("content", "userId") VALUES (\'test\', 2) ON CONFLICT ("userId", "content") DO UPDATE SET "content" = EXCLUDED."content", "userId" = EXCLUDED."userId"' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2] +}); + +Harness.test({ + query: post.insert({ + content: 'test', + userId: 2 + }).onConflict({ + columns: ['userId'], + update: ['content'] + }).where(post.userId.equals(2)), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + text : 'INSERT INTO "post" ("content", "userId") VALUES ($1, $2) ON CONFLICT ("userId") DO UPDATE SET "content" = EXCLUDED."content" WHERE ("post"."userId" = $3)', + string: 'INSERT INTO "post" ("content", "userId") VALUES (\'test\', 2) ON CONFLICT ("userId") DO UPDATE SET "content" = EXCLUDED."content" WHERE ("post"."userId" = 2)' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2, 2] +}); + +Harness.test({ + query: post.insert({ + content: 'test', + userId: 2 + }).onConflict({ + constraint: 'conc_userId', + update: ['content'] + }).where(post.userId.equals(2)), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + text : 'INSERT INTO "post" ("content", "userId") VALUES ($1, $2) ON CONFLICT ON CONSTRAINT "conc_userId" DO UPDATE SET "content" = EXCLUDED."content" WHERE ("post"."userId" = $3)', + string: 'INSERT INTO "post" ("content", "userId") VALUES (\'test\', 2) ON CONFLICT ON CONSTRAINT "conc_userId" DO UPDATE SET "content" = EXCLUDED."content" WHERE ("post"."userId" = 2)' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2, 2] +}); + +Harness.test({ + query: post.insert({ + content: 'test', + userId: 2 + }).onConflict({ + columns: ['userId'], + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + text : 'INSERT INTO "post" ("content", "userId") VALUES ($1, $2) ON CONFLICT ("userId") DO NOTHING', + string: 'INSERT INTO "post" ("content", "userId") VALUES (\'test\', 2) ON CONFLICT ("userId") DO NOTHING' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2] +}); + +Harness.test({ + query: post.insert({ + content: 'test', + userId: 2 + }).onConflict({ + constraint: 'conc_userId', + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + text : 'INSERT INTO "post" ("content", "userId") VALUES ($1, $2) ON CONFLICT ON CONSTRAINT "conc_userId" DO NOTHING', + string: 'INSERT INTO "post" ("content", "userId") VALUES (\'test\', 2) ON CONFLICT ON CONSTRAINT "conc_userId" DO NOTHING' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2] +}); + +Harness.test({ + query: contentTable.insert({ + contentId: 20, + text : "something" + }).onConflict({ + columns: ['contentId'], + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + text : 'INSERT INTO "content" ("content_id", "text") VALUES ($1, $2) ON CONFLICT ("content_id") DO NOTHING', + string: 'INSERT INTO "content" ("content_id", "text") VALUES (20, \'something\') ON CONFLICT ("content_id") DO NOTHING' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [20, "something"] +}); + +Harness.test({ + query: contentTable.insert({ + contentId: 20, + text : "something", + contentPosts : "another thing", + }).onConflict({ + columns: ['contentId'], + update: ['contentPosts'] + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + text : 'INSERT INTO "content" ("content_id", "text", "content_posts") VALUES ($1, $2, $3) ON CONFLICT ("content_id") DO UPDATE SET "content_posts" = EXCLUDED."content_posts"', + string: 'INSERT INTO "content" ("content_id", "text", "content_posts") VALUES (20, \'something\', \'another thing\') ON CONFLICT ("content_id") DO UPDATE SET "content_posts" = EXCLUDED."content_posts"' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [20, "something", "another thing"] +}); + +Harness.test({ + query: post.insert([]), + + mysql: { + text : 'SELECT `post`.* FROM `post` WHERE (1=2)', + string: 'SELECT `post`.* FROM `post` WHERE (1=2)' + }, + params: [] +}); + +Harness.test({ + query: arrayTable.insert(arrayTable.id.value(1), arrayTable.numbers.value([2, 3, 4])), + pg: { + text : 'INSERT INTO "arraytest" ("id", "numbers") VALUES ($1, $2)', + string: 'INSERT INTO "arraytest" ("id", "numbers") VALUES (1, \'{2,3,4}\')' + }, + sqlite: { + text : 'INSERT INTO "arraytest" ("id", "numbers") VALUES ($1, $2)', + string: 'INSERT INTO "arraytest" ("id", "numbers") VALUES (1, \'[2,3,4]\')' + }, + mysql: { + text : 'INSERT INTO `arraytest` (`id`, `numbers`) VALUES (?, ?)', + string: 'INSERT INTO `arraytest` (`id`, `numbers`) VALUES (1, (2, 3, 4))' + }, + oracle: { + text : 'INSERT INTO "arraytest" ("id", "numbers") VALUES (:1, :2)', + string: 'INSERT INTO "arraytest" ("id", "numbers") VALUES (1, (2, 3, 4))' + } +}); + +Harness.test({ + query: arrayTable.insert(arrayTable.id.value(1), arrayTable.numbers.value(["one", "two", "three"])), + pg: { + text : 'INSERT INTO "arraytest" ("id", "numbers") VALUES ($1, $2)', + string: 'INSERT INTO "arraytest" ("id", "numbers") VALUES (1, \'{"one","two","three"}\')' + }, + sqlite: { + text : 'INSERT INTO "arraytest" ("id", "numbers") VALUES ($1, $2)', + string: 'INSERT INTO "arraytest" ("id", "numbers") VALUES (1, \'["one","two","three"]\')' + }, + mysql: { + text : 'INSERT INTO `arraytest` (`id`, `numbers`) VALUES (?, ?)', + string: 'INSERT INTO `arraytest` (`id`, `numbers`) VALUES (1, (\'one\', \'two\', \'three\'))' + }, + oracle: { + text : 'INSERT INTO "arraytest" ("id", "numbers") VALUES (:1, :2)', + string: 'INSERT INTO "arraytest" ("id", "numbers") VALUES (1, (\'one\', \'two\', \'three\'))' + } +}); + +Harness.test({ + query: post.insert(post.userId).select(user.id).from(user), + pg: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"' + }, + sqlite: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"' + }, + mysql: { + text : 'INSERT INTO `post` (`userId`) SELECT `user`.`id` FROM `user`', + string: 'INSERT INTO `post` (`userId`) SELECT `user`.`id` FROM `user`' + }, + mssql: { + text : 'INSERT INTO [post] ([userId]) SELECT [user].[id] FROM [user]', + string: 'INSERT INTO [post] ([userId]) SELECT [user].[id] FROM [user]' + }, + oracle: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"' + }, + params: [] +}); + +Harness.test({ + query: post.insert(post.userId).select(user.id).from(user).onConflict({ + columns: ['userId'], + update: ['content'] + }), + pg: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" ON CONFLICT ("userId") DO UPDATE SET "content" = EXCLUDED."content"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" ON CONFLICT ("userId") DO UPDATE SET "content" = EXCLUDED."content"' + }, + sqlite: { + throws: true + }, + mysql: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); + +Harness.test({ + query: post.insert(post.userId).add(user.select(user.id)), + pg: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"' + }, + sqlite: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"' + }, + mysql: { + text : 'INSERT INTO `post` (`userId`) SELECT `user`.`id` FROM `user`', + string: 'INSERT INTO `post` (`userId`) SELECT `user`.`id` FROM `user`' + }, + mssql: { + text : 'INSERT INTO [post] ([userId]) SELECT [user].[id] FROM [user]', + string: 'INSERT INTO [post] ([userId]) SELECT [user].[id] FROM [user]' + }, + oracle: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"' + }, + params: [] +}); + +Harness.test({ + query: post.insert(post.userId).add(user.select(user.id).from(user)), + pg: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"' + }, + sqlite: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"' + }, + mysql: { + text : 'INSERT INTO `post` (`userId`) SELECT `user`.`id` FROM `user`', + string: 'INSERT INTO `post` (`userId`) SELECT `user`.`id` FROM `user`' + }, + mssql: { + text : 'INSERT INTO [post] ([userId]) SELECT [user].[id] FROM [user]', + string: 'INSERT INTO [post] ([userId]) SELECT [user].[id] FROM [user]' + }, + oracle: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user"' + }, + params: [] +}); + +Harness.test({ + query: post.insert(post.userId).add(user.select(user.id).order(user.id)), + pg: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" ORDER BY "user"."id"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" ORDER BY "user"."id"' + }, + sqlite: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" ORDER BY "user"."id"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" ORDER BY "user"."id"' + }, + mysql: { + text : 'INSERT INTO `post` (`userId`) SELECT `user`.`id` FROM `user` ORDER BY `user`.`id`', + string: 'INSERT INTO `post` (`userId`) SELECT `user`.`id` FROM `user` ORDER BY `user`.`id`' + }, + mssql: { + text : 'INSERT INTO [post] ([userId]) SELECT [user].[id] FROM [user] ORDER BY [user].[id]', + string: 'INSERT INTO [post] ([userId]) SELECT [user].[id] FROM [user] ORDER BY [user].[id]' + }, + oracle: { + text : 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" ORDER BY "user"."id"', + string: 'INSERT INTO "post" ("userId") SELECT "user"."id" FROM "user" ORDER BY "user"."id"' + }, + params: [] +}); + diff --git a/test/dialects/join-tests.js b/test/dialects/join-tests.js index d4e242af..2e0c6882 100644 --- a/test/dialects/join-tests.js +++ b/test/dialects/join-tests.js @@ -19,6 +19,14 @@ Harness.test({ text : 'SELECT `user`.`name`, `post`.`content` FROM `user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`)', string: 'SELECT `user`.`name`, `post`.`content` FROM `user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`)' }, + mssql: { + text : 'SELECT [user].[name], [post].[content] FROM [user] INNER JOIN [post] ON ([user].[id] = [post].[userId])', + string: 'SELECT [user].[name], [post].[content] FROM [user] INNER JOIN [post] ON ([user].[id] = [post].[userId])' + }, + oracle: { + text : 'SELECT "user"."name", "post"."content" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId")', + string: 'SELECT "user"."name", "post"."content" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId")' + }, params: [] }); @@ -36,6 +44,14 @@ Harness.test({ text : '`user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`)', string: '`user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`)' }, + mssql: { + text : '[user] INNER JOIN [post] ON ([user].[id] = [post].[userId])', + string: '[user] INNER JOIN [post] ON ([user].[id] = [post].[userId])' + }, + oracle: { + text : '"user" INNER JOIN "post" ON ("user"."id" = "post"."userId")', + string: '"user" INNER JOIN "post" ON ("user"."id" = "post"."userId")' + }, params: [] }); @@ -58,6 +74,14 @@ Harness.test({ text : 'SELECT `user`.`name`, `post`.`content`, `comment`.`text` FROM `user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`) INNER JOIN `comment` ON (`post`.`id` = `comment`.`postId`)', string: 'SELECT `user`.`name`, `post`.`content`, `comment`.`text` FROM `user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`) INNER JOIN `comment` ON (`post`.`id` = `comment`.`postId`)' }, + mssql: { + text : 'SELECT [user].[name], [post].[content], [comment].[text] FROM [user] INNER JOIN [post] ON ([user].[id] = [post].[userId]) INNER JOIN [comment] ON ([post].[id] = [comment].[postId])', + string: 'SELECT [user].[name], [post].[content], [comment].[text] FROM [user] INNER JOIN [post] ON ([user].[id] = [post].[userId]) INNER JOIN [comment] ON ([post].[id] = [comment].[postId])' + }, + oracle: { + text : 'SELECT "user"."name", "post"."content", "comment"."text" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId") INNER JOIN "comment" ON ("post"."id" = "comment"."postId")', + string: 'SELECT "user"."name", "post"."content", "comment"."text" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId") INNER JOIN "comment" ON ("post"."id" = "comment"."postId")' + }, params: [] }); @@ -75,6 +99,14 @@ Harness.test({ text : 'SELECT `user`.`name`, `post`.`content` FROM `user` LEFT JOIN `post` ON (`user`.`id` = `post`.`userId`)', string: 'SELECT `user`.`name`, `post`.`content` FROM `user` LEFT JOIN `post` ON (`user`.`id` = `post`.`userId`)' }, + mssql: { + text : 'SELECT [user].[name], [post].[content] FROM [user] LEFT JOIN [post] ON ([user].[id] = [post].[userId])', + string: 'SELECT [user].[name], [post].[content] FROM [user] LEFT JOIN [post] ON ([user].[id] = [post].[userId])' + }, + oracle: { + text : 'SELECT "user"."name", "post"."content" FROM "user" LEFT JOIN "post" ON ("user"."id" = "post"."userId")', + string: 'SELECT "user"."name", "post"."content" FROM "user" LEFT JOIN "post" ON ("user"."id" = "post"."userId")' + }, params: [] }); @@ -97,6 +129,14 @@ Harness.test({ text : 'SELECT `user`.`name`, `post`.`content` FROM `user` LEFT JOIN `post` ON (`user`.`id` = `post`.`userId`) LEFT JOIN `comment` ON (`post`.`id` = `comment`.`postId`)', string: 'SELECT `user`.`name`, `post`.`content` FROM `user` LEFT JOIN `post` ON (`user`.`id` = `post`.`userId`) LEFT JOIN `comment` ON (`post`.`id` = `comment`.`postId`)' }, + mssql: { + text : 'SELECT [user].[name], [post].[content] FROM [user] LEFT JOIN [post] ON ([user].[id] = [post].[userId]) LEFT JOIN [comment] ON ([post].[id] = [comment].[postId])', + string: 'SELECT [user].[name], [post].[content] FROM [user] LEFT JOIN [post] ON ([user].[id] = [post].[userId]) LEFT JOIN [comment] ON ([post].[id] = [comment].[postId])' + }, + oracle: { + text : 'SELECT "user"."name", "post"."content" FROM "user" LEFT JOIN "post" ON ("user"."id" = "post"."userId") LEFT JOIN "comment" ON ("post"."id" = "comment"."postId")', + string: 'SELECT "user"."name", "post"."content" FROM "user" LEFT JOIN "post" ON ("user"."id" = "post"."userId") LEFT JOIN "comment" ON ("post"."id" = "comment"."postId")' + }, params: [] }); @@ -113,16 +153,78 @@ Harness.test({ .from(user.join(subposts) .on(user.id.equals(subposts.subpostUserId))), pg: { - text : 'SELECT "user"."name", "subposts"."content" FROM "user" INNER JOIN (SELECT "post"."content", "post"."userId" AS "subpostUserId" FROM "post") subposts ON ("user"."id" = "subposts"."subpostUserId")', - string: 'SELECT "user"."name", "subposts"."content" FROM "user" INNER JOIN (SELECT "post"."content", "post"."userId" AS "subpostUserId" FROM "post") subposts ON ("user"."id" = "subposts"."subpostUserId")' + text : 'SELECT "user"."name", "subposts"."content" FROM "user" INNER JOIN (SELECT "post"."content", "post"."userId" AS "subpostUserId" FROM "post") "subposts" ON ("user"."id" = "subposts"."subpostUserId")', + string: 'SELECT "user"."name", "subposts"."content" FROM "user" INNER JOIN (SELECT "post"."content", "post"."userId" AS "subpostUserId" FROM "post") "subposts" ON ("user"."id" = "subposts"."subpostUserId")' }, sqlite: { - text : 'SELECT "user"."name", "subposts"."content" FROM "user" INNER JOIN (SELECT "post"."content", "post"."userId" AS "subpostUserId" FROM "post") subposts ON ("user"."id" = "subposts"."subpostUserId")', - string: 'SELECT "user"."name", "subposts"."content" FROM "user" INNER JOIN (SELECT "post"."content", "post"."userId" AS "subpostUserId" FROM "post") subposts ON ("user"."id" = "subposts"."subpostUserId")' + text : 'SELECT "user"."name", "subposts"."content" FROM "user" INNER JOIN (SELECT "post"."content", "post"."userId" AS "subpostUserId" FROM "post") "subposts" ON ("user"."id" = "subposts"."subpostUserId")', + string: 'SELECT "user"."name", "subposts"."content" FROM "user" INNER JOIN (SELECT "post"."content", "post"."userId" AS "subpostUserId" FROM "post") "subposts" ON ("user"."id" = "subposts"."subpostUserId")' }, mysql: { - text : 'SELECT `user`.`name`, `subposts`.`content` FROM `user` INNER JOIN (SELECT `post`.`content`, `post`.`userId` AS `subpostUserId` FROM `post`) subposts ON (`user`.`id` = `subposts`.`subpostUserId`)', - string: 'SELECT `user`.`name`, `subposts`.`content` FROM `user` INNER JOIN (SELECT `post`.`content`, `post`.`userId` AS `subpostUserId` FROM `post`) subposts ON (`user`.`id` = `subposts`.`subpostUserId`)' + text : 'SELECT `user`.`name`, `subposts`.`content` FROM `user` INNER JOIN (SELECT `post`.`content`, `post`.`userId` AS `subpostUserId` FROM `post`) `subposts` ON (`user`.`id` = `subposts`.`subpostUserId`)', + string: 'SELECT `user`.`name`, `subposts`.`content` FROM `user` INNER JOIN (SELECT `post`.`content`, `post`.`userId` AS `subpostUserId` FROM `post`) `subposts` ON (`user`.`id` = `subposts`.`subpostUserId`)' + }, + mssql: { + text : 'SELECT [user].[name], [subposts].[content] FROM [user] INNER JOIN (SELECT [post].[content], [post].[userId] AS [subpostUserId] FROM [post]) [subposts] ON ([user].[id] = [subposts].[subpostUserId])', + string: 'SELECT [user].[name], [subposts].[content] FROM [user] INNER JOIN (SELECT [post].[content], [post].[userId] AS [subpostUserId] FROM [post]) [subposts] ON ([user].[id] = [subposts].[subpostUserId])' + }, + oracle: { + text : 'SELECT "user"."name", "subposts"."content" FROM "user" INNER JOIN (SELECT "post"."content", "post"."userId" "subpostUserId" FROM "post") "subposts" ON ("user"."id" = "subposts"."subpostUserId")', + string: 'SELECT "user"."name", "subposts"."content" FROM "user" INNER JOIN (SELECT "post"."content", "post"."userId" "subpostUserId" FROM "post") "subposts" ON ("user"."id" = "subposts"."subpostUserId")' }, params: [] }); + +Harness.test({ + query: user.select().from(user.leftJoinLateral(post.subQuery().select(post.userId))), + pg: { + text : 'SELECT "user".* FROM "user" LEFT JOIN LATERAL (SELECT "post"."userId" FROM "post") ON true', + string: 'SELECT "user".* FROM "user" LEFT JOIN LATERAL (SELECT "post"."userId" FROM "post") ON true' + }, + mssql: { + text : 'SELECT [user].* FROM [user] OUTER APPLY (SELECT [post].[userId] FROM [post])', + string: 'SELECT [user].* FROM [user] OUTER APPLY (SELECT [post].[userId] FROM [post])' + }, + oracle: { + text : 'SELECT "user".* FROM "user" OUTER APPLY (SELECT "post"."userId" FROM "post")', + string: 'SELECT "user".* FROM "user" OUTER APPLY (SELECT "post"."userId" FROM "post")' + }, + params: [] +}); + +Harness.test({ + query: user.select().from(user.leftJoinLateral(post.subQuery().select(post.userId).where(user.id.equals(post.userId)))), + pg: { + text : 'SELECT "user".* FROM "user" LEFT JOIN LATERAL (SELECT "post"."userId" FROM "post" WHERE ("user"."id" = "post"."userId")) ON true', + string: 'SELECT "user".* FROM "user" LEFT JOIN LATERAL (SELECT "post"."userId" FROM "post" WHERE ("user"."id" = "post"."userId")) ON true' + }, + mssql: { + text : 'SELECT [user].* FROM [user] OUTER APPLY (SELECT [post].[userId] FROM [post] WHERE ([user].[id] = [post].[userId]))', + string: 'SELECT [user].* FROM [user] OUTER APPLY (SELECT [post].[userId] FROM [post] WHERE ([user].[id] = [post].[userId]))' + }, + oracle: { + text : 'SELECT "user".* FROM "user" OUTER APPLY (SELECT "post"."userId" FROM "post" WHERE ("user"."id" = "post"."userId"))', + string: 'SELECT "user".* FROM "user" OUTER APPLY (SELECT "post"."userId" FROM "post" WHERE ("user"."id" = "post"."userId"))' + }, + params: [] +}); + +Harness.test({ + query: user.select().from(user + .leftJoinLateral(post.subQuery().select(post.userId)) + .leftJoinLateral(comment.subQuery().select(comment.postId))), + pg: { + text : 'SELECT "user".* FROM "user" LEFT JOIN LATERAL (SELECT "post"."userId" FROM "post") ON true LEFT JOIN LATERAL (SELECT "comment"."postId" FROM "comment") ON true', + string: 'SELECT "user".* FROM "user" LEFT JOIN LATERAL (SELECT "post"."userId" FROM "post") ON true LEFT JOIN LATERAL (SELECT "comment"."postId" FROM "comment") ON true' + }, + mssql: { + text : 'SELECT [user].* FROM [user] OUTER APPLY (SELECT [post].[userId] FROM [post]) OUTER APPLY (SELECT [comment].[postId] FROM [comment])', + string: 'SELECT [user].* FROM [user] OUTER APPLY (SELECT [post].[userId] FROM [post]) OUTER APPLY (SELECT [comment].[postId] FROM [comment])' + }, + oracle: { + text : 'SELECT "user".* FROM "user" OUTER APPLY (SELECT "post"."userId" FROM "post") OUTER APPLY (SELECT "comment"."postId" FROM "comment")', + string: 'SELECT "user".* FROM "user" OUTER APPLY (SELECT "post"."userId" FROM "post") OUTER APPLY (SELECT "comment"."postId" FROM "comment")' + }, + params: [] +}); + diff --git a/test/dialects/join-to-tests.js b/test/dialects/join-to-tests.js index 5aca7e39..d50f8817 100644 --- a/test/dialects/join-to-tests.js +++ b/test/dialects/join-to-tests.js @@ -50,6 +50,14 @@ Harness.test({ text : '`user` INNER JOIN `post` ON (`user`.`id` = `post`.`ownerId`)', string: '`user` INNER JOIN `post` ON (`user`.`id` = `post`.`ownerId`)' }, + mssql: { + text : '[user] INNER JOIN [post] ON ([user].[id] = [post].[ownerId])', + string: '[user] INNER JOIN [post] ON ([user].[id] = [post].[ownerId])' + }, + oracle: { + text : '"user" INNER JOIN "post" ON ("user"."id" = "post"."ownerId")', + string: '"user" INNER JOIN "post" ON ("user"."id" = "post"."ownerId")' + }, params: [] }); @@ -67,6 +75,14 @@ Harness.test({ text : '`post` INNER JOIN `user` ON (`user`.`id` = `post`.`ownerId`)', string: '`post` INNER JOIN `user` ON (`user`.`id` = `post`.`ownerId`)' }, + mssql: { + text : '[post] INNER JOIN [user] ON ([user].[id] = [post].[ownerId])', + string: '[post] INNER JOIN [user] ON ([user].[id] = [post].[ownerId])' + }, + oracle: { + text : '"post" INNER JOIN "user" ON ("user"."id" = "post"."ownerId")', + string: '"post" INNER JOIN "user" ON ("user"."id" = "post"."ownerId")' + }, params: [] }); @@ -84,5 +100,13 @@ Harness.test({ text : '`user` INNER JOIN `photo` ON (`user`.`id` = `photo`.`ownerId`)', string: '`user` INNER JOIN `photo` ON (`user`.`id` = `photo`.`ownerId`)' }, + mssql: { + text : '[user] INNER JOIN [photo] ON ([user].[id] = [photo].[ownerId])', + string: '[user] INNER JOIN [photo] ON ([user].[id] = [photo].[ownerId])' + }, + oracle: { + text : '"user" INNER JOIN "photo" ON ("user"."id" = "photo"."ownerId")', + string: '"user" INNER JOIN "photo" ON ("user"."id" = "photo"."ownerId")' + }, params: [] }); diff --git a/test/dialects/limit-and-offset-tests.js b/test/dialects/limit-and-offset-tests.js index aa83033c..6561c14b 100644 --- a/test/dialects/limit-and-offset-tests.js +++ b/test/dialects/limit-and-offset-tests.js @@ -20,6 +20,10 @@ Harness.test({ text : 'SELECT `user`.* FROM `user` ORDER BY `user`.`name` LIMIT 1', string: 'SELECT `user`.* FROM `user` ORDER BY `user`.`name` LIMIT 1' }, + mssql: { + text : 'SELECT TOP(1) [user].* FROM [user] ORDER BY [user].[name]', + string: 'SELECT TOP(1) [user].* FROM [user] ORDER BY [user].[name]' + }, params: [] }); @@ -37,6 +41,10 @@ Harness.test({ text : 'SELECT `user`.* FROM `user` ORDER BY `user`.`name` LIMIT 3 OFFSET 6', string: 'SELECT `user`.* FROM `user` ORDER BY `user`.`name` LIMIT 3 OFFSET 6' }, + mssql: { + text : 'SELECT [user].* FROM [user] ORDER BY [user].[name] OFFSET 6 ROWS FETCH NEXT 3 ROWS ONLY', + string: 'SELECT [user].* FROM [user] ORDER BY [user].[name] OFFSET 6 ROWS FETCH NEXT 3 ROWS ONLY' + }, params: [] }); @@ -54,6 +62,14 @@ Harness.test({ text : 'SELECT `user`.* FROM `user` ORDER BY `user`.`name` OFFSET 10', string: 'SELECT `user`.* FROM `user` ORDER BY `user`.`name` OFFSET 10' }, + mssql: { + text : 'SELECT [user].* FROM [user] ORDER BY [user].[name] OFFSET 10 ROWS', + string: 'SELECT [user].* FROM [user] ORDER BY [user].[name] OFFSET 10 ROWS' + }, + oracle: { + text : 'SELECT "user".* FROM "user" ORDER BY "user"."name" OFFSET 10 ROWS', + string: 'SELECT "user".* FROM "user" ORDER BY "user"."name" OFFSET 10 ROWS' + }, params: [] }); @@ -75,5 +91,15 @@ Harness.test({ text : 'SELECT `user`.* FROM `user` WHERE (`user`.`name` = ?) OFFSET (SELECT FLOOR(RANDOM() * COUNT(*)) FROM `user` WHERE (`user`.`name` = ?)) LIMIT 1', string: 'SELECT `user`.* FROM `user` WHERE (`user`.`name` = \'John\') OFFSET (SELECT FLOOR(RANDOM() * COUNT(*)) FROM `user` WHERE (`user`.`name` = \'John\')) LIMIT 1' }, + mssql: { + text : 'Microsoft SQL Server does not support OFFSET without and ORDER BY.', + throws: true + }, + oracle: { + text : 'SELECT "user".* FROM "user" WHERE ("user"."name" = :1) OFFSET (SELECT FLOOR(RANDOM() * COUNT(*)) FROM "user" WHERE ("user"."name" = :2)) ROWS FETCH NEXT 1 ROWS ONLY', + string: 'SELECT "user".* FROM "user" WHERE ("user"."name" = \'John\') OFFSET (SELECT FLOOR(RANDOM() * COUNT(*)) FROM "user" WHERE ("user"."name" = \'John\')) ROWS FETCH NEXT 1 ROWS ONLY' + }, values: ['John', 'John'] }); + +// TODO: Should probably have a test case like the one above but including an ORDER BY clause so the mssql case can be tested \ No newline at end of file diff --git a/test/dialects/literal-tests.js b/test/dialects/literal-tests.js index e1940f5a..c31d4271 100644 --- a/test/dialects/literal-tests.js +++ b/test/dialects/literal-tests.js @@ -17,6 +17,10 @@ Harness.test({ text : 'SELECT foo, `user`.`name`, 123 AS `onetwothree` FROM `user`', string: 'SELECT foo, `user`.`name`, 123 AS `onetwothree` FROM `user`' }, + oracle: { + text : 'SELECT foo, "user"."name", 123 "onetwothree" FROM "user"', + string: 'SELECT foo, "user"."name", 123 "onetwothree" FROM "user"' + }, params: [] }); @@ -35,6 +39,10 @@ Harness.test({ text : 'SELECT `user`.* FROM `user` WHERE foo = bar', string: 'SELECT `user`.* FROM `user` WHERE foo = bar' }, + oracle: { + text : 'SELECT "user".* FROM "user" WHERE foo = bar', + string: 'SELECT "user".* FROM "user" WHERE foo = bar' + }, params: [] }); @@ -45,16 +53,20 @@ var subquery = user.subQuery('subquery_for_count').select(user.literal(1).as('co Harness.test({ query: user.select(subquery.count_column.count()).from(subquery), pg: { - text : 'SELECT COUNT("subquery_for_count"."count_column") AS "count_column_count" FROM (SELECT 1 AS "count_column" FROM "user" LIMIT 10 OFFSET 20) subquery_for_count', - string: 'SELECT COUNT("subquery_for_count"."count_column") AS "count_column_count" FROM (SELECT 1 AS "count_column" FROM "user" LIMIT 10 OFFSET 20) subquery_for_count' + text : 'SELECT COUNT("subquery_for_count"."count_column") AS "count_column_count" FROM (SELECT 1 AS "count_column" FROM "user" LIMIT 10 OFFSET 20) "subquery_for_count"', + string: 'SELECT COUNT("subquery_for_count"."count_column") AS "count_column_count" FROM (SELECT 1 AS "count_column" FROM "user" LIMIT 10 OFFSET 20) "subquery_for_count"' }, sqlite: { - text : 'SELECT COUNT("subquery_for_count"."count_column") AS "count_column_count" FROM (SELECT 1 AS "count_column" FROM "user" LIMIT 10 OFFSET 20) subquery_for_count', - string: 'SELECT COUNT("subquery_for_count"."count_column") AS "count_column_count" FROM (SELECT 1 AS "count_column" FROM "user" LIMIT 10 OFFSET 20) subquery_for_count' + text : 'SELECT COUNT("subquery_for_count"."count_column") AS "count_column_count" FROM (SELECT 1 AS "count_column" FROM "user" LIMIT 10 OFFSET 20) "subquery_for_count"', + string: 'SELECT COUNT("subquery_for_count"."count_column") AS "count_column_count" FROM (SELECT 1 AS "count_column" FROM "user" LIMIT 10 OFFSET 20) "subquery_for_count"' }, mysql: { - text : 'SELECT COUNT(`subquery_for_count`.`count_column`) AS `count_column_count` FROM (SELECT 1 AS `count_column` FROM `user` LIMIT 10 OFFSET 20) subquery_for_count', - string: 'SELECT COUNT(`subquery_for_count`.`count_column`) AS `count_column_count` FROM (SELECT 1 AS `count_column` FROM `user` LIMIT 10 OFFSET 20) subquery_for_count' + text : 'SELECT COUNT(`subquery_for_count`.`count_column`) AS `count_column_count` FROM (SELECT 1 AS `count_column` FROM `user` LIMIT 10 OFFSET 20) `subquery_for_count`', + string: 'SELECT COUNT(`subquery_for_count`.`count_column`) AS `count_column_count` FROM (SELECT 1 AS `count_column` FROM `user` LIMIT 10 OFFSET 20) `subquery_for_count`' + }, + oracle: { + text : 'SELECT COUNT("subquery_for_count"."count_column") "count_column_count" FROM (SELECT 1 "count_column" FROM "user" OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY) "subquery_for_count"', + string: 'SELECT COUNT("subquery_for_count"."count_column") "count_column_count" FROM (SELECT 1 "count_column" FROM "user" OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY) "subquery_for_count"' }, params: [] }); diff --git a/test/dialects/matches-test.js b/test/dialects/matches-test.js new file mode 100644 index 00000000..c385641c --- /dev/null +++ b/test/dialects/matches-test.js @@ -0,0 +1,49 @@ +'use strict'; + +var Harness = require('./support'); +var post = Harness.definePostTable(); +var customerAlias = Harness.defineCustomerAliasTable(); +var sql = require(__dirname + '/../../lib').setDialect('postgres'); + +//Postgres needs the to_tsquery function to use with @@ operator +Harness.test({ + query: post.select(post.star()).where(post.content.match(sql.functions.TO_TSQUERY('hello'))), + pg: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."content" @@ TO_TSQUERY($1))', + string: 'SELECT "post".* FROM "post" WHERE ("post"."content" @@ TO_TSQUERY(\'hello\'))' + }, + params: ['hello'] +}); + + +Harness.test({ + query: post.select(post.star()).where(post.content.match('hello')), + sqlite: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."content" MATCH $1)', + string: 'SELECT "post".* FROM "post" WHERE ("post"."content" MATCH \'hello\')' + }, + mysql: { + text : 'SELECT `post`.* FROM `post` WHERE (MATCH `post`.`content` AGAINST ?)', + string: 'SELECT `post`.* FROM `post` WHERE (MATCH `post`.`content` AGAINST \'hello\')' + }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE (CONTAINS ([post].[content], @1))', + string: 'SELECT [post].* FROM [post] WHERE (CONTAINS ([post].[content], \'hello\'))' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE (INSTR ("post"."content", :1) > 0)', + string: 'SELECT "post".* FROM "post" WHERE (INSTR ("post"."content", \'hello\') > 0)' + }, + params: ['hello'] +}); + +//matches, ordered by best rank first +Harness.test({ + query: post.select(post.id, sql.functions.TS_RANK_CD(post.content, sql.functions.TO_TSQUERY('hello')).as('rank')). + where(post.content.match(sql.functions.TO_TSQUERY('hello'))).order(sql.functions.TS_RANK_CD(post.content, sql.functions.TO_TSQUERY('hello')).descending()), + pg: { + text : 'SELECT "post"."id", TS_RANK_CD("post"."content", TO_TSQUERY($1)) AS "rank" FROM "post" WHERE ("post"."content" @@ TO_TSQUERY($2)) ORDER BY TS_RANK_CD("post"."content", TO_TSQUERY($3)) DESC', + string: 'SELECT "post"."id", TS_RANK_CD("post"."content", TO_TSQUERY(\'hello\')) AS "rank" FROM "post" WHERE ("post"."content" @@ TO_TSQUERY(\'hello\')) ORDER BY TS_RANK_CD("post"."content", TO_TSQUERY(\'hello\')) DESC' + }, + params: ['hello','hello','hello'] +}); diff --git a/test/dialects/namespace-tests.js b/test/dialects/namespace-tests.js index 2ebeb086..5f6b4a56 100644 --- a/test/dialects/namespace-tests.js +++ b/test/dialects/namespace-tests.js @@ -20,6 +20,14 @@ Harness.test({ text : 'SELECT `u`.`name` FROM `user` AS `u`', string: 'SELECT `u`.`name` FROM `user` AS `u`' }, + mssql: { + text : 'SELECT [u].[name] FROM [user] AS [u]', + string: 'SELECT [u].[name] FROM [user] AS [u]' + }, + oracle: { + text : 'SELECT "u"."name" FROM "user" "u"', + string: 'SELECT "u"."name" FROM "user" "u"' + }, params: [] }); @@ -37,6 +45,14 @@ Harness.test({ text : 'SELECT `u`.* FROM `user` AS `u`', string: 'SELECT `u`.* FROM `user` AS `u`' }, + mssql: { + text : 'SELECT [u].* FROM [user] AS [u]', + string: 'SELECT [u].* FROM [user] AS [u]' + }, + oracle: { + text : 'SELECT "u".* FROM "user" "u"', + string: 'SELECT "u".* FROM "user" "u"' + }, params: [] }); @@ -55,6 +71,14 @@ Harness.test({ text : 'SELECT `u`.`name` FROM `user` AS `u` INNER JOIN `post` AS `p` ON ((`u`.`id` = `p`.`userId`) AND (`p`.`id` = ?))', string: 'SELECT `u`.`name` FROM `user` AS `u` INNER JOIN `post` AS `p` ON ((`u`.`id` = `p`.`userId`) AND (`p`.`id` = 3))' }, + mssql: { + text : 'SELECT [u].[name] FROM [user] AS [u] INNER JOIN [post] AS [p] ON (([u].[id] = [p].[userId]) AND ([p].[id] = @1))', + string: 'SELECT [u].[name] FROM [user] AS [u] INNER JOIN [post] AS [p] ON (([u].[id] = [p].[userId]) AND ([p].[id] = 3))' + }, + oracle: { + text : 'SELECT "u"."name" FROM "user" "u" INNER JOIN "post" "p" ON (("u"."id" = "p"."userId") AND ("p"."id" = :1))', + string: 'SELECT "u"."name" FROM "user" "u" INNER JOIN "post" "p" ON (("u"."id" = "p"."userId") AND ("p"."id" = 3))' + }, params: [3] }); @@ -72,6 +96,14 @@ Harness.test({ text : 'SELECT `p`.`content`, `u`.`name` FROM `user` AS `u` INNER JOIN `post` AS `p` ON ((`u`.`id` = `p`.`userId`) AND (`p`.`content` IS NOT NULL))', string: 'SELECT `p`.`content`, `u`.`name` FROM `user` AS `u` INNER JOIN `post` AS `p` ON ((`u`.`id` = `p`.`userId`) AND (`p`.`content` IS NOT NULL))' }, + mssql: { + text : 'SELECT [p].[content], [u].[name] FROM [user] AS [u] INNER JOIN [post] AS [p] ON (([u].[id] = [p].[userId]) AND ([p].[content] IS NOT NULL))', + string: 'SELECT [p].[content], [u].[name] FROM [user] AS [u] INNER JOIN [post] AS [p] ON (([u].[id] = [p].[userId]) AND ([p].[content] IS NOT NULL))' + }, + oracle: { + text : 'SELECT "p"."content", "u"."name" FROM "user" "u" INNER JOIN "post" "p" ON (("u"."id" = "p"."userId") AND ("p"."content" IS NOT NULL))', + string: 'SELECT "p"."content", "u"."name" FROM "user" "u" INNER JOIN "post" "p" ON (("u"."id" = "p"."userId") AND ("p"."content" IS NOT NULL))' + }, params: [] }); @@ -102,5 +134,13 @@ Harness.test({ text : 'SELECT `comment`.`text`, `comment`.`userId` FROM `comment`', string: 'SELECT `comment`.`text`, `comment`.`userId` FROM `comment`' }, + mssql: { + text : 'SELECT [comment].[text], [comment].[userId] FROM [comment]', + string: 'SELECT [comment].[text], [comment].[userId] FROM [comment]' + }, + orcle: { + text : 'SELECT "comment"."text", "comment"."userId" FROM "comment"', + string: 'SELECT "comment"."text", "comment"."userId" FROM "comment"' + }, params: [] }); diff --git a/test/dialects/not-in-clause-tests.js b/test/dialects/not-in-clause-tests.js index b6655e3a..11647fee 100644 --- a/test/dialects/not-in-clause-tests.js +++ b/test/dialects/not-in-clause-tests.js @@ -17,6 +17,14 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (1=1)', string: 'SELECT `post`.* FROM `post` WHERE (1=1)' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE (1=1)', + string: 'SELECT [post].* FROM [post] WHERE (1=1)' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE (1=1)', + string: 'SELECT "post".* FROM "post" WHERE (1=1)' + }, params: [] }); @@ -34,6 +42,14 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (`post`.`id` NOT IN (?))', string: 'SELECT `post`.* FROM `post` WHERE (`post`.`id` NOT IN (1))' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE ([post].[id] NOT IN (@1))', + string: 'SELECT [post].* FROM [post] WHERE ([post].[id] NOT IN (1))' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."id" NOT IN (:1))', + string: 'SELECT "post".* FROM "post" WHERE ("post"."id" NOT IN (1))' + }, params: [1] }); @@ -51,6 +67,14 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IS NOT NULL)', string: 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IS NOT NULL)' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE ([post].[id] IS NOT NULL)', + string: 'SELECT [post].* FROM [post] WHERE ([post].[id] IS NOT NULL)' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."id" IS NOT NULL)', + string: 'SELECT "post".* FROM "post" WHERE ("post"."id" IS NOT NULL)' + }, params: [] }); @@ -68,6 +92,14 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (`post`.`id` NOT IN (?, ?))', string: 'SELECT `post`.* FROM `post` WHERE (`post`.`id` NOT IN (1, 2))' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE ([post].[id] NOT IN (@1, @2))', + string: 'SELECT [post].* FROM [post] WHERE ([post].[id] NOT IN (1, 2))' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."id" NOT IN (:1, :2))', + string: 'SELECT "post".* FROM "post" WHERE ("post"."id" NOT IN (1, 2))' + }, params: [1, 2] }); @@ -85,6 +117,14 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IS NOT NULL)', string: 'SELECT `post`.* FROM `post` WHERE (`post`.`id` IS NOT NULL)' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE ([post].[id] IS NOT NULL)', + string: 'SELECT [post].* FROM [post] WHERE ([post].[id] IS NOT NULL)' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."id" IS NOT NULL)', + string: 'SELECT "post".* FROM "post" WHERE ("post"."id" IS NOT NULL)' + }, params: [] }); @@ -102,6 +142,14 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (NOT (`post`.`id` IN (?, ?) OR `post`.`id` IS NULL))', string: 'SELECT `post`.* FROM `post` WHERE (NOT (`post`.`id` IN (1, 2) OR `post`.`id` IS NULL))' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE (NOT ([post].[id] IN (@1, @2) OR [post].[id] IS NULL))', + string: 'SELECT [post].* FROM [post] WHERE (NOT ([post].[id] IN (1, 2) OR [post].[id] IS NULL))' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE (NOT ("post"."id" IN (:1, :2) OR "post"."id" IS NULL))', + string: 'SELECT "post".* FROM "post" WHERE (NOT ("post"."id" IN (1, 2) OR "post"."id" IS NULL))' + }, params: [1, 2] }); @@ -119,5 +167,13 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (NOT (`post`.`id` IN (?, ?) OR `post`.`id` IS NULL))', string: 'SELECT `post`.* FROM `post` WHERE (NOT (`post`.`id` IN (1, 2) OR `post`.`id` IS NULL))' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE (NOT ([post].[id] IN (@1, @2) OR [post].[id] IS NULL))', + string: 'SELECT [post].* FROM [post] WHERE (NOT ([post].[id] IN (1, 2) OR [post].[id] IS NULL))' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE (NOT ("post"."id" IN (:1, :2) OR "post"."id" IS NULL))', + string: 'SELECT "post".* FROM "post" WHERE (NOT ("post"."id" IN (1, 2) OR "post"."id" IS NULL))' + }, params: [1, 2] }); diff --git a/test/dialects/order-tests.js b/test/dialects/order-tests.js index 297ce99d..a0813d8e 100644 --- a/test/dialects/order-tests.js +++ b/test/dialects/order-tests.js @@ -18,6 +18,14 @@ Harness.test({ text : 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`', string: 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`' }, + mssql: { + text : 'SELECT [post].[content] FROM [post] ORDER BY [post].[content]', + string: 'SELECT [post].[content] FROM [post] ORDER BY [post].[content]' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content"', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content"' + }, params: [] }); @@ -35,6 +43,14 @@ Harness.test({ text : 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`, `post`.`userId` DESC', string: 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`, `post`.`userId` DESC' }, + mssql: { + text : 'SELECT [post].[content] FROM [post] ORDER BY [post].[content], [post].[userId] DESC', + string: 'SELECT [post].[content] FROM [post] ORDER BY [post].[content], [post].[userId] DESC' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content", "post"."userId" DESC', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content", "post"."userId" DESC' + }, params: [] }); @@ -52,6 +68,14 @@ Harness.test({ text : 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`, `post`.`userId` DESC', string: 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`, `post`.`userId` DESC' }, + mssql: { + text : 'SELECT [post].[content] FROM [post] ORDER BY [post].[content], [post].[userId] DESC', + string: 'SELECT [post].[content] FROM [post] ORDER BY [post].[content], [post].[userId] DESC' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content", "post"."userId" DESC', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content", "post"."userId" DESC' + }, params: [] }); @@ -69,6 +93,14 @@ Harness.test({ text : 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`, `post`.`userId` DESC', string: 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`, `post`.`userId` DESC' }, + mssql: { + text : 'SELECT [post].[content] FROM [post] ORDER BY [post].[content], [post].[userId] DESC', + string: 'SELECT [post].[content] FROM [post] ORDER BY [post].[content], [post].[userId] DESC' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content", "post"."userId" DESC', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content", "post"."userId" DESC' + }, params: [] }); @@ -86,6 +118,14 @@ Harness.test({ text : 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`, `post`.`userId` DESC', string: 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`, `post`.`userId` DESC' }, + mssql: { + text : 'SELECT [post].[content] FROM [post] ORDER BY [post].[content], [post].[userId] DESC', + string: 'SELECT [post].[content] FROM [post] ORDER BY [post].[content], [post].[userId] DESC' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content", "post"."userId" DESC', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content", "post"."userId" DESC' + }, params: [] }); @@ -103,6 +143,14 @@ Harness.test({ text : 'SELECT (`post`.`content` IS NULL) FROM `post` ORDER BY (`post`.`content` IS NULL)', string: 'SELECT (`post`.`content` IS NULL) FROM `post` ORDER BY (`post`.`content` IS NULL)' }, + mssql: { + text : 'SELECT ([post].[content] IS NULL) FROM [post] ORDER BY ([post].[content] IS NULL)', + string: 'SELECT ([post].[content] IS NULL) FROM [post] ORDER BY ([post].[content] IS NULL)' + }, + oracle: { + text : 'SELECT ("post"."content" IS NULL) FROM "post" ORDER BY ("post"."content" IS NULL)', + string: 'SELECT ("post"."content" IS NULL) FROM "post" ORDER BY ("post"."content" IS NULL)' + }, params: [] }); @@ -120,6 +168,14 @@ Harness.test({ text : 'SELECT (`post`.`content` IS NULL) FROM `post` ORDER BY (`post`.`content` IS NULL) DESC', string: 'SELECT (`post`.`content` IS NULL) FROM `post` ORDER BY (`post`.`content` IS NULL) DESC' }, + mssql: { + text : 'SELECT ([post].[content] IS NULL) FROM [post] ORDER BY ([post].[content] IS NULL) DESC', + string: 'SELECT ([post].[content] IS NULL) FROM [post] ORDER BY ([post].[content] IS NULL) DESC' + }, + oracle: { + text : 'SELECT ("post"."content" IS NULL) FROM "post" ORDER BY ("post"."content" IS NULL) DESC', + string: 'SELECT ("post"."content" IS NULL) FROM "post" ORDER BY ("post"."content" IS NULL) DESC' + }, params: [] }); @@ -137,6 +193,14 @@ Harness.test({ text : 'SELECT (`post`.`content` IS NULL) FROM `post` ORDER BY (`post`.`content` IS NULL)', string: 'SELECT (`post`.`content` IS NULL) FROM `post` ORDER BY (`post`.`content` IS NULL)' }, + mssql: { + text : 'SELECT ([post].[content] IS NULL) FROM [post] ORDER BY ([post].[content] IS NULL)', + string: 'SELECT ([post].[content] IS NULL) FROM [post] ORDER BY ([post].[content] IS NULL)' + }, + oracle: { + text : 'SELECT ("post"."content" IS NULL) FROM "post" ORDER BY ("post"."content" IS NULL)', + string: 'SELECT ("post"."content" IS NULL) FROM "post" ORDER BY ("post"."content" IS NULL)' + }, params: [] }); @@ -154,6 +218,14 @@ Harness.test({ text : 'SELECT RTRIM(`post`.`content`) FROM `post` ORDER BY RTRIM(`post`.`content`)', string: 'SELECT RTRIM(`post`.`content`) FROM `post` ORDER BY RTRIM(`post`.`content`)' }, + mssql: { + text : 'SELECT RTRIM([post].[content]) FROM [post] ORDER BY RTRIM([post].[content])', + string: 'SELECT RTRIM([post].[content]) FROM [post] ORDER BY RTRIM([post].[content])' + }, + oracle: { + text : 'SELECT RTRIM("post"."content") FROM "post" ORDER BY RTRIM("post"."content")', + string: 'SELECT RTRIM("post"."content") FROM "post" ORDER BY RTRIM("post"."content")' + }, params: [] }); @@ -171,5 +243,123 @@ Harness.test({ text : 'SELECT RTRIM(`post`.`content`) FROM `post` ORDER BY RTRIM(`post`.`content`) DESC', string: 'SELECT RTRIM(`post`.`content`) FROM `post` ORDER BY RTRIM(`post`.`content`) DESC' }, + mssql: { + text : 'SELECT RTRIM([post].[content]) FROM [post] ORDER BY RTRIM([post].[content]) DESC', + string: 'SELECT RTRIM([post].[content]) FROM [post] ORDER BY RTRIM([post].[content]) DESC' + }, + oracle: { + text : 'SELECT RTRIM("post"."content") FROM "post" ORDER BY RTRIM("post"."content") DESC', + string: 'SELECT RTRIM("post"."content") FROM "post" ORDER BY RTRIM("post"."content") DESC' + }, + params: [] +}); + +Harness.test({ + query: post.select(post.content).order(post.content.descending), + pg: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content" DESC NULLS LAST', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content" DESC NULLS LAST', + config: { + nullOrder: "last" + } + }, + sqlite: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content" DESC', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content" DESC' + }, + mysql: { + text : 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content` DESC', + string: 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content` DESC' + }, + mssql: { + text : 'SELECT [post].[content] FROM [post] ORDER BY [post].[content] DESC', + string: 'SELECT [post].[content] FROM [post] ORDER BY [post].[content] DESC' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content" DESC', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content" DESC' + }, + params: [] +}); + +Harness.test({ + query: post.select(post.content).order(post.content), + pg: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content" NULLS LAST', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content" NULLS LAST', + config: { + nullOrder: "last" + } + }, + sqlite: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content"', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content"' + }, + mysql: { + text : 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`', + string: 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`' + }, + mssql: { + text : 'SELECT [post].[content] FROM [post] ORDER BY [post].[content]', + string: 'SELECT [post].[content] FROM [post] ORDER BY [post].[content]' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content"', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content"' + }, params: [] }); + +Harness.test({ + query: post.select(post.content).order(post.content.asc), + pg: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content" NULLS FIRST', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content" NULLS FIRST', + config: { + nullOrder: "first" + } + }, + sqlite: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content"', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content"' + }, + mysql: { + text : 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`', + string: 'SELECT `post`.`content` FROM `post` ORDER BY `post`.`content`' + }, + mssql: { + text : 'SELECT [post].[content] FROM [post] ORDER BY [post].[content]', + string: 'SELECT [post].[content] FROM [post] ORDER BY [post].[content]' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content"', + string: 'SELECT "post"."content" FROM "post" ORDER BY "post"."content"' + }, + params: [] +}); + +Harness.test({ + query: post.select(post.content).order([]), + pg: { + text : 'SELECT "post"."content" FROM "post"', + string: 'SELECT "post"."content" FROM "post"' + }, + sqlite: { + text : 'SELECT "post"."content" FROM "post"', + string: 'SELECT "post"."content" FROM "post"' + }, + mysql: { + text : 'SELECT `post`.`content` FROM `post`', + string: 'SELECT `post`.`content` FROM `post`' + }, + mssql: { + text : 'SELECT [post].[content] FROM [post]', + string: 'SELECT [post].[content] FROM [post]' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post"', + string: 'SELECT "post"."content" FROM "post"' + }, + params: [] +}); + diff --git a/test/dialects/regex-tests.js b/test/dialects/regex-tests.js index afddce99..40dde618 100644 --- a/test/dialects/regex-tests.js +++ b/test/dialects/regex-tests.js @@ -13,6 +13,15 @@ Harness.test({ params: ['age'] }); +Harness.test({ + query: customer.select(customer.metadata.iregex('age')), + pg: { + text : 'SELECT ("customer"."metadata" ~* $1) FROM "customer"', + string: 'SELECT ("customer"."metadata" ~* \'age\') FROM "customer"' + }, + params: ['age'] +}); + Harness.test({ query: customer.select(customer.metadata.notRegex('age')), pg: { @@ -21,3 +30,12 @@ Harness.test({ }, params: ['age'] }); + +Harness.test({ + query: customer.select(customer.metadata.notIregex('age')), + pg: { + text : 'SELECT ("customer"."metadata" !~* $1) FROM "customer"', + string: 'SELECT ("customer"."metadata" !~* \'age\') FROM "customer"' + }, + params: ['age'] +}); diff --git a/test/dialects/replace-tests.js b/test/dialects/replace-tests.js new file mode 100644 index 00000000..72af0e4b --- /dev/null +++ b/test/dialects/replace-tests.js @@ -0,0 +1,1000 @@ +'use strict'; + +var Harness = require('./support'); +var post = Harness.definePostTable(); +var user = Harness.defineUserTable(); +var contentTable = Harness.defineContentTable(); +var customerAliasTable = Harness.defineCustomerAliasTable(); + +var arrayTable = require('../../lib/table').define({ + name: 'arraytest', + columns: ['id', 'numbers'] +}); + +Harness.test({ + query: post.replace(post.content.value('test'), post.userId.value(1)), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("content", "userId") VALUES ($1, $2)', + string: 'REPLACE INTO "post" ("content", "userId") VALUES (\'test\', 1)' + }, + mysql: { + text : 'REPLACE INTO `post` (`content`, `userId`) VALUES (?, ?)', + string: 'REPLACE INTO `post` (`content`, `userId`) VALUES (\'test\', 1)' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 1] +}); + +Harness.test({ + query: post.replace(post.content.value('whoah')), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("content") VALUES ($1)', + string: 'REPLACE INTO "post" ("content") VALUES (\'whoah\')' + }, + mysql: { + text : 'REPLACE INTO `post` (`content`) VALUES (?)', + string: 'REPLACE INTO `post` (`content`) VALUES (\'whoah\')' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['whoah'] +}); + +Harness.test({ + query: post.replace({length: 0}), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("length") VALUES ($1)', + string: 'REPLACE INTO "post" ("length") VALUES (0)' + }, + mysql: { + text : 'REPLACE INTO `post` (`length`) VALUES (?)', + string: 'REPLACE INTO `post` (`length`) VALUES (0)' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [0] +}); + +Harness.test({ + query: post.replace({ + content: 'test', + userId: 2 + }), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("content", "userId") VALUES ($1, $2)', + string: 'REPLACE INTO "post" ("content", "userId") VALUES (\'test\', 2)' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2] +}); + +Harness.test({ + query: post.replace({ + content: post.sql.functions.LOWER('TEST'), + userId: 2 + }), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("content", "userId") VALUES (LOWER($1), $2)', + string: 'REPLACE INTO "post" ("content", "userId") VALUES (LOWER(\'TEST\'), 2)' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['TEST', 2] +}); + +// allow bulk replace +Harness.test({ + query: post.replace([{ + content: 'whoah' + }, { + content: 'hey' + } + ]), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("content") VALUES ($1), ($2)', + string: 'REPLACE INTO "post" ("content") VALUES (\'whoah\'), (\'hey\')' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['whoah', 'hey'] +}); + +Harness.test({ + query: post.replace([{ + content: 'whoah', + userId: 1 + }, { + content: 'hey', + userId: 2 + } + ]), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("content", "userId") VALUES ($1, $2), ($3, $4)', + string: 'REPLACE INTO "post" ("content", "userId") VALUES (\'whoah\', 1), (\'hey\', 2)' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['whoah', 1, 'hey', 2] +}); + +// consistent order +Harness.test({ + query: post.replace([{ + content: 'whoah', + userId: 1 + }, { + userId: 2, + content: 'hey' + } + ]), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("content", "userId") VALUES ($1, $2), ($3, $4)', + string: 'REPLACE INTO "post" ("content", "userId") VALUES (\'whoah\', 1), (\'hey\', 2)' + }, + mysql: { + text : 'REPLACE INTO `post` (`content`, `userId`) VALUES (?, ?), (?, ?)', + string: 'REPLACE INTO `post` (`content`, `userId`) VALUES (\'whoah\', 1), (\'hey\', 2)' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['whoah', 1, 'hey', 2] +}); + +Harness.test({ + query: post.replace({}), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" DEFAULT VALUES', + string: 'REPLACE INTO "post" DEFAULT VALUES' + }, + mysql: { + text : 'REPLACE INTO `post` () VALUES ()', + string: 'REPLACE INTO `post` () VALUES ()' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); + +Harness.test({ + query: post.replace({}).returning('*'), + pg: { + throws: true + }, + sqlite: { + throws: true + }, + mysql: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); + +Harness.test({ + query: post.replace({}).returning(post.star()), + pg: { + throws: true + }, + sqlite: { + throws: true + }, + mysql: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); + +Harness.test({ + query: post.replace({}).returning(post.id), + pg: { + throws: true + }, + sqlite: { + throws: true + }, + mysql: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); + +Harness.test({ + query: post.replace({}).returning(post.id, post.content), + pg: { + throws: true + }, + sqlite: { + throws: true + }, + mysql: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); + +Harness.test({ + query: post.replace({}).returning([post.id, post.content]), + pg: { + throws: true + }, + sqlite: { + throws: true + }, + mysql: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); + +// handle missing columns +Harness.test({ + query: post.replace([{ + content: 'whoah', + userId: 1 + }, { + content: 'hey' + } + ]), + pg: { + throws: true + }, + sqlite: { + text : 'Sqlite requires the same number of columns in each replace row', + throws: true + }, + mysql: { + text : 'REPLACE INTO `post` (`content`, `userId`) VALUES (?, ?), (?, DEFAULT)', + string: 'REPLACE INTO `post` (`content`, `userId`) VALUES (\'whoah\', 1), (\'hey\', DEFAULT)', + params: ['whoah', 1, 'hey'] + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, +}); + +Harness.test({ + query: post.replace([{ + userId: 1 + }, { + content: 'hey', + userId: 2 + } + ]), + pg: { + throws: true + }, + sqlite: { + text : 'Sqlite requires the same number of columns in each replace row', + throws: true + }, + mysql: { + text : 'REPLACE INTO `post` (`userId`, `content`) VALUES (?, DEFAULT), (?, ?)', + string: 'REPLACE INTO `post` (`userId`, `content`) VALUES (1, DEFAULT), (2, \'hey\')', + params: [1, 2, 'hey'] + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, +}); + +Harness.test({ + query: post.replace(post.content, post.userId) + .select('\'test\'', user.id).from(user).where(user.name.like('A%')), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE $1)', + string: 'REPLACE INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE \'A%\')' + }, + mysql: { + text : 'REPLACE INTO `post` (`content`, `userId`) SELECT \'test\', `user`.`id` FROM `user` WHERE (`user`.`name` LIKE ?)', + string: 'REPLACE INTO `post` (`content`, `userId`) SELECT \'test\', `user`.`id` FROM `user` WHERE (`user`.`name` LIKE \'A%\')' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['A%'] +}); + +Harness.test({ + query: post.replace([post.content, post.userId]) + .select('\'test\'', user.id).from(user).where(user.name.like('A%')), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE $1)', + string: 'REPLACE INTO "post" ("content", "userId") SELECT \'test\', "user"."id" FROM "user" WHERE ("user"."name" LIKE \'A%\')' + }, + mysql: { + text : 'REPLACE INTO `post` (`content`, `userId`) SELECT \'test\', `user`.`id` FROM `user` WHERE (`user`.`name` LIKE ?)', + string: 'REPLACE INTO `post` (`content`, `userId`) SELECT \'test\', `user`.`id` FROM `user` WHERE (`user`.`name` LIKE \'A%\')' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['A%'] +}); + +Harness.test({ + query: post.replace(post.userId) + .select(user.id).from(user).where(user.name.like('A%')), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("userId") SELECT "user"."id" FROM "user" WHERE ("user"."name" LIKE $1)', + string: 'REPLACE INTO "post" ("userId") SELECT "user"."id" FROM "user" WHERE ("user"."name" LIKE \'A%\')' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['A%'] +}); + +Harness.test({ + query: post.replace(post.userId) + .select(post.userId).from(user.join(post).on(user.id.equals(post.userId))).where(post.tags.like('A%')), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("userId") SELECT "post"."userId" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId") WHERE ("post"."tags" LIKE $1)', + string: 'REPLACE INTO "post" ("userId") SELECT "post"."userId" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId") WHERE ("post"."tags" LIKE \'A%\')' + }, + mysql: { + text : 'REPLACE INTO `post` (`userId`) SELECT `post`.`userId` FROM `user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`) WHERE (`post`.`tags` LIKE ?)', + string: 'REPLACE INTO `post` (`userId`) SELECT `post`.`userId` FROM `user` INNER JOIN `post` ON (`user`.`id` = `post`.`userId`) WHERE (`post`.`tags` LIKE \'A%\')' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['A%'] +}); + +Harness.test({ + query: post.replace(post.userId).select(user.id).distinct().from(user), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("userId") SELECT DISTINCT "user"."id" FROM "user"', + string: 'REPLACE INTO "post" ("userId") SELECT DISTINCT "user"."id" FROM "user"' + }, + mysql: { + text : 'REPLACE INTO `post` (`userId`) SELECT DISTINCT `user`.`id` FROM `user`', + string: 'REPLACE INTO `post` (`userId`) SELECT DISTINCT `user`.`id` FROM `user`' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); + +// Binary replaces +Harness.test({ + query: post.replace(post.content.value(new Buffer('test')), post.userId.value(2)), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("content", "userId") VALUES ($1, $2)', + string: 'REPLACE INTO "post" ("content", "userId") VALUES (x\'74657374\', 2)' + }, + mysql: { + text : 'REPLACE INTO `post` (`content`, `userId`) VALUES (?, ?)', + string: 'REPLACE INTO `post` (`content`, `userId`) VALUES (x\'74657374\', 2)' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [new Buffer('test'), 2] +}); + +Harness.test({ + query: post.replace({ + content: new Buffer('test'), + userId: 2 + }), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("content", "userId") VALUES ($1, $2)', + string: 'REPLACE INTO "post" ("content", "userId") VALUES (x\'74657374\', 2)' + }, + mysql: { + text : 'REPLACE INTO `post` (`content`, `userId`) VALUES (?, ?)', + string: 'REPLACE INTO `post` (`content`, `userId`) VALUES (x\'74657374\', 2)' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [new Buffer('test'), 2] +}); + +Harness.test({ + query: post.replace([{ + content: new Buffer('whoah') + }, { + content: new Buffer('hey') + } + ]), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("content") VALUES ($1), ($2)', + string: 'REPLACE INTO "post" ("content") VALUES (x\'77686f6168\'), (x\'686579\')' + }, + mysql: { + text : 'REPLACE INTO `post` (`content`) VALUES (?), (?)', + string: 'REPLACE INTO `post` (`content`) VALUES (x\'77686f6168\'), (x\'686579\')' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [new Buffer('whoah'), new Buffer('hey')] +}); + +Harness.test({ + query: post.replace({ + content: 'test', + userId: 2 + }).onDuplicate({ + content: 'testupdate', + }), + pg: { + throws: true + }, + sqlite: { + throws: true + }, + mysql: { + text : 'REPLACE INTO `post` (`content`, `userId`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `post`.`content` = ?', + string: 'REPLACE INTO `post` (`content`, `userId`) VALUES (\'test\', 2) ON DUPLICATE KEY UPDATE `post`.`content` = \'testupdate\'' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2, 'testupdate'] +}); + +Harness.test({ + query: customerAliasTable.replace({ + id : 2, + name : 'test' + }).onConflict({ + columns: ['id'], + update: ['name'] + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [2, 'test'] +}); + +Harness.test({ + query: customerAliasTable.replace({ + id : 2, + name : 'test' + }).orIgnore(), + mysql: { + throws: true + }, + sqlite: { + text : 'REPLACE OR IGNORE INTO "customer" ("id", "name") VALUES ($1, $2)', + string: 'REPLACE OR IGNORE INTO "customer" ("id", "name") VALUES (2, \'test\')' + }, + pg: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [2, 'test'] +}); + +Harness.test({ + query: post.replace({ + content: 'test', + userId: 2 + }).onConflict({ + columns: ['userId'], + update: ['content'] + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2] +}); + +Harness.test({ + query: post.replace({ + content: 'test', + userId: 2 + }).onConflict({ + columns: ['userId','content'], + update: ['content','userId'] + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2] +}); + +Harness.test({ + query: post.replace({ + content: 'test', + userId: 2 + }).onConflict({ + columns: ['userId'], + update: ['content'] + }).where(post.userId.equals(2)), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2, 2] +}); + +Harness.test({ + query: post.replace({ + content: 'test', + userId: 2 + }).onConflict({ + constraint: 'conc_userId', + update: ['content'] + }).where(post.userId.equals(2)), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2, 2] +}); + +Harness.test({ + query: post.replace({ + content: 'test', + userId: 2 + }).onConflict({ + columns: ['userId'], + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2] +}); + +Harness.test({ + query: post.replace({ + content: 'test', + userId: 2 + }).onConflict({ + constraint: 'conc_userId', + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: ['test', 2] +}); + +Harness.test({ + query: contentTable.replace({ + contentId: 20, + text : "something" + }).onConflict({ + columns: ['contentId'], + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [20, "something"] +}); + +Harness.test({ + query: contentTable.replace({ + contentId: 20, + text : "something", + contentPosts : "another thing", + }).onConflict({ + columns: ['contentId'], + update: ['contentPosts'] + }), + mysql: { + throws: true + }, + sqlite: { + throws: true + }, + pg: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [20, "something", "another thing"] +}); + +Harness.test({ + query: post.replace([]), + + mysql: { + text : 'SELECT `post`.* FROM `post` WHERE (1=2)', + string: 'SELECT `post`.* FROM `post` WHERE (1=2)' + }, + params: [] +}); + +Harness.test({ + query: arrayTable.replace(arrayTable.id.value(1), arrayTable.numbers.value([2, 3, 4])), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "arraytest" ("id", "numbers") VALUES ($1, $2)', + string: 'REPLACE INTO "arraytest" ("id", "numbers") VALUES (1, \'[2,3,4]\')' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + } +}); + +Harness.test({ + query: arrayTable.replace(arrayTable.id.value(1), arrayTable.numbers.value(["one", "two", "three"])), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "arraytest" ("id", "numbers") VALUES ($1, $2)', + string: 'REPLACE INTO "arraytest" ("id", "numbers") VALUES (1, \'["one","two","three"]\')' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + } +}); + +Harness.test({ + query: post.replace(post.userId).select(user.id).from(user), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("userId") SELECT "user"."id" FROM "user"', + string: 'REPLACE INTO "post" ("userId") SELECT "user"."id" FROM "user"' + }, + mysql: { + text : 'REPLACE INTO `post` (`userId`) SELECT `user`.`id` FROM `user`', + string: 'REPLACE INTO `post` (`userId`) SELECT `user`.`id` FROM `user`' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); + +Harness.test({ + query: post.replace(post.userId).select(user.id).from(user).onConflict({ + columns: ['userId'], + update: ['content'] + }), + pg: { + throws: true + }, + sqlite: { + throws: true + }, + mysql: { + throws: true + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); + +Harness.test({ + query: post.replace(post.userId).add(user.select(user.id)), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("userId") SELECT "user"."id" FROM "user"', + string: 'REPLACE INTO "post" ("userId") SELECT "user"."id" FROM "user"' + }, + mysql: { + text : 'REPLACE INTO `post` (`userId`) SELECT `user`.`id` FROM `user`', + string: 'REPLACE INTO `post` (`userId`) SELECT `user`.`id` FROM `user`' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); + +Harness.test({ + query: post.replace(post.userId).add(user.select(user.id).from(user)), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("userId") SELECT "user"."id" FROM "user"', + string: 'REPLACE INTO "post" ("userId") SELECT "user"."id" FROM "user"' + }, + mysql: { + text : 'REPLACE INTO `post` (`userId`) SELECT `user`.`id` FROM `user`', + string: 'REPLACE INTO `post` (`userId`) SELECT `user`.`id` FROM `user`' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); + +Harness.test({ + query: post.replace(post.userId).add(user.select(user.id).order(user.id)), + pg: { + throws: true + }, + sqlite: { + text : 'REPLACE INTO "post" ("userId") SELECT "user"."id" FROM "user" ORDER BY "user"."id"', + string: 'REPLACE INTO "post" ("userId") SELECT "user"."id" FROM "user" ORDER BY "user"."id"' + }, + mysql: { + text : 'REPLACE INTO `post` (`userId`) SELECT `user`.`id` FROM `user` ORDER BY `user`.`id`', + string: 'REPLACE INTO `post` (`userId`) SELECT `user`.`id` FROM `user` ORDER BY `user`.`id`' + }, + mssql: { + throws: true + }, + oracle: { + throws: true + }, + params: [] +}); diff --git a/test/dialects/returning-tests.js b/test/dialects/returning-tests.js new file mode 100644 index 00000000..ebbb0b2e --- /dev/null +++ b/test/dialects/returning-tests.js @@ -0,0 +1,20 @@ +var Harness = require('./support'); +var user = Harness.defineUserTable(); + +Harness.test({ + query: user.insert({name: 'joe'}).returning(), + pg: { + text : 'INSERT INTO "user" ("name") VALUES ($1) RETURNING *', + string: 'INSERT INTO "user" ("name") VALUES (\'joe\') RETURNING *' + }, + params: ['joe'] +}); + +Harness.test({ + query: user.insert({name: 'joe'}).returning('id'), + pg: { + text : 'INSERT INTO "user" ("name") VALUES ($1) RETURNING id', + string: 'INSERT INTO "user" ("name") VALUES (\'joe\') RETURNING id' + }, + params: ['joe'] +}); diff --git a/test/dialects/schema-tests.js b/test/dialects/schema-tests.js index a0fca635..11e330da 100644 --- a/test/dialects/schema-tests.js +++ b/test/dialects/schema-tests.js @@ -24,6 +24,14 @@ Harness.test({ text : 'SELECT `staging`.`user`.`id` FROM `staging`.`user`', string: 'SELECT `staging`.`user`.`id` FROM `staging`.`user`' }, + mssql: { + text : 'SELECT [staging].[user].[id] FROM [staging].[user]', + string: 'SELECT [staging].[user].[id] FROM [staging].[user]' + }, + oracle: { + text : 'SELECT "staging"."user"."id" FROM "staging"."user"', + string: 'SELECT "staging"."user"."id" FROM "staging"."user"' + }, params: [] }); @@ -41,6 +49,14 @@ Harness.test({ text : 'SELECT COUNT(`staging`.`user`.`id`) AS `id_count` FROM `staging`.`user`', string: 'SELECT COUNT(`staging`.`user`.`id`) AS `id_count` FROM `staging`.`user`' }, + mssql: { + text : 'SELECT COUNT([staging].[user].[id]) AS [id_count] FROM [staging].[user]', + string: 'SELECT COUNT([staging].[user].[id]) AS [id_count] FROM [staging].[user]' + }, + oracle: { + text : 'SELECT COUNT("staging"."user"."id") "id_count" FROM "staging"."user"', + string: 'SELECT COUNT("staging"."user"."id") "id_count" FROM "staging"."user"' + }, params: [] }); @@ -58,6 +74,14 @@ Harness.test({ text : 'SELECT `staging`.`user`.`id`, `staging`.`user`.`name` FROM `staging`.`user`', string: 'SELECT `staging`.`user`.`id`, `staging`.`user`.`name` FROM `staging`.`user`' }, + mssql: { + text : 'SELECT [staging].[user].[id], [staging].[user].[name] FROM [staging].[user]', + string: 'SELECT [staging].[user].[id], [staging].[user].[name] FROM [staging].[user]' + }, + oracle: { + text : 'SELECT "staging"."user"."id", "staging"."user"."name" FROM "staging"."user"', + string: 'SELECT "staging"."user"."id", "staging"."user"."name" FROM "staging"."user"' + }, params: [] }); @@ -76,6 +100,14 @@ Harness.test({ text : 'SELECT `uws`.`name` FROM `staging`.`user` AS `uws`', string: 'SELECT `uws`.`name` FROM `staging`.`user` AS `uws`' }, + mssql: { + text : 'SELECT [uws].[name] FROM [staging].[user] AS [uws]', + string: 'SELECT [uws].[name] FROM [staging].[user] AS [uws]' + }, + oracle: { + text : 'SELECT "uws"."name" FROM "staging"."user" "uws"', + string: 'SELECT "uws"."name" FROM "staging"."user" "uws"' + }, params: [] }); @@ -99,6 +131,14 @@ Harness.test({ text : 'SELECT `staging`.`user`.`name`, `dev`.`post`.`content` FROM `staging`.`user` INNER JOIN `dev`.`post` ON (`staging`.`user`.`id` = `dev`.`post`.`userId`)', string: 'SELECT `staging`.`user`.`name`, `dev`.`post`.`content` FROM `staging`.`user` INNER JOIN `dev`.`post` ON (`staging`.`user`.`id` = `dev`.`post`.`userId`)' }, + mssql: { + text : 'SELECT [staging].[user].[name], [dev].[post].[content] FROM [staging].[user] INNER JOIN [dev].[post] ON ([staging].[user].[id] = [dev].[post].[userId])', + string: 'SELECT [staging].[user].[name], [dev].[post].[content] FROM [staging].[user] INNER JOIN [dev].[post] ON ([staging].[user].[id] = [dev].[post].[userId])' + }, + oracle: { + text : 'SELECT "staging"."user"."name", "dev"."post"."content" FROM "staging"."user" INNER JOIN "dev"."post" ON ("staging"."user"."id" = "dev"."post"."userId")', + string: 'SELECT "staging"."user"."name", "dev"."post"."content" FROM "staging"."user" INNER JOIN "dev"."post" ON ("staging"."user"."id" = "dev"."post"."userId")' + }, params: [] }); @@ -116,5 +156,13 @@ Harness.test({ text : 'SELECT `uws`.`name`, `dev`.`post`.`content` FROM `staging`.`user` AS `uws` INNER JOIN `dev`.`post` ON (`uws`.`id` = `dev`.`post`.`userId`)', string: 'SELECT `uws`.`name`, `dev`.`post`.`content` FROM `staging`.`user` AS `uws` INNER JOIN `dev`.`post` ON (`uws`.`id` = `dev`.`post`.`userId`)' }, + mssql: { + text : 'SELECT [uws].[name], [dev].[post].[content] FROM [staging].[user] AS [uws] INNER JOIN [dev].[post] ON ([uws].[id] = [dev].[post].[userId])', + string: 'SELECT [uws].[name], [dev].[post].[content] FROM [staging].[user] AS [uws] INNER JOIN [dev].[post] ON ([uws].[id] = [dev].[post].[userId])' + }, + oracle: { + text : 'SELECT "uws"."name", "dev"."post"."content" FROM "staging"."user" "uws" INNER JOIN "dev"."post" ON ("uws"."id" = "dev"."post"."userId")', + string: 'SELECT "uws"."name", "dev"."post"."content" FROM "staging"."user" "uws" INNER JOIN "dev"."post" ON ("uws"."id" = "dev"."post"."userId")' + }, params: [] }); diff --git a/test/dialects/select-tests.js b/test/dialects/select-tests.js index 0809574c..2892c8ae 100644 --- a/test/dialects/select-tests.js +++ b/test/dialects/select-tests.js @@ -2,6 +2,9 @@ var Harness = require('./support'); var post = Harness.definePostTable(); +var user = Harness.defineUserTable(); +var customerAlias = Harness.defineCustomerAliasTable(); +var Sql = require('../../lib'); Harness.test({ query: post.select(post.id).select(post.content), @@ -17,5 +20,442 @@ Harness.test({ text : 'SELECT `post`.`id`, `post`.`content` FROM `post`', string: 'SELECT `post`.`id`, `post`.`content` FROM `post`' }, + mssql: { + text : 'SELECT [post].[id], [post].[content] FROM [post]', + string: 'SELECT [post].[id], [post].[content] FROM [post]' + }, + oracle: { + text : 'SELECT "post"."id", "post"."content" FROM "post"', + string: 'SELECT "post"."id", "post"."content" FROM "post"' + }, + params: [] +}); + +Harness.test({ + query: customerAlias.select(customerAlias.star()), + pg: { + text : 'SELECT "customer"."id" AS "id_alias", "customer"."name" AS "name_alias", "customer"."age" AS "age_alias", "customer"."income" AS "income_alias", "customer"."metadata" AS "metadata_alias" FROM "customer"', + string: 'SELECT "customer"."id" AS "id_alias", "customer"."name" AS "name_alias", "customer"."age" AS "age_alias", "customer"."income" AS "income_alias", "customer"."metadata" AS "metadata_alias" FROM "customer"' + }, + sqlite: { + text : 'SELECT "customer"."id" AS "id_alias", "customer"."name" AS "name_alias", "customer"."age" AS "age_alias", "customer"."income" AS "income_alias", "customer"."metadata" AS "metadata_alias" FROM "customer"', + string: 'SELECT "customer"."id" AS "id_alias", "customer"."name" AS "name_alias", "customer"."age" AS "age_alias", "customer"."income" AS "income_alias", "customer"."metadata" AS "metadata_alias" FROM "customer"' + }, + mysql: { + text : 'SELECT `customer`.`id` AS `id_alias`, `customer`.`name` AS `name_alias`, `customer`.`age` AS `age_alias`, `customer`.`income` AS `income_alias`, `customer`.`metadata` AS `metadata_alias` FROM `customer`', + string: 'SELECT `customer`.`id` AS `id_alias`, `customer`.`name` AS `name_alias`, `customer`.`age` AS `age_alias`, `customer`.`income` AS `income_alias`, `customer`.`metadata` AS `metadata_alias` FROM `customer`' + }, + mssql: { + text : 'SELECT [customer].[id] AS [id_alias], [customer].[name] AS [name_alias], [customer].[age] AS [age_alias], [customer].[income] AS [income_alias], [customer].[metadata] AS [metadata_alias] FROM [customer]', + string: 'SELECT [customer].[id] AS [id_alias], [customer].[name] AS [name_alias], [customer].[age] AS [age_alias], [customer].[income] AS [income_alias], [customer].[metadata] AS [metadata_alias] FROM [customer]' + }, + oracle: { + text : 'SELECT "customer"."id" "id_alias", "customer"."name" "name_alias", "customer"."age" "age_alias", "customer"."income" "income_alias", "customer"."metadata" "metadata_alias" FROM "customer"', + string: 'SELECT "customer"."id" "id_alias", "customer"."name" "name_alias", "customer"."age" "age_alias", "customer"."income" "income_alias", "customer"."metadata" "metadata_alias" FROM "customer"' + }, + params: [] +}); + +// Test that we can generate a SELECT claus without a FROM clause +Harness.test({ + query: Sql.select(), + pg: { + text : 'SELECT ', + string: 'SELECT ' + }, + sqlite: { + text : 'SELECT ', + string: 'SELECT ' + }, + mysql: { + text : 'SELECT ', + string: 'SELECT ' + }, + mssql: { + text : 'SELECT ', + string: 'SELECT ' + }, + oracle: { + text : 'SELECT ', + string: 'SELECT ' + }, + params: [] +}); + +// Test that we can generate a SELECT claus without a FROM clause +Harness.test({ + query: Sql.select("1"), + pg: { + text : 'SELECT 1', + string: 'SELECT 1' + }, + sqlite: { + text : 'SELECT 1', + string: 'SELECT 1' + }, + mysql: { + text : 'SELECT 1', + string: 'SELECT 1' + }, + mssql: { + text : 'SELECT 1', + string: 'SELECT 1' + }, + oracle: { + text : 'SELECT 1', + string: 'SELECT 1' + }, + params: [] +}); + +Harness.test({ + query: Sql.select("1").where("1=1"), + pg: { + text : 'SELECT 1 WHERE (1=1)', + string: 'SELECT 1 WHERE (1=1)' + }, + sqlite: { + text : 'SELECT 1 WHERE (1=1)', + string: 'SELECT 1 WHERE (1=1)' + }, + mysql: { + text : 'SELECT 1 WHERE (1=1)', + string: 'SELECT 1 WHERE (1=1)' + }, + mssql: { + text : 'SELECT 1 WHERE (1=1)', + string: 'SELECT 1 WHERE (1=1)' + }, + oracle: { + text : 'SELECT 1 WHERE (1=1)', + string: 'SELECT 1 WHERE (1=1)' + }, + params: [] +}); + +Harness.test({ + query: Sql.select(post.select(post.id)), + pg: { + text : 'SELECT (SELECT "post"."id" FROM "post")', + string: 'SELECT (SELECT "post"."id" FROM "post")' + }, + sqlite: { + text : 'SELECT (SELECT "post"."id" FROM "post")', + string: 'SELECT (SELECT "post"."id" FROM "post")' + }, + mysql: { + text : 'SELECT (SELECT `post`.`id` FROM `post`)', + string: 'SELECT (SELECT `post`.`id` FROM `post`)' + }, + mssql: { + text : 'SELECT (SELECT [post].[id] FROM [post])', + string: 'SELECT (SELECT [post].[id] FROM [post])' + }, + oracle: { + text : 'SELECT (SELECT "post"."id" FROM "post")', + string: 'SELECT (SELECT "post"."id" FROM "post")' + }, params: [] }); + +Harness.test({ + query: Sql.select(post.select(post.content).plus(post.select(post.content))), + pg: { + text : 'SELECT ((SELECT "post"."content" FROM "post") + (SELECT "post"."content" FROM "post"))', + string: 'SELECT ((SELECT "post"."content" FROM "post") + (SELECT "post"."content" FROM "post"))' + }, + sqlite: { + text : 'SELECT ((SELECT "post"."content" FROM "post") + (SELECT "post"."content" FROM "post"))', + string: 'SELECT ((SELECT "post"."content" FROM "post") + (SELECT "post"."content" FROM "post"))' + }, + mysql: { + text : 'SELECT ((SELECT `post`.`content` FROM `post`) + (SELECT `post`.`content` FROM `post`))', + string: 'SELECT ((SELECT `post`.`content` FROM `post`) + (SELECT `post`.`content` FROM `post`))' + }, + mssql: { + text : 'SELECT ((SELECT [post].[content] FROM [post]) + (SELECT [post].[content] FROM [post]))', + string: 'SELECT ((SELECT [post].[content] FROM [post]) + (SELECT [post].[content] FROM [post]))' + }, + oracle: { + text : 'SELECT ((SELECT "post"."content" FROM "post") + (SELECT "post"."content" FROM "post"))', + string: 'SELECT ((SELECT "post"."content" FROM "post") + (SELECT "post"."content" FROM "post"))' + }, + params: [] +}); + +Harness.test({ + query: post.select(post.id.as('col1')), + pg: { + text : 'SELECT "post"."id" AS "col1" FROM "post"', + string: 'SELECT "post"."id" AS "col1" FROM "post"' + }, + sqlite: { + text : 'SELECT "post"."id" AS "col1" FROM "post"', + string: 'SELECT "post"."id" AS "col1" FROM "post"' + }, + mysql: { + text : 'SELECT `post`.`id` AS `col1` FROM `post`', + string: 'SELECT `post`.`id` AS `col1` FROM `post`' + }, + mssql: { + text : 'SELECT [post].[id] AS [col1] FROM [post]', + string: 'SELECT [post].[id] AS [col1] FROM [post]' + }, + oracle: { + text : 'SELECT "post"."id" "col1" FROM "post"', + string: 'SELECT "post"."id" "col1" FROM "post"' + }, + params: [] +}); + +Harness.test({ + query: post.select(Sql.constant(4)), + pg: { + text : 'SELECT $1 FROM "post"', + string: 'SELECT 4 FROM "post"' + }, + sqlite: { + text : 'SELECT $1 FROM "post"', + string: 'SELECT 4 FROM "post"' + }, + mysql: { + text : 'SELECT ? FROM `post`', + string: 'SELECT 4 FROM `post`' + }, + mssql: { + text : 'SELECT @1 FROM [post]', + string: 'SELECT 4 FROM [post]' + }, + oracle: { + text : 'SELECT :1 FROM "post"', + string: 'SELECT 4 FROM "post"' + }, + params: [4] +}); + +Harness.test({ + query: post.select(post.id,Sql.constant(4)), + pg: { + text : 'SELECT "post"."id", $1 FROM "post"', + string: 'SELECT "post"."id", 4 FROM "post"' + }, + sqlite: { + text : 'SELECT "post"."id", $1 FROM "post"', + string: 'SELECT "post"."id", 4 FROM "post"' + }, + mysql: { + text : 'SELECT `post`.`id`, ? FROM `post`', + string: 'SELECT `post`.`id`, 4 FROM `post`' + }, + mssql: { + text : 'SELECT [post].[id], @1 FROM [post]', + string: 'SELECT [post].[id], 4 FROM [post]' + }, + oracle: { + text : 'SELECT "post"."id", :1 FROM "post"', + string: 'SELECT "post"."id", 4 FROM "post"' + }, + params: [4] +}); + +Harness.test({ + query: post.select(Sql.constant(4).as('col1')), + pg: { + text : 'SELECT $1 AS "col1" FROM "post"', + string: 'SELECT 4 AS "col1" FROM "post"' + }, + sqlite: { + text : 'SELECT $1 AS "col1" FROM "post"', + string: 'SELECT 4 AS "col1" FROM "post"' + }, + mysql: { + text : 'SELECT ? AS `col1` FROM `post`', + string: 'SELECT 4 AS `col1` FROM `post`' + }, + mssql: { + text : 'SELECT @1 AS [col1] FROM [post]', + string: 'SELECT 4 AS [col1] FROM [post]' + }, + oracle: { + text : 'SELECT :1 "col1" FROM "post"', + string: 'SELECT 4 "col1" FROM "post"' + }, + params: [4] +}); + +Harness.test({ + query: post.select(Sql.constant(4).plus(5)), + pg: { + text : 'SELECT ($1 + $2) FROM "post"', + string: 'SELECT (4 + 5) FROM "post"' + }, + sqlite: { + text : 'SELECT ($1 + $2) FROM "post"', + string: 'SELECT (4 + 5) FROM "post"' + }, + mysql: { + text : 'SELECT (? + ?) FROM `post`', + string: 'SELECT (4 + 5) FROM `post`' + }, + mssql: { + text : 'SELECT (@1 + @2) FROM [post]', + string: 'SELECT (4 + 5) FROM [post]' + }, + oracle: { + text : 'SELECT (:1 + :2) FROM "post"', + string: 'SELECT (4 + 5) FROM "post"' + }, + params: [4,5] +}); + +Harness.test({ + query: post.select(Sql.constant(4).plus(5).as('col1')), + pg: { + text : 'SELECT ($1 + $2) AS "col1" FROM "post"', + string: 'SELECT (4 + 5) AS "col1" FROM "post"' + }, + sqlite: { + text : 'SELECT ($1 + $2) AS "col1" FROM "post"', + string: 'SELECT (4 + 5) AS "col1" FROM "post"' + }, + mysql: { + text : 'SELECT (? + ?) AS `col1` FROM `post`', + string: 'SELECT (4 + 5) AS `col1` FROM `post`' + }, + mssql: { + text : 'SELECT (@1 + @2) AS [col1] FROM [post]', + string: 'SELECT (4 + 5) AS [col1] FROM [post]' + }, + oracle: { + text : 'SELECT (:1 + :2) "col1" FROM "post"', + string: 'SELECT (4 + 5) "col1" FROM "post"' + }, + params: [4,5] +}); + +Harness.test({ + query: post.select(Sql.constant(4),Sql.constant("abc"),Sql.constant(true)), + pg: { + text : 'SELECT $1, $2, $3 FROM "post"', + string: 'SELECT 4, \'abc\', TRUE FROM "post"' + }, + sqlite: { + text : 'SELECT $1, $2, $3 FROM "post"', + string: 'SELECT 4, \'abc\', 1 FROM "post"' + }, + mysql: { + text : 'SELECT ?, ?, ? FROM `post`', + string: 'SELECT 4, \'abc\', TRUE FROM `post`' + }, + mssql: { + text : 'SELECT @1, @2, @3 FROM [post]', + string: 'SELECT 4, \'abc\', TRUE FROM [post]' + }, + oracle: { + text : 'SELECT :1, :2, :3 FROM "post"', + string: 'SELECT 4, \'abc\', TRUE FROM "post"' + }, + params: [4,'abc',true] +}); + +Harness.test({ + query: post.select(Sql.constant(1).sum()), + pg: { + text : 'SELECT SUM($1) AS "constant_sum" FROM "post"', + string: 'SELECT SUM(1) AS "constant_sum" FROM "post"' + }, + sqlite: { + text : 'SELECT SUM($1) AS "constant_sum" FROM "post"', + string: 'SELECT SUM(1) AS "constant_sum" FROM "post"' + }, + mysql: { + text : 'SELECT SUM(?) AS `constant_sum` FROM `post`', + string: 'SELECT SUM(1) AS `constant_sum` FROM `post`' + }, + mssql: { + text : 'SELECT SUM(@1) AS [constant_sum] FROM [post]', + string: 'SELECT SUM(1) AS [constant_sum] FROM [post]' + }, + oracle: { + text : 'SELECT SUM(:1) "constant_sum" FROM "post"', + string: 'SELECT SUM(1) "constant_sum" FROM "post"' + }, + params: [1] +}); + +Harness.test({ + query: Sql.select(post.select(post.id).as("column1")), + pg: { + text : 'SELECT (SELECT "post"."id" FROM "post") AS "column1"', + string: 'SELECT (SELECT "post"."id" FROM "post") AS "column1"' + }, + sqlite: { + text : 'SELECT (SELECT "post"."id" FROM "post") AS "column1"', + string: 'SELECT (SELECT "post"."id" FROM "post") AS "column1"' + }, + mysql: { + text : 'SELECT (SELECT `post`.`id` FROM `post`) AS `column1`', + string: 'SELECT (SELECT `post`.`id` FROM `post`) AS `column1`' + }, + mssql: { + text : 'SELECT (SELECT [post].[id] FROM [post]) AS [column1]', + string: 'SELECT (SELECT [post].[id] FROM [post]) AS [column1]' + }, + oracle: { + text : 'SELECT (SELECT "post"."id" FROM "post") "column1"', + string: 'SELECT (SELECT "post"."id" FROM "post") "column1"' + }, + params: [] +}); + +Harness.test({ + query: Sql.select(post.select(post.count()).as("column1")), + pg: { + text : 'SELECT (SELECT COUNT("post".*) AS "post_count" FROM "post") AS "column1"', + string: 'SELECT (SELECT COUNT("post".*) AS "post_count" FROM "post") AS "column1"' + }, + sqlite: { + text : 'SELECT (SELECT COUNT("post".*) AS "post_count" FROM "post") AS "column1"', + string: 'SELECT (SELECT COUNT("post".*) AS "post_count" FROM "post") AS "column1"' + }, + mysql: { + text : 'SELECT (SELECT COUNT(*) AS `post_count` FROM `post`) AS `column1`', + string: 'SELECT (SELECT COUNT(*) AS `post_count` FROM `post`) AS `column1`' + }, + mssql: { + text : 'SELECT (SELECT COUNT(*) AS [post_count] FROM [post]) AS [column1]', + string: 'SELECT (SELECT COUNT(*) AS [post_count] FROM [post]) AS [column1]' + }, + oracle: { + text : 'SELECT (SELECT COUNT(*) "post_count" FROM "post") "column1"', + string: 'SELECT (SELECT COUNT(*) "post_count" FROM "post") "column1"' + }, + params: [] +}); + +Harness.test({ + query: Sql.select(post.select(post.id).as("column1"),user.select(user.id).as("column2")), + pg: { + text : 'SELECT (SELECT "post"."id" FROM "post") AS "column1", (SELECT "user"."id" FROM "user") AS "column2"', + string: 'SELECT (SELECT "post"."id" FROM "post") AS "column1", (SELECT "user"."id" FROM "user") AS "column2"' + }, + sqlite: { + text : 'SELECT (SELECT "post"."id" FROM "post") AS "column1", (SELECT "user"."id" FROM "user") AS "column2"', + string: 'SELECT (SELECT "post"."id" FROM "post") AS "column1", (SELECT "user"."id" FROM "user") AS "column2"' + }, + mysql: { + text : 'SELECT (SELECT `post`.`id` FROM `post`) AS `column1`, (SELECT `user`.`id` FROM `user`) AS `column2`', + string: 'SELECT (SELECT `post`.`id` FROM `post`) AS `column1`, (SELECT `user`.`id` FROM `user`) AS `column2`' + }, + mssql: { + text : 'SELECT (SELECT [post].[id] FROM [post]) AS [column1], (SELECT [user].[id] FROM [user]) AS [column2]', + string: 'SELECT (SELECT [post].[id] FROM [post]) AS [column1], (SELECT [user].[id] FROM [user]) AS [column2]' + }, + oracle: { + text : 'SELECT (SELECT "post"."id" FROM "post") "column1", (SELECT "user"."id" FROM "user") "column2"', + string: 'SELECT (SELECT "post"."id" FROM "post") "column1", (SELECT "user"."id" FROM "user") "column2"' + }, + params: [] +}); + + diff --git a/test/dialects/shortcut-tests.js b/test/dialects/shortcut-tests.js index 62e27574..35c9a90b 100644 --- a/test/dialects/shortcut-tests.js +++ b/test/dialects/shortcut-tests.js @@ -19,6 +19,14 @@ Harness.test({ text : 'SELECT `user`.* FROM `user`', string: 'SELECT `user`.* FROM `user`' }, + mssql: { + text : 'SELECT [user].* FROM [user]', + string: 'SELECT [user].* FROM [user]' + }, + oracle: { + text : 'SELECT "user".* FROM "user"', + string: 'SELECT "user".* FROM "user"' + }, params: [] }); @@ -36,6 +44,14 @@ Harness.test({ text : 'SELECT * FROM `user` WHERE (`user`.`name` = ?)', string: 'SELECT * FROM `user` WHERE (`user`.`name` = 3)' }, + mssql: { + text : 'SELECT * FROM [user] WHERE ([user].[name] = @1)', + string: 'SELECT * FROM [user] WHERE ([user].[name] = 3)' + }, + oracle: { + text : 'SELECT * FROM "user" WHERE ("user"."name" = :1)', + string: 'SELECT * FROM "user" WHERE ("user"."name" = 3)' + }, params: [3] }); @@ -53,6 +69,14 @@ Harness.test({ text : 'SELECT * FROM `user` WHERE ((`user`.`name` = ?) AND (`user`.`id` = ?))', string: 'SELECT * FROM `user` WHERE ((`user`.`name` = 3) AND (`user`.`id` = 1))' }, + mssql: { + text : 'SELECT * FROM [user] WHERE (([user].[name] = @1) AND ([user].[id] = @2))', + string: 'SELECT * FROM [user] WHERE (([user].[name] = 3) AND ([user].[id] = 1))' + }, + oracle: { + text : 'SELECT * FROM "user" WHERE (("user"."name" = :1) AND ("user"."id" = :2))', + string: 'SELECT * FROM "user" WHERE (("user"."name" = 3) AND ("user"."id" = 1))' + }, params: [3, 1] }); @@ -71,6 +95,14 @@ Harness.test({ text : 'SELECT `post`.`content` FROM `post`', string: 'SELECT `post`.`content` FROM `post`' }, + mssql: { + text : 'SELECT [post].[content] FROM [post]', + string: 'SELECT [post].[content] FROM [post]' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post"', + string: 'SELECT "post"."content" FROM "post"' + }, params: [] }); @@ -88,6 +120,14 @@ Harness.test({ text : 'SELECT `post`.`content` FROM `post` WHERE (`post`.`userId` = ?)', string: 'SELECT `post`.`content` FROM `post` WHERE (`post`.`userId` = 1)' }, + mssql: { + text : 'SELECT [post].[content] FROM [post] WHERE ([post].[userId] = @1)', + string: 'SELECT [post].[content] FROM [post] WHERE ([post].[userId] = 1)' + }, + oracle: { + text : 'SELECT "post"."content" FROM "post" WHERE ("post"."userId" = :1)', + string: 'SELECT "post"."content" FROM "post" WHERE ("post"."userId" = 1)' + }, params: [1] }); @@ -109,5 +149,13 @@ Harness.test({ text : 'SELECT * FROM `post` WHERE (((`post`.`content` IS NULL) OR (`post`.`content` = ?)) AND (`post`.`userId` = ?))', string: 'SELECT * FROM `post` WHERE (((`post`.`content` IS NULL) OR (`post`.`content` = \'\')) AND (`post`.`userId` = 1))' }, + mssql: { + text : 'SELECT * FROM [post] WHERE ((([post].[content] IS NULL) OR ([post].[content] = @1)) AND ([post].[userId] = @2))', + string: 'SELECT * FROM [post] WHERE ((([post].[content] IS NULL) OR ([post].[content] = \'\')) AND ([post].[userId] = 1))' + }, + oracle: { + text : 'SELECT * FROM "post" WHERE ((("post"."content" IS NULL) OR ("post"."content" = :1)) AND ("post"."userId" = :2))', + string: 'SELECT * FROM "post" WHERE ((("post"."content" IS NULL) OR ("post"."content" = \'\')) AND ("post"."userId" = 1))' + }, params: ['', 1] }); diff --git a/test/dialects/subfield-tests.js b/test/dialects/subfield-tests.js new file mode 100644 index 00000000..aeaab51d --- /dev/null +++ b/test/dialects/subfield-tests.js @@ -0,0 +1,42 @@ +'use strict'; + +var Harness = require('./support'); +var customer = Harness.defineCustomerCompositeTable(); +var Sql = require('../../lib').setDialect('postgres'); + +Harness.test({ + query: customer.select(customer.info.subfields.age), + pg: { + text : 'SELECT ("customer"."info")."age" FROM "customer"', + string: 'SELECT ("customer"."info")."age" FROM "customer"' + }, + params: [] +}); + + +Harness.test({ + query: customer.select(customer.info.subfields.age.as('years')), + pg: { + text : 'SELECT ("customer"."info")."age" AS "years" FROM "customer"', + string: 'SELECT ("customer"."info")."age" AS "years" FROM "customer"' + }, + params: [] +}); + +Harness.test({ + query: customer.select(customer.id).where(customer.info.subfields.salary.equals(10)), + pg: { + text : 'SELECT "customer"."id" FROM "customer" WHERE (("customer"."info")."salary" = $1)', + string: 'SELECT "customer"."id" FROM "customer" WHERE (("customer"."info")."salary" = 10)' + }, + params: [10] +}); + +Harness.test({ + query: customer.select(customer.info.subfields.name.distinct()), + pg: { + text : 'SELECT DISTINCT(("customer"."info")."name") FROM "customer"', + string: 'SELECT DISTINCT(("customer"."info")."name") FROM "customer"' + }, + params: [] +}); diff --git a/test/dialects/subquery-tests.js b/test/dialects/subquery-tests.js index 5c60c271..05d76f1f 100644 --- a/test/dialects/subquery-tests.js +++ b/test/dialects/subquery-tests.js @@ -3,8 +3,34 @@ var Harness = require('./support'); var customer = Harness.defineCustomerTable(); var user = Harness.defineUserTable(); +var post = Harness.definePostTable(); var Sql = require('../../lib'); +Harness.test({ + query: user.select(user.name).where(user.id.in(post.select(post.userId))), + pg: { + text: 'SELECT "user"."name" FROM "user" WHERE ("user"."id" IN (SELECT "post"."userId" FROM "post"))', + string: 'SELECT "user"."name" FROM "user" WHERE ("user"."id" IN (SELECT "post"."userId" FROM "post"))' + }, + sqlite: { + text: 'SELECT "user"."name" FROM "user" WHERE ("user"."id" IN (SELECT "post"."userId" FROM "post"))', + string: 'SELECT "user"."name" FROM "user" WHERE ("user"."id" IN (SELECT "post"."userId" FROM "post"))' + }, + mysql: { + text: 'SELECT `user`.`name` FROM `user` WHERE (`user`.`id` IN (SELECT `post`.`userId` FROM `post`))', + string: 'SELECT `user`.`name` FROM `user` WHERE (`user`.`id` IN (SELECT `post`.`userId` FROM `post`))' + }, + mssql: { + text: 'SELECT [user].[name] FROM [user] WHERE ([user].[id] IN (SELECT [post].[userId] FROM [post]))', + string: 'SELECT [user].[name] FROM [user] WHERE ([user].[id] IN (SELECT [post].[userId] FROM [post]))', + }, + oracle: { + text: 'SELECT "user"."name" FROM "user" WHERE ("user"."id" IN (SELECT "post"."userId" FROM "post"))', + string: 'SELECT "user"."name" FROM "user" WHERE ("user"."id" IN (SELECT "post"."userId" FROM "post"))' + }, + params: [] +}); + Harness.test({ query: user.name.in( customer.subQuery().select(customer.name).where( @@ -23,6 +49,14 @@ Harness.test({ text : '(`user`.`name` IN (SELECT `customer`.`name` FROM `customer` WHERE (`user`.`name` IN (SELECT `customer`.`name` FROM `customer` WHERE (`user`.`name` LIKE ?)))))', string: '(`user`.`name` IN (SELECT `customer`.`name` FROM `customer` WHERE (`user`.`name` IN (SELECT `customer`.`name` FROM `customer` WHERE (`user`.`name` LIKE \'%HELLO%\')))))' }, + mssql: { + text : '([user].[name] IN (SELECT [customer].[name] FROM [customer] WHERE ([user].[name] IN (SELECT [customer].[name] FROM [customer] WHERE ([user].[name] LIKE @1)))))', + string: '([user].[name] IN (SELECT [customer].[name] FROM [customer] WHERE ([user].[name] IN (SELECT [customer].[name] FROM [customer] WHERE ([user].[name] LIKE \'%HELLO%\')))))' + }, + oracle: { + text : '("user"."name" IN (SELECT "customer"."name" FROM "customer" WHERE ("user"."name" IN (SELECT "customer"."name" FROM "customer" WHERE ("user"."name" LIKE :1)))))', + string: '("user"."name" IN (SELECT "customer"."name" FROM "customer" WHERE ("user"."name" IN (SELECT "customer"."name" FROM "customer" WHERE ("user"."name" LIKE \'%HELLO%\')))))' + }, params: ['%HELLO%'] }); @@ -40,22 +74,68 @@ Harness.test({ text : 'SELECT * FROM (SELECT * FROM `user`)', string: 'SELECT * FROM (SELECT * FROM `user`)' }, + mssql: { + text : 'SELECT * FROM (SELECT * FROM [user])', + string: 'SELECT * FROM (SELECT * FROM [user])' + }, + oracle: { + text : 'SELECT * FROM (SELECT * FROM "user")', + string: 'SELECT * FROM (SELECT * FROM "user")' + }, params: [] }); +// Subquery with a date +Harness.test({ + query: Sql.select('*').from(post.subQuery().where(post.content.equals(new Date('Sat, 01 Jan 2000 00:00:00 GMT')))), + pg: { + text : 'SELECT * FROM (SELECT * FROM "post" WHERE ("post"."content" = $1))', + string: 'SELECT * FROM (SELECT * FROM "post" WHERE ("post"."content" = \'2000-01-01T00:00:00.000Z\'))' + }, + sqlite: { + text : 'SELECT * FROM (SELECT * FROM "post" WHERE ("post"."content" = $1))', + string: 'SELECT * FROM (SELECT * FROM "post" WHERE ("post"."content" = 946684800000))', + config: { + dateTimeMillis: true + } + }, + mysql: { + text : 'SELECT * FROM (SELECT * FROM `post` WHERE (`post`.`content` = ?))', + string: 'SELECT * FROM (SELECT * FROM `post` WHERE (`post`.`content` = \'2000-01-01T00:00:00.000Z\'))' + }, + mssql: { + text : 'SELECT * FROM (SELECT * FROM [post] WHERE ([post].[content] = @1))', + string: 'SELECT * FROM (SELECT * FROM [post] WHERE ([post].[content] = \'2000-01-01T00:00:00.000Z\'))' + }, + oracle: { + text : 'SELECT * FROM (SELECT * FROM "post" WHERE ("post"."content" = :1))', + string: 'SELECT * FROM (SELECT * FROM "post" WHERE ("post"."content" = \'2000-01-01T00:00:00.000Z\'))' + }, + params: [new Date('Sat, 01 Jan 2000 00:00:00 GMT')] +}); + + Harness.test({ query: Sql.select('*').from(customer.subQuery('T1')).from(user.subQuery('T2')), pg: { - text : 'SELECT * FROM (SELECT * FROM "customer") T1 , (SELECT * FROM "user") T2', - string: 'SELECT * FROM (SELECT * FROM "customer") T1 , (SELECT * FROM "user") T2' + text : 'SELECT * FROM (SELECT * FROM "customer") "T1" , (SELECT * FROM "user") "T2"', + string: 'SELECT * FROM (SELECT * FROM "customer") "T1" , (SELECT * FROM "user") "T2"' }, sqlite: { - text : 'SELECT * FROM (SELECT * FROM "customer") T1 , (SELECT * FROM "user") T2', - string: 'SELECT * FROM (SELECT * FROM "customer") T1 , (SELECT * FROM "user") T2' + text : 'SELECT * FROM (SELECT * FROM "customer") "T1" , (SELECT * FROM "user") "T2"', + string: 'SELECT * FROM (SELECT * FROM "customer") "T1" , (SELECT * FROM "user") "T2"' }, mysql: { - text : 'SELECT * FROM (SELECT * FROM `customer`) T1 , (SELECT * FROM `user`) T2', - string: 'SELECT * FROM (SELECT * FROM `customer`) T1 , (SELECT * FROM `user`) T2' + text : 'SELECT * FROM (SELECT * FROM `customer`) `T1` , (SELECT * FROM `user`) `T2`', + string: 'SELECT * FROM (SELECT * FROM `customer`) `T1` , (SELECT * FROM `user`) `T2`' + }, + mssql: { + text : 'SELECT * FROM (SELECT * FROM [customer]) [T1] , (SELECT * FROM [user]) [T2]', + string: 'SELECT * FROM (SELECT * FROM [customer]) [T1] , (SELECT * FROM [user]) [T2]' + }, + oracle: { + text : 'SELECT * FROM (SELECT * FROM "customer") "T1" , (SELECT * FROM "user") "T2"', + string: 'SELECT * FROM (SELECT * FROM "customer") "T1" , (SELECT * FROM "user") "T2"' }, params: [] }); @@ -77,6 +157,14 @@ Harness.test({ text : '(`customer`.`name` BETWEEN (SELECT MIN(`customer`.`name`) FROM `customer`) AND (SELECT MAX(`customer`.`name`) FROM `customer`))', string: '(`customer`.`name` BETWEEN (SELECT MIN(`customer`.`name`) FROM `customer`) AND (SELECT MAX(`customer`.`name`) FROM `customer`))' }, + mssql: { + text : '([customer].[name] BETWEEN (SELECT MIN([customer].[name]) FROM [customer]) AND (SELECT MAX([customer].[name]) FROM [customer]))', + string: '([customer].[name] BETWEEN (SELECT MIN([customer].[name]) FROM [customer]) AND (SELECT MAX([customer].[name]) FROM [customer]))' + }, + oracle: { + text : '("customer"."name" BETWEEN (SELECT MIN("customer"."name") FROM "customer") AND (SELECT MAX("customer"."name") FROM "customer"))', + string: '("customer"."name" BETWEEN (SELECT MIN("customer"."name") FROM "customer") AND (SELECT MAX("customer"."name") FROM "customer"))' + }, params: [] }); @@ -94,5 +182,92 @@ Harness.test({ text : '(EXISTS (SELECT * FROM `user` WHERE (`user`.`name` = `customer`.`name`)))', string: '(EXISTS (SELECT * FROM `user` WHERE (`user`.`name` = `customer`.`name`)))' }, + mssql: { + text : '(EXISTS (SELECT * FROM [user] WHERE ([user].[name] = [customer].[name])))', + string: '(EXISTS (SELECT * FROM [user] WHERE ([user].[name] = [customer].[name])))' + }, + oracle: { + text : '(EXISTS (SELECT * FROM "user" WHERE ("user"."name" = "customer"."name")))', + string: '(EXISTS (SELECT * FROM "user" WHERE ("user"."name" = "customer"."name")))' + }, + params: [] +}); + +var limitUsers = user.subQuery('limit-users').select(user.id, user.name).from(user).order(user.name).limit(10).offset(10); +Harness.test({ + query: Sql.select(limitUsers.name, post.tags).from(limitUsers.leftJoin(post).on(post.userId.equals(limitUsers.id))), + pg: { + text : 'SELECT "limit-users"."name", "post"."tags" FROM (SELECT "user"."id", "user"."name" FROM "user" ORDER BY "user"."name" LIMIT 10 OFFSET 10) "limit-users" LEFT JOIN "post" ON ("post"."userId" = "limit-users"."id")', + string: 'SELECT "limit-users"."name", "post"."tags" FROM (SELECT "user"."id", "user"."name" FROM "user" ORDER BY "user"."name" LIMIT 10 OFFSET 10) "limit-users" LEFT JOIN "post" ON ("post"."userId" = "limit-users"."id")' + }, + sqlite: { + text : 'SELECT "limit-users"."name", "post"."tags" FROM (SELECT "user"."id", "user"."name" FROM "user" ORDER BY "user"."name" LIMIT 10 OFFSET 10) "limit-users" LEFT JOIN "post" ON ("post"."userId" = "limit-users"."id")', + string: 'SELECT "limit-users"."name", "post"."tags" FROM (SELECT "user"."id", "user"."name" FROM "user" ORDER BY "user"."name" LIMIT 10 OFFSET 10) "limit-users" LEFT JOIN "post" ON ("post"."userId" = "limit-users"."id")' + }, + mysql: { + text : 'SELECT `limit-users`.`name`, `post`.`tags` FROM (SELECT `user`.`id`, `user`.`name` FROM `user` ORDER BY `user`.`name` LIMIT 10 OFFSET 10) `limit-users` LEFT JOIN `post` ON (`post`.`userId` = `limit-users`.`id`)', + string: 'SELECT `limit-users`.`name`, `post`.`tags` FROM (SELECT `user`.`id`, `user`.`name` FROM `user` ORDER BY `user`.`name` LIMIT 10 OFFSET 10) `limit-users` LEFT JOIN `post` ON (`post`.`userId` = `limit-users`.`id`)' + }, + mssql: { + text : 'SELECT [limit-users].[name], [post].[tags] FROM (SELECT [user].[id], [user].[name] FROM [user] ORDER BY [user].[name] OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY) [limit-users] LEFT JOIN [post] ON ([post].[userId] = [limit-users].[id])', + string: 'SELECT [limit-users].[name], [post].[tags] FROM (SELECT [user].[id], [user].[name] FROM [user] ORDER BY [user].[name] OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY) [limit-users] LEFT JOIN [post] ON ([post].[userId] = [limit-users].[id])' + }, + oracle: { + text : 'SELECT "limit-users"."name", "post"."tags" FROM (SELECT "user"."id", "user"."name" FROM "user" ORDER BY "user"."name" OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY) "limit-users" LEFT JOIN "post" ON ("post"."userId" = "limit-users"."id")', + string: 'SELECT "limit-users"."name", "post"."tags" FROM (SELECT "user"."id", "user"."name" FROM "user" ORDER BY "user"."name" OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY) "limit-users" LEFT JOIN "post" ON ("post"."userId" = "limit-users"."id")' + }, params: [] }); + +// Top-level subQuery +Harness.test({ + query: Sql.subQuery().select(user.id).from(user), + pg: { + text : '(SELECT "user"."id" FROM "user")', + string: '(SELECT "user"."id" FROM "user")' + }, + sqlite: { + text : '(SELECT "user"."id" FROM "user")', + string: '(SELECT "user"."id" FROM "user")' + }, + mysql: { + text : '(SELECT `user`.`id` FROM `user`)', + string: '(SELECT `user`.`id` FROM `user`)' + }, + mssql: { + text : '(SELECT [user].[id] FROM [user])', + string: '(SELECT [user].[id] FROM [user])' + }, + oracle: { + text : '(SELECT "user"."id" FROM "user")', + string: '(SELECT "user"."id" FROM "user")' + }, + params: [] +}); + +// Top-level subQuery with alias +Harness.test({ + query: Sql.subQuery("x").select(user.id).from(user), + pg: { + text : '(SELECT "user"."id" FROM "user") "x"', + string: '(SELECT "user"."id" FROM "user") "x"' + }, + sqlite: { + text : '(SELECT "user"."id" FROM "user") "x"', + string: '(SELECT "user"."id" FROM "user") "x"' + }, + mysql: { + text : '(SELECT `user`.`id` FROM `user`) `x`', + string: '(SELECT `user`.`id` FROM `user`) `x`' + }, + mssql: { + text : '(SELECT [user].[id] FROM [user]) [x]', + string: '(SELECT [user].[id] FROM [user]) [x]' + }, + oracle: { + text : '(SELECT "user"."id" FROM "user") "x"', + string: '(SELECT "user"."id" FROM "user") "x"' + }, + params: [] +}); + diff --git a/test/dialects/support.js b/test/dialects/support.js index a85fabe7..4a9fa427 100644 --- a/test/dialects/support.js +++ b/test/dialects/support.js @@ -7,7 +7,9 @@ var Table = require('../../lib/table'); var dialects = { pg : require('../../lib/dialect/postgres'), sqlite : require('../../lib/dialect/sqlite'), - mysql : require('../../lib/dialect/mysql') + mysql : require('../../lib/dialect/mysql'), + mssql : require('../../lib/dialect/mssql'), + oracle : require('../../lib/dialect/oracle') }; module.exports = { @@ -25,15 +27,15 @@ module.exports = { // check if this query is expected to throw if (expectedObject.throws) { assert.throws(function() { - new DialectClass().getQuery(expected.query); + new DialectClass(expectedObject.config).getQuery(expected.query); }); } else { // build query for dialect - var compiledQuery = new DialectClass().getQuery(expected.query); + var compiledQuery = new DialectClass(expectedObject.config).getQuery(expected.query); // test result is correct var expectedText = expectedObject.text || expectedObject; - assert.equal(compiledQuery.text, expectedText, 'query result'); + assert.equal(compiledQuery.text, expectedText); // if params are specified then test these are correct var expectedParams = expectedObject.params || expected.params; @@ -49,10 +51,10 @@ module.exports = { // test the toString if (expectedObject.throws) { assert.throws(function() { - new DialectClass().getString(expected.query); + new DialectClass(expectedObject.config).getString(expected.query); }); } else { - var compiledString = new DialectClass().getString(expected.query); + var compiledString = new DialectClass(expectedObject.config).getString(expected.query); // test result is correct assert.equal(compiledString, expectedObject.string); @@ -74,7 +76,7 @@ module.exports = { definePostTable: function() { return Table.define({ name: 'post', - columns: ['id', 'userId', 'content', 'tags'] + columns: ['id', 'userId', 'content', 'tags', 'length'] }); }, @@ -92,11 +94,44 @@ module.exports = { }); }, + // This table defines the customer attributes as a composite field + defineCustomerCompositeTable: function() { + return Table.define({ + name: 'customer', + columns: { + id: {}, + info: {subfields: ['name', 'age', 'salary']} + } + }); + }, + + defineCustomerAliasTable: function() { + return Table.define({ + name: 'customer', + columns: { + id: {property: 'id_alias'}, + name: {property: 'name_alias'}, + age: {property: 'age_alias'}, + income: {property: 'income_alias'}, + metadata: {property: 'metadata_alias'} + } + }); + }, + // This table contains column names that correspond to popularly used variables in formulas. defineVariableTable: function() { return Table.define({ name: 'variable', columns: ['a', 'b', 'c', 'd', 't', 'u', 'v', 'x', 'y', 'z'] }); + }, + +// this table is for testing snakeName related stuff + defineContentTable: function() { + return Table.define({ + name: 'content', + columns: ['content_id', 'text', 'content_posts'], + snakeToCamel: true + }); } }; diff --git a/test/dialects/table-tests.js b/test/dialects/table-tests.js index eae326bc..6740a7c8 100644 --- a/test/dialects/table-tests.js +++ b/test/dialects/table-tests.js @@ -17,6 +17,14 @@ Harness.test({ text : 'SELECT `user`.`id` FROM `user`', string: 'SELECT `user`.`id` FROM `user`' }, + mssql: { + text : 'SELECT [user].[id] FROM [user]', + string: 'SELECT [user].[id] FROM [user]' + }, + oracle: { + text : 'SELECT "user"."id" FROM "user"', + string: 'SELECT "user"."id" FROM "user"' + }, params: [] }); @@ -34,6 +42,14 @@ Harness.test({ text : 'SELECT `user`.`id`, `user`.`name` FROM `user`', string: 'SELECT `user`.`id`, `user`.`name` FROM `user`' }, + mssql: { + text : 'SELECT [user].[id], [user].[name] FROM [user]', + string: 'SELECT [user].[id], [user].[name] FROM [user]' + }, + oracle: { + text : 'SELECT "user"."id", "user"."name" FROM "user"', + string: 'SELECT "user"."id", "user"."name" FROM "user"' + }, params: [] }); @@ -51,6 +67,14 @@ Harness.test({ text : 'SELECT `user`.* FROM `user`', string: 'SELECT `user`.* FROM `user`' }, + mssql: { + text : 'SELECT [user].* FROM [user]', + string: 'SELECT [user].* FROM [user]' + }, + oracle: { + text : 'SELECT "user".* FROM "user"', + string: 'SELECT "user".* FROM "user"' + }, params: [] }); @@ -68,6 +92,10 @@ Harness.test({ text: 'SELECT `user`.`id`, `user`.`name` FROM `user`', string: 'SELECT `user`.`id`, `user`.`name` FROM `user`' }, + oracle: { + text: 'SELECT "user"."id", "user"."name" FROM "user"', + string: 'SELECT "user"."id", "user"."name" FROM "user"' + }, params: [] }); @@ -85,6 +113,10 @@ Harness.test({ text: 'SELECT `user`.`id`, `user`.`name` FROM `user`', string: 'SELECT `user`.`id`, `user`.`name` FROM `user`' }, + oracle: { + text: 'SELECT "user"."id", "user"."name" FROM "user"', + string: 'SELECT "user"."id", "user"."name" FROM "user"' + }, params: [] }); @@ -102,6 +134,10 @@ Harness.test({ text: 'SELECT `user`.`id`, `user`.`name` FROM `user`', string: 'SELECT `user`.`id`, `user`.`name` FROM `user`' }, + oracle: { + text: 'SELECT "user"."id", "user"."name" FROM "user"', + string: 'SELECT "user"."id", "user"."name" FROM "user"' + }, params: [] }); @@ -119,6 +155,10 @@ Harness.test({ text: 'SELECT `user`.*, `user`.`id` AS `foo_id`, `user`.`name` AS `foo_name`, `user`.`id` AS `bar_id`, `user`.`name` AS `bar_name` FROM `user`', string: 'SELECT `user`.*, `user`.`id` AS `foo_id`, `user`.`name` AS `foo_name`, `user`.`id` AS `bar_id`, `user`.`name` AS `bar_name` FROM `user`' }, + oracle: { + text: 'SELECT "user".*, "user"."id" "foo_id", "user"."name" "foo_name", "user"."id" "bar_id", "user"."name" "bar_name" FROM "user"', + string: 'SELECT "user".*, "user"."id" "foo_id", "user"."name" "foo_name", "user"."id" "bar_id", "user"."name" "bar_name" FROM "user"' + }, params: [] }); @@ -136,6 +176,14 @@ Harness.test({ text : 'SELECT `user`.`id` FROM `user` WHERE (`user`.`name` = ?)', string: 'SELECT `user`.`id` FROM `user` WHERE (`user`.`name` = \'foo\')' }, + mssql: { + text : 'SELECT [user].[id] FROM [user] WHERE ([user].[name] = @1)', + string: 'SELECT [user].[id] FROM [user] WHERE ([user].[name] = \'foo\')' + }, + oracle: { + text : 'SELECT "user"."id" FROM "user" WHERE ("user"."name" = :1)', + string: 'SELECT "user"."id" FROM "user" WHERE ("user"."name" = \'foo\')' + }, params: ['foo'] }); @@ -153,6 +201,14 @@ Harness.test({ text : 'SELECT `user`.`id` FROM `user` WHERE ((`user`.`name` = ?) OR (`user`.`name` = ?))', string: 'SELECT `user`.`id` FROM `user` WHERE ((`user`.`name` = \'foo\') OR (`user`.`name` = \'bar\'))' }, + mssql: { + text : 'SELECT [user].[id] FROM [user] WHERE (([user].[name] = @1) OR ([user].[name] = @2))', + string: 'SELECT [user].[id] FROM [user] WHERE (([user].[name] = \'foo\') OR ([user].[name] = \'bar\'))' + }, + oracle: { + text : 'SELECT "user"."id" FROM "user" WHERE (("user"."name" = :1) OR ("user"."name" = :2))', + string: 'SELECT "user"."id" FROM "user" WHERE (("user"."name" = \'foo\') OR ("user"."name" = \'bar\'))' + }, params: ['foo', 'bar'] }); @@ -170,6 +226,14 @@ Harness.test({ text : 'SELECT `user`.`id` FROM `user` WHERE ((`user`.`name` = ?) AND (`user`.`name` = ?))', string: 'SELECT `user`.`id` FROM `user` WHERE ((`user`.`name` = \'foo\') AND (`user`.`name` = \'bar\'))' }, + mssql: { + text : 'SELECT [user].[id] FROM [user] WHERE (([user].[name] = @1) AND ([user].[name] = @2))', + string: 'SELECT [user].[id] FROM [user] WHERE (([user].[name] = \'foo\') AND ([user].[name] = \'bar\'))' + }, + oracle: { + text : 'SELECT "user"."id" FROM "user" WHERE (("user"."name" = :1) AND ("user"."name" = :2))', + string: 'SELECT "user"."id" FROM "user" WHERE (("user"."name" = \'foo\') AND ("user"."name" = \'bar\'))' + }, params: ['foo', 'bar'] }); @@ -187,6 +251,14 @@ Harness.test({ text : 'SELECT `user`.`id` FROM `user` WHERE ((`user`.`name` = ?) OR (`user`.`name` = ?))', string: 'SELECT `user`.`id` FROM `user` WHERE ((`user`.`name` = \'foo\') OR (`user`.`name` = \'bar\'))' }, + mssql: { + text : 'SELECT [user].[id] FROM [user] WHERE (([user].[name] = @1) OR ([user].[name] = @2))', + string: 'SELECT [user].[id] FROM [user] WHERE (([user].[name] = \'foo\') OR ([user].[name] = \'bar\'))' + }, + oracle: { + text : 'SELECT "user"."id" FROM "user" WHERE (("user"."name" = :1) OR ("user"."name" = :2))', + string: 'SELECT "user"."id" FROM "user" WHERE (("user"."name" = \'foo\') OR ("user"."name" = \'bar\'))' + }, params: ['foo', 'bar'] }); @@ -204,6 +276,14 @@ Harness.test({ text : 'SELECT `user`.`id` FROM `user` WHERE (((`user`.`name` = ?) OR (`user`.`name` = ?)) AND (`user`.`name` = ?))', string: 'SELECT `user`.`id` FROM `user` WHERE (((`user`.`name` = \'foo\') OR (`user`.`name` = \'baz\')) AND (`user`.`name` = \'bar\'))' }, + mssql: { + text : 'SELECT [user].[id] FROM [user] WHERE ((([user].[name] = @1) OR ([user].[name] = @2)) AND ([user].[name] = @3))', + string: 'SELECT [user].[id] FROM [user] WHERE ((([user].[name] = \'foo\') OR ([user].[name] = \'baz\')) AND ([user].[name] = \'bar\'))' + }, + oracle: { + text : 'SELECT "user"."id" FROM "user" WHERE ((("user"."name" = :1) OR ("user"."name" = :2)) AND ("user"."name" = :3))', + string: 'SELECT "user"."id" FROM "user" WHERE ((("user"."name" = \'foo\') OR ("user"."name" = \'baz\')) AND ("user"."name" = \'bar\'))' + }, params: ['foo', 'baz', 'bar'] }); @@ -221,6 +301,14 @@ Harness.test({ text : 'SELECT `user`.`id` FROM `user` WHERE (`user`.`name` IN (?, ?))', string: 'SELECT `user`.`id` FROM `user` WHERE (`user`.`name` IN (\'foo\', \'bar\'))' }, + mssql: { + text : 'SELECT [user].[id] FROM [user] WHERE ([user].[name] IN (@1, @2))', + string: 'SELECT [user].[id] FROM [user] WHERE ([user].[name] IN (\'foo\', \'bar\'))' + }, + oracle: { + text : 'SELECT "user"."id" FROM "user" WHERE ("user"."name" IN (:1, :2))', + string: 'SELECT "user"."id" FROM "user" WHERE ("user"."name" IN (\'foo\', \'bar\'))' + }, params: ['foo', 'bar'] }); @@ -238,6 +326,14 @@ Harness.test({ text : 'SELECT `user`.`id` FROM `user` WHERE ((`user`.`name` IN (?, ?)) AND (`user`.`id` = ?))', string: 'SELECT `user`.`id` FROM `user` WHERE ((`user`.`name` IN (\'foo\', \'bar\')) AND (`user`.`id` = 1))' }, + mssql: { + text : 'SELECT [user].[id] FROM [user] WHERE (([user].[name] IN (@1, @2)) AND ([user].[id] = @3))', + string: 'SELECT [user].[id] FROM [user] WHERE (([user].[name] IN (\'foo\', \'bar\')) AND ([user].[id] = 1))' + }, + oracle: { + text : 'SELECT "user"."id" FROM "user" WHERE (("user"."name" IN (:1, :2)) AND ("user"."id" = :3))', + string: 'SELECT "user"."id" FROM "user" WHERE (("user"."name" IN (\'foo\', \'bar\')) AND ("user"."id" = 1))' + }, params: ['foo', 'bar', 1] }); @@ -255,6 +351,14 @@ Harness.test({ text : 'SELECT `user`.`id`, `user`.`name` FROM `user`', string: 'SELECT `user`.`id`, `user`.`name` FROM `user`' }, + mssql: { + text : 'SELECT [user].[id], [user].[name] FROM [user]', + string: 'SELECT [user].[id], [user].[name] FROM [user]' + }, + oracle: { + text : 'SELECT "user"."id", "user"."name" FROM "user"', + string: 'SELECT "user"."id", "user"."name" FROM "user"' + }, params: [] }); @@ -279,6 +383,14 @@ Harness.test({ text : 'SELECT `user`.`id` FROM `user` WHERE (((`user`.`name` = ?) AND (`user`.`id` = ?)) OR ((`user`.`name` = ?) AND (`user`.`id` = ?)))', string: 'SELECT `user`.`id` FROM `user` WHERE (((`user`.`name` = \'boom\') AND (`user`.`id` = 1)) OR ((`user`.`name` = \'bang\') AND (`user`.`id` = 2)))' }, + mssql: { + text : 'SELECT [user].[id] FROM [user] WHERE ((([user].[name] = @1) AND ([user].[id] = @2)) OR (([user].[name] = @3) AND ([user].[id] = @4)))', + string: 'SELECT [user].[id] FROM [user] WHERE ((([user].[name] = \'boom\') AND ([user].[id] = 1)) OR (([user].[name] = \'bang\') AND ([user].[id] = 2)))' + }, + oracle: { + text : 'SELECT "user"."id" FROM "user" WHERE ((("user"."name" = :1) AND ("user"."id" = :2)) OR (("user"."name" = :3) AND ("user"."id" = :4)))', + string: 'SELECT "user"."id" FROM "user" WHERE ((("user"."name" = \'boom\') AND ("user"."id" = 1)) OR (("user"."name" = \'bang\') AND ("user"."id" = 2)))' + }, params: ['boom', 1, 'bang', 2] }); @@ -296,6 +408,14 @@ Harness.test({ text : 'SELECT `user`.`name` AS `user name`, `user`.`id` AS `user id` FROM `user`', string: 'SELECT `user`.`name` AS `user name`, `user`.`id` AS `user id` FROM `user`' }, + mssql: { + text : 'SELECT [user].[name] AS [user name], [user].[id] AS [user id] FROM [user]', + string: 'SELECT [user].[name] AS [user name], [user].[id] AS [user id] FROM [user]' + }, + oracle: { + text : 'SELECT "user"."name" "user name", "user"."id" "user id" FROM "user"', + string: 'SELECT "user"."name" "user name", "user"."id" "user id" FROM "user"' + }, params: [] }); @@ -313,6 +433,14 @@ Harness.test({ text : 'SELECT `user`.`name` AS `user name` FROM `user` WHERE (`user`.`name` = ?)', string: 'SELECT `user`.`name` AS `user name` FROM `user` WHERE (`user`.`name` = \'brian\')' }, + mssql: { + text : 'SELECT [user].[name] AS [user name] FROM [user] WHERE ([user].[name] = @1)', + string: 'SELECT [user].[name] AS [user name] FROM [user] WHERE ([user].[name] = \'brian\')' + }, + oracle: { + text : 'SELECT "user"."name" "user name" FROM "user" WHERE ("user"."name" = :1)', + string: 'SELECT "user"."name" "user name" FROM "user" WHERE ("user"."name" = \'brian\')' + }, params: ['brian'] }); @@ -330,6 +458,14 @@ Harness.test({ text : 'SELECT `user`.`name` FROM `user` WHERE (`user`.`name` = ?)', string: 'SELECT `user`.`name` FROM `user` WHERE (`user`.`name` = \'brian\')' }, + mssql: { + text : 'SELECT [user].[name] FROM [user] WHERE ([user].[name] = @1)', + string: 'SELECT [user].[name] FROM [user] WHERE ([user].[name] = \'brian\')' + }, + oracle: { + text : 'SELECT "user"."name" FROM "user" WHERE ("user"."name" = :1)', + string: 'SELECT "user"."name" FROM "user" WHERE ("user"."name" = \'brian\')' + }, params: ['brian'] }); @@ -347,6 +483,14 @@ Harness.test({ text : 'SELECT name FROM user WHERE (name <> NULL)', string: 'SELECT name FROM user WHERE (name <> NULL)' }, + mssql: { + text : 'SELECT name FROM user WHERE (name <> NULL)', + string: 'SELECT name FROM user WHERE (name <> NULL)' + }, + oracle: { + text : 'SELECT name FROM user WHERE (name <> NULL)', + string: 'SELECT name FROM user WHERE (name <> NULL)' + }, params: [] }); @@ -364,6 +508,14 @@ Harness.test({ text : 'SELECT name,id FROM user WHERE (name <> NULL)', string: 'SELECT name,id FROM user WHERE (name <> NULL)' }, + mssql: { + text : 'SELECT name,id FROM user WHERE (name <> NULL)', + string: 'SELECT name,id FROM user WHERE (name <> NULL)' + }, + oracle: { + text : 'SELECT name,id FROM user WHERE (name <> NULL)', + string: 'SELECT name,id FROM user WHERE (name <> NULL)' + }, params: [] }); @@ -381,6 +533,14 @@ Harness.test({ text : 'SELECT name, id FROM user WHERE (name <> NULL)', string: 'SELECT name, id FROM user WHERE (name <> NULL)' }, + mssql: { + text : 'SELECT name, id FROM user WHERE (name <> NULL)', + string: 'SELECT name, id FROM user WHERE (name <> NULL)' + }, + oracle: { + text : 'SELECT name, id FROM user WHERE (name <> NULL)', + string: 'SELECT name, id FROM user WHERE (name <> NULL)' + }, params: [] }); @@ -398,6 +558,14 @@ Harness.test({ text : 'SELECT name, id FROM user WHERE ((name <> NULL) AND (id <> NULL))', string: 'SELECT name, id FROM user WHERE ((name <> NULL) AND (id <> NULL))' }, + mssql: { + text : 'SELECT name, id FROM user WHERE ((name <> NULL) AND (id <> NULL))', + string: 'SELECT name, id FROM user WHERE ((name <> NULL) AND (id <> NULL))' + }, + oracle: { + text : 'SELECT name, id FROM user WHERE ((name <> NULL) AND (id <> NULL))', + string: 'SELECT name, id FROM user WHERE ((name <> NULL) AND (id <> NULL))' + }, params: [] }); @@ -417,6 +585,14 @@ Harness.test({ text : 'SELECT name FROM user WHERE (`user`.`name` = ?)', string: 'SELECT name FROM user WHERE (`user`.`name` = \'brian\')' }, + mssql: { + text : 'SELECT name FROM user WHERE ([user].[name] = @1)', + string: 'SELECT name FROM user WHERE ([user].[name] = \'brian\')' + }, + oracle: { + text : 'SELECT name FROM user WHERE ("user"."name" = :1)', + string: 'SELECT name FROM user WHERE ("user"."name" = \'brian\')' + }, params: ['brian'] }); @@ -437,6 +613,14 @@ Harness.test({ text : 'SELECT name FROM user WHERE ((`user`.`name` = ?) AND (`user`.`id` = ?))', string: 'SELECT name FROM user WHERE ((`user`.`name` = \'brian\') AND (`user`.`id` = 1))' }, + mssql: { + text : 'SELECT name FROM user WHERE (([user].[name] = @1) AND ([user].[id] = @2))', + string: 'SELECT name FROM user WHERE (([user].[name] = \'brian\') AND ([user].[id] = 1))' + }, + oracle: { + text : 'SELECT name FROM user WHERE (("user"."name" = :1) AND ("user"."id" = :2))', + string: 'SELECT name FROM user WHERE (("user"."name" = \'brian\') AND ("user"."id" = 1))' + }, params: ['brian', 1] }); @@ -454,6 +638,14 @@ Harness.test({ text : 'SELECT `user`.`name` AS `quote"quote"tick``tick``` FROM `user`', string: 'SELECT `user`.`name` AS `quote"quote"tick``tick``` FROM `user`' }, + mssql: { + text : 'SELECT [user].[name] AS [quote"quote"tick`tick`] FROM [user]', + string: 'SELECT [user].[name] AS [quote"quote"tick`tick`] FROM [user]' + }, + oracle: { + text : 'SELECT "user"."name" "quote""quote""tick`tick`" FROM "user"', + string: 'SELECT "user"."name" "quote""quote""tick`tick`" FROM "user"' + }, params: [] }); @@ -471,5 +663,13 @@ Harness.test({ text : 'SELECT `user`.* FROM `user` WHERE (`user`.`id` IN (SELECT `user`.`id` FROM `user`))', string: 'SELECT `user`.* FROM `user` WHERE (`user`.`id` IN (SELECT `user`.`id` FROM `user`))' }, + mssql: { + text : 'SELECT [user].* FROM [user] WHERE ([user].[id] IN (SELECT [user].[id] FROM [user]))', + string: 'SELECT [user].* FROM [user] WHERE ([user].[id] IN (SELECT [user].[id] FROM [user]))' + }, + oracle: { + text : 'SELECT "user".* FROM "user" WHERE ("user"."id" IN (SELECT "user"."id" FROM "user"))', + string: 'SELECT "user".* FROM "user" WHERE ("user"."id" IN (SELECT "user"."id" FROM "user"))' + }, params: [] }); diff --git a/test/dialects/ternary-clause-tests.js b/test/dialects/ternary-clause-tests.js index 20ba7c38..04832fbc 100644 --- a/test/dialects/ternary-clause-tests.js +++ b/test/dialects/ternary-clause-tests.js @@ -18,6 +18,14 @@ Harness.test({ text : 'SELECT `customer`.* FROM `customer` WHERE (`customer`.`age` BETWEEN ? AND ?)', string: 'SELECT `customer`.* FROM `customer` WHERE (`customer`.`age` BETWEEN 18 AND 25)' }, + mssql: { + text : 'SELECT [customer].* FROM [customer] WHERE ([customer].[age] BETWEEN @1 AND @2)', + string: 'SELECT [customer].* FROM [customer] WHERE ([customer].[age] BETWEEN 18 AND 25)' + }, + oracle: { + text : 'SELECT "customer".* FROM "customer" WHERE ("customer"."age" BETWEEN :1 AND :2)', + string: 'SELECT "customer".* FROM "customer" WHERE ("customer"."age" BETWEEN 18 AND 25)' + }, params: [18, 25] }); @@ -35,5 +43,13 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (`post`.`userId` BETWEEN (SELECT MIN(`customer`.`id`) AS `id_min` FROM `customer`) AND (SELECT MAX(`customer`.`id`) AS `id_max` FROM `customer`))', string: 'SELECT `post`.* FROM `post` WHERE (`post`.`userId` BETWEEN (SELECT MIN(`customer`.`id`) AS `id_min` FROM `customer`) AND (SELECT MAX(`customer`.`id`) AS `id_max` FROM `customer`))' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE ([post].[userId] BETWEEN (SELECT MIN([customer].[id]) AS [id_min] FROM [customer]) AND (SELECT MAX([customer].[id]) AS [id_max] FROM [customer]))', + string: 'SELECT [post].* FROM [post] WHERE ([post].[userId] BETWEEN (SELECT MIN([customer].[id]) AS [id_min] FROM [customer]) AND (SELECT MAX([customer].[id]) AS [id_max] FROM [customer]))' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."userId" BETWEEN (SELECT MIN("customer"."id") "id_min" FROM "customer") AND (SELECT MAX("customer"."id") "id_max" FROM "customer"))', + string: 'SELECT "post".* FROM "post" WHERE ("post"."userId" BETWEEN (SELECT MIN("customer"."id") "id_min" FROM "customer") AND (SELECT MAX("customer"."id") "id_max" FROM "customer"))' + }, params: [] }); diff --git a/test/dialects/tostring-tests.js b/test/dialects/tostring-tests.js index d5e56cc8..53d413e8 100644 --- a/test/dialects/tostring-tests.js +++ b/test/dialects/tostring-tests.js @@ -19,6 +19,14 @@ Harness.test({ text : '(`post`.`content` = ?)', string: '(`post`.`content` = NULL)' }, + mssql: { + text : '([post].[content] = @1)', + string: '([post].[content] = NULL)' + }, + oracle: { + text : '("post"."content" = :1)', + string: '("post"."content" = NULL)' + }, params: [null] }); @@ -37,6 +45,14 @@ Harness.test({ text : '(`post`.`content` = ?)', string: '(`post`.`content` = 3.14)' }, + mssql: { + text : '([post].[content] = @1)', + string: '([post].[content] = 3.14)' + }, + oracle: { + text : '("post"."content" = :1)', + string: '("post"."content" = 3.14)' + }, params: [3.14] }); @@ -55,6 +71,14 @@ Harness.test({ text : '(`post`.`content` = ?)', string: '(`post`.`content` = \'hello\'\'\')' }, + mssql: { + text : '([post].[content] = @1)', + string: '([post].[content] = \'hello\'\'\')' + }, + oracle: { + text : '("post"."content" = :1)', + string: '("post"."content" = \'hello\'\'\')' + }, params: ['hello\''] }); @@ -73,6 +97,14 @@ Harness.test({ text : '(`post`.`content` = (?, ?, ?))', string: '(`post`.`content` = (1, \'2\', NULL))' }, + mssql: { + text : 'SQL Server does not support arrays.', + throws: true + }, + oracle: { + text : 'SQL Server does not support arrays.', + throws: true + }, params: [1, '2', null] }); @@ -91,6 +123,43 @@ Harness.test({ text : '(`post`.`content` = ?)', string: '(`post`.`content` = \'2000-01-01T00:00:00.000Z\')' }, + mssql: { + text : '([post].[content] = @1)', + string: '([post].[content] = \'2000-01-01T00:00:00.000Z\')' + }, + oracle: { + text : '("post"."content" = :1)', + string: '("post"."content" = \'2000-01-01T00:00:00.000Z\')' + }, + params: [new Date('Sat, 01 Jan 2000 00:00:00 GMT')] +}); + +// Date to milliseconds +Harness.test({ + query: post.content.equals(new Date('Sat, 01 Jan 2000 00:00:00 GMT')), + pg: { + text : '("post"."content" = $1)', + string: '("post"."content" = \'2000-01-01T00:00:00.000Z\')' + }, + sqlite: { + text : '("post"."content" = $1)', + string: '("post"."content" = 946684800000)', + config: { + dateTimeMillis: true + } + }, + mysql: { + text : '(`post`.`content` = ?)', + string: '(`post`.`content` = \'2000-01-01T00:00:00.000Z\')' + }, + mssql: { + text : '([post].[content] = @1)', + string: '([post].[content] = \'2000-01-01T00:00:00.000Z\')' + }, + oracle: { + text : '("post"."content" = :1)', + string: '("post"."content" = \'2000-01-01T00:00:00.000Z\')' + }, params: [new Date('Sat, 01 Jan 2000 00:00:00 GMT')] }); @@ -115,6 +184,14 @@ Harness.test({ text : '(`post`.`content` = ?)', string: '(`post`.`content` = \'secretMessage\')' }, + mssql: { + text : '([post].[content] = @1)', + string: '([post].[content] = \'secretMessage\')' + }, + oracle: { + text : '("post"."content" = :1)', + string: '("post"."content" = \'secretMessage\')' + }, params: [customObject] }); diff --git a/test/dialects/truncate-table-tests.js b/test/dialects/truncate-table-tests.js new file mode 100644 index 00000000..cfdb04da --- /dev/null +++ b/test/dialects/truncate-table-tests.js @@ -0,0 +1,29 @@ +'use strict'; + +var Harness = require('./support'); +var post = Harness.definePostTable(); + +Harness.test({ + query: post.truncate(), + pg: { + text : 'TRUNCATE TABLE "post"', + string: 'TRUNCATE TABLE "post"' + }, + sqlite: { + text : 'DELETE FROM "post"', + string: 'DELETE FROM "post"' + }, + mysql: { + text : 'TRUNCATE TABLE `post`', + string: 'TRUNCATE TABLE `post`' + }, + mssql: { + text : 'TRUNCATE TABLE [post]', + string: 'TRUNCATE TABLE [post]' + }, + oracle: { + text : 'TRUNCATE TABLE "post"', + string: 'TRUNCATE TABLE "post"' + }, + params: [] +}); diff --git a/test/dialects/unary-clause-tests.js b/test/dialects/unary-clause-tests.js index e7f6e3bd..875de382 100644 --- a/test/dialects/unary-clause-tests.js +++ b/test/dialects/unary-clause-tests.js @@ -18,6 +18,14 @@ Harness.test({ text : 'SELECT `customer`.* FROM `customer` WHERE (`customer`.`age` IS NOT NULL)', string: 'SELECT `customer`.* FROM `customer` WHERE (`customer`.`age` IS NOT NULL)' }, + mssql: { + text : 'SELECT [customer].* FROM [customer] WHERE ([customer].[age] IS NOT NULL)', + string: 'SELECT [customer].* FROM [customer] WHERE ([customer].[age] IS NOT NULL)' + }, + oracle: { + text : 'SELECT "customer".* FROM "customer" WHERE ("customer"."age" IS NOT NULL)', + string: 'SELECT "customer".* FROM "customer" WHERE ("customer"."age" IS NOT NULL)' + }, params: [] }); @@ -35,5 +43,13 @@ Harness.test({ text : 'SELECT `post`.* FROM `post` WHERE (`post`.`userId` IN (SELECT `customer`.`id` FROM `customer` WHERE (`customer`.`age` IS NULL)))', string: 'SELECT `post`.* FROM `post` WHERE (`post`.`userId` IN (SELECT `customer`.`id` FROM `customer` WHERE (`customer`.`age` IS NULL)))' }, + mssql: { + text : 'SELECT [post].* FROM [post] WHERE ([post].[userId] IN (SELECT [customer].[id] FROM [customer] WHERE ([customer].[age] IS NULL)))', + string: 'SELECT [post].* FROM [post] WHERE ([post].[userId] IN (SELECT [customer].[id] FROM [customer] WHERE ([customer].[age] IS NULL)))' + }, + oracle: { + text : 'SELECT "post".* FROM "post" WHERE ("post"."userId" IN (SELECT "customer"."id" FROM "customer" WHERE ("customer"."age" IS NULL)))', + string: 'SELECT "post".* FROM "post" WHERE ("post"."userId" IN (SELECT "customer"."id" FROM "customer" WHERE ("customer"."age" IS NULL)))' + }, params: [] }); diff --git a/test/dialects/update-tests.js b/test/dialects/update-tests.js index 1553e7a5..eb3d0b3e 100644 --- a/test/dialects/update-tests.js +++ b/test/dialects/update-tests.js @@ -3,6 +3,7 @@ var Harness = require('./support'); var post = Harness.definePostTable(); var user = Harness.defineUserTable(); +var variable = Harness.defineVariableTable(); Harness.test({ query: post.update({ @@ -20,6 +21,14 @@ Harness.test({ text : 'UPDATE `post` SET `content` = ?', string: 'UPDATE `post` SET `content` = \'test\'' }, + mssql: { + text : 'UPDATE [post] SET [content] = @1', + string: 'UPDATE [post] SET [content] = \'test\'' + }, + oracle: { + text : 'UPDATE "post" SET "content" = :1', + string: 'UPDATE "post" SET "content" = \'test\'' + }, params: ['test'] }); @@ -40,6 +49,14 @@ Harness.test({ text : 'UPDATE `post` SET `content` = ?, `userId` = ?', string: 'UPDATE `post` SET `content` = \'test\', `userId` = 3' }, + mssql: { + text : 'UPDATE [post] SET [content] = @1, [userId] = @2', + string: 'UPDATE [post] SET [content] = \'test\', [userId] = 3' + }, + oracle: { + text : 'UPDATE "post" SET "content" = :1, "userId" = :2', + string: 'UPDATE "post" SET "content" = \'test\', "userId" = 3' + }, params: ['test', 3] }); @@ -60,6 +77,14 @@ Harness.test({ text : 'UPDATE `post` SET `content` = ?, `userId` = ?', string: 'UPDATE `post` SET `content` = NULL, `userId` = 3' }, + mssql: { + text : 'UPDATE [post] SET [content] = @1, [userId] = @2', + string: 'UPDATE [post] SET [content] = NULL, [userId] = 3' + }, + oracle: { + text : 'UPDATE "post" SET "content" = :1, "userId" = :2', + string: 'UPDATE "post" SET "content" = NULL, "userId" = 3' + }, params: [null, 3] }); @@ -80,6 +105,14 @@ Harness.test({ text : 'UPDATE `post` SET `content` = ?, `userId` = ? WHERE (`post`.`content` = ?)', string: 'UPDATE `post` SET `content` = \'test\', `userId` = 3 WHERE (`post`.`content` = \'no\')' }, + mssql: { + text : 'UPDATE [post] SET [content] = @1, [userId] = @2 WHERE ([post].[content] = @3)', + string: 'UPDATE [post] SET [content] = \'test\', [userId] = 3 WHERE ([post].[content] = \'no\')' + }, + oracle: { + text : 'UPDATE "post" SET "content" = :1, "userId" = :2 WHERE ("post"."content" = :3)', + string: 'UPDATE "post" SET "content" = \'test\', "userId" = 3 WHERE ("post"."content" = \'no\')' + }, params: ['test', 3, 'no'] }); @@ -99,6 +132,14 @@ Harness.test({ text : 'UPDATE `post` SET `content` = `user`.`name` FROM `user` WHERE (`post`.`userId` = `user`.`id`)', string: 'UPDATE `post` SET `content` = `user`.`name` FROM `user` WHERE (`post`.`userId` = `user`.`id`)' }, + mssql: { + text : 'UPDATE [post] SET [content] = [user].[name] FROM [user] WHERE ([post].[userId] = [user].[id])', + string: 'UPDATE [post] SET [content] = [user].[name] FROM [user] WHERE ([post].[userId] = [user].[id])' + }, + oracle: { + text : 'UPDATE "post" SET "content" = "user"."name" FROM "user" WHERE ("post"."userId" = "user"."id")', + string: 'UPDATE "post" SET "content" = "user"."name" FROM "user" WHERE ("post"."userId" = "user"."id")' + }, params: [] }); @@ -119,6 +160,14 @@ Harness.test({ text : 'UPDATE `post` SET `userId` = `user`.`id` FROM `user` WHERE (`post`.`userId` = `user`.`id`)', string: 'UPDATE `post` SET `userId` = `user`.`id` FROM `user` WHERE (`post`.`userId` = `user`.`id`)' }, + mssql: { + text : 'UPDATE [post] SET [userId] = [user].[id] FROM [user] WHERE ([post].[userId] = [user].[id])', + string: 'UPDATE [post] SET [userId] = [user].[id] FROM [user] WHERE ([post].[userId] = [user].[id])' + }, + oracle: { + text : 'UPDATE "post" SET "userId" = "user"."id" FROM "user" WHERE ("post"."userId" = "user"."id")', + string: 'UPDATE "post" SET "userId" = "user"."id" FROM "user" WHERE ("post"."userId" = "user"."id")' + }, params: [] }); @@ -139,5 +188,59 @@ Harness.test({ text : 'UPDATE `post` SET `content` = ?', string: 'UPDATE `post` SET `content` = x\'74657374\'' }, + oracle: { + text : 'UPDATE "post" SET "content" = :1', + string: 'UPDATE "post" SET "content" = utl_raw.cast_to_varchar2(hextoraw(\'74657374\'))' + }, params: [new Buffer('test')] }); + +// Boolean updates +Harness.test({ + query: variable.update({ + a: true, + b: false + }), + pg: { + text : 'UPDATE "variable" SET "a" = $1, "b" = $2', + string: 'UPDATE "variable" SET "a" = TRUE, "b" = FALSE' + }, + sqlite: { + text : 'UPDATE "variable" SET "a" = $1, "b" = $2', + string: 'UPDATE "variable" SET "a" = 1, "b" = 0' + }, + mysql: { + text : 'UPDATE `variable` SET `a` = ?, `b` = ?', + string: 'UPDATE `variable` SET `a` = TRUE, `b` = FALSE' + }, + oracle: { + text : 'UPDATE "variable" SET "a" = :1, "b" = :2', + string: 'UPDATE "variable" SET "a" = TRUE, "b" = FALSE' + }, + params: [true, false] +}); + +// Object updates +Harness.test({ + query: variable.update({ + a: {"id": 1, "value": 2}, + b: [{"id": 2, "value": 3}, {"id": 3, "value": 4}] + }), + pg: { + text : 'UPDATE "variable" SET "a" = $1, "b" = $2', + string: 'UPDATE "variable" SET "a" = \'{"id":1,"value":2}\', "b" = \'[{"id":2,"value":3},{"id":3,"value":4}]\'' + }, + sqlite: { + text : 'UPDATE "variable" SET "a" = $1, "b" = $2', + string: 'UPDATE "variable" SET "a" = \'{"id":1,"value":2}\', "b" = \'[{"id":2,"value":3},{"id":3,"value":4}]\'' + }, + mysql: { + text : 'UPDATE `variable` SET `a` = ?, `b` = ?', + string: 'UPDATE `variable` SET `a` = \'{"id":1,"value":2}\', `b` = (\'{"id":2,"value":3}\', \'{"id":3,"value":4}\')' + }, + oracle: { + text : 'UPDATE "variable" SET "a" = :1, "b" = :2', + string: 'UPDATE "variable" SET "a" = \'{"id":1,"value":2}\', "b" = (\'{"id":2,"value":3}\', \'{"id":3,"value":4}\')' + }, + params: [{"id": 1, "value": 2}, [{"id": 2, "value": 3}, {"id": 3, "value": 4}]] +}); \ No newline at end of file diff --git a/test/dialects/value-expression-tests.js b/test/dialects/value-expression-tests.js index b8b30d8e..d5c7fcd4 100644 --- a/test/dialects/value-expression-tests.js +++ b/test/dialects/value-expression-tests.js @@ -20,6 +20,14 @@ Harness.test({ text : 'SELECT `customer`.`name`, (`customer`.`income` % ?) FROM `customer` WHERE (((`customer`.`age` + ?) * (`customer`.`age` - ?)) = ?)', string: 'SELECT `customer`.`name`, (`customer`.`income` % 100) FROM `customer` WHERE (((`customer`.`age` + 5) * (`customer`.`age` - 2)) = 10)' }, + mssql: { + text : 'SELECT [customer].[name], ([customer].[income] % @1) FROM [customer] WHERE ((([customer].[age] + @2) * ([customer].[age] - @3)) = @4)', + string: 'SELECT [customer].[name], ([customer].[income] % 100) FROM [customer] WHERE ((([customer].[age] + 5) * ([customer].[age] - 2)) = 10)' + }, + oracle: { + text : 'SELECT "customer"."name", ("customer"."income" % :1) FROM "customer" WHERE ((("customer"."age" + :2) * ("customer"."age" - :3)) = :4)', + string: 'SELECT "customer"."name", ("customer"."income" % 100) FROM "customer" WHERE ((("customer"."age" + 5) * ("customer"."age" - 2)) = 10)' + }, params: [100, 5, 2, 10] }); @@ -38,6 +46,14 @@ Harness.test({ text : 'SELECT `customer`.`name` FROM `customer` WHERE (`customer`.`name` LIKE (`customer`.`id` + ?))', string: 'SELECT `customer`.`name` FROM `customer` WHERE (`customer`.`name` LIKE (`customer`.`id` + \'hello\'))' }, + mssql: { + text : 'SELECT [customer].[name] FROM [customer] WHERE ([customer].[name] LIKE ([customer].[id] + @1))', + string: 'SELECT [customer].[name] FROM [customer] WHERE ([customer].[name] LIKE ([customer].[id] + \'hello\'))' + }, + oracle: { + text : 'SELECT "customer"."name" FROM "customer" WHERE ("customer"."name" LIKE ("customer"."id" + :1))', + string: 'SELECT "customer"."name" FROM "customer" WHERE ("customer"."name" LIKE ("customer"."id" + \'hello\'))' + }, params: ['hello'] }); @@ -57,6 +73,14 @@ Harness.test({ text : 'SELECT ((((`variable`.`a` * `variable`.`a`) / ?) + (`variable`.`v` * `variable`.`t`)) = `variable`.`d`) FROM `variable`', string: 'SELECT ((((`variable`.`a` * `variable`.`a`) / 2) + (`variable`.`v` * `variable`.`t`)) = `variable`.`d`) FROM `variable`' }, + mssql: { + text : 'SELECT (((([variable].[a] * [variable].[a]) / @1) + ([variable].[v] * [variable].[t])) = [variable].[d]) FROM [variable]', + string: 'SELECT (((([variable].[a] * [variable].[a]) / 2) + ([variable].[v] * [variable].[t])) = [variable].[d]) FROM [variable]' + }, + oracle: { + text : 'SELECT (((("variable"."a" * "variable"."a") / :1) + ("variable"."v" * "variable"."t")) = "variable"."d") FROM "variable"', + string: 'SELECT (((("variable"."a" * "variable"."a") / 2) + ("variable"."v" * "variable"."t")) = "variable"."d") FROM "variable"' + }, params: [2] }); @@ -75,6 +99,14 @@ Harness.test({ text : 'SELECT (((`variable`.`a` * `variable`.`a`) + (`variable`.`b` * `variable`.`b`)) = (`variable`.`c` * `variable`.`c`)) FROM `variable`', string: 'SELECT (((`variable`.`a` * `variable`.`a`) + (`variable`.`b` * `variable`.`b`)) = (`variable`.`c` * `variable`.`c`)) FROM `variable`' }, + mssql: { + text : 'SELECT ((([variable].[a] * [variable].[a]) + ([variable].[b] * [variable].[b])) = ([variable].[c] * [variable].[c])) FROM [variable]', + string: 'SELECT ((([variable].[a] * [variable].[a]) + ([variable].[b] * [variable].[b])) = ([variable].[c] * [variable].[c])) FROM [variable]' + }, + oracle: { + text : 'SELECT ((("variable"."a" * "variable"."a") + ("variable"."b" * "variable"."b")) = ("variable"."c" * "variable"."c")) FROM "variable"', + string: 'SELECT ((("variable"."a" * "variable"."a") + ("variable"."b" * "variable"."b")) = ("variable"."c" * "variable"."c")) FROM "variable"' + }, params: [] }); @@ -82,16 +114,46 @@ Harness.test({ query: post.select(post.id).where(post.content.equals(new Buffer('test'))), pg: { text : 'SELECT "post"."id" FROM "post" WHERE ("post"."content" = $1)', - string: 'SELECT "post"."id" FROM "post" WHERE ("post"."content" = \'\\x74657374\')', + string: 'SELECT "post"."id" FROM "post" WHERE ("post"."content" = \'\\x74657374\')' }, sqlite: { text : 'SELECT "post"."id" FROM "post" WHERE ("post"."content" = $1)', - string: 'SELECT "post"."id" FROM "post" WHERE ("post"."content" = x\'74657374\')', + string: 'SELECT "post"."id" FROM "post" WHERE ("post"."content" = x\'74657374\')' }, mysql: { text : 'SELECT `post`.`id` FROM `post` WHERE (`post`.`content` = ?)', - string: 'SELECT `post`.`id` FROM `post` WHERE (`post`.`content` = x\'74657374\')', + string: 'SELECT `post`.`id` FROM `post` WHERE (`post`.`content` = x\'74657374\')' + }, + oracle: { + text : 'SELECT "post"."id" FROM "post" WHERE ("post"."content" = :1)', + string: 'SELECT "post"."id" FROM "post" WHERE ("post"."content" = utl_raw.cast_to_varchar2(hextoraw(\'74657374\')))' }, params: [new Buffer('test')] }); +// concat tests +Harness.test({ + query: post.select(post.content.concat(post.tags)), + pg: { + text : 'SELECT ("post"."content" || "post"."tags") FROM "post"', + string: 'SELECT ("post"."content" || "post"."tags") FROM "post"' + }, + sqlite: { + text : 'SELECT ("post"."content" || "post"."tags") FROM "post"', + string: 'SELECT ("post"."content" || "post"."tags") FROM "post"' + }, + mysql: { + text : 'SELECT (`post`.`content` || `post`.`tags`) FROM `post`', + string: 'SELECT (`post`.`content` || `post`.`tags`) FROM `post`' + }, + mssql: { + text : 'SELECT ([post].[content] + [post].[tags]) FROM [post]', + string: 'SELECT ([post].[content] + [post].[tags]) FROM [post]' + }, + oracle: { + text : 'SELECT ("post"."content" || "post"."tags") FROM "post"', + string: 'SELECT ("post"."content" || "post"."tags") FROM "post"' + }, + params: [] +}); + diff --git a/test/dialects/where-clause-tests.js b/test/dialects/where-clause-tests.js index 7fef43f2..3282b7d9 100644 --- a/test/dialects/where-clause-tests.js +++ b/test/dialects/where-clause-tests.js @@ -17,6 +17,14 @@ Harness.test({ text : 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))', string: 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))' }, + mssql: { + text : 'SELECT * FROM [user] WHERE (([user].[id] IS NOT NULL) AND ([user].[name] IS NOT NULL))', + string: 'SELECT * FROM [user] WHERE (([user].[id] IS NOT NULL) AND ([user].[name] IS NOT NULL))' + }, + oracle: { + text : 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))', + string: 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))' + }, params: [] }); @@ -34,5 +42,164 @@ Harness.test({ text : 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))', string: 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))' }, + mssql: { + text : 'SELECT * FROM [user] WHERE (([user].[id] IS NOT NULL) AND ([user].[name] IS NOT NULL))', + string: 'SELECT * FROM [user] WHERE (([user].[id] IS NOT NULL) AND ([user].[name] IS NOT NULL))' + }, + oracle: { + text : 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))', + string: 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))' + }, params: [] }); + +Harness.test({ + query: user.where([user.id.isNotNull(), user.name.isNotNull()]), + pg: { + text : 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))', + string: 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))' + }, + mysql: { + text : 'SELECT * FROM `user` WHERE ((`user`.`id` IS NOT NULL) AND (`user`.`name` IS NOT NULL))', + string: 'SELECT * FROM `user` WHERE ((`user`.`id` IS NOT NULL) AND (`user`.`name` IS NOT NULL))' + }, + sqlite: { + text : 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))', + string: 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))' + }, + mssql: { + text : 'SELECT * FROM [user] WHERE (([user].[id] IS NOT NULL) AND ([user].[name] IS NOT NULL))', + string: 'SELECT * FROM [user] WHERE (([user].[id] IS NOT NULL) AND ([user].[name] IS NOT NULL))' + }, + oracle: { + text : 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))', + string: 'SELECT * FROM "user" WHERE (("user"."id" IS NOT NULL) AND ("user"."name" IS NOT NULL))' + }, + params: [] +}); + +Harness.test({ + query: user.where([]), + pg: { + text : 'SELECT * FROM "user" WHERE (1 = 1)', + string: 'SELECT * FROM "user" WHERE (1 = 1)' + }, + mysql: { + text : 'SELECT * FROM `user` WHERE (1 = 1)', + string: 'SELECT * FROM `user` WHERE (1 = 1)' + }, + sqlite: { + text : 'SELECT * FROM "user" WHERE (1 = 1)', + string: 'SELECT * FROM "user" WHERE (1 = 1)' + }, + mssql: { + text : 'SELECT * FROM [user] WHERE (1 = 1)', + string: 'SELECT * FROM [user] WHERE (1 = 1)' + }, + oracle: { + text : 'SELECT * FROM "user" WHERE (1 = 1)', + string: 'SELECT * FROM "user" WHERE (1 = 1)' + }, + params: [] +}); + +Harness.test({ + query: user.select().where(user.id.equals(1)).and(user.name.equals('a')), + pg: { + text : 'SELECT "user".* FROM "user" WHERE (("user"."id" = $1) AND ("user"."name" = $2))', + string: 'SELECT "user".* FROM "user" WHERE (("user"."id" = 1) AND ("user"."name" = \'a\'))' + }, + mysql: { + text : 'SELECT `user`.* FROM `user` WHERE ((`user`.`id` = ?) AND (`user`.`name` = ?))', + string: 'SELECT `user`.* FROM `user` WHERE ((`user`.`id` = 1) AND (`user`.`name` = \'a\'))' + }, + sqlite: { + text : 'SELECT "user".* FROM "user" WHERE (("user"."id" = $1) AND ("user"."name" = $2))', + string: 'SELECT "user".* FROM "user" WHERE (("user"."id" = 1) AND ("user"."name" = \'a\'))' + }, + mssql: { + text : 'SELECT [user].* FROM [user] WHERE (([user].[id] = @1) AND ([user].[name] = @2))', + string: 'SELECT [user].* FROM [user] WHERE (([user].[id] = 1) AND ([user].[name] = \'a\'))' + }, + oracle: { + text : 'SELECT "user".* FROM "user" WHERE (("user"."id" = :1) AND ("user"."name" = :2))', + string: 'SELECT "user".* FROM "user" WHERE (("user"."id" = 1) AND ("user"."name" = \'a\'))' + }, + params: [1,'a'] +}); + +Harness.test({ + query: user.select().and(user.id.equals(1)), + pg: { + text : 'SELECT "user".* FROM "user" WHERE ("user"."id" = $1)', + string: 'SELECT "user".* FROM "user" WHERE ("user"."id" = 1)' + }, + mysql: { + text : 'SELECT `user`.* FROM `user` WHERE (`user`.`id` = ?)', + string: 'SELECT `user`.* FROM `user` WHERE (`user`.`id` = 1)' + }, + sqlite: { + text : 'SELECT "user".* FROM "user" WHERE ("user"."id" = $1)', + string: 'SELECT "user".* FROM "user" WHERE ("user"."id" = 1)' + }, + mssql: { + text : 'SELECT [user].* FROM [user] WHERE ([user].[id] = @1)', + string: 'SELECT [user].* FROM [user] WHERE ([user].[id] = 1)' + }, + oracle: { + text : 'SELECT "user".* FROM "user" WHERE ("user"."id" = :1)', + string: 'SELECT "user".* FROM "user" WHERE ("user"."id" = 1)' + }, + params: [1] +}); + +Harness.test({ + query: user.select().or(user.id.equals(1)), + pg: { + text : 'SELECT "user".* FROM "user" WHERE ("user"."id" = $1)', + string: 'SELECT "user".* FROM "user" WHERE ("user"."id" = 1)' + }, + mysql: { + text : 'SELECT `user`.* FROM `user` WHERE (`user`.`id` = ?)', + string: 'SELECT `user`.* FROM `user` WHERE (`user`.`id` = 1)' + }, + sqlite: { + text : 'SELECT "user".* FROM "user" WHERE ("user"."id" = $1)', + string: 'SELECT "user".* FROM "user" WHERE ("user"."id" = 1)' + }, + mssql: { + text : 'SELECT [user].* FROM [user] WHERE ([user].[id] = @1)', + string: 'SELECT [user].* FROM [user] WHERE ([user].[id] = 1)' + }, + oracle: { + text : 'SELECT "user".* FROM "user" WHERE ("user"."id" = :1)', + string: 'SELECT "user".* FROM "user" WHERE ("user"."id" = 1)' + }, + params: [1] +}); + +Harness.test({ + query: user.select().and(user.id.equals(1)).or(user.name.equals('a')), + pg: { + text : 'SELECT "user".* FROM "user" WHERE (("user"."id" = $1) OR ("user"."name" = $2))', + string: 'SELECT "user".* FROM "user" WHERE (("user"."id" = 1) OR ("user"."name" = \'a\'))' + }, + mysql: { + text : 'SELECT `user`.* FROM `user` WHERE ((`user`.`id` = ?) OR (`user`.`name` = ?))', + string: 'SELECT `user`.* FROM `user` WHERE ((`user`.`id` = 1) OR (`user`.`name` = \'a\'))' + }, + sqlite: { + text : 'SELECT "user".* FROM "user" WHERE (("user"."id" = $1) OR ("user"."name" = $2))', + string: 'SELECT "user".* FROM "user" WHERE (("user"."id" = 1) OR ("user"."name" = \'a\'))' + }, + mssql: { + text : 'SELECT [user].* FROM [user] WHERE (([user].[id] = @1) OR ([user].[name] = @2))', + string: 'SELECT [user].* FROM [user] WHERE (([user].[id] = 1) OR ([user].[name] = \'a\'))' + }, + oracle: { + text : 'SELECT "user".* FROM "user" WHERE (("user"."id" = :1) OR ("user"."name" = :2))', + string: 'SELECT "user".* FROM "user" WHERE (("user"."id" = 1) OR ("user"."name" = \'a\'))' + }, + params: [1,'a'] +}); + diff --git a/test/function-tests.js b/test/function-tests.js index 076c2ed5..6c53072d 100644 --- a/test/function-tests.js +++ b/test/function-tests.js @@ -5,7 +5,12 @@ var sql = require(__dirname + '/../lib').setDialect('postgres'); var user = sql.define({ name: 'user', - columns: ['id', 'email', 'name'] + columns: [ + {name: 'id'}, + {name:'email'}, + {name: 'name'}, + {name: 'age', property: 'howOld'} + ] }); suite('function', function() { @@ -16,6 +21,14 @@ suite('function', function() { assert.equal(aliasedUpper.text, 'UPPER("user"."email") AS "upperAlias"'); }); + test('function call on aliased column', function() { + var round = sql.functions.ROUND; + var aliasedRound = round(user.howOld, 2).toQuery(); + + assert.equal(aliasedRound.text, 'ROUND("user"."age", $1)'); + assert.equal(aliasedRound.values[0], 2); + }); + test('creating function call works', function() { var upper = sql.functionCallCreator('UPPER'); var functionCall = upper('hello', 'world').toQuery(); @@ -71,4 +84,10 @@ suite('function', function() { assert.equal(query.text, 'SELECT (AVG((DISTINCT((COUNT("user"."id") + MAX("user"."id"))) - MIN("user"."id"))) * $1) FROM "user"'); assert.equal(query.values[0], 100); }); + + test('use custom function', function() { + var query = user.select(sql.function('PHRASE_TO_TSQUERY')('simple', user.name)).toQuery(); + assert.equal(query.text, 'SELECT PHRASE_TO_TSQUERY($1, "user"."name") FROM "user"'); + assert.equal(query.values[0], 'simple'); + }); }); diff --git a/test/index-tests.js b/test/index-tests.js index 79cbd6ce..f25839e1 100644 --- a/test/index-tests.js +++ b/test/index-tests.js @@ -27,6 +27,15 @@ suite('index', function() { assert.equal(sql.create('mysql').dialectName, 'mysql'); }); + test('stores the mssql dialect', function() { + assert.equal(sql.create('mssql').dialectName, 'mssql'); + }); + + test('stores the oracle dialect', function() { + assert.equal(sql.create('oracle').dialectName, 'oracle'); + }); + + test('can create a query using the default dialect', function() { var query = sql.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toQuery(); assert.equal(query.text, 'SELECT "user"."id" FROM "user" WHERE ("user"."email" = $1)'); @@ -41,47 +50,60 @@ suite('index', function() { }); test('sql.create creates an instance with a new dialect', function() { - var mysql = sql.create('mysql'); - var query = mysql.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toQuery(); - assert.equal(query.text, 'SELECT `user`.`id` FROM `user` WHERE (`user`.`email` = ?)'); - assert.equal(query.values[0], 'brian.m.carlson@gmail.com'); - + var mysql = sql.create('mysql'); + var query = mysql.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toQuery(); + assert.equal(query.text, 'SELECT `user`.`id` FROM `user` WHERE (`user`.`email` = ?)'); + assert.equal(query.values[0], 'brian.m.carlson@gmail.com'); }); test('sql.define for parallel dialects work independently', function() { + var mssql = sql.create('mssql'); var mysql = sql.create('mysql'); var postgres = sql.create('postgres'); var sqlite = sql.create('sqlite'); + var oracle = sql.create('oracle'); + var mssqlTable = mssql.define({name: 'table', columns: ['column']}); var mysqlTable = mysql.define({name: 'table', columns: ['column']}); var postgresTable = postgres.define({name: 'table', columns: ['column']}); var sqliteTable = sqlite.define({name: 'table', columns: ['column']}); + var oracleTable = oracle.define({name: 'table', columns: ['column']}); assert.equal(mysqlTable.sql, mysql); assert.equal(postgresTable.sql, postgres); assert.equal(sqliteTable.sql, sqlite); + assert.equal(mssqlTable.sql, mssql); + assert.equal(oracleTable.sql, oracle); }); test('using Sql as a class', function() { var Sql = sql.Sql; + var mssql = new Sql('mssql'); var mysql = new Sql('mysql'); var postgres = new Sql('postgres'); var sqlite = new Sql('sqlite'); + var oracle = new Sql('oracle'); assert.equal(mysql.dialect, require(__dirname + '/../lib/dialect/mysql')); assert.equal(postgres.dialect, require(__dirname + '/../lib/dialect/postgres')); assert.equal(sqlite.dialect, require(__dirname + '/../lib/dialect/sqlite')); + assert.equal(mssql.dialect, require(__dirname + '/../lib/dialect/mssql')); + assert.equal(oracle.dialect, require(__dirname + '/../lib/dialect/oracle')); }); test('override dialect for toQuery using dialect name', function() { var Sql = sql.Sql; + var mssql = new Sql('mssql'); var mysql = new Sql('mysql'); var postgres = new Sql('postgres'); var sqlite = new Sql('sqlite'); + var oracle = new Sql('oracle'); var sqliteQuery = mysql.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toQuery('sqlite'); var postgresQuery = sqlite.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toQuery('postgres'); var mysqlQuery = postgres.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toQuery('mysql'); + var mssqlQuery = mysql.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toQuery('mssql'); + var oracleQuery = oracle.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toQuery('oracle'); var values = ['brian.m.carlson@gmail.com']; assert.equal(sqliteQuery.text, 'SELECT "user"."id" FROM "user" WHERE ("user"."email" = $1)'); @@ -92,6 +114,12 @@ suite('index', function() { assert.equal(mysqlQuery.text, 'SELECT `user`.`id` FROM `user` WHERE (`user`.`email` = ?)'); assert.deepEqual(mysqlQuery.values, values); + + assert.equal(mssqlQuery.text, 'SELECT [user].[id] FROM [user] WHERE ([user].[email] = @1)'); + assert.deepEqual(mssqlQuery.values, values); + + assert.equal(oracleQuery.text, 'SELECT "user"."id" FROM "user" WHERE ("user"."email" = :1)'); + assert.deepEqual(oracleQuery.values, values); }); test('override dialect for toQuery using invalid dialect name', function() { @@ -127,10 +155,15 @@ suite('index', function() { var mysql = new Sql('mysql'); var postgres = new Sql('postgres'); var sqlite = new Sql('sqlite'); + var mssql = new Sql('mssql'); + var oracle = new Sql('oracle'); var sqliteQuery = mysql.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toNamedQuery('user.select_brian','sqlite'); var postgresQuery = sqlite.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toNamedQuery('user.select_brian','postgres'); var mysqlQuery = postgres.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toNamedQuery('user.select_brian','mysql'); + var oracleQuery = mssql.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toNamedQuery('user.select_brian','oracle'); + var mssqlQuery = oracle.select(user.id).from(user).where(user.email.equals('brian.m.carlson@gmail.com')).toNamedQuery('user.select_brian','mssql'); + var values = ['brian.m.carlson@gmail.com']; assert.equal(sqliteQuery.text, 'SELECT "user"."id" FROM "user" WHERE ("user"."email" = $1)'); @@ -144,6 +177,14 @@ suite('index', function() { assert.equal(mysqlQuery.text, 'SELECT `user`.`id` FROM `user` WHERE (`user`.`email` = ?)'); assert.deepEqual(mysqlQuery.values, values); assert.equal('user.select_brian', mysqlQuery.name); + + assert.equal(mssqlQuery.text, 'SELECT [user].[id] FROM [user] WHERE ([user].[email] = @1)'); + assert.deepEqual(mssqlQuery.values, values); + assert.equal('user.select_brian', mssqlQuery.name); + + assert.equal(oracleQuery.text, 'SELECT "user"."id" FROM "user" WHERE ("user"."email" = :1)'); + assert.deepEqual(oracleQuery.values, values); + assert.equal('user.select_brian', oracleQuery.name); }); @@ -154,4 +195,20 @@ suite('index', function() { }); }); + test('mssql default parameter place holder is @index', function() { + var Sql = sql.Sql; + var mssql = new Sql('mssql'); + var query = mssql.select(user.id).from(user).where(user.email.equals('x@y.com')).toQuery(); + assert.equal(query.text, 'SELECT [user].[id] FROM [user] WHERE ([user].[email] = @1)'); + assert.equal(query.values[0], 'x@y.com'); + }); + + test('mssql override default parameter placeholder with ?', function() { + var Sql = sql.Sql; + var mssql = new Sql('mssql',{questionMarkParameterPlaceholder:true}); + var query = mssql.select(user.id).from(user).where(user.email.equals('x@y.com')).toQuery(); + assert.equal(query.text, 'SELECT [user].[id] FROM [user] WHERE ([user].[email] = ?)'); + assert.equal(query.values[0], 'x@y.com'); + }); + }); diff --git a/test/mocha.opts b/test/mocha.opts index 5efaf24d..850a6c2f 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1 +1,2 @@ +--reporter dot --ui tdd diff --git a/test/table-tests.js b/test/table-tests.js index 43c13791..73d43367 100644 --- a/test/table-tests.js +++ b/test/table-tests.js @@ -167,6 +167,19 @@ test('hasColumn', function() { assert.equal(table.hasColumn('baz'), true); }); +test('hasColumn with user-defined column property', function() { + var table = Table.define({ + name: 'blah', + columns: [{ + name: 'id', + property: 'theId' + }, {name: 'foo'}] + }); + + assert.equal(table.hasColumn('id'), true); + assert.equal(table.hasColumn('theId'), true); +}); + test('the column "from" does not overwrite the from method', function() { var table = Table.define({ name: 'foo', columns: [] }); table.addColumn('from'); @@ -187,6 +200,40 @@ test('set and get schema', function () { assert.equal(table.getSchema(), 'barbarz'); }); +suite('table.clone', function() { + test('check if it is a copy, not just a reference', function() { + var table = Table.define({ name: 'foo', columns: [] }); + var copy = table.clone(); + assert.notEqual(table, copy); + }); + + test('copy columns', function() { + var table = Table.define({ name: 'foo', columns: ['bar'] }); + var copy = table.clone(); + assert(copy.get('bar') instanceof Column); + }); + + test('overwrite config while copying', function() { + var table = Table.define({ + name: 'foo', + schema: 'foobar', + columns: ['bar'], + snakeToCamel: true, + columnWhiteList: true + }); + + var copy = table.clone({ + schema: 'test', + snakeToCamel: false, + columnWhiteList: false + }); + + assert.equal(copy.getSchema(), 'test'); + assert.equal(copy.snakeToCamel, false); + assert.equal(copy.columnWhiteList, false); + }); +}); + test('dialects', function () { var sql = new Sql.Sql('mysql'); var foo = sql.define({ name: 'foo', columns: [ 'id' ] }), @@ -200,4 +247,27 @@ test('dialects', function () { bar = sql.define({ name: 'bar', columns: [ 'id' ] }); actual = foo.join(bar).on(bar.id.equals(1)).toString(); assert.equal(actual, '"foo" INNER JOIN "bar" ON ("bar"."id" = 1)'); -}); \ No newline at end of file +}); + +test('limit', function () { + var user = Table.define({name: 'user', columns: ['id', 'name']}); + var query = user.limit(3); + assert.equal(query.nodes.length, 1); + assert.equal(query.nodes[0].type, 'LIMIT'); + assert.equal(query.nodes[0].count, 3); +}); + +test('offset', function () { + var user = Table.define({name: 'user', columns: ['id', 'name']}); + var query = user.offset(20); + assert.equal(query.nodes.length, 1); + assert.equal(query.nodes[0].type, 'OFFSET'); + assert.equal(query.nodes[0].count, 20); +}); + +test('order', function () { + var user = Table.define({name: 'user', columns: ['id', 'name']}); + var query = user.order(user.name); + assert.equal(query.nodes.length, 1); + assert.equal(query.nodes[0].type, 'ORDER BY'); +});