On Jan 28, 2014, at 8:30 PM, a_t_smith <amos.t.sm...@gmail.com> wrote:

> Following up on earlier comments I tried manually calling the db function and 
> passing the arrayvar built via cx_Oracle cursor and got "ORA-01484: arrays 
> can only be bound to PL/SQL statements".
> 
> Alternately, I found that manually wrapping the array values with the 
> database type name "works", i.e. rp = session.execute('select 
> some_db_func(int_array(1,2,3,4,5)) from dual') .
> 
> I could not find a way to convert the int_array(1,2,3,4,5) part of the 
> statement into a param though, so I'm not sure if/how to move forward with 
> this either. 
> 
> I tried breaking this into two parts but it doesn't seem to know how to get 
> the array out of resultproxy.
> 
> arrayResult = session.execute('select int_array(1,2,3,4,5) from dual')
> funcResult = session.execute(session.query().from_statement("select 
> some_db_func(:a) from dual").params(a=arrayResult))
> 
> Is there a way to render a udt like class into literal part of query rather 
> than binding it as a parameter?

there is, but it would kind of disqualify this as something we can add to 
SQLAlchemy directly b.c. it’s basically a security hazard (as unlikely as it is 
in this case).

essentially if the “literal_binds” flag is passed through to the compiler it 
will render bound parameters inline.   This flag can be set on a per-element 
basis using the recipe below:

from sqlalchemy.sql.expression import BindParameter
from sqlalchemy.ext.compiler import compiles


class LiteralBindParam(BindParameter):
    pass

@compiles(LiteralBindParam)
def literal_bind(element, compiler, **kw):
    kw['literal_binds'] = True
    return compiler.visit_bindparam(element, **kw)

from sqlalchemy.sql import select, column

stmt = select([column('x'), column('y')]).\
            where(column('x') == 5).\
            where(column('y') == LiteralBindParam(None, 7))

print stmt

will print:

SELECT x, y 
WHERE x = :x_1 AND y = 7


from there, if the type of the LiteralBindParameter implements 
“literal_processor()”, that controls how the literal value is rendered into the 
statement.


> 
> On Tuesday, January 28, 2014 3:26:25 PM UTC-8, Michael Bayer wrote:
> 
> no, this is the part i was suggesting needs to be improved.  for the moment, 
> the OracleExecutionContext is looking for parameters that need special 
> things.  you can also intercept the parameters being sent to cx_oracle using 
> a before_cursor_execute event, which might be a way to interact with the 
> cursor directly without modifying the cx_oracle dialect directly.
> 
> that is 
> 
> from sqlalchemy import event
> 
> @event.listens_for(Engine, “before_cursor_execute”)
> def look_for_array_params(conn, cursor, statement, parameters, context, 
> executemany):
>    if context and context.compiled:
>        for key in parameters:
>           bindparam = context.compiled.binds[key]
>           if isinstance(bindparam.type_, OracleArrayType):
>               parameters[key] = 
> cursor.call_special_oracle_api(parameters[key])
> 
> this is sort of deep stuff so you’d need to familiarize a bit with the 
> execution flow (assuming the above doesn’t work as written).
> 
> 
> 
> 
> -- 
> 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 sqlalchemy+unsubscr...@googlegroups.com.
> To post to this group, send email to sqlalchemy@googlegroups.com.
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/groups/opt_out.

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to