驱动程序接口变更日志

Metabase 0.54.0

  • 添加了一个特性 :test/arrays 和多方法 native-array-query,以支持对支持数组类型的数据库进行数组类型测试。

Metabase 0.53.0

  • 添加了多方法 bad-connection-details,以允许模拟用于测试的错误连接参数。

Metabase 0.52.0

  • Metabase 0.52.0 的 Docker 镜像现在使用 Java 21 而不是 Java 11。请确保针对 Java 21 测试您的驱动程序,并确保其工作正常。

    我们发现我们自己的几个驱动程序在较新 JVM 中引入的安全性更改方面遇到了问题;因此,我们目前正在设置 JVM 标志

    --add-opens java.base/java.nio=ALL-UNNAMED
    

    在运行 Metabase 时禁用其中一些新的安全检查。如果您的测试在未设置标志的情况下在 Java 21 中遇到问题,请尝试在设置标志的情况下运行 - 这可能会解决问题。

Metabase 0.51.4

  • 又添加了一个驱动程序特性:describe-indexes。如果驱动程序选择支持此特性,则必须实现多方法 metabase.driver/describe-indexes,以替代 metabase.driver/describe-table-indexes

  • 已添加多方法 metabase.driver.sql-jdbc.sync.describe-table/describe-indexes-sql。如果驱动程序支持 describe-indexes 并且您想要使用 metabase.driver/describe-indexes 的默认 JDBC 实现,则需要实现该方法。

