Skip to content
Snippets Groups Projects
Select Git revision
  • 04b2867392454b67521a6ab663f68b3daa204133
  • master default protected
  • replication_test
  • dev protected
  • release-1.10 protected
  • 556-usage-statistics
  • 553-semantic-recommendation-2
  • 553-semantic-recommendation
  • release-1.9 protected
  • 551-init-broker-service-permissions
  • 549-test-oai-pmh
  • 545-saving-multiple-times-breaks-pid-metadata
  • 499-standalone-compute-service-2
  • 539-load-tests
  • hotfix/helm-chart
  • luca_ba_new_interface
  • 534-bug-when-adding-access-to-user-that-is-not-registered-at-dashboard-service
  • release-1.8 protected
  • 533-integrate-semantic-recommendation
  • feature/openshift
  • 518-spark-doesn-t-map-the-headers-correct
  • v1.10.4 protected
  • v1.10.3 protected
  • v1.10.2 protected
  • v1.10.1 protected
  • v1.10.0-rc13 protected
  • v1.10.0-rc12 protected
  • v1.10.0-rc11 protected
  • v1.10.0-rc10 protected
  • v1.10.0-rc9 protected
  • v1.10.0-rc8 protected
  • v1.10.0-rc7 protected
  • v1.10.0-rc6 protected
  • v1.10.0-rc5 protected
  • v1.10.0-rc4 protected
  • v1.10.0-rc3 protected
  • v1.10.0-rc2 protected
  • v1.10.0rc1 protected
  • v1.10.0rc0 protected
  • v1.10.0 protected
  • v1.9.3 protected
41 results

query-service.ts

