Skip to content

Commit

Permalink
add: count & receive
Browse files Browse the repository at this point in the history
wip add: DatabaseTupleRepository

wip #377
  • Loading branch information
zin- committed Aug 16, 2024
1 parent 87975dd commit a6f7cc6
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 6 deletions.
135 changes: 135 additions & 0 deletions integration_test/framework/database_tuple_repository_tests.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:mem/databases/table_definitions/base.dart';
import 'package:mem/framework/database/definition/column/boolean_column_definition.dart';
import 'package:mem/framework/database/definition/database_definition.dart';
import 'package:mem/framework/database/definition/table_definition.dart';
import 'package:mem/framework/database/factory.dart';
import 'package:mem/framework/repository/condition/conditions.dart';
import 'package:mem/framework/repository/database_tuple_repository.dart';

import '../../test/framework/repository/database_tuple_entity_test.dart';
import '../../test/framework/repository/entity_test.dart';

const _name = "DatabaseTupleRepository tests";

final _defColA = BooleanColumnDefinition(TestObjectEntity.fieldNames[0]);
final _defTableTestObject =
TableDefinition('test_object', [_defColA, ...defColsBase]);
final _defDbTest = DatabaseDefinition('test_db', 1, [_defTableTestObject]);

class _TestObjectRepository extends DatabaseTupleRepository<TestObjectEntity> {
_TestObjectRepository() : super(_defDbTest, _defTableTestObject);

@override
TestObjectEntity pack(Map<String, dynamic> map) =>
TestObjectDatabaseTupleEntity.fromMap(map);
}

void main() => group(
_name,
() {
late String databasePath;
setUpAll(
() async {
databasePath =
await DatabaseFactory.buildDatabasePath(_defDbTest.name);

await DatabaseFactory
// ignore: deprecated_member_use_from_same_package
.nativeFactory
.deleteDatabase(databasePath);
},
);

test(
'#new',
() async {
_TestObjectRepository();

expect(
await DatabaseFactory
// ignore: deprecated_member_use_from_same_package
.nativeFactory
.databaseExists(databasePath),
false);
},
);

group(
'operations',
() {
final repository = _TestObjectRepository();

group(
'#count',
() {
setUpAll(
() async {
final falseSample = TestObjectEntity(false);
final trueSample = TestObjectEntity(true);
final now = DateTime.now();

final dbA = await DatabaseFactory.open(_defDbTest);

await dbA.delete(_defTableTestObject);
await dbA.insert(_defTableTestObject,
falseSample.toMap..addAll({defColCreatedAt.name: now}));
await dbA.insert(_defTableTestObject,
falseSample.toMap..addAll({defColCreatedAt.name: now}));
await dbA.insert(_defTableTestObject,
trueSample.toMap..addAll({defColCreatedAt.name: now}));
},
);

test(
': all.',
() async {
final count = await repository.count();

expect(count, 3);
},
);
test(
': condition.',
() async {
final count = await repository.count(
condition: Equals(_defColA.name, false));

expect(count, 2);
},
);
},
);

group(
'#receive',
() {
setUpAll(
() async {
final dbA = await DatabaseFactory.open(_defDbTest);

await dbA.delete(_defTableTestObject);
},
);

test(
': received.',
() async {
final now = DateTime.now();
final entity = TestObjectEntity(false);

final received =
await repository.receive(entity, createdAt: now);

expect(
received,
equals(TestObjectDatabaseTupleEntity(entity.a).withMap(
{defPkId.name: 1, defColCreatedAt.name: now})));
},
);
},
);
},
);
},
);
3 changes: 3 additions & 0 deletions integration_test/framework/framework_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import 'database_factory_tests.dart' as database_factory_tests;
import 'database_repository_tests.dart' as database_repository_tests;
import 'database_tuple_repository_tests_v1.dart'
as database_tuple_repository_tests_v1;
import 'database_tuple_repository_tests.dart'
as database_tuple_repository_tests;

const _name = "Framework test";

