you don't really need the columns(...) part if you are sending the text() object to connection.execute(). That's mostly a thing to help when using the ORM which I don't think you want to be using here.
Also set echo='debug' on create_engine which will log all the rows coming back. On Fri, Apr 27, 2018 at 12:12 PM, Jeremy Flowers <jeremy.g.flow...@gmail.com> wrote: > Hah.. Seems Oracle ROWNUM starts from 1, not 0.. > When you select between 3 and 4 - nothing returns. There's an Oracle > quirk... > > On Fri, Apr 27, 2018 at 5:03 PM, Jeremy Flowers <jeremy.g.flow...@gmail.com> > wrote: >> >> Have tried dropping session.execute and using connection.execute - where >> the method of parameter binding seems to work... >> >> == >> >> #!/usr/bin/env python >> import sqlalchemy >> from sqlalchemy.types import Integer >> from sqlalchemy.sql.expression import bindparam >> from sqlalchemy import text, create_engine, column >> stmt = text('WITH J1(JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, >> LVL) AS (' + >> 'SELECT JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, 1 >> ' + >> 'FROM TIDAL.JOBMST ' + >> 'WHERE JOBMST_PRNTID IS NULL ' + >> 'UNION ALL ' + >> 'SELECT J2.JOBMST_ID, J2.JOBMST_NAME, J2.JOBMST_PRNTID, >> J2.JOBMST_TYPE, ' + >> 'J1.LVL + 1 ' + >> 'FROM TIDAL.JOBMST J2 ' + >> 'INNER JOIN J1 ON J2.JOBMST_PRNTID = J1.JOBMST_ID ' >> 'WHERE J2.JOBMST_PRNTID IS NOT NULL ' + >> ') SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQ ' + >> 'SELECT * ' + >> 'FROM J1 '+ >> 'WHERE ROWNUM BETWEEN :s AND :f ' + >> 'ORDER BY DISP_SEQ ') >> stmt.columns(column('JOBMST_ID'), column('JOBMST_NAME'), >> column('JOBMST_PRNT_ID'), column('LVL'),column('DISP_SEQ')) >> stmt.bindparams(bindparam('s', type_=Integer), bindparam('f', >> type_=Integer)) >> engine = create_engine('oracle://TIDAL:Password123@WINTIDAL:1521/ORCL', >> echo=True) >> connection = engine.connect() >> offset = 0 >> limit = 2 >> more_results = True >> while more_results: >> start = offset >> finish = offset + limit - 1 >> print('Start: {0}, Finish {1}'.format(start,finish)) >> partial_results = connection.execute(stmt, s = start, f = >> finish).fetchall() >> offset += limit >> if partial_results == [] or offset == 4: >> more_results = False >> for row in partial_results: >> print(row.items()) >> connection.close() >> >> === >> >> C:\opt\tidalconversion>jobwalktext.py >> 2018-04-27 16:44:58,037 INFO sqlalchemy.engine.base.Engine SELECT USER >> FROM DUAL >> 2018-04-27 16:44:58,037 INFO sqlalchemy.engine.base.Engine {} >> 2018-04-27 16:44:58,040 INFO sqlalchemy.engine.base.Engine SELECT >> CAST('test plain returns' AS VARCHAR(60 CHAR)) AS anon_1 FROM DUAL >> 2018-04-27 16:44:58,040 INFO sqlalchemy.engine.base.Engine {} >> 2018-04-27 16:44:58,041 INFO sqlalchemy.engine.base.Engine SELECT >> CAST('test unicode returns' AS NVARCHAR2(60)) AS anon_1 FROM DUAL >> >> C:\opt\tidalconversion>jobwalktext.py >> 2018-04-27 16:58:13,199 INFO sqlalchemy.engine.base.Engine SELECT USER >> FROM DUAL >> 2018-04-27 16:58:13,199 INFO sqlalchemy.engine.base.Engine {} >> 2018-04-27 16:58:13,202 INFO sqlalchemy.engine.base.Engine SELECT >> CAST('test plain returns' AS VARCHAR(60 CHAR)) AS anon_1 FROM DUAL2018-04-27 >> 16:58:13,202 INFO sqlalchemy.engine.base.Engine {}2018-04-27 16:58:13,203 >> INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS >> NVARCHAR2(60)) AS anon_1 FROM DUAL2018-04-27 16:58:13,203 INFO >> sqlalchemy.engine.base.Engine {}2018-04-27 16:58:13,204 INFO >> sqlalchemy.engine.base.Engine select value from nls_session_parameters where >> parameter = 'NLS_NUMERIC_CHARACTERS' >> 2018-04-27 16:58:13,204 INFO sqlalchemy.engine.base.Engine {} >> Start: 0, Finish 1 >> 2018-04-27 16:58:13,206 INFO sqlalchemy.engine.base.Engine WITH >> J1(JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, LVL) AS (SELECT >> JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, 1 FROM TIDAL.JOBMST >> WHERE JOBMST_PRNTID IS NULL UNION ALL SELECT J2.JOBMST_ID, J2.JOBMST_NAME, >> J2.JOBMST_PRNTID, J2.JOBMST_TYPE, J1.LVL + 1 FROM TIDAL.JOBMST J2 INNER JOIN >> J1 ON J2.JOBMST_PRNTID = J1.JOBMST_ID WHERE J2.JOBMST_PRNTID IS NOT NULL ) >> SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQ SELECT * FROM J1 WHERE ROWNUM >> BETWEEN :s AND :f ORDER BY DISP_SEQ2018-04-27 16:58:13,207 INFO >> sqlalchemy.engine.base.Engine {'s': 0, 'f': 1}[('jobmst_id', 57020), >> ('jobmst_name', '6G_ZAFIN_PROD'), ('jobmst_prntid', None), ('jobmst_type', >> 1), ('lvl', 1), ('disp_seq', 1)] >> Start: 2, Finish 3 >> 2018-04-27 16:58:13,510 INFO sqlalchemy.engine.base.Engine WITH >> J1(JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, LVL) AS (SELECT >> JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, 1 FROM TIDAL.JOBMST >> WHERE JOBMST_PRNTID IS NULL UNION ALL SELECT J2.JOBMST_ID, J2.JOBMST_NAME, >> J2.JOBMST_PRNTID, J2.JOBMST_TYPE, J1.LVL + 1 FROM TIDAL.JOBMST J2 INNER JOIN >> J1 ON J2.JOBMST_PRNTID = J1.JOBMST_ID WHERE J2.JOBMST_PRNTID IS NOT NULL ) >> SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQ SELECT * FROM J1 WHERE ROWNUM >> BETWEEN :s AND :f ORDER BY DISP_SEQ >> 2018-04-27 16:58:13,511 INFO sqlalchemy.engine.base.Engine {'s': 2, 'f': >> 3} >> >> C:\opt\tidalconversion> >> >> === >> >> For some bizarre reasone, the tuple for the row only prints first record.. >> I can see the record selection works correctly.. had to move where above >> order by since before.. >> It seems the parameter binding works fine. Don't thing I necessarly needed >> have stmt.bindparams - seemed to work equally well without that. >> Anyone see anything obvious? >> == >> Here's same output with , echo=False >> == >> C:\opt\tidalconversion>jobwalktext.py >> Start: 0, Finish 1 >> [('jobmst_id', 57020), ('jobmst_name', '6G_ZAFIN_PROD'), ('jobmst_prntid', >> None), ('jobmst_type', 1), ('lvl', 1), ('disp_seq', 1)] >> Start: 2, Finish 3 >> >> C:\opt\tidalconversion> >> >> On Fri, Apr 27, 2018 at 4:12 PM, Jeremy Flowers >> <jeremy.g.flow...@gmail.com> wrote: >>> >>> I'm thinking along these lines. But can't get it to work. >>> #!/usr/bin/env python >>> import sqlalchemy >>> from sqlalchemy import text, create_engine, column >>> from sqlalchemy.orm import Session, sessionmaker >>> stmt = text('''WITH J1(JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, >>> JOBMST_TYPE, LVL) AS ( >>> SELECT JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, >>> JOBMST_TYPE, 1 >>> FROM TIDAL.JOBMST >>> WHERE JOBMST_PRNTID IS NULL >>> UNION ALL >>> SELECT J2.JOBMST_ID, J2.JOBMST_NAME, J2.JOBMST_PRNTID, >>> J2.JOBMST_TYPE, >>> J1.LVL + 1 >>> FROM TIDAL.JOBMST J2 >>> INNER JOIN J1 ON J2.JOBMST_PRNTID = J1.JOBMST_ID >>> WHERE J2.JOBMST_PRNTID IS NOT NULL >>> ) SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQ >>> SELECT * >>> FROM J1 >>> ORDER BY DISP_SEQ >>> WHERE ROWNUM BETWEEN :s AND :f >>> ''') >>> stmt.columns(column('JOBMST_ID'), column('JOBMST_NAME'), >>> column('JOBMST_PRNT_ID'), column('LVL'),column('DISP_SEQ')) >>> engine = create_engine('oracle://TIDAL:Password123@WINTIDAL:1521/ORCL', >>> echo=False) >>> Session = sessionmaker(bind=engine) >>> ses = Session() >>> more_results = True >>> offset = 0 >>> limit = 2 >>> while more_results: >>> start = offset >>> finish = offset + limit - 1 >>> partial_results = ses.execute(stmt, s = start, f = finish) >>> offset += limit >>> if partial_results == [] or offset == 4: >>> more_results = False >>> for row in partial_results: >>> print(row.items()) >>> >>> Getting >>> TypeError: get_bind() got an unexpected keyword argument 's' >>> >>> Got idea from here... >>> https://security.openstack.org/guidelines/dg_parameterize-database-queries.html >>> - it's obviously wrong! >>> >>> On Fri, Apr 27, 2018 at 3:49 PM, Jeremy Flowers >>> <jeremy.g.flow...@gmail.com> wrote: >>>> >>>> Right so some sort of statement bind.. >>>> Just found this didn't work: >>>> >>>> #!/usr/bin/env python >>>> import sqlalchemy >>>> from sqlalchemy import text, create_engine, column >>>> from sqlalchemy.orm import Session, sessionmaker >>>> stmt = text('''WITH J1(JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, >>>> JOBMST_TYPE, LVL) AS ( >>>> SELECT JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, >>>> JOBMST_TYPE, 1 >>>> FROM TIDAL.JOBMST >>>> WHERE JOBMST_PRNTID IS NULL >>>> UNION ALL >>>> SELECT J2.JOBMST_ID, J2.JOBMST_NAME, J2.JOBMST_PRNTID, >>>> J2.JOBMST_TYPE, >>>> J1.LVL + 1 >>>> FROM TIDAL.JOBMST J2 >>>> INNER JOIN J1 ON J2.JOBMST_PRNTID = J1.JOBMST_ID >>>> WHERE J2.JOBMST_PRNTID IS NOT NULL >>>> ) SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQ >>>> SELECT * >>>> FROM J1 >>>> ORDER BY DISP_SEQ''') >>>> stmt.columns(column('JOBMST_ID'), column('JOBMST_NAME'), >>>> column('JOBMST_PRNT_ID'), column('LVL'),column('DISP_SEQ')) >>>> engine = create_engine('oracle://TIDAL:Password123@WINTIDAL:1521/ORCL', >>>> echo=False) >>>> Session = sessionmaker(bind=engine) >>>> ses = Session() >>>> more_results = True >>>> offset = 0 >>>> limit = 2 >>>> while more_results: >>>> partial_results = ses.execute(stmt).offset(offset).limit(limit) >>>> offset += limit >>>> if partial_results == [] or offset == 4: >>>> more_results = False >>>> for row in partial_results: >>>> print(row.items()) >>>> >>>> On Fri, Apr 27, 2018 at 3:19 PM, Simon King <si...@simonking.org.uk> >>>> wrote: >>>>> >>>>> No, you'll need to convert that to the equivalent SQL. >>>>> >>>>> On Fri, Apr 27, 2018 at 3:14 PM, Jeremy Flowers >>>>> <jeremy.g.flow...@gmail.com> wrote: >>>>> > But can you still do things like slice(0,5)? Struggling to get that >>>>> > to work >>>>> > atm... >>>>> > >>>>> > On Fri, Apr 27, 2018 at 2:48 PM, Simon King <si...@simonking.org.uk> >>>>> > wrote: >>>>> >> >>>>> >> On Fri, Apr 27, 2018 at 12:57 PM, Jeremy Flowers >>>>> >> <jeremy.g.flow...@gmail.com> wrote: >>>>> >> > Right... >>>>> >> > Been trawling back thru this chain of exchanges.. >>>>> >> > Looking for this: >>>>> >> >> >>>>> >> >> At this point I would echo Mike's question: why can't you just >>>>> >> >> use >>>>> >> >> "text()"? >>>>> >> > >>>>> >> > Just spotted another comment from Mike, that I've just fixed >>>>> >> > too... >>>>> >> >> >>>>> >> >> the literal() has to be against the regular value 1 and not the >>>>> >> >> string... >>>>> >> > >>>>> >> > >>>>> >> >> as a practical matter, this query is Oracle-specific in any >>>>> >> >> case, is there a reason you can't just use text() ? The reason >>>>> >> >> text() exists is for when one has the exact SQL they want already >>>>> >> >> and >>>>> >> >> there is no need to work it into the expression language. >>>>> >> > >>>>> >> > >>>>> >> > Can I just put that into some sort of session execute? >>>>> >> > If there's a relevant example someone can point me to, it would >>>>> >> > help. >>>>> >> > I'll >>>>> >> > have a dig around. >>>>> >> > >>>>> >> >>>>> >> There are a few examples of using text() with the ORM here: >>>>> >> >>>>> >> >>>>> >> >>>>> >> http://docs.sqlalchemy.org/en/latest/orm/tutorial.html#using-textual-sql >>>>> >> >>>>> >> session.execute() behaves more like the Core-level >>>>> >> connection.execute(), which is described here: >>>>> >> >>>>> >> >>>>> >> >>>>> >> http://docs.sqlalchemy.org/en/latest/core/tutorial.html#sqlexpression-text >>>>> >> >>>>> >> Simon >>>>> >> >>>>> >> -- >>>>> >> 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 a topic in >>>>> >> the >>>>> >> Google Groups "sqlalchemy" group. >>>>> >> To unsubscribe from this topic, visit >>>>> >> >>>>> >> https://groups.google.com/d/topic/sqlalchemy/aWJT1VdY3LU/unsubscribe. >>>>> >> To unsubscribe from this group and all its topics, send an email to >>>>> >> sqlalchemy+unsubscr...@googlegroups.com. >>>>> >> To post to this group, send email to sqlalchemy@googlegroups.com. >>>>> >> 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 sqlalchemy+unsubscr...@googlegroups.com. >>>>> > To post to this group, send email to sqlalchemy@googlegroups.com. >>>>> > 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 a topic in the >>>>> Google Groups "sqlalchemy" group. >>>>> To unsubscribe from this topic, visit >>>>> https://groups.google.com/d/topic/sqlalchemy/aWJT1VdY3LU/unsubscribe. >>>>> To unsubscribe from this group and all its topics, send an email to >>>>> sqlalchemy+unsubscr...@googlegroups.com. >>>>> To post to this group, send email to sqlalchemy@googlegroups.com. >>>>> 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 sqlalchemy+unsubscr...@googlegroups.com. > To post to this group, send email to sqlalchemy@googlegroups.com. > 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 sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.