import CassandraExplorer from '@/services/datastores/cassandra/lib/CassandraExplorer' ; import { generateCqlStatements , generateCsv , } from '@/services/datastores/cassandra/lib/utils/export-utils' ; import { CassandraExportFormat , ITableColumn , ITableSchema , IKeyQuery , } from '@/services/datastores/cassandra/typings/cassandra' ; import { IClusterDefinition } from '@/typings/typings' ; import { sendFile } from '@/utils/response-utils' ; import { Response } from 'express' ; /**
 * Provides a way to generate an exported version a C* result set.
 * Supports downloading as a file in serveral formats or generating
 * the CQL INSERT statements for the given result set.
 */ export default class CassandraResultsExporter { public columns : ITableColumn [ ] = [ ] ; public rows : Array < { [ column ] : any ; } > = [ ] ; public keyQuery : IKeyQuery | undefined = undefined ; constructor ( readonly schema , readonly cluster , readonly cassandraApi ) { } public build ( columns , rows , filter ) { const columnNames = new Set ( this . schema . columns . map ( ( col ) => col . name ) ) ; this . columns = columns . filter ( ( column ) => columnNames . has ( column . name ) ) ; this . rows = rows ; this . keyQuery = filter ; return new CassandraResultsStream ( this ) ; } } class CassandraResultsStream { constructor ( readonly exporter ) { } param res param format param sendAsFile public send ( res , format , sendAsFile ) { const { cassandraApi , columns , rows , schema , keyQuery } = this . exporter ; if ( ! keyQuery ) { throw new Error ( 'KeyQuery missing from Exporter' ) ; } let records = [ ] ; let content ; const { encoding } = keyQuery . options ; if ( format === 'cql' ) { records = generateCqlStatements ( schema , rows , cassandraApi , encoding ) ; content = [ ... records , '' ] . join ( ';\n' ) ; } else if ( format === 'csv' ) { content = generateCsv ( schema , columns , rows ) ; } else { throw new Error ( 'Unsupported export format' ) ; } if ( sendAsFile ) { const filename = `${ this . generateFilename ( format ) }.${ format }` ; sendFile ( res , 'text/plain' , filename , Buffer . from ( content , 'utf-8' ) ) ; } else { res . json ( { records } ) ; } } private generateFilename ( format ) { const { cluster , keyQuery , schema } = this . exporter ; const { keyspace , name } = schema ; const pieces = [ cluster . name . toUpperCase ( ) , `${ keyspace }.${ name }` ] ; if ( keyQuery && Object . keys ( keyQuery . primaryKey ) . length > 0 ) { pieces . push ( Object . entries ( keyQuery . primaryKey ) . map ( ( [ key , details ] ) => `${ key }.${ details . value }` ) . join ( '__' ) ) ; } if ( format === 'cql' ) { pieces . push ( 'insert' ) ; } return pieces . join ( '____' ) ; } }