*NO*: you gave me...
SELECT SEARCH DEPTH FIRST...
There is a SELECT where it shouldn't have been.

It should have been *suffixed* to prior statement... NOT *prefixed*...

The search/set does a tree walk and adds a numeric id to the columns called
DISP_SEQ
You can traverse the hierarchy depth or breadth first and so the sequential
number allocation will

I see you have some new regular expression code for me to get my head
around.
Is that removing the SELECT prior to SEARCH?
After the DISP_SEQ, SELECT should be re-added...
Is the code doing that too?

and I gave you:
>
>           SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQ
>          SELECT
>              j1.jobmst_id,
>              j1.jobmst_name,
>              j1.jobmst_prntid,
>              j1.jobmst_type,
>              j1.lvl
>             FROM j1 ORDER BY DISP_SEQ
>

@compiles(Select, "oracle")
> def _add_search_hints(element, compiler, **kw):
>     text = compiler.visit_select(element, **kw)
>     for prefix, _ in element._prefixes:
>         prefix = prefix.text
>         text = re.sub(r'SELECT %s' % prefix, "%s SELECT" % prefix, text)
>     return text


On Thu, Apr 26, 2018 at 10:53 PM, Mike Bayer <mike...@zzzcomputing.com>
wrote:

> Here's that, also the literal() has to be against the regular value 1
> and not the string else it casts as string:
>
> from sqlalchemy import *
> from sqlalchemy.ext.declarative import declarative_base
> from sqlalchemy.orm import Session, aliased
> from sqlalchemy.ext.compiler import compiles
> from sqlalchemy.sql.expression import Select
> import re
>
>
> @compiles(Select, "oracle")
> def _add_search_hints(element, compiler, **kw):
>     text = compiler.visit_select(element, **kw)
>     for prefix, _ in element._prefixes:
>         prefix = prefix.text
>         text = re.sub(r'SELECT %s' % prefix, "%s SELECT" % prefix, text)
>     return text
>
> Base = declarative_base()
>
>
> class JobMst(Base):
>     __tablename__ = 'jobmst'
>
>     jobmst_id = Column(Integer, primary_key=True)
>     jobmst_name = Column(String(50))
>     jobmst_prntid = Column(Integer)
>     jobmst_type = Column(String(10))
>
> e = create_engine("oracle://scott:tiger@oracle1120", echo=True)
> Base.metadata.create_all(e)
>
> s = Session(e)
>
> j2 = aliased(JobMst, name="j2")
>
> j1 = s.query(
>     JobMst.jobmst_id, JobMst.jobmst_name, JobMst.jobmst_prntid,
>     JobMst.jobmst_type, literal(1).label("lvl")
> ).filter(JobMst.jobmst_prntid == None).cte(recursive=True, name="j1")
> j1 = j1.union_all(
>     s.query(
>         j2.jobmst_id, j2.jobmst_name,
>         j2.jobmst_prntid, j2.jobmst_type, j1.c.lvl + literal(1)).join(
>         j1, j2.jobmst_prntid == j1.c.jobmst_id
>     ).filter(j2.jobmst_prntid != None)
> )
>
> stmt = s.query(j1).prefix_with(
>     "SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQ"
> ).order_by(text("DISP_SEQ"))
>
> stmt.all()
>
>
> please modify the database URL and optionally the column names if they
> are wrong and run this as is.
>
>
>
> On Thu, Apr 26, 2018 at 5:42 PM, Mike Bayer <mike...@zzzcomputing.com>
> wrote:
> > the issue is that your original query ends with:
> >
> >         SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQ
> >             SELECT *
> >             FROM J1 ORDER BY DISP_SEQ
> >
> > and I gave you:
> >
> >           SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQ
> >          SELECT
> >              j1.jobmst_id,
> >              j1.jobmst_name,
> >              j1.jobmst_prntid,
> >              j1.jobmst_type,
> >              j1.lvl
> >             FROM j1 ORDER BY DISP_SEQ
> >
> > I apologize for this mistake.
> >
> > Basically it's not appropriate to use select.with_prefix() in this
> > particular case as it applies prefixes subsequent to the SELECT
> > keyword.  The SQLAlchemy Oracle dialect does not currently have
> > support for special strings added in front of the SELECT keyword.    I
> > can provide you with a recipe that allows for this to be possible,
> > however, 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.
> >
> > If you want to continue using the expression language I can show you a
> > recipe to add those special keywords to the left side of the SELECT
> > keyword.
> >
> >
> >
> >
> >
> >
> >
> > On Thu, Apr 26, 2018 at 5:33 PM, Mike Bayer <mike...@zzzcomputing.com>
> wrote:
> >> OK, your original SQL works, will find the difference
> >>
> >> On Thu, Apr 26, 2018 at 5:32 PM, Mike Bayer <mike...@zzzcomputing.com>
> wrote:
> >>> Jeremy -
> >>>
> >>> This whole thread is based on an exact SQL that you have asked for,
> >>> and that was the query I gave you.   Going back to the script I
> >>> posted, the SQL output when I run it via query.all() vs. just
> >>> query.statement.compile() is identical except for the label names
> >>> applied to the final column names, which is not the cause of this
> >>> error.
> >>>
> >>> please give me **the exact SQL statement that you know runs
> >>> correctly** and I will show you how to render it.
> >>>
> >>>
> >>> On Thu, Apr 26, 2018 at 5:30 PM, Jeremy Flowers
> >>> <jeremy.g.flow...@gmail.com> wrote:
> >>>> Does this need to be submitted as an error on Git somewhere?
> >>>>
> >>>> On Thu, Apr 26, 2018 at 10:29 PM, Jeremy Flowers
> >>>> <jeremy.g.flow...@gmail.com> wrote:
> >>>>>
> >>>>> I can confirm. I copied and pasted Mike's Python verbatim, and got
> exactly
> >>>>> same issues with generated SQL
> >>>>>
> >>>>> On Thu, Apr 26, 2018 at 10:21 PM, Jeremy Flowers
> >>>>> <jeremy.g.flow...@gmail.com> wrote:
> >>>>>>
> >>>>>> I hacked the parameterised query:
> >>>>>> This works..
> >>>>>> WITH j1(jobmst_id, jobmst_name, jobmst_prntid, jobmst_type, lvl) AS
> (
> >>>>>>    (SELECT jobmst.jobmst_id AS jobmst_id, jobmst.jobmst_name AS
> >>>>>> jobmst_name, jobmst.jobmst_prntid AS jobmst_prntid,
> jobmst.jobmst_type AS
> >>>>>> jobmst_type, 1 AS lvl
> >>>>>>     FROM jobmst
> >>>>>>     WHERE jobmst.jobmst_prntid IS NULL
> >>>>>> )
> >>>>>> UNION ALL
> >>>>>> SELECT j2.jobmst_id AS j2_jobmst_id, j2.jobmst_name AS
> j2_jobmst_name,
> >>>>>> j2.jobmst_prntid AS j2_jobmst_prntid, j2.jobmst_type AS
> j2_jobmst_type,
> >>>>>> j1.lvl + 1 As lvl
> >>>>>> FROM jobmst j2
> >>>>>> 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 j1.jobmst_id, j1.jobmst_name, j1.jobmst_prntid,
> j1.jobmst_type,
> >>>>>> j1.lvl
> >>>>>> FROM j1 ORDER BY DISP_SEQ
> >>>>>>
> >>>>>> So, the AS names are ok it seems... But, the SELECT should come
> after
> >>>>>> DISP_SEQ too
> >>>>>>
> >>>>>> On Thu, Apr 26, 2018 at 10:17 PM, Jeremy Flowers
> >>>>>> <jeremy.g.flow...@gmail.com> wrote:
> >>>>>>>
> >>>>>>> Mike I know what the problem is.
> >>>>>>> The SQL emitted by SQLAlchemy is wrong!
> >>>>>>> This is why I get: ORA-00923: FROM keyword not found where
> expected. You
> >>>>>>> only get error code when you try to execute the code - with
> first(), all(),
> >>>>>>> slice()
> >>>>>>> Look for the <----- in the generated code.... (x4)
> >>>>>>>
> >>>>>>> ====
> >>>>>>> This is my Original SQL:
> >>>>>>>
> >>>>>>> WITH J1(JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, LVL)
> AS  (
> >>>>>>>   SELECT * FROM (
> >>>>>>>     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
> >>>>>>> ===
> >>>>>>>
> >>>>>>> This is the code output by printing the Oracle dialect:
> >>>>>>>
> >>>>>>> WITH j1(jobmst_id, jobmst_name, jobmst_prntid, jobmst_type, lvl)
> AS .
> >>>>>>> <----- Look no opening parenthesis
> >>>>>>>    (SELECT jobmst.jobmst_id AS jobmst_id, jobmst.jobmst_name AS
> >>>>>>> jobmst_name, jobmst.jobmst_prntid AS jobmst_prntid,
> jobmst.jobmst_type AS
> >>>>>>> jobmst_type, :param_1 AS lvl
> >>>>>>>     FROM jobmst
> >>>>>>>     WHERE jobmst.jobmst_prntid IS NULL
> >>>>>>>
> >>>>>>> <!----- LOOK no closing parenthesis
> >>>>>>> UNION ALL
> >>>>>>> SELECT j2.jobmst_id AS j2_jobmst_id, j2.jobmst_name AS
> j2_jobmst_name,
> >>>>>>> j2.jobmst_prntid AS j2_jobmst_prntid, j2.jobmst_type AS
> j2_jobmst_type,
> >>>>>>> j1.lvl + :lvl_1 AS anon_1 .   <!----- the AS names should match
> what's
> >>>>>>> inside WITH()
> >>>>>>> FROM jobmst j2
> >>>>>>> JOIN j1 ON j2.jobmst_prntid = j1.jobmst_id
> >>>>>>> WHERE j2.jobmst_prntid IS NOT NULL
> >>>>>>> )
> >>>>>>> SELECT SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQ j1.jobmst_id,
> >>>>>>> j1.jobmst_name, j1.jobmst_prntid, j1.jobmst_type, j1.lvl .  <-----
> There
> >>>>>>> should be no SELECT before SEARCH (my why prefix - should be
> suffix)
> >>>>>>> FROM j1 ORDER BY DISP_SEQ
> >>>>>>>
> >>>>>>> ===
> >>>>>>>
> >>>>>>>
> >>>>>>
> >>>>>
> >>>>
> >>>> --
> >>>> 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.

Reply via email to