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,223 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- XPath Query Strategy
4
-
5
- This module implements the XPath query strategy for XML 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 ADocumentQueryStrategy
17
- from ...errors import XWNodeTypeError, XWNodeValueError
18
- from ...contracts import QueryMode, QueryTrait
19
-
20
-
21
- class XPathStrategy(ADocumentQueryStrategy):
22
- """
23
- XPath query strategy for XML data queries.
24
-
25
- Supports:
26
- - XPath 1.0 and 2.0 features
27
- - Location paths and expressions
28
- - Predicates and functions
29
- - Axes and node tests
30
- - Namespace support
31
- """
32
-
33
- def __init__(self, **options):
34
- super().__init__(**options)
35
- self._mode = QueryMode.XPATH
36
- self._traits = QueryTrait.DOCUMENT | QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL
37
-
38
- def execute(self, query: str, **kwargs) -> Any:
39
- """Execute XPath query."""
40
- if not self.validate_query(query):
41
- raise XWNodeValueError(f"Invalid XPath query: {query}")
42
-
43
- query_type = self._get_query_type(query)
44
-
45
- if query_type == "location_path":
46
- return self._execute_location_path(query, **kwargs)
47
- elif query_type == "expression":
48
- return self._execute_expression(query, **kwargs)
49
- elif query_type == "function":
50
- return self._execute_function(query, **kwargs)
51
- else:
52
- raise XWNodeValueError(f"Unsupported query type: {query_type}")
53
-
54
- def validate_query(self, query: str) -> bool:
55
- """Validate XPath query syntax."""
56
- if not query or not isinstance(query, str):
57
- return False
58
-
59
- # Basic XPath validation
60
- query = query.strip()
61
-
62
- # Check for XPath syntax
63
- if query.startswith("/") or query.startswith("//") or query.startswith("@") or query.startswith("."):
64
- return True
65
-
66
- # Check for XPath functions
67
- xpath_functions = ["text", "name", "local-name", "namespace-uri", "count", "position", "last", "string", "number", "boolean", "not", "true", "false", "contains", "starts-with", "ends-with", "substring", "substring-before", "substring-after", "normalize-space", "translate", "concat", "string-length", "sum", "floor", "ceiling", "round", "id", "key", "document", "format-number", "unparsed-entity-uri", "unparsed-entity-public-id", "generate-id", "system-property", "element-available", "function-available", "current", "lang", "local-name", "namespace-uri", "name", "string", "number", "boolean", "not", "true", "false", "contains", "starts-with", "ends-with", "substring", "substring-before", "substring-after", "normalize-space", "translate", "concat", "string-length", "sum", "floor", "ceiling", "round", "id", "key", "document", "format-number", "unparsed-entity-uri", "unparsed-entity-public-id", "generate-id", "system-property", "element-available", "function-available", "current", "lang"]
68
-
69
- for func in xpath_functions:
70
- if func in query:
71
- return True
72
-
73
- # Check for axes
74
- axes = ["ancestor", "ancestor-or-self", "attribute", "child", "descendant", "descendant-or-self", "following", "following-sibling", "namespace", "parent", "preceding", "preceding-sibling", "self"]
75
-
76
- for axis in axes:
77
- if f"{axis}::" in query:
78
- return True
79
-
80
- return False
81
-
82
- def get_query_plan(self, query: str) -> Dict[str, Any]:
83
- """Get XPath query execution plan."""
84
- query_type = self._get_query_type(query)
85
-
86
- return {
87
- "query_type": query_type,
88
- "operation": query_type,
89
- "complexity": self._estimate_complexity(query),
90
- "estimated_cost": self._estimate_cost(query),
91
- "expressions": self._extract_expressions(query),
92
- "optimization_hints": self._get_optimization_hints(query)
93
- }
94
-
95
- def path_query(self, path: str) -> Any:
96
- """Execute path-based query."""
97
- # XPath path queries
98
- query = f"/{path}"
99
- return self.execute(query)
100
-
101
- def filter_query(self, filter_expression: str) -> Any:
102
- """Execute filter query."""
103
- query = f"//*[{filter_expression}]"
104
- return self.execute(query)
105
-
106
- def projection_query(self, fields: List[str]) -> Any:
107
- """Execute projection query."""
108
- if len(fields) == 1:
109
- query = f"//{fields[0]}"
110
- else:
111
- field_list = " | ".join([f"//{field}" for field in fields])
112
- query = f"({field_list})"
113
-
114
- return self.execute(query)
115
-
116
- def sort_query(self, sort_fields: List[str], order: str = "asc") -> Any:
117
- """Execute sort query."""
118
- # XPath doesn't have built-in sorting, use position
119
- if order.lower() == "desc":
120
- query = f"//*[position() = last() - position() + 1]"
121
- else:
122
- query = f"//*[position()]"
123
-
124
- return self.execute(query)
125
-
126
- def limit_query(self, limit: int, offset: int = 0) -> Any:
127
- """Execute limit query."""
128
- if offset > 0:
129
- query = f"//*[position() > {offset} and position() <= {offset + limit}]"
130
- else:
131
- query = f"//*[position() <= {limit}]"
132
-
133
- return self.execute(query)
134
-
135
- def _get_query_type(self, query: str) -> str:
136
- """Extract query type from XPath query."""
137
- query = query.strip()
138
-
139
- if "/" in query or "//" in query:
140
- return "location_path"
141
- elif "(" in query and ")" in query:
142
- return "function"
143
- else:
144
- return "expression"
145
-
146
- def _execute_location_path(self, query: str, **kwargs) -> Any:
147
- """Execute location path."""
148
- return {"result": "XPath location path executed", "query": query}
149
-
150
- def _execute_expression(self, query: str, **kwargs) -> Any:
151
- """Execute expression."""
152
- return {"result": "XPath expression executed", "query": query}
153
-
154
- def _execute_function(self, query: str, **kwargs) -> Any:
155
- """Execute function call."""
156
- return {"result": "XPath function executed", "query": query}
157
-
158
- def _estimate_complexity(self, query: str) -> str:
159
- """Estimate query complexity."""
160
- expressions = self._extract_expressions(query)
161
-
162
- if len(expressions) > 5:
163
- return "HIGH"
164
- elif len(expressions) > 2:
165
- return "MEDIUM"
166
- else:
167
- return "LOW"
168
-
169
- def _estimate_cost(self, query: str) -> int:
170
- """Estimate query cost."""
171
- complexity = self._estimate_complexity(query)
172
- if complexity == "HIGH":
173
- return 100
174
- elif complexity == "MEDIUM":
175
- return 50
176
- else:
177
- return 25
178
-
179
- def _extract_expressions(self, query: str) -> List[str]:
180
- """Extract XPath expressions from query."""
181
- expressions = []
182
-
183
- # Location paths
184
- if "/" in query:
185
- expressions.append("path")
186
- if "//" in query:
187
- expressions.append("descendant")
188
- if "@" in query:
189
- expressions.append("attribute")
190
- if "[" in query and "]" in query:
191
- expressions.append("predicate")
192
-
193
- # Axes
194
- axes = ["ancestor", "ancestor-or-self", "attribute", "child", "descendant", "descendant-or-self", "following", "following-sibling", "namespace", "parent", "preceding", "preceding-sibling", "self"]
195
- for axis in axes:
196
- if f"{axis}::" in query:
197
- expressions.append(axis)
198
-
199
- # Functions
200
- xpath_functions = ["text", "name", "local-name", "namespace-uri", "count", "position", "last", "string", "number", "boolean", "not", "true", "false", "contains", "starts-with", "ends-with", "substring", "substring-before", "substring-after", "normalize-space", "translate", "concat", "string-length", "sum", "floor", "ceiling", "round", "id", "key", "document", "format-number", "unparsed-entity-uri", "unparsed-entity-public-id", "generate-id", "system-property", "element-available", "function-available", "current", "lang"]
201
- for func in xpath_functions:
202
- if func in query:
203
- expressions.append(func)
204
-
205
- return expressions
206
-
207
- def _get_optimization_hints(self, query: str) -> List[str]:
208
- """Get query optimization hints."""
209
- hints = []
210
-
211
- if "//" in query:
212
- hints.append("Consider using specific paths instead of descendant navigation")
213
-
214
- if "[" in query and "]" in query:
215
- hints.append("Consider using indexes for predicate operations")
216
-
217
- if "position()" in query:
218
- hints.append("Consider using last() for better performance")
219
-
220
- if "text()" in query:
221
- hints.append("Consider using normalize-space() for text processing")
222
-
223
- return hints
@@ -1,258 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- XQuery Query Strategy
4
-
5
- This module implements the XQuery query strategy for XML 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 ADocumentQueryStrategy
17
- from ...errors import XWNodeTypeError, XWNodeValueError
18
- from ...contracts import QueryMode, QueryTrait
19
-
20
-
21
- class XQueryStrategy(ADocumentQueryStrategy):
22
- """
23
- XQuery query strategy for XML data queries.
24
-
25
- Supports:
26
- - XQuery 1.0 and 3.0 features
27
- - FLWOR expressions
28
- - XPath expressions
29
- - XML construction
30
- - Functions and modules
31
- """
32
-
33
- def __init__(self, **options):
34
- super().__init__(**options)
35
- self._mode = QueryMode.XQUERY
36
- self._traits = QueryTrait.DOCUMENT | QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL
37
-
38
- def execute(self, query: str, **kwargs) -> Any:
39
- """Execute XQuery query."""
40
- if not self.validate_query(query):
41
- raise XWNodeValueError(f"Invalid XQuery query: {query}")
42
-
43
- query_type = self._get_query_type(query)
44
-
45
- if query_type == "flwor":
46
- return self._execute_flwor(query, **kwargs)
47
- elif query_type == "xpath":
48
- return self._execute_xpath(query, **kwargs)
49
- elif query_type == "construction":
50
- return self._execute_construction(query, **kwargs)
51
- else:
52
- raise XWNodeValueError(f"Unsupported query type: {query_type}")
53
-
54
- def validate_query(self, query: str) -> bool:
55
- """Validate XQuery query syntax."""
56
- if not query or not isinstance(query, str):
57
- return False
58
-
59
- # Basic XQuery validation
60
- query = query.strip()
61
-
62
- # Check for XQuery keywords
63
- xquery_keywords = ["for", "let", "where", "order by", "group by", "return", "declare", "namespace", "import", "module", "function", "variable", "element", "attribute", "text", "comment", "processing-instruction", "document", "collection"]
64
-
65
- query_lower = query.lower()
66
- for keyword in xquery_keywords:
67
- if keyword in query_lower:
68
- return True
69
-
70
- # Check for XPath expressions
71
- if "/" in query or "//" in query or "@" in query or "[" in query:
72
- return True
73
-
74
- return False
75
-
76
- def get_query_plan(self, query: str) -> Dict[str, Any]:
77
- """Get XQuery query execution plan."""
78
- query_type = self._get_query_type(query)
79
-
80
- return {
81
- "query_type": query_type,
82
- "operation": query_type,
83
- "complexity": self._estimate_complexity(query),
84
- "estimated_cost": self._estimate_cost(query),
85
- "expressions": self._extract_expressions(query),
86
- "optimization_hints": self._get_optimization_hints(query)
87
- }
88
-
89
- def path_query(self, path: str) -> Any:
90
- """Execute path-based query."""
91
- # XQuery path queries
92
- query = f"doc()/{path}"
93
- return self.execute(query)
94
-
95
- def filter_query(self, filter_expression: str) -> Any:
96
- """Execute filter query."""
97
- query = f"""
98
- for $item in doc()//*
99
- where {filter_expression}
100
- return $item
101
- """
102
- return self.execute(query)
103
-
104
- def projection_query(self, fields: List[str]) -> Any:
105
- """Execute projection query."""
106
- if len(fields) == 1:
107
- query = f"""
108
- for $item in doc()//*
109
- return $item/{fields[0]}
110
- """
111
- else:
112
- field_list = ", ".join([f"$item/{field}" for field in fields])
113
- query = f"""
114
- for $item in doc()//*
115
- return <result>{{ {field_list} }}</result>
116
- """
117
-
118
- return self.execute(query)
119
-
120
- def sort_query(self, sort_fields: List[str], order: str = "asc") -> Any:
121
- """Execute sort query."""
122
- if order.lower() == "desc":
123
- query = f"""
124
- for $item in doc()//*
125
- order by $item/{sort_fields[0]} descending
126
- return $item
127
- """
128
- else:
129
- query = f"""
130
- for $item in doc()//*
131
- order by $item/{sort_fields[0]}
132
- return $item
133
- """
134
-
135
- return self.execute(query)
136
-
137
- def limit_query(self, limit: int, offset: int = 0) -> Any:
138
- """Execute limit query."""
139
- if offset > 0:
140
- query = f"""
141
- for $item at $pos in doc()//*
142
- where $pos > {offset}
143
- return $item
144
- """
145
- # Use subsequence for limit
146
- return self._execute_function(f"subsequence(doc()//*, {offset + 1}, {limit})")
147
- else:
148
- query = f"""
149
- for $item in doc()//*
150
- return $item
151
- """
152
- return self._execute_function(f"subsequence(doc()//*, 1, {limit})")
153
-
154
- def _get_query_type(self, query: str) -> str:
155
- """Extract query type from XQuery query."""
156
- query = query.strip()
157
-
158
- if "for" in query.lower() or "let" in query.lower():
159
- return "flwor"
160
- elif "<" in query and ">" in query:
161
- return "construction"
162
- elif "/" in query or "//" in query:
163
- return "xpath"
164
- else:
165
- return "unknown"
166
-
167
- def _execute_flwor(self, query: str, **kwargs) -> Any:
168
- """Execute FLWOR expression."""
169
- return {"result": "XQuery FLWOR executed", "query": query}
170
-
171
- def _execute_xpath(self, query: str, **kwargs) -> Any:
172
- """Execute XPath expression."""
173
- return {"result": "XQuery XPath executed", "query": query}
174
-
175
- def _execute_construction(self, query: str, **kwargs) -> Any:
176
- """Execute XML construction."""
177
- return {"result": "XQuery construction executed", "query": query}
178
-
179
- def _execute_function(self, query: str, **kwargs) -> Any:
180
- """Execute function call."""
181
- return {"result": "XQuery function executed", "query": query}
182
-
183
- def _estimate_complexity(self, query: str) -> str:
184
- """Estimate query complexity."""
185
- expressions = self._extract_expressions(query)
186
-
187
- if len(expressions) > 5:
188
- return "HIGH"
189
- elif len(expressions) > 2:
190
- return "MEDIUM"
191
- else:
192
- return "LOW"
193
-
194
- def _estimate_cost(self, query: str) -> int:
195
- """Estimate query cost."""
196
- complexity = self._estimate_complexity(query)
197
- if complexity == "HIGH":
198
- return 150
199
- elif complexity == "MEDIUM":
200
- return 75
201
- else:
202
- return 35
203
-
204
- def _extract_expressions(self, query: str) -> List[str]:
205
- """Extract XQuery expressions from query."""
206
- expressions = []
207
-
208
- # FLWOR expressions
209
- if "for" in query.lower():
210
- expressions.append("for")
211
- if "let" in query.lower():
212
- expressions.append("let")
213
- if "where" in query.lower():
214
- expressions.append("where")
215
- if "order by" in query.lower():
216
- expressions.append("order by")
217
- if "group by" in query.lower():
218
- expressions.append("group by")
219
- if "return" in query.lower():
220
- expressions.append("return")
221
-
222
- # XPath expressions
223
- if "/" in query:
224
- expressions.append("path")
225
- if "//" in query:
226
- expressions.append("descendant")
227
- if "@" in query:
228
- expressions.append("attribute")
229
- if "[" in query and "]" in query:
230
- expressions.append("predicate")
231
-
232
- # XML construction
233
- if "<" in query and ">" in query:
234
- expressions.append("construction")
235
-
236
- # Functions
237
- if "(" in query and ")" in query:
238
- expressions.append("function")
239
-
240
- return expressions
241
-
242
- def _get_optimization_hints(self, query: str) -> List[str]:
243
- """Get query optimization hints."""
244
- hints = []
245
-
246
- if "//" in query:
247
- hints.append("Consider using specific paths instead of descendant navigation")
248
-
249
- if "for" in query.lower() and "let" in query.lower():
250
- hints.append("Consider using let for computed values")
251
-
252
- if "[" in query and "]" in query:
253
- hints.append("Consider using indexes for predicate operations")
254
-
255
- if "order by" in query.lower():
256
- hints.append("Consider using indexes for ordered queries")
257
-
258
- return hints