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

# Graph

> blobhub.types.orientdb: run OrientDB SQL against a graph blob revision

`blobhub.types.orientdb.Graph` is the typed module for `blobhub.graph.orientdb` blobs. Each revision of such a blob
is its own OrientDB database, and `Graph` runs one OrientDB SQL statement at a time against it. That is the
module's whole surface.

```python theme={null}
import blobhub
from blobhub.types.orientdb import Graph

hub = blobhub.connect()
graph = Graph(hub.blob("acme", "knowledge").revision())    # or revision.typed()

graph.execute("CREATE VERTEX V SET name = 'fox'", write=True)
result = graph.execute("SELECT FROM V WHERE name = :name", {"name": "fox"})
for vertex in result.vertices:
    print(vertex["@rid"], vertex["@class"], vertex.get("name"))
```

`Graph(revision)` raises `TypeMismatch` when the revision's blob is not a graph blob.

## Execute

`graph.execute(statement, params=None, *, write=False)` runs one statement and returns a `GraphResult` with two
lists, `vertices` and `edges`. Each item is an OrientDB record as a `dict`, carrying its `@rid` and `@class`.

| | A read | A write |
| :- | :- | :- |
| How | `write=False`, the default | `write=True` |
| Sent to | the revision's [query channel](/sdk/blobs-and-revisions#the-data-channel) | the command channel |
| Statements | exactly one `SELECT`, `TRAVERSE` or `MATCH` | any statement |
| Revisions | a draft or a committed one | a draft only |

* **A read refuses anything else.** A statement that is not one `SELECT`, `TRAVERSE` or `MATCH` raises
  `CommandError` with `error` `mutating_command_in_query_mode`, before it reaches OrientDB. The message adds that
  `write=True` sends it through the command channel.
* **A write needs a draft.** A committed revision raises `Conflict` with `error` `revision_not_writable`.
* **`params` fills placeholders:** a `dict` for named ones (`:name`), a `list` for positional ones (`?`).
* **A statement returns at most 50 records**, with OrientDB's fetch plan `*:1`. Use `SKIP` and `LIMIT` in the
  statement to page through more.
* **An empty statement** raises `ValueError` before any request.

## Errors

When OrientDB refuses a statement, the message reads `OrientDB refused the statement: <reason>`, and the full detail
is in `error.details`.

| Error | When |
| :- | :- |
| `CommandError` `invalid_query` | OrientDB refused the statement. |
| `CommandError` `mutating_command_in_query_mode` | A read was not one `SELECT`, `TRAVERSE` or `MATCH`. |
| `Conflict` `revision_not_writable` | A write against a committed revision. |
| `ServerError` `graph_store_unavailable` | The revision's database could not be opened. |

A read is retried after a server error or a network failure; a write is retried only when it never reached the
platform, so a `CREATE VERTEX` that timed out is never sent twice. It may still have run once: check before you
repeat it. See [Errors and retries](/sdk/errors#why-a-write-is-not-retried).

## See also

* [Blob Types → Graph](/blob-types/introduction#graph) — the graph blob type.
* [Blobs and revisions](/sdk/blobs-and-revisions) — drafts, commits and the data channel.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.