matrx-orm 3.1.99__tar.gz → 3.1.100__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 (347) hide show
  1. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/PKG-INFO +1 -1
  2. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/catalog.py +61 -1
  3. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/FEATURE.md +4 -0
  4. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/extended/app_error_handler.py +12 -2
  5. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/query/executor.py +23 -16
  6. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/pyproject.toml +1 -1
  7. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_exceptions.py +15 -0
  8. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/.gitignore +0 -0
  9. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/AGENTS.md +0 -0
  10. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/BASE_CLASS_METHODS.md +0 -0
  11. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/CLAUDE.md +0 -0
  12. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/MODEL_API.md +0 -0
  13. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/README.md +0 -0
  14. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/database/orm/extended/managers/ai_model_base.py +0 -0
  15. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/docs/migrations.md +0 -0
  16. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/FEATURE.md +0 -0
  17. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/MODULE_README.md +0 -0
  18. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/__init__.py +0 -0
  19. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/adapters/MODULE_README.md +0 -0
  20. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/adapters/__init__.py +0 -0
  21. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/adapters/async_postgresql.py +0 -0
  22. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/adapters/base_adapter.py +0 -0
  23. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/adapters/postgresql.py +0 -0
  24. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
  25. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/adapters/supabase_adapter.py +0 -0
  26. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/admin/FEATURE.md +0 -0
  27. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/admin/__init__.py +0 -0
  28. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/admin/router.py +0 -0
  29. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/api/__init__.py +0 -0
  30. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/api/auth.py +0 -0
  31. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/api/config.py +0 -0
  32. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/api/handlers.py +0 -0
  33. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/api/protocol.py +0 -0
  34. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/api/server.py +0 -0
  35. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/associations.py +0 -0
  36. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/cache_debug.py +0 -0
  37. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/catalog_sql.py +0 -0
  38. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/client/MODULE_README.md +0 -0
  39. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/client/__init__.py +0 -0
  40. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/client/postgres_connection.py +0 -0
  41. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/client/postgrest.py +0 -0
  42. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/client/supabase_auth.py +0 -0
  43. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/client/supabase_config.py +0 -0
  44. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/client/supabase_manager.py +0 -0
  45. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/EXTENDED-TASK.md +0 -0
  46. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/MODULE_README.md +0 -0
  47. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
  48. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/TASKS.md +0 -0
  49. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/__init__.py +0 -0
  50. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/async_db_manager.py +0 -0
  51. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/base.py +0 -0
  52. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/config.py +0 -0
  53. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/connections.py +0 -0
  54. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/db_function.py +0 -0
  55. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/diagnostics.py +0 -0
  56. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/expressions.py +0 -0
  57. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/extended.py +0 -0
  58. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/fields.py +0 -0
  59. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/introspection.py +0 -0
  60. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/listen.py +0 -0
  61. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/loop_filters.py +0 -0
  62. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/model_dto.py +0 -0
  63. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/model_view.py +0 -0
  64. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/one_database.py +0 -0
  65. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/paginator.py +0 -0
  66. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/pool_maintenance.py +0 -0
  67. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/pool_watch.py +0 -0
  68. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/pooler_role.py +0 -0
  69. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/pydantic_bridge.py +0 -0
  70. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/registry.py +0 -0
  71. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/relations.py +0 -0
  72. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/resilience.py +0 -0
  73. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/rls_session.py +0 -0
  74. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/signals.py +0 -0
  75. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/tls.py +0 -0
  76. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/transaction.py +0 -0
  77. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/types.py +0 -0
  78. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/core/write_queue.py +0 -0
  79. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/entity.py +0 -0
  80. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/error_handling.py +0 -0
  81. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/exceptions.py +0 -0
  82. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/extended/__init__.py +0 -0
  83. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/identity_rule.py +0 -0
  84. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/local_sqlite.py +0 -0
  85. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/middleware/__init__.py +0 -0
  86. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/middleware/base.py +0 -0
  87. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/migrations/MODULE_README.md +0 -0
  88. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/migrations/__init__.py +0 -0
  89. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/migrations/cli.py +0 -0
  90. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/migrations/ddl.py +0 -0
  91. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/migrations/diff.py +0 -0
  92. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/migrations/executor.py +0 -0
  93. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/migrations/integration.py +0 -0
  94. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/migrations/loader.py +0 -0
  95. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/migrations/operations.py +0 -0
  96. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/migrations/state.py +0 -0
  97. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/migrations/table_filter.py +0 -0
  98. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/FEATURE.md +0 -0
  99. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/MODULE_README.md +0 -0
  100. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/__init__.py +0 -0
  101. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/bulk_update_values.py +0 -0
  102. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/conflict.py +0 -0
  103. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/conflict_writes.py +0 -0
  104. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/create.py +0 -0
  105. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/db_functions.py +0 -0
  106. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/delete.py +0 -0
  107. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/dynamic_admin.py +0 -0
  108. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/dynamic_crud.py +0 -0
  109. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/graph_walk.py +0 -0
  110. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/latest_rows.py +0 -0
  111. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/queue_claim.py +0 -0
  112. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/read.py +0 -0
  113. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/relational_backfill.py +0 -0
  114. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/staging_load.py +0 -0
  115. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/operations/update.py +0 -0
  116. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/platform_db.py +0 -0
  117. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/py.typed +0 -0
  118. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/python_sql/MODULE_README.md +0 -0
  119. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/python_sql/__init__.py +0 -0
  120. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/python_sql/db_objects.py +0 -0
  121. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
  122. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
  123. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/query/FEATURE.md +0 -0
  124. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/query/MODULE_README.md +0 -0
  125. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/query/__init__.py +0 -0
  126. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/query/builder.py +0 -0
  127. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/FEATURE.md +0 -0
  128. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/MODULE_README.md +0 -0
  129. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/__init__.py +0 -0
  130. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/code_handler.py +0 -0
  131. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/codegen_writer.py +0 -0
  132. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/columns.py +0 -0
  133. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/common.py +0 -0
  134. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/diff_preview.py +0 -0
  135. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
  136. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/generator.py +0 -0
  137. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
  138. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
  139. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
  140. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
  141. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/package_wiring.py +0 -0
  142. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/relationships.py +0 -0
  143. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/runner.py +0 -0
  144. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/schema.py +0 -0
  145. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/schema_manager.py +0 -0
  146. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/tables.py +0 -0
  147. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/schema_builder/views.py +0 -0
  148. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/secrets_battery/FEATURE.md +0 -0
  149. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/secrets_battery/__init__.py +0 -0
  150. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/secrets_battery/attachments.py +0 -0
  151. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/secrets_battery/crypto.py +0 -0
  152. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/secrets_battery/items.py +0 -0
  153. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/secrets_battery/model.py +0 -0
  154. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/secrets_battery/org_service.py +0 -0
  155. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/secrets_battery/service.py +0 -0
  156. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/README.md +0 -0
  157. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/__init__.py +0 -0
  158. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/coalesce.py +0 -0
  159. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/dag.py +0 -0
  160. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/errors.py +0 -0
  161. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/fallback.py +0 -0
  162. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/flush.py +0 -0
  163. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/lifecycle.py +0 -0
  164. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/managed.py +0 -0
  165. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/op.py +0 -0
  166. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/reads.py +0 -0
  167. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/session.py +0 -0
  168. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/session/telemetry.py +0 -0
  169. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/sql_executor/MODULE_README.md +0 -0
  170. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/sql_executor/__init__.py +0 -0
  171. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/sql_executor/executor.py +0 -0
  172. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/sql_executor/queries.py +0 -0
  173. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/sql_executor/registry.py +0 -0
  174. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/sql_executor/types.py +0 -0
  175. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/sql_executor/utils.py +0 -0
  176. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/state.py +0 -0
  177. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/utils/__init__.py +0 -0
  178. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/utils/sql_utils.py +0 -0
  179. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/matrx_orm/utils/type_converters.py +0 -0
  180. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/scripts/git-branches.sh +0 -0
  181. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/scripts/publish.sh +0 -0
  182. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/scripts/release.sh +0 -0
  183. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/MODULE_README.md +0 -0
  184. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/__init__.py +0 -0
  185. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/conftest.py +0 -0
  186. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/MODULE_README.md +0 -0
  187. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/__init__.py +0 -0
  188. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_admin_db_columns.py +0 -0
  189. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_admin_response_rendering.py +0 -0
  190. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_admin_search_negation.py +0 -0
  191. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_admin_search_sentinels.py +0 -0
  192. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_advisory_lock.py +0 -0
  193. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_agent_message.py +0 -0
  194. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_api_auth.py +0 -0
  195. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_api_config.py +0 -0
  196. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_api_handlers.py +0 -0
  197. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_api_protocol.py +0 -0
  198. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_array_agg_order_by.py +0 -0
  199. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_associations.py +0 -0
  200. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_bulk_hydration_offload.py +0 -0
  201. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_bulk_update_by_pk.py +0 -0
  202. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
  203. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_cache_debug.py +0 -0
  204. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_call_function.py +0 -0
  205. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_case_when.py +0 -0
  206. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_catalog.py +0 -0
  207. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_composite_pk_filter.py +0 -0
  208. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_composite_pk_write_paths.py +0 -0
  209. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_config.py +0 -0
  210. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_conflict_target.py +0 -0
  211. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_conflict_writes.py +0 -0
  212. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_connection_codecs.py +0 -0
  213. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_connection_poison_guard.py +0 -0
  214. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_connection_primitives.py +0 -0
  215. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_count_composite_distinct.py +0 -0
  216. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_db_function_field.py +0 -0
  217. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_ddl_generator.py +0 -0
  218. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_derived_table.py +0 -0
  219. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_dirty_tracking.py +0 -0
  220. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_dynamic_crud.py +0 -0
  221. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
  222. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_expression_primitives.py +0 -0
  223. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_fields.py +0 -0
  224. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
  225. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_from_alias.py +0 -0
  226. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_fts.py +0 -0
  227. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_func_expression_args.py +0 -0
  228. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_graph_walk.py +0 -0
  229. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_having_annotate_alias.py +0 -0
  230. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
  231. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_introspect_rls_policies.py +0 -0
  232. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_join_and_aggregate.py +0 -0
  233. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_latest_rows.py +0 -0
  234. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_listen_notify.py +0 -0
  235. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_local_sqlite.py +0 -0
  236. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_managed_write_guard.py +0 -0
  237. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_matrx_entity.py +0 -0
  238. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_migration_diff_types.py +0 -0
  239. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_migration_loader.py +0 -0
  240. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_model_instance.py +0 -0
  241. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_model_meta.py +0 -0
  242. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_optimistic_concurrency.py +0 -0
  243. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_order_by_expression.py +0 -0
  244. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_parameter_name_hydration.py +0 -0
  245. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_patch_jsonb_path.py +0 -0
  246. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_pool_holder_census.py +0 -0
  247. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_pool_loop_recreation.py +0 -0
  248. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_pool_maintenance.py +0 -0
  249. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_postgrest_filters.py +0 -0
  250. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_pydantic_bridge.py +0 -0
  251. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_query_builder.py +0 -0
  252. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_query_error_detail.py +0 -0
  253. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_query_executor_sql.py +0 -0
  254. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_query_timeout.py +0 -0
  255. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
  256. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_queue_claim.py +0 -0
  257. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_registry.py +0 -0
  258. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_registry_multi_database.py +0 -0
  259. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_registry_multi_schema.py +0 -0
  260. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_relational_backfill.py +0 -0
  261. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_relations.py +0 -0
  262. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_resilience.py +0 -0
  263. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_rls_session_scope.py +0 -0
  264. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_schema_exists.py +0 -0
  265. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_session_advisory_lock.py +0 -0
  266. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_state_cache.py +0 -0
  267. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_subquery_filter_raw.py +0 -0
  268. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_subquery_in_filter.py +0 -0
  269. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_subquery_nested_expressions.py +0 -0
  270. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_supabase_auth.py +0 -0
  271. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_supabase_config.py +0 -0
  272. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_tls.py +0 -0
  273. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_typed_join_projection.py +0 -0
  274. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_typed_predicates.py +0 -0
  275. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_update_case_expression.py +0 -0
  276. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_update_subquery.py +0 -0
  277. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_update_with_rebase.py +0 -0
  278. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_upsert_default_leak.py +0 -0
  279. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_upsert_with_conflict.py +0 -0
  280. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_values_jsonb_decode.py +0 -0
  281. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_watched_lifecycle.py +0 -0
  282. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level1/test_write_retry_semantics.py +0 -0
  283. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level2/MODULE_README.md +0 -0
  284. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level2/__init__.py +0 -0
  285. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level2/conftest.py +0 -0
  286. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level2/test_bulk_ops.py +0 -0
  287. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level2/test_cache_integration.py +0 -0
  288. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level2/test_crud.py +0 -0
  289. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level2/test_foreign_keys.py +0 -0
  290. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level2/test_m2m.py +0 -0
  291. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level2/test_manager.py +0 -0
  292. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level2/test_migrations_live.py +0 -0
  293. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level2/test_query_execution.py +0 -0
  294. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/level2/test_schema_diff.py +0 -0
  295. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/live_pooler_role.py +0 -0
  296. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project/.env.example +0 -0
  297. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project/README.md +0 -0
  298. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project/__init__.py +0 -0
  299. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project/generate.py +0 -0
  300. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project/generated/.gitkeep +0 -0
  301. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project/matrx_orm.yaml +0 -0
  302. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project/test_schema_generation.py +0 -0
  303. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project_desktop/.env.example +0 -0
  304. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project_desktop/README.md +0 -0
  305. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project_desktop/__init__.py +0 -0
  306. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project_desktop/client_example.py +0 -0
  307. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project_desktop/client_example.ts +0 -0
  308. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project_desktop/client_supabase_example.py +0 -0
  309. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/sample_project_desktop/server.py +0 -0
  310. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/entity_tests.py +0 -0
  311. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/test_base_generation.py +0 -0
  312. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/test_composite_pk_fk_generation.py +0 -0
  313. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/test_composite_unique_generation.py +0 -0
  314. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/test_dto_identity_generation.py +0 -0
  315. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/test_entity_capability_generation.py +0 -0
  316. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/test_enum_ordering.py +0 -0
  317. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/test_generate_schema.py +0 -0
  318. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/test_junction_analysis.py +0 -0
  319. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/test_multi_schema_output.py +0 -0
  320. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/test_sql_expression_defaults.py +0 -0
  321. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/test_table_relationships_query.py +0 -0
  322. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema/test_view_generation.py +0 -0
  323. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema_builder/test_array_default_parsing.py +0 -0
  324. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema_builder/test_focused_generation_plan.py +0 -0
  325. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/schema_builder/test_host_models_aggregator.py +0 -0
  326. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/__init__.py +0 -0
  327. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/conftest.py +0 -0
  328. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/test_cache_no_downgrade.py +0 -0
  329. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/test_capture_poison_proof.py +0 -0
  330. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/test_coalesce.py +0 -0
  331. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/test_dag.py +0 -0
  332. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/test_disk_spill_fallback.py +0 -0
  333. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/test_flush_individual_fallback.py +0 -0
  334. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/test_governed_write.py +0 -0
  335. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/test_managed.py +0 -0
  336. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/test_op_enqueue_site.py +0 -0
  337. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/test_reads.py +0 -0
  338. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/session/test_session.py +0 -0
  339. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/test_database_name_alias.py +0 -0
  340. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/test_db_functions.py +0 -0
  341. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/test_model_cls_refactor.py +0 -0
  342. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/test_no_blocking_asyncpg_tls.py +0 -0
  343. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/test_one_database.py +0 -0
  344. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/test_pooler_role_guard.py +0 -0
  345. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/test_secrets_battery.py +0 -0
  346. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/tests/test_sql_param_casts.py +0 -0
  347. {matrx_orm-3.1.99 → matrx_orm-3.1.100}/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.99
