UNPKG

msnodesqlv8

Version:

Microsoft Driver for Node.js SQL Server compatible with all versions of Node.

263 lines (231 loc) 6.7 kB
'use strict' const { ServerDialect } = require('./dialect') class ProcedureParamMeta { constructor (raw) { this.proc_name = raw.proc_name this.type_desc = raw.type_desc this.object_id = raw.object_id this.has_default_value = raw.has_default_value this.default_value = raw.default_value this.is_output = raw.is_output this.precision = raw.precision this.scale = raw.scale this.name = raw.name this.type_id = raw.type_id this.max_length = raw.max_length this.order = raw.order this.collation = raw.collation this.is_user_defined = raw.is_user_defined } } /* { proc_name: "test_sp", type_desc: "SQL_STORED_PROCEDURE", object_id: 1446165539, has_default_value: false, default_value: null, is_output: false, name: "@param", type_id: "varchar", max_length: 50, order: 1, collation: "SQL_Latin1_General_CP1_CI_AS", is_user_defined: null, } */ class ProcedureParamFactory { makeParam (procName, paramName, paramType, paramLength, isOutput) { return { proc_name: procName, type_desc: 'SQL_STORED_PROCEDURE', object_id: -1, has_default_value: false, default_value: null, is_output: isOutput, name: paramName, type_id: paramType, max_length: paramLength, order: 1, collation: '', is_user_defined: null } } returnParam () { return { is_output: true, name: '@returns', type_id: 'int', max_length: 4, order: 0, is_user_defined: false, has_default_value: false, default_value: null, collation: null } } } class ProcedureMeta { constructor (name, paramVector) { this.name = name this.dialect = ServerDialect.SqlServer this.paramVector = paramVector.map(p => new ProcedureParamMeta(p)) const summary = this.constructMeta(name, this.paramVector) this.select = summary.select this.signature = summary.signature this.summary = summary this.params = summary.params this.outputParams = summary.outputParams this.inputParams = summary.inputParams this.paramByName = summary.paramByName } reconstruct () { this.constructMeta(this.name, this.paramVector) } constructMeta (name, paramVector) { paramVector = paramVector.filter(p => p.object_id !== null) const outputParams = paramVector.filter(p => p.is_output) const inputParams = paramVector.filter(p => !p.is_output) const signature = this.buildSignature(paramVector, name) const select = this.asSelect(paramVector, name) const summary = this.summarise(name, paramVector) const paramByName = paramVector.reduce((agg, latest) => { if (latest.name) { agg[latest.name.slice(1)] = latest } return agg }, {}) return { select, signature, summary, params: paramVector, outputParams, inputParams, paramByName } } isSybase () { return this.dialect === ServerDialect.Sybase } isSqlServer () { return this.dialect === ServerDialect.SqlServer } buildSignature (pv, name) { const pars = pv.reduce((aggr, latest, i) => { if (i > 0) { aggr.push(`${latest.name} = ?`) } return aggr }, []).join(', ') return `{ ? = call ${name}(${pars}) }` } asSelect (pv, procedure) { if (this.isSqlServer()) { return this.asSelectSqlServer(pv, procedure) } else { return this.asSelectSybase(pv, procedure) } } asSelectSqlServer (pv, procName) { const params = [] const parameters = [] pv.forEach(param => { if (param.name !== '@returns') { parameters.push(param) } }) parameters.forEach(param => { if (param.is_output) { const s = `${param.name} ${param.type_id}` params.push(s) } }) const cmdParam = ['@___return___ int'].concat(params).join(', ') let cmd = `declare ${cmdParam};` cmd += `exec @___return___ = ${procName} ` const spp = parameters.map(param => { return (param.is_output) ? `${param.name}=${param.name} output` : param.name + '=?' }) const params2 = this.asOutput(parameters) const sppJoined = spp.join(', ') cmd += sppJoined + ';' const selectCmd = `select ${['@___return___ as \'___return___\''].concat(params2).join(', ')}` cmd += selectCmd + ';' return cmd } asSelectSybase (pv, procName) { const params = [] const parameters = [] pv.forEach(param => { if (param.name !== '@returns') { parameters.push(param) } }) parameters.forEach(param => { if (param.is_output) { const size = param.type_id === 'varchar' ? `(${param.max_length})` : '' const s = `${param.name} ${param.type_id}${size}` params.push(s) } }) let cmdParam = ['@___return___ int'].concat(params).join(', ') let cmd = `declare ${cmdParam} ` cmd += `exec @___return___ = ${procName} ` const spp = [] parameters.forEach(param => { if (param.is_output) { // output parameter cmdParam = `${param.name} output` spp.push(cmdParam) } else { // input parameter cmdParam = param.name + '=?' spp.push(cmdParam) } }) const params2 = this.asOutput(parameters) const sppJoined = spp.join(', ') cmd += sppJoined + ' ' const selectCmd = `select ${['@___return___ as \'___return___\''].concat(params2).join(', ')}` cmd += selectCmd + ' ' return cmd } asOutput (parameters) { const params2 = [] parameters.forEach(param => { if (param.is_output) { let paramName = param.name if (paramName[0] === '@') { paramName = paramName.substring(1) } const cmdParam = `${param.name} as ${paramName}` params2.push(cmdParam) } }) return params2 } summarise (name, pv) { if (!pv || pv.length === 0) return 'proc does not exist.' let s = `${this.descp(pv[0])} ${name}( ` for (let i = 1; i < pv.length; i += 1) { s += this.descp(pv[i]) if (i < pv.length - 1) { s += ', ' } } s += ' ) ' return s } descp (p) { let s = '' s += `${p.name} [ ${p.type_id}${p.is_output ? ' out ' : ' in '} ] ` return s } } exports.ProcedureMeta = ProcedureMeta exports.ProcedureParamFactory = ProcedureParamFactory