All Projects → zombodb → Pgx

zombodb / Pgx

Licence: mit
Build Postgres Extensions with Rust!

Programming Languages

rust
11053 projects

Projects that are alternatives of or similar to Pgx

Pg hashids
Short unique id generator for PostgreSQL, using hashids
Stars: ✭ 164 (-81.84%)
Mutual labels:  postgresql, postgres, postgresql-extension
Plv8
V8 Engine Javascript Procedural Language add-on for PostgreSQL
Stars: ✭ 1,195 (+32.34%)
Mutual labels:  postgresql, postgres, postgresql-extension
Wasmer Postgres
💽🕸 Postgres library to run WebAssembly binaries.
Stars: ✭ 245 (-72.87%)
Mutual labels:  postgresql, postgres, postgresql-extension
Bgworker
Background Worker Processes for PostgreSQL written in Go
Stars: ✭ 77 (-91.47%)
Mutual labels:  postgresql, postgres, postgresql-extension
Pg auto failover
Postgres extension and service for automated failover and high-availability
Stars: ✭ 564 (-37.54%)
Mutual labels:  postgresql, postgres, postgresql-extension
Citus
Distributed PostgreSQL as an extension
Stars: ✭ 5,580 (+517.94%)
Mutual labels:  postgresql, postgres
Labnotebook
LabNotebook is a tool that allows you to flexibly monitor, record, save, and query all your machine learning experiments.
Stars: ✭ 526 (-41.75%)
Mutual labels:  postgresql, postgres
Schemats
Generate typescript interface definitions from SQL database schema
Stars: ✭ 799 (-11.52%)
Mutual labels:  postgresql, postgres
Pgaudit
PostgreSQL Audit Extension
Stars: ✭ 532 (-41.09%)
Mutual labels:  postgresql, postgresql-extension
Zapatos
Zero-abstraction Postgres for TypeScript: a non-ORM database library
Stars: ✭ 448 (-50.39%)
Mutual labels:  postgresql, postgres
Pg Boss
Queueing jobs in Node.js using PostgreSQL like a boss
Stars: ✭ 525 (-41.86%)
Mutual labels:  postgresql, postgres
Pg acoustid
PostgreSQL extension for working with AcoustID fingerprints
Stars: ✭ 6 (-99.34%)
Mutual labels:  postgresql, postgresql-extension
Libpqxx
The official C++ client API for PostgreSQL.
Stars: ✭ 492 (-45.51%)
Mutual labels:  postgresql, postgres
Compose Postgres
Postgresql & pgadmin4 powered by compose
Stars: ✭ 477 (-47.18%)
Mutual labels:  postgresql, postgres
Efcore.pg
Entity Framework Core provider for PostgreSQL
Stars: ✭ 838 (-7.2%)
Mutual labels:  postgresql, postgres
Beam
A type-safe, non-TH Haskell SQL library and ORM
Stars: ✭ 454 (-49.72%)
Mutual labels:  postgresql, postgres
Postgres dba
The missing set of useful tools for Postgres DBAs and all engineers
Stars: ✭ 532 (-41.09%)
Mutual labels:  postgresql, postgres
Supabase
The open source Firebase alternative. Follow to stay updated about our public Beta.
Stars: ✭ 25,142 (+2684.27%)
Mutual labels:  postgresql, postgres
Pgmetrics
Collect and display information and stats from a running PostgreSQL server
Stars: ✭ 612 (-32.23%)
Mutual labels:  postgresql, postgres
Blog
Everything about database,business.(Most for PostgreSQL).
Stars: ✭ 6,330 (+601%)
Mutual labels:  postgresql, postgres

cargo test --all crates.io badge docs.rs badge Twitter Follow Discord Chat


Logo

pgx

Build Postgres Extensions with Rust!

pgx is a framework for developing PostgreSQL extensions in Rust and strives to be as idiomatic and safe as possible.

pgx supports Postgres v10, v11, v12, and v13.

Feel free to join our Discord Server.

Key Features

