sqlobjects 2.0.0__tar.gz → 2.0.1__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 (82) hide show
  1. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/CHANGELOG.md +6 -0
  2. {sqlobjects-2.0.0/sqlobjects.egg-info → sqlobjects-2.0.1}/PKG-INFO +1 -1
  3. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/pyproject.toml +1 -1
  4. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/__init__.py +1 -1
  5. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/metadata.py +27 -8
  6. {sqlobjects-2.0.0 → sqlobjects-2.0.1/sqlobjects.egg-info}/PKG-INFO +1 -1
  7. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/LICENSE +0 -0
  8. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/README.md +0 -0
  9. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/docs/rules/01-database-session-guide.md +0 -0
  10. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/docs/rules/02-model-definition-guide.md +0 -0
  11. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/docs/rules/03-query-operations-guide.md +0 -0
  12. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/docs/rules/04-crud-operations-guide.md +0 -0
  13. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/docs/rules/05-relationships-guide.md +0 -0
  14. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/docs/rules/06-validation-signals-guide.md +0 -0
  15. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/docs/rules/07-performance-guide.md +0 -0
  16. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/docs/rules/README.md +0 -0
  17. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/setup.cfg +0 -0
  18. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/_install_rules.py +0 -0
  19. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/cascade.py +0 -0
  20. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/contrib/__init__.py +0 -0
  21. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/contrib/asgi.py +0 -0
  22. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/contrib/fastapi.py +0 -0
  23. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/database/__init__.py +0 -0
  24. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/database/config.py +0 -0
  25. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/database/manager.py +0 -0
  26. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/exceptions.py +0 -0
  27. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/expressions/__init__.py +0 -0
  28. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/expressions/aggregate.py +0 -0
  29. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/expressions/base.py +0 -0
  30. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/expressions/cte.py +0 -0
  31. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/expressions/explain.py +0 -0
  32. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/expressions/function.py +0 -0
  33. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/expressions/mixins.py +0 -0
  34. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/expressions/scalar.py +0 -0
  35. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/expressions/subquery.py +0 -0
  36. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/expressions/terminal.py +0 -0
  37. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/expressions/window.py +0 -0
  38. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/__init__.py +0 -0
  39. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/core.py +0 -0
  40. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/functions.py +0 -0
  41. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/proxies.py +0 -0
  42. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/relations/__init__.py +0 -0
  43. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/relations/descriptors.py +0 -0
  44. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/relations/managers.py +0 -0
  45. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/relations/prefetch.py +0 -0
  46. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/relations/strategies.py +0 -0
  47. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/relations/utils.py +0 -0
  48. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/shortcuts.py +0 -0
  49. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/types/__init__.py +0 -0
  50. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/types/base.py +0 -0
  51. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/types/comparators.py +0 -0
  52. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/types/registry.py +0 -0
  53. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/fields/utils.py +0 -0
  54. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/internal/__init__.py +0 -0
  55. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/internal/operations.py +0 -0
  56. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/internal/results.py +0 -0
  57. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/mixins.py +0 -0
  58. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/model.py +0 -0
  59. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/objects/__init__.py +0 -0
  60. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/objects/bulk.py +0 -0
  61. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/objects/core.py +0 -0
  62. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/objects/upsert.py +0 -0
  63. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/py.typed +0 -0
  64. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/queries/__init__.py +0 -0
  65. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/queries/builder.py +0 -0
  66. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/queries/dialect.py +0 -0
  67. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/queries/executor.py +0 -0
  68. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/queryset.py +0 -0
  69. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/session.py +0 -0
  70. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/signals.py +0 -0
  71. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/sql_logging.py +0 -0
  72. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/utils/__init__.py +0 -0
  73. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/utils/inspect.py +0 -0
  74. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/utils/naming.py +0 -0
  75. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/utils/pattern.py +0 -0
  76. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects/validators.py +0 -0
  77. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects.egg-info/SOURCES.txt +0 -0
  78. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects.egg-info/dependency_links.txt +0 -0
  79. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects.egg-info/entry_points.txt +0 -0
  80. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects.egg-info/requires.txt +0 -0
  81. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/sqlobjects.egg-info/top_level.txt +0 -0
  82. {sqlobjects-2.0.0 → sqlobjects-2.0.1}/tests/test_config.py +0 -0
@@ -1,3 +1,9 @@
1
+ ## 2.0.1 (2026-08-31)
2
+
3
+ ### Fix
4
+
5
+ - **metadata**: include dialect kwargs in index dedup signature
6
+
1
7
  ## 2.0.0 (2026-08-19)
2
8
 
