Thank you very much!

I tried version 1 with hybrid properties which look something like this:

class Quetschmass(Base):
    __tablename__ = 'MyTable'


    ID = Column(sa.Integer, primary_key=True)
    serial_number = Column(types.NCHAR)

    @hybrid_property
    def SN(self):
        return int(self.serial_number )


    @SN.setter
    def SN(self, value):
        self.serial_number = str(value)


    @SN.expression
    def SN(self):
        return sa.func.CONVERT(sa.literal_column('INT'), self.serial_number 
)

Which seems to work as expected for most cases:

obj= MyTable(SN=13)
session.add(obj)
session.commit()

# Resulting SQL:
# INSERT INTO [MyTable] ([Head_SN]) OUTPUT inserted.[ID] VALUES (?)

objects = session.query(MyTable).filter(MyTable.SN < 100)

# Resulting SQL:
# SELECT [MyTable].[ID] AS [MyTable_ID], [MyTable].[serial_number] AS [
MyTable_serial_number] 
# FROM [MyTable] 
# WHERE CONVERT(INT, [MyTable].[serial_number]) < ?

session.query(Quetschmass).filter(Quetschmass.SN == 
13).delete(synchronize_session='fetch')
session.commit()

# Resulting SQL:
# SELECT [MyTable].[ID] AS [MyTable_ID] 
# FROM [MyTable] 
# WHERE CONVERT(INT, [MyTable].[serial_number]) = ?
#
# DELETE FROM [MyTable] WHERE CONVERT(INT, [MyTable].[serial_number]) = ?


The only question is about the delete(synchronize_session='fetch'). Why is 
this required?



Am Freitag, 3. August 2018 15:35:40 UTC+2 schrieb Mike Bayer:
>
> On Fri, Aug 3, 2018 at 5:29 AM, Jürg Rast <[email protected] <javascript:>> 
> wrote: 
> > bind_expression() seems to be applied on the wrong side of the where 
> clause. 
> > For example, my bind_expression function looks like this: 
> > 
> >     def bind_expression(self, val): 
> >         return sa.func.CONVERT(sa.literal_column('INT'), val) 
> > 
> > If I use this in a query like 
> > 
> >   engine.execute(table.select(table.c.serial_number > 
> > 500).limit(1)).fetchone()) 
> > 
> > The following SQL is executed: 
> > 
> > SELECT TOP 1 [MyTable].[ID], CONVERT(INT, [MyTable].[serial_number ]) AS 
> > [serial_number ] 
> > FROM [MyTable] 
> > WHERE [MyTable].[serial_number ] > CONVERT(INT, ?) 
> > 
> > So, the CONVERT is applied to the value (in my case 500) and not to the 
> > colum ([MyTable].[serial_number] in my case). I expected something like 
> > 
> > SELECT TOP 1 [MyTable].[ID], CONVERT(INT, [MyTable].[serial_number ]) AS 
> > [serial_number ] 
> > FROM [MyTable] 
> > WHERE CONVERT(INT, [MyTable].[serial_number ]) > ? 
> > 
> > Is this also possible? 
>
> the bind/column/result methods of types are only used for the link 
> between Python values and SQL code.  They don't apply to SQL elements 
> that are within a statement that don't link to a Python value being 
> passed in such as a column. 
>
> Options for having a particular column always have a CONVERT function 
> around it no matter where it is include: 
>
> 1. when you place the column in your query, don't use the variable 
> that refers to the column (e.g. MyModel.column), use the "convert" 
> function version of it (eg. MyModel.converted_column).  Options for 
> this with the ORM include using column_property() as well as hybrids. 
>  By far the simplest way to do this. 
>
> 2. create a custom type that also overrides comparison methods, such 
> that the column expression part of it receives the CONVERT.   This is 
> a fairly intricate way to travel in this case since you need that 
> function probably on a lot of comparisons (__lt__, __le__, __eq__, 
> etc) and there may be some edge cases that make certain things more 
> challenging when doing this (e.g. the conversion happens when you 
> don't want it to, kinds of situations).  An introduction is at 
>
> http://docs.sqlalchemy.org/en/latest/core/custom_types.html#redefining-and-creating-new-operators.
>  
>
>
> 3. apply statement processing using a visitor.   this would be even 
> more complicated than #2 so probably not worth it. 
>
>
> > 
> > 
> > Am Dienstag, 31. Juli 2018 18:59:39 UTC+2 schrieb Mike Bayer: 
> >> 
> >> A WHERE clause is going to be binding your parameter into the SQL so 
> you 
> >> need to use the bind_expression() method as well, in a manner very 
> similar 
> >> to how you are using column_expression(). 
> >> 
> >> On Tue, Jul 31, 2018, 12:45 PM Jürg Rast <[email protected]> wrote: 
> >>> 
> >>> I have to work with a old database which stores almost all information 
> as 
> >>> strings (VARCHAR, NCHAR). To create a usable interface, I tought of 
> creating 
> >>> a UserDefinedType or a TypeDecorator to convert the values which are 
> fed to 
> >>> the database or loaded from the database. 
> >>> 
> >>> Both versions seem to work when used like this: 
> >>> 
> >>> class IntegerString(types.UserDefinedType): 
> >>> 
> >>> 
> >>>     def get_col_spec(self): 
> >>>         return 'NCHAR' 
> >>> 
> >>> 
> >>>     def column_expression(self, col): 
> >>>         return sa.func.CONVERT(sa.literal_column('INT'), col) 
> >>> 
> >>> 
> >>> 
> >>> 
> >>> class TestType(types.TypeDecorator): 
> >>> 
> >>> 
> >>>     impl = types.NCHAR 
> >>> 
> >>> 
> >>>     def process_bind_param(self, value, dialect): 
> >>>         return str(value) 
> >>> 
> >>> 
> >>>     def process_result_value(self, value, dialect): 
> >>>         return int(value) 
> >>> 
> >>> 
> >>> Where the IntergerString works at the database level and the TestType 
> >>> works at the application level. However, what is missing is type 
> conversion 
> >>> if the column is used in Where Clauses. Is there a method to apply the 
> type 
> >>> conversion at the database level for where clauses? 
> >>> 
> >>> 
> >>> -- 
> >>> SQLAlchemy - 
> >>> The Python SQL Toolkit and Object Relational Mapper 
> >>> 
> >>> http://www.sqlalchemy.org/ 
> >>> 
> >>> To post example code, please provide an MCVE: Minimal, Complete, and 
> >>> Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
> >>> description. 
> >>> --- 
> >>> 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 https://groups.google.com/group/sqlalchemy. 
> >>> For more options, visit https://groups.google.com/d/optout. 
> > 
> > -- 
> > SQLAlchemy - 
> > The Python SQL Toolkit and Object Relational Mapper 
> > 
> > http://www.sqlalchemy.org/ 
> > 
> > To post example code, please provide an MCVE: Minimal, Complete, and 
> > Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
> > description. 
> > --- 
> > 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] <javascript:>. 
> > To post to this group, send email to [email protected] 
> <javascript:>. 
> > Visit this group at https://groups.google.com/group/sqlalchemy. 
> > For more options, visit https://groups.google.com/d/optout. 
>

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
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 https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to