> Попытайтесь. И удивитесь, как много странных случаев, которые в красивые ограничения не
> укладываются - разного рода генерация имён таблиц на лету и тому
> подобное. Если проект крупнее hello world - никуда не денетесь, будете
> время от времени собирать запрос строкой, со всеми вытекающими рисками.Это делается элементарно:
let field_name = get_one_more_field_name();
let result = query_builder()
.select(["uid", "nickname", field_name])
.from(USERS_TABLE)
.where(less(length("nickname"), 5))
.execute(SQL_CONNECTION);
Функции less и length, понятно, возвращают объекты, которые затем where компилирует в строчку. Или может не where, может стоит сначала собрать всё в один объект-запрос, проверив параллельно синтаксис, а затем всё за раз скомпилировать, чтобы не выделять память под строку с запросом, а непосредственно писать запрос в сокет sql.
Если напрягает то, что все эти "uid", "nickname" будут прогоняться через функцию экранирования каждый раз, дёргая каждый раз кучу и тормозя выполнение, то ничто не мешает объявить тип EscapedSqlString, который будет содержать в себе строку, а функция sql_escape_string, будет этот тип "разворачивать", возвращая строку изнутре не экранируя её, а обычный String она будет экранировать. Использование EscapedSqlString привносит возможностей скосячить, но так же оно привносит дополнительных трудностей, из-за чего самый простой способ использовать EscapedSqlString это:
const UID = EscapedSqlString::new("uid");
const NICKNAME = EscapedSqlString::new("nickname");
и затем:
.select([UID, NICKNAME, field_name])
и
.where(less(length(NICKNAME), 5))
Конечно, если мы говорим об интерпретируемом языке, то подобный подход всё равно добавит тормозов, потому что придётся собирать временный объект, но добавит оно не особо, а вот создать sql-инъекцию можно будет разве что злоумышленно.