popoto.backends.postgres.plan¶
popoto.backends.postgres.plan
¶
SQL rendering of query plans for the Postgres backend (#759 M1b).
Two steps, kept apart on purpose:
- :func:
popoto.backends.planning.plan_from_call(backend-neutral, run by the query layer for every non-Redis backend) turns the public call (:class:QueryCall, the call exactly asQuery.filter/countreceived it) into a protocol :class:QueryPlan--where,order_by,limit,project-- while reproducing the query layer's validation (the sameQueryExceptiontext for an unknown parameter, a non-boolean__isnull, a malformed__between, a partitionedSortedFieldqueried without its partition) and its ordering rules (explicitorder_by>Meta.order_by> the first filteredSortedField's score order). On Redis those rules live in the moved filter body; here they become plan terms. - :func:
render_where/ :func:render_order(this module) turn plan terms into SQL over a :class:~popoto.backends.postgres.schema.TableSpec.
Null handling mirrors Redis's set algebra, not SQL's three-valued logic: a
negated subtree renders as NOT coalesce(…, false), so ~Q(x=1)
includes rows whose x is NULL exactly as all_keys - matches does.
to_db_value(py_type, value)
¶
A Python value as the column wants it. A naive datetime is UTC --
the same instant SortedFieldMixin.convert_to_numeric scores it as
(#519) -- so comparisons and ordering agree with Redis.
Source code in src/popoto/backends/postgres/plan.py
to_column_value(ts, name, value)
¶
value of field name as its column stores it (M1.1): the
collections as jsonb (:mod:.codec), a TagField as its
normalised text[], a Relationship as the target's key string.
Source code in src/popoto/backends/postgres/plan.py
render_where(ts, kinds, where, *, live=True)
¶
(" WHERE …", params), or ("", []) for no predicate.
On a Meta.ttl model the TTL read filter is ANDed on (M5, .ttl):
every reader that scopes the record table through this -- select,
count, ranking, search, recall -- sees only rows that have not
expired. live=False leaves it off. A model without Meta.ttl
renders exactly as before.
Source code in src/popoto/backends/postgres/plan.py
non_null_fields(where)
¶
Fields the predicate guarantees are not NULL: a range lookup (or a
non-None exact match) in the top-level conjunction.
Source code in src/popoto/backends/postgres/plan.py
render_order(ts, terms, not_null=frozenset())
¶
ORDER BY for terms plus the deterministic tie-break
_pk COLLATE "C" (Redis's bytewise member order).
A NULL sorts as the type's zero value, as prepare_results's
getattr(obj, f) or type() does; a descending primary term reverses
the whole order, as list(reversed(…)) does on Redis. For a field in
not_null (the WHERE already excludes its NULL rows) the bare
column is ordered, so its B-tree can serve the ORDER BY … LIMIT.