exonware-xwnode 0.0.1.21__py3-none-any.whl → 0.0.1.23__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 (250) hide show
  1. exonware/__init__.py +8 -1
  2. exonware/xwnode/__init__.py +18 -5
  3. exonware/xwnode/add_strategy_types.py +165 -0
  4. exonware/xwnode/base.py +7 -5
  5. exonware/xwnode/common/__init__.py +1 -1
  6. exonware/xwnode/common/graph/__init__.py +30 -0
  7. exonware/xwnode/common/graph/caching.py +131 -0
  8. exonware/xwnode/common/graph/contracts.py +100 -0
  9. exonware/xwnode/common/graph/errors.py +44 -0
  10. exonware/xwnode/common/graph/indexing.py +260 -0
  11. exonware/xwnode/common/graph/manager.py +568 -0
  12. exonware/xwnode/common/management/__init__.py +3 -5
  13. exonware/xwnode/common/management/manager.py +9 -9
  14. exonware/xwnode/common/management/migration.py +6 -6
  15. exonware/xwnode/common/monitoring/__init__.py +3 -5
  16. exonware/xwnode/common/monitoring/metrics.py +7 -3
  17. exonware/xwnode/common/monitoring/pattern_detector.py +2 -2
  18. exonware/xwnode/common/monitoring/performance_monitor.py +6 -2
  19. exonware/xwnode/common/patterns/__init__.py +3 -5
  20. exonware/xwnode/common/patterns/advisor.py +1 -1
  21. exonware/xwnode/common/patterns/flyweight.py +6 -2
  22. exonware/xwnode/common/patterns/registry.py +203 -184
  23. exonware/xwnode/common/utils/__init__.py +25 -11
  24. exonware/xwnode/common/utils/simple.py +1 -1
  25. exonware/xwnode/config.py +3 -8
  26. exonware/xwnode/contracts.py +4 -105
  27. exonware/xwnode/defs.py +413 -159
  28. exonware/xwnode/edges/strategies/__init__.py +86 -4
  29. exonware/xwnode/edges/strategies/_base_edge.py +2 -2
  30. exonware/xwnode/edges/strategies/adj_list.py +287 -121
  31. exonware/xwnode/edges/strategies/adj_matrix.py +316 -222
  32. exonware/xwnode/edges/strategies/base.py +1 -1
  33. exonware/xwnode/edges/strategies/{edge_bidir_wrapper.py → bidir_wrapper.py} +45 -4
  34. exonware/xwnode/edges/strategies/bitemporal.py +520 -0
  35. exonware/xwnode/edges/strategies/{edge_block_adj_matrix.py → block_adj_matrix.py} +77 -6
  36. exonware/xwnode/edges/strategies/bv_graph.py +664 -0
  37. exonware/xwnode/edges/strategies/compressed_graph.py +217 -0
  38. exonware/xwnode/edges/strategies/{edge_coo.py → coo.py} +46 -4
  39. exonware/xwnode/edges/strategies/{edge_csc.py → csc.py} +45 -4
  40. exonware/xwnode/edges/strategies/{edge_csr.py → csr.py} +94 -12
  41. exonware/xwnode/edges/strategies/{edge_dynamic_adj_list.py → dynamic_adj_list.py} +46 -4
  42. exonware/xwnode/edges/strategies/edge_list.py +168 -0
  43. exonware/xwnode/edges/strategies/edge_property_store.py +2 -2
  44. exonware/xwnode/edges/strategies/euler_tour.py +560 -0
  45. exonware/xwnode/edges/strategies/{edge_flow_network.py → flow_network.py} +2 -2
  46. exonware/xwnode/edges/strategies/graphblas.py +449 -0
  47. exonware/xwnode/edges/strategies/hnsw.py +637 -0
  48. exonware/xwnode/edges/strategies/hop2_labels.py +467 -0
  49. exonware/xwnode/edges/strategies/{edge_hyperedge_set.py → hyperedge_set.py} +2 -2
  50. exonware/xwnode/edges/strategies/incidence_matrix.py +250 -0
  51. exonware/xwnode/edges/strategies/k2_tree.py +613 -0
  52. exonware/xwnode/edges/strategies/link_cut.py +626 -0
  53. exonware/xwnode/edges/strategies/multiplex.py +532 -0
  54. exonware/xwnode/edges/strategies/{edge_neural_graph.py → neural_graph.py} +2 -2
  55. exonware/xwnode/edges/strategies/{edge_octree.py → octree.py} +69 -11
  56. exonware/xwnode/edges/strategies/{edge_quadtree.py → quadtree.py} +66 -10
  57. exonware/xwnode/edges/strategies/roaring_adj.py +438 -0
  58. exonware/xwnode/edges/strategies/{edge_rtree.py → rtree.py} +43 -5
  59. exonware/xwnode/edges/strategies/{edge_temporal_edgeset.py → temporal_edgeset.py} +24 -5
  60. exonware/xwnode/edges/strategies/{edge_tree_graph_basic.py → tree_graph_basic.py} +78 -7
  61. exonware/xwnode/edges/strategies/{edge_weighted_graph.py → weighted_graph.py} +188 -10
  62. exonware/xwnode/errors.py +3 -6
  63. exonware/xwnode/facade.py +20 -20
  64. exonware/xwnode/nodes/strategies/__init__.py +29 -9
  65. exonware/xwnode/nodes/strategies/adjacency_list.py +650 -177
  66. exonware/xwnode/nodes/strategies/aho_corasick.py +358 -183
  67. exonware/xwnode/nodes/strategies/array_list.py +36 -3
  68. exonware/xwnode/nodes/strategies/art.py +581 -0
  69. exonware/xwnode/nodes/strategies/{node_avl_tree.py → avl_tree.py} +77 -6
  70. exonware/xwnode/nodes/strategies/{node_b_plus_tree.py → b_plus_tree.py} +81 -40
  71. exonware/xwnode/nodes/strategies/{node_btree.py → b_tree.py} +79 -9
  72. exonware/xwnode/nodes/strategies/base.py +469 -98
  73. exonware/xwnode/nodes/strategies/{node_bitmap.py → bitmap.py} +12 -12
  74. exonware/xwnode/nodes/strategies/{node_bitset_dynamic.py → bitset_dynamic.py} +11 -11
  75. exonware/xwnode/nodes/strategies/{node_bloom_filter.py → bloom_filter.py} +15 -2
  76. exonware/xwnode/nodes/strategies/bloomier_filter.py +519 -0
  77. exonware/xwnode/nodes/strategies/bw_tree.py +531 -0
  78. exonware/xwnode/nodes/strategies/contracts.py +1 -1
  79. exonware/xwnode/nodes/strategies/{node_count_min_sketch.py → count_min_sketch.py} +3 -2
  80. exonware/xwnode/nodes/strategies/{node_cow_tree.py → cow_tree.py} +135 -13
  81. exonware/xwnode/nodes/strategies/crdt_map.py +629 -0
  82. exonware/xwnode/nodes/strategies/{node_cuckoo_hash.py → cuckoo_hash.py} +2 -2
  83. exonware/xwnode/nodes/strategies/{node_xdata_optimized.py → data_interchange_optimized.py} +21 -4
  84. exonware/xwnode/nodes/strategies/dawg.py +876 -0
  85. exonware/xwnode/nodes/strategies/deque.py +321 -153
  86. exonware/xwnode/nodes/strategies/extendible_hash.py +93 -0
  87. exonware/xwnode/nodes/strategies/{node_fenwick_tree.py → fenwick_tree.py} +111 -19
  88. exonware/xwnode/nodes/strategies/hamt.py +403 -0
  89. exonware/xwnode/nodes/strategies/hash_map.py +354 -67
  90. exonware/xwnode/nodes/strategies/heap.py +105 -5
  91. exonware/xwnode/nodes/strategies/hopscotch_hash.py +525 -0
  92. exonware/xwnode/nodes/strategies/{node_hyperloglog.py → hyperloglog.py} +6 -5
  93. exonware/xwnode/nodes/strategies/interval_tree.py +742 -0
  94. exonware/xwnode/nodes/strategies/kd_tree.py +703 -0
  95. exonware/xwnode/nodes/strategies/learned_index.py +533 -0
  96. exonware/xwnode/nodes/strategies/linear_hash.py +93 -0
  97. exonware/xwnode/nodes/strategies/linked_list.py +316 -119
  98. exonware/xwnode/nodes/strategies/{node_lsm_tree.py → lsm_tree.py} +219 -15
  99. exonware/xwnode/nodes/strategies/masstree.py +130 -0
  100. exonware/xwnode/nodes/strategies/{node_persistent_tree.py → persistent_tree.py} +149 -9
  101. exonware/xwnode/nodes/strategies/priority_queue.py +544 -132
  102. exonware/xwnode/nodes/strategies/queue.py +249 -120
  103. exonware/xwnode/nodes/strategies/{node_red_black_tree.py → red_black_tree.py} +183 -72
  104. exonware/xwnode/nodes/strategies/{node_roaring_bitmap.py → roaring_bitmap.py} +19 -6
  105. exonware/xwnode/nodes/strategies/rope.py +717 -0
  106. exonware/xwnode/nodes/strategies/{node_segment_tree.py → segment_tree.py} +106 -106
  107. exonware/xwnode/nodes/strategies/{node_set_hash.py → set_hash.py} +30 -29
  108. exonware/xwnode/nodes/strategies/{node_skip_list.py → skip_list.py} +74 -6
  109. exonware/xwnode/nodes/strategies/sparse_matrix.py +427 -131
  110. exonware/xwnode/nodes/strategies/{node_splay_tree.py → splay_tree.py} +55 -6
  111. exonware/xwnode/nodes/strategies/stack.py +244 -112
  112. exonware/xwnode/nodes/strategies/{node_suffix_array.py → suffix_array.py} +5 -1
  113. exonware/xwnode/nodes/strategies/t_tree.py +94 -0
  114. exonware/xwnode/nodes/strategies/{node_treap.py → treap.py} +75 -6
  115. exonware/xwnode/nodes/strategies/{node_tree_graph_hybrid.py → tree_graph_hybrid.py} +46 -5
  116. exonware/xwnode/nodes/strategies/trie.py +153 -9
  117. exonware/xwnode/nodes/strategies/union_find.py +111 -5
  118. exonware/xwnode/nodes/strategies/veb_tree.py +856 -0
  119. exonware/xwnode/strategies/__init__.py +5 -51
  120. exonware/xwnode/version.py +3 -3
  121. {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/METADATA +23 -3
  122. exonware_xwnode-0.0.1.23.dist-info/RECORD +130 -0
  123. exonware/xwnode/edges/strategies/edge_adj_list.py +0 -353
  124. exonware/xwnode/edges/strategies/edge_adj_matrix.py +0 -445
  125. exonware/xwnode/nodes/strategies/_base_node.py +0 -307
  126. exonware/xwnode/nodes/strategies/node_aho_corasick.py +0 -525
  127. exonware/xwnode/nodes/strategies/node_array_list.py +0 -179
  128. exonware/xwnode/nodes/strategies/node_hash_map.py +0 -273
  129. exonware/xwnode/nodes/strategies/node_heap.py +0 -196
  130. exonware/xwnode/nodes/strategies/node_linked_list.py +0 -413
  131. exonware/xwnode/nodes/strategies/node_trie.py +0 -257
  132. exonware/xwnode/nodes/strategies/node_union_find.py +0 -192
  133. exonware/xwnode/queries/executors/__init__.py +0 -47
  134. exonware/xwnode/queries/executors/advanced/__init__.py +0 -37
  135. exonware/xwnode/queries/executors/advanced/aggregate_executor.py +0 -50
  136. exonware/xwnode/queries/executors/advanced/ask_executor.py +0 -50
  137. exonware/xwnode/queries/executors/advanced/construct_executor.py +0 -50
  138. exonware/xwnode/queries/executors/advanced/describe_executor.py +0 -50
  139. exonware/xwnode/queries/executors/advanced/for_loop_executor.py +0 -50
  140. exonware/xwnode/queries/executors/advanced/foreach_executor.py +0 -50
  141. exonware/xwnode/queries/executors/advanced/join_executor.py +0 -50
  142. exonware/xwnode/queries/executors/advanced/let_executor.py +0 -50
  143. exonware/xwnode/queries/executors/advanced/mutation_executor.py +0 -50
  144. exonware/xwnode/queries/executors/advanced/options_executor.py +0 -50
  145. exonware/xwnode/queries/executors/advanced/pipe_executor.py +0 -50
  146. exonware/xwnode/queries/executors/advanced/subscribe_executor.py +0 -50
  147. exonware/xwnode/queries/executors/advanced/subscription_executor.py +0 -50
  148. exonware/xwnode/queries/executors/advanced/union_executor.py +0 -50
  149. exonware/xwnode/queries/executors/advanced/window_executor.py +0 -51
  150. exonware/xwnode/queries/executors/advanced/with_cte_executor.py +0 -50
  151. exonware/xwnode/queries/executors/aggregation/__init__.py +0 -21
  152. exonware/xwnode/queries/executors/aggregation/avg_executor.py +0 -50
  153. exonware/xwnode/queries/executors/aggregation/count_executor.py +0 -38
  154. exonware/xwnode/queries/executors/aggregation/distinct_executor.py +0 -50
  155. exonware/xwnode/queries/executors/aggregation/group_executor.py +0 -50
  156. exonware/xwnode/queries/executors/aggregation/having_executor.py +0 -50
  157. exonware/xwnode/queries/executors/aggregation/max_executor.py +0 -50
  158. exonware/xwnode/queries/executors/aggregation/min_executor.py +0 -50
  159. exonware/xwnode/queries/executors/aggregation/sum_executor.py +0 -50
  160. exonware/xwnode/queries/executors/aggregation/summarize_executor.py +0 -50
  161. exonware/xwnode/queries/executors/array/__init__.py +0 -9
  162. exonware/xwnode/queries/executors/array/indexing_executor.py +0 -51
  163. exonware/xwnode/queries/executors/array/slicing_executor.py +0 -51
  164. exonware/xwnode/queries/executors/base.py +0 -257
  165. exonware/xwnode/queries/executors/capability_checker.py +0 -204
  166. exonware/xwnode/queries/executors/contracts.py +0 -166
  167. exonware/xwnode/queries/executors/core/__init__.py +0 -17
  168. exonware/xwnode/queries/executors/core/create_executor.py +0 -96
  169. exonware/xwnode/queries/executors/core/delete_executor.py +0 -99
  170. exonware/xwnode/queries/executors/core/drop_executor.py +0 -100
  171. exonware/xwnode/queries/executors/core/insert_executor.py +0 -39
  172. exonware/xwnode/queries/executors/core/select_executor.py +0 -152
  173. exonware/xwnode/queries/executors/core/update_executor.py +0 -102
  174. exonware/xwnode/queries/executors/data/__init__.py +0 -13
  175. exonware/xwnode/queries/executors/data/alter_executor.py +0 -50
  176. exonware/xwnode/queries/executors/data/load_executor.py +0 -50
  177. exonware/xwnode/queries/executors/data/merge_executor.py +0 -50
  178. exonware/xwnode/queries/executors/data/store_executor.py +0 -50
  179. exonware/xwnode/queries/executors/defs.py +0 -93
  180. exonware/xwnode/queries/executors/engine.py +0 -221
  181. exonware/xwnode/queries/executors/errors.py +0 -68
  182. exonware/xwnode/queries/executors/filtering/__init__.py +0 -25
  183. exonware/xwnode/queries/executors/filtering/between_executor.py +0 -80
  184. exonware/xwnode/queries/executors/filtering/filter_executor.py +0 -79
  185. exonware/xwnode/queries/executors/filtering/has_executor.py +0 -70
  186. exonware/xwnode/queries/executors/filtering/in_executor.py +0 -70
  187. exonware/xwnode/queries/executors/filtering/like_executor.py +0 -76
  188. exonware/xwnode/queries/executors/filtering/optional_executor.py +0 -76
  189. exonware/xwnode/queries/executors/filtering/range_executor.py +0 -80
  190. exonware/xwnode/queries/executors/filtering/term_executor.py +0 -77
  191. exonware/xwnode/queries/executors/filtering/values_executor.py +0 -71
  192. exonware/xwnode/queries/executors/filtering/where_executor.py +0 -44
  193. exonware/xwnode/queries/executors/graph/__init__.py +0 -15
  194. exonware/xwnode/queries/executors/graph/in_traverse_executor.py +0 -51
  195. exonware/xwnode/queries/executors/graph/match_executor.py +0 -51
  196. exonware/xwnode/queries/executors/graph/out_executor.py +0 -51
  197. exonware/xwnode/queries/executors/graph/path_executor.py +0 -51
  198. exonware/xwnode/queries/executors/graph/return_executor.py +0 -51
  199. exonware/xwnode/queries/executors/ordering/__init__.py +0 -9
  200. exonware/xwnode/queries/executors/ordering/by_executor.py +0 -50
  201. exonware/xwnode/queries/executors/ordering/order_executor.py +0 -51
  202. exonware/xwnode/queries/executors/projection/__init__.py +0 -9
  203. exonware/xwnode/queries/executors/projection/extend_executor.py +0 -50
  204. exonware/xwnode/queries/executors/projection/project_executor.py +0 -50
  205. exonware/xwnode/queries/executors/registry.py +0 -173
  206. exonware/xwnode/queries/parsers/__init__.py +0 -26
  207. exonware/xwnode/queries/parsers/base.py +0 -86
  208. exonware/xwnode/queries/parsers/contracts.py +0 -46
  209. exonware/xwnode/queries/parsers/errors.py +0 -53
  210. exonware/xwnode/queries/parsers/sql_param_extractor.py +0 -318
  211. exonware/xwnode/queries/strategies/__init__.py +0 -24
  212. exonware/xwnode/queries/strategies/base.py +0 -236
  213. exonware/xwnode/queries/strategies/cql.py +0 -201
  214. exonware/xwnode/queries/strategies/cypher.py +0 -181
  215. exonware/xwnode/queries/strategies/datalog.py +0 -70
  216. exonware/xwnode/queries/strategies/elastic_dsl.py +0 -70
  217. exonware/xwnode/queries/strategies/eql.py +0 -70
  218. exonware/xwnode/queries/strategies/flux.py +0 -70
  219. exonware/xwnode/queries/strategies/gql.py +0 -70
  220. exonware/xwnode/queries/strategies/graphql.py +0 -240
  221. exonware/xwnode/queries/strategies/gremlin.py +0 -181
  222. exonware/xwnode/queries/strategies/hiveql.py +0 -214
  223. exonware/xwnode/queries/strategies/hql.py +0 -70
  224. exonware/xwnode/queries/strategies/jmespath.py +0 -219
  225. exonware/xwnode/queries/strategies/jq.py +0 -66
  226. exonware/xwnode/queries/strategies/json_query.py +0 -66
  227. exonware/xwnode/queries/strategies/jsoniq.py +0 -248
  228. exonware/xwnode/queries/strategies/kql.py +0 -70
  229. exonware/xwnode/queries/strategies/linq.py +0 -238
  230. exonware/xwnode/queries/strategies/logql.py +0 -70
  231. exonware/xwnode/queries/strategies/mql.py +0 -68
  232. exonware/xwnode/queries/strategies/n1ql.py +0 -210
  233. exonware/xwnode/queries/strategies/partiql.py +0 -70
  234. exonware/xwnode/queries/strategies/pig.py +0 -215
  235. exonware/xwnode/queries/strategies/promql.py +0 -70
  236. exonware/xwnode/queries/strategies/sparql.py +0 -220
  237. exonware/xwnode/queries/strategies/sql.py +0 -275
  238. exonware/xwnode/queries/strategies/xml_query.py +0 -66
  239. exonware/xwnode/queries/strategies/xpath.py +0 -223
  240. exonware/xwnode/queries/strategies/xquery.py +0 -258
  241. exonware/xwnode/queries/strategies/xwnode_executor.py +0 -332
  242. exonware/xwnode/queries/strategies/xwquery.py +0 -456
  243. exonware_xwnode-0.0.1.21.dist-info/RECORD +0 -214
  244. /exonware/xwnode/nodes/strategies/{node_ordered_map.py → ordered_map.py} +0 -0
  245. /exonware/xwnode/nodes/strategies/{node_ordered_map_balanced.py → ordered_map_balanced.py} +0 -0
  246. /exonware/xwnode/nodes/strategies/{node_patricia.py → patricia.py} +0 -0
  247. /exonware/xwnode/nodes/strategies/{node_radix_trie.py → radix_trie.py} +0 -0
  248. /exonware/xwnode/nodes/strategies/{node_set_tree.py → set_tree.py} +0 -0
  249. {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/WHEEL +0 -0
  250. {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/licenses/LICENSE +0 -0
@@ -1,70 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- GQL Query Strategy
4
-
5
- This module implements the GQL query strategy for ISO/IEC 39075:2024 Graph Query Language operations.
6
-
7
- Company: eXonware.com
8
- Author: Eng. Muhammad AlShehri
9
- Email: connect@exonware.com
10
- Version: 0.0.1.21
11
- Generation Date: January 2, 2025
12
- """
13
-
14
- from typing import Any, Dict, List, Optional
15
- from .base import AGraphQueryStrategy
16
- from ...errors import XWNodeValueError
17
- from ...contracts import QueryMode, QueryTrait
18
-
19
-
20
- class GQLStrategy(AGraphQueryStrategy):
21
- """GQL query strategy for ISO/IEC 39075:2024 Graph Query Language operations."""
22
-
23
- def __init__(self, **options):
24
- super().__init__(**options)
25
- self._mode = QueryMode.GQL
26
- self._traits = QueryTrait.GRAPH | QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL
27
-
28
- def execute(self, query: str, **kwargs) -> Any:
29
- """Execute GQL query."""
30
- if not self.validate_query(query):
31
- raise XWNodeValueError(f"Invalid GQL query: {query}")
32
- return {"result": "GQL query executed", "query": query}
33
-
34
- def validate_query(self, query: str) -> bool:
35
- """Validate GQL query syntax."""
36
- if not query or not isinstance(query, str):
37
- return False
38
- return any(op in query.upper() for op in ["MATCH", "SELECT", "WHERE", "RETURN", "CREATE", "DELETE"])
39
-
40
- def get_query_plan(self, query: str) -> Dict[str, Any]:
41
- """Get GQL query execution plan."""
42
- return {
43
- "query_type": "GQL",
44
- "complexity": "HIGH",
45
- "estimated_cost": 150
46
- }
47
-
48
- def match_query(self, pattern: str, where_clause: str = None) -> Any:
49
- """Execute MATCH query."""
50
- return self.execute(f"MATCH {pattern}")
51
-
52
- def create_query(self, pattern: str) -> Any:
53
- """Execute CREATE query."""
54
- return self.execute(f"CREATE {pattern}")
55
-
56
- def delete_query(self, pattern: str) -> Any:
57
- """Execute DELETE query."""
58
- return self.execute(f"DELETE {pattern}")
59
-
60
- def set_query(self, pattern: str) -> Any:
61
- """Execute SET query."""
62
- return self.execute(f"SET {pattern}")
63
-
64
- def remove_query(self, pattern: str) -> Any:
65
- """Execute REMOVE query."""
66
- return self.execute(f"REMOVE {pattern}")
67
-
68
- def merge_query(self, pattern: str) -> Any:
69
- """Execute MERGE query."""
70
- return self.execute(f"MERGE {pattern}")
@@ -1,240 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- GraphQL Query Strategy
4
-
5
- This module implements the GraphQL query strategy for graph-based data queries.
6
-
7
- Company: eXonware.com
8
- Author: Eng. Muhammad AlShehri
9
- Email: connect@exonware.com
10
- Version: 0.0.1.21
11
- Generation Date: January 2, 2025
12
- """
13
-
14
- import re
15
- from typing import Any, Dict, List, Optional, Union
16
- from .base import AGraphQueryStrategy
17
- from ...errors import XWNodeTypeError, XWNodeValueError
18
- from ...contracts import QueryMode, QueryTrait
19
-
20
-
21
- class GraphQLStrategy(AGraphQueryStrategy):
22
- """
23
- GraphQL query strategy for graph-based data queries.
24
-
25
- Supports:
26
- - Queries and mutations
27
- - Fragments and variables
28
- - Introspection
29
- - Subscriptions
30
- - Schema validation
31
- """
32
-
33
- def __init__(self, **options):
34
- super().__init__(**options)
35
- self._mode = QueryMode.GRAPHQL
36
- self._traits = QueryTrait.GRAPH | QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL
37
-
38
- def execute(self, query: str, **kwargs) -> Any:
39
- """Execute GraphQL query."""
40
- if not self.validate_query(query):
41
- raise XWNodeValueError(f"Invalid GraphQL query: {query}")
42
-
43
- query_type = self._get_query_type(query)
44
-
45
- if query_type == "query":
46
- return self._execute_query(query, **kwargs)
47
- elif query_type == "mutation":
48
- return self._execute_mutation(query, **kwargs)
49
- elif query_type == "subscription":
50
- return self._execute_subscription(query, **kwargs)
51
- else:
52
- raise XWNodeValueError(f"Unsupported query type: {query_type}")
53
-
54
- def validate_query(self, query: str) -> bool:
55
- """Validate GraphQL query syntax."""
56
- if not query or not isinstance(query, str):
57
- return False
58
-
59
- # Basic GraphQL validation
60
- query = query.strip()
61
-
62
- # Check for valid GraphQL operations
63
- valid_operations = ["query", "mutation", "subscription"]
64
- for operation in valid_operations:
65
- if query.startswith(operation) or query.startswith("{"):
66
- return True
67
-
68
- return False
69
-
70
- def get_query_plan(self, query: str) -> Dict[str, Any]:
71
- """Get GraphQL query execution plan."""
72
- query_type = self._get_query_type(query)
73
-
74
- return {
75
- "query_type": query_type,
76
- "operation": query_type,
77
- "complexity": self._estimate_complexity(query),
78
- "estimated_cost": self._estimate_cost(query),
79
- "fields": self._extract_fields(query),
80
- "optimization_hints": self._get_optimization_hints(query)
81
- }
82
-
83
- def path_query(self, start: Any, end: Any) -> List[Any]:
84
- """Execute path query."""
85
- query = f"""
86
- query {{
87
- path(start: "{start}", end: "{end}") {{
88
- nodes
89
- edges
90
- cost
91
- }}
92
- }}
93
- """
94
- return self.execute(query)
95
-
96
- def neighbor_query(self, node: Any) -> List[Any]:
97
- """Execute neighbor query."""
98
- query = f"""
99
- query {{
100
- node(id: "{node}") {{
101
- neighbors {{
102
- id
103
- properties
104
- }}
105
- }}
106
- }}
107
- """
108
- return self.execute(query)
109
-
110
- def shortest_path_query(self, start: Any, end: Any) -> List[Any]:
111
- """Execute shortest path query."""
112
- query = f"""
113
- query {{
114
- shortestPath(start: "{start}", end: "{end}") {{
115
- path
116
- distance
117
- hops
118
- }}
119
- }}
120
- """
121
- return self.execute(query)
122
-
123
- def connected_components_query(self) -> List[List[Any]]:
124
- """Execute connected components query."""
125
- query = """
126
- query {
127
- connectedComponents {
128
- components {
129
- nodes
130
- size
131
- }
132
- }
133
- }
134
- """
135
- return self.execute(query)
136
-
137
- def cycle_detection_query(self) -> List[List[Any]]:
138
- """Execute cycle detection query."""
139
- query = """
140
- query {
141
- cycles {
142
- cycles {
143
- nodes
144
- length
145
- }
146
- }
147
- }
148
- """
149
- return self.execute(query)
150
-
151
- def _get_query_type(self, query: str) -> str:
152
- """Extract query type from GraphQL query."""
153
- query = query.strip()
154
-
155
- if query.startswith("mutation"):
156
- return "mutation"
157
- elif query.startswith("subscription"):
158
- return "subscription"
159
- elif query.startswith("query") or query.startswith("{"):
160
- return "query"
161
- else:
162
- return "unknown"
163
-
164
- def _execute_query(self, query: str, **kwargs) -> Any:
165
- """Execute GraphQL query."""
166
- return {"result": "GraphQL query executed", "query": query}
167
-
168
- def _execute_mutation(self, query: str, **kwargs) -> Any:
169
- """Execute GraphQL mutation."""
170
- return {"result": "GraphQL mutation executed", "query": query}
171
-
172
- def _execute_subscription(self, query: str, **kwargs) -> Any:
173
- """Execute GraphQL subscription."""
174
- return {"result": "GraphQL subscription executed", "query": query}
175
-
176
- def _estimate_complexity(self, query: str) -> str:
177
- """Estimate query complexity."""
178
- # Count nested fields and connections
179
- depth = self._calculate_query_depth(query)
180
-
181
- if depth > 5:
182
- return "HIGH"
183
- elif depth > 2:
184
- return "MEDIUM"
185
- else:
186
- return "LOW"
187
-
188
- def _estimate_cost(self, query: str) -> int:
189
- """Estimate query cost."""
190
- complexity = self._estimate_complexity(query)
191
- if complexity == "HIGH":
192
- return 150
193
- elif complexity == "MEDIUM":
194
- return 75
195
- else:
196
- return 25
197
-
198
- def _calculate_query_depth(self, query: str) -> int:
199
- """Calculate query nesting depth."""
200
- depth = 0
201
- max_depth = 0
202
-
203
- for char in query:
204
- if char == '{':
205
- depth += 1
206
- max_depth = max(max_depth, depth)
207
- elif char == '}':
208
- depth -= 1
209
-
210
- return max_depth
211
-
212
- def _extract_fields(self, query: str) -> List[str]:
213
- """Extract field names from GraphQL query."""
214
- # Simple field extraction
215
- fields = []
216
- lines = query.split('\n')
217
-
218
- for line in lines:
219
- line = line.strip()
220
- if line and not line.startswith('{') and not line.startswith('}'):
221
- if ':' in line:
222
- field = line.split(':')[0].strip()
223
- fields.append(field)
224
-
225
- return fields
226
-
227
- def _get_optimization_hints(self, query: str) -> List[str]:
228
- """Get query optimization hints."""
229
- hints = []
230
-
231
- if self._calculate_query_depth(query) > 3:
232
- hints.append("Consider reducing query depth to improve performance")
233
-
234
- if "..." in query:
235
- hints.append("Consider using fragments for reusable query parts")
236
-
237
- if query.count('{') > 10:
238
- hints.append("Consider breaking down complex queries into smaller ones")
239
-
240
- return hints
@@ -1,181 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Gremlin Query Strategy
4
-
5
- This module implements the Gremlin query strategy for Apache TinkerPop graph queries.
6
-
7
- Company: eXonware.com
8
- Author: Eng. Muhammad AlShehri
9
- Email: connect@exonware.com
10
- Version: 0.0.1.21
11
- Generation Date: January 2, 2025
12
- """
13
-
14
- import re
15
- from typing import Any, Dict, List, Optional, Union
16
- from .base import AGraphQueryStrategy
17
- from ...errors import XWNodeTypeError, XWNodeValueError
18
- from ...contracts import QueryMode, QueryTrait
19
-
20
-
21
- class GremlinStrategy(AGraphQueryStrategy):
22
- """
23
- Gremlin query strategy for Apache TinkerPop graph queries.
24
-
25
- Supports:
26
- - Gremlin traversal language
27
- - Graph traversal operations
28
- - Vertex and edge operations
29
- - Property and label operations
30
- - Path and cycle detection
31
- """
32
-
33
- def __init__(self, **options):
34
- super().__init__(**options)
35
- self._mode = QueryMode.GREMLIN
36
- self._traits = QueryTrait.GRAPH | QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL
37
-
38
- def execute(self, query: str, **kwargs) -> Any:
39
- """Execute Gremlin query."""
40
- if not self.validate_query(query):
41
- raise XWNodeValueError(f"Invalid Gremlin query: {query}")
42
-
43
- query_type = self._get_query_type(query)
44
-
45
- if query_type == "traversal":
46
- return self._execute_traversal(query, **kwargs)
47
- elif query_type == "vertex":
48
- return self._execute_vertex(query, **kwargs)
49
- elif query_type == "edge":
50
- return self._execute_edge(query, **kwargs)
51
- else:
52
- raise XWNodeValueError(f"Unsupported query type: {query_type}")
53
-
54
- def validate_query(self, query: str) -> bool:
55
- """Validate Gremlin query syntax."""
56
- if not query or not isinstance(query, str):
57
- return False
58
-
59
- # Basic Gremlin validation
60
- query = query.strip()
61
-
62
- # Check for Gremlin keywords
63
- gremlin_keywords = ["g.", "V", "E", "addV", "addE", "drop", "has", "hasLabel", "hasId", "out", "in", "both", "outE", "inE", "bothE", "outV", "inV", "bothV", "values", "key", "label", "id", "count", "limit", "range", "order", "by", "select", "where", "and", "or", "not", "is", "within", "without", "between", "inside", "outside", "within", "without", "between", "inside", "outside", "within", "without", "between", "inside", "outside"]
64
-
65
- for keyword in gremlin_keywords:
66
- if keyword in query:
67
- return True
68
-
69
- return False
70
-
71
- def get_query_plan(self, query: str) -> Dict[str, Any]:
72
- """Get Gremlin query execution plan."""
73
- query_type = self._get_query_type(query)
74
-
75
- return {
76
- "query_type": query_type,
77
- "operation": query_type,
78
- "complexity": self._estimate_complexity(query),
79
- "estimated_cost": self._estimate_cost(query),
80
- "steps": self._extract_steps(query),
81
- "optimization_hints": self._get_optimization_hints(query)
82
- }
83
-
84
- def path_query(self, start: Any, end: Any) -> List[Any]:
85
- """Execute path query."""
86
- query = f"g.V('{start}').repeat(out()).until(hasId('{end}')).path()"
87
- return self.execute(query)
88
-
89
- def neighbor_query(self, node: Any) -> List[Any]:
90
- """Execute neighbor query."""
91
- query = f"g.V('{node}').both()"
92
- return self.execute(query)
93
-
94
- def shortest_path_query(self, start: Any, end: Any) -> List[Any]:
95
- """Execute shortest path query."""
96
- query = f"g.V('{start}').repeat(out()).until(hasId('{end}')).path().limit(1)"
97
- return self.execute(query)
98
-
99
- def connected_components_query(self) -> List[List[Any]]:
100
- """Execute connected components query."""
101
- query = "g.V().repeat(both()).until(cyclicPath()).dedup()"
102
- return self.execute(query)
103
-
104
- def cycle_detection_query(self) -> List[List[Any]]:
105
- """Execute cycle detection query."""
106
- query = "g.V().repeat(out()).until(cyclicPath()).path()"
107
- return self.execute(query)
108
-
109
- def _get_query_type(self, query: str) -> str:
110
- """Extract query type from Gremlin query."""
111
- query = query.strip()
112
-
113
- if "V(" in query or "E(" in query:
114
- return "traversal"
115
- elif "addV" in query or "V(" in query:
116
- return "vertex"
117
- elif "addE" in query or "E(" in query:
118
- return "edge"
119
- else:
120
- return "unknown"
121
-
122
- def _execute_traversal(self, query: str, **kwargs) -> Any:
123
- """Execute traversal query."""
124
- return {"result": "Gremlin traversal executed", "query": query}
125
-
126
- def _execute_vertex(self, query: str, **kwargs) -> Any:
127
- """Execute vertex query."""
128
- return {"result": "Gremlin vertex executed", "query": query}
129
-
130
- def _execute_edge(self, query: str, **kwargs) -> Any:
131
- """Execute edge query."""
132
- return {"result": "Gremlin edge executed", "query": query}
133
-
134
- def _estimate_complexity(self, query: str) -> str:
135
- """Estimate query complexity."""
136
- steps = self._extract_steps(query)
137
-
138
- if len(steps) > 10:
139
- return "HIGH"
140
- elif len(steps) > 5:
141
- return "MEDIUM"
142
- else:
143
- return "LOW"
144
-
145
- def _estimate_cost(self, query: str) -> int:
146
- """Estimate query cost."""
147
- complexity = self._estimate_complexity(query)
148
- if complexity == "HIGH":
149
- return 180
150
- elif complexity == "MEDIUM":
151
- return 90
152
- else:
153
- return 45
154
-
155
- def _extract_steps(self, query: str) -> List[str]:
156
- """Extract Gremlin steps from query."""
157
- steps = []
158
-
159
- # Common Gremlin steps
160
- gremlin_steps = ["V", "E", "addV", "addE", "drop", "has", "hasLabel", "hasId", "out", "in", "both", "outE", "inE", "bothE", "outV", "inV", "bothV", "values", "key", "label", "id", "count", "limit", "range", "order", "by", "select", "where", "and", "or", "not", "is", "within", "without", "between", "inside", "outside", "repeat", "until", "emit", "times", "path", "dedup", "cyclicPath"]
161
-
162
- for step in gremlin_steps:
163
- if step in query:
164
- steps.append(step)
165
-
166
- return steps
167
-
168
- def _get_optimization_hints(self, query: str) -> List[str]:
169
- """Get query optimization hints."""
170
- hints = []
171
-
172
- if "repeat" in query:
173
- hints.append("Consider using limit() with repeat() to prevent infinite loops")
174
-
175
- if "path" in query:
176
- hints.append("Consider using dedup() with path() to avoid duplicate paths")
177
-
178
- if "count" in query:
179
- hints.append("Consider using count() early in the traversal for better performance")
180
-
181
- return hints