Skip to content

Commit

Permalink
Merge pull request #37 from lteacher/task/#36-stream-to-list
Browse files Browse the repository at this point in the history
Closes #36
  • Loading branch information
lteacher committed May 18, 2016
2 parents f4700b5 + bb0936a commit 8daa18c
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 77 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<User> users = await Model.findAll('User').run();
// Find all users (String or Type are valid args)
List<User> users = await Model.findAll('User').run();
// Insert a user object
List ids = await Model.insertFrom(user).run();
Expand Down
28 changes: 11 additions & 17 deletions lib/src/datalayer/adapters/mysql/mysql_query_executor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<List<dynamic>> execMultiResults() async =>
_mapResults(await executeSql(buildQuery()));
}
46 changes: 21 additions & 25 deletions lib/src/datalayer/adapters/postgres/postgres_query_executor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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<List<dynamic>> execMultiResults() async =>
_mapResults(await executeSql(buildQuery()));

List mapInsertCmd(token) {
var result = super.mapInsertCmd(token);
result.add('returning $key'); // Add the primary key mapping
Expand Down
8 changes: 4 additions & 4 deletions lib/src/datalayer/querylang/tokens/runnable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<dynamic>] with the single result
abstract class SingleResultRunnable extends Runnable {
/// Runs the query chain producing an async result
Future<dynamic> run();
}

/// Defines a [Runnable] which returns a [Stream] of multiple results
/// Defines a [Runnable] which returns a [Future<List>] of multiple results
abstract class MultipleResultRunnable extends Runnable {
/// Runs the query chain producing a Stream of async results
Stream<dynamic> run();
/// Runs the query chain producing a List of results
Future<List<dynamic>> run();
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: shellstone
version: 0.1.5
version: 0.1.6
homepage: https://github.com/lteacher/shellstone
authors:
- Hugo Armstrong <@lteacher>
Expand Down
26 changes: 13 additions & 13 deletions test/datalayer/mysql_adapter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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)
Expand All @@ -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')
Expand All @@ -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')
Expand All @@ -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) {
Expand All @@ -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')
Expand All @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
Loading

0 comments on commit 8daa18c

Please sign in to comment.