Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
476 changes: 476 additions & 0 deletions .golangci.yml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fmt: # Format code
.PHONY: lint
lint: # Lint code
@echo "Linting code..."
@golangci-lint run --timeout 5m
@golangci-lint run --timeout 5m --fix

.PHONY: install
install: # Install dependencies
Expand Down
2 changes: 2 additions & 0 deletions internal/dialect/dialect.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ func (d Dialect) GooseDialect() database.Dialect {
return database.DialectMySQL
case Postgres:
return database.DialectPostgres
case Unknown:
return database.DialectCustom
default:
return database.DialectCustom
}
Expand Down
2 changes: 1 addition & 1 deletion internal/parser/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package parser

import "regexp"

func ParseMigrationName(filename string) (tableName string, create bool) {
func ParseMigrationName(filename string) (string, bool) {
// Regex patterns for common migration styles
createPattern := regexp.MustCompile(`^create_(?P<table>[a-z0-9_]+?)(?:_table)?$`)
addColPattern := regexp.MustCompile(`^add_(?P<columns>[a-z0-9_]+?)_to_(?P<table>[a-z0-9_]+?)(?:_table)?$`)
Expand Down
2 changes: 1 addition & 1 deletion internal/util/util.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package util
package util //nolint:revive // Helper functions for general purposes.

func Optional[T any](defaultValue T, values ...T) T {
if len(values) > 0 {
Expand Down
24 changes: 24 additions & 0 deletions lefthook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pre-commit:
parallel: true
commands:
fmt:
glob: "*.go"
run: go fmt ./...

mod-tidy:
glob: "{go.mod,go.sum}"
run: go mod tidy

golangci-lint:
glob: "*.go"
run: golangci-lint run --fix --timeout 5m

commit-msg:
commands:
check-message:
run: |
if ! grep -qE "^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .+" {1}; then
echo "Commit message must follow conventional commits format"
echo "Example: feat: add new feature"
exit 1
fi
4 changes: 2 additions & 2 deletions migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import (
"github.com/pressly/goose/v3/database"
)

// Migrate handles database migrations
// Migrate handles database migrations.
type Migrate struct {
dialect dialect.Dialect
db *sql.DB
migrationDir string
tableName string
}

// New creates a new Migrate instance
// New creates a new Migrate instance.
func New(dialectValue string, opts ...Option) (*Migrate, error) {
dialectVal := dialect.FromString(dialectValue)
if dialectVal == dialect.Unknown {
Expand Down
84 changes: 48 additions & 36 deletions schema/blueprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ const (
columnTypeTimestampTz string = "timestampTz"
columnTypeYear string = "year"
columnTypeBinary string = "binary"
columnTypeJson string = "json"
columnTypeJsonb string = "jsonb"
columnTypeJSON string = "json"
columnTypeJSONB string = "jsonb"
columnTypeGeography string = "geography"
columnTypeGeometry string = "geometry"
columnTypePoint string = "point"
columnTypeUuid string = "uuid"
columnTypeUUID string = "uuid"
columnTypeEnum string = "enum"
)

Expand Down Expand Up @@ -305,17 +305,17 @@ func (b *Blueprint) Binary(name string, length ...int) ColumnDefinition {

// JSON creates a new JSON column definition in the blueprint.
func (b *Blueprint) JSON(name string) ColumnDefinition {
return b.addColumn(columnTypeJson, name)
return b.addColumn(columnTypeJSON, name)
}

// JSONB creates a new JSONB column definition in the blueprint.
func (b *Blueprint) JSONB(name string) ColumnDefinition {
return b.addColumn(columnTypeJsonb, name)
return b.addColumn(columnTypeJSONB, name)
}

// UUID creates a new UUID column definition in the blueprint.
func (b *Blueprint) UUID(name string) ColumnDefinition {
return b.addColumn(columnTypeUuid, name)
return b.addColumn(columnTypeUUID, name)
}

// Geography creates a new geography column definition in the blueprint.
Expand Down Expand Up @@ -541,33 +541,48 @@ func (b *Blueprint) addImpliedCommands() {

func (b *Blueprint) addFluentIndexes() {
for _, col := range b.columns {
if col.primary != nil {
if b.dialect == dialect.MySQL {
continue
}
if !*col.primary && col.change {
b.DropPrimary([]string{col.name})
col.primary = nil
}
skipped := b.addFluentIndexPrimary(col)
if skipped {
continue
}
if col.index != nil {
if *col.index {
b.Index(col.name).Name(col.indexName)
col.index = nil
} else if !*col.index && col.change {
b.DropIndex([]string{col.name})
col.index = nil
}
b.addFluentIndexIndex(col)
b.addFluentIndexUnique(col)
}
}

func (b *Blueprint) addFluentIndexPrimary(col *columnDefinition) bool {
if col.primary != nil {
if b.dialect == dialect.MySQL {
return true
}
if !*col.primary && col.change {
b.DropPrimary([]string{col.name})
col.primary = nil
}
}
return false
}

if col.unique != nil {
if *col.unique {
b.Unique(col.name).Name(col.uniqueName)
col.unique = nil
} else if !*col.unique && col.change {
b.DropUnique([]string{col.name})
col.unique = nil
}
func (b *Blueprint) addFluentIndexIndex(col *columnDefinition) {
if col.index != nil {
if *col.index {
b.Index(col.name).Name(col.indexName)
col.index = nil
} else if !*col.index && col.change {
b.DropIndex([]string{col.name})
col.index = nil
}
}
}

func (b *Blueprint) addFluentIndexUnique(col *columnDefinition) {
if col.unique != nil {
if *col.unique {
b.Unique(col.name).Name(col.uniqueName)
col.unique = nil
} else if !*col.unique && col.change {
b.DropUnique([]string{col.name})
col.unique = nil
}
}
}
Expand All @@ -585,22 +600,19 @@ func (b *Blueprint) getFluentStatements() []string {
}

func (b *Blueprint) build(ctx *Context) error {
statements, err := b.toSql()
statements, err := b.toSQL()
if err != nil {
return err
}
for _, statement := range statements {
// if b.verbose {
// log.Println(statement)
// }
if _, err := ctx.Exec(statement); err != nil {
if _, err = ctx.Exec(statement); err != nil {
return err
}
}
return nil
}

func (b *Blueprint) toSql() ([]string, error) {
func (b *Blueprint) toSQL() ([]string, error) {
b.addImpliedCommands()

var statements []string
Expand Down
2 changes: 2 additions & 0 deletions schema/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ func NewBuilder(dialectValue string) (Builder, error) {
return newMysqlBuilder(), nil
case dialect.Postgres:
return newPostgresBuilder(), nil
case dialect.Unknown:
return nil, errors.New("unsupported dialect: " + dialectValue)
default:
return nil, errors.New("unsupported dialect: " + dialectValue)
}
Expand Down
2 changes: 1 addition & 1 deletion schema/column_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type columnDefinition struct {
//
// Example:
//
// schema.Timestamp("created_at").Default(schema.Expression("CURRENT_TIMESTAMP"))
// schema.Timestamp("created_at").Default(schema.Expression("CURRENT_TIMESTAMP")).
type Expression string

func (e Expression) String() string {
Expand Down
3 changes: 2 additions & 1 deletion schema/grammar.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package schema

import (
"errors"
"fmt"
"slices"
"strings"
Expand Down Expand Up @@ -41,7 +42,7 @@ type baseGrammar struct{}
func (g *baseGrammar) CompileForeign(blueprint *Blueprint, command *command) (string, error) {
if len(command.columns) == 0 || slices.Contains(command.columns, "") || command.on == "" ||
len(command.references) == 0 || slices.Contains(command.references, "") {
return "", fmt.Errorf("foreign key definition is incomplete: column, on, and references must be set")
return "", errors.New("foreign key definition is incomplete: column, on, and references must be set")
}
onDelete := ""
if command.onDelete != "" {
Expand Down
27 changes: 20 additions & 7 deletions schema/mysql_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@
if err != nil {
return nil, err
}
defer rows.Close() //nolint:errcheck
defer rows.Close()

var columns []*Column
for rows.Next() {
var col Column
var nullableStr string
if err := rows.Scan(
if err = rows.Scan(
&col.Name, &col.TypeName, &col.TypeFull,
&col.Collation, &nullableStr,
&col.DefaultVal, &col.Comment,
Expand All @@ -53,6 +53,10 @@
}
columns = append(columns, &col)
}
if err = rows.Err(); err != nil {
return nil, err
}

return columns, nil
}

Expand All @@ -70,18 +74,22 @@
if err != nil {
return nil, err
}
defer rows.Close() //nolint:errcheck
defer rows.Close()

var indexes []*Index
for rows.Next() {
var idx Index
var columnsStr string
if err := rows.Scan(&idx.Name, &columnsStr, &idx.Type, &idx.Unique); err != nil {
if err = rows.Scan(&idx.Name, &columnsStr, &idx.Type, &idx.Unique); err != nil {
return nil, err
}
idx.Columns = strings.Split(columnsStr, ",")
indexes = append(indexes, &idx)
}
if err = rows.Err(); err != nil {
return nil, err
}

return indexes, nil
}

Expand All @@ -98,16 +106,20 @@
if err != nil {
return nil, err
}
defer rows.Close() //nolint:errcheck
defer rows.Close()

var tables []*TableInfo
for rows.Next() {
var table TableInfo
if err := rows.Scan(&table.Name, &table.Size, &table.Comment, &table.Engine, &table.Collation); err != nil {
if err = rows.Scan(&table.Name, &table.Size, &table.Comment, &table.Engine, &table.Collation); err != nil {
return nil, err
}
tables = append(tables, &table)
}
if err = rows.Err(); err != nil {
return nil, err
}

return tables, nil
}

Expand Down Expand Up @@ -142,6 +154,7 @@
return true, nil // All specified columns exist
}

// nolint: dupl,godoclint // Similar code exists in other builder files

Check failure on line 157 in schema/mysql_builder.go

View workflow job for this annotation

GitHub Actions / lint

directive `// nolint: dupl,godoclint // Similar code exists in other builder files` should be written without leading space as `//nolint: dupl,godoclint // Similar code exists in other builder files` (nolintlint)
func (b *mysqlBuilder) HasIndex(c *Context, tableName string, indexes []string) (bool, error) {
if c == nil || tableName == "" {
return false, errors.New("invalid arguments: context is nil or table name is empty")
Expand Down Expand Up @@ -198,7 +211,7 @@

row := c.QueryRow(query)
var exists bool
if err := row.Scan(&exists); err != nil {
if err = row.Scan(&exists); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return false, nil // Table does not exist
}
Expand Down
Loading
Loading