mirror of https://github.com/AMT-Cheif/drift.git
Document list subqueries, add test
This commit is contained in:
parent
a102323857
commit
df89513130
|
@ -225,6 +225,56 @@ from the referred table. For instance, if we had a table `foo` with an `id INT`
|
|||
and a `bar TEXT` column. Then, `SELECT foo.** FROM foo` might be desugared to
|
||||
`SELECT foo.id AS "nested_0.id", foo.bar AS "nested_0".bar FROM foo`.
|
||||
|
||||
## `LIST` subqueries
|
||||
|
||||
Starting from Drift version `1.4.0`, subqueries can also be selected as a full
|
||||
list. Simply put the subquery in a `LIST()` function to include all rows of the
|
||||
subquery in the result set.
|
||||
|
||||
Re-using the `coordinates` and `saved_routes` tables introduced in the example
|
||||
for [nested results](#nested-results), we add a new table storing coordinates
|
||||
along a route:
|
||||
|
||||
```sql
|
||||
CREATE TABLE route_points (
|
||||
route INTEGER NOT NULL REFERENCES saved_routes (id),
|
||||
point INTEGER NOT NULL REFERENCES coordinates (id),
|
||||
index_on_route INTEGER,
|
||||
PRIMARY KEY (route, point)
|
||||
);
|
||||
```
|
||||
|
||||
Now, assume we wanted to query a route with information about all points
|
||||
along the way. While this requires two SQL statements, we can write this as a
|
||||
single drift query that is then split into the two statements automatically:
|
||||
|
||||
```sql
|
||||
routeWithPoints: SELECT
|
||||
route.**
|
||||
LIST(SELECT coordinates.* FROM route_points
|
||||
INNER JOIN coordinates ON id = point
|
||||
WHERE route = route.id
|
||||
ORDER BY index_on_route
|
||||
) AS points
|
||||
FROM saved_routes route;
|
||||
```
|
||||
|
||||
This will generate a result set containing a `SavedRoute route` field along with a
|
||||
`List<Point> points` list of all points along the route.
|
||||
|
||||
Internally, drift will split this query into two separate queries:
|
||||
- The outer `SELECT route.** FROM saved_routes route` SQL queries
|
||||
- A separate `SELECT coordinates.* FROM route_points ... ORDER BY index_on_route` query
|
||||
that is run for each row in the outer query. The `route.id` reference in the inner
|
||||
query is replaced with a variable that drift binds to the actual value in the
|
||||
outer query.
|
||||
|
||||
While `LIST()` subqueries are a very powerful feature, they can be costly when the outer query
|
||||
has lots of rows (as the inner query is executed for each outer row).
|
||||
|
||||
Also, as `LIST()` needs a semantic rewrite of the original statement, this feature is only
|
||||
supported with the `new_sql_code_generation` [build option]({{ '../Advanced Features/builder_options.md' | pageUrl }}).
|
||||
|
||||
## Dart interop
|
||||
Drift files work perfectly together with drift's existing Dart API:
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
@TestOn('vm')
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../data/tables/custom_tables.dart';
|
||||
|
||||
void main() {
|
||||
late CustomTablesDb db;
|
||||
|
||||
setUp(() {
|
||||
db = CustomTablesDb(NativeDatabase.memory());
|
||||
});
|
||||
|
||||
tearDown(() => db.close());
|
||||
|
||||
test('collects results for LIST subqueries', () async {
|
||||
var results = await db.nested('a').get();
|
||||
expect(results, isEmpty);
|
||||
|
||||
final defaults = await db.withDefaults.insertReturning(
|
||||
WithDefaultsCompanion.insert(a: const Value('a'), b: const Value(1)));
|
||||
final constraints = await db.withConstraints
|
||||
.insertReturning(WithConstraintsCompanion.insert(
|
||||
a: const Value('one'),
|
||||
b: 1,
|
||||
));
|
||||
|
||||
results = await db.nested('a').get();
|
||||
expect(results, hasLength(1));
|
||||
|
||||
final result = results.single;
|
||||
expect(result.defaults, defaults);
|
||||
expect(result.nestedQuery0, [constraints]);
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue