pgdog_plugin/lib.rs
1//! PgDog plugins library.
2//!
3//! Implements data types and methods plugins can use to interact with PgDog at runtime.
4//!
5//! # Getting started
6//!
7//! Create a Rust library package with Cargo:
8//!
9//! ```bash
10//! cargo init --lib my_plugin
11//! ```
12//!
13//! The plugin needs to be built as a C ABI-compatible shared library. Add the following to Cargo.toml in the new plugin directory:
14//!
15//! ```toml
16//! [lib]
17//! crate-type = ["rlib", "cdylib"]
18//! ```
19//!
20//! ## Dependencies
21//!
22//! PgDog is using [`pg_query`] to parse SQL. It produces an Abstract Syntax Tree (AST) which plugins can use to inspect queries
23//! and make statement routing decisions.
24//!
25//! The AST is computed by PgDog at runtime. It then passes it down to plugins, using a FFI interface. To make this safe, plugins must follow the
26//! following 2 requirements:
27//!
28//! 1. Plugins must be compiled with the **same version of the Rust compiler** as PgDog. This is automatically checked at runtime and plugins that don't do this are not loaded.
29//! 2. Plugins must use the **same version of [`pg_query`] crate** as PgDog. This is checked at runtime but requires a build-time script executed by the plugin.
30//!
31//! #### Configure dependencies
32//!
33//! Add the following to your plugin's `Cargo.toml`:
34//!
35//! ```toml
36//! [dependencies]
37//! pg_query = "6.1.0"
38//! pgdog-plugin = "0.1.2"
39//!
40//! [build-dependencies]
41//! pgdog-plugin-build = "0.1"
42//! ```
43//!
44//! #### Build script
45//!
46//! In the same directory as `Cargo.toml`, add the `build.rs` file and with the following code:
47//!
48//! ```ignore
49//! fn main() {
50//! pgdog_plugin_build::pg_query_version();
51//! }
52//! ```
53//!
54//!
55//! # Required methods
56//!
57//! All plugins need to implement a set of functions that PgDog calls at runtime to load the plugin. You can implement them automatically
58//! using a macro. Inside the plugin's `src/lib.rs` file, add the following code:
59//!
60//! ```
61//! // src/lib.rs
62//! use pgdog_plugin::macros;
63//!
64//! macros::plugin!();
65//! ```
66//!
67//! # Routing queries
68//!
69//! Plugins are most commonly used to route queries. To do this, they need to implement a function that reads
70//! the [`Context`] passed in by PgDog, and returns a [`Route`] that indicates which database the query should be sent to.
71//!
72//! ### Example
73//!
74//! ```
75//! use pgdog_plugin::{macros, Context, Route};
76//!
77//! #[macros::route]
78//! fn route(context: Context) -> Route {
79//! Route::default()
80//! }
81//! ```
82//!
83//! The [`macros::route`] macro wraps the function into a safe FFI interface which PgDog calls at runtime.
84//!
85//! ### Errors
86//!
87//! Plugin functions cannot return errors or panic. To handle errors, you can log them to `stderr` and return a default route,
88//! which PgDog will ignore. Plugins currently cannot be used to block queries.
89//!
90//! # Enabling plugins
91//!
92//! Plugins are shared libraries, loaded by PgDog at runtime using `dlopen(3)`. Make sure to place your plugin
93//! into one of the following locations:
94//!
95//! - PgDog's working directory (`$PWD`)
96//! - Any of the system default paths, e.g.: `/lib`, `/usr/lib`, `/lib64`, `/usr/lib64`, etc.
97//! - Path specified by the `LD_LIBRARY_PATH` (on Linux) or `DYLD_LIBRARY_PATH` (Mac OS).
98//!
99//! PgDog doesn't load plugins automatically. For each plugin you'd like to use, add it to `pgdog.toml`:
100//!
101//! ```toml
102//! [[plugins]]
103//! name = "my_plugin"
104//! ```
105//!
106//! Just like with compilers, omit the `lib` prefix and the platform-specific extension (e.g.: `.so` or `.dylib`).
107
108/// Bindgen-generated FFI bindings.
109#[allow(non_upper_case_globals)]
110#[allow(non_camel_case_types)]
111#[allow(non_snake_case)]
112pub mod bindings;
113
114pub mod ast;
115pub mod comp;
116pub mod context;
117pub mod plugin;
118pub mod string;
119
120pub use bindings::*;
121pub use context::*;
122pub use plugin::*;
123
124pub use libloading;
125
126pub use pgdog_macros as macros;