Hi there,
I'm working with a database where the original designer has chosen to
represent a large number of values as bitflags. Nearly every table in the
database has a 'flags' integer which is bitwise ORred or ANDed with
constants stored in the application code to extract the relevant options.
I'm trying to wrap this in a custom type which will allow me to refer to
these values individually as booleans and I can't figure out the correct
approach. Here's an example:
class TestFlags(object):
flag_value_one = 1
flag_value_two = 2
flag_value_three = 4
flag_value_four = 8
class TestModel(TestBase):
__tablename__ = "testmodel"
id = Column("id", Integer, primary_key=True)
flags = Column("flags", Integer)
flag_one = column_property(Column("flags", Flag(TestFlags,
"flag_value_one")))
flag_two = column_property(Column("flags", Flag(TestFlags,
"flag_value_two")))
flag_three = column_property(Column("flags", Flag(TestFlags,
"flag_value_three")))
flag_four = column_property(Column("flags", Flag(TestFlags,
"flag_value_four")))
So what I want to be able to do is these kind of interactions
m = session.query(TestModel).filter(TestModel.flag_one == True).first()
m.flag_one = False
session.add(m.flag_one)
session.commit()
assert((m.flags & 1) == 0)
I can see how one would accomplish this with hybrid attributes but with
every table having 5 to 10 flags defined on it that would lead to a lot of
typing, hence the custom type approach. I attempted the following:
class Flag(TypeDecorator):
impl = Integer
def __init__(self, flag_constants, flag_name, *args, **kwargs):
super(Flag, self).__init__(*args, **kwargs)
self.flag_constants = flag_constants
self.flag_name = flag_name
def column_expression(self, col):
return col.op("&")(getattr(self.flag_constants, self.flag_name))
Which works great for querying values but not for updating or inserting
them. Another point which I can't figure out is what to do if updating
multiple flags in the same step. It seems to me that it would make more
sense to do this in process_bind_param but then obviously there is no
current value of the flag integer for me to operate against. So, I'm a bit
lost, any ideas on how to implement this would be greatly appreciated.
Thanks
Alex
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.