Hi!

> Try out the ischema_names thing for now.

Works like a charm - thanks a lot!

I know about manually overwriting column types (which works a sw ell of 
course), but I wanted to keep the application independent from the table 
structure (which is in a migrate repository)...

This looks very nice:
> 

my_float = FLOAT(53).with_variant(postgresql.DOUBLE_PRECISION(), 
"postgresql").with_variant(OracleBinaryDouble, "oracle")
However, it doesn't work for me (v0.7.6), or am I doing something wrong? -

----<code>---------
# Imports

import sqlalchemy
import sqlalchemy.types
import sqlalchemy.orm
import sqlalchemy.dialects

# Define User customized type

class OracleBinaryDouble(sqlalchemy.types.UserDefinedType):

    def get_col_spec(self):
        return "BINARY_DOUBLE"

BinaryDouble = sqlalchemy.types.FLOAT(53).with_variant(OracleBinaryDouble, 
"oracle")

# Database connection

engine = sqlalchemy.create_engine("oracle://XXX:ppp@tcdbs2:1521/YYY")
conn = engine.connect()
metadata = sqlalchemy.MetaData()

# Define a table using the custom data type

table = sqlalchemy.Table('test_table', metadata, 
sqlalchemy.Column('double', BinaryDouble))

# Create and insert something

metadata.create_all(engine)
conn.execute(table.insert(), double = 5.0)

conn.close()

----</code>------------

which throws an error:

Traceback (most recent call last):
  File "sqla_cust_types.py", line 30, in <module>
    conn.execute(table.insert(), double = 5.0)
  File 
"/homespace/grasppf/linux/11.1/intel/lib/python2.7/site-packages/sqlalchemy/engine/base.py",
 
line 1450, in execute
    params)
  File 
"/homespace/grasppf/linux/11.1/intel/lib/python2.7/site-packages/sqlalchemy/engine/base.py",
 
line 1583, in _execute_clauseelement
    compiled_sql, distilled_params
  File 
"/homespace/grasppf/linux/11.1/intel/lib/python2.7/site-packages/sqlalchemy/engine/base.py",
 
line 1650, in _execute_context
    None, None)
  File 
"/homespace/grasppf/linux/11.1/intel/lib/python2.7/site-packages/sqlalchemy/engine/base.py",
 
line 1646, in _execute_context
    context = constructor(dialect, self, conn, *args)
  File 
"/homespace/grasppf/linux/11.1/intel/lib/python2.7/site-packages/sqlalchemy/engine/default.py",
 
line 450, in _init_compiled
    processors = compiled._bind_processors
  File 
"/homespace/grasppf/linux/11.1/intel/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py",
 
line 485, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File 
"/homespace/grasppf/linux/11.1/intel/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py",
 
line 287, in _bind_processors
    for bindparam in self.bind_names )
  File 
"/homespace/grasppf/linux/11.1/intel/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py",
 
line 284, in <genexpr>
    (key, value) for key, value in
  File 
"/homespace/grasppf/linux/11.1/intel/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py",
 
line 287, in <genexpr>
    for bindparam in self.bind_names )
  File 
"/homespace/grasppf/linux/11.1/intel/lib/python2.7/site-packages/sqlalchemy/types.py",
 
line 201, in _cached_bind_processor
    d = self._dialect_info(dialect)
  File 
"/homespace/grasppf/linux/11.1/intel/lib/python2.7/site-packages/sqlalchemy/types.py",
 
line 226, in _dialect_info
    impl = self._gen_dialect_impl(dialect)
  File 
"/homespace/grasppf/linux/11.1/intel/lib/python2.7/site-packages/sqlalchemy/types.py",
 
line 492, in _gen_dialect_impl
    typedesc = self.load_dialect_impl(dialect).dialect_impl(dialect)
sqlalchemy.exc.StatementError: unbound method dialect_impl() must be called 
with OracleBinaryDouble instance as first argument (got 
OracleDialect_cx_oracle instance instead) (original cause: TypeError: 
unbound method dialect_impl() must be called with OracleBinaryDouble 
instance as first argument (got OracleDialect_cx_oracle instance instead)) 
'INSERT INTO test_table (double) VALUES (:double)' [{'double': 5.0}]

Thanks again!

   Christian.





