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 sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to