Browse Source

Fix merge conflict on tests

master
beedi 9 years ago
parent
commit
091b0b91a3
  1. 2
      .travis.yml
  2. 215
      lib/dialect/mssql.js
  3. 2
      lib/dialect/mysql.js
  4. 28
      lib/dialect/oracle.js
  5. 112
      lib/dialect/postgres.js
  6. 53
      lib/dialect/sqlite.js
  7. 1
      lib/node/column.js
  8. 4
      lib/node/drop.js
  9. 2
      lib/node/parameter.js
  10. 10
      lib/node/query.js
  11. 4
      lib/node/truncate.js
  12. 18
      lib/node/valueExpression.js
  13. 10
      lib/table.js
  14. 8
      package.json
  15. 24
      runtests.js
  16. 50
      test/column-tests.js
  17. 10
      test/dialects/case-tests.js
  18. 114
      test/dialects/create-table-tests.js
  19. 45
      test/dialects/insert-tests.js
  20. 2
      test/dialects/subquery-tests.js
  21. 51
      test/dialects/update-tests.js
  22. 16
      test/index-tests.js

2
.travis.yml

@ -1,4 +1,6 @@
language: node_js
node_js:
- "5.0"
- "4.2"
- "0.10"
- "0.11"

215
lib/dialect/mssql.js

