peewee-async icon indicating copy to clipboard operation
peewee-async copied to clipboard

Using currval after insert_from with no inserted rows

Open vonafor opened this issue 8 years ago • 2 comments

Environment: PostgreSQL 9.6.6 aiopg 0.13.2 peewee 2.10.2 peewee-async 0.5.10 psycopg2 2.7.3.2

Assume we have the code like that

import asyncio

import peewee as pw
import peewee_async


db_name =  # database name
db_conf =  # conf

database = peewee_async.PooledPostgresqlDatabase(
    db_name, **db_conf
)


class A(pw.Model):
    name = pw.IntegerField(default=0)

    class Meta:
        db_table = "table_a"
        database = database


class B(pw.Model):
    name = pw.IntegerField(default=0)

    class Meta:
        db_table = "table_b"
        database = database


A.create_table(True)
B.create_table(True)


objects = peewee_async.Manager(database)
objects.database.allow_sync = False


async def handler():
    await objects.execute(B.insert_from([B.name], A.select(A.name)))

loop = asyncio.get_event_loop()
loop.run_until_complete(handler())
loop.close()

If we execute it we get an exception

Traceback (most recent call last):
  File "rock.py", line 48, in <module>
    loop.run_until_complete(handler())
  File "/usr/local/lib/python3.6/asyncio/base_events.py", line 467, in run_until_complete
    return future.result()
  File "rock.py", line 45, in handler
    await objects.execute(B.insert_from([B.id], A.select(A.id)))
  File "/home/yamitrofanov/.virtualenvs/peewee_async/local/lib/python3.6/site-packages/peewee_async.py", line 271, in execute
    return (yield from execute(query))
  File "/home/yamitrofanov/.virtualenvs/peewee_async/local/lib/python3.6/site-packages/peewee_async.py", line 435, in execute
    return (yield from coroutine(query))
  File "/home/yamitrofanov/.virtualenvs/peewee_async/local/lib/python3.6/site-packages/peewee_async.py", line 610, in insert
    cursor, query.model_class)
  File "/home/yamitrofanov/.virtualenvs/peewee_async/local/lib/python3.6/site-packages/peewee_async.py", line 1162, in last_insert_id_async
    yield from cursor.execute("SELECT CURRVAL('%s\"%s\"')" % (schema, seq))
  File "/home/yamitrofanov/.virtualenvs/peewee_async/local/lib/python3.6/site-packages/aiopg/cursor.py", line 114, in execute
    yield from self._conn._poll(waiter, timeout)
  File "/home/yamitrofanov/.virtualenvs/peewee_async/local/lib/python3.6/site-packages/aiopg/connection.py", line 238, in _poll
    yield from asyncio.wait_for(self._waiter, timeout, loop=self._loop)
  File "/usr/local/lib/python3.6/asyncio/tasks.py", line 358, in wait_for
    return fut.result()
  File "/home/yamitrofanov/.virtualenvs/peewee_async/local/lib/python3.6/site-packages/aiopg/connection.py", line 135, in _ready
    state = self._conn.poll()
psycopg2.OperationalError: currval of sequence "table_b_id_seq" is not yet defined in this session

The last_insert_id_async uses CURRVAL.

The currval description says: Return the value most recently obtained by nextval for this sequence in the current session. (An error is reported if nextval has never been called for this sequence in this session.) Because this is returning a session-local value, it gives a predictable answer whether or not other sessions have executed nextval since the current session did.

In case above there are not rows in the table B(in general, if the query in insert_from does not return any rows). So there is nothing to insert that's why nextval has not been executed and the error occurred. I think this situation should be managed.

vonafor avatar Jan 15 '18 16:01 vonafor

Same issue here :/

jersobh avatar Jul 19 '18 12:07 jersobh

Could you try switching newer peewee / peewee-async? Probably this issue has been already solved there.

rudyryk avatar Aug 05 '18 21:08 rudyryk