3
+ Version: 3.1.100
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
@@ -30,6 +30,7 @@ __all__ = [
30
30
  "column_privileges",
31
31
  "entity_capability_state",
32
32
  "event_trigger_state",
33
+ "function_source",
33
34
  ]
34
35
 
35
36
 
@@ -320,6 +321,47 @@ async def first_party_function_bodies(
320
321
  return [{"name": str(row["name"]), "source": str(row["source"] or "")} for row in rows]
321
322
 
322
323
 
324
+ async def function_source(
325
+ database: str,
326
+ *,
327
+ schema: str,
328
+ name: str,
329
+ ) -> str | None:
330
+ """Return one function's live ``prosrc``, or ``None`` when it does not exist.
331
+
332
+ The single-function twin of :func:`first_party_function_bodies`, which only
333
+ answers "give me everything". A truth-vs-code guard almost always wants ONE
334
+ named function — "is the floor constant in the trigger still the one Python
335
+ believes?" — and every such guard was hand-writing the same `pg_proc` join
336
+ outside the ORM to get it (`aidream/scripts/check_crawl_cadence_floor_parity.py`
337
+ was doing exactly that, over its own raw `asyncpg.connect`).
338
+
339
+ ``None`` distinguishes "not installed" from "installed and empty", which is
340
+ the distinction those guards act on: a missing enforcement function is a
341
+ louder finding than a disagreeing one.
342
+
343
+ Overloads: returns the FIRST body by ``oid``. A guard that cares about a
344
+ specific overload should assert on the signature separately — this helper
345
+ deliberately does not try to encode overload resolution.
346
+ """
347
+ rows = await _query(
348
+ database,
349
+ """
350
+ SELECT p.prosrc AS source
351
+ FROM pg_proc p
352
+ JOIN pg_namespace n ON n.oid = p.pronamespace
353
+ WHERE n.nspname = $1 AND p.proname = $2
354
+ ORDER BY p.oid
355
+ LIMIT 1
356
+ """,
357
+ schema,
358
+ name,
359
+ )
360
+ if not rows:
361
+ return None
362
+ return str(rows[0]["source"] or "")
363
+
364
+
323
365
  async def first_party_view_definitions(
324
366
  database: str,
325
367
  *,
@@ -462,9 +504,27 @@ async def org_backstop_coverage(database: str) -> list[dict[str, Any]]:
462
504
  -- `_inherit_org`), and `plan` uses `_stamp_from_node`. Keying on
463
505
  -- the trigger name reported correctly-backstopped children as
464
506
  -- DRIFT (D232 §C, 2026-08-21).
507
+ --
508
+ -- FOUR, not three: `platform.stamp_run_org` (10 run tables) is a
509
+ -- real backstop -- owner -> personal org, unattended -> SYSTEM
510
+ -- org, else RAISE -- so it cannot leave organization_id NULL. It
511
+ -- was missing here, and this gate is BLOCKING. Green only by
512
+ -- luck: 8 of its 10 tables also carry `_stamp_org_default`, and
513
+ -- the 2 that rely on it alone (docproc.page_extraction_runs,
514
+ -- legal.ingest_runs) have no owner column, so has_owner is false
515
+ -- and the gate skips them. Add a `created_by` to either and this
516
+ -- gate would have blocked every release over a correctly
517
+ -- backstopped table (matrx-frontend D241, 2026-08-21).
518
+ --
519
+ -- Adding a name here is a RULING, not housekeeping: read the
520
+ -- function body first and confirm it cannot RETURN with a NULL
521
+ -- organization_id. An accept-list that is too short blocks good
522
+ -- releases; one that is too long silently passes a table whose
523
+ -- org-forgetting write will 500 in production.
465
524
  AND bp.proname IN ('_stamp_org_default',
466
525
  'inherit_org_from_parent',
467
- '_stamp_from_node')) AS has_backstop
526
+ '_stamp_from_node',
527
+ 'stamp_run_org')) AS has_backstop
468
528
  FROM pg_catalog_columns c
