Skip to content

Databases

scaf separates the concepts of databases (execution targets) and dialects (query languages):

  • Database: Where queries run (Neo4j, PostgreSQL, MySQL, SQLite)
  • Dialect: The query language used (Cypher, SQL)

This allows multiple databases to share a dialect. For example, PostgreSQL, MySQL, and SQLite all use the SQL dialect.

DatabaseDialectStatusDriver
Neo4jCypher✅ Availableneo4j-go-driver
PostgreSQLSQL🚧 Coming soonpgx
MySQLSQL🚧 Coming soongo-sql-driver
SQLiteSQL🚧 Coming soonmodernc.org/sqlite

Neo4j is the graph database using the Cypher query language.

neo4j:
uri: bolt://localhost:7687
username: neo4j
password: password
database: neo4j # optional, defaults to neo4j
# Standard bolt protocol
uri: bolt://localhost:7687
# Bolt with routing (cluster)
uri: neo4j://cluster.example.com:7687
# With SSL
uri: bolt+s://secure.example.com:7687
uri: neo4j+s://secure.example.com:7687
fn GetUser
fn GetUserWithFriends
fn CreateUser `
CREATE (u:User {id: $id, name: $name, email: $email})
RETURN u
`

Supported Cypher clauses:

  • MATCH, OPTIONAL MATCH
  • CREATE, MERGE
  • SET, REMOVE
  • DELETE, DETACH DELETE
  • RETURN, WITH
  • WHERE, ORDER BY, LIMIT, SKIP
  • UNWIND, FOREACH
  • CALL (procedures)
  • UNION, UNION ALL
postgres:
host: localhost
port: 5432
database: mydb
user: postgres
password: password
sslmode: disable # disable, require, verify-ca, verify-full

Or using a connection URI:

postgres:
uri: postgres://postgres:password@localhost:5432/mydb?sslmode=disable
fn GetUser `
SELECT name, email, age
FROM users
WHERE id = $userId
`
fn GetUserWithPosts `
SELECT
u.name,
u.email,
COUNT(p.id) as post_count
FROM users u
LEFT JOIN posts p ON p.author_id = u.id
WHERE u.id = $userId
GROUP BY u.id, u.name, u.email
`
fn CreateUser `
INSERT INTO users (id, name, email)
VALUES ($id, $name, $email)
RETURNING id, name, email
`
mysql:
host: localhost
port: 3306
database: mydb
user: root
password: password
sqlite:
path: ./test.db
# or :memory: for in-memory database

Each database uses a specific query dialect:

Used by: Neo4j

Graph query language for pattern matching:

fn Example `
MATCH (n:Node {prop: $value})-[r:RELATES_TO]->(m)
RETURN n.name, type(r), m.name
`

Used by: PostgreSQL, MySQL, SQLite

Standard SQL with database-specific extensions:

fn Example `
SELECT name FROM nodes WHERE prop = $value
`

All databases use $paramName for parameters:

fn Example `
-- Works in both Cypher and SQL
WHERE id = $userId AND status = $status
`

Databases map results to scaf’s value types:

Database Typescaf Type
Stringstring
Integernumber
Floatnumber
Booleanboolean
Nullnull
Array/Listlist
Map/Objectmap
Date/Timestring (ISO format)

Neo4j nodes and relationships are flattened in results:

fn GetUser `
MATCH (u:User {id: $id})
RETURN u
`
// Result keys: u.name, u.email, u.labels, u.elementId
fn GetUserWithRelations `
MATCH (u:User {id: $userId})
OPTIONAL MATCH (u)-[:FRIENDS_WITH]->(f:User)
OPTIONAL MATCH (u)-[:AUTHORED]->(p:Post)
RETURN
u.name,
collect(DISTINCT f.name) as friends,
collect(DISTINCT p.title) as posts
`