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,318 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- #exonware/xwnode/src/exonware/xwnode/queries/parsers/sql_param_extractor.py
4
-
5
- SQL Parameter Extractor
6
-
7
- Extracts structured parameters from SQL-style queries.
8
- Uses regex for simplicity - follows DEV_GUIDELINES.md.
9
-
10
- Company: eXonware.com
11
- Author: Eng. Muhammad AlShehri
12
- Email: connect@exonware.com
13
- Version: 0.0.1.21
14
- Generation Date: 09-Oct-2025
15
- """
16
-
17
- import re
18
- from typing import Dict, Any, List, Union
19
-
20
- from .base import AParamExtractor
21
- from .errors import ParseError
22
-
23
-
24
- class SQLParamExtractor(AParamExtractor):
25
- """
26
- SQL parameter extractor using regex.
27
-
28
- Extracts structured parameters from SQL queries for executor consumption.
29
- Implements IParamExtractor interface per DEV_GUIDELINES.md.
30
- """
31
-
32
- def extract_params(self, query: str, action_type: str) -> Dict[str, Any]:
33
- """
34
- Extract parameters based on action type.
35
-
36
- Args:
37
- query: SQL query string
38
- action_type: Type of action (SELECT, INSERT, etc.)
39
-
40
- Returns:
41
- Structured parameters dictionary
42
- """
43
- # Route to appropriate extractor
44
- extractors = {
45
- 'SELECT': self.extract_select_params,
46
- 'INSERT': self.extract_insert_params,
47
- 'UPDATE': self.extract_update_params,
48
- 'DELETE': self.extract_delete_params,
49
- 'WHERE': self.extract_where_params,
50
- 'COUNT': self.extract_count_params,
51
- 'GROUP': self.extract_group_by_params,
52
- 'ORDER': self.extract_order_by_params,
53
- }
54
-
55
- extractor = extractors.get(action_type)
56
- if extractor:
57
- return extractor(query)
58
-
59
- # Fallback: return raw query
60
- return {'raw': query}
61
-
62
- def can_parse(self, query: str) -> bool:
63
- """Check if query looks like SQL."""
64
- query_upper = query.upper()
65
- sql_keywords = ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'FROM', 'WHERE']
66
- return any(kw in query_upper for kw in sql_keywords)
67
-
68
- def extract_select_params(self, sql: str) -> Dict[str, Any]:
69
- """Extract SELECT statement parameters."""
70
- params = {}
71
-
72
- # Extract SELECT fields
73
- select_match = re.search(r'SELECT\s+(.*?)\s+FROM', sql, re.IGNORECASE | re.DOTALL)
74
- if select_match:
75
- fields_str = select_match.group(1).strip()
76
- params['fields'] = self._split_fields(fields_str)
77
- else:
78
- params['fields'] = ['*']
79
-
80
- # Extract FROM table
81
- from_match = re.search(r'FROM\s+(\w+)', sql, re.IGNORECASE)
82
- if from_match:
83
- params['from'] = from_match.group(1)
84
- params['path'] = from_match.group(1) # Alias for compatibility
85
-
86
- # Extract WHERE conditions
87
- where_match = re.search(r'WHERE\s+(.+?)(?:ORDER|GROUP|LIMIT|$)', sql, re.IGNORECASE | re.DOTALL)
88
- if where_match:
89
- params['where'] = self._parse_where_condition(where_match.group(1).strip())
90
-
91
- # Extract ORDER BY
92
- order_match = re.search(r'ORDER\s+BY\s+(.*?)(?:LIMIT|$)', sql, re.IGNORECASE | re.DOTALL)
93
- if order_match:
94
- params['order_by'] = order_match.group(1).strip()
95
-
96
- # Extract GROUP BY
97
- group_match = re.search(r'GROUP\s+BY\s+(.*?)(?:HAVING|ORDER|LIMIT|$)', sql, re.IGNORECASE | re.DOTALL)
98
- if group_match:
99
- params['group_by'] = [f.strip() for f in group_match.group(1).split(',')]
100
-
101
- # Extract LIMIT
102
- limit_match = re.search(r'LIMIT\s+(\d+)', sql, re.IGNORECASE)
103
- if limit_match:
104
- params['limit'] = int(limit_match.group(1))
105
-
106
- return params
107
-
108
- def extract_insert_params(self, sql: str) -> Dict[str, Any]:
109
- """Extract INSERT statement parameters."""
110
- params = {}
111
-
112
- # INSERT INTO table VALUES {...}
113
- into_match = re.search(r'INSERT\s+INTO\s+(\w+)', sql, re.IGNORECASE)
114
- if into_match:
115
- params['target'] = into_match.group(1)
116
-
117
- # Extract VALUES
118
- values_match = re.search(r'VALUES\s+(.+)', sql, re.IGNORECASE | re.DOTALL)
119
- if values_match:
120
- values_str = values_match.group(1).strip()
121
- # Try to parse as JSON-like dict/list
122
- try:
123
- # Remove outer braces and parse key:value pairs
124
- if values_str.startswith('{'):
125
- params['values'] = self._parse_dict_literal(values_str)
126
- elif values_str.startswith('('):
127
- params['values'] = self._parse_tuple_literal(values_str)
128
- except:
129
- params['values'] = values_str
130
-
131
- return params
132
-
133
- def extract_update_params(self, sql: str) -> Dict[str, Any]:
134
- """Extract UPDATE statement parameters."""
135
- params = {}
136
-
137
- # UPDATE table SET ...
138
- table_match = re.search(r'UPDATE\s+(\w+)', sql, re.IGNORECASE)
139
- if table_match:
140
- params['target'] = table_match.group(1)
141
-
142
- # Extract SET clause
143
- set_match = re.search(r'SET\s+(.+?)(?:WHERE|$)', sql, re.IGNORECASE | re.DOTALL)
144
- if set_match:
145
- params['values'] = self._parse_set_clause(set_match.group(1).strip())
146
-
147
- # Extract WHERE
148
- where_match = re.search(r'WHERE\s+(.+?)$', sql, re.IGNORECASE | re.DOTALL)
149
- if where_match:
150
- params['where'] = self._parse_where_condition(where_match.group(1).strip())
151
-
152
- return params
153
-
154
- def extract_delete_params(self, sql: str) -> Dict[str, Any]:
155
- """Extract DELETE statement parameters."""
156
- params = {}
157
-
158
- # DELETE FROM table
159
- from_match = re.search(r'DELETE\s+FROM\s+(\w+)', sql, re.IGNORECASE)
160
- if from_match:
161
- params['target'] = from_match.group(1)
162
-
163
- # Extract WHERE
164
- where_match = re.search(r'WHERE\s+(.+?)$', sql, re.IGNORECASE | re.DOTALL)
165
- if where_match:
166
- params['where'] = self._parse_where_condition(where_match.group(1).strip())
167
-
168
- return params
169
-
170
- def extract_where_params(self, sql: str) -> Dict[str, Any]:
171
- """Extract WHERE clause parameters."""
172
- # Extract just the condition part
173
- where_match = re.search(r'WHERE\s+(.+?)(?:ORDER|GROUP|LIMIT|$)', sql, re.IGNORECASE | re.DOTALL)
174
- if where_match:
175
- return self._parse_where_condition(where_match.group(1).strip())
176
- return {}
177
-
178
- def extract_count_params(self, sql: str) -> Dict[str, Any]:
179
- """Extract COUNT parameters."""
180
- params = {}
181
-
182
- # COUNT(*) or COUNT(field)
183
- count_match = re.search(r'COUNT\s*\(\s*([^)]+)\s*\)', sql, re.IGNORECASE)
184
- if count_match:
185
- field = count_match.group(1).strip()
186
- params['field'] = field if field != '*' else None
187
-
188
- # Extract FROM
189
- from_match = re.search(r'FROM\s+(\w+)', sql, re.IGNORECASE)
190
- if from_match:
191
- params['from'] = from_match.group(1)
192
- params['path'] = from_match.group(1)
193
-
194
- # Extract WHERE
195
- where_match = re.search(r'WHERE\s+(.+?)(?:ORDER|GROUP|LIMIT|$)', sql, re.IGNORECASE | re.DOTALL)
196
- if where_match:
197
- params['where'] = self._parse_where_condition(where_match.group(1).strip())
198
-
199
- return params
200
-
201
- def extract_group_by_params(self, sql: str) -> Dict[str, Any]:
202
- """Extract GROUP BY parameters."""
203
- params = {}
204
-
205
- # GROUP BY fields
206
- group_match = re.search(r'GROUP\s+BY\s+(.*?)(?:HAVING|ORDER|LIMIT|$)', sql, re.IGNORECASE | re.DOTALL)
207
- if group_match:
208
- params['fields'] = [f.strip() for f in group_match.group(1).split(',')]
209
-
210
- # Extract HAVING
211
- having_match = re.search(r'HAVING\s+(.+?)(?:ORDER|LIMIT|$)', sql, re.IGNORECASE | re.DOTALL)
212
- if having_match:
213
- params['having'] = self._parse_where_condition(having_match.group(1).strip())
214
-
215
- return params
216
-
217
- def extract_order_by_params(self, sql: str) -> Dict[str, Any]:
218
- """Extract ORDER BY parameters."""
219
- params = {}
220
-
221
- # ORDER BY field ASC/DESC
222
- order_match = re.search(r'ORDER\s+BY\s+(.*?)(?:LIMIT|$)', sql, re.IGNORECASE | re.DOTALL)
223
- if order_match:
224
- order_clause = order_match.group(1).strip()
225
-
226
- # Parse: field ASC, field2 DESC
227
- order_fields = []
228
- for field_spec in order_clause.split(','):
229
- field_spec = field_spec.strip()
230
- if ' DESC' in field_spec.upper():
231
- field = field_spec.upper().replace(' DESC', '').strip()
232
- order_fields.append({'field': field, 'direction': 'DESC'})
233
- elif ' ASC' in field_spec.upper():
234
- field = field_spec.upper().replace(' ASC', '').strip()
235
- order_fields.append({'field': field, 'direction': 'ASC'})
236
- else:
237
- order_fields.append({'field': field_spec, 'direction': 'ASC'})
238
-
239
- params['fields'] = order_fields
240
-
241
- return params
242
-
243
- def _parse_where_condition(self, condition: str) -> Dict[str, Any]:
244
- """
245
- Parse WHERE condition into structured format.
246
-
247
- Supports: field operator value
248
- Examples: age > 50, name = 'John', price >= 100
249
- """
250
- condition = condition.strip()
251
-
252
- # Check for operators in order of precedence
253
- operators = ['>=', '<=', '!=', '<>', '>', '<', '=', 'LIKE', 'IN']
254
-
255
- for op in operators:
256
- # Case-insensitive for word operators
257
- if op.isalpha():
258
- pattern = rf'\s+{op}\s+'
259
- match = re.search(pattern, condition, re.IGNORECASE)
260
- if match:
261
- field = condition[:match.start()].strip()
262
- value = condition[match.end():].strip()
263
- return {
264
- 'field': field,
265
- 'operator': op.upper(),
266
- 'value': self._parse_value(value) if op.upper() != 'IN' else self._parse_in_values(value)
267
- }
268
- else:
269
- if op in condition:
270
- parts = condition.split(op, 1)
271
- if len(parts) == 2:
272
- return {
273
- 'field': parts[0].strip(),
274
- 'operator': op,
275
- 'value': self._parse_value(parts[1].strip())
276
- }
277
-
278
- # Can't parse - return as expression
279
- return {'expression': condition}
280
-
281
- def _parse_in_values(self, values_str: str) -> List:
282
- """Parse IN clause values."""
283
- # IN ['value1', 'value2'] or IN ('value1', 'value2')
284
- values_str = values_str.strip().strip('[]()').strip()
285
- values = [self._parse_value(v.strip()) for v in values_str.split(',')]
286
- return values
287
-
288
- def _parse_set_clause(self, set_str: str) -> Dict[str, Any]:
289
- """Parse SET clause in UPDATE."""
290
- assignments = {}
291
-
292
- # Split by comma
293
- for assignment in set_str.split(','):
294
- if '=' in assignment:
295
- field, value = assignment.split('=', 1)
296
- assignments[field.strip()] = self._parse_value(value.strip())
297
-
298
- return assignments
299
-
300
- def _parse_dict_literal(self, dict_str: str) -> Dict[str, Any]:
301
- """Parse dictionary literal from string."""
302
- # Simple parser for {key: value, key2: value2}
303
- dict_str = dict_str.strip('{}').strip()
304
- result = {}
305
-
306
- for pair in dict_str.split(','):
307
- if ':' in pair:
308
- key, value = pair.split(':', 1)
309
- result[key.strip()] = self._parse_value(value.strip())
310
-
311
- return result
312
-
313
- def _parse_tuple_literal(self, tuple_str: str) -> List[Any]:
314
- """Parse tuple literal from string."""
315
- # Simple parser for (value1, value2, value3)
316
- tuple_str = tuple_str.strip('()').strip()
317
- return [self._parse_value(v.strip()) for v in tuple_str.split(',')]
318
-
@@ -1,24 +0,0 @@
1
- """
2
- Query Strategies Package
3
-
4
- This package contains all query strategy implementations organized by type:
5
- - Linear queries (index-based, value-based)
6
- - Tree queries (key-based, range queries)
7
- - Graph queries (path queries, neighbor queries)
8
-
9
- Company: eXonware.com
10
- Author: Eng. Muhammad AlShehri
11
- Email: connect@exonware.com
12
- Version: 0.0.1.21
13
- Generation Date: January 2, 2025
14
- """
15
-
16
- from .base import AQueryStrategy
17
- from .xwquery_strategy import XWQueryScriptStrategy
18
- from .xwnode_executor import XWNodeQueryActionExecutor
19
-
20
- __all__ = [
21
- 'AQueryStrategy',
22
- 'XWQueryScriptStrategy',
23
- 'XWNodeQueryActionExecutor'
24
- ]
@@ -1,236 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Query Strategy Base Classes
4
-
5
- This module defines the abstract base classes for all query strategy implementations:
6
- - AQueryStrategy: Base strategy for all query implementations
7
-
8
- Company: eXonware.com
9
- Author: Eng. Muhammad AlShehri
10
- Email: connect@exonware.com
11
- Version: 0.0.1.21
12
- Generation Date: January 2, 2025
13
- """
14
-
15
- from abc import ABC, abstractmethod
16
- from typing import Any, Optional, List, Dict, Union, Type
17
- from datetime import datetime
18
-
19
- from ...contracts import iQuery, iQueryResult, IQueryStrategy, QueryMode, QueryTrait
20
- from ...errors import XWNodeTypeError, XWNodeValueError
21
- from ...base import XWNodeBase
22
-
23
-
24
- class AQueryStrategy(IQueryStrategy):
25
- """Base strategy for all query implementations with XWQuery Script support."""
26
-
27
- def __init__(self, **options):
28
- """Initialize query strategy."""
29
- self._options = options
30
- self._mode = options.get('mode', QueryMode.AUTO)
31
- self._traits = options.get('traits', QueryTrait.NONE)
32
-
33
- @abstractmethod
34
- def execute(self, query: str, **kwargs) -> Any:
35
- """Execute query."""
36
- pass
37
-
38
- @abstractmethod
39
- def validate_query(self, query: str) -> bool:
40
- """Validate query syntax."""
41
- pass
42
-
43
- @abstractmethod
44
- def get_query_plan(self, query: str) -> Dict[str, Any]:
45
- """Get query execution plan."""
46
- pass
47
-
48
- def get_mode(self) -> QueryMode:
49
- """Get strategy mode."""
50
- return self._mode
51
-
52
- def get_traits(self) -> QueryTrait:
53
- """Get strategy traits."""
54
- return self._traits
55
-
56
- def to_native(self) -> 'XWQueryScriptStrategy':
57
- """Convert this strategy to XWQueryScriptStrategy using actions."""
58
- from .xwquery_strategy import XWQueryScriptStrategy
59
- return XWQueryScriptStrategy()
60
-
61
- def to_actions_tree(self, query: str) -> XWNodeBase:
62
- """Convert query to actions tree - default implementation."""
63
- script_strategy = self.to_native().from_format(query, self.get_query_type())
64
- return script_strategy.get_actions_tree()
65
-
66
- def from_actions_tree(self, actions_tree: XWNodeBase) -> str:
67
- """Convert actions tree to query - default implementation."""
68
- script_strategy = self.to_native()
69
- script_strategy._actions_tree = actions_tree
70
- return script_strategy.to_format(self.get_query_type())
71
-
72
- def get_query_type(self) -> str:
73
- """Get the query type for this strategy."""
74
- return self.__class__.__name__.replace('Strategy', '').upper()
75
-
76
-
77
- class AQueryActionExecutor(AQueryStrategy):
78
- """Abstract base for query action executors with XWQuery Script support."""
79
-
80
- @abstractmethod
81
- def execute_query(self, query: str, query_type: str, **kwargs) -> Any:
82
- """Execute a query on this backend."""
83
- pass
84
-
85
- @abstractmethod
86
- def validate_query(self, query: str, query_type: str) -> bool:
87
- """Validate if this backend can handle the query."""
88
- pass
89
-
90
- @abstractmethod
91
- def get_supported_query_types(self) -> List[str]:
92
- """Get list of query types this backend supports."""
93
- pass
94
-
95
- def to_native(self) -> 'XWQueryScriptStrategy':
96
- """Convert this executor to XWQueryScriptStrategy using actions."""
97
- from .xwquery_strategy import XWQueryScriptStrategy
98
- return XWQueryScriptStrategy()
99
-
100
- def to_actions_tree(self, query: str) -> XWNodeBase:
101
- """Convert query to actions tree - default implementation."""
102
- script_strategy = self.to_native().from_format(query, self.get_query_type())
103
- return script_strategy.get_actions_tree()
104
-
105
- def from_actions_tree(self, actions_tree: XWNodeBase) -> str:
106
- """Convert actions tree to query - default implementation."""
107
- script_strategy = self.to_native()
108
- script_strategy._actions_tree = actions_tree
109
- return script_strategy.to_format(self.get_query_type())
110
-
111
-
112
- class ALinearQueryStrategy(AQueryStrategy):
113
- """Linear query capabilities."""
114
-
115
- def find_by_index(self, index: int) -> Any:
116
- """Find element by index."""
117
- raise NotImplementedError("Subclasses must implement find_by_index")
118
-
119
- def find_by_value(self, value: Any) -> List[int]:
120
- """Find indices by value."""
121
- raise NotImplementedError("Subclasses must implement find_by_value")
122
-
123
- def range_query(self, start_index: int, end_index: int) -> List[Any]:
124
- """Query range of indices."""
125
- raise NotImplementedError("Subclasses must implement range_query")
126
-
127
- def count_occurrences(self, value: Any) -> int:
128
- """Count occurrences of value."""
129
- raise NotImplementedError("Subclasses must implement count_occurrences")
130
-
131
-
132
- class ATreeQueryStrategy(AQueryStrategy):
133
- """Tree query capabilities."""
134
-
135
- def find_by_key(self, key: Any) -> Any:
136
- """Find by key."""
137
- raise NotImplementedError("Subclasses must implement find_by_key")
138
-
139
- def range_query(self, start_key: Any, end_key: Any) -> List[Any]:
140
- """Range query."""
141
- raise NotImplementedError("Subclasses must implement range_query")
142
-
143
- def prefix_query(self, prefix: str) -> List[Any]:
144
- """Find all keys with prefix."""
145
- raise NotImplementedError("Subclasses must implement prefix_query")
146
-
147
- def suffix_query(self, suffix: str) -> List[Any]:
148
- """Find all keys with suffix."""
149
- raise NotImplementedError("Subclasses must implement suffix_query")
150
-
151
-
152
- class AGraphQueryStrategy(AQueryStrategy):
153
- """Graph query capabilities."""
154
-
155
- def path_query(self, start: Any, end: Any) -> List[Any]:
156
- """Path query."""
157
- raise NotImplementedError("Subclasses must implement path_query")
158
-
159
- def neighbor_query(self, node: Any) -> List[Any]:
160
- """Neighbor query."""
161
- raise NotImplementedError("Subclasses must implement neighbor_query")
162
-
163
- def shortest_path_query(self, start: Any, end: Any) -> List[Any]:
164
- """Shortest path query."""
165
- raise NotImplementedError("Subclasses must implement shortest_path_query")
166
-
167
- def connected_components_query(self) -> List[List[Any]]:
168
- """Connected components query."""
169
- raise NotImplementedError("Subclasses must implement connected_components_query")
170
-
171
- def cycle_detection_query(self) -> List[List[Any]]:
172
- """Cycle detection query."""
173
- raise NotImplementedError("Subclasses must implement cycle_detection_query")
174
-
175
-
176
- class AStructuredQueryStrategy(AQueryStrategy):
177
- """Structured query capabilities for SQL-like languages."""
178
-
179
- @abstractmethod
180
- def select_query(self, table: str, columns: List[str], where_clause: str = None) -> Any:
181
- """Execute SELECT query."""
182
- pass
183
-
184
- @abstractmethod
185
- def insert_query(self, table: str, data: Dict[str, Any]) -> Any:
186
- """Execute INSERT query."""
187
- pass
188
-
189
- @abstractmethod
190
- def update_query(self, table: str, data: Dict[str, Any], where_clause: str = None) -> Any:
191
- """Execute UPDATE query."""
192
- pass
193
-
194
- @abstractmethod
195
- def delete_query(self, table: str, where_clause: str = None) -> Any:
196
- """Execute DELETE query."""
197
- pass
198
-
199
- @abstractmethod
200
- def join_query(self, tables: List[str], join_conditions: List[str]) -> Any:
201
- """Execute JOIN query."""
202
- pass
203
-
204
- @abstractmethod
205
- def aggregate_query(self, table: str, functions: List[str], group_by: List[str] = None) -> Any:
206
- """Execute aggregate query."""
207
- pass
208
-
209
-
210
- class ADocumentQueryStrategy(AQueryStrategy):
211
- """Document query capabilities for JSON/XML-like languages."""
212
-
213
- @abstractmethod
214
- def path_query(self, path: str) -> Any:
215
- """Execute path-based query."""
216
- pass
217
-
218
- @abstractmethod
219
- def filter_query(self, filter_expression: str) -> Any:
220
- """Execute filter query."""
221
- pass
222
-
223
- @abstractmethod
224
- def projection_query(self, fields: List[str]) -> Any:
225
- """Execute projection query."""
226
- pass
227
-
228
- @abstractmethod
229
- def sort_query(self, sort_fields: List[str], order: str = "asc") -> Any:
230
- """Execute sort query."""
231
- pass
232
-
233
- @abstractmethod
234
- def limit_query(self, limit: int, offset: int = 0) -> Any:
235
- """Execute limit query."""
236
- pass