diff --git a/client/lib/libphylum/db/db.dart b/client/lib/libphylum/db/db.dart index 857c06c3..dd376027 100644 --- a/client/lib/libphylum/db/db.dart +++ b/client/lib/libphylum/db/db.dart @@ -1,13 +1,14 @@ import 'dart:io'; import 'package:drift/drift.dart'; -import 'package:phylum/libphylum/db/resources.dart'; import 'unsupported.dart' if (dart.library.ffi) 'native.dart' if (dart.library.html) 'web.dart'; part 'db.g.dart'; -@DriftDatabase(tables: [Resources]) +@DriftDatabase(include: { + 'resources.drift', +}) class AppDatabase extends _$AppDatabase { static Directory? storageDir; static Directory? tmpDir; @@ -16,7 +17,7 @@ class AppDatabase extends _$AppDatabase { AppDatabase({required this.id}) : super(_openConnection(id)); @override - int get schemaVersion => 10; + int get schemaVersion => 11; @override MigrationStrategy get migration => MigrationStrategy( diff --git a/client/lib/libphylum/db/db.g.dart b/client/lib/libphylum/db/db.g.dart index acdb7a55..9719908f 100644 --- a/client/lib/libphylum/db/db.g.dart +++ b/client/lib/libphylum/db/db.g.dart @@ -3,104 +3,103 @@ part of 'db.dart'; // ignore_for_file: type=lint -class $ResourcesTable extends Resources - with TableInfo<$ResourcesTable, Resource> { +class Resources extends Table with TableInfo { @override final GeneratedDatabase attachedDatabase; final String? _alias; - $ResourcesTable(this.attachedDatabase, [this._alias]); + Resources(this.attachedDatabase, [this._alias]); static const VerificationMeta _idMeta = const VerificationMeta('id'); - @override late final GeneratedColumn id = GeneratedColumn( 'id', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL PRIMARY KEY'); static const VerificationMeta _parentMeta = const VerificationMeta('parent'); - @override late final GeneratedColumn parent = GeneratedColumn( 'parent', aliasedName, true, type: DriftSqlType.string, requiredDuringInsert: false, - defaultConstraints: - GeneratedColumn.constraintIsAlways('REFERENCES resources (id)')); + $customConstraints: 'REFERENCES resources(id)'); static const VerificationMeta _nameMeta = const VerificationMeta('name'); - @override late final GeneratedColumn name = GeneratedColumn( 'name', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL'); static const VerificationMeta _dirMeta = const VerificationMeta('dir'); - @override late final GeneratedColumn dir = GeneratedColumn( 'dir', aliasedName, false, type: DriftSqlType.bool, requiredDuringInsert: true, - defaultConstraints: - GeneratedColumn.constraintIsAlways('CHECK ("dir" IN (0, 1))')); + $customConstraints: 'NOT NULL CHECK (dir IN (0, 1))'); static const VerificationMeta _createdMeta = const VerificationMeta('created'); - @override late final GeneratedColumn created = GeneratedColumn( 'created', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + $customConstraints: ''); static const VerificationMeta _modifiedMeta = const VerificationMeta('modified'); - @override late final GeneratedColumn modified = GeneratedColumn( 'modified', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + $customConstraints: ''); static const VerificationMeta _deletedMeta = const VerificationMeta('deleted'); - @override late final GeneratedColumn deleted = GeneratedColumn( 'deleted', aliasedName, false, type: DriftSqlType.bool, requiredDuringInsert: false, - defaultConstraints: - GeneratedColumn.constraintIsAlways('CHECK ("deleted" IN (0, 1))'), - defaultValue: const Constant(false)); + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (deleted IN (0, 1))', + defaultValue: const CustomExpression('0')); static const VerificationMeta _contentSizeMeta = const VerificationMeta('contentSize'); - @override late final GeneratedColumn contentSize = GeneratedColumn( 'content_size', aliasedName, false, type: DriftSqlType.int, requiredDuringInsert: false, - defaultValue: const Constant(0)); + $customConstraints: 'NOT NULL DEFAULT 0', + defaultValue: const CustomExpression('0')); static const VerificationMeta _contentSha256Meta = const VerificationMeta('contentSha256'); - @override late final GeneratedColumn contentSha256 = GeneratedColumn( 'content_sha256', aliasedName, false, type: DriftSqlType.string, requiredDuringInsert: false, - defaultValue: const Constant("")); + $customConstraints: 'NOT NULL DEFAULT \'\'', + defaultValue: const CustomExpression('\'\'')); static const VerificationMeta _contentTypeMeta = const VerificationMeta('contentType'); - @override late final GeneratedColumn contentType = GeneratedColumn( 'content_type', aliasedName, false, type: DriftSqlType.string, requiredDuringInsert: false, - defaultValue: const Constant("")); + $customConstraints: 'NOT NULL DEFAULT \'\'', + defaultValue: const CustomExpression('\'\'')); static const VerificationMeta _permissionsMeta = const VerificationMeta('permissions'); - @override late final GeneratedColumn permissions = GeneratedColumn( 'permissions', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: ''); static const VerificationMeta _publinksMeta = const VerificationMeta('publinks'); - @override late final GeneratedColumn publinks = GeneratedColumn( 'publinks', aliasedName, false, type: DriftSqlType.int, requiredDuringInsert: false, - defaultValue: const Constant(0)); + $customConstraints: 'NOT NULL DEFAULT 0', + defaultValue: const CustomExpression('0')); static const VerificationMeta _lastRefreshMeta = const VerificationMeta('lastRefresh'); - @override late final GeneratedColumn lastRefresh = GeneratedColumn( 'last_refresh', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + $customConstraints: ''); @override List get $columns => [ id, @@ -233,9 +232,12 @@ class $ResourcesTable extends Resources } @override - $ResourcesTable createAlias(String alias) { - return $ResourcesTable(attachedDatabase, alias); + Resources createAlias(String alias) { + return Resources(attachedDatabase, alias); } + + @override + bool get dontWriteConstraints => true; } class Resource extends DataClass implements Insertable { @@ -333,12 +335,12 @@ class Resource extends DataClass implements Insertable { created: serializer.fromJson(json['created']), modified: serializer.fromJson(json['modified']), deleted: serializer.fromJson(json['deleted']), - contentSize: serializer.fromJson(json['contentSize']), - contentSha256: serializer.fromJson(json['contentSha256']), - contentType: serializer.fromJson(json['contentType']), + contentSize: serializer.fromJson(json['content_size']), + contentSha256: serializer.fromJson(json['content_sha256']), + contentType: serializer.fromJson(json['content_type']), permissions: serializer.fromJson(json['permissions']), publinks: serializer.fromJson(json['publinks']), - lastRefresh: serializer.fromJson(json['lastRefresh']), + lastRefresh: serializer.fromJson(json['last_refresh']), ); } @override @@ -352,12 +354,12 @@ class Resource extends DataClass implements Insertable { 'created': serializer.toJson(created), 'modified': serializer.toJson(modified), 'deleted': serializer.toJson(deleted), - 'contentSize': serializer.toJson(contentSize), - 'contentSha256': serializer.toJson(contentSha256), - 'contentType': serializer.toJson(contentType), + 'content_size': serializer.toJson(contentSize), + 'content_sha256': serializer.toJson(contentSha256), + 'content_type': serializer.toJson(contentType), 'permissions': serializer.toJson(permissions), 'publinks': serializer.toJson(publinks), - 'lastRefresh': serializer.toJson(lastRefresh), + 'last_refresh': serializer.toJson(lastRefresh), }; } @@ -657,7 +659,23 @@ class ResourcesCompanion extends UpdateCompanion { abstract class _$AppDatabase extends GeneratedDatabase { _$AppDatabase(QueryExecutor e) : super(e); $AppDatabaseManager get managers => $AppDatabaseManager(this); - late final $ResourcesTable resources = $ResourcesTable(this); + late final Resources resources = Resources(this); + Selectable parents(String id) { + return customSelect( + 'WITH RECURSIVE parents (id, parent, name, permissions) AS (SELECT id, parent, name, permissions FROM resources WHERE id = ?1 UNION ALL SELECT r.id, r.parent, r.name, r.permissions FROM resources AS r JOIN parents AS p ON r.id = p.parent) SELECT * FROM parents', + variables: [ + Variable(id) + ], + readsFrom: { + resources, + }).map((QueryRow row) => ParentsResult( + id: row.read('id'), + parent: row.readNullable('parent'), + name: row.read('name'), + permissions: row.readNullable('permissions'), + )); + } + @override Iterable> get allTables => allSchemaEntities.whereType>(); @@ -665,7 +683,7 @@ abstract class _$AppDatabase extends GeneratedDatabase { List get allSchemaEntities => [resources]; } -typedef $$ResourcesTableCreateCompanionBuilder = ResourcesCompanion Function({ +typedef $ResourcesCreateCompanionBuilder = ResourcesCompanion Function({ required String id, Value parent, required String name, @@ -681,7 +699,7 @@ typedef $$ResourcesTableCreateCompanionBuilder = ResourcesCompanion Function({ Value lastRefresh, Value rowid, }); -typedef $$ResourcesTableUpdateCompanionBuilder = ResourcesCompanion Function({ +typedef $ResourcesUpdateCompanionBuilder = ResourcesCompanion Function({ Value id, Value parent, Value name, @@ -698,27 +716,8 @@ typedef $$ResourcesTableUpdateCompanionBuilder = ResourcesCompanion Function({ Value rowid, }); -final class $$ResourcesTableReferences - extends BaseReferences<_$AppDatabase, $ResourcesTable, Resource> { - $$ResourcesTableReferences(super.$_db, super.$_table, super.$_typedResult); - - static $ResourcesTable _parentTable(_$AppDatabase db) => db.resources - .createAlias($_aliasNameGenerator(db.resources.parent, db.resources.id)); - - $$ResourcesTableProcessedTableManager? get parent { - if ($_item.parent == null) return null; - final manager = $$ResourcesTableTableManager($_db, $_db.resources) - .filter((f) => f.id($_item.parent!)); - final item = $_typedResult.readTableOrNull(_parentTable($_db)); - if (item == null) return manager; - return ProcessedTableManager( - manager.$state.copyWith(prefetchedData: [item])); - } -} - -class $$ResourcesTableFilterComposer - extends Composer<_$AppDatabase, $ResourcesTable> { - $$ResourcesTableFilterComposer({ +class $ResourcesFilterComposer extends Composer<_$AppDatabase, Resources> { + $ResourcesFilterComposer({ required super.$db, required super.$table, super.joinBuilder, @@ -728,6 +727,9 @@ class $$ResourcesTableFilterComposer ColumnFilters get id => $composableBuilder( column: $table.id, builder: (column) => ColumnFilters(column)); + ColumnFilters get parent => $composableBuilder( + column: $table.parent, builder: (column) => ColumnFilters(column)); + ColumnFilters get name => $composableBuilder( column: $table.name, builder: (column) => ColumnFilters(column)); @@ -760,31 +762,10 @@ class $$ResourcesTableFilterComposer ColumnFilters get lastRefresh => $composableBuilder( column: $table.lastRefresh, builder: (column) => ColumnFilters(column)); - - $$ResourcesTableFilterComposer get parent { - final $$ResourcesTableFilterComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.parent, - referencedTable: $db.resources, - getReferencedColumn: (t) => t.id, - builder: (joinBuilder, - {$addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer}) => - $$ResourcesTableFilterComposer( - $db: $db, - $table: $db.resources, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - )); - return composer; - } } -class $$ResourcesTableOrderingComposer - extends Composer<_$AppDatabase, $ResourcesTable> { - $$ResourcesTableOrderingComposer({ +class $ResourcesOrderingComposer extends Composer<_$AppDatabase, Resources> { + $ResourcesOrderingComposer({ required super.$db, required super.$table, super.joinBuilder, @@ -794,6 +775,9 @@ class $$ResourcesTableOrderingComposer ColumnOrderings get id => $composableBuilder( column: $table.id, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get parent => $composableBuilder( + column: $table.parent, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get name => $composableBuilder( column: $table.name, builder: (column) => ColumnOrderings(column)); @@ -827,31 +811,10 @@ class $$ResourcesTableOrderingComposer ColumnOrderings get lastRefresh => $composableBuilder( column: $table.lastRefresh, builder: (column) => ColumnOrderings(column)); - - $$ResourcesTableOrderingComposer get parent { - final $$ResourcesTableOrderingComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.parent, - referencedTable: $db.resources, - getReferencedColumn: (t) => t.id, - builder: (joinBuilder, - {$addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer}) => - $$ResourcesTableOrderingComposer( - $db: $db, - $table: $db.resources, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - )); - return composer; - } } -class $$ResourcesTableAnnotationComposer - extends Composer<_$AppDatabase, $ResourcesTable> { - $$ResourcesTableAnnotationComposer({ +class $ResourcesAnnotationComposer extends Composer<_$AppDatabase, Resources> { + $ResourcesAnnotationComposer({ required super.$db, required super.$table, super.joinBuilder, @@ -861,6 +824,9 @@ class $$ResourcesTableAnnotationComposer GeneratedColumn get id => $composableBuilder(column: $table.id, builder: (column) => column); + GeneratedColumn get parent => + $composableBuilder(column: $table.parent, builder: (column) => column); + GeneratedColumn get name => $composableBuilder(column: $table.name, builder: (column) => column); @@ -893,50 +859,30 @@ class $$ResourcesTableAnnotationComposer GeneratedColumn get lastRefresh => $composableBuilder( column: $table.lastRefresh, builder: (column) => column); - - $$ResourcesTableAnnotationComposer get parent { - final $$ResourcesTableAnnotationComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.parent, - referencedTable: $db.resources, - getReferencedColumn: (t) => t.id, - builder: (joinBuilder, - {$addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer}) => - $$ResourcesTableAnnotationComposer( - $db: $db, - $table: $db.resources, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - )); - return composer; - } } -class $$ResourcesTableTableManager extends RootTableManager< +class $ResourcesTableManager extends RootTableManager< _$AppDatabase, - $ResourcesTable, + Resources, Resource, - $$ResourcesTableFilterComposer, - $$ResourcesTableOrderingComposer, - $$ResourcesTableAnnotationComposer, - $$ResourcesTableCreateCompanionBuilder, - $$ResourcesTableUpdateCompanionBuilder, - (Resource, $$ResourcesTableReferences), + $ResourcesFilterComposer, + $ResourcesOrderingComposer, + $ResourcesAnnotationComposer, + $ResourcesCreateCompanionBuilder, + $ResourcesUpdateCompanionBuilder, + (Resource, BaseReferences<_$AppDatabase, Resources, Resource>), Resource, - PrefetchHooks Function({bool parent})> { - $$ResourcesTableTableManager(_$AppDatabase db, $ResourcesTable table) + PrefetchHooks Function()> { + $ResourcesTableManager(_$AppDatabase db, Resources table) : super(TableManagerState( db: db, table: table, createFilteringComposer: () => - $$ResourcesTableFilterComposer($db: db, $table: table), + $ResourcesFilterComposer($db: db, $table: table), createOrderingComposer: () => - $$ResourcesTableOrderingComposer($db: db, $table: table), + $ResourcesOrderingComposer($db: db, $table: table), createComputedFieldComposer: () => - $$ResourcesTableAnnotationComposer($db: db, $table: table), + $ResourcesAnnotationComposer($db: db, $table: table), updateCompanionCallback: ({ Value id = const Value.absent(), Value parent = const Value.absent(), @@ -1002,65 +948,41 @@ class $$ResourcesTableTableManager extends RootTableManager< rowid: rowid, ), withReferenceMapper: (p0) => p0 - .map((e) => ( - e.readTable(table), - $$ResourcesTableReferences(db, table, e) - )) + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) .toList(), - prefetchHooksCallback: ({parent = false}) { - return PrefetchHooks( - db: db, - explicitlyWatchedTables: [], - addJoins: < - T extends TableManagerState< - dynamic, - dynamic, - dynamic, - dynamic, - dynamic, - dynamic, - dynamic, - dynamic, - dynamic, - dynamic, - dynamic>>(state) { - if (parent) { - state = state.withJoin( - currentTable: table, - currentColumn: table.parent, - referencedTable: - $$ResourcesTableReferences._parentTable(db), - referencedColumn: - $$ResourcesTableReferences._parentTable(db).id, - ) as T; - } - - return state; - }, - getPrefetchedDataCallback: (items) async { - return []; - }, - ); - }, + prefetchHooksCallback: null, )); } -typedef $$ResourcesTableProcessedTableManager = ProcessedTableManager< +typedef $ResourcesProcessedTableManager = ProcessedTableManager< _$AppDatabase, - $ResourcesTable, + Resources, Resource, - $$ResourcesTableFilterComposer, - $$ResourcesTableOrderingComposer, - $$ResourcesTableAnnotationComposer, - $$ResourcesTableCreateCompanionBuilder, - $$ResourcesTableUpdateCompanionBuilder, - (Resource, $$ResourcesTableReferences), + $ResourcesFilterComposer, + $ResourcesOrderingComposer, + $ResourcesAnnotationComposer, + $ResourcesCreateCompanionBuilder, + $ResourcesUpdateCompanionBuilder, + (Resource, BaseReferences<_$AppDatabase, Resources, Resource>), Resource, - PrefetchHooks Function({bool parent})>; + PrefetchHooks Function()>; class $AppDatabaseManager { final _$AppDatabase _db; $AppDatabaseManager(this._db); - $$ResourcesTableTableManager get resources => - $$ResourcesTableTableManager(_db, _db.resources); + $ResourcesTableManager get resources => + $ResourcesTableManager(_db, _db.resources); +} + +class ParentsResult { + final String id; + final String? parent; + final String name; + final String? permissions; + ParentsResult({ + required this.id, + this.parent, + required this.name, + this.permissions, + }); } diff --git a/client/lib/libphylum/db/resources.dart b/client/lib/libphylum/db/resources.dart deleted file mode 100644 index c8e05f0c..00000000 --- a/client/lib/libphylum/db/resources.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:drift/drift.dart'; - -class Resources extends Table { - TextColumn get id => text()(); - TextColumn get parent => text().nullable().references(Resources, #id)(); - TextColumn get name => text()(); - BoolColumn get dir => boolean()(); - DateTimeColumn get created => dateTime().nullable()(); - DateTimeColumn get modified => dateTime().nullable()(); - BoolColumn get deleted => boolean().withDefault(const Constant(false))(); - IntColumn get contentSize => integer().withDefault(const Constant(0))(); - TextColumn get contentSha256 => text().withDefault(const Constant(""))(); - TextColumn get contentType => text().withDefault(const Constant(""))(); - TextColumn get permissions => text().nullable()(); - IntColumn get publinks => integer().withDefault(const Constant(0))(); - DateTimeColumn get lastRefresh => dateTime().nullable()(); - - @override - Set get primaryKey => {id}; - - // @override - // List>>? get uniqueKeys => [ - // {parent, name} - // ]; -} diff --git a/client/lib/libphylum/db/resources.drift b/client/lib/libphylum/db/resources.drift new file mode 100644 index 00000000..082a3d54 --- /dev/null +++ b/client/lib/libphylum/db/resources.drift @@ -0,0 +1,25 @@ +CREATE TABLE IF NOT EXISTS "resources"( + "id" TEXT NOT NULL PRIMARY KEY, + "parent" TEXT REFERENCES resources (id), + "name" TEXT NOT NULL, + "dir" BOOLEAN NOT NULL CHECK ("dir" IN (0, 1)), + "created" DATETIME, + "modified" DATETIME, + "deleted" BOOLEAN NOT NULL DEFAULT 0 CHECK ("deleted" IN (0, 1)), + "content_size" INTEGER NOT NULL DEFAULT 0, + "content_sha256" TEXT NOT NULL DEFAULT '', + "content_type" TEXT NOT NULL DEFAULT '', + "permissions" TEXT, + "publinks" INTEGER NOT NULL DEFAULT 0, + "last_refresh" DATETIME +); +parents: WITH RECURSIVE parents(id, parent, name, permissions) AS ( + SELECT id, parent, name, permissions + FROM resources + WHERE id = :id + UNION ALL + SELECT r.id, r.parent, r.name, r.permissions + FROM resources r + JOIN parents p + ON r.id = p.parent +) SELECT * from parents; \ No newline at end of file diff --git a/client/lib/libphylum/repositories/resource_repository.dart b/client/lib/libphylum/repositories/resource_repository.dart index 65bdb911..3e3928f5 100644 --- a/client/lib/libphylum/repositories/resource_repository.dart +++ b/client/lib/libphylum/repositories/resource_repository.dart @@ -34,15 +34,15 @@ class ResourceRepository { return (_selectChildren(id)..orderBy([(u) => OrderingTerm.desc(u.dir), (u) => OrderingTerm.asc(u.name.collate(Collate.noCase))])).watch(); } - SimpleSelectStatement<$ResourcesTable, Resource> _selectResource(String id) { + SimpleSelectStatement _selectResource(String id) { return account.db.resources.select()..where((f) => f.id.equals(id) & f.deleted.equals(false)); } - SimpleSelectStatement<$ResourcesTable, Resource> _selectChildren(String id) { + SimpleSelectStatement _selectChildren(String id) { return account.db.resources.select()..where((f) => f.parent.equals(id) & f.deleted.equals(false)); } - SimpleSelectStatement<$ResourcesTable, Resource> _selectResources(Iterable ids) { + SimpleSelectStatement _selectResources(Iterable ids) { return account.db.resources.select()..where((f) => f.id.isIn(ids)); } @@ -64,7 +64,7 @@ class ResourceRepository { ); } - Future updateResource(String id, Insertable Function($$ResourcesTableUpdateCompanionBuilder o) fn) { + Future updateResource(String id, Insertable Function($ResourcesUpdateCompanionBuilder o) fn) { return account.db.managers.resources.filter((f) => f.id.equals(id)).update(fn); }