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

clientGeneratedAs column option #3413

Open
tomasweigenast opened this issue Jan 16, 2025 · 2 comments
Open

clientGeneratedAs column option #3413

tomasweigenast opened this issue Jan 16, 2025 · 2 comments
Labels
enhancement New feature or request

Comments

@tomasweigenast
Copy link

tomasweigenast commented Jan 16, 2025

It would be nice if Drift implements the column option clientGeneratedAs. It would look like clientDefault, taking a function that accepts the companion as input, and returns a Value<ColumnType>?, but it would be executed every time we mutate the data in the database.

For example:

class Customers extends Table {
  Int64Column get id => int64().clientDefault(() => randomId())();
  IntColumn get etag => integer().withDefault(currentEpoch)();
  DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
  DateTimeColumn get modifiedAt => dateTime().withDefault(currentDateAndTime)();
  DateTimeColumn get deletedAt => dateTime().nullable()();
  TextColumn get name => text()();
  TextColumn get search => text().clientGeneratedAs((companion) => companion.name.present ? Value(companion.name.value.withoutDiacritics()) : null);

  @override
  Set<Column<Object>>? get primaryKey => {id};
}

It would allow us to specify how data mutates in the database without the need of using companion.copyWith() to mutate the search, which in this case changes when name changes.

@tomasweigenast tomasweigenast added the enhancement New feature or request label Jan 16, 2025
@simolus3
Copy link
Owner

I think I understand what you're getting at, but I'm still trying to understand how this use case is distinct from a stored generatedAs. Is the intention essentially to run more complex Dart code in generatedAs?

I guess what mainly worries me is how this would play out with e.g. a CustomersCompanion.custom used to insert or update rows based on arbitrary SQL expressions.

It's worth mentioning that this is possible already (at least in SQLite) by defining a custom function:

final db = Database(NativeDatabase.memory(setup: (database) {
  database.createFunction(
    functionName: 'remove_diacritics',
    function: (args) {
      return (args[0] as String).removeDiacritics();
    },
  );
}));

And then calling something like this in generatedAt:

extension RemoveDiacritics on Expression<String> {
  Expression<String> removeDiacritics() => FunctionCallExpression('remove_diacritics', [this]);
}

(obviously, possible is not the same thing as simple and we should perhaps find a better solution for this)

@tomasweigenast
Copy link
Author

I completely forgot about custom sqlite functions. Maybe this solution won't work using .custom in companions, and alert the user about that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants