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
|
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`.
|
`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
|
## Dart interop
|
||||||
Drift files work perfectly together with drift's existing Dart API:
|
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