SQL Recipes

SQL recipes for directly querying and managing the ORES Database Schema.

Initial Setup

These recipes must be run in order using the postgres superuser to bootstrap the ORES database infrastructure. Run each step once when setting up a new PostgreSQL server.

Step 1: Setup password for user postgres

If you have not yet added a password to postgres, login as that user and in psql:

alter user postgres password 'SECURE PASSWORD';

To generate a secure password:

pwgen -c 25 | head -n1
ohzo4cohmoof1Cai2Xaxohsie

Then add the secure password to your authinfo.gpg, e.g.:

machine localhost login postgres password ohzo4cohmoof1Cai2Xaxohsie

Step 2: Teardown (Clean Slate)

To make sure you do not have any remnants of a previous install, do:

\ir '$project_sql_dir'/teardown_all.sql
--- Step 1: Dropping test databases ---
No test databases found.
--- Step 2: Dropping instance databases ---
No db_list provided. Skipping instance database drops.
--- Step 3: Dropping ores_template ---
DROP DATABASE
--- Step 4: Dropping ores_admin ---
DROP DATABASE
--- Step 5: Dropping ores role ---
DROP ROLE

This will drop all ORES infrastructure databases (template, admin) and the ores role. To also drop instance databases, provide an explicit list:

-- First discover instances (if ores_admin exists):
-- \c ores_admin
-- SELECT * FROM admin_ores_instance_databases_view;

-- Then teardown with explicit list:
\set db_list 'ores_happy_penguin,ores_dancing_fox'
\ir '$project_sql_dir'/teardown_all.sql

Step 3: Install Extensions

Installs required PostgreSQL extensions (btree_gist, TimescaleDB). TimescaleDB must be installed on your system. For Debian, as root:

curl -s https://packagecloud.io/install/repositories/timescale/timescaledb/script.deb.sh | sudo bash
apt-get install postgresql-18-timescaledb

It then must be added to shared_preload_libraries in postgresql.conf:

shared_preload_libraries = 'timescaledb'

Restart PostgreSQL after modifying the config, then run:

\ir '$project_sql_dir'/setup_extensions.sql
CREATE EXTENSION
DO
extname	extversion
btree_gist	1.8
timescaledb	2.24.0

You may need to enable community edition if available. At present it's not available for Postgres 18 on Debian.

alter system set timescaledb.license = 'timescale';
select pg_reload_conf();
show timescaledb.license;

Step 4: Create ORES User

Creates the ores application user. Generate a secure password first:

pwgen -c 25 1

Then run the script with the password as a variable. From the command line:

psql -U postgres -v ores_password='YOUR_SECURE_PASSWORD' -f projects/ores.sql/setup_user.sql

Add the password to your authinfo.gpg:

machine localhost login ores password YOUR_SECURE_PASSWORD

Step 5: Create Admin Database

Creates ores_admin with cluster-level utilities (name generation, cleanup):

\ir '$project_sql_dir'/admin/setup_admin.sql
CREATE DATABASE
GRANT
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE VIEW
CREATE VIEW
CREATE VIEW
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
GRANT
GRANT
GRANT
ALTER DEFAULT PRIVILEGES
ALTER DEFAULT PRIVILEGES

If you need to drop to recreate:

drop database if exists ores_admin;
DROP DATABASE

Step 6: Create Template Database

Creates ores_template with the complete application schema. The template contains schema only (tables, indexes, triggers) - no data is pre-populated.

After creating a database instance, you can optionally seed data using the population scripts (see Population Scripts section).

