ORA-00936 (отсутствующее выражение), когда groovy script пытается выбрать

#oracle #groovy

#Oracle #groovy

Вопрос:

Итак, я видел кучу потоков об этой ошибке SQL, но я не вижу решения для этой конкретной ситуации. Короче говоря, у меня есть сервер обработки сообщений, который выполняет некоторые сценарии для полезных нагрузок перед передачей полезной нагрузки. Эти скрипты находятся в groovy, и я получаю сообщение об ошибке в моем журнале следующим образом:

 WARNING groovy.sql.Sql [process-1{channel}] - 
  Failed to execute: 
    select column
      from table
        where field1 = ?
          and field2 in ([468001])
   because: ORA-00936: missing expression
  

Это файл журнала. Когда я на самом деле распечатываю строку, созданную groovy, это следующее:

 select column
  from table
    where field1 = 2.5249083E7
      and field2 in (groovy.sql.Sql$35@f7326f4e)
  

Я предполагаю, что научная нотация — это именно тот способ, которым groovy печатает этот тип, и расширение создает объект, который печатается не очень хорошо.

Фактический groovy-код, который создает эту ошибку, является

 sql.eachRow("""
  select column
    from table
      where field1 = $var1
        and field2 in (${Sql.expand(varList2.join(','))})
""") { row ->
  

Часть, которая меня смущает, заключается в том, что этот точный код в этом скрипте отлично выполняется в другой точке в другом groovy script. Это буквально скопировано и вставлено (хотя я этого не писал, и это один из моих немногих groovy-опытов, так что это мало что значит). Если у кого-нибудь есть какие-либо советы, это было бы потрясающе.

Я был бы более чем счастлив, если бы кто-нибудь сказал мне, что я идиот и почему. Это такая простая ошибка, что я предполагаю, что я упускаю что-то очевидное. Я переименовал переменные и имена таблиц / столбцов, но могу заверить вас, что они написаны правильно, и копирование / вставка заполненной версии возвращает данные.

Комментарии:

1. Что varList2 в запросе, который работает, и что это здесь?

2. То же самое в обоих. Это список, но он содержит только одну вещь (целое число, обычно около 6 цифр). Это проблема с нашей моделью данных. Первоначально мы думали, что он будет содержать более одной вещи, но в итоге мы просто выполнили «один к одному» вместо «один ко многим» в настройке таблицы. Отсюда список, в котором никогда не бывает более одного элемента.

3. Все еще происходит сбой с and field2 = ${varList2.take(1)}

4. Проблема, судя по журналу, заключается в квадратных скобках, которые заключаются в значение. Вам нужно посмотреть, почему ${Sql.expand(varList2.join(','))} заканчивается как [468001] , а не просто 468001 . В других местах работает тот же шаблон, возможно, вы меняете параметр, который изменяет поведение расширения? Или это часть varList2 значения перед объединением / расширением? Если у вас все еще та же проблема с = , можете ли вы привязать ее вместо этого?

5. Метод Sql.expand удобен и предполагает безопасность. Но следует отметить, что это потенциальный инструмент для SQL-инъекции . Что может быть продемонстрировано с varList2 = ['468001) or (1=1'] предоставлением доступа ко всей таблице.

Ответ №1:

Основная причина была диагностирована @tim_yates и @Alex. В любом случае я бы предложил использовать другой подход для привязки СПИСКА IN (тот же подход, который используется в Hibernate).

  groovyCon.eachRow 
    ('select * from mytab where x in ('   varList2.collect{'?'}.join(',')   ')',varList2) 
      {println it}
  

Это приводит к s строке SQL

  select * from mytab where x in (?,?)
  

что не только защищает от SQL-инъекций, но и более эффективно, поскольку запросы с той же мощностью в СПИСКЕ IN могут быть повторно использованы без жесткого анализа.

Кроме того, при попытке передать неправильные типы данных вы получаете исключение:

  Caught: java.sql.SQLException: Invalid column type