Skip to content

Commit

Permalink
Fix query when only aggregate fields are requested (#140)
Browse files Browse the repository at this point in the history
`pypinfo numpy percent3` creates a query with an empty `GROUP BY` clause which results in a BigQuery exception:
`google.api_core.exceptions.BadRequest: 400 Syntax error: Unexpected keyword ORDER at [10:1]`

This commit fixes the logic used to conditionally build the `GROUP BY` clause.
  • Loading branch information
mayeut committed Jun 12, 2022
1 parent b01fa6d commit 5924bd9
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 16 deletions.
20 changes: 6 additions & 14 deletions pypinfo/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,20 +149,12 @@ def build_query(
if where:
query += f' AND {where}\n'

if len(fields) > 1:
gb = 'GROUP BY\n'
initial_length = len(gb)

non_aggregate_fields = []
for field in fields[:-1]:
if field not in AGGREGATES:
non_aggregate_fields.append(field.name)
gb += ' '
gb += ', '.join(non_aggregate_fields)
gb += '\n'

if len(gb) > initial_length:
query += gb
non_aggregate_fields = [field.name for field in fields if field not in AGGREGATES]
if non_aggregate_fields:
query += 'GROUP BY\n'
query += ' '
query += ', '.join(non_aggregate_fields)
query += '\n'

query += f'ORDER BY\n {order or Downloads.name} DESC\n'
query += f'LIMIT {limit}'
Expand Down
2 changes: 1 addition & 1 deletion pypinfo/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@
Libc = Field('libc_name', 'details.distro.libc.lib')
LibcVersion = Field('libc_version', 'details.distro.libc.version')

AGGREGATES = {Percent3, Percent2}
AGGREGATES = {Downloads, Percent3, Percent2}
33 changes: 32 additions & 1 deletion tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pytest

from pypinfo import core
from pypinfo.fields import File, PythonVersion
from pypinfo.fields import File, Percent3, PythonVersion

ROWS = [
['python_version', 'percent', 'download_count'],
Expand Down Expand Up @@ -259,6 +259,37 @@ def test_build_query_no_project():
assert output == expected


def test_build_query_only_aggregate():
# pypinfo -sd -2 -ed -1 -l 20 numpy percent3
project = "numpy"
all_fields = [Percent3]
start_date = "-2"
end_date = "-1"
days = None
limit = 20
where = None
order = None
pip = True
expected = r"""
SELECT
ROUND(100 * SUM(CASE WHEN REGEXP_EXTRACT(details.python, r"^([^\.]+)") = "3" THEN 1 ELSE 0 END) / COUNT(*), 1) as percent_3,
COUNT(*) as download_count,
FROM `bigquery-public-data.pypi.file_downloads`
WHERE timestamp BETWEEN TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL -2 DAY) AND TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL -1 DAY)
AND file.project = "numpy"
AND details.installer.name = "pip"
ORDER BY
download_count DESC
LIMIT 20
""".strip() # noqa: E501

# Act
output = core.build_query(project, all_fields, start_date, end_date, days, limit, where, order, pip)

# Assert
assert output == expected


def test_build_query_bad_end_date():
# Arrange
project = "pycodestyle"
Expand Down

0 comments on commit 5924bd9

Please sign in to comment.