2022-06-06 13:44:21 +00:00
|
|
|
import { QueryError, QueryResult, QueryService, ConnectionTestResult } from '@tooljet-plugins/common';
|
|
|
|
|
import { SourceOptions, QueryOptions } from './types';
|
2022-06-22 09:09:29 +00:00
|
|
|
const AthenaExpress = require('athena-express');
|
|
|
|
|
const AWS = require('aws-sdk');
|
2022-06-06 13:44:21 +00:00
|
|
|
|
|
|
|
|
export default class Athena implements QueryService {
|
2022-06-14 13:25:46 +00:00
|
|
|
async run(sourceOptions: SourceOptions, queryOptions: QueryOptions): Promise<QueryResult> {
|
2022-06-06 13:44:21 +00:00
|
|
|
let result = {};
|
2022-06-14 10:40:35 +00:00
|
|
|
const athenaClient = await this.getConnection(sourceOptions);
|
2022-06-06 13:44:21 +00:00
|
|
|
const myQuery = {
|
2022-06-14 10:40:35 +00:00
|
|
|
sql: queryOptions.query,
|
|
|
|
|
db: sourceOptions.database,
|
2022-06-14 12:44:37 +00:00
|
|
|
...(queryOptions.pagination?.length > 0 && { pagination: queryOptions.pagination }),
|
2022-06-14 19:25:39 +00:00
|
|
|
...(queryOptions?.nextToken?.length > 0 && { nextToken: queryOptions.nextToken }),
|
|
|
|
|
...(queryOptions?.queryExecutionId?.length > 0 && { queryExecutionId: queryOptions.queryExecutionId }),
|
2022-06-06 13:44:21 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
2022-06-14 11:35:13 +00:00
|
|
|
const data = await athenaClient.query(myQuery);
|
|
|
|
|
result = this.toJson(data);
|
2022-06-06 13:44:21 +00:00
|
|
|
} catch (error) {
|
|
|
|
|
throw new QueryError('Query could not be completed', error.message, {});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
status: 'ok',
|
|
|
|
|
data: result,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async testConnection(sourceOptions: SourceOptions): Promise<ConnectionTestResult> {
|
2022-06-14 10:40:35 +00:00
|
|
|
const athenaClient = await this.getConnection(sourceOptions);
|
2022-06-28 05:10:13 +00:00
|
|
|
await athenaClient.query('SHOW TABLES');
|
|
|
|
|
|
2022-06-06 13:44:21 +00:00
|
|
|
return {
|
|
|
|
|
status: 'ok',
|
|
|
|
|
};
|
|
|
|
|
}
|
2022-06-14 13:25:46 +00:00
|
|
|
async getConnection(sourceOptions: SourceOptions): Promise<any> {
|
2022-06-22 09:09:29 +00:00
|
|
|
const awsCredentials = {
|
|
|
|
|
region: sourceOptions.region,
|
|
|
|
|
accessKeyId: sourceOptions.access_key,
|
|
|
|
|
secretAccessKey: sourceOptions.secret_key,
|
|
|
|
|
};
|
2022-06-06 13:44:21 +00:00
|
|
|
|
2022-06-07 11:17:08 +00:00
|
|
|
AWS.config.update(awsCredentials);
|
2022-06-14 10:40:35 +00:00
|
|
|
|
|
|
|
|
const athenaExpressConfig = {
|
|
|
|
|
aws: AWS,
|
2022-06-07 11:17:08 +00:00
|
|
|
db: sourceOptions.database,
|
2022-06-14 13:21:33 +00:00
|
|
|
...(sourceOptions?.output_location?.length > 0 && { s3: sourceOptions?.output_location }),
|
2022-06-06 13:44:21 +00:00
|
|
|
};
|
2022-06-14 10:40:35 +00:00
|
|
|
|
|
|
|
|
const athenaExpress = new AthenaExpress(athenaExpressConfig);
|
|
|
|
|
return athenaExpress;
|
2022-06-06 13:44:21 +00:00
|
|
|
}
|
2022-06-14 11:35:13 +00:00
|
|
|
private toJson(data) {
|
|
|
|
|
return JSON.parse(
|
|
|
|
|
JSON.stringify(data, (_, v) => (typeof v === 'bigint' ? `${v}n` : v)).replace(/"(-?\d+)n"/g, (_, a) => a)
|
|
|
|
|
);
|
2022-06-14 08:27:58 +00:00
|
|
|
}
|
2022-06-06 13:44:21 +00:00
|
|
|
}
|