matrx-orm 3.1.197__tar.gz → 3.1.199__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.
Files changed (425) hide show
  1. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/CHANGELOG.md +6 -0
  2. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/PKG-INFO +1 -1
  3. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/__init__.py +2 -0
  4. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/FEATURE.md +11 -0
  5. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/async_db_manager.py +20 -3
  6. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/db_function.py +38 -17
  7. matrx_orm-3.1.199/matrx_orm/core/statement_ceiling.py +170 -0
  8. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/pyproject.toml +1 -1
  9. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_call_function.py +21 -3
  10. matrx_orm-3.1.199/tests/test_statement_ceiling_warning.py +128 -0
  11. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/.gitignore +0 -0
  12. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/AGENTS.md +0 -0
  13. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/BASE_CLASS_METHODS.md +0 -0
  14. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/CLAUDE.md +0 -0
  15. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/MODEL_API.md +0 -0
  16. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/README.md +0 -0
  17. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/database/orm/extended/managers/ai_model_base.py +0 -0
  18. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/docs/migrations.md +0 -0
  19. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/FEATURE.md +0 -0
  20. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/MODULE_README.md +0 -0
  21. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/adapters/MODULE_README.md +0 -0
  22. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/adapters/__init__.py +0 -0
  23. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/adapters/async_postgresql.py +0 -0
  24. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/adapters/base_adapter.py +0 -0
  25. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
  26. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/adapters/supabase_adapter.py +0 -0
  27. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/admin/FEATURE.md +0 -0
  28. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/admin/__init__.py +0 -0
  29. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/admin/router.py +0 -0
  30. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/api/__init__.py +0 -0
  31. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/api/auth.py +0 -0
  32. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/api/config.py +0 -0
  33. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/api/handlers.py +0 -0
  34. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/api/protocol.py +0 -0
  35. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/api/server.py +0 -0
  36. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/associations.py +0 -0
  37. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/cache_debug.py +0 -0
  38. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/catalog.py +0 -0
  39. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/catalog_sql.py +0 -0
  40. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/client/MODULE_README.md +0 -0
  41. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/client/__init__.py +0 -0
  42. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/client/postgres_connection.py +0 -0
  43. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/client/postgrest.py +0 -0
  44. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/client/supabase_auth.py +0 -0
  45. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/client/supabase_config.py +0 -0
  46. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/client/supabase_manager.py +0 -0
  47. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/EXTENDED-TASK.md +0 -0
  48. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/MODULE_README.md +0 -0
  49. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
  50. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/TASKS.md +0 -0
  51. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/__init__.py +0 -0
  52. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/admin_lane.py +0 -0
  53. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/base.py +0 -0
  54. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/config.py +0 -0
  55. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/connections.py +0 -0
  56. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/diagnostics.py +0 -0
  57. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/expressions.py +0 -0
  58. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/extended.py +0 -0
  59. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/fields.py +0 -0
  60. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/introspection.py +0 -0
  61. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/listen.py +0 -0
  62. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/loop_filters.py +0 -0
  63. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/model_dto.py +0 -0
  64. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/model_view.py +0 -0
  65. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/one_database.py +0 -0
  66. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/paginator.py +0 -0
  67. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/pool_maintenance.py +0 -0
  68. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/pool_watch.py +0 -0
  69. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/pooler_role.py +0 -0
  70. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/pydantic_bridge.py +0 -0
  71. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/registry.py +0 -0
  72. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/relations.py +0 -0
  73. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/resilience.py +0 -0
  74. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/rls_session.py +0 -0
  75. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/session_context.py +0 -0
  76. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/signals.py +0 -0
  77. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/tls.py +0 -0
  78. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/transaction.py +0 -0
  79. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/types.py +0 -0
  80. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/write_queue.py +0 -0
  81. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/core/write_retry.py +0 -0
  82. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/entity.py +0 -0
  83. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/error_handling.py +0 -0
  84. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/exceptions.py +0 -0
  85. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/extended/__init__.py +0 -0
  86. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/extended/app_error_handler.py +0 -0
  87. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/identity_rule.py +0 -0
  88. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/local_sqlite.py +0 -0
  89. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/middleware/__init__.py +0 -0
  90. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/middleware/base.py +0 -0
  91. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/migrations/MODULE_README.md +0 -0
  92. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/migrations/__init__.py +0 -0
  93. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/migrations/cli.py +0 -0
  94. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/migrations/ddl.py +0 -0
  95. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/migrations/diff.py +0 -0
  96. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/migrations/executor.py +0 -0
  97. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/migrations/integration.py +0 -0
  98. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/migrations/loader.py +0 -0
  99. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/migrations/operations.py +0 -0
  100. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/migrations/state.py +0 -0
  101. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/migrations/table_filter.py +0 -0
  102. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/no_org_assignment.py +0 -0
  103. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/FEATURE.md +0 -0
  104. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/MODULE_README.md +0 -0
  105. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/__init__.py +0 -0
  106. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/bulk_update_values.py +0 -0
  107. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/catalog_select.py +0 -0
  108. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/conflict.py +0 -0
  109. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/conflict_writes.py +0 -0
  110. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/create.py +0 -0
  111. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/db_functions.py +0 -0
  112. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/delete.py +0 -0
  113. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/dynamic_admin.py +0 -0
  114. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/dynamic_crud.py +0 -0
  115. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/graph_walk.py +0 -0
  116. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/latest_rows.py +0 -0
  117. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/queue_claim.py +0 -0
  118. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/read.py +0 -0
  119. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/relational_backfill.py +0 -0
  120. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/staging_load.py +0 -0
  121. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/operations/update.py +0 -0
  122. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/platform_access.py +0 -0
  123. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/platform_db.py +0 -0
  124. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/py.typed +0 -0
  125. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/pytest_live_db_guard.py +0 -0
  126. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/pytest_lock_guard.py +0 -0
  127. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/pytest_plugin.py +0 -0
  128. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/python_sql/MODULE_README.md +0 -0
  129. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/python_sql/__init__.py +0 -0
  130. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/python_sql/db_objects.py +0 -0
  131. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
  132. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
  133. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/query/FEATURE.md +0 -0
  134. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/query/MODULE_README.md +0 -0
  135. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/query/__init__.py +0 -0
  136. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/query/builder.py +0 -0
  137. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/query/executor.py +0 -0
  138. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/resources/__init__.py +0 -0
  139. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/resources/additional-assigners-2026-09-12.json +0 -0
  140. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/resources/org_assignment_trigger_baseline.json +0 -0
  141. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/FEATURE.md +0 -0
  142. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/MODULE_README.md +0 -0
  143. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/__init__.py +0 -0
  144. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/code_handler.py +0 -0
  145. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/codegen_writer.py +0 -0
  146. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/columns.py +0 -0
  147. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/common.py +0 -0
  148. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/diff_preview.py +0 -0
  149. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
  150. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/generator.py +0 -0
  151. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
  152. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
  153. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
  154. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
  155. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/package_wiring.py +0 -0
  156. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/relationships.py +0 -0
  157. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/runner.py +0 -0
  158. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/schema.py +0 -0
  159. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/schema_manager.py +0 -0
  160. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/tables.py +0 -0
  161. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/schema_builder/views.py +0 -0
  162. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/FEATURE.md +0 -0
  163. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/__init__.py +0 -0
  164. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/attachments.py +0 -0
  165. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/backup_restore.py +0 -0
  166. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/crypto.py +0 -0
  167. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/host_authorization.py +0 -0
  168. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/items.py +0 -0
  169. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/model.py +0 -0
  170. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/mutation_receipts.py +0 -0
  171. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/native_enable.py +0 -0
  172. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/native_lifecycle.py +0 -0
  173. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/native_passkeys.py +0 -0
  174. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/native_source.py +0 -0
  175. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/org_service.py +0 -0
  176. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/org_vault_gate.py +0 -0
  177. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/service.py +0 -0
  178. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/secrets_battery/vault_history.py +0 -0
  179. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/README.md +0 -0
  180. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/__init__.py +0 -0
  181. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/coalesce.py +0 -0
  182. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/dag.py +0 -0
  183. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/errors.py +0 -0
  184. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/fallback.py +0 -0
  185. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/flush.py +0 -0
  186. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/lifecycle.py +0 -0
  187. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/managed.py +0 -0
  188. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/op.py +0 -0
  189. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/reads.py +0 -0
  190. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/session.py +0 -0
  191. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/session/telemetry.py +0 -0
  192. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/sql_executor/MODULE_README.md +0 -0
  193. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/sql_executor/__init__.py +0 -0
  194. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/sql_executor/executor.py +0 -0
  195. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/sql_executor/queries.py +0 -0
  196. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/sql_executor/registry.py +0 -0
  197. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/sql_executor/types.py +0 -0
  198. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/sql_executor/utils.py +0 -0
  199. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/state.py +0 -0
  200. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/utils/__init__.py +0 -0
  201. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/utils/sql_utils.py +0 -0
  202. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/utils/type_converters.py +0 -0
  203. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/matrx_orm/write_actor.py +0 -0
  204. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/scripts/git-branches.sh +0 -0
  205. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/scripts/publish.sh +0 -0
  206. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/scripts/release.sh +0 -0
  207. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/MODULE_README.md +0 -0
  208. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/__init__.py +0 -0
  209. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/conftest.py +0 -0
  210. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/MODULE_README.md +0 -0
  211. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/__init__.py +0 -0
  212. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_adapter_registry.py +0 -0
  213. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_admin_db_columns.py +0 -0
  214. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_admin_response_rendering.py +0 -0
  215. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_admin_search_negation.py +0 -0
  216. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_admin_search_sentinels.py +0 -0
  217. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_advisory_lock.py +0 -0
  218. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_agent_message.py +0 -0
  219. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_api_auth.py +0 -0
  220. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_api_config.py +0 -0
  221. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_api_handlers.py +0 -0
  222. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_api_protocol.py +0 -0
  223. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_array_agg_order_by.py +0 -0
  224. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_association_trigger_actor_naming.py +0 -0
  225. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_associations.py +0 -0
  226. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_associations_wiring.py +0 -0
  227. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_bulk_hydration_offload.py +0 -0
  228. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_bulk_update_by_pk.py +0 -0
  229. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
  230. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_cache_debug.py +0 -0
  231. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_case_when.py +0 -0
  232. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_catalog.py +0 -0
  233. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_column_scoped_writes.py +0 -0
  234. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_committed_row_guard.py +0 -0
  235. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_composite_pk_filter.py +0 -0
  236. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_composite_pk_write_paths.py +0 -0
  237. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_config.py +0 -0
  238. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_conflict_target.py +0 -0
  239. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_conflict_writes.py +0 -0
  240. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_connection_codecs.py +0 -0
  241. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_connection_poison_guard.py +0 -0
  242. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_connection_primitives.py +0 -0
  243. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_count_composite_distinct.py +0 -0
  244. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_count_limit_param_leak.py +0 -0
  245. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_db_function_field.py +0 -0
  246. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_ddl_generator.py +0 -0
  247. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_deadlock_retry.py +0 -0
  248. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_derived_table.py +0 -0
  249. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_dirty_tracking.py +0 -0
  250. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_dynamic_crud.py +0 -0
  251. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_exceptions.py +0 -0
  252. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
  253. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_expression_primitives.py +0 -0
  254. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_fields.py +0 -0
  255. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
  256. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_fk_cycle_resolution.py +0 -0
  257. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_from_alias.py +0 -0
  258. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_fts.py +0 -0
  259. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_func_expression_args.py +0 -0
  260. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_graph_walk.py +0 -0
  261. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_having_annotate_alias.py +0 -0
  262. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
  263. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_introspect_rls_policies.py +0 -0
  264. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_join_and_aggregate.py +0 -0
  265. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_latest_rows.py +0 -0
  266. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_listen_notify.py +0 -0
  267. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_local_sqlite.py +0 -0
  268. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_lock_contention_retry.py +0 -0
  269. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_managed_write_guard.py +0 -0
  270. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_matrx_entity.py +0 -0
  271. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_migration_diff_types.py +0 -0
  272. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_migration_loader.py +0 -0
  273. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_model_instance.py +0 -0
  274. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_model_meta.py +0 -0
  275. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_optimistic_concurrency.py +0 -0
  276. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_order_by_expression.py +0 -0
  277. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_org_assignment_inventory.py +0 -0
  278. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_orm_banners_are_client_safe.py +0 -0
  279. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_parameter_name_hydration.py +0 -0
  280. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_patch_jsonb_path.py +0 -0
  281. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_percentile_cont.py +0 -0
  282. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_persisted_count.py +0 -0
  283. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_person_scoped_session_bypasses_shared_cache.py +0 -0
  284. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_pool_create_never_wedges.py +0 -0
  285. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_pool_holder_census.py +0 -0
  286. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_pool_loop_recreation.py +0 -0
  287. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_pool_maintenance.py +0 -0
  288. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_postgrest_filters.py +0 -0
  289. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_pydantic_bridge.py +0 -0
  290. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_query_builder.py +0 -0
  291. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_query_error_detail.py +0 -0
  292. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_query_executor_sql.py +0 -0
  293. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_query_timeout.py +0 -0
  294. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
  295. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_queue_claim.py +0 -0
  296. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_read_connection_retry.py +0 -0
  297. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_registry.py +0 -0
  298. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_registry_multi_database.py +0 -0
  299. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_registry_multi_schema.py +0 -0
  300. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_relational_backfill.py +0 -0
  301. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_relations.py +0 -0
  302. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_resilience.py +0 -0
  303. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_rls_session_scope.py +0 -0
  304. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_schema_exists.py +0 -0
  305. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_session_advisory_lock.py +0 -0
  306. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_standalone_write_session_context.py +0 -0
  307. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_state_cache.py +0 -0
  308. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_subquery_filter_raw.py +0 -0
  309. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_subquery_in_filter.py +0 -0
  310. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_subquery_nested_expressions.py +0 -0
  311. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_supabase_auth.py +0 -0
  312. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_supabase_config.py +0 -0
  313. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_tls.py +0 -0
  314. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_transaction_database_identity.py +0 -0
  315. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_typed_join_projection.py +0 -0
  316. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_typed_predicates.py +0 -0
  317. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_update_case_expression.py +0 -0
  318. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_update_subquery.py +0 -0
  319. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_update_with_rebase.py +0 -0
  320. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_upsert_default_leak.py +0 -0
  321. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_upsert_with_conflict.py +0 -0
  322. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_values_jsonb_decode.py +0 -0
  323. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_watched_lifecycle.py +0 -0
  324. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_write_queue_deadline.py +0 -0
  325. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level1/test_write_retry_semantics.py +0 -0
  326. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/MODULE_README.md +0 -0
  327. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/__init__.py +0 -0
  328. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/conftest.py +0 -0
  329. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/test_bulk_ops.py +0 -0
  330. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/test_cache_integration.py +0 -0
  331. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/test_crud.py +0 -0
  332. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/test_foreign_keys.py +0 -0
  333. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/test_m2m.py +0 -0
  334. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/test_manager.py +0 -0
  335. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/test_migrations_live.py +0 -0
  336. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/test_query_execution.py +0 -0
  337. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/test_schema_diff.py +0 -0
  338. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/level2/verify_committed_row_guard_pg17.py +0 -0
  339. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/live_pooler_role.py +0 -0
  340. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/native_source_cases.py +0 -0
  341. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/native_source_oracle.rs +0 -0
  342. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project/.env.example +0 -0
  343. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project/README.md +0 -0
  344. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project/__init__.py +0 -0
  345. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project/generate.py +0 -0
  346. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project/generated/.gitkeep +0 -0
  347. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project/matrx_orm.yaml +0 -0
  348. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project/test_schema_generation.py +0 -0
  349. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project_desktop/.env.example +0 -0
  350. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project_desktop/README.md +0 -0
  351. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project_desktop/__init__.py +0 -0
  352. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project_desktop/client_example.py +0 -0
  353. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project_desktop/client_example.ts +0 -0
  354. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project_desktop/client_supabase_example.py +0 -0
  355. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/sample_project_desktop/server.py +0 -0
  356. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/entity_tests.py +0 -0
  357. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_base_generation.py +0 -0
  358. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_composite_pk_fk_generation.py +0 -0
  359. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_composite_unique_generation.py +0 -0
  360. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_dto_identity_generation.py +0 -0
  361. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_entity_capability_generation.py +0 -0
  362. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_enum_ordering.py +0 -0
  363. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_generate_schema.py +0 -0
  364. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_junction_analysis.py +0 -0
  365. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_multi_schema_output.py +0 -0
  366. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_schema_analysis.py +0 -0
  367. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_sql_expression_defaults.py +0 -0
  368. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_table_relationships_query.py +0 -0
  369. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema/test_view_generation.py +0 -0
  370. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema_builder/test_array_default_parsing.py +0 -0
  371. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema_builder/test_focused_generation_plan.py +0 -0
  372. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema_builder/test_host_models_aggregator.py +0 -0
  373. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/schema_builder/test_never_filter_columns.py +0 -0
  374. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/__init__.py +0 -0
  375. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/conftest.py +0 -0
  376. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_a_failed_capture_still_names_the_failure.py +0 -0
  377. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_cache_no_downgrade.py +0 -0
  378. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_capture_poison_proof.py +0 -0
  379. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_coalesce.py +0 -0
  380. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_dag.py +0 -0
  381. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_disk_spill_fallback.py +0 -0
  382. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_flush_individual_fallback.py +0 -0
  383. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_governed_write.py +0 -0
  384. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_live_db_guard_plugin.py +0 -0
  385. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_managed.py +0 -0
  386. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_op_enqueue_site.py +0 -0
  387. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_reads.py +0 -0
  388. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_record_error_bounded_insert.py +0 -0
  389. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_record_error_storm.py +0 -0
  390. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_session.py +0 -0
  391. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/session/test_spill_guard_plugin.py +0 -0
  392. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_array_arg_element_type.py +0 -0
  393. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_attachment_mutation_serialization.py +0 -0
  394. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_backup_alias_conflict.py +0 -0
  395. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_backup_history_restore.py +0 -0
  396. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_backup_restore_live.py +0 -0
  397. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_call_function_as.py +0 -0
  398. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_call_function_none_mode.py +0 -0
  399. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_composite_fk_is_not_a_column_fk.py +0 -0
  400. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_database_name_alias.py +0 -0
  401. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_db_functions.py +0 -0
  402. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_dsn_password_masking.py +0 -0
  403. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_dynamic_select_unregistered.py +0 -0
  404. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_immutable_insert_or_exact_verify.py +0 -0
  405. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_keyed_digest.py +0 -0
  406. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_model_cls_refactor.py +0 -0
  407. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_native_enable.py +0 -0
  408. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_native_lifecycle.py +0 -0
  409. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_native_lifecycle_fences.py +0 -0
  410. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_native_passkey_receipts.py +0 -0
  411. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_native_source.py +0 -0
  412. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_no_blocking_asyncpg_tls.py +0 -0
  413. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_one_database.py +0 -0
  414. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_order_by_desc_nulls_last.py +0 -0
  415. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_org_vault_gate.py +0 -0
  416. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_pooler_role_guard.py +0 -0
  417. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_secret_audit_names_its_organization.py +0 -0
  418. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_secrets_battery.py +0 -0
  419. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_secrets_minting_keys.py +0 -0
  420. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_shared_lock_guard.py +0 -0
  421. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_sql_param_casts.py +0 -0
  422. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_sync_twins_guard.py +0 -0
  423. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_update_result_truthiness.py +0 -0
  424. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_user_visible_lookup.py +0 -0
  425. {matrx_orm-3.1.197 → matrx_orm-3.1.199}/tests/test_vault_aggregate_recovery_stateful.py +0 -0
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ - **Fix: a driver timeout longer than the server's statement ceiling screams.**
6
+ `call_function` / `call_function_as` / `execute_query` read the connection's
7
+ effective `statement_timeout` and log one WARNING per call site when the
8
+ `timeout=` passed is longer (Postgres cancels at the ceiling regardless). New
9
+ `SERVER_CEILING` sentinel: `timeout=SERVER_CEILING` waits the connection's
10
+ ceiling + 1 s. Guard: `tests/test_statement_ceiling_warning.py`.
5
11
  - **Fix (security): the by-id cache never answers inside `rls_session`.** The
