2014-12-26 1 views
1

Я пытаюсь использовать Jooq для выполнения INSERT в базе данных PostgreSQL. Запрос завершается с ошибкой, если строка содержит символ обратной косой черты с кодом состояния SQL: 42601, что означает SYNTAX ERROR.Обратная косая черта в предложении Jooq/PostgreSQL INSERT

  • Jooq: 3.4.4
  • драйвера PostgreSQL: 8.4-702.jdbc4
  • PostgreSQL: «PostgreSQL 8.4.20 на x86_64-RedHat-Linux-гну, составленный GCC GCC (НКУ) 4.4 +0,7 20120313 (Red Hat 4.4.7-4), 64-разрядный»
  • JDK 1.8.0_25
  • Spring Tool Suite 3.6.0.RELEASE

База данных:

CREATE TABLE datahub.test (
    body TEXT NOT NULL 
); 

Jooq код, генерируемый с использованием Maven:

  • jooq-CodeGen-Maven версии 3.4.4
  • generator.name: org.jooq.util.DefaultGenerator
  • генератора. database.name: org.jooq.util.postgres.PostgresDatabase

Единица теста

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"/spring-config.xml"}) 
public class BatchExceptionJooqTest { 
    private static Logger log = LogManager.getLogger(BatchExceptionJooqTest.class); 
    @Autowired 
    private DSLContext db; 
    @Test 
    public void runBasicJooqTest(){ 
     try{ 
      final List<InsertQuery<TestRecord>> batchUpdate = Lists.newLinkedList(); 
      InsertQuery<TestRecord> insertQuery = db.insertQuery(TEST); 
      insertQuery.addValue(TEST.BODY, "It's a bit more complicated than just doing copy and paste... :\\"); 
      batchUpdate.add(insertQuery); 
      db.batch(batchUpdate).execute(); 
     }catch(Exception e){ 
      log.error(e); 
     } 
    } 
} 

Проблема

Тест терпит неудачу с исключением:

2014-12-26 17: 11: 16490 [Основная] ОШИБКА BatchExceptionJooqTest: 36: runBasicJooqTest - орг .jooq.exception.DataAccessException: SQL [null]; Пакетный ввод 0 вставляется в «datahub». Значения «test» («body») («Это немного сложнее, чем просто копировать и вставлять ...: \») было прервано. Вызовите getNextException, чтобы увидеть причину.

Тест проходит, если вместо строки: "It's a bit more complicated than just doing copy and paste... :\\" Я использую строку: "It's a bit more complicated than just doing copy and paste... :\\\\". Это кажется немного непоследовательным по сравнению с тем, что происходит с одной цитатой во время операции. Он правильно удваивается, чтобы пройти через синтаксический анализатор SQL. Не так с обратной косой чертой.

Я читал где-то, что экранирование обратной косой черты с помощью другой обратной косой черты не является частью стандарта SQL, и Postgre в последнее время изменил свое поведение по умолчанию. Однако я не совсем понимаю смысл manual p 4.1.2.2 - кажется, это указывает на то, что двойная обратная косая черта должна работать, и на самом деле нет никакой причины для jooq не делать этого.

Так .. может кто-то пожалуйста, объясните, если описанная ситуация в Jooq:

  1. желательна поведение и нет обходного пути, кроме удвоения всех входящих обратных слэшей моего приложения обработки?
  2. Желаемое поведение, но есть изменение конфигурации, которое я могу сделать, чтобы Jooq обрабатывал обратную косую черту аналогично одинарным кавычкам?
  3. Это ошибка?
  4. Что я делаю неправильно?

Спасибо

ответ

1

Вы используете PostgreSQL 8.x. В этой версии система по умолчанию принимала обратные следы с экранированными строковыми литералами даже без предшествующих E.

Чтобы избежать этого, вы должны установить для параметра конфигурации сервера standard_conforming_strings значение ON.

Настоятельно рекомендуется перейти на версию PostgreSQL выше 8.x, так как версии 8.x достигли конца жизни и больше не поддерживаются.

+0

Этот флаг Postgre действительно влияет на то, как Jooq форматирует строку параметров, которую он отправляет в базу данных? Самое странное, что Jooq форматирует одиночные котировки, но не обратную косую черту. – Tarmo

+1

@Tarmo: jOOQ явно не поддерживает PostgreSQL 8.x со всеми причудами, которые существовали, когда эта версия была свежей. Другими словами, jOOQ не знает об этом конкретном поведении. –

+0

Лукас Эдер прав. Что касается jOOQ, обратная косая черта внутри строки не является особым символом. Включив опцию конфигурации, о которой я упоминал, вы делаете PostgreSQL 8.x совместимой с текущей версией. – RealSkeptic

0

jOOQ 3.5 представил org.jooq.conf.Settings.backslashEscaping (https://github.com/jOOQ/jOOQ/issues/3000). Это было в основном введено для MySQL, который по-прежнему по умолчанию не соответствует стандартным строковым литералам, использующим обратную косую черту.

Обратите внимание, что этот параметр влияет только на встроенные значения привязки, поэтому при привязке значений к PreparedStatement он не будет сбрасывать обратные слэши.

Я согласен с RealSkeptic's answer, в котором предлагается изменить поведение базы данных или обновить ее до более новой версии PostgreSQL.