Metabase 0.51.0

  • 添加了新的可选方法 metabase.driver/query-result-metadata,用于高效计算查询的元数据,而无需实际运行查询。:sql-jdbc 已被赋予默认实现;未基于此的驱动程序,如果可以在不实际运行查询的情况下确定结果元数据,也应添加其实现,以便在保存问题时获得更好的性能。有关更多信息以及在哪里可以找到示例实现,请参阅方法文档字符串。

  • 在 0.51.0 之前,为了生成带有内联参数的 SQL 查询,Metabase 会生成一个参数化的 SQL 字符串,然后尝试解析 SQL 替换,并将 ? 占位符替换为驱动程序方法 metabase.driver.sql.util.unprepare/unprepare-value 中的内联值。在 0.51.0+ 中,Metabase 改为使用 Honey SQL 2 的 :inline 选项生成这些查询,从而消除了解析和替换 ? 占位符的需要。因此,metabase.driver.sql.util.unprepare 命名空间已被弃用;您应该删除驱动程序中所有对它的使用。

  • metabase.driver.sql.util.unprepare/unprepare-value 方法已被新方法 metabase.driver.sql.query-processor/inline-value 替换。这两个函数的签名相同,您应该能够简单地将所有 unprepare-value 实现更改为 inline-value。有关此更改的示例,请参阅 PR #45008

    目前,unprepare-value 的实现将自动用作 inline-value 的实现,但 unprepare-value 计划在 0.54.0 中删除。

  • metabase.driver.sql.query-processor/format-honeysql 现在是一个多方法,主要是为了您可以在需要始终在没有参数化的情况下编译时绑定 *compile-with-inline-parameters*

  • 已添加动态变量 metabase.driver/*compile-with-inline-parameters*(默认为 false);可以生成参数化查询的驱动程序应在其 metabase.driver/mbql->native 的实现中查看其值,并相应地调整其输出。对于支持参数化的基于 :sql-jdbc 的驱动程序,这在共享的 metabase.driver.sql.query-processor 代码中处理,因此您无需在此处进行任何调整。对于不支持 JDBC 样式参数化查询的 :sql 驱动程序,您可以实现 format-honeysql 并绑定 *compile-with-inline-parameters*,如上所述。有关如何执行此操作的示例,请参阅 :athena 驱动程序。

  • metabase.driver.sql.util.unprepare/unprepare 已被删除,它接受一个参数化的 SQL 字符串并对其进行解参数化或“未准备”。相反,如果您需要一个参数直接拼接在 SQL 中的查询,请如上所述绑定 metabase.driver/*compile-with-inline-parameters*

  • 同样,驱动程序方法 metabase.driver/splice-parameters-into-native-query 已被标记为已弃用,如果调用,默认实现将抛出异常。使用首先生成带有内联参数的查询的代码,重新编写生成参数化查询,然后调用 unpreparesplice-parameters-into-native-query 的代码,如上所述。如果需要,测试可以使用 metabase.query-processor.compile/compile-with-inline-parameters

  • metabase.query-processor.compile/compile-and-splice-parameters 已被删除;将用法替换为 metabase.query-processor.compile/compile-with-inline-parameters

  • metabase.driver.sql.query-processor/format-honeysql 的三元arity(它具有 Honey SQL 版本的附加参数)已被删除;将所有用法替换为二元arity 版本。自 Metabase 0.49.0 以来,Honey SQL 2 一直是唯一支持的版本。

  • 有时传递给用于加载和销毁测试数据的方法的 :skip-drop-db? 选项不再传递,您可以删除检查它的代码。测试数据代码现在可以更好地避免对 metabase.test.data.interface/create-db! 进行不必要的/冗余的调用,因此测试数据加载代码在加载测试数据之前不需要调用 DROP DATABASE IF EXISTS

  • 基于 JDBC 的数据库的测试数据加载已进行了某种程度的改进。多方法 metabase.test.data.sql-jdbc.load-data/load-data! 和用于它的辅助函数已被删除,取而代之的是几个新的更易于组合和理解的多方法。

  • metabase.test.data.sql-jdbc.load-data/row-xform 是加载测试数据时应用于每一行的 transducer。默认实现是 identity,但您可以使用 metabase.test.data.sql-jdbc.load-data/add-ids-xform 将 ID 添加到每一行(这取代了已删除的 metabase.test.data.sql-jdbc.load-data/load-data-add-ids 函数)和 metabase.test.data.sql-jdbc.load-data/maybe-add-ids-xform(它取代了 metabase.test.data.sql-jdbc.load-data/load-data-maybe-add-ids!metabase.test.data.sql-jdbc.load-data/load-data-maybe-add-ids-chunked!)。

  • metabase.test.data.sql-jdbc.load-data/chunk-size 用于控制每个批次应加载的行数。默认值为 200,但您可以实现此方法并返回 nil 以一次性加载所有数据,而无需考虑行数。metabase.test.data.sql-jdbc.load-data/*chunk-size*metabase.test.data.sql-jdbc.load-data/load-data-chunkedmetabase.test.data.sql-jdbc.load-data/load-data-all-at-once!metabase.test.data.sql-jdbc.load-data/load-data-chunked! 和其他类似函数不再需要,并且已被删除。

  • metabase.test.data.sql-jdbc.load-data/chunk-xform 是应用于每块行(取决于 chunk-size)或整组行(如果 chunk-sizenil)的 transducer。默认值为 identity。它可用于实现每个块的特殊行为,例如将块写入 CSV 文件以在 metabase.test.data.sql-jdbc.load-data/do-insert! 方法中单独加载。有关此示例,请参阅 metabase.test.data.vertica

  • 连接现在创建一次,并重复用于大部分测试数据加载。metabase.test.data.sql-jdbc.load-data/do-insert! 的第二个参数现在是 java.sql.Connection 而不是 clojure.java.jdbc 规范。

  • 同样,metabase.test.data.sql-jdbc.execute/execute-sql! 和辅助函数(如 metabase.test.data.sql-jdbc.execute/sequentially-execute-sql!)现在使用 java.sql.Connection 而不是 DatabaseDefinition:server:db *上下文* 一起调用;适当的连接类型会自动创建并在调用代码中传入。相应地更新您的方法实现和用法。

  • 添加了方法 metabase.test.data.interface/dataset-already-loaded?,用于检查测试数据集是否已加载。基于 JDBC 的驱动程序具有默认实现,该实现检查是否可以连接到数据库;对于实际上并未在测试中物理创建新数据库的驱动程序,您可能需要覆盖此实现。您可以通过运行测试 metabase.test.data.sql-jdbc-test/dataset-already-loaded?-test 来检查基于 JDBC 的驱动程序是否使用默认实现正确工作。

  • metabase.test.data.sql.ddl/insert-rows-ddl-statements 已重命名为 metabase.test.data.sql.ddl/insert-rows-dml-statements,因为 INSERT 是 DML,而不是 DDL。请相应地更新您的方法实现。

  • 已删除 :foreign-keys 驱动程序功能。:metadata/keys-constraints 应该用于在同步期间支持外键关系报告的驱动程序。隐式连接现在依赖于 :left-join 功能。对于基于 :sql 的驱动程序,默认值为 true。现在,所有连接功能默认都为基于 :sql 的驱动程序启用。以前,这些功能依赖于 :foreign-keys 功能。如果您的驱动程序支持 :left-join,则现在将执行重新映射和隐式连接的测试。

  • 添加了 :parameterized-sql 驱动程序功能,以区分在测试中不支持参数化 SQL 的驱动程序。目前,仅对 :sparksql 禁用此功能。

  • 已删除测试方法 metabase.test.data.interface/supports-time-type?metabase.test.data.interface/supports-timestamptz-type?,并分别替换为功能 :test/time-type:test/timestamptz-type。如果您实现了这些方法,请将实现替换为驱动程序的 metabase.driver/database-supports? 实现以及等效的功能关键字。

  • 使用 metabase.driver.sql.query-processor/->honeysql 的驱动程序可以实现 :metabase.driver.sql.query-processor/nfc-path,以在字段标识符中包含 nfc-path。这样,就可以使用 <table>.<record>.<record-field> 引用类似记录的字段。有关示例,请参见 bigquery-cloud-sdk。默认为 nil,表示路径不应成为标识符的一部分。

  • 添加了 :test/dynamic-dataset-loading 功能。它使驱动程序能够退出在测试运行时需要创建新的、非预加载的数据集的测试。

  • 添加了 :temporal/requires-default-unit 功能。对于大多数驱动程序,它应为 false,但对于少数驱动程序(例如旧的、pre-JDBC Druid 驱动程序)来说,它对于查找所有时间字段引用并在其上放置 :temporal-unit :default 是必要的。以前,默认设置是为所有驱动程序完成的,但这引入了一些下游问题,因此现在只有那些需要它的驱动程序才能设置此功能。

Metabase 0.50.17

  • 添加了方法 metabase.driver/incorporate-auth-provider-details,用于驱动程序特定的行为,该行为需要将身份验证提供程序的响应合并到数据库详细信息中。在大多数情况下,这意味着根据身份验证提供程序及其响应设置 :password 和/或 :username。

Metabase 0.50.16

  • :type/fingerprinting-unsupported 已在 metabase.types 命名空间中添加。与用于字段值扫描的 :type/field-values-unsupported 类似,它用于确定是否应为特定字段计算指纹。在编写本文时,该逻辑在 metabase.sync.analyze.fingerprint/fields-to-fingerprint-base-clause 中执行。

  • :type/Large 也已在 metabase.types 命名空间中添加。驱动程序作者可以使用它来指示特定字段包含足够大的值,以跳过指纹识别或字段值扫描。将来它也可以用于其他目的。示例包括 Oracle CLOB 或 Postgres JSON 列。

Metabase 0.50.0

  • Metabase metabase.mbql.* 命名空间已移动到 metabase.legacy-mbql.*。您可能不需要在驱动程序中使用这些命名空间,但如果您使用了,请更新它们。

  • 添加了多方法 metabase.driver/truncate!。此方法用于以最有效的方式删除表中的行。目前,这仅对于支持 :uploads 功能的驱动程序是必需的,并且基于 JDBC 的驱动程序具有默认实现。

  • 添加了新功能 :window-functions/cumulative。实现此方法的驱动程序应在其本机查询语言中实现累积和 (:cum-sum) 和累积计数 (:cum-count) 聚合子句。对于非 SQL 驱动程序(不是基于我们的 :sql:sql-jdbc 驱动程序的驱动程序),此功能标志默认设置为 false;累积聚合的旧的(已损坏的)后处理实现将继续使用。(有关旧实现为何损坏的更多信息,请参见问题 #13634#15118。)

    如果可能,应更新非 SQL 驱动程序以本机实现累积聚合。

    SQL 实现使用 OVER (...) 表达式。它将自动将 GROUP BY 表达式(如 date_trunc())移动到 SUBSELECT 中,以便像 BigQuery 这样挑剔的数据库可以引用普通列标识符。生成的实际 SQL 将类似于

    SELECT
      created_at_month,
      sum(sum(total) OVER (ORDER BY created_at_month ROWS UNBOUNDED PRECEDING) AS cumulative_sum
    FROM (
      SELECT
        date_trunc('month', created_at) AS created_at_month,
        total
      FROM
        my_table
      ) source
    GROUP BY
      created_at_month
    ORDER BY
      created_at_month
    

    如果非 SQL 驱动程序想要利用相同的查询转换,可以使用 metabase.query-processor.util.transformations.nest-breakouts/nest-breakouts-in-stages-with-window-aggregation。有关在需要时使用此转换的示例,请参见 :sql 的默认 metabase.driver.sql.query-processor/preprocess 实现。

    您可以运行 metabase.query-processor-test.cumulative-aggregation-test 中的新测试,以验证您的驱动程序实现是否正常工作。

  • metabase.driver.common/class->base-type 不再支持 Joda Time 类。它们自 2019 年起已被弃用。

  • 添加了新功能 :window-functions/offset,以表示驱动程序支持新的 MBQL :offset 子句(等效于 SQL leadlag 函数)。对于基于 :sql:sql-jdbc 的驱动程序,默认启用此功能。其他驱动程序应为此子句添加实现并启用功能标志。

  • :type/field-values-unsupportedmetabase.types 命名空间中添加。它在字段值计算逻辑中使用,以确定是否应为特定字段计算其字段值。在编写本文时,这在 metabase.models.field-values/field-should-have-field-values? 中执行。由此推导,驱动程序开发人员有一种方法可以避免为与用于计算的查询不兼容的字段进行字段值计算。例如,可能是 Druid 的 COMPLEX<JSON> 数据库类型字段。有关示例,请参见 metabase.driver.druid-jdbc 中的 sql-jdbc.sync/database-type->base-type:druid-jdbc 实现以及 metabase.types 命名空间中的派生。

  • 添加了新功能 :metadata/key-constraints,以表示驱动程序支持在模式级别定义和强制执行外键约束。这是一个与 :foreign-keys 不同的、更强的条件。某些数据库(Presto、Athena 等)支持查询外键关系 (:foreign-keys),但不在模式中跟踪或强制执行这些关系。在 :sql:sql-jdbc 驱动程序中,默认为 true;在第一方 SparkSQL、Presto 和 Athena 驱动程序中,设置为 false

  • 添加了新功能 :connection/multiple-databases,以指示此驱动程序的连接是对应于多个数据库还是仅对应于一个数据库。默认值为 false,其中连接指定单个数据库。这是像 Postgres 这样的经典关系数据库和一些云数据库的常见情况。相比之下,像 Athena 这样的驱动程序将其设置为 true,因为它连接到 S3 存储桶并将其中的每个文件都视为一个数据库。

  • 添加了新功能 :identifiers-with-spaces,以指示驱动程序在何处支持包含空格字符的标识符,如表名或列名。默认为 false

  • 添加了新功能 :uuid-type,以指示此数据库能够区分 UUID 并根据 UUID 进行筛选。只有少数数据库支持本机 UUID 类型。默认值为 false

Metabase 0.49.22

  • 添加了一个新的可选方法 metabase.driver.sql/json-field-length。对于所有派生自 :sql 并支持 :nested-field-columns 功能的驱动程序,都应实现此方法。如果实现此方法,Metabase 将跳过在“sync-fields”步骤期间查询大型 JSON 值,否则可能会减慢嵌套字段列的推断速度并导致 Metabase 耗尽堆空间。

Metabase 0.49.9

  • 添加了另一个驱动程序功能:upload-with-auto-pk。它仅影响支持 uploads 的驱动程序,并且是可选支持的。默认情况下,驱动程序支持此功能,如果无法创建带有自动递增整数列的表,则可以选择不支持它。驱动程序可以使用 driver/database-supports? 覆盖默认值。

Metabase 0.49.1

  • 添加了另一个驱动程序功能:describe-fields。如果驱动程序选择加入支持此功能,则必须实现多方法 metabase.driver/describe-fields,以替代 metabase.driver/describe-table

  • 添加了多方法 metabase.driver.sql-jdbc.sync.describe-table/describe-fields-sql。如果驱动程序支持 describe-fields 并且您想使用 metabase.driver/describe-fields 的默认 JDBC 实现,则需要实现此方法。

Metabase 0.49.0

  • 多方法 metabase.driver/describe-table-fks 已弃用,建议使用 metabase.driver/describe-fksmetabase.driver/describe-table-fks 将在 0.52.0 中删除。

  • 添加了多方法 metabase.driver/describe-fks。如果数据库支持 :foreign-keys:describe-fks 功能,则需要实现此方法。它取代了 metabase.driver/describe-table-fks 方法,该方法现已弃用。

  • 添加了多方法 metabase.driver.sql-jdbc.sync.describe-table/describe-fks-sql。如果您想使用 metabase.driver/describe-fks 的默认 JDBC 实现,则需要实现此方法。

  • 添加了多方法 metabase.driver/alter-columns!。此方法用于更改数据库中表的列。目前,这仅对于支持 :uploads 功能的驱动程序是必需的,并且基于 JDBC 的驱动程序具有默认实现。

  • 添加了多方法 metabase.driver.sql-jdbc.sync.interface/alter-columns-sql。此方法允许您自定义 metabase.driver/alter-columns! 的默认 JDBC 实现使用的查询。

  • 添加了多方法 metabase.driver.sql-jdbc.sync.interface/current-user-table-privileges。基于 JDBC 的驱动程序可以实现此方法,以提高 metabase.driver/describe-database 的默认 SQL JDBC 实现的性能。如果数据库支持 :table-privileges 功能并且驱动程序是基于 JDBC 的,则需要实现此方法。

  • 多方法 metabase.driver/create-table! 可以接受一个额外的可选映射,其中包含一个可选键 primary-keymetabase.driver/upload-type->database-type 也必须更改,以便如果 :metabase.upload/auto-incrementing-int-pk 作为 upload-type 参数提供,则该函数应返回不包含主键约束的类型。有关更多信息,请参见 PR #22166。只有当数据库支持 :uploads 功能时,才需要实现这些更改。

  • 添加了多方法 metabase.driver/create-auto-pk-with-append-csv?。仅当数据库在 47 或更早版本中支持 :uploads 功能时,才需要实现此方法,如果支持,则应返回 true。

  • 添加了多方法 metabase.driver/add-columns!。此方法用于向数据库中的表添加列。仅当数据库在 47 或更早版本中支持 :uploads 功能时,才需要实现此方法。

  • 添加了一个新的驱动程序方法 metabase.driver/describe-table-indexes 以及一个新功能 :index-info。此方法用于获取一组已索引或复合索引中第一列的列名。

  • 在 0.46.0 中已弃用的 metabase.util.honeysql-extensions 已被删除。不再支持使用 Honey SQL 1 的基于 SQL 的驱动程序。有关更多信息,请参见 0.46.0 注释。metabase.driver.sql.query-processor/honey-sql-version 现在已弃用,不再调用。假定所有驱动程序都使用 Honey SQL 2。

  • 方法 metabase.driver.sql.parameters.substitution/align-temporal-unit-with-param-type 现在已弃用。请改用 metabase.driver.sql.parameters.substitution/align-temporal-unit-with-param-type-and-value,后者可以访问 value,因此为选择正确的转换单位提供了更大的灵活性。

Metabase 0.48.0

  • metabase.mbql.schema 中的 MBQL 模式现在使用 Malli 而不是 Schema。如果您在结合 Schema 使用此命名空间,则需要更新代码以改用 Malli。

  • 添加了另一个驱动程序功能::table-privileges。此功能指示我们是否可以在数据库同步时存储数据库的表级权限。

  • 添加了多方法 metabase.driver/current-user-table-privileges。此方法用于获取数据库连接的当前用户拥有的权限集。如果数据库支持 :table-privileges 功能,则需要实现此方法。

  • metabase.query-processor.store (qp.store) 中的以下函数现已弃用

    • qp.store/database
    • qp.store/table
    • qp.store/field

    更新为使用 metabase.lib.metadata (lib.metadata) 中的相应函数

    (qp.store/database)       => (lib.metadata/database (qp.store/metadata-provider))
    (qp.store/table table-id) => (lib.metadata/table (qp.store/metadata-provider) table-id)
    (qp.store/field field-id) => (lib.metadata/field (qp.store/metadata-provider) field-id)
    

    请注意,新方法将键作为 kebab-case 而不是 snake_case 返回。

  • 同样,驱动程序不应直接访问应用程序数据库(通过 toucan 函数或其他方式);请改用 lib.metadata 函数。此访问权限可能会在将来的版本中被阻止。

  • metabase.models.table/Table/:model/Table 实现 metabase.driver.sql.query-processor/->honeysql 的 SQL 驱动程序应更新为为 :metadata/table 实现它。与上述更改一样,主要区别在于新的元数据映射使用 kebab-case 键而不是 snake_case 键。

  • metabase.driver.sql.query-processor/cast-field-if-needed 现在期望 lib.metadata/field 返回的 kebab-case 字段。

  • metabase.query-processor.store/fetch-and-store-database!metabase.query-processor.store/fetch-and-store-tables!metabase.query-processor.store/fetch-and-store-fields! 已被删除。现在,事物会根据需要自动获取,并且不再需要这些调用。

  • metabase.models.field/json-field? 已被删除,请改用 metabase.lib.field/json-field?。请注意,新函数接受 lib.metadata/field 返回的字段,即 kebab-case 映射。

  • 测试应尽量避免使用任何 with-temp 帮助程序或应用程序数据库对象;而是使用上述元数据函数以及 metabase.libmetabase.lib.test-utilmetabase.query-processor.test-util 中的帮助程序元数据提供程序来模拟它们,例如 mock-metadata-providermetabase-provider-with-cards-for-queriesremap-metadata-providermerged-mock-metadata-provider

  • metabase.query-processor.util.add-alias-info/field-reference 现已弃用。如果您的驱动程序实现了它,请改为实现 metabase.query-processor.util.add-alias-info/field-reference-mlv2。两者之间的唯一区别是后者传递的字段元数据带有 kebab-case 键,而前者传递的旧版元数据带有 snake_case 键。

  • 在 0.34 中已弃用的 metabase.driver/current-db-time 以及相关方法和帮助程序函数已被删除。请改为实现 metabase.driver/db-default-timezone

  • 用于编写基于 JDBC 的驱动程序的 metabase.driver/db-default-timezone 实现的帮助程序 metabase.driver.sql-jdbc.sync.interface/db-default-timezone 已弃用,并计划在 0.51.0 或更高版本中删除。您可以轻松地直接实现 metabase.driver/db-default-timezone,并使用 metabase.driver.sql-jdbc.execute/do-with-connection-with-options 获取数据库的 java.sql.Connection

  • 添加了一个新的多方法 metabase.driver.sql.parameters.substitution/align-temporal-unit-with-param-type,它为 fieldparam-type 和给定的驱动程序返回合适的时态单位转换关键字。生成的关键字将用于调用相应的 metabase.driver.sql.query-processor/date 实现来转换 field。如果此 fieldparam-type 组合不需要转换,则返回 nil

  • 添加了多方法 metabase.driver.sql-jdbc.execute/inject-remark。它允许基于 JDBC 的驱动程序覆盖如何将 SQL 查询备注添加到查询的默认行为(将其作为注释前置)。

  • 多方法 metabase.driver.sql-jdbc.sync.interface/fallback-metadata-query 的arity已从 3 更新为 4,现在它接受一个额外的 db 参数。新函数参数为:[driver db-name-or-nil schema table]

Metabase 0.47.0

  • 添加了一个新的驱动程序功能::schemas。此功能指示数据库是否在模式(也称为命名空间)中组织表。大多数数据库都有模式,因此默认情况下此功能处于启用状态。只有当数据库未在模式中存储表时,才需要为 :schemas 实现多方法 metabase.driver/database-supports?

  • 添加了另一个驱动程序功能::uploads:uploads 功能指示数据库是否支持将 CSV 文件上传到数据库中的表。要支持 uploads 功能,请实现以下新的多方法:metabase.driver/create-table!(创建表)、metabase.driver/drop-table!(删除表)和 metabase.driver/insert-into!(将值插入表)。

  • 添加了多方法 metabase.driver/syncable-schemas。此方法用于列出要将 CSV 上传到的模式,并且应包括所有可以同步的模式。目前,仅当数据库具有模式并且数据库支持 :uploads 功能时,才需要实现此方法。

  • 多方法 metabase.driver/supports? 已弃用,建议使用 metabase.driver/database-supports?database-supports? 的现有默认实现当前调用 supports?,但它将在 0.50.0 中删除。

  • metabase.driver.sql-jdbc.execute/connection-with-timezone 已标记为已弃用,并计划在 Metabase 0.50.0 中删除。新的方法 metabase.driver.sql-jdbc.execute/do-with-connection-with-options 取代了它。迁移到新方法非常简单。有关更多信息,请参见 PR #22166。您应该使用 metabase.driver.sql-jdbc.execute/do-with-connection-with-options 而不是 clojure.java.jdbc/with-db-connectionclojure.java.jdbc/get-connection

  • 添加了多方法 set-role!set-role-statementdefault-database-role。这些方法用于启用连接模拟,这是在 0.47.0 中添加的新功能。连接模拟允许将用户分配给特定的数据库角色,这些角色在执行任何查询之前设置,以便可以在数据库级别而不是(或结合)Metabase 的内置权限系统来限制对表的访问。

  • 多方法 metabase.driver.sql-jdbc.sync.describe-table/get-table-pks 已更改为返回向量而非集合。

  • 函数 metabase.query-processor.timezone/report-timezone-id-if-supported 已更新为接受一个额外的 database 参数,用于以前只有一个参数的arity。此函数可能在驱动程序的多方法的实现中使用。

  • metabase.driver/prettify-native-form 已添加,以使驱动程序开发人员能够使用特定于其驱动程序的本机表单格式。有关详细信息,请参见 PR #34991

Metabase 0.46.0

  • 在 Metabase 0.46.0 中,构建驱动程序的过程略有变化。您的构建命令现在应类似于以下内容

    # Example for building the driver with bash or similar
    
    # switch to the local checkout of the Metabase repo
    cd /path/to/metabase/repo
    
    # get absolute path to the driver project directory
    DRIVER_PATH=`readlink -f ~/sudoku-driver`
    
    # Build driver. See explanation in sample Sudoku driver README
    clojure \
      -Sdeps "{:aliases {:sudoku {:extra-deps {com.metabase/sudoku-driver {:local/root \"$DRIVER_PATH\"}}}}}"  \
      -X:build:sudoku \
      build-drivers.build-driver/build-driver! \
      "{:driver :sudoku, :project-dir \"$DRIVER_PATH\", :target-dir \"$DRIVER_PATH/target\"}"
    

    请查看我们的 Sudoku 驱动程序示例的构建说明,以了解命令的说明。

    请注意,虽然此命令本身需要输入很多内容,但您不再需要在驱动程序的 deps.edn 文件中指定 :build 别名。

    请在 https://ask.clojure.net.cn/index.php/7843/allow-specifying-aliases-coordinates-that-point-projects 上投赞成票,这将使我们能够在将来简化驱动程序构建命令。

  • 添加了多方法 metabase.driver/table-rows-sample。当 Metabase 需要表中的有限样本时(例如在指纹识别时),将使用此方法。在 metabase.db.metadata-queries 命名空间中定义的默认实现运行 MBQL 查询,使用常规查询处理器来生成样本行。这在大多数情况下都足够好,因此除非确实必要,否则不应实现此多方法。当前,唯一使用特殊实现的情况是 BigQuery,它不遵守 limit 子句。

  • 添加了多方法 metabase.driver.sql.query-processor/datetime-diff。此方法供 :datetime-diff 子句的 ->honeysql 实现使用。如果您想使用 :datetime-diff 的默认 SQL 实现 ->honeysql(包括跨所有单位的参数类型验证),建议实现此方法。

  • 添加了多方法 metabase.query-processor.util.add-alias-info/field-reference。此方法用于通过 add-alias-info 中间件生成对字段的引用。(请注意,此中间件是可选的,当前仅由 SQL 和 MongoDB 驱动程序使用。)默认实现返回字段实例的名称。如果仅名称不是有效的引用,则应覆盖它。例如,MongoDB 支持嵌套文档,并且对嵌套字段的引用应包含整个路径。有关替代实现,请参见命名空间 metabase.driver.mongo.query-processor

  • 在 0.43.0 中已弃用的多方法 metabase.driver.sql-jdbc.sync.interface/syncable-schemas(别名为 metabase.driver.sql-jdbc.sync/syncable-schemas)已被删除。请改为实现 metabase.driver.sql-jdbc.sync.interface/filtered-syncable-schemas。有关更多详细信息,请参见下面的 0.43.0 注释。

  • 在 0.42.0 中已弃用的多方法 metabase.driver/format-custom-field-name 已被删除。请改为实现 metabase.driver/escape-alias。有关更多信息,请参见下面的 0.42.0 注释。

  • 在 0.35.0 中已弃用的多方法 metabase.driver.sql-jdbc.execute/read-column 已被删除。请改为实现 metabase.driver.sql-jdbc.execute/read-column-thunk。有关更多信息,请参见下面的 0.35.0 注释。

Honey SQL 2

以下内容仅适用于 SQL 驱动程序;对于非 SQL 驱动程序,您可以忽略它。

在 Metabase 0.46.0 之前,SQL 驱动程序使用 Honey SQL 1 作为编译查询的中间目标。在 0.46.0 中,我们已开始迁移到 Honey SQL 2 作为新的中间目标的过程。

我们计划继续支持使用 Honey SQL 1,直到 Metabase 0.49.0。请务必在此之前迁移您的驱动程序。

在 Metabase 0.46.x、0.47.x 和 0.48.x 中,您可以通过实现 metabase.driver.sql.query-processor/honey-sql-version 多方法来指定驱动程序应使用的 Honey SQL 版本

(require '[metabase.driver.sql.query-processor :as sql.qp])

;;; use Honey SQL 2 for :my-driver
(defmethod sql.qp/honey-sql-version :my-driver
  [_driver]
  2)

此方法必须返回 12。目前,默认实现返回 1。实际上,这意味着您目前需要选择启用 Honey SQL 2 编译。最好尽早执行此操作,以便您的驱动程序为 0.49.0 版本做好充分准备。

在 Metabase 0.47.x 或 0.48.x 版本中,我们可能会将默认 Honey SQL 版本更改为 2,以确保每个人都意识到 0.49.0 版本中即将到来的重大更改,并为他们提供一个或两个发布周期来更新其驱动程序以适配 Honey SQL 2。在 0.49.0 版本之前,您仍然可以通过实现 sql.qp/honey-sql-version 并返回 1 来选择使用 Honey SQL 1。

您需要更改的内容

我们的 Honey SQL 实用程序命名空间 metabase.util.honeysql-extensions(通常别名为 hx)已更新,以生成适用于 Honey SQL 1 或 Honey SQL 2 的形式。这是根据您的驱动程序的 honey-sql-version 自动完成的。metabase.driver.sql.query-processor 本身也以相同的方式支持这两种目标版本。

您需要对驱动程序代码进行的实际更改可能相当小。移植驱动程序时,最重要的事情是注意以下几点

  1. 避免使用 Honey SQL 1 命名空间中的内容,例如 honeysql.corehoneysql.format。如果必须使用,请改用 Honey SQL honey.sql;您可能两者都不需要。

  2. 虽然您可以在短期内继续使用 metabase.util.honeysql-extensions,因为它能够以 Honey SQL 的任一版本为目标,但我们可能会在未来的某个时候删除此命名空间。请更新您的代码以改用 metabase.util.honey-sql-2。这两个命名空间实现了几乎相同的辅助函数集,因此您只需切换您在 ns 表单中 :require 的命名空间即可。

  3. honeysql.core/call 不再存在;对于像 (hsql/call :my_function 1 2) 这样的形式,您只需返回一个普通的向量,例如 [:my_function 1 2](hsql/raw "x") 现在是 [:raw "x"]。可以使用 honey.sql/register-fn! 向 Honey SQL 2 注册新的处理程序。Honey SQL 1 的 honeysql.format./ToSql 协议没有等效项,因此您不应再定义一次性类型来实现自定义 SQL 编译规则。请改用 honey.sql/register-fn!

  4. 在 Honey SQL 1 中,您可以通过实现多方法 honeysql.format/fn-handler 在更大程度上注册函数。Metabase 以这种方式注册了函数 :extract:distinct-count:percentile-cont。对于 Honey SQL 2,我们将这些函数注册为 metabase.util.honey-sql-2 命名空间中的限定关键字,以防止混淆它们的定义位置。因此,如果您正在使用这些函数,则需要更新关键字。

    ;;; Honey SQL 1
    (hsql/call :distinct-count expr)
    

    变为

    ;;; Honey SQL 2
    (require '[metabase.util.honey-sql-2 :as h2x])
    
    [::h2x/distinct-count expr]
    
  5. 由于自定义表达式现在只是像 [:my_function 1] 这样的普通向量,如果它们出现在 :select:from 或其他向量可能被解释为 [expression alias] 的位置,您可能需要将表达式包装在额外的向量中。例如:

    ;; Honey SQL 1
    (honeysql.core/format {:select [[:my_function 1]]})
    ;; => ["SELECT my_function AS 1"]
    
    ;; Honey SQL 2
    ;;
    ;; WRONG
    (honey.sql/format {:select [[:my_function 1]]})
    ;; => ["SELECT my_function AS ?" 1]
    
    ;; CORRECT
    (honey.sql/format {:select [[[:my_function 1]]]})
    ;; => ["SELECT MY_FUNCTION(?)" 1]
    

    SQL 查询处理器会自动为它生成的表单执行此操作,因此您只需在覆盖它生成 :select 或其他顶级子句的方式时才需要担心这一点。

  6. 数字默认情况下是参数化的,例如 {:select [1]} 变为 SELECT ? 而不是 SELECT 1。您可以使用 :inline 强制 SQL 内联生成:{:select [[[:inline 1]]]} 变为 SELECT 1。由 SQL 查询处理器代码生成的数字应自动内联,但您可能需要确保您生成的任何数字都包装在 :inline 中,如果它们可能最终成为 GROUP BY 子句内的表达式。某些数据库只有在表达式 *未* 参数化时才能识别它们是相同的事物

    -- This is okay
    SELECT x + 1
    FROM table
    GROUP BY x + 1
    
    -- Bad: DB doesn't know whether the two x + ? expressions are the same thing
    SELECT x + ?
    FROM table
    GROUP BY x + ?
    

内联内容时请谨慎使用 :inline – 注意不要在不受信任的字符串或其他 SQL 注入途径上使用它。仅内联 number? 类型的内容才是安全的选择。

请阅读 Honey SQL 1.x 和 2.x 之间的差异,以获取有关库版本之间差异的更多信息。

注意:这些重大更改有望在 0.46.0 版本发布之前修复。如果已修复,此处将进行更新。

metabase.util.honeysql_extensions.Identifermetabase.util.honeysql_extensions.TypedHoneySQLForm 已分别移动到 metabase.util.honey_sql_1.Identifermetabase.util.honey_sql_1.TypedHoneySQLForm。如果您的驱动程序直接引用这些类名,您可能需要更新内容以使用新的类名。

同样,metabase.util.honeysql-extensions/->AtTimeZone 已被删除;请改用 metabase.util.honeysql-extensions/at-time-zone

Metabase 0.45.0

  • metabase.driver.sql-jdbc.connection/details->connection-spec-for-testing-connection 已在 Metabase 0.45.0 版本中删除,因为它会泄漏 SSH 隧道。请参阅 #24445。如果您正在使用此函数,请更新您的代码以改用 metabase.driver.sql-jdbc.connection/with-connection-spec-for-testing-connection,它会在自身之后正确清理。

新方法

  • 已添加 metabase.driver.sql-jdbc.sync.describe-table-fields。如果您想覆盖用于获取表的字段元数据(例如类型)的默认行为,请实现此方法。

  • 已添加 metabase.driver.sql-jdbc.sync.describe-table/get-table-pks。此方法用于获取给定表的主键集。

  • 已添加 ->honeysql [<driver> :convert-timezone]。如果您希望您的驱动程序支持 convertTimezone 表达式,请实现此方法。此方法接受 2 个或 3 个参数,并返回一个 timestamp without time zone 列。

Metabase 0.43.0

  • MBQL 查询中的 :expressions 映射现在使用字符串作为键而不是关键字(请参阅 #14647)。只有当您直接访问或操作此映射时,才需要关注这一点。从 :sql 派生的驱动程序,为 [<driver> :expression] 实现 ->honeysql 的驱动程序可能需要更新。实用程序函数 metabase.mbql.util/expression-with-name 至少自 Metabase 0.35.0 版本以来就已可用,并且可以处理两种类型的键。强烈建议您使用此函数而不是直接访问 :expressions,因为这样做可以使您的驱动程序与 0.42.0 以及 0.43.0 和更高版本兼容。

  • 现在在 sql-jdbc.sync 命名空间下有一个 describe-nested-field-columns 方法,该方法返回 NestedFCMetadata 的实例。这是为了允许 Postgres 中的 JSON 列,以及最终允许其他通常是普通 RDBMS 的数据库,但有时它们会有一个包含 JSON 或其他语义的反规范化列。给定一个具有反规范化列的表,这些列具有嵌套字段语义(因此,类型化的子字段仍然是反规范化的,但在行之间类型稳定),返回值应为 NestedFCMetadata,它是扁平化键路径到检测到的子字段的映射。字段检测同步将通过这些嵌套类型进行丰富。这与我们对 mongo 所做的方式有很大不同,因为每种 JSON 列都不同,但它将在每次同步时运行,因此即使在巨大的表和这些巨大表上的巨大反规范化列上,它也不能太慢。

Metabase 0.42.0

Metabase 0.42.0 版本中的更改会影响从 :sql(包括 :sql-jdbc)派生的驱动程序。非 SQL 驱动程序可能不需要任何更改。

0.42.0 版本对 SQL 查询处理器编译和确定 MBQL :field 子句别名的方式引入了几项重大更改。有关更多背景信息,请参阅拉取请求 #19384

如果您正在操作字段或表别名,我们整合了许多重叠的变量和方法,这意味着您可能需要删除已弃用的方法实现。

重大更改

  • 不再调用字段实例的 metabase.driver.sql.query-processor/->honeysql 方法,例如:

    (defmethod sql.qp/->honeysql [:my-driver (class Field)]
      [driver field]
      ...)
    

    所有编译现在都由 MBQL :field 子句方法处理,例如:

    (defmethod sql.qp/->honeysql [:my-driver :field]
      [driver field-clause]
      ...)
    

    如果您在此处执行了某些特殊操作,则需要将该特殊登录逻辑移动到 [<driver> :field] 中。(但是,您可能不再需要此特殊逻辑 – 请参阅下文。)

  • :field:expression:aggregation-options 子句现在包含有关您应在 SQL AS 的左侧和右侧或查询中其他位置使用哪些别名来引用它们的信息。有关新信息的详细讨论,请参阅 PR #19610,以下称为 /#19610 信息/。

  • 如果您有 :field(class Field)->honeysql 的自定义实现::field->honeysql 方法应使用或替换 #19610 信息,而不是尝试以其他某种方式确定或覆盖它。

新方法

  • metabase.driver/escape-alias(从 metabase.driver.sql.query-processor/escape-alias 移动而来,后者在 0.41.0 版本中引入)现在用于生成 #19610 信息,并在整个 SQL QP 代码中一致使用。如果您需要出于任何原因转换生成的字段别名(例如,转义不允许的字符),请实现此方法。

  • 已添加 metabase.driver.sql-jdbc.sync.interface/filtered-syncable-schemas,并将最终取代 metabase.driver.sql-jdbc.sync.interface/syncable-schemas。它的用途类似,只是它还传递了包含和排除模式(例如:auth*,data*)以进一步过滤将要同步的模式。

已弃用的方法和变量

除非另有说明,否则以下方法和变量计划在 Metabase 0.45.0 版本中删除。

  • metabase.driver/format-custom-field-name 现在未使用。请改用 metabase.driver/escape-alias 实现。

  • metabase.driver.sql.query-processor/escape-alias 已重命名为 metabase.driver/escape-alias。其他一切都相同。

  • metabase.driver.sql.query-processor/field-clause->alias 不再使用可选参数 unique-name-fn。别名现在在转义后自动变得唯一;如果您需要在使它们唯一之前执行某些特殊操作,请实现 metabase.driver/escape-alias。(如果您需要执行 *真正* 特殊的操作,唯一别名也会被再次转义。)

  • metabase.driver.sql.query-processor/field->alias 在 0.41.0 版本中已弃用,现在在 0.42.0 版本中未使用。实现此方法不再有任何效果。如果您需要执行某些特殊操作,请改用 metabase.driver/escape-alias;如果您需要出于某种原因转义别名,请使用 #19610 信息。此方法仍计划在 Metabase 0.44.0 版本中删除。

  • metabase.driver.sql.query-processor/*field-options* 现在未使用,并且不再自动绑定。如果您出于某种原因需要字段选项,请参阅我们的 SQL Server 驱动程序,以获取有关如何创建它的示例。

  • metabase.driver.sql.query-processor/*table-alias* 现在未使用,并且不再自动绑定。请改用或覆盖 #19610 信息 中的 :metabase.query-processor.util.add-alias-info/source-table

  • metabase.driver.sql.query-processor/*source-query* 现在未使用,并且不再自动绑定。请改用 metabase.driver.sql.query-processor/*inner-query*,即使我们不在源查询内部,它也始终绑定。

  • metabase.driver.sql.query-processor/field->identifier 现在未使用。在任何情况下都不应再需要实现此方法。如果您需要在此处执行某些特殊操作,请覆盖 [<driver> :field]->honeysql 并操作 #19610 信息

  • metabase.driver.sql.query-processor/prefix-field-alias 不再使用。以前,它是为了让驱动程序有机会转义为连接字段自动生成的别名。这不再必要,因为 metabase.driver/escape-alias 会在自动生成的别名上调用。如果您需要执行某些特殊操作,请实现 metabase.driver/escape-alias
  • metabase.driver.sql-jdbc.sync.interface/syncable-schemas 已弃用,建议改用 metabase.driver.sql-jdbc.sync.interface/filtered-syncable-schemas(见上文)。syncable-schemas 的现有默认实现目前调用 filtered-syncable-schemas(使用 nil 过滤器,即过滤操作实际上是空操作),但它最终将被删除。

已删除的方法和变量

  • 在 0.39.0 版本中弃用的 metabase.mbql.schema/DatetimeFieldUnit 现在已删除。

旧版本

在 0.42.0 版本之前,此信息在我们的 Wiki 中跟踪。您可以在下表中找到 0.42.0 版本之前的版本更改

版本 Wiki 页面
0.41.0 更改
0.40.0 无更改。
0.39.0 无更改。
0.38.0 更改
0.37.0 更改
0.36.0 更改
0.35.0 更改

阅读其他 Metabase 版本的文档。