SQL Interface
GraphQLite works as a standard SQLite extension, providing the cypher() function.
Loading the Extension
SQLite CLI
sqlite3 graph.db
.load /path/to/graphqlite
Or with automatic extension loading:
sqlite3 -cmd ".load /path/to/graphqlite" graph.db
Programmatically
SELECT load_extension('/path/to/graphqlite');
The cypher() Function
Basic Usage
SELECT cypher('MATCH (n) RETURN n.name');
With Parameters
SELECT cypher(
'MATCH (n:Person {name: $name}) RETURN n',
'{"name": "Alice"}'
);
Return Format
The cypher() function returns results as JSON:
SELECT cypher('MATCH (n:Person) RETURN n.name, n.age');
-- Returns: [{"n.name": "Alice", "n.age": 30}, {"n.name": "Bob", "n.age": 25}]
Working with Results
Extract Values with JSON Functions
SELECT json_extract(value, '$.n.name') AS name
FROM json_each(cypher('MATCH (n:Person) RETURN n'));
Algorithm Results
SELECT
json_extract(value, '$.node_id') AS id,
json_extract(value, '$.score') AS score
FROM json_each(cypher('RETURN pageRank()'))
ORDER BY score DESC
LIMIT 10;
Join with Regular Tables
-- Assuming you have a regular 'users' table
SELECT u.email, json_extract(g.value, '$.degree')
FROM users u
JOIN json_each(cypher('RETURN degreeCentrality()')) g
ON u.id = json_extract(g.value, '$.user_id');
Write Operations
-- Create nodes
SELECT cypher('CREATE (n:Person {name: "Alice", age: 30})');
-- Create relationships
SELECT cypher('
MATCH (a:Person {name: "Alice"}), (b:Person {name: "Bob"})
CREATE (a)-[:KNOWS]->(b)
');
-- Update properties
SELECT cypher('
MATCH (n:Person {name: "Alice"})
SET n.age = 31
');
-- Delete
SELECT cypher('
MATCH (n:Person {name: "Alice"})
DETACH DELETE n
');
Schema Tables
GraphQLite creates these tables automatically. See Storage Model for detailed documentation.
Core Tables
SELECT * FROM nodes;
-- id (auto-increment primary key)
SELECT * FROM node_labels;
-- node_id, label
SELECT * FROM edges;
-- id, source_id, target_id, type
SELECT * FROM property_keys;
-- id, key (normalized property names)
Property Tables
Properties use key_id as a foreign key to property_keys for normalization:
SELECT * FROM node_props_text; -- node_id, key_id, value
SELECT * FROM node_props_int; -- node_id, key_id, value
SELECT * FROM node_props_real; -- node_id, key_id, value
SELECT * FROM node_props_bool; -- node_id, key_id, value
SELECT * FROM edge_props_text; -- edge_id, key_id, value
SELECT * FROM edge_props_int; -- edge_id, key_id, value
SELECT * FROM edge_props_real; -- edge_id, key_id, value
SELECT * FROM edge_props_bool; -- edge_id, key_id, value
Direct SQL Access
You can query the underlying tables directly for debugging or advanced use cases:
-- Count nodes by label
SELECT label, COUNT(*) FROM node_labels GROUP BY label;
-- Find nodes with a specific property (join through property_keys)
SELECT n.id, pk.key, p.value
FROM nodes n
JOIN node_props_text p ON n.id = p.node_id
JOIN property_keys pk ON p.key_id = pk.id
WHERE pk.key = 'name';
-- Find all properties for a specific node
SELECT pk.key, p.value
FROM node_props_text p
JOIN property_keys pk ON p.key_id = pk.id
WHERE p.node_id = 1;
-- Find edges with their endpoint info
SELECT e.id, e.type, e.source_id, e.target_id
FROM edges e
WHERE e.type = 'KNOWS';
Transaction Support
GraphQLite respects SQLite transactions:
BEGIN;
SELECT cypher('CREATE (a:Person {name: "Alice"})');
SELECT cypher('CREATE (b:Person {name: "Bob"})');
SELECT cypher('MATCH (a:Person {name: "Alice"}), (b:Person {name: "Bob"}) CREATE (a)-[:KNOWS]->(b)');
COMMIT;
Or rollback on error:
BEGIN;
SELECT cypher('CREATE (n:Person {name: "Test"})');
ROLLBACK; -- Node is not created