On Wednesday, March 14, 2012 7:59:00 PM UTC, Michael Bayer wrote:
>
>
> On Mar 14, 2012, at 4:45 AM, marq wrote:
>
> > Hello,
> > 
> > I'm a beginner in SQLAlchemy - apologies if I'm asking for the
> > obvious...
> > 
> > I have a user defined type for Oracle (w/ SQLAlchemy 0.7.5)
> > 
> >       class OracleBinaryDouble(sqlalchemy.types.UserDefinedType):
> > 
> >        """Native double / double precision floating point data type
> >        for Oracle.
> > 
> >        """
> > 
> >        def get_col_spec(self):
> >            return "BINARY_DOUBLE"
> > 
> > which is then used in a type decorator to construct a matching user
> > defined type for all engines:
> > 
> >       class BinaryDouble(sqlalchemy.types.TypeDecorator):
> > 
> >        """Platform-independent double precision floating point type.
> > 
> >        Uses MySQL's DOUBLE and Oracle's BINARY_DOUBLE data type.
> > 
> >        """
> > 
> >        impl = sqlalchemy.types.Numeric
> > 
> >        def load_dialect_impl(self, dialect):
> >            if dialect.name == 'mysql':
> >                return
> > dialect.type_descriptor(sqlalchemy.dialects.mysql.FLOAT(53))
> >            elif dialect.name == 'sqlite':
> >                return
> > dialect.type_descriptor(sqlalchemy.dialects.sqlite.FLOAT)
> >            elif dialect.name == 'oracle':
> >                return dialect.type_descriptor(OracleBinaryDouble)
> >            elif dialect.name == 'postgresql':
> >                return
> > dialect.type_descriptor(sqlalchemy.dialects.postgresql.DOUBLE_PRECISION)
> >            else:
> >                return dialect.type_descriptor(FLOAT(53)) # 53+ bit
> > mantissa is a double precision number
>
> Some comments.  If you use sqlalchemy.types.FLOAT(53), you'll get exactly 
> FLOAT(53) in MySQL and SQLite, so you don't need to switch for those.
>
> Next, we have the "different types for different backends" built in a more 
> accessible way via with_variant():
>
> my_float = FLOAT(53).with_variant(postgresql.DOUBLE_PRECISION(), 
> "postgresql").with_variant(OracleBinaryDouble, "oracle")
>
> > 
> > When defining a database table, i.e. like
> > 
> >   meta = MetaData()
> >   level1a = Table('level1a', meta,
> >                   Column('l1a_file',              String(333),
> > primary_key = True),
> >                   Column('lon',                   BinaryDouble),
> >                   Column('lat',                   BinaryDouble)
> >   )
> > 
> > working with that table is fine, and works as intended (i.e., storing
> > double precision floating point numbers as BINARY_DOUBLE in Oracle.
> > 
> > When reflecting this table in Oracle, as in
> > 
> >       Base = sqlalchemy.ext.declarative.declarative_base()
> > 
> >    class Level1a(Base):
> >        __table__ = sqlalchemy.Table("level1a", Base.metadata,
> >                                     autoload = True, autoload_with =
> > engine)
> > 
> > I receive warnings from the Oracle driver, saying
> > 
> >   .../python2.7/site-packages/sqlalchemy/engine/reflection.py:47:
> > SAWarning: Did not recognize type 'BINARY_DOUBLE' of column 'lon'
> >  ret = fn(self, con, *args, **kw)
> >   .../python2.7/site-packages/sqlalchemy/engine/reflection.py:47:
> > SAWarning: Did not recognize type 'BINARY_DOUBLE' of column 'lat'
> >  ret = fn(self, con, *args, **kw)
> > 
> > What am I missing (or doing wrong)? I assume that the BinaryDouble
> > type must be registered somehow, but how?
>
> there's no first class API at the moment to register database types with 
> the reflection dictionary; however, if you were to populate your string 
> into sqlalchemy.dialects.oracle.base.ischema_names that would have the 
> desired effect:
>
> from sqlalchemy.dialects.oracle.base import ischema_names
> ischema_names['BINARY_DOUBLE'] = OracleBinaryDouble
>
> though we also can add these names to the distribution as people request.
>
> The other way these types can be set at reflection time is by overriding 
> the column, though this is a less automated:
>
> Table("name", metadata, Column("double_col", OracleBinaryDouble), 
> autoload=True)
>
> I also had the thought that we could make this doable with the 
> "column_reflect" event....though that won't give you what you need for now. 
>   Try out the ischema_names thing for now.
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/G9x0M7o8WbkJ.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to