Expand All @@ -23,5 +25,6 @@ void main() => group(
database_repository_tests.main();

database_tuple_repository_tests_v1.main();
database_tuple_repository_tests.main();

Check failure on line 28 in integration_test/framework/framework_test.dart

View workflow job for this annotation

GitHub Actions / Report (Medium test (Windows) (framework))

integration_test/framework/framework_test.dart ► Framework test DatabaseTupleRepository tests operations #count ► : condition.

Failed test found in: reports/test_report.log Error: SqfliteFfiException(error, Invalid argument(s): Invalid sql argument type 'bool': false}) DatabaseException(Invalid argument(s): Invalid sql argument type 'bool': false)
Raw output
[T] TIME: 2024-08-16T13:37:21.517736 DatabaseTupleRepository.count [start] :: {
  condition: a = false,
}
[T] TIME: 2024-08-16T13:37:21.518739 DatabaseAccessor.count [start] :: {
  tableDefinition: TableDefinition: {name: test_object, columnDefinitions: (BooleanColumnDefinition: {name: a, type: INTEGER, notNull: true, isPrimaryKey: false}, IntegerColumnDefinition: {name: id, type: INTEGER, notNull: true, isPrimaryKey: true}, TimestampColumnDefinition: {name: createdAt, type: TIMESTAMP, notNull: true, isPrimaryKey: false}, TimestampColumnDefinition: {name: updatedAt, type: TIMESTAMP, notNull: false, isPrimaryKey: false}, TimestampColumnDefinition: {name: archivedAt, type: TIMESTAMP, notNull: false, isPrimaryKey: false}), singularName: null},
  where: a = ?,
  whereArgs: [
    false,
  ],
}
*** WARNING ***

Invalid argument false with type bool.
Only num, String and Uint8List are supported. See https://github.com/tekartik/sqflite/blob/master/sqflite/doc/supported_types.md for details

This will throw an exception in the future. For now it is displayed once per type.

    
[E] TIME: 2024-08-16T13:37:21.523743 responseToResultOrThrow [error] !!  ERROR: SqfliteFfiException(error, Invalid argument(s): Invalid sql argument type 'bool': false}) DatabaseException(Invalid argument(s): Invalid sql argument type 'bool': false)
[E] TIME: 2024-08-16T13:37:21.524741 responseToResultOrThrow [error] !!  ERROR: SqfliteFfiException(error, Invalid argument(s): Invalid sql argument type 'bool': false}) DatabaseException(Invalid argument(s): Invalid sql argument type 'bool': false)
package:sqflite_common_ffi/src/method_call.dart 125:9                                                           responseToResultOrThrow
package:sqflite_common_ffi/src/isolate.dart 33:12                                                               SqfliteIsolate.handle
===== asynchronous gap ===========================
package:stream_channel                                                                                          _GuaranteeSink.add
c:/Users/RUNNER~1/AppData/Local/Temp/flutter_tools.eec78bb6/flutter_test_listener.1fb71642/listener.dart 53:22  main.<fn>
},
);
63 changes: 63 additions & 0 deletions lib/framework/repository/database_tuple_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import 'package:mem/databases/table_definitions/base.dart';
import 'package:mem/framework/database/accessor.dart';
import 'package:mem/framework/database/definition/database_definition.dart';
import 'package:mem/framework/database/definition/table_definition.dart';
import 'package:mem/framework/repository/condition/conditions.dart';
import 'package:mem/framework/repository/database_repository.dart';
import 'package:mem/framework/repository/entity.dart';
import 'package:mem/framework/repository/repository.dart';
import 'package:mem/logger/log_service.dart';

