Я пытаюсь выполнить SQL-запрос, используя функцию Oracle json_value()
, используя PreparedStatement
.
Примите следующие настройки таблицы:
drop table foo cascade constraints purge;
create table foo
(
id integer primary key,
payload clob,
constraint ensure_json check (payload IS JSON STRICT)
);
insert into foo values (1, '{"data": {"k1": 1, "k2": "foo"}}');
Следующий запрос SQL работает нормально:
select *
from foo
where json_value(payload, '$.data.k1') = '1'
и возвращает ожидаемую строку.
Однако, когда я пытаюсь выполнить этот запрос, используя PreparedStatement
, как в следующем фрагменте кода:
String sql =
"select *\n" +
"from foo\n" +
"where json_value(payload, ?) = ?";
PreparedStatement pstmt = conection.prepareStatement(sql);
pstmt.setString(1, "$.data.k1");
pstmt.setString(2, "1");
ResultSet rs = pstmt.executeQuery();
(я убрал все проверки ошибок из примера, чтобы было проще)
В результате:
java.sql.SQLException: ORA-40454: выражение пути не является литералом
Преступник передает значение пути json (индекс параметра 1), второй параметр не является проблемой.
Когда я заменяю (только) первый параметр на строковую константу json_value(payload, '$.data.k1') = ?
, подготовленный оператор работает нормально.
В отчаянной попытке я также попытался включить в параметр одинарные кавычки: pstmt.setString(1, "'$.data.k1'")
, но неудивительно, что Oracle тоже не примет это (то же сообщение об ошибке).
Я также пытался использовать json_value(payload, concat('$.', ?) )
и только передавать "data.k1"
в качестве параметра - тот же результат.
Итак, вопрос:
- Как передать выражение пути JSON в функцию Oracle
json_value
, используя параметр PreparedStatement
?
Есть идеи? Это ошибка в драйвере или в Oracle? (Я не смог найти что-нибудь в Службе поддержки Oracle)
Или это просто случай "не реализован"?
Окружающая среда:
Я использую Oracle 18.0
Я попробовал 18 * и 19.3 версию драйвера ojdbc10.jar
вместе с OpenJDK 11.