在Athena中执行命名查询

时间:2018-06-04 09:00:06

标签: amazon-web-services sql-injection amazon-athena named-query

我们希望使用javascript sdk by aws

在Athena中执行参数化查询

似乎Athena的命名查询可能是这样做的,但是文档似乎非常神秘,无法理解如何去做。

如果有人可以帮我们做以下事情,那就太棒了

  • 在athena中避免sql注入的推荐方法是什么?
  • 创建参数化查询,例如SELECT c FROM Country c WHERE c.name = :name
  • 传递name参数的值
  • 执行此查询

2 个答案:

答案 0 :(得分:1)

不幸的是,命名查询是Athena的一个怪异功能,

雅典娜不像许多RDBMS一样支持准备好的语句。有一些SQL库支持在客户端进行参数扩展-Ruby的续集是我经验丰富的库,很遗憾,我无法为您提供JavaScript的建议。

在雅典娜的SQL方言中转义并不是很复杂。在标识符中,双引号需要转义为两个双引号,而在文字字符串中,单引号需要转义为单引号。其他数据类型只需要是干净的,例如整数只能是数字。

此外,请记住,在Athena中,SQL注入的危险与在RDBMS中不同:Athena无法删除您的数据。如果您正确设置了IAM权限,则用户甚至无法删除表,即使由于某种原因与允许删除表的用户一起运行查询,表也只是元数据,可以轻松地再次进行设置。

答案 1 :(得分:-2)

即使可以从最终用户运行查询,也要记住,AWS Athena具有一些service limits并且仅实现SQL Subset

最后,Athena将查询存储桶中的一些S3文件,其中文件数量会影响查询的执行,查询完成后,最终结果将是存储分区中的文件。< / p>

我通常使用以下结构在雅典娜中执行查询。

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);
    }
});

如果您需要更多信息,请在评论中提出,我会尽力改善。