|
43
|
43
|
);
|
|
44
|
44
|
```
|
|
45
|
45
|
|
|
|
46
|
+### Catalog
|
|
|
47
|
+
|
|
|
48
|
+| Obiect | Tip | Rol |
|
|
|
49
|
+|--------|-----|-----|
|
|
|
50
|
+| `documents` | table | Document-store runtime pentru registry și Work Orders |
|
|
|
51
|
+| `sqlite_autoindex_documents_1` | index intern SQLite | Indexul automat creat pentru `PRIMARY KEY (name)` |
|
|
|
52
|
+
|
|
|
53
|
+Nu există alte tabele, view-uri, trigger-e sau indexuri definite de aplicație în schema curentă.
|
|
|
54
|
+
|
|
|
55
|
+### Tabel: `documents`
|
|
|
56
|
+
|
|
|
57
|
+| Coloană | Tip declarat | Null | Default | Cheie | Descriere |
|
|
|
58
|
+|---------|--------------|------|---------|-------|-----------|
|
|
|
59
|
+| `name` | `TEXT` | `NOT NULL` implicit prin PK | none | `PRIMARY KEY` | Identificatorul documentului operațional. Valorile cunoscute sunt `hosts_yaml` și `work_orders_yaml`. |
|
|
|
60
|
+| `content` | `TEXT` | `NOT NULL` | none | none | Payload-ul documentului, serializat ca YAML strict compatibil cu parserul aplicației. |
|
|
|
61
|
+| `updated_at` | `TEXT` | `NOT NULL` | none | none | Timestamp ISO UTC setat de aplicație la insert/update. |
|
|
|
62
|
+
|
|
|
63
|
+### Chei
|
|
|
64
|
+
|
|
|
65
|
+| Tabel | Cheie | Coloane | Observații |
|
|
|
66
|
+|-------|------|---------|------------|
|
|
|
67
|
+| `documents` | Primary key | `name` | Garantează un singur rând pentru fiecare document operațional. |
|
|
|
68
|
+
|
|
|
69
|
+SQLite implementează cheia primară textuală prin indexul intern `sqlite_autoindex_documents_1`.
|
|
|
70
|
+
|
|
|
71
|
+### Indexuri
|
|
|
72
|
+
|
|
|
73
|
+| Index | Tabel | Coloane | Unic | Creat de | Rol |
|
|
|
74
|
+|-------|-------|---------|------|----------|-----|
|
|
|
75
|
+| `sqlite_autoindex_documents_1` | `documents` | `name` | da | SQLite | Lookup rapid pentru `SELECT ... WHERE name = ?` și enforcement pentru primary key. |
|
|
|
76
|
+
|
|
|
77
|
+Nu există indexuri explicite definite de aplicație. Nu există index pe `updated_at`, pentru că aplicația nu face query-uri de tip listare istorică sau filtrare temporală.
|
|
|
78
|
+
|
|
|
79
|
+### Relații
|
|
|
80
|
+
|
|
|
81
|
+Nu există foreign keys între tabele, pentru că schema curentă are o singură tabelă.
|
|
|
82
|
+
|
|
|
83
|
+Relațiile de business sunt în interiorul YAML-ului din `content`, nu modelate relational. De exemplu:
|
|
|
84
|
+
|
|
|
85
|
+- hosturile, numele, rolurile și sursele sunt structuri YAML în documentul `hosts_yaml`
|
|
|
86
|
+- checklist-ul și acțiunile unui Work Order sunt structuri YAML în documentul `work_orders_yaml`
|
|
|
87
|
+- acțiunile Work Order referă `host_id` textual în YAML, nu printr-un `FOREIGN KEY`
|
|
|
88
|
+
|
|
|
89
|
+`PRAGMA foreign_keys = ON` este activat ca pregătire pentru o schemă viitoare cu tabele relaționale, dar în schema curentă nu are efect practic.
|
|
|
90
|
+
|
|
|
91
|
+### Constrângeri
|
|
|
92
|
+
|
|
|
93
|
+| Tabel | Constrângere | Efect |
|
|
|
94
|
+|-------|--------------|-------|
|
|
|
95
|
+| `documents` | `PRIMARY KEY (name)` | Nu permite două documente cu același `name`. |
|
|
|
96
|
+| `documents` | `content TEXT NOT NULL` | Nu permite documente fără payload. |
|
|
|
97
|
+| `documents` | `updated_at TEXT NOT NULL` | Nu permite rânduri fără timestamp de modificare. |
|
|
|
98
|
+
|
|
|
99
|
+Nu există `CHECK` constraints pentru valorile permise în `name`, formatul YAML sau formatul timestamp-ului. Aceste validări sunt făcute în codul Perl prin parserul strict YAML și prin fluxurile API.
|
|
|
100
|
+
|
|
|
101
|
+### Operațiuni SQL folosite de aplicație
|
|
|
102
|
+
|
|
|
103
|
+Citire document:
|
|
|
104
|
+
|
|
|
105
|
+```sql
|
|
|
106
|
+SELECT content FROM documents WHERE name = ?;
|
|
|
107
|
+```
|
|
|
108
|
+
|
|
|
109
|
+Insert/update document:
|
|
|
110
|
+
|
|
|
111
|
+```sql
|
|
|
112
|
+INSERT INTO documents (name, content, updated_at)
|
|
|
113
|
+VALUES (?, ?, ?)
|
|
|
114
|
+ON CONFLICT(name) DO UPDATE
|
|
|
115
|
+SET content = excluded.content,
|
|
|
116
|
+ updated_at = excluded.updated_at;
|
|
|
117
|
+```
|
|
|
118
|
+
|
|
|
119
|
+Creare schemă:
|
|
|
120
|
+
|
|
|
121
|
+```sql
|
|
|
122
|
+CREATE TABLE IF NOT EXISTS documents (
|
|
|
123
|
+ name TEXT PRIMARY KEY,
|
|
|
124
|
+ content TEXT NOT NULL,
|
|
|
125
|
+ updated_at TEXT NOT NULL
|
|
|
126
|
+);
|
|
|
127
|
+```
|
|
|
128
|
+
|
|
46
|
129
|
Setări aplicate la conectare:
|
|
47
|
130
|
|
|
48
|
131
|
```sql
|
|
50
|
133
|
PRAGMA foreign_keys = ON;
|
|
51
|
134
|
```
|
|
52
|
135
|
|
|
|
136
|
+### Versiune schemă
|
|
|
137
|
+
|
|
|
138
|
+Nu există încă tabelă `schema_migrations` sau `schema_version`. Schema este implicit versiunea 1 și este definită de blocul `CREATE TABLE IF NOT EXISTS documents` din `scripts/host_manager.pl`.
|
|
|
139
|
+
|
|
53
|
140
|
În schema curentă există o singură tabelă generică, `documents`. Conținutul operațional rămâne serializat în formatul YAML strict deja folosit de aplicație. Alegerea este deliberată pentru migrarea minimă: sursa de adevăr se mută din working tree în SQLite fără să schimbăm încă parserul, UI-ul sau formatul exporturilor.
|
|
54
|
141
|
|
|
55
|
142
|
## Documente
|
|
126
|
213
|
```bash
|
|
127
|
214
|
cd /usr/local/xdev-host-manager
|
|
128
|
215
|
sqlite3 var/host-manager.sqlite '.schema'
|
|
|
216
|
+sqlite3 var/host-manager.sqlite '.tables'
|
|
|
217
|
+sqlite3 var/host-manager.sqlite 'pragma table_info(documents);'
|
|
|
218
|
+sqlite3 var/host-manager.sqlite 'pragma index_list(documents);'
|
|
|
219
|
+sqlite3 var/host-manager.sqlite 'pragma index_info(sqlite_autoindex_documents_1);'
|
|
|
220
|
+sqlite3 var/host-manager.sqlite 'pragma foreign_key_list(documents);'
|
|
129
|
221
|
sqlite3 var/host-manager.sqlite 'select name, updated_at, length(content) from documents order by name;'
|
|
130
|
222
|
sqlite3 var/host-manager.sqlite 'select content from documents where name = "hosts_yaml";'
|
|
131
|
223
|
sqlite3 var/host-manager.sqlite 'select content from documents where name = "work_orders_yaml";'
|