My module is called sandbox.py
After importing it to ipython and letting it run, here's what I get
for the test you suggested:

In [47]: (sandbox.price_sources.c.desciption=='EJV').right.type
Out[47]: OracleChar(length=100, convert_unicode=False,
assert_unicode=None)

The trouble that for some reason the code goes into
sqlalchemy.types.String.get_dbapi_type instead of
sqlalchemy.databases.oracle.OracleChar

In [14]: pdb.run('sandbox.test()')
> <string>(1)<module>()
(Pdb) b /usr/local/lib/python2.6/site-packages/SQLAlchemy-0.5.5-
py2.6.egg/sqlalchemy/engine/default.py:322
Breakpoint 7 at /usr/local/lib/python2.6/site-packages/
SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/engine/default.py:322
(Pdb) c
2009-10-02 17:58:18,020 INFO sqlalchemy.engine.base.Engine.0x...97ec
SELECT USER FROM DUAL
2009-10-02 17:58:18,020 INFO sqlalchemy.engine.base.Engine.0x...97ec
{}
2009-10-02 17:58:18,025 INFO sqlalchemy.engine.base.Engine.0x...97ec
select table_name from all_tables where table_name=:name and
owner=:schema_name
2009-10-02 17:58:18,026 INFO sqlalchemy.engine.base.Engine.0x...97ec
{'name': 'VICTOR_PRICE_SOURCES', 'schema_name': 'CDOCOLLAT'}
> /usr/local/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/engine/default.py(322)set_input_sizes()
-> dbtype = typeengine.dialect_impl(self.dialect).get_dbapi_type
(self.dialect.dbapi)
(Pdb) dbtype
*** NameError: name 'dbtype' is not defined
(Pdb) typeengine.dialect_impl(self.dialect)

OracleChar(length=100, convert_unicode=False, assert_unicode=None)

(Pdb) # we should be going into OracleChar.get_dbapi_type

*** SyntaxError: unexpected EOF while parsing (<stdin>, line 1)
(Pdb) s
--Call--
> /usr/local/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/types.py(124)dialect_impl()
-> def dialect_impl(self, dialect, **kwargs):
(Pdb) l
119               Column('data', MyType(16))
120               )
121
122         """
123
124  ->     def dialect_impl(self, dialect, **kwargs):
125             try:
126                 return self._impl_dict[dialect]
127             except AttributeError:
128                 self._impl_dict = weakref.WeakKeyDictionary()   #
will be optimized in 0.6
129                 return self._impl_dict.setdefault(dialect,
dialect.type_descriptor(self))
(Pdb) l
130             except KeyError:
131                 return self._impl_dict.setdefault(dialect,
dialect.type_descriptor(self))
132
133         def __getstate__(self):
134             d = self.__dict__.copy()
135             d.pop('_impl_dict', None)
136             return d
137
138         def get_col_spec(self):
139             """Return the DDL representation for this type."""
140             raise NotImplementedError()
(Pdb) dialect
<sqlalchemy.databases.oracle.OracleDialect object at 0xa1ae54c>
(Pdb) n
> /usr/local/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/types.py(125)dialect_impl()
-> try:
(Pdb) n
> /usr/local/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/types.py(126)dialect_impl()
-> return self._impl_dict[dialect]
(Pdb) n
--Return--
> /usr/local/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/types.py(126)dialect_impl()->OracleCh...ode=None)
-> return self._impl_dict[dialect]
(Pdb) l
121
122         """
123
124         def dialect_impl(self, dialect, **kwargs):
125             try:
126  ->             return self._impl_dict[dialect]
127             except AttributeError:
128                 self._impl_dict = weakref.WeakKeyDictionary()   #
will be optimized in 0.6
129                 return self._impl_dict.setdefault(dialect,
dialect.type_descriptor(self))
130             except KeyError:
131                 return self._impl_dict.setdefault(dialect,
dialect.type_descriptor(self))
(Pdb) dialect
<sqlalchemy.databases.oracle.OracleDialect object at 0xa1ae54c>
(Pdb) n
--Call--
> /usr/local/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/types.py(477)get_dbapi_type()
-> def get_dbapi_type(self, dbapi):
(Pdb) l
472                         return value
473                 return process
474             else:
475                 return None
476
477  ->     def get_dbapi_type(self, dbapi):
478             return dbapi.STRING
479
480     class Text(String):
481         """A variably sized string type.
482
(Pdb) l 1
  1     # types.py
  2     # Copyright (C) 2005, 2006, 2007, 2008, 2009 Michael Bayer
mike...@zzzcomputing.com
  3     #
  4     # This module is part of SQLAlchemy and is released under
  5     # the MIT License: http://www.opensource.org/licenses/mit-license.php
  6
  7     """defines genericized SQL types, each represented by a
