UNPKG

es-entity

Version:

ORM framework for Node js based on Ecmascript 6 and Typescript.

220 lines (182 loc) 6.9 kB
import { Transform } from 'stream'; import Context from '../Context.js'; import { TABLE_COLUMN_KEYS } from '../decorators/Constants.js'; import * as model from '../model/index.js'; import * as types from '../model/types.js'; import * as sql from '../sql/index.js'; import DBSet from './DBSet.js'; import IQuerySet from './IQuerySet.js'; import SelectQuerySet from './SelectQuerySet.js'; /** * QuerySet */ class QuerySet<T extends Object> extends IQuerySet<T> { protected EntityType: types.IEntityType<T>; protected dbSet: DBSet; alias: string; stat = new sql.Statement(); selectKeys: string[]; constructor(context: Context, EntityType: types.IEntityType<T>, dbSet: DBSet) { super(); this.context = context; this.EntityType = EntityType; this.dbSet = dbSet; this.alias = this.dbSet.tableName.charAt(0); this.stat.collection.value = this.dbSet.tableName; this.stat.collection.alias = this.alias; this.selectKeys = Reflect.getMetadata(TABLE_COLUMN_KEYS, this.EntityType.prototype); } // getEntity() { // let res = new this.EntityType(); // let keys: string[] = Reflect.getMetadata(TABLE_COLUMN_KEYS, this.EntityType.prototype); // keys.forEach(key => { // let field = Reflect.get(res, key); // if (field instanceof model.LinkObject || field instanceof model.LinkArray) { // field.bind(this.context, res); // } // }); // return res; // } // Select Functions prepareSelectStatement() { this.stat.command = sql.types.Command.SELECT; // Get all Columns let targetKeys: string[] = Reflect.getMetadata(TABLE_COLUMN_KEYS, this.EntityType.prototype); let fields = this.dbSet.filterFields(targetKeys); this.stat.columns = this.getColumnExprs(fields, this.alias); } async list() { this.prepareSelectStatement(); let result = await this.context.execute(this.stat); return result.rows.map(this.transformer); } transformer(row: any) { let obj = new this.EntityType(); this.selectKeys.forEach(key => { let fieldMapping = this.dbSet.fieldMap.get(key); if (fieldMapping) { let colName = fieldMapping.colName; let val = row[colName]; Reflect.set(obj, key, val); } else { let field = Reflect.get(obj, key); if (field instanceof model.LinkObject || field instanceof model.LinkArray) { field.bind(this.context, obj); } } }); return obj; } async stream() { this.prepareSelectStatement(); let dataStream = await this.context.stream(this.stat); let that = this; return dataStream.pipe( new Transform({ transform(chunk, encoding, callback) { callback(null, that.transformer(chunk)); } }) ); } async listPlain(keys: (keyof T)[]): Promise<Partial<T>[]> { this.stat.command = sql.types.Command.SELECT; let fields = this.dbSet.filterFields(<string[]>keys); this.stat.columns = this.getColumnExprs(fields, this.alias); let input = await this.context.execute(this.stat); let data = input.rows.map(row => { let obj: Partial<T> = {}; fields.forEach(field => { let colName = field.colName; let val = row[colName] ?? row[colName.toLowerCase()] ?? row[colName.toUpperCase()]; Reflect.set(obj, field.fieldName, val); }); return obj; }); return data; } // Selection Functions select<U extends Object>(EntityType: types.IEntityType<U>): IQuerySet<U> { let res = new SelectQuerySet(this.context, EntityType, this.dbSet); return res; } // Conditional Functions where(param: types.IWhereFunc<model.WhereExprBuilder<T>>, ...args: any[]) { let fieldMap = new Map(Array.from(this.dbSet.fieldMap)); let eb = new model.WhereExprBuilder<T>(fieldMap); let res = param(eb, args); if (res && res instanceof sql.Expression && res.exps.length > 0) { this.stat.where = this.stat.where.add(res); } return this; } groupBy(param: types.IArrFieldFunc<model.GroupExprBuilder<T>>) { let fieldMap = new Map(Array.from(this.dbSet.fieldMap)); let eb = new model.GroupExprBuilder<T>(fieldMap); let res = param(eb); if (res && Array.isArray(res)) { res.forEach(expr => { if (expr instanceof sql.Expression && expr.exps.length > 0) { this.stat.groupBy.push(expr); } }); } return this; } orderBy(param: types.IArrFieldFunc<model.OrderExprBuilder<T>>) { let fieldMap = new Map(Array.from(this.dbSet.fieldMap)); let eb = new model.OrderExprBuilder<T>(fieldMap); let res = param(eb); if (res && Array.isArray(res)) { res.forEach(a => { if (a instanceof sql.Expression && a.exps.length > 0) { this.stat.orderBy.push(a); } }); } return this; } limit(size: number, index?: number) { this.stat.limit = new sql.Expression(null, sql.types.Operator.Limit); this.stat.limit.exps.push(new sql.Expression(size.toString())); if (index) { this.stat.limit.exps.push(new sql.Expression(index.toString())); } return this; } async update(entity: T, ...updatedKeys: (keyof T)[]) { this.stat.command = sql.types.Command.UPDATE; // Dynamic update let keys: string[] = Reflect.getMetadata(TABLE_COLUMN_KEYS, entity.constructor.prototype); let fields = this.dbSet.filterFields(keys).filter(field => (<(string | symbol)[]>updatedKeys).includes(field.fieldName)); if (fields.length == 0) throw new Error('Update Fields Empty'); fields.forEach(field => { let c1 = new sql.Expression(field.colName); let c2 = new sql.Expression('?'); let val = Reflect.get(entity, field.fieldName); c2.args.push(val); let expr = new sql.Expression(null, sql.types.Operator.Equal, c1, c2); this.stat.columns.push(expr); }); let result = await this.context.execute(this.stat); if (result.error) throw result.error; } async delete() { this.stat.command = sql.types.Command.DELETE; let result = await this.context.execute(this.stat); if (result.error) throw result.error; } // join<A extends Object>(coll: IQuerySet<A>, param: types.IJoinFunc<model.WhereExprBuilder<T>, model.GroupExprBuilder<A>>, joinType?: sql.types.Join): IQuerySet<T & A> { // joinType = joinType ?? sql.types.Join.InnerJoin; // let temp: sql.Expression | null = null; // if (param && param instanceof Function) { // let mainObj = new model.WhereExprBuilder<T>(this.dbSet.fieldMap); // let joinObj = new model.GroupExprBuilder(coll.) coll.getEntity(); // temp = param(mainObj, joinObj); // } // if (!(temp && temp instanceof sql.Expression && temp.exps.length > 0)) // throw new Error('Invalid Join'); // return new JoinQuerySet<T, A>(this, coll, joinType, temp); // } } export default QuerySet;