import { computed , makeObservable } from 'mobx' ; import { DataTypeLogicalOperation , ResultDataFormat , SqlDataFilterConstraint } from '@cloudbeaver/core-sdk' ; import { DatabaseDataAction } from '../../DatabaseDataAction' ; import type { IDatabaseDataOptions } from '../../IDatabaseDataOptions' ; import type { IDatabaseDataSource } from '../../IDatabaseDataSource' ; import type { IDatabaseResultSet } from '../../IDatabaseResultSet' ; import { EOrder , Order } from '../../Order' ; import { databaseDataAction } from '../DatabaseDataActionDecorator' ; import type { IDatabaseDataConstraintAction } from '../IDatabaseDataConstraintAction' ; export const IS_NULL_ID = 'IS_NULL' ; export const IS_NOT_NULL_ID = 'IS_NOT_NULL' ; @ databaseDataAction ( ) export class ResultSetConstraintAction extends DatabaseDataAction < IDatabaseDataOptions , IDatabaseResultSet > implements IDatabaseDataConstraintAction < IDatabaseResultSet > { static dataFormat = [ ResultDataFormat . Resultset , ResultDataFormat . Document ] ; get supported ( ) : boolean { return this . source . results . length < 2 ; } get orderConstraints ( ) : SqlDataFilterConstraint [ ] { if ( ! this . source . options ) { throw new Error ( 'Options must be provided' ) ; } return this . source . options . constraints . filter ( isOrderConstraint ) ; } get filterConstraints ( ) : SqlDataFilterConstraint [ ] { if ( ! this . source . options ) { throw new Error ( 'Options must be provided' ) ; } return this . source . options . constraints . filter ( isFilterConstraint ) ; } constructor ( source , result ) { super ( source , result ) ; makeObservable ( this , { orderConstraints : computed , filterConstraints : computed , } ) ; } private deleteConstraint ( attribute ) { if ( ! this . source . options ) { return ; } this . source . options . constraints = this . source . options . constraints . filter ( constraint => constraint . attribute !== attribute ) ; } private deleteEmptyConstraint ( attribute ) { const constraint = this . get ( attribute ) ; if ( constraint && ! isFilterConstraint ( constraint ) && ! isOrderConstraint ( constraint ) ) { this . deleteConstraint ( attribute ) ; } } private getMaxOrderPosition ( ) { return Math . max ( 0 , ... this . orderConstraints . map ( constraint => constraint . orderPosition !== undefined ? constraint . orderPosition + 1 : - 1 ) ) ; } get ( attribute ) { if ( ! this . source . options ) { throw new Error ( 'Options must be provided' ) ; } return this . source . options . constraints . find ( constraint => constraint . attribute === attribute ) ; } deleteAll ( ) { if ( ! this . source . options ) { return ; } this . source . options . constraints = [ ] ; } deleteFilter ( attribute ) { const constraint = this . get ( attribute ) ; if ( constraint ) { deleteLogicalOperationFromConstraint ( constraint ) ; this . deleteEmptyConstraint ( attribute ) ; } } deleteFilters ( ) { if ( ! this . source . options ) { throw new Error ( 'Options must be provided' ) ; } const newConstraints = [ ] ; for ( const constraint of this . source . options . constraints ) { deleteLogicalOperationFromConstraint ( constraint ) ; if ( isOrderConstraint ( constraint ) ) { newConstraints . push ( constraint ) ; } } this . source . options . constraints = newConstraints ; } deleteOrders ( ) { if ( ! this . source . options ) { throw new Error ( 'Options must be provided' ) ; } const newConstraints = [ ] ; for ( const constraint of this . source . options . constraints ) { deleteOrderFromConstraint ( constraint ) ; if ( isFilterConstraint ( constraint ) ) { newConstraints . push ( constraint ) ; } } this . source . options . constraints = newConstraints ; } deleteOrder ( attribute ) { const constraint = this . get ( attribute ) ; if ( constraint ) { deleteOrderFromConstraint ( constraint ) ; this . deleteEmptyConstraint ( attribute ) ; } } deleteDataFilters ( ) { if ( ! this . source . options ) { throw new Error ( 'Options must be provided' ) ; } this . deleteFilters ( ) ; this . source . options . whereFilter = '' ; } deleteData ( ) { if ( ! this . source . options ) { throw new Error ( 'Options must be provided' ) ; } this . deleteAll ( ) ; this . source . options . whereFilter = '' ; } setFilter ( attribute , operator , value ? ) { if ( ! this . source . options ) { throw new Error ( 'Options must be provided' ) ; } const currentConstraint = this . get ( attribute ) ; if ( currentConstraint ) { currentConstraint . operator = operator ; if ( value !== undefined ) { currentConstraint . value = value ; } else if ( currentConstraint . value !== undefined ) { delete currentConstraint . value ; } return ; } const constraint = { attribute , operator , } ; if ( value !== undefined ) { constraint . value = value ; } this . source . options . constraints . push ( constraint ) ; } setOrder ( attribute , order , multiple ) { if ( ! this . source . options ) { throw new Error ( 'Options must be provided' ) ; } const resetOrder = order === null ; if ( ! multiple ) { this . deleteOrders ( ) ; } const currentConstraint = this . get ( attribute ) ; if ( ! currentConstraint ) { if ( ! resetOrder ) { this . source . options . constraints . push ( { attribute , orderPosition : this . getMaxOrderPosition ( ) , orderAsc : order === EOrder . asc , } ) ; } return ; } if ( ! resetOrder ) { if ( ! isOrderConstraint ( currentConstraint ) ) { currentConstraint . orderPosition = this . getMaxOrderPosition ( ) ; } currentConstraint . orderAsc = order === EOrder . asc ; } else { if ( isFilterConstraint ( currentConstraint ) ) { deleteOrderFromConstraint ( currentConstraint ) ; } else { this . deleteConstraint ( currentConstraint . attribute ) ; } } } getOrder ( attribute ) { if ( ! this . source . options ) { throw new Error ( 'Options must be provided' ) ; } const currentConstraint = this . get ( attribute ) ; if ( ! currentConstraint || ! isOrderConstraint ( currentConstraint ) ) { return null ; } return currentConstraint . orderAsc ? EOrder . asc : EOrder . desc ; } } export function nullOperationsFilter ( operation ) { return operation . id === IS_NULL_ID || operation . id === IS_NOT_NULL_ID ; } export function getNextOrder ( order ) { switch ( order ) { case EOrder . asc : return EOrder . desc ; case EOrder . desc : return null ; default : return EOrder . asc ; } } export function wrapOperationArgument ( operationId , argument ) { if ( operationId === 'LIKE' ) { return `%${ argument }%` ; } return argument ; } export function isFilterConstraint ( constraint ) { return constraint . operator !== undefined ; } export function isOrderConstraint ( constraint ) { return constraint . orderAsc !== undefined ; } function deleteOrderFromConstraint ( constraint ) { delete constraint . orderAsc ; delete constraint . orderPosition ; return constraint ; } function deleteLogicalOperationFromConstraint ( constraint ) { delete constraint . operator ; delete constraint . value ; return constraint ; }