469
529
  JOIN pg_catalog_tables tb
470
530
  ON tb.table_schema=c.table_schema AND tb.table_name=c.table_name
@@ -170,6 +170,10 @@ can never disagree about who the blocker was.
170
170
  Verified against the live database: 2026-08-21.
171
171
 
172
172
  ## Change log
173
+ - 2026-08-22: Preserved the deepest Postgres SQLSTATE on `AppError` as a
174
+ lightweight classification (without retaining traceback frames), so an
175
+ idempotent transactional owner can recover from a database role transition
176
+ without parsing rendered error prose.
173
177
  - 2026-08-21: Added the idle-in-transaction ceiling on every pool and the
174
178
  `long_transactions` blocker-naming primitive (feedback c72a32ac).
175
179
 
@@ -1,9 +1,9 @@
1
- from collections.abc import Mapping
1
+ from collections.abc import Callable, Mapping
2
2
  from functools import wraps
3
3
  import inspect
4
4
  import sys
5
5
  import traceback
6
- from typing import Callable, Protocol, TypeVar, runtime_checkable
6
+ from typing import Protocol, TypeVar, runtime_checkable
7
7
 
8
8
  DEFAULT_CLIENT_MESSAGE = "Oops. Something went wrong. Please reload the page and try again."
9
9
 
