exonware-xwnode 0.0.1.22__py3-none-any.whl → 0.0.1.24__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.24.dist-info/METADATA +900 -0
- exonware_xwnode-0.0.1.24.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/METADATA +0 -168
- 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.24.dist-info}/WHEEL +0 -0
- {exonware_xwnode-0.0.1.22.dist-info → exonware_xwnode-0.0.1.24.dist-info}/licenses/LICENSE +0 -0
@@ -1,220 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
SPARQL Query Strategy
|
4
|
-
|
5
|
-
This module implements the SPARQL query strategy for RDF 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 AGraphQueryStrategy
|
17
|
-
from ...errors import XWNodeTypeError, XWNodeValueError
|
18
|
-
from ...contracts import QueryMode, QueryTrait
|
19
|
-
|
20
|
-
|
21
|
-
class SPARQLStrategy(AGraphQueryStrategy):
|
22
|
-
"""
|
23
|
-
SPARQL query strategy for RDF data queries.
|
24
|
-
|
25
|
-
Supports:
|
26
|
-
- SELECT, CONSTRUCT, ASK, DESCRIBE queries
|
27
|
-
- SPARQL 1.1 features
|
28
|
-
- Property paths
|
29
|
-
- Federated queries
|
30
|
-
- Update operations
|
31
|
-
"""
|
32
|
-
|
33
|
-
def __init__(self, **options):
|
34
|
-
super().__init__(**options)
|
35
|
-
self._mode = QueryMode.SPARQL
|
36
|
-
self._traits = QueryTrait.GRAPH | QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL
|
37
|
-
|
38
|
-
def execute(self, query: str, **kwargs) -> Any:
|
39
|
-
"""Execute SPARQL query."""
|
40
|
-
if not self.validate_query(query):
|
41
|
-
raise XWNodeValueError(f"Invalid SPARQL query: {query}")
|
42
|
-
|
43
|
-
query_type = self._get_query_type(query)
|
44
|
-
|
45
|
-
if query_type == "SELECT":
|
46
|
-
return self._execute_select(query, **kwargs)
|
47
|
-
elif query_type == "CONSTRUCT":
|
48
|
-
return self._execute_construct(query, **kwargs)
|
49
|
-
elif query_type == "ASK":
|
50
|
-
return self._execute_ask(query, **kwargs)
|
51
|
-
elif query_type == "DESCRIBE":
|
52
|
-
return self._execute_describe(query, **kwargs)
|
53
|
-
else:
|
54
|
-
raise XWNodeValueError(f"Unsupported query type: {query_type}")
|
55
|
-
|
56
|
-
def validate_query(self, query: str) -> bool:
|
57
|
-
"""Validate SPARQL query syntax."""
|
58
|
-
if not query or not isinstance(query, str):
|
59
|
-
return False
|
60
|
-
|
61
|
-
# Basic SPARQL validation
|
62
|
-
query = query.strip().upper()
|
63
|
-
valid_operations = ["SELECT", "CONSTRUCT", "ASK", "DESCRIBE", "INSERT", "DELETE", "LOAD", "CLEAR"]
|
64
|
-
|
65
|
-
for operation in valid_operations:
|
66
|
-
if query.startswith(operation):
|
67
|
-
return True
|
68
|
-
|
69
|
-
return False
|
70
|
-
|
71
|
-
def get_query_plan(self, query: str) -> Dict[str, Any]:
|
72
|
-
"""Get SPARQL query execution plan."""
|
73
|
-
query_type = self._get_query_type(query)
|
74
|
-
|
75
|
-
return {
|
76
|
-
"query_type": query_type,
|
77
|
-
"operation": query_type,
|
78
|
-
"complexity": self._estimate_complexity(query),
|
79
|
-
"estimated_cost": self._estimate_cost(query),
|
80
|
-
"triple_patterns": self._count_triple_patterns(query),
|
81
|
-
"optimization_hints": self._get_optimization_hints(query)
|
82
|
-
}
|
83
|
-
|
84
|
-
def path_query(self, start: Any, end: Any) -> List[Any]:
|
85
|
-
"""Execute path query using SPARQL property paths."""
|
86
|
-
query = f"""
|
87
|
-
SELECT ?path ?length
|
88
|
-
WHERE {{
|
89
|
-
<{start}> (<>|!<>)* ?path .
|
90
|
-
?path (<>|!<>)* <{end}> .
|
91
|
-
BIND(LENGTH(?path) AS ?length)
|
92
|
-
}}
|
93
|
-
"""
|
94
|
-
return self.execute(query)
|
95
|
-
|
96
|
-
def neighbor_query(self, node: Any) -> List[Any]:
|
97
|
-
"""Execute neighbor query."""
|
98
|
-
query = f"""
|
99
|
-
SELECT ?neighbor ?predicate
|
100
|
-
WHERE {{
|
101
|
-
<{node}> ?predicate ?neighbor .
|
102
|
-
}}
|
103
|
-
"""
|
104
|
-
return self.execute(query)
|
105
|
-
|
106
|
-
def shortest_path_query(self, start: Any, end: Any) -> List[Any]:
|
107
|
-
"""Execute shortest path query."""
|
108
|
-
query = f"""
|
109
|
-
SELECT ?path (COUNT(?step) AS ?length)
|
110
|
-
WHERE {{
|
111
|
-
<{start}> (<>|!<>)* ?path .
|
112
|
-
?path (<>|!<>)* <{end}> .
|
113
|
-
}}
|
114
|
-
GROUP BY ?path
|
115
|
-
ORDER BY ?length
|
116
|
-
LIMIT 1
|
117
|
-
"""
|
118
|
-
return self.execute(query)
|
119
|
-
|
120
|
-
def connected_components_query(self) -> List[List[Any]]:
|
121
|
-
"""Execute connected components query."""
|
122
|
-
query = """
|
123
|
-
SELECT ?component (COUNT(?node) AS ?size)
|
124
|
-
WHERE {
|
125
|
-
?node ?p ?o .
|
126
|
-
?o ?p2 ?node .
|
127
|
-
}
|
128
|
-
GROUP BY ?component
|
129
|
-
"""
|
130
|
-
return self.execute(query)
|
131
|
-
|
132
|
-
def cycle_detection_query(self) -> List[List[Any]]:
|
133
|
-
"""Execute cycle detection query."""
|
134
|
-
query = """
|
135
|
-
SELECT ?cycle
|
136
|
-
WHERE {
|
137
|
-
?node ?p ?node .
|
138
|
-
BIND(?node AS ?cycle)
|
139
|
-
}
|
140
|
-
"""
|
141
|
-
return self.execute(query)
|
142
|
-
|
143
|
-
def _get_query_type(self, query: str) -> str:
|
144
|
-
"""Extract query type from SPARQL query."""
|
145
|
-
query = query.strip().upper()
|
146
|
-
for operation in ["SELECT", "CONSTRUCT", "ASK", "DESCRIBE", "INSERT", "DELETE", "LOAD", "CLEAR"]:
|
147
|
-
if query.startswith(operation):
|
148
|
-
return operation
|
149
|
-
return "UNKNOWN"
|
150
|
-
|
151
|
-
def _execute_select(self, query: str, **kwargs) -> Any:
|
152
|
-
"""Execute SELECT query."""
|
153
|
-
return {"result": "SPARQL SELECT executed", "query": query}
|
154
|
-
|
155
|
-
def _execute_construct(self, query: str, **kwargs) -> Any:
|
156
|
-
"""Execute CONSTRUCT query."""
|
157
|
-
return {"result": "SPARQL CONSTRUCT executed", "query": query}
|
158
|
-
|
159
|
-
def _execute_ask(self, query: str, **kwargs) -> Any:
|
160
|
-
"""Execute ASK query."""
|
161
|
-
return {"result": "SPARQL ASK executed", "query": query}
|
162
|
-
|
163
|
-
def _execute_describe(self, query: str, **kwargs) -> Any:
|
164
|
-
"""Execute DESCRIBE query."""
|
165
|
-
return {"result": "SPARQL DESCRIBE executed", "query": query}
|
166
|
-
|
167
|
-
def _estimate_complexity(self, query: str) -> str:
|
168
|
-
"""Estimate query complexity."""
|
169
|
-
triple_count = self._count_triple_patterns(query)
|
170
|
-
|
171
|
-
if triple_count > 10:
|
172
|
-
return "HIGH"
|
173
|
-
elif triple_count > 5:
|
174
|
-
return "MEDIUM"
|
175
|
-
else:
|
176
|
-
return "LOW"
|
177
|
-
|
178
|
-
def _estimate_cost(self, query: str) -> int:
|
179
|
-
"""Estimate query cost."""
|
180
|
-
complexity = self._estimate_complexity(query)
|
181
|
-
if complexity == "HIGH":
|
182
|
-
return 200
|
183
|
-
elif complexity == "MEDIUM":
|
184
|
-
return 100
|
185
|
-
else:
|
186
|
-
return 50
|
187
|
-
|
188
|
-
def _count_triple_patterns(self, query: str) -> int:
|
189
|
-
"""Count triple patterns in SPARQL query."""
|
190
|
-
# Count occurrences of triple patterns
|
191
|
-
pattern_count = 0
|
192
|
-
|
193
|
-
# Look for triple patterns in WHERE clause
|
194
|
-
where_match = re.search(r'WHERE\s*\{([^}]+)\}', query, re.IGNORECASE | re.DOTALL)
|
195
|
-
if where_match:
|
196
|
-
where_clause = where_match.group(1)
|
197
|
-
# Count lines that look like triple patterns
|
198
|
-
lines = where_clause.split('\n')
|
199
|
-
for line in lines:
|
200
|
-
line = line.strip()
|
201
|
-
if line and not line.startswith('#') and not line.startswith('FILTER'):
|
202
|
-
if '?' in line or '<' in line or '"' in line:
|
203
|
-
pattern_count += 1
|
204
|
-
|
205
|
-
return pattern_count
|
206
|
-
|
207
|
-
def _get_optimization_hints(self, query: str) -> List[str]:
|
208
|
-
"""Get query optimization hints."""
|
209
|
-
hints = []
|
210
|
-
|
211
|
-
if self._count_triple_patterns(query) > 8:
|
212
|
-
hints.append("Consider breaking down complex queries into smaller ones")
|
213
|
-
|
214
|
-
if "OPTIONAL" in query.upper():
|
215
|
-
hints.append("Consider using FILTER instead of OPTIONAL for better performance")
|
216
|
-
|
217
|
-
if "UNION" in query.upper():
|
218
|
-
hints.append("Consider using property paths instead of UNION when possible")
|
219
|
-
|
220
|
-
return hints
|
@@ -1,275 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
SQL Query Strategy
|
4
|
-
|
5
|
-
This module implements the SQL query strategy for structured 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 AStructuredQueryStrategy
|
17
|
-
from ...errors import XWNodeTypeError, XWNodeValueError
|
18
|
-
from ...contracts import QueryMode, QueryTrait
|
19
|
-
from ...base import XWNodeBase
|
20
|
-
|
21
|
-
|
22
|
-
class SQLStrategy(AStructuredQueryStrategy):
|
23
|
-
"""
|
24
|
-
SQL query strategy for standard SQL operations.
|
25
|
-
|
26
|
-
Supports:
|
27
|
-
- SELECT, INSERT, UPDATE, DELETE operations
|
28
|
-
- JOIN operations
|
29
|
-
- Aggregate functions
|
30
|
-
- WHERE clauses
|
31
|
-
- ORDER BY, GROUP BY, HAVING
|
32
|
-
"""
|
33
|
-
|
34
|
-
def __init__(self, **options):
|
35
|
-
super().__init__(**options)
|
36
|
-
self._mode = QueryMode.SQL
|
37
|
-
self._traits = QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL | QueryTrait.BATCH
|
38
|
-
|
39
|
-
def execute(self, query: str, **kwargs) -> Any:
|
40
|
-
"""Execute SQL query."""
|
41
|
-
if not self.validate_query(query):
|
42
|
-
raise XWNodeValueError(f"Invalid SQL query: {query}")
|
43
|
-
|
44
|
-
query_type = self._get_query_type(query)
|
45
|
-
|
46
|
-
if query_type == "SELECT":
|
47
|
-
return self._execute_select(query, **kwargs)
|
48
|
-
elif query_type == "INSERT":
|
49
|
-
return self._execute_insert(query, **kwargs)
|
50
|
-
elif query_type == "UPDATE":
|
51
|
-
return self._execute_update(query, **kwargs)
|
52
|
-
elif query_type == "DELETE":
|
53
|
-
return self._execute_delete(query, **kwargs)
|
54
|
-
else:
|
55
|
-
raise XWNodeValueError(f"Unsupported query type: {query_type}")
|
56
|
-
|
57
|
-
def validate_query(self, query: str) -> bool:
|
58
|
-
"""Validate SQL query syntax."""
|
59
|
-
if not query or not isinstance(query, str):
|
60
|
-
return False
|
61
|
-
|
62
|
-
# Basic SQL validation
|
63
|
-
query = query.strip().upper()
|
64
|
-
valid_operations = ["SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "ALTER"]
|
65
|
-
|
66
|
-
for operation in valid_operations:
|
67
|
-
if query.startswith(operation):
|
68
|
-
return True
|
69
|
-
|
70
|
-
return False
|
71
|
-
|
72
|
-
def get_query_plan(self, query: str) -> Dict[str, Any]:
|
73
|
-
"""Get SQL query execution plan."""
|
74
|
-
query_type = self._get_query_type(query)
|
75
|
-
|
76
|
-
return {
|
77
|
-
"query_type": query_type,
|
78
|
-
"operation": query_type,
|
79
|
-
"complexity": self._estimate_complexity(query),
|
80
|
-
"estimated_cost": self._estimate_cost(query),
|
81
|
-
"optimization_hints": self._get_optimization_hints(query)
|
82
|
-
}
|
83
|
-
|
84
|
-
def select_query(self, table: str, columns: List[str], where_clause: str = None) -> Any:
|
85
|
-
"""Execute SELECT query."""
|
86
|
-
query = f"SELECT {', '.join(columns)} FROM {table}"
|
87
|
-
if where_clause:
|
88
|
-
query += f" WHERE {where_clause}"
|
89
|
-
|
90
|
-
return self.execute(query)
|
91
|
-
|
92
|
-
def insert_query(self, table: str, data: Dict[str, Any]) -> Any:
|
93
|
-
"""Execute INSERT query."""
|
94
|
-
columns = list(data.keys())
|
95
|
-
values = list(data.values())
|
96
|
-
|
97
|
-
query = f"INSERT INTO {table} ({', '.join(columns)}) VALUES ({', '.join(['?' for _ in values])})"
|
98
|
-
return self.execute(query, values=values)
|
99
|
-
|
100
|
-
def update_query(self, table: str, data: Dict[str, Any], where_clause: str = None) -> Any:
|
101
|
-
"""Execute UPDATE query."""
|
102
|
-
set_clause = ', '.join([f"{k} = ?" for k in data.keys()])
|
103
|
-
query = f"UPDATE {table} SET {set_clause}"
|
104
|
-
|
105
|
-
if where_clause:
|
106
|
-
query += f" WHERE {where_clause}"
|
107
|
-
|
108
|
-
return self.execute(query, values=list(data.values()))
|
109
|
-
|
110
|
-
def delete_query(self, table: str, where_clause: str = None) -> Any:
|
111
|
-
"""Execute DELETE query."""
|
112
|
-
query = f"DELETE FROM {table}"
|
113
|
-
if where_clause:
|
114
|
-
query += f" WHERE {where_clause}"
|
115
|
-
|
116
|
-
return self.execute(query)
|
117
|
-
|
118
|
-
def join_query(self, tables: List[str], join_conditions: List[str]) -> Any:
|
119
|
-
"""Execute JOIN query."""
|
120
|
-
if len(tables) < 2:
|
121
|
-
raise XWNodeValueError("JOIN requires at least 2 tables")
|
122
|
-
|
123
|
-
query = f"SELECT * FROM {tables[0]}"
|
124
|
-
for i, table in enumerate(tables[1:], 1):
|
125
|
-
if i <= len(join_conditions):
|
126
|
-
query += f" JOIN {table} ON {join_conditions[i-1]}"
|
127
|
-
else:
|
128
|
-
query += f" CROSS JOIN {table}"
|
129
|
-
|
130
|
-
return self.execute(query)
|
131
|
-
|
132
|
-
def aggregate_query(self, table: str, functions: List[str], group_by: List[str] = None) -> Any:
|
133
|
-
"""Execute aggregate query."""
|
134
|
-
query = f"SELECT {', '.join(functions)} FROM {table}"
|
135
|
-
if group_by:
|
136
|
-
query += f" GROUP BY {', '.join(group_by)}"
|
137
|
-
|
138
|
-
return self.execute(query)
|
139
|
-
|
140
|
-
def _get_query_type(self, query: str) -> str:
|
141
|
-
"""Extract query type from SQL query."""
|
142
|
-
query = query.strip().upper()
|
143
|
-
for operation in ["SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "ALTER"]:
|
144
|
-
if query.startswith(operation):
|
145
|
-
return operation
|
146
|
-
return "UNKNOWN"
|
147
|
-
|
148
|
-
def _execute_select(self, query: str, **kwargs) -> Any:
|
149
|
-
"""Execute SELECT query."""
|
150
|
-
# Placeholder implementation
|
151
|
-
return {"result": "SELECT executed", "query": query}
|
152
|
-
|
153
|
-
def _execute_insert(self, query: str, **kwargs) -> Any:
|
154
|
-
"""Execute INSERT query."""
|
155
|
-
# Placeholder implementation
|
156
|
-
return {"result": "INSERT executed", "query": query}
|
157
|
-
|
158
|
-
def _execute_update(self, query: str, **kwargs) -> Any:
|
159
|
-
"""Execute UPDATE query."""
|
160
|
-
# Placeholder implementation
|
161
|
-
return {"result": "UPDATE executed", "query": query}
|
162
|
-
|
163
|
-
def _execute_delete(self, query: str, **kwargs) -> Any:
|
164
|
-
"""Execute DELETE query."""
|
165
|
-
# Placeholder implementation
|
166
|
-
return {"result": "DELETE executed", "query": query}
|
167
|
-
|
168
|
-
def _estimate_complexity(self, query: str) -> str:
|
169
|
-
"""Estimate query complexity."""
|
170
|
-
query = query.upper()
|
171
|
-
if "JOIN" in query:
|
172
|
-
return "HIGH"
|
173
|
-
elif "GROUP BY" in query or "ORDER BY" in query:
|
174
|
-
return "MEDIUM"
|
175
|
-
else:
|
176
|
-
return "LOW"
|
177
|
-
|
178
|
-
def _estimate_cost(self, query: str) -> int:
|
179
|
-
"""Estimate query cost."""
|
180
|
-
complexity = self._estimate_complexity(query)
|
181
|
-
if complexity == "HIGH":
|
182
|
-
return 100
|
183
|
-
elif complexity == "MEDIUM":
|
184
|
-
return 50
|
185
|
-
else:
|
186
|
-
return 10
|
187
|
-
|
188
|
-
def _get_optimization_hints(self, query: str) -> List[str]:
|
189
|
-
"""Get query optimization hints."""
|
190
|
-
hints = []
|
191
|
-
query = query.upper()
|
192
|
-
|
193
|
-
if "SELECT *" in query:
|
194
|
-
hints.append("Consider specifying columns instead of using *")
|
195
|
-
if "WHERE" not in query and "SELECT" in query:
|
196
|
-
hints.append("Consider adding WHERE clause to limit results")
|
197
|
-
if "ORDER BY" in query:
|
198
|
-
hints.append("Consider adding index on ORDER BY columns")
|
199
|
-
|
200
|
-
return hints
|
201
|
-
|
202
|
-
def to_actions_tree(self, sql_query: str) -> XWNodeBase:
|
203
|
-
"""Convert SQL query to XWQuery Script actions tree."""
|
204
|
-
from .xwquery_strategy import XWQueryScriptStrategy
|
205
|
-
|
206
|
-
# Parse SQL into XWQuery Script actions
|
207
|
-
script_strategy = XWQueryScriptStrategy()
|
208
|
-
|
209
|
-
# Map SQL constructs to XWQuery actions:
|
210
|
-
# SELECT -> SELECT action
|
211
|
-
# FROM -> FROM action
|
212
|
-
# WHERE -> WHERE action
|
213
|
-
# JOIN -> JOIN action (with nested conditions)
|
214
|
-
# Subqueries -> nested SELECT actions
|
215
|
-
# etc.
|
216
|
-
|
217
|
-
# For now, create a basic actions tree
|
218
|
-
actions = {
|
219
|
-
"root": {
|
220
|
-
"type": "PROGRAM",
|
221
|
-
"statements": [
|
222
|
-
{
|
223
|
-
"type": "SELECT",
|
224
|
-
"id": "sql_action_1",
|
225
|
-
"content": sql_query,
|
226
|
-
"line_number": 1,
|
227
|
-
"timestamp": "2025-01-02T00:00:00",
|
228
|
-
"children": []
|
229
|
-
}
|
230
|
-
],
|
231
|
-
"comments": [],
|
232
|
-
"metadata": {
|
233
|
-
"version": "1.0",
|
234
|
-
"created": "2025-01-02T00:00:00",
|
235
|
-
"source_format": "SQL"
|
236
|
-
}
|
237
|
-
}
|
238
|
-
}
|
239
|
-
|
240
|
-
return XWNodeBase.from_native(actions)
|
241
|
-
|
242
|
-
def from_actions_tree(self, actions_tree: XWNodeBase) -> str:
|
243
|
-
"""Convert XWQuery Script actions tree to SQL query."""
|
244
|
-
from .xwquery_strategy import XWQueryScriptStrategy
|
245
|
-
|
246
|
-
script_strategy = XWQueryScriptStrategy(actions_tree)
|
247
|
-
return script_strategy.to_format("SQL")
|
248
|
-
|
249
|
-
def can_handle(self, query_string: str) -> bool:
|
250
|
-
"""Check if this strategy can handle the given query string."""
|
251
|
-
return self.validate_query(query_string)
|
252
|
-
|
253
|
-
def get_supported_operations(self) -> List[str]:
|
254
|
-
"""Get list of supported query operations."""
|
255
|
-
return [
|
256
|
-
"SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "ALTER",
|
257
|
-
"JOIN", "UNION", "GROUP BY", "ORDER BY", "HAVING", "WHERE",
|
258
|
-
"WITH", "CASE", "WINDOW", "PARTITION BY", "OVER"
|
259
|
-
]
|
260
|
-
|
261
|
-
def estimate_complexity(self, query_string: str) -> Dict[str, Any]:
|
262
|
-
"""Estimate query complexity and resource requirements."""
|
263
|
-
complexity = self._estimate_complexity(query_string)
|
264
|
-
cost = self._estimate_cost(query_string)
|
265
|
-
|
266
|
-
return {
|
267
|
-
"complexity_level": complexity,
|
268
|
-
"estimated_cost": cost,
|
269
|
-
"has_joins": "JOIN" in query_string.upper(),
|
270
|
-
"has_subqueries": "SELECT" in query_string.upper().replace("SELECT", "", 1),
|
271
|
-
"has_aggregates": any(func in query_string.upper() for func in ["SUM", "COUNT", "AVG", "MIN", "MAX"]),
|
272
|
-
"has_window_functions": "OVER" in query_string.upper(),
|
273
|
-
"query_length": len(query_string),
|
274
|
-
"estimated_memory": "high" if complexity == "HIGH" else "medium" if complexity == "MEDIUM" else "low"
|
275
|
-
}
|
@@ -1,66 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
XML Query Strategy
|
4
|
-
|
5
|
-
This module implements the XML Query strategy for generic XML 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 XMLQueryStrategy(ADocumentQueryStrategy):
|
21
|
-
"""XML Query strategy for generic XML operations."""
|
22
|
-
|
23
|
-
def __init__(self, **options):
|
24
|
-
super().__init__(**options)
|
25
|
-
self._mode = QueryMode.XML_QUERY
|
26
|
-
self._traits = QueryTrait.DOCUMENT | QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL
|
27
|
-
|
28
|
-
def execute(self, query: str, **kwargs) -> Any:
|
29
|
-
"""Execute XML query."""
|
30
|
-
if not self.validate_query(query):
|
31
|
-
raise XWNodeValueError(f"Invalid XML query: {query}")
|
32
|
-
return {"result": "XML query executed", "query": query}
|
33
|
-
|
34
|
-
def validate_query(self, query: str) -> bool:
|
35
|
-
"""Validate XML query syntax."""
|
36
|
-
if not query or not isinstance(query, str):
|
37
|
-
return False
|
38
|
-
return any(op in query for op in ["<", ">", "/", "//", "@", "[", "]"])
|
39
|
-
|
40
|
-
def get_query_plan(self, query: str) -> Dict[str, Any]:
|
41
|
-
"""Get XML query execution plan."""
|
42
|
-
return {
|
43
|
-
"query_type": "XML_QUERY",
|
44
|
-
"complexity": "MEDIUM",
|
45
|
-
"estimated_cost": 60
|
46
|
-
}
|
47
|
-
|
48
|
-
def path_query(self, path: str) -> Any:
|
49
|
-
"""Execute path-based query."""
|
50
|
-
return self.execute(f"//{path}")
|
51
|
-
|
52
|
-
def filter_query(self, filter_expression: str) -> Any:
|
53
|
-
"""Execute filter query."""
|
54
|
-
return self.execute(f"//*[{filter_expression}]")
|
55
|
-
|
56
|
-
def projection_query(self, fields: List[str]) -> Any:
|
57
|
-
"""Execute projection query."""
|
58
|
-
return self.execute(f"//*[{' or '.join(fields)}]")
|
59
|
-
|
60
|
-
def sort_query(self, sort_fields: List[str], order: str = "asc") -> Any:
|
61
|
-
"""Execute sort query."""
|
62
|
-
return self.execute(f"//*[sort by {sort_fields[0]}]")
|
63
|
-
|
64
|
-
def limit_query(self, limit: int, offset: int = 0) -> Any:
|
65
|
-
"""Execute limit query."""
|
66
|
-
return self.execute(f"//*[position() > {offset} and position() <= {offset + limit}]")
|