UNPKG

epiquery2

Version:

run templated queries from the http's using learnings from 1

94 lines (77 loc) 2.88 kB
events = require 'events' Q = require 'q' log = require 'simplog' _ = require 'lodash-contrib' ConnectionPool = require 'tedious-connection-pool' tedious = require 'tedious' os = require 'os' #yes virginia, this won't work on single core machines #buy a real computer POOL = null poolConfig = min: 2 max: 4 log: true class MSSQLDriver extends events.EventEmitter constructor: (@query, @config, @context) -> escape: (context) -> _.walk.preorder context, (value, key, parent) -> if parent parent[key] = value.replace(/'/g, "''") if _.isString(value) parseQueryParameters: () -> lines = @query.match ///^--@.*$///mg _.map lines, (line) => line = line.replace '--', '' line = line.replace '=', '' [varName,type,value] = line.split /\s+/ varName = varName.replace('@','') type = type.replace /\(.*\)/ value = _.reduce value.split('.'), (doc,prop) -> doc[prop] , @context.templateContext { varName, type, value } execute: () => @rowSetStarted = false connect_deferred = Q.defer() request_complete_deferred = Q.defer() #connect if not POOL POOL = new ConnectionPool(poolConfig, @config) POOL.acquire connect_deferred.makeNodeResolver() connect_deferred.promise.then (conn) => request = new tedious.Request @query, request_complete_deferred.makeNodeResolver() # make sure that no matter how our request-complete event ends, we close # the connection request_complete_deferred.promise.fin () -> conn.release() request_complete_deferred.promise.then () => this.emit('endrowset') if @rowSetStarted this.emit 'endquery' # we use this event to split up multipe result sets as each result set # is preceeded by a columnMetadata event request.on 'columnMetadata', () => this.emit('endrowset') if @rowSetStarted this.emit 'beginrowset' @rowSetStarted = true request.on 'row', (columns) => this.emit('beginrowset') if not @rowSetStarted @rowSetStarted = true c = _.map(columns, @mapper.bind({})) this.emit 'row', c parameters = @parseQueryParameters() unless _.isEmpty parameters parameters.forEach (param) -> request.addParameter(param.varName, tedious.TYPES[param.type], parseInt(param.value || 0)) return conn.execSql request conn.execSqlBatch request, (error) => log.error "[q:#{@context}] connect failed %j", error this.emit 'error', error Q.all([ connect_deferred.promise, request_complete_deferred.promise ]).fail( (error) => this.emit 'error', error ).done() module.exports.DriverClass = MSSQLDriver