【问题标题】:Get original sql query in postgres extension in C在 C 中的 postgres 扩展中获取原始 sql 查询
【发布时间】:2014-02-05 23:11:24
【问题描述】:

我正在用 C (c++) 创建对 postgres 的扩展。它是一种新的数据类型,其行为类似于文本,但由 HSM 设备加密。但是我有问题要使用一个以上的密钥来保护数据。我的想法是获取原始 sql 查询并对其进行处理以选择我应该使用的密钥。但我不知道该怎么做,或者是否有可能?

我的目标是将数据库中的一些现有文本字段更改为加密字段。这就是为什么我不能直接为我的类型提供密钥号的原因。外部应用程序必须将类型视为文本。

通常有 userID 字段,单个查询总是使用该 id 来获取或设置加密数据。基于该字段,我想选择键。 HSM 本身可以拥有数十亿个密钥,这意味着每个用户都可以拥有自己的密钥。如果我需要自己解析字符串,这不是问题,我更有能力做到这一点。性能也不是问题,HSM 太慢了,我只能在一秒钟内编码或解码几个字段。

【问题讨论】:

  • 用 C 或 C++ 创建扩展,是哪一个?
  • 我正在使用 C++ 进行开发,但 postgres 扩展接口需要使用 C 语言,并且 postgres 还提供了 C 函数与之通信。
  • @Logman 你知道 Pg 使用了基于longjmp 的错误处理,它不适用于 C++ 异常吗?您需要在 Pg 和 C++ 之间的边界处使用 extern "C" 接口,并在每个边界处捕获 C++ 异常并将它们转换为 PostgreSQL 错误 (ereport)。您也不能从任何需要堆栈展开的地方调用任何可能以ERROR 或更高级别调用elogereport 的PostgreSQL 函数。在实践中,这意味着编写一个不使用 libpq 并且只公开 C 接口的 C++ 库,然后是一个包装器 PostgreSQL 类型。
  • 简短的回答是肯定的;)。实际上我写了整个扩展,但现在我只使用一个键。

标签: sql c postgresql


【解决方案1】:

在规划器和执行器的大部分部分,当前(子)查询在传递的PlannerInfo 结构中可用,通常:

PlannerInfo *root

这有一个包含Query 对象的parse 成员。

在系统早期,在重写器中,直接传递为Query *root

在这两种情况下,如果对嵌套子查询进行评估,您将获得子查询。没有简单的方法可以访问父节点Query

查询树并不总是在执行路径的更深处可用,例如在表达式求值中。你不应该在那里指代它。表达式是自包含的,不需要引用查询的其余部分。

所以你在做你想做的事时会遇到问题。坦率地说,这是因为从声音上看这是一个非常糟糕的设计。您应该考虑的是:

  • 使用函数将类型编码/解码到/从明文,允许您传递参数;或者可能

  • 使用该类型的 typmod 来存储所需的信息(但请注意,typmod 不会跨强制转换、子查询等保留)。

还有debug_query_string 全局,但真的不要使用它。它是未解析的查询文本,因此无论如何它都不会帮助您。如果你(ab)在你的代码中使用它,我会哭的。我只是告诉你它存在,所以我可以告诉你不要使用它。

到目前为止,您最好的选择是为此使用基于函数的接口。

【讨论】:

  • 我不想让你哭泣,但你所说的我唯一的选择是使用 debug_query_string。我不能使用函数,因为我不能将查询更改为数据库。你能告诉我如何从 C 接口访问 debug_query_string 吗?
  • @Logman 查看标题。但请注意:debug_query_string 并不总是设置(例如 autovacuum);它也可能不会设置为您正在执行的同一查询,特别是在涉及嵌套查询和子查询或 pl/pgsql 的情况下。使用它真的是不对的。沿着这条路走下去,你的扩展很可能会随机崩溃,用错误的密钥加密东西(不可预测)等等。如果你知道所有将针对数据库运行的查询并且没有任何改变,那么你可能会侥幸逃脱,但是...现实不是那样的,如果是的话,它不会一直这样。
  • @Logman 也许如果您解释了密钥选择的标准,我可以提供更多有用的建议。并解释了您打算如何根据客户端查询文本自动选择正确的键。 (编辑问题?)
猜你喜欢
  • 2013-10-31
  • 2010-12-03
  • 2020-11-03
  • 2016-09-14
  • 1970-01-01
  • 2017-03-11
  • 2015-07-13
  • 1970-01-01
  • 2017-07-16
相关资源
最近更新 更多