ADBC 驱动程序管理器与连接配置¶
注意
本文档介绍了如何使用 驱动程序管理器 来加载驱动程序。通常情况下,使用 ADBC 并不强制要求使用驱动程序管理器,但它允许加载与应用程序语言不同的驱动程序,并在单个应用程序中使用多个驱动程序时改善体验。有关驱动程序管理器工作原理的更多信息,请参阅 驱动程序与驱动程序管理器如何协同工作。
有两种方法可以通过驱动程序管理器传递数据库选项:
在应用程序代码中将所有选项直接指定为驱动程序管理器的参数(有关详细信息,请参阅 ADBC API 标准 中的 SetOption 系列函数)。
引用包含选项的 连接配置,并可选择通过上述方法设置某些选项来覆盖部分默认配置。
连接配置将驱动程序和数据库选项组合在可重用的配置中。这允许用户:
在文件或环境变量中定义连接信息
在多个应用程序间共享连接配置
分发标准化的连接设置
避免在应用程序代码中硬编码驱动程序名称和凭据
配置会在 AdbcDatabaseInit() 期间、驱动程序初始化之前被加载。来自配置文件的选项会自动应用,但不会覆盖已通过 AdbcDatabaseSetOption() 设置的选项。
快速入门¶
通过 URI 使用配置¶
使用配置最简单的方法是通过 URI
AdbcDatabase database;
AdbcDatabaseNew(&database, &error);
AdbcDatabaseSetOption(&database, "uri", "profile://my_snowflake_prod", &error);
AdbcDatabaseInit(&database, &error);
通过选项使用配置¶
或者,直接指定配置名称
AdbcDatabase database;
AdbcDatabaseNew(&database, &error);
AdbcDatabaseSetOption(&database, "profile", "my_snowflake_prod", &error);
AdbcDatabaseInit(&database, &error);
配置文件格式¶
基于文件系统的配置使用 TOML 格式,结构如下:
# The version is required.
profile_version = 1
# The driver is optional, but if not provided it must be set by the application.
driver = "snowflake"
# The Options table is required, even if empty
[Options]
# String options
adbc.snowflake.sql.account = "mycompany"
adbc.snowflake.sql.warehouse = "COMPUTE_WH"
adbc.snowflake.sql.database = "PRODUCTION"
adbc.snowflake.sql.schema = "PUBLIC"
# Integer options
adbc.snowflake.sql.client_session_keep_alive_heartbeat_frequency = 3600
# Double options
adbc.snowflake.sql.client_timeout = 30.5
# Boolean options (converted to "true" or "false" strings)
adbc.snowflake.sql.client_session_keep_alive = true
profile_version¶
必需:是
类型:整数
支持的值:
1
profile_version 字段指定配置文件格式的版本。目前仅支持版本 1。这将在保持向后兼容性的同时支持未来的更改。
driver¶
必需:否
类型:字符串
driver 字段指定要加载的 ADBC 驱动程序。这可以是:
驱动程序或驱动程序清单名称(例如
"snowflake")共享库的路径(例如
"/usr/local/lib/libadbc_driver_snowflake.so")驱动程序清单的路径(例如
"/etc/adbc/drivers/snowflake.toml")
如果省略,则必须通过其他方式(例如 driver 选项或 uri 参数)指定驱动程序。如果应用程序指定了驱动程序,并且所指定的配置本身也引用了一个驱动程序,则两者必须完全匹配,否则会报错。驱动程序的加载方式与通过 AdbcDatabaseSetOption("driver", "<driver>") 指定时相同。有关详细信息,请参阅 ADBC 驱动程序管理器与清单。
选项部分¶
[Options] 部分包含在创建 AdbcDatabase 时要应用的驱动程序特定配置选项。即使为空,也必须包含此部分。选项可以是以下类型:
- 字符串值
使用
AdbcDatabaseSetOption()应用adbc.snowflake.sql.account = "mycompany" adbc.snowflake.sql.warehouse = "COMPUTE_WH"
- 整数值
使用
AdbcDatabaseSetOptionInt()应用adbc.snowflake.sql.client_session_keep_alive_heartbeat_frequency = 3600
- 双精度浮点值
使用
AdbcDatabaseSetOptionDouble()应用adbc.snowflake.sql.client_timeout = 30.5
- 布尔值
转换为字符串
"true"或"false"并使用AdbcDatabaseSetOption()应用adbc.snowflake.sql.client_session_keep_alive = true
警告
如果应用程序覆盖了选项值,但所使用的类型与配置文件中的类型不同,则结果将是未定义的。
值替换¶
配置文件值支持环境变量和其他动态内容的替换。这允许配置文件引用敏感信息(如密码或令牌),而无需在配置文件中硬编码。可以使用 {{ }} 语法注入动态值,类似于许多模板引擎。在双花括号内,驱动程序管理器可以识别某些函数来执行替换。
目前唯一可识别的函数是用于环境变量替换的 env_var(),但未来可能会扩展以支持其他类型的动态内容。
重要提示
动态内容替换仅适用于选项值,而不适用于键。
环境变量替换¶
配置文件值可以使用 {{ env_var() }} 语法引用环境变量
profile_version = 1
driver = "adbc_driver_snowflake"
[Options]
adbc.snowflake.sql.account = "{{ env_var(SNOWFLAKE_ACCOUNT) }}"
adbc.snowflake.sql.auth_token = "{{ env_var(SNOWFLAKE_TOKEN) }}"
adbc.snowflake.sql.warehouse = "COMPUTE_WH"
当驱动程序管理器遇到 {{ env_var(VAR_NAME) }} 时,它会将占位符替换为环境变量 VAR_NAME 的内容。如果未设置该环境变量,则占位符被替换为空字符串,并继续处理值的其余部分(例如 "foo{{ env_var(MISSING) }}bar" 将变为 "foobar")。
配置搜索路径¶
当使用配置名称(而非绝对路径)时,驱动程序管理器会在以下位置搜索 <profile_name>.toml:
附加搜索路径(如果已通过
additional_profile_search_path_list选项配置)ADBC_PROFILE_PATH 环境变量(Unix 上使用冒号分隔,Windows 上使用分号分隔)
Conda 环境(如果构建时启用了 Conda 支持且设置了
CONDA_PREFIX)$CONDA_PREFIX/etc/adbc/profiles/
用户配置目录:
Linux:若已设置
$XDG_CONFIG_HOME/adbc/profiles,否则为~/.config/adbc/profiles/macOS:
~/Library/Application Support/ADBC/Profiles/Windows:
%LOCALAPPDATA%\ADBC\Profiles\
驱动程序管理器按顺序搜索这些位置,并使用找到的第一个匹配配置文件。
使用绝对路径¶
若要指定配置文件的绝对路径:
// Via profile option
AdbcDatabaseSetOption(&database, "profile", "/etc/adbc/profiles/production.toml", &error);
// Via URI (must have .toml extension)
AdbcDatabaseSetOption(&database, "uri", "profile:///etc/adbc/profiles/production.toml", &error);
示例¶
示例 1:Snowflake 生产环境配置¶
文件:~/.config/adbc/profiles/snowflake_prod.toml
profile_version = 1
driver = "snowflake"
[Options]
adbc.snowflake.sql.account = "{{ env_var(SNOWFLAKE_ACCOUNT) }}"
adbc.snowflake.sql.auth_token = "{{ env_var(SNOWFLAKE_TOKEN) }}"
adbc.snowflake.sql.warehouse = "PRODUCTION_WH"
adbc.snowflake.sql.database = "PROD_DB"
adbc.snowflake.sql.schema = "PUBLIC"
adbc.snowflake.sql.client_session_keep_alive = true
adbc.snowflake.sql.client_session_keep_alive_heartbeat_frequency = 3600
用法
// Set environment variables
setenv("SNOWFLAKE_ACCOUNT", "mycompany", 1);
setenv("SNOWFLAKE_TOKEN", "secret_token", 1);
// Use profile
AdbcDatabase database;
AdbcDatabaseNew(&database, &error);
AdbcDatabaseSetOption(&database, "uri", "profile://snowflake_prod", &error);
AdbcDatabaseInit(&database, &error);
示例 2:PostgreSQL 开发环境配置¶
文件:~/.config/adbc/profiles/postgres_dev.toml
profile_version = 1
driver = "postgresql"
[Options]
uri = "postgresql://:5432/dev_db?sslmode=disable"
username = "dev_user"
password = "{{ env_var(POSTGRES_DEV_PASSWORD) }}"
示例 3:驱动程序无关的通用配置¶
配置文件可以省略驱动程序字段,以实现可重用的配置
文件:~/.config/adbc/profiles/default_timeouts.toml
profile_version = 1
# No driver specified - can be used with any driver
[Options]
adbc.connection.timeout = 30.0
adbc.statement.timeout = 60.0
用法(单独指定驱动程序)
AdbcDatabase database;
AdbcDatabaseNew(&database, &error);
AdbcDatabaseSetOption(&database, "driver", "adbc_driver_snowflake", &error);
AdbcDatabaseSetOption(&database, "profile", "default_timeouts", &error);
AdbcDatabaseInit(&database, &error);
高级用法¶
选项优先级¶
选项按以下顺序应用(后面的覆盖前面的):
驱动程序默认值
配置文件选项(来自
[Options]部分)在
AdbcDatabaseInit()之前通过AdbcDatabaseSetOption()设置的选项
示例
AdbcDatabase database;
AdbcDatabaseNew(&database, &error);
// Profile sets warehouse = "COMPUTE_WH"
AdbcDatabaseSetOption(&database, "profile", "snowflake_prod", &error);
// This overrides the profile setting
AdbcDatabaseSetOption(&database, "adbc.snowflake.sql.warehouse", "ANALYTICS_WH", &error);
AdbcDatabaseInit(&database, &error);
// Result: warehouse = "ANALYTICS_WH"
注意
不同类型的选项是单独设置的。例如,如果配置文件定义了一个整数值的选项,而应用程序设置了相同的选项但使用的是字符串值,则哪个值生效取决于实现定义。如果应用程序改用整数值,则应用程序的值会按预期生效。
自定义配置提供程序¶
应用程序可以实现自定义配置提供程序,以从替代来源(数据库、密钥保管库、配置服务等)加载配置。
接口定义¶
配置提供程序必须实现 AdbcConnectionProfile 接口
struct AdbcConnectionProfile {
void* private_data;
// this will be called by the driver manager after retrieving the necessary information from the profile.
void (*release)(struct AdbcConnectionProfile* profile);
AdbcStatusCode (*GetDriverName)(struct AdbcConnectionProfile* profile,
const char** driver_name,
AdbcDriverInit* init_func,
struct AdbcError* error);
AdbcStatusCode (*GetOptions)(struct AdbcConnectionProfile* profile,
const char*** keys, const char*** values,
size_t* num_options, struct AdbcError* error);
AdbcStatusCode (*GetIntOptions)(struct AdbcConnectionProfile* profile,
const char*** keys, const int64_t** values,
size_t* num_options, struct AdbcError* error);
AdbcStatusCode (*GetDoubleOptions)(struct AdbcConnectionProfile* profile,
const char*** keys, const double** values,
size_t* num_options, struct AdbcError* error);
};
提供程序函数¶
提供程序函数签名
typedef AdbcStatusCode (*AdbcConnectionProfileProvider)(
const char* profile_name,
const char* additional_search_path_list,
struct AdbcConnectionProfile* out,
struct AdbcError* error);
实现示例¶
// Example: Load profiles from a key-value store
AdbcStatusCode MyCustomProfileProvider(const char* profile_name,
const char* additional_search_path_list,
struct AdbcConnectionProfile* out,
struct AdbcError* error) {
// Fetch profile from custom source
MyProfileData* data = LoadProfileFromKeyVault(profile_name);
if (!data) {
SetError(error, "Profile not found in key vault");
return ADBC_STATUS_NOT_FOUND;
}
std::memset(out, 0, sizeof(struct AdbcConnectionProfile));
// Populate profile structure
out->private_data = data;
out->release = MyProfileRelease;
out->GetDriverName = MyGetDriverName;
out->GetOptions = MyGetOptions;
out->GetIntOptions = MyGetIntOptions;
out->GetDoubleOptions = MyGetDoubleOptions;
return ADBC_STATUS_OK;
}
// Register custom provider
AdbcDatabase database;
AdbcDatabaseNew(&database, &error);
AdbcDriverManagerDatabaseSetProfileProvider(&database, MyCustomProfileProvider, &error);
AdbcDatabaseSetOption(&database, "profile", "prod_config", &error);
AdbcDatabaseInit(&database, &error);
使用场景¶
开发与生产环境区分¶
为不同环境维护单独的配置文件
# Development
export ADBC_PROFILE=snowflake_dev
# Production
export ADBC_PROFILE=snowflake_prod
应用程序代码
const char* profile = getenv("ADBC_PROFILE");
if (!profile) profile = "default";
AdbcDatabaseSetOption(&database, "profile", profile, &error);
凭据管理¶
将凭据与代码分开存储
[Options]
adbc.snowflake.sql.account = "mycompany"
adbc.snowflake.sql.auth_token = "{{ env_var(SNOWFLAKE_TOKEN) }}"
然后通过环境变量、密钥管理器或配置服务设置 SNOWFLAKE_TOKEN。
多租户应用程序¶
使用配置文件来支持不同的客户配置
char profile_name[256];
snprintf(profile_name, sizeof(profile_name), "customer_%s", customer_id);
AdbcDatabaseSetOption(&database, "profile", profile_name, &error);
测试¶
使用配置文件在模拟数据库和真实数据库之间切换
#ifdef TESTING
const char* profile = "mock_database";
#else
const char* profile = "production";
#endif
AdbcDatabaseSetOption(&database, "profile", profile, &error);
错误处理¶
找不到配置文件¶
如果找不到配置文件,AdbcDatabaseInit() 会返回 ADBC_STATUS_NOT_FOUND,并附带详细的错误消息,列出所有已搜索的位置
[Driver Manager] Profile not found: my_profile
Also searched these paths for profiles:
ADBC_PROFILE_PATH: /custom/path
user config dir: /home/user/.config/adbc/profiles
system config dir: /etc/adbc/profiles
配置文件格式无效¶
如果配置文件存在但格式错误,AdbcDatabaseInit() 会返回 ADBC_STATUS_INVALID_ARGUMENT
[Driver Manager] Could not open profile. Error at line 5: expected '=' after key.
Profile: /home/user/.config/adbc/profiles/my_profile.toml
缺少驱动程序¶
如果配置文件未指定驱动程序,且未通过其他方式提供
[Driver Manager] Must provide 'driver' parameter
(or encode driver in 'uri' parameter)
最佳实践¶
使用环境变量存储密钥:切勿直接将凭据存储在配置文件中。
# Good password = "{{ env_var(DB_PASSWORD) }}" # Bad password = "my_secret_password"
分层组织配置文件:使用附加搜索路径将相关配置文件分组到子目录中。
记录配置模式:维护每个配置文件所需环境变量的文档。
版本控制不含密钥:当使用
{{ env_var(VAR_NAME) }}处理敏感值时,配置文件可以进行版本控制。测试配置加载:在 CI/CD 流水线中验证配置文件是否正确加载。
使用有意义的名称:以描述性方式命名配置文件(例如
snowflake_prod_analytics而非profile1)。验证环境变量:在调用
AdbcDatabaseInit()之前,检查所需的环境变量是否已设置。
API 参考¶
设置配置提供程序¶
AdbcStatusCode AdbcDriverManagerDatabaseSetProfileProvider(
struct AdbcDatabase* database,
AdbcConnectionProfileProvider provider,
struct AdbcError* error);
设置自定义连接配置提供程序。必须在 AdbcDatabaseInit() 之前调用。
参数
database:要配置的数据库对象provider:配置提供程序函数,或NULL(使用默认文件系统提供程序)error:可选的错误输出
返回值: 成功时返回 ADBC_STATUS_OK,否则返回错误代码。
设置附加搜索路径¶
可以通过 additional_profile_search_path_list 选项完成。它必须在 AdbcDatabaseInit() 之前设置。此选项的值是一个操作系统特定的分隔列表(Unix 上为 :,Windows 上为 ;),或设为 NULL 以清除。
示例
// Unix/Linux/macOS
AdbcDatabaseSetOption(
&database,
"additional_profile_search_path_list",
"/opt/app/profiles:/etc/app/profiles",
&error);
// Windows
AdbcDatabaseSetOption(
&database,
"additional_profile_search_path_list",
"C:\\App\\Profiles;C:\\ProgramData\\App\\Profiles",
&error);
另请参阅¶
驱动程序与驱动程序管理器如何协同工作 - 驱动程序管理器概述
ADBC API 标准 - 驱动程序规范和选项
驱动程序管理器 - C++ 驱动程序管理器参考