mirror of
https://github.com/immich-app/drift.git
synced 2026-09-30 13:22:57 +08:00
Fix some bugs in the sql parser, another integration test
This commit is contained in:
@@ -69,6 +69,10 @@ class PreferenceConverter extends TypeConverter<Preferences, String> {
|
|||||||
'SELECT * FROM users u ORDER BY (SELECT COUNT(*) FROM friendships WHERE first_user = u.id OR second_user = u.id) DESC LIMIT :amount',
|
'SELECT * FROM users u ORDER BY (SELECT COUNT(*) FROM friendships WHERE first_user = u.id OR second_user = u.id) DESC LIMIT :amount',
|
||||||
'amountOfGoodFriends':
|
'amountOfGoodFriends':
|
||||||
'SELECT COUNT(*) FROM friendships f WHERE f.really_good_friends AND (f.first_user = :user OR f.second_user = :user)',
|
'SELECT COUNT(*) FROM friendships f WHERE f.really_good_friends AND (f.first_user = :user OR f.second_user = :user)',
|
||||||
|
'friendsOf': '''SELECT u.* FROM friendships f
|
||||||
|
INNER JOIN users u ON u.id IN (f.first_user, f.second_user) AND
|
||||||
|
u.id != :user
|
||||||
|
WHERE (f.first_user = :user OR f.second_user = :user)''',
|
||||||
'userCount': 'SELECT COUNT(id) FROM users',
|
'userCount': 'SELECT COUNT(id) FROM users',
|
||||||
'settingsFor': 'SELECT preferences FROM users WHERE id = :user',
|
'settingsFor': 'SELECT preferences FROM users WHERE id = :user',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -147,6 +147,20 @@ class UsersCompanion extends UpdateCompanion<User> {
|
|||||||
this.profilePicture = const Value.absent(),
|
this.profilePicture = const Value.absent(),
|
||||||
this.preferences = const Value.absent(),
|
this.preferences = const Value.absent(),
|
||||||
});
|
});
|
||||||
|
UsersCompanion copyWith(
|
||||||
|
{Value<int> id,
|
||||||
|
Value<String> name,
|
||||||
|
Value<DateTime> birthDate,
|
||||||
|
Value<Uint8List> profilePicture,
|
||||||
|
Value<Preferences> preferences}) {
|
||||||
|
return UsersCompanion(
|
||||||
|
id: id ?? this.id,
|
||||||
|
name: name ?? this.name,
|
||||||
|
birthDate: birthDate ?? this.birthDate,
|
||||||
|
profilePicture: profilePicture ?? this.profilePicture,
|
||||||
|
preferences: preferences ?? this.preferences,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class $UsersTable extends Users with TableInfo<$UsersTable, User> {
|
class $UsersTable extends Users with TableInfo<$UsersTable, User> {
|
||||||
@@ -388,6 +402,16 @@ class FriendshipsCompanion extends UpdateCompanion<Friendship> {
|
|||||||
this.secondUser = const Value.absent(),
|
this.secondUser = const Value.absent(),
|
||||||
this.reallyGoodFriends = const Value.absent(),
|
this.reallyGoodFriends = const Value.absent(),
|
||||||
});
|
});
|
||||||
|
FriendshipsCompanion copyWith(
|
||||||
|
{Value<int> firstUser,
|
||||||
|
Value<int> secondUser,
|
||||||
|
Value<bool> reallyGoodFriends}) {
|
||||||
|
return FriendshipsCompanion(
|
||||||
|
firstUser: firstUser ?? this.firstUser,
|
||||||
|
secondUser: secondUser ?? this.secondUser,
|
||||||
|
reallyGoodFriends: reallyGoodFriends ?? this.reallyGoodFriends,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class $FriendshipsTable extends Friendships
|
class $FriendshipsTable extends Friendships
|
||||||
@@ -585,6 +609,29 @@ abstract class _$Database extends GeneratedDatabase {
|
|||||||
}).map((rows) => rows.map(_rowToAmountOfGoodFriendsResult).toList());
|
}).map((rows) => rows.map(_rowToAmountOfGoodFriendsResult).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<User>> friendsOf(
|
||||||
|
int user,
|
||||||
|
{@Deprecated('No longer needed with Moor 1.6 - see the changelog for details')
|
||||||
|
QueryEngine operateOn}) {
|
||||||
|
return (operateOn ?? this).customSelect(
|
||||||
|
'SELECT u.* FROM friendships f\n INNER JOIN users u ON u.id IN (f.first_user, f.second_user) AND\n u.id != :user\n WHERE (f.first_user = :user OR f.second_user = :user)',
|
||||||
|
variables: [
|
||||||
|
Variable.withInt(user),
|
||||||
|
]).then((rows) => rows.map(_rowToUser).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<List<User>> watchFriendsOf(int user) {
|
||||||
|
return customSelectStream(
|
||||||
|
'SELECT u.* FROM friendships f\n INNER JOIN users u ON u.id IN (f.first_user, f.second_user) AND\n u.id != :user\n WHERE (f.first_user = :user OR f.second_user = :user)',
|
||||||
|
variables: [
|
||||||
|
Variable.withInt(user),
|
||||||
|
],
|
||||||
|
readsFrom: {
|
||||||
|
friendships,
|
||||||
|
users
|
||||||
|
}).map((rows) => rows.map(_rowToUser).toList());
|
||||||
|
}
|
||||||
|
|
||||||
UserCountResult _rowToUserCountResult(QueryRow row) {
|
UserCountResult _rowToUserCountResult(QueryRow row) {
|
||||||
return UserCountResult(
|
return UserCountResult(
|
||||||
cOUNTid: row.readInt('COUNT(id)'),
|
cOUNTid: row.readInt('COUNT(id)'),
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:tests/database/database.dart';
|
||||||
|
import 'package:tests/suite/suite.dart';
|
||||||
|
|
||||||
|
void crudTests(TestExecutor executor) {
|
||||||
|
test('inserting updates a select stream', () async {
|
||||||
|
final db = Database(executor.createExecutor());
|
||||||
|
final friends = db.watchFriendsOf(1);
|
||||||
|
|
||||||
|
final a = await db.getUserById(1);
|
||||||
|
final b = await db.getUserById(2);
|
||||||
|
|
||||||
|
final expectation = expectLater(
|
||||||
|
friends,
|
||||||
|
emitsInOrder(
|
||||||
|
[
|
||||||
|
isEmpty, // initial state without friendships
|
||||||
|
[b] // after we called makeFriends(a,b)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await db.makeFriends(a, b);
|
||||||
|
await expectation;
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:moor/moor.dart';
|
import 'package:moor/moor.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
import 'package:tests/suite/crud_tests.dart';
|
||||||
import 'package:tests/suite/transactions.dart';
|
import 'package:tests/suite/transactions.dart';
|
||||||
|
|
||||||
import 'custom_objects.dart';
|
import 'custom_objects.dart';
|
||||||
@@ -17,6 +18,7 @@ void runAllTests(TestExecutor executor) {
|
|||||||
await executor.deleteData();
|
await executor.deleteData();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
crudTests(executor);
|
||||||
migrationTests(executor);
|
migrationTests(executor);
|
||||||
customObjectTests(executor);
|
customObjectTests(executor);
|
||||||
transactionTests(executor);
|
transactionTests(executor);
|
||||||
|
|||||||
@@ -23,3 +23,5 @@ dependency_overrides:
|
|||||||
path: ../../../moor
|
path: ../../../moor
|
||||||
moor_generator:
|
moor_generator:
|
||||||
path: ../../../moor_generator
|
path: ../../../moor_generator
|
||||||
|
sqlparser:
|
||||||
|
path: ../../../sqlparser
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:analyzer/dart/constant/value.dart';
|
import 'package:analyzer/dart/constant/value.dart';
|
||||||
|
import 'package:build/build.dart';
|
||||||
import 'package:moor_generator/src/state/errors.dart';
|
import 'package:moor_generator/src/state/errors.dart';
|
||||||
import 'package:moor_generator/src/model/specified_table.dart';
|
import 'package:moor_generator/src/model/specified_table.dart';
|
||||||
import 'package:moor_generator/src/model/sql_query.dart';
|
import 'package:moor_generator/src/model/sql_query.dart';
|
||||||
@@ -49,8 +50,8 @@ class SqlParser {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
foundQueries.add(QueryHandler(name, context, _mapper).handle());
|
foundQueries.add(QueryHandler(name, context, _mapper).handle());
|
||||||
} catch (e) {
|
} catch (e, s) {
|
||||||
print('Error while generating APIs for ${context.sql}: $e');
|
log.warning('Error while generating APIs for ${context.sql}', e, s);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
# We use netlify to deploy the documentation.
|
# We use netlify to deploy the documentation.
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
base = "docs/"
|
base = "docs"
|
||||||
publish = "docs/public"
|
publish = "docs/public"
|
||||||
command = 'git submodule update --init --recursive && HUGO_ENV="production" hugo'
|
command = 'git submodule update --init --recursive && HUGO_ENV="production" hugo'
|
||||||
|
|
||||||
|
|||||||
@@ -136,7 +136,9 @@ class TypeResolver {
|
|||||||
if (sqlParameters is ExprFunctionParameters) {
|
if (sqlParameters is ExprFunctionParameters) {
|
||||||
return sqlParameters.parameters;
|
return sqlParameters.parameters;
|
||||||
} else if (sqlParameters is StarFunctionParameter) {
|
} else if (sqlParameters is StarFunctionParameter) {
|
||||||
return call.scope.availableColumns;
|
// if * is used as a parameter, it refers to all columns in all tables
|
||||||
|
// that are available in the current scope.
|
||||||
|
return call.scope.availableColumns.whereType<TableColumn>().toList();
|
||||||
}
|
}
|
||||||
throw ArgumentError('Unknown parameters: $sqlParameters');
|
throw ArgumentError('Unknown parameters: $sqlParameters');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,6 +95,11 @@ class Scanner {
|
|||||||
_addToken(TokenType.more);
|
_addToken(TokenType.more);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case '!':
|
||||||
|
if (_match('=')) {
|
||||||
|
_addToken(TokenType.exclamationEqual);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case '=':
|
case '=':
|
||||||
_addToken(_match('=') ? TokenType.doubleEqual : TokenType.equal);
|
_addToken(_match('=') ? TokenType.doubleEqual : TokenType.equal);
|
||||||
break;
|
break;
|
||||||
@@ -138,8 +143,7 @@ class Scanner {
|
|||||||
} else if (canStartColumnName(char)) {
|
} else if (canStartColumnName(char)) {
|
||||||
_identifier();
|
_identifier();
|
||||||
} else {
|
} else {
|
||||||
errors.add(TokenizerError(
|
errors.add(TokenizerError('Unexpected character.', _currentLocation));
|
||||||
'Unexpected character.', SourceLocation(_currentOffset)));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ Map<String, TokenType> testCases = {
|
|||||||
'<': TokenType.less,
|
'<': TokenType.less,
|
||||||
'>=': TokenType.moreEqual,
|
'>=': TokenType.moreEqual,
|
||||||
'>': TokenType.more,
|
'>': TokenType.more,
|
||||||
|
'!=': TokenType.exclamationEqual,
|
||||||
"'hello there'": TokenType.stringLiteral,
|
"'hello there'": TokenType.stringLiteral,
|
||||||
'1.123': TokenType.numberLiteral,
|
'1.123': TokenType.numberLiteral,
|
||||||
'1.32e5': TokenType.numberLiteral,
|
'1.32e5': TokenType.numberLiteral,
|
||||||
|
|||||||
Reference in New Issue
Block a user