import { inject , injectable } from 'inversify' ; import * as apid from '../../../api' ; import Recorded from '../../db/entities/Recorded' ; import RecordedTag from '../../db/entities/RecordedTag' ; import StrUtil from '../../util/StrUtil' ; import IPromiseRetry from '../IPromiseRetry' ; import DBUtil from './DBUtil' ; import IDBOperator from './IDBOperator' ; import IRecordedTagDB from './IRecordedTagDB' ; @ injectable ( ) export default class RecordedTagDB implements IRecordedTagDB { private op : IDBOperator ; private promieRetry : IPromiseRetry ; constructor ( @ inject ( 'IDBOperator' ) op , @ inject ( 'IPromiseRetry' ) promieRetry ) { this . op = op ; this . promieRetry = promieRetry ; } param items return public async restore ( items ) { const connection = await this . op . getConnection ( ) ; const queryRunner = connection . createQueryRunner ( ) ; await queryRunner . startTransaction ( ) ; let hasError = false ; try { await queryRunner . manager . delete ( RecordedTag , { } ) ; for ( const item of items ) { await queryRunner . manager . insert ( RecordedTag , item ) ; } await queryRunner . commitTransaction ( ) ; } catch ( err ) { console . error ( err ) ; hasError = err ; await queryRunner . rollbackTransaction ( ) ; } finally { await queryRunner . release ( ) ; } if ( hasError ) { throw new Error ( 'restore error' ) ; } } param tag return public async insertOnce ( tag ) { const connection = await this . op . getConnection ( ) ; const queryBuilder = connection . createQueryBuilder ( ) . insert ( ) . into ( RecordedTag ) . values ( tag ) ; const insertedResult = await this . promieRetry . run ( ( ) => { return queryBuilder . execute ( ) ; } ) ; return insertedResult . identifiers [ 0 ] . id ; } param tagId param name param color return public async updateOnce ( tagId , name , color ) { const tag = await this . findId ( tagId ) ; if ( tag === null ) { throw new Error ( 'TagIsNull' ) ; } const connection = await this . op . getConnection ( ) ; const queryBuilder = connection . createQueryBuilder ( ) . update ( RecordedTag ) . set ( { name : name , color : color , halfWidthName : StrUtil . toHalf ( name ) , } ) . where ( { id : tagId } ) ; await this . promieRetry . run ( ( ) => { return queryBuilder . execute ( ) ; } ) ; } param tagId param recordedId return public async setRelation ( tagId , recordedId ) { const recorded = await this . findRecorded ( recordedId ) ; const tag = await this . findId ( tagId ) ; if ( tag === null ) { throw new Error ( 'RecordedTagIsUndefined' ) ; } recorded . tags . push ( tag ) ; await this . promieRetry . run ( ( ) => { return recorded . save ( ) ; } ) ; } private async findRecorded ( recordedId ) { const connection = await this . op . getConnection ( ) ; const queryBuilder = await connection . getRepository ( Recorded ) . createQueryBuilder ( 'recorded' ) . where ( { id : recordedId } ) . leftJoinAndSelect ( 'recorded.tags' , 'recorded_tag' ) ; const recorded = await this . promieRetry . run ( ( ) => { return queryBuilder . getOne ( ) ; } ) ; if ( typeof recorded === 'undefined' ) { throw new Error ( 'RecordedIsUndefined' ) ; } return recorded ; } param tagid param recordedId Promise public async deleteRelation ( tagId , recordedId ) { const recorded = await this . findRecorded ( recordedId ) ; recorded . tags = recorded . tags . filter ( tag => { return tag . id !== tagId ; } ) ; await this . promieRetry . run ( ( ) => { return recorded . save ( ) ; } ) ; } param recordedId return public async deleteAllRelation ( recordedId ) { const recorded = await this . findRecorded ( recordedId ) ; recorded . tags = [ ] ; await this . promieRetry . run ( ( ) => { return recorded . save ( ) ; } ) ; } param tagId return public async deleteOnce ( tagId ) { const connection = await this . op . getConnection ( ) ; const queryBuilder = connection . createQueryBuilder ( ) . delete ( ) . from ( RecordedTag ) . where ( { id : tagId , } ) ; await this . promieRetry . run ( ( ) => { return queryBuilder . execute ( ) ; } ) ; } param tagId return public async findId ( tagId ) { const connection = await this . op . getConnection ( ) ; const queryBuilder = connection . getRepository ( RecordedTag ) . createQueryBuilder ( 'recorded_tag' ) . where ( { id : tagId } ) ; const result = await this . promieRetry . run ( ( ) => { return queryBuilder . getOne ( ) ; } ) ; return typeof result === 'undefined' ? null : result ; } param option return public async findAll ( option ) { const connection = await this . op . getConnection ( ) ; let queryBuilder = connection . getRepository ( RecordedTag ) . createQueryBuilder ( 'recorded' ) ; const querys = [ ] ; if ( typeof option . excludeTagId !== 'undefined' ) { querys . push ( { query : 'id not in (:...id)' , values : { id : option . excludeTagId , } , } ) ; } if ( typeof option . name !== 'undefined' ) { const names = StrUtil . toHalf ( option . name ) . split ( / / ) ; const like = this . op . getLikeStr ( false ) ; const nameAnd = [ ] ; const values = { } ; names . forEach ( ( str , i ) => { str = `%${ str }%` ; const valueName = `name${ i }` ; values [ valueName ] = str ; nameAnd . push ( `halfWidthName ${ like } :${ valueName }` ) ; } ) ; const or = [ ] ; if ( nameAnd . length > 0 ) { or . push ( `(${ DBUtil . createAndQuery ( nameAnd ) })` ) ; } querys . push ( { query : DBUtil . createOrQuery ( or ) , values : values , } ) ; } for ( const q of querys ) { queryBuilder = queryBuilder . andWhere ( q . query , q . values ) ; } if ( typeof option . offset !== 'undefined' ) { queryBuilder = queryBuilder . skip ( option . offset ) ; } if ( typeof option . limit !== 'undefined' ) { queryBuilder = queryBuilder . take ( option . limit ) ; } return await this . promieRetry . run ( ( ) => { return queryBuilder . getManyAndCount ( ) ; } ) ; } }