meta-log-db
Version:
Native database package for Meta-Log (ProLog, DataLog, R5RS)
185 lines • 6.22 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TripleStore = void 0;
const sparql_parser_js_1 = require("./sparql-parser.js");
const sparql_executor_js_1 = require("./sparql-executor.js");
/**
* RDF Triple Store
*/
class TripleStore {
constructor() {
this.triples = [];
this.queryCache = new Map();
this.cacheEnabled = true;
}
/**
* Add triples to the store
*/
addTriples(triples) {
this.triples.push(...triples);
}
/**
* Query triples by pattern
*/
query(pattern) {
return this.triples.filter(triple => {
if (pattern.subject && triple.subject !== pattern.subject) {
return false;
}
if (pattern.predicate && triple.predicate !== pattern.predicate) {
return false;
}
if (pattern.object) {
const objStr = typeof triple.object === 'string'
? triple.object
: triple.object.value;
if (objStr !== pattern.object) {
return false;
}
}
return true;
});
}
/**
* Execute SPARQL query (enhanced implementation)
* Supports: SELECT, DISTINCT, ORDER BY, LIMIT, OFFSET, FILTER, OPTIONAL
*/
async sparql(query) {
// Check cache
if (this.cacheEnabled) {
const cached = this.queryCache.get(query);
if (cached) {
return cached;
}
}
try {
// Parse query using enhanced parser
const parsedQuery = sparql_parser_js_1.SparqlParser.parse(query);
// Execute query using enhanced executor
const executor = new sparql_executor_js_1.SparqlExecutor(this.triples);
const result = await executor.execute(parsedQuery);
// Cache result
if (this.cacheEnabled) {
this.queryCache.set(query, result);
}
return result;
}
catch (error) {
// Fallback to simplified parser for backward compatibility
return this.sparqlSimple(query);
}
}
/**
* Simple SPARQL query execution (backward compatibility)
*/
async sparqlSimple(query) {
// Simple SELECT query parser
const selectMatch = query.match(/SELECT\s+(.*?)\s+WHERE/i);
if (!selectMatch) {
throw new Error('Unsupported SPARQL query format');
}
const variables = selectMatch[1].split(/\s+/).filter(v => v.startsWith('?'));
// Extract WHERE clause patterns
const whereMatch = query.match(/WHERE\s*\{([^}]+)\}/is);
if (!whereMatch) {
return { results: { bindings: [] } };
}
const patterns = this.parseSparqlPatterns(whereMatch[1]);
const bindings = [];
// Simple pattern matching
for (const pattern of patterns) {
const matches = this.query(pattern);
for (const match of matches) {
const binding = {};
if (pattern.subject?.startsWith('?')) {
binding[pattern.subject] = { value: match.subject, type: 'uri' };
}
if (pattern.predicate?.startsWith('?')) {
binding[pattern.predicate] = { value: match.predicate, type: 'uri' };
}
if (pattern.object?.startsWith('?')) {
const objValue = typeof match.object === 'string' ? match.object : match.object.value;
binding[pattern.object] = { value: objValue, type: 'uri' };
}
bindings.push(binding);
}
}
return { results: { bindings } };
}
/**
* Enable/disable query caching
*/
setCacheEnabled(enabled) {
this.cacheEnabled = enabled;
if (!enabled) {
this.queryCache.clear();
}
}
/**
* Clear query cache
*/
clearCache() {
this.queryCache.clear();
}
/**
* Parse SPARQL patterns from WHERE clause
*/
parseSparqlPatterns(whereClause) {
const patterns = [];
const lines = whereClause.split('\n').map(l => l.trim()).filter(l => l);
for (const line of lines) {
const match = line.match(/(\S+)\s+(\S+)\s+(\S+)\s*\./);
if (match) {
patterns.push({
subject: match[1],
predicate: match[2],
object: match[3]
});
}
}
return patterns;
}
/**
* RDFS entailment (simplified)
*/
rdfsEntailment(triples) {
const entailed = [...triples];
const rdfType = '<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>';
const rdfsSubClassOf = '<http://www.w3.org/2000/01/rdf-schema#subClassOf>';
// Find subClassOf relationships
const subClassTriples = triples.filter(t => t.predicate === rdfsSubClassOf);
// Apply subClassOf transitivity
for (const subClassTriple of subClassTriples) {
const subClass = subClassTriple.subject;
const superClass = typeof subClassTriple.object === 'string'
? subClassTriple.object
: subClassTriple.object.value;
// Find all instances of subClass
const instances = triples.filter(t => t.predicate === rdfType &&
(typeof t.object === 'string' ? t.object : t.object.value) === subClass);
// Add type assertions for superClass
for (const instance of instances) {
entailed.push({
subject: instance.subject,
predicate: rdfType,
object: superClass
});
}
}
return entailed;
}
/**
* Get all triples
*/
getTriples() {
return [...this.triples];
}
/**
* Clear all triples
*/
clear() {
this.triples = [];
}
}
exports.TripleStore = TripleStore;
//# sourceMappingURL=triple-store.js.map