|
|
@ -31,7 +31,7 @@ Mssql.prototype._quoteCharacter = '['; |
|
|
|
Mssql.prototype._arrayAggFunctionName = ''; |
|
|
|
|
|
|
|
Mssql.prototype._getParameterPlaceholder = function(index, value) { |
|
|
|
if (this.config.questionMarkParameterPlaceholder) return '?'; |
|
|
|
if (this.config.questionMarkParameterPlaceholder) return '?'; |
|
|
|
return '@' + index; |
|
|
|
}; |
|
|
|
|
|
|
@ -246,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; |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
@ -281,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"); // 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
|
|
|
|
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) {
|
|
|
@ -373,19 +373,19 @@ 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){ |
|
|
|