为 objection.js 所做的所有查询打印完整的 SQL

Eug*_*Kim 7 objection.js

我正在寻找一种方法来捕获Objection.js库执行的所有查询的原始 SQL ,并将绑定插入到 SQL 字符串中。

我意识到有一个Knex 事件处理程序可以利用,但是它的第二个参数on('query', data)是一个包含 SQL 模板的对象,其中的绑定是分开的。

例如

{
  sql: "select \"accounts\".* from \"accounts\" where \"id\" = ?",
  bindings: [1]
}
Run Code Online (Sandbox Code Playgroud)

我想知道是否最优雅的方法是使用.toString()QueryBuilder 上存在的方法,但我认为回调中没有 QueryBuilder 的特定实例。理想情况下,我不会重新发明轮子并重新编写 Knex 的插值方法。

任何指针将不胜感激。

谢谢!

dar*_*nge 7

您可以使用该.toKnexQuery()函数提取底层 knex 查询构建器并获得对.toSQL()和 的访问权限.toQuery()

我使用 Objection 的第 2 版测试并验证了以下示例。我.toKnexQuery()版本 1 文档中找不到,因此无法验证它是否适用于早期版本的反对意见。

// Users.js
const { Model } = require('objection')

class Users extends Model {
  static get tableName() { return 'users' }
  // Insert jsonSchema, relationMappings, etc. here
}

module.exports = Users
Run Code Online (Sandbox Code Playgroud)
const Users = require('./path/to/Users')

const builder = Users.query()
  .findById(1)
  .toKnexQuery()

console.log(builder.toQuery())
// "select `users`.* from `users` where `users`.`id` = 1"

console.log(builder.toSQL())
// {
//   method: 'select',
//   bindings: [ 1 ],
//   sql: 'select `users`.* from `users` where `users`.`id` = ?'
// }
Run Code Online (Sandbox Code Playgroud)

可能应该重申的是,除了.toString(),.toQuery()也可能容易受到 SQL 注入攻击(请参阅此处)。

一种更“负责任”的方式来修改查询可能是这样的(使用 MySQL):

const { sql, bindings } = Users.query()
  .insert({ id: 1 })
  .toKnexQuery()
  .toSQL()
  .toNative()

Users.knex().raw(`${sql} ON DUPLICATE KEY UPDATE foo = ?`, [...bindings, 'bar'])
Run Code Online (Sandbox Code Playgroud)

  • 这是一个有用的答案,但对于“*所有*查询”的考虑不起作用。我正在使用 `withGraphFetched()` 方法来获取相关数据,这些技术没有打印出“后续”查询的查询(不知道如何称呼它们...... Objection.js 不使用与 `withGraphFetched 的联接` 但运行后续查询)。 (6认同)

Mik*_*stö 4

Knex / objection.js 不提供任何可以安全地进行插值的方法。.toString()在某些情况下可能会产生无效结果,并且它们可能容易受到 SQL 注入攻击。

如果仅用于调试目的,那么了解如何.toQuery()实现会有所帮助。https://github.com/knex/knex/blob/e37aeaa31c8ef9c1b07d2e4d3ec6607e557d800d/lib/interface.js#L12

knex.client._formatQuery(sql, bindings, tz)
Run Code Online (Sandbox Code Playgroud)

但它不是公共 API,因此即使在 knex 的补丁版本之间也不能保证相同。