matrx-orm 3.1.159__tar.gz → 3.1.161__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 (386) hide show
  1. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/BASE_CLASS_METHODS.md +14 -0
  2. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/PKG-INFO +2 -2
  3. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/__init__.py +12 -0
  4. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/adapters/MODULE_README.md +0 -29
  5. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/transaction.py +22 -0
  6. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/query/executor.py +11 -0
  7. matrx_orm-3.1.161/matrx_orm/write_actor.py +234 -0
  8. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/pyproject.toml +2 -2
  9. matrx_orm-3.1.159/matrx_orm/adapters/postgresql.py +0 -167
  10. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/.gitignore +0 -0
  11. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/AGENTS.md +0 -0
  12. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/CLAUDE.md +0 -0
  13. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/MODEL_API.md +0 -0
  14. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/README.md +0 -0
  15. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/database/orm/extended/managers/ai_model_base.py +0 -0
  16. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/docs/migrations.md +0 -0
  17. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/FEATURE.md +0 -0
  18. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/MODULE_README.md +0 -0
  19. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/adapters/__init__.py +0 -0
  20. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/adapters/async_postgresql.py +0 -0
  21. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/adapters/base_adapter.py +0 -0
  22. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
  23. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/adapters/supabase_adapter.py +0 -0
  24. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/admin/FEATURE.md +0 -0
  25. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/admin/__init__.py +0 -0
  26. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/admin/router.py +0 -0
  27. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/api/__init__.py +0 -0
  28. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/api/auth.py +0 -0
  29. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/api/config.py +0 -0
  30. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/api/handlers.py +0 -0
  31. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/api/protocol.py +0 -0
  32. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/api/server.py +0 -0
  33. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/associations.py +0 -0
  34. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/cache_debug.py +0 -0
  35. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/catalog.py +0 -0
  36. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/catalog_sql.py +0 -0
  37. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/client/MODULE_README.md +0 -0
  38. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/client/__init__.py +0 -0
  39. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/client/postgres_connection.py +0 -0
  40. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/client/postgrest.py +0 -0
  41. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/client/supabase_auth.py +0 -0
  42. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/client/supabase_config.py +0 -0
  43. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/client/supabase_manager.py +0 -0
  44. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/EXTENDED-TASK.md +0 -0
  45. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/FEATURE.md +0 -0
  46. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/MODULE_README.md +0 -0
  47. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
  48. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/TASKS.md +0 -0
  49. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/__init__.py +0 -0
  50. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/async_db_manager.py +0 -0
  51. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/base.py +0 -0
  52. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/config.py +0 -0
  53. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/connections.py +0 -0
  54. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/db_function.py +0 -0
  55. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/diagnostics.py +0 -0
  56. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/expressions.py +0 -0
  57. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/extended.py +0 -0
  58. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/fields.py +0 -0
  59. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/introspection.py +0 -0
  60. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/listen.py +0 -0
  61. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/loop_filters.py +0 -0
  62. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/model_dto.py +0 -0
  63. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/model_view.py +0 -0
  64. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/one_database.py +0 -0
  65. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/paginator.py +0 -0
  66. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/pool_maintenance.py +0 -0
  67. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/pool_watch.py +0 -0
  68. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/pooler_role.py +0 -0
  69. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/pydantic_bridge.py +0 -0
  70. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/registry.py +0 -0
  71. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/relations.py +0 -0
  72. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/resilience.py +0 -0
  73. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/rls_session.py +0 -0
  74. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/session_context.py +0 -0
  75. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/signals.py +0 -0
  76. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/tls.py +0 -0
  77. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/types.py +0 -0
  78. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/write_queue.py +0 -0
  79. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/core/write_retry.py +0 -0
  80. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/entity.py +0 -0
  81. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/error_handling.py +0 -0
  82. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/exceptions.py +0 -0
  83. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/extended/__init__.py +0 -0
  84. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/extended/app_error_handler.py +0 -0
  85. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/identity_rule.py +0 -0
  86. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/local_sqlite.py +0 -0
  87. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/middleware/__init__.py +0 -0
  88. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/middleware/base.py +0 -0
  89. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/migrations/MODULE_README.md +0 -0
  90. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/migrations/__init__.py +0 -0
  91. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/migrations/cli.py +0 -0
  92. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/migrations/ddl.py +0 -0
  93. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/migrations/diff.py +0 -0
  94. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/migrations/executor.py +0 -0
  95. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/migrations/integration.py +0 -0
  96. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/migrations/loader.py +0 -0
  97. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/migrations/operations.py +0 -0
  98. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/migrations/state.py +0 -0
  99. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/migrations/table_filter.py +0 -0
  100. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/no_org_assignment.py +0 -0
  101. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/FEATURE.md +0 -0
  102. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/MODULE_README.md +0 -0
  103. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/__init__.py +0 -0
  104. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/bulk_update_values.py +0 -0
  105. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/catalog_select.py +0 -0
  106. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/conflict.py +0 -0
  107. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/conflict_writes.py +0 -0
  108. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/create.py +0 -0
  109. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/db_functions.py +0 -0
  110. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/delete.py +0 -0
  111. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/dynamic_admin.py +0 -0
  112. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/dynamic_crud.py +0 -0
  113. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/graph_walk.py +0 -0
  114. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/latest_rows.py +0 -0
  115. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/queue_claim.py +0 -0
  116. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/read.py +0 -0
  117. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/relational_backfill.py +0 -0
  118. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/staging_load.py +0 -0
  119. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/operations/update.py +0 -0
  120. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/platform_access.py +0 -0
  121. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/platform_db.py +0 -0
  122. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/py.typed +0 -0
  123. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/pytest_lock_guard.py +0 -0
  124. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/pytest_plugin.py +0 -0
  125. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/python_sql/MODULE_README.md +0 -0
  126. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/python_sql/__init__.py +0 -0
  127. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/python_sql/db_objects.py +0 -0
  128. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
  129. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
  130. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/query/FEATURE.md +0 -0
  131. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/query/MODULE_README.md +0 -0
  132. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/query/__init__.py +0 -0
  133. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/query/builder.py +0 -0
  134. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/resources/__init__.py +0 -0
  135. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/resources/additional-assigners-2026-09-12.json +0 -0
  136. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/resources/org_assignment_trigger_baseline.json +0 -0
  137. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/FEATURE.md +0 -0
  138. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/MODULE_README.md +0 -0
  139. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/__init__.py +0 -0
  140. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/code_handler.py +0 -0
  141. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/codegen_writer.py +0 -0
  142. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/columns.py +0 -0
  143. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/common.py +0 -0
  144. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/diff_preview.py +0 -0
  145. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
  146. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/generator.py +0 -0
  147. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
  148. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
  149. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
  150. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
  151. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/package_wiring.py +0 -0
  152. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/relationships.py +0 -0
  153. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/runner.py +0 -0
  154. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/schema.py +0 -0
  155. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/schema_manager.py +0 -0
  156. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/tables.py +0 -0
  157. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/schema_builder/views.py +0 -0
  158. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/secrets_battery/FEATURE.md +0 -0
  159. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/secrets_battery/__init__.py +0 -0
  160. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/secrets_battery/attachments.py +0 -0
  161. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/secrets_battery/crypto.py +0 -0
  162. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/secrets_battery/host_authorization.py +0 -0
  163. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/secrets_battery/items.py +0 -0
  164. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/secrets_battery/model.py +0 -0
  165. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/secrets_battery/mutation_receipts.py +0 -0
  166. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/secrets_battery/org_service.py +0 -0
  167. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/secrets_battery/service.py +0 -0
  168. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/README.md +0 -0
  169. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/__init__.py +0 -0
  170. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/coalesce.py +0 -0
  171. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/dag.py +0 -0
  172. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/errors.py +0 -0
  173. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/fallback.py +0 -0
  174. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/flush.py +0 -0
  175. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/lifecycle.py +0 -0
  176. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/managed.py +0 -0
  177. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/op.py +0 -0
  178. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/reads.py +0 -0
  179. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/session.py +0 -0
  180. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/session/telemetry.py +0 -0
  181. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/sql_executor/MODULE_README.md +0 -0
  182. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/sql_executor/__init__.py +0 -0
  183. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/sql_executor/executor.py +0 -0
  184. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/sql_executor/queries.py +0 -0
  185. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/sql_executor/registry.py +0 -0
  186. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/sql_executor/types.py +0 -0
  187. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/sql_executor/utils.py +0 -0
  188. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/state.py +0 -0
  189. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/utils/__init__.py +0 -0
  190. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/utils/sql_utils.py +0 -0
  191. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/matrx_orm/utils/type_converters.py +0 -0
  192. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/scripts/git-branches.sh +0 -0
  193. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/scripts/publish.sh +0 -0
  194. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/scripts/release.sh +0 -0
  195. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/MODULE_README.md +0 -0
  196. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/__init__.py +0 -0
  197. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/conftest.py +0 -0
  198. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/MODULE_README.md +0 -0
  199. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/__init__.py +0 -0
  200. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_adapter_registry.py +0 -0
  201. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_admin_db_columns.py +0 -0
  202. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_admin_response_rendering.py +0 -0
  203. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_admin_search_negation.py +0 -0
  204. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_admin_search_sentinels.py +0 -0
  205. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_advisory_lock.py +0 -0
  206. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_agent_message.py +0 -0
  207. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_api_auth.py +0 -0
  208. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_api_config.py +0 -0
  209. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_api_handlers.py +0 -0
  210. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_api_protocol.py +0 -0
  211. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_array_agg_order_by.py +0 -0
  212. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_associations.py +0 -0
  213. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_associations_wiring.py +0 -0
  214. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_bulk_hydration_offload.py +0 -0
  215. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_bulk_update_by_pk.py +0 -0
  216. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
  217. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_cache_debug.py +0 -0
  218. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_call_function.py +0 -0
  219. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_case_when.py +0 -0
  220. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_catalog.py +0 -0
  221. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_committed_row_guard.py +0 -0
  222. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_composite_pk_filter.py +0 -0
  223. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_composite_pk_write_paths.py +0 -0
  224. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_config.py +0 -0
  225. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_conflict_target.py +0 -0
  226. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_conflict_writes.py +0 -0
  227. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_connection_codecs.py +0 -0
  228. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_connection_poison_guard.py +0 -0
  229. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_connection_primitives.py +0 -0
  230. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_count_composite_distinct.py +0 -0
  231. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_count_limit_param_leak.py +0 -0
  232. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_db_function_field.py +0 -0
  233. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_ddl_generator.py +0 -0
  234. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_deadlock_retry.py +0 -0
  235. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_derived_table.py +0 -0
  236. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_dirty_tracking.py +0 -0
  237. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_dynamic_crud.py +0 -0
  238. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_exceptions.py +0 -0
  239. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
  240. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_expression_primitives.py +0 -0
  241. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_fields.py +0 -0
  242. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
  243. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_from_alias.py +0 -0
  244. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_fts.py +0 -0
  245. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_func_expression_args.py +0 -0
  246. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_graph_walk.py +0 -0
  247. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_having_annotate_alias.py +0 -0
  248. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
  249. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_introspect_rls_policies.py +0 -0
  250. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_join_and_aggregate.py +0 -0
  251. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_latest_rows.py +0 -0
  252. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_listen_notify.py +0 -0
  253. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_local_sqlite.py +0 -0
  254. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_lock_contention_retry.py +0 -0
  255. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_managed_write_guard.py +0 -0
  256. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_matrx_entity.py +0 -0
  257. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_migration_diff_types.py +0 -0
  258. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_migration_loader.py +0 -0
  259. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_model_instance.py +0 -0
  260. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_model_meta.py +0 -0
  261. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_optimistic_concurrency.py +0 -0
  262. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_order_by_expression.py +0 -0
  263. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_org_assignment_inventory.py +0 -0
  264. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_orm_banners_are_client_safe.py +0 -0
  265. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_parameter_name_hydration.py +0 -0
  266. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_patch_jsonb_path.py +0 -0
  267. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_persisted_count.py +0 -0
  268. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_pool_holder_census.py +0 -0
  269. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_pool_loop_recreation.py +0 -0
  270. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_pool_maintenance.py +0 -0
  271. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_postgrest_filters.py +0 -0
  272. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_pydantic_bridge.py +0 -0
  273. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_query_builder.py +0 -0
  274. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_query_error_detail.py +0 -0
  275. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_query_executor_sql.py +0 -0
  276. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_query_timeout.py +0 -0
  277. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
  278. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_queue_claim.py +0 -0
  279. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_read_connection_retry.py +0 -0
  280. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_registry.py +0 -0
  281. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_registry_multi_database.py +0 -0
  282. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_registry_multi_schema.py +0 -0
  283. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_relational_backfill.py +0 -0
  284. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_relations.py +0 -0
  285. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_resilience.py +0 -0
  286. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_rls_session_scope.py +0 -0
  287. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_schema_exists.py +0 -0
  288. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_session_advisory_lock.py +0 -0
  289. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_standalone_write_session_context.py +0 -0
  290. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_state_cache.py +0 -0
  291. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_subquery_filter_raw.py +0 -0
  292. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_subquery_in_filter.py +0 -0
  293. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_subquery_nested_expressions.py +0 -0
  294. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_supabase_auth.py +0 -0
  295. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_supabase_config.py +0 -0
  296. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_tls.py +0 -0
  297. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_transaction_database_identity.py +0 -0
  298. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_typed_join_projection.py +0 -0
  299. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_typed_predicates.py +0 -0
  300. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_update_case_expression.py +0 -0
  301. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_update_subquery.py +0 -0
  302. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_update_with_rebase.py +0 -0
  303. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_upsert_default_leak.py +0 -0
  304. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_upsert_with_conflict.py +0 -0
  305. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_values_jsonb_decode.py +0 -0
  306. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_watched_lifecycle.py +0 -0
  307. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_write_queue_deadline.py +0 -0
  308. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level1/test_write_retry_semantics.py +0 -0
  309. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/MODULE_README.md +0 -0
  310. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/__init__.py +0 -0
  311. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/conftest.py +0 -0
  312. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/test_bulk_ops.py +0 -0
  313. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/test_cache_integration.py +0 -0
  314. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/test_crud.py +0 -0
  315. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/test_foreign_keys.py +0 -0
  316. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/test_m2m.py +0 -0
  317. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/test_manager.py +0 -0
  318. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/test_migrations_live.py +0 -0
  319. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/test_query_execution.py +0 -0
  320. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/test_schema_diff.py +0 -0
  321. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/level2/verify_committed_row_guard_pg17.py +0 -0
  322. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/live_pooler_role.py +0 -0
  323. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project/.env.example +0 -0
  324. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project/README.md +0 -0
  325. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project/__init__.py +0 -0
  326. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project/generate.py +0 -0
  327. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project/generated/.gitkeep +0 -0
  328. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project/matrx_orm.yaml +0 -0
  329. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project/test_schema_generation.py +0 -0
  330. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project_desktop/.env.example +0 -0
  331. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project_desktop/README.md +0 -0
  332. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project_desktop/__init__.py +0 -0
  333. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project_desktop/client_example.py +0 -0
  334. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project_desktop/client_example.ts +0 -0
  335. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project_desktop/client_supabase_example.py +0 -0
  336. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/sample_project_desktop/server.py +0 -0
  337. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/entity_tests.py +0 -0
  338. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_base_generation.py +0 -0
  339. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_composite_pk_fk_generation.py +0 -0
  340. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_composite_unique_generation.py +0 -0
  341. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_dto_identity_generation.py +0 -0
  342. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_entity_capability_generation.py +0 -0
  343. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_enum_ordering.py +0 -0
  344. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_generate_schema.py +0 -0
  345. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_junction_analysis.py +0 -0
  346. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_multi_schema_output.py +0 -0
  347. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_schema_analysis.py +0 -0
  348. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_sql_expression_defaults.py +0 -0
  349. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_table_relationships_query.py +0 -0
  350. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema/test_view_generation.py +0 -0
  351. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema_builder/test_array_default_parsing.py +0 -0
  352. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema_builder/test_focused_generation_plan.py +0 -0
  353. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/schema_builder/test_host_models_aggregator.py +0 -0
  354. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/__init__.py +0 -0
  355. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/conftest.py +0 -0
  356. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_cache_no_downgrade.py +0 -0
  357. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_capture_poison_proof.py +0 -0
  358. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_coalesce.py +0 -0
  359. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_dag.py +0 -0
  360. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_disk_spill_fallback.py +0 -0
  361. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_flush_individual_fallback.py +0 -0
  362. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_governed_write.py +0 -0
  363. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_managed.py +0 -0
  364. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_op_enqueue_site.py +0 -0
  365. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_reads.py +0 -0
  366. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_record_error_bounded_insert.py +0 -0
  367. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_record_error_storm.py +0 -0
  368. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_session.py +0 -0
  369. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/session/test_spill_guard_plugin.py +0 -0
  370. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_array_arg_element_type.py +0 -0
  371. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_database_name_alias.py +0 -0
  372. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_db_functions.py +0 -0
  373. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_dynamic_select_unregistered.py +0 -0
  374. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_immutable_insert_or_exact_verify.py +0 -0
  375. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_keyed_digest.py +0 -0
  376. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_model_cls_refactor.py +0 -0
  377. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_no_blocking_asyncpg_tls.py +0 -0
  378. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_one_database.py +0 -0
  379. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_order_by_desc_nulls_last.py +0 -0
  380. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_pooler_role_guard.py +0 -0
  381. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_secrets_battery.py +0 -0
  382. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_secrets_minting_keys.py +0 -0
  383. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_shared_lock_guard.py +0 -0
  384. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_sql_param_casts.py +0 -0
  385. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_sync_twins_guard.py +0 -0
  386. {matrx_orm-3.1.159 → matrx_orm-3.1.161}/tests/test_user_visible_lookup.py +0 -0
@@ -559,6 +559,20 @@ Tests: `packages/matrx-orm/tests/level1/test_update_case_expression.py`.
559
559
 
560
560
  ### Session-scoped advisory lock — `advisory_lock` / `try_advisory_lock` / `advisory_unlock`
561
561
 
562
+ > 🚨 **A session lock is only a lock where the connection has backend affinity.**
563
+ > Through a connection pooler in TRANSACTION mode (Supavisor, PgBouncer, RDS Proxy…)
564
+ > consecutive statements on one leased connection can land on DIFFERENT backends: the
565
+ > lock is released the instant its own statement ends, `pg_advisory_unlock` reports it
566
+ > was never held, and two independent callers BOTH acquire the same key while the code
567
+ > reads as correct. Measured, not theorised — one deployment reached this way billed two
568
+ > model calls for one answer and let two concurrent OAuth refreshes replay a one-use
569
+ > refresh token (2026-09-17). Prove `SELECT pg_backend_pid()` is stable across two
570
+ > statements on your connection before using these three functions. If it is not, guard
571
+ > the work with a durable claim ROW (`INSERT … ON CONFLICT DO NOTHING` plus a lease), or
572
+ > with `advisory_xact_lock` inside ONE `transaction()` when the guarded section fits in a
573
+ > single transaction — a pooler pins one backend for an explicit transaction.
574
+ > The tests below assert the SQL text only; no unit test can catch this.
575
+
562
576
  Three top-level primitives (`matrx_orm.core.transaction`, exported from `matrx_orm`) —
