Skip to content

Commit

Permalink
Improve docs on postgres date types
Browse files Browse the repository at this point in the history
  • Loading branch information
simolus3 committed Jan 5, 2025
1 parent 53ce1f6 commit 38b1e4a
Show file tree
Hide file tree
Showing 9 changed files with 329 additions and 23 deletions.
34 changes: 21 additions & 13 deletions docs/docs/Platforms/postgres.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,26 +86,34 @@ These will be moved into separate libraries in a future major release to avoid c
aware of them for the time being.
This section lists affected APIs and workarounds to make them work PostgreSQL.

1. Most parts of the `Migrator` API are SQLite-specific. You will be able to create tables on PostgreSQL as well,
but methods like `alterTable` will only work with SQLite.
The [migrations](#migrations) section below describes possible workarounds - the recommended approach is to
export your drift schema and then use dedicated migration tools for PostgreSQL.
2. Drift's datetime columns were designed to work with SQLite, which doesn't have dedicated datetime types.
Most of the date time APIs (like `currentDateAndTime`) will not work with PostgreSQL.
When using drift databases with PostgreSQL, we suggest avoiding the default `dateTime()` column type and instead
use `PgTypes.date` or `PgTypes.datetime`.
If you need to support both sqlite3 and Postgres, consider using [dialect-aware types](../sql_api/types.md#dialect-awareness).

### Migrations

Most parts of the `Migrator` API are SQLite-specific. You will be able to create tables on PostgreSQL as well,
but methods like `alterTable` will only work with SQLite.
While it's possible to use drift migrations with PostgreSQL databases, the recommended approach for now is to
[export your drift schema](../Tools/index.md#exporting) and then use dedicated migration tools for PostgreSQL.

In sqlite3, the current schema version is stored in the database file. To support drift's migration API
being built ontop of this mechanism in Postgres as well, drift creates a `__schema` table storing
being built on top of this mechanism in Postgres as well, drift creates a `__schema` table storing
the current schema version.

This migration mechanism works for simple deployments, but is unsuitable for large database setups
with many application servers connecting to postgres. For those, an existing migration management
with many application servers connecting to a postgres serve. For those, an existing migration management
tool is a more reliable alternative. If you chose to manage migrations with another tool, you can
disable migrations in postgres by passing `enableMigrations: false` to the `PgDatabase` constructor.
disable migrations in drift by passing `enableMigrations: false` to the `PgDatabase` constructor.

### DateTime columns

Drift's `datetime()` columns were designed to work with SQLite, which doesn't have dedicated datetime types.
Most of the date time APIs (like `currentDateAndTime`) will not work with PostgreSQL.
When using drift databases with PostgreSQL, we suggest avoiding the default `dateTime()` column type and instead
use `PgTypes.date` or `PgTypes.datetime`:

{{ load_snippet('time','lib/snippets/platforms/postgres.dart.excerpt.json') }}

If you need to support both sqlite3 and Postgres, consider using [dialect-aware types](../sql_api/types.md#dialect-awareness):

{{ load_snippet('time-dialectaware','lib/snippets/platforms/postgres.dart.excerpt.json') }}

## Current state

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/dart_api/tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,4 +448,4 @@ targets:
# store_date_time_values_as_text: true
```

See the [DateTime Guide](../guides/datetime-migrations.md) for more information on how dates are stored and how to switch between storage methods.
See the [DateTime migration guide](../guides/datetime-migrations.md) for more information on how dates are stored and how to switch between storage methods.
64 changes: 62 additions & 2 deletions docs/lib/snippets/_shared/todo_tables.drift.dart
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,41 @@ class $$TodoItemsTableTableManager extends i0.RootTableManager<
i1.$$TodoItemsTableReferences(db, table, e)
))
.toList(),
prefetchHooksCallback: null,
prefetchHooksCallback: ({category = false}) {
return i0.PrefetchHooks(
db: db,
explicitlyWatchedTables: [],
addJoins: <
T extends i0.TableManagerState<
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic>>(state) {
if (category) {
state = state.withJoin(
currentTable: table,
currentColumn: table.category,
referencedTable:
i1.$$TodoItemsTableReferences._categoryTable(db),
referencedColumn:
i1.$$TodoItemsTableReferences._categoryTable(db).id,
) as T;
}

return state;
},
getPrefetchedDataCallback: (items) async {
return [];
},
);
},
));
}

Expand Down Expand Up @@ -438,7 +472,33 @@ class $$CategoriesTableTableManager extends i0.RootTableManager<
i1.$$CategoriesTableReferences(db, table, e)
))
.toList(),
prefetchHooksCallback: null,
prefetchHooksCallback: ({todoItemsRefs = false}) {
return i0.PrefetchHooks(
db: db,
explicitlyWatchedTables: [
if (todoItemsRefs)
i3.ReadDatabaseContainer(db)
.resultSet<i1.$TodoItemsTable>('todo_items')
],
addJoins: null,
getPrefetchedDataCallback: (items) async {
return [
if (todoItemsRefs)
await i0.$_getPrefetchedData(
currentTable: table,
referencedTable: i1.$$CategoriesTableReferences
._todoItemsRefsTable(db),
managerFromTypedResult: (p0) => i1
.$$CategoriesTableReferences(db, table, p0)
.todoItemsRefs,
referencedItemsForCurrentItem: (item,
referencedItems) =>
referencedItems.where((e) => e.category == item.id),
typedResults: items)
];
},
);
},
));
}

Expand Down
2 changes: 1 addition & 1 deletion docs/lib/snippets/modular/custom_types/type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ class _FallbackDurationType implements CustomSqlType<Duration> {
return 'integer';
}
}
// #enddocregion fallback

const durationType = DialectAwareSqlType<Duration>.via(
fallback: _FallbackDurationType(),
overrides: {
SqlDialect.postgres: DurationType(),
},
);
// #enddocregion fallback
60 changes: 58 additions & 2 deletions docs/lib/snippets/modular/drift/example.drift.dart
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,39 @@ class $TodosTableManager extends i0.RootTableManager<
.map((e) =>
(e.readTable(table), i1.$TodosReferences(db, table, e)))
.toList(),
prefetchHooksCallback: null,
prefetchHooksCallback: ({category = false}) {
return i0.PrefetchHooks(
db: db,
explicitlyWatchedTables: [],
addJoins: <
T extends i0.TableManagerState<
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic>>(state) {
if (category) {
state = state.withJoin(
currentTable: table,
currentColumn: table.category,
referencedTable: i1.$TodosReferences._categoryTable(db),
referencedColumn: i1.$TodosReferences._categoryTable(db).id,
) as T;
}

return state;
},
getPrefetchedDataCallback: (items) async {
return [];
},
);
},
));
}

Expand Down Expand Up @@ -410,7 +442,31 @@ class $CategoriesTableManager extends i0.RootTableManager<
.map((e) =>
(e.readTable(table), i1.$CategoriesReferences(db, table, e)))
.toList(),
prefetchHooksCallback: null,
prefetchHooksCallback: ({todosRefs = false}) {
return i0.PrefetchHooks(
db: db,
explicitlyWatchedTables: [
if (todosRefs)
i2.ReadDatabaseContainer(db).resultSet<i1.Todos>('todos')
],
addJoins: null,
getPrefetchedDataCallback: (items) async {
return [
if (todosRefs)
await i0.$_getPrefetchedData(
currentTable: table,
referencedTable:
i1.$CategoriesReferences._todosRefsTable(db),
managerFromTypedResult: (p0) =>
i1.$CategoriesReferences(db, table, p0).todosRefs,
referencedItemsForCurrentItem: (item,
referencedItems) =>
referencedItems.where((e) => e.category == item.id),
typedResults: items)
];
},
);
},
));
}

Expand Down
42 changes: 41 additions & 1 deletion docs/lib/snippets/modular/drift/with_existing.drift.dart
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,47 @@ class $FriendsTableManager extends i0.RootTableManager<
.map((e) =>
(e.readTable(table), i2.$FriendsReferences(db, table, e)))
.toList(),
prefetchHooksCallback: null,
prefetchHooksCallback: ({userA = false, userB = false}) {
return i0.PrefetchHooks(
db: db,
explicitlyWatchedTables: [],
addJoins: <
T extends i0.TableManagerState<
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic>>(state) {
if (userA) {
state = state.withJoin(
currentTable: table,
currentColumn: table.userA,
referencedTable: i2.$FriendsReferences._userATable(db),
referencedColumn: i2.$FriendsReferences._userATable(db).id,
) as T;
}
if (userB) {
state = state.withJoin(
currentTable: table,
currentColumn: table.userB,
referencedTable: i2.$FriendsReferences._userBTable(db),
referencedColumn: i2.$FriendsReferences._userBTable(db).id,
) as T;
}

return state;
},
getPrefetchedDataCallback: (items) async {
return [];
},
);
},
));
}

Expand Down
77 changes: 75 additions & 2 deletions docs/lib/snippets/modular/many_to_many/relational.drift.dart
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,34 @@ class $$ShoppingCartsTableTableManager extends i0.RootTableManager<
i2.$$ShoppingCartsTableReferences(db, table, e)
))
.toList(),
prefetchHooksCallback: null,
prefetchHooksCallback: ({shoppingCartEntriesRefs = false}) {
return i0.PrefetchHooks(
db: db,
explicitlyWatchedTables: [
if (shoppingCartEntriesRefs)
i4.ReadDatabaseContainer(db)
.resultSet<i2.$ShoppingCartEntriesTable>(
'shopping_cart_entries')
],
addJoins: null,
getPrefetchedDataCallback: (items) async {
return [
if (shoppingCartEntriesRefs)
await i0.$_getPrefetchedData(
currentTable: table,
referencedTable: i2.$$ShoppingCartsTableReferences
._shoppingCartEntriesRefsTable(db),
managerFromTypedResult: (p0) => i2
.$$ShoppingCartsTableReferences(db, table, p0)
.shoppingCartEntriesRefs,
referencedItemsForCurrentItem:
(item, referencedItems) => referencedItems
.where((e) => e.shoppingCart == item.id),
typedResults: items)
];
},
);
},
));
}

Expand Down Expand Up @@ -487,7 +514,53 @@ class $$ShoppingCartEntriesTableTableManager extends i0.RootTableManager<
i2.$$ShoppingCartEntriesTableReferences(db, table, e)
))
.toList(),
prefetchHooksCallback: null,
prefetchHooksCallback: ({shoppingCart = false, item = false}) {
return i0.PrefetchHooks(
db: db,
explicitlyWatchedTables: [],
addJoins: <
T extends i0.TableManagerState<
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic>>(state) {
if (shoppingCart) {
state = state.withJoin(
currentTable: table,
currentColumn: table.shoppingCart,
referencedTable: i2.$$ShoppingCartEntriesTableReferences
._shoppingCartTable(db),
referencedColumn: i2.$$ShoppingCartEntriesTableReferences
._shoppingCartTable(db)
.id,
) as T;
}
if (item) {
state = state.withJoin(
currentTable: table,
currentColumn: table.item,
referencedTable:
i2.$$ShoppingCartEntriesTableReferences._itemTable(db),
referencedColumn: i2.$$ShoppingCartEntriesTableReferences
._itemTable(db)
.id,
) as T;
}

return state;
},
getPrefetchedDataCallback: (items) async {
return [];
},
);
},
));
}

Expand Down
Loading

0 comments on commit 38b1e4a

Please sign in to comment.