From cdbdfb5099f3f73aac8cdba2490bca1a77c90049 Mon Sep 17 00:00:00 2001 From: Grosan Flaviu Gheorghe Date: Fri, 10 Jan 2020 12:20:56 +0000 Subject: [PATCH 1/6] Added optional bound parameters for the query(...) method. --- lib/athenaExpress.js | 30 +++++++++++++++++++++++++----- package.json | 3 ++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/athenaExpress.js b/lib/athenaExpress.js index 77ee0d5..42a2c54 100644 --- a/lib/athenaExpress.js +++ b/lib/athenaExpress.js @@ -5,7 +5,8 @@ const COST_PER_MB = 0.000004768, //Based on $5/TB COST_FOR_10MB = COST_PER_MB * 10; const readline = require("readline"), - csv = require("csvtojson"); + csv = require("csvtojson"), + SqlString = require("sqlstring"); module.exports = class AthenaExpress { constructor(init) { @@ -28,7 +29,24 @@ module.exports = class AthenaExpress { }; } - async query(query) { + /** + * Executes an Athena SQL Query. + * + * If the 'query' parameter is a string, SQL parameters should be + * passed in via the 'queryParams' optional parameter. + * + * If the 'query' parameter is an object, parameters should be + * passed in via the 'query.queryParams' optional array. + * + * Examples: + * await query('SELECT * FROM movies WHERE movie_title = ?', ['Spider-Man']); + * await query({ sql: 'SELECT * FROM movies WHERE movie_title = ?', queryParams: ['Spider-Man']}); + * + * @param {String|Object} query + * @param {Array} [queryParams=[]] Optional + * @returns {Promise} + */ + async query(query, queryParams) { const config = this.config; let results = {}; @@ -38,7 +56,7 @@ module.exports = class AthenaExpress { if (!query) throw new TypeError("SQL query is missing"); try { - const queryExecutionId = await startQueryExecution(query, config); + const queryExecutionId = await startQueryExecution(query, queryParams, config); const queryStatus = await checkIfExecutionCompleted( queryExecutionId, config @@ -82,8 +100,10 @@ module.exports = class AthenaExpress { } }; -function startQueryExecution(query, config) { - const QueryString = query.sql || query; +function startQueryExecution(query, queryParams, config) { + const QueryString = query.sql ? + SqlString.format(query.sql, query.queryParams || []) + : SqlString.format(query, queryParams || []); const params = { QueryString, diff --git a/package.json b/package.json index d7a92a2..570cd90 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "mocha-lcov-reporter": "^1.3.0" }, "dependencies": { - "csvtojson": "^2.0.10" + "csvtojson": "^2.0.10", + "sqlstring": "^2.3.1" } } From 0adcc0559d47d5fc7697d0ea03f39eafcd00fd8f Mon Sep 17 00:00:00 2001 From: Grosan Flaviu Gheorghe Date: Fri, 10 Jan 2020 12:23:46 +0000 Subject: [PATCH 2/6] Updated documentation to reflect the use of bound parameters. --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bc447cb..89a175d 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,8 @@ const athenaExpress = new AthenaExpress(athenaExpressConfig); ```javascript let myQuery = { - sql: "SELECT elb_name, request_port, request_ip FROM elb_logs LIMIT 3" /* required */, + sql: "SELECT elb_name, request_port, request_ip FROM elb_logs LIMIT ?" /* required */, + queryParams: [3], db: "sampledb" /* optional. You could specify a database here or in the advance configuration option mentioned above*/ }; @@ -172,7 +173,8 @@ athenaExpress ```javascript (async () => { let myQuery = { - sql: "SELECT elb_name, request_port, request_ip FROM elb_logs LIMIT 3" /* required */, + sql: "SELECT elb_name, request_port, request_ip FROM elb_logs LIMIT ?" /* required */, + queryParams: [3], db: "sampledb" /* optional. You could specify a database here or in the configuration constructor*/ }; @@ -213,7 +215,8 @@ const athenaExpress = new AthenaExpress(athenaExpressConfig); //Invoking a query on Amazon Athena (async () => { let myQuery = { - sql: "SELECT elb_name, request_port, request_ip FROM elb_logs LIMIT 3", + sql: "SELECT elb_name, request_port, request_ip FROM elb_logs LIMIT ?", + queryParams: [3], db: "sampledb" }; @@ -248,10 +251,10 @@ const athenaExpressConfig = { const athenaExpress = new AthenaExpress(athenaExpressConfig); exports.handler = async event => { - const sqlQuery = "SELECT elb_name, request_port, request_ip FROM elb_logs LIMIT 3"; + const sqlQuery = "SELECT elb_name, request_port, request_ip FROM elb_logs LIMIT ?"; try { - let results = await athenaExpress.query(sqlQuery); + let results = await athenaExpress.query(sqlQuery, [3]); return results; } catch (error) { return error; From 0f5834e1dbdb6e3ee5b21886728beaf9ca88473a Mon Sep 17 00:00:00 2001 From: Grosan Flaviu Gheorghe Date: Fri, 10 Jan 2020 12:32:11 +0000 Subject: [PATCH 3/6] Documentation prune. --- lib/athenaExpress.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/athenaExpress.js b/lib/athenaExpress.js index 42a2c54..9638cd1 100644 --- a/lib/athenaExpress.js +++ b/lib/athenaExpress.js @@ -39,8 +39,9 @@ module.exports = class AthenaExpress { * passed in via the 'query.queryParams' optional array. * * Examples: - * await query('SELECT * FROM movies WHERE movie_title = ?', ['Spider-Man']); - * await query({ sql: 'SELECT * FROM movies WHERE movie_title = ?', queryParams: ['Spider-Man']}); + * await athenaExpress.query('SELECT * FROM movies WHERE movie_title = ?', ['Spider-Man']); + * await athenaExpress + * .query({ sql: 'SELECT * FROM movies WHERE movie_title = ?', queryParams: ['Spider-Man']}); * * @param {String|Object} query * @param {Array} [queryParams=[]] Optional From 1bc3ad44aa6e4f55e1edad1aa17d26c86602ad03 Mon Sep 17 00:00:00 2001 From: Grosan Flaviu Gheorghe Date: Wed, 12 Jan 2022 09:29:01 +0000 Subject: [PATCH 4/6] Code formatting and naming convention updates. --- README.md | 6 +++--- lib/athenaExpress.js | 10 +++++----- lib/helpers.js | 8 +++----- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 33597d9..5c0b2b7 100644 --- a/README.md +++ b/README.md @@ -189,7 +189,7 @@ let myQuery = { /*Option 1: object notation*/ let myQuery = { sql: "SELECT elb_name, request_port, request_ip FROM elb_logs LIMIT ?" /* required */, - queryParams: [3], + QueryParams: [3], db: "sampledb" /* optional. You could specify a database here or in the advance configuration option mentioned above*/ }; @@ -213,7 +213,7 @@ athenaExpress /*Option 1: object notation*/ let myQuery = { sql: "SELECT elb_name, request_port, request_ip FROM elb_logs LIMIT ?" /* required */, - queryParams: [3], + QueryParams: [3], db: "sampledb" /* optional. You could specify a database here or in the configuration constructor*/ }; @@ -265,7 +265,7 @@ const athenaExpress = new AthenaExpress(athenaExpressConfig); (async () => { let myQuery = { sql: "SELECT elb_name, request_port, request_ip FROM elb_logs LIMIT ?", - queryParams: [3], + QueryParams: [3], db: "sampledb" }; diff --git a/lib/athenaExpress.js b/lib/athenaExpress.js index c059beb..e1069d5 100644 --- a/lib/athenaExpress.js +++ b/lib/athenaExpress.js @@ -84,8 +84,8 @@ module.exports = class AthenaExpress { if (loweredCaseKeys.hasOwnProperty("catalog")) { config.catalog = loweredCaseKeys.catalog; } - if (loweredCaseKeys.hasOwnProperty("queryparams")) { - config.queryParams = loweredCaseKeys.queryparams; + if (loweredCaseKeys.hasOwnProperty("queryparams")) { + config.QueryParams = loweredCaseKeys.queryparams; } if (loweredCaseKeys.hasOwnProperty("sql")) { config.sql = loweredCaseKeys.sql; @@ -103,13 +103,13 @@ module.exports = class AthenaExpress { config.QueryExecutionId = query; } else { config.sql = query; + config.QueryParams = queryParams; } try { if (initiateQueryInAthena) { config.QueryExecutionId = await helpers.startQueryExecution( - config, - queryParams + config ); if (!config.waitForResults) { @@ -163,4 +163,4 @@ module.exports = class AthenaExpress { throw new Error(error); } } -}; \ No newline at end of file +}; diff --git a/lib/helpers.js b/lib/helpers.js index 968a890..f789796 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -3,15 +3,13 @@ const readline = require("readline"), csv = require("csvtojson"), - SqlString = require("sqlstring"); + SqlString = require("sqlstring"); let s3Metadata = null; -function startQueryExecution(config, queryParams) { +function startQueryExecution(config) { const params = { - QueryString: config.sql ? - SqlString.format(config.sql, config.queryParams || []) - : SqlString.format(config, queryParams || []), + QueryString: SqlString.format(config.sql, config.queryParams || []), WorkGroup: config.workgroup, ResultConfiguration: { OutputLocation: config.s3Bucket, From c1edf3524d840f0f82a2d2e85d06c24bd7083fe0 Mon Sep 17 00:00:00 2001 From: Grosan Flaviu Gheorghe Date: Wed, 12 Jan 2022 09:30:18 +0000 Subject: [PATCH 5/6] Method documentation update. --- lib/athenaExpress.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/athenaExpress.js b/lib/athenaExpress.js index e1069d5..36665a1 100644 --- a/lib/athenaExpress.js +++ b/lib/athenaExpress.js @@ -46,12 +46,12 @@ module.exports = class AthenaExpress { * passed in via the 'queryParams' optional parameter. * * If the 'query' parameter is an object, parameters should be - * passed in via the 'query.queryParams' optional array. + * passed in via the 'query.QueryParams' optional array. * * Examples: * await athenaExpress.query('SELECT * FROM movies WHERE movie_title = ?', ['Spider-Man']); * await athenaExpress - * .query({ sql: 'SELECT * FROM movies WHERE movie_title = ?', queryParams: ['Spider-Man']}); + * .query({ sql: 'SELECT * FROM movies WHERE movie_title = ?', QueryParams: ['Spider-Man']}); * * @param {String|Object} query * @param {Array} [queryParams=[]] Optional From b262b2e1c24253b8a684f982f32d22a4c7504c76 Mon Sep 17 00:00:00 2001 From: Grosan Flaviu Gheorghe Date: Wed, 12 Jan 2022 09:31:44 +0000 Subject: [PATCH 6/6] Fixed parameter name typo. --- lib/helpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/helpers.js b/lib/helpers.js index f789796..1d29984 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -9,7 +9,7 @@ let s3Metadata = null; function startQueryExecution(config) { const params = { - QueryString: SqlString.format(config.sql, config.queryParams || []), + QueryString: SqlString.format(config.sql, config.QueryParams || []), WorkGroup: config.workgroup, ResultConfiguration: { OutputLocation: config.s3Bucket,