tursodatabase / libsql

libSQL is a fork of SQLite that is both Open Source, and Open Contributions.
https://turso.tech/libsql
MIT License
11.54k stars 287 forks source link

lastrowid API not working on libsql-server hosted databases #1097

Open mjmammoth opened 8 months ago

mjmammoth commented 8 months ago

The lastrowid API always returns a 0 from libsql-server databases. For local file and in-memory databases it seems to work fine. Embedded local databases with sync seem to be fine as well.

To test, I created a python script that uses the libsql-experimental-python package to test against the different connection types. The script drops a table, creates a table, and then inserts twice, printing the lastrowid after each operation, to which I would expect the result [0, 0, 1, 2] for all the connection types.

import libsql_experimental as libsql
import os

LIBSQL_URL=os.environ.get("LIBSQL_URL")
LIBSQL_AUTH_TOKEN=os.environ.get("LIBSQL_AUTH_TOKEN")

def test_lastrowid(test_name, *args, **kwargs):
    row_ids = []
    connection = libsql.connect(*args, **kwargs)
    cursor = connection.cursor()
    cursor.execute("DROP TABLE IF EXISTS heroes")
    row_ids.append(cursor.lastrowid) # 0
    cursor.execute("CREATE TABLE heroes (id INTEGER PRIMARY KEY, hero_name TEXT)")
    row_ids.append(cursor.lastrowid) # 0
    cursor.execute("INSERT INTO heroes (hero_name) VALUES ('Batman')")
    row_ids.append(cursor.lastrowid) # 1
    cursor.execute("INSERT INTO heroes (hero_name) VALUES ('Superman')")
    row_ids.append(cursor.lastrowid) # 2
    print(f'{test_name}: {row_ids}')
    connection.commit()

test_lastrowid("Local file", "test.db")
test_lastrowid("In memory", ":memory:")
test_lastrowid("Local SQLD", database="http://127.0.0.1:8080")
test_lastrowid("Remote Turso", database=LIBSQL_URL, auth_token=LIBSQL_AUTH_TOKEN)
test_lastrowid("Embedded turso replica", "localsync.db", sync_url=LIBSQL_URL, auth_token=LIBSQL_AUTH_TOKEN)

Actual results are:

Local file: [0, 0, 1, 2]
In memory: [0, 0, 1, 2]
Local SQLD: [0, 0, 0, 0]
Remote Turso: [0, 0, 0, 0]
Embedded turso replica: [0, 0, 1, 2]
penberg commented 3 months ago

Update: this reproduces on latest Python package as well. Steps to fix: (1) verify that the libsql Rust crate returns a proper lastrowid and (2) then audit the Python package.