diff --git a/README.md b/README.md index 582c908..27f8c0c 100644 --- a/README.md +++ b/README.md @@ -10,18 +10,18 @@ a sibling of the `mongo` lib. Class is **`PsqlDB`**. `requirements.txt`: ``` -psql @ git+ssh://git@git.rethinkstudios.io/rethink-public/psql.git@v0.1.2 +psql @ git+ssh://git@git.rethinkstudios.io/rethink-public/psql.git@v0.1.3 ``` Direct: ```bash -pip install "psql @ git+ssh://git@git.rethinkstudios.io/rethink-public/psql.git@v0.1.2" +pip install "psql @ git+ssh://git@git.rethinkstudios.io/rethink-public/psql.git@v0.1.3" ``` Pulls `asyncpg`. -Drop the `@v0.1.2` suffix from the line above to install the latest unpinned. +Drop the `@v0.1.3` suffix from the line above to install the latest unpinned. ## The two-layer API diff --git a/pyproject.toml b/pyproject.toml index b6fe72f..2d89773 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "psql" -version = "0.1.2" +version = "0.1.3" description = "async postgres wrapper over asyncpg: two-layer API (friendly verbs + raw escape hatch), fail-loud, config-free" requires-python = ">=3.10" dependencies = [ diff --git a/src/psql/psql.py b/src/psql/psql.py index f39c57e..b0dfb1a 100644 --- a/src/psql/psql.py +++ b/src/psql/psql.py @@ -373,13 +373,21 @@ class _Transaction: def _where(conditions: Optional[Dict[str, Any]]) -> tuple: """build a parameterized `WHERE col = $1 AND ...` clause + the params list - returns ("", []) when there are no conditions. equality only. + returns ("", []) when there are no conditions. equality only. a None value renders as + `col IS NULL` (not `col = $n` bound to NULL, which sql never matches) and does not + consume a placeholder. """ if not conditions: return "", [] - cols = list(conditions.keys()) - clause = " AND ".join(f"{_quote_ident(c)} = ${i + 1}" for i, c in enumerate(cols)) - return f" WHERE {clause}", list(conditions.values()) + parts = [] + params = [] + for col, val in conditions.items(): + if val is None: + parts.append(f"{_quote_ident(col)} IS NULL") + else: + params.append(val) + parts.append(f"{_quote_ident(col)} = ${len(params)}") + return f" WHERE {' AND '.join(parts)}", params def _status_count(status: str) -> int: