Parameterized Queries
Parameterized queries prevent SQL injection and properly handle special characters. This guide shows how to use them.
Basic Usage
Use $parameter syntax in Cypher and pass a dictionary of parameters to Connection.cypher():
from graphqlite import Graph
g = Graph(":memory:")
# Named parameters via the connection
results = g.connection.cypher(
"MATCH (n:Person {name: $name}) WHERE n.age > $age RETURN n",
{"name": "Alice", "age": 30}
)
With the Connection API
The Connection.cypher() method accepts parameters as a dictionary:
from graphqlite import connect
conn = connect(":memory:")
# Create with parameters
conn.cypher(
"CREATE (n:Person {name: $name, age: $age})",
{"name": "Bob", "age": 25}
)
# Query with parameters
results = conn.cypher(
"MATCH (n:Person) WHERE n.age >= $min_age RETURN n.name",
{"min_age": 21}
)
With Raw SQL
When using the SQLite interface directly:
SELECT cypher(
'MATCH (n:Person {name: $name}) RETURN n',
'{"name": "Alice"}'
);
Parameter Types
Parameters support all JSON types:
params = json.dumps({
"string_val": "hello",
"int_val": 42,
"float_val": 3.14,
"bool_val": True,
"null_val": None,
"array_val": [1, 2, 3]
})
Use Cases
User Input
Always use parameters for user-provided values:
def search_by_name(user_input: str):
# Safe - user input is parameterized
return g.connection.cypher(
"MATCH (n:Person {name: $name}) RETURN n",
{"name": user_input}
)
Batch Operations
people = [
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25},
{"name": "Carol", "age": 35},
]
for person in people:
g.connection.cypher(
"CREATE (n:Person {name: $name, age: $age})",
person
)
Complex Values
Parameters handle special characters automatically:
# This works correctly even with quotes and newlines
text = "He said \"hello\"\nand then left."
g.connection.cypher(
"CREATE (n:Note {content: $text})",
{"text": text}
)
Benefits
- Security: Prevents Cypher injection attacks
- Correctness: Properly handles quotes, newlines, and special characters
- Performance: Query plans can be cached (future optimization)
- Clarity: Separates query logic from data
Common Patterns
Optional Parameters
def search(name: str = None, min_age: int = None):
conditions = []
params = {}
if name:
conditions.append("n.name = $name")
params["name"] = name
if min_age:
conditions.append("n.age >= $min_age")
params["min_age"] = min_age
where = f"WHERE {' AND '.join(conditions)}" if conditions else ""
return g.connection.cypher(
f"MATCH (n:Person) {where} RETURN n",
params if params else None
)
Lists in Parameters
names = ["Alice", "Bob", "Carol"]
results = g.connection.cypher(
"MATCH (n:Person) WHERE n.name IN $names RETURN n",
{"names": names}
)