OriginChain docs
reference · sql clients

Connect a SQL client

OriginChain speaks the PostgreSQL wire protocol. You can point an ordinary Postgres client at your database and run SQL against the same data your HTTP API calls see - one store, one source of truth.

limited preview · rolling out

Wire-protocol access is in limited preview and is being enabled gradually. Self-serve enablement covers single-node instances for now - for HA or multi-node configurations, talk to us. If your instance doesn't show a SQL access panel in the console yet, the listener isn't switched on for you - everything on this page also works over the SQL endpoint of the HTTP API today. This page states plainly what works over the wire and what doesn't; the matrix below is the honest version, not the optimistic one.

What you can connect.

Any client or driver that speaks the PostgreSQL protocol can connect. The three we verify against are psql, DBeaver, and pgAdmin - walkthroughs for each are below. Language drivers that use the same protocol (libpq, JDBC's PostgreSQL driver, node-postgres, psycopg, pgx, and friends) connect the same way, and so does the standard PostgreSQL ODBC driver - DSN details below.

not supported

MySQL Workbench and SQL Server Management Studio (SSMS) cannot connect. They speak different wire protocols (the MySQL protocol and TDS respectively), not PostgreSQL's - no connection setting will make them work. Don't spend an afternoon on it; use one of the three clients above.

Connection details.

Host, port, username and password are per-database and live in the console: open your instance and look for the SQL access panel. The port is PostgreSQL's stock 5432; authentication is SCRAM-SHA-256 (the flow every current Postgres client speaks), and the connection must use TLS - keep sslmode=require.

YOUR SQL CLIENTDBeaver · pgAdminpsql · ODBC (psqlODBC)any PostgreSQL driverPostgreSQL wire protocol:5432TLSSCRAM-SHA-256ORIGINCHAIN INSTANCEOne storeSQL · vectorsfull-text · graph
Your existing Postgres client speaks the wire protocol straight to the instance — the same one your HTTP API, vectors and full-text indexes live in. No driver, no ORM, no schema changes.
host      <your-database-host>    # console -> your instance -> SQL access
port      5432                    # PostgreSQL's stock port - the panel shows it too
database  postgres                # cosmetic - see the note below this block
user      <user>                  # shown in the SQL access panel
password  <password>              # shown in the SQL access panel
sslmode   require

# Or as one connection URI:
postgresql://<user>:<password>@<your-database-host>:5432/postgres?sslmode=require
the database field is cosmetic

Which database you connect to is decided by your credentials, not by the database field. The server reports a single database named postgres to every client, whatever you type there. Leave it as postgres so GUI clients resolve their navigation tree cleanly - but know that typing something else neither connects you elsewhere nor protects anything. (The console's connection string may name a different database - same cosmetic field, connects identically.)

One more gate before the first connect: the SQL port is reachable only from addresses on your instance's IP Access List - it is never open to the world. An empty list means the port stays closed and every client times out. Add the address you connect from (console → your instance → Network access) and retry.

Client walkthroughs.

Each tab is the short version: the fields that matter and the one gotcha worth knowing in advance. pgAdmin gets a fuller step-by-step just below, and ODBC consumers have a section of their own.

DBeaver  —  Connect to a database
MainPostgreSQLSSL
Server Host
<your-database-host>
Port
5432
Database
postgres
Authentication
Database Native
Username
<user>
Password
••••••••••••
ConnectedTest ConnectionFinish
DBeaver → Database → New Database Connection → PostgreSQL. Fill the Main tab as above; on the SSL tab tick Use SSL and set SSL mode to require. All values come from the console’s SQL access panel.
connect with your client
# One line - paste the values from the console's SQL access panel:
psql "host=<your-database-host> port=5432 dbname=postgres \
      user=<user> password=<password> sslmode=require"

# Gotcha: \copy (and the COPY protocol generally) is not supported yet.
# Bulk-load with a multi-row INSERT ... VALUES (...), (...) instead,
# or use the HTTP ingest API. Everything else psql does day-to-day -
# queries, \d, \dt, \df, PREPARE/EXECUTE, transactions - works.

pgAdmin 4, step by step.

The tab above is the short version; this is the full register-server pass. Open the console's SQL access tab first - every value below comes from it, and the password is shown once, when it's generated. Copy it before you leave the page.

Register — Server×
GeneralConnectionParametersSSL
Host name/address
<your-database-host>
Port
5432
Maintenance database
postgres
Username
<user>
Password
••••••••••••
Save password?
CloseResetSave
pgAdmin 4 → right-click Servers → Register → Server. On the Connection tab enter the values above; on the SSL tab set SSL mode to Require. Everything comes from the console’s SQL access panel — copy the password when it is shown.
  1. Register the server. Right-click Servers in the object explorer → RegisterServer. On the General tab, give it any name you like.
  2. Connection tab. Host name/address: your database host from the SQL access tab - it looks like <tenant-ulid>.ap-south-1.db.originchain.ai. Port: 5432. Maintenance database: originchain, as the panel shows it - the field is cosmetic (see the note under connection details), and the browser tree shows a single database named postgres either way. Username and Password: paste from the panel; tick Save password if you want pgAdmin to keep it.
  3. SSL mode = Require. On the Parameters tab in current pgAdmin releases; older releases put it on a dedicated SSL tab next to Connection. There is no authentication setting to pick - pgAdmin negotiates SCRAM-SHA-256 automatically.
  4. Save. The object browser and the Query Tool are the supported surfaces. The Dashboard panels read PostgreSQL's statistics tables (pg_stat_activity and friends), which this adapter does not serve - expect empty panels there, not data.
connection timed out?

That's the IP Access List, not pgAdmin. The SQL port is reachable only from addresses on your instance's list, and an empty list means the port stays closed - every connection attempt times out. Add the address you connect from (console → your instance → Network access) and retry.

Sessions running under a database-user identity - which is what the SQL access tab issues - are read-only: every query is filtered by row-level security and column masking for that user, exactly as the HTTP API, and write statements are refused with SQLSTATE 0A000. Writes go through the HTTP SQL endpoint - the full story is under the limits section below.

ODBC (psqlODBC).

The standard PostgreSQL ODBC driver (psqlODBC) works - it speaks the same wire protocol as everything above. Install it, pick the Unicode variant, and map the DSN fields to the same values from the console's SQL access tab:

Driver     PostgreSQL Unicode     # psqlODBC - the stock PostgreSQL ODBC driver
Server     <your-database-host>   # looks like <tenant-ulid>.ap-south-1.db.originchain.ai
Port       5432
Database   originchain            # cosmetic - see the note under connection details
User Name  <user>                 # console -> your instance -> SQL access
Password   <password>             # shown once, when it's generated - copy it then
SSL Mode   require

Or as one connection string, for anything that takes a DSN-less connection:

Driver={PostgreSQL Unicode};Server=<tenant-ulid>.ap-south-1.db.originchain.ai;Port=5432;Database=originchain;Uid=<user>;Pwd=<password>;SSLmode=require;
excel, power bi, and friends: read-only

ODBC consumers connect under the database-user credential from the SQL access tab, and those sessions are read-only. Refreshing a workbook or report works, and every query is filtered by row-level security and column masking for that user - a report shows exactly what its user is allowed to see. Anything that tries to write back over the connection is refused with SQLSTATE 0A000; writes go through the HTTP SQL endpoint.

First connection timing out? Same cause as pgAdmin above - the IP Access List. Add your address under Network access first.

SQL compatibility.

The honest matrix. Works over wire means your SQL client runs it directly (and the HTTP SQL endpoint runs it too). API only means the capability exists, but through the HTTP API rather than your SQL client. Not yet means exactly that - we'd rather tell you here than have you find out in production. One caveat spans every row: write statements over the wire apply to a single-node instance without row or column controls. A session running under a database-user identity, and any replicated configuration, gets a read-only wire - see the limits below.

Capability Status Notes
SELECT works over wire Simple and extended protocol, text and binary result formats. Typed columns come back with their real PostgreSQL types (NUMERIC, TIMESTAMPTZ, DATE, UUID, BYTEA, JSON, 1-D arrays, ...).
INSERT / UPDATE / DELETE works over wire Including RETURNING and INSERT ... ON CONFLICT. Constraint failures surface real SQLSTATEs (23505, 23502, 23503, ...), so driver error handling works unchanged.
transactions works over wire BEGIN / COMMIT / ROLLBACK, plus real savepoints (SAVEPOINT / ROLLBACK TO / RELEASE). Isolation is READ COMMITTED - see the limits below for what happens if you ask for more.
prepared statements works over wire Both kinds: the protocol-level flow every driver uses (Parse/Bind/Execute, text and binary parameters for the common scalar types) and SQL-level PREPARE / EXECUTE / DEALLOCATE.
stored procedures works over wire CREATE PROCEDURE / CREATE FUNCTION, CALL (including row-returning bodies), DROP PROCEDURE / FUNCTION. Routines are shared with the HTTP API - create on one surface, call from the other.
views API only CREATE VIEW and queries against views run over the HTTP SQL endpoint. Over the wire, CREATE VIEW is refused and a view's name doesn't resolve yet.
materialized views API only Plain CREATE MATERIALIZED VIEW name AS select works over the HTTP SQL endpoint and installs a real materialized view (OR REPLACE and WITH NO DATA are refused); the dedicated flow drives the same engine. Over the wire it is refused - see the limits below.
triggers not yet No trigger surface exists on either the wire or the HTTP API. CREATE TRIGGER is refused everywhere; there is no partial or emulated version to be surprised by.

DDL over the wire, for completeness: CREATE TABLE and DROP TABLE are real (the drop cascades through rows and indexes, same as the API path). CREATE INDEX, CREATE SEQUENCE and ALTER TABLE are API-only for now. WITH (CTEs) is refused over the wire. COPY (both directions) is not supported yet on any client.

Limits, stated plainly.

SERIALIZABLE is refused, not faked.

Wire connections run at READ COMMITTED. If you ask for more - SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, BEGIN ISOLATION LEVEL REPEATABLE READ, or the equivalent session default - the server returns an error (SQLSTATE 0A000) naming the level it can't deliver. It never acknowledges the request and quietly gives you READ COMMITTED anyway. That's deliberate: a database that says yes and delivers less is lying to your correctness logic - write-skew protection you believe you have but don't is worse than an error at connection time. Levels at or below READ COMMITTED are accepted as-is, so drivers that set read-committed on connect work unchanged. Serializable transactions are available - through the HTTP transactions API, on single-node configurations.

Materialized-view DDL lives on the HTTP endpoint, not the wire.

Plain CREATE MATERIALIZED VIEW name AS select works over the HTTP SQL endpoint - it is populated at creation, and lands in the same refresh and inspection flow as views defined through the materialized views reference. Two forms are refused rather than half-honoured: OR REPLACE (drop, then create) and WITH NO DATA. Over the wire, CREATE MATERIALIZED VIEW is refused.

Row and column controls come with an identity - and a read-only wire.

Where column masks or row-security policies exist, the wire never serves data without knowing who is asking: enabling SQL access on an instance that carries them requires database-user credentials, and a listener that cannot resolve one refuses to serve those objects rather than read them in the clear. When a session does run under a database-user identity, every SELECT is filtered and masked for that user, per session, exactly as the HTTP API - and the session is read-only: every write verb (INSERT / UPDATE / DELETE, CREATE / DROP / ALTER / TRUNCATE, CALL, GRANT / REVOKE) is refused with SQLSTATE 0A000 and points you at the HTTP SQL endpoint for the write. Replicated configurations get the same read-only wire regardless of identity - an inline wire write would bypass the replication path.

Multi-node configurations refuse what they can't guarantee.

The same honesty rule applies across configurations: on a sharded or replicated setup, surfaces that can't uphold their guarantee are refused with a clear error rather than served with silently weaker semantics. Concretely: serializable API transactions are single-node only - a sharded configuration refuses to open one - and on replicated setups they are further restricted to point reads. If a request succeeds, its stated guarantee holds; if we can't hold it, you get an error you can code against.