【问题标题】:Adding conditions to database queries in an orthogonal way以正交方式向数据库查询添加条件
【发布时间】:2014-07-03 23:54:59
【问题描述】:

当前的问题是如何以“正交方式”向预先存在的应用程序发出的 SQL 数据库查询添加条件,这意味着该操作应该以应用程序不需要关心的方式完成。如果您好奇,实际问题涉及添加多租户相关标准,以防止租户相互获取数据。实际上,这意味着向 WHERE 子句添加额外的条件(可能在查询中的多个位置)。

我的团队一直在研究一种解决方案,该解决方案涉及在将查询发送到 DBMS 之前“拦截”和解析查询。许多人可能都知道,SQL 解析并不是最简单的实现方式,尤其是当您需要支持大多数主要 DBMS 的语法扩展时。

另一个被抛出的想法是可以让 DBMS 自己处理标准注入。毕竟,它是对查询语法有充分了解的一个元素,并且(希望)在执行它之前对其进行修改应该没有问题。那么问题将是弄清楚如何将多租户元数据传递给 DBMS。这完全可行吗?这是个坏主意吗?

关于如何解决这个问题的任何其他想法?

感谢您的宝贵时间。

【问题讨论】:

    标签: sql parsing multi-tenant database


    【解决方案1】:

    浏览视图不是更容易吗,每个视图都仅限于适用的用户数据。预先编写的 SQL 可以使用视图的基本名称,然后在代码中对其进行修改,为视图名称添加前缀或后缀,以提供用户的视图。

    例子:

    tennant_data 具有名为tennant_data_user1tennant_data_user2 的视图。 你的 SQL 是select col1, col2 from tennant_data_{view} 您的程序代码获取当前用户的名称(user1 或 user2),并在 SQL 中将 {view} 替换为他们的用户 ID,然后执行 SQL。

    根据您使用的 DBMS(和语言?),您可能会授予访问权限,以便 user1 只能使用 xxx_user1 视图等,因此他们不可能误用查看或直接访问基础表。

    【讨论】:

      【解决方案2】:

      使用服务器端技术

      当然,实现此功能的理想位置是在服务器端。一些数据库实现了像 Oracle's Virtual Private Database 这样的功能,完全可以满足您的需求。

      您还可以通过将所有直接表访问替换为(可能是可更新的)视图来模拟该功能,其中包含使用SYS_CONTEXT(在 Oracle 中)对相关列的过滤器。使用这种方法,数据库客户端将永远无法绕过那些您将在任何地方添加的额外谓词。

      使用客户端技术

      您没有提到您正在使用的技术堆栈,但在 Java 中,这可以通过 jOOQ 完成。 jOOQ 附带一个 SQL 解析器,可以将 SQL 语句解析为表达式树。其主要用例之一是将 SQL 从一种方言翻译成另一种方言,如下所示:

      例如在 SQL Server 或 PostgreSQL 上运行的这条语句:

      try (DSLContext ctx = DSL.using("...");
           Connection c = ctx.parsingConnection(); // Magic here
           Statement s = c.createStatement();
           ResultSet rs = s.executeQuery(
               "SELECT * FROM (VALUES (1), (2), (3)) t(a)")) {
      
          while (rs.next())
              System.out.println(rs.getInt(1));
      }
      

      可以在 Oracle 中翻译成这个等价的语句:

      select t.a from (
        (select null a from dual where 1 = 0) union all
        (select * from (
          (select 1 from dual) union all
          (select 2 from dual) union all
          (select 3 from dual)
        ) t)
      ) t
      

      一旦有了 jOOQ 表达式树,就可以使用 jOOQ 的 VisitListener 对其进行转换,如以下文章所示:

      免责声明:

      • jOOQ 只能解析 jOOQ API 也支持的 SQL 功能。 The grammar can be seen here。这对于您现有的应用程序可能还不够,具体取决于您使用了多少供应商特定的功能。
      • 我在 jOOQ 背后的公司工作,所以很明显,这个答案是有偏见的。

      【讨论】:

        猜你喜欢
        • 2018-07-17
        • 1970-01-01
        • 1970-01-01
        • 2018-12-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多