matrx-orm 3.1.89__tar.gz → 3.1.91__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/PKG-INFO +2 -2
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/query/executor.py +54 -25
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/pyproject.toml +2 -2
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_join_and_aggregate.py +54 -1
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/.gitignore +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/AGENTS.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/BASE_CLASS_METHODS.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/CLAUDE.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/MODEL_API.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/database/orm/extended/managers/ai_model_base.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/docs/migrations.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/FEATURE.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/adapters/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/adapters/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/adapters/async_postgresql.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/adapters/base_adapter.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/adapters/postgresql.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/adapters/supabase_adapter.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/admin/FEATURE.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/admin/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/admin/router.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/api/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/api/auth.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/api/config.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/api/handlers.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/api/protocol.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/api/server.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/associations.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/cache_debug.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/catalog.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/catalog_sql.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/client/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/client/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/client/postgres_connection.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/client/postgrest.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/client/supabase_auth.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/client/supabase_config.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/client/supabase_manager.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/EXTENDED-TASK.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/FEATURE.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/TASKS.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/async_db_manager.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/base.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/config.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/connections.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/db_function.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/diagnostics.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/expressions.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/extended.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/fields.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/introspection.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/listen.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/loop_filters.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/model_dto.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/model_view.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/one_database.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/paginator.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/pool_maintenance.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/pool_watch.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/pooler_role.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/pydantic_bridge.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/registry.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/relations.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/resilience.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/rls_session.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/signals.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/tls.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/transaction.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/types.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/core/write_queue.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/entity.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/error_handling.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/exceptions.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/extended/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/extended/app_error_handler.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/identity_rule.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/local_sqlite.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/middleware/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/middleware/base.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/migrations/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/migrations/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/migrations/cli.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/migrations/ddl.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/migrations/diff.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/migrations/executor.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/migrations/integration.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/migrations/loader.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/migrations/operations.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/migrations/state.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/migrations/table_filter.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/FEATURE.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/bulk_update_values.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/conflict.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/conflict_writes.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/create.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/db_functions.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/delete.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/dynamic_admin.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/dynamic_crud.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/graph_walk.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/latest_rows.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/queue_claim.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/read.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/relational_backfill.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/staging_load.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/operations/update.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/platform_db.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/py.typed +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/python_sql/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/python_sql/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/python_sql/db_objects.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/query/FEATURE.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/query/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/query/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/query/builder.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/FEATURE.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/code_handler.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/codegen_writer.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/columns.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/common.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/diff_preview.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/generator.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/package_wiring.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/relationships.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/runner.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/schema.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/schema_manager.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/tables.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/schema_builder/views.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/secrets_battery/FEATURE.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/secrets_battery/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/secrets_battery/attachments.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/secrets_battery/crypto.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/secrets_battery/items.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/secrets_battery/model.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/secrets_battery/org_service.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/secrets_battery/service.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/coalesce.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/dag.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/errors.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/fallback.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/flush.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/lifecycle.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/managed.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/op.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/reads.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/session.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/session/telemetry.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/sql_executor/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/sql_executor/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/sql_executor/executor.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/sql_executor/queries.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/sql_executor/registry.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/sql_executor/types.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/sql_executor/utils.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/state.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/utils/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/utils/sql_utils.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/matrx_orm/utils/type_converters.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/scripts/git-branches.sh +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/scripts/publish.sh +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/scripts/release.sh +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/conftest.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_admin_db_columns.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_admin_response_rendering.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_admin_search_negation.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_admin_search_sentinels.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_advisory_lock.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_agent_message.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_api_auth.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_api_config.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_api_handlers.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_api_protocol.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_array_agg_order_by.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_associations.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_bulk_hydration_offload.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_bulk_update_by_pk.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_cache_debug.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_call_function.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_case_when.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_catalog.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_composite_pk_filter.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_composite_pk_write_paths.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_config.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_conflict_target.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_conflict_writes.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_connection_codecs.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_connection_poison_guard.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_connection_primitives.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_count_composite_distinct.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_db_function_field.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_ddl_generator.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_derived_table.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_dirty_tracking.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_dynamic_crud.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_exceptions.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_expression_primitives.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_fields.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_from_alias.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_fts.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_func_expression_args.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_graph_walk.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_having_annotate_alias.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_introspect_rls_policies.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_latest_rows.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_listen_notify.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_local_sqlite.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_managed_write_guard.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_matrx_entity.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_migration_diff_types.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_migration_loader.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_model_instance.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_model_meta.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_optimistic_concurrency.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_order_by_expression.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_parameter_name_hydration.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_patch_jsonb_path.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_pool_holder_census.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_pool_loop_recreation.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_pool_maintenance.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_postgrest_filters.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_pydantic_bridge.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_query_builder.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_query_error_detail.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_query_executor_sql.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_query_timeout.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_queue_claim.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_registry.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_registry_multi_database.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_registry_multi_schema.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_relational_backfill.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_relations.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_resilience.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_rls_session_scope.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_schema_exists.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_session_advisory_lock.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_state_cache.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_subquery_filter_raw.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_subquery_in_filter.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_subquery_nested_expressions.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_supabase_auth.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_supabase_config.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_tls.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_typed_join_projection.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_typed_predicates.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_update_case_expression.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_update_subquery.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_update_with_rebase.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_upsert_default_leak.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_upsert_with_conflict.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_values_jsonb_decode.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_watched_lifecycle.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level1/test_write_retry_semantics.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level2/MODULE_README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level2/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level2/conftest.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level2/test_bulk_ops.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level2/test_cache_integration.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level2/test_crud.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level2/test_foreign_keys.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level2/test_m2m.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level2/test_manager.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level2/test_migrations_live.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level2/test_query_execution.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/level2/test_schema_diff.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/live_pooler_role.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project/.env.example +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project/README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project/generate.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project/generated/.gitkeep +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project/matrx_orm.yaml +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project/test_schema_generation.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project_desktop/.env.example +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project_desktop/README.md +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project_desktop/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project_desktop/client_example.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project_desktop/client_example.ts +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project_desktop/client_supabase_example.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/sample_project_desktop/server.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/entity_tests.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/test_base_generation.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/test_composite_pk_fk_generation.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/test_composite_unique_generation.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/test_dto_identity_generation.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/test_entity_capability_generation.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/test_enum_ordering.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/test_generate_schema.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/test_junction_analysis.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/test_multi_schema_output.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/test_sql_expression_defaults.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/test_table_relationships_query.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema/test_view_generation.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema_builder/test_array_default_parsing.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema_builder/test_focused_generation_plan.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/schema_builder/test_host_models_aggregator.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/__init__.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/conftest.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/test_cache_no_downgrade.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/test_capture_poison_proof.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/test_coalesce.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/test_dag.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/test_disk_spill_fallback.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/test_flush_individual_fallback.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/test_governed_write.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/test_managed.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/test_op_enqueue_site.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/test_reads.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/session/test_session.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/test_database_name_alias.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/test_db_functions.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/test_model_cls_refactor.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/test_no_blocking_asyncpg_tls.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/test_one_database.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/test_pooler_role_guard.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/test_secrets_battery.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/test_sql_param_casts.py +0 -0
- {matrx_orm-3.1.89 → matrx_orm-3.1.91}/tests/test_sync_twins_guard.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: matrx-orm
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.91
|
|
4
4
|
Summary: Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching
|
|
5
5
|
Project-URL: Homepage, https://github.com/AI-Matrix-Engine/aidream-current
|
|
6
6
|
Project-URL: Repository, https://github.com/AI-Matrix-Engine/aidream-current
|
|
@@ -25,7 +25,7 @@ Requires-Python: >=3.13
|
|
|
25
25
|
Requires-Dist: asyncpg>=0.31.0
|
|
26
26
|
Requires-Dist: cryptography>=43.0
|
|
27
27
|
Requires-Dist: gitpython>=3.1.40
|
|
28
|
-
Requires-Dist: matrx-utils>=2.0.
|
|
28
|
+
Requires-Dist: matrx-utils>=2.0.20
|
|
29
29
|
Requires-Dist: psycopg-pool>=3.2.5
|
|
30
30
|
Requires-Dist: psycopg[binary]>=3.2.5
|
|
31
31
|
Requires-Dist: python-dotenv>=1.0
|
|
@@ -494,6 +494,42 @@ class QueryExecutor:
|
|
|
494
494
|
# Main SQL builder
|
|
495
495
|
# ------------------------------------------------------------------
|
|
496
496
|
|
|
497
|
+
def _explicit_join_clauses(self, params: list[Any]) -> list[str]:
|
|
498
|
+
"""SQL for every ``QueryBuilder.join()`` on this query.
|
|
499
|
+
|
|
500
|
+
Extracted so COUNT can emit the SAME joins the SELECT does. It could
|
|
501
|
+
not, and a ``.join(...).count()`` produced
|
|
502
|
+
``SELECT COUNT(*) FROM base WHERE joined.col = $1`` — valid-looking SQL
|
|
503
|
+
that Postgres rejects with *missing FROM-clause entry*. Found 2026-08-20
|
|
504
|
+
via ``kg.entity.mentions``, which was dead on every call because its
|
|
505
|
+
total count is a joined count.
|
|
506
|
+
"""
|
|
507
|
+
clauses: list[str] = []
|
|
508
|
+
for j in self._full_query_dict.get("joins", []) or []:
|
|
509
|
+
j_model = j.get("model")
|
|
510
|
+
if j_model is None or not hasattr(j_model, "_meta"):
|
|
511
|
+
raise ValidationError(
|
|
512
|
+
model=self.model,
|
|
513
|
+
reason="join() requires a model class with _meta",
|
|
514
|
+
details={"join": j},
|
|
515
|
+
)
|
|
516
|
+
j_table = j_model._meta.qualified_table_name
|
|
517
|
+
j_type = (j.get("type") or "INNER").upper()
|
|
518
|
+
j_alias = j.get("alias")
|
|
519
|
+
j_on = j.get("on")
|
|
520
|
+
if not j_on:
|
|
521
|
+
raise ValidationError(
|
|
522
|
+
model=self.model,
|
|
523
|
+
reason="join() requires a non-empty `on` clause",
|
|
524
|
+
details={"join": j},
|
|
525
|
+
)
|
|
526
|
+
j_on_sql = j_on.as_sql(params, current_table=self._base_ref())
|
|
527
|
+
if j_alias:
|
|
528
|
+
clauses.append(f"{j_type} JOIN {j_table} AS {j_alias} ON {j_on_sql}")
|
|
529
|
+
else:
|
|
530
|
+
clauses.append(f"{j_type} JOIN {j_table} ON {j_on_sql}")
|
|
531
|
+
return clauses
|
|
532
|
+
|
|
497
533
|
def _build_query(self) -> tuple[str, list[Any]]:
|
|
498
534
|
"""Construct the SELECT SQL statement and bound parameter list."""
|
|
499
535
|
params: list[Any] = []
|
|
@@ -536,29 +572,7 @@ class QueryExecutor:
|
|
|
536
572
|
|
|
537
573
|
# 1b. Explicit JOIN clauses from QueryBuilder.join()
|
|
538
574
|
explicit_joins: list[dict[str, Any]] = self._full_query_dict.get("joins", [])
|
|
539
|
-
|
|
540
|
-
j_model = j.get("model")
|
|
541
|
-
if j_model is None or not hasattr(j_model, "_meta"):
|
|
542
|
-
raise ValidationError(
|
|
543
|
-
model=self.model,
|
|
544
|
-
reason="join() requires a model class with _meta",
|
|
545
|
-
details={"join": j},
|
|
546
|
-
)
|
|
547
|
-
j_table = j_model._meta.qualified_table_name
|
|
548
|
-
j_type = (j.get("type") or "INNER").upper()
|
|
549
|
-
j_alias = j.get("alias")
|
|
550
|
-
j_on = j.get("on")
|
|
551
|
-
if not j_on:
|
|
552
|
-
raise ValidationError(
|
|
553
|
-
model=self.model,
|
|
554
|
-
reason="join() requires a non-empty `on` clause",
|
|
555
|
-
details={"join": j},
|
|
556
|
-
)
|
|
557
|
-
j_on = j_on.as_sql(params, current_table=self._base_ref())
|
|
558
|
-
if j_alias:
|
|
559
|
-
join_clauses.append(f"{j_type} JOIN {j_table} AS {j_alias} ON {j_on}")
|
|
560
|
-
else:
|
|
561
|
-
join_clauses.append(f"{j_type} JOIN {j_table} ON {j_on}")
|
|
575
|
+
join_clauses.extend(self._explicit_join_clauses(params))
|
|
562
576
|
|
|
563
577
|
# 2. Regular columns
|
|
564
578
|
# When the caller lists an annotated alias in .values() (e.g. after
|
|
@@ -1550,18 +1564,33 @@ class QueryExecutor:
|
|
|
1550
1564
|
return instances[0] if instances else None
|
|
1551
1565
|
return self._make(results[0])
|
|
1552
1566
|
|
|
1553
|
-
|
|
1554
|
-
"""COUNT(*)
|
|
1567
|
+
def _build_count_query(self) -> tuple[str, list[Any]]:
|
|
1568
|
+
"""SQL + params for ``COUNT(*)`` over the current query.
|
|
1569
|
+
|
|
1570
|
+
Separate from :meth:`count` so the emission is testable without a
|
|
1571
|
+
database — the join bug below shipped precisely because nothing could
|
|
1572
|
+
assert on this string.
|
|
1573
|
+
"""
|
|
1555
1574
|
params: list[Any] = []
|
|
1556
1575
|
from_target = self._from_target(params)
|
|
1576
|
+
# JOINs belong to the count as much as to the select — a WHERE that
|
|
1577
|
+
# references a joined table is unrunnable without them.
|
|
1578
|
+
join_clauses = self._explicit_join_clauses(params)
|
|
1557
1579
|
where_clause, where_params = self._extract_where_clause()
|
|
1558
1580
|
if where_clause and params:
|
|
1559
1581
|
where_clause = _shift_param_refs(where_clause, len(params))
|
|
1560
1582
|
params.extend(where_params)
|
|
1561
1583
|
|
|
1562
1584
|
count_sql = f"SELECT COUNT(*) as count FROM {from_target}"
|
|
1585
|
+
if join_clauses:
|
|
1586
|
+
count_sql += " " + " ".join(join_clauses)
|
|
1563
1587
|
if where_clause:
|
|
1564
1588
|
count_sql += f" WHERE {where_clause}"
|
|
1589
|
+
return count_sql, params
|
|
1590
|
+
|
|
1591
|
+
async def count(self) -> int:
|
|
1592
|
+
"""COUNT(*) for the current WHERE clause."""
|
|
1593
|
+
count_sql, params = self._build_count_query()
|
|
1565
1594
|
|
|
1566
1595
|
try:
|
|
1567
1596
|
statement_timeout = self._full_query_dict.get("timeout")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "matrx-orm"
|
|
3
|
-
version = "3.1.
|
|
3
|
+
version = "3.1.91"
|
|
4
4
|
description = "Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "MIT" }
|
|
@@ -41,7 +41,7 @@ dependencies = [
|
|
|
41
41
|
"gitpython>=3.1.40",
|
|
42
42
|
"psycopg[binary]>=3.2.5",
|
|
43
43
|
"psycopg-pool>=3.2.5",
|
|
44
|
-
"matrx-utils>=2.0.
|
|
44
|
+
"matrx-utils>=2.0.20",
|
|
45
45
|
"pyyaml>=6.0.3",
|
|
46
46
|
"python-dotenv>=1.0",
|
|
47
47
|
"cryptography>=43.0",
|
|
@@ -18,7 +18,7 @@ the RAG ORM cleanup plan:
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
import pytest
|
|
21
|
-
from matrx_orm import ColumnComparison, F
|
|
21
|
+
from matrx_orm import ColumnComparison, Compare, F
|
|
22
22
|
from matrx_orm.core.base import Model, ModelMeta
|
|
23
23
|
from matrx_orm.core.expressions import Count, Min, Sum
|
|
24
24
|
from matrx_orm.core.fields import (
|
|
@@ -396,3 +396,56 @@ class TestGroupByBareValuesProjectsGroupedColumns:
|
|
|
396
396
|
assert "entity_id" in select_clause
|
|
397
397
|
assert "COUNT(id) AS n" in sql
|
|
398
398
|
assert "confidence" not in select_clause
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
class TestJoinedCountSqlEmission:
|
|
402
|
+
"""``count()`` must emit the SAME joins the select does.
|
|
403
|
+
|
|
404
|
+
Live defect (2026-08-20): it did not. ``kg.entity.mentions`` counts its
|
|
405
|
+
total through a join, so every call produced
|
|
406
|
+
``SELECT COUNT(*) FROM rag.kg_chunks WHERE rag.kg_chunk_entities.entity_id = $1``
|
|
407
|
+
and Postgres rejected it with *missing FROM-clause entry for table
|
|
408
|
+
"kg_chunk_entities"* — the node was dead on 100% of calls.
|
|
409
|
+
"""
|
|
410
|
+
|
|
411
|
+
def _joined_builder(self):
|
|
412
|
+
CE = _make_chunk_entity_model()
|
|
413
|
+
C = _make_chunk_model()
|
|
414
|
+
return (
|
|
415
|
+
QueryBuilder(C)
|
|
416
|
+
.join(
|
|
417
|
+
CE,
|
|
418
|
+
on=ColumnComparison(
|
|
419
|
+
F("rag.kg_chunk_entities.chunk_id"), "=", F("rag.kg_chunks.id")
|
|
420
|
+
),
|
|
421
|
+
)
|
|
422
|
+
.filter(
|
|
423
|
+
Compare(
|
|
424
|
+
F("rag.kg_chunk_entities.entity_id"),
|
|
425
|
+
"=",
|
|
426
|
+
"33333333-3333-3333-3333-333333333333",
|
|
427
|
+
)
|
|
428
|
+
)
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
def test_count_includes_the_join(self):
|
|
432
|
+
sql, params = QueryExecutor(self._joined_builder()._build_query())._build_count_query()
|
|
433
|
+
assert sql.startswith("SELECT COUNT(*) as count FROM rag.kg_chunks")
|
|
434
|
+
assert (
|
|
435
|
+
"INNER JOIN rag.kg_chunk_entities "
|
|
436
|
+
"ON rag.kg_chunk_entities.chunk_id = rag.kg_chunks.id" in sql
|
|
437
|
+
)
|
|
438
|
+
from_pos = sql.index("FROM rag.kg_chunks")
|
|
439
|
+
join_pos = sql.index("INNER JOIN rag.kg_chunk_entities")
|
|
440
|
+
where_pos = sql.index("WHERE")
|
|
441
|
+
assert from_pos < join_pos < where_pos
|
|
442
|
+
assert params[-1] == "33333333-3333-3333-3333-333333333333"
|
|
443
|
+
|
|
444
|
+
def test_count_without_a_join_is_unchanged(self):
|
|
445
|
+
O = _make_order_model()
|
|
446
|
+
qb = QueryBuilder(O).filter(status="paid")
|
|
447
|
+
sql, params = QueryExecutor(qb._build_query())._build_count_query()
|
|
448
|
+
assert "JOIN" not in sql
|
|
449
|
+
assert sql.startswith("SELECT COUNT(*) as count FROM ")
|
|
450
|
+
assert "orders" in sql
|
|
451
|
+
assert params == ["paid"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|