Knex: вложенные необработанные запросы, экранирование "?"персонаж - PullRequest
0 голосов
/ 01 июня 2018

Я пытаюсь использовать Postgresql LTREE с knex.
Чтобы управлять им, я должен использовать необработанные запросы knex, потому что, очевидно, LTREE не является родным в knex (это специфично для postgresql)

Оператором в postgresql и LTREE является символ ?, в knex.raw символ ? используется для привязки значений (как всем известно), поэтому возникает конфликт.

Еще раз, это не такпроблема, потому что мы можем использовать \\? для предотвращения замены значений, когда knex находит ? в необработанном запросе.

Моя проблема в том, что мне нужно выполнить «SELECT EXISTS» моего запроса, содержащего knex.raw с символом \\?, а в knex я использую: knex.raw(myQuery).wrap('SELECT EXISTS(', ')'), чтобы выполнить SELECT EXISTS.Итак, у меня есть вложенные необработанные запросы, один для выбора существует и один в myQuery для условия postgresql ltree.

Во время выполнения запроса первый knex.raw преобразует исходный \\? в => ?, что нормально, и второй knex.raw будет выполнять ту же работу, он найдет ? и захочет связать данные, но я не даю ему данные, и поэтому knex выдает ошибку !!!

Решение состоит в том, чтобы поместить \\\\? вместо \\?, при этом первый knex.raw преобразует запрос с помощью \\?, а второй knex.raw преобразует окончательный запрос с ?, чтоэто то, что я хочу в postgresql (не пытаясь делать привязки)

Это здорово!Но myQuery генерируется универсальной функцией, которая вызывается в контексте с SELECT EXISTS, но также в контексте без SELECT EXISTS, и если я добавлю \\\\? только с одним knex.raw (контекст без SELECT EXISTS), он также выдастошибка postgresql на этот раз (потому что postgresql не может распознать \\?).

Можно ли экранировать символ `?` Через все knex.raw?

Плохое (но работающее) решение - установить параметр для функции, которая генерирует запрос кточно, если это контекст вложенных необработанных запросов или нет.

edit:

Вот простой пример кода, который мы можем иметь:

const functionThatCreatesTheSubQuery = () => {
    const condition = knex.raw('columnWithLTree \\? array["Root.Noeud1"]::lquery[]');
    return this.where(condition);
};
knex.raw( 
    knex.select('property')
        .from('table') 
        .where(functionThatCreatesTheSubQuery())
).wrap('SELECT EXISTS (', ')');

Это не получается, потому чтопервый knex.raw удаляет первый двойной \\ из \\?, а второй knex.raw для .wrap будет ожидать привязки

1 Ответ

0 голосов
/ 18 июля 2018

Вы передаете конструктор запросов в knex.raw(...) в качестве параметра в

knex.raw( 
    // this is not valid parameter
    knex.select('property')
        .from('table') 
        .where(functionThatCreatesTheSubQuery())
).wrap('SELECT EXISTS (', ')');

Это должно быть что-то вроде:

knex.raw('SELECT EXISTS (?)', [
    knex.select('property')
        .from('table') 
        .where(functionThatCreatesTheSubQuery())
]);

Необработанная подпись вызова равна knex.raw(String, [binding1, binding2, ...])

Вот пример runkit, который показывает, что вопросительный знак по-прежнему экранирован https://runkit.com/embed/bbtfooz9o1yn

Причина, по которой исходный запрос кажется работающим, заключается в том, что, вероятно, в какой-то момент, когда построитель запросов передается в knex.raw() какдля этого вызывается первый параметр, .toString(), который преобразует построитель запросов в простую строку SQL, где ? -марки не экранированы.

...