我正在尝试将 Postgresql LTREE 与 knex 一起使用。
为了管理它,我必须使用 knex 的原始查询,因为显然 LTREE 在 knex 中不是本机的(它特定于 postgresql)
postgresql 和 LTREE 中的操作符是 character ?
,在 knex.raw 中,?
character 是用来绑定值的(众所周知),所以存在冲突。
再一次,这不是问题,因为我们可以使用它\\?
来防止替换 knex?
在原始查询中找到 a 的值。
我的问题是我需要对包含带有\\?
字符的 knex.raw 的查询执行“SELECT EXISTS”,并且在 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 转义 `?` 字符?
一个糟糕的解决方案(但一个可行的解决方案)是为生成查询的函数设置一个参数,以精确判断它是否是嵌套原始查询的上下文。
编辑 :
这是我们可以拥有的代码的简单示例:
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 删除了第一个 double并且 .wrap\\
的\\?
第二个 knex.raw 将等待绑定