ferro-orm 0.10.3__tar.gz → 0.10.4__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.
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/CHANGELOG.md +9 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/Cargo.lock +17 -17
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/Cargo.toml +1 -1
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/PKG-INFO +1 -1
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/pyproject.toml +1 -1
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/lib.rs +1 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/operations.rs +16 -37
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/query.rs +62 -0
- ferro_orm-0.10.4/src/schema_bind.rs +49 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_structural_types.py +39 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.github/PERMISSIONS.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.github/PYPI_CHECKLIST.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.github/PYPI_SETUP.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.github/generated/wheels.generated.yml +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.github/pull_request_template.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.github/workflows/ci.yml +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.github/workflows/packaging-smoke.yml +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.github/workflows/publish-docs.yml +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.github/workflows/publish.yml +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.github/workflows/release.yml +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.gitignore +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.pre-commit-config.yaml +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/.python-version +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/AGENTS.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/CONTRIBUTING.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/LICENSE +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/README.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/TEST_RESULTS.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/api/exceptions.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/api/fields.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/api/model.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/api/query.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/api/raw-sql.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/api/relationships.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/api/transactions.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/api/utilities.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/brainstorms/2026-04-29-named-connections-role-routing-requirements.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/brainstorms/2026-05-08-typed-query-predicates-requirements.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/brainstorms/2026-05-13-configurable-column-storage-types-requirements.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/brainstorms/2026-05-14-autogenerate-support-for-db-type-requirements.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/changelog.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/coming-soon.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/concepts/architecture.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/concepts/identity-map.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/concepts/performance.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/concepts/query-typing.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/concepts/type-safety.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/contributing.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/faq.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/getting-started/installation.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/getting-started/next-steps.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/getting-started/tutorial.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/guide/backend.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/guide/database.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/guide/migrations.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/guide/models-and-fields.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/guide/mutations.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/guide/queries.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/guide/relationships.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/guide/transactions.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/howto/multiple-databases.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/howto/pagination.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/howto/soft-deletes.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/howto/testing.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/howto/timestamps.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/index.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/migration-sqlalchemy.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/plans/2026-04-24-001-refactor-multi-db-backend-architecture-plan.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/plans/2026-04-29-001-typed-null-binds-plan.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/plans/2026-04-29-002-feat-named-connections-plan.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/plans/2026-05-07-001-refactor-generic-model-connection-plan.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/plans/2026-05-08-001-feat-typed-query-predicates-plan.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/plans/2026-05-13-001-feat-configurable-column-storage-types-plan.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/README.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/issues/pydantic-slots-missing-after-ferro-hydration.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/issues/python-3.14-deferred-annotation-typeerror-swallow.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/issues/sa-pk-column-nullable-divergence.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/issues/sa-vs-rust-unique-constraint-shape.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/issues/sqlite-null-hydrates-as-int-zero.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/issues/typed-where-null-panics-is-null.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/patterns/configurable-column-storage-types.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/patterns/cross-emitter-ddl-parity.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/patterns/foreign-key-index.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/patterns/index-unique-redundancy.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/patterns/shadow-fk-columns.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/patterns/typed-null-binds.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/stylesheets/extra.css +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/why-ferro.md +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/justfile +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/mkdocs.yml +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/scripts/demo_queries.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/backend.rs +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/connection.rs +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/__init__.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/_annotation_utils.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/_core.pyi +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/_shadow_fk_types.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/base.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/composite_indexes.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/composite_uniques.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/exceptions.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/fields.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/metaclass.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/migrations/__init__.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/migrations/alembic.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/models.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/py.typed +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/query/__init__.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/query/builder.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/query/nodes.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/raw.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/relations/__init__.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/relations/descriptors.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/schema_metadata.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/ferro/state.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/schema.rs +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/src/state.rs +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/__init__.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/conftest.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/db_backends.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_aggregation.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_alembic_autogenerate.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_alembic_bridge.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_alembic_db_type.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_alembic_nullability.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_alembic_type_mapping.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_auto_migrate.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_bulk_update.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_composite_index.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_composite_unique.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_connection.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_connection_redaction.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_constraints.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_cross_emitter_parity.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_crud.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_db_backends.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_db_type_cross_emitter_parity.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_db_type_integration.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_db_type_typing.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_db_type_validation.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_deletion.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_docs_examples.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_documentation_features.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_field_wrapper.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_helpers.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_hydration.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_metaclass_internals.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_metadata.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_models.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_named_connections_integration.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_one_to_one.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_query_builder.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_query_typing.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_raw_sql.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_refresh.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_relationship_engine.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_schema.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_schema_constraints.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_schema_db_type_metadata.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_schema_enum_annotations.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_shadow_fk_types.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_sqlite_alembic_reconnect_hydration.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_static_contracts.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_string_search.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_temporal_types.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_transactions.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/tests/test_typed_null_binds.py +0 -0
- {ferro_orm-0.10.3 → ferro_orm-0.10.4}/uv.lock +0 -0
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v0.10.4 (2026-05-24)
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
- **query**: Cast native Postgres enum RHS in `.where()` filters
|
|
9
|
+
([#64](https://github.com/syn54x/ferro-orm/pull/64),
|
|
10
|
+
[`7fea893`](https://github.com/syn54x/ferro-orm/commit/7fea89320fd2216a956ae32e8ae6f4829dd8fcf7))
|
|
11
|
+
|
|
12
|
+
|
|
4
13
|
## v0.10.3 (2026-05-21)
|
|
5
14
|
|
|
6
15
|
### Bug Fixes
|
|
@@ -25,9 +25,9 @@ dependencies = [
|
|
|
25
25
|
|
|
26
26
|
[[package]]
|
|
27
27
|
name = "autocfg"
|
|
28
|
-
version = "1.5.
|
|
28
|
+
version = "1.5.1"
|
|
29
29
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
30
|
-
checksum = "
|
|
30
|
+
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
|
31
31
|
|
|
32
32
|
[[package]]
|
|
33
33
|
name = "base64"
|
|
@@ -61,9 +61,9 @@ dependencies = [
|
|
|
61
61
|
|
|
62
62
|
[[package]]
|
|
63
63
|
name = "bumpalo"
|
|
64
|
-
version = "3.20.
|
|
64
|
+
version = "3.20.3"
|
|
65
65
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
66
|
-
checksum = "
|
|
66
|
+
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
|
67
67
|
|
|
68
68
|
[[package]]
|
|
69
69
|
name = "byteorder"
|
|
@@ -294,7 +294,7 @@ dependencies = [
|
|
|
294
294
|
|
|
295
295
|
[[package]]
|
|
296
296
|
name = "ferro"
|
|
297
|
-
version = "0.10.
|
|
297
|
+
version = "0.10.4"
|
|
298
298
|
dependencies = [
|
|
299
299
|
"dashmap",
|
|
300
300
|
"once_cell",
|
|
@@ -711,9 +711,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
|
|
711
711
|
|
|
712
712
|
[[package]]
|
|
713
713
|
name = "js-sys"
|
|
714
|
-
version = "0.3.
|
|
714
|
+
version = "0.3.99"
|
|
715
715
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
716
|
-
checksum = "
|
|
716
|
+
checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11"
|
|
717
717
|
dependencies = [
|
|
718
718
|
"cfg-if",
|
|
719
719
|
"futures-util",
|
|
@@ -1292,9 +1292,9 @@ dependencies = [
|
|
|
1292
1292
|
|
|
1293
1293
|
[[package]]
|
|
1294
1294
|
name = "serde_json"
|
|
1295
|
-
version = "1.0.
|
|
1295
|
+
version = "1.0.150"
|
|
1296
1296
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1297
|
-
checksum = "
|
|
1297
|
+
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
|
1298
1298
|
dependencies = [
|
|
1299
1299
|
"itoa",
|
|
1300
1300
|
"memchr",
|
|
@@ -1892,9 +1892,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
|
|
|
1892
1892
|
|
|
1893
1893
|
[[package]]
|
|
1894
1894
|
name = "wasm-bindgen"
|
|
1895
|
-
version = "0.2.
|
|
1895
|
+
version = "0.2.122"
|
|
1896
1896
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1897
|
-
checksum = "
|
|
1897
|
+
checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409"
|
|
1898
1898
|
dependencies = [
|
|
1899
1899
|
"cfg-if",
|
|
1900
1900
|
"once_cell",
|
|
@@ -1905,9 +1905,9 @@ dependencies = [
|
|
|
1905
1905
|
|
|
1906
1906
|
[[package]]
|
|
1907
1907
|
name = "wasm-bindgen-macro"
|
|
1908
|
-
version = "0.2.
|
|
1908
|
+
version = "0.2.122"
|
|
1909
1909
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1910
|
-
checksum = "
|
|
1910
|
+
checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6"
|
|
1911
1911
|
dependencies = [
|
|
1912
1912
|
"quote",
|
|
1913
1913
|
"wasm-bindgen-macro-support",
|
|
@@ -1915,9 +1915,9 @@ dependencies = [
|
|
|
1915
1915
|
|
|
1916
1916
|
[[package]]
|
|
1917
1917
|
name = "wasm-bindgen-macro-support"
|
|
1918
|
-
version = "0.2.
|
|
1918
|
+
version = "0.2.122"
|
|
1919
1919
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1920
|
-
checksum = "
|
|
1920
|
+
checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e"
|
|
1921
1921
|
dependencies = [
|
|
1922
1922
|
"bumpalo",
|
|
1923
1923
|
"proc-macro2",
|
|
@@ -1928,9 +1928,9 @@ dependencies = [
|
|
|
1928
1928
|
|
|
1929
1929
|
[[package]]
|
|
1930
1930
|
name = "wasm-bindgen-shared"
|
|
1931
|
-
version = "0.2.
|
|
1931
|
+
version = "0.2.122"
|
|
1932
1932
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1933
|
-
checksum = "
|
|
1933
|
+
checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437"
|
|
1934
1934
|
dependencies = [
|
|
1935
1935
|
"unicode-ident",
|
|
1936
1936
|
]
|
|
@@ -560,30 +560,6 @@ async fn postgres_temporal_cast_by_column(
|
|
|
560
560
|
Ok(out)
|
|
561
561
|
}
|
|
562
562
|
|
|
563
|
-
fn postgres_enum_type_name_for_column(
|
|
564
|
-
col_name: &str,
|
|
565
|
-
enum_udt: &HashMap<String, String>,
|
|
566
|
-
col_info: Option<&serde_json::Value>,
|
|
567
|
-
) -> Option<String> {
|
|
568
|
-
// db_type takes precedence over the JSON-schema enum_type_name: when the
|
|
569
|
-
// user has asked for `text` / `varchar(N)` / etc. storage, the column is
|
|
570
|
-
// no longer a native Postgres enum UDT and we must not CAST values to a
|
|
571
|
-
// non-existent type. This mirrors the Alembic-side _map_to_sa_type
|
|
572
|
-
// override. See AGENTS.md § I-1.
|
|
573
|
-
if let Some(info) = col_info
|
|
574
|
-
&& info.get("db_type").and_then(|v| v.as_str()).is_some()
|
|
575
|
-
{
|
|
576
|
-
return None;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
enum_udt.get(col_name).cloned().or_else(|| {
|
|
580
|
-
col_info?
|
|
581
|
-
.get("enum_type_name")?
|
|
582
|
-
.as_str()
|
|
583
|
-
.map(std::string::ToString::to_string)
|
|
584
|
-
})
|
|
585
|
-
}
|
|
586
|
-
|
|
587
563
|
fn schema_property<'a>(
|
|
588
564
|
schema: &'a serde_json::Value,
|
|
589
565
|
col_name: &str,
|
|
@@ -630,12 +606,10 @@ fn schema_value_expr(
|
|
|
630
606
|
|
|
631
607
|
if let serde_json::Value::String(s) = value
|
|
632
608
|
&& backend == SqlDialect::Postgres
|
|
633
|
-
&& let Some(tn) =
|
|
609
|
+
&& let Some(tn) =
|
|
610
|
+
crate::schema_bind::postgres_enum_type_name_for_column(col_name, enum_udt, col_info)
|
|
634
611
|
{
|
|
635
|
-
return Ok(
|
|
636
|
-
Expr::value(sea_query::Value::String(Some(Box::new(s.clone()))))
|
|
637
|
-
.cast_as(Alias::new(tn.as_str())),
|
|
638
|
-
);
|
|
612
|
+
return Ok(crate::schema_bind::postgres_enum_string_rhs_expr(s, &tn));
|
|
639
613
|
}
|
|
640
614
|
|
|
641
615
|
if is_uuid_pg {
|
|
@@ -1572,7 +1546,7 @@ pub fn fetch_filtered<'py>(
|
|
|
1572
1546
|
let name = cls.getattr("__name__")?.extract::<String>()?;
|
|
1573
1547
|
let cls_py = cls.unbind();
|
|
1574
1548
|
|
|
1575
|
-
let query_def: QueryDef = serde_json::from_str(&query_json).map_err(|e| {
|
|
1549
|
+
let mut query_def: QueryDef = serde_json::from_str(&query_json).map_err(|e| {
|
|
1576
1550
|
pyo3::exceptions::PyValueError::new_err(format!("Invalid query JSON: {}", e))
|
|
1577
1551
|
})?;
|
|
1578
1552
|
|
|
@@ -1582,10 +1556,10 @@ pub fn fetch_filtered<'py>(
|
|
|
1582
1556
|
let use_identity_map = engine.is_identity_map_enabled();
|
|
1583
1557
|
|
|
1584
1558
|
let table_name = name.to_lowercase();
|
|
1585
|
-
let
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1559
|
+
let postgres_enum_udt =
|
|
1560
|
+
postgres_enum_udt_by_column(&table_name, &engine, &tx_conn, backend).await?;
|
|
1561
|
+
query_def.postgres_enum_udt = postgres_enum_udt.clone();
|
|
1562
|
+
let pg_native_enum_cols: HashSet<String> = postgres_enum_udt.keys().cloned().collect();
|
|
1589
1563
|
// ...
|
|
1590
1564
|
let (sql, bind_values, pk_col, schema_for_decode) = {
|
|
1591
1565
|
let registry = MODEL_REGISTRY.read().map_err(|_| {
|
|
@@ -1762,7 +1736,7 @@ pub fn count_filtered(
|
|
|
1762
1736
|
tx_id: Option<String>,
|
|
1763
1737
|
using: Option<String>,
|
|
1764
1738
|
) -> PyResult<Bound<'_, PyAny>> {
|
|
1765
|
-
let query_def: QueryDef = serde_json::from_str(&query_json).map_err(|e| {
|
|
1739
|
+
let mut query_def: QueryDef = serde_json::from_str(&query_json).map_err(|e| {
|
|
1766
1740
|
pyo3::exceptions::PyValueError::new_err(format!("Invalid query JSON: {}", e))
|
|
1767
1741
|
})?;
|
|
1768
1742
|
|
|
@@ -1770,6 +1744,8 @@ pub fn count_filtered(
|
|
|
1770
1744
|
let (_, engine, tx_conn, backend) = active_route_for_operation(tx_id, using)?;
|
|
1771
1745
|
|
|
1772
1746
|
let table_name = name.to_lowercase();
|
|
1747
|
+
query_def.postgres_enum_udt =
|
|
1748
|
+
postgres_enum_udt_by_column(&table_name, &engine, &tx_conn, backend).await?;
|
|
1773
1749
|
// ... sql ...
|
|
1774
1750
|
let (sql, bind_values) = {
|
|
1775
1751
|
let mut select = Query::select();
|
|
@@ -1964,7 +1940,7 @@ pub fn delete_filtered(
|
|
|
1964
1940
|
tx_id: Option<String>,
|
|
1965
1941
|
using: Option<String>,
|
|
1966
1942
|
) -> PyResult<Bound<'_, PyAny>> {
|
|
1967
|
-
let query_def: QueryDef = serde_json::from_str(&query_json).map_err(|e| {
|
|
1943
|
+
let mut query_def: QueryDef = serde_json::from_str(&query_json).map_err(|e| {
|
|
1968
1944
|
pyo3::exceptions::PyValueError::new_err(format!("Invalid query JSON: {}", e))
|
|
1969
1945
|
})?;
|
|
1970
1946
|
|
|
@@ -1972,6 +1948,8 @@ pub fn delete_filtered(
|
|
|
1972
1948
|
let (_, engine, tx_conn, backend) = active_route_for_operation(tx_id, using)?;
|
|
1973
1949
|
|
|
1974
1950
|
let table_name = name.to_lowercase();
|
|
1951
|
+
query_def.postgres_enum_udt =
|
|
1952
|
+
postgres_enum_udt_by_column(&table_name, &engine, &tx_conn, backend).await?;
|
|
1975
1953
|
// ... sql ...
|
|
1976
1954
|
let (sql, bind_values) = {
|
|
1977
1955
|
let mut delete = Query::delete();
|
|
@@ -2008,7 +1986,7 @@ pub fn update_filtered(
|
|
|
2008
1986
|
tx_id: Option<String>,
|
|
2009
1987
|
using: Option<String>,
|
|
2010
1988
|
) -> PyResult<Bound<'_, PyAny>> {
|
|
2011
|
-
let query_def: QueryDef = serde_json::from_str(&query_json).map_err(|e| {
|
|
1989
|
+
let mut query_def: QueryDef = serde_json::from_str(&query_json).map_err(|e| {
|
|
2012
1990
|
pyo3::exceptions::PyValueError::new_err(format!("Invalid query JSON: {}", e))
|
|
2013
1991
|
})?;
|
|
2014
1992
|
|
|
@@ -2025,6 +2003,7 @@ pub fn update_filtered(
|
|
|
2025
2003
|
|
|
2026
2004
|
let table_name = name.to_lowercase();
|
|
2027
2005
|
let enum_udt = postgres_enum_udt_by_column(&table_name, &engine, &tx_conn, backend).await?;
|
|
2006
|
+
query_def.postgres_enum_udt = enum_udt.clone();
|
|
2028
2007
|
let uuid_columns =
|
|
2029
2008
|
postgres_uuid_column_names(&table_name, &engine, &tx_conn, backend).await?;
|
|
2030
2009
|
let ts_cast =
|
|
@@ -2,6 +2,7 @@ use crate::state::{MODEL_REGISTRY, SqlDialect};
|
|
|
2
2
|
use sea_query::{Alias, Condition, Expr, SimpleExpr};
|
|
3
3
|
use serde::Deserialize;
|
|
4
4
|
use serde_json::Value;
|
|
5
|
+
use std::collections::HashMap;
|
|
5
6
|
|
|
6
7
|
#[derive(Debug, Deserialize)]
|
|
7
8
|
pub struct QueryNode {
|
|
@@ -38,6 +39,10 @@ pub struct QueryDef {
|
|
|
38
39
|
pub limit: Option<u64>,
|
|
39
40
|
pub offset: Option<u64>,
|
|
40
41
|
pub m2m: Option<M2mContext>,
|
|
42
|
+
/// Populated from `pg_catalog` before building filter SQL. Not part of the
|
|
43
|
+
/// Python query JSON payload.
|
|
44
|
+
#[serde(skip)]
|
|
45
|
+
pub postgres_enum_udt: HashMap<String, String>,
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
impl QueryDef {
|
|
@@ -202,6 +207,12 @@ impl QueryDef {
|
|
|
202
207
|
) -> SimpleExpr {
|
|
203
208
|
if let Value::String(s) = val {
|
|
204
209
|
if backend == SqlDialect::Postgres {
|
|
210
|
+
if let Some(tn) =
|
|
211
|
+
crate::schema_bind::native_postgres_enum_udt_name(col_name, &self.postgres_enum_udt)
|
|
212
|
+
{
|
|
213
|
+
return crate::schema_bind::postgres_enum_string_rhs_expr(s, tn);
|
|
214
|
+
}
|
|
215
|
+
|
|
205
216
|
if let Ok(parsed) = uuid::Uuid::parse_str(s) {
|
|
206
217
|
let schema_uuid = model_column_is_uuid(&self.model_name, col_name);
|
|
207
218
|
if schema_uuid || infer_uuid_without_schema {
|
|
@@ -430,6 +441,7 @@ mod tests {
|
|
|
430
441
|
use crate::backend::BackendKind;
|
|
431
442
|
use sea_query::{Alias, PostgresQueryBuilder, Query, SqliteQueryBuilder, Value as SeaValue};
|
|
432
443
|
use serde_json::json;
|
|
444
|
+
use std::collections::HashMap;
|
|
433
445
|
|
|
434
446
|
fn empty_query_def(model_name: &str) -> QueryDef {
|
|
435
447
|
QueryDef {
|
|
@@ -439,6 +451,7 @@ mod tests {
|
|
|
439
451
|
limit: None,
|
|
440
452
|
offset: None,
|
|
441
453
|
m2m: None,
|
|
454
|
+
postgres_enum_udt: HashMap::new(),
|
|
442
455
|
}
|
|
443
456
|
}
|
|
444
457
|
|
|
@@ -479,6 +492,7 @@ mod tests {
|
|
|
479
492
|
limit: None,
|
|
480
493
|
offset: None,
|
|
481
494
|
m2m: None,
|
|
495
|
+
postgres_enum_udt: HashMap::new(),
|
|
482
496
|
};
|
|
483
497
|
let mut select = Query::select();
|
|
484
498
|
select
|
|
@@ -508,6 +522,7 @@ mod tests {
|
|
|
508
522
|
limit: None,
|
|
509
523
|
offset: None,
|
|
510
524
|
m2m: None,
|
|
525
|
+
postgres_enum_udt: HashMap::new(),
|
|
511
526
|
};
|
|
512
527
|
let mut select = Query::select();
|
|
513
528
|
select
|
|
@@ -675,6 +690,53 @@ mod tests {
|
|
|
675
690
|
}
|
|
676
691
|
}
|
|
677
692
|
|
|
693
|
+
#[test]
|
|
694
|
+
fn enum_rhs_emits_cast_to_schema_enum_type_on_postgres() {
|
|
695
|
+
let mut query_def = empty_query_def("WidgetColor");
|
|
696
|
+
query_def
|
|
697
|
+
.postgres_enum_udt
|
|
698
|
+
.insert("color".to_string(), "color".to_string());
|
|
699
|
+
|
|
700
|
+
let rhs = query_def.value_rhs_simple_expr_for_backend(
|
|
701
|
+
"color",
|
|
702
|
+
&json!("red"),
|
|
703
|
+
false,
|
|
704
|
+
BackendKind::Postgres,
|
|
705
|
+
);
|
|
706
|
+
let sql = Query::select().expr(rhs).to_string(PostgresQueryBuilder);
|
|
707
|
+
|
|
708
|
+
assert!(
|
|
709
|
+
sql.to_lowercase().contains("as \"color\"") || sql.to_lowercase().contains("as color"),
|
|
710
|
+
"enum filter rhs should CAST to the UDT name, got: {sql}"
|
|
711
|
+
);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
#[test]
|
|
715
|
+
fn enum_rhs_skips_cast_without_native_enum_column() {
|
|
716
|
+
crate::state::MODEL_REGISTRY.write().unwrap().insert(
|
|
717
|
+
"WidgetTextColor".to_string(),
|
|
718
|
+
json!({
|
|
719
|
+
"properties": {
|
|
720
|
+
"color": {"enum_type_name": "color", "db_type": "text"}
|
|
721
|
+
}
|
|
722
|
+
}),
|
|
723
|
+
);
|
|
724
|
+
let query_def = empty_query_def("WidgetTextColor");
|
|
725
|
+
|
|
726
|
+
let rhs = query_def.value_rhs_simple_expr_for_backend(
|
|
727
|
+
"color",
|
|
728
|
+
&json!("red"),
|
|
729
|
+
false,
|
|
730
|
+
BackendKind::Postgres,
|
|
731
|
+
);
|
|
732
|
+
let sql = Query::select().expr(rhs).to_string(PostgresQueryBuilder);
|
|
733
|
+
|
|
734
|
+
assert!(
|
|
735
|
+
!sql.to_lowercase().contains("as \"color\"") && !sql.to_lowercase().contains("as color"),
|
|
736
|
+
"auto-migrate TEXT enum columns must not cast without catalog UDT: {sql}"
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
|
|
678
740
|
#[test]
|
|
679
741
|
fn decimal_rhs_keeps_numeric_cast_for_now() {
|
|
680
742
|
// Native numeric typed binds are deferred (plan §3 Scope Boundaries);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
//! Shared schema-driven bind helpers for INSERT/UPDATE and query-filter paths.
|
|
2
|
+
|
|
3
|
+
use sea_query::{Alias, Expr, SimpleExpr};
|
|
4
|
+
use std::collections::HashMap;
|
|
5
|
+
|
|
6
|
+
/// Native Postgres enum UDT for `col_name`, from catalog introspection only.
|
|
7
|
+
///
|
|
8
|
+
/// Query-filter predicates use this path so auto-migrate TEXT columns (which
|
|
9
|
+
/// carry `enum_type_name` in schema but are not `typtype = 'e'`) keep plain
|
|
10
|
+
/// text binds. INSERT/UPDATE may still fall back to schema metadata via
|
|
11
|
+
/// [`postgres_enum_type_name_for_column`].
|
|
12
|
+
pub(crate) fn native_postgres_enum_udt_name<'a>(
|
|
13
|
+
col_name: &str,
|
|
14
|
+
enum_udt: &'a HashMap<String, String>,
|
|
15
|
+
) -> Option<&'a str> {
|
|
16
|
+
enum_udt.get(col_name).map(|s| s.as_str())
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/// Resolve the Postgres enum UDT name for a column when binding a string RHS.
|
|
20
|
+
///
|
|
21
|
+
/// `enum_udt` comes from catalog introspection (INSERT/UPDATE). `col_info` is
|
|
22
|
+
/// the model field schema fragment (`enum_type_name`, `db_type`, etc.).
|
|
23
|
+
///
|
|
24
|
+
/// When `db_type` is set, native enum casting is suppressed — the column is no
|
|
25
|
+
/// longer stored as a Postgres enum UDT (see AGENTS.md I-1 / Alembic parity).
|
|
26
|
+
pub(crate) fn postgres_enum_type_name_for_column(
|
|
27
|
+
col_name: &str,
|
|
28
|
+
enum_udt: &HashMap<String, String>,
|
|
29
|
+
col_info: Option<&serde_json::Value>,
|
|
30
|
+
) -> Option<String> {
|
|
31
|
+
if let Some(info) = col_info
|
|
32
|
+
&& info.get("db_type").and_then(|v| v.as_str()).is_some()
|
|
33
|
+
{
|
|
34
|
+
return None;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
enum_udt.get(col_name).cloned().or_else(|| {
|
|
38
|
+
col_info?
|
|
39
|
+
.get("enum_type_name")?
|
|
40
|
+
.as_str()
|
|
41
|
+
.map(std::string::ToString::to_string)
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// RHS expression for a non-null string compared against a native Postgres enum column.
|
|
46
|
+
pub(crate) fn postgres_enum_string_rhs_expr(s: &str, enum_type_name: &str) -> SimpleExpr {
|
|
47
|
+
Expr::value(sea_query::Value::String(Some(Box::new(s.to_string()))))
|
|
48
|
+
.cast_as(Alias::new(enum_type_name))
|
|
49
|
+
}
|
|
@@ -276,6 +276,45 @@ async def test_native_postgres_enum_column_decodes_via_text_cast(
|
|
|
276
276
|
assert fetched.format == TranscriptFormat.PDF
|
|
277
277
|
|
|
278
278
|
|
|
279
|
+
@pytest.mark.asyncio
|
|
280
|
+
@pytest.mark.postgres_only
|
|
281
|
+
async def test_native_postgres_enum_where_lambda_count(db_url, postgres_base_url, db_schema_name):
|
|
282
|
+
"""Regression for #63: filter predicates must cast enum RHS to the PG UDT."""
|
|
283
|
+
|
|
284
|
+
class Color(str, Enum):
|
|
285
|
+
RED = "red"
|
|
286
|
+
BLUE = "blue"
|
|
287
|
+
|
|
288
|
+
class Widget(Model):
|
|
289
|
+
id: Annotated[int | None, FerroField(primary_key=True)] = None
|
|
290
|
+
color: Color
|
|
291
|
+
|
|
292
|
+
import psycopg
|
|
293
|
+
|
|
294
|
+
with psycopg.connect(postgres_base_url) as conn:
|
|
295
|
+
conn.execute(f'SET search_path TO "{db_schema_name}"')
|
|
296
|
+
conn.execute("CREATE TYPE color AS ENUM ('red', 'blue')")
|
|
297
|
+
conn.execute(
|
|
298
|
+
"""
|
|
299
|
+
CREATE TABLE widget (
|
|
300
|
+
id integer PRIMARY KEY,
|
|
301
|
+
color color NOT NULL
|
|
302
|
+
)
|
|
303
|
+
"""
|
|
304
|
+
)
|
|
305
|
+
conn.execute("INSERT INTO widget (id, color) VALUES (1, 'red'), (2, 'blue')")
|
|
306
|
+
conn.commit()
|
|
307
|
+
|
|
308
|
+
await connect(db_url, auto_migrate=False)
|
|
309
|
+
|
|
310
|
+
count = await Widget.where(lambda w, c=Color.RED: w.color == c).count()
|
|
311
|
+
assert count == 1
|
|
312
|
+
|
|
313
|
+
rows = await Widget.where(lambda w: w.color != Color.BLUE).all()
|
|
314
|
+
assert len(rows) == 1
|
|
315
|
+
assert rows[0].color == Color.RED
|
|
316
|
+
|
|
317
|
+
|
|
279
318
|
@pytest.mark.asyncio
|
|
280
319
|
@pytest.mark.postgres_only
|
|
281
320
|
async def test_native_postgres_enum_plain_str_column(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/plans/2026-04-29-002-feat-named-connections-plan.md
RENAMED
|
File without changes
|
|
File without changes
|
{ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/plans/2026-05-08-001-feat-typed-query-predicates-plan.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/issues/sa-pk-column-nullable-divergence.md
RENAMED
|
File without changes
|
{ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/issues/sa-vs-rust-unique-constraint-shape.md
RENAMED
|
File without changes
|
{ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/issues/sqlite-null-hydrates-as-int-zero.md
RENAMED
|
File without changes
|
{ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/issues/typed-where-null-panics-is-null.md
RENAMED
|
File without changes
|
{ferro_orm-0.10.3 → ferro_orm-0.10.4}/docs/solutions/patterns/configurable-column-storage-types.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|