@@ -85,6 +85,16 @@ class AppError(Exception):
85
85
  self._inner_banner: str | None = (
86
86
  str(original) if _inner_has_custom_banner(original) else None
87
87
  )
88
+ # Keep the stable Postgres classification without retaining the
89
+ # frame-heavy exception object. Callers that own an idempotent,
90
+ # transactional unit can use this to recover from a database role
91
+ # transition (for example SQLSTATE 25006) without parsing prose.
92
+ if original is not None:
93
+ from matrx_orm.exceptions import describe_db_exception
94
+
95
+ self.db_sqlstate: str | None = describe_db_exception(original).sqlstate
96
+ else:
97
+ self.db_sqlstate = None
88
98
  super().__init__(message)
89
99
 
90
100
  def __str__(self) -> str:
@@ -1527,11 +1527,18 @@ class QueryExecutor:
1527
1527
  # report "0 deleted" even when rows were removed.
1528
1528
  sql += " RETURNING 1"
1529
1529
 
1530
- try:
1531
- result = await self.db.execute_write(sql, *where_params)
1532
- return len(result)
1533
- except DatabaseError as e:
1534
- raise DatabaseError(f"Delete failed: {str(e)}") from e
1530
+ # A DatabaseError from execute_write is ALREADY the typed, formatted ORM
1531
+ # error (PermissionDeniedError, ForeignKeyViolationError, ...). Catching
1532
+ # it here and re-raising the BASE class downgraded every one of them to a
1533
+ # generic DatabaseError, so a caller could no longer tell "permission
1534
+ # denied" from "a child row still references this" — and `str(e)` folded
1535
+ # the original's ANSI-coloured multi-line block into a message. Found by
1536
+ # `scripts/_verify_batch_access_model.py`, whose whole job is asserting a
1537
+ # user's DELETE is refused for the RIGHT reason: `except
1538
+ # PermissionDeniedError` silently missed it and the probe reported the
1539
+ # write had SUCCEEDED. Let the typed error through untouched.
1540
+ result = await self.db.execute_write(sql, *where_params)
1541
+ return len(result)
1535
1542
 
