Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use native postgres boolean type instead of integers #2116

Merged
merged 19 commits into from
Nov 8, 2022
Merged
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
33 changes: 19 additions & 14 deletions drift/example/main.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions drift/lib/src/runtime/api/connection_user.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ abstract class DatabaseConnectionUser {
/// values. In the future, they could be expanded to dialect-specific options.
DriftDatabaseOptions get options => attachedDatabase.options;

/// A [SqlTypes] mapping configuration to use when mapping values between Dart
/// and SQL.
SqlTypes get typeMapping => options.createTypeMapping(executor.dialect);

/// The database class that this user is attached to.
@visibleForOverriding
GeneratedDatabase get attachedDatabase;
Expand Down
14 changes: 12 additions & 2 deletions drift/lib/src/runtime/api/options.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import '../types/mapping.dart';
import 'package:drift/drift.dart';

/// Database-specific options used by drift.
///
Expand All @@ -7,8 +7,11 @@ import '../types/mapping.dart';
class DriftDatabaseOptions {
/// Configuration for [SqlTypes] describing how to map Dart values from and to
/// SQL values.
@Deprecated('UsecreateTypeMapping instead')
final SqlTypes types;

final bool _storeDateTimeAsText;

/// Creates database-specific database options.
///
/// When [storeDateTimeAsText] is enabled (it defaults to `false` for
Expand All @@ -20,6 +23,13 @@ class DriftDatabaseOptions {
/// [the documentation]: https://drift.simonbinder.eu/docs/getting-started/advanced_dart_tables/#supported-column-types
const DriftDatabaseOptions({
bool storeDateTimeAsText = false,
}) : types =
}) : _storeDateTimeAsText = storeDateTimeAsText,
// ignore: deprecated_member_use_from_same_package
types =
storeDateTimeAsText ? const SqlTypes(true) : const SqlTypes(false);

/// Creates a type mapping suitable for these options and the given [dialect].
SqlTypes createTypeMapping(SqlDialect dialect) {
return SqlTypes(_storeDateTimeAsText, dialect);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class _BetweenExpression extends Expression<bool> {

// We don't want to compare datetime values lexicographically, so we convert
// them to a comparable unit
if (context.options.types.storeDateTimesAsText) {
if (context.typeMapping.storeDateTimesAsText) {
if (target is Expression<DateTime>) target = target.julianday;
if (lower is Expression<DateTime>) lower = lower.julianday;
if (higher is Expression<DateTime>) higher = higher.julianday;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ class _StrftimeSingleFieldExpression extends Expression<int> {
context.buffer.write("CAST(strftime('$format', ");
date.writeInto(context);

if (!context.options.types.storeDateTimesAsText) {
if (!context.typeMapping.storeDateTimesAsText) {
context.buffer.write(", 'unixepoch'");
}
context.buffer.write(') AS INTEGER)');
Expand Down Expand Up @@ -300,7 +300,7 @@ class _DependingOnDateTimeExpression<D extends Object> extends Expression<D> {
Object.hash(_DependingOnDateTimeExpression, forTimestamps, forIsoString);

Expression<D> _expressionForContext(GenerationContext context) {
if (context.options.types.storeDateTimesAsText) {
if (context.typeMapping.storeDateTimesAsText) {
return forIsoString;
} else {
return forTimestamps;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ class _Comparison extends InfixOperator<bool> {

if (left is Expression<DateTime> &&
right is Expression<DateTime> &&
context.options.types.storeDateTimesAsText) {
context.typeMapping.storeDateTimesAsText) {
// Compare julianday values instead of texts
writeInner(context, left.julianday);
context.writeWhitespace();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class Variable<T extends Object> extends Expression<T> {
/// database engine. For instance, a [DateTime] will me mapped to its unix
/// timestamp.
dynamic mapToSimpleValue(GenerationContext context) {
return context.options.types.mapToSqlVariable(value);
return context.typeMapping.mapToSqlVariable(value);
}

@override
Expand All @@ -83,7 +83,10 @@ class Variable<T extends Object> extends Expression<T> {
context.buffer
..write(mark)
..write(explicitStart + context.amountOfVariables);
context.introduceVariable(this, mapToSimpleValue(context));
context.introduceVariable(
this,
mapToSimpleValue(context),
);
} else {
context.buffer.write(mark);
context.introduceVariable(this, mapToSimpleValue(context));
Expand Down Expand Up @@ -117,7 +120,7 @@ class Constant<T extends Object> extends Expression<T> {

@override
void writeInto(GenerationContext context) {
context.buffer.write(context.options.types.mapToSqlLiteral(value));
context.buffer.write(context.typeMapping.mapToSqlLiteral(value));
}

@override
Expand Down
12 changes: 10 additions & 2 deletions drift/lib/src/runtime/query_builder/generation_context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ class GenerationContext {
final List<ResultSetImplementation> watchedTables = [];

/// The options to use when mapping values from and to the database.
@Deprecated('Use typeMapping instead')
final DriftDatabaseOptions options;

/// The [SqlTypes] configuration used for mapping values to the database.
final SqlTypes typeMapping;

/// The [SqlDialect] that should be respected when generating the query.
SqlDialect get dialect => executor?.executor.dialect ?? SqlDialect.sqlite;

Expand Down Expand Up @@ -58,12 +62,16 @@ class GenerationContext {
/// database.
GenerationContext.fromDb(DatabaseConnectionUser this.executor,
{this.supportsVariables = true})
: options = executor.options;
// ignore: deprecated_member_use_from_same_package
: options = executor.options,
typeMapping = executor.typeMapping;

/// Constructs a custom [GenerationContext] by setting the fields manually.
/// See [GenerationContext.fromDb] for a more convenient factory.
GenerationContext(this.options, this.executor,
{this.supportsVariables = true});
{this.supportsVariables = true})
: typeMapping = options
.createTypeMapping(executor?.executor.dialect ?? SqlDialect.sqlite);

/// Introduces a variable that will be sent to the database engine. Whenever
/// this method is called, a question mark should be added to the [buffer] so
Expand Down
45 changes: 37 additions & 8 deletions drift/lib/src/runtime/query_builder/schema/column_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class GeneratedColumn<T extends Object> extends Column<T> {
final bool $nullable;

/// Default constraints generated by drift.
final String? _defaultConstraints;
final void Function(GenerationContext)? _defaultConstraints;

/// Custom constraints that have been specified for this column.
///
Expand Down Expand Up @@ -65,8 +65,7 @@ class GeneratedColumn<T extends Object> extends Column<T> {

/// Whether this column has an `AUTOINCREMENT` primary key constraint that was
/// created by drift.
bool get hasAutoIncrement =>
_defaultConstraints?.contains('AUTOINCREMENT') == true;
final bool hasAutoIncrement;

@override
String get name => $name;
Expand All @@ -78,13 +77,14 @@ class GeneratedColumn<T extends Object> extends Column<T> {
this.$nullable, {
this.clientDefault,
required this.type,
String? defaultConstraints,
void Function(GenerationContext)? defaultConstraints,
this.$customConstraints,
this.defaultValue,
this.additionalChecks,
this.requiredDuringInsert = false,
this.generatedAs,
this.check,
this.hasAutoIncrement = false,
}) : _defaultConstraints = defaultConstraints;

/// Applies a type converter to this column.
Expand All @@ -106,6 +106,7 @@ class GeneratedColumn<T extends Object> extends Column<T> {
requiredDuringInsert,
generatedAs,
check,
hasAutoIncrement,
);
}

Expand Down Expand Up @@ -157,9 +158,7 @@ class GeneratedColumn<T extends Object> extends Column<T> {

// these custom constraints refer to builtin constraints from drift
if (!isSerial && _defaultConstraints != null) {
into.buffer
..write(' ')
..write(_defaultConstraints);
_defaultConstraints!(into);
}
} else if ($customConstraints?.isNotEmpty == true) {
into.buffer
Expand Down Expand Up @@ -247,6 +246,34 @@ class GeneratedColumn<T extends Object> extends Column<T> {
return const VerificationResult.success();
};
}

/// A helper method to make creating [defaultConstraints] simpler. Used when
/// the constraint does not depend on the dialect.
///
/// Used by generated code.
static Function(GenerationContext) constraintIsAlways(String constraint) =>
(context) => context.buffer
..write(' ')
..write(constraint);

/// A helper method to make creating [defaultConstraints] simpler. Used when
/// the constraint depends on the dialect.
///
/// Used by generated code.
static Function(GenerationContext) constraintsDependsOnDialect(
Map<SqlDialect, String> constraints,
) =>
(context) {
final constraint = constraints[context.dialect];

if (constraint == null || constraint.isEmpty) {
return;
}

context.buffer
..write(' ')
..write(constraint);
};
}

/// A [GeneratedColumn] with a type converter attached to it.
Expand All @@ -265,13 +292,14 @@ class GeneratedColumnWithTypeConverter<D, S extends Object>
bool nullable,
S? Function()? clientDefault,
DriftSqlType<S> type,
String? defaultConstraints,
void Function(GenerationContext)? defaultConstraints,
String? customConstraints,
Expression<S>? defaultValue,
VerificationResult Function(S?, VerificationMeta)? additionalChecks,
bool requiredDuringInsert,
GeneratedAs? generatedAs,
Expression<bool> Function()? check,
bool hasAutoIncrement,
) : super(
name,
tableName,
Expand All @@ -285,6 +313,7 @@ class GeneratedColumnWithTypeConverter<D, S extends Object>
requiredDuringInsert: requiredDuringInsert,
generatedAs: generatedAs,
check: check,
hasAutoIncrement: hasAutoIncrement,
);

S? _mapDartValue(D? dartValue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class QueryRow {
/// support non-nullable types.
T read<T>(String key) {
final type = DriftSqlType.forNullableType<T>();
return _db.options.types.read(type, data[key]) as T;
return _db.typeMapping.read(type, data[key]) as T;
}

/// Reads a nullable value from this row.
Expand All @@ -90,7 +90,7 @@ class QueryRow {
/// drift (e.g. booleans, strings, numbers, dates, `Uint8List`s).
T? readNullable<T extends Object>(String key) {
final type = DriftSqlType.forType<T>();
return _db.options.types.read(type, data[key]);
return _db.typeMapping.read(type, data[key]);
}

/// Reads a bool from the column named [key].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ class JoinedSelectStatement<FirstT extends HasResultSet, FirstD>
final expr = aliasedColumn.key;
final value = row[aliasedColumn.value];

readColumns[expr] = ctx.options.types.read(expr.driftSqlType, value);
readColumns[expr] = ctx.typeMapping.read(expr.driftSqlType, value);
}

return TypedResult(readTables, QueryRow(row, database), readColumns);
Expand Down
Loading