Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/brick_sqlite/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## 4.1.0

- Add ability to run migrations `down` by calling `#migrate(down: true)` #594
- `#queryToSql` is added to support Brick Query debugging
- Fix querying associations of the same table by specifying an `AS` name

## 4.0.2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ class QuerySqlTransformer<_Model extends SqliteModel> {

/// Finally add the column to the complete phrase
final sqliteColumn = passedAdapter.tableName != adapter.tableName || _queryHasAssociations
? '`${passedAdapter.tableName}`.${definition.columnName}'
? '${AssociationFragment.joinName(passedAdapter.tableName, definition.columnName)}.${definition.columnName}'
: _queryHasAssociations
? '`${adapter.tableName}`.${definition.columnName}'
? '${AssociationFragment.joinName(adapter.tableName, definition.columnName)}.${definition.columnName}'
: definition.columnName;
final where = WhereColumnFragment(condition, sqliteColumn);
_values.addAll(where.values);
Expand Down Expand Up @@ -218,18 +218,24 @@ class AssociationFragment {

if (oneToOneAssociation) {
return [
'INNER JOIN `$foreignTableName` ON $localTableColumn = `$foreignTableName`.$primaryKeyColumn',
'INNER JOIN `$foreignTableName` AS ${joinName(foreignTableName, definition.columnName)} ON $localTableColumn = `$foreignTableName`.$primaryKeyColumn',
];
}

final joinsTableName =
InsertForeignKey.joinsTableName(localColumnName, localTableName: localTableName);
// ['1','2','3','4']
return [
'INNER JOIN `$joinsTableName` ON `$localTableName`.$primaryKeyColumn = `$joinsTableName`.${InsertForeignKey.joinsTableLocalColumnName(localTableName)}',
'INNER JOIN `$foreignTableName` ON `$foreignTableName`.$primaryKeyColumn = `$joinsTableName`.${InsertForeignKey.joinsTableForeignColumnName(foreignTableName)}',
'INNER JOIN `$joinsTableName` AS ${joinName(localTableName, definition.columnName)} ON `$localTableName`.$primaryKeyColumn = `$joinsTableName`.${InsertForeignKey.joinsTableLocalColumnName(localTableName)}',
'INNER JOIN `$foreignTableName` AS ${joinName(foreignTableName, definition.columnName)} ON `$foreignTableName`.$primaryKeyColumn = `$joinsTableName`.${InsertForeignKey.joinsTableForeignColumnName(foreignTableName)}',
];
}

/// Generate a unique name for the join table association.
/// This naming permits queries to reference associations of the same table.
/// Further discussion: https://github.com/GetDutchie/brick/issues/590
static String joinName(String tableName, String columnName) =>
'`_brick_join_${columnName}_$tableName`';
}

/// Column and iterable comparison
Expand Down Expand Up @@ -375,7 +381,11 @@ class AllOtherClausesFragment<T extends SqliteModel> {
final orderBy = query?.orderBy.map((p) {
final fieldDefinition = fieldsToColumns[p.evaluatedField];
final isAssociation = fieldDefinition?.association ?? false;
final field = '`${adapter.tableName}`.${fieldDefinition?.columnName ?? p.evaluatedField}';
final tablePrefix = AssociationFragment.joinName(
adapter.tableName,
fieldDefinition?.columnName ?? p.evaluatedField,
);
final field = '$tablePrefix.${fieldDefinition?.columnName ?? p.evaluatedField}';
if (!isAssociation) {
if (fieldDefinition?.type == DateTime) {
return 'datetime($field) ${p.ascending ? 'ASC' : 'DESC'}';
Expand All @@ -389,7 +399,7 @@ class AllOtherClausesFragment<T extends SqliteModel> {

final associationAdapter = modelDictionary.adapterFor[fieldDefinition?.type];
final associationField =
'`${associationAdapter?.tableName}`.${associationAdapter?.fieldsToSqliteColumns[p.associationField]?.columnName ?? p.associationField}';
'$tablePrefix.${associationAdapter?.fieldsToSqliteColumns[p.associationField]?.columnName ?? p.associationField}';
if (fieldDefinition?.type == DateTime) {
return 'datetime($associationField) ${p.ascending ? 'ASC' : 'DESC'}';
}
Expand Down Expand Up @@ -418,7 +428,7 @@ class AllOtherClausesFragment<T extends SqliteModel> {
if (definition != null) {
replacement = replacement.replaceAll(
part,
'`${adapter.tableName}`.${definition.columnName}',
'${AssociationFragment.joinName(adapter.tableName, definition.columnName)}.${definition.columnName}',
);
}
}
Expand Down
10 changes: 10 additions & 0 deletions packages/brick_sqlite/lib/src/sqlite_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,16 @@ class SqliteProvider<TProviderModel extends SqliteModel> implements Provider<TPr
}
}

/// Extension to print the SQL for a query. Writing and using SQL directly is
/// an antipattern; [Query] should always be used as the translation for multiple,
/// disparate providers.
String queryToSql<TModel extends SqliteModel>(Query query) {
return QuerySqlTransformer<TModel>(
modelDictionary: modelDictionary,
query: query,
).statement;
}

/// Fetch results for model with a custom SQL statement.
/// It is recommended to use [get] whenever possible. **Advanced use only**.
Future<List<TModel>> rawGet<TModel extends TProviderModel>(
Expand Down
Loading