pg_ask is a PostgreSQL extension that integrates AI capabilities directly into your database, allowing you to generate and execute SQL queries using natural language.
- Natural Language to SQL: Convert plain English questions into SQL queries
- Two Operation Modes:
pg_gen_query(): Generate SQL without executing (preview mode)pg_gen_execute(): Generate and execute SQL, returning a cursor for result fetching
- Schema-Aware: Automatically inspects your database schema to generate contextually appropriate queries
- AI Provider Support: Works with OpenAI-compatible APIs (OpenAI, Groq, etc.)
- Built for PostgreSQL 16+: Native C++ extension for optimal performance
The fastest way to try pg_ask is using our pre-built Docker image:
# Pull the image
docker pull ghcr.io/abiji-2020/pg_ask:latest
# Run with your API key
docker run -d \
--name pg_ask \
-e POSTGRES_PASSWORD=mysecretpassword \
-e PG_ASK_AI_KEY=your_api_key_here \
-p 5432:5432 \
ghcr.io/abiji-2020/pg_ask:latest
# Connect and use
psql -h localhost -U postgres -d postgresOnce connected, the extension is already installed:
-- Generate SQL query (preview mode)
SELECT pg_gen_query('show me all users who registered this month');
-- Generate and execute SQL using cursor
BEGIN;
SELECT pg_gen_execute('list all tables in the database');
FETCH ALL FROM ai_query_result;
COMMIT;Create a .env file:
POSTGRES_PASSWORD=your_secure_password
PG_ASK_AI_KEY=your_api_key_hereCreate docker-compose.yaml:
version: '3.8'
services:
postgres:
image: ghcr.io/abiji-2020/pg_ask:latest
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: postgres
POSTGRES_USER: postgres
PG_ASK_AI_KEY: ${PG_ASK_AI_KEY}
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:Start the service:
docker-compose up -dDownload and install the pre-built extension:
# Download the installer script
curl -fsSL https://abiji-2020.github.io/pg_ask/install.sh -o install.sh
chmod +x install.sh
# Install the extension
sudo ./install.sh
# Restart PostgreSQL
sudo systemctl restart postgresqlNote: Set your API key as an environment variable before starting PostgreSQL (see Configuration section below).
- Operating System: Linux (Ubuntu 20.04+, Debian 11+, or compatible)
- PostgreSQL 16+ (with development headers)
- CMake 3.15+
- C++20 compatible compiler (GCC 10+, Clang 11+)
- Git
# Clone the repository
git clone https://github.com/Abiji-2020/pg_ask.git
cd pg_ask
# Initialize submodules (ai-sdk-cpp)
git submodule update --init --recursive
# Create build directory
mkdir -p build && cd build
# Configure with CMake
cmake -DUSE_AI_SDK=ON \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=20 \
..
# Build the extension
make -j$(nproc)
# Install (requires sudo)
sudo make install-- Connect to your database
psql -U postgres -d your_database
-- Create the extension
CREATE EXTENSION pg_ask;
-- Verify installation
\dx pg_askThe extension requires configuration via environment variables. API keys should never be stored in postgresql.conf for security reasons.
| Variable | Description | Required | Default |
|---|---|---|---|
PG_ASK_AI_KEY |
API key for AI provider | Yes | - |
POSTGRES_PASSWORD |
PostgreSQL superuser password | Yes (Docker) | - |
POSTGRES_USER |
PostgreSQL username | No | postgres |
POSTGRES_DB |
Default database name | No | postgres |
You can customize the AI model and endpoint using PostgreSQL configuration parameters:
| Parameter | Description | Default |
|---|---|---|
pg_ask.model |
AI model to use for SQL generation | gpt-4o (OpenAI default) |
pg_ask.endpoint |
API endpoint URL for the AI provider | https://api.openai.com/v1 (OpenAI) |
Setting Configuration Parameters:
-- Set for current session
SET pg_ask.model = 'gpt-4';
SET pg_ask.endpoint = 'https://api.openai.com/v1';
-- Use Groq instead
SET pg_ask.model = 'mixtral-8x7b-32768';
SET pg_ask.endpoint = 'https://api.groq.com/openai';
-- Set in postgresql.conf for persistent configuration
-- Add these lines to postgresql.conf:
-- pg_ask.model = 'gpt-3.5-turbo'
-- pg_ask.endpoint = 'https://api.openai.com/v1'
-- Set at database level
ALTER DATABASE mydb SET pg_ask.model = 'gpt-4';
-- Set at user level
ALTER USER myuser SET pg_ask.endpoint = 'https://api.groq.com/openai';Supported Models and Endpoints:
- OpenAI (default):
- Endpoint:
https://api.openai.com/v1 - Models:
gpt-4o(default),gpt-4,gpt-3.5-turbo
- Endpoint:
- Groq:
- Endpoint:
https://api.groq.com/openai - Models:
mixtral-8x7b-32768,llama-3.1-70b-versatile
- Endpoint:
- Azure OpenAI:
- Endpoint: Your Azure endpoint
- Models: Your deployed model names
- OpenRouter:
- Endpoint:
https://openrouter.ai/api/v1 - Models: Various models via OpenRouter
- Endpoint:
Use a .env file with docker-compose:
PG_ASK_AI_KEY=your_api_key_here
POSTGRES_PASSWORD=your_secure_passwordOr pass directly in docker run:
docker run -e PG_ASK_AI_KEY=your_key -e POSTGRES_PASSWORD=pass ...Edit the PostgreSQL systemd service file:
sudo systemctl edit postgresqlAdd the environment variable:
[Service]
Environment="PG_ASK_AI_KEY=your_api_key_here"Reload and restart:
sudo systemctl daemon-reload
sudo systemctl restart postgresqlCreate an environment file:
sudo nano /etc/postgresql/16/main/environmentAdd:
PG_ASK_AI_KEY=your_api_key_here
Ensure PostgreSQL reads this file on startup.
Generates SQL from natural language but does NOT execute it. Use this to preview the generated query.
Syntax:
pg_gen_query(natural_language_query text) RETURNS textExamples:
-- Preview the generated SQL
SELECT pg_gen_query('show me all users created in the last 7 days');
-- Result (example):
-- SELECT * FROM users WHERE created_at >= CURRENT_DATE - INTERVAL '7 days';
-- Use the generated SQL as needed
SELECT pg_gen_query('count users by registration month');Generates SQL from natural language and executes it, returning a cursor for fetching results.
Syntax:
pg_gen_execute(natural_language_query text) RETURNS refcursorImportant: This function returns a cursor reference. You must fetch results from the cursor within a transaction block.
Examples:
-- Basic usage: open cursor and fetch results
BEGIN;
SELECT pg_gen_execute('list all tables in the public schema');
FETCH ALL FROM ai_query_result;
COMMIT;
-- Count records
BEGIN;
SELECT pg_gen_execute('how many users are there?');
FETCH ALL FROM ai_query_result;
COMMIT;
-- Fetch results one at a time
BEGIN;
SELECT pg_gen_execute('show me top 10 customers by revenue');
FETCH NEXT FROM ai_query_result; -- Get first row
FETCH NEXT FROM ai_query_result; -- Get second row
-- ... continue fetching
COMMIT;
-- Fetch specific number of rows
BEGIN;
SELECT pg_gen_execute('list all products');
FETCH 5 FROM ai_query_result; -- Get first 5 rows
FETCH 5 FROM ai_query_result; -- Get next 5 rows
COMMIT;
-- Use FORWARD and BACKWARD navigation
BEGIN;
SELECT pg_gen_execute('show daily sales for last 30 days');
FETCH FORWARD 10 FROM ai_query_result; -- Get first 10
FETCH BACKWARD 5 FROM ai_query_result; -- Go back 5
COMMIT;Cursor Operations:
FETCH ALL FROM ai_query_result- Fetch all rowsFETCH NEXT FROM ai_query_result- Fetch next single rowFETCH n FROM ai_query_result- Fetch next n rowsFETCH FORWARD n FROM ai_query_result- Move forward and fetch n rowsFETCH BACKWARD n FROM ai_query_result- Move backward and fetch n rowsCLOSE ai_query_result- Explicitly close cursor (automatic on COMMIT)
Why Cursors?
Cursors provide several advantages:
- Memory efficiency: Fetch large result sets incrementally
- Flexibility: Navigate forward and backward through results
- Control: Process results at your own pace
- No column definition needed: Unlike SETOF RECORD, cursors don't require predefined column lists
┌─────────────────────────────────────────────────────────────┐
│ PostgreSQL Server │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ pg_ask Extension │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ │
│ │ │ pg_ask.cpp │ │ explorer.cpp │ │ ai_engine.cpp│ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ PG Functions │─▶│ Schema │─▶│ AI SDK │ │ │
│ │ │ │ │ Inspector │ │ Integration │ │ │
│ │ └──────────────┘ └──────────────┘ └─────────────┘ │ │
│ │ │ │ │ │ │
│ └─────────┼──────────────────┼─────────────────┼─────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Catalog │ │ System │ │ Network │ │
│ │ Tables │ │ Caches │ │ (HTTPS) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌───────────────┐
│ AI Provider │
│ (OpenAI/Groq) │
└───────────────┘
- pg_ask.cpp: Entry point, exposes the
pg_gen_queryfunction (C++);pg_gen_executeis a PL/pgSQL wrapper - explorer.cpp: Database schema inspection and formatting
- ai_engine.cpp: AI SDK wrapper for prompt building and SQL generation
- ai-sdk-cpp: Third-party AI SDK for communicating with AI providers
pg_ask/
├── src/ # C++ source files
│ ├── pg_ask.cpp # Main extension entry point
│ ├── explorer.cpp # Schema inspection utilities
│ └── ai_engine.cpp # AI integration wrapper
├── include/ # Public headers
│ ├── explorer.h
│ └── ai_engine.h
├── pg/ # PostgreSQL extension metadata
│ ├── pg_ask.control # Extension control file
│ └── pg_ask--1.0.sql # Extension installation SQL
├── docker/ # Docker build configurations
│ ├── Dockerfile
│ ├── Dockerfile.minimal
│ └── init-extension.sql
├── scripts/ # Installation scripts
│ └── install.sh
├── third_party/ # External dependencies
│ └── ai-sdk-cpp/ # AI SDK (submodule)
├── CMakeLists.txt # Build configuration
└── docker-compose.yaml # Docker Compose setup
# Clone with submodules
git clone --recursive https://github.com/Abiji-2020/pg_ask.git
cd pg_ask
# Build with debug symbols
mkdir -p build && cd build
cmake -DUSE_AI_SDK=ON -DCMAKE_BUILD_TYPE=Debug ..
make -j$(nproc)
# Install locally for testing
sudo make install# Start test database with Docker
docker-compose up -d
# Connect and test
psql -h localhost -U postgres -d postgres
# Run manual tests
CREATE EXTENSION pg_ask;
SELECT pg_gen_query('test query');# Build minimal image
docker build -f docker/Dockerfile.minimal -t pg_ask:local .
# Run locally
docker run -d \
-e POSTGRES_PASSWORD=test \
-e PG_ASK_AI_KEY=your_key \
-p 5432:5432 \
pg_ask:local-- Check if extension files are installed
SELECT * FROM pg_available_extensions WHERE name = 'pg_ask';
-- Check PostgreSQL logs
sudo tail -f /var/log/postgresql/postgresql-16-main.log# Verify API key is set (check environment)
docker exec pg_ask env | grep PG_ASK_AI_KEY
# For system PostgreSQL
sudo systemctl show postgresql | grep Environment
# Test API connectivity
psql -c "SELECT pg_gen_query('simple test');"# Ensure PostgreSQL dev headers are installed
# Ubuntu/Debian
sudo apt-get install postgresql-server-dev-16
# RedHat/CentOS
sudo yum install postgresql16-devel
# Verify pg_config is available
pg_config --versionIf you get cursor-related errors:
-- ERROR: cursor "ai_query_result" does not exist
-- SOLUTION: Cursors must be used within a transaction block
-- Wrong:
SELECT pg_gen_execute('list users');
FETCH ALL FROM ai_query_result; -- Error: no transaction
-- Correct:
BEGIN;
SELECT pg_gen_execute('list users');
FETCH ALL FROM ai_query_result;
COMMIT;
-- Cursor already closed
-- SOLUTION: Cursors are automatically closed on COMMIT
BEGIN;
SELECT pg_gen_execute('list users');
FETCH ALL FROM ai_query_result;
COMMIT;
-- Can't fetch again here - cursor is closed# Check container logs
docker logs pg_ask
# Verify environment variables
docker exec pg_ask env | grep PG_ASK
# Connect to container
docker exec -it pg_ask psql -U postgresContributions are welcome! Please see our Contributing Guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with ai-sdk-cpp
- Powered by PostgreSQL
- AI capabilities provided by OpenAI, Groq, and other providers
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: Project Wiki
Made with ❤️ for the PostgreSQL community