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