> ## Documentation Index
> Fetch the complete documentation index at: https://docs.parable.work/llms.txt
> Use this file to discover all available pages before exploring further.

# Flight SQL

> Connect directly to Parable's read-only Workspace data plane through Arrow Flight SQL.

Arrow Flight SQL is the protocol beneath Parable's SQL SDK experience. The
Workspace API authenticates and authorizes each gRPC request, then proxies the
stream to Query Layer without transforming Arrow payloads.

Start with [Query with SDKs](/protocols/sql/query-with-sdks) when you want a
language-specific client. Use this page when configuring an ADBC, JDBC, BI, or
custom Flight SQL client.

## Connection contract

| Setting                 | Value                                           |
| ----------------------- | ----------------------------------------------- |
| Endpoint                | The Workspace API host provided for SQL access. |
| Service path            | `/arrow.flight.protocol.FlightService/*`        |
| Authentication metadata | `authorization: Bearer <token>`                 |
| Workspace metadata      | `x-tenant: <workspace-slug>`                    |
| Workspace permission    | `tenant.view`                                   |

`x-tenant-slug` is accepted as an alias for the historical `x-tenant` protocol
key. Continue to call the product scope a Workspace in prose; do not rename the
wire key.

Authentication happens through bearer metadata. The Flight `Handshake` RPC is
not supported, so clients must send authorization metadata on calls rather than
depending on the handshake flow.

### Who runs your query

The Workspace API resolves your bearer to a person and forwards that identity
to Query Layer as `x-user-id` and `x-session-id`, signed with the Workspace
API's own short-lived service token. Your bearer never leaves the Workspace
API. Every read of a Provider table is evaluated for that person's Policies,
so a query that reaches Query Layer with no person attached is refused with
`UNAUTHENTICATED` and error code `QL-TN-006` (`Source access requires a
verified principal`) rather than served unfiltered.

Only first-party services connect to Query Layer directly, and each presents a
service token bound to its own identity on the `x-parable-service-token`
metadata key. A direct connection that forwards `x-user-id` without a valid
Workspace API token is refused with `UNAUTHENTICATED` (`QL-TN-003`); a token
bound to another service is refused with `PERMISSION_DENIED` (`QL-TN-004`).

The scheduled-query runner (`query-runner`) is the one caller with a rollout
exception. Its two actions, `parable.plan_query.v1` and
`parable.publish_catalog.v1`, are bound to a `query-runner` token, and a token
bound to any other service is refused on them. While the Query Layer's
`QUERY_LAYER_QUERY_RUNNER_TOKEN_REQUIRED` switch is off (its default) those two
actions are also admitted with no token at all, each such call logging a
warning that names the action, so the runner and the Query Layer can deploy in
either order. With the switch on, an anonymous runner action is
`UNAUTHENTICATED` (`QL-TN-003`) like every other anonymous bound action. The
[Query Layer runbook](/runbooks/query-layer-ide#query-runner-identity) has the
flip procedure.

<Info>
  SQL access and its endpoint are provisioned per Workspace. Contact your
  Parable representative when a Workspace does not have access yet.
</Info>

## Connect with ADBC

```python theme={null}
import os

import adbc_driver_flightsql.dbapi
from adbc_driver_flightsql import DatabaseOptions

connection = adbc_driver_flightsql.dbapi.connect(
    os.environ["PARABLE_FLIGHT_URL"],
    db_kwargs={
        DatabaseOptions.AUTHORIZATION_HEADER.value:
            f"Bearer {os.environ['PARABLE_API_TOKEN']}",
        f"{DatabaseOptions.RPC_CALL_HEADER_PREFIX.value}x-tenant":
            os.environ["PARABLE_WORKSPACE"],
    },
)

cursor = connection.cursor()
cursor.execute("SELECT * FROM workspace.users LIMIT 10")
print(cursor.fetch_arrow_table())
```

Production endpoints use TLS. Local and in-cluster development endpoints can
use cleartext HTTP/2 when their environment explicitly exposes it.

## Request lifecycle

For a statement query:

1. `GetFlightInfo` validates and plans the SQL, then returns an opaque ticket.
2. `DoGet` executes from that ticket and streams Arrow record batches.
3. The client releases the result stream when it has consumed or abandoned it.

Prepared statements follow the same read path with a server-issued handle. See
[supported operations](/protocols/sql/sql-behavior/supported-operations) for
the complete command matrix.

## Metadata discovery

Flight SQL supports catalog, schema, table, table-type, SQL capability, and
logical key discovery. `GetTables` can include an Arrow IPC schema for every
matching table, including optional Parable semantic metadata.

[Discover tables and columns](/protocols/sql/data-catalog/discover-tables-and-columns)
shows how to use those operations.

## Errors and retries

Unsupported commands return gRPC `UNIMPLEMENTED`. Invalid authentication and
Workspace selection return gRPC authentication, permission, or argument
statuses rather than HTTP JSON errors.

When query concurrency is saturated, Query Layer can return
`RESOURCE_EXHAUSTED` with Parable error code `QL-IN-008`. A client can retry a
read-only query with bounded exponential backoff. Do not retry invalid SQL,
authentication failures, or permission failures without changing the request.