@ -6,6 +6,14 @@
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 = [];
@ -23,6 +31,7 @@ Mssql.prototype._quoteCharacter = '[';
Mssql.prototype._arrayAggFunctionName = '';
Mssql.prototype._getParameterPlaceholder = function(index, value) {
if (this.config.questionMarkParameterPlaceholder) return '?';
return '@' + index;
};
@ -95,7 +104,7 @@ Mssql.prototype.visitAlter = function(alter) {
var table = self._queryNode.table;
var result = ['EXEC sp_rename '+self.visit(table.toNode())+', '+self.visit(alter.nodes[0].nodes[0])];
self._visitingAlter = false;
return result
return result;
}
// Implement our own rename column:
@ -110,7 +119,7 @@ Mssql.prototype.visitAlter = function(alter) {
"'COLUMN'"
];
self._visitingAlter = false;
return result
return result;
}
if (isAlterAddColumn(alter)) return _addColumn();
@ -124,13 +133,13 @@ Mssql.prototype.visitAlter = function(alter) {
// CASE WHEN true THEN xxx END
// the "true" has to be a boolean expression like 1=1
Mssql.prototype.visitCase = function(caseExp) {
var _this=this
var _this=this;
function _whenValue(node){
if (node.type!='PARAMETER') return _this.visit(node);
// dealing with a true/false value
var val=node.value();
if (val==true) return '1=1'; else return '0=1';
if (val===true) return '1=1'; else return '0=1';
}
assert(caseExp.whenList.length == caseExp.thenList.length);
@ -146,7 +155,7 @@ Mssql.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);
}
@ -154,7 +163,7 @@ Mssql.prototype.visitCase = function(caseExp) {
text += ' END)';
return [text];
}
};
Mssql.prototype.visitColumn = function(columnNode) {
var self=this;
@ -162,12 +171,12 @@ Mssql.prototype.visitColumn = function(columnNode) {
var inSelectClause;
function _arrayAgg(){
throw new Error("SQL Server does not support array_agg.")
throw new Error("SQL Server does not support array_agg.");
}
function _countStar(){
// Implement our own since count(table.*) is invalid in Mssql
var result='COUNT(*)'
var result='COUNT(*)';
if(inSelectClause && columnNode.alias) {
result += ' AS ' + self.quote(columnNode.alias);
}
@ -184,8 +193,8 @@ Mssql.prototype.visitColumn = function(columnNode) {
Mssql.prototype.visitCreate = function(create) {
var isNotExists=isCreateIfNotExists(create)
var isTemporary=isCreateTemporary(create)
var isNotExists=isCreateIfNotExists(create);
var isTemporary=isCreateTemporary(create);
if (!isNotExists && !isTemporary) {
return Mssql.super_.prototype.visitCreate.call(this, create);
}
@ -210,7 +219,7 @@ Mssql.prototype.visitCreate = function(create) {
// if (schema) { whereClause+=' AND TABLE_SCHEMA = schemaResult.join(' ')}
// Add some tests for this as well
if (!isNotExists) return createResult
if (!isNotExists) return createResult;
return ['IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES '+whereClause+') BEGIN '+createResult.join(' ')+' END'];
};
@ -237,24 +246,24 @@ Mssql.prototype.visitDrop = function(drop) {
Mssql.prototype.visitFunctionCall = function(functionCall) {
this._visitingFunctionCall = true;
var name=functionCall.name
// override the LENGTH function since mssql calls it LEN
if (name=="LENGTH") name="LEN"
var name=functionCall.name;
// override the LENGTH function since mssql calls it LEN
if (name=="LENGTH") name="LEN";
var txt = name + '(' + functionCall.nodes.map(this.visit.bind(this)).join(', ') + ')';
this._visitingFunctionCall = false;
return [txt];
};
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;
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;
};
/**
@ -272,63 +281,63 @@ Mssql.prototype.visitOrderBy = function(orderBy) {
* @returns {String[]}
*/
Mssql.prototype.visitQueryHelper=function(actions,targets,filters){
function _handleLimitAndOffset(){
var limitInfo=Mssql.super_.prototype.findNode.call(this, filters, "LIMIT");
var offsetInfo=Mssql.super_.prototype.findNode.call(this, filters, "OFFSET");
var orderByInfo=Mssql.super_.prototype.findNode.call(this, filters, "ORDER BY");
// 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");
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
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;
_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) {
@ -364,71 +373,71 @@ Mssql.prototype.visitReturning = function() {
// 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;
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
return node.count.type ? dialect.visit(node.count) : node.count;
}
function isAlterAddColumn(alter){
if (alter.nodes.length==0) return false;
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.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.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.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.length===0) return false;
if (create.nodes[0].type!='IF NOT EXISTS') return false;
return true;
};
}
function isCreateTemporary(create){
return create.options.isTemporary
};
return create.options.isTemporary;
}
function isDropIfExists(drop){
if (drop.nodes.length==0) return false;
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;

2
lib/dialect/mysql.js

@ -100,6 +100,6 @@ Mysql.prototype.visitBinary = function(binary) {
return [text];
}
return Mysql.super_.prototype.visitBinary.call(this, binary);
}
};
module.exports = Mysql;

28
lib/dialect/oracle.js

@ -75,7 +75,7 @@ Oracle.prototype.visitDrop = function(drop) {
};
Oracle.prototype.visitCreate = function(create) {
var isNotExists=isCreateIfNotExists(create)
var isNotExists=isCreateIfNotExists(create);
//var isTemporary=isCreateTemporary(create)
var createText = Oracle.super_.prototype.visitCreate.call(this, create);
if (isNotExists) {
@ -144,8 +144,8 @@ Oracle.prototype.visitQueryHelper=function(actions,targets,filters){
output[limit+2] = temp[2];
}
return this.output;
}
return this.output;
};
Oracle.prototype.visitColumn = function(columnNode) {
var self=this;
@ -153,12 +153,12 @@ Oracle.prototype.visitColumn = function(columnNode) {
var inSelectClause;
function _arrayAgg(){
throw new Error("Oracle does not support array_agg.")
throw new Error("Oracle does not support array_agg.");
}
function _countStar(){
// Implement our own since count(table.*) is invalid in Oracle
var result='COUNT(*)'
var result='COUNT(*)';
if(inSelectClause && columnNode.alias) {
result += self._aliasText + self.quote(columnNode.alias);
}
@ -222,35 +222,35 @@ Oracle.prototype.visitDropIndex = function(node) {
Oracle.prototype.visitCase = function(caseExp) {
return Mssql.prototype.visitCase.call(this, caseExp);
}
};
function isCreateIfNotExists(create){
if (create.nodes.length==0) return false;
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
};
return create.options.isTemporary;
}
function isDropIfExists(drop){
if (drop.nodes.length==0) return false;
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;
};
}
module.exports = Oracle;

112
lib/dialect/postgres.js

@ -26,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';
@ -36,13 +36,29 @@ 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(', ') + ')';
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) &&
!_.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 (_.isFunction(value.toISOString)) {
// Date object's default toString format does not get parsed well
// Handle date like objects using toISOString
@ -51,7 +67,8 @@ Postgres.prototype._getParameterValue = function(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');
@ -187,14 +204,14 @@ Postgres.prototype.quote = function(word, quoteCharacter) {
}
// handle square brackets specially
if (q=='['){
return '['+word+']'
return '['+word+']';
} else {
return q + word.replace(new RegExp(q,'g'),q+q) + q;
}
};
Postgres.prototype.visitSelect = function(select) {
var result = ['SELECT']
var result = ['SELECT'];
if (select.isDistinct) result.push('DISTINCT');
@ -281,7 +298,7 @@ Postgres.prototype.visitCreate = function(create) {
var col_nodes = table.columns.map(function(col) { return col.toNode(); });
var result = ['CREATE TABLE'];
if (create.options.isTemporary) result=['CREATE TEMPORARY 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()));
var primary_col_nodes = col_nodes.filter(function(n) {
@ -539,7 +556,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);
}
@ -547,7 +564,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) + ']';
@ -594,7 +611,7 @@ Postgres.prototype.visitQuery = function(queryNode) {
var node = queryNode.nodes[i];
switch(node.type) {
case "SELECT":
isSelect = true;
isSelect = true; // jshint ignore:line
case "DELETE":
actions.push(node);
break;
@ -637,7 +654,7 @@ Postgres.prototype.visitQuery = function(queryNode) {
throw new Error('Create View requires a Select.');
}
}
return this.visitQueryHelper(actions,targets,filters)
return this.visitQueryHelper(actions,targets,filters);
};
/**
@ -649,16 +666,16 @@ Postgres.prototype.visitQuery = function(queryNode) {
* @returns {String[]}
*/
Postgres.prototype.visitQueryHelper=function(actions,targets,filters){
this.handleDistinct(actions, filters)
// 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);
}
// implicit 'from'
return this.output;
}
this.handleDistinct(actions, filters);
// 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);
}
// implicit 'from'
return this.output;
};
Postgres.prototype.visitSubquery = function(queryNode) {
// create another query builder of the current class to build the subquery
@ -702,11 +719,11 @@ Postgres.prototype.visitColumn = function(columnNode) {
var inSelectClause =
this.visitingReturning ||
(!this._selectOrDeleteEndIndex
&& !this._visitingWhere
&& !inInsertUpdateClause
&& !inDdlClause
&& !this.visitingCase
&& !this._visitingJoin
&& !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;
@ -766,7 +783,7 @@ Postgres.prototype.visitColumn = function(columnNode) {
txt.push(this.quote(columnNode.name));
}
if(closeParen) {
for(var i = 0; i < closeParen; i++) {
for(var j = 0; j < closeParen; j++) {
txt.push(')');
}
}
@ -785,6 +802,9 @@ Postgres.prototype.visitColumn = function(columnNode) {
} else if (columnNode.notNull) {
txt.push(' NOT NULL');
}
if (!columnNode.primaryKey && columnNode.unique) {
txt.push(' UNIQUE');
}
}
if (!!columnNode.references) {
@ -813,7 +833,7 @@ Postgres.prototype.visitColumn = function(columnNode) {
var onDelete = columnNode.references.onDelete;
if (onDelete) onDelete = onDelete.toUpperCase();
if (onDelete === 'CASCADE' || onDelete === 'RESTRICT') {
txt.push(' ON DELETE ' + onDelete)
txt.push(' ON DELETE ' + onDelete);
}
var constraint = columnNode.references.constraint;
if (constraint) {
@ -1003,26 +1023,26 @@ Postgres.prototype.visitCreateView = function(createView) {
* @returns {Object|undefined} {index:number, node:Node}
*/
Postgres.prototype.findNode=function(list,type) {
for (var i= 0, len=list.length; i<len; i++) {
var n=list[i];
if (n.type==type) return {index:i,node:n};
}
return undefined
}
for (var i= 0, len=list.length; i<len; i++) {
var n=list[i];
if (n.type==type) return {index:i,node:n};
}
return undefined;
};
/**
* pulls the DISTINCT node out of the filters and flags the SELECT node that it should be distinct.
* Broken out as a separate function so that dialects that derive from this class can still use this functionality.
*/
Postgres.prototype.handleDistinct = function(actions,filters) {
var distinctNode = this.findNode(filters,"DISTINCT");
//if (!distinctNode) distinctNode = _findNode(targets,"DISTINCT");
//if (!distinctNode) distinctNode = _findNode(actions,"DISTINCT");
if (!distinctNode) return
var selectInfo = this.findNode(actions,"SELECT");
if (!selectInfo) return // there should be one by now, I think
// mark the SELECT node that it's distinct
selectInfo.node.isDistinct = true;
}
var distinctNode = this.findNode(filters,"DISTINCT");
//if (!distinctNode) distinctNode = _findNode(targets,"DISTINCT");
//if (!distinctNode) distinctNode = _findNode(actions,"DISTINCT");
if (!distinctNode) return;
var selectInfo = this.findNode(actions,"SELECT");
if (!selectInfo) return; // there should be one by now, I think
// mark the SELECT node that it's distinct
selectInfo.node.isDistinct = true;
};
module.exports = Postgres;

53
lib/dialect/sqlite.js

@ -1,5 +1,6 @@
'use strict';
var _ = require('lodash');
var util = require('util');
var assert = require('assert');
@ -23,6 +24,10 @@ Sqlite.prototype._getParameterValue = function(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);
}
@ -38,32 +43,32 @@ Sqlite.prototype.visitDropColumn = function() {
};
Sqlite.prototype.visitFunctionCall = function(functionCall) {
var _this=this
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
}
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();
else txt = name + '(' + functionCall.nodes.map(this.visit.bind(this)).join(', ') + ')';
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;
}
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();
else txt = name + '(' + functionCall.nodes.map(this.visit.bind(this)).join(', ') + ')';
this._visitingFunctionCall = false;
return [txt];
@ -123,6 +128,6 @@ Sqlite.prototype.visitBinary = function(binary) {
return ret;
}
return Sqlite.super_.prototype.visitBinary.call(this, binary);
}
};
module.exports = Sqlite;

1
lib/node/column.js

@ -24,6 +24,7 @@ module.exports = Node.define({
this.subfieldContainer = config.subfieldContainer;
this.subfields = config.subfields;
this.autoGenerated = !!config.autoGenerated;
this.unique = !!config.unique;
},
as: function(alias) {
this.alias = alias;

4
lib/node/drop.js

@ -6,7 +6,7 @@ module.exports = Node.define({
type: 'DROP',
constructor: function(table) {
Node.call(this);
this.add(table);
Node.call(this);
this.add(table);
}
});

2
lib/node/parameter.js

@ -7,7 +7,7 @@ var ParameterNode = module.exports = Node.define({
constructor: function(val) {
Node.call(this);
this._val = val;
this.isExplicit = false;
this.isExplicit = false;
},
value: function() {
return this._val;

10
lib/node/query.js

@ -233,10 +233,10 @@ var Query = Node.define({
},
parameter: function(v) {
var param = ParameterNode.getNodeOrParameterNode(v);
param.isExplicit = true;
return this.add(param);
},
var param = ParameterNode.getNodeOrParameterNode(v);
param.isExplicit = true;
return this.add(param);
},
delete: function(params) {
var result;
@ -280,7 +280,7 @@ var Query = Node.define({
var col = self.table.get(key);
if(col && !col.autoGenerated)
var val = o[key];
onDuplicate.add(col.value(ParameterNode.getNodeOrParameterNode(val)));
onDuplicate.add(col.value(ParameterNode.getNodeOrParameterNode(val))); // jshint ignore:line
});
return self.add(onDuplicate);

4
lib/node/truncate.js

@ -6,7 +6,7 @@ module.exports = Node.define({
type: 'TRUNCATE',
constructor: function(table) {
Node.call(this);
this.add(table);
Node.call(this);
this.add(table);
}
});

18
lib/node/valueExpression.js

@ -77,18 +77,6 @@ var ValueExpressionMixin = function() {
return new SliceNode(this.toNode(), processParams(start), processParams(end));
};
var containsMethod = function(set) {
return new ContainsNode(this.toNode(), processParams(set));
};
var containedByMethod = function(set) {
return new ContainedByNode(this.toNode(), processParams(set));
};
var overlapMethod = function(set) {
return new OverlapNode(this.toNode(), processParams(set));
};
var castMethod = function(dataType) {
return new CastNode(this.toNode(), dataType);
};
@ -103,15 +91,15 @@ var ValueExpressionMixin = function() {
};
var caseMethod = function(whenList, thenList, elseBranch) {
if (undefined != elseBranch) {
if (undefined !== elseBranch) {
elseBranch = processParams(elseBranch);
}
return new CaseNode({
whenList : processParams(whenList),
thenList : processParams(thenList),
else : elseBranch
})
}
});
};
return {
isNull : postfixUnaryMethod('IS NULL'),

10
lib/table.js

@ -15,7 +15,7 @@ var Table = function(config) {
this._name = config.name;
this._initialConfig = config;
this.columnWhiteList = !!config.columnWhiteList;
this.isTemporary=!!config.isTemporary
this.isTemporary=!!config.isTemporary;
this.snakeToCamel = !!config.snakeToCamel;
this.columns = [];
this.table = this;
@ -76,10 +76,10 @@ Table.prototype.createColumn = function(col) {
table: this,
subfieldContainer: col,
name: subfield
})]
})];
}, this))
.object()
.value()
.fromPairs()
.value();
}
}
@ -195,7 +195,7 @@ Table.prototype.subQuery = function(alias) {
Table.prototype.insert = function() {
var query = new Query(this);
if(arguments[0].length == 0){
if(arguments[0].length === 0){
query.select.call(query, this.star());
query.where.apply(query,["1=2"]);
} else {

8
package.json

@ -2,7 +2,7 @@
"author": "brianc <brian.m.carlson@gmail.com>",
"name": "sql",
"description": "sql builder",
"version": "0.64.1",
"version": "0.67.0",
"homepage": "https://github.com/brianc/node-sql",
"license": "MIT",
"repository": {
@ -11,14 +11,16 @@
},
"main": "lib/",
"scripts": {
"test": "node ./runtests"
"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": "*",

24
runtests.js

@ -1,18 +1,18 @@
var childProcess = require("child_process")
var path = require("path")
var childProcess = require("child_process");
var path = require("path");
var env = process.env
env.NODE_ENV = "test"
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)
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)
})
process.exit(code);
});

