docs: add database state detection guide to db-customization README

Adds a detection query set and decision tree to determine from the
database itself whether it is a new deployment, an unmigrated 0.11.6
database, an upgraded 0.11.6 database, or a clean 13.0 state — and which
script to run in each case.

Part-of: <http://gitlab.vnc.biz/uxf/vnctalk-prosody/-/merge_requests/3>
This commit is contained in:
2026-07-15 17:58:02 +02:00
parent ea043d759c
commit 86fdfbb986
+75
View File
@@ -61,6 +61,81 @@ database), run them first, then the two 13.0 scripts above.
All 13.0 scripts are safe to re-run (idempotent). The legacy scripts are **not**
idempotent and must not be re-run on a database that already has the objects.
## Detecting the database state
Run this detection query to determine which scenario applies:
```sql
-- 1. Prosody storage tables exist?
select exists (select 1 from information_schema.tables where table_name = 'prosody') as prosody_table_exists;
-- 2. Derived tables exist (any db-customization ever applied)?
select exists (select 1 from information_schema.tables where table_name = 'processed_messages') as derived_tables_exist;
-- 3. room_membership view: old (_affiliations) or new (per-row) format?
select pg_get_viewdef('room_membership'::regclass, true) as room_membership_def;
-- 4. room_nicknames view still exists? (dropped by 13.0 scripts)
select exists (select 1 from information_schema.views where table_name = 'room_nicknames') as room_nicknames_view_exists;
-- 5. update_group_owners: legacy RULE vs 13.0 TRIGGER?
select 'rule' as kind from pg_rules where rulename = 'update_group_owners'
union all
select 'trigger' as kind from pg_trigger where tgname = 'update_group_owners';
-- 6. update_room_nick_jid trigger WHEN clause: _affiliations (old) or _data (new)?
select pg_get_triggerdef(oid) from pg_trigger where tgname = 'update_room_nick_jid';
```
### Decision tree
```
1. prosody table exists?
NO → Start Prosody 13.0.6 once so mod_storage_sql creates the tables,
then re-run detection.
YES → continue to 2
2. derived tables exist (processed_messages etc.)?
NO → NEW DEPLOYMENT
Run: psql -f prosody-13-new-deployment.sql
YES → continue to 3
3. room_membership view references '_affiliations' / jsonb_object_keys?
YES → 0.11.6 LEGACY, NOT YET MIGRATED
(legacy scripts were applied under 0.11.6, 13.0 scripts not yet run)
Run: psql -f prosody-13-rules-triggers.sql
psql -f prosody-13-migration-once.sql
NO → already on 13.0 format → continue to 4
4. update_group_owners legacy RULE still present (alongside the TRIGGER)?
YES → UPGRADED FROM 0.11.6, 13.0 scripts already applied
The dead rule is harmless (fires on key='_affiliations' which never
matches). Optionally drop it:
drop rule if exists update_group_owners on prosody;
Re-run prosody-13-rules-triggers.sql for drift correction if needed.
NO → continue to 5
5. room_nicknames view exists?
YES → INCOMPLETE MIGRATION (legacy objects not cleaned up)
Re-run: psql -f prosody-13-rules-triggers.sql
NO → CLEAN 13.0 STATE (new deployment or fully migrated)
All scripts are in sync. Re-run any 13.0 script for
drift correction if desired (all are idempotent).
```
### Quick reference: detection signals per scenario
| Signal | New deployment | 0.11.6, not migrated | Upgraded from 0.11.6 | Clean 13.0 |
|--------|---------------|----------------------|----------------------|------------|
| `processed_messages` table | absent | present | present | present |
| `room_membership` uses `_affiliations` | n/a | **yes** | no | no |
| `room_membership` uses per-row `key like '%@%'` | n/a | no | **yes** | **yes** |
| `room_nicknames` view exists | absent | **yes** | no | no |
| `update_group_owners` is a RULE | absent | **yes** | yes (dead) | absent |
| `update_group_owners` is a TRIGGER | absent | no | **yes** | **yes** |
| `update_room_nick_jid` fires on `_data` | n/a | no | **yes** | **yes** |
| `update_room_nick_jid` fires on `_affiliations` | n/a | **yes** | no | no |
## What changed between 0.11.6 and 13.0.6
Under 0.11.6, MUC affiliations were stored as a single JSON blob in one row