1

So I get that when I call list() on a Query object, that executes the query and returns the results as a list.

What I'm wondering is what exactly is happening in the source code to make the Query fire SQL and grab the results.

HLH
  • 1,097
  • 4
  • 15
  • 22
  • 1
    Might want to enable logging (as seen [here](http://stackoverflow.com/questions/2950385/debugging-displaying-sql-command-sent-to-the-db-by-sqlalchemy) ) and see what query actually gets executed when list is called. – TJ1S Jul 29 '15 at 00:24

1 Answers1

1

When do you list(query), python invokes the method __iter__(), as for any container, for the class Query.

This method initializes context and eventually calls _execute_and_instances(), and internal method of class Query, which gets the connection from the session and executes the query statement.

def _execute_and_instances(self, querycontext):
    conn = self._connection_from_session(
        mapper=self._mapper_zero_or_none(),
        clause=querycontext.statement,
        close_with_result=True)

    result = conn.execute(querycontext.statement, self._params)
    return loading.instances(self, result, querycontext)

So the query is executed just when the list object is created.

It's not much detail, and I hope it is enough to answer your question. Maybe some context on why you are asking would allow to go into more relevant details. Hope it helps anyway.

EDIT: After clarifications via comments, as for your second question (i.e. how to add a traceback of your call as a comment in the query, to be logged in the server): I don't think is feasible just modifying in one single point.

Most queries go through the object Query, and its method _compile_context is a common point where the query is composed. If you launch either a usual query (a select with filters and so on) or a delete, it will go through this method.

However, session.add is completely different. At the moment of adding the object not much is really done (regarding the query I mean; of course the new object is registered). The objects are only inserted when you perform commit (as expected btw). session.flush starts this process. At that point, you have available SQLAlchemy's mapper and you could get the instance of the object you are actually adding (e.g. an instance of your class User). If you have added the traceback at the moment of creating your instance, you could recover it here and add it to the query as a comment.

At any rate, this would not be easy at all, difficult to maintain as well, while it is only for debugging. I understand what you are trying to do but it is too much effort for a result which is not so great (in my opinion).

lrnzcig
  • 3,868
  • 4
  • 36
  • 50
  • This is very helpful! The context would be that I'm trying to write a wrapper around session.query, session.add, session.delete, etc. that inserts a comment into the query sent to the SQL server with a traceback of when the relevant method is called. What would make it easier is if there is one particular lower level method that is called by all of these that I can wrap instead of doing them each individually – HLH Jul 29 '15 at 17:42
  • 1
    Ok, but you want to add your stuff when the query is actually sent to the server? I mean, `session.add` composes a query (I don't know if it does it just at the point of the call, I would have to check it), but that query is not sent to the server until `commit`. The same with a `select`, you first compose the query but it is actually sent when you need the data. I think the common point you are looking for, if you want the point in which the query is actually sent, it is `connection.execute`. – lrnzcig Jul 29 '15 at 18:22
  • 1
    2nd question: what exactly you want to add? If it is only a comment, `SQLAlchemy` has really loads of logging (@TJ1S has already provided a link). – lrnzcig Jul 29 '15 at 18:29
  • I want to add my stuff when the query is composed, i.e. when `session.add` is called. I want to make the comment show up in the actual query so that it's recorded in the MySQL general log. The comment should basically just be the first line of a traceback saying which file and which line the query came from. – HLH Jul 29 '15 at 19:11
  • 1
    Ok, I understand. Then your point is not `connection.execute`. You could do it somewhere in the `Query` object. Let me take a look and I'll get back to you if I find something. (Be patient, it is a bit late in my timezone and might leave it for tomorrow.) – lrnzcig Jul 29 '15 at 19:15
  • Hi. No, I don't think there is a common point as you are requesting. The method `_compile_context` of `Query` is common for most operations, e.g. for a normal query and a delete, but the `session.add` is done in a completely different way, without the query, I can't figure it out. I give up, sorry and good luck! – lrnzcig Jul 29 '15 at 20:58