Fixed failed test cases

This commit is contained in:
thomashii 2022-05-16 13:04:21 +08:00
parent 178bc924c1
commit 03885543c2
23 changed files with 125 additions and 50 deletions

View file

@ -2,8 +2,10 @@
## 6.0.0-beta.3
* Updated transaction for `MariaDbExecutor`
* Updated transaction for `MySqlExecutor`
* Fixed transaction for `MariaDbExecutor`
* Fixed transaction for `MySqlExecutor`
* Fixed error for non `id` primary key
* Changed test cases to use tables instead of temporary tables to overcome limitations
## 6.0.0-beta.2

View file

@ -7,7 +7,7 @@
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 (stable)
* MariaDbExecutor (beta)
* MySqlExecutor (beta)
## Supported database version
@ -51,3 +51,9 @@ This package contains the SQL Executor required by Angel3 ORM to work with MySQL
await connection.connect(timeoutMs: 10000);
var executor = MySqlExecutor(connection, logger: logger);
```
## Known limitation
* UTC time is not supported
* Blob is not supported

View file

@ -22,6 +22,8 @@ class MySqlExecutor extends QueryExecutor {
return _connection.close();
}
MySQLConnection get rawConnection => _connection;
/*
Future<Transaction> _startTransaction() {
if (_connection is Transaction) {
@ -115,6 +117,8 @@ class MySqlExecutor extends QueryExecutor {
query = query.replaceAll("?", ":id");
substitutionValues.clear();
substitutionValues['id'] = result.lastInsertID;
} else {
query = _convertSQL(query, substitutionValues);
}
} else if (query.startsWith("UPDATE")) {
await _connection.execute(query, substitutionValues);
@ -133,6 +137,17 @@ class MySqlExecutor extends QueryExecutor {
});
}
String _convertSQL(String query, Map<String, dynamic> substitutionValues) {
var newQuery = query;
for (var k in substitutionValues.keys) {
var fromPattern = '.$k = ?';
var toPattern = '.$k = :$k';
newQuery = newQuery.replaceFirst(fromPattern, toPattern);
}
return newQuery;
}
@override
Future<T> transaction<T>(FutureOr<T> Function(QueryExecutor) f) async {
logger.warning("Transaction");

View file

@ -11,23 +11,28 @@ void main() {
});
group('mysql', () {
group('belongsTo',
() => belongsToTests(my(['author', 'book']), close: closeMy));
group(
'belongsTo',
() => belongsToTests(createTables(['author', 'book']),
close: dropTables));
group(
'edgeCase',
() => edgeCaseTests(my(['unorthodox', 'weird_join', 'song', 'numba']),
close: closeMy));
() => edgeCaseTests(
createTables(['unorthodox', 'weird_join', 'song', 'numba']),
close: dropTables));
group('enumAndNested',
() => enumAndNestedTests(my(['has_car']), close: closeMy));
group('hasMany', () => hasManyTests(my(['tree', 'fruit']), close: closeMy));
() => enumAndNestedTests(createTables(['has_car']), close: dropTables));
group('hasMany',
() => hasManyTests(createTables(['tree', 'fruit']), close: dropTables));
// NOTE: MySQL/MariaDB do not support jsonb data type
//group('hasMap', () => hasMapTests(my(['has_map']), close: closeMy));
//group('hasMap', () => hasMapTests(createTables(['has_maps']), close: dropTables));
// NOTE: mysql1 driver do not support CAST();
//group('hasOne', () => hasOneTests(my(['leg', 'foot']), close: closeMy));
//group('hasOne', () => hasOneTests(createTables(['legs', 'feet']), close: dropTables));
group(
'manyToMany',
() =>
manyToManyTests(my(['user', 'role', 'user_role']), close: closeMy));
group('standalone', () => standaloneTests(my(['car']), close: closeMy));
() => manyToManyTests(createTables(['user', 'role', 'user_role']),
close: dropTables));
group('standalone',
() => standaloneTests(createTables(['car']), close: dropTables));
});
}

View file

@ -6,15 +6,47 @@ import 'package:logging/logging.dart';
import 'package:mysql1/mysql1.dart';
import 'package:mysql_client/mysql_client.dart';
FutureOr<QueryExecutor> Function() my(Iterable<String> schemas) {
return () => connectToMySql(schemas);
List tmpTables = [];
FutureOr<QueryExecutor> Function() createTables(List<String> schemas) {
// For MySQL
return () => _connectToMySql(schemas);
// For MariaDB
// return () => _connectToMariaDb(tables);
}
Future<void> closeMy(QueryExecutor executor) =>
(executor as MySqlExecutor).close();
// For MySQL
Future<void> dropTables(QueryExecutor executor) async {
var sqlExecutor = (executor as MySqlExecutor);
for (var tableName in tmpTables.reversed) {
await sqlExecutor.rawConnection.execute('drop table $tableName;');
}
return sqlExecutor.close();
}
// Executor for MariaDB 10.2.x
Future<MariaDbExecutor> connectToMariaDb(Iterable<String> schemas) async {
// For MariaDB
/* Future<void> dropTables(QueryExecutor executor) {
var sqlExecutor = (executor as MariaDbExecutor);
for (var tableName in tmpTables.reversed) {
sqlExecutor.query(tableName, 'DROP TABLE $tableName', {});
}
return sqlExecutor.close();
} */
String extractTableName(String createQuery) {
var start = createQuery.indexOf('EXISTS');
var end = createQuery.indexOf('(');
if (start == -1 || end == -1) {
return '';
}
return createQuery.substring(start + 6, end).trim();
}
// Executor for MariaDB
Future<MariaDbExecutor> _connectToMariaDb(List<String> schemas) async {
var settings = ConnectionSettings(
host: 'localhost',
port: 3306,
@ -23,7 +55,9 @@ Future<MariaDbExecutor> connectToMariaDb(Iterable<String> schemas) async {
password: 'Test123*');
var connection = await MySqlConnection.connect(settings);
var logger = Logger('orm_mysql');
var logger = Logger('orm_mariadb');
tmpTables.clear();
for (var s in schemas) {
// MySQL driver does not support multiple sql queries
@ -34,6 +68,11 @@ Future<MariaDbExecutor> connectToMariaDb(Iterable<String> schemas) async {
if (q.trim().isNotEmpty) {
//await connection.execute(q);
await connection.query(q);
var tableName = extractTableName(q);
if (tableName != '') {
tmpTables.add(tableName);
}
}
}
}
@ -41,20 +80,22 @@ Future<MariaDbExecutor> connectToMariaDb(Iterable<String> schemas) async {
return MariaDbExecutor(connection, logger: logger);
}
// Executor for MySQL 8.x.x
Future<MySqlExecutor> connectToMySql(Iterable<String> schemas) async {
// Executor for MySQL
Future<MySqlExecutor> _connectToMySql(List<String> schemas) async {
var connection = await MySQLConnection.createConnection(
databaseName: 'orm_test',
port: 3306,
host: "localhost",
userName: Platform.environment['MYSQL_USERNAME'] ?? 'test',
password: Platform.environment['MYSQL_PASSWORD'] ?? 'Test123*',
);
secure: false);
await connection.connect();
await connection.connect(timeoutMs: 10000);
var logger = Logger('orm_mysql');
tmpTables.clear();
for (var s in schemas) {
// MySQL driver does not support multiple sql queries
var data = await File('test/migrations/$s.sql').readAsString();
@ -63,6 +104,11 @@ Future<MySqlExecutor> connectToMySql(Iterable<String> schemas) async {
//print("Table: [$q]");
if (q.trim().isNotEmpty) {
await connection.execute(q);
var tableName = extractTableName(q);
if (tableName != '') {
tmpTables.add(tableName);
}
}
}
}

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE authors (
CREATE TABLE IF NOT EXISTS authors (
id serial PRIMARY KEY,
name varchar(255) UNIQUE NOT NULL,
created_at timestamp,

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE books (
CREATE TABLE IF NOT EXISTS books (
id serial PRIMARY KEY,
author_id int NOT NULL,
partner_author_id int,

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE cars (
CREATE TABLE IF NOT EXISTS cars (
id serial PRIMARY KEY,
make varchar(255) NOT NULL,
description TEXT NOT NULL,

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE feet (
CREATE TABLE IF NOT EXISTS feet (
id serial PRIMARY KEY,
leg_id int NOT NULL,
n_toes int NOT NULL,

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE fruits (
CREATE TABLE IF NOT EXISTS fruits (
id serial,
tree_id int,
common_name varchar(255),

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE has_cars (
CREATE TABLE IF NOT EXISTS has_cars (
id serial PRIMARY KEY,
type int not null,
created_at timestamp,

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE has_maps (
CREATE TABLE IF NOT EXISTS has_maps (
id serial PRIMARY KEY,
value jsonb not null,
list jsonb not null,

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE legs (
CREATE TABLE IF NOT EXISTS legs (
id serial PRIMARY KEY,
name varchar(255) NOT NULL,
created_at timestamp,

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE numbas (
CREATE TABLE IF NOT EXISTS numbas (
i int NOT NULL UNIQUE,
parent int,
created_at TIMESTAMP,

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE roles (
CREATE TABLE IF NOT EXISTS roles (
id serial PRIMARY KEY,
name varchar(255),
created_at timestamp,

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE songs (
CREATE TABLE IF NOT EXISTS songs (
id serial,
weird_join_id int,
title varchar(255),

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE trees (
CREATE TABLE IF NOT EXISTS trees (
id serial,
rings smallint UNIQUE,
created_at timestamp,

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE unorthodoxes (
CREATE TABLE IF NOT EXISTS unorthodoxes (
name varchar(255) NOT NULL UNIQUE,
PRIMARY KEY(name)
);

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE users (
CREATE TABLE IF NOT EXISTS users (
id serial PRIMARY KEY,
username varchar(255),
password varchar(255),

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE role_users (
CREATE TABLE IF NOT EXISTS role_users (
id serial PRIMARY KEY,
user_id int NOT NULL,
role_id int NOT NULL,

View file

@ -1,15 +1,15 @@
CREATE TEMPORARY TABLE weird_joins (
CREATE TABLE IF NOT EXISTS weird_joins (
id serial,
join_name varchar(255),
PRIMARY KEY(id)
);
CREATE TEMPORARY TABLE foos (
CREATE TABLE IF NOT EXISTS foos (
bar varchar(255) not null UNIQUE,
PRIMARY KEY(bar)
);
CREATE TEMPORARY TABLE foo_pivots (
CREATE TABLE IF NOT EXISTS foo_pivots (
weird_join_id int,
foo_bar varchar(255)
);

View file

@ -14,7 +14,7 @@ void main() async {
// if (rec.stackTrace != null) print(rec.stackTrace);
//});
belongsToTests(my(['author', 'book']), close: closeMy);
belongsToTests(createTables(['author', 'book']), close: dropTables);
//hasOneTests(my(['leg', 'foot']), close: closeMy);
//standaloneTests(my(['car']), close: closeMy);

View file

@ -61,7 +61,8 @@ void manyToManyTests(FutureOr<QueryExecutor> Function() createExecutor,
..username = 'thosakwe'
..password = 'Hahahahayoureallythoughtiwasstupidenoughtotypethishere'
..email = 'thosakwe AT gmail.com';
thosakwe = (await thosakweQuery.insert(executor)).value;
var result = await thosakweQuery.insert(executor);
thosakwe = result.value;
print('=== THOSAKWE: ${thosakwe?.toJson()}');
// Allow thosakwe to publish...