1536
1543
  # ------------------------------------------------------------------
1537
1544
  # SELECT terminal methods
@@ -1592,17 +1599,17 @@ class QueryExecutor:
1592
1599
  """COUNT(*) for the current WHERE clause."""
1593
1600
  count_sql, params = self._build_count_query()
1594
1601
 
1595
- try:
1596
- statement_timeout = self._full_query_dict.get("timeout")
1597
- if statement_timeout is not None:
1598
- result = await self.db.execute_query(
1599
- count_sql, *params, statement_timeout=statement_timeout
1600
- )
1601
- else:
1602
- result = await self.db.execute_query(count_sql, *params)
1603
- return result[0]["count"] if result else 0
1604
- except DatabaseError as e:
1605
- raise DatabaseError(f"Count query failed: {str(e)}") from e
1602
+ # Same downgrade as delete() above: the DatabaseError arriving here is
1603
+ # already the typed, formatted ORM error, and re-raising the base class
1604
+ # destroyed that type for every caller. Let it through untouched.
1605
+ statement_timeout = self._full_query_dict.get("timeout")
1606
+ if statement_timeout is not None:
1607
+ result = await self.db.execute_query(
1608
+ count_sql, *params, statement_timeout=statement_timeout
1609
+ )
1610
+ else:
1611
+ result = await self.db.execute_query(count_sql, *params)
1612
+ return result[0]["count"] if result else 0
1606
1613
 
