MySQL Support¶
Excalibase GraphQL supports MySQL 8.4+ as a first-class database backend. All core features work out of the box — simply point the application at your MySQL database and get a full GraphQL API automatically.
Quick Start¶
# Start the MySQL stack
docker-compose -f docker-compose.mysql.yml up -d
# GraphQL endpoint
http://localhost:10001/graphql
Configuration¶
spring:
datasource:
url: jdbc:mysql://localhost:3306/excalibase
username: excalibase
password: password123
driver-class-name: com.mysql.cj.jdbc.Driver
app:
schemas: excalibase
database-type: mysql
server:
port: 10001
Supported Features¶
CRUD Operations¶
Full create, read, update, and delete on every table:
# Query with filtering and pagination
{
excalibaseCustomer(
where: { active: { eq: 1 } }
orderBy: { last_name: "ASC" }
limit: 10
offset: 0
) {
customer_id
first_name
last_name
email
}
}
# Create
mutation {
createExcalibaseCustomer(input: {
first_name: "Alice"
last_name: "Smith"
email: "alice@example.com"
}) {
customer_id
first_name
last_name
}
}
# Update
mutation {
updateExcalibaseCustomer(id: 1, input: { email: "newemail@example.com" }) {
customer_id
email
}
}
# Delete
mutation {
deleteExcalibaseCustomer(id: 1) {
customer_id
}
}
# Bulk create
mutation {
createManyExcalibaseCustomer(inputs: [
{ first_name: "Bob", last_name: "Jones", email: "bob@example.com" }
{ first_name: "Carol", last_name: "White", email: "carol@example.com" }
]) {
customer_id
first_name
}
}
ENUM Types¶
MySQL ENUM columns are reflected as GraphQL enum types:
CREATE TABLE task (
task_id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200) NOT NULL,
status ENUM('todo', 'in_progress', 'done', 'cancelled') DEFAULT 'todo',
priority ENUM('low', 'medium', 'high', 'critical') DEFAULT 'medium'
);
{
excalibaseTask(where: { status: { eq: "in_progress" }, priority: { eq: "high" } }) {
task_id
title
status
priority
}
}
JSON Types¶
MySQL JSON columns are surfaced as GraphQL String (JSON-serialized):
CREATE TABLE product_detail (
detail_id BIGINT AUTO_INCREMENT PRIMARY KEY,
product_id BIGINT NOT NULL,
attributes JSON,
metadata JSON,
tags JSON
);
Views¶
Read-only GraphQL types are generated for MySQL views:
{
excalibaseActiveCustomers {
customer_id
first_name
last_name
email
}
}
{
excalibaseOrdersSummary {
customer_id
first_name
last_name
order_count
total_spent
}
}
Foreign Key Relationships¶
Forward and reverse FK fields are automatically added to the schema:
{
excalibaseOrders {
order_id
total
status
excalibaseCustomer { # forward FK: orders.customer_id -> customer
first_name
last_name
}
}
}
{
excalibaseCustomer {
customer_id
first_name
excalibaseOrders { # reverse FK: all orders for this customer
order_id
total
status
}
}
}
Aggregate Queries¶
Cursor-Based Pagination¶
{
excalibaseCustomerConnection(first: 10, after: "cursor123") {
edges {
node {
customer_id
first_name
last_name
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
totalCount
}
}
Stored Procedures¶
See Stored Procedures for full details. MySQL example:
# Call a stored procedure
mutation {
callExcalibaseGetCustomerOrderCount(p_customer_id: 1)
}
# Transfer funds (IN/OUT params)
mutation {
callExcalibaseTransferFunds(
p_from_wallet_id: 1
p_to_wallet_id: 2
p_amount: 200.00
)
}
Results are returned as a JSON string. Parse on the client:
const result = JSON.parse(data.callExcalibaseTransferFunds);
console.log(result.p_status); // "SUCCESS"
Filtering Operators¶
| Operator | Description | Example |
|---|---|---|
eq |
Equal | { status: { eq: "active" } } |
neq |
Not equal | { status: { neq: "cancelled" } } |
gt / gte |
Greater than / or equal | { total: { gte: 50 } } |
lt / lte |
Less than / or equal | { price: { lte: 100 } } |
in |
In list | { status: { in: ["pending", "processing"] } } |
notIn |
Not in list | { status: { notIn: ["cancelled"] } } |
isNull |
Is null | { email: { isNull: true } } |
isNotNull |
Is not null | { email: { isNotNull: true } } |
contains |
Substring match | { first_name: { contains: "ali" } } |
startsWith |
Prefix match | { last_name: { startsWith: "Sm" } } |
endsWith |
Suffix match | { email: { endsWith: "@example.com" } } |
like |
SQL LIKE pattern | { email: { like: "%@gmail%" } } |
Differences from PostgreSQL¶
| Feature | PostgreSQL | MySQL |
|---|---|---|
orderBy value |
Enum (ASC / DESC) |
String ("ASC" / "DESC") |
| Update mutation | update{Table}(input: { pk, fields... }) |
update{Table}(id: X, input: { fields... }) |
| Aggregate result | Nested per-column (sum { total }) |
Flat scalars (sum, avg) |
| Subscriptions / CDC | Supported | Not yet supported |
| Custom composite types | Supported | N/A |
| Array types | Supported | N/A |
Limitations¶
- CDC / Subscriptions — real-time subscriptions via Change Data Capture are PostgreSQL-only for now
- Spatial types — PostGIS equivalents not yet supported