import { Sequelize , Transaction } from 'sequelize' ; import { getBySequelize } from './squel.factory' ; import { BaseBuilder , Expression , FieldOptions , Select } from 'squel' ; import { Page } from '../model' ; export class Query { private readonly selectQuery : Select ; private readonly countQuery : Select ; private _pageSize : number ; private _page : number ; constructor ( private sequelize , private transaction ? ) { const squel = getBySequelize ( sequelize ) ; this . selectQuery = squel . select ( ) ; this . countQuery = squel . select ( ) . field ( '0' ) ; } distinct ( ) { this . selectQuery . distinct ( ) ; return this ; } field ( name , alias ? , options ? ) { this . selectQuery . field ( name , alias , options ) ; return this ; } fields ( fields , options ? ) { this . selectQuery . fields ( fields , options ) ; return this ; } from ( name , alias ? ) { this . selectQuery . from ( name , alias ) ; this . countQuery . from ( name , alias ) ; return this ; } join ( name , alias ? , condition ? ) { this . selectQuery . join ( name , alias , condition ) ; this . countQuery . join ( name , alias , condition ) ; return this ; } left_join ( name , alias ? , condition ? ) { this . selectQuery . left_join ( name , alias , condition ) ; this . countQuery . left_join ( name , alias , condition ) ; return this ; } right_join ( name , alias ? , condition ? ) { this . selectQuery . right_join ( name , alias , condition ) ; this . countQuery . right_join ( name , alias , condition ) ; return this ; } outer_join ( name , alias ? , condition ? ) { this . selectQuery . outer_join ( name , alias , condition ) ; this . countQuery . outer_join ( name , alias , condition ) ; return this ; } where ( condition , ... args ) { this . selectQuery . where ( condition , ... args ) ; this . countQuery . where ( condition , ... args ) ; return this ; } having ( condition , ... args ) { this . selectQuery . having ( condition , ... args ) ; this . countQuery . having ( condition , ... args ) ; return this ; } order ( field , direction ? , ... values ) { this . selectQuery . order ( field , direction , ... values ) ; return this ; } group ( field ) { this . selectQuery . group ( field ) ; this . countQuery . group ( field ) ; return this ; } limit ( limit ) { this . selectQuery . limit ( limit ) ; return this ; } offset ( offset ) { this . selectQuery . offset ( offset ) ; return this ; } async getPage ( ) { const pageSize = this . _pageSize ; const page = this . _page ; const [ result , count ] = await Promise . all ( [ this . list ( ) , this . count ( ) ] ) ; return { list : result , count : count , page , pages : Math . ceil ( count / pageSize ) } ; } size ( size ) { if ( size === undefined || size === null ) return this ; this . _pageSize = size ; this . limit ( size ) ; return this ; } page ( page , size ) { this . size ( size ) ; this . _page = page ; this . offset ( ( page - 1 ) * size ) ; return this ; } async list ( ) { const { text , values } = this . selectQuery . toParam ( ) ; const [ result ] = await this . sequelize . query ( text , { replacements : values , transaction : this . transaction } ) ; return result ; } ; async single ( ) { const { text , values } = this . selectQuery . limit ( 1 ) . toParam ( ) ; const [ result ] = await this . sequelize . query ( text , { replacements : values , transaction : this . transaction } ) ; return result . length ? result [ 0 ] : null ; } async count ( ) { const { text , values } = this . countQuery . toParam ( ) ; const query = `SELECT COUNT(*) as cnt FROM (${ text }) c` ; const [ countResult ] = await this . sequelize . query ( query , { replacements : values , transaction : this . transaction } ) ; return parseInt ( countResult [ 0 ] . cnt , 10 ) ; } }