1607
1614
  async def exists(self) -> bool:
1608
1615
  """EXISTS check for the current WHERE clause."""
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "matrx-orm"
3
- version = "3.1.99"
3
+ version = "3.1.100"
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" }
@@ -2,6 +2,7 @@
2
2
 
3
3
  import matrx_orm.exceptions as exceptions_module
4
4
 
5
+ from matrx_orm.extended.app_error_handler import AppError
5
6
  from matrx_orm.exceptions import (
6
7
  AdapterError,
7
8
  CacheError,
@@ -43,6 +44,20 @@ class _FakePgError(Exception):
43
44
  return {"code": self.sqlstate, **self._fields}
44
45
 
45
46
 
47
+ def test_app_error_preserves_sqlstate_without_retaining_original() -> None:
48
+ driver_error = _FakePgError("25006", {"message": "read only"})
49
+ wrapped = QueryError(
50
+ message="write failed",
51
+ details={"operation": "update", "error": "read only"},
52
+ )
53
+ wrapped.__cause__ = driver_error
54
+
55
+ error = AppError(message="write failed", original=wrapped)
56
+
57
+ assert error.db_sqlstate == "25006"
58
+ assert not hasattr(error, "original")
59
+
60
+
46
61
  class TestORMExceptionBase:
47
62
  def test_caller_capture_never_reads_source_files(self, monkeypatch):
48
63
  def fail_if_called():
File without changes
File without changes
File without changes
File without changes
File without changes