Databases
Databases
Section titled “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.
Supported Databases
Section titled “Supported Databases”| Database | Dialect | Status | Driver |
|---|---|---|---|
| Neo4j | Cypher | ✅ Available | neo4j-go-driver |
| PostgreSQL | SQL | 🚧 Coming soon | pgx |
| MySQL | SQL | 🚧 Coming soon | go-sql-driver |
| SQLite | SQL | 🚧 Coming soon | modernc.org/sqlite |
Neo4j is the graph database using the Cypher query language.
Configuration
Section titled “Configuration”neo4j: uri: bolt://localhost:7687 username: neo4j password: password database: neo4j # optional, defaults to neo4jConnection URI Formats
Section titled “Connection URI Formats”# Standard bolt protocoluri: bolt://localhost:7687
# Bolt with routing (cluster)uri: neo4j://cluster.example.com:7687
# With SSLuri: bolt+s://secure.example.com:7687uri: neo4j+s://secure.example.com:7687Example Queries
Section titled “Example Queries”fn GetUser
fn GetUserWithFriends
fn CreateUser `CREATE (u:User {id: $id, name: $name, email: $email})RETURN u`Cypher Features
Section titled “Cypher Features”Supported Cypher clauses:
MATCH,OPTIONAL MATCHCREATE,MERGESET,REMOVEDELETE,DETACH DELETERETURN,WITHWHERE,ORDER BY,LIMIT,SKIPUNWIND,FOREACHCALL(procedures)UNION,UNION ALL
PostgreSQL (Coming Soon)
Section titled “PostgreSQL (Coming Soon)”Planned Configuration
Section titled “Planned Configuration”postgres: host: localhost port: 5432 database: mydb user: postgres password: password sslmode: disable # disable, require, verify-ca, verify-fullOr using a connection URI:
postgres: uri: postgres://postgres:password@localhost:5432/mydb?sslmode=disableExample SQL Queries
Section titled “Example SQL Queries”fn GetUser `SELECT name, email, ageFROM usersWHERE id = $userId`
fn GetUserWithPosts `SELECT u.name, u.email, COUNT(p.id) as post_countFROM users uLEFT JOIN posts p ON p.author_id = u.idWHERE u.id = $userIdGROUP BY u.id, u.name, u.email`
fn CreateUser `INSERT INTO users (id, name, email)VALUES ($id, $name, $email)RETURNING id, name, email`MySQL (Coming Soon)
Section titled “MySQL (Coming Soon)”Planned Configuration
Section titled “Planned Configuration”mysql: host: localhost port: 3306 database: mydb user: root password: passwordSQLite (Coming Soon)
Section titled “SQLite (Coming Soon)”Planned Configuration
Section titled “Planned Configuration”sqlite: path: ./test.db # or :memory: for in-memory databaseDialects
Section titled “Dialects”Each database uses a specific query dialect:
Cypher Dialect
Section titled “Cypher 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`SQL Dialect
Section titled “SQL Dialect”Used by: PostgreSQL, MySQL, SQLite
Standard SQL with database-specific extensions:
fn Example `SELECT name FROM nodes WHERE prop = $value`Parameter Syntax
Section titled “Parameter Syntax”All databases use $paramName for parameters:
fn Example `-- Works in both Cypher and SQLWHERE id = $userId AND status = $status`Return Value Mapping
Section titled “Return Value Mapping”Databases map results to scaf’s value types:
| Database Type | scaf Type |
|---|---|
| String | string |
| Integer | number |
| Float | number |
| Boolean | boolean |
| Null | null |
| Array/List | list |
| Map/Object | map |
| Date/Time | string (ISO format) |
Neo4j-Specific Types
Section titled “Neo4j-Specific Types”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.elementIdDatabase Comparison
Section titled “Database Comparison”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`fn GetUserWithRelations `SELECT u.name, array_agg(DISTINCT f.name) as friends, array_agg(DISTINCT p.title) as postsFROM users uLEFT JOIN friendships fr ON fr.user_id = u.idLEFT JOIN users f ON f.id = fr.friend_idLEFT JOIN posts p ON p.author_id = u.idWHERE u.id = $userIdGROUP BY u.id, u.name`