Подтвердить что ты не робот

Препятствует ли спецификация JDBC '?' от использования в качестве оператора (вне кавычек)?

Из вопрос Сэма Макбета:

Есть ли что-нибудь в спецификации JDBC, которая позволяет? быть экранированным и быть чем-то иным, чем заполнитель параметров?

Например, Postgres позволяет использовать ? в качестве оператора:

SELECT * FROM tbl WHERE tbl.data ? 'abc'

Можно ли использовать драйвер JDBC? как оператор по-прежнему совместим с JDBC?

4b9b3361

Ответ 1

Я думаю, что будет вполне приемлемо, если драйвер JDBC позволит ? Оператор должен быть удален и использоваться как есть, но это может 1) усложнить анализатор для фактического определения параметров этого оператора и 2) может запутать людей (и, возможно, инструменты), к которым привыкли ? только значение параметра-заполнителя.

Таким образом, мое предложение было бы обеспечить какой-то побег (или альтернативный оператор). Однако, глядя на спецификацию JDBC, драйверы должны использовать только синтаксис перехода JDBC для реализации escape-выражений, определенных в спецификации JDBC (13.4.2: "Синтаксис escape не предназначен для использования для вызова пользовательских скалярных функций или функций, специфичных для поставщика. msgstr "; хотя это конкретно о побеге {fn...}).

Так что либо вам нужно использовать альтернативный выход, либо "нарушать" правила (я не думаю, что кто-то будет против). Если вам нужен более авторитетный ответ, вы можете отправить свой вопрос в список рассылки jdbc-spec-обсуждения. Я уверен, что Ланс Андерсен (ведущий специализации JDBC) даст ответ.

Редактировать:

Также интересно отметить, что в разделе 6.2 спецификации JDBC (Руководства и требования) сказано:

Драйверы должны предоставлять доступ ко всем функциям, реализованным базовым источником данных, включая функции, расширяющие API JDBC. Цель состоит в том, чтобы приложения, использующие API JDBC, имели доступ к тому же набору функций, что и собственные приложения.

Итак, исходя из того, что вы должны (не должны) поддерживать ? -operator, вам просто нужно найти практичный способ сделать это.


Обновление основано на обсуждении jdbc-spec-обсуждения

Согласно Лансу Андерсену, спецификация JDBC следует спецификации SQL в отношении вопросительных знаков: они могут использоваться только в качестве заполнителей параметров в тексте запроса (кроме, конечно, в комментариях и цитируемом тексте), как такое использование ? как и в PostgreSQL, операторы hstore не будут допущены. (см. это сообщение)

Доступный вариант заключается в предоставлении псевдонима или экранирования для оператора, при условии, что это не вступает в противоречие с будущими изменениями (что довольно трудно сделать без ясновидения;). Лучшее решение - предотвратить проблемы с будущими изменениями JDBC - это, вероятно, пользовательский выход.

JDBC на самом деле не определяет побег продавца, но Лэнс Андерсен предлагает побег, который похож на побег JDBC: {postgres <thing to be escaped>}; использование имени поставщика или имени_привода в этом экранировании предоставит форму пространства имен, которая должна предотвратить конфликт со спецификацией. (см. это сообщение)

Чтобы соответствовать "нормальным" функциям JDBC, я бы предложил определить escape, которое позволит задать запрос в вашем вопросе следующим образом:

SELECT * FROM tbl WHERE {postgres containskey(tbl.data, 'abc')}

Я выбрал containskey ключ на основе значения ? в документации магазина. Похожие предложения для ?&: containsallkeys) и для ?| : containsanykey. Для согласованности вы можете рассмотреть возможность сделать это и для других операторов hstore.

Вы также можете решить избежать только вопросительный знак. Например, экранируйте с помощью {postgres '?'} Или {postgres qm} (qm для знака вопроса). Я думаю, что удобочитаемость меньше, чем мое предложение о выходе из функции:

SELECT * FROM tbl WHERE tbl.data {postgres '?'} 'abc'

Обновлено на основе нового предложения для JDBC v.Next(4.4?)

Следующая спецификация JDBC (вероятно, под номером 4.4), вероятно, добавит явное экранирование JDBC, чтобы полностью экранировать фрагменты запроса, с явным намерением иметь возможность экранировать вопросительные знаки для систем баз данных, которые не используют родные вопросительные знаки для маркеров параметров. и необходимо поддерживать другое использование вопросительных знаков.

Предложенный синтаксис будет {\ <thing-to escape> \} (который уже поддерживается драйвером Oracle JDBC как нестандартный escape). С этим синтаксисом маркер параметра можно затем экранировать с помощью {\?\} (В строковом литерале: {\\?\\}) или экранировать больший фрагмент для улучшения читабельности.

См. Также SQL 2016 MATCH, ПРИЗНАЮЩИЙ параметр JDBC Маркерные /Escape-символы и предыдущее обсуждение в списке рассылки jdbc-spec-обсуждения.

Ответ 2

Если у вас есть последний драйвер postgresql, вы можете использовать:

??

Изменение исходного запроса:

SELECT * FROM tbl WHERE tbl.data ?? 'abc'

Подробности находятся в этом запросе на растяжение - https://github.com/pgjdbc/pgjdbc/pull/227 Это изменение было сделано уже после первоначального вопроса, но стоит отметить, что сейчас есть простой ответ.

Ответ 3

Я ничего не вижу в спецификации JDBC, которая позволила бы экранировать ?. Почти все, что он говорит о ?:

Маркеры параметров, представленные как "?" в строке SQL, используются для указания входных значений для оператора, который может меняться во время выполнения. [1]

и позже...

Параметрические ординалы, которые являются целыми числами, переданными методу меток approriate, относятся к маркерам параметров ( "?" ) в инструкции, начиная с единицы. [2]

И он определяет только синтаксис escape-кода для небольшого набора функций, ни один из которых не может быть применен к ?:

JDBC определяет синтаксис escape для следующего:

  • скалярные функции
  • литералы даты и времени
  • внешние соединения
  • вызов хранимых процедур
  • escape-символы для предложений LIKE [3]

В целом, похоже, что спецификация JDBC имеет очень "строгий" язык (по сравнению, например, с некоторыми спецификационными документами W3C, которые должны использовать и должны много), поэтому я не знаю, является ли драйвер, который разрешенный ?, который будет экранирован, будет технически несовместимым, но он, вероятно, будет несовместимым.

Это даже не похоже, что даже драйвер Postgres разрешил бы это, так как метод в драйвере, который на самом деле разбирает операторы SQL для ? doesn ' t проверить любые escape-символы.


1. Спецификация JDBC 4.1, раздел 13.2 — Интерфейс PreparedStatement
2. Спецификация JDBC 4.1, раздел 13.3.2; Настройка параметров
3. Спецификация JDBC 4.1, раздел 13.4 — Симулятор Escape