exonware-xwnode 0.0.1.13__py3-none-any.whl → 0.0.1.15__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 (213) hide show
  1. exonware/__init__.py +1 -1
  2. exonware/xwnode/__init__.py +1 -1
  3. exonware/xwnode/base.py +1 -1
  4. exonware/xwnode/common/__init__.py +20 -0
  5. exonware/xwnode/common/management/__init__.py +26 -0
  6. exonware/xwnode/{strategies → common/management}/manager.py +2 -2
  7. exonware/xwnode/common/monitoring/__init__.py +26 -0
  8. exonware/xwnode/{strategies → common/monitoring}/metrics.py +2 -2
  9. exonware/xwnode/{strategies → common/monitoring}/pattern_detector.py +2 -2
  10. exonware/xwnode/{strategies → common/monitoring}/performance_monitor.py +2 -2
  11. exonware/xwnode/common/patterns/__init__.py +26 -0
  12. exonware/xwnode/{strategies → common/patterns}/advisor.py +1 -1
  13. exonware/xwnode/{strategies → common/patterns}/flyweight.py +4 -4
  14. exonware/xwnode/{strategies → common/patterns}/registry.py +109 -112
  15. exonware/xwnode/common/utils/__init__.py +26 -0
  16. exonware/xwnode/{strategies/edges → edges/strategies}/__init__.py +1 -1
  17. exonware/xwnode/{strategies/edges → edges/strategies}/base.py +3 -3
  18. exonware/xwnode/facade.py +4 -3
  19. exonware/xwnode/{strategies/nodes → nodes/strategies}/__init__.py +1 -1
  20. exonware/xwnode/{strategies/nodes → nodes/strategies}/adjacency_list.py +7 -2
  21. exonware/xwnode/{strategies/nodes → nodes/strategies}/aho_corasick.py +6 -1
  22. exonware/xwnode/{strategies/nodes → nodes/strategies}/array_list.py +6 -1
  23. exonware/xwnode/{strategies/nodes → nodes/strategies}/base.py +24 -4
  24. exonware/xwnode/nodes/strategies/contracts.py +116 -0
  25. exonware/xwnode/{strategies/nodes → nodes/strategies}/deque.py +7 -2
  26. exonware/xwnode/{strategies/nodes → nodes/strategies}/hash_map.py +4 -0
  27. exonware/xwnode/{strategies/nodes → nodes/strategies}/heap.py +6 -1
  28. exonware/xwnode/{strategies/nodes → nodes/strategies}/linked_list.py +6 -1
  29. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_aho_corasick.py +6 -1
  30. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_array_list.py +4 -0
  31. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_avl_tree.py +6 -1
  32. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_b_plus_tree.py +6 -1
  33. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_bitmap.py +6 -1
  34. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_bitset_dynamic.py +6 -1
  35. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_bloom_filter.py +4 -0
  36. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_btree.py +6 -1
  37. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_count_min_sketch.py +4 -0
  38. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_cow_tree.py +6 -1
  39. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_fenwick_tree.py +6 -1
  40. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_hash_map.py +4 -0
  41. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_heap.py +6 -1
  42. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_hyperloglog.py +4 -0
  43. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_linked_list.py +4 -0
  44. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_lsm_tree.py +6 -1
  45. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_ordered_map.py +6 -1
  46. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_ordered_map_balanced.py +6 -1
  47. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_patricia.py +6 -1
  48. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_persistent_tree.py +6 -1
  49. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_radix_trie.py +6 -1
  50. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_red_black_tree.py +6 -1
  51. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_roaring_bitmap.py +6 -1
  52. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_segment_tree.py +6 -1
  53. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_set_hash.py +4 -0
  54. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_set_tree.py +6 -1
  55. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_skip_list.py +6 -1
  56. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_splay_tree.py +6 -1
  57. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_suffix_array.py +6 -1
  58. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_treap.py +6 -1
  59. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_tree_graph_hybrid.py +4 -0
  60. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_trie.py +6 -1
  61. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_union_find.py +6 -1
  62. exonware/xwnode/{strategies/nodes → nodes/strategies}/node_xdata_optimized.py +4 -0
  63. exonware/xwnode/{strategies/nodes → nodes/strategies}/priority_queue.py +7 -2
  64. exonware/xwnode/{strategies/nodes → nodes/strategies}/queue.py +7 -2
  65. exonware/xwnode/{strategies/nodes → nodes/strategies}/sparse_matrix.py +7 -2
  66. exonware/xwnode/{strategies/nodes → nodes/strategies}/stack.py +7 -2
  67. exonware/xwnode/{strategies/nodes → nodes/strategies}/trie.py +6 -1
  68. exonware/xwnode/{strategies/nodes → nodes/strategies}/union_find.py +6 -1
  69. exonware/xwnode/queries/executors/__init__.py +47 -0
  70. exonware/xwnode/queries/executors/advanced/__init__.py +37 -0
  71. exonware/xwnode/queries/executors/advanced/aggregate_executor.py +50 -0
  72. exonware/xwnode/queries/executors/advanced/ask_executor.py +50 -0
  73. exonware/xwnode/queries/executors/advanced/construct_executor.py +50 -0
  74. exonware/xwnode/queries/executors/advanced/describe_executor.py +50 -0
  75. exonware/xwnode/queries/executors/advanced/for_loop_executor.py +50 -0
  76. exonware/xwnode/queries/executors/advanced/foreach_executor.py +50 -0
  77. exonware/xwnode/queries/executors/advanced/join_executor.py +50 -0
  78. exonware/xwnode/queries/executors/advanced/let_executor.py +50 -0
  79. exonware/xwnode/queries/executors/advanced/mutation_executor.py +50 -0
  80. exonware/xwnode/queries/executors/advanced/options_executor.py +50 -0
  81. exonware/xwnode/queries/executors/advanced/pipe_executor.py +50 -0
  82. exonware/xwnode/queries/executors/advanced/subscribe_executor.py +50 -0
  83. exonware/xwnode/queries/executors/advanced/subscription_executor.py +50 -0
  84. exonware/xwnode/queries/executors/advanced/union_executor.py +50 -0
  85. exonware/xwnode/queries/executors/advanced/window_executor.py +51 -0
  86. exonware/xwnode/queries/executors/advanced/with_cte_executor.py +50 -0
  87. exonware/xwnode/queries/executors/aggregation/__init__.py +21 -0
  88. exonware/xwnode/queries/executors/aggregation/avg_executor.py +50 -0
  89. exonware/xwnode/queries/executors/aggregation/count_executor.py +38 -0
  90. exonware/xwnode/queries/executors/aggregation/distinct_executor.py +50 -0
  91. exonware/xwnode/queries/executors/aggregation/group_executor.py +50 -0
  92. exonware/xwnode/queries/executors/aggregation/having_executor.py +50 -0
  93. exonware/xwnode/queries/executors/aggregation/max_executor.py +50 -0
  94. exonware/xwnode/queries/executors/aggregation/min_executor.py +50 -0
  95. exonware/xwnode/queries/executors/aggregation/sum_executor.py +50 -0
  96. exonware/xwnode/queries/executors/aggregation/summarize_executor.py +50 -0
  97. exonware/xwnode/queries/executors/array/__init__.py +9 -0
  98. exonware/xwnode/queries/executors/array/indexing_executor.py +51 -0
  99. exonware/xwnode/queries/executors/array/slicing_executor.py +51 -0
  100. exonware/xwnode/queries/executors/base.py +257 -0
  101. exonware/xwnode/queries/executors/capability_checker.py +204 -0
  102. exonware/xwnode/queries/executors/contracts.py +166 -0
  103. exonware/xwnode/queries/executors/core/__init__.py +17 -0
  104. exonware/xwnode/queries/executors/core/create_executor.py +96 -0
  105. exonware/xwnode/queries/executors/core/delete_executor.py +99 -0
  106. exonware/xwnode/queries/executors/core/drop_executor.py +100 -0
  107. exonware/xwnode/queries/executors/core/insert_executor.py +39 -0
  108. exonware/xwnode/queries/executors/core/select_executor.py +152 -0
  109. exonware/xwnode/queries/executors/core/update_executor.py +102 -0
  110. exonware/xwnode/queries/executors/data/__init__.py +13 -0
  111. exonware/xwnode/queries/executors/data/alter_executor.py +50 -0
  112. exonware/xwnode/queries/executors/data/load_executor.py +50 -0
  113. exonware/xwnode/queries/executors/data/merge_executor.py +50 -0
  114. exonware/xwnode/queries/executors/data/store_executor.py +50 -0
  115. exonware/xwnode/queries/executors/engine.py +221 -0
  116. exonware/xwnode/queries/executors/errors.py +68 -0
  117. exonware/xwnode/queries/executors/filtering/__init__.py +25 -0
  118. exonware/xwnode/queries/executors/filtering/between_executor.py +80 -0
  119. exonware/xwnode/queries/executors/filtering/filter_executor.py +79 -0
  120. exonware/xwnode/queries/executors/filtering/has_executor.py +70 -0
  121. exonware/xwnode/queries/executors/filtering/in_executor.py +70 -0
  122. exonware/xwnode/queries/executors/filtering/like_executor.py +76 -0
  123. exonware/xwnode/queries/executors/filtering/optional_executor.py +76 -0
  124. exonware/xwnode/queries/executors/filtering/range_executor.py +80 -0
  125. exonware/xwnode/queries/executors/filtering/term_executor.py +77 -0
  126. exonware/xwnode/queries/executors/filtering/values_executor.py +71 -0
  127. exonware/xwnode/queries/executors/filtering/where_executor.py +44 -0
  128. exonware/xwnode/queries/executors/graph/__init__.py +15 -0
  129. exonware/xwnode/queries/executors/graph/in_traverse_executor.py +51 -0
  130. exonware/xwnode/queries/executors/graph/match_executor.py +51 -0
  131. exonware/xwnode/queries/executors/graph/out_executor.py +51 -0
  132. exonware/xwnode/queries/executors/graph/path_executor.py +51 -0
  133. exonware/xwnode/queries/executors/graph/return_executor.py +51 -0
  134. exonware/xwnode/queries/executors/ordering/__init__.py +9 -0
  135. exonware/xwnode/queries/executors/ordering/by_executor.py +50 -0
  136. exonware/xwnode/queries/executors/ordering/order_executor.py +51 -0
  137. exonware/xwnode/queries/executors/projection/__init__.py +9 -0
  138. exonware/xwnode/queries/executors/projection/extend_executor.py +50 -0
  139. exonware/xwnode/queries/executors/projection/project_executor.py +50 -0
  140. exonware/xwnode/queries/executors/registry.py +173 -0
  141. exonware/xwnode/queries/executors/types.py +93 -0
  142. exonware/xwnode/queries/parsers/__init__.py +26 -0
  143. exonware/xwnode/queries/parsers/base.py +86 -0
  144. exonware/xwnode/queries/parsers/contracts.py +46 -0
  145. exonware/xwnode/queries/parsers/errors.py +53 -0
  146. exonware/xwnode/queries/parsers/sql_param_extractor.py +318 -0
  147. exonware/xwnode/{strategies/queries → queries/strategies}/__init__.py +1 -1
  148. exonware/xwnode/{strategies/queries → queries/strategies}/base.py +1 -1
  149. exonware/xwnode/{strategies/queries → queries/strategies}/cql.py +1 -1
  150. exonware/xwnode/{strategies/queries → queries/strategies}/cypher.py +1 -1
  151. exonware/xwnode/{strategies/queries → queries/strategies}/datalog.py +1 -1
  152. exonware/xwnode/{strategies/queries → queries/strategies}/elastic_dsl.py +1 -1
  153. exonware/xwnode/{strategies/queries → queries/strategies}/eql.py +1 -1
  154. exonware/xwnode/{strategies/queries → queries/strategies}/flux.py +1 -1
  155. exonware/xwnode/{strategies/queries → queries/strategies}/gql.py +1 -1
  156. exonware/xwnode/{strategies/queries → queries/strategies}/graphql.py +1 -1
  157. exonware/xwnode/{strategies/queries → queries/strategies}/gremlin.py +1 -1
  158. exonware/xwnode/{strategies/queries → queries/strategies}/hiveql.py +1 -1
  159. exonware/xwnode/{strategies/queries → queries/strategies}/hql.py +1 -1
  160. exonware/xwnode/{strategies/queries → queries/strategies}/jmespath.py +1 -1
  161. exonware/xwnode/{strategies/queries → queries/strategies}/jq.py +1 -1
  162. exonware/xwnode/{strategies/queries → queries/strategies}/json_query.py +1 -1
  163. exonware/xwnode/{strategies/queries → queries/strategies}/jsoniq.py +1 -1
  164. exonware/xwnode/{strategies/queries → queries/strategies}/kql.py +1 -1
  165. exonware/xwnode/{strategies/queries → queries/strategies}/linq.py +1 -1
  166. exonware/xwnode/{strategies/queries → queries/strategies}/logql.py +1 -1
  167. exonware/xwnode/{strategies/queries → queries/strategies}/mql.py +1 -1
  168. exonware/xwnode/{strategies/queries → queries/strategies}/n1ql.py +1 -1
  169. exonware/xwnode/{strategies/queries → queries/strategies}/partiql.py +1 -1
  170. exonware/xwnode/{strategies/queries → queries/strategies}/pig.py +1 -1
  171. exonware/xwnode/{strategies/queries → queries/strategies}/promql.py +1 -1
  172. exonware/xwnode/{strategies/queries → queries/strategies}/sparql.py +1 -1
  173. exonware/xwnode/{strategies/queries → queries/strategies}/sql.py +1 -1
  174. exonware/xwnode/{strategies/queries → queries/strategies}/xml_query.py +1 -1
  175. exonware/xwnode/{strategies/queries → queries/strategies}/xpath.py +1 -1
  176. exonware/xwnode/{strategies/queries → queries/strategies}/xquery.py +1 -1
  177. exonware/xwnode/{strategies/queries → queries/strategies}/xwnode_executor.py +1 -1
  178. exonware/xwnode/{strategies/queries → queries/strategies}/xwquery.py +43 -11
  179. exonware/xwnode/strategies/__init__.py +8 -8
  180. exonware/xwnode/version.py +3 -3
  181. {exonware_xwnode-0.0.1.13.dist-info → exonware_xwnode-0.0.1.15.dist-info}/METADATA +2 -3
  182. exonware_xwnode-0.0.1.15.dist-info/RECORD +214 -0
  183. exonware/xwnode/strategies/impls/__init__.py +0 -13
  184. exonware/xwnode/strategies/nodes/_base_node.py +0 -307
  185. exonware_xwnode-0.0.1.13.dist-info/RECORD +0 -132
  186. /exonware/xwnode/{strategies → common/management}/migration.py +0 -0
  187. /exonware/xwnode/{strategies → common/utils}/simple.py +0 -0
  188. /exonware/xwnode/{strategies → common/utils}/utils.py +0 -0
  189. /exonware/xwnode/{strategies/impls → edges/strategies}/_base_edge.py +0 -0
  190. /exonware/xwnode/{strategies/edges → edges/strategies}/adj_list.py +0 -0
  191. /exonware/xwnode/{strategies/edges → edges/strategies}/adj_matrix.py +0 -0
  192. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_adj_list.py +0 -0
  193. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_adj_matrix.py +0 -0
  194. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_bidir_wrapper.py +0 -0
  195. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_block_adj_matrix.py +0 -0
  196. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_coo.py +0 -0
  197. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_csc.py +0 -0
  198. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_csr.py +0 -0
  199. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_dynamic_adj_list.py +0 -0
  200. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_flow_network.py +0 -0
  201. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_hyperedge_set.py +0 -0
  202. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_neural_graph.py +0 -0
  203. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_octree.py +0 -0
  204. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_property_store.py +0 -0
  205. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_quadtree.py +0 -0
  206. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_rtree.py +0 -0
  207. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_temporal_edgeset.py +0 -0
  208. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_tree_graph_basic.py +0 -0
  209. /exonware/xwnode/{strategies/impls → edges/strategies}/edge_weighted_graph.py +0 -0
  210. /exonware/xwnode/{strategies/impls → nodes/strategies}/_base_node.py +0 -0
  211. /exonware/xwnode/{strategies/nodes → nodes/strategies}/node_cuckoo_hash.py +0 -0
  212. {exonware_xwnode-0.0.1.13.dist-info → exonware_xwnode-0.0.1.15.dist-info}/WHEEL +0 -0
  213. {exonware_xwnode-0.0.1.13.dist-info → exonware_xwnode-0.0.1.15.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ #exonware/xwnode/src/exonware/xwnode/queries/parsers/base.py
4
+
5
+ Parser Base Classes
6
+
7
+ Abstract base class for parameter extractors.
8
+ Follows DEV_GUIDELINES.md: base.py extends contracts.py interfaces.
9
+
10
+ Company: eXonware.com
11
+ Author: Eng. Muhammad AlShehri
12
+ Email: connect@exonware.com
13
+ Version: 0.0.1.15
14
+ Generation Date: 09-Oct-2025
15
+ """
16
+
17
+ from abc import ABC
18
+ from typing import Dict, Any, Union
19
+
20
+ from .contracts import IParamExtractor
21
+ from .errors import ParseError
22
+
23
+
24
+ class AParamExtractor(IParamExtractor, ABC):
25
+ """
26
+ Abstract base class for parameter extractors.
27
+
28
+ Extends IParamExtractor interface per DEV_GUIDELINES.md.
29
+ """
30
+
31
+ def _parse_value(self, value_str: str) -> Union[str, int, float, bool, None]:
32
+ """
33
+ Parse value from string to appropriate type.
34
+
35
+ Args:
36
+ value_str: String representation of value
37
+
38
+ Returns:
39
+ Parsed value with correct type
40
+ """
41
+ value_str = value_str.strip().strip('"').strip("'")
42
+
43
+ # Try boolean
44
+ if value_str.lower() == 'true':
45
+ return True
46
+ if value_str.lower() == 'false':
47
+ return False
48
+ if value_str.lower() == 'null' or value_str.lower() == 'none':
49
+ return None
50
+
51
+ # Try number
52
+ try:
53
+ if '.' in value_str:
54
+ return float(value_str)
55
+ return int(value_str)
56
+ except ValueError:
57
+ pass
58
+
59
+ # Return as string
60
+ return value_str
61
+
62
+ def _split_fields(self, fields_str: str) -> list:
63
+ """Split comma-separated fields, handling nested expressions."""
64
+ if fields_str.strip() == '*':
65
+ return ['*']
66
+
67
+ fields = []
68
+ current = []
69
+ paren_depth = 0
70
+
71
+ for char in fields_str:
72
+ if char == '(':
73
+ paren_depth += 1
74
+ elif char == ')':
75
+ paren_depth -= 1
76
+ elif char == ',' and paren_depth == 0:
77
+ fields.append(''.join(current).strip())
78
+ current = []
79
+ continue
80
+ current.append(char)
81
+
82
+ if current:
83
+ fields.append(''.join(current).strip())
84
+
85
+ return fields
86
+
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ #exonware/xwnode/src/exonware/xwnode/queries/parsers/contracts.py
4
+
5
+ Parser Contracts
6
+
7
+ Interfaces for query parameter extractors.
8
+ Follows DEV_GUIDELINES.md: contracts.py for all interfaces.
9
+
10
+ Company: eXonware.com
11
+ Author: Eng. Muhammad AlShehri
12
+ Email: connect@exonware.com
13
+ Version: 0.0.1.15
14
+ Generation Date: 09-Oct-2025
15
+ """
16
+
17
+ from abc import ABC, abstractmethod
18
+ from typing import Dict, Any
19
+
20
+
21
+ class IParamExtractor(ABC):
22
+ """
23
+ Interface for parameter extractors.
24
+
25
+ Extracts structured parameters from query strings.
26
+ """
27
+
28
+ @abstractmethod
29
+ def extract_params(self, query: str, action_type: str) -> Dict[str, Any]:
30
+ """
31
+ Extract structured parameters from query.
32
+
33
+ Args:
34
+ query: Raw query string
35
+ action_type: Type of action (SELECT, INSERT, etc.)
36
+
37
+ Returns:
38
+ Structured parameters dictionary
39
+ """
40
+ pass
41
+
42
+ @abstractmethod
43
+ def can_parse(self, query: str) -> bool:
44
+ """Check if this extractor can parse the query."""
45
+ pass
46
+
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ #exonware/xwnode/src/exonware/xwnode/queries/parsers/errors.py
4
+
5
+ Parser Errors
6
+
7
+ Module-specific errors for query parsers.
8
+ Extends root error classes per DEV_GUIDELINES.md - no redundancy.
9
+
10
+ Company: eXonware.com
11
+ Author: Eng. Muhammad AlShehri
12
+ Email: connect@exonware.com
13
+ Version: 0.0.1.15
14
+ Generation Date: 09-Oct-2025
15
+ """
16
+
17
+ # Import and REUSE root error classes per DEV_GUIDELINES
18
+ from ...errors import XWNodeError, XWNodeValueError
19
+
20
+
21
+ class ParserError(XWNodeError):
22
+ """
23
+ Base error for parser operations.
24
+
25
+ Extends XWNodeError from root - follows DEV_GUIDELINES principle.
26
+ """
27
+ pass
28
+
29
+
30
+ class ParseError(ParserError):
31
+ """Raised when query parsing fails."""
32
+
33
+ def __init__(self, query: str, reason: str, position: int = None):
34
+ message = f"Failed to parse query: {reason}"
35
+ if position is not None:
36
+ message += f" at position {position}"
37
+ super().__init__(message)
38
+ self.query = query
39
+ self.reason = reason
40
+ self.position = position
41
+
42
+
43
+ class UnsupportedSyntaxError(ParserError):
44
+ """Raised when syntax is not supported."""
45
+ pass
46
+
47
+
48
+ __all__ = [
49
+ 'ParserError',
50
+ 'ParseError',
51
+ 'UnsupportedSyntaxError',
52
+ ]
53
+
@@ -0,0 +1,318 @@
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.15
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
+
@@ -9,7 +9,7 @@ This package contains all query strategy implementations organized by type:
9
9
  Company: eXonware.com
10
10
  Author: Eng. Muhammad AlShehri
11
11
  Email: connect@exonware.com
12
- Version: 0.0.1.13
12
+ Version: 0.0.1.15
13
13
  Generation Date: January 2, 2025
14
14
  """
15
15
 
@@ -8,7 +8,7 @@ This module defines the abstract base classes for all query strategy implementat
8
8
  Company: eXonware.com
9
9
  Author: Eng. Muhammad AlShehri
10
10
  Email: connect@exonware.com
11
- Version: 0.0.1.13
11
+ Version: 0.0.1.15
12
12
  Generation Date: January 2, 2025
13
13
  """
14
14
 
@@ -7,7 +7,7 @@ This module implements the CQL query strategy for Cassandra Query Language opera
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the Cypher query strategy for Neo4j graph queries.
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the Datalog query strategy for Datalog operations.
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the Elasticsearch DSL query strategy for Elasticsearch Qu
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the EQL query strategy for Elasticsearch Query Language o
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the Flux query strategy for InfluxDB Flux operations.
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the GQL query strategy for ISO/IEC 39075:2024 Graph Query
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the GraphQL query strategy for graph-based data queries.
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the Gremlin query strategy for Apache TinkerPop graph que
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the HiveQL query strategy for Apache Hive SQL operations.
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the HQL query strategy for Hibernate Query Language opera
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the JMESPath query strategy for JSON data queries.
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the jq query strategy for jq JSON processor operations.
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the JSON Query strategy for generic JSON operations.
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13
 
@@ -7,7 +7,7 @@ This module implements the JSONiq query strategy for JSON data queries.
7
7
  Company: eXonware.com
8
8
  Author: Eng. Muhammad AlShehri
9
9
  Email: connect@exonware.com
10
- Version: 0.0.1.13
10
+ Version: 0.0.1.15
11
11
  Generation Date: January 2, 2025
12
12
  """
13
13