UNPKG

zing-orm

Version:
420 lines 36.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MssqlRepository = void 0; const RepositoryParams_1 = require("../types/RepositoryParams"); const JoiUtils_1 = require("../../util/JoiUtils"); const CommonTools_1 = require("../../util/CommonTools"); const globals_1 = require("../../util/globals"); const knex_1 = require("knex"); const oracledb = require('oracledb'); const _ = require('lodash'); var Request = require('tedious').Request; var TYPES = require('tedious').TYPES; //todo Entity @Column const MssqlTypes = { Number: TYPES.Numeric, String: TYPES.VarChar, Date: TYPES.DateTime, }; /** * Entity manager supposed to work with any entity, automatically find its repository and call its methods, * whatever entity type are you passing. */ class MssqlRepository { // ------------------------------------------------------------------------- // Constructor // ------------------------------------------------------------------------- constructor(_connection, _entity) { // super(async () => { try { if (!_entity) { throw Error(`constructor params::_entity can not be ${JSON.stringify(_entity)} !!!`); } this.connection = _connection; this.queryBuilder = (0, knex_1.knex)({ client: 'mssql' }); this.entity = _entity; this.tableName = (0, globals_1.findTableName)(_entity); } catch (err) { //todo console.error("初始化 MssqlRepository Class 失败!!!", err); } // }) } // ------------------------------------------------------------------------- // Public Methods // ------------------------------------------------------------------------- async executeSql(params) { try { await JoiUtils_1.JoiUtils.checkParams(RepositoryParams_1.ExecuteSqlParamsSchema, params); return await MssqlRepository.executeSqlRaw(this.connection, params); } catch (err) { console.log("executeSql error:", err); } } static async executeSqlRaw(connection, params) { return new Promise(async (resolve, reject) => { try { await JoiUtils_1.JoiUtils.checkParams(RepositoryParams_1.ExecuteSqlParamsSchema, params); var { sql, binds = {}, options = {} } = params; console.log("executeSqlRaw params: ", sql, binds, options); let rows = []; let request = new Request(sql, (err, rowCount) => { if (err) { reject(err); } let result = { rowCount, rows }; console.log("executeSqlRaw Query results: "); console.dir(result); resolve(result); }); if (JSON.stringify(binds) !== '{}') { for (var key in binds) { console.log("addParameter: p" + key + " = " + binds[key]); request.addParameter(`p${key}`, MssqlTypes[CommonTools_1.CommonTools.getClass(binds[key])], binds[key]); } } request.on('row', function (row) { let newRow = _.reduce(row, function (a, k) { // console.log("_column: ", _column) a[k.metadata.colName] = k.value; return a; }, {}); rows.push(newRow); }); connection.execSql(request); } catch (err) { console.log("executeSqlRaw error:", err); } }); } // ------------------------------------------------------------------------- // Protected Methods // ------------------------------------------------------------------------- /** * Find with pagination and condition. * - cant use findAndCount for both params * - use createQueryBuilder * @param params 参数 * @param params.current 页码 * @param params.pageSize 页面条数 * @param params.sort 排序 * @param dataFunc 数据处理函数 */ //todo add filter, knex async getPage(params) { try { await JoiUtils_1.JoiUtils.checkParams(RepositoryParams_1.GetPageParamsSchema, params); let { current, pageSize, options } = params; let sql = ''; let count_sql = ''; //todo add sql builder and make sure entity.name is not undefined if (!!options && !!options.schema) { sql = `SELECT * FROM (SELECT A.*, ROWNUM AS MY_RNUM FROM ( SELECT * FROM "${options.schema}"."${this.tableName}") A WHERE ROWNUM <= :maxnumrows + :offset) WHERE MY_RNUM > :offset`; count_sql = `SELECT count(id) FROM "${options.schema}"."${this.tableName}"`; } else { sql = `SELECT * FROM (SELECT A.*, ROWNUM AS MY_RNUM FROM ( SELECT * FROM "${this.tableName}") A WHERE ROWNUM <= :maxnumrows + :offset) WHERE MY_RNUM > :offset`; count_sql = `SELECT count(id) FROM "${this.tableName}"`; } const result1 = await this.executeSql({ sql, binds: { offset: (current - 1) * pageSize, maxnumrows: pageSize }, options: { prefetchRows: pageSize + 1, fetchArraySize: pageSize } }); const result2 = await this.executeSql({ sql: count_sql }); const total = result2.rows[0]['COUNT(ID)']; return { // Optional totalPage: Math.ceil(total / pageSize), current, pageSize, // Required total, list: result1.rows }; } catch (err) { console.error("MssqlRepository getPage 失败!!!", err); throw Error(`MssqlRepository getPage 失败!!!, 错误: ${err}`); } } /** * get documents by filter of collection * @param {object} _params - params object * @param {object} _params.filter - filter of attrs. * @param {object} _params.like - the object to like the documents to get from the collection * @param {array} _params.sorts - array of sort str for attrs. * @param {object} _params.options - query options, e.g. keepAttrs-res attrs; hasEdge-edge res; * @return {AqlQuery} - interface AqlQuery by arangodb */ async getsByFilter(params) { try { await JoiUtils_1.JoiUtils.checkParams(RepositoryParams_1.GetsByFilterParamsSchema, params); let { filter, options } = params; let filterTemp = Object.assign({}, filter); // let { filter, sorts, options } = params; let tempQuery = this.queryBuilder(this.tableName); for (const key in filterTemp) { const data = filterTemp[key]; if (Array.isArray(data)) { // 数组参数,则‘in’ tempQuery = tempQuery.whereIn(key, data); delete filterTemp[key]; } else if (!!data && Object.prototype.toString.call(data) === '[object Object]') { //todo 暂时不支持 /** * 对象参数结构{opr, value} * 支持:==, !=, <, <=, >, >=, IN, NOT IN, LIKE, =~, !~ * 注意: typeof null === 'object' * 增加:opr = 'POSITION' 时需要处理数组属性的查询参数 */ tempQuery.where(`${key}`, data.opr, data.value); delete filterTemp[key]; } } if (Object.keys(filterTemp).length !== 0) { tempQuery = tempQuery.where(Object.assign({}, filterTemp)); } if (!!options && !!options.schema) { tempQuery = tempQuery.withSchema(options.schema); } if (!!options && !!options.keepAttrs) { tempQuery = tempQuery.column(options.keepAttrs).select(); } else { tempQuery = tempQuery.select('*'); } const query = tempQuery.toSQL().toNative(); console.log("getsByFilter query: ", query); const result = await this.executeSql({ sql: query.sql, binds: query.bindings, }); return result.rows; } catch (err) { console.error("MssqlRepository getsByFilter 失败!!!", err); throw Error(`MssqlRepository getsByFilter 失败!!!, 错误: ${err}`); } } /** * update document by _id && newObj from collection * @param {object} _params - the _id of the document * @param {string} _params.filter - the _id of the document * @param {object} _params.newObj - the newObj of the document * @return {AqlQuery} - interface AqlQuery by arangodb */ async updatesByFilter(params) { try { await JoiUtils_1.JoiUtils.checkParams(RepositoryParams_1.UpdatesByFilterParamsSchema, params); let { filter, newObj, options } = params; let filterTemp = Object.assign({}, filter); //todo 检查Entity attributes let newObjTemp = Object.assign({}, newObj); // let { filter, sorts, options } = params; let tempQuery = this.queryBuilder(this.tableName); for (const key in filterTemp) { const data = filterTemp[key]; if (Array.isArray(data)) { // 数组参数,则‘in’ tempQuery = tempQuery.whereIn(key, data); delete filterTemp[key]; } else if (!!data && Object.prototype.toString.call(data) === '[object Object]') { //todo 暂时不支持 /** * 对象参数结构{opr, value} * 支持:==, !=, <, <=, >, >=, IN, NOT IN, LIKE, =~, !~ * 注意: typeof null === 'object' * 增加:opr = 'POSITION' 时需要处理数组属性的查询参数 */ tempQuery.where(`${key}`, data.opr, data.value); delete filterTemp[key]; } } if (Object.keys(filterTemp).length !== 0) { tempQuery = tempQuery.where(Object.assign({}, filterTemp)); } if (!!options && !!options.schema) { tempQuery = tempQuery.withSchema(options.schema); } if (!!options && !!options.returns) { tempQuery = tempQuery.returning(options.returns); } const query = tempQuery.update(Object.assign({}, newObjTemp)).toSQL().toNative(); let bindingsObj = {}; for (let i = 0; i < query.bindings.length; i++) { if (typeof query.bindings[i] === 'object' && query.bindings[i].constructor.name === 'ReturningHelper') { // bindingsObj[i] = { // [query.bindings[i].columnName]: { dir: oracledb.BIND_OUT } // }; query.sql = _.replace(query.sql, `:${i + 1}`, `:${query.bindings[i].columnName}`); //todo 通过Entity 获取 返回字段的变量类型 用以生成 outBinds type bindingsObj[query.bindings[i].columnName + ''] = { dir: oracledb.BIND_OUT }; } else { bindingsObj[i + 1] = query.bindings[i]; } } // console.log('bindingsObj: ', bindingsObj); console.log("updatesByFilter query: ", query); const result = await this.executeSql({ sql: query.sql, binds: bindingsObj, options: { autoCommit: true } }); return result.rows; } catch (err) { console.error("MssqlRepository updatesByFilter 失败!!!", err); throw Error(`MssqlRepository updatesByFilter 失败!!!, 错误: ${err}`); } } async save(params) { try { await JoiUtils_1.JoiUtils.checkParams(RepositoryParams_1.SaveParamsSchema, params); let { obj, options } = params; //todo 检查Entity attributes let tempQuery = this.queryBuilder(this.tableName); if (!!options && !!options.schema) { tempQuery = tempQuery.withSchema(options.schema); } if (!!options && !!options.returns) { tempQuery = tempQuery.returning(options.returns); } const query = tempQuery.insert(obj).toSQL().toNative(); let bindingsObj = {}; for (let i = 0; i < query.bindings.length; i++) { if (typeof query.bindings[i] === 'object' && query.bindings[i].constructor.name === 'ReturningHelper') { // bindingsObj[i] = { // [query.bindings[i].columnName]: { dir: oracledb.BIND_OUT } // }; query.sql = _.replace(query.sql, `:${i + 1}`, `:${query.bindings[i].columnName}`); bindingsObj[query.bindings[i].columnName + ''] = { dir: oracledb.BIND_OUT }; } else { bindingsObj[i + 1] = query.bindings[i]; } } const result = await this.executeSql({ sql: query.sql, binds: bindingsObj, options: { autoCommit: true } }); return result.rows; } catch (err) { console.error("MssqlRepository save 失败!!!", err); throw Error(`MssqlRepository save 失败!!!, 错误: ${err}`); } } async deletesByFilter(params) { try { await JoiUtils_1.JoiUtils.checkParams(RepositoryParams_1.DeletesByFilterParamsSchema, params); let { filter, options } = params; let filterTemp = Object.assign({}, filter); //todo 检查Entity attributes // let { filter, sorts, options } = params; let tempQuery = this.queryBuilder(this.tableName); for (const key in filterTemp) { const data = filterTemp[key]; if (Array.isArray(data)) { // 数组参数,则‘in’ tempQuery = tempQuery.whereIn(key, data); delete filterTemp[key]; } else if (!!data && Object.prototype.toString.call(data) === '[object Object]') { //todo 暂时不支持 /** * 对象参数结构{opr, value} * 支持:==, !=, <, <=, >, >=, IN, NOT IN, LIKE, =~, !~ * 注意: typeof null === 'object' * 增加:opr = 'POSITION' 时需要处理数组属性的查询参数 */ tempQuery.where(`${key}`, data.opr, data.value); } } if (Object.keys(filterTemp).length !== 0) { tempQuery = tempQuery.where(Object.assign({}, filterTemp)); } if (!!options && !!options.schema) { tempQuery = tempQuery.withSchema(options.schema); } //todo return can't work // if (!!options && !!options.returns) { // tempQuery = tempQuery.returning(options.returns) // } const query = tempQuery.del().toSQL().toNative(); let bindingsObj = {}; for (let i = 0; i < query.bindings.length; i++) { if (typeof query.bindings[i] === 'object' && query.bindings[i].constructor.name === 'ReturningHelper') { query.sql = _.replace(query.sql, `:${i + 1}`, `:${query.bindings[i].columnName}`); bindingsObj[query.bindings[i].columnName + ''] = { dir: oracledb.BIND_OUT }; } else { bindingsObj[i + 1] = query.bindings[i]; } } if (!!options && !!options.returns && Array.isArray(options.returns)) { let returningStr = ' returning'; for (let i = 0; i < options.returns.length; i++) { returningStr = returningStr + ` "${options.returns[i]}" INTO :${options.returns[i]}`; bindingsObj[options.returns[i] + ''] = { dir: oracledb.BIND_OUT }; } query.sql = query.sql + returningStr; } // console.log('bindingsObj: ', bindingsObj); const result = await this.executeSql({ sql: query.sql, binds: bindingsObj, options: { autoCommit: true } }); return result.rows; } catch (err) { console.error("MssqlRepository deletesByFilter 失败!!!", err); throw Error(`MssqlRepository deletesByFilter 失败!!!, 错误: ${err}`); } } async executeProcedure(params) { try { await JoiUtils_1.JoiUtils.checkParams(RepositoryParams_1.ExecuteProcedureParamsSchema, params); let { binds, options } = params; let bindsStr = ''; for (var key in binds) { bindsStr = bindsStr + ` :${key},`; } bindsStr = bindsStr.slice(0, -1); console.log('bindsStr:', bindsStr); var schema = ''; if (!!options && !!options.schema) { schema = options.schema; } const query = this.queryBuilder.raw(`BEGIN "${schema}"."${this.tableName}"(${bindsStr}); COMMIT; END;`).toSQL().toNative(); console.log('query: ', query); const result = await this.executeSql({ sql: query.sql, binds: binds }); return result.rows; } catch (err) { console.error("MssqlRepository executeProcedure 失败!!!", err); throw Error(`MssqlRepository executeProcedure 失败!!!, 错误: ${err}`); } } } exports.MssqlRepository = MssqlRepository; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTXNzcWxSZXBvc2l0b3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiTXNzcWxSZXBvc2l0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGdFQWVtQztBQUNuQyxrREFBK0M7QUFDL0Msd0RBQXFEO0FBQ3JELGdEQUFtRDtBQUNuRCwrQkFBNEI7QUFDNUIsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0FBQ3JDLE1BQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUM1QixJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxDQUFDO0FBQ3pDLElBQUksS0FBSyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxLQUFLLENBQUM7QUFFckMscUJBQXFCO0FBQ3JCLE1BQU0sVUFBVSxHQUFHO0lBQ2YsTUFBTSxFQUFFLEtBQUssQ0FBQyxPQUFPO0lBQ3JCLE1BQU0sRUFBRSxLQUFLLENBQUMsT0FBTztJQUNyQixJQUFJLEVBQUUsS0FBSyxDQUFDLFFBQVE7Q0FDdkIsQ0FBQTtBQUdEOzs7R0FHRztBQUNILE1BQWEsZUFBZTtJQWtCeEIsNEVBQTRFO0lBQzVFLGNBQWM7SUFDZCw0RUFBNEU7SUFDNUUsWUFBWSxXQUFnQixFQUFFLE9BQVk7UUFDdEMsc0JBQXNCO1FBQ3RCLElBQUk7WUFDQSxJQUFJLENBQUMsT0FBTyxFQUFFO2dCQUNWLE1BQU0sS0FBSyxDQUFDLDBDQUEwQyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQzthQUN4RjtZQUNELElBQUksQ0FBQyxVQUFVLEdBQUcsV0FBVyxDQUFDO1lBQzlCLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBQSxXQUFJLEVBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUM5QyxJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQztZQUN0QixJQUFJLENB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