Updated DateTime to non UTC

This commit is contained in:
thomashii@dukefirehawk.com 2022-07-16 10:44:49 +08:00
parent f0a5e7c6fc
commit 793a8ac115
13 changed files with 141 additions and 40 deletions

View file

@ -0,0 +1,20 @@
version: "3.8"
services:
mariadb:
image: mariadb:latest
restart: "no"
ports:
- "3306:3306"
environment:
- MARIADB_ROOT_PASSWORD=Qwerty
volumes:
- "mariadb:/var/lib/mysql"
networks:
- webnet
volumes:
mariadb:
driver: local
networks:
webnet:

View file

@ -0,0 +1,20 @@
version: "3.8"
services:
mysql:
image: mysql:latest
restart: "no"
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=Qwerty
volumes:
- "mysql:/var/lib/mysql"
networks:
- webnet
volumes:
mysql:
driver: local
networks:
webnet:

View file

@ -2,7 +2,7 @@ version: "3.8"
services: services:
pgdb: pgdb:
image: postgres:latest image: postgres:latest
restart: always restart: "no"
ports: ports:
- "5432:5432" - "5432:5432"
environment: environment:
@ -12,7 +12,6 @@ services:
- "db:/var/lib/postgresql/data" - "db:/var/lib/postgresql/data"
networks: networks:
- webnet - webnet
volumes: volumes:
db: db:
driver: local driver: local

View file

@ -0,0 +1,21 @@
version: "3.8"
services:
redis:
image: redis:latest
restart: "no"
ports:
- "5432:5432"
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
volumes:
- "redis:/data"
networks:
- webnet
volumes:
redis:
driver: local
networks:
webnet:

View file

@ -23,7 +23,7 @@ class MariaDbSchema extends Schema {
_log.severe('Failed to run query: [ $sql ]', e); _log.severe('Failed to run query: [ $sql ]', e);
throw e; throw e;
}); });
affectedRows = result?.affectedRows ?? 0; affectedRows = result.affectedRows ?? 0;
}); });
return affectedRows; return affectedRows;

View file

@ -371,7 +371,7 @@ abstract class Query<T, Where extends QueryWhere> extends QueryBase<T> {
var insertion = values?.compileInsert(this, tableName); var insertion = values?.compileInsert(this, tableName);
if (insertion == '') { if (insertion == '') {
throw StateError('No values have been specified for update.'); throw StateError('No values have been specified for insertion.');
} else { } else {
var sql = compile({}); var sql = compile({});
var returningSql = ''; var returningSql = '';

View file

@ -16,7 +16,7 @@ abstract class QueryValues {
String compileInsert(Query query, String tableName) { String compileInsert(Query query, String tableName) {
var data = Map<String, dynamic>.from(toMap()); var data = Map<String, dynamic>.from(toMap());
var now = DateTime.now().toUtc(); var now = DateTime.now();
if (data.containsKey('created_at') && data['created_at'] == null) { if (data.containsKey('created_at') && data['created_at'] == null) {
data['created_at'] = now; data['created_at'] = now;
} }
@ -71,7 +71,7 @@ abstract class QueryValues {
if (data.isEmpty) { if (data.isEmpty) {
return ''; return '';
} }
var now = DateTime.now().toUtc(); var now = DateTime.now();
if (data.containsKey('created_at') && data['created_at'] == null) { if (data.containsKey('created_at') && data['created_at'] == null) {
data.remove('created_at'); data.remove('created_at');
} }

View file

@ -7,8 +7,8 @@
This package contains the SQL Executor required by Angel3 ORM to work with MySQL and MariaDB respectively. In order to better support the differences in MySQL and MariaDb underlying protocols, two different drives have to be used. For MariaDb 10.2.x, `mysql1` driver provides the best results, while `mysql_client` driver handles MySQL 8.x.x without issues. This package contains the SQL Executor required by Angel3 ORM to work with MySQL and MariaDB respectively. In order to better support the differences in MySQL and MariaDb underlying protocols, two different drives have to be used. For MariaDb 10.2.x, `mysql1` driver provides the best results, while `mysql_client` driver handles MySQL 8.x.x without issues.
* MariaDbExecutor (beta) * MariaDbExecutor
* MySqlExecutor (beta) * MySqlExecutor
## Supported database version ## Supported database version
@ -26,8 +26,8 @@ This package contains the SQL Executor required by Angel3 ORM to work with MySQL
host: 'localhost', host: 'localhost',
port: 3306, port: 3306,
db: 'orm_test', db: 'orm_test',
user: 'Test', user: 'test',
password: 'Test123*'); password: 'test123');
var connection = await MySqlConnection.connect(settings); var connection = await MySqlConnection.connect(settings);
var logger = Logger('orm_mariadb'); var logger = Logger('orm_mariadb');
@ -44,7 +44,7 @@ This package contains the SQL Executor required by Angel3 ORM to work with MySQL
port: 3306, port: 3306,
databaseName: "orm_test", databaseName: "orm_test",
userName: "test", userName: "test",
password: "Test123*", password: "test123",
secure: false); secure: false);
var logger = Logger('orm_mysql'); var logger = Logger('orm_mysql');
@ -52,8 +52,48 @@ This package contains the SQL Executor required by Angel3 ORM to work with MySQL
var executor = MySqlExecutor(connection, logger: logger); var executor = MySqlExecutor(connection, logger: logger);
``` ```
### Issues
* Blob
* DateTime value not in UTC
* Transaction is broken
## Creating a new database in MariaDB/MySQL
1. Login to MariaDB/MySQL database console with the following command.
```bash
mysql -u root -p
```
1. Run the following commands to create a new database, `orm_test` and grant both local and remote access to user, `test`. Replace `orm_test`, `test` and `test123` with your own database name, username and password respectively.
```mysql
create database orm_test;
create user 'test'@'localhost' identified by 'test123';
grant all privileges on orm_test.* to 'test'@'localhost';
create user 'test'@'%' identified by 'test123';
grant all privileges on orm_test.* to 'test'@'%';
```
## Known limitation ## Known limitation
* UTC time is not supported ### Using `mysql1` driver on MariabDb
* Blob
* DateTime value not in UTC
* Transaction is broken
### Using `mysql1` driver on MySQL
* Blob is not supported * Blob is not supported
### Using `mysql_client` driver on MariabDb
* Blob is not supported
### Using `mysql_client` driver on MySQL
* Blob is not supported

View file

@ -13,8 +13,8 @@ part 'main.g.dart';
void main() async { void main() async {
//hierarchicalLoggingEnabled = true; //hierarchicalLoggingEnabled = true;
//await mariaDBExample(); await mariaDBExample();
await mysqlExample(); //await mysqlExample();
exit(0); exit(0);
} }
@ -28,8 +28,8 @@ Future<void> mariaDBExample() async {
host: 'localhost', host: 'localhost',
port: 3306, port: 3306,
db: 'orm_test', db: 'orm_test',
user: 'Test', user: 'test',
password: 'Test123*'); password: 'test123');
var connection = await MySqlConnection.connect(settings); var connection = await MySqlConnection.connect(settings);
print("Connected to MariaDb"); print("Connected to MariaDb");
@ -61,7 +61,7 @@ Future<void> mysqlExample() async {
port: 3306, port: 3306,
databaseName: "orm_test", databaseName: "orm_test",
userName: "test", userName: "test",
password: "Test123*", password: "test123",
secure: false); secure: false);
print("Connected to MySQL"); print("Connected to MySQL");

View file

@ -34,9 +34,9 @@ class MariaDbExecutor extends QueryExecutor {
var params = substitutionValues.values.toList(); var params = substitutionValues.values.toList();
//logger?.warning('Query: $query'); logger.warning('Query: $query');
//logger?.warning('Values: $params'); logger.warning('Values: $params');
//logger?.warning('Returning Query: $returningQuery'); logger.warning('Returning Query: $returningQuery');
if (returningQuery.isNotEmpty) { if (returningQuery.isNotEmpty) {
// Handle insert, update and delete // Handle insert, update and delete
@ -66,6 +66,7 @@ class MariaDbExecutor extends QueryExecutor {
@override @override
Future<T> transaction<T>(FutureOr<T> Function(QueryExecutor) f) async { Future<T> transaction<T>(FutureOr<T> Function(QueryExecutor) f) async {
T? returnValue = await _connection.transaction((ctx) async { T? returnValue = await _connection.transaction((ctx) async {
// TODO: This is broken
var conn = ctx as MySqlConnection; var conn = ctx as MySqlConnection;
try { try {
logger.fine('Entering transaction'); logger.fine('Entering transaction');

View file

@ -17,18 +17,18 @@ dev_dependencies:
build_runner: ^2.0.1 build_runner: ^2.0.1
test: ^1.21.0 test: ^1.21.0
lints: ^1.0.0 lints: ^1.0.0
# dependency_overrides: dependency_overrides:
# angel3_serialize: # angel3_serialize:
# path: ../../serialize/angel_serialize # path: ../../serialize/angel_serialize
# angel3_serialize_generator: # angel3_serialize_generator:
# path: ../../serialize/angel_serialize_generator # path: ../../serialize/angel_serialize_generator
# angel3_model: # angel3_model:
# path: ../../model # path: ../../model
# angel3_orm_test: angel3_orm_test:
# path: ../angel_orm_test path: ../angel_orm_test
# angel3_orm: angel3_orm:
# path: ../angel_orm path: ../angel_orm
# angel3_orm_generator: # angel3_orm_generator:
# path: ../angel_orm_generator # path: ../angel_orm_generator
# angel3_migration: angel3_migration:
# path: ../angel_migration path: ../angel_migration

View file

@ -10,14 +10,14 @@ List tmpTables = [];
FutureOr<QueryExecutor> Function() createTables(List<String> schemas) { FutureOr<QueryExecutor> Function() createTables(List<String> schemas) {
// For MySQL // For MySQL
return () => _connectToMySql(schemas); //return () => _connectToMySql(schemas);
// For MariaDB // For MariaDB
// return () => _connectToMariaDb(tables); return () => _connectToMariaDb(schemas);
} }
// For MySQL // For MySQL
Future<void> dropTables(QueryExecutor executor) async { Future<void> dropTables2(QueryExecutor executor) async {
var sqlExecutor = (executor as MySqlExecutor); var sqlExecutor = (executor as MySqlExecutor);
for (var tableName in tmpTables.reversed) { for (var tableName in tmpTables.reversed) {
await sqlExecutor.rawConnection.execute('drop table $tableName;'); await sqlExecutor.rawConnection.execute('drop table $tableName;');
@ -26,13 +26,13 @@ Future<void> dropTables(QueryExecutor executor) async {
} }
// For MariaDB // For MariaDB
/* Future<void> dropTables(QueryExecutor executor) { Future<void> dropTables(QueryExecutor executor) {
var sqlExecutor = (executor as MariaDbExecutor); var sqlExecutor = (executor as MariaDbExecutor);
for (var tableName in tmpTables.reversed) { for (var tableName in tmpTables.reversed) {
sqlExecutor.query(tableName, 'DROP TABLE $tableName', {}); sqlExecutor.query(tableName, 'DROP TABLE $tableName', {});
} }
return sqlExecutor.close(); return sqlExecutor.close();
} */ }
String extractTableName(String createQuery) { String extractTableName(String createQuery) {
var start = createQuery.indexOf('EXISTS'); var start = createQuery.indexOf('EXISTS');
@ -51,8 +51,8 @@ Future<MariaDbExecutor> _connectToMariaDb(List<String> schemas) async {
host: 'localhost', host: 'localhost',
port: 3306, port: 3306,
db: 'orm_test', db: 'orm_test',
user: 'Test', user: 'test',
password: 'Test123*'); password: 'test123');
var connection = await MySqlConnection.connect(settings); var connection = await MySqlConnection.connect(settings);
var logger = Logger('orm_mariadb'); var logger = Logger('orm_mariadb');
@ -87,7 +87,7 @@ Future<MySqlExecutor> _connectToMySql(List<String> schemas) async {
port: 3306, port: 3306,
host: "localhost", host: "localhost",
userName: Platform.environment['MYSQL_USERNAME'] ?? 'test', userName: Platform.environment['MYSQL_USERNAME'] ?? 'test',
password: Platform.environment['MYSQL_PASSWORD'] ?? 'Test123*', password: Platform.environment['MYSQL_PASSWORD'] ?? 'test123',
secure: false); secure: false);
await connection.connect(timeoutMs: 10000); await connection.connect(timeoutMs: 10000);

View file

@ -3,7 +3,7 @@ import 'package:angel3_orm/angel3_orm.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'models/car.dart'; import 'models/car.dart';
final DateTime y2k = DateTime.utc(2000, 1, 1); final DateTime y2k = DateTime(2000, 1, 1);
void standaloneTests(FutureOr<QueryExecutor> Function() createExecutor, void standaloneTests(FutureOr<QueryExecutor> Function() createExecutor,
{FutureOr<void> Function(QueryExecutor)? close}) { {FutureOr<void> Function(QueryExecutor)? close}) {
@ -173,9 +173,9 @@ void standaloneTests(FutureOr<QueryExecutor> Function() createExecutor,
}); });
test('insert', () async { test('insert', () async {
var recalledAt = DateTime.now().toUtc(); var recalledAt = DateTime.now();
var query = CarQuery(); var query = CarQuery();
var now = DateTime.now().toUtc(); var now = DateTime.now();
query.values query.values
..make = 'Honda' ..make = 'Honda'
..description = 'Hello' ..description = 'Hello'
@ -198,7 +198,7 @@ void standaloneTests(FutureOr<QueryExecutor> Function() createExecutor,
}); });
test('insert car', () async { test('insert car', () async {
var recalledAt = DateTime.now().toUtc(); var recalledAt = DateTime.now();
var beetle = Car( var beetle = Car(
make: 'Beetle', make: 'Beetle',
description: 'Herbie', description: 'Herbie',