Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wrap a column in a CAST operation

I have an MSSQL database with tables which I cannot change and only ever interact with it as read only (SELECT statements). I am using sqlalchemy. What I need to do is to automatically wrap specific columns in CAST() SQL operations for every query. I want to do this at a low level so my code never needs to think about the problem. The reason I am doing this is explained in this question.

My table is something like this:

from sqlalchemy import Column, Integer, Sequence
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class myTable(Base):
    __tablename__ = u'mytable'
    id = Column(Integer, Sequence('table_id_seq'), primary_key=True)
    problem_field = Column(DECIMAL(12, 4), nullable=True)

I have been trying to use a TypeDecorator like this:

from sqlalchemy import Column, Integer, Sequence, types
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql.expression import cast

Base = declarative_base()

class CastToFloatType(types.TypeDecorator):
    '''Converts stored Decimal values to Floats via CAST operation
    '''
    impl = types.Numeric
    def column_expression(self, col):
        return cast(col, Float)

class myTable(Base):
    __tablename__ = u'mytable'
    id = Column(Integer, Sequence('table_id_seq'), primary_key=True)
    wrapped_field = Column(CastToFloatType, nullable=True)

But it doesn't seem to do anything.

like image 848
Graeme Stuart Avatar asked Nov 06 '13 17:11

Graeme Stuart


1 Answers

I think you need to make sure you're on at least version 0.8 of SQLAlchemy, where the column_expression() feature was added. A simple test of your code works on this end:

from sqlalchemy import Column, Integer, Sequence, types, Float
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql.expression import cast

Base = declarative_base()

class CastToFloatType(types.TypeDecorator):
    '''Converts stored Decimal values to Floats via CAST operation
    '''
    impl = types.Numeric
    def column_expression(self, col):
        return cast(col, Float)

class myTable(Base):
    __tablename__ = u'mytable'
    id = Column(Integer, Sequence('table_id_seq'), primary_key=True)
    wrapped_field = Column(CastToFloatType, nullable=True)

from sqlalchemy.orm import Session
s = Session()
print s.query(myTable)

output:

SELECT mytable.id AS mytable_id, CAST(mytable.wrapped_field AS FLOAT) AS mytable_wrapped_field 
FROM mytable
like image 108
zzzeek Avatar answered Oct 04 '22 02:10

zzzeek