563
577
  the SESSION-scoped sibling of `advisory_xact_lock`/`try_advisory_xact_lock`. A
564
578
  transaction-scoped lock auto-releases at COMMIT/ROLLBACK, which doesn't fit a lock held
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: matrx-orm
3
- Version: 3.1.159
3
+ Version: 3.1.161
4
4
  Summary: Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching
5
5
  Project-URL: Homepage, https://github.com/AI-Matrix-Engine/aidream-current
6
6
  Project-URL: Repository, https://github.com/AI-Matrix-Engine/aidream-current
@@ -25,7 +25,7 @@ Requires-Python: >=3.13
25
25
  Requires-Dist: asyncpg>=0.31.0
26
26
  Requires-Dist: cryptography>=43.0
27
27
  Requires-Dist: gitpython>=3.1.40
28
- Requires-Dist: matrx-utils>=2.0.47
28
+ Requires-Dist: matrx-utils>=2.0.48
29
29
  Requires-Dist: psycopg-pool>=3.2.5
30
30
  Requires-Dist: psycopg[binary]>=3.2.5
31
31
  Requires-Dist: python-dotenv>=1.0
@@ -264,6 +264,13 @@ from .core.session_context import (
264
264
  declaring_actor,
265
265
  session_context_gucs,
266
266
  )
