Rust PostgreSQL扩展开发库pgrx-pg-config的使用:简化PostgreSQL插件配置与构建流程
Rust PostgreSQL扩展开发库pgrx-pg-config的使用:简化PostgreSQL插件配置与构建流程
概述
pgrx-pg-config是一个包含PostgreSQL pg_config
抽象/包装的crate,用于与pgrx
一起使用。
安装
在项目目录中运行以下Cargo命令:
cargo add pgrx-pg-config
或者在Cargo.toml中添加以下行:
pgrx-pg-config = "0.16.0"
完整示例代码
以下是一个使用pgrx-pg-config开发PostgreSQL扩展的完整示例:
// 引入必要的依赖
use pgrx_pg_config::{PgConfig, PgConfigSelector};
fn main() {
// 获取默认的PostgreSQL配置
let pg_config = PgConfig::default();
// 或者使用特定版本的PostgreSQL配置
let selector = PgConfigSelector::new()
.with_version("15"); // 指定PostgreSQL版本
let pg_config = PgConfig::from(selector).expect("Failed to find PostgreSQL installation");
// 打印PostgreSQL安装信息
println!("PostgreSQL version: {}", pg_config.version());
println!("Installation directory: {}", pg_config.prefix().display());
println!("Include directory: {}", pg_config.include_dir().display());
println!("Library directory: {}", pg_config.lib_dir().display());
println!("Shared library extension: {}", pg_config.shared_library_extension());
// 在构建PostgreSQL扩展时使用这些路径
// 这通常在build.rs文件中完成
}
构建脚本示例
在项目的build.rs文件中,你可以这样使用pgrx-pg-config:
// build.rs
use pgrx_pg_config::PgConfig;
fn main() {
// 获取PostgreSQL配置
let pg_config = PgConfig::default();
// 设置必要的构建环境变量
println!("cargo:rustc-env=PG_INCLUDE_DIR={}", pg_config.include_dir().display());
println!("cargo:rustc-env=PG_LIB_DIR={}", pg_config.lib_dir().display());
println!("cargo:rustc-env=PG_VERSION={}", pg_config.version());
// 其他构建配置...
}
功能说明
pgrx-pg-config提供了以下主要功能:
- 自动发现系统上安装的PostgreSQL版本
- 获取PostgreSQL安装路径、包含目录和库目录
- 支持多个PostgreSQL版本共存时的选择
- 简化PostgreSQL扩展的构建过程
完整示例demo
以下是一个更完整的PostgreSQL扩展开发示例,结合了pgrx-pg-config的使用:
// src/lib.rs
use pgrx::prelude::*;
// 定义一个PostgreSQL函数
#[pg_extern]
fn hello_pgrx() -> &'static str {
"Hello, pgrx!"
}
// 定义扩展的入口点
#[cfg(any(test, feature = "pg_test"))]
mod tests {
use pgrx::prelude::*;
#[pg_test]
fn test_hello_pgrx() {
assert_eq!("Hello, pgrx!", crate::hello_pgrx());
}
}
// build.rs
use pgrx_pg_config::PgConfig;
fn main() {
// 获取PostgreSQL配置
let pg_config = PgConfig::default();
// 设置构建环境变量
println!("cargo:rustc-env=PG_INCLUDE_DIR={}", pg_config.include_dir().display());
println!("cargo:rustc-env=PG_LIB_DIR={}", pg_config.lib_dir().display());
println!("cargo:rustc-env=PG_VERSION={}", pg_config.version());
// 告诉Cargo如果PostgreSQL配置变化需要重新构建
println!("cargo:rerun-if-changed=build.rs");
}
# Cargo.toml
[package]
name = "my_pgrx_extension"
version = "0.1.0"
edition = "2021"
[lib]
name = "my_pgrx_extension"
crate-type = ["cdylib"]
[dependencies]
pgrx = { version = "0.9", features = ["pg15"] }
pgrx-pg-config = "0.16.0"
[features]
pg_test = []
维护者
- Eric Ridge
- Jubilee
- PgCentral Foundation, Inc.
1 回复
pgrx-pg-config: 简化PostgreSQL扩展开发的Rust库
pgrx-pg-config
是pgrx
工具链的一部分,专门用于简化Rust开发PostgreSQL扩展时的配置和构建流程。
主要功能
- 自动检测PostgreSQL安装路径
- 提供正确的编译标志和链接选项
- 简化跨平台构建过程
- 支持多个PostgreSQL版本
安装方法
在Cargo.toml中添加依赖:
[dependencies]
pgrx-pg-config = "0.11"
基本使用方法
1. 获取PostgreSQL配置
use pgrx_pg_config::PgConfig;
fn main() {
// 获取默认的PostgreSQL配置
let pg_config = PgConfig::default();
println!("PostgreSQL版本: {}", pg_config.version()?);
println!("包含目录: {}", pg_config.include_dir()?.display());
println!("库目录: {}", pg_config.lib_dir()?.display());
}
2. 多版本支持
use pgrx_pg_config::{PgConfig, PgVersion};
// 获取特定版本的PostgreSQL配置
let pg12_config = PgConfig::new(PgVersion::new(12, Some(3)));
3. 在构建脚本中使用
在build.rs中:
fn main() {
// 告诉cargo如果PostgreSQL配置变化需要重新构建
println!("cargo:rerun-if-changed=build.rs");
let pg_config = pgrx_pg_config::PgConfig::default();
// 设置包含路径
println!("cargo:rustc-env=PG_INCLUDE_DIR={}",
pg_config.include_dir().unwrap().display());
}
高级配置
自定义PostgreSQL路径
use pgrx_pg_config::{PgConfig, PgVersion};
let custom_config = PgConfig::with_path(
PgVersion::new(14, None),
"/path/to/postgresql/bin/pg_config"
).unwrap();
检查扩展支持
if pg_config.has_extension("plpgsql") {
println!("PL/pgSQL支持已启用");
}
与pgrx配合使用
当使用pgrx框架开发PostgreSQL扩展时,pgrx-pg-config会自动处理大部分配置:
[dependencies]
pgrx = { version = "0.11", features = ["pg14"] }
然后在扩展代码中:
use pgrx::prelude::*;
pg_module_magic!();
#[pg_extern]
fn hello_pgrx() -> &'static str {
"Hello, pgrx!"
}
环境变量覆盖
可以通过环境变量覆盖默认配置:
export PGRX_PG_CONFIG_OVERRIDE=/path/to/pg_config
cargo build
注意事项
- 确保系统上安装了对应版本的PostgreSQL开发包
- 跨版本编译时需要指定正确的feature flag
- 在非标准位置安装PostgreSQL时需要手动配置路径
pgrx-pg-config大大简化了Rust开发PostgreSQL扩展的配置过程,让开发者可以更专注于业务逻辑的实现。
完整示例Demo
下面是一个完整的PostgreSQL扩展开发示例,展示如何使用pgrx-pg-config和pgrx:
- 首先创建项目并添加依赖:
# Cargo.toml
[package]
name = "my_pg_extension"
version = "0.1.0"
edition = "2021"
[lib]
name = "my_pg_extension"
crate-type = ["cdylib"]
[dependencies]
pgrx = { version = "0.11", features = ["pg14"] }
pgrx-pg-config = "0.11"
- 创建build.rs构建脚本:
// build.rs
fn main() {
println!("cargo:rerun-if-changed=build.rs");
let pg_config = pgrx_pg_config::PgConfig::default();
// 设置PostgreSQL包含目录
println!("cargo:rustc-env=PG_INCLUDE_DIR={}",
pg_config.include_dir().unwrap().display());
// 检查是否支持plpgsql扩展
if pg_config.has_extension("plpgsql") {
println!("cargo:rustc-cfg=feature=\"plpgsql\"");
}
}
- 主扩展代码:
// src/lib.rs
use pgrx::prelude::*;
// 必须的宏,用于初始化扩展
pg_module_magic!();
// 定义一个简单的PostgreSQL函数
#[pg_extern]
fn add_numbers(a: i32, b: i32) -> i32 {
a + b
}
// 定义一个返回表的函数
#[pg_extern]
fn generate_series(start: i32, end: i32, step: i32) ->
TableIterator<'static, (name!(value, i32))> {
TableIterator::new((start..=end).step_by(step as usize).map(|i| (i,)))
}
// 扩展初始化时的回调
#[pg_guard]
pub extern "C" fn _PG_init() {
// 可以在这里执行初始化逻辑
println!("My PostgreSQL扩展已加载");
}
// 测试模块
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add_numbers() {
assert_eq!(add_numbers(2, 3), 5);
}
}
- 使用扩展:
-- 在PostgreSQL中加载扩展
CREATE EXTENSION my_pg_extension;
-- 使用扩展中的函数
SELECT add_numbers(5, 7); -- 返回12
SELECT * FROM generate_series(1, 10, 2); -- 返回1,3,5,7,9
这个完整示例展示了如何:
- 配置Cargo.toml依赖
- 使用pgrx-pg-config在构建脚本中设置路径
- 定义简单的PostgreSQL函数
- 定义返回表的函数
- 处理扩展初始化和测试
通过这个模板,你可以快速开始开发自己的PostgreSQL扩展。