Снежинка-динамика c SQL: параметры цитирования - PullRequest
0 голосов
/ 29 февраля 2020

На основе документов Snowflake:

Динамическое создание оператора SQL

Как указано в SQL Инъекция (в этом топи c), будьте осторожны, чтобы защититься от атак при использовании Dynami c SQL.

Создать хранимую процедуру. Эта процедура позволяет вам передать имя таблицы и получить количество строк в этой таблице (эквивалентно select count (*) из table_name):

create or replace procedure get_row_count(table_name VARCHAR)
    returns float 
    not null
    language javascript
    as
    $$
    var row_count = 0;
    // Dynamically compose the SQL statement to execute.
    // Note that we uppercased the input parameter name.
    var sql_command = "select count(*) from " + TABLE_NAME;
    // Run the statement.
    var stmt = snowflake.createStatement(
           {
           sqlText: sql_command
           }
        );
    var res = stmt.execute();
    // Get back the row count. Specifically, ...
    // ... first, get the first (and in this case only) row from the
    //  result set ...
    res.next();
    // ... then extract the returned value (which in this case is the
    // number of rows in the table).
    row_count = res.getColumnValue(1);
    return row_count;
    $$
    ;

Приведенный пример не выглядит safe: "select count(*) from " + TABLE_NAME; - простая конкатенация строк

Таким образом, можно запускать такой код:

CALL get_row_count('TAB');    -- intended use
CALL get_row_count('(SELECT * FROM TAB UNION ALL SELECT * FROM TAB) s'); -- subquery

Первой идеей было запустить код с помощью функции TABLE/IDENTIFIER (в лист будет выглядеть так):

SET TABLE_NAME = 'TAB';  -- works
SET TABLE_NAME = '(SELECT * FROM TAB UNION SELECT * FROM TAB) s'; 
-- error: error line 1 at position 27 invalid identifier '$TABLE_NAME'
SELECT COUNT(*) FROM TABLE($TABLE_NAME);

И как часть процедуры:

var sql_command = "SET TABLE_NAME = " + TABLE_NAME + "; SELECT COUNT(*) FROM TABLE($TABLE_NAME);";

Но это не будет работать, так как:

Ошибка выполнения в хранимой процедуре GET_ROW_COUNT: Несколько SQL операторов в одном вызове API не поддерживаются; используйте вместо одного вызова API один оператор .


Используя TABLE/IDENTIFIER и переменную привязки:

create or replace procedure get_row_count(table_name VARCHAR)
returns float 
not null
language javascript
as
$$
var row_count = 0;
// Dynamically compose the SQL statement to execute.
// Note that we uppercased the input parameter name.
var sql_command = "select count(*) from TABLE(:1)";
// Run the statement.
var stmt = snowflake.createStatement(
       {
       sqlText: sql_command,
       binds: [TABLE_NAME]
       }
    );
var res = stmt.execute();
res.next();
row_count = res.getColumnValue(1);
return row_count;
$$
;

Вызов:

CALL get_row_count('TAB'); --works
CALL get_row_count('(SELECT * FROM TAB UNION ALL SELECT * FROM TAB) s');
-- SQL compilation error: syntax error line 1 at position 0 unexpected '('.

Вопросы:

  1. Можно ли как-то запустить несколько операторов в одном пакете (snowflake.createStatement)?
  2. Есть ли опция для безопасно квотенем в JS, вроде:

    var sql_command = "select count(*) from " + FUNC(TABLE_NAME);

  3. Есть ли потенциальные fl aws с TABLE и значениями привязки подход?

...