267
+ from .write_actor import (
268
+ ACTOR_REQUIRED_TABLES,
269
+ UndeterminedWriteActor,
270
+ set_write_feature_resolver,
271
+ write_needs_named_actor,
272
+ writing_system,
273
+ )
267
274
  from .core.signals import (
268
275
  Signal,
269
276
  post_create,
@@ -685,6 +692,11 @@ __all__ = [
685
692
  "declared_actor_gucs",
686
693
  "declaring_actor",
687
694
  "session_context_gucs",
695
+ "ACTOR_REQUIRED_TABLES",
696
+ "UndeterminedWriteActor",
697
+ "set_write_feature_resolver",
698
+ "write_needs_named_actor",
699
+ "writing_system",
688
700
  "advisory_xact_lock",
689
701
  "try_advisory_xact_lock",
690
702
  "advisory_lock",
@@ -71,35 +71,6 @@ Filepath: src/matrx_orm/adapters/__init__.py [python]
71
71
 
72
72
 
73
73
 
74
- ---
75
- Filepath: src/matrx_orm/adapters/postgresql.py [python]
76
-
77
- class PostgreSQLAdapter(BaseAdapter):
78
- def __init__(self)
79
- async def _get_connection(self)
80
- async def execute_query(self, query: Dict[str, Any]) -> List[Dict[str, Any]]
81
- async def count(self, query: Dict[str, Any]) -> int
82
- async def exists(self, query: Dict[str, Any]) -> bool
83
- async def insert(self, query: Dict[str, Any]) -> Dict[str, Any]
84
- async def bulk_insert(self, query: Dict[str, Any]) -> List[Dict[str, Any]]
85
- async def update(self, query: Dict[str, Any], data: Dict[str, Any]) -> int
86
- async def bulk_update(self, query: Dict[str, Any]) -> int
87
- async def delete(self, query: Dict[str, Any]) -> int
88
- async def close(self)
89
- async def transaction(self)
90
- async def savepoint(self, name: str)
91
- async def rollback_to_savepoint(self, name: str)
92
- async def release_savepoint(self, name: str)
93
- def _build_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]
94
- def _build_count_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]
95
- def _build_exists_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]
96
- def _build_insert_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]
97
- def _build_bulk_insert_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]
98
- def _build_update_sql(self, query: Dict[str, Any], data: Dict[str, Any]) -> Tuple[str, List[Any]]
99
- def _build_bulk_update_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]
100
- def _build_delete_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]
101
-
102
-
103
74
  ---
104
75
  Filepath: src/matrx_orm/adapters/base_adapter.py [python]
105
76
 
@@ -143,6 +143,24 @@ async def advisory_lock(key: str | int, *, connection: Any) -> None:
143
143
  same connection (e.g. a long-running background pass that itself opens
144
144
  its own nested transactions).
145
145
 