3
9
  ### BREAKING CHANGE
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlobjects
3
- Version: 2.0.0
3
+ Version: 2.0.1
4
4
  Summary: Django-style async ORM library based on SQLAlchemy with chainable queries, Q objects, and relationship loading
5
5
  Author-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
6
6
  Maintainer-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sqlobjects"
3
- version = "2.0.0"
3
+ version = "2.0.1"
4
4
  description = "Django-style async ORM library based on SQLAlchemy with chainable queries, Q objects, and relationship loading"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -19,7 +19,7 @@ from .queryset import Q, QuerySet
19
19
  from .sql_logging import ObjectLogger, get_caller_frame
20
20
 
21
21
 
22
- __version__ = "2.0.0"
22
+ __version__ = "2.0.1"
23
23
 
24
24
  __all__ = [
25
25
  # Core classes
@@ -595,29 +595,48 @@ class ModelProcessor(type):
595
595
  def col_sig(idx):
596
596
  return tuple(sorted(col.name for col in idx.columns)) if idx.columns else None
597
597
 
598
- full_sig_map: dict[tuple, list] = {} # (cols, unique) -> indexes
598
+ def dialect_sig(idx):
599
+ # Dialect kwargs (postgresql_where / postgresql_using / mysql_using, etc.)
600
+ # are part of an index's identity: same columns with different partial
601
+ # predicates or access methods are distinct indexes, not duplicates.
602
+ # Values may be str or SQLAlchemy expressions, so compare via str().
603
+ # dialect_kwargs only holds explicitly passed args, not dialect defaults.
604
+ kwargs = getattr(idx, "dialect_kwargs", None) or {}
605
+ return tuple(sorted((k, str(v)) for k, v in kwargs.items() if v is not None))
606
+
607
+ def is_partial(idx):
608
+ return any(k.endswith("_where") for k, _ in dialect_sig(idx))
609
+
610
+ full_sig_map: dict[tuple, list] = {} # (cols, unique, dialect_sig) -> indexes
599
611
  col_map: dict[tuple, list] = {} # cols -> indexes
600
612
 
601
613
  for idx in list(table.indexes):
602
614
  cs = col_sig(idx)
603
615
  if cs is None:
604
616
  continue
605
- full_sig_map.setdefault((cs, getattr(idx, "unique", False)), []).append(idx)
617
+ full_sig_map.setdefault((cs, getattr(idx, "unique", False), dialect_sig(idx)), []).append(idx)
606
618
  col_map.setdefault(cs, []).append(idx)
607
619
 
608
620
  to_remove: set = set()
609
621
 
610
- # Remove exact duplicates: prefer explicit names over SQLAlchemy auto-generated "ix_*"
622
+ # Remove exact duplicates (same columns, unique flag, and dialect kwargs):
623
+ # prefer explicit names over SQLAlchemy auto-generated "ix_*". Sort by name
624
+ # so the kept index is deterministic regardless of set iteration order.
611
625
  for indexes in full_sig_map.values():
612
626
  if len(indexes) > 1:
613
- explicit = [i for i in indexes if not (i.name and i.name.startswith("ix_"))]
614
- keep = explicit[0] if explicit else indexes[0]
627
+ explicit = sorted(
628
+ (i for i in indexes if not (i.name and i.name.startswith("ix_"))),
629
+ key=lambda i: i.name or "",
630
+ )
631
+ keep = explicit[0] if explicit else sorted(indexes, key=lambda i: i.name or "")[0]
615
632
  to_remove.update(i for i in indexes if i is not keep)
616
633
 
617
- # Remove non-unique when unique exists on same columns
634
+ # Remove full-table non-unique when a full-table unique exists on same columns.
635
+ # Partial indexes (unique or not) never participate: a partial unique index
636
+ # only covers rows matching its predicate and cannot replace a full index.
618
637
  for indexes in col_map.values():
619
- if any(getattr(i, "unique", False) for i in indexes):
620
- to_remove.update(i for i in indexes if not getattr(i, "unique", False))
638
+ if any(getattr(i, "unique", False) and not is_partial(i) for i in indexes):
639
+ to_remove.update(i for i in indexes if not getattr(i, "unique", False) and not is_partial(i))
621
640
 
622
641
  for idx in to_remove:
623
642
  table.indexes.discard(idx)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlobjects
3
- Version: 2.0.0
3
+ Version: 2.0.1
4
4
  Summary: Django-style async ORM library based on SQLAlchemy with chainable queries, Q objects, and relationship loading
5
5
  Author-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
6
6
  Maintainer-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
File without changes
File without changes
File without changes