1use std::ops::Deref;
2
3use derivative::Derivative;
4use ids::DbIdent;
5
6use self::{
7 attribute::AttributeList, column::Column, composite::Composite, diagnostics::Report, ids::Ident, index::{Check, Index, PrimaryKey, UniqueConstraint}, names::{ItemKind, TypeIdent}, root::Schema, scalar::{Enum, Scalar, ScalarAnnotation}, sql::Sql, table::{ForeignKey, Table, TableAnnotation}, uid::RenameMap, view::View
8};
9
10pub mod column;
11pub mod composite;
12pub mod index;
13pub mod mixin;
14pub mod process;
15pub mod root;
16pub mod scalar;
17pub mod sql;
18pub mod table;
19pub mod trigger;
20pub mod view;
21
22pub mod ids;
23pub mod names;
24
25pub mod parser;
26
27pub mod attribute;
28
29mod changelist;
30pub mod renamelist;
31
32pub use changelist::{mk_change_list, ChangeList, IsCompatible, IsIsomorph};
33
34mod span;
35pub mod uid;
36pub use uid::HasUid;
37
38pub mod diagnostics;
39
40mod util;
41
42#[macro_export]
43macro_rules! w {
44 ($out:expr_2021, $($tt:tt)*) => {{
45 use std::fmt::Write;
46 write!($out, $($tt)*).unwrap();
47 }};
48}
49#[macro_export]
50macro_rules! wl {
51 ($out:ident, $($tt:tt)*) => {{
52 use std::fmt::Write;
53 writeln!($out, $($tt)*).unwrap();
54 }};
55 ($out:ident) => {{
56 use std::fmt::Write;
57 writeln!($out).unwrap();
58 }};
59}
60#[macro_export]
61macro_rules! newty_enum {
62 (
63 $(#[$($attr:tt)+])*
64 $vis:vis enum $name:ident {$($Variant:ident = $accessor:ident),* $(,)+}
65 ) => {
66 $(#[$($attr)+])*
67 #[derive(derivative::Derivative)]
68 #[derivative(Debug)]
69 $vis enum $name {
70 $(
71 #[derivative(Debug = "transparent")]
72 $Variant($Variant),
73 )*
74 }
75 paste::paste!{impl $name {$(
76 $vis fn [<is_ $accessor>](&self) -> bool {
77 matches!(self, Self::$Variant(_))
78 }
79 $vis fn [<as_ $accessor>](&self) -> Option<&$Variant> {
80 match self {
81 Self::$Variant(value) => Some(value),
82 _ => None,
83 }
84 }
85 $vis fn [<as_ $accessor _mut>](&mut self) -> Option<&mut $Variant> {
86 match self {
87 Self::$Variant(value) => Some(value),
88 _ => None,
89 }
90 }
91 )*}}
92 };
93}
94
95#[derive(Derivative)]
96#[derivative(Debug)]
97pub struct TableItem<'a, I> {
98 #[derivative(Debug = "ignore")]
99 pub table: SchemaTable<'a>,
100 pub value: &'a I,
101}
102impl<'a, I> TableItem<'a, I> {
103 pub fn unchecked_new(table: SchemaTable<'a>, value: &'a I) -> Self {
104 Self { table, value }
105 }
106}
107impl<I> Deref for TableItem<'_, I> {
108 type Target = I;
109 fn deref(&self) -> &Self::Target {
110 self.value
111 }
112}
113impl<I> Clone for TableItem<'_, I> {
114 fn clone(&self) -> Self {
115 *self
116 }
117}
118impl<I> Copy for TableItem<'_, I> {}
119impl<T> IsCompatible for TableItem<'_, T>
120where
121 T: IsCompatible,
122{
123 fn is_compatible(&self, new: &Self, rn: &RenameMap, report_self: &mut Report, report_new: &mut Report) -> bool {
124 self.value.is_compatible(new.value, rn, report_self, report_new)
125 }
126}
127impl<T> IsIsomorph for TableItem<'_, T>
128where
129 T: IsIsomorph,
130{
131 fn is_isomorph(&self, other: &Self, rn: &RenameMap, report_self: &mut Report, report_other: &mut Report) -> bool {
132 self.value.is_isomorph(other.value, rn, report_self, report_other)
133 }
134}
135impl<T> HasUid for TableItem<'_, T>
136where
137 T: HasUid,
138{
139 fn uid(&self) -> uid::Uid {
140 self.value.uid()
141 }
142}
143impl<T> HasDefaultDbName for TableItem<'_, T>
144where
145 T: HasDefaultDbName,
146{
147 type Kind = T::Kind;
148
149 fn default_db(&self) -> Option<DbIdent<Self::Kind>> {
150 self.value.default_db()
151 }
152}
153impl<T> HasIdent for TableItem<'_, T>
154where
155 T: HasIdent,
156{
157 type Kind = T::Kind;
158
159 fn id(&self) -> Ident<Self::Kind> {
160 self.value.id()
161 }
162}
163
164pub type TableIndex<'a> = TableItem<'a, Index>;
165pub type TableColumn<'a> = TableItem<'a, Column>;
166pub type TableForeignKey<'a> = TableItem<'a, ForeignKey>;
167pub type TableSql<'a> = TableItem<'a, Sql>;
168pub type TablePrimaryKey<'a> = TableItem<'a, PrimaryKey>;
169pub type TableCheck<'a> = TableItem<'a, Check>;
170pub type TableUniqueConstraint<'a> = TableItem<'a, UniqueConstraint>;
171
172pub struct SchemaSql<'a> {
173 pub schema: &'a Schema,
174 pub sql: &'a Sql,
175}
176impl Deref for SchemaSql<'_> {
177 type Target = Sql;
178 fn deref(&self) -> &Self::Target {
179 self.sql
180 }
181}
182
183#[derive(Debug, PartialEq, Clone, Copy)]
184pub struct Diff<I> {
185 pub old: I,
186 pub new: I,
187}
188pub type SchemaDiff<'a> = Diff<&'a Schema>;
189pub type TableDiff<'a> = Diff<SchemaTable<'a>>;
190pub type EnumDiff<'a> = Diff<SchemaEnum<'a>>;
191pub type ColumnDiff<'a> = Diff<TableColumn<'a>>;
192
193#[derive(Clone, Copy, Derivative)]
194#[derivative(Debug)]
195pub struct SchemaEnum<'a> {
196 #[derivative(Debug = "ignore")]
197 pub schema: &'a Schema,
198 pub en: &'a Enum,
199}
200
201impl Deref for SchemaEnum<'_> {
202 type Target = Enum;
203
204 fn deref(&self) -> &Self::Target {
205 self.en
206 }
207}
208
209#[derive(Clone, Copy, Debug)]
210pub enum SchemaItem<'a> {
211 Table(SchemaTable<'a>),
212 Enum(SchemaEnum<'a>),
213 Scalar(SchemaScalar<'a>),
214 Composite(SchemaComposite<'a>),
215 View(SchemaView<'a>),
216}
217derive_is_isomorph_by_id_name!(SchemaItem<'_>);
218impl SchemaItem<'_> {
219 pub fn as_enum(&self) -> Option<SchemaEnum> {
220 match self {
221 Self::Enum(e) => Some(*e),
222 _ => None,
223 }
224 }
225 pub fn as_scalar(&self) -> Option<SchemaScalar> {
226 match self {
227 Self::Scalar(e) => Some(*e),
228 _ => None,
229 }
230 }
231 pub fn as_composite(&self) -> Option<SchemaComposite> {
232 match self {
233 Self::Composite(e) => Some(*e),
234 _ => None,
235 }
236 }
237 pub fn as_table(&self) -> Option<SchemaTable> {
238 match self {
239 Self::Table(e) => Some(*e),
240 _ => None,
241 }
242 }
243 pub fn as_type(&self) -> Option<SchemaType> {
244 Some(match self {
245 SchemaItem::Enum(e) => SchemaType::Enum(*e),
246 SchemaItem::Scalar(s) => SchemaType::Scalar(*s),
247 SchemaItem::Composite(c) => SchemaType::Composite(*c),
248 _ => return None,
249 })
250 }
251 pub fn as_view(&self) -> Option<SchemaView> {
252 match self {
253 Self::View(e) => Some(*e),
254 _ => None,
255 }
256 }
257 pub fn schema(&self) -> &Schema {
258 match self {
259 SchemaItem::Table(t) => t.schema,
260 SchemaItem::Enum(e) => e.schema,
261 SchemaItem::Scalar(s) => s.schema,
262 SchemaItem::Composite(c) => c.schema,
263 SchemaItem::View(v) => v.schema,
264 }
265 }
266 pub fn is_external(&self) -> bool {
267 match self {
268 SchemaItem::Table(t) => t.is_external(),
269 SchemaItem::Enum(_) => false,
270 SchemaItem::Scalar(s) => s.is_external(),
271 SchemaItem::Composite(_) => false,
272 SchemaItem::View(_) => false,
273 }
274 }
275}
276impl HasUid for SchemaItem<'_> {
277 fn uid(&self) -> uid::Uid {
278 match self {
279 SchemaItem::Table(t) => t.uid(),
280 SchemaItem::Enum(e) => e.uid(),
281 SchemaItem::Scalar(s) => s.uid(),
282 SchemaItem::Composite(s) => s.uid(),
283 SchemaItem::View(v) => v.uid(),
284 }
285 }
286}
287impl HasIdent for SchemaItem<'_> {
288 type Kind = ItemKind;
289
290 fn id(&self) -> Ident<Self::Kind> {
291 match self {
292 SchemaItem::Table(t) => Ident::unchecked_cast(t.id()),
293 SchemaItem::Enum(e) => Ident::unchecked_cast(e.id()),
294 SchemaItem::Scalar(s) => Ident::unchecked_cast(s.id()),
295 SchemaItem::Composite(s) => Ident::unchecked_cast(s.id()),
296 SchemaItem::View(v) => Ident::unchecked_cast(v.id()),
297 }
298 }
299}
300impl HasDefaultDbName for SchemaItem<'_> {
301 type Kind = ItemKind;
302
303 fn default_db(&self) -> Option<DbIdent<Self::Kind>> {
304 match self {
305 SchemaItem::Table(t) => t.default_db().map(DbIdent::unchecked_from),
306 SchemaItem::Enum(e) => e.default_db().map(DbIdent::unchecked_from),
307 SchemaItem::Scalar(s) => s.default_db().map(DbIdent::unchecked_from),
308 SchemaItem::Composite(s) => s.default_db().map(DbIdent::unchecked_from),
309 SchemaItem::View(v) => v.default_db().map(DbIdent::unchecked_from),
310 }
311 }
312}
313
314#[derive(Clone, Copy, Derivative)]
315#[derivative(Debug)]
316pub struct SchemaScalar<'a> {
317 #[derivative(Debug = "ignore")]
318 pub schema: &'a Schema,
319 pub scalar: &'a Scalar,
320}
321impl Deref for SchemaScalar<'_> {
322 type Target = Scalar;
323
324 fn deref(&self) -> &Self::Target {
325 self.scalar
326 }
327}
328
329#[derive(Clone, Copy, Derivative)]
330#[derivative(Debug)]
331pub struct SchemaComposite<'a> {
332 #[derivative(Debug = "ignore")]
333 pub schema: &'a Schema,
334 pub composite: &'a Composite,
335}
336impl Deref for SchemaComposite<'_> {
337 type Target = Composite;
338
339 fn deref(&self) -> &Self::Target {
340 self.composite
341 }
342}
343
344#[derive(Clone, Copy, Debug)]
345pub enum SchemaType<'a> {
346 Enum(SchemaEnum<'a>),
347 Scalar(SchemaScalar<'a>),
348 Composite(SchemaComposite<'a>),
349}
350impl<'a> SchemaType<'a> {
351 pub fn ident(&self) -> TypeIdent {
352 match self {
353 SchemaType::Scalar(s) => s.id(),
354 SchemaType::Enum(e) => e.id(),
355 SchemaType::Composite(e) => e.id(),
356 }
357 }
358 pub fn has_default(&self) -> bool {
359 match self {
360 SchemaType::Scalar(s) => s
361 .annotations
362 .iter()
363 .any(|a| matches!(a, ScalarAnnotation::Default(_))),
364 SchemaType::Enum(_) => false,
365 SchemaType::Composite(_) => false,
366 }
367 }
368 pub fn attrlist(&self) -> &AttributeList {
369 match self {
370 SchemaType::Scalar(s) => &s.attrlist,
371 SchemaType::Enum(e) => &e.attrlist,
372 SchemaType::Composite(c) => &c.attrlist,
373 }
374 }
375 pub fn depend_on(&self, out: &mut Vec<TypeIdent>) {
376 match self {
377 SchemaType::Enum(e) => out.push(e.id()),
378 SchemaType::Scalar(s) => s.depend_on(out),
379 SchemaType::Composite(c) => {
380 out.push(c.id());
382 }
383 }
384 }
385 pub fn type_dependencies(&self, out: &mut Vec<TypeIdent>) {
386 match self {
387 SchemaType::Enum(_e) => {
388 }
390 SchemaType::Scalar(s) => {
391 s.type_dependencies(out);
393 }
394 SchemaType::Composite(c) => {
395 for f in c.fields() {
397 f.ty().depend_on(out);
398 }
399 }
400 }
401 }
402 pub fn as_schema_item(self) -> SchemaItem<'a> {
403 match self {
404 SchemaType::Enum(schema_enum) => SchemaItem::Enum(schema_enum),
405 SchemaType::Scalar(schema_scalar) => SchemaItem::Scalar(schema_scalar),
406 SchemaType::Composite(schema_composite) => SchemaItem::Composite(schema_composite),
407 }
408 }
409}
410
411#[derive(Clone, Copy, Derivative)]
412#[derivative(Debug)]
413pub struct SchemaTable<'a> {
414 #[derivative(Debug = "ignore")]
415 pub schema: &'a Schema,
416 pub table: &'a Table,
417}
418
419impl SchemaTable<'_> {
420 pub fn sql<'a>(&'a self, sql: &'a Sql) -> TableSql<'a> {
421 TableSql {
422 table: *self,
423 value: sql,
424 }
425 }
426 pub fn primary_key(&self) -> Option<TablePrimaryKey<'_>> {
427 let pk = self.table.primary_key()?;
428 Some(TablePrimaryKey {
429 table: *self,
430 value: pk,
431 })
432 }
433 pub fn checks(&self) -> impl Iterator<Item = TableCheck> {
434 self.annotations
435 .iter()
436 .filter_map(TableAnnotation::as_check)
437 .map(|value| TableCheck {
438 table: *self,
439 value,
440 })
441 }
442 pub fn unique_constraints(&self) -> impl Iterator<Item = TableUniqueConstraint> {
443 self.annotations
444 .iter()
445 .filter_map(TableAnnotation::as_unique_constraint)
446 .map(|value| TableUniqueConstraint {
447 table: *self,
448 value,
449 })
450 }
451}
452impl Deref for SchemaTable<'_> {
453 type Target = Table;
454
455 fn deref(&self) -> &Self::Target {
456 self.table
457 }
458}
459
460#[derive(Clone, Copy, Derivative)]
461#[derivative(Debug)]
462pub struct SchemaView<'a> {
463 #[derivative(Debug = "ignore")]
464 pub schema: &'a Schema,
465 pub view: &'a View,
466}
467impl Deref for SchemaView<'_> {
468 type Target = View;
469
470 fn deref(&self) -> &Self::Target {
471 self.view
472 }
473}
474
475#[derive(Clone, Copy, Derivative)]
476#[derivative(Debug)]
477pub enum SchemaTableOrView<'a> {
478 Table(SchemaTable<'a>),
479 View(SchemaView<'a>),
480}
481
482pub trait HasIdent {
483 type Kind;
484 fn id(&self) -> Ident<Self::Kind>;
485}
486impl<T> HasIdent for &T
487where
488 T: HasIdent,
489{
490 type Kind = T::Kind;
491
492 fn id(&self) -> Ident<Self::Kind> {
493 (*self).id()
494 }
495}
496pub trait HasDefaultDbName {
497 type Kind;
498 fn default_db(&self) -> Option<DbIdent<Self::Kind>>;
499}
500impl<T> HasDefaultDbName for &T
501where
502 T: HasDefaultDbName,
503{
504 type Kind = T::Kind;
505
506 fn default_db(&self) -> Option<DbIdent<Self::Kind>> {
507 (*self).default_db()
508 }
509}
510
511#[macro_export]
512macro_rules! def_name_impls {
513 ($t:ty, $k:ident) => {
514 impl $crate::uid::HasUid for $t {
515 fn uid(&self) -> $crate::uid::Uid {
516 $crate::uid::HasUid::uid(&self.uid)
517 }
518 }
519 impl $crate::HasIdent for $t {
520 type Kind = $k;
521 fn id(&self) -> $crate::ids::Ident<Self::Kind> {
522 self.name.code.clone()
523 }
524 }
525 impl $crate::HasDefaultDbName for $t {
526 type Kind = $k;
527 fn default_db(&self) -> Option<$crate::ids::DbIdent<Self::Kind>> {
528 self.name.db.clone()
529 }
530 }
531 };
532}
533
534#[macro_export]
535macro_rules! delegate_name_impls {
536 ($t:ty, $k:ident) => {
537 impl $crate::uid::HasUid for $t {
538 fn uid(&self) -> $crate::uid::Uid {
539 self.value.uid()
540 }
541 }
542 impl $crate::HasIdent for $t {
543 type Kind = $k;
544 fn id(&self) -> $crate::ids::Ident<Self::Kind> {
545 self.value.id()
546 }
547 }
548 impl $crate::HasDefaultDbName for $t {uiaa matrix
549 type Kind = $k;
550 fn default_db(&self) -> Option<$crate::ids::DbIdent<Self::Kind>> {
551 self.value.default_db()
552 }
553 }
554 };
555}
556
557#[macro_export]
558macro_rules! db_name_impls {
559 ($t:ty, $k:ident) => {
560 impl $crate::uid::HasUid for $t {
561 fn uid(&self) -> Uid {
562 $crate::uid::HasUid::uid(&self.uid)
563 }
564 }
565 impl $crate::HasDefaultDbName for $t {
566 type Kind = $k;
567 fn default_db(&self) -> Option<$crate::ids::DbIdent<Self::Kind>> {
568 self.name.clone()
569 }
570 }
571 };
572}
573
574#[macro_export]
575macro_rules! id_impls {
576 ($t:ty, $k:ident) => {
577 impl $crate::uid::HasUid for $t {
578 fn uid(&self) -> $crate::uid::Uid {
579 $crate::uid::HasUid::uid(&self.uid)
580 }
581 }
582 impl $crate::HasIdent for $t {
583 type Kind = $k;
584 fn id(&self) -> $crate::ids::Ident<Self::Kind> {
585 self.name.clone()
586 }
587 }
588 };
589}