dbschema 0.1.1

Define database schema's as HCL files, and generate idempotent SQL migrations
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
use hcl::Value;
use serde::Serialize;

#[derive(Debug, Clone, Default, Serialize)]
pub struct Config {
    pub providers: Vec<ProviderSpec>,
    pub functions: Vec<FunctionSpec>,
    pub procedures: Vec<ProcedureSpec>,
    pub aggregates: Vec<AggregateSpec>,
    pub operators: Vec<OperatorSpec>,
    pub triggers: Vec<TriggerSpec>,
    pub rules: Vec<RuleSpec>,
    pub event_triggers: Vec<EventTriggerSpec>,
    pub extensions: Vec<ExtensionSpec>,
    pub collations: Vec<CollationSpec>,
    pub sequences: Vec<SequenceSpec>,
    pub schemas: Vec<SchemaSpec>,
    pub enums: Vec<EnumSpec>,
    pub domains: Vec<DomainSpec>,
    pub types: Vec<CompositeTypeSpec>,
    pub tables: Vec<TableSpec>,
    pub indexes: Vec<StandaloneIndexSpec>,
    pub statistics: Vec<StatisticsSpec>,
    pub views: Vec<ViewSpec>,
    pub materialized: Vec<MaterializedViewSpec>,
    pub policies: Vec<PolicySpec>,
    pub roles: Vec<RoleSpec>,
    pub tablespaces: Vec<TablespaceSpec>,
    pub grants: Vec<GrantSpec>,
    pub foreign_data_wrappers: Vec<ForeignDataWrapperSpec>,
    pub foreign_servers: Vec<ForeignServerSpec>,
    pub foreign_tables: Vec<ForeignTableSpec>,
    pub text_search_dictionaries: Vec<TextSearchDictionarySpec>,
    pub text_search_configurations: Vec<TextSearchConfigurationSpec>,
    pub text_search_templates: Vec<TextSearchTemplateSpec>,
    pub text_search_parsers: Vec<TextSearchParserSpec>,
    pub publications: Vec<PublicationSpec>,
    pub subscriptions: Vec<SubscriptionSpec>,
    pub tests: Vec<TestSpec>,
    pub outputs: Vec<OutputSpec>,
}

