참고소스 수정본
This commit is contained in:
370
참고/ontocast-main/ontocast/tool/structured_sparql.py
Normal file
370
참고/ontocast-main/ontocast/tool/structured_sparql.py
Normal file
@@ -0,0 +1,370 @@
|
||||
"""Structured SPARQL parser and executor.
|
||||
|
||||
This module provides tools for parsing and executing structured SPARQL queries
|
||||
with separate ADD, UPDATE, and REMOVE sections.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from ontocast.onto.enum import SPARQLOperationType
|
||||
from ontocast.onto.rdfgraph import RDFGraph
|
||||
from ontocast.onto.sparql_models import (
|
||||
SPARQLOperationModel,
|
||||
StructuredSPARQLQueryModel,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StructuredSPARQLParser:
|
||||
"""Parser for structured SPARQL queries with ADD, UPDATE, REMOVE sections."""
|
||||
|
||||
def __init__(self):
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
def parse_structured_query(self, query_text: str) -> StructuredSPARQLQueryModel:
|
||||
"""Parse a structured SPARQL query from text.
|
||||
|
||||
Args:
|
||||
query_text: The structured SPARQL query text
|
||||
|
||||
Returns:
|
||||
StructuredSPARQLQueryModel: Parsed structured query
|
||||
"""
|
||||
self.logger.info("Parsing structured SPARQL query")
|
||||
|
||||
# Split into sections
|
||||
sections = self._split_into_sections(query_text)
|
||||
|
||||
# Parse each section and combine all operations
|
||||
all_operations = []
|
||||
all_operations.extend(
|
||||
self._parse_section_operations(
|
||||
sections.get("ADD", ""), SPARQLOperationType.INSERT
|
||||
)
|
||||
)
|
||||
all_operations.extend(
|
||||
self._parse_section_operations(
|
||||
sections.get("UPDATE", ""), SPARQLOperationType.UPDATE
|
||||
)
|
||||
)
|
||||
all_operations.extend(
|
||||
self._parse_section_operations(
|
||||
sections.get("REMOVE", ""), SPARQLOperationType.DELETE
|
||||
)
|
||||
)
|
||||
|
||||
# Extract namespaces
|
||||
namespaces = self._extract_namespaces(query_text)
|
||||
|
||||
structured_query = StructuredSPARQLQueryModel(
|
||||
operations=all_operations,
|
||||
namespaces=namespaces,
|
||||
)
|
||||
|
||||
self.logger.info(f"Parsed structured query: {structured_query.get_summary()}")
|
||||
return structured_query
|
||||
|
||||
def _split_into_sections(self, query_text: str) -> dict[str, str]:
|
||||
"""Split query text into ADD, UPDATE, REMOVE sections.
|
||||
|
||||
Args:
|
||||
query_text: The query text to split
|
||||
|
||||
Returns:
|
||||
dict[str, str]: Dictionary mapping section names to content
|
||||
"""
|
||||
sections = {}
|
||||
current_section = None
|
||||
current_content = []
|
||||
|
||||
lines = query_text.split("\n")
|
||||
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
|
||||
# Check for section headers
|
||||
if line.upper().startswith("-- ADD SECTION:") or line.upper().startswith(
|
||||
"ADD SECTION:"
|
||||
):
|
||||
if current_section:
|
||||
sections[current_section] = "\n".join(current_content)
|
||||
current_section = "ADD"
|
||||
current_content = []
|
||||
elif line.upper().startswith(
|
||||
"-- UPDATE SECTION:"
|
||||
) or line.upper().startswith("UPDATE SECTION:"):
|
||||
if current_section:
|
||||
sections[current_section] = "\n".join(current_content)
|
||||
current_section = "UPDATE"
|
||||
current_content = []
|
||||
elif line.upper().startswith(
|
||||
"-- REMOVE SECTION:"
|
||||
) or line.upper().startswith("REMOVE SECTION:"):
|
||||
if current_section:
|
||||
sections[current_section] = "\n".join(current_content)
|
||||
current_section = "REMOVE"
|
||||
current_content = []
|
||||
else:
|
||||
current_content.append(line)
|
||||
|
||||
# Add the last section
|
||||
if current_section:
|
||||
sections[current_section] = "\n".join(current_content)
|
||||
|
||||
return sections
|
||||
|
||||
def _parse_section_operations(
|
||||
self, section_content: str, default_type: SPARQLOperationType
|
||||
) -> list[SPARQLOperationModel]:
|
||||
"""Parse operations from a section.
|
||||
|
||||
Args:
|
||||
section_content: The section content
|
||||
default_type: Default operation type for the section
|
||||
|
||||
Returns:
|
||||
list[SPARQLOperationModel]: List of parsed operations
|
||||
"""
|
||||
operations = []
|
||||
|
||||
if not section_content.strip():
|
||||
return operations
|
||||
|
||||
# Split by PREFIX blocks and INSERT/UPDATE/DELETE blocks
|
||||
blocks = self._split_into_blocks(section_content)
|
||||
|
||||
for block in blocks:
|
||||
if block.strip():
|
||||
operation = self._create_operation_from_block(block, default_type)
|
||||
if operation:
|
||||
operations.append(operation)
|
||||
|
||||
return operations
|
||||
|
||||
def _split_into_blocks(self, content: str) -> list[str]:
|
||||
"""Split content into SPARQL operation blocks.
|
||||
|
||||
Args:
|
||||
content: The content to split
|
||||
|
||||
Returns:
|
||||
list[str]: List of operation blocks
|
||||
"""
|
||||
blocks = []
|
||||
current_block = []
|
||||
in_operation = False
|
||||
|
||||
lines = content.split("\n")
|
||||
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
|
||||
if not line:
|
||||
continue
|
||||
|
||||
# Check if this is the start of a new operation
|
||||
if (
|
||||
line.upper().startswith("INSERT")
|
||||
or line.upper().startswith("UPDATE")
|
||||
or line.upper().startswith("DELETE")
|
||||
):
|
||||
# Save previous block if exists
|
||||
if current_block:
|
||||
blocks.append("\n".join(current_block))
|
||||
|
||||
# Start new block
|
||||
current_block = [line]
|
||||
in_operation = True
|
||||
elif in_operation:
|
||||
current_block.append(line)
|
||||
|
||||
# Check if operation is complete
|
||||
if line == "}" and current_block:
|
||||
blocks.append("\n".join(current_block))
|
||||
current_block = []
|
||||
in_operation = False
|
||||
|
||||
# Add any remaining block
|
||||
if current_block:
|
||||
blocks.append("\n".join(current_block))
|
||||
|
||||
return blocks
|
||||
|
||||
def _create_operation_from_block(
|
||||
self, block: str, default_type: SPARQLOperationType
|
||||
) -> SPARQLOperationModel | None:
|
||||
"""Create a SPARQL operation from a block.
|
||||
|
||||
Args:
|
||||
block: The operation block
|
||||
default_type: Default operation type
|
||||
|
||||
Returns:
|
||||
SPARQLOperationModel | None: Created operation or None if invalid
|
||||
"""
|
||||
if not block.strip():
|
||||
return None
|
||||
|
||||
# Determine operation type
|
||||
if block.upper().startswith("INSERT"):
|
||||
operation_type = SPARQLOperationType.INSERT
|
||||
elif block.upper().startswith("UPDATE"):
|
||||
operation_type = SPARQLOperationType.UPDATE
|
||||
elif block.upper().startswith("DELETE"):
|
||||
operation_type = SPARQLOperationType.DELETE
|
||||
else:
|
||||
operation_type = default_type
|
||||
|
||||
return SPARQLOperationModel(operation_type=operation_type, query=block.strip())
|
||||
|
||||
def _extract_namespaces(self, query_text: str) -> dict[str, str]:
|
||||
"""Extract namespace declarations from query text.
|
||||
|
||||
Args:
|
||||
query_text: The query text
|
||||
|
||||
Returns:
|
||||
dict[str, str]: Dictionary mapping prefixes to URIs
|
||||
"""
|
||||
namespaces = {}
|
||||
|
||||
lines = query_text.split("\n")
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
|
||||
if line.upper().startswith("PREFIX "):
|
||||
# Parse PREFIX declaration
|
||||
parts = line.split()
|
||||
if len(parts) >= 3:
|
||||
prefix = parts[1].rstrip(":")
|
||||
uri = parts[2].strip("<>")
|
||||
namespaces[prefix] = uri
|
||||
|
||||
return namespaces
|
||||
|
||||
|
||||
class StructuredSPARQLExecutor:
|
||||
"""Executor for structured SPARQL queries."""
|
||||
|
||||
def __init__(self, sparql_tool):
|
||||
"""Initialize the executor.
|
||||
|
||||
Args:
|
||||
sparql_tool: The SPARQL tool for executing operations
|
||||
"""
|
||||
self.sparql_tool = sparql_tool
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
def execute_structured_query(
|
||||
self, structured_query: StructuredSPARQLQueryModel, graph: RDFGraph
|
||||
) -> bool:
|
||||
"""Execute a structured SPARQL query.
|
||||
|
||||
Args:
|
||||
structured_query: The structured query to execute
|
||||
graph: The RDF graph to execute against
|
||||
|
||||
Returns:
|
||||
bool: True if execution was successful
|
||||
"""
|
||||
self.logger.info(
|
||||
f"Executing structured query: {structured_query.get_summary()}"
|
||||
)
|
||||
|
||||
try:
|
||||
# Execute operations in order: ADD, UPDATE, REMOVE
|
||||
all_operations = structured_query.get_all_operations()
|
||||
|
||||
for operation in all_operations:
|
||||
# Execute SPARQLOperationModel directly
|
||||
self.sparql_tool.execute_operation(operation)
|
||||
self.logger.debug(
|
||||
f"Executed {operation.operation_type.value} operation"
|
||||
)
|
||||
|
||||
self.logger.info("Structured query execution completed successfully")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Failed to execute structured query: {e}")
|
||||
return False
|
||||
|
||||
def execute_add_operations(
|
||||
self, structured_query: StructuredSPARQLQueryModel, graph: RDFGraph
|
||||
) -> bool:
|
||||
"""Execute only ADD operations from a structured query.
|
||||
|
||||
Args:
|
||||
structured_query: The structured query
|
||||
graph: The RDF graph to execute against
|
||||
|
||||
Returns:
|
||||
bool: True if execution was successful
|
||||
"""
|
||||
return self._execute_operations(structured_query.get_add_operations(), "ADD")
|
||||
|
||||
def execute_update_operations(
|
||||
self, structured_query: StructuredSPARQLQueryModel, graph: RDFGraph
|
||||
) -> bool:
|
||||
"""Execute only UPDATE operations from a structured query.
|
||||
|
||||
Args:
|
||||
structured_query: The structured query
|
||||
graph: The RDF graph to execute against
|
||||
|
||||
Returns:
|
||||
bool: True if execution was successful
|
||||
"""
|
||||
return self._execute_operations(
|
||||
structured_query.get_update_operations(), "UPDATE"
|
||||
)
|
||||
|
||||
def execute_remove_operations(
|
||||
self, structured_query: StructuredSPARQLQueryModel, graph: RDFGraph
|
||||
) -> bool:
|
||||
"""Execute only REMOVE operations from a structured query.
|
||||
|
||||
Args:
|
||||
structured_query: The structured query
|
||||
graph: The RDF graph to execute against
|
||||
|
||||
Returns:
|
||||
bool: True if execution was successful
|
||||
"""
|
||||
return self._execute_operations(
|
||||
structured_query.get_remove_operations(), "REMOVE"
|
||||
)
|
||||
|
||||
def _execute_operations(
|
||||
self, operations: list[SPARQLOperationModel], section_name: str
|
||||
) -> bool:
|
||||
"""Execute a list of operations.
|
||||
|
||||
Args:
|
||||
operations: List of operations to execute
|
||||
section_name: Name of the section for logging
|
||||
|
||||
Returns:
|
||||
bool: True if execution was successful
|
||||
"""
|
||||
if not operations:
|
||||
self.logger.info(f"No {section_name} operations to execute")
|
||||
return True
|
||||
|
||||
try:
|
||||
for operation in operations:
|
||||
# Execute SPARQLOperationModel directly
|
||||
self.sparql_tool.execute_operation(operation)
|
||||
self.logger.debug(
|
||||
f"Executed {section_name} {operation.operation_type.value} operation"
|
||||
)
|
||||
|
||||
self.logger.info(
|
||||
f"Executed {len(operations)} {section_name} operations successfully"
|
||||
)
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Failed to execute {section_name} operations: {e}")
|
||||
return False
|
||||
Reference in New Issue
Block a user