\ir '$project_sql_dir'/setup_template.sql
CREATE DATABASE
GRANT
CREATE EXTENSION
DO
extname	extversion
btree_gist	1.8
timescaledb	2.24.0
CREATE SCHEMA
CREATE EXTENSION
GRANT
GRANT
SET
CREATE FUNCTION
SET
CREATE TABLE
CREATE INDEX
CREATE FUNCTION
CREATE TRIGGER
CREATE RULE
CREATE FUNCTION
CREATE TRIGGER
SET
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE FUNCTION
CREATE TRIGGER
CREATE FUNCTION
CREATE TRIGGER
SET
CREATE TABLE
CREATE INDEX
CREATE FUNCTION
CREATE TRIGGER
SET
CREATE FUNCTION
CREATE TRIGGER
SET
CREATE TABLE
CREATE INDEX
CREATE INDEX
SET
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
DO
SET
DO
CREATE FUNCTION
CREATE FUNCTION
SET
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
DO
SET
DO
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
SET
CREATE TABLE
CREATE INDEX
CREATE FUNCTION
CREATE TRIGGER
CREATE RULE
SET
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE FUNCTION
CREATE TRIGGER
CREATE RULE
SET
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE FUNCTION
CREATE TRIGGER
CREATE RULE
SET
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE FUNCTION
CREATE TRIGGER
CREATE RULE
SET
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
SET
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE FUNCTION
CREATE TRIGGER
CREATE RULE
SET
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE FUNCTION
CREATE TRIGGER
CREATE RULE
SET
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE FUNCTION
CREATE TRIGGER
CREATE RULE
SET
CREATE TABLE
CREATE INDEX
CREATE FUNCTION
CREATE TRIGGER
CREATE RULE
SET
CREATE TABLE
CREATE INDEX
CREATE FUNCTION
COMMENT
CREATE FUNCTION
COMMENT
GRANT
GRANT
ALTER DEFAULT PRIVILEGES
ALTER DEFAULT PRIVILEGES
UPDATE 1

If you need to drop to recreate:

update pg_database set datistemplate = false where datname = 'ores_template';
drop database if exists ores_template;
UPDATE 1
DROP DATABASE

Step 7: Create Database Instance

Creates a new database instance from the template. Run this each time you need a new database (development, testing, production, etc.).

With Auto-Generated Whimsical Name

\ir '$project_sql_dir'/create_instance.sql
CREATE DATABASE
name	enabled	description
database_created
ores_frosty_leaf

With Specific Name

psql -U postgres -v db_name='ores_frosty_leaf' -f projects/ores.sql/create_instance.sql

Recipes

Day-to-day recipes for querying and managing ORES databases. These use the ores application user.

Database Management

These recipes require the initial setup (Steps 1-3) to be completed first.

List All ORES Databases

List all databases created from the ORES template:

select * from admin_ores_databases_view;
database_name
ores_nameless_sea

List Test Databases

List databases created by automated tests (ores_test_*, oresdb_test_*):

select * from admin_test_databases_view;
database_name

List Instance Databases

List instance databases only (excludes test and template):

select * from ores_instance_databases;
database_name
ores_dark_wildflower

Delete All Test Databases

Delete all test databases. Uses \gexec because DROP DATABASE cannot run inside a transaction block:

select format('DROP DATABASE IF EXISTS %I;', database_name)
from test_databases \gexec

Delete All ORES Databases

WARNING: This deletes ALL ORES databases (instances, templates, test). Use with caution!

select format('DROP DATABASE IF EXISTS %I;', database_name)
from admin_ores_databases_view \gexec
DROP DATABASE

Delete All Instance Databases

Delete all instance databases (preserves templates and test databases):

select format('DROP DATABASE IF EXISTS %I;', database_name)
from admin_ores_instance_databases_view \gexec
DROP DATABASE

Preview Cleanup SQL

Generate cleanup SQL without executing (for review):

select generate_cleanup_test_databases_sql();
generate_cleanup_test_databases_sql
-- No test databases found to clean up.

Generate Whimsical Database Name

Generate a unique whimsical name for a new database:

select admin_generate_unique_database_name_from_server_fn();
admin_generate_unique_database_name_from_server_fn
ores_little_morning

Accounts

List All Current Accounts

Get all currently active accounts (where valid_to is infinity):

