PL/PRQL is a PostgreSQL extension that lets you write stored procedures with PRQL. The extension supports PostgreSQL v13-18 on Linux and macOS.
PRQL (Pipelined Relational Query Language) is an open source query language for data manipulation and analysis that compiles to SQL. PRQL introduces a pipeline concept similar to Unix pipes that transforms data line-by-line. The sequential series of transformations reduces the complexity often encountered with nested SQL queries and makes your data manipulation logic easier to read and write. With PL/PRQL you can write Procedural Language (PL) functions with PRQL instead of the traditional PL/pgSQL, combining the simplicity of PRQL with the power of stored procedures.
- Write functions with PRQL - Useful for large analytical queries
- Compile PRQL queries to SQL queries - Useful for development and debugging
- Execute PRQL queries - Useful for prototyping and custom queries in ORMs
PRQL shines when your SQL queries becomes long and complex. You can manage this complexity by porting your most impressive SQL incantations to PRQL functions, which can then be used in dashboards, business logic or other database code. For example:
create function match_stats(int) returns table(player text, kd_ratio float) as $$
from matches
filter match_id == $1
group player (
aggregate {
total_kills = sum kills,
total_deaths = sum deaths
}
)
filter total_deaths > 0
derive kd_ratio = total_kills / total_deaths
select { player, kd_ratio }
$$ language plprql;
select * from match_stats(1001)
player | kd_ratio
---------+----------
Player1 | 0.625
Player2 | 1.6
(2 rows)You can use prql_to_sql() to see the SQL statements that PostgreSQL executes under the hood. This function invokes the PRQL compiler and shows you the resulting SQL code. Using the example above:
select prql_to_sql('...'); -- statements above omitted for brevity
prql_to_sql
-------------
WITH table_0 AS (
SELECT player, COALESCE(SUM(kills), 0) AS _expr_0, COALESCE(SUM(deaths), 0) AS _expr_1
FROM matches
WHERE match_id = $1
GROUP BY player
)
SELECT player, _expr_0 / _expr_1 AS kd_ratio
FROM table_0
WHERE _expr_1 > 0
-- Generated by PRQL compiler version:0.11.1 (https://prql-lang.org)
(1 row)You can run PRQL code directly with the prql function. This is useful for e.g. custom queries in application code:
select prql('from matches | filter player == ''Player1''')
as (id int, match_id int, round int, player text, kills int, deaths int)
limit 2;
id | match_id | round | player | kills | deaths
----+----------+-------+---------+-------+--------
1 | 1001 | 1 | Player1 | 4 | 1
3 | 1001 | 2 | Player1 | 1 | 7
(2 rows)
-- Same as above, but returns cursor
select prql('from matches | filter player == ''Player1''', 'player1_cursor');
fetch 2 from player1_cursor;For more information on the design of the extension, see the design document.
For more information on PRQL, visit the PRQL website, playground or repository.
Note
PRQL supports select statements only. insert, update, and delete statements, and your other database code, will continue to live in vanilla SQL, ORMs, or other database frameworks.
You can install the PL/PRQL extension in four ways:
- Install Deb File: Download .deb file from releases page.
- Install From Source: Clone the repository and build the extension on your own machine.
- Run Dockerfile: Build a docker image with PostgreSQL and the extension.
- Run Shell Script: Download and run a shell script builds the extension on your own machine for you.
The instruction assume you use Ubuntu or Debian.
Follow these steps to install PL/PRQL from one of the released deb files:
-
Download the deb file that matches your operating system from the Releases page.
-
Open a terminal and change to the directory where the
.debfile was downloaded. Install the package with dpkg, e.g.:sudo dpkg -i plprql-18.0.0-postgresql-18-debian-bookworm-amd64.deb
-
If dpkg reports missing dependencies, run the following command to fix them:
sudo apt-get install -f
This only requires that you have PostgreSQL installed on beforehand. Replace the major version of PostgreSQL in the deb's filename if needed. Supported versions are 13, 14, 15, 16, 17, and 18.
PL/PRQL is built on top of the pgrx framework for writing PostgreSQL extensions in Rust. This framework comes with development tools that you need to install. Follow these steps to set up your development environment:
-
Install
cargo.curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y -
Install
cargo-pgrx.cargo install --locked --version=0.16.1 cargo-pgrx
The version of
cargo-pgrxmust match the version ofpgrxinplprql/Cargo.toml. -
Initialize
pgrxfor your system.cargo pgrx init --pg18 <PG18>
where
<PG18>is the path to your system installation'spg_configtool (typically/usr/bin/pg_config). Supported versions are PostgreSQL v13-18. You can also runcargo pgrx initand havepgrxdownload, install, and compile PostgreSQL v13-18. These installations are managed bypgrxand used for development and testing. Individualpgrx-managed installations can be installed using e.g.cargo pgrx init --pg18 download. -
Clone this repository.
git clone https://github.com/kaspermarstal/plprql
-
cdinto root directory and install the extension to the PostgreSQL specified by thepg_configcurrently on your$PATH.cd plprql/plprql cargo pgrx install --releaseYou can target a specific PostgreSQL installation by providing the path of another
pg_configusing the-cflag. -
Fire up your system PostgreSQL installation and start writing functions right away! You can also try out PL/PRQL in an installation managed by
pgrx:$ cargo pgrx run pg18 psql> create extension plprql; psql> create function match_stats(int) returns table(total_kills real, total_deaths real) as $$ from rounds filter match_id == $1 aggregate { total_kills = sum kills, total_deaths = sum deaths } $$ language plprql psql> select match_stats(1);
The docker/plprql.Dockerfile builds the postgres:18-bookworm docker image with the extension installed. You run this Dockerfile on your own machine with the following commands:
curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/kaspermarstal/plprql/main/docker/plprql.Dockerfile > plprql.Dockerfile
docker build --tag 'plprql' . -f plprql.DockerfileThe dockerfile downloads a .deb file from the releases page and installs it into the official postgres:18-bookworm image.
You can quickly test that the extension is installed and works as expected:
CONTAINER_ID=$(docker run -d -e POSTGRES_HOST_AUTH_METHOD=trust plprql)
docker exec $CONTAINER_ID psql -U postgres -c "create extension plprql;"
docker exec $CONTAINER_ID psql -U postgres -c "select prql_to_sql('from table')"Run the following command to download and execute the shell script in scripts/install.sh:
curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/kaspermarstal/plprql/main/scripts/install.sh | bashThis will install the tip of the main branch using pg_config on your path.
You can customize the PostgreSQL installation and/or the PL/PRQL version using the --pg-config and --revision flags:
curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/kaspermarstal/plprql/main/scripts/install.sh > install.sh
chmod +x ./install.sh
./install.sh --pg-version /usr/bin/pg_config --revision 186faeaYou need the following packages for the shell script to run:
- A C compiler
- PostgreSQL and header files
- Rust, Cargo, and pgrx
- Utilities for the shell script (curl, wget, gnupg, lsb-release, git, jq)
You can install these dependencies with the following commands:
sudo apt-get update && apt-get upgrade
sudo apt-get install -y curl wget gnupg lsb-release git build-essential
sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
sudo apt-get update
sudo apt-get install -y postgresql-18 postgresql-server-dev-18
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source ~/.bashrc
cargo install --locked --version=0.16.1 cargo-pgrx
cargo pgrx init --pg18 $(which pg_config)You can run tests using cargo pgrx test pg18. Unit tests are in the main plprql crate while integration tests are in the plprql-tests crate. From the root source directory:
cd plprql && echo "\q" | cargo pgrx run pg18 && cargo test --no-default-features --features pg18
cd ../plprql-tests && echo "\q" | cargo pgrx run pg18 && cargo test --no-default-features --features pg18Supported PostgreSQL versions are pg13, pg14, pg15, pg16, pg17, and pg18.
PL/PRQL's versioning scheme follows PostgreSQL's major version: <pg-major>.<major>.<minor>:
18.0.0
│ │ │
│ │ └─ Minor version (non-breaking changes in PL/PRQL)
│ └─── Major version (breaking changes in PL/PRQL)
└───── PostgreSQL major version
The first number indicates the latest PostgreSQL major version supported by this release. The second and third numbers track PL/PRQL's own changes:
- Second number (major): Breaking changes in PL/PRQL's API, behavior, or SQL interface.
- Third number (minor): Bug fixes, performance improvements, and backward-compatible changes in PL/PRQL.
Examples:
18.0.0- Initial release of PL/PRQL for PostgreSQL 1818.1.0- Breaking change in PL/PRQL functionality (still for PostgreSQL 18)18.0.1- Bug fix or minor improvement in PL/PRQL (for PostgreSQL 18)
To check your installed plprql version, run SELECT extversion FROM pg_extension WHERE extname = 'plprql';.
Apache 2.0 License