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提供了以下主要功能:

  1. 自动发现系统上安装的PostgreSQL版本
  2. 获取PostgreSQL安装路径、包含目录和库目录
  3. 支持多个PostgreSQL版本共存时的选择
  4. 简化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-configpgrx工具链的一部分,专门用于简化Rust开发PostgreSQL扩展时的配置和构建流程。

主要功能

  1. 自动检测PostgreSQL安装路径
  2. 提供正确的编译标志和链接选项
  3. 简化跨平台构建过程
  4. 支持多个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

注意事项

  1. 确保系统上安装了对应版本的PostgreSQL开发包
  2. 跨版本编译时需要指定正确的feature flag
  3. 在非标准位置安装PostgreSQL时需要手动配置路径

pgrx-pg-config大大简化了Rust开发PostgreSQL扩展的配置过程,让开发者可以更专注于业务逻辑的实现。

完整示例Demo

下面是一个完整的PostgreSQL扩展开发示例,展示如何使用pgrx-pg-config和pgrx:

  1. 首先创建项目并添加依赖:
# 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"
  1. 创建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\"");
    }
}
  1. 主扩展代码:
// 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);
    }
}
  1. 使用扩展:
-- 在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扩展。

回到顶部