Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -125,27 +125,38 @@ DatabaseDescription _parseGeneratorMetadata(

final relations = [
for (final table in _relationsOf(document, 'tables', schemas))
(relation: table, isInsertable: true, isUpdatable: true),
(relation: table, isInsertable: true, isUpdatable: true, isView: false),
for (final foreignTable in _relationsOf(
document,
'foreignTables',
schemas,
))
(relation: foreignTable, isInsertable: true, isUpdatable: true),
(
relation: foreignTable,
isInsertable: true,
isUpdatable: true,
isView: false,
),
for (final view in _relationsOf(document, 'views', schemas))
(
relation: view,
isInsertable:
(view['is_insert_enabled'] ?? view['is_updatable']) as bool,
isUpdatable:
(view['is_update_enabled'] ?? view['is_updatable']) as bool,
isView: true,
),
for (final materializedView in _relationsOf(
document,
'materializedViews',
schemas,
))
(relation: materializedView, isInsertable: false, isUpdatable: false),
(
relation: materializedView,
isInsertable: false,
isUpdatable: false,
isView: true,
),
];

// Document order is kept: `sortGeneratorMetadata` orders columns by name
Expand Down Expand Up @@ -180,15 +191,16 @@ DatabaseDescription _parseGeneratorMetadata(
),
};
final generatedRelations = {
for (final (:relation, isInsertable: _, isUpdatable: _) in relations)
for (final (:relation, isInsertable: _, isUpdatable: _, isView: _)
in relations)
(relation['schema'] as String, relation['name'] as String),
};
final functionsByRelationId = _functionsByRelationId(document, typesById);

final tables = <TableDescription>[];
final enumsByType = <(String, String), EnumDescription>{};

for (final (:relation, :isInsertable, :isUpdatable) in relations) {
for (final (:relation, :isInsertable, :isUpdatable, :isView) in relations) {
final relationSchema = relation['schema'] as String;
final relationName = relation['name'] as String;

Expand Down Expand Up @@ -242,7 +254,9 @@ DatabaseDescription _parseGeneratorMetadata(
_rangeBoundKinds[isArray ? format.substring(1) : format],
enumValues: isEnum ? enumValues : null,
enumType: enumDescription,
isRequired: !isNullable && !hasDefault,
// A view column does not carry the default of the column it reads,
// so an insert through the view may still omit it.
isRequired: !isView && !isNullable && !hasDefault,
hasDefault: hasDefault,
isNullable: isNullable,
isReadOnly:
Expand Down
20 changes: 10 additions & 10 deletions packages/supabase_typegen/test/fixtures/generator_metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@
"is_identity": false,
"identity_generation": null,
"is_generated": false,
"is_nullable": true,
"is_nullable": false,
"is_updatable": false,
"is_unique": false,
"check": null,
Expand Down Expand Up @@ -375,7 +375,7 @@
"is_identity": false,
"identity_generation": null,
"is_generated": false,
"is_nullable": true,
"is_nullable": false,
"is_updatable": true,
"is_unique": false,
"check": null,
Expand Down Expand Up @@ -417,7 +417,7 @@
"is_identity": false,
"identity_generation": null,
"is_generated": false,
"is_nullable": true,
"is_nullable": false,
"is_updatable": true,
"is_unique": false,
"check": null,
Expand All @@ -438,7 +438,7 @@
"is_identity": false,
"identity_generation": null,
"is_generated": false,
"is_nullable": true,
"is_nullable": false,
"is_updatable": true,
"is_unique": false,
"check": null,
Expand All @@ -459,7 +459,7 @@
"is_identity": false,
"identity_generation": null,
"is_generated": false,
"is_nullable": true,
"is_nullable": false,
"is_updatable": true,
"is_unique": false,
"check": null,
Expand All @@ -480,7 +480,7 @@
"is_identity": false,
"identity_generation": null,
"is_generated": false,
"is_nullable": true,
"is_nullable": false,
"is_updatable": false,
"is_unique": false,
"check": null,
Expand All @@ -501,7 +501,7 @@
"is_identity": false,
"identity_generation": null,
"is_generated": false,
"is_nullable": true,
"is_nullable": false,
"is_updatable": false,
"is_unique": false,
"check": null,
Expand All @@ -522,7 +522,7 @@
"is_identity": false,
"identity_generation": null,
"is_generated": false,
"is_nullable": true,
"is_nullable": false,
"is_updatable": false,
"is_unique": false,
"check": null,
Expand Down Expand Up @@ -8168,7 +8168,7 @@
"is_setof_return": true
},
"computed_field_of": 16392,
"error": null
"error": "the function public.latest_book with parameter or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache"
}
]
},
Expand Down Expand Up @@ -8327,7 +8327,7 @@
"is_setof_return": true
},
"computed_field_of": 16392,
"error": null
"error": "the function public.recent_books with parameter or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,17 @@ void main() {
'author_id',
'book_count',
]);
expect(authorStats.columns.first.isNullable, isTrue);
expect(authorStats.columns.first.isNullable, isFalse);
expect(authorStats.columns.last.isNullable, isTrue);
});

