> For the complete documentation index, see [llms.txt](https://tyrix.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tyrix.gitbook.io/docs/script-resources/tyrix-frames/database.md).

# Database

Three tables are created automatically on first start. No manual import is needed — `schema.sql` ships as a reference copy for DBAs and hosts that require one, but the runtime executes an identical copy itself.

Watch for this on start:

```
[tyrix_frames] schema ready (v2)
[tyrix_frames] loaded 0 frame(s)
```

## Tables

| Table                         | Purpose                                                                                             |
| ----------------------------- | --------------------------------------------------------------------------------------------------- |
| `tyrix_frames`                | One row per placed canvas — owner, size, model variant, position, bucket, photo and its adjustment. |
| `tyrix_frames_gallery`        | Each player's saved photo collection.                                                               |
| `tyrix_frames_schema_version` | Single row tracking the applied migration version.                                                  |

### tyrix\_frames

| Column                     | Notes                                                                                                                                             |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                       | Primary key. This is the frame id shown in the admin panel and Discord logs.                                                                      |
| `owner`                    | `VARCHAR(64)`. The per-character identifier from the framework bridge — the ESX identifier, the QB/QBox citizenid, or a `license:` in standalone. |
| `size`                     | `VARCHAR(8)`, e.g. `16x20`.                                                                                                                       |
| `model`                    | The assigned prop variant, e.g. `tyrix_frame_16x20_c`. Stored so variant assignment survives a restart.                                           |
| `x` `y` `z` `rx` `ry` `rz` | Position and rotation.                                                                                                                            |
| `bucket`                   | Routing bucket. Indexed.                                                                                                                          |
| `photo_url`                | `VARCHAR(512)`, nullable.                                                                                                                         |
| `photo_transform`          | `JSON`, nullable — the move/scale/rotate adjustment.                                                                                              |
| `created_at` `updated_at`  | Timestamps, shown in the admin panel.                                                                                                             |

Indexed on `bucket` and `owner`.

### tyrix\_frames\_gallery

| Column                   | Notes                                                                  |
| ------------------------ | ---------------------------------------------------------------------- |
| `id`                     | Primary key.                                                           |
| `owner`                  | Same identifier as above. Indexed.                                     |
| `url`                    | The photo. Unique per owner — the same player cannot save a duplicate. |
| `created_at` `last_used` | Ordering and reuse tracking.                                           |

The unique key is on `(owner, url(255))`, so two different players saving the same image is fine.

## Migrations

The resource pins a `SCHEMA_VERSION` internally and compares it against the row in `tyrix_frames_schema_version` on every start.

{% stepper %}
{% step %}

### Fresh install

The `CREATE TABLE` statements above are already current, so the version is written straight to the latest and no migration runs.
{% endstep %}

{% step %}

### Existing install behind the current version

Each migration from `current + 1` up to the target runs in order, then the version row is updated.
{% endstep %}
{% endstepper %}

This matters because `CREATE TABLE IF NOT EXISTS` does nothing to a table that already exists — a database from an older build has the table but not its newer columns or collations. The version row is what lets the resource know which of those changes it still owes you.

Migrations are written to be safe to re-run.

## Ownership and the owner column

`owner` is a **per-character** identifier on all three frameworks, so a player's canvases follow the character that placed them, not the account.

Standalone is the exception: with no character system it stores the account's `license:`. At 48 characters that fits the column comfortably — ESX already stores 46-character `char1:` values there.

Nothing parses the identifier. It is compared only against itself and passed as a bound parameter, so any format your framework produces is safe, including the colons.

## Deleting data

There is no built-in wipe command. If you need to clear canvases:

```sql
-- everything
TRUNCATE TABLE `tyrix_frames`;

-- one player's canvases
DELETE FROM `tyrix_frames` WHERE `owner` = 'char1:abcdef...';

-- one routing bucket
DELETE FROM `tyrix_frames` WHERE `bucket` = 5;
```

{% hint style="warning" %}
Restart the resource afterwards. The registry is held in memory and loaded once at start, so changing the table underneath a running server will not be reflected until it reloads.
{% endhint %}

Deleting from `tyrix_frames` does not touch `tyrix_frames_gallery` — a player's saved photos are independent of whether any canvas currently displays them.