// FIXME byIdの引数の型のためにSavedEntityの型以外にIが必要になっている
// Rにidの型情報が含まれているのに改めて渡す必要があるのはおかしい
// DatabaseTupleに型情報を付与することでズレは発生しなくなった
// ただ、これだと未保存のDatabaseTupleが
// FIXME SavedEntityはSavedDatabaseTupleをmixinしている必要があるが型制約を定義できていない
abstract class DatabaseTupleRepository<E extends Entity> extends Repository<E> {
final DatabaseDefinition _databaseDefinition;
final TableDefinition _tableDefinition;

DatabaseTupleRepository(this._databaseDefinition, this._tableDefinition);

DatabaseAccessor? _databaseAccessor;

late final Future<DatabaseAccessor> _dbA = (() async => _databaseAccessor ??=
await DatabaseRepository().receive(_databaseDefinition))();

Future<int> count({
Condition? condition,
}) =>
v(
() async => (await _dbA).count(
_tableDefinition,
where: condition?.where(),
whereArgs: condition?.whereArgs(),
),
{
'condition': condition,
},
);

E pack(Map<String, dynamic> map);

Future<E> receive(E entity, {DateTime? createdAt}) => v(
() async {
final entityMap = entity.toMap;

entityMap[defColCreatedAt.name] = createdAt ?? DateTime.now();

final id = await _databaseAccessor!.insert(
_tableDefinition,
entityMap,
);

entityMap[defPkId.name] = id;

return pack(entityMap);
},
{
'entity': entity,
'createdAt': createdAt,
},
);
}
15 changes: 15 additions & 0 deletions lib/framework/repository/entity.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@ abstract class EntityV1 {}

mixin Entity {
Map<String, dynamic> get toMap;

@override
String toString() => "${super.toString()}: $toMap";

@override
int get hashCode => toMap.entries.fold(
0,
(value, element) =>
value ^ element.key.hashCode ^ element.value.hashCode,
);

@override
bool operator ==(Object other) =>
identical(this, other) ||
(runtimeType == other.runtimeType && hashCode == other.hashCode);
}
// memo
// - view, domain, dataのそれぞれの領域で似た内容でも型が変わることになるはず
Expand Down
2 changes: 2 additions & 0 deletions lib/framework/repository/repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ mixin Discarder<E extends EntityV2> on RepositoryV2<E> {
abstract class RepositoryV1<E extends EntityV1, Result> {
Future<Result> receive(E entity);
}

abstract class Repository<E extends Entity> {}
12 changes: 6 additions & 6 deletions test/framework/repository/database_tuple_entity_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import 'entity_test.dart';

const _name = 'DatabaseTupleEntity test';

class _TestObjectDatabaseTupleEntity extends TestObjectEntity
class TestObjectDatabaseTupleEntity extends TestObjectEntity
with DatabaseTupleEntity<int> {
_TestObjectDatabaseTupleEntity(super.a);
TestObjectDatabaseTupleEntity(super.a);

_TestObjectDatabaseTupleEntity.fromMap(Map<String, dynamic> map)
TestObjectDatabaseTupleEntity.fromMap(Map<String, dynamic> map)
: super.fromMap(map) {
withMap(map);
}
Expand All @@ -24,7 +24,7 @@ void main() => group(
() {
const a = false;

final testObject = _TestObjectDatabaseTupleEntity(a);
final testObject = TestObjectDatabaseTupleEntity(a);

expect(testObject.a, equals(a));
},
Expand All @@ -41,7 +41,7 @@ void main() => group(
defColArchivedAt.name: null
};

final testObject = _TestObjectDatabaseTupleEntity.fromMap(map);
final testObject = TestObjectDatabaseTupleEntity.fromMap(map);

expect(testObject.a, map[TestObjectEntity.fieldNames[0]]);
},
Expand All @@ -58,7 +58,7 @@ void main() => group(
defColArchivedAt.name: null
};

final testObject = _TestObjectDatabaseTupleEntity.fromMap(map);
final testObject = TestObjectDatabaseTupleEntity.fromMap(map);

expect(testObject.toMap, map);
},
Expand Down
13 changes: 13 additions & 0 deletions test/framework/repository/entity_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,18 @@ void main() => group(
testObject.toMap, equals({TestObjectEntity.fieldNames[0]: a}));
},
);

test(
'#==',
() {
const a = false;
const b = false;

final testObjectA = TestObjectEntity(a);
final testObjectB = TestObjectEntity(b);

expect(testObjectA, equals(testObjectB));
},
);
},
);

0 comments on commit a6f7cc6

Please sign in to comment.