62

I'm using async_engine. When I try to execute anything:

async with self.async_engine.connect() as con:
    query = "SELECT id, name FROM item LIMIT 50;"
    result = await con.execute(f"{query}")

I'm getting:

Exception has occurred: ObjectNotExecutableError
Not an executable object: 'SELECT id, name FROM item LIMIT 50;'

This question was asked before by user @stilmaniac but it is now deleted from SO.

I found it in Google Search cache, here is copy.

I have the same issue so I'm reasking it, but the original version is below:


I'm trying to create tables from metadata as follows:

Base = declarative_base()

properties = Table(
    'properties', Base.metadata,
    # ...
    Column('geolocation', Geography(geometry_type='POINT', srid=4326)),
    # ... 
)

engine = create_async_engine("postgresql+asyncpg://user:password@postgres/")
async with engine.begin() as conn:
    await conn.run_sync(Base.metadata.create_all)

Gives me the following error:

sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: 'CREATE INDEX "idx_properties_geolocation" ON "properties" USING GIST ("geolocation")'

Considering this doc

Versions:

  • OS: macOS 11.4 ARM
  • SQLAlchemy: 1.4.22
  • Python: 3.6
2
  • Have you tried using it without f strings? Commented Oct 8, 2021 at 4:31
  • @ReedJones f"{}" gives the same result as str(), it wasn't the cause. Commented Oct 12, 2021 at 12:31

3 Answers 3

158

As the exception message suggests, the str 'SELECT id, name FROM item LIMIT 50;' is not an executable object. To make it executable, wrap it with sqlalchemy.text.

from sqlalchemy import text

async with self.async_engine.connect() as con:
    query = "SELECT id, name FROM item LIMIT 50;"
    result = await con.execute(text(query))

async.connection.execute requires that its statement argument

[...] is always an object that is in both the ClauseElement and Executable hierarchies, including:

  • Select

  • Insert, Update, Delete

  • TextClause and TextualSelect

  • DDL and objects which inherit from DDLElement

The synchronous connection.execute method permits raw strings, but this is deprecated in v1.4 and has been removed in SQLAlchemy 2.0.

Sign up to request clarification or add additional context in comments.

1 Comment

very grateful for this answer - I genuinely thought I was going mad...
11

It is due to sqlalchemy treats query as string, below workaround is working

from sqlalchemy import text
query = 'insert into table_name values(1,2,3)'
 with pool.connect() as db_conn:
     db_conn.execute(text(query))

Comments

6

This issue is related to this thread

Workaround: To avoid this bug, I just reverted the version of SQLAlchemy back to older than 2.0 :

  1. Firstly, confirm if your SQLAlchmey version is 2.0 or beyond. To do so, run
pip show sqlalchemy

Which will show something like this:

Verify current version from output:
Name: SQLAlchemy
Version: 2.0.9

Summary: Database Abstraction Library
Home-page: https://www.sqlalchemy.org
Author: Mike Bayer
Author-email: [email protected]
License: MIT
Location: /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages
Requires: typing-extensions
Required-by: pandasql
  1. Revert back to older version (install a specific version of SQLAlchemy using below command):
pip install SQLAlchemy==1.4.17

Confirm the version once:

pip show sqlalchemy

Rerun your script.

2 Comments

Downvoted because that’s a complicated solution (going back to 1.4 may require changing a lot of code) to a non-problem: the accepted answer already works with SQLAlchemy 2.0.
@bfontaine and yet it saved my day, thus +1 ;-] It's not a non-problem if you accidentally install the latest version and wonder what's going on? Upgrading may require changing a lot of code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.