Skip to content

sqlite3: when passing incomplete aggregate class, raises wrong error in specific conditions #95462

Closed as not planned
@rinsuki

Description

@rinsuki

Bug report

when register incomplete aggregate class (missing step method), and first call (on one query) is with empty data, sqlite3 library raises wrong error.

import sqlite3
import traceback

db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE users (id INTEGER NOT NULL)")
db.execute("INSERT INTO users VALUES (0)")
db.execute("INSERT INTO users VALUES (1)")
db.execute("CREATE TABLE scores (player_id INTEGER NOT NULL, score INTEGER NOT NULL)")
db.execute("INSERT INTO scores (player_id, score) VALUES (1, 10)")

class Median:
    def __init__(self):
        self.data = []

    # ohh i just typo
    def steeep(self, x):
        self.data.append(x)

    def finalize(self):
        data = sorted(self.data)
        ld = len(data)
        if ld == 0:
            return int(0)
        elif ld % 2 == 0:
            return int((data[ld // 2 - 1] + data[ld // 2]) / 2)
        else:
            return int(data[ld // 2])

db.create_aggregate("median", 1, Median)
try:
    cur = db.execute("SELECT player_id, median(score) FROM scores GROUP BY player_id")
    print(cur.fetchall())
except:
    traceback.print_exc()

try:
    cur = db.execute("SELECT users.id, median(score) FROM users LEFT JOIN scores ON users.id = scores.player_id GROUP BY player_id ORDER BY users.id DESC")
    print(cur.fetchall())
except:
    traceback.print_exc()

this repro code prints two error, and they should be same.

in 3.11.0a5 or older, python prints different error (wrong behaviour).

Traceback (most recent call last):
  File "/app/sqlite-aggregate-test.py", line 31, in <module>
    cur = db.execute("SELECT player_id, median(score) FROM scores GROUP BY player_id")
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Median' object has no attribute 'step'
Traceback (most recent call last):
  File "/app/sqlite-aggregate-test.py", line 37, in <module>
    cur = db.execute("SELECT users.id, median(score) FROM users LEFT JOIN scores ON users.id = scores.player_id GROUP BY player_id ORDER BY users.id DESC")
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sqlite3.OperationalError: user-defined aggregate's '__init__' method raised error

but it was resolved in 3.11.0a6 (#31604) or newer, now python prints same error (correct behaviour).

Traceback (most recent call last):
  File "/app/sqlite-aggregate-test.py", line 31, in <module>
    cur = db.execute("SELECT player_id, median(score) FROM scores GROUP BY player_id")
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sqlite3.OperationalError: user-defined aggregate's 'step' method not defined
Traceback (most recent call last):
  File "/app/sqlite-aggregate-test.py", line 37, in <module>
    cur = db.execute("SELECT users.id, median(score) FROM users LEFT JOIN scores ON users.id = scores.player_id GROUP BY player_id ORDER BY users.id DESC")
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sqlite3.OperationalError: user-defined aggregate's 'step' method not defined

in 3.11/main branch, any work is not needed because already fixed, but it would be good to backport it for older versions.

Your environment

All of these are tested on arm64/AArch64 machine (Apple M1 Max).

  • Docker python image with these tags:
    • 3.11.0a5-alpine3.15
    • 3.10.5-alpine3.15
    • 3.10.5-bullseye
    • 3.9.13-alpine3.15
    • 3.8.13-alpine3.15
    • 3.7.13-alpine3.15
  • Installed from Homebrew (macOS 12.5), Python 3.9.13

Metadata

Metadata

Labels

3.10only security fixestopic-sqlite3type-bugAn unexpected behavior, bug, or error

Projects

Status

Discarded

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions