Building and Using Named Queries
Short summary
Raw SPARQL queries expose security risks, performance problems, and require too much schema knowledge. Storing queries as named, self-describing entities in RDF itself solves these issues by creating a controlled API layer that handles parameterization, access control, and logging.
- Direct SPARQL queries are dangerous: simple queries can crash systems with large datasets, prompt injection is trivial, and there's no access control—anyone with graph access sees everything.
- Most real-world graph operations (80%) fall into standard patterns like "get items from a list" or "update an item"—naming these as reusable queries eliminates the need for most people to write SPARQL at all.
- Named queries stored as RDF with metadata enable agents to self-discover available operations, support safe parameterization through text substitution (not SPARQL variables), enforce permissions locally, and log all access without redeploying code.
Full summary
SPARQL queries have a fundamental problem: they're treated like raw SQL calls with no real infrastructure around them. The author identifies seven concrete issues. There's no access control—anyone with graph access sees everything. Simple queries can crash systems with billion-triple datasets. Prompt injection is a real threat. Most people lack the schema knowledge to write queries safely. Parameterization is clunky, typically done through VALUES keywords or external dictionaries. SPARQL UPDATE operations are particularly dangerous because even trivial updates can cause serious damage. And critically, when you export a dataset, you lose the query logic that gives the data meaning—the two get separated.
The solution is named queries: storing SPARQL queries as RDF triples within the graph itself, wrapped with metadata. This isn't novel—APIs have encapsulated queries for years—but keeping them as text in the database creates real advantages. Metadata can include SHACL schemas describing parameters and expected outputs, letting AI agents decide which query to run. You add new queries by inserting triples, not recompiling code. All reads and writes go through these named interfaces, never directly to the graph, which means you can enforce access control and log every interaction. You can inject user identity information that changes results based on permissions—something much harder with inline queries. The author has tested these ideas in practice.
The concrete implementation uses a self-describing structure in Turtle format. A named query object stores the SPARQL text, query type, description, and parameter definitions. Parameters use text placeholders like `{{class}}` that get substituted before parsing, not SPARQL variables—this matters because placeholders can sit anywhere, even inside FILTER clauses. Required parameters are enforced; optional ones fall back to defaults. The example query retrieves instances of a class with optional substring filtering on labels and comments. Using `COALESCE(STR(?label), "")` handles unbound variables gracefully, treating missing data the same as empty data so filters work predictably. This structure lets the system understand what each query does, what it needs, and what it returns.