# pg_liquid
A high-performance PostgreSQL extension for Liquid template processing, built with Rust and pgrx.



## Overview
`pg_liquid` brings the power of [Liquid templating](https://shopify.github.io/liquid/) directly into PostgreSQL. This extension provides two main functions for validating and rendering Liquid templates with JSON data, enabling dynamic content generation within your database.
Liquid is a safe, template language originally created by Shopify and used by Jekyll, GitHub Pages, and many other platforms. With `pg_liquid`, you can leverage this powerful templating system directly in your PostgreSQL queries and stored procedures.
## Features
- **๐ Syntax Validation**: Check if Liquid template code has valid syntax
- **๐จ Template Rendering**: Process Liquid templates with JSON data to generate final output
- **โก High Performance**: Built in Rust for optimal performance and memory safety
- **๐ PostgreSQL Native**: Seamless integration with PostgreSQL's JSONB type
- **๐ Full Liquid Support**: Complete support for Liquid syntax including filters, conditionals, loops, and more
- **๐ก๏ธ Memory Safe**: Rust implementation prevents memory leaks and crashes
- **๐งช Well Tested**: Comprehensive test suite ensuring reliability
## Installation
### Prerequisites
- PostgreSQL 13+ with development headers
- Rust 1.70+
- pgrx framework
### Quick Start
#### 1. Install pgrx
```bash
cargo install --locked cargo-pgrx
```
#### 2. Initialize pgrx
Replace `pg17` with your PostgreSQL version (pg13, pg14, pg15, pg16, or pg17):
```bash
cargo pgrx init --pg17 $(which pg_config)
```
#### 3. Build and Install the Extension
```bash
# Clone just the pg_liquid directory or download the standalone package
git clone https://github.com/pitorg/pg_liquid
cd pg_liquid
cargo pgrx install --release
```
#### 4. Enable the Extension
Connect to your PostgreSQL database and run:
```sql
CREATE EXTENSION liquid;
```
### Development Installation
For development and testing:
```bash
cd pg_liquid
cargo pgrx run --release
```
**Note**: This extension is completely standalone and does not require any other components from the liquid-rust repository. It uses the published `liquid` crate from crates.io.
**Architecture**: The extension follows the pgrx pattern where the crate is named `pg_liquid` but creates an extension called `liquid` with functions in the `liquid` schema.
This will start a PostgreSQL instance with the extension already loaded.
### Verify Installation
Once installed, verify the extension works:
```sql
-- Connect to your PostgreSQL database
CREATE EXTENSION liquid;
-- Test basic functionality
SELECT liquid.check_valid_syntax('Hello {{ name }}!');
-- Should return: true
SELECT liquid.render('Hello {{ name }}!', '{"name": "World"}'::jsonb);
-- Should return: "Hello World!"
```
## Functions
The extension provides two main functions in the `liquid` schema:
### `liquid.check_valid_syntax(liquid_code TEXT) โ BOOLEAN`
Validates whether the provided Liquid template code has valid syntax.
**Parameters:**
- `liquid_code` (TEXT): The Liquid template code to validate
**Returns:**
- `BOOLEAN`: `true` if the syntax is valid, `false` otherwise
**Examples:**
```sql
-- Valid syntax examples
SELECT liquid.check_valid_syntax('Hello {{ name }}!');
-- Returns: true
```
### `liquid.render(liquid_code TEXT, data JSONB) โ TEXT`
Renders a Liquid template with the provided JSON data.
**Parameters:**
- `liquid_code` (TEXT): The Liquid template code to render
- `data` (JSONB): JSON object containing the data to use in template rendering
**Returns:**
- `TEXT`: The rendered template output
**Examples:**
```sql
-- Basic variable substitution
SELECT liquid.render(
'Hello {{ user.name }}! You have {{ user.credits }} credits.',
'{
"user": {
"name": "Alice",
"credits": 100
}
}'::jsonb
);
-- Returns: "Hello Alice! You have 100 credits."
-- Conditional rendering
SELECT liquid.render(
'{% if user.is_premium %}Premium user{% else %}Regular user{% endif %}',
'{"user": {"is_premium": true}}'::jsonb
);
-- Returns: "Premium user"
```
## Liquid Syntax Support
`pg_liquid` supports the complete Liquid syntax.
## Performance
`pg_liquid` is built with performance in mind:
- **Rust Implementation**: Leverages Rust's zero-cost abstractions and memory safety
- **Compiled Templates**: Templates are parsed once and can be cached for repeated use
- **Efficient JSON Handling**: Direct integration with PostgreSQL's JSONB type
- **Memory Safe**: No memory leaks or buffer overflows
### Benchmarks
Real-world performance testing shows excellent throughput for template rendering:
```sql
-- Test: 1 million simple liquid template renders
SELECT count(*) FROM (
SELECT liquid.render(
'Hej {{ user.name }}'::text,
format('{"user":{"name":"%s"}}', generate_series)::jsonb
)
FROM generate_series(1,1000000)
) AS x;
-- Result: 1,000,000 renders in 13.716 seconds
-- Performance: ~73,000 renders per second
-- Per-operation: ~13.7 microseconds per render
```
**Performance Summary:**
- **Throughput**: ~73,000 template renders per second
- **Latency**: ~13.7 microseconds per render operation
- **Comparison**: ~96x slower than simple `replace()` (expected for full template engine)
- **Use Case**: Excellent for high-throughput applications requiring dynamic content
## Error Handling
The extension handles errors gracefully:
- **Syntax Validation**: Use `check_valid_syntax()` to check templates before rendering
- **Detailed Error Messages**: Clear error messages for debugging template issues
- **Safe Failures**: Invalid templates return errors rather than crashing the database
```sql
-- Validate before rendering
SELECT CASE
WHEN liquid.check_valid_syntax('{{ user.name }') THEN
liquid.render('{{ user.name }', '{"user": {"name": "Alice"}}'::jsonb)
ELSE
'Invalid template syntax'
END;
```
## Testing
Run the test suite:
```bash
cargo pgrx test
```
This will run both Rust unit tests and PostgreSQL integration tests.
### Development Setup
1. Get the pg_liquid directory (standalone)
2. Install dependencies: `cargo install cargo-pgrx`
3. Initialize pgrx: `cargo pgrx init`
4. Run tests: `cargo pgrx test`
5. Start development server: `cargo pgrx run`
**Dependencies**: This extension only depends on the published `liquid` crate from crates.io and does not require any local dependencies.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Related Projects
- [liquid-rust](https://github.com/cobalt-org/liquid-rust) - The underlying Liquid implementation
- [pgrx](https://github.com/pgcentralfoundation/pgrx) - PostgreSQL extension framework
- [Liquid](https://shopify.github.io/liquid/) - The original Liquid template language