146
+ 🚨 **REQUIRES CONNECTION AFFINITY — READ THIS BEFORE USING IT.** A
147
+ session-scoped lock lives in the backend session, so it is only a lock if
148
+ every statement of the guarded section reaches the SAME backend. Through a
149
+ connection pooler in TRANSACTION mode (Supavisor, PgBouncer, RDS Proxy…)
150
+ consecutive statements on one leased connection can land on DIFFERENT
151
+ backends: the lock is then released the instant its own statement ends,
152
+ ``pg_advisory_unlock`` reports it was never held, and two independent
153
+ callers BOTH acquire the same key while the code reads as correct. Measured,
154
+ not theorised — a deployment reached this way billed two model calls for one
155
+ answer and let two concurrent OAuth refreshes replay a one-use refresh
156
+ token. Before reaching for this: prove the backend pid is stable across two
157
+ statements on your connection (``SELECT pg_backend_pid()`` twice). If it is
158
+ not, this function cannot help you — guard the work with a durable claim ROW
159
+ (``INSERT … ON CONFLICT DO NOTHING`` plus a lease) instead, or use
160
+ :func:`advisory_xact_lock` INSIDE one ``transaction()`` when the whole
161
+ guarded section fits in a single transaction (a pooler pins one backend for
162
+ an explicit transaction).
163
+
146
164
  Requires an explicit ``connection=`` (an asyncpg connection obtained via
147
165
  :func:`acquire_connection`, held for the duration of the locked section) —
148
166
  a session-scoped lock has no meaning tied to the ``transaction()``
@@ -175,6 +193,10 @@ async def try_advisory_lock(key: str | int, *, connection: Any) -> bool:
175
193
  blocks/queues). Same connection/release contract as :func:`advisory_lock`
176
194
  — pair with :func:`advisory_unlock` in a ``try/finally``.
177
195
 
196
+ 🚨 The same connection-affinity warning as :func:`advisory_lock` applies in
197
+ full: through a transaction-mode pooler this returns ``True`` for TWO
198
+ concurrent callers on the same key.
199
+
178
200
  The single-worker serialization shape: several callers race to start the
179
201
  same background pass (e.g. one per org); the first to arrive wins and
180
202
  runs it, the rest skip (no waiting) and let the winner's release + their
@@ -11,6 +11,7 @@ from matrx_utils import vcprint
11
11
  from matrx_orm.adapters import AdapterRegistry
12
12
  from matrx_orm.adapters.base_adapter import BaseAdapter
13
13
  from matrx_orm.core.types import AggregateResult, UpdateResult
14
+ from matrx_orm.write_actor import names_its_actor
14
15
  from matrx_orm.exceptions import (
15
16
  DatabaseError,
16
17
  IntegrityError,
@@ -1192,6 +1193,7 @@ class QueryExecutor:
1192
1193
  )
1193
1194
  return await self.db.execute_write_dict(query)
1194
1195
 
1196
+ @names_its_actor
1195
1197
  async def insert(self, query: dict[str, Any]) -> dict[str, Any]:
1196
1198
  """INSERT a single row, RETURNING *."""
1197
1199
  self._guard_writable("insert")
@@ -1236,6 +1238,7 @@ class QueryExecutor:
1236
1238
  # inside another IntegrityError, producing banner-in-banner output.
1237
1239
  raise
1238
1240
 
1241
+ @names_its_actor
1239
1242
  async def bulk_insert(self, query: dict[str, Any]) -> list[Model]:
1240
1243
  """Bulk INSERT, RETURNING *."""
1241
1244
  self._guard_writable("bulk_insert")
@@ -1310,6 +1313,7 @@ class QueryExecutor:
1310
1313
  },
1311
1314
  ) from e
1312
1315
 
1316
+ @names_its_actor
1313
1317
  async def upsert(self, query: dict[str, Any]) -> dict[str, Any]:
1314
1318
  """INSERT ... ON CONFLICT (...) DO UPDATE SET ... RETURNING *
1315
1319
 
@@ -1379,6 +1383,7 @@ class QueryExecutor:
1379
1383
  # Already classified upstream — see note on single-insert.
1380
1384
  raise
1381
1385
 
1386
+ @names_its_actor
1382
1387
  async def bulk_upsert(self, query: dict[str, Any]) -> list[Model]:
1383
1388
  """Bulk INSERT ... ON CONFLICT DO UPDATE.
1384
1389
 
@@ -1524,6 +1529,7 @@ class QueryExecutor:
1524
1529
  inner_where = f" WHERE {where_clause}" if where_clause else ""
1525
1530
  return f" WHERE {pk} IN (SELECT {pk} FROM {table}{inner_where} ORDER BY {pk} FOR UPDATE)"
1526
1531
 
1532
+ @names_its_actor
1527
1533
  async def update(self, **kwargs: Any) -> UpdateResult:
1528
1534
  """UPDATE rows matching the WHERE clause built from filters."""
1529
1535
  self._guard_writable("update")
@@ -1655,6 +1661,11 @@ class QueryExecutor:
1655
1661
  details={"operation": "update", "error": describe_db_exception(e).as_text()},
1656
1662
  ) from e
1657
1663
 
1664
+ # DELETE too, and not out of tidiness: a hard delete on
1665
+ # ``platform.associations`` fires ``_gc_assoc_harddelete``, which writes
1666
+ # OTHER tables inside this statement. That cascade is exactly where the
1667
+ # unnamed-actor refusal surfaced "nowhere near the writer that caused it".
1668
+ @names_its_actor
1658
1669
  async def delete(self) -> int:
1659
1670
  """DELETE rows matching the WHERE clause."""
1660
1671
  self._guard_writable("delete")
