exonware-xwnode 0.0.1.22__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.
- exonware/__init__.py +1 -1
- exonware/xwnode/__init__.py +18 -5
- exonware/xwnode/add_strategy_types.py +165 -0
- exonware/xwnode/common/__init__.py +1 -1
- exonware/xwnode/common/graph/__init__.py +30 -0
- exonware/xwnode/common/graph/caching.py +131 -0
- exonware/xwnode/common/graph/contracts.py +100 -0
- exonware/xwnode/common/graph/errors.py +44 -0
- exonware/xwnode/common/graph/indexing.py +260 -0
- exonware/xwnode/common/graph/manager.py +568 -0
- exonware/xwnode/common/management/__init__.py +3 -5
- exonware/xwnode/common/management/manager.py +2 -2
- exonware/xwnode/common/management/migration.py +3 -3
- exonware/xwnode/common/monitoring/__init__.py +3 -5
- exonware/xwnode/common/monitoring/metrics.py +6 -2
- exonware/xwnode/common/monitoring/pattern_detector.py +1 -1
- exonware/xwnode/common/monitoring/performance_monitor.py +5 -1
- exonware/xwnode/common/patterns/__init__.py +3 -5
- exonware/xwnode/common/patterns/flyweight.py +5 -1
- exonware/xwnode/common/patterns/registry.py +202 -183
- exonware/xwnode/common/utils/__init__.py +25 -11
- exonware/xwnode/common/utils/simple.py +1 -1
- exonware/xwnode/config.py +3 -8
- exonware/xwnode/contracts.py +4 -105
- exonware/xwnode/defs.py +413 -159
- exonware/xwnode/edges/strategies/__init__.py +86 -4
- exonware/xwnode/edges/strategies/_base_edge.py +2 -2
- exonware/xwnode/edges/strategies/adj_list.py +287 -121
- exonware/xwnode/edges/strategies/adj_matrix.py +316 -222
- exonware/xwnode/edges/strategies/base.py +1 -1
- exonware/xwnode/edges/strategies/{edge_bidir_wrapper.py → bidir_wrapper.py} +45 -4
- exonware/xwnode/edges/strategies/bitemporal.py +520 -0
- exonware/xwnode/edges/strategies/{edge_block_adj_matrix.py → block_adj_matrix.py} +77 -6
- exonware/xwnode/edges/strategies/bv_graph.py +664 -0
- exonware/xwnode/edges/strategies/compressed_graph.py +217 -0
- exonware/xwnode/edges/strategies/{edge_coo.py → coo.py} +46 -4
- exonware/xwnode/edges/strategies/{edge_csc.py → csc.py} +45 -4
- exonware/xwnode/edges/strategies/{edge_csr.py → csr.py} +94 -12
- exonware/xwnode/edges/strategies/{edge_dynamic_adj_list.py → dynamic_adj_list.py} +46 -4
- exonware/xwnode/edges/strategies/edge_list.py +168 -0
- exonware/xwnode/edges/strategies/edge_property_store.py +2 -2
- exonware/xwnode/edges/strategies/euler_tour.py +560 -0
- exonware/xwnode/edges/strategies/{edge_flow_network.py → flow_network.py} +2 -2
- exonware/xwnode/edges/strategies/graphblas.py +449 -0
- exonware/xwnode/edges/strategies/hnsw.py +637 -0
- exonware/xwnode/edges/strategies/hop2_labels.py +467 -0
- exonware/xwnode/edges/strategies/{edge_hyperedge_set.py → hyperedge_set.py} +2 -2
- exonware/xwnode/edges/strategies/incidence_matrix.py +250 -0
- exonware/xwnode/edges/strategies/k2_tree.py +613 -0
- exonware/xwnode/edges/strategies/link_cut.py +626 -0
- exonware/xwnode/edges/strategies/multiplex.py +532 -0
- exonware/xwnode/edges/strategies/{edge_neural_graph.py → neural_graph.py} +2 -2
- exonware/xwnode/edges/strategies/{edge_octree.py → octree.py} +69 -11
- exonware/xwnode/edges/strategies/{edge_quadtree.py → quadtree.py} +66 -10
- exonware/xwnode/edges/strategies/roaring_adj.py +438 -0
- exonware/xwnode/edges/strategies/{edge_rtree.py → rtree.py} +43 -5
- exonware/xwnode/edges/strategies/{edge_temporal_edgeset.py → temporal_edgeset.py} +24 -5
- exonware/xwnode/edges/strategies/{edge_tree_graph_basic.py → tree_graph_basic.py} +78 -7
- exonware/xwnode/edges/strategies/{edge_weighted_graph.py → weighted_graph.py} +188 -10
- exonware/xwnode/errors.py +3 -6
- exonware/xwnode/facade.py +20 -20
- exonware/xwnode/nodes/strategies/__init__.py +29 -9
- exonware/xwnode/nodes/strategies/adjacency_list.py +650 -177
- exonware/xwnode/nodes/strategies/aho_corasick.py +358 -183
- exonware/xwnode/nodes/strategies/array_list.py +36 -3
- exonware/xwnode/nodes/strategies/art.py +581 -0
- exonware/xwnode/nodes/strategies/{node_avl_tree.py → avl_tree.py} +77 -6
- exonware/xwnode/nodes/strategies/{node_b_plus_tree.py → b_plus_tree.py} +81 -40
- exonware/xwnode/nodes/strategies/{node_btree.py → b_tree.py} +79 -9
- exonware/xwnode/nodes/strategies/base.py +469 -98
- exonware/xwnode/nodes/strategies/{node_bitmap.py → bitmap.py} +12 -12
- exonware/xwnode/nodes/strategies/{node_bitset_dynamic.py → bitset_dynamic.py} +11 -11
- exonware/xwnode/nodes/strategies/{node_bloom_filter.py → bloom_filter.py} +15 -2
- exonware/xwnode/nodes/strategies/bloomier_filter.py +519 -0
- exonware/xwnode/nodes/strategies/bw_tree.py +531 -0
- exonware/xwnode/nodes/strategies/contracts.py +1 -1
- exonware/xwnode/nodes/strategies/{node_count_min_sketch.py → count_min_sketch.py} +3 -2
- exonware/xwnode/nodes/strategies/{node_cow_tree.py → cow_tree.py} +135 -13
- exonware/xwnode/nodes/strategies/crdt_map.py +629 -0
- exonware/xwnode/nodes/strategies/{node_cuckoo_hash.py → cuckoo_hash.py} +2 -2
- exonware/xwnode/nodes/strategies/{node_xdata_optimized.py → data_interchange_optimized.py} +21 -4
- exonware/xwnode/nodes/strategies/dawg.py +876 -0
- exonware/xwnode/nodes/strategies/deque.py +321 -153
- exonware/xwnode/nodes/strategies/extendible_hash.py +93 -0
- exonware/xwnode/nodes/strategies/{node_fenwick_tree.py → fenwick_tree.py} +111 -19
- exonware/xwnode/nodes/strategies/hamt.py +403 -0
- exonware/xwnode/nodes/strategies/hash_map.py +354 -67
- exonware/xwnode/nodes/strategies/heap.py +105 -5
- exonware/xwnode/nodes/strategies/hopscotch_hash.py +525 -0
- exonware/xwnode/nodes/strategies/{node_hyperloglog.py → hyperloglog.py} +6 -5
- exonware/xwnode/nodes/strategies/interval_tree.py +742 -0
- exonware/xwnode/nodes/strategies/kd_tree.py +703 -0
- exonware/xwnode/nodes/strategies/learned_index.py +533 -0
- exonware/xwnode/nodes/strategies/linear_hash.py +93 -0
- exonware/xwnode/nodes/strategies/linked_list.py +316 -119
- exonware/xwnode/nodes/strategies/{node_lsm_tree.py → lsm_tree.py} +219 -15
- exonware/xwnode/nodes/strategies/masstree.py +130 -0
- exonware/xwnode/nodes/strategies/{node_persistent_tree.py → persistent_tree.py} +149 -9
- exonware/xwnode/nodes/strategies/priority_queue.py +544 -132
- exonware/xwnode/nodes/strategies/queue.py +249 -120
- exonware/xwnode/nodes/strategies/{node_red_black_tree.py → red_black_tree.py} +183 -72
- exonware/xwnode/nodes/strategies/{node_roaring_bitmap.py → roaring_bitmap.py} +19 -6
- exonware/xwnode/nodes/strategies/rope.py +717 -0
- exonware/xwnode/nodes/strategies/{node_segment_tree.py → segment_tree.py} +106 -106
- exonware/xwnode/nodes/strategies/{node_set_hash.py → set_hash.py} +30 -29
- exonware/xwnode/nodes/strategies/{node_skip_list.py → skip_list.py} +74 -6
- exonware/xwnode/nodes/strategies/sparse_matrix.py +427 -131
- exonware/xwnode/nodes/strategies/{node_splay_tree.py → splay_tree.py} +55 -6
- exonware/xwnode/nodes/strategies/stack.py +244 -112
- exonware/xwnode/nodes/strategies/{node_suffix_array.py → suffix_array.py} +5 -1
- exonware/xwnode/nodes/strategies/t_tree.py +94 -0
- exonware/xwnode/nodes/strategies/{node_treap.py → treap.py} +75 -6
- exonware/xwnode/nodes/strategies/{node_tree_graph_hybrid.py → tree_graph_hybrid.py} +46 -5
- exonware/xwnode/nodes/strategies/trie.py +153 -9
- exonware/xwnode/nodes/strategies/union_find.py +111 -5
- exonware/xwnode/nodes/strategies/veb_tree.py +856 -0
- exonware/xwnode/strategies/__init__.py +5 -51
- exonware/xwnode/version.py +3 -3
- {exonware_xwnode-0.0.1.22.dist-info → exonware_xwnode-0.0.1.23.dist-info}/METADATA +23 -3
- exonware_xwnode-0.0.1.23.dist-info/RECORD +130 -0
- exonware/xwnode/edges/strategies/edge_adj_list.py +0 -353
- exonware/xwnode/edges/strategies/edge_adj_matrix.py +0 -445
- exonware/xwnode/nodes/strategies/_base_node.py +0 -307
- exonware/xwnode/nodes/strategies/node_aho_corasick.py +0 -525
- exonware/xwnode/nodes/strategies/node_array_list.py +0 -179
- exonware/xwnode/nodes/strategies/node_hash_map.py +0 -273
- exonware/xwnode/nodes/strategies/node_heap.py +0 -196
- exonware/xwnode/nodes/strategies/node_linked_list.py +0 -413
- exonware/xwnode/nodes/strategies/node_trie.py +0 -257
- exonware/xwnode/nodes/strategies/node_union_find.py +0 -192
- exonware/xwnode/queries/executors/__init__.py +0 -47
- exonware/xwnode/queries/executors/advanced/__init__.py +0 -37
- exonware/xwnode/queries/executors/advanced/aggregate_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/ask_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/construct_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/describe_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/for_loop_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/foreach_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/join_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/let_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/mutation_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/options_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/pipe_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/subscribe_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/subscription_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/union_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/window_executor.py +0 -51
- exonware/xwnode/queries/executors/advanced/with_cte_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/__init__.py +0 -21
- exonware/xwnode/queries/executors/aggregation/avg_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/count_executor.py +0 -38
- exonware/xwnode/queries/executors/aggregation/distinct_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/group_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/having_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/max_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/min_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/sum_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/summarize_executor.py +0 -50
- exonware/xwnode/queries/executors/array/__init__.py +0 -9
- exonware/xwnode/queries/executors/array/indexing_executor.py +0 -51
- exonware/xwnode/queries/executors/array/slicing_executor.py +0 -51
- exonware/xwnode/queries/executors/base.py +0 -257
- exonware/xwnode/queries/executors/capability_checker.py +0 -204
- exonware/xwnode/queries/executors/contracts.py +0 -166
- exonware/xwnode/queries/executors/core/__init__.py +0 -17
- exonware/xwnode/queries/executors/core/create_executor.py +0 -96
- exonware/xwnode/queries/executors/core/delete_executor.py +0 -99
- exonware/xwnode/queries/executors/core/drop_executor.py +0 -100
- exonware/xwnode/queries/executors/core/insert_executor.py +0 -39
- exonware/xwnode/queries/executors/core/select_executor.py +0 -152
- exonware/xwnode/queries/executors/core/update_executor.py +0 -102
- exonware/xwnode/queries/executors/data/__init__.py +0 -13
- exonware/xwnode/queries/executors/data/alter_executor.py +0 -50
- exonware/xwnode/queries/executors/data/load_executor.py +0 -50
- exonware/xwnode/queries/executors/data/merge_executor.py +0 -50
- exonware/xwnode/queries/executors/data/store_executor.py +0 -50
- exonware/xwnode/queries/executors/defs.py +0 -93
- exonware/xwnode/queries/executors/engine.py +0 -221
- exonware/xwnode/queries/executors/errors.py +0 -68
- exonware/xwnode/queries/executors/filtering/__init__.py +0 -25
- exonware/xwnode/queries/executors/filtering/between_executor.py +0 -80
- exonware/xwnode/queries/executors/filtering/filter_executor.py +0 -79
- exonware/xwnode/queries/executors/filtering/has_executor.py +0 -70
- exonware/xwnode/queries/executors/filtering/in_executor.py +0 -70
- exonware/xwnode/queries/executors/filtering/like_executor.py +0 -76
- exonware/xwnode/queries/executors/filtering/optional_executor.py +0 -76
- exonware/xwnode/queries/executors/filtering/range_executor.py +0 -80
- exonware/xwnode/queries/executors/filtering/term_executor.py +0 -77
- exonware/xwnode/queries/executors/filtering/values_executor.py +0 -71
- exonware/xwnode/queries/executors/filtering/where_executor.py +0 -44
- exonware/xwnode/queries/executors/graph/__init__.py +0 -15
- exonware/xwnode/queries/executors/graph/in_traverse_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/match_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/out_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/path_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/return_executor.py +0 -51
- exonware/xwnode/queries/executors/ordering/__init__.py +0 -9
- exonware/xwnode/queries/executors/ordering/by_executor.py +0 -50
- exonware/xwnode/queries/executors/ordering/order_executor.py +0 -51
- exonware/xwnode/queries/executors/projection/__init__.py +0 -9
- exonware/xwnode/queries/executors/projection/extend_executor.py +0 -50
- exonware/xwnode/queries/executors/projection/project_executor.py +0 -50
- exonware/xwnode/queries/executors/registry.py +0 -173
- exonware/xwnode/queries/parsers/__init__.py +0 -26
- exonware/xwnode/queries/parsers/base.py +0 -86
- exonware/xwnode/queries/parsers/contracts.py +0 -46
- exonware/xwnode/queries/parsers/errors.py +0 -53
- exonware/xwnode/queries/parsers/sql_param_extractor.py +0 -318
- exonware/xwnode/queries/strategies/__init__.py +0 -24
- exonware/xwnode/queries/strategies/base.py +0 -236
- exonware/xwnode/queries/strategies/cql.py +0 -201
- exonware/xwnode/queries/strategies/cypher.py +0 -181
- exonware/xwnode/queries/strategies/datalog.py +0 -70
- exonware/xwnode/queries/strategies/elastic_dsl.py +0 -70
- exonware/xwnode/queries/strategies/eql.py +0 -70
- exonware/xwnode/queries/strategies/flux.py +0 -70
- exonware/xwnode/queries/strategies/gql.py +0 -70
- exonware/xwnode/queries/strategies/graphql.py +0 -240
- exonware/xwnode/queries/strategies/gremlin.py +0 -181
- exonware/xwnode/queries/strategies/hiveql.py +0 -214
- exonware/xwnode/queries/strategies/hql.py +0 -70
- exonware/xwnode/queries/strategies/jmespath.py +0 -219
- exonware/xwnode/queries/strategies/jq.py +0 -66
- exonware/xwnode/queries/strategies/json_query.py +0 -66
- exonware/xwnode/queries/strategies/jsoniq.py +0 -248
- exonware/xwnode/queries/strategies/kql.py +0 -70
- exonware/xwnode/queries/strategies/linq.py +0 -238
- exonware/xwnode/queries/strategies/logql.py +0 -70
- exonware/xwnode/queries/strategies/mql.py +0 -68
- exonware/xwnode/queries/strategies/n1ql.py +0 -210
- exonware/xwnode/queries/strategies/partiql.py +0 -70
- exonware/xwnode/queries/strategies/pig.py +0 -215
- exonware/xwnode/queries/strategies/promql.py +0 -70
- exonware/xwnode/queries/strategies/sparql.py +0 -220
- exonware/xwnode/queries/strategies/sql.py +0 -275
- exonware/xwnode/queries/strategies/xml_query.py +0 -66
- exonware/xwnode/queries/strategies/xpath.py +0 -223
- exonware/xwnode/queries/strategies/xquery.py +0 -258
- exonware/xwnode/queries/strategies/xwnode_executor.py +0 -332
- exonware/xwnode/queries/strategies/xwquery.py +0 -456
- exonware_xwnode-0.0.1.22.dist-info/RECORD +0 -214
- /exonware/xwnode/nodes/strategies/{node_ordered_map.py → ordered_map.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_ordered_map_balanced.py → ordered_map_balanced.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_patricia.py → patricia.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_radix_trie.py → radix_trie.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_set_tree.py → set_tree.py} +0 -0
- {exonware_xwnode-0.0.1.22.dist-info → exonware_xwnode-0.0.1.23.dist-info}/WHEEL +0 -0
- {exonware_xwnode-0.0.1.22.dist-info → exonware_xwnode-0.0.1.23.dist-info}/licenses/LICENSE +0 -0
@@ -1,248 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
JSONiq Query Strategy
|
4
|
-
|
5
|
-
This module implements the JSONiq query strategy for JSON data queries.
|
6
|
-
|
7
|
-
Company: eXonware.com
|
8
|
-
Author: Eng. Muhammad AlShehri
|
9
|
-
Email: connect@exonware.com
|
10
|
-
Version: 0.0.1.22
|
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 JSONiqStrategy(ADocumentQueryStrategy):
|
22
|
-
"""
|
23
|
-
JSONiq query strategy for JSON data queries.
|
24
|
-
|
25
|
-
Supports:
|
26
|
-
- JSONiq 1.0 and 1.1 features
|
27
|
-
- FLWOR expressions
|
28
|
-
- JSON navigation
|
29
|
-
- Type system
|
30
|
-
- Functions and modules
|
31
|
-
"""
|
32
|
-
|
33
|
-
def __init__(self, **options):
|
34
|
-
super().__init__(**options)
|
35
|
-
self._mode = QueryMode.JSONIQ
|
36
|
-
self._traits = QueryTrait.DOCUMENT | QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL
|
37
|
-
|
38
|
-
def execute(self, query: str, **kwargs) -> Any:
|
39
|
-
"""Execute JSONiq query."""
|
40
|
-
if not self.validate_query(query):
|
41
|
-
raise XWNodeValueError(f"Invalid JSONiq 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 == "path":
|
48
|
-
return self._execute_path(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 JSONiq query syntax."""
|
56
|
-
if not query or not isinstance(query, str):
|
57
|
-
return False
|
58
|
-
|
59
|
-
# Basic JSONiq validation
|
60
|
-
query = query.strip()
|
61
|
-
|
62
|
-
# Check for JSONiq keywords
|
63
|
-
jsoniq_keywords = ["for", "let", "where", "order by", "group by", "return", "collection", "json", "object", "array"]
|
64
|
-
|
65
|
-
query_lower = query.lower()
|
66
|
-
for keyword in jsoniq_keywords:
|
67
|
-
if keyword in query_lower:
|
68
|
-
return True
|
69
|
-
|
70
|
-
# Check for JSON path expressions
|
71
|
-
if "$" 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 JSONiq 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
|
-
# JSONiq path queries
|
92
|
-
query = f"$${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 collection()
|
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 collection()
|
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 collection()
|
115
|
-
return {{ {field_list} }}
|
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 collection()
|
125
|
-
order by $$item.{sort_fields[0]} descending
|
126
|
-
return $$item
|
127
|
-
"""
|
128
|
-
else:
|
129
|
-
query = f"""
|
130
|
-
for $$item in collection()
|
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 in collection()
|
142
|
-
where count($$item) > {offset}
|
143
|
-
return $$item
|
144
|
-
"""
|
145
|
-
# Use subsequence for limit
|
146
|
-
return self._execute_function(f"subsequence(collection(), {offset + 1}, {limit})")
|
147
|
-
else:
|
148
|
-
query = f"""
|
149
|
-
for $$item in collection()
|
150
|
-
return $$item
|
151
|
-
"""
|
152
|
-
return self._execute_function(f"subsequence(collection(), 1, {limit})")
|
153
|
-
|
154
|
-
def _get_query_type(self, query: str) -> str:
|
155
|
-
"""Extract query type from JSONiq query."""
|
156
|
-
query = query.strip()
|
157
|
-
|
158
|
-
if "for" in query.lower() or "let" in query.lower():
|
159
|
-
return "flwor"
|
160
|
-
elif "$" in query or ".." in query:
|
161
|
-
return "path"
|
162
|
-
elif "(" in query and ")" in query:
|
163
|
-
return "function"
|
164
|
-
else:
|
165
|
-
return "unknown"
|
166
|
-
|
167
|
-
def _execute_flwor(self, query: str, **kwargs) -> Any:
|
168
|
-
"""Execute FLWOR expression."""
|
169
|
-
return {"result": "JSONiq FLWOR executed", "query": query}
|
170
|
-
|
171
|
-
def _execute_path(self, query: str, **kwargs) -> Any:
|
172
|
-
"""Execute path expression."""
|
173
|
-
return {"result": "JSONiq path executed", "query": query}
|
174
|
-
|
175
|
-
def _execute_function(self, query: str, **kwargs) -> Any:
|
176
|
-
"""Execute function call."""
|
177
|
-
return {"result": "JSONiq function executed", "query": query}
|
178
|
-
|
179
|
-
def _estimate_complexity(self, query: str) -> str:
|
180
|
-
"""Estimate query complexity."""
|
181
|
-
expressions = self._extract_expressions(query)
|
182
|
-
|
183
|
-
if len(expressions) > 5:
|
184
|
-
return "HIGH"
|
185
|
-
elif len(expressions) > 2:
|
186
|
-
return "MEDIUM"
|
187
|
-
else:
|
188
|
-
return "LOW"
|
189
|
-
|
190
|
-
def _estimate_cost(self, query: str) -> int:
|
191
|
-
"""Estimate query cost."""
|
192
|
-
complexity = self._estimate_complexity(query)
|
193
|
-
if complexity == "HIGH":
|
194
|
-
return 120
|
195
|
-
elif complexity == "MEDIUM":
|
196
|
-
return 60
|
197
|
-
else:
|
198
|
-
return 30
|
199
|
-
|
200
|
-
def _extract_expressions(self, query: str) -> List[str]:
|
201
|
-
"""Extract JSONiq expressions from query."""
|
202
|
-
expressions = []
|
203
|
-
|
204
|
-
# FLWOR expressions
|
205
|
-
if "for" in query.lower():
|
206
|
-
expressions.append("for")
|
207
|
-
if "let" in query.lower():
|
208
|
-
expressions.append("let")
|
209
|
-
if "where" in query.lower():
|
210
|
-
expressions.append("where")
|
211
|
-
if "order by" in query.lower():
|
212
|
-
expressions.append("order by")
|
213
|
-
if "group by" in query.lower():
|
214
|
-
expressions.append("group by")
|
215
|
-
if "return" in query.lower():
|
216
|
-
expressions.append("return")
|
217
|
-
|
218
|
-
# Path expressions
|
219
|
-
if "$" in query:
|
220
|
-
expressions.append("path")
|
221
|
-
if ".." in query:
|
222
|
-
expressions.append("descendant")
|
223
|
-
if "[]" in query:
|
224
|
-
expressions.append("array")
|
225
|
-
|
226
|
-
# Function calls
|
227
|
-
if "(" in query and ")" in query:
|
228
|
-
expressions.append("function")
|
229
|
-
|
230
|
-
return expressions
|
231
|
-
|
232
|
-
def _get_optimization_hints(self, query: str) -> List[str]:
|
233
|
-
"""Get query optimization hints."""
|
234
|
-
hints = []
|
235
|
-
|
236
|
-
if "for" in query.lower() and "let" in query.lower():
|
237
|
-
hints.append("Consider using let for computed values")
|
238
|
-
|
239
|
-
if ".." in query:
|
240
|
-
hints.append("Consider using specific paths instead of descendant navigation")
|
241
|
-
|
242
|
-
if "[]" in query:
|
243
|
-
hints.append("Consider using array indexing for better performance")
|
244
|
-
|
245
|
-
if "order by" in query.lower():
|
246
|
-
hints.append("Consider using indexes for ordered queries")
|
247
|
-
|
248
|
-
return hints
|
@@ -1,70 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
KQL Query Strategy
|
4
|
-
|
5
|
-
This module implements the KQL query strategy for Kusto Query Language operations.
|
6
|
-
|
7
|
-
Company: eXonware.com
|
8
|
-
Author: Eng. Muhammad AlShehri
|
9
|
-
Email: connect@exonware.com
|
10
|
-
Version: 0.0.1.22
|
11
|
-
Generation Date: January 2, 2025
|
12
|
-
"""
|
13
|
-
|
14
|
-
from typing import Any, Dict, List, Optional
|
15
|
-
from .base import AStructuredQueryStrategy
|
16
|
-
from ...errors import XWNodeValueError
|
17
|
-
from ...contracts import QueryMode, QueryTrait
|
18
|
-
|
19
|
-
|
20
|
-
class KQLStrategy(AStructuredQueryStrategy):
|
21
|
-
"""KQL query strategy for Kusto Query Language operations."""
|
22
|
-
|
23
|
-
def __init__(self, **options):
|
24
|
-
super().__init__(**options)
|
25
|
-
self._mode = QueryMode.KQL
|
26
|
-
self._traits = QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL | QueryTrait.BATCH
|
27
|
-
|
28
|
-
def execute(self, query: str, **kwargs) -> Any:
|
29
|
-
"""Execute KQL query."""
|
30
|
-
if not self.validate_query(query):
|
31
|
-
raise XWNodeValueError(f"Invalid KQL query: {query}")
|
32
|
-
return {"result": "KQL query executed", "query": query}
|
33
|
-
|
34
|
-
def validate_query(self, query: str) -> bool:
|
35
|
-
"""Validate KQL query syntax."""
|
36
|
-
if not query or not isinstance(query, str):
|
37
|
-
return False
|
38
|
-
return any(op in query.upper() for op in ["TABLE", "WHERE", "PROJECT", "SUMMARIZE", "JOIN"])
|
39
|
-
|
40
|
-
def get_query_plan(self, query: str) -> Dict[str, Any]:
|
41
|
-
"""Get KQL query execution plan."""
|
42
|
-
return {
|
43
|
-
"query_type": "KQL",
|
44
|
-
"complexity": "MEDIUM",
|
45
|
-
"estimated_cost": 90
|
46
|
-
}
|
47
|
-
|
48
|
-
def select_query(self, table: str, columns: List[str], where_clause: str = None) -> Any:
|
49
|
-
"""Execute SELECT query."""
|
50
|
-
return self.execute(f"{table} | project {', '.join(columns)}")
|
51
|
-
|
52
|
-
def insert_query(self, table: str, data: Dict[str, Any]) -> Any:
|
53
|
-
"""Execute INSERT query."""
|
54
|
-
return self.execute(f"INSERT INTO {table} VALUES {data}")
|
55
|
-
|
56
|
-
def update_query(self, table: str, data: Dict[str, Any], where_clause: str = None) -> Any:
|
57
|
-
"""Execute UPDATE query."""
|
58
|
-
return self.execute(f"UPDATE {table} SET {data}")
|
59
|
-
|
60
|
-
def delete_query(self, table: str, where_clause: str = None) -> Any:
|
61
|
-
"""Execute DELETE query."""
|
62
|
-
return self.execute(f"DELETE FROM {table}")
|
63
|
-
|
64
|
-
def join_query(self, tables: List[str], join_conditions: List[str]) -> Any:
|
65
|
-
"""Execute JOIN query."""
|
66
|
-
return self.execute(f"{tables[0]} | join {tables[1]}")
|
67
|
-
|
68
|
-
def aggregate_query(self, table: str, functions: List[str], group_by: List[str] = None) -> Any:
|
69
|
-
"""Execute aggregate query."""
|
70
|
-
return self.execute(f"{table} | summarize {', '.join(functions)}")
|
@@ -1,238 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
LINQ Query Strategy
|
4
|
-
|
5
|
-
This module implements the LINQ query strategy for Language Integrated Query operations.
|
6
|
-
|
7
|
-
Company: eXonware.com
|
8
|
-
Author: Eng. Muhammad AlShehri
|
9
|
-
Email: connect@exonware.com
|
10
|
-
Version: 0.0.1.22
|
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 LINQStrategy(ADocumentQueryStrategy):
|
22
|
-
"""
|
23
|
-
LINQ query strategy for Language Integrated Query operations.
|
24
|
-
|
25
|
-
Supports:
|
26
|
-
- Query syntax and method syntax
|
27
|
-
- LINQ to Objects, LINQ to XML, LINQ to SQL
|
28
|
-
- Lambda expressions
|
29
|
-
- Deferred execution
|
30
|
-
- Query composition
|
31
|
-
"""
|
32
|
-
|
33
|
-
def __init__(self, **options):
|
34
|
-
super().__init__(**options)
|
35
|
-
self._mode = QueryMode.LINQ
|
36
|
-
self._traits = QueryTrait.DOCUMENT | QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL
|
37
|
-
|
38
|
-
def execute(self, query: str, **kwargs) -> Any:
|
39
|
-
"""Execute LINQ query."""
|
40
|
-
if not self.validate_query(query):
|
41
|
-
raise XWNodeValueError(f"Invalid LINQ query: {query}")
|
42
|
-
|
43
|
-
query_type = self._get_query_type(query)
|
44
|
-
|
45
|
-
if query_type == "query_syntax":
|
46
|
-
return self._execute_query_syntax(query, **kwargs)
|
47
|
-
elif query_type == "method_syntax":
|
48
|
-
return self._execute_method_syntax(query, **kwargs)
|
49
|
-
else:
|
50
|
-
raise XWNodeValueError(f"Unsupported query type: {query_type}")
|
51
|
-
|
52
|
-
def validate_query(self, query: str) -> bool:
|
53
|
-
"""Validate LINQ query syntax."""
|
54
|
-
if not query or not isinstance(query, str):
|
55
|
-
return False
|
56
|
-
|
57
|
-
# Basic LINQ validation
|
58
|
-
query = query.strip()
|
59
|
-
|
60
|
-
# Check for LINQ keywords
|
61
|
-
linq_keywords = ["from", "where", "select", "group", "orderby", "join", "let", "into"]
|
62
|
-
method_keywords = ["Where", "Select", "GroupBy", "OrderBy", "Join", "Take", "Skip", "First", "Last"]
|
63
|
-
|
64
|
-
query_lower = query.lower()
|
65
|
-
for keyword in linq_keywords:
|
66
|
-
if keyword in query_lower:
|
67
|
-
return True
|
68
|
-
|
69
|
-
for keyword in method_keywords:
|
70
|
-
if keyword in query:
|
71
|
-
return True
|
72
|
-
|
73
|
-
return False
|
74
|
-
|
75
|
-
def get_query_plan(self, query: str) -> Dict[str, Any]:
|
76
|
-
"""Get LINQ query execution plan."""
|
77
|
-
query_type = self._get_query_type(query)
|
78
|
-
|
79
|
-
return {
|
80
|
-
"query_type": query_type,
|
81
|
-
"operation": query_type,
|
82
|
-
"complexity": self._estimate_complexity(query),
|
83
|
-
"estimated_cost": self._estimate_cost(query),
|
84
|
-
"operations": self._extract_operations(query),
|
85
|
-
"optimization_hints": self._get_optimization_hints(query)
|
86
|
-
}
|
87
|
-
|
88
|
-
def path_query(self, path: str) -> Any:
|
89
|
-
"""Execute path-based query."""
|
90
|
-
# LINQ path queries are typically for XML
|
91
|
-
query = f"""
|
92
|
-
from element in document.Descendants()
|
93
|
-
where element.Name == "{path}"
|
94
|
-
select element
|
95
|
-
"""
|
96
|
-
return self.execute(query)
|
97
|
-
|
98
|
-
def filter_query(self, filter_expression: str) -> Any:
|
99
|
-
"""Execute filter query."""
|
100
|
-
query = f"""
|
101
|
-
from item in source
|
102
|
-
where {filter_expression}
|
103
|
-
select item
|
104
|
-
"""
|
105
|
-
return self.execute(query)
|
106
|
-
|
107
|
-
def projection_query(self, fields: List[str]) -> Any:
|
108
|
-
"""Execute projection query."""
|
109
|
-
if len(fields) == 1:
|
110
|
-
query = f"""
|
111
|
-
from item in source
|
112
|
-
select item.{fields[0]}
|
113
|
-
"""
|
114
|
-
else:
|
115
|
-
field_list = ", ".join([f"item.{field}" for field in fields])
|
116
|
-
query = f"""
|
117
|
-
from item in source
|
118
|
-
select new {{ {field_list} }}
|
119
|
-
"""
|
120
|
-
|
121
|
-
return self.execute(query)
|
122
|
-
|
123
|
-
def sort_query(self, sort_fields: List[str], order: str = "asc") -> Any:
|
124
|
-
"""Execute sort query."""
|
125
|
-
if order.lower() == "desc":
|
126
|
-
query = f"""
|
127
|
-
from item in source
|
128
|
-
orderby {sort_fields[0]} descending
|
129
|
-
select item
|
130
|
-
"""
|
131
|
-
else:
|
132
|
-
query = f"""
|
133
|
-
from item in source
|
134
|
-
orderby {sort_fields[0]}
|
135
|
-
select item
|
136
|
-
"""
|
137
|
-
|
138
|
-
return self.execute(query)
|
139
|
-
|
140
|
-
def limit_query(self, limit: int, offset: int = 0) -> Any:
|
141
|
-
"""Execute limit query."""
|
142
|
-
if offset > 0:
|
143
|
-
query = f"""
|
144
|
-
from item in source
|
145
|
-
select item
|
146
|
-
"""
|
147
|
-
# Use Skip and Take methods
|
148
|
-
return self._execute_method_syntax(f"source.Skip({offset}).Take({limit})")
|
149
|
-
else:
|
150
|
-
query = f"""
|
151
|
-
from item in source
|
152
|
-
select item
|
153
|
-
"""
|
154
|
-
return self._execute_method_syntax(f"source.Take({limit})")
|
155
|
-
|
156
|
-
def _get_query_type(self, query: str) -> str:
|
157
|
-
"""Extract query type from LINQ query."""
|
158
|
-
query = query.strip()
|
159
|
-
|
160
|
-
if query.startswith("from ") or " from " in query:
|
161
|
-
return "query_syntax"
|
162
|
-
elif any(method in query for method in ["Where", "Select", "GroupBy", "OrderBy", "Join"]):
|
163
|
-
return "method_syntax"
|
164
|
-
else:
|
165
|
-
return "unknown"
|
166
|
-
|
167
|
-
def _execute_query_syntax(self, query: str, **kwargs) -> Any:
|
168
|
-
"""Execute LINQ query syntax."""
|
169
|
-
return {"result": "LINQ query syntax executed", "query": query}
|
170
|
-
|
171
|
-
def _execute_method_syntax(self, query: str, **kwargs) -> Any:
|
172
|
-
"""Execute LINQ method syntax."""
|
173
|
-
return {"result": "LINQ method syntax executed", "query": query}
|
174
|
-
|
175
|
-
def _estimate_complexity(self, query: str) -> str:
|
176
|
-
"""Estimate query complexity."""
|
177
|
-
operations = self._extract_operations(query)
|
178
|
-
|
179
|
-
if len(operations) > 5:
|
180
|
-
return "HIGH"
|
181
|
-
elif len(operations) > 2:
|
182
|
-
return "MEDIUM"
|
183
|
-
else:
|
184
|
-
return "LOW"
|
185
|
-
|
186
|
-
def _estimate_cost(self, query: str) -> int:
|
187
|
-
"""Estimate query cost."""
|
188
|
-
complexity = self._estimate_complexity(query)
|
189
|
-
if complexity == "HIGH":
|
190
|
-
return 100
|
191
|
-
elif complexity == "MEDIUM":
|
192
|
-
return 50
|
193
|
-
else:
|
194
|
-
return 25
|
195
|
-
|
196
|
-
def _extract_operations(self, query: str) -> List[str]:
|
197
|
-
"""Extract LINQ operations from query."""
|
198
|
-
operations = []
|
199
|
-
|
200
|
-
# Query syntax operations
|
201
|
-
if "from" in query.lower():
|
202
|
-
operations.append("from")
|
203
|
-
if "where" in query.lower():
|
204
|
-
operations.append("where")
|
205
|
-
if "select" in query.lower():
|
206
|
-
operations.append("select")
|
207
|
-
if "group" in query.lower():
|
208
|
-
operations.append("group")
|
209
|
-
if "orderby" in query.lower():
|
210
|
-
operations.append("orderby")
|
211
|
-
if "join" in query.lower():
|
212
|
-
operations.append("join")
|
213
|
-
|
214
|
-
# Method syntax operations
|
215
|
-
method_operations = ["Where", "Select", "GroupBy", "OrderBy", "Join", "Take", "Skip", "First", "Last", "Count", "Sum", "Average", "Min", "Max"]
|
216
|
-
for operation in method_operations:
|
217
|
-
if operation in query:
|
218
|
-
operations.append(operation)
|
219
|
-
|
220
|
-
return operations
|
221
|
-
|
222
|
-
def _get_optimization_hints(self, query: str) -> List[str]:
|
223
|
-
"""Get query optimization hints."""
|
224
|
-
hints = []
|
225
|
-
|
226
|
-
if "Count()" in query:
|
227
|
-
hints.append("Consider using Count() with predicate for better performance")
|
228
|
-
|
229
|
-
if "First()" in query:
|
230
|
-
hints.append("Consider using FirstOrDefault() to avoid exceptions")
|
231
|
-
|
232
|
-
if "ToList()" in query:
|
233
|
-
hints.append("Consider using deferred execution when possible")
|
234
|
-
|
235
|
-
if "Select" in query and "Where" in query:
|
236
|
-
hints.append("Consider combining Select and Where operations")
|
237
|
-
|
238
|
-
return hints
|
@@ -1,70 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
LogQL Query Strategy
|
4
|
-
|
5
|
-
This module implements the LogQL query strategy for Grafana Loki Log Query Language operations.
|
6
|
-
|
7
|
-
Company: eXonware.com
|
8
|
-
Author: Eng. Muhammad AlShehri
|
9
|
-
Email: connect@exonware.com
|
10
|
-
Version: 0.0.1.22
|
11
|
-
Generation Date: January 2, 2025
|
12
|
-
"""
|
13
|
-
|
14
|
-
from typing import Any, Dict, List, Optional
|
15
|
-
from .base import AStructuredQueryStrategy
|
16
|
-
from ...errors import XWNodeValueError
|
17
|
-
from ...contracts import QueryMode, QueryTrait
|
18
|
-
|
19
|
-
|
20
|
-
class LogQLStrategy(AStructuredQueryStrategy):
|
21
|
-
"""LogQL query strategy for Grafana Loki Log Query Language operations."""
|
22
|
-
|
23
|
-
def __init__(self, **options):
|
24
|
-
super().__init__(**options)
|
25
|
-
self._mode = QueryMode.LOGQL
|
26
|
-
self._traits = QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL | QueryTrait.TEMPORAL | QueryTrait.STREAMING
|
27
|
-
|
28
|
-
def execute(self, query: str, **kwargs) -> Any:
|
29
|
-
"""Execute LogQL query."""
|
30
|
-
if not self.validate_query(query):
|
31
|
-
raise XWNodeValueError(f"Invalid LogQL query: {query}")
|
32
|
-
return {"result": "LogQL query executed", "query": query}
|
33
|
-
|
34
|
-
def validate_query(self, query: str) -> bool:
|
35
|
-
"""Validate LogQL query syntax."""
|
36
|
-
if not query or not isinstance(query, str):
|
37
|
-
return False
|
38
|
-
return any(op in query for op in ["{", "}", "|", "rate", "sum", "count", "avg", "max", "min"])
|
39
|
-
|
40
|
-
def get_query_plan(self, query: str) -> Dict[str, Any]:
|
41
|
-
"""Get LogQL query execution plan."""
|
42
|
-
return {
|
43
|
-
"query_type": "LogQL",
|
44
|
-
"complexity": "MEDIUM",
|
45
|
-
"estimated_cost": 90
|
46
|
-
}
|
47
|
-
|
48
|
-
def select_query(self, table: str, columns: List[str], where_clause: str = None) -> Any:
|
49
|
-
"""Execute SELECT query."""
|
50
|
-
return self.execute(f"{{job=\"{table}\"}}")
|
51
|
-
|
52
|
-
def insert_query(self, table: str, data: Dict[str, Any]) -> Any:
|
53
|
-
"""Execute INSERT query."""
|
54
|
-
return self.execute(f"INSERT INTO {table} VALUES {data}")
|
55
|
-
|
56
|
-
def update_query(self, table: str, data: Dict[str, Any], where_clause: str = None) -> Any:
|
57
|
-
"""Execute UPDATE query."""
|
58
|
-
return self.execute(f"UPDATE {table} SET {data}")
|
59
|
-
|
60
|
-
def delete_query(self, table: str, where_clause: str = None) -> Any:
|
61
|
-
"""Execute DELETE query."""
|
62
|
-
return self.execute(f"DELETE FROM {table}")
|
63
|
-
|
64
|
-
def join_query(self, tables: List[str], join_conditions: List[str]) -> Any:
|
65
|
-
"""Execute JOIN query."""
|
66
|
-
return self.execute(f"{{job=\"{tables[0]}\"}} | join {{job=\"{tables[1]}\"}}")
|
67
|
-
|
68
|
-
def aggregate_query(self, table: str, functions: List[str], group_by: List[str] = None) -> Any:
|
69
|
-
"""Execute aggregate query."""
|
70
|
-
return self.execute(f"{{job=\"{table}\"}} | {functions[0]}()")
|
@@ -1,68 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
MQL Query Strategy
|
4
|
-
|
5
|
-
This module implements the MQL query strategy for MongoDB Query Language operations.
|
6
|
-
|
7
|
-
Company: eXonware.com
|
8
|
-
Author: Eng. Muhammad AlShehri
|
9
|
-
Email: connect@exonware.com
|
10
|
-
Version: 0.0.1.22
|
11
|
-
Generation Date: January 2, 2025
|
12
|
-
"""
|
13
|
-
|
14
|
-
from typing import Any, Dict, List, Optional
|
15
|
-
from .base import ADocumentQueryStrategy
|
16
|
-
from ...errors import XWNodeValueError
|
17
|
-
from ...contracts import QueryMode, QueryTrait
|
18
|
-
|
19
|
-
|
20
|
-
class MQLStrategy(ADocumentQueryStrategy):
|
21
|
-
"""MQL query strategy for MongoDB Query Language operations."""
|
22
|
-
|
23
|
-
def __init__(self, **options):
|
24
|
-
super().__init__(**options)
|
25
|
-
self._mode = QueryMode.MQL
|
26
|
-
self._traits = QueryTrait.DOCUMENT | QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL
|
27
|
-
|
28
|
-
def execute(self, query: str, **kwargs) -> Any:
|
29
|
-
"""Execute MQL query."""
|
30
|
-
if not self.validate_query(query):
|
31
|
-
raise XWNodeValueError(f"Invalid MQL query: {query}")
|
32
|
-
return {"result": "MQL query executed", "query": query}
|
33
|
-
|
34
|
-
def validate_query(self, query: str) -> bool:
|
35
|
-
"""Validate MQL query syntax."""
|
36
|
-
if not query or not isinstance(query, str):
|
37
|
-
return False
|
38
|
-
return any(op in query for op in ["find", "aggregate", "insert", "update", "delete", "createIndex"])
|
39
|
-
|
40
|
-
def get_query_plan(self, query: str) -> Dict[str, Any]:
|
41
|
-
"""Get MQL query execution plan."""
|
42
|
-
return {
|
43
|
-
"query_type": "MQL",
|
44
|
-
"complexity": "MEDIUM",
|
45
|
-
"estimated_cost": 80
|
46
|
-
}
|
47
|
-
|
48
|
-
def path_query(self, path: str) -> Any:
|
49
|
-
"""Execute path-based query."""
|
50
|
-
return self.execute(f"db.collection.find({{{path}: {{$exists: true}}}})")
|
51
|
-
|
52
|
-
def filter_query(self, filter_expression: str) -> Any:
|
53
|
-
"""Execute filter query."""
|
54
|
-
return self.execute(f"db.collection.find({filter_expression})")
|
55
|
-
|
56
|
-
def projection_query(self, fields: List[str]) -> Any:
|
57
|
-
"""Execute projection query."""
|
58
|
-
projection = {field: 1 for field in fields}
|
59
|
-
return self.execute(f"db.collection.find({{}}, {projection})")
|
60
|
-
|
61
|
-
def sort_query(self, sort_fields: List[str], order: str = "asc") -> Any:
|
62
|
-
"""Execute sort query."""
|
63
|
-
sort_order = 1 if order == "asc" else -1
|
64
|
-
return self.execute(f"db.collection.find().sort({{{sort_fields[0]}: {sort_order}}})")
|
65
|
-
|
66
|
-
def limit_query(self, limit: int, offset: int = 0) -> Any:
|
67
|
-
"""Execute limit query."""
|
68
|
-
return self.execute(f"db.collection.find().skip({offset}).limit({limit})")
|