Re: [sqlalchemy] Issue on inserts statements for pg explain recipe

2018-10-04 Thread Mike Bayer
On Thu, Oct 4, 2018 at 5:10 AM  wrote:
>
> That's great ! Thanks a lot !
>
> Btw it seems that the
>
> self.inline = getattr(stmt, 'inline', None)
>
> is no longer necessary, I tryed my insert exemple with it commented and it 
> still runned fine.

well there's also an "inline" argument for Insert() so maybe it was
trying to preserve that, I don't remember.

>
>
> Le jeudi 4 octobre 2018 05:23:02 UTC+2, Mike Bayer a écrit :
>>
>> The insert is by itself not a RETURNING and doesn't return any rows.
>> The actual exception raised is:
>>
>> sqlalchemy.exc.ResourceClosedError: This result object does not return
>> rows. It has been closed automatically.
>>
>> and you'll get this just if you run the insert by itself:
>>
>> returning_query = Foo.__table__.insert()
>> print(sess.execute(returning_query, {'id': 1}).fetchall())
>>
>> Python 3 is just also showing you the exception we catch internally
>> which is the "'NoneType' object has no attribute 'fetchall'"  one, but
>> that is normal, we are catching that to detect that this result
>> doesn't return any rows.
>>
>> the cursor is getting closed because for any DML that doesn't return
>> rows, it closes the cursor because there's no other point at which it
>> could naturally be closed automatically from the point of view of the
>> resultproxy.
>>
>> If you tell the insert statement to return rows, the cursor doesnt get
>> closed and the explain gets the rows back:
>>
>> returning_query = Foo.__table__.insert().returning(Foo.id)
>>
>> print(sess.execute(explain(returning_query), {"id": 1}).fetchall())
>>
>> EXPLAIN INSERT INTO foo (id) VALUES (%(id)s) RETURNING foo.id
>> 2018-10-03 23:15:38,272 INFO sqlalchemy.engine.base.Engine {'id': 1}
>> [('Insert on foo  (cost=0.00..0.01 rows=1 width=4)',), ('  ->  Result
>> (cost=0.00..0.01 rows=1 width=4)',)]
>>
>> to get the insert() to return the rows without returning being
>> present, we have to flip off the flags that are telling the execution
>> context that this is an INSERT, or more generally crud, that are
>> making it autoclose the cursor:
>>
>> @compiles(explain, 'postgresql')
>> def pg_explain(element, compiler, **kw):
>> text = "EXPLAIN "
>> if element.analyze:
>> text += "ANALYZE "
>> text += compiler.process(element.statement, **kw)
>> compiler.isinsert = compiler.isupdate = compiler.isdelete = False
>> return text
>>
>> that seems to fix the codepath that is looking for _returning also, so
>> I'll add that.
>>
>>
>>
>> On Wed, Oct 3, 2018 at 5:04 AM  wrote:
>> >
>> > Hello,
>> >
>> > I use the recipe for explain as described 
>> > (https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/Explain), which 
>> > does the job completely for select statements (I have no idea how it works 
>> > however :p) in version 1.2.11
>> > The recipe at the moment is
>> >
>> > from sqlalchemy import *
>> > from sqlalchemy.ext.compiler import compiles
>> > from sqlalchemy.sql.expression import Executable, ClauseElement, 
>> > _literal_as_text
>> >
>> >
>> > class explain(Executable, ClauseElement):
>> > def __init__(self, stmt, analyze=False):
>> > self.statement = _literal_as_text(stmt)
>> > self.analyze = analyze
>> > # helps with INSERT statements
>> > self.inline = getattr(stmt, 'inline', None)
>> >
>> >
>> > @compiles(explain, 'postgresql')
>> > def pg_explain(element, compiler, **kw):
>> > text = "EXPLAIN "
>> > if element.analyze:
>> > text += "ANALYZE "
>> > text += compiler.process(element.statement, **kw)
>> > return text
>> >
>> >
>> > The recipe is not up to date, as it doesn't work on inserts, however by 
>> > replacing
>> >
>> > self.inline = getattr(stmt, 'inline', None)
>> > by
>> > self._returning = getattr(stmt, '_returning', None)
>> > self.table = getattr(stmt, 'table', None)
>> >
>> > It works on inserts with returning, however it crashes when I try to 
>> > fetchall() on explain of simple inserts with a "AttributeError: 'NoneType' 
>> > object has no attribute 'fetchall'"
>> > Below a code which have an error
>> >
>> >
>> >
>> > from sqlalchemy import *
>> > from sqlalchemy.ext.compiler import compiles
>> > from sqlalchemy.ext.declarative import declarative_base
>> > from sqlalchemy.orm import sessionmaker, aliased
>> >
>> >
>> >
>> >
>> > class explain(Executable, ClauseElement):
>> > def __init__(self, stmt, analyze=False):
>> > self.statement = _literal_as_text(stmt)
>> > self.analyze = analyze
>> > # helps with INSERT statements
>> > self._returning = getattr(stmt, '_returning', None)
>> >
>> >
>> > self.table = getattr(stmt, 'table', None)
>> >
>> >
>> >
>> >
>> > @compiles(explain, 'postgresql')
>> > def pg_explain(element, compiler, **kw):
>> > text = "EXPLAIN "
>> > if element.analyze:
>> > text += "ANALYZE "
>> > text += compiler.process(element.statement, **kw)
>> > return text
>> >
>> >
>> >
>> >
>> > Base = 

Re: [sqlalchemy] Issue on inserts statements for pg explain recipe

2018-10-04 Thread nicolas . rolin
That's great ! Thanks a lot !

Btw it seems that the

self.inline = getattr(stmt, 'inline', None)

is no longer necessary, I tryed my insert exemple with it commented and it 
still runned fine.


Le jeudi 4 octobre 2018 05:23:02 UTC+2, Mike Bayer a écrit :
>
> The insert is by itself not a RETURNING and doesn't return any rows. 
> The actual exception raised is: 
>
> sqlalchemy.exc.ResourceClosedError: This result object does not return 
> rows. It has been closed automatically. 
>
> and you'll get this just if you run the insert by itself: 
>
> returning_query = Foo.__table__.insert() 
> print(sess.execute(returning_query, {'id': 1}).fetchall()) 
>
> Python 3 is just also showing you the exception we catch internally 
> which is the "'NoneType' object has no attribute 'fetchall'"  one, but 
> that is normal, we are catching that to detect that this result 
> doesn't return any rows. 
>
> the cursor is getting closed because for any DML that doesn't return 
> rows, it closes the cursor because there's no other point at which it 
> could naturally be closed automatically from the point of view of the 
> resultproxy. 
>
> If you tell the insert statement to return rows, the cursor doesnt get 
> closed and the explain gets the rows back: 
>
> returning_query = Foo.__table__.insert().returning(Foo.id) 
>
> print(sess.execute(explain(returning_query), {"id": 1}).fetchall()) 
>
> EXPLAIN INSERT INTO foo (id) VALUES (%(id)s) RETURNING foo.id 
> 2018-10-03 23:15:38,272 INFO sqlalchemy.engine.base.Engine {'id': 1} 
> [('Insert on foo  (cost=0.00..0.01 rows=1 width=4)',), ('  ->  Result 
> (cost=0.00..0.01 rows=1 width=4)',)] 
>
> to get the insert() to return the rows without returning being 
> present, we have to flip off the flags that are telling the execution 
> context that this is an INSERT, or more generally crud, that are 
> making it autoclose the cursor: 
>
> @compiles(explain, 'postgresql') 
> def pg_explain(element, compiler, **kw): 
> text = "EXPLAIN " 
> if element.analyze: 
> text += "ANALYZE " 
> text += compiler.process(element.statement, **kw) 
> compiler.isinsert = compiler.isupdate = compiler.isdelete = False 
> return text 
>
> that seems to fix the codepath that is looking for _returning also, so 
> I'll add that. 
>
>
>
> On Wed, Oct 3, 2018 at 5:04 AM > wrote: 
> > 
> > Hello, 
> > 
> > I use the recipe for explain as described (
> https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/Explain), which 
> does the job completely for select statements (I have no idea how it works 
> however :p) in version 1.2.11 
> > The recipe at the moment is 
> > 
> > from sqlalchemy import * 
> > from sqlalchemy.ext.compiler import compiles 
> > from sqlalchemy.sql.expression import Executable, ClauseElement, 
> _literal_as_text 
> > 
> > 
> > class explain(Executable, ClauseElement): 
> > def __init__(self, stmt, analyze=False): 
> > self.statement = _literal_as_text(stmt) 
> > self.analyze = analyze 
> > # helps with INSERT statements 
> > self.inline = getattr(stmt, 'inline', None) 
> > 
> > 
> > @compiles(explain, 'postgresql') 
> > def pg_explain(element, compiler, **kw): 
> > text = "EXPLAIN " 
> > if element.analyze: 
> > text += "ANALYZE " 
> > text += compiler.process(element.statement, **kw) 
> > return text 
> > 
> > 
> > The recipe is not up to date, as it doesn't work on inserts, however by 
> replacing 
> > 
> > self.inline = getattr(stmt, 'inline', None) 
> > by 
> > self._returning = getattr(stmt, '_returning', None) 
> > self.table = getattr(stmt, 'table', None) 
> > 
> > It works on inserts with returning, however it crashes when I try to 
> fetchall() on explain of simple inserts with a "AttributeError: 'NoneType' 
> object has no attribute 'fetchall'" 
> > Below a code which have an error 
> > 
> > 
> > 
> > from sqlalchemy import * 
> > from sqlalchemy.ext.compiler import compiles 
> > from sqlalchemy.ext.declarative import declarative_base 
> > from sqlalchemy.orm import sessionmaker, aliased 
> > 
> > 
> > 
> > 
> > class explain(Executable, ClauseElement): 
> > def __init__(self, stmt, analyze=False): 
> > self.statement = _literal_as_text(stmt) 
> > self.analyze = analyze 
> > # helps with INSERT statements 
> > self._returning = getattr(stmt, '_returning', None) 
> > 
> > 
> > self.table = getattr(stmt, 'table', None) 
> > 
> > 
> > 
> > 
> > @compiles(explain, 'postgresql') 
> > def pg_explain(element, compiler, **kw): 
> > text = "EXPLAIN " 
> > if element.analyze: 
> > text += "ANALYZE " 
> > text += compiler.process(element.statement, **kw) 
> > return text 
> > 
> > 
> > 
> > 
> > Base = declarative_base() 
> > 
> > 
> > class Foo(Base): 
> > __tablename__ = 'foo' 
> > id = Column(Integer, primary_key=True) 
> > 
> > 
> > engine = create_engine(postgres_uri, echo=False) 
> > 
> > 
> > 

Re: [sqlalchemy] Issue on inserts statements for pg explain recipe

2018-10-03 Thread Mike Bayer
The insert is by itself not a RETURNING and doesn't return any rows.
The actual exception raised is:

sqlalchemy.exc.ResourceClosedError: This result object does not return
rows. It has been closed automatically.

and you'll get this just if you run the insert by itself:

returning_query = Foo.__table__.insert()
print(sess.execute(returning_query, {'id': 1}).fetchall())

Python 3 is just also showing you the exception we catch internally
which is the "'NoneType' object has no attribute 'fetchall'"  one, but
that is normal, we are catching that to detect that this result
doesn't return any rows.

the cursor is getting closed because for any DML that doesn't return
rows, it closes the cursor because there's no other point at which it
could naturally be closed automatically from the point of view of the
resultproxy.

If you tell the insert statement to return rows, the cursor doesnt get
closed and the explain gets the rows back:

returning_query = Foo.__table__.insert().returning(Foo.id)

print(sess.execute(explain(returning_query), {"id": 1}).fetchall())

EXPLAIN INSERT INTO foo (id) VALUES (%(id)s) RETURNING foo.id
2018-10-03 23:15:38,272 INFO sqlalchemy.engine.base.Engine {'id': 1}
[('Insert on foo  (cost=0.00..0.01 rows=1 width=4)',), ('  ->  Result
(cost=0.00..0.01 rows=1 width=4)',)]

to get the insert() to return the rows without returning being
present, we have to flip off the flags that are telling the execution
context that this is an INSERT, or more generally crud, that are
making it autoclose the cursor:

@compiles(explain, 'postgresql')
def pg_explain(element, compiler, **kw):
text = "EXPLAIN "
if element.analyze:
text += "ANALYZE "
text += compiler.process(element.statement, **kw)
compiler.isinsert = compiler.isupdate = compiler.isdelete = False
return text

that seems to fix the codepath that is looking for _returning also, so
I'll add that.



On Wed, Oct 3, 2018 at 5:04 AM  wrote:
>
> Hello,
>
> I use the recipe for explain as described 
> (https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/Explain), which 
> does the job completely for select statements (I have no idea how it works 
> however :p) in version 1.2.11
> The recipe at the moment is
>
> from sqlalchemy import *
> from sqlalchemy.ext.compiler import compiles
> from sqlalchemy.sql.expression import Executable, ClauseElement, 
> _literal_as_text
>
>
> class explain(Executable, ClauseElement):
> def __init__(self, stmt, analyze=False):
> self.statement = _literal_as_text(stmt)
> self.analyze = analyze
> # helps with INSERT statements
> self.inline = getattr(stmt, 'inline', None)
>
>
> @compiles(explain, 'postgresql')
> def pg_explain(element, compiler, **kw):
> text = "EXPLAIN "
> if element.analyze:
> text += "ANALYZE "
> text += compiler.process(element.statement, **kw)
> return text
>
>
> The recipe is not up to date, as it doesn't work on inserts, however by 
> replacing
>
> self.inline = getattr(stmt, 'inline', None)
> by
> self._returning = getattr(stmt, '_returning', None)
> self.table = getattr(stmt, 'table', None)
>
> It works on inserts with returning, however it crashes when I try to 
> fetchall() on explain of simple inserts with a "AttributeError: 'NoneType' 
> object has no attribute 'fetchall'"
> Below a code which have an error
>
>
>
> from sqlalchemy import *
> from sqlalchemy.ext.compiler import compiles
> from sqlalchemy.ext.declarative import declarative_base
> from sqlalchemy.orm import sessionmaker, aliased
>
>
>
>
> class explain(Executable, ClauseElement):
> def __init__(self, stmt, analyze=False):
> self.statement = _literal_as_text(stmt)
> self.analyze = analyze
> # helps with INSERT statements
> self._returning = getattr(stmt, '_returning', None)
>
>
> self.table = getattr(stmt, 'table', None)
>
>
>
>
> @compiles(explain, 'postgresql')
> def pg_explain(element, compiler, **kw):
> text = "EXPLAIN "
> if element.analyze:
> text += "ANALYZE "
> text += compiler.process(element.statement, **kw)
> return text
>
>
>
>
> Base = declarative_base()
>
>
> class Foo(Base):
> __tablename__ = 'foo'
> id = Column(Integer, primary_key=True)
>
>
> engine = create_engine(postgres_uri, echo=False)
>
>
> Base.metadata.create_all(engine)
>
>
> sess = sessionmaker(engine)()
>
>
> returning_query = Foo.__table__.insert()
>
>
> print(sess.execute(explain("INSERT INTO foo VALUES (1)")).fetchall())
> print(sess.execute(explain(returning_query), {'id': 1}).fetchall())
>
>
> My 2 questions :
> - can the recipe be updated for newer versions of sqlalchemy (the inline -> 
> _returning and table change) ?
> - How can I change the recipe so I can fetch for inserts (I know it is pretty 
> fucking useless, but it is supposed not to crash) ?
>
> --
> Nicolas Rolin
>
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> 

[sqlalchemy] Issue on inserts statements for pg explain recipe

2018-10-03 Thread nicolas . rolin
Hello,

I use the recipe for explain as described 
(https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/Explain), which 
does the job completely for select statements (I have no idea how it works 
however :p) in version 1.2.11
The recipe at the moment is 

from sqlalchemy import *
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import Executable, ClauseElement, 
_literal_as_text


class explain(Executable, ClauseElement):
def __init__(self, stmt, analyze=False):
self.statement = _literal_as_text(stmt)
self.analyze = analyze
# helps with INSERT statements
self.inline = getattr(stmt, 'inline', None)


@compiles(explain, 'postgresql')
def pg_explain(element, compiler, **kw):
text = "EXPLAIN "
if element.analyze:
text += "ANALYZE "
text += compiler.process(element.statement, **kw)
return text


The recipe is not up to date, as it doesn't work on inserts, however by 
replacing

self.inline = getattr(stmt, 'inline', None)
by 
self._returning = getattr(stmt, '_returning', None)
self.table = getattr(stmt, 'table', None)

It works on inserts with returning, however it crashes when I try to 
fetchall() on explain of simple inserts with a "AttributeError: 'NoneType' 
object has no attribute 'fetchall'"
Below a code which have an error 



from sqlalchemy import *
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, aliased




class explain(Executable, ClauseElement):
def __init__(self, stmt, analyze=False):
self.statement = _literal_as_text(stmt)
self.analyze = analyze
# helps with INSERT statements
self._returning = getattr(stmt, '_returning', None)


self.table = getattr(stmt, 'table', None)




@compiles(explain, 'postgresql')
def pg_explain(element, compiler, **kw):
text = "EXPLAIN "
if element.analyze:
text += "ANALYZE "
text += compiler.process(element.statement, **kw)
return text




Base = declarative_base()


class Foo(Base):
__tablename__ = 'foo'
id = Column(Integer, primary_key=True)


engine = create_engine(postgres_uri, echo=False)


Base.metadata.create_all(engine)


sess = sessionmaker(engine)()


returning_query = Foo.__table__.insert()


print(sess.execute(explain("INSERT INTO foo VALUES (1)")).fetchall())
print(sess.execute(explain(returning_query), {'id': 1}).fetchall())


My 2 questions :
- can the recipe be updated for newer versions of sqlalchemy (the inline -> 
_returning and table change) ?
- How can I change the recipe so I can fetch for inserts (I know it is 
pretty fucking useless, but it is supposed not to crash) ?

-- 
Nicolas Rolin

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