Blame
  • Martin Weise's avatar
    Martin Weise authored
    04b28673
    History
    query-service.ts 11.52 KiB
    import {format} from 'sql-formatter'
    import type {AxiosRequestConfig} from 'axios'
    import {axiosErrorToApiError} from '@/utils'
    
    export const useQueryService = (): any => {
      async function findAll(databaseId: number, persisted: boolean): Promise<QueryDto[]> {
        const axios = useAxiosInstance()
        console.debug('find queries')
        return new Promise<QueryDto[]>((resolve, reject) => {
          axios.get<QueryDto[]>(`/api/database/${databaseId}/subset`, {params: (persisted && {persisted})})
            .then((response) => {
              console.info(`Found ${response.data.length} query(s)`)
              resolve(response.data)
            })
            .catch((error) => {
              if (error.response.status === 403) {
                /* ignore */
                resolve([])
              }
              console.error('Failed to find queries', error)
              reject(axiosErrorToApiError(error))
            })
        })
      }
    
      async function findOne(databaseId: number, queryId: number): Promise<QueryDto> {
        const axios = useAxiosInstance()
        console.debug('find query with id', queryId, 'in database with id', databaseId)
        return new Promise<QueryDto>((resolve, reject) => {
          axios.get<QueryDto>(`/api/database/${databaseId}/subset/${queryId}`)
            .then((response) => {
              console.info('Found query with id', queryId, 'in database with id', databaseId)
              resolve(response.data)
            })
            .catch((error) => {
              console.error('Failed to find query', error)
              reject(axiosErrorToApiError(error))
            })
        })
      }
    
      async function update(databaseId: number, queryId: number, data: QueryPersistDto): Promise<QueryDto> {
        const axios = useAxiosInstance()
        console.debug('update query with id', queryId, 'in database with id', databaseId)
        return new Promise<QueryDto>((resolve, reject) => {
          axios.put<QueryDto>(`/api/database/${databaseId}/subset/${queryId}`, data)
            .then((response) => {
              console.info('Updated query with id', queryId, 'in database with id', databaseId)
              resolve(response.data)
            })
            .catch((error) => {
              console.error('Failed to update query', error)
              reject(axiosErrorToApiError(error))
            })
        })
      }
    
      async function exportCsv(databaseId: number, queryId: number): Promise<any> {
        const axios = useAxiosInstance()
        const config: AxiosRequestConfig = {
          responseType: 'blob',
          headers: {
            Accept: 'text/csv'
          }
        }
        console.debug('export query with id', queryId, 'in database with id', databaseId)
        return new Promise<any>((resolve, reject) => {
          axios.get<any>(`/api/database/${databaseId}/subset/${queryId}`, config)
            .then((response) => {
              console.info('Exported query with id', queryId, 'in database with id', databaseId)
              resolve(response.data)
            })
            .catch((error) => {
              console.error('Failed to export query', error)
              reject(axiosErrorToApiError(error))
            })
        })
      }
    
      async function execute(databaseId: number, data: ExecuteStatementDto, timestamp: Date | null, page: number, size: number): Promise<QueryResultDto> {
        const axios = useAxiosInstance()
        console.debug('execute query in database with id', databaseId)
        return new Promise<QueryResultDto>((resolve, reject) => {
          axios.post<QueryResultDto>(`/api/database/${databaseId}/subset`, data, {params: mapFilter(timestamp, page, size), timeout: 600_000})
            .then((response) => {
              console.info('Executed query with id', response.data.id, ' in database with id', databaseId)
              resolve(response.data)
            })
            .catch((error) => {
              console.error('Failed to execute query', error)
              reject(axiosErrorToApiError(error))
            })
        })
      }
    
      async function reExecuteData(databaseId: number, queryId: number, page: number, size: number): Promise<QueryResultDto> {
        const axios = useAxiosInstance()
        console.debug('re-execute query in database with id', databaseId)
        return new Promise<QueryResultDto>((resolve, reject) => {
          axios.get<QueryResultDto>(`/api/database/${databaseId}/subset/${queryId}/data`, { params: mapFilter(null, page, size) })
            .then((response) => {
              console.info('Re-executed query in database with id', databaseId)
              resolve(response.data)
            })
            .catch((error) => {
              console.error('Failed to re-execute query', error)
              reject(axiosErrorToApiError(error))
            })
        })
      }
    
      async function reExecuteCount(databaseId: number, queryId: number): Promise<number> {
        const axios = useAxiosInstance()
        console.debug('re-execute query in database with id', databaseId)
        return new Promise<number>((resolve, reject) => {
          axios.head<void>(`/api/database/${databaseId}/subset/${queryId}/data`)
            .then((response) => {
              const count: number = Number(response.headers['x-count'])
              console.info('Found', count, 'tuples for query', queryId, 'in database with id', databaseId)
              resolve(count)
            })
            .catch((error) => {
              console.error('Failed to re-execute query', error)
              reject(axiosErrorToApiError(error))
            })
        })
      }
    
      function build(table: TableDto, columns: ColumnDto[], clauses: any[]): QueryBuildResultDto {
        var sql = 'SELECT'
        for (let i = 0; i < columns.length; i++) {
          sql += `${i > 0 ? ',' : ''} \`${columns[i].internal_name}\``
        }
        sql += ` FROM \`${table}\``
        if (clauses.length > 0) {
          sql += ' WHERE'
          for (let i = 0; i < clauses.length; i++) {
            const clause = clauses[i]
            if (clause.type === 'and' || clause.type === 'or') {
              sql += ` ${clause.type.toUpperCase()} `
              continue
            }
            const fCol = columns.filter(c => c.internal_name === clause.params[0])
            if (fCol.length === 0) {
              return {
                error: true,
                reason: 'column.exists',
                column: clause.params[0],
                raw: null,
                formatted: null
              }
            }
            sql += ` \`${clause.params[0]}\` ${clause.params[1]} `
            const fCon = mySql8DataTypes().filter(t => t.value === fCol[0].column_type)
            if (fCol.length === 0) {
              return {
                error: true,
                reason: 'type.exists',
                column: fCol[0].column_type,
                raw: null,
                formatted: null
              }
            }
            if (!fCon[0].isBuildable) {
              return {
                error: true,
                reason: 'type.build',
                column: fCol[0].column_type,
                raw: null,
                formatted: null
              }
            }
            if (fCon[0].quoted) {
              sql += `'${clause.params[2]}'`
            } else {
              sql += `${clause.params[2]}`
            }
          }
        }
        return {
          error: false,
          reason: null,
          column: null,
          raw: sql,
          formatted: format(sql, {
            language: 'mysql',
            keywordCase: 'upper'
          })
        }
      }
    
      function mapFilter(timestamp: Date | null, page: number, size: number) {
        if (!timestamp) {
          return {page, size}
        }
        return {timestamp, page, size}
      }
    
      function mySql8DataTypes(): MySql8DataType[] {
        return [
          {value: 'bigint', text: 'BIGINT(size)', defaultSize: null, defaultD: null, signed: null, zerofill: false, quoted: false, isBuildable: true, hint: null},
          {value: 'binary', text: 'BINARY(size)', minSize: 0, maxSize: 255, defaultSize: 255, defaultD: null, quoted: false, isBuildable: false, hint: 'size in Bytes'},
          {value: 'bit', text: 'BIT(size)', minSize: 1, maxSize: 64, defaultSize: null, defaultD: null, quoted: false, isBuildable: true, hint: null},
          {value: 'blob', text: 'BLOB(size)', minSize: 0, maxSize: 65535, defaultSize: null, defaultD: null, quoted: false, isBuildable: false, hint: 'size in Bytes'},
          {value: 'bool', text: 'BOOL', defaultSize: null, defaultD: null, quoted: false, isBuildable: true},
          {value: 'char', text: 'CHAR(size)', minSize: 0, maxSize: 255, defaultSize: 255, defaultD: null, quoted: true, isBuildable: true},
          {value: 'date', text: 'DATE', defaultSize: null, defaultD: null, quoted: true, isBuildable: true, hint: 'min. 1000-01-01, max. 9999-12-31'},
          {value: 'datetime', text: 'DATETIME(fsp)', minSize: 0, maxSize: 6, defaultSize: null, defaultD: null, quoted: true, isBuildable: true, hint: 'fsp=microsecond precision, min. 1000-01-01 00:00:00.0, max. 9999-12-31 23:59:59.9'},
          {value: 'decimal', text: 'DECIMAL(size, d)', minSize: 0, maxSize: 65, defaultSize: null, defaultD: null, minD: 0, maxD: 38, signed: null, quoted: false, isBuildable: true},
          {value: 'double', text: 'DOUBLE(size, d)', defaultSize: null, defaultD: null, signed: null, quoted: false, isBuildable: true},
          {value: 'enum', text: 'ENUM(val1,val2,...)', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
          {value: 'float', text: 'FLOAT(p)', defaultSize: null, defaultD: null, signed: null, quoted: false, isBuildable: true},
          {value: 'int', text: 'INT(size)', defaultSize: null, defaultD: null, signed: null, zerofill: false, quoted: false, isBuildable: true, hint: 'size in Bytes'},
          {value: 'longblob', text: 'LONGBLOB', defaultSize: null, defaultD: null, quoted: false, isBuildable: false, hint: 'max. 3.999 GiB'},
          {value: 'longtext', text: 'LONGTEXT', defaultSize: null, defaultD: null, quoted: true, isBuildable: true,  hint: 'max. 3.999 GiB'},
          {value: 'mediumblob', text: 'MEDIUMBLOB', defaultSize: null, defaultD: null, quoted: false, isBuildable: false, hint: 'max. 15.999 MiB'},
          {value: 'mediumint', text: 'MEDIUMINT(size)', defaultSize: null, defaultD: null, signed: null, zerofill: false, quoted: false, isBuildable: true, hint: 'size in Bytes'},
          {value: 'mediumtext', text: 'MEDIUMTEXT', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
          {value: 'set', text: 'SET(val1,val2,...)', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
          {value: 'smallint', text: 'SMALLINT(size)', defaultSize: null, defaultD: null, signed: null, zerofill: false, quoted: false, isBuildable: true, hint: 'size in Bytes'},
          {value: 'text', text: 'TEXT(size)', minSize: 0, defaultSize: null, defaultD: null, quoted: true, isBuildable: true, hint: 'size in #characters'},
          {value: 'time', text: 'TIME(fsp)', minSize: 0, maxSize: 6, defaultSize: 0, defaultD: null, quoted: true, isBuildable: true, hint: 'fsp=microsecond precision, min. 0, max. 6'},
          {value: 'timestamp', text: 'TIMESTAMP(fsp)', minSize: 0, maxSize: 6, defaultSize: 0, defaultD: null, quoted: true, isBuildable: true, hint: 'fsp=microsecond precision, min. 0, max. 6'},
          {value: 'tinyblob', text: 'TINYBLOB', defaultSize: null, defaultD: null, quoted: false, isBuildable: false},
          {value: 'tinyint', text: 'TINYINT(size)', defaultSize: null, defaultD: null, quoted: false, isBuildable: true, hint: 'size in Bytes'},
          {value: 'tinytext', text: 'TINYTEXT', defaultSize: null, defaultD: null, quoted: true, isBuildable: true, hint: 'max. 255 characters'},
          {value: 'year', text: 'YEAR', minSize: 2, maxSize: 4, sizeSteps: 2, defaultSize: null, defaultD: null, quoted: true, isBuildable: true, hint: 'min. 1901, max. 2155'},
          {value: 'varbinary', text: 'VARBINARY(size)', defaultSize: null, defaultD: null, quoted: false, isBuildable: false},
          {value: 'varchar', text: 'VARCHAR(size)', minSize: 0, maxSize: 65532, defaultSize: 255, defaultD: null, quoted: true, isBuildable: true, hint: 'max. characters depends on the encoding'}
        ]
      }
    
      return {findAll, findOne, update, exportCsv, execute, reExecuteData, reExecuteCount, build, mySql8DataTypes}
    }