@@ -0,0 +1,234 @@
1
+ """ONE DOOR: a write to a table that refuses an unnamed actor names one here.
2
+
3
+ 🚨 THE CLASS THIS CLOSES (2026-09-17). ``platform.associations`` refuses a write
4
+ that declares ``actor_tier=code`` and names no system — "an AI did it" with no
5
+ name is not provenance — and it reads that name from ``SET LOCAL`` GUCs, which
6
+ exist only inside a transaction that declared them.
7
+
8
+ ``68db29e50b`` put the fix on the ASSOCIATION ENGINE (``assoc.associate(...)``),
9
+ which covered the eleven service writers that go through it and covered nothing
10
+ else. Four production writers call the model straight —
11
+ ``aidream/services/agent_data/operations.py``, ``kind_records/store.py``,
12
+ ``kind_records/children.py``, ``google_sync/records.py`` — and the engine's own
13
+ ``associate`` reaches the table through ``get_or_create``, a fifth method the
14
+ census grep for ``Associations.create`` never saw. A safe path beside an unsafe
15
+ one is not a fix: the door has to be removed, not signposted.
16
+
17
+ So the seam sits UNDER every one of them, at the ORM's DML floor
18
+ (``QueryExecutor.insert`` / ``bulk_insert`` / ``upsert`` / ``bulk_upsert`` /
19
+ ``update``). Nothing writes a row without passing through those five methods —
20
+ ``create``, ``bulk_create``, ``get_or_create``, ``update_or_create``, ``save``,
21
+ ``upsert``, the managers in ``matrx_orm.extended`` and any future entry point
22
+ all funnel here — so there is exactly one place a write to an actor-required
23
+ table can happen, and it declares the actor.
24
+
25
+ WHAT IT DECLARES, AND WHY NEVER A CONSTANT
26
+ ------------------------------------------
27
+ A caller that already declared an actor passes straight through, byte for byte
28
+ unchanged: the seam only speaks when nobody did. What it then says is the name
29
+ of the code ACTUALLY making the write — the running feature when the host's
30
+ context names one, else the calling module. There is no fallback string. The
31
+ first version of this walk stopped at the generic ``aidream_association_write``
32
+ whenever it found no ``aidream.`` frame, which satisfies the database's
33
+ constraint while defeating the entire point of it: the operator reading
34
+ ``updated_by_system`` learns nothing, and a script, a package or a worker —
35
+ exactly the automated paths this exists for — all resolve to the same
36
+ meaningless word. When the writer cannot be named this raises
37
+ :class:`UndeterminedWriteActor` AT THE CALL SITE, naming the frame it could not
38
+ resolve, which is the loud failure the doctrine requires of a stand-in.
39
+ """
40
+
41
+ from __future__ import annotations
42
+
43
+ import functools
44
+ from collections.abc import AsyncIterator, Callable
45
+ from contextlib import asynccontextmanager
46
+ from pathlib import Path
47
+ from types import FrameType
48
+ from typing import Any
49
+
50
+ __all__ = [
51
+ "ACTOR_REQUIRED_TABLES",
52
+ "UndeterminedWriteActor",
53
+ "actor_named_for_write",
54
+ "names_its_actor",
55
+ "set_write_feature_resolver",
56
+ "write_needs_named_actor",
57
+ "writing_system",
58
+ ]
59
+
60
+ #: ``(schema, table)`` pairs whose database-side rule refuses a write that
61
+ #: declares ``actor_tier=code`` and names no system. Membership is what makes
62
+ #: the seam speak; every other table's writes are untouched (no extra
63
+ #: transaction, no extra round trip).
64
+ ACTOR_REQUIRED_TABLES: frozenset[tuple[str, str]] = frozenset(
65
+ {
66
+ ("platform", "associations"),
67
+ }
68
+ )
69
+
70
+ #: How long a system name may be. ``app.actor_system`` is text, but a name
71
+ #: longer than this is a stack artefact, not a name a person can act on.
72
+ _MAX_SYSTEM = 64
73
+
74
+
75
+ class UndeterminedWriteActor(RuntimeError):
76
+ """The code making this write could not be named, so nothing was written.
77
+
78
+ Deliberately fatal. The alternative — a constant like
79
+ ``aidream_association_write`` — passes the database's check and tells the
80
+ operator reading the row nothing at all.
81
+ """
82
+
83
+
84
+ _feature_resolver: Callable[[], str | None] | None = None
85
+
86
+
87
+ def set_write_feature_resolver(resolver: Callable[[], str | None] | None) -> None:
88
+ """Teach the seam how to ask the HOST which feature is running.
89
+
90
+ matrx-orm cannot import the host, and the running feature is the truthful,
91
+ operator-actionable answer when there is one. ``aidream`` wires
92
+ ``try_get_app_context().source_feature`` here at startup. Unwired (a script,
93
+ a test, another package) the seam falls back to the calling module, which is
94
+ still a real name — never a constant.
95
+ """
96
+ global _feature_resolver
97
+ _feature_resolver = resolver
98
+
99
+
100
+ def write_needs_named_actor(model: Any) -> bool:
101
+ """Does a write to ``model``'s table have to name its actor?"""
102
+ if model is None:
103
+ return False
104
+ schema = getattr(model, "_db_schema", None)
105
+ table = getattr(model, "_table_name", None)
106
+ if not schema or not table:
107
+ return False
108
+ return (str(schema), str(table)) in ACTOR_REQUIRED_TABLES
109
+
110
+
111
+ # Frames that are the plumbing, never the author. The ORM's own modules and the
112
+ # generic async/context machinery it is wrapped in say nothing about WHO wrote
113
+ # the row, so the walk steps over them to reach the first frame that does.
114
+ _PLUMBING_PREFIXES: tuple[str, ...] = (
115
+ "matrx_orm.",
116
+ "contextlib",
117
+ "asyncio.",
118
+ "functools",
119
+ )
120
+ _PLUMBING_MODULES: frozenset[str] = frozenset({"matrx_orm", "asyncio", "contextlib", "functools"})
121
+
122
+
123
+ def _is_plumbing(module: str) -> bool:
124
+ return module in _PLUMBING_MODULES or module.startswith(_PLUMBING_PREFIXES)
125
+
126
+
127
+ def _name_of(frame: FrameType) -> str | None:
128
+ """A name a person can act on for the code running in ``frame``.
129
+
130
+ The last TWO dotted segments of the module, because the leaf alone is a
131
+ coin flip: ``records`` is ``google_sync/records.py`` and four other files,
132
+ and an operator reading ``updated_by_system='records'`` is no better off
133
+ than with a constant. ``google_sync.records`` names the writer.
134
+ """
135
+ module = str(frame.f_globals.get("__name__") or "")
136
+ if module and module != "__main__":
137
+ return ".".join(module.split(".")[-2:])[:_MAX_SYSTEM]
138
+ filename = str(frame.f_globals.get("__file__") or "")
139
+ stem = Path(filename).stem if filename else ""
140
+ return stem[:_MAX_SYSTEM] or None
141
+
142
+
143
+ def writing_system() -> str:
144
+ """WHICH system is writing this row — read off the running program, never invented.
145
+
146
+ Raises :class:`UndeterminedWriteActor` rather than returning a placeholder.
147
+ """
148
+ if _feature_resolver is not None:
149
+ try:
150
+ feature = _feature_resolver()
151
+ except Exception: # noqa: BLE001 — a broken host hook must not name the row
152
+ feature = None
153
+ if feature and str(feature).strip():
154
+ return str(feature).strip()[:_MAX_SYSTEM]
155
+
156
+ import sys
157
+
158
+ frame: FrameType | None = sys._getframe(1)
159
+ # The frame a person would look at if this refuses: the innermost one that
160
+ # is not the ORM itself. Reporting the OUTERMOST frame instead names
161
+ # `.venv/bin/pytest` or the process entry point, which is useless.
162
+ nearest: FrameType | None = frame
163
+ while frame is not None:
164
+ module = str(frame.f_globals.get("__name__") or "")
165
+ if nearest is None or str(nearest.f_globals.get("__name__") or "").startswith("matrx_orm"):
166
+ if not module.startswith("matrx_orm"):
167
+ nearest = frame
168
+ if not _is_plumbing(module):
169
+ name = _name_of(frame)
170
+ if name:
171
+ return name
172
+ frame = frame.f_back
173
+
174
+ where = (
175
+ f"{nearest.f_code.co_filename}:{nearest.f_lineno}"
176
+ if nearest is not None
177
+ else "an unreadable stack"
178
+ )
179
+ raise UndeterminedWriteActor(
180
+ "A write to an actor-required table could not name the code making it. "
181
+ f"The outermost frame the seam could read was {where}, and every frame above "
182
+ "it belongs to the ORM or to async plumbing. Declare the actor at the call "
183
+ "site — `async with actor_session('code', '<your system>'):` — rather than "
184
+ "letting an unnamed write reach the database, which would be refused there "
185
+ "anyway, at CASCADE time, nowhere near here."
186
+ )
187
+
188
+
189
+ @asynccontextmanager
190
+ async def actor_named_for_write(database: str) -> AsyncIterator[None]:
191
+ """Run the block with an actor declared, if nobody declared one already.
192
+
193
+ Pass-through when ``current_actor()`` is set: a caller that named itself is
194
+ never second-guessed, and no transaction is opened on its behalf.
195
+ """
196
+ from matrx_orm.core.session_context import current_actor, declaring_actor
197
+ from matrx_orm.core.transaction import set_local_guc, transaction
198
+
199
+ if current_actor() is not None:
200
+ yield
201
+ return
202
+
203
+ system = writing_system()
204
+ # The GUCs are transaction-local, so the declaration is only worth anything
205
+ # inside one. Nested, this opens a SAVEPOINT and the SET LOCAL applies to
206
+ # the enclosing transaction — which is correct: the enclosing work had no
207
+ # actor either.
208
+ async with transaction(database=database):
209
+ with declaring_actor("code", system) as actor:
210
+ for guc_name, guc_value in actor.as_gucs().items():
211
+ await set_local_guc(guc_name, guc_value)
212
+ yield
213
+
214
+
215
+ def names_its_actor(method: Callable[..., Any]) -> Callable[..., Any]:
216
+ """Mark a ``QueryExecutor`` DML method as passing through the seam.
217
+
218
+ Every DML method on the executor carries this, and
219
+ ``matrx_orm/tests/test_every_write_door_names_its_actor.py`` walks the
220
+ executor's AST to prove a newly added one does too — a new write door is
221
+ the only way this class could re-open.
222
+ """
223
+
224
+ @functools.wraps(method)
225
+ async def wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
226
+ model = getattr(self, "model", None)
227
+ if not write_needs_named_actor(model):
228
+ return await method(self, *args, **kwargs)
229
+ database = getattr(self, "database", None) or getattr(model, "_database", None)
230
+ async with actor_named_for_write(str(database)):
231
+ return await method(self, *args, **kwargs)
232
+
233
+ wrapper.__matrx_names_its_actor__ = True # type: ignore[attr-defined]
234
+ return wrapper
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "matrx-orm"
3
- version = "3.1.159"
3
+ version = "3.1.161"
4
4
  description = "Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -41,7 +41,7 @@ dependencies = [