select id, username, email, version, valid_from
from ores.accounts
where valid_to = '9999-12-31 23:59:59'::timestamptz
order by username;
id	username	email	version	valid_from

List All Account Versions

View the complete temporal history of an account:

select id, username, email, version, valid_from, valid_to
from ores.accounts
where username = 'admin'
order by valid_from;
id	username	email	version	valid_from	valid_to

Get Account by Username

select id, username, email, version, valid_from
from ores.accounts
where username = 'admin'
  and valid_to = '9999-12-31 23:59:59'::timestamptz;
id	username	email	version	valid_from

Get Account by UUID

select id, username, email, version, valid_from
from ores.accounts
where id = 'your-uuid-here'
  and valid_to = '9999-12-31 23:59:59'::timestamptz;

Count Active Accounts

select count(*) as active_accounts
from ores.accounts
where valid_to = '9999-12-31 23:59:59'::timestamptz;

Login Info

List All Login Info

View login tracking for all accounts:

select li.account_id, a.username, li.last_login, li.failed_logins,
       li.locked, li.online, li.last_ip
from ores.login_info li
join ores.accounts a on a.id = li.account_id
  and a.valid_to = '9999-12-31 23:59:59'::timestamptz
order by li.last_login desc nulls last;

Find Locked Accounts

select li.account_id, a.username, li.failed_logins, li.last_attempt_ip
from ores.login_info li
join ores.accounts a on a.id = li.account_id
  and a.valid_to = '9999-12-31 23:59:59'::timestamptz
where li.locked = 1;

Find Online Users

select a.username, li.last_login, li.last_ip
from ores.login_info li
join ores.accounts a on a.id = li.account_id
  and a.valid_to = '9999-12-31 23:59:59'::timestamptz
where li.online = 1;

Sessions

List Recent Sessions

select s.id, a.username, s.start_time, s.end_time,
       s.client_ip, s.country_code, s.city
from ores.sessions s
join ores.accounts a on a.id = s.account_id
  and a.valid_to = '9999-12-31 23:59:59'::timestamptz
order by s.start_time desc
limit 20;

Session Statistics by User

select a.username,
       count(*) as total_sessions,
       sum(s.bytes_sent) as total_bytes_sent,
       sum(s.bytes_received) as total_bytes_received
from ores.sessions s
join ores.accounts a on a.id = s.account_id
  and a.valid_to = '9999-12-31 23:59:59'::timestamptz
group by a.username
order by total_sessions desc;

Population Scripts

The database template contains schema only - no data is pre-populated. After creating a database instance, run these scripts to seed essential data:

-- RBAC and system flags (required for application to function)
\ir '$project_sql_dir'/populate/populate.sql

-- Reference data (optional - currencies, country flags, images)
\ir '$project_sql_dir'/populate/reference_data.sql
SET
CREATE FUNCTION
upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

upsert_permission

DROP FUNCTION
total_permissions
24
SET
CREATE FUNCTION
CREATE FUNCTION
upsert_role
d7aed9b2-4ff5-4c2c-9896-515b8e9495fc
upsert_role
3f4a4fec-7f8d-467d-aa8f-4a115beb31cf
upsert_role
c9ff75b9-e043-495f-8e5e-e33dfb4f768e
upsert_role
eb406e9b-dd1e-4b56-a243-e0e7aff713ea
upsert_role
4280845f-ce87-4c2e-9d83-bdf0ca9ab07a
upsert_role
a457bb0f-d5f0-4f05-978c-f0b5663747c8
assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

assign_permission_to_role

DROP FUNCTION
DROP FUNCTION
summary	count
Roles:	6
Role-Permission assignments:	21
SET
CREATE FUNCTION
upsert_system_flag

upsert_system_flag

upsert_system_flag

upsert_system_flag

