Databases: PostgreSQL, MySQL, SQL Server, Oracle Database and MongoDB
How to connect your own databases for read-only questions. Each person signs in with their own database login, so the database's own grants decide what they see.
Status: in testing. Built against each database's documented behaviour, and tested against a real PostgreSQL and simulated MySQL, SQL Server, Oracle Database and MongoDB servers; not yet used with a customer's live database.
| Source | Kind | Covers |
|---|---|---|
| SQL database | database |
PostgreSQL (including Amazon RDS, Aurora, Azure and Cloud SQL), MySQL and MariaDB, SQL Server and Azure SQL, and Oracle Database 12.1 or later (including Oracle Autonomous Database and Amazon RDS for Oracle). The admin picks the engine. |
| MongoDB | mongodb |
MongoDB, including MongoDB Atlas. |
Everything here is read-only: propose_change refuses changes to database sources.
How sign-in works
Databases have no "Sign in with..." page, so each person types their own database username and password into a sign-in form served by SourceLace. There is no shared SourceLace login to your database.
- The sign-in link works once, for 10 minutes, and stops after three wrong passwords.
- SourceLace keeps the password encrypted with your organization's own key, uses it only for that person's requests, and never logs it, shows it, or puts it in the audit trail.
- If the password changes later, SourceLace asks the person to connect again.
1. For your database administrator
Give each person their own read-only login
Create one login per person, with read access only. A group role makes this easy to manage. Narrow it as far as you like (some schemas, tables or collections): SourceLace only ever sees what the person's login can see.
PostgreSQL
-- Once: a group that may read the tables people should see.
CREATE ROLE sourcelace_readers NOLOGIN;
GRANT CONNECT ON DATABASE sales TO sourcelace_readers;
GRANT USAGE ON SCHEMA public TO sourcelace_readers;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO sourcelace_readers;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO sourcelace_readers;
-- For each person:
CREATE ROLE ann_lee LOGIN PASSWORD 'a long password' IN ROLE sourcelace_readers;
ALTER ROLE ann_lee SET default_transaction_read_only = on;
Use hostssl (not host) lines in pg_hba.conf for these logins, so they can only connect over TLS.
MySQL and MariaDB
-- Once:
CREATE ROLE 'sourcelace_reader';
GRANT SELECT, SHOW VIEW ON sales.* TO 'sourcelace_reader';
-- For each person:
CREATE USER 'ann_lee'@'%' IDENTIFIED BY 'a long password' REQUIRE SSL;
GRANT 'sourcelace_reader' TO 'ann_lee'@'%';
SET DEFAULT ROLE 'sourcelace_reader' TO 'ann_lee'@'%';
SQL Server
CREATE LOGIN ann_lee WITH PASSWORD = 'a long password';
USE Sales;
CREATE USER ann_lee FOR LOGIN ann_lee;
ALTER ROLE db_datareader ADD MEMBER ann_lee;
On Azure SQL you can create the user in the database directly (CREATE USER ann_lee WITH PASSWORD = '...') and add it to db_datareader. SourceLace signs in with SQL logins (username and password); Microsoft Entra sign-in to the database is not supported yet.
Oracle Database
Oracle signs people in as database users, and a user's name is also its schema. Create one user per person and give them SELECT through a role:
-- Once: a role that may read the tables people should see.
CREATE ROLE sourcelace_reader;
GRANT SELECT ON sales.orders TO sourcelace_reader;
GRANT SELECT ON sales.customers TO sourcelace_reader;
-- (or, on Oracle 23ai, every table of a schema at once: GRANT SELECT ANY TABLE ON SCHEMA sales TO sourcelace_reader;)
-- For each person:
CREATE USER ann_lee IDENTIFIED BY "a long password";
GRANT CREATE SESSION TO ann_lee;
GRANT sourcelace_reader TO ann_lee;
Existing named users work as they are: SourceLace reads with whatever they can already see. Grant SELECT (or READ), not EXECUTE: a function that changes data inside its own transaction (PRAGMA AUTONOMOUS_TRANSACTION) could get round Oracle's read-only transaction, so only the database's grants stop that.
SourceLace connects with the database's service name, such as SALESPDB or sales.corvanta.com (SELECT sys_context('USERENV', 'SERVICE_NAME') FROM dual shows it); the older SID form is not supported. No Oracle Client software is needed, and Oracle Database 12.1 or later works.
MongoDB
use sales
db.createUser({ user: "ann_lee", pwd: passwordPrompt(), roles: [{ role: "read", db: "sales" }] })
On MongoDB Atlas: Database Access → Add New Database User, password authentication, with the built-in role read on the database (under Specific Privileges).
Let SourceLace in
SourceLace connects from its own servers to your database, so the database must:
- Have an address reachable from the internet, such as
db.corvanta.comor an RDS endpoint. SourceLace's cloud refuses private addresses (10.x, 172.16–31.x, 192.168.x, localhost), so that no organization can point it at another's internal systems. - Allow SourceLace's outbound IP addresses in its firewall or security group (AWS security group, Azure SQL firewall rule, Atlas Network Access → IP Access List), and nothing else from the internet. Ask support@sourcelace.com for the current list.
- Listen on the port your SourceLace admin enters (usually 5432, 3306, 1433, 1521 or 27017; an Oracle TLS listener is often on 2484, and Oracle Autonomous Database on 1522).
TLS (encryption)
Every connection is encrypted, and SourceLace checks the database's certificate and that it was issued for the host name your admin entered. Make sure:
- TLS is on in the database (
ssl = onin PostgreSQL,require_secure_transport = ONin MySQL, Force Encryption in SQL Server, aTCPSlistener endpoint in Oracle'slistener.ora,net.tls.mode: requireTLSin MongoDB). Managed services have it on already. For Oracle Autonomous Database, allow TLS connections without a wallet (mutual TLS not required), with SourceLace's IP addresses on its access control list. - The certificate is valid for the host name people connect to. If you use a different name (a CNAME), add it to the certificate.
- If the certificate was signed by a private certificate authority (Amazon RDS, some Azure servers, or your company's own CA), give your SourceLace admin that CA's certificate (a PEM file starting
-----BEGIN CERTIFICATE-----). For Amazon RDS this is the regional bundle from AWS's Using SSL/TLS to encrypt a connection page.
2. For your SourceLace admin
Add the source on Manage sources → Add a source.
SQL database options
Kind: SQL database (database).
| Option | Type | Default | Example | What it is |
|---|---|---|---|---|
engine |
One of postgres, mysql, sqlserver, oracle |
(required) | postgres |
The kind of database. MariaDB uses mysql; Azure SQL uses sqlserver; Oracle Database uses oracle. |
host |
Host name | (required) | db.corvanta.com |
The server's name only: no https://, no port. |
port |
Number | 5432, 3306, 1433 or 1521, by engine | 5433 |
The port. For Oracle, the port of the database's TLS listener (often 2484). |
database |
Text | (required) | sales |
The database to read. For Oracle, the service name, such as SALESPDB (not the SID). |
ca_cert |
PEM certificate | (none) | -----BEGIN CERTIFICATE----- ... |
The certificate of a private CA (see TLS above). It may be pasted on one line. |
tls |
verify or off |
verify |
verify |
off is accepted only for a database on the same computer as SourceLace, so in practice always verify. |
MongoDB options
Kind: MongoDB (mongodb).
| Option | Type | Default | Example | What it is |
|---|---|---|---|---|
host |
Host name | (required) | mongo.corvanta.com or cluster0.abcde.mongodb.net |
The server's name, or the Atlas cluster address. |
port |
Number | 27017 |
27018 |
The port (not used with srv). |
database |
Text | (required) | sales |
The database to read. |
auth_source |
Text | the database option |
admin |
The database where users are defined. |
srv |
true or false |
false |
true |
true for a mongodb+srv:// address, as MongoDB Atlas uses. |
ca_cert, tls |
As for SQL databases. |
Then each person clicks Connect and signs in on SourceLace's form with their own username and password.
3. What people can do, and how it stays read-only
- SQL databases take
sql: oneSELECT(orWITH ... SELECT) in the engine's own dialect, on tables namedschema.tableassearch_schemalists them (SELECT TOP 10 ...on SQL Server,FETCH FIRST 10 ROWS ONLYon Oracle,LIMIT 10elsewhere). On Oracle, a table name without a schema is looked up in the person's own schema, and names written without quotes are matched in upper case, as Oracle stores them.get_recordworks on tables with a single-column primary key. - MongoDB takes
mongodb: one JSON object, either a find, such as{"collection": "orders", "filter": {"status": "open"}, "sort": {"placed": -1}, "limit": 50}, or an aggregation pipeline, such as{"collection": "orders", "aggregate": [{"$match": {"status": "open"}}, {"$group": {"_id": "$region", "orders": {"$sum": 1}}}]}. Ids and dates use MongoDB Extended JSON, such as{"$oid": "..."}and{"$date": "2026-10-01T00:00:00Z"}.
Checked before anything is sent:
- SQL: a single statement starting with
SELECTorWITH; nothing that writes (INSERT,UPDATE,DELETE,MERGE,CREATE,DROP,ALTER,TRUNCATE,GRANT,SELECT ... INTO,COPY,EXEC,CALLand so on), nothing that locks rows (FOR UPDATE,FOR SHARE), no system procedures (xp_...,sp_...), and no functions that reach outside the query or change state (such aspg_sleep,pg_read_file,dblink,nextval,LOAD_FILE,OPENROWSET,WAITFOR). On Oracle, also no PL/SQL packages (DBMS_...,UTL_...such asUTL_HTTP,OWA_...,HTP), no URI types (such asHTTPURITYPE), nothing in theSYSschema, no database links (orders@other_db) and no functions defined inside the query (WITH FUNCTION). - MongoDB: only read stages (
$match,$project,$group,$sort,$limit,$skip,$unwind,$lookup,$facetand similar).$outand$merge(which write) are refused, and so are$where,$functionand$accumulator(which run code) anywhere in the query.system.collections are off limits.
Enforced on the database too:
| Database | Read-only | Time limit |
|---|---|---|
| PostgreSQL | A READ ONLY transaction, always rolled back |
statement_timeout |
| MySQL and MariaDB | START TRANSACTION READ ONLY, rolled back |
max_execution_time (MariaDB: max_statement_time) |
| SQL Server | A transaction that is always rolled back, with ApplicationIntent=ReadOnly. SQL Server has no read-only transaction, so the login's db_datareader role matters most. |
Query timeout |
| Oracle Database | SET TRANSACTION READ ONLY first, then the query, then always a rollback |
call_timeout on the connection |
| MongoDB | MongoDB has no read-only session, so the read role and the checks above do this work. Reads prefer a secondary. |
maxTimeMS |
Each query may run for 30 seconds and returns at most 2,000 rows to SourceLace, 50 shown at a time. Results stay in memory for 30 minutes and are never written to a database. Each request opens its own connection and closes it straight after. Schema comes from the database's own catalog (for Oracle, ALL_TABLES, ALL_VIEWS, ALL_TAB_COLUMNS and ALL_CONSTRAINTS, leaving out the schemas Oracle itself maintains), which lists only what the person can read; for MongoDB, describe_object samples 20 documents and reports field names and types only.
When something goes wrong
| What you see | What to do |
|---|---|
| "Set the option 'host': the database server's name, such as db.corvanta.com." (or 'database', 'engine') | Fill in that option. |
| "'...' is not a host name. Give only the name, such as db.corvanta.com." | Remove https://, the port, and any path. |
| "TLS can only be turned off for a database on the same computer as SourceLace (localhost)..." | Remove tls: off. |
| "The option 'ca_cert' must be a PEM certificate (-----BEGIN CERTIFICATE-----...)." | Paste the whole CA certificate, including the BEGIN and END lines. |
| "... is a private network address, and this SourceLace server only connects to databases on the internet..." | Use the database's public address and allow SourceLace's outbound IP addresses. |
| "... could not be reached. Check the host and port, and that the database allows connections from SourceLace's IP addresses." | Check host, port and the firewall allowlist. If it ends "(the database does not know that service name)", fix the Oracle database option: it must be the service name, not the SID. |
| "... could not be reached securely: its TLS certificate could not be checked. An admin can set the source's ca_cert option..." | Set ca_cert, or fix the certificate's host name. |
| "The database refused that username and password too many times. Ask for a new sign-in link to try again." | Connect again for a new link, and check the username and password with your DBA. |
| "This sign-in link has expired or was already used. Ask for a new one." | Click Connect again. |
| "... no longer accepts your database username or password." (or MongoDB) | The password changed or the login was removed. Connect again. |
| "... did not finish the query in time. Narrow it down and try again." | Add filters or a smaller limit. |
| "... refused the query: ..." | The database's own reason follows, such as a missing grant or an unknown column. |
| "There is no table or view ... that you can read. Call search_schema to find it." | Check the name (schema.table); the login may lack a grant. |
| "... has no single-column primary key. Use query with a WHERE clause instead." | Use query instead of get_record. |
| "'...' is not a collection you can read. Call search_schema to list them." | Check the collection name and the login's read role. |