- 安装
- 文档
- 入门
- 连接
- 数据导入
- 客户端 API
- 概览
- ADBC
- C
- C++
- CLI
- Dart
- Go
- Java (JDBC)
- Julia
- Node.js (已弃用)
- Node.js (Neo)
- ODBC
- PHP
- Python
- R
- Rust
- Swift
- Wasm
- SQL
- 介绍
- 语句
- 概览
- ANALYZE
- ALTER TABLE
- ALTER VIEW
- ATTACH 和 DETACH
- CALL
- CHECKPOINT
- COMMENT ON
- COPY
- CREATE INDEX
- CREATE MACRO
- CREATE SCHEMA
- CREATE SECRET
- CREATE SEQUENCE
- CREATE TABLE
- CREATE VIEW
- CREATE TYPE
- DELETE
- DESCRIBE
- DROP
- EXPORT 和 IMPORT DATABASE
- INSERT
- LOAD / INSTALL
- PIVOT
- 性能分析
- SELECT
- SET / RESET
- SET VARIABLE
- SUMMARIZE
- 事务管理
- UNPIVOT
- UPDATE
- USE
- VACUUM
- 查询语法
- SELECT
- FROM 和 JOIN
- WHERE
- GROUP BY
- GROUPING SETS
- HAVING
- ORDER BY
- LIMIT 和 OFFSET
- SAMPLE
- 展开嵌套
- WITH
- WINDOW
- QUALIFY
- VALUES
- FILTER
- 集合操作
- 预处理语句
- 数据类型
- 表达式
- 函数
- 概览
- 聚合函数
- 数组函数
- 位字符串函数
- Blob 函数
- 日期格式化函数
- 日期函数
- 日期部分函数
- 枚举函数
- 间隔函数
- Lambda 函数
- 列表函数
- 映射函数
- 嵌套函数
- 数值函数
- 模式匹配
- 正则表达式
- 结构体函数
- 文本函数
- 时间函数
- 时间戳函数
- 带时区时间戳函数
- 联合函数
- 实用函数
- 窗口函数
- 约束
- 索引
- 元查询
- DuckDB 的 SQL 方言
- 示例
- 配置
- 扩展
- 核心扩展
- 概览
- 自动补全
- Avro
- AWS
- Azure
- Delta
- DuckLake
- 编码
- Excel
- 全文搜索
- httpfs (HTTP 和 S3)
- Iceberg
- ICU
- inet
- jemalloc
- MySQL
- PostgreSQL
- 空间
- SQLite
- TPC-DS
- TPC-H
- UI
- VSS
- 指南
- 概览
- 数据查看器
- 数据库集成
- 文件格式
- 概览
- CSV 导入
- CSV 导出
- 直接读取文件
- Excel 导入
- Excel 导出
- JSON 导入
- JSON 导出
- Parquet 导入
- Parquet 导出
- 查询 Parquet 文件
- 使用 file: 协议访问文件
- 网络和云存储
- 概览
- HTTP Parquet 导入
- S3 Parquet 导入
- S3 Parquet 导出
- S3 Iceberg 导入
- S3 Express One
- GCS 导入
- Cloudflare R2 导入
- 通过 HTTPS / S3 使用 DuckDB
- Fastly 对象存储导入
- 元查询
- ODBC
- 性能
- Python
- 安装
- 执行 SQL
- Jupyter Notebooks
- marimo Notebooks
- Pandas 上的 SQL
- 从 Pandas 导入
- 导出到 Pandas
- 从 Numpy 导入
- 导出到 Numpy
- Arrow 上的 SQL
- 从 Arrow 导入
- 导出到 Arrow
- Pandas 上的关系型 API
- 多个 Python 线程
- 与 Ibis 集成
- 与 Polars 集成
- 使用 fsspec 文件系统
- SQL 编辑器
- SQL 功能
- 代码片段
- 故障排除
- 术语表
- 离线浏览
- 操作手册
- 开发
- 内部结构
- 为什么选择 DuckDB
- 行为准则
- 发布日历
- 路线图
- 站点地图
- 在线演示
扩展版本控制
大多数软件都有某种版本号。版本号有几个重要目的:
- 将二进制文件与源代码的特定状态关联起来
- 允许确定预期的功能集
- 允许确定API的状态
- 允许高效处理错误报告(例如,错误
#1337
是在版本v3.4.5
中引入的) - 允许确定发布的先后顺序(例如,版本
v1.2.3
早于v1.2.4
) - 给出预期稳定性的指示(例如,
v0.0.1
可能不是很稳定,而v13.11.0
可能很稳定)
与DuckDB本身一样,DuckDB扩展也有自己的版本号。为确保这些版本号在各种扩展中具有一致的语义,DuckDB的核心扩展使用一套版本控制方案,规定了扩展应如何进行版本控制。核心扩展的版本控制方案由3个不同的稳定性级别组成:不稳定、预发布和稳定。让我们逐一介绍这3个级别并描述它们的格式。
不稳定扩展
不稳定扩展是指无法(或不愿)对其当前稳定性或其实现稳定的目标做出任何保证的扩展。不稳定扩展通过扩展的短 Git 哈希进行标记。
例如,在撰写本文时,vss
扩展的版本是一个不稳定扩展,版本号为690bfc5
。
对于版本号采用不稳定格式的扩展,应该期待什么?
- 通过在扩展仓库中查找哈希值,可以找到扩展源代码的状态
- 功能可能在每次发布时更改或完全移除
- 此扩展的API可能在每次发布时更改
- 此扩展可能不遵循结构化的发布周期,新的(破坏性)版本可随时发布
预发布扩展
预发布扩展是不稳定扩展的下一步。它们使用SemVer格式的版本进行标记,更具体地说,是v0.y.z
格式的版本。在语义化版本控制中,以v0
开头的版本具有特殊含义:它们表明常规版本(>v1.0.0
)的更严格语义尚不适用。这基本上意味着一个扩展正在努力成为一个稳定扩展,但尚未完全达到。
例如,在撰写本文时,delta
扩展的版本是一个预发布扩展,版本号为v0.1.0
。
对于版本号采用预发布格式的扩展,应该期待什么?
- 该扩展是根据对应标签的源代码编译的。
- 语义化版本控制语义适用。有关详细信息,请参阅语义化版本控制规范。
- 该扩展遵循发布周期,新功能在每夜构建中测试,然后才分组发布并推送到
core
仓库。 - 应提供描述每次发布新增内容的发布说明,以便于理解不同版本之间的差异。
稳定扩展
稳定扩展是扩展稳定性的最后一步。这通过使用格式为vx.y.z
(其中x>0
)的稳定 SemVer 来表示。
例如,在撰写本文时,parquet
扩展的版本是一个稳定扩展,版本号为v1.0.0
。
对于版本号采用稳定格式的扩展,应该期待什么?本质上与预发布扩展相同,但现在适用更严格的 SemVer 语义:扩展的API现在应该稳定,并且只有在主版本号提升时才会以不向后兼容的方式更改。有关详细信息,请参阅 SemVer 规范。
预发布和稳定核心扩展的发布周期
通常,扩展的发布周期取决于其稳定性级别。不稳定扩展通常与DuckDB的发布周期同步,但也可能在DuckDB发布之间悄悄更新。预发布和稳定扩展遵循其自己的发布周期。这些周期可能与DuckDB发布重合,也可能不重合。要了解特定扩展的发布周期,请查阅相应扩展的文档或GitHub页面。通常,预发布和稳定扩展会将其发布记录为GitHub发布,您可以在delta
扩展中看到一个示例。
最后,还有一个小例外:所有in-tree(内置)扩展都只遵循DuckDB的发布周期。
每夜构建
与DuckDB本身一样,DuckDB的核心扩展也提供每夜或开发构建版本,可用于在正式发布前试用新功能。当您的工作流程依赖于某个新功能,或需要确认您的技术栈与即将发布的版本兼容时,这会很有用。
由于目前DuckDB扩展的二进制文件与单个DuckDB版本紧密绑定,因此扩展的每夜构建略显复杂。由于这种紧密连接,存在组合爆炸的潜在风险。因此,并非所有每夜扩展构建和每夜DuckDB构建的组合都可用。
一般来说,使用每夜构建有两种方式:使用每夜DuckDB构建和使用稳定DuckDB构建。让我们来看看两者之间的区别。
从稳定版 DuckDB 开始
在大多数情况下,用户会对特定扩展的每夜构建感兴趣,但不一定希望切换到使用DuckDB本身的每夜构建。这允许使用某个前沿功能,同时限制接触不稳定代码的风险。
为了实现这一点,核心扩展倾向于定期将构建版本推送到core_nightly
仓库。我们来看一个例子。
首先,我们安装一个稳定版 DuckDB 构建。
然后我们可以像这样安装和加载一个每夜扩展:
INSTALL aws FROM core_nightly;
LOAD aws;
在这个例子中,我们正在使用最新每夜构建的 aws 扩展,配合最新稳定版本的 DuckDB。
从每夜版 DuckDB 开始
当DuckDB CI生成DuckDB本身的每夜二进制文件时,这些二进制文件会附带一组固定版本的扩展。此扩展版本将针对该特定DuckDB构建进行测试,但可能不是最新的开发构建。我们来看一个例子。
首先,我们安装一个每夜版 DuckDB 构建。然后,我们可以按预期安装和加载aws
扩展。
INSTALL aws;
LOAD aws;
更新扩展
DuckDB有一个专用语句,可以自动将所有扩展更新到最新版本。输出将向用户提供哪些扩展从哪个版本更新到哪个版本的信息。例如:
UPDATE EXTENSIONS;
扩展名称 | 仓库 | 更新结果 | 之前版本 | 当前版本 |
---|---|---|---|---|
httpfs | core | 无可用更新 | 70fd6a8a24 | 70fd6a8a24 |
delta | core | 已更新 | d9e5cc1 | 04c61e4 |
azure | core_nightly | 无可用更新 | 49b63dc | 49b63dc |
aws | core | 无可用更新 | 42c78d3 | 42c78d3 |
请注意,DuckDB 将在每个扩展的源仓库中查找更新。因此,如果一个扩展是从core_nightly
安装的,它将使用最新的每夜构建进行更新。
更新语句也可以提供一个要更新的特定扩展列表:
UPDATE EXTENSIONS (httpfs, aws);
扩展名称 | 仓库 | 更新结果 | 之前版本 | 当前版本 |
---|---|---|---|---|
httpfs | core | 无可用更新 | 7ce5308 | 7ce5308 |
aws | core | 无可用更新 | 4f318eb | 4f318eb |
目标 DuckDB 版本
目前,扩展在编译时会与特定版本的 DuckDB 绑定。这意味着,例如,为 0.10.3 版本编译的扩展二进制文件不适用于 1.0.0 版本。在大多数情况下,这不会引起任何问题,并且是完全透明的;DuckDB 将自动确保为其版本安装正确的二进制文件。对于扩展开发者而言,这意味着每当发布新版本的 DuckDB 时,他们必须确保创建新的二进制文件。但是,请注意,DuckDB 提供了一个扩展模板,这使得操作相当简单。
内置(In-Tree)与外置(Out-of-Tree)
最初,DuckDB 扩展仅存在于 DuckDB 主仓库 github.com/duckdb/duckdb
中。这些扩展被称为内置(in-tree)扩展。后来,增加了外置(out-of-tree)扩展的概念,即扩展被分离到它们自己的仓库中,我们称之为外置扩展。
虽然从用户的角度来看,通常没有明显差异,但仍有一些与版本控制相关的细微差异:
- 内置扩展使用 DuckDB 的版本,而不是拥有自己的版本
- 内置扩展没有专门的发布说明,它们的更改反映在常规的DuckDB 发布说明中
- 核心外置扩展通常位于名为
github.com/duckdb/duckdb-extension_name
的仓库中,但名称可能有所不同。有关详细信息,请参阅核心扩展的完整列表。