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

# Lake Query

> Execute SQL queries against the oleander lake.

## `query(sql, options?)`

Execute a SQL query against the oleander lake using DuckDB. Returns structured results with columns, types, and rows. If the API rejects the query, the SDK raises instead of returning a failed result.

```python theme={null}
result = await client.query(
    "SELECT * FROM oleander.default.flowers LIMIT 10"
)

columns = result.results.columns       # ["sepal_length", "sepal_width", ...]
rows = result.results.rows             # [[5.1, 3.5, ...], ...]
count = result.row_count               # 10
elapsed = result.execution_time        # "42ms"
```

### Parameters

<ParamField body="sql" type="str" required>
  The SQL query to execute. Supports DuckDB SQL syntax.
</ParamField>

<ParamField body="options" type="QueryOptions">
  Optional query options. Pass a `QueryOptions` instance to configure behavior.
</ParamField>

<ParamField body="options.save" type="bool" default="False">
  When `True`, persists query results as a table. The table name is returned in `saved_table_name`.
</ParamField>

### Saving results

Use `QueryOptions(save=True)` to persist query results as a table for later use.

```python theme={null}
from oleander_sdk import QueryOptions

result = await client.query(
    "SELECT * FROM oleander.default.flowers LIMIT 10",
    QueryOptions(save=True)
)

if result.saved_table_name:
    follow_up = await client.query(
        f"SELECT avg(sepal_length) FROM {result.saved_table_name}"
    )
```

### Iterating over results

```python theme={null}
result = await client.query(
    "SELECT species, sepal_length FROM oleander.default.flowers LIMIT 10"
)

columns = result.results.columns
rows = result.results.rows
species_idx = columns.index("species")
sepal_length_idx = columns.index("sepal_length")

for row in rows:
    species = row[species_idx]
    sepal_length = row[sepal_length_idx]
    # process each record ...
```

### Return type: `LakeQueryResult`

| Field              | Type                 | Description                                              |
| ------------------ | -------------------- | -------------------------------------------------------- |
| `success`          | `bool`               | Whether the query executed successfully                  |
| `results`          | `QueryResultColumns` | Query results with `columns`, `column_types`, and `rows` |
| `row_count`        | `Optional[int]`      | Number of rows returned                                  |
| `execution_time`   | `Optional[str]`      | Query execution time (for example, `"42ms"`)             |
| `saved_table_name` | `Optional[str]`      | Table name if `save=True` was used                       |
| `query`            | `Optional[str]`      | The original SQL query                                   |
