Skip to content

Commit 156f3e4

Browse files
committed
add support for default column values
1 parent 4310c56 commit 156f3e4

21 files changed

Lines changed: 163 additions & 31 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Unreleased
2+
3+
- Added support for default column values via the `@Default` annotation.
4+
15
# 0.17.0
26

37
- Require dart sdk `>=3.7.0`.

doc/models.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,41 @@ abstract class Book {
4141
}
4242
```
4343

44+
## Default Values
45+
46+
You can specify a SQL default value for a model field using the `@Default()` annotation.
47+
The annotation takes a raw SQL expression string which will be emitted verbatim into the generated `CREATE TABLE` statement.
48+
49+
```dart
50+
@Model()
51+
abstract class Book {
52+
@PrimaryKey()
53+
String get id;
54+
55+
// string default (note the single quotes are part of the value)
56+
@Default("'untitled'")
57+
String get title;
58+
59+
// numeric default (no quotes)
60+
@Default('0')
61+
int get pageCount;
62+
63+
// datetime default using the provided convenience constructor
64+
@Default.currentTimestamp()
65+
DateTime get createdAt;
66+
}
67+
```
68+
69+
When inserting a new value, any property that is not provided will be set to the default value.
70+
71+
```dart
72+
db.books.insertOne(BookInsertRequest(
73+
id: 'book0'
74+
// title, pageCount and createdAt are optional and
75+
// will be set to their default values if not provided
76+
));
77+
```
78+
4479
## Relations
4580

4681
When using relational database systems, you model your data using relations, namely one-to-one,

example/lib/database.schema.dart

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example/lib/models/invoice.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ abstract class Invoice {
1212
String get title;
1313
String get invoiceId;
1414

15+
@Default.currentTimestamp()
16+
DateTime get createdAt;
17+
1518
@HiddenIn(#Owner)
1619
Account? get account;
1720

example/lib/models/invoice.schema.dart

Lines changed: 12 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/src/builder/elements/column/column_element.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ abstract mixin class NamedColumnElement implements ParameterColumnElement {
1414
bool get isNullable;
1515
String get sqlType;
1616
String get rawSqlType;
17+
String? get defaultValue;
1718
}
1819

1920
mixin RelationalColumnElement implements ColumnElement {

lib/src/builder/elements/column/field_column_element.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ class FieldColumnElement extends ColumnElement with NamedColumnElement {
1515

1616
late final bool isAutoIncrement;
1717

18+
@override
19+
late final String? defaultValue;
20+
1821
FieldColumnElement(this.parameter, TableElement parentTable, BuilderState state)
1922
: super(parentTable, state) {
2023
isAutoIncrement =
@@ -34,6 +37,16 @@ class FieldColumnElement extends ColumnElement with NamedColumnElement {
3437
throw 'Column field was annotated with "${r.toSource()}", which is not supported.\n'
3538
' - ${parameter.displayString()}';
3639
}
40+
41+
final defaultAnnotation =
42+
defaultChecker.firstAnnotationOf(parameter) ??
43+
defaultChecker.firstAnnotationOf(getter ?? parameter);
44+
if (defaultAnnotation != null) {
45+
var r = ConstantReader(defaultAnnotation);
46+
defaultValue = r.read('value').stringValue;
47+
} else {
48+
defaultValue = null;
49+
}
3750
}
3851

3952
@override

lib/src/builder/elements/column/foreign_column_element.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,7 @@ class ForeignColumnElement extends ColumnElement
5050
return true;
5151
}
5252
}
53+
54+
@override
55+
String? get defaultValue => null;
5356
}

lib/src/builder/generators/insert_generator.dart

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,14 @@ class InsertGenerator {
8787

8888
String toInsertValue(NamedColumnElement e) {
8989
final converter = e.converter;
90-
if (converter != null) {
91-
return '\${values.add(${converter.toSource()}.tryEncode(r.${e.paramName}))}:${e.rawSqlType}';
90+
final value =
91+
converter != null
92+
? '\${values.add(${converter.toSource()}.tryEncode(r.${e.paramName}))}:${e.rawSqlType}'
93+
: '\${values.add(r.${e.paramName})}:${e.rawSqlType}';
94+
if (e.defaultValue != null) {
95+
return '\${r.${e.paramName} != null ? \'$value\' : \'DEFAULT\'}';
9296
} else {
93-
return '\${values.add(r.${e.paramName})}:${e.rawSqlType}';
97+
return value;
9498
}
9599
}
96100

@@ -121,7 +125,8 @@ class InsertGenerator {
121125
if (!column.isAutoIncrement) {
122126
requestFields.add(
123127
MapEntry(
124-
column.parameter.type.getDisplayString(withNullability: true),
128+
column.parameter.type.getDisplayString(withNullability: false) +
129+
(column.isNullable || column.defaultValue != null ? '?' : ''),
125130
column.paramName,
126131
),
127132
);

lib/src/builder/generators/table_json_generator.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ class TableJsonGenerator {
88
'columns': {
99
for (var column in table.columns)
1010
if (column is NamedColumnElement)
11-
column.columnName: {'type': column.sqlType, if (column.isNullable) 'isNullable': true},
11+
column.columnName: {
12+
'type': column.sqlType,
13+
if (column.isNullable) 'isNullable': true,
14+
if (column.defaultValue case String v) 'default': v,
15+
},
1216
},
1317
'constraints': [
1418
if (table.primaryKeyColumn != null)

0 commit comments

Comments
 (0)