zing-orm
Version:
386 lines • 34 kB
JavaScript
;
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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