6
12
  StateManager cache is shared process-wide and keyed by primary key alone, so a
7
13
  row fetched for one person (or the privileged process) was served to another
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: matrx-orm
3
- Version: 3.1.197
3
+ Version: 3.1.199
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
@@ -31,6 +31,7 @@ from .core.config import (
31
31
  resolve_pool_mode,
32
32
  )
33
33
  from .core.db_function import ArrayArg, TypedArg, call_function, call_function_as, call_function_sync
34
+ from .core.statement_ceiling import SERVER_CEILING
34
35
  from .core.connections import (
35
36
  create_external_pool,
36
37
  get_registered_pool,
@@ -472,6 +473,7 @@ __all__ = [
472
473
  "install_asyncpg_idle_close_filter",
473
474
  # ── DB-side function calls (RPC) ──────────────────────────────────────────
474
475
  "call_function",
476
+ "SERVER_CEILING",
475
477
  "call_function_as",
476
478
  "call_function_sync",
477
479
  "MatrxEntity",
@@ -126,6 +126,16 @@ for scalar, row-set, discarded-result, and active-transaction calls. Callers can
126
126
  therefore distinguish an ambiguous in-flight RPC from a pool-acquire failure and
127
127
  must choose replay policy explicitly.
128
128
 
129
+ **A driver `timeout=` never outlives the server's statement ceiling silently.**
130
+ `call_function(..., timeout=N)` / `call_function_as` / `execute_query(statement_timeout=N)`
131
+ set only asyncpg's wait; Postgres still cancels at the connection's `statement_timeout`
132
+ (the `postgres` role carries 30 s since aidream migration 0919, or a `SET LOCAL` from
133
+ `rls_session`). `core/statement_ceiling.py` reads that ceiling from the connection
134
+ (`pg_settings`, once per database for pool connections, live inside a transaction) and
135
+ logs one WARNING per call site when N exceeds it. `timeout=SERVER_CEILING` resolves to
136
+ the ceiling + 1 s, for a bounded statement that needs more than the pool's 10 s default.
137
+ Static twin: aidream `scripts/check_driver_timeout_vs_statement_ceiling.py`.
138
+
129
139
  **Opt-in transient retries can be bounded and desynchronized.**
130
140
  `retry_on_transient(..., jitter_ratio=...)` retains deterministic exponential
131
141
  backoff by default; a caller recovering a replay-safe lock conflict can add at
@@ -329,6 +339,7 @@ can never disagree about who the blocker was.
329
339
  Verified against the live database: 2026-08-21.
330
340
 
331
341
  ## Change log
342
+ - 2026-09-30: `statement_ceiling.py` — a driver timeout above the server's statement ceiling is logged once per call site; `SERVER_CEILING` sentinel. ~19 callers passed 60-600 s under the 30 s `postgres` ceiling (the nightly keyword classifier was cancelled at 30 s for eight days).
332
343
  - 2026-09-12 (later): ONE retry mechanism. Two independent lock-retry
333
344
  implementations for the same class landed hours apart — a `LockContentionError`
334
345
  + constant-budget loop inside `execute_query`, and a `TransientTransactionError`
@@ -24,6 +24,7 @@ from matrx_orm.core.pooler_role import (
24
24
  assert_no_session_role_change,
25
25
  reprove_empty_read,
26
26
  )
27
+ from matrx_orm.core.statement_ceiling import resolve_driver_timeout
27
28
  from matrx_orm.core.tls import resolve_asyncpg_ssl
28
29
  from matrx_orm.exceptions import (
29
30
  AdapterError,
@@ -1286,7 +1287,9 @@ class AsyncDatabaseManager:
1286
1287
  per-call ``fetch(..., timeout=)`` and overrides the pool's
1287
1288
  ``command_timeout`` for this statement only — the QueryBuilder
1288
1289
  ``.timeout()`` seam for known-long reads. ``None`` keeps the pool
1289
- default.
1290
+ default. It is a DRIVER timeout: the server's own statement_timeout
1291
+ still cancels at its ceiling, and a value above it is logged once per
1292
+ call site (``matrx_orm.core.statement_ceiling``).
1290
1293
  """
1291
1294
  # Layer 1 of the pooler-role defence: SQL that would leave a borrowed role
1292
1295
  # on a shared server connection never reaches Postgres. See
@@ -1302,6 +1305,13 @@ class AsyncDatabaseManager:
1302
1305
  tx_conn = None
1303
1306
 
1304
1307
  if tx_conn is not None:
1308
+ statement_timeout = await resolve_driver_timeout(
1309
+ tx_conn,
1310
+ database=config_name,
1311
+ timeout=statement_timeout,
1312
+ operation="execute_query",
1313
+ in_transaction=True,
1314
+ )
1305
1315
  try:
1306
1316
  results = await tx_conn.fetch(query, *args, timeout=statement_timeout)
1307
1317
  return [dict(r) for r in results]
@@ -1411,8 +1421,15 @@ class AsyncDatabaseManager:
1411
1421
  read_attempt = 0
1412
1422
  while True:
1413
1423
  async with cls.get_connection(config_name, timeout) as conn:
1424
+ driver_timeout = await resolve_driver_timeout(
1425
+ conn,
1426
+ database=config_name,
1427
+ timeout=statement_timeout,
1428
+ operation="execute_query",
1429
+ in_transaction=False,
1430
+ )
1414
1431
  try:
1415
- results = await conn.fetch(query, *args, timeout=statement_timeout)
1432
+ results = await conn.fetch(query, *args, timeout=driver_timeout)
1416
1433
  if read_attempt > 0:
1417
1434
  logger.warning(
1418
1435
  "[read-retry] SELECT HEALED on attempt %d after a "
@@ -1435,7 +1452,7 @@ class AsyncDatabaseManager:
1435
1452
  config_name=config_name,
1436
1453
  query=query,
1437
1454
  args=args,
1438
- statement_timeout=statement_timeout,
1455
+ statement_timeout=driver_timeout,
1439
1456
  normalize=_normalize_record,
1440
1457
  )
1441
1458
  if true_rows is not None:
@@ -69,6 +69,7 @@ from dataclasses import dataclass
69
69
  from typing import Any, Literal
70
70
 
71
71
  from matrx_orm.core.async_db_manager import AsyncDatabaseManager
72
+ from matrx_orm.core.statement_ceiling import DriverTimeout, resolve_driver_timeout
72
73
  from matrx_orm.core.transaction import get_active_connection
73
74
  from matrx_orm.core.write_retry import (
74
75
  is_confidently_aborted_lock_contention,
@@ -191,14 +192,14 @@ def _validate_identifier(name: str, kind: str) -> None:
191
192
  )
192
193
 
193
194
 
194
- async def call_function( # noqa: ASYNC109 — maps onto asyncpg's per-call timeout
195
+ async def call_function(
195
196
  database: str,
196
197
  schema: str,
197
198
  function: str,
198
199
  *args: Any,
199
200
  mode: Literal["scalar", "none", "rows"] = "scalar",
200
201
  field: str | None = None,
201
- timeout: float | None = None,
202
+ timeout: DriverTimeout = None, # noqa: ASYNC109 — maps onto asyncpg's per-call timeout
202
203
  ) -> Any:
203
204
  """Call ``schema.function(args...)`` and return its value.
204
205
 
@@ -222,9 +223,15 @@ async def call_function( # noqa: ASYNC109 — maps onto asyncpg's per-call time
222
223
  timeout: per-call driver timeout in seconds, overriding the pool's
223
224
  ``command_timeout`` (default 10s). Use for known-slow analytical
224
225
  functions (aggregation RPCs) that legitimately exceed the pool
225
- default; ``None`` keeps the pool's setting. A server-side
226
- ``statement_timeout`` (e.g. from ``rls_session``) still applies
227
- independently.
226
+ default; ``None`` keeps the pool's setting. It does NOT lengthen
227
+ the server's ``statement_timeout`` (the role default — 30 s for
228
+ ``postgres`` since aidream migration 0919 — or a ``SET LOCAL`` from
229
+ ``rls_session``): Postgres still cancels at that ceiling, and a
230
+ timeout above it is logged once per call site as a WARNING
231
+ (``matrx_orm.core.statement_ceiling``). Pass
232
+ ``timeout=SERVER_CEILING`` for a bounded statement that needs more
233
+ than the pool default: it waits exactly as long as the server
234
+ allows, read from the connection.
228
235
 
229
236
  Returns:
230
237
  The scalar value (mode="scalar"), ``None`` (mode="none"), or
@@ -257,21 +264,28 @@ async def call_function( # noqa: ASYNC109 — maps onto asyncpg's per-call time
257
264
  else:
258
265
  sql = f"SELECT {call}"
259
266
 
260
- async def invoke(conn: Any) -> Any:
267
+ async def invoke(conn: Any, *, in_transaction: bool = False) -> Any:
268
+ driver_timeout = await resolve_driver_timeout(
269
+ conn,
270
+ database=database,
271
+ timeout=timeout,
272
+ operation=f"call_function {schema}.{function}",
273
+ in_transaction=in_transaction,
274
+ )
261
275
  try:
262
276
  if mode == "none":
263
- await conn.execute(sql, *bound_args, timeout=timeout)
277
+ await conn.execute(sql, *bound_args, timeout=driver_timeout)
264
278
  return None
265
279
  if mode == "rows":
266
- rows = await conn.fetch(sql, *bound_args, timeout=timeout)
280
+ rows = await conn.fetch(sql, *bound_args, timeout=driver_timeout)
267
281
  return [dict(r) for r in rows]
268
- return await conn.fetchval(sql, *bound_args, timeout=timeout)
282
+ return await conn.fetchval(sql, *bound_args, timeout=driver_timeout)
269
283
  except TimeoutError as exc:
270
284
  raise QueryTimeoutError(
271
285
  operation=f"call_function:{schema}.{function}",
272
286
  query=sql,
273
287
  args=bound_args,
274
- timeout=timeout,
288
+ timeout=driver_timeout,
275
289
  original_error=exc,
276
290
  ) from None
277
291
 
@@ -281,7 +295,7 @@ async def call_function( # noqa: ASYNC109 — maps onto asyncpg's per-call time
281
295
  # transaction's owner can redo the unit, so no retry here — the refusal is
282
296
  # typed the same way ``execute_query``'s transaction branch types it.
283
297
  try:
284
- return await invoke(active_conn)
298
+ return await invoke(active_conn, in_transaction=True)
285
299
  except Exception as exc:
286
300
  if not is_confidently_aborted_lock_contention(exc):
287
301
  raise
@@ -306,14 +320,14 @@ async def call_function( # noqa: ASYNC109 — maps onto asyncpg's per-call time
306
320
  )
307
321
 
308
322
 
309
- async def call_function_as( # noqa: ASYNC109 — maps onto asyncpg's per-call timeout
323
+ async def call_function_as(
310
324
  actor_id: str,
311
325
  database: str,
312
326
  schema: str,
313
327
  function: str,
314
328
  *args: Any,
315
329
  mode: Literal["scalar", "none", "rows"] = "scalar",
316
- timeout: float | None = None,
330
+ timeout: DriverTimeout = None, # noqa: ASYNC109 — maps onto asyncpg's per-call timeout
317
331
  ) -> Any:
318
332
  """Call ``schema.function(args...)`` on the server connection AS ``actor_id``.
319
333
 
@@ -354,13 +368,20 @@ async def call_function_as( # noqa: ASYNC109 — maps onto asyncpg's per-call t
354
368
 
355
369
  async def _attempt() -> Any:
356
370
  async with AsyncDatabaseManager.get_connection(database) as conn:
371
+ driver_timeout = await resolve_driver_timeout(
372
+ conn,
373
+ database=database,
374
+ timeout=timeout,
375
+ operation=f"call_function_as {schema}.{function}",
376
+ in_transaction=False,
377
+ )
357
378
  if mode == "none":
358
- await conn.execute(sql, *bound_args, timeout=timeout)
379
+ await conn.execute(sql, *bound_args, timeout=driver_timeout)
359
380
  return None
360
381
  if mode == "rows":
361
- rows = await conn.fetch(sql, *bound_args, timeout=timeout)
382
+ rows = await conn.fetch(sql, *bound_args, timeout=driver_timeout)
362
383
  return [dict(r) for r in rows]
363
- return await conn.fetchval(sql, *bound_args, timeout=timeout)
384
+ return await conn.fetchval(sql, *bound_args, timeout=driver_timeout)
364
385
 
365
386
  return await run_with_lock_retry(_attempt, config_name=database, query=sql, args=bound_args)
366
387
 
@@ -372,7 +393,7 @@ def call_function_sync(
372
393
  *args: Any,
373
394
  mode: Literal["scalar", "none", "rows"] = "scalar",
374
395
  field: str | None = None,
375
- timeout: float | None = None,
396
+ timeout: DriverTimeout = None,
376
397
  ) -> Any:
377
398
  """Synchronous twin of :func:`call_function`. Sync contexts only."""
378
399
  import asyncio
@@ -0,0 +1,170 @@
1
+ """A driver ``timeout=`` longer than the server's statement ceiling is a lie — say so.
2
+
3
+ ``call_function(..., timeout=300)`` and ``execute_query(..., statement_timeout=300)`` set
4
+ the DRIVER's (asyncpg's) per-call timeout. They do not, and cannot, lengthen the
5
+ server's own ``statement_timeout``: that comes from the connecting role's default
6
+ (``ALTER ROLE … SET statement_timeout``), the pool's server settings, or a
7
+ ``SET [LOCAL] statement_timeout`` issued as its own statement before the call
8
+ (``rls_session`` / ``acting_as_user(statement_timeout_ms=…)``). When the driver
9
+ timeout is the longer of the two, the caller believes it has minutes and Postgres
10
+ cancels it at the ceiling (``57014 canceling statement due to statement timeout``).
11
+
12
+ That is what froze the approved nightly keyword classifier for eight days in
13
+ September 2026: aidream migration 0919 capped the ``postgres`` role at 30 s on
14
+ purpose, and a job that passed ``timeout=300`` for a 55–128 s statement was cut at
15
+ 30 s every night.
16
+
17
+ This module reads the ceiling from its one source of truth — the connection's own
18
+ effective ``statement_timeout`` (``pg_settings.setting``, milliseconds), which already
19
+ folds in the role default, the pool settings and any ``SET LOCAL`` — and logs a
20
+ WARNING, once per call site, when the driver timeout exceeds it. It never blocks the
21
+ call: the statement still runs exactly as before. The static twin is
22
+ ``aidream/scripts/check_driver_timeout_vs_statement_ceiling.py``.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import logging
28
+ import sys
29
+ from typing import Any
30
+
31
+ logger = logging.getLogger("matrx_orm.statement_ceiling")
32
+
33
+ _CEILING_SQL = "SELECT setting::bigint FROM pg_settings WHERE name = 'statement_timeout'"
34
+
35
+ #: Pool connections share one effective ceiling per database (role default + pool
36
+ #: settings), so it is read once per database. A transaction connection may carry a
37
+ #: ``SET LOCAL``, so it is always read live.
38
+ _POOL_CEILING_MS: dict[str, int] = {}
39
+ _WARNED: set[tuple[str, str, int]] = set()
40
+ _UNREADABLE_WARNED: set[str] = set()
41
+
42
+ _ORM_PACKAGE_MARKER = "/matrx_orm/"
43
+
44
+
45
+ def _caller_site() -> str:
46
+ """The first frame outside matrx_orm — the code that chose the timeout."""
47
+ frame = sys._getframe(1)
48
+ while frame is not None:
49
+ filename = frame.f_code.co_filename
50
+ if _ORM_PACKAGE_MARKER not in filename.replace("\\", "/") and "/asyncio/" not in filename:
51
+ return f"{filename}:{frame.f_lineno} ({frame.f_code.co_name})"
52
+ frame = frame.f_back
53
+ return "<unknown caller>"
54
+
55
+
56
+ async def _read_ceiling_ms(conn: Any, *, database: str, in_transaction: bool) -> int | None:
57
+ if not in_transaction and database in _POOL_CEILING_MS:
58
+ return _POOL_CEILING_MS[database]
59
+ try:
60
+ value = await conn.fetchval(_CEILING_SQL)
61
+ ceiling_ms = int(value)
62
+ except Exception as exc: # noqa: BLE001 — the check must never break the call it guards
63
+ if database not in _UNREADABLE_WARNED:
64
+ _UNREADABLE_WARNED.add(database)
65
+ logger.warning(
66
+ "[matrx-orm] statement-ceiling check could not read statement_timeout on %r "
67
+ "(%s: %s); driver timeouts on this database are unchecked until it can. "
68
+ "Remedy: make pg_settings readable to the pool role.",
69
+ database,
70
+ type(exc).__name__,
71
+ exc,
72
+ )
73
+ return None
74
+ if not in_transaction:
75
+ _POOL_CEILING_MS[database] = ceiling_ms
76
+ return ceiling_ms
77
+
78
+
79
+ class ServerCeiling:
80
+ """Sentinel for ``timeout=``: wait exactly as long as the server itself allows.
81
+
82
+ For a statement that legitimately needs more than the pool's driver default
83
+ (``command_timeout``, 10 s) but is bounded under the server's ceiling: the driver
84
+ timeout is resolved per call from the connection's own ``statement_timeout`` plus
85
+ :data:`SERVER_CEILING_MARGIN_SECONDS`, so Postgres's ``57014`` — the true answer —
86
+ always arrives before the driver gives up, and no caller carries a second copy of
87
+ the ceiling as a number.
88
+ """
89
+
90
+ _instance: ServerCeiling | None = None
91
+
92
+ def __new__(cls) -> ServerCeiling:
93
+ if cls._instance is None:
94
+ cls._instance = super().__new__(cls)
95
+ return cls._instance
96
+
97
+ def __repr__(self) -> str:
98
+ return "SERVER_CEILING"
99
+
100
+
101
+ SERVER_CEILING = ServerCeiling()
102
+
103
+ #: How much longer than the server's ceiling the driver waits under ``SERVER_CEILING``,
104
+ #: so the server's cancellation (with its real error) is what the caller sees.
105
+ SERVER_CEILING_MARGIN_SECONDS = 1.0
106
+
107
+ DriverTimeout = float | ServerCeiling | None
108
+
109
+
110
+ async def resolve_driver_timeout(
111
+ conn: Any,
112
+ *,
113
+ database: str,
114
+ timeout: DriverTimeout, # noqa: ASYNC109 — the caller's asyncpg timeout, inspected, never awaited
115
+ operation: str,
116
+ in_transaction: bool,
117
+ ) -> float | None:
118
+ """The driver timeout to pass to asyncpg for this call — and a scream when it lies.
119
+
120
+ ``SERVER_CEILING`` resolves to the connection's ceiling plus the margin. A number
121
+ larger than the ceiling is passed through unchanged (the call is never blocked) and
122
+ logged once per call site as a WARNING naming the caller and the ceiling.
123
+ """
124
+ if timeout is None:
125
+ return None
126
+ if isinstance(timeout, ServerCeiling):
127
+ ceiling_ms = await _read_ceiling_ms(conn, database=database, in_transaction=in_transaction)
128
+ if ceiling_ms is None:
129
+ return None # unreadable — already announced by _read_ceiling_ms
130
+ if ceiling_ms <= 0:
131
+ key = ("<server-ceiling-unbounded>", database, 0)
132
+ if key not in _WARNED:
133
+ _WARNED.add(key)
134
+ logger.warning(
135
+ "[matrx-orm] %s asked for timeout=SERVER_CEILING on %r but this connection has "
136
+ "no statement_timeout (0); the pool's driver default applies instead. Remedy: "
137
+ "give the role or the session a statement_timeout.",
138
+ _caller_site(),
139
+ database,
140
+ )
141
+ return None
142
+ return ceiling_ms / 1000 + SERVER_CEILING_MARGIN_SECONDS
143
+ if timeout <= 0:
144
+ return timeout
145
+ ceiling_ms = await _read_ceiling_ms(conn, database=database, in_transaction=in_transaction)
146
+ if not ceiling_ms or ceiling_ms <= 0:
147
+ # 0 means Postgres enforces no statement ceiling on this connection.
148
+ return timeout
149
+ if timeout * 1000 <= ceiling_ms:
150
+ return timeout
151
+ site = _caller_site()
152
+ key = (site, database, ceiling_ms)
153
+ if key not in _WARNED:
154
+ _WARNED.add(key)
155
+ logger.warning(
156
+ f"[matrx-orm] DRIVER TIMEOUT OUTLIVES THE SERVER CEILING: {site} passes timeout={timeout:g}s "
157
+ f"to {operation} on {database!r}, but this connection's statement_timeout is "
158
+ f"{ceiling_ms / 1000:g}s — Postgres cancels the statement at {ceiling_ms / 1000:g}s "
159
+ f"(57014) no matter what the driver waits for. Remedy: bound the statement below the "
160
+ f"ceiling (split it per site/span) and pass timeout=SERVER_CEILING, or declare the "
161
+ f"server clock with rls_session/acting_as_user(statement_timeout_ms=...)."
162
+ )
163
+ return timeout
164
+
165
+
166
+ def reset_statement_ceiling_cache() -> None:
167
+ """Test seam: forget cached ceilings and already-warned call sites."""
168
+ _POOL_CEILING_MS.clear()
169
+ _WARNED.clear()
170
+ _UNREADABLE_WARNED.clear()
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "matrx-orm"
3
- version = "3.1.197"
3
+ version = "3.1.199"
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" }
@@ -9,7 +9,7 @@ they ever reach a query string; arguments are always bound parameters.
9
9
 
10
10
  from __future__ import annotations
11
11
 
12
- from unittest.mock import AsyncMock
12
+ from unittest.mock import AsyncMock, call
13
13
 
14
14
  import pytest
15
15
  from matrx_orm.core import transaction as tx_module
@@ -268,11 +268,29 @@ class TestConnectionAndDriverOptions:
268
268
  assert pool.databases == ["analytics"]
269
269
 
270
270
  async def test_per_call_timeout_reaches_the_driver(self, pool) -> None:
271
+ # A numeric timeout must inspect the server ceiling once per pooled
272
+ # database, then pass the caller's requested timeout through unchanged.
273
+ # Keep the ceiling lookup separate from the RPC assertion: both queries
274
+ # are required, but only the latter is the operation under test.
275
+ from matrx_orm.core.statement_ceiling import _CEILING_SQL, reset_statement_ceiling_cache
276
+
277
+ reset_statement_ceiling_cache()
278
+
279
+ async def fetchval(sql, *args, timeout=None):
280
+ if sql == _CEILING_SQL:
281
+ return 30_000
282
+ return "ok"
283
+
284
+ pool.conn.fetchval.side_effect = fetchval
271
285
  await call_function("db", "public", "slow_rollup", "org-1", timeout=45.0)
272
286
  await call_function("db", "public", "slow_reconcile", "org-1", mode="none", timeout=90.0)
273
- pool.conn.fetchval.assert_awaited_once_with(
274
- 'SELECT "public"."slow_rollup"($1)', "org-1", timeout=45.0
287
+ pool.conn.fetchval.assert_has_awaits(
288
+ [
289
+ call(_CEILING_SQL),
290
+ call('SELECT "public"."slow_rollup"($1)', "org-1", timeout=45.0),
291
+ ]
275
292
  )
293
+ assert pool.conn.fetchval.await_count == 2 # one cached ceiling read, one RPC
276
294
  pool.conn.execute.assert_awaited_once_with(
277
295
  'SELECT count(*) FROM "public"."slow_reconcile"($1)', "org-1", timeout=90.0
278
296
  )
@@ -0,0 +1,128 @@
1
+ """A driver ``timeout=`` above the server's statement ceiling must scream, once per site.
2
+
3
+ ``call_function(..., timeout=300)`` only sets asyncpg's wait. The 30 s role ceiling
4
+ (aidream migration 0919) still cancels the statement, which is how the nightly keyword
5
+ classifier froze for eight days in September 2026 without a word in any log.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ from contextlib import asynccontextmanager
12
+
13
+ import pytest
14
+
15
+ from matrx_orm.core import db_function
16
+ from matrx_orm.core.statement_ceiling import reset_statement_ceiling_cache
17
+
18
+
19
+ class _Conn:
20
+ def __init__(self, ceiling_ms: int) -> None:
21
+ self.ceiling_ms = ceiling_ms
22
+ self.ceiling_reads = 0
23
+ self.calls: list[str] = []
24
+
25
+ async def fetchval(self, sql, *args, timeout=None):
26
+ if "pg_settings" in sql:
27
+ self.ceiling_reads += 1
28
+ return self.ceiling_ms
29
+ self.calls.append(sql)
30
+ return 1
31
+
32
+
33
+ @pytest.fixture(autouse=True)
34
+ def _fresh_cache():
35
+ reset_statement_ceiling_cache()
36
+ yield
37
+ reset_statement_ceiling_cache()
38
+
39
+
40
+ def _patch(monkeypatch, conn: _Conn, *, active: bool = False) -> None:
41
+ @asynccontextmanager
42
+ async def _get_connection(database, timeout=10.0):
43
+ yield conn
44
+
45
+ monkeypatch.setattr(db_function, "get_active_connection", lambda: conn if active else None)
46
+ monkeypatch.setattr(db_function.AsyncDatabaseManager, "get_connection", _get_connection)
47
+
48
+
49
+ def _ceiling_warnings(caplog) -> list[str]:
50
+ return [r.getMessage() for r in caplog.records if "OUTLIVES THE SERVER CEILING" in r.getMessage()]
51
+
52
+
53
+ async def test_timeout_above_the_ceiling_warns_once_naming_caller_and_ceiling(monkeypatch, caplog):
54
+ conn = _Conn(ceiling_ms=30_000)
55
+ _patch(monkeypatch, conn)
56
+ caplog.set_level(logging.WARNING, logger="matrx_orm.statement_ceiling")
57
+
58
+ for _ in range(3):
59
+ assert await db_function.call_function("db", "seo", "slow_fn", timeout=300) == 1
60
+
61
+ warnings = _ceiling_warnings(caplog)
62
+ assert len(warnings) == 1, warnings
63
+ assert "test_statement_ceiling_warning.py" in warnings[0]
64
+ assert "timeout=300s" in warnings[0] and "statement_timeout is 30s" in warnings[0]
65
+ assert "seo.slow_fn" in warnings[0]
66
+ # The pool ceiling is read once per database, not once per call.
67
+ assert conn.ceiling_reads == 1
68
+ # The call itself still ran every time — the check never blocks.
69
+ assert len(conn.calls) == 3
70
+
71
+
72
+ async def test_timeout_within_the_ceiling_is_silent(monkeypatch, caplog):
73
+ conn = _Conn(ceiling_ms=30_000)
74
+ _patch(monkeypatch, conn)
75
+ caplog.set_level(logging.WARNING, logger="matrx_orm.statement_ceiling")
76
+
77
+ await db_function.call_function("db", "seo", "fast_fn", timeout=25)
78
+ await db_function.call_function("db", "seo", "fast_fn") # no timeout: nothing to read
79
+
80
+ assert _ceiling_warnings(caplog) == []
81
+ assert conn.ceiling_reads == 1
82
+
83
+
84
+ async def test_a_declared_server_clock_in_the_transaction_is_honoured(monkeypatch, caplog):
85
+ # rls_session/acting_as_user(statement_timeout_ms=120_000) issued SET LOCAL: the
86
+ # connection's live ceiling is 120 s, so a 120 s driver timeout is honest.
87
+ conn = _Conn(ceiling_ms=120_000)
88
+ _patch(monkeypatch, conn, active=True)
89
+ caplog.set_level(logging.WARNING, logger="matrx_orm.statement_ceiling")
90
+
91
+ await db_function.call_function("db", "seo", "long_fn", timeout=120)
92
+ await db_function.call_function("db", "seo", "long_fn", timeout=120)
93
+
94
+ assert _ceiling_warnings(caplog) == []
95
+ # A transaction connection may carry SET LOCAL, so it is read live every call.
96
+ assert conn.ceiling_reads == 2
97
+
98
+
99
+ async def test_zero_ceiling_means_unbounded_and_is_silent(monkeypatch, caplog):
100
+ conn = _Conn(ceiling_ms=0)
101
+ _patch(monkeypatch, conn)
102
+ caplog.set_level(logging.WARNING, logger="matrx_orm.statement_ceiling")
103
+
104
+ await db_function.call_function("db", "ops", "fn", timeout=600)
105
+
106
+ assert _ceiling_warnings(caplog) == []
107
+
108
+
109
+ async def test_server_ceiling_waits_exactly_as_long_as_the_server_allows(monkeypatch, caplog):
110
+ from matrx_orm import SERVER_CEILING
111
+ from matrx_orm.core.statement_ceiling import SERVER_CEILING_MARGIN_SECONDS
112
+
113
+ seen: list[float | None] = []
114
+
115
+ class _TimedConn(_Conn):
116
+ async def fetchval(self, sql, *args, timeout=None):
117
+ if "pg_settings" not in sql:
118
+ seen.append(timeout)
119
+ return await super().fetchval(sql, *args, timeout=timeout)
120
+
121
+ conn = _TimedConn(ceiling_ms=30_000)
122
+ _patch(monkeypatch, conn)
123
+ caplog.set_level(logging.WARNING, logger="matrx_orm.statement_ceiling")
124
+
125
+ await db_function.call_function("db", "seo", "bounded_fn", timeout=SERVER_CEILING)
126
+
127
+ assert seen == [30 + SERVER_CEILING_MARGIN_SECONDS]
128
+ assert _ceiling_warnings(caplog) == []
File without changes
File without changes
File without changes
File without changes
File without changes