DROP FUNCTION
name	enabled	description
system.bootstrap_mode	1	Indicates whether the system is in bootstrap mode (waiting for initial admin account).
system.disable_password_validation	0	When enabled, disables strict password validation. FOR TESTING/DEVELOPMENT ONLY.
system.signup_requires_authorization	0	Controls whether new signups require admin authorization. NOT YET IMPLEMENTED - enabling will cause signup to fail.
system.user_signups	0	Controls whether user self-registration is allowed.
entity	count
Permissions	24
Roles	6
System Flags	4
INSERT 0 1
CREATE FUNCTION
SET
load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

load_flag

SET
INSERT 0 158
SET
INSERT 0 158
entity	count
Currencies	158
Images	276
Tags	1

All scripts are idempotent and can be safely re-run.

View Seeded Permissions

List all permissions seeded by permissions_populate.sql:

select code, description
from ores.permissions
where valid_to = '9999-12-31 23:59:59'::timestamptz
order by code;

View Seeded Roles

List all roles seeded by roles_populate.sql:

select name, description
from ores.roles
where valid_to = '9999-12-31 23:59:59'::timestamptz
order by name;

View Role-Permission Assignments

List which permissions are assigned to each role:

select r.name as role_name, p.code as permission
from ores.role_permissions rp
join ores.roles r on r.id = rp.role_id
  and r.valid_to = '9999-12-31 23:59:59'::timestamptz
join ores.permissions p on p.id = rp.permission_id
  and p.valid_to = '9999-12-31 23:59:59'::timestamptz
where rp.valid_to = '9999-12-31 23:59:59'::timestamptz
order by r.name, p.code;

View Seeded System Flags

List all system flags seeded by system_flags_populate.sql:

select name, enabled, description
from ores.feature_flags
where name like 'system.%'
  and valid_to = '9999-12-31 23:59:59'::timestamptz
order by name;

Re-run All Population Scripts

