From bb0936ad185a54101b9d8db0f575b2480e8a3bd1 Mon Sep 17 00:00:00 2001 From: Hugo Armstrong Date: Wed, 18 May 2016 20:37:11 +1000 Subject: [PATCH] Closes #36 Converted streams to List. Filter still occurs on the stream but the final result is a List as its more pleasant for a developer and makes sense for relationships --- README.md | 8 ++-- .../adapters/mysql/mysql_query_executor.dart | 28 +++++------ .../postgres/postgres_query_executor.dart | 46 +++++++++---------- .../datalayer/querylang/tokens/runnable.dart | 8 ++-- pubspec.yaml | 2 +- test/datalayer/mysql_adapter_test.dart | 26 +++++------ test/datalayer/postgres_adapter_test.dart | 26 +++++------ 7 files changed, 67 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 1b99be7..6fa4241 100644 --- a/README.md +++ b/README.md @@ -102,13 +102,13 @@ main() async { await Shellstone.setup(); // Get the first user where it matches the query - User user = await Model.find('User').where('username').eq('1234').run(); + User user = await Model.find(User).where('username').eq('1234').run(); - // Get user using filter + // Get user using filter (the filter is lazily executed on the streaming query results) user = await Model.find('User').filter((user) => user.lastName == 'Smith').run(); - // Find all users - Stream users = await Model.findAll('User').run(); + // Find all users (String or Type are valid args) + List users = await Model.findAll('User').run(); // Insert a user object List ids = await Model.insertFrom(user).run(); diff --git a/lib/src/datalayer/adapters/mysql/mysql_query_executor.dart b/lib/src/datalayer/adapters/mysql/mysql_query_executor.dart index ec0bc7c..2980b36 100644 --- a/lib/src/datalayer/adapters/mysql/mysql_query_executor.dart +++ b/lib/src/datalayer/adapters/mysql/mysql_query_executor.dart @@ -17,7 +17,7 @@ class MysqlQueryExecutor extends SqlExecutor { getPlaceholder(field) => '?'; // Executes a query - Future executeSql(String sql) async { + Future executeSql(String sql, [bool release]) async { var query = await adapter.pool.prepare(sql); var results; @@ -66,32 +66,26 @@ class MysqlQueryExecutor extends SqlExecutor { var results = await executeSql(buildQuery()); if (isModify) { - // Somehow its a stream of streams? return results; } else { - var fields = results.fields.map((f) => f.name); - - // Get the rows to a list and map it as otherwise its - // just not possible to know if it is empty to take the `first` - List rows = await results - .map((row) => new Map.fromIterables(fields, row)) - .map((row) => EntityBuilder.unwrap(chain.entity, row)) - .where((user) => filter != null ? filter(user) : true) - .toList(); + List rows = await _mapResults(results); return new Future.value(!rows.isEmpty ? rows.first : null); } } - // Executes a query that will return a Stream, hence the generator - Stream execMultiResults() async* { - var results = await executeSql(buildQuery()); - + Future _mapResults(results) async { var fields = results.fields.map((f) => f.name); - yield* results + // Return the mapped results list + return await results .map((row) => new Map.fromIterables(fields, row)) .map((row) => EntityBuilder.unwrap(chain.entity, row)) - .where((user) => filter != null ? filter(user) : true); + .where((user) => filter != null ? filter(user) : true) + .toList(); } + + // Executes a query that will return a list of results + Future> execMultiResults() async => + _mapResults(await executeSql(buildQuery())); } diff --git a/lib/src/datalayer/adapters/postgres/postgres_query_executor.dart b/lib/src/datalayer/adapters/postgres/postgres_query_executor.dart index 741c9e2..f47b05b 100644 --- a/lib/src/datalayer/adapters/postgres/postgres_query_executor.dart +++ b/lib/src/datalayer/adapters/postgres/postgres_query_executor.dart @@ -18,15 +18,18 @@ class PostgresQueryExecutor extends SqlExecutor { getPlaceholder(field) => '@${_tokenCount++}'; // Execute some sql - executeSql(sql,[bool release]) async { + executeSql(sql, [bool release]) async { // conn = await psql.connect(adapter.uri); conn = await adapter.pool.connect(); var result; - if (isInsert) result = _execInsert(sql); - else if (isModify) result = _execModify(sql); - else result = await conn.query(sql, values); + if (isInsert) + result = _execInsert(sql); + else if (isModify) + result = _execModify(sql); + else + result = await conn.query(sql, values); if (release) await conn.close(); @@ -67,36 +70,29 @@ class PostgresQueryExecutor extends SqlExecutor { return results; } else { - List rows = await results - .map((row) => EntityBuilder.unwrap(chain.entity, row.toMap())) - .where((user) => filter != null ? filter(user) : true) - .toList(); - - conn.close(); + List rows = await _mapResults(results); return new Future.value(!rows.isEmpty ? rows.first : null); } } - // Executes a query that will return a Stream, hence the generator - Stream execMultiResults() async* { - var results = await executeSql(buildQuery()); - - // Use this to attach the connection close - var ctrl = new StreamController(); - var done = ctrl.addStream(results); + // Map the results over + _mapResults(results) { + var list = results + .map((row) => EntityBuilder.unwrap(chain.entity, row.toMap())) + .where((user) => filter != null ? filter(user) : true) + .toList(); - // When done close the controller and the connection - done.then((_) { - ctrl.close(); - conn.close(); - }); + // Later on complete close the connection + list.then((_) => conn.close()); - yield* ctrl.stream - .map((row) => EntityBuilder.unwrap(chain.entity, row.toMap())) - .where((user) => filter != null ? filter(user) : true); + return list; } + // Executes a query that will return a list of results + Future> execMultiResults() async => + _mapResults(await executeSql(buildQuery())); + List mapInsertCmd(token) { var result = super.mapInsertCmd(token); result.add('returning $key'); // Add the primary key mapping diff --git a/lib/src/datalayer/querylang/tokens/runnable.dart b/lib/src/datalayer/querylang/tokens/runnable.dart index 4e37ba4..6a0743b 100644 --- a/lib/src/datalayer/querylang/tokens/runnable.dart +++ b/lib/src/datalayer/querylang/tokens/runnable.dart @@ -5,14 +5,14 @@ abstract class Runnable { dynamic run(); } -/// Defines a [Runnable] which returns a [Future] with the single result +/// Defines a [Runnable] which returns a [Future] with the single result abstract class SingleResultRunnable extends Runnable { /// Runs the query chain producing an async result Future run(); } -/// Defines a [Runnable] which returns a [Stream] of multiple results +/// Defines a [Runnable] which returns a [Future] of multiple results abstract class MultipleResultRunnable extends Runnable { - /// Runs the query chain producing a Stream of async results - Stream run(); + /// Runs the query chain producing a List of results + Future> run(); } diff --git a/pubspec.yaml b/pubspec.yaml index e1d841e..86a2eb8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: shellstone -version: 0.1.5 +version: 0.1.6 homepage: https://github.com/lteacher/shellstone authors: - Hugo Armstrong <@lteacher> diff --git a/test/datalayer/mysql_adapter_test.dart b/test/datalayer/mysql_adapter_test.dart index 3252bb5..9b22cf7 100644 --- a/test/datalayer/mysql_adapter_test.dart +++ b/test/datalayer/mysql_adapter_test.dart @@ -101,7 +101,7 @@ main() { test('Model.findAll(`User`).where(f).eq(v) finds the correct two users', () async { - Stream results = + List results = await Model.findAll('MysqlUser').where('lastName').eq('Jones').run(); List users = []; await results.forEach((user) { @@ -113,7 +113,7 @@ main() { test('Model.findAll(`User`).where(f).ne(v) finds the correct user', () async { - Stream results = + List results = await Model.findAll('MysqlUser').where('lastName').ne('Jones').run(); List users = []; await results.forEach((user) { @@ -125,7 +125,7 @@ main() { test('Model.findAll(`User`).where(f).gt(v) finds the correct single user', () async { - Stream results = await Model.findAll('MysqlUser').where('id').gt(5).run(); + List results = await Model.findAll('MysqlUser').where('id').gt(5).run(); List users = []; await results.forEach((user) { users.add(user.firstName); @@ -136,7 +136,7 @@ main() { test('Model.findAll(`User`).where(f).ge(v) finds the correct two users', () async { - Stream results = await Model.findAll('MysqlUser').where('id').ge(5).run(); + List results = await Model.findAll('MysqlUser').where('id').ge(5).run(); List users = []; await results.forEach((user) { users.add(user.firstName); @@ -147,7 +147,7 @@ main() { test('Model.findAll(`User`).where(f).lt(v) finds the correct single user', () async { - Stream results = await Model.findAll('MysqlUser').where('id').lt(2).run(); + List results = await Model.findAll('MysqlUser').where('id').lt(2).run(); List users = []; await results.forEach((user) { users.add(user.firstName); @@ -158,7 +158,7 @@ main() { test('Model.findAll(`User`).where(f).le(v) finds the correct two users', () async { - Stream results = await Model.findAll('MysqlUser').where('id').le(2).run(); + List results = await Model.findAll('MysqlUser').where('id').le(2).run(); List users = []; await results.forEach((user) { users.add(user.firstName); @@ -170,7 +170,7 @@ main() { test( 'Model.findAll(`User`).where(f).eq(v).or(f).eq(v) finds the correct two users', () async { - Stream results = await Model + List results = await Model .findAll('MysqlUser') .where('id') .eq(1) @@ -188,7 +188,7 @@ main() { test( 'Model.findAll(`User`).where(f).eq(v).and(f).eq(v) finds the correct users', () async { - Stream results = await Model + List results = await Model .findAll('MysqlUser') .where('lastName') .eq('Jones') @@ -206,7 +206,7 @@ main() { test( 'Model.findAll(`User`).where(f).complex A... finds the correct two users', () async { - Stream results = await Model + List results = await Model .findAll('MysqlUser') .where('lastName') .eq('Jones') @@ -226,7 +226,7 @@ main() { test( 'Model.findAll(`User`).where(f).complex B... finds the correct two users', () async { - Stream results = + List results = await Model.findAll('MysqlUser').where('id').gt(1).and('id').lt(3).run(); List users = []; await results.forEach((user) { @@ -252,7 +252,7 @@ main() { test('Model.findAll(`User`).filter(user) returns the correct users', () async { - Stream results = await Model + List results = await Model .findAll('MysqlUser') .filter( (user) => user.firstName == 'Jim' || user.firstName == 'Charles') @@ -271,7 +271,7 @@ main() { }); test('Model.findAll(`User`).filter(user) returns the empty set', () async { - Stream results = + List results = await Model.findAll('MysqlUser').filter((user) => true == false).run(); List users = []; await results.forEach((user) { @@ -316,7 +316,7 @@ main() { test('Model.update(User,values) can modify many entities', () async { await Model.update(MysqlUser,{'lastName':'Smith'}).where('lastName').eq('Jones').run(); - Stream results = + List results = await Model.findAll('MysqlUser').filter((user) => user.lastName == 'Smith').run(); List users = []; await results.forEach((user) { diff --git a/test/datalayer/postgres_adapter_test.dart b/test/datalayer/postgres_adapter_test.dart index caed75b..3724264 100644 --- a/test/datalayer/postgres_adapter_test.dart +++ b/test/datalayer/postgres_adapter_test.dart @@ -101,7 +101,7 @@ main() { test('Model.findAll(`User`).where(f).eq(v) finds the correct two users', () async { - Stream results = + List results = await Model.findAll('PostgresUser').where('lastName').eq('Jones').run(); List users = []; await results.forEach((user) { @@ -113,7 +113,7 @@ main() { test('Model.findAll(`User`).where(f).ne(v) finds the correct user', () async { - Stream results = + List results = await Model.findAll('PostgresUser').where('lastName').ne('Jones').run(); List users = []; await results.forEach((user) { @@ -125,7 +125,7 @@ main() { test('Model.findAll(`User`).where(f).gt(v) finds the correct single user', () async { - Stream results = await Model.findAll('PostgresUser').where('id').gt(5).run(); + List results = await Model.findAll('PostgresUser').where('id').gt(5).run(); List users = []; await results.forEach((user) { users.add(user.firstName); @@ -136,7 +136,7 @@ main() { test('Model.findAll(`User`).where(f).ge(v) finds the correct two users', () async { - Stream results = await Model.findAll('PostgresUser').where('id').ge(5).run(); + List results = await Model.findAll('PostgresUser').where('id').ge(5).run(); List users = []; await results.forEach((user) { users.add(user.firstName); @@ -147,7 +147,7 @@ main() { test('Model.findAll(`User`).where(f).lt(v) finds the correct single user', () async { - Stream results = await Model.findAll('PostgresUser').where('id').lt(2).run(); + List results = await Model.findAll('PostgresUser').where('id').lt(2).run(); List users = []; await results.forEach((user) { users.add(user.firstName); @@ -158,7 +158,7 @@ main() { test('Model.findAll(`User`).where(f).le(v) finds the correct two users', () async { - Stream results = await Model.findAll('PostgresUser').where('id').le(2).run(); + List results = await Model.findAll('PostgresUser').where('id').le(2).run(); List users = []; await results.forEach((user) { users.add(user.firstName); @@ -170,7 +170,7 @@ main() { test( 'Model.findAll(`User`).where(f).eq(v).or(f).eq(v) finds the correct two users', () async { - Stream results = await Model + List results = await Model .findAll('PostgresUser') .where('id') .eq(1) @@ -188,7 +188,7 @@ main() { test( 'Model.findAll(`User`).where(f).eq(v).and(f).eq(v) finds the correct users', () async { - Stream results = await Model + List results = await Model .findAll('PostgresUser') .where('lastName') .eq('Jones') @@ -206,7 +206,7 @@ main() { test( 'Model.findAll(`User`).where(f).complex A... finds the correct two users', () async { - Stream results = await Model + List results = await Model .findAll('PostgresUser') .where('lastName') .eq('Jones') @@ -226,7 +226,7 @@ main() { test( 'Model.findAll(`User`).where(f).complex B... finds the correct two users', () async { - Stream results = + List results = await Model.findAll('PostgresUser').where('id').gt(1).and('id').lt(3).run(); List users = []; await results.forEach((user) { @@ -252,7 +252,7 @@ main() { test('Model.findAll(`User`).filter(user) returns the correct users', () async { - Stream results = await Model + List results = await Model .findAll('PostgresUser') .filter( (user) => user.firstName == 'Jim' || user.firstName == 'Charles') @@ -271,7 +271,7 @@ main() { }); test('Model.findAll(`User`).filter(user) returns the empty set', () async { - Stream results = + List results = await Model.findAll('PostgresUser').filter((user) => true == false).run(); List users = []; await results.forEach((user) { @@ -316,7 +316,7 @@ main() { test('Model.update(User,values) can modify many entities', () async { await Model.update(PostgresUser,{'lastName':'Smith'}).where('lastName').eq('Jones').run(); - Stream results = + List results = await Model.findAll('PostgresUser').filter((user) => user.lastName == 'Smith').run(); List users = []; await results.forEach((user) {