Typealiases and easier defaults for scoped components

Closes #1993.
This commit is contained in:
North101 2022-08-19 23:22:28 +01:00 committed by GitHub
parent 5a49c9540b
commit a927d3717a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 107 additions and 95 deletions

View File

@ -1606,12 +1606,13 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
}
Selectable<Config> readMultiple(List<String> var1,
{OrderBy Function(ConfigTable config) clause = _$moor$default$0}) {
{ReadMultiple$clause? clause}) {
var $arrayStartIndex = 1;
final expandedvar1 = $expandVar($arrayStartIndex, var1.length);
$arrayStartIndex += var1.length;
final generatedclause =
$write(clause(this.config), startIndex: $arrayStartIndex);
final generatedclause = $write(
clause?.call(this.config) ?? const OrderBy.nothing(),
startIndex: $arrayStartIndex);
$arrayStartIndex += generatedclause.amountOfVariables;
return customSelect(
'SELECT * FROM config WHERE config_key IN ($expandedvar1) ${generatedclause.sql}',
@ -1625,12 +1626,11 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
}).asyncMap(config.mapFromRow);
}
Selectable<Config> readDynamic(
{Expression<bool> Function(ConfigTable config) predicate =
_$moor$default$1}) {
Selectable<Config> readDynamic({ReadDynamic$predicate? predicate}) {
var $arrayStartIndex = 1;
final generatedpredicate =
$write(predicate(this.config), startIndex: $arrayStartIndex);
final generatedpredicate = $write(
predicate?.call(this.config) ?? const CustomExpression('(TRUE)'),
startIndex: $arrayStartIndex);
$arrayStartIndex += generatedpredicate.amountOfVariables;
return customSelect('SELECT * FROM config WHERE ${generatedpredicate.sql}',
variables: [
@ -1643,10 +1643,11 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
}
Selectable<String> typeConverterVar(SyncType? var1, List<SyncType?> var2,
{Expression<bool> Function(ConfigTable config) pred = _$moor$default$2}) {
{TypeConverterVar$pred? pred}) {
var $arrayStartIndex = 2;
final generatedpred =
$write(pred(this.config), startIndex: $arrayStartIndex);
final generatedpred = $write(
pred?.call(this.config) ?? const CustomExpression('(TRUE)'),
startIndex: $arrayStartIndex);
$arrayStartIndex += generatedpred.amountOfVariables;
final expandedvar2 = $expandVar($arrayStartIndex, var2.length);
$arrayStartIndex += var2.length;
@ -1694,9 +1695,7 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
});
}
Selectable<MultipleResult> multiple(
{required Expression<bool> Function(WithDefaults d, WithConstraints c)
predicate}) {
Selectable<MultipleResult> multiple({required Multiple$predicate predicate}) {
var $arrayStartIndex = 1;
final generatedpredicate = $write(
predicate(
@ -1734,8 +1733,7 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
}).asyncMap(email.mapFromRow);
}
Selectable<ReadRowIdResult> readRowId(
{required Expression<int> Function(ConfigTable config) expr}) {
Selectable<ReadRowIdResult> readRowId({required ReadRowId$expr expr}) {
var $arrayStartIndex = 1;
final generatedexpr =
$write(expr(this.config), startIndex: $arrayStartIndex);
@ -1865,11 +1863,9 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
const DriftDatabaseOptions(storeDateTimeAsText: true);
}
OrderBy _$moor$default$0(ConfigTable _) => const OrderBy.nothing();
Expression<bool> _$moor$default$1(ConfigTable _) =>
const CustomExpression('(TRUE)');
Expression<bool> _$moor$default$2(ConfigTable _) =>
const CustomExpression('(TRUE)');
typedef ReadMultiple$clause = OrderBy Function(ConfigTable config);
typedef ReadDynamic$predicate = Expression<bool> Function(ConfigTable config);
typedef TypeConverterVar$pred = Expression<bool> Function(ConfigTable config);
class JsonResult extends CustomResultSet {
final String key;
@ -1927,6 +1923,9 @@ class MultipleResult extends CustomResultSet {
}
}
typedef Multiple$predicate = Expression<bool> Function(
WithDefaults d, WithConstraints c);
class ReadRowIdResult extends CustomResultSet {
final int rowid;
final String configKey;
@ -1966,6 +1965,8 @@ class ReadRowIdResult extends CustomResultSet {
}
}
typedef ReadRowId$expr = Expression<int> Function(ConfigTable config);
class NestedResult extends CustomResultSet {
final WithDefault defaults;
final List<WithConstraint> nestedQuery0;

View File

@ -827,6 +827,12 @@ class FoundDartPlaceholder extends FoundElement {
type is ExpressionDartPlaceholderType &&
(type as ExpressionDartPlaceholderType).defaultValue != null;
bool get hasDefaultOrImplicitFallback =>
hasDefault ||
(type is SimpleDartPlaceholderType &&
(type as SimpleDartPlaceholderType).kind ==
SimpleDartPlaceholderKind.orderBy);
FoundDartPlaceholder(this.type, this.name, this.availableResultSets);
@override

View File

@ -4,6 +4,7 @@ import 'package:drift_dev/src/analyzer/sql_queries/explicit_alias_transformer.da
import 'package:drift_dev/src/analyzer/sql_queries/nested_queries.dart';
import 'package:drift_dev/src/utils/string_escaper.dart';
import 'package:drift_dev/writer.dart';
import 'package:recase/recase.dart';
import 'package:sqlparser/sqlparser.dart' hide ResultColumn;
import 'sql_writer.dart';
@ -254,20 +255,25 @@ class QueryWriter {
void _writeParameters(SqlQuery query) {
final namedElements = <FoundElement>[];
String scopedTypeName(FoundDartPlaceholder element) {
return '${ReCase(query.name).pascalCase}\$${ReCase(element.name).camelCase}';
}
String typeFor(FoundElement element) {
var type = element.dartTypeCode();
return element.dartTypeCode();
}
if (element is FoundDartPlaceholder &&
element.writeAsScopedFunction(options)) {
// Generate a function providing result sets that are in scope as args
String writeScopedTypeFor(FoundDartPlaceholder element) {
final root = scope.root;
final type = typeFor(element);
final scopedType = scopedTypeName(element);
final args = element.availableResultSets
.map((e) => '${e.argumentType} ${e.name}')
.join(', ');
type = '$type Function($args)';
}
final args = element.availableResultSets
.map((e) => '${e.argumentType} ${e.name}')
.join(', ');
root.leaf().write('typedef $scopedType = $type Function($args);');
return type;
return scopedType;
}
var needsComma = false;
@ -285,7 +291,11 @@ class QueryWriter {
} else {
if (needsComma) _buffer.write(', ');
final type = typeFor(element);
var type = typeFor(element);
if (element is FoundDartPlaceholder &&
element.writeAsScopedFunction(options)) {
type = writeScopedTypeFor(element);
}
_buffer.write('$type ${element.dartParameterName}');
needsComma = true;
}
@ -302,62 +312,27 @@ class QueryWriter {
needsComma = true;
String? defaultCode;
var isNullable = false;
var type = typeFor(optional);
if (optional is FoundDartPlaceholder) {
final kind = optional.type;
if (kind is ExpressionDartPlaceholderType &&
kind.defaultValue != null) {
// Wrap the default expression in parentheses to avoid issues with
// the surrounding precedence in SQL.
final sql = SqlWriter(scope.options)
.writeNodeIntoStringLiteral(Parentheses(kind.defaultValue!));
defaultCode = 'const CustomExpression($sql)';
} else if (kind is SimpleDartPlaceholderType &&
kind.kind == SimpleDartPlaceholderKind.orderBy) {
defaultCode = 'const OrderBy.nothing()';
}
// If optional Dart placeholders are written as functions, they are
// generated as nullable parameters. The default is handled with a
// `??` in the method's body.
if (optional.writeAsScopedFunction(options)) {
isNullable = optional.hasDefaultOrImplicitFallback;
type = writeScopedTypeFor(optional);
// If the parameter is converted to a scoped function, we also need to
// generate a scoped function as a default value. Since defaults have
// to be constants, we generate a top-level function which is then
// used as a tear-off.
if (optional.writeAsScopedFunction(options) && defaultCode != null) {
final root = scope.root;
final counter = root.counter++;
// ignore: prefer_interpolation_to_compose_strings
final functionName = r'_$moor$default$' + counter.toString();
final buffer = root.leaf()
..write(optional.dartTypeCode(scope.generationOptions))
..write(' ')
..write(functionName)
..write('(');
var i = 0;
for (final arg in optional.availableResultSets) {
if (i != 0) buffer.write(', ');
buffer
..write(arg.argumentType)
..write(' ')
..write('_' * (i + 1));
i++;
if (isNullable) {
type += '?';
}
buffer
..write(') => ')
..write(defaultCode)
..write(';');
// With the function being written, the default code is just a tear-
// off of that function
defaultCode = functionName;
} else {
defaultCode = _defaultForDartPlaceholder(optional, scope);
}
}
final type = typeFor(optional);
// No default value, this element is required if it's not nullable
var isMarkedAsRequired = false;
var isNullable = false;
if (optional is FoundVariable) {
isMarkedAsRequired = optional.isRequired;
isNullable = optional.nullableInDart;
@ -382,7 +357,7 @@ class QueryWriter {
}
void _writeExpandedDeclarations(SqlQuery query) {
_ExpandedDeclarationWriter(query, options, _buffer)
_ExpandedDeclarationWriter(query, options, scope, _buffer)
.writeExpandedDeclarations();
}
@ -441,13 +416,15 @@ String _converter(UsedTypeConverter converter) {
class _ExpandedDeclarationWriter {
final SqlQuery query;
final DriftOptions options;
final Scope _scope;
final StringBuffer _buffer;
bool indexCounterWasDeclared = false;
bool needsIndexCounter = false;
int highestIndexBeforeArray = 0;
_ExpandedDeclarationWriter(this.query, this.options, this._buffer);
_ExpandedDeclarationWriter(
this.query, this.options, this._scope, this._buffer);
void writeExpandedDeclarations() {
// When the SQL query is written to a Dart string, we give each variable an
@ -532,7 +509,17 @@ class _ExpandedDeclarationWriter {
return table;
}
}).join(', ');
return '${element.dartParameterName}($args)';
final defaultValue = _defaultForDartPlaceholder(element, _scope);
if (defaultValue != null) {
// Optional elements written as a function are generated as nullable
// parameters. We need to emit the default if the actual value is
// null at runtime.
return '${element.dartParameterName}?.call($args) ?? $defaultValue';
} else {
return '${element.dartParameterName}($args)';
}
} else {
// We can just use the parameter directly
return element.dartParameterName;
@ -694,3 +681,21 @@ class _ExpandedVariableWriter {
_buffer.write('...${placeholderContextName(element)}.introducedVariables');
}
}
String? _defaultForDartPlaceholder(
FoundDartPlaceholder placeholder, Scope scope) {
final kind = placeholder.type;
if (kind is ExpressionDartPlaceholderType && kind.defaultValue != null) {
// Wrap the default expression in parentheses to avoid issues with
// the surrounding precedence in SQL.
final sql = SqlWriter(scope.options)
.writeNodeIntoStringLiteral(Parentheses(kind.defaultValue!));
return 'const CustomExpression($sql)';
} else if (kind is SimpleDartPlaceholderType &&
kind.kind == SimpleDartPlaceholderKind.orderBy) {
return 'const OrderBy.nothing()';
} else {
assert(!placeholder.hasDefaultOrImplicitFallback);
return null;
}
}

View File

@ -2,19 +2,6 @@
part of 'database.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Preferences _$PreferencesFromJson(Map<String, dynamic> json) => Preferences(
json['receiveEmails'] as bool,
);
Map<String, dynamic> _$PreferencesToJson(Preferences instance) =>
<String, dynamic>{
'receiveEmails': instance.receiveEmails,
};
// **************************************************************************
// DriftDatabaseGenerator
// **************************************************************************
@ -665,3 +652,16 @@ class FriendshipsOfResult {
.toString();
}
}
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Preferences _$PreferencesFromJson(Map<String, dynamic> json) => Preferences(
json['receiveEmails'] as bool,
);
Map<String, dynamic> _$PreferencesToJson(Preferences instance) =>
<String, dynamic>{
'receiveEmails': instance.receiveEmails,
};