Add JSON schema struct generation (#210)

All structs matched well except for `PrimaryKey` which we mapped
differently, I've refactored it to `Pk` as it doesn't seem to support
different names for go and JSON

---------

Signed-off-by: Alexis Rico <sferadev@gmail.com>
Co-authored-by: Andrew Farries <andyrb@gmail.com>
This commit is contained in:
Alexis Rico 2023-12-01 17:01:40 +01:00 committed by GitHub
parent 5812acc886
commit 788bac6e4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 766 additions and 238 deletions

8
Makefile Normal file
View File

@ -0,0 +1,8 @@
.PHONY: generate
generate:
# Generate the types from the JSON schema
docker run -v $$PWD/schema.json:/mnt/schema.json omissis/go-jsonschema:0.14.1 --only-models -p migrations --tags json /mnt/schema.json > pkg/migrations/types.go
# Add the license header
echo "// SPDX-License-Identifier: Apache-2.0" | cat - pkg/migrations/types.go > pkg/migrations/types.go.tmp
mv pkg/migrations/types.go.tmp pkg/migrations/types.go

View File

@ -2,11 +2,6 @@
package migrations
type CheckConstraint struct {
Name string `json:"name"`
Constraint string `json:"constraint"`
}
func (c *CheckConstraint) Validate() error {
if c.Name == "" {
return FieldRequiredError{Name: "name"}

View File

@ -4,12 +4,6 @@ package migrations
import "github.com/xataio/pgroll/pkg/schema"
type ForeignKeyReference struct {
Name string `json:"name"`
Table string `json:"table"`
Column string `json:"column"`
}
func (f *ForeignKeyReference) Validate(s *schema.Schema) error {
if f.Name == "" {
return FieldRequiredError{Name: "name"}

View File

@ -12,12 +12,6 @@ import (
"github.com/xataio/pgroll/pkg/schema"
)
type OpAddColumn struct {
Table string `json:"table"`
Up *string `json:"up"`
Column Column `json:"column"`
}
var _ Operation = (*OpAddColumn)(nil)
func (o *OpAddColumn) Start(ctx context.Context, conn *sql.DB, stateSchema string, s *schema.Schema, cbs ...CallbackFn) error {
@ -173,7 +167,7 @@ func (o *OpAddColumn) Validate(ctx context.Context, s *schema.Schema) error {
return FieldRequiredError{Name: "up"}
}
if o.Column.PrimaryKey {
if o.Column.Pk {
return errors.New("adding primary key columns is not supported")
}

View File

@ -24,9 +24,9 @@ func TestAddColumn(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -121,9 +121,9 @@ func TestAddForeignKeyColumn(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -136,9 +136,9 @@ func TestAddForeignKeyColumn(t *testing.T) {
Name: "orders",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "quantity",
@ -223,9 +223,9 @@ func TestAddForeignKeyColumn(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -238,9 +238,9 @@ func TestAddForeignKeyColumn(t *testing.T) {
Name: "orders",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "quantity",
@ -332,9 +332,9 @@ func TestAddColumnWithUpSql(t *testing.T) {
Name: "products",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -419,9 +419,9 @@ func TestAddNotNullColumnWithNoDefault(t *testing.T) {
Name: "products",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -485,9 +485,9 @@ func TestAddColumnValidation(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -604,9 +604,9 @@ func TestAddColumnWithCheckConstraint(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",

View File

@ -10,19 +10,6 @@ import (
"github.com/xataio/pgroll/pkg/schema"
)
type OpAlterColumn struct {
Table string `json:"table"`
Column string `json:"column"`
Name string `json:"name"`
Type string `json:"type"`
Check *CheckConstraint `json:"check"`
References *ForeignKeyReference `json:"references"`
Nullable *bool `json:"nullable"`
Unique *UniqueConstraint `json:"unique"`
Up string `json:"up"`
Down string `json:"down"`
}
var _ Operation = (*OpAlterColumn)(nil)
func (o *OpAlterColumn) Start(ctx context.Context, conn *sql.DB, stateSchema string, s *schema.Schema, cbs ...CallbackFn) error {

View File

@ -18,9 +18,9 @@ func TestAlterColumnValidation(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -32,9 +32,9 @@ func TestAlterColumnValidation(t *testing.T) {
Name: "posts",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "title",

View File

@ -24,9 +24,9 @@ func TestChangeColumnType(t *testing.T) {
Name: "reviews",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "username",
@ -157,9 +157,9 @@ func TestChangeColumnTypeValidation(t *testing.T) {
Name: "reviews",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "username",

View File

@ -12,12 +12,6 @@ import (
"github.com/xataio/pgroll/pkg/schema"
)
type OpCreateIndex struct {
Name string `json:"name"`
Table string `json:"table"`
Columns []string `json:"columns"`
}
var _ Operation = (*OpCreateIndex)(nil)
func (o *OpCreateIndex) Start(ctx context.Context, conn *sql.DB, stateSchema string, s *schema.Schema, cbs ...CallbackFn) error {

View File

@ -22,9 +22,9 @@ func TestCreateIndex(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -73,9 +73,9 @@ func TestCreateIndexOnMultipleColumns(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",

View File

@ -13,22 +13,6 @@ import (
var _ Operation = (*OpCreateTable)(nil)
type OpCreateTable struct {
Name string `json:"name"`
Columns []Column `json:"columns"`
}
type Column struct {
Name string `json:"name"`
Type string `json:"type"`
Nullable bool `json:"nullable"`
Unique bool `json:"unique"`
PrimaryKey bool `json:"pk"`
Default *string `json:"default"`
Check *CheckConstraint `json:"check"`
References *ForeignKeyReference `json:"references"`
}
func (o *OpCreateTable) Start(ctx context.Context, conn *sql.DB, stateSchema string, s *schema.Schema, cbs ...CallbackFn) error {
tempName := TemporaryName(o.Name)
_, err := conn.ExecContext(ctx, fmt.Sprintf("CREATE TABLE %s (%s)",
@ -117,7 +101,7 @@ func columnsToSQL(cols []Column) string {
func ColumnToSQL(col Column) string {
sql := fmt.Sprintf("%s %s", pq.QuoteIdentifier(col.Name), col.Type)
if col.PrimaryKey {
if col.Pk {
sql += " PRIMARY KEY"
}
if col.Unique {

View File

@ -25,9 +25,9 @@ func TestCreateTable(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -84,9 +84,9 @@ func TestCreateTable(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -104,9 +104,9 @@ func TestCreateTable(t *testing.T) {
Name: "orders",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "user_id",
@ -181,9 +181,9 @@ func TestCreateTable(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -246,9 +246,9 @@ func TestCreateTableValidation(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -266,9 +266,9 @@ func TestCreateTableValidation(t *testing.T) {
Name: "orders",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "user_id",

View File

@ -11,12 +11,6 @@ import (
"github.com/xataio/pgroll/pkg/schema"
)
type OpDropColumn struct {
Table string `json:"table"`
Column string `json:"column"`
Down *string `json:"down,omitempty"`
}
var _ Operation = (*OpDropColumn)(nil)
func (o *OpDropColumn) Start(ctx context.Context, conn *sql.DB, stateSchema string, s *schema.Schema, cbs ...CallbackFn) error {

View File

@ -24,9 +24,9 @@ func TestDropColumnWithDownSQL(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",

View File

@ -11,14 +11,6 @@ import (
"github.com/xataio/pgroll/pkg/schema"
)
type OpDropConstraint struct {
Table string `json:"table"`
Column string `json:"column"`
Name string `json:"name"`
Up string `json:"up"`
Down string `json:"down"`
}
var _ Operation = (*OpDropConstraint)(nil)
func (o *OpDropConstraint) Start(ctx context.Context, conn *sql.DB, stateSchema string, s *schema.Schema, cbs ...CallbackFn) error {

View File

@ -24,9 +24,9 @@ func TestDropConstraint(t *testing.T) {
Name: "posts",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "title",
@ -153,9 +153,9 @@ func TestDropConstraint(t *testing.T) {
Name: "posts",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "title",
@ -219,9 +219,9 @@ func TestDropConstraint(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -233,9 +233,9 @@ func TestDropConstraint(t *testing.T) {
Name: "posts",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "title",
@ -384,9 +384,9 @@ func TestDropConstraint(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -466,9 +466,9 @@ func TestDropConstraintValidation(t *testing.T) {
Name: "posts",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "title",

View File

@ -10,10 +10,6 @@ import (
"github.com/xataio/pgroll/pkg/schema"
)
type OpDropIndex struct {
Name string `json:"name"`
}
var _ Operation = (*OpDropIndex)(nil)
func (o *OpDropIndex) Start(ctx context.Context, conn *sql.DB, stateSchema string, s *schema.Schema, cbs ...CallbackFn) error {

View File

@ -22,9 +22,9 @@ func TestDropIndex(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",

View File

@ -11,10 +11,6 @@ import (
"github.com/xataio/pgroll/pkg/schema"
)
type OpDropTable struct {
Name string `json:"name"`
}
var _ Operation = (*OpDropTable)(nil)
func (o *OpDropTable) Start(ctx context.Context, conn *sql.DB, stateSchema string, s *schema.Schema, cbs ...CallbackFn) error {

View File

@ -22,9 +22,9 @@ func TestDropTable(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",

View File

@ -11,11 +11,6 @@ import (
var _ Operation = (*OpRawSQL)(nil)
type OpRawSQL struct {
Up string `json:"up"`
Down string `json:"down,omitempty"`
}
func (o *OpRawSQL) Start(ctx context.Context, conn *sql.DB, stateSchema string, s *schema.Schema, cbs ...CallbackFn) error {
_, err := conn.ExecContext(ctx, o.Up)
if err != nil {

View File

@ -23,9 +23,9 @@ func TestRenameColumn(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "username",

View File

@ -13,11 +13,6 @@ import (
var _ Operation = (*OpRenameTable)(nil)
type OpRenameTable struct {
From string `json:"from"`
To string `json:"to"`
}
func (o *OpRenameTable) Start(ctx context.Context, conn *sql.DB, stateSchema string, s *schema.Schema, cbs ...CallbackFn) error {
return s.RenameTable(o.From, o.To)
}

View File

@ -23,9 +23,9 @@ func TestSetCheckConstraint(t *testing.T) {
Name: "posts",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "title",
@ -148,9 +148,9 @@ func TestSetCheckConstraintValidation(t *testing.T) {
Name: "posts",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "title",

View File

@ -23,9 +23,9 @@ func TestSetForeignKey(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -37,9 +37,9 @@ func TestSetForeignKey(t *testing.T) {
Name: "posts",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "title",
@ -183,9 +183,9 @@ func TestSetForeignKeyValidation(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -197,9 +197,9 @@ func TestSetForeignKeyValidation(t *testing.T) {
Name: "posts",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "title",

View File

@ -24,9 +24,9 @@ func TestSetNotNull(t *testing.T) {
Name: "reviews",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "username",
@ -166,9 +166,9 @@ func TestSetNotNull(t *testing.T) {
Name: "reviews",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "username",
@ -235,9 +235,9 @@ func TestSetNotNullValidation(t *testing.T) {
Name: "reviews",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "username",
@ -288,9 +288,9 @@ func TestSetNotNullValidation(t *testing.T) {
Name: "reviews",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "username",

View File

@ -13,16 +13,6 @@ import (
"github.com/xataio/pgroll/pkg/schema"
)
type OpSetReplicaIdentity struct {
Table string `json:"table"`
Identity ReplicaIdentity `json:"identity"`
}
type ReplicaIdentity struct {
Type string `json:"type"`
Index string `json:"index"`
}
var _ Operation = (*OpSetReplicaIdentity)(nil)
func (o *OpSetReplicaIdentity) Start(ctx context.Context, conn *sql.DB, stateSchema string, s *schema.Schema, cbs ...CallbackFn) error {

View File

@ -19,9 +19,9 @@ func TestSetReplicaIdentity(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",
@ -150,9 +150,9 @@ func TestSetReplicaIdentityValidation(t *testing.T) {
Name: "users",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "name",

View File

@ -24,9 +24,9 @@ func TestSetColumnUnique(t *testing.T) {
Name: "reviews",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "username",
@ -125,9 +125,9 @@ func TestSetColumnUnique(t *testing.T) {
Name: "reviews",
Columns: []migrations.Column{
{
Name: "id",
Type: "serial",
PrimaryKey: true,
Name: "id",
Type: "serial",
Pk: true,
},
{
Name: "username",

211
pkg/migrations/types.go Normal file
View File

@ -0,0 +1,211 @@
// SPDX-License-Identifier: Apache-2.0
// Code generated by github.com/atombender/go-jsonschema, DO NOT EDIT.
package migrations
// Check constraint definition
type CheckConstraint struct {
// Constraint expression
Constraint string `json:"constraint"`
// Name of check constraint
Name string `json:"name"`
}
// Column definition
type Column struct {
// Check constraint for the column
Check *CheckConstraint `json:"check,omitempty"`
// Default value for the column
Default *string `json:"default,omitempty"`
// Name of the column
Name string `json:"name"`
// Indicates if the column is nullable
Nullable bool `json:"nullable"`
// Indicates if the column is part of the primary key
Pk bool `json:"pk"`
// Foreign key constraint for the column
References *ForeignKeyReference `json:"references,omitempty"`
// Postgres type of the column
Type string `json:"type"`
// Indicates if the column values must be unique
Unique bool `json:"unique"`
}
// Foreign key reference definition
type ForeignKeyReference struct {
// Name of the referenced column
Column string `json:"column"`
// Name of the foreign key constraint
Name string `json:"name"`
// Name of the referenced table
Table string `json:"table"`
}
// Add column operation
type OpAddColumn struct {
// Column to add
Column Column `json:"column"`
// Name of the table
Table string `json:"table"`
// SQL expression for up migration
Up *string `json:"up,omitempty"`
}
// Alter column operation
type OpAlterColumn struct {
// Add check constraint to the column
Check *CheckConstraint `json:"check,omitempty"`
// Name of the column
Column string `json:"column"`
// SQL expression for down migration
Down string `json:"down"`
// New name of the column (for rename column operation)
Name string `json:"name"`
// Indicates if the column is nullable (for add not null constraint operation)
Nullable *bool `json:"nullable,omitempty"`
// Add foreign key constraint to the column
References *ForeignKeyReference `json:"references,omitempty"`
// Name of the table
Table string `json:"table"`
// New type of the column (for change type operation)
Type string `json:"type"`
// Add unique constraint to the column
Unique *UniqueConstraint `json:"unique,omitempty"`
// SQL expression for up migration
Up string `json:"up"`
}
// Create index operation
type OpCreateIndex struct {
// Names of columns on which to define the index
Columns []string `json:"columns"`
// Index name
Name string `json:"name"`
// Name of table on which to define the index
Table string `json:"table"`
}
// Create table operation
type OpCreateTable struct {
// Columns corresponds to the JSON schema field "columns".
Columns []Column `json:"columns"`
// Name of the table
Name string `json:"name"`
}
// Drop column operation
type OpDropColumn struct {
// Name of the column
Column string `json:"column"`
// SQL expression for down migration
Down *string `json:"down,omitempty"`
// Name of the table
Table string `json:"table"`
}
// Drop constraint operation
type OpDropConstraint struct {
// Name of the column
Column string `json:"column"`
// SQL expression for down migration
Down string `json:"down"`
// Name of the constraint
Name string `json:"name"`
// Name of the table
Table string `json:"table"`
// SQL expression for up migration
Up string `json:"up"`
}
// Drop index operation
type OpDropIndex struct {
// Index name
Name string `json:"name"`
}
// Drop table operation
type OpDropTable struct {
// Name of the table
Name string `json:"name"`
}
// Raw SQL operation
type OpRawSQL struct {
// SQL expression for down migration
Down string `json:"down,omitempty"`
// SQL expression for up migration
Up string `json:"up"`
}
// Rename table operation
type OpRenameTable struct {
// Old name of the table
From string `json:"from"`
// New name of the table
To string `json:"to"`
}
// Set replica identity operation
type OpSetReplicaIdentity struct {
// Replica identity to set
Identity ReplicaIdentity `json:"identity"`
// Name of the table
Table string `json:"table"`
}
// PgRoll migration definition
type PgRollMigration struct {
// Name of the migration
Name string `json:"name"`
// Operations corresponds to the JSON schema field "operations".
Operations []interface{} `json:"operations"`
}
// Replica identity definition
type ReplicaIdentity struct {
// Name of the index to use as replica identity
Index string `json:"index"`
// Type of replica identity
Type string `json:"type"`
}
// Unique constraint definition
type UniqueConstraint struct {
// Name of unique constraint
Name string `json:"name"`
}

View File

@ -2,10 +2,6 @@
package migrations
type UniqueConstraint struct {
Name string `json:"name"`
}
func (c *UniqueConstraint) Validate() error {
if c.Name == "" {
return FieldRequiredError{Name: "name"}

View File

@ -466,9 +466,9 @@ func createTableOp(tableName string) *migrations.OpCreateTable {
Name: tableName,
Columns: []migrations.Column{
{
Name: "id",
Type: "integer",
PrimaryKey: true,
Name: "id",
Type: "integer",
Pk: true,
},
{
Name: "name",

407
schema.json Normal file
View File

@ -0,0 +1,407 @@
{
"$id": "https://raw.githubusercontent.com/xataio/pgroll/main/schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "JSON Schema for pgroll migrations",
"description": "This JSON schema defines the structure and properties of pgroll migrations.",
"allOf": [{ "$ref": "#/$defs/PgRollMigration" }],
"$defs": {
"CheckConstraint": {
"additionalProperties": false,
"description": "Check constraint definition",
"properties": {
"constraint": {
"description": "Constraint expression",
"type": "string"
},
"name": {
"description": "Name of check constraint",
"type": "string"
}
},
"required": ["constraint", "name"],
"type": "object"
},
"Column": {
"additionalProperties": false,
"description": "Column definition",
"properties": {
"check": {
"$ref": "#/$defs/CheckConstraint",
"description": "Check constraint for the column"
},
"default": {
"description": "Default value for the column",
"type": "string"
},
"name": {
"description": "Name of the column",
"type": "string"
},
"nullable": {
"description": "Indicates if the column is nullable",
"type": "boolean"
},
"pk": {
"description": "Indicates if the column is part of the primary key",
"type": "boolean"
},
"references": {
"$ref": "#/$defs/ForeignKeyReference",
"description": "Foreign key constraint for the column"
},
"type": {
"description": "Postgres type of the column",
"type": "string"
},
"unique": {
"description": "Indicates if the column values must be unique",
"type": "boolean"
}
},
"required": ["name", "nullable", "pk", "type", "unique"],
"type": "object"
},
"ForeignKeyReference": {
"additionalProperties": false,
"description": "Foreign key reference definition",
"properties": {
"column": {
"description": "Name of the referenced column",
"type": "string"
},
"name": {
"description": "Name of the foreign key constraint",
"type": "string"
},
"table": {
"description": "Name of the referenced table",
"type": "string"
}
},
"required": ["column", "name", "table"],
"type": "object"
},
"OpAddColumn": {
"additionalProperties": false,
"description": "Add column operation",
"properties": {
"column": {
"$ref": "#/$defs/Column",
"description": "Column to add"
},
"table": {
"description": "Name of the table",
"type": "string"
},
"up": {
"description": "SQL expression for up migration",
"type": "string"
}
},
"required": ["column", "table"],
"type": "object"
},
"OpAlterColumn": {
"additionalProperties": false,
"description": "Alter column operation",
"properties": {
"check": {
"$ref": "#/$defs/CheckConstraint",
"description": "Add check constraint to the column"
},
"column": {
"description": "Name of the column",
"type": "string"
},
"down": {
"description": "SQL expression for down migration",
"type": "string"
},
"name": {
"description": "New name of the column (for rename column operation)",
"type": "string"
},
"nullable": {
"description": "Indicates if the column is nullable (for add not null constraint operation)",
"type": "boolean"
},
"references": {
"$ref": "#/$defs/ForeignKeyReference",
"description": "Add foreign key constraint to the column"
},
"table": {
"description": "Name of the table",
"type": "string"
},
"type": {
"description": "New type of the column (for change type operation)",
"type": "string"
},
"unique": {
"$ref": "#/$defs/UniqueConstraint",
"description": "Add unique constraint to the column"
},
"up": {
"description": "SQL expression for up migration",
"type": "string"
}
},
"required": ["column", "down", "name", "table", "type", "up"],
"type": "object"
},
"OpCreateIndex": {
"additionalProperties": false,
"description": "Create index operation",
"properties": {
"columns": {
"description": "Names of columns on which to define the index",
"items": {
"type": "string"
},
"type": "array"
},
"name": {
"description": "Index name",
"type": "string"
},
"table": {
"description": "Name of table on which to define the index",
"type": "string"
}
},
"required": ["columns", "name", "table"],
"type": "object"
},
"OpCreateTable": {
"additionalProperties": false,
"description": "Create table operation",
"properties": {
"columns": {
"items": {
"$ref": "#/$defs/Column",
"description": "Columns to add to the table"
},
"type": "array"
},
"name": {
"description": "Name of the table",
"type": "string"
}
},
"required": ["columns", "name"],
"type": "object"
},
"OpDropColumn": {
"additionalProperties": false,
"description": "Drop column operation",
"properties": {
"column": {
"description": "Name of the column",
"type": "string"
},
"down": {
"description": "SQL expression for down migration",
"type": "string"
},
"table": {
"description": "Name of the table",
"type": "string"
}
},
"required": ["column", "table"],
"type": "object"
},
"OpDropConstraint": {
"additionalProperties": false,
"description": "Drop constraint operation",
"properties": {
"column": {
"description": "Name of the column",
"type": "string"
},
"down": {
"description": "SQL expression for down migration",
"type": "string"
},
"name": {
"description": "Name of the constraint",
"type": "string"
},
"table": {
"description": "Name of the table",
"type": "string"
},
"up": {
"description": "SQL expression for up migration",
"type": "string"
}
},
"required": ["column", "down", "name", "table", "up"],
"type": "object"
},
"OpDropIndex": {
"additionalProperties": false,
"description": "Drop index operation",
"properties": {
"name": {
"description": "Index name",
"type": "string"
}
},
"required": ["name"],
"type": "object"
},
"OpDropTable": {
"additionalProperties": false,
"description": "Drop table operation",
"properties": {
"name": {
"description": "Name of the table",
"type": "string"
}
},
"required": ["name"],
"type": "object"
},
"OpRawSQL": {
"additionalProperties": false,
"description": "Raw SQL operation",
"properties": {
"down": {
"default": "",
"description": "SQL expression for down migration",
"type": "string"
},
"up": {
"description": "SQL expression for up migration",
"type": "string"
}
},
"required": ["up"],
"type": "object"
},
"OpRenameTable": {
"additionalProperties": false,
"description": "Rename table operation",
"properties": {
"from": {
"description": "Old name of the table",
"type": "string"
},
"to": {
"description": "New name of the table",
"type": "string"
}
},
"required": ["from", "to"],
"type": "object"
},
"OpSetReplicaIdentity": {
"additionalProperties": false,
"description": "Set replica identity operation",
"properties": {
"identity": {
"$ref": "#/$defs/ReplicaIdentity",
"description": "Replica identity to set"
},
"table": {
"description": "Name of the table",
"type": "string"
}
},
"required": ["identity", "table"],
"type": "object"
},
"PgRollMigration": {
"additionalProperties": false,
"description": "PgRoll migration definition",
"properties": {
"name": {
"description": "Name of the migration",
"type": "string"
},
"operations": {
"items": {
"anyOf": [
{
"$ref": "#/$defs/OpAddColumn",
"description": "Add column operation"
},
{
"$ref": "#/$defs/OpAlterColumn",
"description": "Alter column operation"
},
{
"$ref": "#/$defs/OpCreateIndex",
"description": "Create index operation"
},
{
"$ref": "#/$defs/OpCreateTable",
"description": "Create table operation"
},
{
"$ref": "#/$defs/OpDropColumn",
"description": "Drop column operation"
},
{
"$ref": "#/$defs/OpDropConstraint",
"description": "Drop constraint operation"
},
{
"$ref": "#/$defs/OpDropIndex",
"description": "Drop index operation"
},
{
"$ref": "#/$defs/OpDropTable",
"description": "Drop table operation"
},
{
"$ref": "#/$defs/OpRawSQL",
"description": "Raw SQL operation"
},
{
"$ref": "#/$defs/OpRenameTable",
"description": "Rename table operation"
},
{
"$ref": "#/$defs/OpSetReplicaIdentity",
"description": "Set replica identity operation"
}
]
},
"type": "array"
}
},
"required": ["name", "operations"],
"type": "object"
},
"ReplicaIdentity": {
"additionalProperties": false,
"description": "Replica identity definition",
"properties": {
"index": {
"description": "Name of the index to use as replica identity",
"type": "string"
},
"type": {
"description": "Type of replica identity",
"type": "string"
}
},
"required": ["index", "type"],
"type": "object"
},
"UniqueConstraint": {
"additionalProperties": false,
"description": "Unique constraint definition",
"properties": {
"name": {
"description": "Name of unique constraint",
"type": "string"
}
},
"required": ["name"],
"type": "object"
}
}
}