|
|
|
|
@@ -8,6 +8,7 @@ import (
|
|
|
|
|
|
|
|
|
|
"git.ksdemosapps.com/kylesoda/go-migrate/internal/app/config"
|
|
|
|
|
dbwrapper "git.ksdemosapps.com/kylesoda/go-migrate/internal/app/db-wrapper"
|
|
|
|
|
db_dialects "git.ksdemosapps.com/kylesoda/go-migrate/internal/app/db-wrapper/db_dialects"
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@@ -32,26 +33,53 @@ func countSourceRows(ctx context.Context, db dbwrapper.DbWrapper, job config.Job
|
|
|
|
|
args []any
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if hasRange && job.SourceTable.PrimaryKey != "" {
|
|
|
|
|
query = fmt.Sprintf("SELECT COUNT_BIG(*) FROM [%s].[%s] WHERE 1=1", schema, table)
|
|
|
|
|
if job.Range.Min != nil {
|
|
|
|
|
op := ">"
|
|
|
|
|
if job.Range.IsMinInclusive {
|
|
|
|
|
op = ">="
|
|
|
|
|
if db.GetDialect() == db_dialects.Postgres {
|
|
|
|
|
if hasRange && job.SourceTable.PrimaryKey != "" {
|
|
|
|
|
query = fmt.Sprintf(`SELECT COUNT(*) FROM "%s"."%s" WHERE 1=1`, schema, table)
|
|
|
|
|
paramIdx := 0
|
|
|
|
|
if job.Range.Min != nil {
|
|
|
|
|
paramIdx++
|
|
|
|
|
op := ">"
|
|
|
|
|
if job.Range.IsMinInclusive {
|
|
|
|
|
op = ">="
|
|
|
|
|
}
|
|
|
|
|
query += fmt.Sprintf(` AND "%s" %s $%d`, job.SourceTable.PrimaryKey, op, paramIdx)
|
|
|
|
|
args = append(args, *job.Range.Min)
|
|
|
|
|
}
|
|
|
|
|
query += fmt.Sprintf(" AND [%s] %s @min", job.SourceTable.PrimaryKey, op)
|
|
|
|
|
args = append(args, sql.Named("min", *job.Range.Min))
|
|
|
|
|
}
|
|
|
|
|
if job.Range.Max != nil {
|
|
|
|
|
op := "<"
|
|
|
|
|
if job.Range.IsMaxInclusive {
|
|
|
|
|
op = "<="
|
|
|
|
|
if job.Range.Max != nil {
|
|
|
|
|
paramIdx++
|
|
|
|
|
op := "<"
|
|
|
|
|
if job.Range.IsMaxInclusive {
|
|
|
|
|
op = "<="
|
|
|
|
|
}
|
|
|
|
|
query += fmt.Sprintf(` AND "%s" %s $%d`, job.SourceTable.PrimaryKey, op, paramIdx)
|
|
|
|
|
args = append(args, *job.Range.Max)
|
|
|
|
|
}
|
|
|
|
|
query += fmt.Sprintf(" AND [%s] %s @max", job.SourceTable.PrimaryKey, op)
|
|
|
|
|
args = append(args, sql.Named("max", *job.Range.Max))
|
|
|
|
|
} else {
|
|
|
|
|
query = fmt.Sprintf(`SELECT COUNT(*) FROM "%s"."%s"`, schema, table)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
query = fmt.Sprintf("SELECT COUNT_BIG(*) FROM [%s].[%s]", schema, table)
|
|
|
|
|
if hasRange && job.SourceTable.PrimaryKey != "" {
|
|
|
|
|
query = fmt.Sprintf("SELECT COUNT_BIG(*) FROM [%s].[%s] WHERE 1=1", schema, table)
|
|
|
|
|
if job.Range.Min != nil {
|
|
|
|
|
op := ">"
|
|
|
|
|
if job.Range.IsMinInclusive {
|
|
|
|
|
op = ">="
|
|
|
|
|
}
|
|
|
|
|
query += fmt.Sprintf(" AND [%s] %s @min", job.SourceTable.PrimaryKey, op)
|
|
|
|
|
args = append(args, sql.Named("min", *job.Range.Min))
|
|
|
|
|
}
|
|
|
|
|
if job.Range.Max != nil {
|
|
|
|
|
op := "<"
|
|
|
|
|
if job.Range.IsMaxInclusive {
|
|
|
|
|
op = "<="
|
|
|
|
|
}
|
|
|
|
|
query += fmt.Sprintf(" AND [%s] %s @max", job.SourceTable.PrimaryKey, op)
|
|
|
|
|
args = append(args, sql.Named("max", *job.Range.Max))
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
query = fmt.Sprintf("SELECT COUNT_BIG(*) FROM [%s].[%s]", schema, table)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var count int64
|
|
|
|
|
@@ -64,7 +92,13 @@ func countSourceRows(ctx context.Context, db dbwrapper.DbWrapper, job config.Job
|
|
|
|
|
func countTargetRows(ctx context.Context, db dbwrapper.DbWrapper, job config.Job) (int64, error) {
|
|
|
|
|
schema := job.TargetTable.Schema
|
|
|
|
|
table := job.TargetTable.Table
|
|
|
|
|
query := fmt.Sprintf(`SELECT COUNT(*) FROM "%s"."%s"`, schema, table)
|
|
|
|
|
|
|
|
|
|
var query string
|
|
|
|
|
if db.GetDialect() == db_dialects.Postgres {
|
|
|
|
|
query = fmt.Sprintf(`SELECT COUNT(*) FROM "%s"."%s"`, schema, table)
|
|
|
|
|
} else {
|
|
|
|
|
query = fmt.Sprintf("SELECT COUNT_BIG(*) FROM [%s].[%s]", schema, table)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var count int64
|
|
|
|
|
if err := db.QueryRow(ctx, query).Scan(&count); err != nil {
|
|
|
|
|
@@ -74,10 +108,22 @@ func countTargetRows(ctx context.Context, db dbwrapper.DbWrapper, job config.Job
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func validateJob(ctx context.Context, sourceDb, targetDb dbwrapper.DbWrapper, job config.Job) ValidationResult {
|
|
|
|
|
var sourceTable, targetTable string
|
|
|
|
|
if sourceDb.GetDialect() == db_dialects.Postgres {
|
|
|
|
|
sourceTable = fmt.Sprintf(`"%s"."%s"`, job.SourceTable.Schema, job.SourceTable.Table)
|
|
|
|
|
} else {
|
|
|
|
|
sourceTable = fmt.Sprintf("[%s].[%s]", job.SourceTable.Schema, job.SourceTable.Table)
|
|
|
|
|
}
|
|
|
|
|
if targetDb.GetDialect() == db_dialects.Postgres {
|
|
|
|
|
targetTable = fmt.Sprintf(`"%s"."%s"`, job.TargetTable.Schema, job.TargetTable.Table)
|
|
|
|
|
} else {
|
|
|
|
|
targetTable = fmt.Sprintf("[%s].[%s]", job.TargetTable.Schema, job.TargetTable.Table)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result := ValidationResult{
|
|
|
|
|
JobName: job.Name,
|
|
|
|
|
SourceTable: fmt.Sprintf("[%s].[%s]", job.SourceTable.Schema, job.SourceTable.Table),
|
|
|
|
|
TargetTable: fmt.Sprintf(`"%s"."%s"`, job.TargetTable.Schema, job.TargetTable.Table),
|
|
|
|
|
SourceTable: sourceTable,
|
|
|
|
|
TargetTable: targetTable,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
|