infrahub-server 1.4.12__py3-none-any.whl → 1.5.0__py3-none-any.whl

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 (234) hide show
  1. infrahub/actions/tasks.py +208 -16
  2. infrahub/api/artifact.py +3 -0
  3. infrahub/api/diff/diff.py +1 -1
  4. infrahub/api/internal.py +2 -0
  5. infrahub/api/query.py +2 -0
  6. infrahub/api/schema.py +27 -3
  7. infrahub/auth.py +5 -5
  8. infrahub/cli/__init__.py +2 -0
  9. infrahub/cli/db.py +160 -157
  10. infrahub/cli/dev.py +118 -0
  11. infrahub/cli/tasks.py +46 -0
  12. infrahub/cli/upgrade.py +56 -9
  13. infrahub/computed_attribute/tasks.py +19 -7
  14. infrahub/config.py +7 -2
  15. infrahub/core/attribute.py +35 -24
  16. infrahub/core/branch/enums.py +1 -1
  17. infrahub/core/branch/models.py +9 -5
  18. infrahub/core/branch/needs_rebase_status.py +11 -0
  19. infrahub/core/branch/tasks.py +72 -10
  20. infrahub/core/changelog/models.py +2 -10
  21. infrahub/core/constants/__init__.py +4 -0
  22. infrahub/core/constants/infrahubkind.py +1 -0
  23. infrahub/core/convert_object_type/object_conversion.py +201 -0
  24. infrahub/core/convert_object_type/repository_conversion.py +89 -0
  25. infrahub/core/convert_object_type/schema_mapping.py +27 -3
  26. infrahub/core/diff/calculator.py +2 -2
  27. infrahub/core/diff/model/path.py +4 -0
  28. infrahub/core/diff/payload_builder.py +1 -1
  29. infrahub/core/diff/query/artifact.py +1 -0
  30. infrahub/core/diff/query/delete_query.py +9 -5
  31. infrahub/core/diff/query/field_summary.py +1 -0
  32. infrahub/core/diff/query/merge.py +39 -23
  33. infrahub/core/graph/__init__.py +1 -1
  34. infrahub/core/initialization.py +7 -4
  35. infrahub/core/manager.py +3 -81
  36. infrahub/core/migrations/__init__.py +3 -0
  37. infrahub/core/migrations/exceptions.py +4 -0
  38. infrahub/core/migrations/graph/__init__.py +13 -10
  39. infrahub/core/migrations/graph/load_schema_branch.py +21 -0
  40. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +1 -1
  41. infrahub/core/migrations/graph/m037_index_attr_vals.py +11 -30
  42. infrahub/core/migrations/graph/m039_ipam_reconcile.py +9 -7
  43. infrahub/core/migrations/graph/m041_deleted_dup_edges.py +149 -0
  44. infrahub/core/migrations/graph/m042_profile_attrs_in_db.py +147 -0
  45. infrahub/core/migrations/graph/m043_create_hfid_display_label_in_db.py +164 -0
  46. infrahub/core/migrations/graph/m044_backfill_hfid_display_label_in_db.py +864 -0
  47. infrahub/core/migrations/query/__init__.py +7 -8
  48. infrahub/core/migrations/query/attribute_add.py +8 -6
  49. infrahub/core/migrations/query/attribute_remove.py +134 -0
  50. infrahub/core/migrations/runner.py +54 -0
  51. infrahub/core/migrations/schema/attribute_kind_update.py +9 -3
  52. infrahub/core/migrations/schema/attribute_supports_profile.py +90 -0
  53. infrahub/core/migrations/schema/node_attribute_add.py +26 -5
  54. infrahub/core/migrations/schema/node_attribute_remove.py +13 -109
  55. infrahub/core/migrations/schema/node_kind_update.py +2 -1
  56. infrahub/core/migrations/schema/node_remove.py +2 -1
  57. infrahub/core/migrations/schema/placeholder_dummy.py +3 -2
  58. infrahub/core/migrations/shared.py +66 -19
  59. infrahub/core/models.py +2 -2
  60. infrahub/core/node/__init__.py +207 -54
  61. infrahub/core/node/create.py +53 -49
  62. infrahub/core/node/lock_utils.py +124 -0
  63. infrahub/core/node/node_property_attribute.py +230 -0
  64. infrahub/core/node/resource_manager/ip_address_pool.py +2 -1
  65. infrahub/core/node/resource_manager/ip_prefix_pool.py +2 -1
  66. infrahub/core/node/resource_manager/number_pool.py +2 -1
  67. infrahub/core/node/standard.py +1 -1
  68. infrahub/core/property.py +11 -0
  69. infrahub/core/protocols.py +8 -1
  70. infrahub/core/query/attribute.py +82 -15
  71. infrahub/core/query/diff.py +61 -16
  72. infrahub/core/query/ipam.py +16 -4
  73. infrahub/core/query/node.py +92 -212
  74. infrahub/core/query/relationship.py +44 -26
  75. infrahub/core/query/subquery.py +0 -8
  76. infrahub/core/relationship/model.py +69 -24
  77. infrahub/core/schema/__init__.py +56 -0
  78. infrahub/core/schema/attribute_schema.py +4 -2
  79. infrahub/core/schema/basenode_schema.py +42 -2
  80. infrahub/core/schema/definitions/core/__init__.py +2 -0
  81. infrahub/core/schema/definitions/core/check.py +1 -1
  82. infrahub/core/schema/definitions/core/generator.py +2 -0
  83. infrahub/core/schema/definitions/core/group.py +16 -2
  84. infrahub/core/schema/definitions/core/repository.py +7 -0
  85. infrahub/core/schema/definitions/core/transform.py +1 -1
  86. infrahub/core/schema/definitions/internal.py +12 -3
  87. infrahub/core/schema/generated/attribute_schema.py +2 -2
  88. infrahub/core/schema/generated/base_node_schema.py +6 -1
  89. infrahub/core/schema/manager.py +3 -0
  90. infrahub/core/schema/node_schema.py +1 -0
  91. infrahub/core/schema/relationship_schema.py +0 -1
  92. infrahub/core/schema/schema_branch.py +295 -10
  93. infrahub/core/schema/schema_branch_display.py +135 -0
  94. infrahub/core/schema/schema_branch_hfid.py +120 -0
  95. infrahub/core/validators/aggregated_checker.py +1 -1
  96. infrahub/database/graph.py +21 -0
  97. infrahub/display_labels/__init__.py +0 -0
  98. infrahub/display_labels/gather.py +48 -0
  99. infrahub/display_labels/models.py +240 -0
  100. infrahub/display_labels/tasks.py +192 -0
  101. infrahub/display_labels/triggers.py +22 -0
  102. infrahub/events/branch_action.py +27 -1
  103. infrahub/events/group_action.py +1 -1
  104. infrahub/events/node_action.py +1 -1
  105. infrahub/generators/constants.py +7 -0
  106. infrahub/generators/models.py +38 -12
  107. infrahub/generators/tasks.py +34 -16
  108. infrahub/git/base.py +42 -2
  109. infrahub/git/integrator.py +22 -14
  110. infrahub/git/tasks.py +52 -2
  111. infrahub/graphql/analyzer.py +9 -0
  112. infrahub/graphql/api/dependencies.py +2 -4
  113. infrahub/graphql/api/endpoints.py +16 -6
  114. infrahub/graphql/app.py +2 -4
  115. infrahub/graphql/initialization.py +2 -3
  116. infrahub/graphql/manager.py +213 -137
  117. infrahub/graphql/middleware.py +12 -0
  118. infrahub/graphql/mutations/branch.py +16 -0
  119. infrahub/graphql/mutations/computed_attribute.py +110 -3
  120. infrahub/graphql/mutations/convert_object_type.py +44 -13
  121. infrahub/graphql/mutations/display_label.py +118 -0
  122. infrahub/graphql/mutations/generator.py +25 -7
  123. infrahub/graphql/mutations/hfid.py +125 -0
  124. infrahub/graphql/mutations/ipam.py +73 -41
  125. infrahub/graphql/mutations/main.py +61 -178
  126. infrahub/graphql/mutations/profile.py +195 -0
  127. infrahub/graphql/mutations/proposed_change.py +8 -1
  128. infrahub/graphql/mutations/relationship.py +2 -2
  129. infrahub/graphql/mutations/repository.py +22 -83
  130. infrahub/graphql/mutations/resource_manager.py +2 -2
  131. infrahub/graphql/mutations/webhook.py +1 -1
  132. infrahub/graphql/queries/resource_manager.py +1 -1
  133. infrahub/graphql/registry.py +173 -0
  134. infrahub/graphql/resolvers/resolver.py +2 -0
  135. infrahub/graphql/schema.py +8 -1
  136. infrahub/graphql/schema_sort.py +170 -0
  137. infrahub/graphql/types/branch.py +4 -1
  138. infrahub/graphql/types/enums.py +3 -0
  139. infrahub/groups/tasks.py +1 -1
  140. infrahub/hfid/__init__.py +0 -0
  141. infrahub/hfid/gather.py +48 -0
  142. infrahub/hfid/models.py +240 -0
  143. infrahub/hfid/tasks.py +191 -0
  144. infrahub/hfid/triggers.py +22 -0
  145. infrahub/lock.py +119 -42
  146. infrahub/locks/__init__.py +0 -0
  147. infrahub/locks/tasks.py +37 -0
  148. infrahub/message_bus/types.py +1 -0
  149. infrahub/patch/plan_writer.py +2 -2
  150. infrahub/permissions/constants.py +2 -0
  151. infrahub/profiles/__init__.py +0 -0
  152. infrahub/profiles/node_applier.py +101 -0
  153. infrahub/profiles/queries/__init__.py +0 -0
  154. infrahub/profiles/queries/get_profile_data.py +98 -0
  155. infrahub/profiles/tasks.py +63 -0
  156. infrahub/proposed_change/tasks.py +67 -14
  157. infrahub/repositories/__init__.py +0 -0
  158. infrahub/repositories/create_repository.py +113 -0
  159. infrahub/server.py +9 -1
  160. infrahub/services/__init__.py +8 -5
  161. infrahub/services/adapters/http/__init__.py +5 -0
  162. infrahub/services/adapters/workflow/worker.py +14 -3
  163. infrahub/task_manager/event.py +5 -0
  164. infrahub/task_manager/models.py +7 -0
  165. infrahub/task_manager/task.py +73 -0
  166. infrahub/tasks/registry.py +6 -4
  167. infrahub/trigger/catalogue.py +4 -0
  168. infrahub/trigger/models.py +2 -0
  169. infrahub/trigger/setup.py +13 -4
  170. infrahub/trigger/tasks.py +6 -0
  171. infrahub/webhook/models.py +1 -1
  172. infrahub/workers/dependencies.py +3 -1
  173. infrahub/workers/infrahub_async.py +10 -2
  174. infrahub/workflows/catalogue.py +118 -3
  175. infrahub/workflows/initialization.py +21 -0
  176. infrahub/workflows/models.py +17 -2
  177. infrahub/workflows/utils.py +2 -1
  178. infrahub_sdk/branch.py +17 -8
  179. infrahub_sdk/checks.py +1 -1
  180. infrahub_sdk/client.py +376 -95
  181. infrahub_sdk/config.py +29 -2
  182. infrahub_sdk/convert_object_type.py +61 -0
  183. infrahub_sdk/ctl/branch.py +3 -0
  184. infrahub_sdk/ctl/check.py +2 -3
  185. infrahub_sdk/ctl/cli_commands.py +20 -12
  186. infrahub_sdk/ctl/config.py +8 -2
  187. infrahub_sdk/ctl/generator.py +6 -3
  188. infrahub_sdk/ctl/graphql.py +184 -0
  189. infrahub_sdk/ctl/repository.py +39 -1
  190. infrahub_sdk/ctl/schema.py +40 -10
  191. infrahub_sdk/ctl/task.py +110 -0
  192. infrahub_sdk/ctl/utils.py +4 -0
  193. infrahub_sdk/ctl/validate.py +5 -3
  194. infrahub_sdk/diff.py +4 -5
  195. infrahub_sdk/exceptions.py +2 -0
  196. infrahub_sdk/generator.py +7 -1
  197. infrahub_sdk/graphql/__init__.py +12 -0
  198. infrahub_sdk/graphql/constants.py +1 -0
  199. infrahub_sdk/graphql/plugin.py +85 -0
  200. infrahub_sdk/graphql/query.py +77 -0
  201. infrahub_sdk/{graphql.py → graphql/renderers.py} +88 -75
  202. infrahub_sdk/graphql/utils.py +40 -0
  203. infrahub_sdk/node/attribute.py +2 -0
  204. infrahub_sdk/node/node.py +28 -20
  205. infrahub_sdk/node/relationship.py +1 -3
  206. infrahub_sdk/playback.py +1 -2
  207. infrahub_sdk/protocols.py +54 -6
  208. infrahub_sdk/pytest_plugin/plugin.py +7 -4
  209. infrahub_sdk/pytest_plugin/utils.py +40 -0
  210. infrahub_sdk/repository.py +1 -2
  211. infrahub_sdk/schema/__init__.py +70 -4
  212. infrahub_sdk/schema/main.py +1 -0
  213. infrahub_sdk/schema/repository.py +8 -0
  214. infrahub_sdk/spec/models.py +7 -0
  215. infrahub_sdk/spec/object.py +54 -6
  216. infrahub_sdk/spec/processors/__init__.py +0 -0
  217. infrahub_sdk/spec/processors/data_processor.py +10 -0
  218. infrahub_sdk/spec/processors/factory.py +34 -0
  219. infrahub_sdk/spec/processors/range_expand_processor.py +56 -0
  220. infrahub_sdk/spec/range_expansion.py +118 -0
  221. infrahub_sdk/task/models.py +6 -4
  222. infrahub_sdk/timestamp.py +18 -6
  223. infrahub_sdk/transforms.py +1 -1
  224. {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/METADATA +9 -10
  225. {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/RECORD +233 -176
  226. infrahub_testcontainers/container.py +114 -2
  227. infrahub_testcontainers/docker-compose-cluster.test.yml +5 -0
  228. infrahub_testcontainers/docker-compose.test.yml +5 -0
  229. infrahub_testcontainers/models.py +2 -2
  230. infrahub_testcontainers/performance_test.py +4 -4
  231. infrahub/core/convert_object_type/conversion.py +0 -134
  232. {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/LICENSE.txt +0 -0
  233. {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/WHEEL +0 -0
  234. {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/entry_points.txt +0 -0
@@ -11,6 +11,7 @@ from infrahub import config
11
11
  from infrahub.core import registry
12
12
  from infrahub.core.constants import (
13
13
  GLOBAL_BRANCH_NAME,
14
+ PROFILE_NODE_RELATIONSHIP_IDENTIFIER,
14
15
  AttributeDBNodeType,
15
16
  RelationshipDirection,
16
17
  RelationshipHierarchyDirection,
@@ -43,7 +44,6 @@ class NodeToProcess:
43
44
 
44
45
  node_id: str
45
46
  node_uuid: str
46
- profile_uuids: list[str]
47
47
 
48
48
  updated_at: str
49
49
 
@@ -142,9 +142,22 @@ class NodeCreateAllQuery(NodeQuery):
142
142
  attributes_ipnetwork: list[AttributeCreateData] = []
143
143
  attributes_indexed: list[AttributeCreateData] = []
144
144
 
145
+ if self.node.has_display_label():
146
+ attributes_indexed.append(
147
+ self.node._display_label.get_node_attribute(node=self.node, at=at).get_create_data(
148
+ node_schema=self.node.get_schema()
149
+ )
150
+ )
151
+ if self.node.has_human_friendly_id():
152
+ attributes_indexed.append(
153
+ self.node._human_friendly_id.get_node_attribute(node=self.node, at=at).get_create_data(
154
+ node_schema=self.node.get_schema()
155
+ )
156
+ )
157
+
145
158
  for attr_name in self.node._attributes:
146
159
  attr: BaseAttribute = getattr(self.node, attr_name)
147
- attr_data = attr.get_create_data()
160
+ attr_data = attr.get_create_data(node_schema=self.node.get_schema())
148
161
  node_type = attr.get_db_node_type()
149
162
 
150
163
  if AttributeDBNodeType.IPHOST in node_type:
@@ -610,6 +623,7 @@ class NodeListGetAttributeQuery(Query):
610
623
 
611
624
  async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG002
612
625
  self.params["ids"] = self.ids
626
+ self.params["profile_relationship_name"] = PROFILE_NODE_RELATIONSHIP_IDENTIFIER
613
627
 
614
628
  branch_filter, branch_params = self.branch.get_query_filter_path(
615
629
  at=self.at, branch_agnostic=self.branch_agnostic
@@ -618,6 +632,7 @@ class NodeListGetAttributeQuery(Query):
618
632
 
619
633
  query = """
620
634
  MATCH (n:Node) WHERE n.uuid IN $ids
635
+ WITH n, exists((n)-[:IS_RELATED]-(:Relationship {name: $profile_relationship_name})) AS might_use_profile
621
636
  MATCH (n)-[:HAS_ATTRIBUTE]-(a:Attribute)
622
637
  """
623
638
  if self.fields:
@@ -627,61 +642,87 @@ class NodeListGetAttributeQuery(Query):
627
642
  self.add_to_query(query)
628
643
 
629
644
  query = """
630
- CALL (n, a) {
631
- MATCH (n)-[r:HAS_ATTRIBUTE]-(a:Attribute)
632
- WHERE %(branch_filter)s
633
- RETURN n as n1, r as r1, a as a1
634
- ORDER BY r.branch_level DESC, r.from DESC
635
- LIMIT 1
636
- }
637
- WITH n1 as n, r1, a1 as a
638
- WHERE r1.status = "active"
639
- WITH n, r1, a
640
- MATCH (a)-[r:HAS_VALUE]-(av:AttributeValue)
641
- WHERE %(branch_filter)s
642
- CALL (a, av) {
643
- MATCH (a)-[r:HAS_VALUE]-(av:AttributeValue)
644
- WHERE %(branch_filter)s
645
- RETURN a as a1, r as r2, av as av1
646
- ORDER BY r.branch_level DESC, r.from DESC
647
- LIMIT 1
648
- }
649
- WITH n, r1, a1 as a, r2, av1 as av
650
- WHERE r2.status = "active"
651
- WITH n, a, av, r1, r2
645
+ CALL (n, a) {
646
+ MATCH (n)-[r:HAS_ATTRIBUTE]-(a:Attribute)
647
+ WHERE %(branch_filter)s
648
+ RETURN r AS r1
649
+ ORDER BY r.branch_level DESC, r.from DESC
650
+ LIMIT 1
651
+ }
652
+ WITH n, r1, a, might_use_profile
653
+ WHERE r1.status = "active"
654
+ WITH n, r1, a, might_use_profile
655
+ CALL (a, might_use_profile) {
656
+ OPTIONAL MATCH (a)-[r:HAS_SOURCE]->(:CoreProfile)
657
+ WHERE might_use_profile = TRUE AND %(branch_filter)s
658
+ RETURN r.status = "active" AS has_active_profile
659
+ ORDER BY r.branch_level DESC, r.from DESC, r.status ASC
660
+ LIMIT 1
661
+ }
662
+ WITH *, has_active_profile = TRUE AS is_from_profile
663
+ CALL (a) {
664
+ MATCH (a)-[r:HAS_VALUE]-(av:AttributeValue)
665
+ WHERE %(branch_filter)s
666
+ RETURN r as r2, av
667
+ ORDER BY r.branch_level DESC, r.from DESC
668
+ LIMIT 1
669
+ }
670
+ WITH n, r1, a, r2, av, is_from_profile
671
+ WHERE r2.status = "active"
652
672
  """ % {"branch_filter": branch_filter}
653
673
  self.add_to_query(query)
654
674
 
655
- self.return_labels = ["n", "a", "av", "r1", "r2"]
675
+ self.return_labels = ["n", "a", "av", "r1", "r2", "is_from_profile"]
656
676
 
657
677
  # Add Is_Protected and Is_visible
658
- rel_isv_branch_filter, _ = self.branch.get_query_filter_path(
659
- at=self.at, branch_agnostic=self.branch_agnostic, variable_name="rel_isv"
660
- )
661
- rel_isp_branch_filter, _ = self.branch.get_query_filter_path(
662
- at=self.at, branch_agnostic=self.branch_agnostic, variable_name="rel_isp"
663
- )
664
678
  query = """
665
- MATCH (a)-[rel_isv:IS_VISIBLE]-(isv:Boolean)
666
- MATCH (a)-[rel_isp:IS_PROTECTED]-(isp:Boolean)
667
- WHERE (%(rel_isv_branch_filter)s) AND (%(rel_isp_branch_filter)s)
668
- """ % {"rel_isv_branch_filter": rel_isv_branch_filter, "rel_isp_branch_filter": rel_isp_branch_filter}
679
+ CALL (a) {
680
+ MATCH (a)-[r:IS_VISIBLE]-(isv:Boolean)
681
+ WHERE (%(branch_filter)s)
682
+ RETURN r AS rel_isv, isv
683
+ ORDER BY rel_isv.branch_level DESC, rel_isv.from DESC, rel_isv.status ASC
684
+ LIMIT 1
685
+ }
686
+ CALL (a) {
687
+ MATCH (a)-[r:IS_PROTECTED]-(isp:Boolean)
688
+ WHERE (%(branch_filter)s)
689
+ RETURN r AS rel_isp, isp
690
+ ORDER BY rel_isp.branch_level DESC, rel_isp.from DESC, rel_isp.status ASC
691
+ LIMIT 1
692
+ }
693
+ """ % {"branch_filter": branch_filter}
669
694
  self.add_to_query(query)
670
695
 
671
696
  self.return_labels.extend(["isv", "isp", "rel_isv", "rel_isp"])
672
697
 
673
698
  if self.include_source:
674
699
  query = """
675
- OPTIONAL MATCH (a)-[rel_source:HAS_SOURCE]-(source)
676
- WHERE all(r IN [rel_source] WHERE ( %(branch_filter)s ))
700
+ CALL (a) {
701
+ OPTIONAL MATCH (a)-[rel_source:HAS_SOURCE]-(source)
702
+ WHERE all(r IN [rel_source] WHERE ( %(branch_filter)s ))
703
+ RETURN source, rel_source
704
+ ORDER BY rel_source.branch_level DESC, rel_source.from DESC, rel_source.status ASC
705
+ LIMIT 1
706
+ }
707
+ WITH *,
708
+ CASE WHEN rel_source.status = "active" THEN source ELSE NULL END AS source,
709
+ CASE WHEN rel_source.status = "active" THEN rel_source ELSE NULL END AS rel_source
677
710
  """ % {"branch_filter": branch_filter}
678
711
  self.add_to_query(query)
679
712
  self.return_labels.extend(["source", "rel_source"])
680
713
 
681
714
  if self.include_owner:
682
715
  query = """
683
- OPTIONAL MATCH (a)-[rel_owner:HAS_OWNER]-(owner)
684
- WHERE all(r IN [rel_owner] WHERE ( %(branch_filter)s ))
716
+ CALL (a) {
717
+ OPTIONAL MATCH (a)-[rel_owner:HAS_OWNER]-(owner)
718
+ WHERE all(r IN [rel_owner] WHERE ( %(branch_filter)s ))
719
+ RETURN owner, rel_owner
720
+ ORDER BY rel_owner.branch_level DESC, rel_owner.from DESC, rel_owner.status ASC
721
+ LIMIT 1
722
+ }
723
+ WITH *,
724
+ CASE WHEN rel_owner.status = "active" THEN owner ELSE NULL END AS owner,
725
+ CASE WHEN rel_owner.status = "active" THEN rel_owner ELSE NULL END AS rel_owner
685
726
  """ % {"branch_filter": branch_filter}
686
727
  self.add_to_query(query)
687
728
  self.return_labels.extend(["owner", "rel_owner"])
@@ -712,6 +753,7 @@ class NodeListGetAttributeQuery(Query):
712
753
  def _extract_attribute_data(self, result: QueryResult) -> AttributeFromDB:
713
754
  attr = result.get_node("a")
714
755
  attr_value = result.get_node("av")
756
+ is_from_profile = result.get_as_type(label="is_from_profile", return_type=bool)
715
757
 
716
758
  data = AttributeFromDB(
717
759
  name=attr.get("name"),
@@ -723,6 +765,7 @@ class NodeListGetAttributeQuery(Query):
723
765
  updated_at=result.get_rel("r2").get("from"),
724
766
  value=attr_value.get("value"),
725
767
  is_default=attr_value.get("is_default"),
768
+ is_from_profile=is_from_profile,
726
769
  content=attr_value._properties,
727
770
  branch=self.branch.name,
728
771
  flag_properties={
@@ -878,6 +921,7 @@ class NodeListGetRelationshipsQuery(Query):
878
921
  RETURN DISTINCT n_uuid, rel_name, peer_uuid, direction
879
922
  """ % {"filters": rels_filter}
880
923
  self.add_to_query(query)
924
+ self.order_by = ["n_uuid", "rel_name", "peer_uuid", "direction"]
881
925
  self.return_labels = ["n_uuid", "rel_name", "peer_uuid", "direction"]
882
926
 
883
927
  def get_peers_group_by_node(self) -> GroupedPeerNodes:
@@ -946,6 +990,8 @@ class NodeListGetInfoQuery(Query):
946
990
  at=self.at, branch_agnostic=self.branch_agnostic
947
991
  )
948
992
  self.params.update(branch_params)
993
+ self.params["ids"] = self.ids
994
+ self.order_by = ["n.uuid"]
949
995
 
950
996
  query = """
951
997
  MATCH p = (root:Root)<-[:IS_PART_OF]-(n:Node)
@@ -959,16 +1005,11 @@ class NodeListGetInfoQuery(Query):
959
1005
  }
960
1006
  WITH n1 as n, r1 as rb
961
1007
  WHERE rb.status = "active"
962
- OPTIONAL MATCH profile_path = (n)-[:IS_RELATED]->(profile_r:Relationship)<-[:IS_RELATED]-(profile:Node)-[:IS_PART_OF]->(:Root)
963
- WHERE profile_r.name = "node__profile"
964
- AND profile.namespace = "Profile"
965
- AND all(r in relationships(profile_path) WHERE %(branch_filter)s and r.status = "active")
966
1008
  """ % {"branch_filter": branch_filter}
967
1009
 
968
1010
  self.add_to_query(query)
969
- self.params["ids"] = self.ids
970
1011
 
971
- self.return_labels = ["collect(profile.uuid) as profile_uuids", "n", "rb"]
1012
+ self.return_labels = ["n", "rb"]
972
1013
 
973
1014
  async def get_nodes(self, db: InfrahubDatabase, duplicate: bool = False) -> AsyncIterator[NodeToProcess]:
974
1015
  """Return all the node objects as NodeToProcess."""
@@ -982,24 +1023,11 @@ class NodeListGetInfoQuery(Query):
982
1023
  schema=schema,
983
1024
  node_id=result.get_node("n").element_id,
984
1025
  node_uuid=result.get_node("n").get("uuid"),
985
- profile_uuids=[str(puuid) for puuid in result.get("profile_uuids")],
986
1026
  updated_at=result.get_rel("rb").get("from"),
987
1027
  branch=node_branch,
988
1028
  labels=list(result.get_node("n").labels),
989
1029
  )
990
1030
 
991
- def get_profile_ids_by_node_id(self) -> dict[str, list[str]]:
992
- profile_id_map: dict[str, list[str]] = {}
993
- for result in self.results:
994
- node_id = result.get_node("n").get("uuid")
995
- profile_ids = result.get("profile_uuids")
996
- if not node_id or not profile_ids:
997
- continue
998
- if node_id not in profile_id_map:
999
- profile_id_map[node_id] = []
1000
- profile_id_map[node_id].extend(profile_ids)
1001
- return profile_id_map
1002
-
1003
1031
 
1004
1032
  class FieldAttributeRequirementType(Enum):
1005
1033
  FILTER = "filter"
@@ -1016,7 +1044,7 @@ class FieldAttributeRequirement:
1016
1044
  types: list[FieldAttributeRequirementType] = dataclass_field(default_factory=list)
1017
1045
 
1018
1046
  @property
1019
- def supports_profile(self) -> bool:
1047
+ def is_attribute_value(self) -> bool:
1020
1048
  return bool(self.field and self.field.is_attribute and self.field_attr_name in ("value", "values", "isnull"))
1021
1049
 
1022
1050
  @property
@@ -1027,26 +1055,10 @@ class FieldAttributeRequirement:
1027
1055
  def is_order(self) -> bool:
1028
1056
  return FieldAttributeRequirementType.ORDER in self.types
1029
1057
 
1030
- @property
1031
- def is_default_query_variable(self) -> str:
1032
- return f"attr{self.index}_is_default"
1033
-
1034
1058
  @property
1035
1059
  def node_value_query_variable(self) -> str:
1036
1060
  return f"attr{self.index}_node_value"
1037
1061
 
1038
- @property
1039
- def profile_value_query_variable(self) -> str:
1040
- return f"attr{self.index}_profile_value"
1041
-
1042
- @property
1043
- def profile_final_value_query_variable(self) -> str:
1044
- return f"attr{self.index}_final_profile_value"
1045
-
1046
- @property
1047
- def final_value_query_variable(self) -> str:
1048
- return f"attr{self.index}_final_value"
1049
-
1050
1062
  @property
1051
1063
  def comparison_operator(self) -> str:
1052
1064
  if self.field_attr_name == "isnull":
@@ -1182,7 +1194,6 @@ class NodeGetListQuery(Query):
1182
1194
  self.params["node_ids"] = self.filters["ids"]
1183
1195
 
1184
1196
  field_attribute_requirements = self._get_field_requirements(disable_order=disable_order)
1185
- use_profiles = any(far for far in field_attribute_requirements if far.supports_profile)
1186
1197
  await self._add_node_filter_attributes(
1187
1198
  db=db, field_attribute_requirements=field_attribute_requirements, branch_filter=branch_filter
1188
1199
  )
@@ -1194,21 +1205,11 @@ class NodeGetListQuery(Query):
1194
1205
  for far in field_attribute_requirements:
1195
1206
  if not far.is_order:
1196
1207
  continue
1197
- if far.supports_profile:
1198
- self.order_by.append(far.final_value_query_variable)
1199
- continue
1200
1208
  self.order_by.append(far.node_value_query_variable)
1201
1209
 
1202
1210
  # Always order by uuid to guarantee pagination, see https://github.com/opsmill/infrahub/pull/4704.
1203
1211
  self.order_by.append("n.uuid")
1204
1212
 
1205
- if use_profiles:
1206
- await self._add_profiles_per_node_query(db=db, branch_filter=branch_filter)
1207
- await self._add_profile_attributes(
1208
- db=db, field_attribute_requirements=field_attribute_requirements, branch_filter=branch_filter
1209
- )
1210
- await self._add_profile_rollups(field_attribute_requirements=field_attribute_requirements)
1211
-
1212
1213
  self._add_final_filter(field_attribute_requirements=field_attribute_requirements)
1213
1214
 
1214
1215
  async def _add_node_filter_attributes(
@@ -1226,8 +1227,6 @@ class NodeGetListQuery(Query):
1226
1227
 
1227
1228
  for far in field_attribute_requirements:
1228
1229
  extra_tail_properties = {far.node_value_query_variable: "value"}
1229
- if far.supports_profile:
1230
- extra_tail_properties[far.is_default_query_variable] = "is_default"
1231
1230
  subquery, subquery_params, subquery_result_name = await build_subquery_filter(
1232
1231
  db=db,
1233
1232
  field=far.field,
@@ -1238,7 +1237,6 @@ class NodeGetListQuery(Query):
1238
1237
  branch=self.branch,
1239
1238
  subquery_idx=far.index,
1240
1239
  partial_match=self.partial_match,
1241
- support_profiles=far.supports_profile,
1242
1240
  extra_tail_properties=extra_tail_properties,
1243
1241
  )
1244
1242
  for query_var in extra_tail_properties:
@@ -1278,9 +1276,6 @@ class NodeGetListQuery(Query):
1278
1276
  for far in field_attribute_requirements:
1279
1277
  if far.field is None:
1280
1278
  continue
1281
- extra_tail_properties = {}
1282
- if far.supports_profile:
1283
- extra_tail_properties[far.is_default_query_variable] = "is_default"
1284
1279
 
1285
1280
  subquery, subquery_params, _ = await build_subquery_order(
1286
1281
  db=db,
@@ -1291,11 +1286,7 @@ class NodeGetListQuery(Query):
1291
1286
  branch=self.branch,
1292
1287
  subquery_idx=far.index,
1293
1288
  result_prefix=far.node_value_query_variable,
1294
- support_profiles=far.supports_profile,
1295
- extra_tail_properties=extra_tail_properties,
1296
1289
  )
1297
- for query_var in extra_tail_properties:
1298
- self._track_variable(query_var)
1299
1290
  self._track_variable(far.node_value_query_variable)
1300
1291
  with_str = ", ".join(self._get_tracked_variables())
1301
1292
 
@@ -1309,122 +1300,11 @@ class NodeGetListQuery(Query):
1309
1300
  self.add_to_query(sort_query)
1310
1301
  self.params.update(sort_params)
1311
1302
 
1312
- async def _add_profiles_per_node_query(self, db: InfrahubDatabase, branch_filter: str) -> None:
1313
- with_str = ", ".join(self._get_tracked_variables())
1314
- froms_str = db.render_list_comprehension(items="relationships(profile_path)", item_name="from")
1315
- profiles_per_node_query = (
1316
- """
1317
- CALL (n) {
1318
- OPTIONAL MATCH profile_path = (n)-[:IS_RELATED]->(profile_r:Relationship)<-[:IS_RELATED]-(maybe_profile_n:Node)-[:IS_PART_OF]->(:Root)
1319
- WHERE profile_r.name = "node__profile"
1320
- AND all(r in relationships(profile_path) WHERE %(branch_filter)s)
1321
- WITH
1322
- maybe_profile_n,
1323
- profile_path,
1324
- reduce(br_lvl = 0, r in relationships(profile_path) | br_lvl + r.branch_level) AS branch_level,
1325
- %(froms_str)s AS froms,
1326
- all(r in relationships(profile_path) WHERE r.status = "active") AS is_active
1327
- RETURN maybe_profile_n, is_active, branch_level, froms
1328
- }
1329
- WITH %(with_str)s, maybe_profile_n, branch_level, froms, is_active
1330
- ORDER BY n.uuid, maybe_profile_n.uuid, branch_level DESC, froms[-1] DESC, froms[-2] DESC, froms[-3] DESC
1331
- WITH %(with_str)s, maybe_profile_n, collect(is_active) as ordered_is_actives
1332
- WITH %(with_str)s, CASE
1333
- WHEN ordered_is_actives[0] = True THEN maybe_profile_n ELSE NULL
1334
- END AS profile_n
1335
- CALL (profile_n) {
1336
- OPTIONAL MATCH profile_priority_path = (profile_n)-[pr1:HAS_ATTRIBUTE]->(a:Attribute)-[pr2:HAS_VALUE]->(av:AttributeValue)
1337
- WHERE a.name = "profile_priority"
1338
- AND all(r in relationships(profile_priority_path) WHERE %(branch_filter)s and r.status = "active")
1339
- RETURN av.value as profile_priority
1340
- ORDER BY pr1.branch_level + pr2.branch_level DESC, pr2.from DESC, pr1.from DESC
1341
- LIMIT 1
1342
- }
1343
- WITH %(with_str)s, profile_n, profile_priority
1344
- """
1345
- ) % {"branch_filter": branch_filter, "with_str": with_str, "froms_str": froms_str}
1346
- self.add_to_query(profiles_per_node_query)
1347
- self._track_variable("profile_n")
1348
- self._track_variable("profile_priority")
1349
-
1350
- async def _add_profile_attributes(
1351
- self, db: InfrahubDatabase, field_attribute_requirements: list[FieldAttributeRequirement], branch_filter: str
1352
- ) -> None:
1353
- attributes_queries: list[str] = []
1354
- attributes_params: dict[str, Any] = {}
1355
- profile_attributes = [far for far in field_attribute_requirements if far.supports_profile]
1356
-
1357
- for profile_attr in profile_attributes:
1358
- if not profile_attr.field:
1359
- continue
1360
- subquery, subquery_params, _ = await build_subquery_order(
1361
- db=db,
1362
- field=profile_attr.field,
1363
- node_alias="profile_n",
1364
- name=profile_attr.field_name,
1365
- order_by=profile_attr.field_attr_name,
1366
- branch_filter=branch_filter,
1367
- branch=self.branch,
1368
- subquery_idx=profile_attr.index,
1369
- result_prefix=profile_attr.profile_value_query_variable,
1370
- support_profiles=False,
1371
- )
1372
- attributes_params.update(subquery_params)
1373
- self._track_variable(profile_attr.profile_value_query_variable)
1374
- with_str = ", ".join(self._get_tracked_variables())
1375
-
1376
- attributes_queries.append("CALL (profile_n) {")
1377
- attributes_queries.append(subquery)
1378
- attributes_queries.append("}")
1379
- attributes_queries.append(f"WITH {with_str}")
1380
-
1381
- self.add_to_query(attributes_queries)
1382
- self.params.update(attributes_params)
1383
-
1384
- async def _add_profile_rollups(self, field_attribute_requirements: list[FieldAttributeRequirement]) -> None:
1385
- profile_attributes = [far for far in field_attribute_requirements if far.supports_profile]
1386
- profile_value_collects = []
1387
- for profile_attr in profile_attributes:
1388
- self._untrack_variable(profile_attr.profile_value_query_variable)
1389
- profile_value_collects.append(
1390
- f"""head(
1391
- reduce(
1392
- non_null_values = [], v in collect({profile_attr.profile_value_query_variable}) |
1393
- CASE WHEN v IS NOT NULL AND v <> "NULL" THEN non_null_values + [v] ELSE non_null_values END
1394
- )
1395
- ) as {profile_attr.profile_final_value_query_variable}"""
1396
- )
1397
- self._untrack_variable("profile_n")
1398
- self._untrack_variable("profile_priority")
1399
- profile_rollup_with_str = ", ".join(self._get_tracked_variables() + profile_value_collects)
1400
- profile_rollup_query = f"""
1401
- ORDER BY n.uuid, profile_priority ASC, profile_n.uuid ASC
1402
- WITH {profile_rollup_with_str}
1403
- """
1404
- self.add_to_query(profile_rollup_query)
1405
- for profile_attr in profile_attributes:
1406
- self._track_variable(profile_attr.profile_final_value_query_variable)
1407
-
1408
- final_value_with = []
1409
- for profile_attr in profile_attributes:
1410
- final_value_with.append(f"""
1411
- CASE
1412
- WHEN {profile_attr.is_default_query_variable} AND {profile_attr.profile_final_value_query_variable} IS NOT NULL
1413
- THEN {profile_attr.profile_final_value_query_variable}
1414
- ELSE {profile_attr.node_value_query_variable}
1415
- END AS {profile_attr.final_value_query_variable}
1416
- """)
1417
- self._untrack_variable(profile_attr.is_default_query_variable)
1418
- self._untrack_variable(profile_attr.profile_final_value_query_variable)
1419
- self._untrack_variable(profile_attr.node_value_query_variable)
1420
- final_value_with_str = ", ".join(self._get_tracked_variables() + final_value_with)
1421
- self.add_to_query(f"WITH {final_value_with_str}")
1422
-
1423
1303
  def _add_final_filter(self, field_attribute_requirements: list[FieldAttributeRequirement]) -> None:
1424
1304
  where_parts = []
1425
1305
  where_str = ""
1426
1306
  for far in field_attribute_requirements:
1427
- if not far.is_filter or not far.supports_profile:
1307
+ if not far.is_filter or not far.is_attribute_value:
1428
1308
  continue
1429
1309
  var_name = f"final_attr_value{far.index}"
1430
1310
  self.params[var_name] = far.field_attr_comparison_value
@@ -1433,11 +1313,11 @@ class NodeGetListQuery(Query):
1433
1313
  # If the any filter is an array/list
1434
1314
  var_array = f"{var_name}_array"
1435
1315
  where_parts.append(
1436
- f"any({var_array} IN ${var_name} WHERE toLower(toString({far.final_value_query_variable})) CONTAINS toLower({var_array}))"
1316
+ f"any({var_array} IN ${var_name} WHERE toLower(toString({far.node_value_query_variable})) CONTAINS toLower({var_array}))"
1437
1317
  )
1438
1318
  else:
1439
1319
  where_parts.append(
1440
- f"toLower(toString({far.final_value_query_variable})) CONTAINS toLower(toString(${var_name}))"
1320
+ f"toLower(toString({far.node_value_query_variable})) CONTAINS toLower(toString(${var_name}))"
1441
1321
  )
1442
1322
  continue
1443
1323
  if far.field and isinstance(far.field, AttributeSchema) and far.field.kind == "List":
@@ -1446,10 +1326,10 @@ class NodeGetListQuery(Query):
1446
1326
  else:
1447
1327
  self.params[var_name] = build_regex_attrs(values=[far.field_attr_comparison_value])
1448
1328
 
1449
- where_parts.append(f"toString({far.final_value_query_variable}) =~ ${var_name}")
1329
+ where_parts.append(f"toString({far.node_value_query_variable}) =~ ${var_name}")
1450
1330
  continue
1451
1331
 
1452
- where_parts.append(f"{far.final_value_query_variable} {far.comparison_operator} ${var_name}")
1332
+ where_parts.append(f"{far.node_value_query_variable} {far.comparison_operator} ${var_name}")
1453
1333
  if where_parts:
1454
1334
  where_str = "WHERE " + " AND ".join(where_parts)
1455
1335
  self.add_to_query(where_str)
@@ -350,17 +350,20 @@ class RelationshipUpdatePropertyQuery(RelationshipQuery):
350
350
 
351
351
  def __init__(
352
352
  self,
353
- properties_to_update: list[str],
354
- data: RelationshipPeerData,
353
+ rel_node_id: str,
354
+ flag_properties_to_update: dict[str, bool],
355
+ node_properties_to_update: dict[str, str],
355
356
  **kwargs,
356
357
  ):
357
- self.properties_to_update = properties_to_update
358
- self.data = data
359
-
358
+ self.rel_node_id = rel_node_id
359
+ if not flag_properties_to_update and not node_properties_to_update:
360
+ raise ValueError("Either flag_properties_to_update or node_properties_to_update must be set")
361
+ self.flag_properties_to_update = flag_properties_to_update
362
+ self.node_properties_to_update = node_properties_to_update
360
363
  super().__init__(**kwargs)
361
364
 
362
365
  async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG002
363
- self.params["rel_node_id"] = self.data.rel_node_id
366
+ self.params["rel_node_id"] = self.rel_node_id
364
367
  self.params["branch"] = self.branch.name
365
368
  self.params["branch_level"] = self.branch.hierarchy_level
366
369
  self.params["at"] = self.at.to_string()
@@ -370,36 +373,51 @@ class RelationshipUpdatePropertyQuery(RelationshipQuery):
370
373
  """
371
374
  self.add_to_query(query)
372
375
 
373
- self.query_add_all_flag_property_merge()
374
376
  self.query_add_all_node_property_merge()
377
+ self.query_add_all_flag_property_merge()
375
378
 
376
- self.query_add_all_flag_property_create()
377
379
  self.query_add_all_node_property_create()
380
+ self.query_add_all_flag_property_create()
378
381
 
379
382
  def query_add_all_flag_property_merge(self) -> None:
380
- for prop_name in self.rel._flag_properties:
381
- if prop_name in self.properties_to_update:
382
- self.query_add_flag_property_merge(name=prop_name)
383
+ for prop_name, prop_value in self.flag_properties_to_update.items():
384
+ self.query_add_flag_property_merge(name=prop_name, value=prop_value)
383
385
 
384
- def query_add_flag_property_merge(self, name: str) -> None:
386
+ def query_add_flag_property_merge(self, name: str, value: bool) -> None:
385
387
  self.add_to_query("MERGE (prop_%s:Boolean { value: $prop_%s })" % (name, name))
386
- self.params[f"prop_{name}"] = getattr(self.rel, name)
388
+ self.params[f"prop_{name}"] = value
387
389
  self.return_labels.append(f"prop_{name}")
388
390
 
389
391
  def query_add_all_node_property_merge(self) -> None:
390
- for prop_name in self.rel._node_properties:
391
- if prop_name in self.properties_to_update:
392
- self.query_add_node_property_merge(name=prop_name)
392
+ branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at)
393
+ self.params.update(branch_params)
393
394
 
394
- def query_add_node_property_merge(self, name: str) -> None:
395
- self.add_to_query("MERGE (prop_%s:Node { uuid: $prop_%s })" % (name, name))
396
- self.params[f"prop_{name}"] = getattr(self.rel, f"{name}_id")
397
- self.return_labels.append(f"prop_{name}")
395
+ for prop_name, prop_value in self.node_properties_to_update.items():
396
+ self.params[f"prop_{prop_name}"] = prop_value
397
+ if self.branch.is_default or self.branch.is_global:
398
+ node_query = """
399
+ MATCH (prop_%(prop_name)s:Node {uuid: $prop_%(prop_name)s })-[r_%(prop_name)s:IS_PART_OF]->(:Root)
400
+ WHERE r_%(prop_name)s.branch IN $branch0
401
+ AND r_%(prop_name)s.status = "active"
402
+ AND r_%(prop_name)s.from <= $at AND (r_%(prop_name)s.to IS NULL OR r_%(prop_name)s.to > $at)
403
+ WITH *
404
+ LIMIT 1
405
+ """ % {"prop_name": prop_name}
406
+ else:
407
+ node_query = """
408
+ MATCH (prop_%(prop_name)s:Node {uuid: $prop_%(prop_name)s })-[r_%(prop_name)s:IS_PART_OF]->(:Root)
409
+ WHERE all(r in [r_%(prop_name)s] WHERE %(branch_filter)s)
410
+ ORDER BY r_%(prop_name)s.branch_level DESC, r_%(prop_name)s.from DESC, r_%(prop_name)s.status ASC
411
+ LIMIT 1
412
+ WITH *
413
+ WHERE r_%(prop_name)s.status = "active"
414
+ """ % {"branch_filter": branch_filter, "prop_name": prop_name}
415
+ self.add_to_query(node_query)
416
+ self.return_labels.append(f"prop_{prop_name}")
398
417
 
399
418
  def query_add_all_flag_property_create(self) -> None:
400
- for prop_name in self.rel._flag_properties:
401
- if prop_name in self.properties_to_update:
402
- self.query_add_flag_property_create(name=prop_name)
419
+ for prop_name in self.flag_properties_to_update:
420
+ self.query_add_flag_property_create(name=prop_name)
403
421
 
404
422
  def query_add_flag_property_create(self, name: str) -> None:
405
423
  query = """
@@ -411,9 +429,8 @@ class RelationshipUpdatePropertyQuery(RelationshipQuery):
411
429
  self.add_to_query(query)
412
430
 
413
431
  def query_add_all_node_property_create(self) -> None:
414
- for prop_name in self.rel._node_properties:
415
- if prop_name in self.properties_to_update:
416
- self.query_add_node_property_create(name=prop_name)
432
+ for prop_name in self.node_properties_to_update:
433
+ self.query_add_node_property_create(name=prop_name)
417
434
 
418
435
  def query_add_node_property_create(self, name: str) -> None:
419
436
  query = """
@@ -1019,6 +1036,7 @@ class RelationshipCountPerNodeQuery(Query):
1019
1036
  """ % {"branch_filter": branch_filter, "path": path}
1020
1037
 
1021
1038
  self.add_to_query(query)
1039
+ self.order_by = ["peer_node.uuid"]
1022
1040
  self.return_labels = ["peer_node.uuid", "COUNT(peer_node.uuid) as nbr_peers"]
1023
1041
 
1024
1042
  async def get_count_per_peer(self) -> dict[str, int]:
@@ -25,12 +25,8 @@ async def build_subquery_filter(
25
25
  partial_match: bool = False,
26
26
  optional_match: bool = False,
27
27
  result_prefix: str = "filter",
28
- support_profiles: bool = False,
29
28
  extra_tail_properties: dict[str, str] | None = None,
30
29
  ) -> tuple[str, dict[str, Any], str]:
31
- support_profiles = (
32
- support_profiles and field and field.is_attribute and filter_name in ("value", "values", "isnull")
33
- )
34
30
  params = {}
35
31
  prefix = f"{result_prefix}{subquery_idx}"
36
32
 
@@ -52,7 +48,6 @@ async def build_subquery_filter(
52
48
  param_prefix=prefix,
53
49
  db=db,
54
50
  partial_match=partial_match,
55
- support_profiles=support_profiles,
56
51
  )
57
52
  params.update(field_params)
58
53
 
@@ -109,10 +104,8 @@ async def build_subquery_order(
109
104
  branch: Branch = None,
110
105
  subquery_idx: int = 1,
111
106
  result_prefix: str | None = None,
112
- support_profiles: bool = False,
113
107
  extra_tail_properties: dict[str, str] | None = None,
114
108
  ) -> tuple[str, dict[str, Any], str]:
115
- support_profiles = support_profiles and field and field.is_attribute and order_by in ("value", "values")
116
109
  params = {}
117
110
  prefix = result_prefix or f"order{subquery_idx}"
118
111
 
@@ -124,7 +117,6 @@ async def build_subquery_order(
124
117
  filter_value=None,
125
118
  branch=branch,
126
119
  param_prefix=prefix,
127
- support_profiles=support_profiles,
128
120
  )
129
121
  params.update(field_params)
130
122