To re-seed an existing database instance (idempotent - won't duplicate data):

-- System data (RBAC + system flags)
\ir '$project_sql_dir'/populate/populate.sql

-- Reference data (currencies, flags, images)
\ir '$project_sql_dir'/populate/reference_data.sql

Re-run Individual Population Scripts

To re-run only specific population scripts:

-- RBAC only
\ir '$project_sql_dir'/populate/permissions_populate.sql
\ir '$project_sql_dir'/populate/roles_populate.sql

-- System flags only
\ir '$project_sql_dir'/populate/system_flags_populate.sql

-- All reference data (currencies, flags, images)
\ir '$project_sql_dir'/populate/reference_data.sql

-- Or individual reference data scripts
\ir '$project_sql_dir'/populate/currencies_populate.sql
\ir '$project_sql_dir'/populate/load_flags.sql
\ir '$project_sql_dir'/populate/flags_populate.sql
\ir '$project_sql_dir'/populate/currency_images_populate.sql

RBAC (Roles and Permissions)

List All Roles

select id, name, description, version
from ores.roles
where valid_to = '9999-12-31 23:59:59'::timestamptz
order by name;
| id                                   | name       | description                                                   | version |
|--------------------------------------+------------+---------------------------------------------------------------+---------|
| dd2ecaec-138b-453c-a110-77441a60583e | Admin      | Full administrative access to all system functions            |       1 |
| b898350f-f704-4e97-b8ec-36c3481af052 | Operations | Operations - currency management and account viewing          |       1 |
| d48b608d-c894-4346-887d-228e342d36c6 | Sales      | Sales operations - read-only currency access                  |       1 |
| d533c93f-bf3c-4d1f-bba8-4e949b976a8a | Support    | Support - read-only access to all resources and admin screens |       1 |
| a74f8a4e-f331-4179-aecb-cda61e472805 | Trading    | Trading operations - currency read access                     |       1 |
| 6e4ee358-1970-400f-a3cb-fbcfe8296f52 | Viewer     | Viewer - basic read-only access to domain data                |       1 |

List All Permissions

select id, code, description
from ores.permissions
where valid_to = '9999-12-31 23:59:59'::timestamptz
order by code;
| id                                   | code                    | description                           |
|--------------------------------------+-------------------------+---------------------------------------|
| 8f827c95-2af4-4d78-9ccb-22f5d9f4df99 | *                       | Full access to all operations         |
| 9e337a58-2ee6-4de4-8946-76015de6e928 | accounts:create         | Create new user accounts              |
| 7151df18-e4c9-4522-bb65-c1055a3e97c1 | accounts:delete         | Delete user accounts                  |
| c225162e-2b04-4685-b1be-0bacbe367e45 | accounts:lock           | Lock user accounts                    |
| 4956001c-5ece-4dc8-b437-c834045c25eb | accounts:read           | View user account details             |
| 5f5f8909-3820-411f-a9f2-d5efb5ad351a | accounts:reset_password | Force password reset on user accounts |
| fc5587f3-72ad-4706-a1ac-ca735af5a919 | accounts:unlock         | Unlock user accounts                  |
| cf4ac1a8-b39e-4faa-b6d3-f9ed3d1ef41a | accounts:update         | Modify user account settings          |
| 43ce84fb-b14a-490a-92d1-4eade25eda37 | currencies:create       | Create new currencies                 |
| 7fb3f2e6-9b0d-4996-9c02-14e39a732acd | currencies:delete       | Delete currencies                     |
| 5472a25a-40cf-4bac-9c95-dda2589f12f7 | currencies:history      | View currency version history         |
| 17f8d400-47fa-4648-8b47-48ab3c1ec82b | currencies:read         | View currency details                 |
| e1bca8df-8133-4c08-9365-160baf99125e | currencies:update       | Modify currency settings              |
| 62e6e9ea-5258-41d2-9107-0602512801e6 | flags:create            | Create new feature flags              |
| 8e42e330-5467-48c2-9a26-5af5b5fcb10e | flags:delete            | Delete feature flags                  |
| 3b26954f-6368-4c12-b2e2-67797d442714 | flags:read              | View feature flag status              |
| 5f72cfef-c8a9-4926-a1a3-f51c955595f7 | flags:update            | Modify feature flag settings          |
| 12e8300a-e76c-4cd6-a439-2098e45393a2 | login_info:read         | View login history and info           |
| 95d69095-1223-4dbb-970e-8042d90d61de | roles:assign            | Assign roles to accounts              |
| 2301fe57-f568-4930-b3ec-4a9fba903932 | roles:create            | Create new roles                      |
| e12a56d4-64a8-436d-8ad8-1909b2439369 | roles:delete            | Delete roles                          |
| eba37c8c-79e2-4193-9a54-ceb555b1cdda | roles:read              | View role details                     |
| cd69a420-e93b-4e41-9bab-ee8d6dcd0b7a | roles:revoke            | Revoke roles from accounts            |
| af5743da-3042-469d-8487-ed859b9de7f5 | roles:update            | Modify role permissions               |

Get Permissions for a Role

select r.name as role_name, p.code as permission_code, p.description
from ores.role_permissions rp
join ores.roles r on r.id = rp.role_id
  and r.valid_to = '9999-12-31 23:59:59'::timestamptz
join ores.permissions p on p.id = rp.permission_id
  and p.valid_to = '9999-12-31 23:59:59'::timestamptz
where rp.valid_to = '9999-12-31 23:59:59'::timestamptz
  and r.name = 'Admin'
order by p.code;
| role_name | permission_code | description                   |
|-----------+-----------------+-------------------------------|
| Admin     | *               | Full access to all operations |

Get Roles for an Account

select a.username, r.name as role_name, ar.assigned_at, ar.assigned_by
from ores.account_roles ar
join ores.accounts a on a.id = ar.account_id
  and a.valid_to = '9999-12-31 23:59:59'::timestamptz
join ores.roles r on r.id = ar.role_id
  and r.valid_to = '9999-12-31 23:59:59'::timestamptz
where ar.valid_to = '9999-12-31 23:59:59'::timestamptz
  and a.username = 'admin'
order by r.name;
| username | role_name | assigned_at | assigned_by |
|----------+-----------+-------------+-------------|

Get All Permissions for an Account (via Roles)

select distinct a.username, p.code as permission_code
from ores.accounts a
join ores.account_roles ar on ar.account_id = a.id
  and ar.valid_to = '9999-12-31 23:59:59'::timestamptz
join ores.role_permissions rp on rp.role_id = ar.role_id
  and rp.valid_to = '9999-12-31 23:59:59'::timestamptz
join ores.permissions p on p.id = rp.permission_id
  and p.valid_to = '9999-12-31 23:59:59'::timestamptz
where a.valid_to = '9999-12-31 23:59:59'::timestamptz
  and a.username = 'admin'
order by p.code;
| username | permission_code |
|----------+-----------------|

Check if Account Has Permission

Uses the built-in RBAC function:

select ores.account_has_permission('admin', 'accounts:create') as has_permission;
|---|

Currencies

List All Currencies

select iso_code, name, symbol, numeric_code, currency_type
from ores.currencies
where valid_to = '9999-12-31 23:59:59'::timestamptz
order by iso_code
limit 10;
| iso_code | name                          | symbol | numeric_code | currency_type |
|----------+-------------------------------+--------+--------------+---------------|
| AED      | UAE Dirham                    | د.إ    |          784 | fiat          |
| AFN      | Afghan Afghani                | ؋      |          971 | fiat          |
| ALL      | Albanian Lek                  | L      |          008 | fiat          |
| AMD      | Armenian Dram                 | ֏     |          051 | fiat          |
| ANG      | Netherlands Antillean Guilder | ƒ      |          532 | fiat          |
| AOA      | Angolan Kwanza                | Kz     |          973 | fiat          |
| ARS      | Argentine Peso                | $      |          032 | fiat          |
| AUD      | Australian Dollar             | A$     |          036 | fiat          |
| AWG      | Aruban Florin                 | ƒ      |          533 | fiat          |
| AZN      | Azerbaijani Manat             | ₼     |          944 | fiat          |

Get Currency Details

select iso_code, name, symbol, fraction_symbol,
       fractions_per_unit, rounding_type, rounding_precision, format
from ores.currencies
where iso_code = 'USD'
      and valid_to = '9999-12-31 23:59:59'::timestamptz;
| iso_code | name      | symbol | fraction_symbol | fractions_per_unit | rounding_type | rounding_precision | format    |
|----------+-----------+--------+-----------------+--------------------+---------------+--------------------+-----------|
| USD      | US Dollar | $      | ¢               |                100 | standard      |                  2 | $#,##0.00 |

Count Currencies by Type

select currency_type, count(*) as count
from ores.currencies
where valid_to = '9999-12-31 23:59:59'::timestamptz
group by currency_type
order by count desc;
| currency_type | count |
|---------------+-------|
| fiat          |   153 |
| commodity     |     4 |
| supranational |     1 |

Get Currency with Flag Image

select c.iso_code, c.name, c.symbol, i.key as flag_key
from ores.currencies c
left join ores.currency_images ci on ci.iso_code = c.iso_code
  and ci.valid_to = '9999-12-31 23:59:59'::timestamptz
left join ores.images i on i.image_id = ci.image_id
  and i.valid_to = '9999-12-31 23:59:59'::timestamptz
where c.valid_to = '9999-12-31 23:59:59'::timestamptz
  and c.iso_code = 'GBP';
| iso_code | name                   | symbol | flag_key |
|----------+------------------------+--------+----------|
| GBP      | British Pound Sterling | £      | gb       |

Feature Flags

List All Feature Flags

select name, enabled, description, version
from ores.feature_flags
where valid_to = '9999-12-31 23:59:59'::timestamptz
order by name;
| name                                 | enabled | description                                                                                                         | version |
|--------------------------------------+---------+---------------------------------------------------------------------------------------------------------------------+---------|
| system.bootstrap_mode                |       1 | Indicates whether the system is in bootstrap mode (waiting for initial admin account).                              |       1 |
| system.disable_password_validation   |       0 | When enabled, disables strict password validation. FOR TESTING/DEVELOPMENT ONLY.                                    |       1 |
| system.signup_requires_authorization |       0 | Controls whether new signups require admin authorization. NOT YET IMPLEMENTED - enabling will cause signup to fail. |       1 |
| system.user_signups                  |       0 | Controls whether user self-registration is allowed.                                                                 |       1 |

Check Feature Flag Status

select name, enabled
from ores.feature_flags
where name like '%bootstrap_mode%'
  and valid_to = '9999-12-31 23:59:59'::timestamptz;
| name                  | enabled |
|-----------------------+---------|
| system.bootstrap_mode |       1 |

List Enabled Features

select name, description
from ores.feature_flags
where enabled = 1
  and valid_to = '9999-12-31 23:59:59'::timestamptz
order by name;
| name                  | description                                                                            |
|-----------------------+----------------------------------------------------------------------------------------|
| system.bootstrap_mode | Indicates whether the system is in bootstrap mode (waiting for initial admin account). |

Images and Tags

List All Images

select image_id, key, description, version
from ores.images
where valid_to = '9999-12-31 23:59:59'::timestamptz
order by key
limit 20;
| image_id                             | key   | description         | version |
|--------------------------------------+-------+---------------------+---------|
| a6ac20cb-f45f-4375-9082-4673bb1f453a | ad    | Flag for code AD    |       1 |
| 31cafad9-db0c-4359-ada8-da331f08949e | ae    | Flag for code AE    |       1 |
| 1116a6b0-7511-4fda-869f-b4f9946c15b4 | af    | Flag for code AF    |       1 |
| c056bd53-7c7b-4313-990c-7b9d1d80828d | ag    | Flag for code AG    |       1 |
| 31959ae1-6f64-4534-9e1a-fd3dd34ef84d | ai    | Flag for code AI    |       1 |
| 458d56d5-e535-477c-8af5-32bc6097c24b | al    | Flag for code AL    |       1 |
| 9e01af37-ac88-4488-a857-81843736cf21 | am    | Flag for code AM    |       1 |
| fcdb0cd7-6184-4bfa-bad0-180cebeb2224 | ao    | Flag for code AO    |       1 |
| 762567e8-d165-4a57-b818-63d21fbe5748 | aq    | Flag for code AQ    |       1 |
| 85de14d6-5556-410b-83dc-c0c92098d5db | ar    | Flag for code AR    |       1 |
| 495b0456-03da-4c9b-b1b9-110a0d8e06f8 | arab  | Flag for code ARAB  |       1 |
| 04bf011e-5cd2-4715-9707-31ce93a9cb2a | as    | Flag for code AS    |       1 |
| 81cf090b-2cdb-4b95-b530-9144bb3246c3 | asean | Flag for code ASEAN |       1 |
| f3d3f779-ed01-4bf2-85fe-99ba62596647 | at    | Flag for code AT    |       1 |
| beb9ef9e-ba7c-438d-9282-85298a083347 | au    | Flag for code AU    |       1 |
| 9dfc69aa-fe57-4518-a988-0e089f58e390 | aw    | Flag for code AW    |       1 |
| e866518b-5625-433d-b2dc-f107af7a222b | ax    | Flag for code AX    |       1 |
| 5e0b55f6-83df-4fda-862a-0d1ab3d5139e | az    | Flag for code AZ    |       1 |
| aa21e9e2-eac2-44dd-a927-7eef3c9ffa30 | ba    | Flag for code BA    |       1 |
| 05f4a87e-b481-4953-b6cd-9e9b5d3fc7a6 | bb    | Flag for code BB    |       1 |

List All Tags

select tag_id, name, description
from ores.tags
where valid_to = '9999-12-31 23:59:59'::timestamptz
order by name;
| tag_id                               | name | description                    |
|--------------------------------------+------+--------------------------------|
| d932c1f5-37fd-48fd-b592-7e7450afded0 | flag | Country and region flag images |

Get Images by Tag

select i.key, i.description
from ores.images i
join ores.image_tags it on it.image_id = i.image_id
  and it.valid_to = '9999-12-31 23:59:59'::timestamptz
join ores.tags t on t.tag_id = it.tag_id
  and t.valid_to = '9999-12-31 23:59:59'::timestamptz
where i.valid_to = '9999-12-31 23:59:59'::timestamptz
  and t.name = 'flag'
order by i.key
limit 20;
| key   | description         |
|-------+---------------------|
| ad    | Flag for code AD    |
| ae    | Flag for code AE    |
| af    | Flag for code AF    |
| ag    | Flag for code AG    |
| ai    | Flag for code AI    |
| al    | Flag for code AL    |
| am    | Flag for code AM    |
| ao    | Flag for code AO    |
| aq    | Flag for code AQ    |
| ar    | Flag for code AR    |
| arab  | Flag for code ARAB  |
| as    | Flag for code AS    |
| asean | Flag for code ASEAN |
| at    | Flag for code AT    |
| au    | Flag for code AU    |
| aw    | Flag for code AW    |
| ax    | Flag for code AX    |
| az    | Flag for code AZ    |
| ba    | Flag for code BA    |
| bb    | Flag for code BB    |

Temporal Queries

View Entity History

See all versions of an entity over time:

select id, username, email, version, valid_from, valid_to,
       case when valid_to = '9999-12-31 23:59:59'::timestamptz
            then 'current' else 'historical' end as status
from ores.accounts
where username = 'admin'
order by valid_from;
| id | username | email | version | valid_from | valid_to | status |
|----+----------+-------+---------+------------+----------+--------|

Point-in-Time Query

Get the state of an entity at a specific point in time:

select id, username, email, version
from ores.accounts
where username = 'admin'
  and valid_from <= '2025-01-15 12:00:00'::timestamptz
  and valid_to > '2025-01-15 12:00:00'::timestamptz;

Count Entity Versions

select username, count(*) as version_count
from ores.accounts
group by username
having count(*) > 1
order by version_count desc;

Administrative

Database Size

select pg_size_pretty(pg_database_size(current_database())) as database_size;
| database_size |
|---------------|
| 12 MB         |

Table Sizes

select schemaname, tablename,
       pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) as size
