Skip to content

Commit

Permalink
Merge pull request #11 from iNishant/feature/postgres-matrix
Browse files Browse the repository at this point in the history
postgres test matrix
  • Loading branch information
iNishant authored Sep 19, 2024
2 parents 5ddaba6 + f59a9aa commit 721e406
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 27 deletions.
46 changes: 28 additions & 18 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,24 @@ on:

permissions:
contents: read

jobs:
build:

test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11"]
django-version: ["4.0", "4.1", "4.2", "5.0", "5.1"]
exclude:
# Django 5.0+ requires Python 3.10+
- python-version: "3.9"
django-version: "5.0"
- python-version: "3.9"
django-version: "5.1"
max-parallel: 5

services:
postgres:
image: postgres
image: postgres:13
env:
POSTGRES_PASSWORD: postgres
options: >-
Expand All @@ -29,17 +38,18 @@ jobs:
- 5432:5432

steps:
- uses: actions/checkout@v3
- name: Set up Python 3.9
uses: actions/setup-python@v3
with:
python-version: "3.9"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r dev-requirements.txt
- name: Run tests
run: |
./check-lint.sh
python manage.py test -v 3 --no-input
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r dev-requirements.txt
pip install Django==${{ matrix.django-version }}
- name: Run tests
run: |
./check-lint.sh
python manage.py test -v 3 --no-input
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Django Querysets Single Query Fetch

Executes multiple querysets over a single db query and returns results which would have been returned in normal evaluation of querysets. This can help in critical paths to avoid network/connection-pooler latency if db cpu/mem are nowhere near exhaustion. Ideal use case is fetching multiple small and optimised independent querysets where above mentioned latencies can dominate total execution time.
Executes multiple querysets over a single db query and returns results which would have been returned in normal evaluation of querysets. This can help in critical paths to avoid network latency. Ideal use case is fetching multiple small and optimised independent querysets where above mentioned latencies can dominate total execution time.

Supports only Postgres as of now

Expand Down Expand Up @@ -45,12 +45,11 @@ Fetching count of queryset using `QuerysetCountWrapper` (since `queryset.count()
from django_querysets_single_query_fetch.service import QuerysetsSingleQueryFetch, QuerysetCountWrapper

querysets = [QuerysetCountWrapper(queryset=queryset1), queryset2, ...]
results = QuerysetsSingleQueryFetch(querysets=querysets)
results = QuerysetsSingleQueryFetch(querysets=querysets)

assert results == [queryset1.count(), list(queryset2), ...]
assert results == [queryset1.count(), list(queryset2), ...]
```


## Contribution suggestions

- Add tests (django version matrix, different types and parsing etc)
Expand All @@ -65,7 +64,6 @@ assert results == [queryset1.count(), list(queryset2), ...]
- MySQL support as an experiment
- "How it works" section/diagram?


## Notes

- Note parallelisation by postgres is not guaranteed, as it depends on lot of config params (max_parallel_workers_per_gather, min_parallel_table_scan_size, max_parallel_workers etc). Even without parallelisation, this can be faster than normal one-by-one evaluation of querysets due to reduced no of network trips.
2 changes: 1 addition & 1 deletion django_querysets_single_query_fetch/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def _get_fetch_count_compiler_from_queryset(
slightly modified copy paste from get_count and get_aggregation in django.db.models.sql.compiler
"""
obj = queryset.query.clone()
obj.add_annotation(Count("*"), alias="__count", is_summary=True)
obj.add_annotation(Count("*"), alias="__count")
added_aggregate_names = ["__count"]
existing_annotations = [
annotation
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
django==4
django==4.2
psycopg2==2.9.9
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

setuptools.setup(
name="django_querysets_single_query_fetch",
version="0.0.11",
version="0.0.12",
description="Execute multiple Django querysets in a single SQL query",
long_description="Utility which executes multiple Django querysets over a single network/query call and returns results which would have been returned in normal evaluation of querysets",
author="Nishant Singh",
author_email="nishant.singh@mydukaan.io",
license="Apache Software License",
packages=["django_querysets_single_query_fetch"],
zip_safe=False,
install_requires=["django>3"],
install_requires=["django>=4.0,<5.2"],
python_requires=">=3.9",
include_package_data=True,
package_data={},
Expand Down

0 comments on commit 721e406

Please sign in to comment.