PostgreSQL Extension SQL Syntax
This page documents the current SQL surface for the pg_kalam PostgreSQL extension.
The key implementation detail is that the extension exposes two different table-definition paths:
-
CREATE TABLE ... USING kalamdbThe shorthand authoring path backed by the DDL hook. This currently assumes the default server namekalam_server. -
CREATE FOREIGN TABLE ... SERVER <name>The explicit PostgreSQL FDW path. Use this when you need a non-default server name or want to mirror a relation directly.
Extension Metadata
Install and verify the extension:
Current helper functions:
kalam_compiled_mode() should currently return remote.
Foreign Server Syntax
Create the PostgreSQL foreign server that points at KalamDB:
Update it with standard PostgreSQL FDW server syntax:
Drop it when you no longer need the bridge:
Supported Server Options
| Option | Required | Purpose |
|---|---|---|
host | Yes | KalamDB host name or IP |
port | Yes | KalamDB gRPC port |
auth_header | No | Authorization header sent to KalamDB |
timeout | No | Request timeout in milliseconds |
ca_cert | No | PEM CA bundle for TLS |
client_cert | No | PEM client certificate for mTLS |
client_key | No | PEM client private key for mTLS |
If you set either client_cert or client_key, you must set both.
Point host and port at KalamDB’s shared RPC listener, not the HTTP API port.
CREATE TABLE ... USING kalamdb
The public table-definition syntax is CREATE TABLE ... USING kalamdb:
This does three things:
- resolves the PostgreSQL schema and table name into the mirrored KalamDB namespace and table,
- creates the target namespace and KalamDB table if needed,
- creates the local foreign table surface and injects the PostgreSQL-visible system columns that
pg_kalammanages locally.
Shared table example
User table example
Stream table example
Notes for USING kalamdb
USING kalamdbselects the extension-managed PostgreSQL authoring path.WITH (type = 'shared' | 'user' | 'stream')selects the KalamDB table type.PRIMARY KEYandDEFAULT SNOWFLAKE_ID()are preserved in KalamDB.SERIAL,BIGSERIAL,SMALLSERIAL, andGENERATED ... AS IDENTITYare normalized into integer columns withDEFAULT SNOWFLAKE_ID()before the KalamDB DDL is sent.- Additional
WITH (...)options are forwarded to the mirrored KalamDBCREATE TABLEstatement. - This shorthand path currently depends on the DDL preload hook and the default server name
kalam_server. - The resulting PostgreSQL object is a foreign table, so follow-up DDL should use
ALTER FOREIGN TABLEandDROP FOREIGN TABLE.
CREATE FOREIGN TABLE ... SERVER ...
Use explicit foreign tables when you need a non-default server or want to mirror a remote relation directly:
Current mapping rules:
- The local PostgreSQL schema is the remote namespace.
- The local PostgreSQL relation name is the remote table name.
OPTIONS (namespace, table)are not the runtime source of truth for the current scan and modify paths.- If a remote column is
FILE, declare the local PostgreSQL column asJSONB.
JSON and JSONB
pg_kalam maps PostgreSQL JSON and JSONB authoring types to KalamDB JSON.
On the CREATE TABLE ... USING kalamdb path, the local PostgreSQL column keeps the type you declared, so use JSONB when you want PostgreSQL’s richer local JSON operator surface.
FILE is the special case: it is always mirrored locally as JSONB.
That syntax compatibility is the contract; PostgreSQL may still evaluate the JSONB expression locally on the mirrored value unless you explicitly route the statement through kalam_exec(...).
When you do send SQL through kalam_exec(...), KalamDB itself supports the same common PostgreSQL-style JSON operators:
KalamDB-side JSON helper functions are also available, including json_get, json_as_text, json_contains, json_length, json_object_keys, and typed extractors such as json_get_int, json_get_float, and json_get_bool.
Current scope:
- KalamDB directly plans
->,->>, and?today. - Do not assume full PostgreSQL
jsonboperator parity for operators such as#>,#>>, or@>yet.
FILE
FILE is the main PostgreSQL extension-specific datatype shortcut.
Current FILE behavior:
- The remote KalamDB schema keeps the
FILElogical type. - The local PostgreSQL surface rewrites that column to
JSONB. - PostgreSQL reads and writes the serialized
FileRefJSON representation. - Binary upload and file lifecycle usually happen through KalamLink or another file-aware KalamDB client, not through a raw PostgreSQL
BYTEAupload path.
System Columns
pg_kalam manages system columns itself. Do not declare them explicitly in CREATE TABLE ... USING kalamdb.
| Column | Where it appears | Rules |
|---|---|---|
_seq | All pg_kalam PostgreSQL tables | Auto-injected as BIGINT, populated from KalamDB read results, read-only from PostgreSQL, and not forwarded when supplied in INSERT or UPDATE |
_userid | User tables only | Auto-injected as TEXT, exposed on reads, and usable as an explicit tenant override only for INSERT |
Current rules:
CREATE TABLE ... USING kalamdb (..., _seq BIGINT, ...)is rejected. The same applies to_useridand_deleted._seqis a read-only metadata column. Query it, sort by it, or return it to clients, but do not treat it as an application-managed field.- For user tables, omitting
_useridonINSERTuses the currentkalam.user_idsession value. - For user tables, including
_useridonINSERToverrides the session value for that inserted row batch. - In a multi-row
INSERT, all rows must use the same_useridvalue. UPDATEandDELETEcontinue to use the session’skalam.user_idscope. Reassigning ownership withUPDATE ... SET _userid = ...is not in the supported surface._deletedis reserved but is not auto-injected into the current PostgreSQL relation surface.
Example:
Forwarded Table Options
Any supported KalamDB table option can be authored from PostgreSQL with the table WITH (...) clause.
That means PostgreSQL can act as the entry point for KalamDB-native table definitions as long as the resulting table options are valid for KalamDB once the extension forwards them.
Common forwarded WITH (...) values
| Option | Purpose |
|---|---|
type | Table type: shared, user, or stream |
flush_policy | Hot-path flush behavior |
storage_id | Target storage backend |
access_level | Shared-table access policy |
ttl_seconds | Stream retention TTL |
deleted_retention_hours | Soft-delete retention window |
Direct Statement Execution
To pass any statement directly to KalamDB, use kalam_exec(...):
kalam_exec(...) sends the SQL string to the KalamDB server as-is.
- For
SELECTstatements, it returns a JSON array string. - For DDL and DML statements, it returns a JSON string message.
- It uses the default foreign server
kalam_server. - It is revoked from
PUBLIC. - It does not currently mirror PostgreSQL
search_pathor current schema automatically, so schema-qualify the statement.
If you were expecting a schema-qualified helper such as kalam.exec(...), the currently exposed PostgreSQL function name is kalam_exec(...).
Query and Mutation Syntax
Select
Insert
_seq is visible for reads but is not a writable application column.
Update
Delete
User-scoped DML
In practice, kalam.user_id is a PostgreSQL SUSET setting, so the executing role must be allowed to change SUSET parameters.
Explicit Transaction Syntax
The PostgreSQL extension supports explicit transaction control for Kalam-backed tables:
Commit example
Read-your-writes and rollback example
Within the same PostgreSQL transaction, reads see the staged writes from that transaction. On COMMIT, the staged writes are made durable in KalamDB. On ROLLBACK, they are discarded.
Transaction observability
Use direct KalamDB SQL or kalam_exec(...) when you want to inspect the server-side session and transaction views from PostgreSQL.
Example via kalam_exec(...) for active pg bridge sessions:
Example via kalam_exec(...) for active explicit transactions across pg and native KalamDB SQL:
Current limits inside explicit transactions
- Shared and user table DML are supported.
- Stream-table writes are rejected inside explicit transactions.
- DDL inside explicit transactions is not supported.
- Savepoints and PostgreSQL subtransactions are not yet supported.
Row Identity for UPDATE and DELETE
The current FDW modify path uses the first non-system column as its row-identity heuristic.
Practical guidance:
- Keep the primary key as the first user column in the table definition.
- If you are mirroring an existing remote table and expect heavy
UPDATEorDELETEuse, validate the behavior against your exact schema before depending on it in production.
Not Yet Supported
IMPORT FOREIGN SCHEMA is not yet supported in the current remote mode:
For now, use CREATE TABLE ... USING kalamdb for PostgreSQL-side authoring or kalam_exec(...) for direct server execution.