Skip to main content

Sources

Docs: Flight SQL · Provider Pool · API tokens Web App: Protection → Access Tokens in your Workspace. This guide takes you from no access to a first query result against the data your Providers sync into Parable. You create a token in your Workspace, connect DBeaver or Python to Parable’s SQL endpoint, and query the Provider Pools with read-only SQL. You need:
  • a Workspace with at least one connected Provider;
  • a Workspace Administrator who can give you a role;
  • DBeaver, or Python 3.10 or later.
Every connection uses these values:

1. Get the Provider Pools Reader role

Ask a Workspace Administrator to give you the Provider Pools Reader role, described as “Query the Provider Pools over SQL”. It lets you query the Provider Pools over SQL, and nothing else. You find tables with SQL (step 7). The administrator:
  1. Opens People → Users.
  2. Opens the actions on your row and chooses Edit Roles.
  3. Selects Provider Pools Reader and chooses Save.
The Data Access and Workspace Administrator roles also let you query, and they reach the Workspace’s other pools too. A member who holds only Viewer cannot query. The same roles decide SQL that runs inside your Workspace and names no Parable, such as SQL Ponder runs for you outside a Parable: Provider Pools Reader reads the Provider Pools, Data Access and Workspace Administrator read every pool, and Viewer alone reads nothing. You do not need Viewer beside the data role for that SQL to run. SQL inside a Parable, such as a Plot’s Preview or Preview Report, follows the Parable’s rule instead: it needs a seat on the Parable and a role that opens Parables, which Provider Pools Reader is not, and it reads the Parable’s Plots; only someone who can edit the Parable’s Plots reads every pool there.

2. Create a SQL token

  1. Sign in to your Workspace and open Protection → Access Tokens. Its address is https://<workspace-slug>.parable.work/platform/protection/access-tokens. A Provider Pools Reader or a Data Access member lands there when they open the Workspace.
  2. In Your tokens, choose Create token.
  3. Under Use it for, keep SQL. The other choice, MCP, creates a token for an MCP host; SQL refuses it.
  4. Enter a Name that says where you will use it, such as DBeaver on my laptop.
  5. Under Expires in, choose 30 days, 90 days, 180 days, or 1 year. The default is 90 days.
  6. Choose Create token.
  7. Copy the token and store it in your password manager. Parable shows it once and cannot show it again. Then choose I have saved it.
The token:
  • works only with SQL, and only in the Workspace where you created it;
  • runs each query with your roles at that moment, so it stops working when your role or your membership is removed;
  • stops working when it expires or is revoked. After a revocation or a removed role, SQL can keep answering for up to 30 seconds.
To revoke a token, open Protection → Access Tokens, open the token’s actions in Your tokens, and choose Revoke token. Workspace Administrators see every member’s token under Members’ tokens and can revoke any of them. People who manage the Workspace’s sign-in can turn tokens off; while they are off, every token is refused and nobody can create one. Treat the token like a password. Create one token for each tool or script, so you can revoke one without breaking the others.

3. Find your Workspace slug

The slug is the first part of your Workspace’s web address. For https://acme.parable.work, the slug is acme. Your SQL tool sends it as x-tenant on every call. A token works only with the slug of the Workspace that created it.

4. Connect DBeaver

DBeaver connects through the Apache Arrow Flight SQL JDBC driver. Other JDBC tools, such as DataGrip, use the same driver, class, URL, and properties.

Run DBeaver on Java 21

Recent DBeaver releases run on Java 25. The driver does not support Java 25, and on it Test Connection fails with ExceptionInInitializerError and Could not initialize class org.apache.arrow.memory.RootAllocator. Point DBeaver at Java 21 before you add the driver:
  1. Install Java 21, for example Eclipse Temurin 21 from Adoptium, or run brew install openjdk@21 on macOS.
  2. Quit DBeaver.
  3. Open dbeaver.ini in a text editor. It is in the DBeaver installation:
  4. Find the line that reads -vm. Replace the line below it with the path to Java 21’s java program (javaw.exe on Windows). If the file has no -vm line, add -vm and the path as two lines at the top of the file. Both lines must come before -vmargs. With Homebrew on macOS, this command prints the path:
  5. On the line after -vmargs, add --add-opens=java.base/java.nio=ALL-UNNAMED if the file does not already have it.
  6. Save the file and start DBeaver.
The start of the file then looks like this, with your own Java path:
dbeaver.ini
A DBeaver upgrade replaces dbeaver.ini, so repeat these steps after each upgrade.

Add the driver

  1. Download the flight-sql-jdbc-driver jar, version 18 or 19, from Maven Central.
  2. In DBeaver, open Database → Driver Manager and choose New.
  3. On Settings, enter:
  4. On Libraries, choose Add File and pick the jar. If DBeaver offers a list of driver classes, choose org.apache.arrow.driver.jdbc.ArrowFlightJdbcDriver.
  5. Choose OK.

Create the connection

  1. Choose Database → New Database Connection, pick Arrow Flight SQL, and choose Next.
  2. Set Host to sql.parable.work and Port to 443. Leave Username and Password empty.
  3. Open Driver properties. Right-click in the list, choose Add new property, and add these two properties:
  4. Choose Test Connection. DBeaver reports that it is connected.
  5. Choose Finish.
