edgedb-python icon indicating copy to clipboard operation
edgedb-python copied to clipboard

Handling default values in QB

Open vpetrovykh opened this issue 5 months ago • 2 comments

If a field has a default value in the schema, we no longer need to pass it to the insert statement. In terms of Python models this means that the field can be omitted as well. The way we want to implement this is by using default values for the Pydantic fields, so that we don't need to change whether a field is optional or required.

In EdgeQL we have __default__ expression to refer to the defined default value. We can expose a std.default that will play the role of this placeholder in Python models. Thus we'd map types in the following pattern:

  • required foo: str -> foo: str
  • required foo: str {default := 'bar'} -> foo: str | std.default
  • foo: str -> foo: str | None
  • foo: str {default := 'bar'} -> foo: str | std.default | None

Notice that None is a separate value here that is not equivalent to "default". In general, we cannot assume that None must be replaced with default because this reasoning doesn't work for optional fields (where None is a legitimate value).

In practice, the users will have to decide how they handle the input data. For a simple case of a required field with a default and no valid "falsy" values, a simple Spam(data.foo or std.default) pattern might be appropriate. If there are valid "falsy" values (like '' or 0), then a more robust pattern would be Spam(data.foo if data.foo is not None else std.default). Etc.

In terms of the save() functionality, the fields with a value of std.default can simply be omitted from the insert.

Fields with value of std.default, should be omitted from other forms of serialization, because the intent is to not have a value specified and also because we cannot consistently serialize std.default into JSON.

vpetrovykh avatar Jul 15 '25 21:07 vpetrovykh

In principle std.default may eventually be a proper equivalent of __default__ in EdgeQL expressions. For now we may restrict it to object creation.

Another possible usage is in the update, i.e. to reset a field of an existing object back to the default. If save() is invoked on an existing object an a field has value std.deefault we can assume that this means that the value needs to be explicitly reset.

vpetrovykh avatar Jul 15 '25 21:07 vpetrovykh

@vpetrovykh Is this still relevant? Fields with defaults are set to DEFAULT_VALUE if they are not explicitly set.

dnwpark avatar Sep 24 '25 22:09 dnwpark