A Managed Development Environment

  • A cargo sub-command (cargo-pgx) for managing the pgx development environment
    • Quickly create a new extension template crate via cargo pgx new
    • Install, configure, compile, and privately install all required Postgres versions via cargo pgx init
    • Run your extension and interactively test with psql via cargo pgx run
    • Unit-test your extension across multiple Postgres versions via cargo pgx test
    • Create installation packages for your extension via cargo pgx package

Target Multiple Postgres Versions

  • Support Postgres v10, v11, v12, and v13 from the same codebase
    • Postgres Rust bindings are organized into pgXX.rs modules
  • Use Rust feature gating to use version-specific APIs
  • Seamlessly test against all versions

Automatic Schema Generation

  • Generates DDL for common SQL objects such as
    • Functions
    • Types
    • Enums
  • Hand-written SQL is supported through the extension_sql! macro or through on-disk .sql files
  • Control the order in which SQL is executed during CREATE EXTENSION ...;

Safety First

  • Translates Rust panic!s into Postgres ERRORs that abort the transaction, not the process
  • Memory Management follows Rust's drop semantics, even in the face of panic! and elog(ERROR)
  • #[pg_guard] procedural macro to ensure the above
  • Postgres Datum is simply Option<T> where T: FromDatum -- NULL Datums are safely represented as Option::None
  • #[pg_test] proc-macro for unit testing in-process within Postgres

First-class UDF support

  • Annotate functions with #[pg_extern] to expose them to Postgres
  • Return impl std::iter::Iterator<Item = T> where T: IntoDatum for automatic set-returning-functions (both RETURNS SETOF and RETURNS TABLE (...) variants
  • DDL automatically generated

Most Postgres Datatypes Transparently Converted to Rust

Postgres Type Rust Type (as Option<T>)
bytea Vec<u8> or &[u8] (zero-copy)
text String or &str (zero-copy)
varchar String or &str (zero-copy) or char
"char" i8
smallint i16
integer i32
bigint i64
oid u32
real f32
double precision f64
bool bool
json pgx::Json(serde_json::Value)
jsonb pgx::Json(serde_json::Value)
date pgx::Date
time pgx::Time
timestamp pgx::Timestamp
time with time zone pgx::TimeWithTimeZone
timestamp with time zone pgx::TimestampWithTimeZone
anyarray pgx::AnyArray
anyelement pgx::AnyElement
box pgx::pg_sys::BOX
point pgx::pgx_sys::Point
tid pgx::pg_sys::ItemPointerData
cstring &std::ffi::CStr
inet pgx::Inet(String) -- TODO: needs better support
numeric pgx::Numeric(String) -- TODO: needs better support
void ()
ARRAY[]::<type> Vec<Option<T>> or pgx::Array<T> (zero-copy)
NULL Option::None
internal pgx::PgBox<T> where T is any Rust/Postgres struct

There are also IntoDatum and FromDatum traits for implementing additional type conversions, along with #[derive(PostgresType)] and #[derive(PostgresEnum)] for automatic conversion of custom types.

Easy Custom Types

  • #[derive(PostgresType)] to use a Rust struct as a Postgres type, represented as a CBOR-encoded object in-memory/on-disk, and JSON as human-readable
    • can provide custom implementations for custom in-memory/on-disk/human-readable representations
  • #[derive(PostgresEnum)] to use a Rust enum as a Postgres enum
  • DDL automatically generated

Server Prgramming Interface (SPI)

  • Safe access into SPI
  • Transparently return owned Datums from an SPI context

Advanced Features

  • Safe access to Postgres' MemoryContext system via pgx::PgMemoryContexts
  • Executor/planner/transaction/subtransaction hooks
  • Safely use Postgres-provided pointers with pgx::PgBox<T> (akin to alloc::boxed::Box<T>)
  • #[pg_guard] proc-macro for guarding extern "C" Rust functions that need to be passed into Postgres
  • Access Postgres' logging system through eprintln!-like macros
  • Direct unsafe access to large parts of Postgres internals via the pgx::pg_sys module
  • lots more!

System Requirements

Getting Started

1. Install cargo-pgx

First you'll want to install the pgx cargo sub-command from crates.io. You'll use it almost exclusively during your development and testing workflow.

$ cargo install cargo-pgx

2. Initialize it

Next, pgx needs to be initialized. You only need to do this once.

$ cargo pgx init

The init command downloads Postgres versions v10, v11, v12, v13 and compiles them to ~/.pgx/. These installations are needed by pgx not only for auto-generating Rust bindings from each version's header files, but also for pgx's test framework.

See the documentation for cargo-pgx for details on how to limit the required postgres versions.

3. Create a new extension

$ cargo pgx new my_extension
$ cd my_extension

This will create a new directory for the extension crate.

my_extension/
├── Cargo.toml
├── my_extension.control
├── sql
│   ├── lib.generated.sql
│   └── load-order.txt
└── src
    └── lib.rs

The new extension includes an example, so you can go ahead an run it right away.

4. Run your extension

$ cargo pgx run pg13  # or pg10 or pg11 or pg12

This compiles the extension to a shared library, copies it to the specified Postgres installation (in ~/.pgx/), starts that Postgres instance and connects you, via psql, to a database named for the extension.

The first time, compilation takes a few minutes as pgx needs to generate almost 200k lines of Rust "bindings" from Postgres' header files.

Once compiled you'll be placed in a psql shell, for, in this case, Postgres 13. Now, we can just load the extension and do a select on the example function.

CREATE EXTENSION my_extension;
SELECT hello_my_extension();

This will return something along the lines of

 hello_my_extension
---------------------
 Hello, my_extension
(1 row)

Digging Deeper

Caveats & Known Issues

There's probably more than are listed here, but a primary things of note are:

  • Threading is not really supported. Postgres is strictly single-threaded. As such, if you do venture into using threads, those threads MUST NOT call any internal Postgres function, or otherwise use any Postgres-provided pointer. There's also a potential problem with Postgres' use of sigprocmask. This was being discussed on the -hackers list, even with a patch provided, but the conversation seems to have stalled (https://www.postgresql.org/message-id/flat/5EF20168.2040508%40anastigmatix.net#4533edb74194d30adfa04a6a2ce635ba).

  • async interactions are unknown right now.

  • pgx uses lots of unsafe Rust. That's generally the nature of the beast when doing FFI wrappers, so be aware.

  • Not all of Postgres' internals are included or even wrapped. This isn't due to it not being possible, it's simply due to it being an incredibly large task. If you identify internal Postgres APIs you need, open an issue and we'll get them exposed, at least through the pgx::pg_sys module.

  • Windows is not supported. It could be, but will require a bit of work with cargo-pgx and figuring out how to compile pgx's "cshim" static library.

TODO

There's a few things on our immediate TODO list

  • Better trigger function support. pgx does support creating trigger functions in Rust (need examples!) but it doesn't automatically generate any of the DDL for them. This too likely needs a procmaro like #[pg_trigger]
  • Automatic extension schema upgrade scripts, based on diffs from a previous git tag and HEAD. Likely, this will be built into the cargo-pgx subcommand and make use of https://github.com/zombodb/postgres-parser.
  • More examples -- especially around memory management and the various derive macros #[derive(PostgresType/Enum)]

Contributing

We are most definitely open to contributions of any kind. Bug Reports, Feature Requests, Documentation, and even sponsorships.

If you'd like to contribute code via a Pull Request, please make it against our develop branch. The master branch is meant to represent what is currently available on crates.io.

Providing wrappers for Postgres' internals is not a straightforward task, and completely wrapping it is going to take quite a bit of time. pgx is generally ready for use now, and it will continue to be developed as time goes on. Your feedback about what you'd like to be able to do with pgx is greatly appreciated.

License

Copyright 2020 ZomboDB, LLC <[email protected]>. All rights reserved.
Use of this source code is governed by the MIT license that can be found in the LICENSE file.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].