subclass of
  8     :class:`~sqlalchemy.types.AbstractType`.  Dialects define
further subclasses of these
  9     types.
 10
 11     For more information see the SQLAlchemy documentation on
types.




On Oct 1, 2:48 pm, "Michael Bayer" <mike...@zzzcomputing.com> wrote:
> volx wrote:
>
> > Here's my program, modified as you suggest. It also creates the table
> > so you can try it on any instance of Oracle. No joy on the result.
> > Seems like the set_inputsizes isn't called? How can I tell for
> > certain?
>
> > import sqlalchemy.types as sqltypes
> > from exceptions import NotImplementedError
>
> > class OracleChar(sqltypes.CHAR):
> >     """Patched OracleChar type to fix padding issue
> >    http://groups.google.com/group/sqlalchemy/browse_thread/thread/965287...
> >     """
> >     def get_col_spec(self):
> >         return "CHAR(%(length)s)" % {'length' : self.length}
>
> >     def get_dbapi_type(self, dbapi):
> >         raise NotImplementedError('gotcha')
> >         return dbapi.FIXED_CHAR
>
> is this using 0.5 or current trunk ?  There's some additional restrictions
> in trunk on setinputsizes due to some cx_oracle bugs I reported.  
> Unfortanately my macbook is in the shop so I won't be able to test this
> myself until possibly next week.   Basically the the "set_input_sizes()"
> in sqlalchemy/base/default.py should be called for all oracle executions
> and the datatype on the bind parameter generated by "mycol == <some
> value>" should be of your type, i.e. isinstance((mycol==5).right.type,
> OracleChar).
>
>
>
> > from sqlalchemy.databases import oracle
> > oracle.OracleChar = OracleChar
>
> > from sqlalchemy import Table, Column, Integer, MetaData
> > from sqlalchemy.databases.oracle import OracleChar
> > from sqlalchemy.sql import select, insert
> > from sqlalchemy import create_engine
>
> > metadata = MetaData()
>
> > price_sources = Table('victor_price_sources', metadata,
> >     Column('pricesource', Integer, primary_key=True),
> >     Column('desciption', OracleChar(100))
> > )
>
> > dburl = "oracle://user:pas...@servername:1521/dbname"
>
> > e = create_engine(dburl, echo=True)
> > metadata.bind = e
> > metadata.create_all()
> > con = e.connect()
>
> > ins = price_sources.insert().values(pricesource=1, desciption='EJV')
> > con.execute(ins)
>
> > s = select([price_sources], price_sources.c.desciption=='EJV')
> > all = con.execute(s).fetchall()
> > print all
>
> > s = select([price_sources])
> > all = con.execute(s).fetchall()
> > print all
>
> > And the results:
>
> > In [1]: import sandbox
> > 2009-10-01 13:24:25,015 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > SELECT USER FROM DUAL
> > 2009-10-01 13:24:25,018 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > {}
> > 2009-10-01 13:24:25,022 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > select table_name from all_tables where table_name=:name and
> > owner=:schema_name
> > 2009-10-01 13:24:25,022 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > {'name': 'VICTOR_PRICE_SOURCES', 'schema_name': 'CDOCOLLAT'}
> > 2009-10-01 13:24:25,027 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > CREATE TABLE victor_price_sources (
> >         pricesource INTEGER NOT NULL,
> >         desciption CHAR(100),
> >         PRIMARY KEY (pricesource)
> > )
>
> > 2009-10-01 13:24:25,027 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > {}
> > 2009-10-01 13:24:25,082 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > COMMIT
> > 2009-10-01 13:24:25,084 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > INSERT INTO victor_price_sources (pricesource, desciption) VALUES
> > (:pricesource, :desciption)
> > 2009-10-01 13:24:25,084 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > {'pricesource': 1, 'desciption': 'EJV'}
> > 2009-10-01 13:24:25,089 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > COMMIT
> > 2009-10-01 13:24:25,092 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > SELECT victor_price_sources.pricesource,
> > victor_price_sources.desciption
> > FROM victor_price_sources
> > WHERE victor_price_sources.desciption = :desciption_1
> > 2009-10-01 13:24:25,092 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > {'desciption_1': 'EJV'}
> > []
> > 2009-10-01 13:24:25,105 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > SELECT victor_price_sources.pricesource,
> > victor_price_sources.desciption
> > FROM victor_price_sources
> > 2009-10-01 13:24:25,105 INFO sqlalchemy.engine.base.Engine.0x...9ccc
> > {}
> > [(1,
> > 'EJV
> > ')]
>
> > On Oct 1, 10:10 am, "Michael Bayer" <mike...@zzzcomputing.com> wrote:
> >> volx wrote:
>
> >> > Micheal:
>
> >> > Thanks for your help thus far. Unfortunately I don't think the
> >> > get_dbapi_type method gets called. From reading your code I see how it
> >> > should be called from pre_exec -> setinputsizes -> get_dbapi_type but
> >> > empirical evidence shows otherwise. Here's my little harness:
>
> >> > import sqlalchemy.types as sqltypes
> >> > from exceptions import NotImplementedError
>
> >> > class OracleChar(sqltypes.CHAR):
> >> >     """Patched OracleChar type to fix padding issue
> >> >  
> >>  http://groups.google.com/group/sqlalchemy/browse_thread/thread/965287...
> >> >     """
> >> >     def get_col_spec(self):
> >> >         return "CHAR(%(length)s)" % {'length' : self.length}
>
> >> >     def get_dbapi_type(self, dbapi):
> >> >         raise NotImplementedError('gotcha')
> >> >         return dbapi.FIXED_CHAR
>
> >> > from sqlalchemy.databases import oracle
> >> > oracle.OracleChar = OracleChar
>
> >> > from sqlalchemy.ext.sqlsoup import SqlSoup
>
> >> > dburl = "oracle://....."
> >> > soup = SqlSoup(dburl)
> >> > all = soup.price_sources.filter_by(desciption='EJV').all()
> >> > print all  # shows empty list, we should not even get here due to
> >> > exception I raise
>
> >> > all = soup.price_sources.filter_by
> >> > (desciption='EJV
> >> > ').all()
> >> > print all  # shows record in list
>
> >> > Returns empty list.
>
> >> SqlSoup uses table reflection and in this case you'd have to ensure that
> >> the column in question is assigned the CHAR datatype, which its very
> >> likely that it's not.    I would start by using a hand-constructed Table
> >> object and testing the behavior against that using simple select()
> >> constructs.
>
> >> > On Sep 30, 3:44 pm, "Michael Bayer" <mike...@zzzcomputing.com> wrote:
> >> >> volx wrote:
>
> >> >> > cx_Oracle actually has thread on that a topic at
> >> >> >http://sourceforge.net/mailarchive/message.php?msg_id=47BED8B8.3983.0...
>
> >> >> > It boils down to having to specify a type for input parameter. Is
> >> that
> >> >> > something I could "plug-in" as a decorator or would that need to be
> >> >> > hacked on SqlAlchemy level?
>
> >> >> here is the thing.  We call setinputsizes() with oracle.  So perhaps
> >> >> OracleChar() needs to have dbapi.FIXED_CHAR established as its
> >> >> get_dbapi_type().   would you care to try monkeypatching this (in
> >> 0.5,
> >> >> the
> >> >> fix for 0.6 would be different) ?
>
> >> >> class OracleChar(sqltypes.CHAR):
> >> >>     def get_col_spec(self):
> >> >>         return "CHAR(%(length)s)" % {'length' : self.length}
>
> >> >>     def get_dbapi_type(self, dbapi):
> >> >>         return dbapi.FIXED_CHAR
>
> >> >> from sqlalchemy.databases import oracle
> >> >> oracle.OracleChar = OracleChar
>
> >> >> > Here's how:
>
> >> >> > In [70]: query = "select * from price_sources where description
> >> >> > = :someparam"
> >> >> > In [71]: cursor.setinputsizes(someparam=cx_Oracle.FIXED_CHAR)
> >> >> > Out[71]: {'someparam': <cx_Oracle.FIXED_CHAR with value None>}
> >> >> > In [72]: cursor.execute(query, dict(someparam='EJV')).fetchall()
> >> >> > Out[72]:
> >> >> > [(149,
>
> >> >> > 'EJV
> >> >> > ')]
>
> >> >> > Any help would be appreciated.
>
> >> >> > On Sep 30, 2:36 pm, volx <victor.o...@gmail.com> wrote:
> >> >> >> I have just now and it looks that this post probably belongs on
> >> >> >> cx_Oracle mailing list.
>
> >> >> >> In [47]: cursor.execute("select * from price_sources where
> >> desciption
> >> >> >> = :someparam", dict(someparam='EJV')).fetchall()
> >> >> >> Out[47]: []
> >> >> >> In [49]: cursor.execute("select * from price_sources where
> >> desciption
> >> >> >> = :someparam", dict
> >> >> >> (someparam='EJV
> >> >> >> ')).fetchall()
> >> >> >> Out[49]:
> >> >> >> [(149,
>
> >> >> >> 'EJV
> >> >> >> ')]
>
> >> >> >> On Sep 30, 2:18 pm, Michael Bayer <mike...@zzzcomputing.com>
> >> wrote:
>
> >> >> >> > On Sep 30, 2:07 pm, volx <victor.o...@gmail.com> wrote:
>
> >> >> >> > > Hello all:
>
> >> >> >> > > Consider table:
>
> >> >> >> > > CREATE TABLE PRICE_SOURCES (
> >> >> >> > >    ID decimal(22) PRIMARY KEY NOT NULL,
> >> >> >> > >    DESCRIPTION char(100) NOT NULL
> >> >> >> > > )
>
> >> >> >> > > and this screen dump from ipython session:
>
> >> >> >> > > In [28]: import cx_Oracle
> >> >> >> > > In [29]: from sqlalchemy.ext.sqlsoup import SqlSoup
> >> >> >> > > In [30]: con = cx_Oracle.connect('myuser/myp...@mydb')
> >> >> >> > > In [31]: cursor = con.cursor()
> >> >> >> > > In [32]: cursor.execute("select * from price_sources where
> >> >> >> description
> >> >> >> > > = 'EJV'").fetchall()
> >> >> >> > > Out[32]:
> >> >> >> > > [(149,
>
> >> >> >> > > 'EJV
> >> >> >> > > ')]
>
> >> >> >> > > Note that the result has padding in the column "description"
> >> as
> >> >> it
> >> >> >> is
> >> >> >> > > of type CHAR(100), with is fixed length.
>
> >> >> >> > > Now, let's do the same in SqlAlchemy.
>
> >> >> >> > > In [33]: soup = SqlSoup('oracle://myuser:myp...@mydb')
> >> >> >> > > In [34]: soup.price_sources.filter_by(description='EJV').all()
> >> >> >> > > Out[34]: []
>
> >> >> >> > > As you can see it returns zero rows. Only after I pad the
> >> >> parameter
> >> >> >> > > for where clause will I get my row back:
>
> >> >> >> > > In [35]: soup.price_sources.filter_by
> >> >> >> > > (desciption='EJV
> >> >> >> > > ').all()
> >> >> >> > > Out[35]: [MappedPrice_sources(pricesource=Decimal
> >> >> >> > > ('149'),desciption='EJV
> >> >> >> > > ')]
>
> >> >> >> > > The same behavior happens even if I use ORM and regardless
> >> >> whether
> >> >> >> the
> >> >> >> > > column metadata is defined with String, OracleString or CHAR.
>
> >> >> >> > > I can understand the query result being padded as it is
> >> >> consistent
> >> >> >> > > with
>
> ...
>
> read more »
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
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