Интерполяция SQL с помощью ScalikeJDBC

Я пытаюсь воспроизвести пример интерполяции SQL с библиотекой ScalikeJDBC (здесь).

val member = sql"select id, name from members where id = ${id}"
println(member.statement)

Но я получаю странный результат:

select id, name from members where id = ?

Что я упустил?

РЕДАКТИРОВАТЬ и ОТВЕЧАТЬ:

Mea culpa, я попытался отладить, почему мой SQL-запрос не работает со строковой интерполяцией, поэтому я печатаю значение запроса. Я получил этот результат, но я не проверял, что все в порядке. Проблема заключалась в том, что мне пришлось использовать SQLSyntax.createUnsafely в строке, которую я хочу использовать для интерполяции.


person Thomas    schedule 16.05.2018    source источник


Ответы (1)


Из вопроса непонятно, что именно вас здесь удивляет. Я полагаю, что вещь, которую вы находите странной, — это заполнитель ? в statement. В упомянутой статье показан точно такой же запрос с заполнителем и даже явно указана причина этого:

Не волнуйтесь, этот код надежно защищен от атак с помощью SQL-инъекций. ${id} будет заполнителем.

Если вы посмотрите на источник SQL, который является базой для всех результатов интерполяции sql"", вы можете увидеть там два поля:

val statement: String,
private[scalikejdbc] val rawParameters: Seq[Any]

и есть также

  final lazy val parameters: Seq[Any] = rawParameters.map {
    case ParameterBinder(v) => v
    case x => x
  }

Это сделано для того, чтобы повторно не реализовывать хитрую логику экранирования SQL в библиотеке. Вместо этого для этого используется стандартный java.sql.PreparedStatement. . Вот почему строка запроса анализируется в запросе-заполнителе и отдельном списке параметров.

P.S. если неясно, почему необходима какая-либо форма экранирования, чтобы избежать SQL-инъекций, или что плохого в SQL-инъекциях, вам, вероятно, следует больше узнать о SQL-инъекции.

person SergGr    schedule 17.05.2018
comment
Я редактирую пост, чтобы объяснить свою ошибку. Спасибо за ваш актуальный ответ - person Thomas; 17.05.2018
comment
@ Томас, в вашем реальном случае может понадобиться createUnsafely, а может и не понадобиться, но на основе предоставленной вами информации невозможно догадаться. Помните, что createUnsafely, как следует из названия, небезопасно, поэтому вам следует позаботиться о возможных SQL-инъекциях самостоятельно. - person SergGr; 17.05.2018
comment
Да, я понимаю, я просто хочу автоматизировать создание таблицы, если она не существует. Что-то вроде: create table if not exists ${tableName}, чтобы сделать это, я должен сделать: val tableName = SQLSyntax.createUnsafely("myTable"), иначе я получил синтаксическую ошибку sql - person Thomas; 17.05.2018
comment
@Thomas, да, DDL не поддерживает заполнители. И если каким-то образом у вас есть много таблиц с одинаковой структурой, но разными именами, это может иметь смысл. Но это, наверное, редкий случай на практике. - person SergGr; 17.05.2018