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/965287c91b790b68
>     """
>     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 behavior everywhere but the where clasues must not. It is
>> a
>> >> big
>> >> >> > > problem if you try to use session.merge() because you have to
>> pad
>> >> >> > > contents of object fields otherwise the ORM will insert a
>> >> duplicate.
>>
>> >> >> > > Please help. I hope I am doing something wrong or missing
>> >> something.
>>
>> >> >> > that's a little strange.  have you tried:
>>
>> >> >> > In [28]: import cx_Oracle
>> >> >> > In [30]: con = cx_Oracle.connect('myuser/myp...@mydb')
>> >> >> > In [31]: cursor = con.cursor()
>> >> >> > In [32]: cursor.execute("select * from price_sources where
>> >> description
>> >> >> > = :someparam", dict(someparam='EJV')).fetchall()
>>
>> >> >> > ?
>>
>> >> >> > since the usage of bind parameters is how it actually runs.  If
>> >> same
>> >> >> > behavior there then it's a cx_oracle behavior.    you can verify
>> >> this
>> >> >> > by turning on SQL echoing.  As a workaround you can build
>> yourself
>> >> a
>> >> >> > TypeDecorator that elongates/truncates incoming strings though
>> that
>> >> >> > seems a little inconvenient.
> >
>


--~--~---------~--~----~------------~-------~--~----~
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