-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from a-givertzman/Schema-read/write
Schema read/write
- Loading branch information
Showing
17 changed files
with
736 additions
and
258 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import 'package:ext_rw/src/sql/sql.dart'; | ||
|
||
typedef SqlBuilder<T> = Sql Function(Sql sql, T entry); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import 'package:ext_rw/ext_rw.dart'; | ||
import 'package:hmi_core/hmi_core_failure.dart'; | ||
import 'package:hmi_core/hmi_core_log.dart'; | ||
import 'package:hmi_core/hmi_core_result_new.dart'; | ||
|
||
class SqlRead<T extends SchemaEntry, P> implements SchemaRead<T, P> { | ||
late final Log _log; | ||
final ApiAddress _address; | ||
final String _authToken; | ||
final String _database; | ||
final bool _keepAlive; | ||
final bool _debug; | ||
final SqlBuilder<P> _sqlBuilder; | ||
final Map<T, Function> _entryFromFactories; | ||
Sql _sql = Sql(sql: ''); | ||
/// | ||
/// | ||
SqlRead({ | ||
required ApiAddress address, | ||
required String authToken, | ||
required String database, | ||
bool keepAlive = false, | ||
bool debug = false, | ||
required SqlBuilder<P> sqlBuilder, | ||
required Map<T, Function> entryFromFactories, | ||
}) : | ||
_address = address, | ||
_authToken = authToken, | ||
_database = database, | ||
_keepAlive = keepAlive, | ||
_debug = debug, | ||
_sqlBuilder = sqlBuilder, | ||
_entryFromFactories = entryFromFactories { | ||
_log = Log("$runtimeType"); | ||
} | ||
// | ||
// | ||
@override | ||
Future<Result<List<T>, Failure>> fetch(P params) { | ||
_sql = _sqlBuilder(_sql, params); | ||
return _fetch(_sql); | ||
} | ||
/// | ||
/// Fetchs data with new [sql] | ||
Future<Result<List<T>, Failure>> _fetch(Sql sql) { | ||
final request = ApiRequest( | ||
address: _address, | ||
authToken: _authToken, | ||
debug: _debug, | ||
query: SqlQuery( | ||
database: _database, | ||
sql: sql.build(), | ||
keepAlive: _keepAlive, | ||
), | ||
); | ||
_log.debug("._fetch | request: $request"); | ||
return request.fetch().then((result) { | ||
return switch (result) { | ||
Ok(value :final reply) => () { | ||
if (reply.hasError) { | ||
return Err<List<T>, Failure>(Failure(message: reply.error.message, stackTrace: StackTrace.current)); | ||
} else { | ||
final List<T> entries = []; | ||
final rows = reply.data; | ||
for (final row in rows) { | ||
final entry = _makeEntry(row); | ||
entries.add(entry); | ||
} | ||
return Ok<List<T>, Failure>(entries); | ||
} | ||
}(), | ||
Err(:final error) => Err<List<T>, Failure>(error), | ||
}; | ||
}); | ||
} | ||
/// | ||
/// | ||
T _makeEntry(Map<String, dynamic> row) { | ||
final constructor = _entryFromFactories[T]; | ||
if (constructor != null) { | ||
return constructor(row); | ||
} | ||
throw Failure( | ||
message: "$runtimeType._makeEntry | Can't find constructor for $T", | ||
stackTrace: StackTrace.current, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
import 'package:ext_rw/ext_rw.dart'; | ||
import 'package:hmi_core/hmi_core_failure.dart'; | ||
import 'package:hmi_core/hmi_core_log.dart'; | ||
import 'package:hmi_core/hmi_core_result_new.dart'; | ||
|
||
class SqlWrite<T extends SchemaEntry> implements SchemaWrite<T> { | ||
late final Log _log; | ||
final ApiAddress _address; | ||
final String _authToken; | ||
final String _database; | ||
final bool _keepAlive; | ||
final bool _debug; | ||
final SqlBuilder<T>? _insertSqlBuilder; | ||
final SqlBuilder<T>? _updateSqlBuilder; | ||
final SqlBuilder<T>? _deleteSqlBuilder; | ||
final Map<T, Function> _entryFromFactories; | ||
final Map<T, Function> _entryEmptyFactories; | ||
/// | ||
/// | ||
SqlWrite({ | ||
required ApiAddress address, | ||
required String authToken, | ||
required String database, | ||
bool keepAlive = false, | ||
bool debug = false, | ||
SqlBuilder<T>? insertSqlBuilder, | ||
SqlBuilder<T>? updateSqlBuilder, | ||
SqlBuilder<T>? deleteSqlBuilder, | ||
required Map<T, Function> entryFromFactories, | ||
required Map<T, Function> entryEmptyFactories, | ||
}) : | ||
_address = address, | ||
_authToken = authToken, | ||
_database = database, | ||
_keepAlive = keepAlive, | ||
_debug = debug, | ||
_insertSqlBuilder = insertSqlBuilder, | ||
_updateSqlBuilder = updateSqlBuilder, | ||
_deleteSqlBuilder = deleteSqlBuilder, | ||
_entryFromFactories = entryFromFactories, | ||
_entryEmptyFactories = entryEmptyFactories { | ||
_log = Log("$runtimeType"); | ||
} | ||
// | ||
// | ||
@override | ||
Future<Result<T, Failure>> insert(T? entry) { | ||
T entry_; | ||
if (entry != null) { | ||
entry_ = entry; | ||
} else { | ||
entry_ = _makeEmptyEntry(); | ||
} | ||
final builder = _insertSqlBuilder; | ||
if (builder != null) { | ||
final initialSql = Sql(sql: ''); | ||
final sql = builder(initialSql, entry_); | ||
return _fetchWith(sql).then((result) { | ||
return switch(result) { | ||
Ok() => () { | ||
return Ok<T, Failure>(entry_); | ||
}(), | ||
Err(:final error) => () { | ||
return Err<T, Failure>(error); | ||
}(), | ||
}; | ||
}); | ||
} | ||
return Future.value( | ||
Err(Failure( | ||
message: "$runtimeType.insert | insertSqlBuilder is not initialized", | ||
stackTrace: StackTrace.current, | ||
)), | ||
); | ||
} | ||
// | ||
// | ||
@override | ||
Future<Result<void, Failure>> update(T entry) { | ||
final builder = _updateSqlBuilder; | ||
if (builder != null) { | ||
final initialSql = Sql(sql: ''); | ||
final sql = builder(initialSql, entry); | ||
return _fetchWith(sql).then((result) { | ||
return switch(result) { | ||
Ok() => () { | ||
return const Ok<void, Failure>(null); | ||
}(), | ||
Err(:final error) => () { | ||
return Err<void, Failure>(error); | ||
}(), | ||
}; | ||
}); | ||
} | ||
return Future.value( | ||
Err(Failure( | ||
message: "$runtimeType.update | updateSqlBuilder is not initialized", | ||
stackTrace: StackTrace.current, | ||
)), | ||
); | ||
} | ||
// | ||
// | ||
@override | ||
Future<Result<void, Failure>> delete(T entry) { | ||
final builder = _deleteSqlBuilder; | ||
if (builder != null) { | ||
final initialSql = Sql(sql: ''); | ||
final sql = builder(initialSql, entry); | ||
return _fetchWith(sql).then((result) { | ||
return switch(result) { | ||
Ok() => () { | ||
return const Ok<void, Failure>(null); | ||
}(), | ||
Err(:final error) => () { | ||
return Err<void, Failure>(error); | ||
}(), | ||
}; | ||
}); | ||
} | ||
return Future.value( | ||
Err(Failure( | ||
message: "$runtimeType.delete | deleteSqlBuilder is not initialized", | ||
stackTrace: StackTrace.current, | ||
)), | ||
); | ||
} | ||
/// | ||
/// Fetchs data with new [sql] | ||
Future<Result<List<T>, Failure>> _fetchWith(Sql sql) { | ||
final request = ApiRequest( | ||
address: _address, | ||
authToken: _authToken, | ||
debug: _debug, | ||
query: SqlQuery( | ||
database: _database, | ||
sql: sql.build(), | ||
keepAlive: _keepAlive, | ||
), | ||
); | ||
_log.debug("._fetchWith | request: $request"); | ||
return request.fetch().then((result) { | ||
return switch (result) { | ||
Ok(:final value) => () { | ||
final reply = value; | ||
if (reply.hasError) { | ||
return Err<List<T>, Failure>(Failure(message: reply.error.message, stackTrace: StackTrace.current)); | ||
} else { | ||
final List<T> entries = []; | ||
final rows = reply.data; | ||
for (final row in rows) { | ||
final entry = _makeEntry(row); | ||
entries.add(entry); | ||
} | ||
return Ok<List<T>, Failure>(entries); | ||
} | ||
}(), | ||
Err(:final error) => Err<List<T>, Failure>(error), | ||
}; | ||
}); | ||
} | ||
/// | ||
/// | ||
T _makeEmptyEntry() { | ||
final constructor = _entryEmptyFactories[T]; | ||
if (constructor != null) { | ||
return constructor(); | ||
} else { | ||
throw Failure( | ||
message: "$runtimeType._makeEntry | Can't find constructor for $T", | ||
stackTrace: StackTrace.current, | ||
); | ||
} | ||
} | ||
/// | ||
/// | ||
T _makeEntry(Map<String, dynamic> row) { | ||
final constructor = _entryFromFactories[T]; | ||
if (constructor != null) { | ||
return constructor(row); | ||
} | ||
throw Failure( | ||
message: "$runtimeType._makeEntry | Can't find constructor for $T", | ||
stackTrace: StackTrace.current, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,7 @@ | ||
abstract class ApiQueryType { | ||
bool valid(); | ||
/// | ||
String buildJson(); | ||
/// | ||
String get authToken; | ||
String buildJson({String authToken = '', bool debug = false}); | ||
/// | ||
String get id; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.