41
41
  "gitpython>=3.1.40",
42
42
  "psycopg[binary]>=3.2.5",
43
43
  "psycopg-pool>=3.2.5",
44
- "matrx-utils>=2.0.47",
44
+ "matrx-utils>=2.0.48",
45
45
  "pyyaml>=6.0.3",
46
46
  "python-dotenv>=1.0",
47
47
  "cryptography>=43.0",
@@ -1,167 +0,0 @@
1
- from typing import Any, Dict, List, Tuple
2
- import asyncpg
3
- from matrx_orm.adapters.base_adapter import BaseAdapter
4
- from matrx_orm import get_database_config
5
- from matrx_orm.core.tls import resolve_asyncpg_ssl
6
- from matrx_utils.conf import settings
7
-
8
-
9
- class PostgreSQLAdapter(BaseAdapter):
10
- def __init__(self):
11
- self.current_database = settings.DEFAULT_DB_PROJECT
12
- self.config = get_database_config(self.current_database)
13
- self.connection = None
14
-
15
- async def _get_connection(self):
16
- if self.connection is None or self.connection.is_closed():
17
- ssl_config = await resolve_asyncpg_ssl(self.config.get("ssl", "require"))
18
- self.connection = await asyncpg.connect(
19
- host=self.config["host"],
20
- port=self.config["port"],
21
- database=self.config["database_name"],
22
- user=self.config["user"],
23
- password=self.config["password"],
24
- ssl=ssl_config,
25
- )
26
- return self.connection
27
-
28
- async def execute_query(self, query: Dict[str, Any]) -> List[Dict[str, Any]]:
29
- sql, params = self._build_sql(query)
30
- connection = await self._get_connection()
31
- rows = await connection.fetch(sql, *params)
32
- return [dict(row) for row in rows]
33
-
34
- async def count(self, query: Dict[str, Any]) -> int:
35
- sql, params = self._build_count_sql(query)
36
- connection = await self._get_connection()
37
- row = await connection.fetchrow(sql, *params)
38
- return row["count"]
39
-
40
- async def exists(self, query: Dict[str, Any]) -> bool:
41
- sql, params = self._build_exists_sql(query)
42
- connection = await self._get_connection()
43
- row = await connection.fetchrow(sql, *params)
44
- return row["exists"]
45
-
46
- async def insert(self, query: Dict[str, Any]) -> Dict[str, Any]:
47
- sql, params = self._build_insert_sql(query)
48
- connection = await self._get_connection()
49
- row = await connection.fetchrow(sql, *params)
50
- return dict(row)
51
-
52
- async def bulk_insert(self, query: Dict[str, Any]) -> List[Dict[str, Any]]:
53
- sql, params = self._build_bulk_insert_sql(query)
54
- connection = await self._get_connection()
55
- await connection.executemany(sql, params)
56
- return await connection.fetch(sql, *params)
57
-
58
- async def update(self, query: Dict[str, Any], data: Dict[str, Any]) -> int:
59
- sql, params = self._build_update_sql(query, data)
60
- connection = await self._get_connection()
61
- result = await connection.execute(sql, *params)
62
- return result
63
-
64
- async def bulk_update(self, query: Dict[str, Any]) -> int:
65
- sql, params = self._build_bulk_update_sql(query)
66
- connection = await self._get_connection()
67
- result = await connection.executemany(sql, params)
68
- return result
69
-
70
- async def delete(self, query: Dict[str, Any]) -> int:
71
- sql, params = self._build_delete_sql(query)
72
- connection = await self._get_connection()
73
- result = await connection.execute(sql, *params)
74
- return result
75
-
76
- async def close(self):
77
- if self.connection is not None and not self.connection.is_closed():
78
- await self.connection.close()
79
-
80
- async def transaction(self):
81
- connection = await self._get_connection()
82
- async with connection.transaction():
83
- yield
84
-
85
- async def savepoint(self, name: str):
86
- connection = await self._get_connection()
87
- await connection.execute(f"SAVEPOINT {name}")
88
-
89
- async def rollback_to_savepoint(self, name: str):
90
- connection = await self._get_connection()
91
- await connection.execute(f"ROLLBACK TO SAVEPOINT {name}")
92
-
93
- async def release_savepoint(self, name: str):
94
- connection = await self._get_connection()
95
- await connection.execute(f"RELEASE SAVEPOINT {name}")
96
-
97
- def _build_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]:
98
- # Generic SQL building logic for select statements
99
- sql = f"SELECT * FROM {query['model'].__tablename__} WHERE "
100
- filters = []
101
- params = []
102
- for field, value in query["filters"].items():
103
- filters.append(f"{field} = ${len(params) + 1}")
104
- params.append(value)
105
- sql += " AND ".join(filters)
106
- return sql, params
107
-
108
- def _build_count_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]:
109
- sql = f"SELECT COUNT(*) FROM {query['model'].__tablename__} WHERE "
110
- filters = []
111
- params = []
112
- for field, value in query["filters"].items():
113
- filters.append(f"{field} = ${len(params) + 1}")
114
- params.append(value)
115
- sql += " AND ".join(filters)
116
- return sql, params
117
-
118
- def _build_exists_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]:
119
- sql = f"SELECT EXISTS(SELECT 1 FROM {query['model'].__tablename__} WHERE "
120
- filters = []
121
- params = []
122
- for field, value in query["filters"].items():
123
- filters.append(f"{field} = ${len(params) + 1}")
124
- params.append(value)
125
- sql += " AND ".join(filters) + ")"
126
- return sql, params
127
-
128
- def _build_insert_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]:
129
- fields = ", ".join(query["data"].keys())
130
- placeholders = ", ".join([f"${i + 1}" for i in range(len(query["data"]))])
131
- sql = f"INSERT INTO {query['model'].__tablename__} ({fields}) VALUES ({placeholders}) RETURNING *"
132
- params = list(query["data"].values())
133
- return sql, params
134
-
135
- def _build_bulk_insert_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]:
136
- fields = ", ".join(query["data"][0].keys())
137
- placeholders = ", ".join([f"${i + 1}" for i in range(len(query["data"][0]))])
138
- sql = f"INSERT INTO {query['model'].__tablename__} ({fields}) VALUES ({placeholders})"
139
- params = [tuple(row.values()) for row in query["data"]]
140
- return sql, params
141
-
142
- def _build_update_sql(
143
- self, query: Dict[str, Any], data: Dict[str, Any]
144
- ) -> Tuple[str, List[Any]]:
145
- set_clause = ", ".join([f"{key} = ${i + 1}" for i, key in enumerate(data.keys())])
146
- sql = f"UPDATE {query['model'].__tablename__} SET {set_clause} WHERE "
147
- filters = []
148
- params = list(data.values())
149
- for field, value in query["filters"].items():
150
- filters.append(f"{field} = ${len(params) + 1}")
151
- params.append(value)
152
- sql += " AND ".join(filters)
153
- return sql, params
154
-
155
- def _build_bulk_update_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]:
156
- # Similar to update but for bulk updates
157
- raise NotImplementedError("Bulk update logic to be implemented")
158
-
159
- def _build_delete_sql(self, query: Dict[str, Any]) -> Tuple[str, List[Any]]:
160
- sql = f"DELETE FROM {query['model'].__tablename__} WHERE "
161
- filters = []
162
- params = []
163
- for field, value in query["filters"].items():
164
- filters.append(f"{field} = ${len(params) + 1}")
165
- params.append(value)
166
- sql += " AND ".join(filters)
167
- return sql, params
File without changes
File without changes
File without changes
File without changes
File without changes