The driver uses TLS by default. Do not set useEncryption=false.

5. Connect with Python

Install the ADBC Flight SQL driver and PyArrow:
Put your token and Workspace slug in environment variables, so the token stays out of your code:
Save this script as first_query.py:
first_query.py
Run it:
It prints the address of every Provider table you can query, then the first 10 rows of the first one. grpc+tls:// connects with TLS. ADBC requires header names in lowercase, so write x-tenant exactly as shown. autocommit=True tells the driver not to open a transaction, since SQL access is read-only and has none.

6. Run a first query

Every Provider table has a three-part address:
{connector} is the Provider’s technical name, such as google or github, and {table} is one of its tables, such as users. There is no USE statement, so always write the full address. In DBeaver, select the connection and open SQL Editor → New SQL script. In Python, pass the SQL to cursor.execute. Run:
Replace <connector> and <table> with a table you can query, for example providers.google.users. DBeaver’s Database Navigator lists them under the providers catalog, and the Python script above prints them. A table can exist before its Provider’s first sync writes rows. An empty result, or the error No data has been written for this table yet, means the table has no data yet, not that your connection is wrong.

7. Find tables and columns

List a Provider’s tables and their columns with SQL. A table’s address, such as providers.google.users, is its catalog, schema and name:
To find which tables hold some kind of data, search by meaning with search_available_data. To find the records themselves, search with search_everything. Discover tables and columns covers the other discovery calls.

What you can query

The Provider Pools Reader role reaches three catalogs: The Workspace’s other pools, workspace, artifacts, and parables, need the Data Access role. With Provider Pools Reader, a query that names them fails with Query references an unknown relation. Within these catalogs, the Workspace’s Provider Policies decide which rows of each Provider table your roles read. A table hidden from your roles reads as empty, and its quarantine and quality tables follow it. If your roles hold All data access, as Workspace Administrator does, you read every row, and each query is recorded in the Workspace’s audit events.

System columns

Every table in the providers catalog has these columns beside the Provider’s own fields: A row is written only when a load changes it, so WHERE dt = '<day>' returns the rows that changed that day, not the whole table. To read current records, read the whole table and filter on the state columns:
Read row state explains these columns in more detail.

Limits

  • Read-only. Only SELECT statements run. Any other statement fails with Only read-only SELECT queries are supported. There are no transactions.
  • Plain EXPLAIN. EXPLAIN followed by a SELECT returns the query’s plan and runs nothing: one logical_plan row and one physical_plan row. The physical plan names each step, its partitions and its keys. It shows no storage path and no filter condition, because a filter can hold a data policy. EXPLAIN ANALYZE runs the query, so it fails with error code QL-SQ-008. EXPLAIN VERBOSE and the other forms fail with QL-SQ-009.
  • One hour per query. The hour covers planning and the whole result, including the time your tool spends reading it. A longer query fails with DEADLINE_EXCEEDED, error code QL-TO-002, and query <id> exceeded timeout of 3600s. Set your tool’s own timeout to at least an hour if you run long queries.
  • 2,000,000 rows per result. A query whose result has more rows fails with RESOURCE_EXHAUSTED and error code QL-SQ-005; nothing is cut off silently. The error can arrive after some rows, so discard any rows your tool read before it. Add LIMIT, filter with WHERE, or aggregate in SQL. To read more rows than that, run one query per range of a column, such as one month at a time.
  • Paid AI calls. One query may send up to 1,000,000 calls of ponder(), embed() and the Jev functions, and spend up to $1,000 on them. A call that would pass a limit is not sent, and the query fails with RESOURCE_EXHAUSTED and error code QL-SQ-010 (calls) or QL-SQ-011 (cost). Call the function over fewer rows, or publish the SQL as a Plot. See the AI call limits.
  • Shared memory. Queries that run at the same time can share memory and temporary disk. A query that asks for more than is left fails with RESOURCE_EXHAUSTED and error code QL-IN-009, whether its own size or the queries beside it used the space. Provider tables are partitioned by dt, the day a load wrote the row, so a WHERE dt bound skips the files of other days. Grouping, DISTINCT, joins, and sorts over every day of a large table need the most memory: bound dt first, and run large queries one at a time rather than together.
  • 600 requests a minute from one IP address. A query takes at least two requests, and DBeaver sends more while you browse. Requests over the limit are refused with HTTP status 429, which most tools report as UNAVAILABLE.
  • The Provider Pools only. The Provider Pools Reader role reaches the three catalogs above and nothing else.
  • One Workspace per token. To query another Workspace, create a token there.

ODBC tools

Parable has no ODBC driver. Tools that need one, such as Power BI and Tableau, are not supported. Use DBeaver, another JDBC tool, or Python.

Troubleshooting

Tools show an error as a gRPC status and a message, such as UNAUTHENTICATED: token expired, and each tool wraps them in its own words. Python ADBC, for example, reports PERMISSION_DENIED: insufficient permissions as UNAUTHORIZED: [FlightSQL] insufficient permissions (PermissionDenied; Prepare). Match on the message.