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

# Connect with a database client

> Query MoleSignal from DBeaver, JDBC, and ADBC over Arrow Flight SQL.

MoleSignal exposes an **Arrow Flight SQL** endpoint so standard database tools can connect
directly and run read-only SQL against organization telemetry — no HTTP glue code required. Results
travel as Arrow record batches, which is significantly faster than JSON for large result sets.

<Note>
  Flight SQL is a gRPC-based protocol. Tools that only speak the PostgreSQL or MySQL wire
  protocol (`psql`, `mysql` CLI, Navicat) cannot connect. Use DBeaver, the Arrow Flight SQL
  JDBC driver, or any ADBC client instead.
</Note>

## Enable the endpoint

The listener is **disabled by default**. Enable the listener in `config.toml` and restart:

```toml theme={null}
[flight_sql]
enabled = true
bind = "0.0.0.0"
port = 5083
# Default time window when the SQL carries no pruning hint (see below)
default_lookback_hours = 24
```

The Flight SQL port is separate from the internal gRPC port (5082). Only expose 5083 to
client networks; keep 5082 inside the cluster. For TLS, terminate at a gRPC-aware ingress.

## Authentication

Flight SQL plugs into MoleSignal's existing auth system. Two credential styles are accepted
in the standard basic-auth handshake:

|                   | Username               | Password         | Best for                          |
| ----------------- | ---------------------- | ---------------- | --------------------------------- |
| **Account login** | account email          | account password | interactive use (DBeaver, ad-hoc) |
| **API token**     | anything (use `token`) | `ms_...` token   | automation, scripts, BI services  |

Account login follows the web UI authentication flow and issues a short-lived session token (JWT).
API token authentication uses the supplied token directly. Clients that send a bearer header
instead of basic auth are also accepted. Both methods scope access to one organization and expose
only that organization's streams and data.

**Choosing an organization** (multi-org accounts): the default matches web login and selects the
first organization. To select another organization, append `@<org>` to the username, such as
`alice@example.com@acme`, where `acme` is the organization name, slug, or id.

<Warning>
  Database clients persist passwords in connection profiles, JDBC URLs, and scripts — a much
  larger exposure surface than a scoped token. **Use account passwords only for interactive
  sessions. Always use an `ms_` API token for automation**. An API token is revocable, can carry
  an expiry, and is limited to one organization. Create a token under **Settings → API Tokens** or via
  [`POST /api/v1/auth/tokens`](/en-US/api/auth/issue-token).
</Warning>

Two more things to know:

* **SSO accounts**: OIDC/SAML-only accounts have no local password, so account login cannot work.
  Use an API token instead.
* **Session expiry**: the JWT issued by account login expires after the server's
  `token_ttl_secs`. Requests then fail with `UNAUTHENTICATED`; DBeaver silently reconnects with
  saved credentials, so interactive use is unaffected. Long-running ADBC scripts should
  use a non-expiring API token instead.

## DBeaver

DBeaver Community does not bundle a Flight SQL driver — register the Arrow Flight SQL JDBC
driver once (about a minute):

1. **Database → Driver Manager → New**
2. On the **Libraries** tab, click **Add Artifact** and paste
   `org.apache.arrow:flight-sql-jdbc-driver:RELEASE`, then **Download/Update**
   (or **Add File** with a locally downloaded driver jar)
3. Back on **Settings**: Driver Name `Arrow Flight SQL`, Class Name
   `org.apache.arrow.driver.jdbc.ArrowFlightJdbcDriver`, URL Template
   `jdbc:arrow-flight-sql://{host}:{port}/?useEncryption=false`
4. **New Connection** → select the newly created driver → Host: MoleSignal server, Port: `5083`
5. Username: account email (optionally `email@org`), Password: account password — or
   Username `token` / Password `ms_...`

The navigator shows one catalog (`molesignal`), four schemas (`logs`, `metrics`, `traces`,
`extend`), and the active organization's streams as tables.

## JDBC

```text theme={null}
jdbc:arrow-flight-sql://molesignal.example.com:5083/?useEncryption=false&user=token&password=ms_...
```

Driver artifact: `org.apache.arrow:flight-sql-jdbc-driver`.

## Python (ADBC)

```python theme={null}
import adbc_driver_flightsql.dbapi as flightsql

conn = flightsql.connect(
    "grpc://molesignal.example.com:5083",
    db_kwargs={"username": "token", "password": "ms_..."},
)
cur = conn.cursor()
cur.execute("SELECT level, count(*) AS n FROM logs.nginx GROUP BY level")
print(cur.fetch_arrow_table())   # or fetchall() / .fetch_df()
```

## Writing queries

* **Qualify tables with the stream type**: `logs.nginx`, `metrics.cpu_usage`,
  `traces.checkout`, `extend.lookup_table`. An unqualified name defaults to `logs`. Fully
  qualified names including the catalog (`molesignal.logs.nginx` — the form generated by DBeaver
  during table browsing) work too.
* **Read-only**: `INSERT` / `UPDATE` / `DELETE` / DDL are rejected.
* **Time window**: Flight SQL has no time-range parameter, so the server scans the last
  `default_lookback_hours` (24h by default) for partition pruning. A `_timestamp` filter in
  the `WHERE` clause still applies within that window. To query further back, raise
  `default_lookback_hours`, or use the [HTTP query API](/en-US/api/query/execute) which takes
  an explicit time range.
* `_timestamp` is returned as a microsecond-precision timestamp column.

## Limitations

* Prepared statements work, but **parameter binding does not** — inline literals instead.
* No transactions (read-only engine).
* PromQL is not available over Flight SQL; use the HTTP API for PromQL.
* Result schema in `FlightInfo` is empty; clients read the schema from the data stream
  (DBeaver and ADBC handle this transparently).

Running Flight SQL queries appear in `GET /api/v1/query/running` and can be cancelled with
`POST /api/v1/query/{id}/cancel`, like any HTTP query.
