UNPKG

zing-orm

Version:
386 lines 34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OracleRepository = void 0; const RepositoryParams_1 = require("../types/RepositoryParams"); const JoiUtils_1 = require("../../util/JoiUtils"); const globals_1 = require("../../util/globals"); const knex_1 = require("knex"); const oracledb = require('oracledb'); const _ = require('lodash'); /** * Entity manager supposed to work with any entity, automatically find its repository and call its methods, * whatever entity type are you passing. */ class OracleRepository { // ------------------------------------------------------------------------- // 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: 'oracledb' }); this.entity = _entity; this.tableName = (0, globals_1.findTableName)(_entity); } catch (err) { //todo console.error("初始化 OracleRepository Class 失败!!!", err); } // }) } // ------------------------------------------------------------------------- // Public Methods // ------------------------------------------------------------------------- async executeSql(params) { try { await JoiUtils_1.JoiUtils.checkParams(RepositoryParams_1.ExecuteSqlParamsSchema, params); return await OracleRepository.executeSqlRaw(this.connection, params); } catch (err) { console.log("executeSql error:", err); } } static async executeSqlRaw(connection, params) { try { await JoiUtils_1.JoiUtils.checkParams(RepositoryParams_1.ExecuteSqlParamsSchema, params); var { sql, binds = {}, options = {} } = params; console.log("executeSqlRaw params: ", sql, binds, options); let result = await connection.execute(sql, binds, options); console.log("executeSqlRaw Query results: "); console.dir(result); return result; } 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("OracleRepository getPage 失败!!!", err); throw Error(`OracleRepository 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("OracleRepository getsByFilter 失败!!!", err); throw Error(`OracleRepository 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.outBinds; } catch (err) { console.error("OracleRepository updatesByFilter 失败!!!", err); throw Error(`OracleRepository 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.outBinds; } catch (err) { console.error("OracleRepository save 失败!!!", err); throw Error(`OracleRepository 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); delete filterTemp[key]; } } 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.outBinds; } catch (err) { console.error("OracleRepository deletesByFilter 失败!!!", err); throw Error(`OracleRepository 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.outBinds; } catch (err) { console.error("OracleRepository executeProcedure 失败!!!", err); throw Error(`OracleRepository executeProcedure 失败!!!, 错误: ${err}`); } } } exports.OracleRepository = OracleRepository; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3JhY2xlUmVwb3NpdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIk9yYWNsZVJlcG9zaXRvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsZ0VBZW1DO0FBQ25DLGtEQUErQztBQUMvQyxnREFBbUQ7QUFDbkQsK0JBQTRCO0FBQzVCLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUNyQyxNQUFNLENBQUMsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDNUI7OztHQUdHO0FBQ0gsTUFBYSxnQkFBZ0I7SUFrQnpCLDRFQUE0RTtJQUM1RSxjQUFjO0lBQ2QsNEVBQTRFO0lBQzVFLFlBQVksV0FBZ0IsRUFBRSxPQUFZO1FBQ3RDLHNCQUFzQjtRQUN0QixJQUFJO1lBQ0EsSUFBSSxDQUFDLE9BQU8sRUFBRTtnQkFDVixNQUFNLEtBQUssQ0FBQywwQ0FBMEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDeEY7WUFDRCxJQUFJLENBQUMsVUFBVSxHQUFHLFdBQVcsQ0FBQztZQUM5QixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUEsV0FBSSxFQUFDLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7WUFDakQsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUM7WUFDdEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFBLHVCQUFhLEVBQUMsT0FBTyxDQUFDLENBQUM7U0FDM0M7UUFBQyxPQUFPLEdBQUcsRUFBRTtZQUNWLE1BQU07WUFDTixPQUFPLENBQUMsS0FBSyxDQUFDLGtDQUFrQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1NBQzFEO1FBQ0QsS0FBSztJQUNULENBQUM7SUFFRCw0RUFBNEU7SUFDNUUsaUJBQWlCO0lBQ2pCLDRFQUE0RTtJQUU1RSxLQUFLLENBQUMsVUFBVSxDQUFDLE1BQXdCO1FBQ3JDLElBQUk7WUFDQSxNQUFNLG1CQUFRLENB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