from pg_tables
where schemaname = 'ores'
order by pg_total_relation_size(schemaname || '.' || tablename) desc;
| schemaname | tablename        | size    |
|------------+------------------+---------|
| ores       | images           | 1232 kB |
| ores       | image_tags       | 176 kB  |
| ores       | currencies       | 96 kB   |
| ores       | currency_images  | 88 kB   |
| ores       | roles            | 72 kB   |
| ores       | tags             | 72 kB   |
| ores       | role_permissions | 64 kB   |
| ores       | permissions      | 56 kB   |
| ores       | feature_flags    | 56 kB   |
| ores       | sessions         | 48 kB   |
| ores       | accounts         | 48 kB   |
| ores       | account_roles    | 40 kB   |
| ores       | login_info       | 32 kB   |
| ores       | ip2country       | 16 kB   |

Row Counts per Table

Uses PostgreSQL statistics for all tables in the schema:

select relname as table_name, n_live_tup as rows
from pg_stat_user_tables
where schemaname = 'ores'
order by n_live_tup desc;
| table_name       | rows |
|------------------+------|
| images           |  276 |
| image_tags       |  276 |
| currency_images  |  158 |
| currencies       |  158 |
| permissions      |   24 |
| role_permissions |   21 |
| roles            |    6 |
| feature_flags    |    4 |
| tags             |    1 |
| ip2country       |    0 |
| account_roles    |    0 |
| sessions         |    0 |
| accounts         |    0 |
| login_info       |    0 |

Footer

Previous: Recipes Schema: SQL Schema