#[derive(Debug, Clone, Serialize)]
pub struct ProviderSpec {
    pub provider_type: String,
    pub version: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct FunctionSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub language: String,
    pub parameters: Vec<String>,
    pub returns: String,
    pub replace: bool,
    pub volatility: Option<String>,
    pub strict: bool,
    pub security: Option<String>,
    pub cost: Option<f64>,
    pub body: String,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct ProcedureSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub language: String,
    pub parameters: Vec<String>,
    pub replace: bool,
    pub security: Option<String>,
    pub body: String,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct AggregateSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub inputs: Vec<String>,
    pub sfunc: String,
    pub stype: String,
    pub finalfunc: Option<String>,
    pub initcond: Option<String>,
    pub parallel: Option<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct OperatorSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub left: Option<String>,
    pub right: Option<String>,
    pub procedure: String,
    pub commutator: Option<String>,
    pub negator: Option<String>,
    pub restrict: Option<String>,
    pub join: Option<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct TriggerSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub table: String,
    pub timing: String,      // BEFORE | AFTER
    pub events: Vec<String>, // INSERT | UPDATE | DELETE
    pub level: String,       // ROW | STATEMENT
    pub function: String,    // function name (unqualified)
    pub function_schema: Option<String>,
    pub when: Option<String>, // optional condition, raw SQL
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct RuleSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub table: String,
    pub event: String,
    pub r#where: Option<String>,
    pub instead: bool,
    pub command: String,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct EventTriggerSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub event: String,
    pub tags: Vec<String>,
    pub function: String,
    pub function_schema: Option<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct ExtensionSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub if_not_exists: bool,
    pub schema: Option<String>,
    pub version: Option<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct CollationSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub if_not_exists: bool,
    pub from: Option<String>,
    pub locale: Option<String>,
    pub lc_collate: Option<String>,
    pub lc_ctype: Option<String>,
    pub provider: Option<String>,
    pub deterministic: Option<bool>,
    pub version: Option<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct SequenceSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub if_not_exists: bool,
    pub r#as: Option<String>,
    pub increment: Option<i64>,
    pub min_value: Option<i64>,
    pub max_value: Option<i64>,
    pub start: Option<i64>,
    pub cache: Option<i64>,
    pub cycle: bool,
    pub owned_by: Option<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct SchemaSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub if_not_exists: bool,
    pub authorization: Option<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct EnumSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub values: Vec<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct DomainSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub r#type: String,
    pub not_null: bool,
    pub default: Option<String>,
    pub constraint: Option<String>,
    pub check: Option<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct CompositeTypeSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub fields: Vec<CompositeTypeFieldSpec>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct CompositeTypeFieldSpec {
    pub name: String,
    pub r#type: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct ViewSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub replace: bool, // OR REPLACE
    pub sql: String,   // SELECT ... body
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct MaterializedViewSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub with_data: bool, // WITH [NO] DATA
    pub sql: String,     // SELECT ... body
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct PolicySpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub table: String,
    pub command: String,       // ALL | SELECT | INSERT | UPDATE | DELETE
    pub r#as: Option<String>,  // PERMISSIVE | RESTRICTIVE
    pub roles: Vec<String>,    // empty => PUBLIC (omit TO clause)
    pub using: Option<String>, // USING (expr)
    pub check: Option<String>, // WITH CHECK (expr)
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct RoleSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub login: bool,
    pub superuser: bool,
    pub createdb: bool,
    pub createrole: bool,
    pub replication: bool,
    pub password: Option<String>,
    pub in_role: Vec<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct TablespaceSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub location: String,
    pub owner: Option<String>,
    pub options: Vec<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct GrantSpec {
    pub name: String,
    pub role: String,
    pub privileges: Vec<String>,
    pub schema: Option<String>,
    pub table: Option<String>,
    pub function: Option<String>,
    pub database: Option<String>,
    pub sequence: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct ForeignDataWrapperSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub handler: Option<String>,
    pub validator: Option<String>,
    pub options: Vec<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct ForeignServerSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub wrapper: String,
    pub r#type: Option<String>,
    pub version: Option<String>,
    pub options: Vec<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct ForeignTableSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub server: String,
    pub columns: Vec<ColumnSpec>,
    pub options: Vec<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct PublicationSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub all_tables: bool,
    pub tables: Vec<PublicationTableSpec>,
    pub publish: Vec<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct PublicationTableSpec {
    pub schema: Option<String>,
    pub table: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct SubscriptionSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub connection: String,
    pub publications: Vec<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct TableSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub if_not_exists: bool,
    pub columns: Vec<ColumnSpec>,
    pub primary_key: Option<PrimaryKeySpec>,
    pub indexes: Vec<IndexSpec>,
    pub checks: Vec<CheckSpec>,
    pub foreign_keys: Vec<ForeignKeySpec>,
    pub partition_by: Option<PartitionBySpec>,
    pub partitions: Vec<PartitionSpec>,
    pub back_references: Vec<BackReferenceSpec>,
    pub lint_ignore: Vec<String>,
    pub comment: Option<String>,
    pub map: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct PartitionBySpec {
    pub strategy: String,
    pub columns: Vec<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct PartitionSpec {
    pub name: String,
    pub values: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct BackReferenceSpec {
    pub name: String,
    pub table: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct ColumnSpec {
    pub name: String,
    pub r#type: String,
    pub nullable: bool,
    pub default: Option<String>,
    pub db_type: Option<String>, // NEW: Database-specific type like "CHAR(32)", "VARCHAR(255)"
    pub lint_ignore: Vec<String>,
    pub comment: Option<String>,
    pub count: usize,
}

#[derive(Debug, Clone, Serialize)]
pub struct PrimaryKeySpec {
    pub name: Option<String>,
    pub columns: Vec<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct CheckSpec {
    pub name: Option<String>,
    pub expression: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct IndexSpec {
    pub name: Option<String>,
    pub columns: Vec<String>,
    pub expressions: Vec<String>,
    pub r#where: Option<String>,
    pub orders: Vec<String>,
    pub operator_classes: Vec<String>,
    pub unique: bool,
}

#[derive(Debug, Clone, Serialize)]
pub struct ForeignKeySpec {
    pub name: Option<String>,
    pub columns: Vec<String>,
    pub ref_schema: Option<String>,
    pub ref_table: String,
    pub ref_columns: Vec<String>,
    pub on_delete: Option<String>,
    pub on_update: Option<String>,
    pub back_reference_name: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct StandaloneIndexSpec {
    pub name: String,
    pub table: String,
    pub schema: Option<String>,
    pub columns: Vec<String>,
    pub expressions: Vec<String>,
    pub r#where: Option<String>,
    pub orders: Vec<String>,
    pub operator_classes: Vec<String>,
    pub unique: bool,
}

#[derive(Debug, Clone, Serialize)]
pub struct StatisticsSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub table: String,
    pub columns: Vec<String>,
    pub kinds: Vec<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct TextSearchDictionarySpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub template: String,
    pub options: Vec<String>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct TextSearchConfigurationMappingSpec {
    pub tokens: Vec<String>,
    pub dictionaries: Vec<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct TextSearchConfigurationSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub parser: String,
    pub mappings: Vec<TextSearchConfigurationMappingSpec>,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct TextSearchTemplateSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub init: Option<String>,
    pub lexize: String,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct TextSearchParserSpec {
    pub name: String,
    pub alt_name: Option<String>,
    pub schema: Option<String>,
    pub start: String,
    pub gettoken: String,
    pub end: String,
    pub headline: Option<String>,
    pub lextypes: String,
    pub comment: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct TestSpec {
    pub name: String,
    pub setup: Vec<String>,
    pub asserts: Vec<String>,
    pub assert_fail: Vec<String>,
    pub teardown: Vec<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct OutputSpec {
    pub name: String,
    pub value: Value,
}