Выполнение именных запросов в Афине
Мы хотим выполнить параметризованный запрос в Athena, используя javascript sdk by aws.
Кажется, что запрос по имени Афины может быть способом, но документация кажется очень загадочной, чтобы понять, как это сделать.
Было бы здорово, если кто-то может помочь нам сделать следующее
- Каков рекомендуемый способ избежать внедрения sql в athena?
- Создайте параметризованный запрос, например
SELECT c FROM Country c WHERE c.name = :name
- Передайте значение параметра
name
- Выполните этот запрос
Ответы
Ответ 1
Именованные запросы - странная особенность Афины, которая, к сожалению, ни к чему не приводит.
Афина не поддерживает готовые заявления, как многие РСУБД. Есть библиотеки SQL с поддержкой для расширения параметров на стороне клиента - у меня есть опыт работы с Sequel для Ruby, к сожалению, я не могу дать вам совет по JavaScript.
Однако ускользнуть от Афины на диалекте SQL не очень сложно. В идентификаторах двойные кавычки должны быть экранированы как две двойные кавычки, а в литеральных строках одинарные кавычки должны быть экранированы как одинарные кавычки. Другие типы данных просто должны быть чистыми, например, только цифры для целых чисел.
Кроме того, имейте в виду, что в Athena опасность внедрения SQL-кода отличается от ситуации в RDBMS: Athena не может удалить ваши данные. Если вы правильно настроили свои разрешения IAM, пользователь не сможет даже удалить таблицы, и даже если вы по какой-то причине запускаете запросы с пользователем, которому разрешено удалять таблицы, таблицы являются просто метаданными и могут быть легко настроены заново.
Ответ 2
Несмотря на то, что можно запускать запрос от конечного пользователя, важно иметь в виду, что AWS Athena имеет некоторые ограничения на обслуживание и реализует только подмножество SQL.
Athena в конце будет запрашивать некоторые файлы S3 в кодах, где количество файлов влияет на выполнение запросов, а после завершения запроса конечным результатом будет файл в промежуточном ведре.
Обычно я использую структуру, подобную следующей, для выполнения запросов в Афине.
const AWS = require('aws-sdk');
const async = require('async')
const athena = new AWS.Athena();
let myTable = 'my_tablename';
let myBucket = 'my_bucket_name';
let myDatabase = 'my_database_name';
async.auto({
execute_query: function(callback) {
let params = {
QueryString: 'select count(*) as line_count from '+myTable,
ResultConfiguration: {
OutputLocation: myBucket
},
QueryExecutionContext: {
Database: myDatabase
}
};
athena.startQueryExecution(params, callback);
},
fetch_results: ['execute_query', function(results, callback) {
let executionData = results.execute_query;
executionData.MaxResults=50;
let retryCount=1;
let maxRetries=300;
async.forever(
function(next) {
athena.getQueryResults(executionData, function(err, data) {
if (err && err.code==='InvalidRequestException') {
if (err.message.match(/.*: (RUNNING|QUEUED)/)) {
retryCount=retryCount+1;
setTimeout(() => {
return next(retryCount>maxRetries ? 'max retries reached for query on: '+myTable : null);
},
1000);
} else {
callback(err);
}
} else {
callback(null,data.ResultSet.Rows[1].Data[1].VarCharValue);
}
});
},
callback
);
}],
function(err, results) {
console.log('err = ', err);
console.log('results = ', results);
}
});
Если вам нужна дополнительная информация, пожалуйста, спросите в комментариях, и я постараюсь улучшить.