allow the possibility of column-level "default" values to populate before persistence (new event + recipe)

Issue #1311 resolved
Former user created an issue

In declarative mode, you are able to write something like:

class Person(DeclarativeBase):
    status = Column(Unicode(20), nullable=False, default=u'alive')

Unfortunately, the "default" parameter is only taken into account when inserting the Person into the database. It means that, until you flush() the session, querying the "status" attribute will return None rather than the default value. It would be handier if the descriptor was smart enough to return the default value when it hasn't been set.

Comments (8)

  1. Mike Bayer repo owner
    • changed milestone to blue sky
    • changed component to orm

    this can be accomplished using an AttributeExtension. that's not a comment on the default behavior of Column with default however.

  2. Mike Bayer repo owner

    let me clarify why its not a trivial behavioral change to make defaults fire off on first ORM attribute access in all cases (as an optional behavior, its not a problem at all).

    The example above is a straight string value, but "default" accommodates Python functions as well as SQL expressions too. The fact that you can have a SQL expression there automatically makes consistent behavior here impossible. If a new object is not attached to a session, accessing the attribute would require an error raise for a SQL-based default.

    If the object is present in the session, accessing the "status" variable could either execute the SQL expression standalone, or it could perform a flush() and refetch from the database. It might seem like the former is appropriate, except it is not always - the default function may be a context-sensitive function which draws upon the other values in the ExecutionContext. It might be a timestamp representing the time that the full row was inserted. It also can in some cases result in many more round trips than the "flush()" approach would have, such as many columns with defaults firing off individually that would otherwise be executed with a single INSERT and SELECT of the whole row. on the other hand defaulting to an implicit flush() is a huge surprise in a wide range of scenarios - automatic flushing of pending objects attached to a session is a big source of problems as the object may not have all required attributes populated.

    The proposed feature is also a big behavioral change for a huge number of applications and would probably cause a lot of breakage and upgrade headaches, for any application which is expecting the default value of None which operates right now.

    It's not controversial at all though to use an attribute extension to provide a pre-flush default.

  3. Mike Bayer repo owner

    and let me correct myself further that AttributeExtension doesn't allow this to be implemented at the moment. you'd have to use descriptors. a possible AttributeExtension approach would be a create_default() method added to its definition, but its signature and behavior would need to be carefully considered.

  4. Mike Bayer repo owner
    • add an init_scalar event, which allows us to build out default-setting recipes such as one that allows us to actively read column-level defaults. References #1311

    → <<cset ee79d879e480>>

  5. Mike Bayer repo owner

    Add an init_scalar event for attributes

    This allows us to build default-setting recipes such as one that allows us to actively read column-level defaults. An example suite is also added.

    Change-Id: I7b022d52cc89526132d5bc4201ac27fea4cf088d Fixes: #1311

    → <<cset e28b44813721>>

  6. Log in to comment