在 voltdb Adhoc 存储过程中将多个参数作为数组传递时出错

Error while passing multiple parameters as array in voltdb Adhoc stored procedure

我有一个场景,我得到一个 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

@Adhoc 系统过程将数组识别为一个参数。这种事情发生在 @Adhoc 上,因为没有计划可以明确说明每个参数是什么的过程。

你把sqlArgs数组解析成实际参数单独传入的想法是对的。您还可以将这些单独的参数连接到 SQL 语句本身。这样,您的临时声明将只是:

voltdbClient.callProcedure("@AdHoc", sql)

完全披露:我在 VoltDB 工作。

我在 VoltDB public slack 频道上发布了同样的问题,得到了一个解决问题的回复,如下所示:

简短的解释是 @Adhoc 的参数在需要 [sql, sqlArg1, sqlArg2, …] 时被转换为 [sql, sqlArgs]。您需要创建一个新数组 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);
}