Обратная косая черта (\) и Цитата (') в поиске / вставке запроса jdbc - PullRequest
0 голосов
/ 18 марта 2019

Я использую JDBC с cratedb (который почти использует протоколы PSQL).Бывает, что когда я пытаюсь выполнить запрос вроде этого

String query = "select * from test where col1='dhruv\'";

, это дает мне исключение Parser.

Caused by: io.crate.shade.org.postgresql.util.PSQLException: Unterminated string literal started at position 39 in SQL select * from test where col1='dhruv\'. Expected  char
    at io.crate.shade.org.postgresql.core.Parser.checkParsePosition(Parser.java:1310)
    at io.crate.shade.org.postgresql.core.Parser.parseSql(Parser.java:1217)

Затем при отладке я обнаружил, что этот код в Parser.java jdbc

 else if (c == '\'') {
                    i0 = i;
                    i = parseSingleQuotes(p_sql, i, stdStrings);
                    checkParsePosition(i, len, i0, p_sql, "Unterminated string literal started at position {0} in SQL {1}. Expected ' char");
                    newsql.append(p_sql, i0, i - i0 + 1);
                }

вызывает проблемы.Согласно моему пониманию, они разбивают значения в массивах символов, и '\'' конфликтует с моим \ в конце утверждения.

Что я знаю или пытался

  • Я читал, что люди просят использовать prepared statement, поскольку такая же проблема возникает со вставками, но мои запросы динамические, поэтому я не могу использоватьчто

  • Нельзя сказать, что невозможно вставить такие значения, как dhruv\ в базу данных.Мы можем вставить напрямую через консоль или json-файлы (кстати, это сложно с помощью java, поскольку нам нужно экранировать один \, а для db \ это не экранирующий символ)

  • Cratedb в последнихверсия имеет строковых литералов с C-Style Escape , но просто для использования этой функции я не могу обновить всю базу данных

Так есть ли способ обойти это?

++ Update

Также найденные запросы, такие как

select * from test where col1='dh\''ruv'

, также не будут работать по той же причине.

++ Подробнее Обновление

  • Итак, согласно моему пониманию select * from workkards where w_number='dhruv\\', во время выполнения он выглядит как select * from workkards where w_number='dhruv\'
    • В 'dhruv\', теперь обратный слеш экранирует кавычку, поэтому кавычка экранируется
    • Таким образом, crate jdbc parser сообщает неопределенную строку, так как ' экранирован

Обход, над которым я работаю

  • Я заменяю \ в коде Java с \, т. е. с обратной косой чертой и пробелом. Пользователь не видит никакой разницы, поскольку пробел не виден
if(value.contains("\\") ){
            return value.replace("\\", "\\ ");
        }
  • Примерно так же, как и выше, похоже, работает find, поскольку я могу вставить значение, но есть одна проблема
  • Значение хранится в базе данных с конечным пробелом, поэтому существует проблемапри поиске этого значения
  • Мы можем применить ту же логику к поисковому запросу, чтобы он работал
  • Остается одна проблема: что если пользователь введет значение, например 'dh\''ruv'

1 Ответ

0 голосов
/ 19 марта 2019

Вы должны по крайней мере избежать одиночной кавычки. Насколько я знаю, "\" обратный слеш не нуждается в экранировании.

Проблема заключается в одинарных кавычках, crate.io использует их для явного обозначения значения столбца, как упоминалось здесь

SELECT "field" FROM "doc"."test" where field = '''dhruv\' limit 100;

Выше приведен результат (пример того, что я запускаю на своей локальной машине).

Таким образом, ваш запрос должен выглядеть следующим образом (обратите внимание на правильное завершение одной кавычкой):

String query = "select * from test where col1='''dhruv\'";

UPDATE:

Тогда я бы предложил, если вам придется сделать это таким образом, экранировать только переменную "escapedValue" и добавить ее

String query = "select * from test where col1=" + "'" + escapedValue + "'";
...