GHC 2018-08-01

1 comment.

, https://git.io/fNovB in coleifer/peewee
Subquery expressions not parenthesized as function arguments
============================================================

peewee version: 3.6.4

It seems that peewee does not parenthesize subquery expressions when used in a function, resulting in syntax errors (at least with SQLite).

Consider this minimal example, where we run the same query with a subquery expression twice, except in the second case we try to coalesce the subquery expression (a sum that could be null) with 0:

```py
#!/usr/bin/env python3

import logging
import sys

import peewee

logger = logging.getLogger('peewee')
logger.addHandler(logging.StreamHandler())
logger.setLevel(logging.DEBUG)

db = peewee.SqliteDatabase('data.db')

class Record(peewee.Model):
    amount = peewee.IntegerField()

    class Meta:
        database = db

db.drop_tables([Record])
db.create_tables([Record], safe=True)
for amount in range(1, 6):
    Record.create(amount=amount)

RecordAlias = Record.alias()
q = (Record
     .select(RecordAlias
             .select(peewee.fn.SUM(RecordAlias.amount))
             .where(RecordAlias.amount < Record.amount).alias('sum'))
     .order_by(peewee.SQL('sum')))
for r in q:
    print(r.sum)

# Collasce a scalar subquery
q = (Record
     .select(peewee.fn.COALESCE(
         RecordAlias
         .select(peewee.fn.SUM(RecordAlias.amount))
         .where(RecordAlias.amount < Record.amount),
         0,
     ).alias('sum'))
     .order_by(peewee.SQL('sum')))
try:
    for r in q:
        print(r.sum)
except peewee.PeeweeException as e:
    sys.exit('Error: %s' % e)
```

When executed, here's the output:

```sql
('DROP TABLE IF EXISTS "record"', [])
('CREATE TABLE IF NOT EXISTS "record" ("id" INTEGER NOT NULL PRIMARY KEY, "amount" INTEGER NOT NULL)', [])
('INSERT INTO "record" ("amount") VALUES (?)', [1])
('INSERT INTO "record" ("amount") VALUES (?)', [2])
('INSERT INTO "record" ("amount") VALUES (?)', [3])
('INSERT INTO "record" ("amount") VALUES (?)', [4])
('INSERT INTO "record" ("amount") VALUES (?)', [5])
('SELECT (SELECT SUM("t1"."amount") FROM "record" AS "t1" WHERE ("t1"."amount" < "t2"."amount")) AS "sum" FROM "record" AS "t2" ORDER BY sum', [])
None
1
3
6
10
('SELECT COALESCE(SELECT SUM("t1"."amount") FROM "record" AS "t1" WHERE ("t1"."amount" < "t2"."amount"), ?) AS "sum" FROM "record" AS "t2" ORDER BY sum', [0])
Error: near "SELECT": syntax error
```

Here the correct query would be

```sql
SELECT COALESCE((SELECT SUM("t1"."amount") FROM "record" AS "t1" WHERE ("t1"."amount" < "t2"."amount")), 0) AS "sum" FROM "record" AS "t2" ORDER BY sum
```

The result of which would be

```
0
1
3
6
10
```