test('non-null view columns are not required on insert', () {
final bookPrices = schema.tables.singleWhere(
(table) => table.name == 'book_prices',
);
final id = bookPrices.columns.singleWhere((column) => column.name == 'id');
expect(id.isNullable, isFalse);
expect(id.isRequired, isFalse);
});

test('foreign tables are insertable and updatable', () {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated by supabase_typegen 0.5.0 from GeneratorMetadata version 1.
// Generated by supabase_typegen 0.5.2 from GeneratorMetadata version 1.
// Do not edit by hand.
//
// Source schemas: evil multiline "schema" name, private, public
Expand Down
66 changes: 17 additions & 49 deletions packages/supabase_typegen/test/goldens/supabase_schema.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated by supabase_typegen 0.5.0 from GeneratorMetadata version 1.
// Generated by supabase_typegen 0.5.2 from GeneratorMetadata version 1.
// Do not edit by hand.
//
// Source schemas: inventory, public
Expand Down Expand Up @@ -215,7 +215,7 @@ class InventoryStock {
/// Aggregated statistics per author
extension type const AuthorStatsRow(Map<String, dynamic> _json)
implements Object {
int? get authorId => _json['author_id'] as int?;
int get authorId => _json['author_id'] as int;
int? get bookCount => _json['book_count'] as int?;

/// The row as decoded from the response.
Expand All @@ -235,9 +235,7 @@ class AuthorStats {
relations: [authors],
);

static const authorId = PostgrestNullableColumn<AuthorStatsRow, int>(
'author_id',
);
static const authorId = PostgrestColumn<AuthorStatsRow, int>('author_id');
static const bookCount = PostgrestNullableColumn<AuthorStatsRow, int>(
'book_count',
);
Expand Down Expand Up @@ -331,9 +329,9 @@ class Authors {
extension type const BookPricesRow(Map<String, dynamic> _json)
implements Object {
num? get discountedPrice => _json['discounted_price'] as num?;
int? get id => _json['id'] as int?;
int get id => _json['id'] as int;
num? get price => _json['price'] as num?;
String? get title => _json['title'] as String?;
String get title => _json['title'] as String;

/// The row as decoded from the response.
Map<String, dynamic> toJson() => _json;
Expand All @@ -349,18 +347,10 @@ extension type const BookPricesInsert._(Map<String, dynamic> _json)
BookPricesInsert({int? id, num? price, String? title})
: this._({'id': ?id, 'price': ?price, 'title': ?title});

/// Returns a copy with `id` set to SQL NULL, overriding any database default.
BookPricesInsert setIdToNull() => BookPricesInsert._({..._json, 'id': null});

/// Returns a copy with `price` set to SQL NULL, overriding any database
/// default.
BookPricesInsert setPriceToNull() =>
BookPricesInsert._({..._json, 'price': null});

/// Returns a copy with `title` set to SQL NULL, overriding any database
/// default.
BookPricesInsert setTitleToNull() =>
BookPricesInsert._({..._json, 'title': null});
}

/// Values for updating rows of `book_prices`. All columns are optional; passing
Expand All @@ -371,18 +361,10 @@ extension type const BookPricesUpdate._(Map<String, dynamic> _json)
BookPricesUpdate({int? id, num? price, String? title})
: this._({'id': ?id, 'price': ?price, 'title': ?title});

/// Returns a copy with `id` set to SQL NULL, overriding any database default.
BookPricesUpdate setIdToNull() => BookPricesUpdate._({..._json, 'id': null});

/// Returns a copy with `price` set to SQL NULL, overriding any database
/// default.
BookPricesUpdate setPriceToNull() =>
BookPricesUpdate._({..._json, 'price': null});

/// Returns a copy with `title` set to SQL NULL, overriding any database
/// default.
BookPricesUpdate setTitleToNull() =>
BookPricesUpdate._({..._json, 'title': null});
}

/// Typed access to the `book_prices` table.
Expand All @@ -402,9 +384,9 @@ class BookPrices {
static const discountedPrice = PostgrestNullableColumn<BookPricesRow, num>(
'discounted_price',
);
static const id = PostgrestNullableColumn<BookPricesRow, int>('id');
static const id = PostgrestColumn<BookPricesRow, int>('id');
static const price = PostgrestNullableColumn<BookPricesRow, num>('price');
static const title = PostgrestNullableColumn<BookPricesRow, String>('title');
static const title = PostgrestColumn<BookPricesRow, String>('title');

/// The `discount` computed field, selected by name; `select()` leaves it out.
static const discount = PostgrestComputedField<BookPricesRow, num>(
Expand All @@ -416,8 +398,8 @@ class BookPrices {
/// column.
extension type const BookSubmissionsRow(Map<String, dynamic> _json)
implements Object {
String? get authorName => _json['author_name'] as String?;
String? get title => _json['title'] as String?;
String get authorName => _json['author_name'] as String;
String get title => _json['title'] as String;

/// The row as decoded from the response.
Map<String, dynamic> toJson() => _json;
Expand All @@ -432,16 +414,6 @@ extension type const BookSubmissionsInsert._(Map<String, dynamic> _json)
implements Object {
BookSubmissionsInsert({String? authorName, String? title})
: this._({'author_name': ?authorName, 'title': ?title});

/// Returns a copy with `author_name` set to SQL NULL, overriding any database
/// default.
BookSubmissionsInsert setAuthorNameToNull() =>
BookSubmissionsInsert._({..._json, 'author_name': null});

/// Returns a copy with `title` set to SQL NULL, overriding any database
/// default.
BookSubmissionsInsert setTitleToNull() =>
BookSubmissionsInsert._({..._json, 'title': null});
}

/// Typed access to the `book_submissions` table.
Expand All @@ -457,22 +429,20 @@ class BookSubmissions {
primaryKey: [],
);

static const authorName = PostgrestNullableColumn<BookSubmissionsRow, String>(
static const authorName = PostgrestColumn<BookSubmissionsRow, String>(
'author_name',
);
static const title = PostgrestNullableColumn<BookSubmissionsRow, String>(
'title',
);
static const title = PostgrestColumn<BookSubmissionsRow, String>('title');
}

/// A row of the `book_summaries` table, as `select()` reads it with every
/// column.
/// Denormalized book and author names
extension type const BookSummariesRow(Map<String, dynamic> _json)
implements Object {
String? get authorName => _json['author_name'] as String?;
int? get id => _json['id'] as int?;
String? get title => _json['title'] as String?;
String get authorName => _json['author_name'] as String;
int get id => _json['id'] as int;
String get title => _json['title'] as String;

/// The row as decoded from the response.
Map<String, dynamic> toJson() => _json;
Expand All @@ -490,13 +460,11 @@ class BookSummaries {
primaryKey: [],
);

static const authorName = PostgrestNullableColumn<BookSummariesRow, String>(
static const authorName = PostgrestColumn<BookSummariesRow, String>(
'author_name',
);
static const id = PostgrestNullableColumn<BookSummariesRow, int>('id');
static const title = PostgrestNullableColumn<BookSummariesRow, String>(
'title',
);
static const id = PostgrestColumn<BookSummariesRow, int>('id');
static const title = PostgrestColumn<BookSummariesRow, String>('title');
}

/// A row of the `books` table, as `select()` reads it with every column.
Expand Down
Loading