-
-
Notifications
You must be signed in to change notification settings - Fork 2
schema.json
⚡️ The schema.js
spec.
Manage your entire database structure declaratively here. Add objects, remove object, modify existing objects in-place, and Linked QL's perfect diffing process will diff your new structure with your active DB structure and compose the relevant SQL that executes against your database. (See ➞ Migrations.)
This specification is your guide!
Below, we start with plain JSON examples in each case, then the relevant spec.
Jump to: DatabaseSchema
, TableSchema
, ColumnSchema
, ConstraintSchema
, IndexSchema
{
// Database name - required
"name": "database_1",
// List of tables - required, even if empty
"tables": []
}
└ Spec
interface DatabaseSchema {
name: string;
tables: TableSchema[];
}
{
// Table name - required
"name": "users",
// List of columns - required, even if empty
"columns": [],
// List of constraints
"constraints": [],
// List of indexes
"indexes": []
}
└ Spec
interface TableSchema {
name: string;
columns: ColumnSchema[];
constraints: TableConstraintSchemaType[];
indexes: IndexSchema[];
}
{
// Column name - required
"name": "id",
// Column type - required
"type": "int",
// PRIMARY_KEY constraint
"primaryKey": true,
// IDENTITY constraint
"identity": true
}
{
// Column name - required
"name": "parent",
// Column type - required
"type": ["int", 3],
// NOT_NULL constraint
"notNull": true,
// FOREIGN_KEY constraint
"foreignKey": {
// Target table - required
"targetTable": "users",
// Target columns - required
"targetColumns": ["id"],
// Match rule
"matchRule": "full",
// Update rule
"updateRule": "cascade",
// Delete rule
"deleteRule": "restrict"
}
}
└ Spec
interface ColumnSchema {
name: string;
type: string | array;
primaryKey?: boolean | PrimaryKeySchema;
foreignKey?: ForeignKeySchema;
uniqueKey?: boolean | UniqueKeySchema;
check?: string | CheckConstraintSchema;
default?: string | DefaultConstraintSchema;
expression?: string | ExpressionConstraintSchema;
identity: boolean | IdentityConstraintSchema;
onUpdate?: string | OnUpdateConstraintSchema; // (MySQL-specific attribute)
autoIncrement?: boolean; // (MySQL-specific attribute)
notNull?: boolean;
null?: boolean;
}
{
// Constraint type - required
"type": "PRIMARY_KEY",
// Columns - required
"columns": ["id_2"],
}
{
// Constraint type - required
"type": "FOREIGN_KEY",
// Columns - required
"columns": ["parent_2"],
// Target table - required
"targetTable": "users",
// Target columns - required
"targetColumns": ["id"],
// Match rule
"matchRule": "full",
// Update rule
"updateRule": "cascade",
// Delete rule
"deleteRule": "restrict"
}
{
// Constraint type - required
"type": "UNIQUE_KEY",
// Columns - required
"columns": ["parent", "full_name"]
}
{
// Constraint type - required
"type": "CHECK",
// Expr - required
"expr": { "matches": ["email", "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$"] }
}
└ Spec
type TableConstraintSchemaType = TablePrimaryKeySchema | TableForeignKeySchema | TableUniqueKeySchema | TableCheckConstraintSchema;
interface TablePrimaryKeySchema extends PrimaryKeySchema {
type: 'PRIMARY_KEY';
columns: string[];
}
interface TableForeignKeySchema extends ForeignKeySchema {
type: 'FOREIGN_KEY';
columns: string[];
}
interface TableUniqueKeySchema extends UniqueKeySchema {
type: 'UNIQUE_KEY';
columns: string[];
}
interface TableCheckConstraintSchema extends CheckConstraintSchema {
type: 'CHECK';
}
type ColumnConstraintSchemaType = PrimaryKeySchema | ForeignKeySchema | UniqueKeySchema | CheckConstraintSchema | DefaultConstraintSchema | ExpressionConstraintSchema | IdentityConstraintSchema | OnUpdateConstraintSchema;
interface PrimaryKeySchema {
name: string;
}
interface ForeignKeySchema {
targetTable: string | string[];
targetColumns: string[];
matchRule?: string;
updateRule?: string | { rule: string, columns: string[] };
deleteRule?: string | { rule: string, columns: string[] };
name?: string;
}
interface UniqueKeySchema {
name: string;
}
interface CheckConstraintSchema {
expr: Expr;
name?: string;
}
interface DefaultConstraintSchema {
expr: Expr;
}
interface ExpressionConstraintSchema {
expr: Expr;
stored: boolean;
}
interface IdentityConstraintSchema {
always: boolean;
}
interface OnUpdateConstraintSchema {
expr: Expr;
}
{
// Index type - required
"type": "FULLTEXT",
// Columns - required
"columns": ["full_name"]
}
└ Spec
interface IndexSchema {
type: string;
columns: string[];
name?: string;
}
To rename a database or table or column or constraint or index, use a temporary attribute (called a diff tag) to specify the new name: $name
, while leaving the old name in place:
{
"name": "database_1",
"$name": "new_database_1"
}
Old names are needed in-place as a means of identification when diffing against your active DB schema. The temporary diff tag ($name
) is automatically removed after new name has been picked up by Linked QL during migration.
[
{
"name": "database_1",
"tables": [
{
"name": "users",
"columns": [
{
"name": "id",
"type": "int",
"primaryKey": true,
"identity": true
},
{
"name": "first_name",
"type": ["varchar", 101]
},
{
"name": "last_name",
"type": ["varchar", 101]
},
{
"name": "full_name",
"type": ["varchar", 101],
"expression": { "join": ["first_name", " ", "last_name"]}
},
{
"name": "email",
"type": ["varchar", 50],
"uniqueKey": true,
"notNull": true,
"check": { "expr": { "matches": ["email", "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$"] } }
},
{
"name": "parent",
"type": "int",
"notNull": true,
"foreignKey": {
"targetTable": "users",
"targetColumns": ["id"],
"matchRule": "full",
"updateRule": "cascade",
"deleteRule": "restrict"
}
}
],
"constraints": [
{
"type": "PRIMARY_KEY",
"columns": ["id_2"],
},
{
"type": "FOREIGN_KEY",
"columns": ["parent_2"],
"targetTable": "users",
"targetColumns": ["id"],
"matchRule": "full",
"updateRule": "cascade",
"deleteRule": "restrict"
},
{
"type": "UNIQUE_KEY",
"name": "constraint_name",
"columns": ["parent", "full_name"]
},
{
"type": "CHECK",
"expr": { "matches": ["email", "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$"] }
}
],
"indexes": [
{
"type": "FULLTEXT",
"columns": ["full_name"]
},
{
"type": "SPATIAL",
"columns": ["full_name"]
}
]
}
]
},
{
"name": "database_2",
"tables": []
}
]