50
test/column-tests.js

@ -36,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({
@ -96,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);
});
});

10
test/dialects/case-tests.js

@ -12,7 +12,7 @@ Harness.test({
},
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`',
@ -40,7 +40,7 @@ Harness.test({
},
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`',
@ -68,7 +68,7 @@ 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`',
@ -96,7 +96,7 @@ 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`',
@ -124,7 +124,7 @@ 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`',

114
test/dialects/create-table-tests.js

@ -479,28 +479,64 @@ var users = Table.define({
Harness.test({
query: users.create(),
pg: {
text : 'CREATE TABLE "users" ("id" int PRIMARY KEY REFERENCES "entity"("id") DEFERRABLE INITIALLY DEFERRED)',
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)',
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)',
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)',
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)',
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: {
@ -539,4 +575,72 @@ Harness.test({
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: []
});

45
test/dialects/insert-tests.js

@ -4,6 +4,11 @@ var Harness = require('./support');
var post = Harness.definePostTable();
var user = Harness.defineUserTable();
var arrayTable = require('../../lib/table').define({
name: 'arraytest',
columns: ['id', 'numbers']
});
Harness.test({
query: post.insert(post.content.value('test'), post.userId.value(1)),
pg: {
@ -630,3 +635,43 @@ Harness.test({
},
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\'))'
}
});

2
test/dialects/subquery-tests.js

@ -29,7 +29,7 @@ Harness.test({
string: 'SELECT "user"."name" FROM "user" WHERE ("user"."id" IN (SELECT "post"."userId" FROM "post"))'
},
params: []
})
});
Harness.test({
query: user.name.in(

51
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({
@ -193,3 +194,53 @@ Harness.test({
},
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}]]
});

16
test/index-tests.js

@ -195,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');
});
});

Loading…
Cancel
Save