Ошибка при передаче нескольких параметров в виде массива в хранимой процедуре adhoc voltdb - PullRequest
0 голосов
/ 09 июля 2019

У меня есть сценарий, в котором я получаю запрос SQL и аргументы SQL (чтобы избежать внедрения SQL) в качестве входных данных.

И я запускаю этот SQL, используя хранимую процедуру VoltDB AdHoc, используя приведенный ниже код.

private static final String voltdbServer = "localhost";
private static final int voltdbPort = 21212;

public ClientResponse runAdHoc(String sql, Object... sqlArgs) throws IOException, ProcCallException
{
    ClientConfig clientConfig = new ClientConfig();
    Client voltdbClient = ClientFactory.createClient(clientConfig);
    voltdbClient.createConnection(voltdbServer, voltdbPort);

    return  voltdbClient.callProcedure("@AdHoc", sql, sqlArgs);
}

Но я получаю ошибку org.voltdb.client.ProcCallException: SQL error while compiling query: Incorrect number of parameters passed: expected 2, passed 1

Для runAdHoc("select * from table where column1 = ? and column2 = ?", "column1", "column2"), когда есть два или более параметров.

И я получаю ошибку org.voltdb.client.ProcCallException: Unable to execute adhoc sql statement(s): Array / Scalar parameter mismatch ([Ljava.lang.String; to java.lang.String)

Для runAdHoc("select * from table where column1 = ?", "column1");, когда есть только один параметр.

Но я не сталкиваюсь с этой проблемой, когда звоню напрямую voltdbClient.callProcedure("@AdHoc", "select * from table where column1 = ? and column2 = ?", "column1", "column2")

Я думаю, что VoltDb не может обрабатывать sqlArgs как отдельные параметры, он обрабатывает их как один массив.

Одним из способов решения этой проблемы является сам анализ строки SQL, а затем ее передача, но я публикую это, чтобы узнать эффективный способ решения этой проблемы.

Примечание: - Использованный SQL - это просто тестовый SQL

Ответы [ 2 ]

1 голос
/ 09 июля 2019

Системная процедура @Adhoc распознает массив как один параметр. Подобные вещи случаются с @Adhoc, потому что нет никакого планирования процедуры, где можно явно указать, что представляет собой каждый параметр.

У вас есть правильная идея разбора массива sqlArgs на фактические параметры для передачи отдельно. Вы также можете объединить эти отдельные параметры в сам оператор SQL. Таким образом, ваше заявление adhoc будет просто:

voltdbClient.callProcedure("@AdHoc", sql)

Полное раскрытие: я работаю в VoltDB.

0 голосов
/ 10 июля 2019

Я разместил тот же вопрос на свободном канале VoltDB и получил один ответ, который решил проблему следующим образом:

Краткое объяснение состоит в том, что ваши параметры для @Adhoc превращаются в [sql, sqlArgs], когда они должны быть [sql, sqlArg1, sqlArg2, …]. Вам нужно будет создать новый массив sqlArgs.length + 1, поместить sql в позицию 0 и скопировать sqlArgs в новый массив, начиная с позиции 1., а затем передать этот вновь созданный массив в вызове на client.callProcedure("@AdHoc", newArray)

Итак, я изменил свой метод runAdHoc, как показано ниже, и он решил эту проблему

public ClientResponse runAdHoc(String sql, Object... sqlArgs) throws IOException, ProcCallException
{
    ClientConfig clientConfig = new ClientConfig();
    Client voltdbClient = ClientFactory.createClient(clientConfig);
    voltdbClient.createConnection(voltdbServer, voltdbPort);

    Object[] procArgs;
    if (sqlArgs == null || sqlArgs.length == 0)
    {
        procArgs = new Object[1];
    } else
    {
        procArgs = new Object[sqlArgs.length + 1];
        System.arraycopy(sqlArgs, 0, procArgs, 1, sqlArgs.length);
    }

    procArgs[0] = sql;

    return  voltdbClient.callProcedure("@AdHoc", procArgs);
}
...