diff --git a/.gitignore b/.gitignore index 8621e47b2..2476367dd 100644 --- a/.gitignore +++ b/.gitignore @@ -22,9 +22,17 @@ dist/ .secrets .DS_Store demo/sling_commands_demo.workflow -demo/sling.demo.2023.10.screenstudio +*.screenstudio ./sling core/dbio/filesys/test/dataset1M.csv core/dbio/filesys/test/dataset100k.csv cmd/sling/tests/suite/ cmd/sling/tests/replications/r.test.yaml + +*..go + +appicon.png +wails.json + +cmd/sling/build/ +cmd/sling/frontend diff --git a/.goreleaser.linux.amd64.yaml b/.goreleaser.linux.amd64.yaml index c7631fdda..2e047c81d 100644 --- a/.goreleaser.linux.amd64.yaml +++ b/.goreleaser.linux.amd64.yaml @@ -5,6 +5,7 @@ project_name: sling before: hooks: - go mod edit -dropreplace='github.com/flarco/g' go.mod + - go mod edit -dropreplace='github.com/slingdata-io/sling' go.mod - go mod tidy # you may remove this if you don't need go generate - go generate ./... diff --git a/.goreleaser.linux.arm64.yaml b/.goreleaser.linux.arm64.yaml index 4e48b91ee..d4646f0b3 100644 --- a/.goreleaser.linux.arm64.yaml +++ b/.goreleaser.linux.arm64.yaml @@ -5,6 +5,7 @@ project_name: sling before: hooks: - go mod edit -dropreplace='github.com/flarco/g' go.mod + - go mod edit -dropreplace='github.com/slingdata-io/sling' go.mod - go mod tidy # you may remove this if you don't need go generate - go generate ./... diff --git a/.goreleaser.mac.yaml b/.goreleaser.mac.yaml index 345dcf047..9c79b12a5 100644 --- a/.goreleaser.mac.yaml +++ b/.goreleaser.mac.yaml @@ -5,6 +5,7 @@ project_name: sling before: hooks: - go mod edit -dropreplace='github.com/flarco/g' go.mod + - go mod edit -dropreplace='github.com/slingdata-io/sling' go.mod - go mod tidy # you may remove this if you don't need go generate - go generate ./... diff --git a/.goreleaser.windows.yaml b/.goreleaser.windows.yaml index 309dd2613..2f24a340a 100644 --- a/.goreleaser.windows.yaml +++ b/.goreleaser.windows.yaml @@ -5,6 +5,7 @@ project_name: sling before: hooks: - go mod edit -dropreplace='github.com/flarco/g' go.mod + - go mod edit -dropreplace='github.com/slingdata-io/sling' go.mod - go mod tidy # you may remove this if you don't need go generate - go generate ./... diff --git a/cmd/sling/sling_cli.go b/cmd/sling/sling_cli.go index a49531235..41f9502ef 100755 --- a/cmd/sling/sling_cli.go +++ b/cmd/sling/sling_cli.go @@ -18,6 +18,7 @@ import ( "github.com/slingdata-io/sling-cli/core" "github.com/slingdata-io/sling-cli/core/env" "github.com/slingdata-io/sling-cli/core/sling" + "github.com/slingdata-io/sling-cli/core/store" "github.com/flarco/g" "github.com/flarco/g/net" @@ -26,7 +27,7 @@ import ( "github.com/spf13/cast" ) -//go:embed * +//go:embed examples.sh var slingFolder embed.FS var examples = `` var ctx = g.NewContext(context.Background()) @@ -36,6 +37,7 @@ var machineID = "" func init() { env.InitLogger() + store.InitDB() } var cliRunFlags = []g.Flag{ @@ -330,14 +332,9 @@ func init() { examplesBytes, _ := slingFolder.ReadFile("examples.sh") examples = string(examplesBytes) - // cliInteractive.Make().Add() - // cliAuth.Make().Add() - // cliCloud.Make().Add() cliConns.Make().Add() - // cliProject.Make().Add() cliRun.Make().Add() cliUpdate.Make().Add() - // cliUi.Make().Add() if telemetry { if projectID == "" { @@ -413,43 +410,44 @@ func main() { sling.ShowProgress = os.Getenv("SLING_SHOW_PROGRESS") != "false" database.UseBulkExportFlowCSV = cast.ToBool(os.Getenv("SLING_BULK_EXPORT_FLOW_CSV")) - go func() { - defer close(done) - exitCode = cliInit() - if !interrupted { - g.SentryFlush(time.Second * 2) - } - }() - exit := func() { time.Sleep(50 * time.Millisecond) // so logger can flush os.Exit(exitCode) } - select { - case <-done: - exit() - case <-kill: - env.Println("\nkilling process...") - exitCode = 111 - exit() - case <-interrupt: - g.SentryClear() - if cliRun.Sc.Used { - env.Println("\ninterrupting...") - interrupted = true - ctx.Cancel() - select { - case <-done: - case <-time.After(5 * time.Second): + go func() { + select { + case <-kill: + env.Println("\nkilling process...") + exitCode = 111 + exit() + case <-interrupt: + g.SentryClear() + if cliRun.Sc.Used { + env.Println("\ninterrupting...") + interrupted = true + ctx.Cancel() + select { + case <-done: + case <-time.After(5 * time.Second): + } } + exit() + return + case <-done: + exit() } - exit() - return + }() + + exitCode = cliInit(done) + if !interrupted { + g.SentryFlush(time.Second * 2) } + time.Sleep(50 * time.Millisecond) // so logger can flush } -func cliInit() int { +func cliInit(done chan struct{}) int { + defer close(done) // recover from panic defer func() { diff --git a/cmd/sling/sling_conns.go b/cmd/sling/sling_conns.go new file mode 100644 index 000000000..d5c997a2c --- /dev/null +++ b/cmd/sling/sling_conns.go @@ -0,0 +1,276 @@ +package main + +import ( + "fmt" + "os" + "sort" + "strings" + "time" + + "github.com/dustin/go-humanize" + "github.com/flarco/g" + "github.com/integrii/flaggy" + "github.com/samber/lo" + "github.com/slingdata-io/sling-cli/core/dbio" + "github.com/slingdata-io/sling-cli/core/dbio/connection" + "github.com/slingdata-io/sling-cli/core/dbio/database" + "github.com/slingdata-io/sling-cli/core/dbio/iop" + "github.com/slingdata-io/sling-cli/core/env" + "github.com/slingdata-io/sling-cli/core/sling" + "github.com/spf13/cast" +) + +func processConns(c *g.CliSC) (ok bool, err error) { + ok = true + + ef := env.LoadSlingEnvFile() + ec := connection.EnvConns{EnvFile: &ef} + asJSON := os.Getenv("SLING_OUTPUT") == "json" + + env.SetTelVal("task_start_time", time.Now()) + defer func() { + env.SetTelVal("task_status", lo.Ternary(err != nil, "error", "success")) + env.SetTelVal("task_end_time", time.Now()) + }() + + switch c.UsedSC() { + case "unset": + name := strings.ToUpper(cast.ToString(c.Vals["name"])) + if name == "" { + flaggy.ShowHelp("") + return ok, nil + } + + err := ec.Unset(name) + if err != nil { + return ok, g.Error(err, "could not unset %s", name) + } + g.Info("connection `%s` has been removed from %s", name, ec.EnvFile.Path) + case "set": + if len(c.Vals) == 0 { + flaggy.ShowHelp("") + return ok, nil + } + + kvArr := []string{cast.ToString(c.Vals["value properties..."])} + kvMap := map[string]interface{}{} + for k, v := range g.KVArrToMap(append(kvArr, flaggy.TrailingArguments...)...) { + k = strings.ToLower(k) + kvMap[k] = v + } + name := strings.ToUpper(cast.ToString(c.Vals["name"])) + + err := ec.Set(name, kvMap) + if err != nil { + return ok, g.Error(err, "could not set %s (See https://docs.slingdata.io/sling-cli/environment)", name) + } + g.Info("connection `%s` has been set in %s. Please test with `sling conns test %s`", name, ec.EnvFile.Path, name) + case "exec": + env.SetTelVal("task", g.Marshal(g.M("type", sling.ConnExec))) + + name := cast.ToString(c.Vals["name"]) + conn, ok := ec.GetConnEntry(name) + if !ok { + return ok, g.Error("did not find connection %s", name) + } + + env.SetTelVal("conn_type", conn.Connection.Type.String()) + + if !conn.Connection.Type.IsDb() { + return ok, g.Error("cannot execute SQL query on a non-database connection (%s)", conn.Connection.Type) + } + + start := time.Now() + dbConn, err := conn.Connection.AsDatabase() + if err != nil { + return ok, g.Error(err, "cannot create database connection (%s)", conn.Connection.Type) + } + + err = dbConn.Connect() + if err != nil { + return ok, g.Error(err, "cannot connect to database (%s)", conn.Connection.Type) + } + + queries := append([]string{cast.ToString(c.Vals["queries..."])}, flaggy.TrailingArguments...) + + var totalAffected int64 + for i, query := range queries { + + query, err = sling.GetSQLText(query) + if err != nil { + return ok, g.Error(err, "cannot get query") + } + + sQuery, err := database.ParseTableName(query, conn.Connection.Type) + if err != nil { + return ok, g.Error(err, "cannot parse query") + } + + if len(database.ParseSQLMultiStatements(query)) == 1 && (!sQuery.IsQuery() || strings.Contains(query, "select") || g.In(conn.Connection.Type, dbio.TypeDbPrometheus, dbio.TypeDbMongoDB)) { + + data, err := dbConn.Query(sQuery.Select(100)) + if err != nil { + return ok, g.Error(err, "cannot execute query") + } + + if asJSON { + fmt.Println(g.Marshal(g.M("fields", data.GetFields(), "rows", data.Rows))) + } else { + fmt.Println(g.PrettyTable(data.GetFields(), data.Rows)) + } + + totalAffected = cast.ToInt64(len(data.Rows)) + } else { + if len(queries) > 1 { + if strings.HasPrefix(query, "file://") { + g.Info("executing query #%d (%s)", i+1, query) + } else { + g.Info("executing query #%d", i+1) + } + } else { + g.Info("executing query") + } + + result, err := dbConn.ExecMulti(query) + if err != nil { + return ok, g.Error(err, "cannot execute query") + } + + affected, _ := result.RowsAffected() + totalAffected = totalAffected + affected + } + } + + end := time.Now() + if totalAffected > 0 { + g.Info("successful! duration: %d seconds (%d affected records)", end.Unix()-start.Unix(), totalAffected) + } else { + g.Info("successful! duration: %d seconds.", end.Unix()-start.Unix()) + } + + if err := testRowCnt(totalAffected); err != nil { + return ok, err + } + + case "list": + fields, rows := ec.List() + if asJSON { + fmt.Println(g.Marshal(g.M("fields", fields, "rows", rows))) + } else { + fmt.Println(g.PrettyTable(fields, rows)) + } + + case "test": + env.SetTelVal("task", g.Marshal(g.M("type", sling.ConnTest))) + name := cast.ToString(c.Vals["name"]) + if conn, ok := ec.GetConnEntry(name); ok { + env.SetTelVal("conn_type", conn.Connection.Type.String()) + env.SetTelVal("conn_keys", lo.Keys(conn.Connection.Data)) + } + + ok, err = ec.Test(name) + if err != nil { + return ok, g.Error(err, "could not test %s (See https://docs.slingdata.io/sling-cli/environment)", name) + } else if ok { + g.Info("success!") // successfully connected + } + case "discover": + env.SetTelVal("task", g.Marshal(g.M("type", sling.ConnDiscover))) + name := cast.ToString(c.Vals["name"]) + conn, ok := ec.GetConnEntry(name) + if ok { + env.SetTelVal("conn_type", conn.Connection.Type.String()) + } + + opt := &connection.DiscoverOptions{ + Pattern: cast.ToString(c.Vals["pattern"]), + ColumnLevel: cast.ToBool(c.Vals["columns"]), + Recursive: cast.ToBool(c.Vals["recursive"]), + } + + files, schemata, err := ec.Discover(name, opt) + if err != nil { + return ok, g.Error(err, "could not discover %s (See https://docs.slingdata.io/sling-cli/environment)", name) + } + + if tables := lo.Values(schemata.Tables()); len(tables) > 0 { + + sort.Slice(tables, func(i, j int) bool { + val := func(t database.Table) string { + return t.FDQN() + } + return val(tables[i]) < val(tables[j]) + }) + + if opt.ColumnLevel { + columns := iop.Columns(lo.Values(schemata.Columns())) + if asJSON { + fmt.Println(columns.JSON(true)) + } else { + fmt.Println(columns.PrettyTable(true)) + } + } else { + fields := []string{"#", "Schema", "Name", "Type", "Columns"} + rows := lo.Map(tables, func(table database.Table, i int) []any { + tableType := lo.Ternary(table.IsView, "view", "table") + if table.Dialect.DBNameUpperCase() { + tableType = strings.ToUpper(tableType) + } + return []any{i + 1, table.Schema, table.Name, tableType, len(table.Columns)} + }) + if asJSON { + fmt.Println(g.Marshal(g.M("fields", fields, "rows", rows))) + } else { + fmt.Println(g.PrettyTable(fields, rows)) + } + } + } else if len(files) > 0 { + if opt.ColumnLevel { + columns := iop.Columns(lo.Values(files.Columns())) + if asJSON { + fmt.Println(columns.JSON(true)) + } else { + fmt.Println(columns.PrettyTable(true)) + } + } else { + + files.Sort() + + fields := []string{"#", "Name", "Type", "Size", "Last Updated (UTC)"} + rows := lo.Map(files, func(file dbio.FileNode, i int) []any { + fileType := lo.Ternary(file.IsDir, "directory", "file") + + lastUpdated := "-" + if file.Updated > 100 { + updated := time.Unix(file.Updated, 0) + delta := strings.Split(g.DurationString(time.Since(updated)), " ")[0] + lastUpdated = g.F("%s (%s ago)", updated.UTC().Format("2006-01-02 15:04:05"), delta) + } + + size := "-" + if !file.IsDir || file.Size > 0 { + size = humanize.IBytes(file.Size) + } + + return []any{i + 1, file.Path(), fileType, size, lastUpdated} + }) + + if asJSON { + fmt.Println(g.Marshal(g.M("fields", fields, "rows", rows))) + } else { + fmt.Println(g.PrettyTable(fields, rows)) + } + + if len(files) > 0 && !(opt.Recursive || opt.Pattern != "") { + g.Info("Those are non-recursive folder or file names (at the root level). Please use the --pattern flag to list sub-folders, or --recursive") + } + } + } else { + g.Info("no result.") + } + + case "": + return false, nil + } + return ok, nil +} diff --git a/cmd/sling/sling_logic.go b/cmd/sling/sling_run.go similarity index 66% rename from cmd/sling/sling_logic.go rename to cmd/sling/sling_run.go index b952e65ce..eec3d0c7a 100755 --- a/cmd/sling/sling_logic.go +++ b/cmd/sling/sling_run.go @@ -1,29 +1,19 @@ package main import ( - "fmt" "os" "os/exec" "path" "path/filepath" "runtime/debug" - "sort" "strings" "time" - "github.com/dustin/go-humanize" - "github.com/integrii/flaggy" "github.com/samber/lo" "gopkg.in/yaml.v2" - "github.com/slingdata-io/sling-cli/core/dbio" - "github.com/slingdata-io/sling-cli/core/dbio/connection" - "github.com/slingdata-io/sling-cli/core/dbio/database" - "github.com/slingdata-io/sling-cli/core/dbio/iop" "github.com/slingdata-io/sling-cli/core/env" - dbioEnv "github.com/slingdata-io/sling-cli/core/env" "github.com/slingdata-io/sling-cli/core/sling" - "github.com/slingdata-io/sling-cli/core/store" "github.com/flarco/g" "github.com/spf13/cast" @@ -36,11 +26,6 @@ var ( rowCount = int64(0) ) -func init() { - // init sqlite - store.InitDB() -} - func processRun(c *g.CliSC) (ok bool, err error) { ok = true cfg := &sling.Config{} @@ -213,7 +198,7 @@ func processRun(c *g.CliSC) (ok bool, err error) { // run as replication is stream is wildcard if cfg.HasWildcard() { rc := cfg.AsReplication() - replicationCfgPath = path.Join(dbioEnv.GetTempFolder(), g.NewTsID("replication.temp")+".json") + replicationCfgPath = path.Join(env.GetTempFolder(), g.NewTsID("replication.temp")+".json") err = os.WriteFile(replicationCfgPath, []byte(g.Marshal(rc)), 0775) if err != nil { return ok, g.Error(err, "could not write temp replication: %s", replicationCfgPath) @@ -435,11 +420,11 @@ func runReplication(cfgPath string, cfgOverwrite *sling.Config, selectStreams .. } counter++ - stream := replication.Streams[name] - if stream == nil { - stream = &sling.ReplicationStreamConfig{} + stream := sling.ReplicationStreamConfig{} + if replication.Streams[name] != nil { + stream = *replication.Streams[name] } - sling.SetStreamDefaults(stream, replication) + sling.SetStreamDefaults(&stream, replication) if stream.Object == "" { return g.Error("need to specify `object`. Please see https://docs.slingdata.io/sling-cli for help.") @@ -530,267 +515,6 @@ func runReplication(cfgPath string, cfgOverwrite *sling.Config, selectStreams .. return eG.Err() } -func processConns(c *g.CliSC) (ok bool, err error) { - ok = true - - ef := env.LoadSlingEnvFile() - ec := connection.EnvConns{EnvFile: &ef} - asJSON := os.Getenv("SLING_OUTPUT") == "json" - - env.SetTelVal("task_start_time", time.Now()) - defer func() { - env.SetTelVal("task_status", lo.Ternary(err != nil, "error", "success")) - env.SetTelVal("task_end_time", time.Now()) - }() - - switch c.UsedSC() { - case "unset": - name := strings.ToUpper(cast.ToString(c.Vals["name"])) - if name == "" { - flaggy.ShowHelp("") - return ok, nil - } - - err := ec.Unset(name) - if err != nil { - return ok, g.Error(err, "could not unset %s", name) - } - g.Info("connection `%s` has been removed from %s", name, ec.EnvFile.Path) - case "set": - if len(c.Vals) == 0 { - flaggy.ShowHelp("") - return ok, nil - } - - kvArr := []string{cast.ToString(c.Vals["value properties..."])} - kvMap := map[string]interface{}{} - for k, v := range g.KVArrToMap(append(kvArr, flaggy.TrailingArguments...)...) { - k = strings.ToLower(k) - kvMap[k] = v - } - name := strings.ToUpper(cast.ToString(c.Vals["name"])) - - err := ec.Set(name, kvMap) - if err != nil { - return ok, g.Error(err, "could not set %s (See https://docs.slingdata.io/sling-cli/environment)", name) - } - g.Info("connection `%s` has been set in %s. Please test with `sling conns test %s`", name, ec.EnvFile.Path, name) - case "exec": - env.SetTelVal("task", g.Marshal(g.M("type", sling.ConnExec))) - - name := cast.ToString(c.Vals["name"]) - conn, ok := ec.GetConnEntry(name) - if !ok { - return ok, g.Error("did not find connection %s", name) - } - - env.SetTelVal("conn_type", conn.Connection.Type.String()) - - if !conn.Connection.Type.IsDb() { - return ok, g.Error("cannot execute SQL query on a non-database connection (%s)", conn.Connection.Type) - } - - start := time.Now() - dbConn, err := conn.Connection.AsDatabase() - if err != nil { - return ok, g.Error(err, "cannot create database connection (%s)", conn.Connection.Type) - } - - err = dbConn.Connect() - if err != nil { - return ok, g.Error(err, "cannot connect to database (%s)", conn.Connection.Type) - } - - queries := append([]string{cast.ToString(c.Vals["queries..."])}, flaggy.TrailingArguments...) - - var totalAffected int64 - for i, query := range queries { - - query, err = sling.GetSQLText(query) - if err != nil { - return ok, g.Error(err, "cannot get query") - } - - sQuery, err := database.ParseTableName(query, conn.Connection.Type) - if err != nil { - return ok, g.Error(err, "cannot parse query") - } - - if len(database.ParseSQLMultiStatements(query)) == 1 && (!sQuery.IsQuery() || strings.Contains(query, "select") || g.In(conn.Connection.Type, dbio.TypeDbPrometheus, dbio.TypeDbMongoDB)) { - - data, err := dbConn.Query(sQuery.Select(100)) - if err != nil { - return ok, g.Error(err, "cannot execute query") - } - - if asJSON { - fmt.Println(g.Marshal(g.M("fields", data.GetFields(), "rows", data.Rows))) - } else { - fmt.Println(g.PrettyTable(data.GetFields(), data.Rows)) - } - - totalAffected = cast.ToInt64(len(data.Rows)) - } else { - if len(queries) > 1 { - if strings.HasPrefix(query, "file://") { - g.Info("executing query #%d (%s)", i+1, query) - } else { - g.Info("executing query #%d", i+1) - } - } else { - g.Info("executing query") - } - - result, err := dbConn.ExecMulti(query) - if err != nil { - return ok, g.Error(err, "cannot execute query") - } - - affected, _ := result.RowsAffected() - totalAffected = totalAffected + affected - } - } - - end := time.Now() - if totalAffected > 0 { - g.Info("successful! duration: %d seconds (%d affected records)", end.Unix()-start.Unix(), totalAffected) - } else { - g.Info("successful! duration: %d seconds.", end.Unix()-start.Unix()) - } - - if err := testRowCnt(totalAffected); err != nil { - return ok, err - } - - case "list": - fields, rows := ec.List() - if asJSON { - fmt.Println(g.Marshal(g.M("fields", fields, "rows", rows))) - } else { - fmt.Println(g.PrettyTable(fields, rows)) - } - - case "test": - env.SetTelVal("task", g.Marshal(g.M("type", sling.ConnTest))) - name := cast.ToString(c.Vals["name"]) - if conn, ok := ec.GetConnEntry(name); ok { - env.SetTelVal("conn_type", conn.Connection.Type.String()) - env.SetTelVal("conn_keys", lo.Keys(conn.Connection.Data)) - } - - ok, err = ec.Test(name) - if err != nil { - return ok, g.Error(err, "could not test %s (See https://docs.slingdata.io/sling-cli/environment)", name) - } else if ok { - g.Info("success!") // successfully connected - } - case "discover": - env.SetTelVal("task", g.Marshal(g.M("type", sling.ConnDiscover))) - name := cast.ToString(c.Vals["name"]) - conn, ok := ec.GetConnEntry(name) - if ok { - env.SetTelVal("conn_type", conn.Connection.Type.String()) - } - - opt := &connection.DiscoverOptions{ - Pattern: cast.ToString(c.Vals["pattern"]), - ColumnLevel: cast.ToBool(c.Vals["columns"]), - Recursive: cast.ToBool(c.Vals["recursive"]), - } - - files, schemata, err := ec.Discover(name, opt) - if err != nil { - return ok, g.Error(err, "could not discover %s (See https://docs.slingdata.io/sling-cli/environment)", name) - } - - if tables := lo.Values(schemata.Tables()); len(tables) > 0 { - - sort.Slice(tables, func(i, j int) bool { - val := func(t database.Table) string { - return t.FDQN() - } - return val(tables[i]) < val(tables[j]) - }) - - if opt.ColumnLevel { - columns := iop.Columns(lo.Values(schemata.Columns())) - if asJSON { - fmt.Println(columns.JSON(true)) - } else { - fmt.Println(columns.PrettyTable(true)) - } - } else { - fields := []string{"#", "Schema", "Name", "Type", "Columns"} - rows := lo.Map(tables, func(table database.Table, i int) []any { - tableType := lo.Ternary(table.IsView, "view", "table") - if table.Dialect.DBNameUpperCase() { - tableType = strings.ToUpper(tableType) - } - return []any{i + 1, table.Schema, table.Name, tableType, len(table.Columns)} - }) - if asJSON { - fmt.Println(g.Marshal(g.M("fields", fields, "rows", rows))) - } else { - fmt.Println(g.PrettyTable(fields, rows)) - } - } - } else if len(files) > 0 { - if opt.ColumnLevel { - columns := iop.Columns(lo.Values(files.Columns())) - if asJSON { - fmt.Println(columns.JSON(true)) - } else { - fmt.Println(columns.PrettyTable(true)) - } - } else { - - files.Sort() - - fields := []string{"#", "Name", "Type", "Size", "Last Updated (UTC)"} - rows := lo.Map(files, func(file dbio.FileNode, i int) []any { - fileType := lo.Ternary(file.IsDir, "directory", "file") - - lastUpdated := "-" - if file.Updated > 100 { - updated := time.Unix(file.Updated, 0) - delta := strings.Split(g.DurationString(time.Since(updated)), " ")[0] - lastUpdated = g.F("%s (%s ago)", updated.UTC().Format("2006-01-02 15:04:05"), delta) - } - - size := "-" - if !file.IsDir || file.Size > 0 { - size = humanize.IBytes(file.Size) - } - - return []any{i + 1, file.Path(), fileType, size, lastUpdated} - }) - - if asJSON { - fmt.Println(g.Marshal(g.M("fields", fields, "rows", rows))) - } else { - fmt.Println(g.PrettyTable(fields, rows)) - } - - if len(files) > 0 && !(opt.Recursive || opt.Pattern != "") { - g.Info("Those are non-recursive folder or file names (at the root level). Please use the --pattern flag to list sub-folders, or --recursive") - } - } - } else { - g.Info("no result.") - } - - case "": - return false, nil - } - return ok, nil -} - -func printUpdateAvailable() { - if updateVersion != "" { - println(updateMessage) - } -} - func parsePayload(payload string, validate bool) (options map[string]any, err error) { payload = strings.TrimSpace(payload) if payload == "" { diff --git a/cmd/sling/sling_test.go b/cmd/sling/sling_test.go index e0899488d..ecba6b4cb 100755 --- a/cmd/sling/sling_test.go +++ b/cmd/sling/sling_test.go @@ -68,6 +68,7 @@ var connMap = map[dbio.Type]connTest{ dbio.TypeDbTrino: {name: "trino", adjustCol: g.Bool(false)}, dbio.TypeDbMongoDB: {name: "mongo", schema: "default"}, dbio.TypeDbPrometheus: {name: "prometheus", schema: "prometheus"}, + dbio.TypeDbProton: {name: "proton", schema: "default", useBulk: g.Bool(true)}, dbio.TypeFileLocal: {name: "local"}, dbio.TypeFileSftp: {name: "sftp"}, @@ -406,10 +407,28 @@ func runOneTask(t *testing.T, file g.FileItem, connType dbio.Type) { } } - if valRowCount := cast.ToInt(cfg.Env["validation_row_count"]); valRowCount > 0 { + if valRowCountVal := cfg.Env["validation_stream_row_count"]; valRowCountVal != "" { + taskCount := cast.ToInt(task.GetCount()) + if strings.HasPrefix(valRowCountVal, ">") { + valRowCount := cast.ToInt(strings.TrimPrefix(valRowCountVal, ">")) + assert.Greater(t, taskCount, valRowCount, "validation_stream_row_count (%s)", file.Name) + } else { + valRowCount := cast.ToInt(valRowCountVal) + assert.EqualValues(t, valRowCount, taskCount, "validation_stream_row_count (%s)", file.Name) + } + } + + if valRowCountVal := cfg.Env["validation_row_count"]; valRowCountVal != "" { conn, _ := task.Config.TgtConn.AsDatabase() - count, _ := conn.GetCount(task.Config.Target.Object) - assert.EqualValues(t, valRowCount, count) + countU, _ := conn.GetCount(task.Config.Target.Object) + count := cast.ToInt(countU) + if strings.HasPrefix(valRowCountVal, ">") { + valRowCount := cast.ToInt(strings.TrimPrefix(valRowCountVal, ">")) + assert.Greater(t, count, valRowCount, "validation_row_count (%s)", file.Name) + } else { + valRowCount := cast.ToInt(valRowCountVal) + assert.EqualValues(t, valRowCount, count, "validation_row_count (%s)", file.Name) + } } // validate file @@ -438,7 +457,7 @@ func runOneTask(t *testing.T, file g.FileItem, connType dbio.Type) { // g.P(dataDB.ColValues(0)) // g.P(dataDB.ColValues(1)) // g.P(valuesDb) - if assert.Equal(t, len(valuesFile), len(valuesDb)) { + if assert.Equal(t, len(valuesFile), len(valuesDb), file.Name) { for i := range valuesDb { valDb := dataDB.Sp.ParseString(cast.ToString(valuesDb[i])) valFile := dataDB.Sp.ParseString(cast.ToString(valuesFile[i])) @@ -532,11 +551,19 @@ func TestSuiteDatabaseSQLServer(t *testing.T) { // } func TestSuiteDatabaseClickhouse(t *testing.T) { + if cast.ToBool(os.Getenv("SKIP_CLICKHOUSE")) { + return + } t.Parallel() testSuite(t, dbio.TypeDbClickhouse) testSuite(t, dbio.Type("clickhouse_http")) } +func TestSuiteDatabaseProton(t *testing.T) { + t.Parallel() + testSuite(t, dbio.TypeDbProton, "22") +} + func TestSuiteDatabaseTrino(t *testing.T) { t.Parallel() testSuite(t, dbio.TypeDbTrino, "1,3,10,16,22") diff --git a/cmd/sling/sling_update.go b/cmd/sling/sling_update.go index 8fd75df26..bc802b2cd 100644 --- a/cmd/sling/sling_update.go +++ b/cmd/sling/sling_update.go @@ -236,3 +236,9 @@ func ExtractTarGz(filePath, outFolder string) (err error) { return nil } + +func printUpdateAvailable() { + if updateVersion != "" { + println(updateMessage) + } +} diff --git a/cmd/sling/tests/suite.db.template.tsv b/cmd/sling/tests/suite.db.template.tsv index 078dcf8f8..be6c0baed 100644 --- a/cmd/sling/tests/suite.db.template.tsv +++ b/cmd/sling/tests/suite.db.template.tsv @@ -1,23 +1,23 @@ n test_name source_conn source_stream source_options target_conn target_object mode source_primary_key source_update_key target_options options env -1 csv_full_refresh file://tests/files/test1.csv {} [conn] [schema].[table] full-refresh "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true, ""pre_sql"" : ""{drop_view}"", ""table_keys"": { ""unique"": [ ""id"" ] }}" {} -2 csv_full_refresh_delimiter file://tests/files/test5.csv {} [conn] [schema].[table]_2 full-refresh +1 csv_full_refresh file://tests/files/test1.csv {} [conn] [schema].[table] full-refresh "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true, ""pre_sql"" : ""{drop_view}"", ""table_keys"": { ""unique"": [ ""id"" ] }}" {} "{""validation_row_count"": ""1000""}" +2 csv_full_refresh_delimiter file://tests/files/test5.csv {} [conn] [schema].[table]_2 full-refresh "{""validation_row_count"": "">0""}" 3 discover_table [conn] [schema].[table] discover "{""validation_contains"": ""create_dt"", ""validation_row_count"": ""10"", ""column_level"": true}" -4 csv_incremental file://tests/files/test1.upsert.csv {} [conn] [schema].[table] incremental id create_dt "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true, ""post_sql"" : ""{drop_view}"", ""pre_sql"" : ""drop table [schema].[table]_2""}" {} "{""validation_file"": ""file://tests/files/test1.result.csv"", ""validation_cols"": ""0,1,2,3,4,6""}" -5 parquet_snapshot file://tests/files/test1.parquet {} [conn] [schema].[table]_snapshot snapshot "{""pre_sql"" : ""create view [schema].[table]_vw as select * from [schema].[table]""}" +4 csv_incremental file://tests/files/test1.upsert.csv {} [conn] [schema].[table] incremental id create_dt "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true, ""post_sql"" : ""{drop_view}"", ""pre_sql"" : ""drop table [schema].[table]_2""}" {} "{""validation_file"": ""file://tests/files/test1.result.csv"", ""validation_cols"": ""0,1,2,3,4,6"", ""validation_row_count"": "">0"", ""validation_stream_row_count"": 14}" +5 parquet_snapshot file://tests/files/test1.parquet {} [conn] [schema].[table]_snapshot snapshot "{""pre_sql"" : ""create view [schema].[table]_vw as select * from [schema].[table]""}" "{""validation_row_count"": "">999""}" 6 parquet_truncate file://tests/files/test1.parquet "{""columns"": {""rating"": ""float""}}" [conn] [schema].[table]_truncate truncate "{""pre_sql"": ""drop table [schema].[table]_snapshot "", ""post_sql"" : ""drop table [schema].[table]_truncate""}" -7 csv_wide_full_refresh file://tests/files/test.wide.csv {} [conn] [schema].[table]_wide full-refresh "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": false, ""table_keys"": { ""unique"": [ ""id"" ] }}" {} +7 csv_wide_full_refresh file://tests/files/test.wide.csv {} [conn] [schema].[table]_wide full-refresh "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": false, ""table_keys"": { ""unique"": [ ""id"" ] }}" {} "{""validation_row_count"": "">0""}" 8 discover_schema [conn] [schema].* discover "{""validation_contains"": ""[table],[table]_wide,[table]_vw""}" 9 discover_filter [conn] [schema].[table]_v* discover "{""validation_contains"": ""[table]_vw"", ""validation_row_count"": "">0""}" -10 table_full_refresh_into_postgres [conn] [schema].[table] {} postgres public.[table]_pg full-refresh "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} +10 table_full_refresh_into_postgres [conn] [schema].[table] {} postgres public.[table]_pg full-refresh "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} "{""validation_row_count"": "">999""}" 11 table_incremental_into_postgres [conn] [schema].[table] {} postgres public.[table]_pg incremental id create_dt "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} "{""validation_file"": ""file://tests/files/test1.result.csv"", ""validation_cols"": ""0,1,2,3,4,6""}" -12 view_full_refresh_into_postgres [conn] [schema].[table]_vw {} postgres public.[table]_pg_vw full-refresh "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} +12 view_full_refresh_into_postgres [conn] [schema].[table]_vw {} postgres public.[table]_pg_vw full-refresh "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} "{""validation_row_count"": "">0""}" 13 sql_full_refresh_into_postgres [conn] select t1.*, {seq_num} as seq_num from [schema].[table] t1 where 1=1 {} postgres public.[table]_pg full-refresh "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} "{""validation_file"": ""file://tests/files/test1.result.csv"", ""validation_cols"": ""0,1,2,3,4,6"", ""seq_num"": 123}" -14 sql_incremental_into_postgres [conn] select * from [schema].[table] where {incremental_where_cond} {} postgres public.[table]_pg incremental id create_dt "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} "{""validation_file"": ""file://tests/files/test1.result.csv"", ""validation_cols"": ""0,1,2,3,4,6""}" +14 sql_incremental_into_postgres [conn] select * from [schema].[table] where {incremental_where_cond} {} postgres public.[table]_pg incremental id create_dt "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} "{""validation_file"": ""file://tests/files/test1.result.csv"", ""validation_cols"": ""0,1,2,3,4,6"", , ""validation_stream_row_count"": "">0""}" 15 table_backfill_into_postgres [conn] [schema].[table] "{""range"":""2020-01-01,2021-01-01""}" postgres public.[table]_pg backfill id create_dt {} {} -16 table_full_refresh_from_postgres postgres public.[table]_pg {} [conn] [schema].[table]_pg full-refresh id "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} -17 table_incremental_from_postgres postgres public.[table]_pg {} [conn] [schema].[table]_pg incremental id create_dt "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": false}" {} "{""validation_file"": ""file://tests/files/test1.result.csv"", ""validation_cols"": ""0,1,2,3,4,6""}" -18 view_full_refresh_from_postgres postgres public.[table]_pg_vw {} [conn] [schema].[table]_vw_pg full-refresh "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} -19 sql_full_refresh_from_postgres postgres select * from public.[table]_pg where 1=1 {} [conn] [schema].[table]_pg full-refresh id create_dt "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} "{""validation_file"": ""file://tests/files/test1.result.csv"", ""validation_cols"": ""0,1,2,3,4,6""}" -20 sql_incremental_from_postgres postgres select * from public.[table]_pg where {incremental_where_cond} {} [conn] [schema].[table]_pg incremental id create_dt "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": false, ""post_sql"": ""{drop_view}""}" {} "{""validation_file"": ""file://tests/files/test1.result.csv"", ""validation_cols"": ""0,1,2,3,4,6""}" -21 table_backfill_from_postgres postgres public.[table]_pg "{""range"":""2020-01-01,2021-01-01""}" [conn] [schema].[table]_pg backfill id create_dt "{""post_sql"": ""drop table [schema].[table] ; drop table [schema].[table]_pg; drop table [schema].[table]_vw_pg""}" {} +16 table_full_refresh_from_postgres postgres public.[table]_pg {} [conn] [schema].[table]_pg full-refresh id "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} "{""validation_row_count"": "">999""}" +17 table_incremental_from_postgres postgres public.[table]_pg {} [conn] [schema].[table]_pg incremental id create_dt "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": false}" {} "{""validation_file"": ""file://tests/files/test1.result.csv"", ""validation_cols"": ""0,1,2,3,4,6"", ""validation_stream_row_count"": "">0""}" +18 view_full_refresh_from_postgres postgres public.[table]_pg_vw {} [conn] [schema].[table]_vw_pg full-refresh "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} "{""validation_row_count"": "">0""}" +19 sql_full_refresh_from_postgres postgres select * from public.[table]_pg where 1=1 {} [conn] [schema].[table]_pg full-refresh id create_dt "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": true}" {} "{""validation_file"": ""file://tests/files/test1.result.csv"", ""validation_cols"": ""0,1,2,3,4,6"", ""validation_row_count"": "">0""}" +20 sql_incremental_from_postgres postgres select * from public.[table]_pg where {incremental_where_cond} {} [conn] [schema].[table]_pg incremental id create_dt "{""adjust_column_type"":true, ""add_new_columns"":true, ""use_bulk"": false, ""post_sql"": ""{drop_view}""}" {} "{""validation_file"": ""file://tests/files/test1.result.csv"", ""validation_cols"": ""0,1,2,3,4,6"", ""validation_row_count"": "">0"", ""validation_stream_row_count"": "">0""}" +21 table_backfill_from_postgres postgres public.[table]_pg "{""range"":""2020-01-01,2021-01-01""}" [conn] [schema].[table]_pg backfill id create_dt "{""post_sql"": ""drop table [schema].[table] ; drop table [schema].[table]_pg; drop table [schema].[table]_vw_pg""}" {} "{""validation_stream_row_count"": "">0""}" 22 discover [conn] discover diff --git a/core/dbio/connection/connection.go b/core/dbio/connection/connection.go index 21f335321..2600290d1 100644 --- a/core/dbio/connection/connection.go +++ b/core/dbio/connection/connection.go @@ -592,6 +592,25 @@ func (c *Connection) setURL() (err error) { } template = "clickhouse://{username}:{password}@{host}:{port}/{database}" + case dbio.TypeDbProton: + setIfMissing("username", c.Data["user"]) + setIfMissing("username", "") // proton can work without a user + setIfMissing("password", "") + setIfMissing("schema", c.Data["database"]) + setIfMissing("port", c.Type.DefPort()) + + // parse http url + if httpUrlStr, ok := c.Data["http_url"]; ok { + u, err := url.Parse(cast.ToString(httpUrlStr)) + if err != nil { + g.Warn("invalid http_url: %s", err.Error()) + } else { + setIfMissing("host", u.Hostname()) + } + setIfMissing("database", "default") + } + + template = "proton://{username}:{password}@{host}:{port}/{database}" case dbio.TypeFileSftp, dbio.TypeFileFtp: setIfMissing("password", "") setIfMissing("port", c.Type.DefPort()) diff --git a/core/dbio/database/database.go b/core/dbio/database/database.go index 0d9a6dcbe..e65ce8755 100755 --- a/core/dbio/database/database.go +++ b/core/dbio/database/database.go @@ -2,12 +2,15 @@ package database import ( "context" + "crypto/tls" + "crypto/x509" "database/sql" "fmt" "math" "net/url" "os" "path" + "runtime/debug" "strings" "sync" "time" @@ -277,6 +280,8 @@ func NewConnContext(ctx context.Context, URL string, props ...string) (Connectio conn = &BigTableConn{URL: URL} } else if strings.HasPrefix(URL, "clickhouse:") { conn = &ClickhouseConn{URL: URL} + } else if strings.HasPrefix(URL, "proton:") { + conn = &ProtonConn{URL: URL} } else if strings.HasPrefix(URL, "snowflake") { conn = &SnowflakeConn{URL: URL} } else if strings.HasPrefix(URL, "sqlite:") { @@ -330,6 +335,8 @@ func getDriverName(dbType dbio.Type) (driverName string) { driverName = "sqlserver" case dbio.TypeDbTrino: driverName = "trino" + case dbio.TypeDbProton: + driverName = "proton" default: driverName = dbType.String() } @@ -583,6 +590,7 @@ func (conn *BaseConn) Connect(timeOut ...int) (err error) { g.F("@127.0.0.1:%d", localPort), ) g.Trace("new connection URL: " + conn.Self().GetURL(connURL)) + conn.SetProp("ssh_url", connURL) // set ssh url for 3rd party bulk loading } if conn.db == nil { @@ -1378,6 +1386,11 @@ func NativeTypeToGeneral(name, dbType string, conn Connection) (colType iop.Colu dbType = strings.ReplaceAll(dbType, "nullable(", "") dbType = strings.TrimSuffix(dbType, ")") } + } else if conn.GetType() == dbio.TypeDbProton { + if strings.HasPrefix(dbType, "nullable(") { + dbType = strings.ReplaceAll(dbType, "nullable(", "") + dbType = strings.TrimSuffix(dbType, ")") + } } else if conn.GetType() == dbio.TypeDbDuckDb || conn.GetType() == dbio.TypeDbMotherDuck { if strings.HasSuffix(dbType, "[]") { dbType = "list" @@ -2895,6 +2908,13 @@ func (conn *BaseConn) OptimizeTable(table *Table, newColumns iop.Columns, isTemp // to the checkum values from the StreamProcessor func (conn *BaseConn) CompareChecksums(tableName string, columns iop.Columns) (err error) { + // recover from panic + defer func() { + if r := recover(); r != nil { + err = g.Error(g.F("panic occurred! %#v\n%s", r, string(debug.Stack()))) + } + }() + table, err := ParseTableName(tableName, conn.GetType()) if err != nil { return g.Error(err, "could not parse table name") @@ -2964,6 +2984,10 @@ func (conn *BaseConn) CompareChecksums(tableName string, columns iop.Columns) (e data, err := conn.Self().Query(sql) if err != nil { return g.Error(err, "error running CompareChecksums query") + } else if len(data.Rows) == 0 { + return g.Error("error running CompareChecksums query. No Rows returns") + } else if len(data.Rows[0]) != len(data.Columns) { + return g.Error("error running CompareChecksums query. Row vs Column size mismatch (%d != %d)", len(data.Rows[0]), len(data.Columns)) } eg := g.ErrorGroup{} @@ -3026,6 +3050,41 @@ func (conn *BaseConn) credsProvided(provider string) bool { return false } +func (conn *BaseConn) getTlsConfig() (tlsConfig *tls.Config, err error) { + if cast.ToBool(conn.GetProp("tls")) { + tlsConfig = &tls.Config{} + } + + cert := conn.GetProp("cert_file") + key := conn.GetProp("cert_key_file") + caCert := conn.GetProp("cert_ca_file") + + if key != "" && cert != "" { + cert, err := tls.LoadX509KeyPair(cert, key) + if err != nil { + return nil, g.Error(err, "Failed to load client certificate") + } + + tlsConfig = &tls.Config{ + Certificates: []tls.Certificate{cert}, + } + + if caCert != "" { + caCert, err := os.ReadFile(caCert) + if err != nil { + return nil, g.Error(err, "Failed to load CA certificate") + } + tlsConfig.RootCAs = x509.NewCertPool() + ok := tlsConfig.RootCAs.AppendCertsFromPEM(caCert) + if !ok { + return nil, g.Error("Failed to parse PEM file") + } + } + } + + return +} + // settingMppBulkImportFlow sets settings for MPP databases type // for BulkImportFlow func settingMppBulkImportFlow(conn Connection, compressor iop.CompressorType) { diff --git a/core/dbio/database/database_bigquery.go b/core/dbio/database/database_bigquery.go index 5f83a5f28..7f1acd513 100755 --- a/core/dbio/database/database_bigquery.go +++ b/core/dbio/database/database_bigquery.go @@ -563,6 +563,7 @@ func (conn *BigQueryConn) importViaLocalStorage(tableFName string, df *iop.Dataf fileReadyChn := make(chan filesys.FileReady, 10) go func() { + fs.SetProp("null_as", `\N`) _, err = fs.WriteDataflowReady(df, localPath, fileReadyChn, iop.DefaultStreamConfig()) if err != nil { @@ -647,6 +648,7 @@ func (conn *BigQueryConn) importViaGoogleStorage(tableFName string, df *iop.Data fileReadyChn := make(chan filesys.FileReady, 10) go func() { + fs.SetProp("null_as", `\N`) _, err = fs.WriteDataflowReady(df, gcsPath, fileReadyChn, iop.DefaultStreamConfig()) if err != nil { @@ -722,6 +724,7 @@ func (conn *BigQueryConn) LoadCSVFromReader(table Table, reader io.Reader, dsCol source.FieldDelimiter = "," source.AllowQuotedNewlines = true source.Quote = `"` + source.NullMarker = `\N` source.SkipLeadingRows = 1 source.Schema = getBqSchema(dsColumns) source.SourceFormat = bigquery.CSV @@ -767,6 +770,7 @@ func (conn *BigQueryConn) CopyFromGCS(gcsURI string, table Table, dsColumns []io gcsRef.FieldDelimiter = "," gcsRef.AllowQuotedNewlines = true gcsRef.Quote = `"` + gcsRef.NullMarker = `\N` gcsRef.SkipLeadingRows = 1 gcsRef.Schema = getBqSchema(dsColumns) if strings.HasSuffix(strings.ToLower(gcsURI), ".gz") { @@ -824,6 +828,11 @@ func (conn *BigQueryConn) BulkExportFlow(tables ...Table) (df *iop.Dataflow, err fs.SetProp("format", "csv") fs.SetProp("columns", g.Marshal(columns)) fs.SetProp("metadata", conn.GetProp("metadata")) + + // setting empty_as_null=true. no way to export with proper null_marker. + // Parquet export doesn't support JSON types + fs.SetProp("empty_as_null", "true") + df, err = fs.ReadDataflow(gsURL) if err != nil { err = g.Error(err, "Could not read "+gsURL) diff --git a/core/dbio/database/database_clickhouse.go b/core/dbio/database/database_clickhouse.go index f037cdf4b..4c25527c7 100755 --- a/core/dbio/database/database_clickhouse.go +++ b/core/dbio/database/database_clickhouse.go @@ -7,10 +7,10 @@ import ( "strings" "time" - "github.com/fatih/color" "github.com/shopspring/decimal" "github.com/slingdata-io/sling-cli/core/dbio" "github.com/slingdata-io/sling-cli/core/dbio/iop" + "github.com/slingdata-io/sling-cli/core/env" "github.com/spf13/cast" "github.com/flarco/g" @@ -38,7 +38,7 @@ func (conn *ClickhouseConn) Connect(timeOut ...int) (err error) { err = conn.BaseConn.Connect(timeOut...) if err != nil { if strings.Contains(err.Error(), "unexpected packet") { - g.Info(color.MagentaString("Try using the `http_url` instead to connect to Clickhouse via HTTP. See https://docs.slingdata.io/connections/database-connections/clickhouse")) + g.Info(env.MagentaString("Try using the `http_url` instead to connect to Clickhouse via HTTP. See https://docs.slingdata.io/connections/database-connections/clickhouse")) } } diff --git a/core/dbio/database/database_duckdb.go b/core/dbio/database/database_duckdb.go index e1d4b8e3e..22f466708 100644 --- a/core/dbio/database/database_duckdb.go +++ b/core/dbio/database/database_duckdb.go @@ -50,7 +50,7 @@ func (conn *DuckDbConn) Init() error { conn.BaseConn.URL = conn.URL conn.BaseConn.Type = dbio.TypeDbDuckDb - if strings.HasPrefix(conn.URL, "motherduck") { + if strings.HasPrefix(conn.URL, "motherduck") || strings.HasPrefix(conn.URL, "duckdb://md:") { conn.BaseConn.Type = dbio.TypeDbMotherDuck } @@ -603,7 +603,7 @@ func (conn *DuckDbConn) StreamRowsContext(ctx context.Context, sql string, optio conn.LogSQL(sql) - cmd.Args = append(cmd.Args, "-csv") + cmd.Args = append(cmd.Args, "-csv", "-nullvalue", `\N\`) conn.setDuckDbFileCmd(cmd) fileContext, _ := conn.getDuckDbFileContext() @@ -646,12 +646,9 @@ func (conn *DuckDbConn) StreamRowsContext(ctx context.Context, sql string, optio ds.SafeInference = true ds.NoDebug = strings.Contains(sql, noDebugKey) ds.SetConfig(conn.Props()) - ds.SetConfig(map[string]string{"delimiter": ",", "header": "true", "transforms": g.Marshal(transforms)}) + ds.SetConfig(map[string]string{"delimiter": ",", "header": "true", "transforms": g.Marshal(transforms), "null_if": `\N\`}) ds.Defer(func() { conn.unlockFileContext(fileContext) }) - // ds.SetConfig(map[string]string{"flatten": "true"}) - // err = ds.ConsumeJsonReader(stdOutReader) - // err = ds.ConsumeParquetReader(stdOutReader) err = ds.ConsumeCsvReader(stdOutReader) if err != nil { ds.Close() @@ -741,6 +738,11 @@ func (conn *DuckDbConn) BulkImportStream(tableFName string, ds *iop.Datastream) return } + if len(ds.Buffer) == 0 { + // nothing to import + return + } + for batch := range ds.BatchChan { if batch.ColumnsChanged() || batch.IsFirst() { columns, err = conn.GetColumns(tableFName, batch.Columns.Names()...) @@ -761,6 +763,7 @@ func (conn *DuckDbConn) BulkImportStream(tableFName string, ds *iop.Datastream) cfgMap := ds.GetConfig() cfgMap["header"] = "true" cfgMap["delimiter"] = "," + cfgMap["null_as"] = `\N` cfgMap["datetime_format"] = "2006-01-02 15:04:05.000000-07:00" ds.SetConfig(cfgMap) @@ -791,7 +794,7 @@ func (conn *DuckDbConn) BulkImportStream(tableFName string, ds *iop.Datastream) }) sqlLines := []string{ - g.F(`insert into %s (%s) select * from read_csv('%s', delim=',', header=True, columns=%s, max_line_size=134217728, parallel=false, quote='"', escape='"');`, table.FDQN(), strings.Join(columnNames, ", "), csvPath, conn.generateCsvColumns(ds.Columns)), + g.F(`insert into %s (%s) select * from read_csv('%s', delim=',', header=True, columns=%s, max_line_size=134217728, parallel=false, quote='"', escape='"', nullstr='\N');`, table.FDQN(), strings.Join(columnNames, ", "), csvPath, conn.generateCsvColumns(ds.Columns)), } var out []byte diff --git a/core/dbio/database/database_mongo.go b/core/dbio/database/database_mongo.go index f06f1f18a..b4bc7c7f5 100644 --- a/core/dbio/database/database_mongo.go +++ b/core/dbio/database/database_mongo.go @@ -9,6 +9,7 @@ import ( "github.com/flarco/g" "github.com/slingdata-io/sling-cli/core/dbio" "github.com/slingdata-io/sling-cli/core/dbio/iop" + "github.com/slingdata-io/sling-cli/core/env" "github.com/spf13/cast" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" @@ -53,8 +54,19 @@ func (conn *MongoDBConn) getNewClient(timeOut ...int) (client *mongo.Client, err ctx, cancel := context.WithTimeout(conn.BaseConn.Context().Ctx, time.Duration(to)*time.Second) defer cancel() - opts := options.Client().SetCompressors([]string{"zstd", "snappy", "zlib"}) - return mongo.Connect(ctx, options.Client().ApplyURI(conn.URL), opts) + opts := []*options.ClientOptions{ + options.Client().ApplyURI(conn.URL), + options.Client().SetCompressors([]string{"zstd", "snappy", "zlib"}), + } + + tlsConfig, err := conn.getTlsConfig() + if err != nil { + return nil, g.Error(err) + } else if tlsConfig != nil { + opts[0].SetTLSConfig(tlsConfig) + } + + return mongo.Connect(ctx, opts...) } // Connect connects to the database @@ -69,6 +81,9 @@ func (conn *MongoDBConn) Connect(timeOut ...int) error { defer cancel() err = conn.Client.Ping(ctx, readpref.Primary()) if err != nil { + if strings.Contains(err.Error(), "server selection error") { + g.Info(env.MagentaString("Try setting the `tls` key to 'true'. See https://docs.slingdata.io/connections/database-connections/mongodb")) + } return g.Error(err, "Failed to ping mongo server") } diff --git a/core/dbio/database/database_mysql.go b/core/dbio/database/database_mysql.go index 1c47bde2a..34fe93af4 100755 --- a/core/dbio/database/database_mysql.go +++ b/core/dbio/database/database_mysql.go @@ -183,7 +183,13 @@ func (conn *MySQLConn) LoadDataOutFile(ctx *g.Context, sql string) (stdOutReader // LoadDataInFile Bulk Import func (conn *MySQLConn) LoadDataInFile(tableFName string, ds *iop.Datastream) (count uint64, err error) { var stderr bytes.Buffer - url, err := dburl.Parse(conn.URL) + + connURL := conn.URL + if su := conn.GetProp("ssh_url"); su != "" { + connURL = su // use ssh url if specified + } + + url, err := dburl.Parse(connURL) if err != nil { err = g.Error(err, "Error dburl.Parse(conn.URL)") return diff --git a/core/dbio/database/database_oracle.go b/core/dbio/database/database_oracle.go index 47a1e9758..06f29588f 100755 --- a/core/dbio/database/database_oracle.go +++ b/core/dbio/database/database_oracle.go @@ -237,7 +237,13 @@ func (conn *OracleConn) BulkImportStream(tableFName string, ds *iop.Datastream) // cannot import when newline in value. Need to scan for new lines. func (conn *OracleConn) SQLLoad(tableFName string, ds *iop.Datastream) (count uint64, err error) { var stderr, stdout bytes.Buffer - url, err := dburl.Parse(conn.ConnString()) + + connURL := conn.ConnString() + if su := conn.GetProp("ssh_url"); su != "" { + connURL = su // use ssh url if specified + } + + url, err := dburl.Parse(connURL) if err != nil { err = g.Error(err, "Error dburl.Parse(conn.URL)") return diff --git a/core/dbio/database/database_prometheus.go b/core/dbio/database/database_prometheus.go index 59cb3d3ff..9151ce57d 100644 --- a/core/dbio/database/database_prometheus.go +++ b/core/dbio/database/database_prometheus.go @@ -37,16 +37,25 @@ func (conn *PrometheusConn) Init() error { return conn.BaseConn.Init() } -// Init initiates the object +// Init initiates the client func (conn *PrometheusConn) getNewClient(timeOut ...int) (client v1.API, err error) { - var rt http.RoundTripper + rt := api.DefaultRoundTripper + + // get tls + tlsConfig, err := conn.getTlsConfig() + if err != nil { + return nil, g.Error(err) + } else if tlsConfig != nil { + rt = &http.Transport{TLSClientConfig: tlsConfig} + } + if token := conn.GetProp("token"); token != "" { - rt = config.NewAuthorizationCredentialsRoundTripper("Bearer", config.Secret(token), api.DefaultRoundTripper) + rt = config.NewAuthorizationCredentialsRoundTripper("Bearer", config.Secret(token), rt) } if user := conn.GetProp("user"); user != "" { - rt = config.NewBasicAuthRoundTripper(user, config.Secret(conn.GetProp("password")), "", "", api.DefaultRoundTripper) + rt = config.NewBasicAuthRoundTripper(user, config.Secret(conn.GetProp("password")), "", "", rt) } c, err := api.NewClient(api.Config{ @@ -255,7 +264,7 @@ func (conn *PrometheusConn) StreamRowsContext(ctx context.Context, query string, if len(sample.Histograms) > 0 { columns = append(columns, iop.Column{ Name: "timestamp", - Type: iop.TimestampType, + Type: iop.BigIntType, Position: len(columns) + 1, }) columns = append(columns, iop.Column{ @@ -291,7 +300,7 @@ func (conn *PrometheusConn) StreamRowsContext(ctx context.Context, query string, } else { columns = append(columns, iop.Column{ Name: "timestamp", - Type: iop.TimestampType, + Type: iop.BigIntType, Position: len(columns) + 1, }) columns = append(columns, iop.Column{ @@ -305,30 +314,33 @@ func (conn *PrometheusConn) StreamRowsContext(ctx context.Context, query string, fieldMap = data.Columns.FieldMap(true) } - row := make([]any, len(data.Columns)) - for k, v := range metricMap { - row[index(k)] = v - } - for _, value := range sample.Values { - row[index("timestamp")] = value.Timestamp.Time() - row[index("value")] = cast.ToFloat64(value.Value) + row := make([]any, len(data.Columns)) + for k, v := range metricMap { + row[index(k)] = v + } + row[index("timestamp")] = value.Timestamp.Unix() + row[index("value")] = value.Value + data.Append(row) } for _, value := range sample.Histograms { - row[index("timestamp")] = value.Timestamp.Time() - row[index("count")] = cast.ToFloat64(value.Histogram.Count) - row[index("sum")] = cast.ToFloat64(value.Histogram.Sum) - for _, bucket := range value.Histogram.Buckets { + row := make([]any, len(data.Columns)) + for k, v := range metricMap { + row[index(k)] = v + } + row[index("timestamp")] = value.Timestamp.Unix() + row[index("count")] = cast.ToFloat64(value.Histogram.Count) + row[index("sum")] = cast.ToFloat64(value.Histogram.Sum) row[index("bucket_boundaries")] = cast.ToInt(bucket.Boundaries) row[index("bucket_count")] = cast.ToFloat64(bucket.Count) row[index("bucket_lower")] = cast.ToFloat64(bucket.Lower) row[index("bucket_upper")] = cast.ToFloat64(bucket.Upper) + data.Append(row) } } - data.Append(row) if Limit > 0 && len(data.Rows) >= Limit { break } @@ -346,7 +358,7 @@ func (conn *PrometheusConn) StreamRowsContext(ctx context.Context, query string, if sample.Histogram != nil { columns = append(columns, iop.Column{ Name: "timestamp", - Type: iop.TimestampType, + Type: iop.BigIntType, Position: len(columns) + 1, }) columns = append(columns, iop.Column{ @@ -382,7 +394,7 @@ func (conn *PrometheusConn) StreamRowsContext(ctx context.Context, query string, } else { columns = append(columns, iop.Column{ Name: "timestamp", - Type: iop.TimestampType, + Type: iop.BigIntType, Position: len(columns) + 1, }) columns = append(columns, iop.Column{ @@ -402,7 +414,7 @@ func (conn *PrometheusConn) StreamRowsContext(ctx context.Context, query string, } if sample.Histogram != nil { - row[index("timestamp")] = sample.Timestamp.Time() + row[index("timestamp")] = sample.Timestamp.Unix() row[index("count")] = cast.ToFloat64(sample.Histogram.Count) row[index("sum")] = cast.ToFloat64(sample.Histogram.Sum) @@ -413,7 +425,7 @@ func (conn *PrometheusConn) StreamRowsContext(ctx context.Context, query string, row[index("bucket_upper")] = cast.ToFloat64(bucket.Upper) } } else { - row[index("timestamp")] = sample.Timestamp.Time() + row[index("timestamp")] = sample.Timestamp.Unix() row[index("value")] = cast.ToFloat64(sample.Value) } @@ -426,7 +438,7 @@ func (conn *PrometheusConn) StreamRowsContext(ctx context.Context, query string, data.Columns = iop.Columns{ { Name: "timestamp", - Type: iop.TimestampType, + Type: iop.BigIntType, Position: 1, }, { @@ -435,12 +447,12 @@ func (conn *PrometheusConn) StreamRowsContext(ctx context.Context, query string, Position: 2, }, } - data.Append([]any{scalar.Timestamp, cast.ToFloat64(scalar.Value)}) + data.Append([]any{scalar.Timestamp.Unix(), cast.ToFloat64(scalar.Value)}) } else if str, ok := result.(*model.String); ok { data.Columns = iop.Columns{ { Name: "timestamp", - Type: iop.TimestampType, + Type: iop.BigIntType, Position: 1, }, { @@ -449,7 +461,7 @@ func (conn *PrometheusConn) StreamRowsContext(ctx context.Context, query string, Position: 2, }, } - data.Append([]any{str.Timestamp, cast.ToFloat64(str.Value)}) + data.Append([]any{str.Timestamp.Unix(), cast.ToFloat64(str.Value)}) } else { return nil, g.Error("invalid result: %#v", result) } diff --git a/core/dbio/database/database_proton.go b/core/dbio/database/database_proton.go new file mode 100755 index 000000000..fdbead1fd --- /dev/null +++ b/core/dbio/database/database_proton.go @@ -0,0 +1,350 @@ +package database + +import ( + "context" + "database/sql" + "fmt" + "strings" + "time" + + "github.com/fatih/color" + "github.com/shopspring/decimal" + "github.com/slingdata-io/sling-cli/core/dbio" + "github.com/slingdata-io/sling-cli/core/dbio/iop" + "github.com/spf13/cast" + _ "github.com/timeplus-io/proton-go-driver/v2" + + "github.com/flarco/g" +) + +// ProtonConn is a Proton connection +type ProtonConn struct { + BaseConn + URL string +} + +// Init initiates the object +func (conn *ProtonConn) Init() error { + + conn.BaseConn.URL = conn.URL + conn.BaseConn.Type = dbio.TypeDbProton + + instance := Connection(conn) + conn.BaseConn.instance = &instance + return conn.BaseConn.Init() +} + +func (conn *ProtonConn) Connect(timeOut ...int) (err error) { + + err = conn.BaseConn.Connect(timeOut...) + if err != nil { + if strings.Contains(err.Error(), "unexpected packet") { + g.Info(color.MagentaString("Try using the `http_url` instead to connect to Proton via HTTP. See https://docs.slingdata.io/connections/database-connections/Proton")) + } + } + + return err +} + +func (conn *ProtonConn) ConnString() string { + + if url := conn.GetProp("http_url"); url != "" { + return url + } + + return conn.BaseConn.ConnString() +} + +// NewTransaction creates a new transaction +func (conn *ProtonConn) NewTransaction(ctx context.Context, options ...*sql.TxOptions) (Transaction, error) { + + context := g.NewContext(ctx) + + if len(options) == 0 { + options = []*sql.TxOptions{&sql.TxOptions{}} + } + + tx, err := conn.Db().BeginTxx(context.Ctx, options[0]) + if err != nil { + return nil, g.Error(err, "could not begin Tx") + } + + Tx := &BaseTransaction{Tx: tx, Conn: conn.Self(), context: &context} + conn.tx = Tx + + // CH does not support transactions at the moment + // Tx := &BlankTransaction{Conn: conn.Self(), context: &context} + + return Tx, nil +} + +// GenerateDDL generates a DDL based on a dataset +func (conn *ProtonConn) GenerateDDL(table Table, data iop.Dataset, temporary bool) (sql string, err error) { + sql, err = conn.BaseConn.GenerateDDL(table, data, temporary) + if err != nil { + return sql, g.Error(err) + } + + partitionBy := "" + if keys, ok := table.Keys[iop.PartitionKey]; ok { + // allow custom SQL expression for partitioning + partitionBy = g.F("partition by (%s)", strings.Join(keys, ", ")) + } else if keyCols := data.Columns.GetKeys(iop.PartitionKey); len(keyCols) > 0 { + colNames := quoteColNames(conn, keyCols.Names()) + partitionBy = g.F("partition by %s", strings.Join(colNames, ", ")) + } + sql = strings.ReplaceAll(sql, "{partition_by}", partitionBy) + + return strings.TrimSpace(sql), nil +} + +// BulkImportStream inserts a stream into a table +func (conn *ProtonConn) BulkImportStream(tableFName string, ds *iop.Datastream) (count uint64, err error) { + var columns iop.Columns + + table, err := ParseTableName(tableFName, conn.GetType()) + if err != nil { + err = g.Error(err, "could not get table name for imoprt") + return + } + + // set default schema + conn.Exec(g.F("use `%s`", table.Schema)) + + // set OnSchemaChange + if df := ds.Df(); df != nil && cast.ToBool(conn.GetProp("adjust_column_type")) { + oldOnColumnChanged := df.OnColumnChanged + df.OnColumnChanged = func(col iop.Column) error { + + // sleep to allow transaction to close + time.Sleep(100 * time.Millisecond) + + ds.Context.Lock() + defer ds.Context.Unlock() + + // use pre-defined function + err = oldOnColumnChanged(col) + if err != nil { + return g.Error(err, "could not process ColumnChange for Postgres") + } + + return nil + } + } + + for batch := range ds.BatchChan { + if batch.ColumnsChanged() || batch.IsFirst() { + columns, err = conn.GetColumns(tableFName, batch.Columns.Names()...) + if err != nil { + return count, g.Error(err, "could not get matching list of columns from table") + } + } + + err = func() error { + // COPY needs a transaction + if conn.Tx() == nil { + err = conn.Begin(&sql.TxOptions{Isolation: sql.LevelDefault}) + if err != nil { + return g.Error(err, "could not begin") + } + defer conn.Rollback() + } + + insFields, err := conn.ValidateColumnNames(columns.Names(), batch.Columns.Names(), true) + if err != nil { + return g.Error(err, "columns mismatch") + } + + insertStatement := conn.GenerateInsertStatement( + table.FullName(), + insFields, + 1, + ) + + stmt, err := conn.Prepare(insertStatement) + if err != nil { + g.Trace("%s: %#v", table, columns.Names()) + return g.Error(err, "could not prepare statement") + } + + decimalCols := []int{} + intCols := []int{} + int64Cols := []int{} + floatCols := []int{} + for i, col := range batch.Columns { + switch { + case col.Type == iop.DecimalType: + decimalCols = append(decimalCols, i) + case col.Type == iop.SmallIntType: + intCols = append(intCols, i) + case col.Type.IsInteger(): + int64Cols = append(int64Cols, i) + case col.Type == iop.FloatType: + floatCols = append(floatCols, i) + } + } + + for row := range batch.Rows { + var eG g.ErrorGroup + + // set decimals correctly + for _, colI := range decimalCols { + if row[colI] != nil { + val, err := decimal.NewFromString(cast.ToString(row[colI])) + if err == nil { + row[colI] = val + } + eG.Capture(err) + } + } + + // set Int32 correctly + for _, colI := range intCols { + if row[colI] != nil { + row[colI], err = cast.ToIntE(row[colI]) + eG.Capture(err) + } + } + + // set Int64 correctly + for _, colI := range int64Cols { + if row[colI] != nil { + row[colI], err = cast.ToInt64E(row[colI]) + eG.Capture(err) + } + } + + // set Float64 correctly + for _, colI := range floatCols { + if row[colI] != nil { + row[colI], err = cast.ToFloat64E(row[colI]) + eG.Capture(err) + } + } + + if err = eG.Err(); err != nil { + err = g.Error(err, "could not convert value for COPY into table %s", tableFName) + ds.Context.CaptureErr(err) + return err + } + + count++ + // Do insert + ds.Context.Lock() + _, err := stmt.Exec(row...) + ds.Context.Unlock() + if err != nil { + ds.Context.CaptureErr(g.Error(err, "could not COPY into table %s", tableFName)) + g.Trace("error for row: %#v", row) + return g.Error(err, "could not execute statement") + } + } + + err = stmt.Close() + if err != nil { + return g.Error(err, "could not close statement") + } + + err = conn.Commit() + if err != nil { + return g.Error(err, "could not commit transaction") + } + + return nil + }() + + if err != nil { + return count, g.Error(err, "could not copy data") + } + } + + ds.SetEmpty() + + g.Debug("COPY %d ROWS", count) + return count, nil +} + +// GenerateInsertStatement returns the proper INSERT statement +func (conn *ProtonConn) GenerateInsertStatement(tableName string, fields []string, numRows int) string { + + values := make([]string, len(fields)) + qFields := make([]string, len(fields)) // quoted fields + + valuesStr := "" + c := 0 + for n := 0; n < numRows; n++ { + for i, field := range fields { + c++ + values[i] = conn.bindVar(i+1, field, n, c) + qFields[i] = conn.Self().Quote(field) + } + valuesStr += fmt.Sprintf("(%s),", strings.Join(values, ", ")) + } + + if conn.GetProp("http_url") != "" { + table, _ := ParseTableName(tableName, conn.GetType()) + tableName = table.NameQ() + } + + statement := g.R( + "INSERT INTO {table} ({fields}) VALUES {values}", + "table", tableName, + "fields", strings.Join(qFields, ", "), + "values", strings.TrimSuffix(valuesStr, ","), + ) + g.Trace("insert statement: "+strings.Split(statement, ") VALUES ")[0]+")"+" x %d", numRows) + return statement +} + +// GenerateUpsertSQL generates the upsert SQL +func (conn *ProtonConn) GenerateUpsertSQL(srcTable string, tgtTable string, pkFields []string) (sql string, err error) { + upsertMap, err := conn.BaseConn.GenerateUpsertExpressions(srcTable, tgtTable, pkFields) + if err != nil { + err = g.Error(err, "could not generate upsert variables") + return + } + + sqlTempl := ` + ALTER TABLE {tgt_table} + DELETE WHERE ({pk_fields}) in ( + SELECT {pk_fields} + FROM {src_table} src + ) + ; + + INSERT INTO {tgt_table} + ({insert_fields}) + SELECT {src_fields} + FROM {src_table} src + ` + sql = g.R( + sqlTempl, + "src_table", srcTable, + "tgt_table", tgtTable, + "src_tgt_pk_equal", upsertMap["src_tgt_pk_equal"], + "insert_fields", upsertMap["insert_fields"], + "src_fields", upsertMap["src_fields"], + "pk_fields", upsertMap["pk_fields"], + ) + + return +} + +func processProtonInsertRow(columns iop.Columns, row []any) []any { + for i := range row { + if columns[i].Type == iop.DecimalType { + sVal := cast.ToString(row[i]) + if sVal != "" { + val, err := decimal.NewFromString(sVal) + if !g.LogError(err, "could not convert value `%s` for Proton decimal", sVal) { + row[i] = val + } + } else { + row[i] = nil + } + } else if columns[i].Type == iop.FloatType { + row[i] = cast.ToFloat64(row[i]) + } + } + return row +} diff --git a/core/dbio/database/database_redshift.go b/core/dbio/database/database_redshift.go index ae86fe343..68ecc9735 100755 --- a/core/dbio/database/database_redshift.go +++ b/core/dbio/database/database_redshift.go @@ -225,6 +225,7 @@ func (conn *RedshiftConn) BulkImportFlow(tableFName string, df *iop.Dataflow) (c df.Defer(func() { filesys.Delete(s3Fs, s3Path) }) // cleanup g.Info("writing to s3 for redshift import") + s3Fs.SetProp("null_as", `\N`) bw, err := s3Fs.WriteDataflow(df, s3Path) if err != nil { return df.Count(), g.Error(err, "error writing to s3") @@ -311,6 +312,8 @@ func (conn *RedshiftConn) CopyFromS3(tableFName, s3Path string, columns iop.Colu "aws_access_key_id", AwsID, "aws_secret_access_key", AwsAccessKey, ) + sql = conn.setEmptyAsNull(sql) + _, err = conn.Exec(sql) if err != nil { conn.WarnStlLoadErrors(err) @@ -320,6 +323,13 @@ func (conn *RedshiftConn) CopyFromS3(tableFName, s3Path string, columns iop.Colu return 0, nil } +func (conn *RedshiftConn) setEmptyAsNull(sql string) string { + if !cast.ToBool(conn.GetProp("empty_as_null")) { + sql = strings.ReplaceAll(sql, " EMPTYASNULL BLANKSASNULL", "") + } + return sql +} + func (conn *RedshiftConn) WarnStlLoadErrors(err error) { if strings.Contains(err.Error(), "stl_load_errors") { conn.Rollback() diff --git a/core/dbio/database/database_snowflake.go b/core/dbio/database/database_snowflake.go index 3a2504922..b69b0b3c6 100755 --- a/core/dbio/database/database_snowflake.go +++ b/core/dbio/database/database_snowflake.go @@ -244,6 +244,7 @@ func (conn *SnowflakeConn) BulkExportFlow(tables ...Table) (df *iop.Dataflow, er fs.SetProp("header", "false") fs.SetProp("format", "csv") + fs.SetProp("null_as", `\N`) fs.SetProp("columns", g.Marshal(columns)) fs.SetProp("metadata", conn.GetProp("metadata")) df, err = fs.ReadDataflow(filePath) @@ -487,6 +488,7 @@ func (conn *SnowflakeConn) CopyViaAWS(tableFName string, df *iop.Dataflow) (coun df.Defer(func() { filesys.Delete(s3Fs, s3Path) }) // cleanup g.Info("writing to s3 for snowflake import") + s3Fs.SetProp("null_as", `\N`) bw, err := s3Fs.WriteDataflow(df, s3Path) if err != nil { return df.Count(), g.Error(err, "Error in FileSysWriteDataflow") @@ -513,6 +515,7 @@ func (conn *SnowflakeConn) CopyFromS3(tableFName, s3Path string) (err error) { "aws_access_key_id", AwsID, "aws_secret_access_key", AwsAccessKey, ) + sql = conn.setEmptyAsNull(sql) g.Info("copying into snowflake from s3") g.Debug("url: " + s3Path) @@ -555,6 +558,7 @@ func (conn *SnowflakeConn) CopyViaAzure(tableFName string, df *iop.Dataflow) (co df.Defer(func() { filesys.Delete(azFs, azPath) }) // cleanup g.Info("writing to azure for snowflake import") + azFs.SetProp("null_as", `\N`) bw, err := azFs.WriteDataflow(df, azPath) if err != nil { return df.Count(), g.Error(err, "Error in FileSysWriteDataflow") @@ -578,6 +582,7 @@ func (conn *SnowflakeConn) CopyFromAzure(tableFName, azPath string) (err error) "azure_path", azPath, "azure_sas_token", azToken, ) + sql = conn.setEmptyAsNull(sql) g.Info("copying into snowflake from azure") g.Debug("url: " + azPath) @@ -703,6 +708,7 @@ func (conn *SnowflakeConn) CopyViaStage(tableFName string, df *iop.Dataflow) (co return } + fs.SetProp("null_as", `\N`) _, err = fs.WriteDataflowReady(df, folderPath, fileReadyChn, iop.DefaultStreamConfig()) if err != nil { @@ -774,6 +780,8 @@ func (conn *SnowflakeConn) CopyViaStage(tableFName string, df *iop.Dataflow) (co "src_columns", strings.Join(srcColumns, ", "), "stage_path", stageFilePath, ) + sql = conn.setEmptyAsNull(sql) + _, err = conn.Exec(sql) if err != nil { err = g.Error(err, "Error with COPY INTO") @@ -806,6 +814,8 @@ func (conn *SnowflakeConn) CopyViaStage(tableFName string, df *iop.Dataflow) (co "src_columns", strings.Join(srcColumns, ", "), "stage_path", stageFolderPath, ) + sql = conn.setEmptyAsNull(sql) + data, err := conn.Query(sql) if err != nil { err = g.Error(err, "Error with COPY INTO") @@ -842,6 +852,13 @@ func (conn *SnowflakeConn) CopyViaStage(tableFName string, df *iop.Dataflow) (co return df.Count(), nil } +func (conn *SnowflakeConn) setEmptyAsNull(sql string) string { + if !cast.ToBool(conn.GetProp("empty_as_null")) { + sql = strings.ReplaceAll(sql, "EMPTY_FIELD_AS_NULL=TRUE", "EMPTY_FIELD_AS_NULL=FALSE") + } + return sql +} + // GetFile Copies from a staging location to a local file or folder func (conn *SnowflakeConn) GetFile(internalStagePath, fPath string) (err error) { query := g.F( diff --git a/core/dbio/database/database_sqlserver.go b/core/dbio/database/database_sqlserver.go index ccad35e50..0b2b7cc51 100755 --- a/core/dbio/database/database_sqlserver.go +++ b/core/dbio/database/database_sqlserver.go @@ -377,7 +377,13 @@ func (conn *MsSQLServerConn) BcpImportFileParrallel(tableFName string, ds *iop.D // need to use delimiter not in field, or do some other transformation func (conn *MsSQLServerConn) BcpImportFile(tableFName, filePath string) (count uint64, err error) { var stderr, stdout bytes.Buffer - url, err := dburl.Parse(conn.URL) + + connURL := conn.URL + if su := conn.GetProp("ssh_url"); su != "" { + connURL = su // use ssh url if specified + } + + url, err := dburl.Parse(connURL) if err != nil { return } diff --git a/core/dbio/database/database_starrocks.go b/core/dbio/database/database_starrocks.go index eb13ada7d..03f13b1eb 100755 --- a/core/dbio/database/database_starrocks.go +++ b/core/dbio/database/database_starrocks.go @@ -427,6 +427,7 @@ func (conn *StarRocksConn) StreamLoad(feURL, tableFName string, df *iop.Dataflow fileReadyChn := make(chan filesys.FileReady, 10) go func() { + fs.SetProp("null_as", `\N`) _, err = fs.WriteDataflowReady(df, localPath, fileReadyChn, iop.DefaultStreamConfig()) if err != nil { df.Context.CaptureErr(g.Error(err, "error writing dataflow to local storage: "+localPath)) diff --git a/core/dbio/database/schemata.go b/core/dbio/database/schemata.go index e7f069f6c..8aec754f6 100644 --- a/core/dbio/database/schemata.go +++ b/core/dbio/database/schemata.go @@ -649,7 +649,7 @@ func ParseColumnName(text string, dialect dbio.Type) (colName string, err error) func GetQualifierQuote(dialect dbio.Type) string { quote := `"` switch dialect { - case dbio.TypeDbMySQL, dbio.TypeDbMariaDB, dbio.TypeDbStarRocks, dbio.TypeDbBigQuery, dbio.TypeDbClickhouse: + case dbio.TypeDbMySQL, dbio.TypeDbMariaDB, dbio.TypeDbStarRocks, dbio.TypeDbBigQuery, dbio.TypeDbClickhouse, dbio.TypeDbProton: quote = "`" case dbio.TypeDbBigTable, dbio.TypeDbMongoDB, dbio.TypeDbPrometheus: quote = "" diff --git a/core/dbio/dbio_types.go b/core/dbio/dbio_types.go index b3bcbf3c9..cc9590547 100644 --- a/core/dbio/dbio_types.go +++ b/core/dbio/dbio_types.go @@ -57,6 +57,7 @@ const ( TypeDbClickhouse Type = "clickhouse" TypeDbMongoDB Type = "mongodb" TypeDbPrometheus Type = "prometheus" + TypeDbProton Type = "proton" ) // ValidateType returns true is type is valid @@ -102,6 +103,7 @@ func (t Type) DefPort() int { TypeDbClickhouse: 9000, TypeDbMongoDB: 27017, TypeDbPrometheus: 9090, + TypeDbProton: 8463, TypeFileFtp: 21, TypeFileSftp: 22, } @@ -117,7 +119,7 @@ func (t Type) DBNameUpperCase() bool { func (t Type) Kind() Kind { switch t { case TypeDbPostgres, TypeDbRedshift, TypeDbStarRocks, TypeDbMySQL, TypeDbMariaDB, TypeDbOracle, TypeDbBigQuery, TypeDbBigTable, - TypeDbSnowflake, TypeDbSQLite, TypeDbSQLServer, TypeDbAzure, TypeDbClickhouse, TypeDbTrino, TypeDbDuckDb, TypeDbMotherDuck, TypeDbMongoDB, TypeDbPrometheus: + TypeDbSnowflake, TypeDbSQLite, TypeDbSQLServer, TypeDbAzure, TypeDbClickhouse, TypeDbTrino, TypeDbDuckDb, TypeDbMotherDuck, TypeDbMongoDB, TypeDbPrometheus, TypeDbProton: return KindDatabase case TypeFileLocal, TypeFileHDFS, TypeFileS3, TypeFileAzure, TypeFileGoogle, TypeFileSftp, TypeFileFtp, TypeFileHTTP, Type("https"): return KindFile @@ -175,6 +177,7 @@ func (t Type) NameLong() string { TypeDbClickhouse: "DB - Clickhouse", TypeDbPrometheus: "DB - Prometheus", TypeDbMongoDB: "DB - MongoDB", + TypeDbProton: "DB - Proton", } return mapping[t] @@ -210,6 +213,7 @@ func (t Type) Name() string { TypeDbPrometheus: "Prometheus", TypeDbMongoDB: "MongoDB", TypeDbAzure: "Azure", + TypeDbProton: "Proton", } return mapping[t] diff --git a/core/dbio/iop/dataset.go b/core/dbio/iop/dataset.go index 8b2b30836..19af2dcb4 100644 --- a/core/dbio/iop/dataset.go +++ b/core/dbio/iop/dataset.go @@ -444,7 +444,7 @@ func (data *Dataset) InferColumnTypes() { valStr := cast.ToString(val) l := len(valStr) - if val == nil || l == 0 { + if val == nil || l == 0 || (data.Sp.Config.NullIf != "" && data.Sp.Config.NullIf == valStr) { columns[j].Stats.NullCnt++ continue } else { diff --git a/core/dbio/iop/datastream.go b/core/dbio/iop/datastream.go index 499de97b2..0312073a7 100644 --- a/core/dbio/iop/datastream.go +++ b/core/dbio/iop/datastream.go @@ -94,18 +94,20 @@ func (m *Metadata) AsMap() map[string]any { // Iterator is the row provider for a datastream type Iterator struct { - Row []any - Reprocess chan []any - IsCasted bool - RowIsCasted bool - Counter uint64 - Context *g.Context - Closed bool - ds *Datastream - dsBufferI int // -1 means ds is not buffered - nextFunc func(it *Iterator) bool - limitCnt uint64 // to not check for df limit each cycle - + Row []any + Reprocess chan []any + IsCasted bool + RowIsCasted bool + Counter uint64 + StreamRowNum uint64 + Context *g.Context + Closed bool + ds *Datastream + dsBufferI int // -1 means ds is not buffered + nextFunc func(it *Iterator) bool + limitCnt uint64 // to not check for df limit each cycle + + prevStreamURL any dsBufferStream []string } @@ -709,7 +711,7 @@ loop: } ds.Columns = append(ds.Columns, col) metaValuesMap[col.Position-1] = func(it *Iterator) any { - return it.Counter + return it.StreamRowNum } } @@ -2358,6 +2360,18 @@ func (it *Iterator) addNewColumns(newRowLen int) { mux.Unlock() } +func (it *Iterator) incrementStreamRowNum() { + if it.dsBufferI == -1 { + return + } + if it.prevStreamURL == it.ds.Metadata.StreamURL.Value { + it.StreamRowNum++ + } else { + it.prevStreamURL = it.ds.Metadata.StreamURL.Value + it.StreamRowNum = 1 + } +} + func (it *Iterator) next() bool { it.RowIsCasted = false // reset RowIsCasted @@ -2379,12 +2393,14 @@ func (it *Iterator) next() bool { if it.dsBufferI < len(it.dsBufferStream) && it.dsBufferStream[it.dsBufferI] != "" { it.ds.Metadata.StreamURL.Value = it.dsBufferStream[it.dsBufferI] } + it.incrementStreamRowNum() it.dsBufferI++ return true } next := it.nextFunc(it) if next { + it.incrementStreamRowNum() it.Counter++ // logic to improve perf but not checking if diff --git a/core/dbio/iop/stream_processor.go b/core/dbio/iop/stream_processor.go index dfd6dfe16..611dedba3 100644 --- a/core/dbio/iop/stream_processor.go +++ b/core/dbio/iop/stream_processor.go @@ -45,6 +45,7 @@ type StreamConfig struct { Header bool `json:"header"` Compression string `json:"compression"` // AUTO | ZIP | GZIP | SNAPPY | NONE NullIf string `json:"null_if"` + NullAs string `json:"null_as"` DatetimeFormat string `json:"datetime_format"` SkipBlankLines bool `json:"skip_blank_lines"` Delimiter string `json:"delimiter"` @@ -272,6 +273,9 @@ func (sp *StreamProcessor) SetConfig(configMap map[string]string) { if configMap["null_if"] != "" { sp.Config.NullIf = configMap["null_if"] } + if configMap["null_as"] != "" { + sp.Config.NullAs = configMap["null_as"] + } if configMap["trim_space"] != "" { sp.Config.TrimSpace = cast.ToBool(configMap["trim_space"]) } @@ -816,7 +820,7 @@ func (sp *StreamProcessor) CastToString(i int, val interface{}, valType ...Colum switch { case val == nil: - return "" + return sp.Config.NullAs case sp.Config.BoolAsInt && typ.IsBool(): switch cast.ToString(val) { case "true", "1", "TRUE": diff --git a/core/dbio/templates/oracle.yaml b/core/dbio/templates/oracle.yaml index 4b8601464..272629376 100755 --- a/core/dbio/templates/oracle.yaml +++ b/core/dbio/templates/oracle.yaml @@ -303,5 +303,5 @@ variable: error_ignore_drop_view: "ORA-00942" bind_string: ":{field}{n}" batch_rows: 20 - date_layout_str: TO_DATE('{value}', 'YYYY-MM-DD HH24:MI:SS') + date_layout_str: TO_DATE('{value}', 'YYYY-MM-DD HH24:MI:SS') # DATE in oracle has a time component timestamp_layout_str: TO_TIMESTAMP('{value}', 'YYYY-MM-DD HH24:MI:SS.FF6') \ No newline at end of file diff --git a/core/dbio/templates/proton.yaml b/core/dbio/templates/proton.yaml new file mode 100755 index 000000000..bad17cf02 --- /dev/null +++ b/core/dbio/templates/proton.yaml @@ -0,0 +1,259 @@ +core: + drop_table: drop table if exists {table} + drop_view: drop view if exists {view} + create_schema: create database {schema} + create_table: create table {table} ({col_types}) engine=MergeTree {partition_by} ORDER BY tuple() + create_temporary_table: create table {table} ({col_types}) engine=Memory + rename_table: ALTER TABLE {table} RENAME TO {new_table} + alter_columns: alter table {table} modify column {col_ddl} + modify_column: '{column} {type}' + update: alter table {table} update {set_fields} where {pk_fields_equal} + + +metadata: + + current_database: + select currentDatabase() + + databases: | + select currentDatabase() as name + + # clickhouse does not have schemas + # has database and table, for example: database1.table1 + # for our purpose a schema is a database + schemas: | + select name as schema_name + from system.databases + order by name + + tables: | + select name as table_name + from system.tables + where engine not in ('View') + and database = '{schema}' + order by name + + views: | + select name as table_name + from system.tables + where engine = 'View' + and database = '{schema}' + order by name + + columns: | + select name as column_name, type as data_type + from system.columns + where database = '{schema}' + and table = '{table}' + order by position + + primary_keys: | + select 1 + + indexes: | + SELECT 1 + + columns_full: | + with tables as ( + select + database, + name as table_name, + engine in ('View') as is_view + from system.tables + where database = '{schema}' and name = '{table}' + ) + select + cols.database as schema_name, + cols.table as table_name, + cols.name as column_name, + cols.type as data_type, + cols.position as position + from system.columns as cols + join tables + on tables.database = cols.database + and tables.table_name = cols.table + order by cols.database, cols.table, cols.position + + schemata: | + with tables as ( + select + database, + name as table_name, + engine in ('View') as is_view + from system.tables + where 1=1 + {{if .schema -}} and database = '{schema}' {{- end}} + {{if .tables -}} and name in ({tables}) {{- end}} + ) + select + cols.database as schema_name, + cols.table as table_name, + tables.is_view as is_view, + cols.name as column_name, + cols.type as data_type, + cols.position as position + from system.columns as cols + join tables + on tables.database = cols.database + and tables.table_name = cols.table + order by cols.database, cols.table, cols.position + + ddl_table: + SHOW CREATE TABLE `{schema}`.`{table}` + + ddl_view: | + SHOW CREATE VIEW `{schema}`.`{table}` + + sessions: + select * + from pg_stat_activity + where state = 'active' + + session_terminate: + select pg_terminate_backend({pid}) + +analysis: + field_chars: | + select + '{schema}' as schema_nm, + '{table}' as table_nm, + '{field}' as field, sum(case when cast({field} as text) ~ '\n' then 1 else 0 end) as cnt_nline, + sum(case when cast({field} as text) ~ '\t' then 1 else 0 end) as cnt_tab, + sum(case when cast({field} as text) ~ ',' then 1 else 0 end) as cnt_comma, + sum(case when cast({field} as text) ~ '"' then 1 else 0 end) as cnt_dquote, + min(char_length(cast({field} as text))) as f_min_len, + max(char_length(cast({field} as text))) as f_max_len + from `{schema}`.`{table}` + + field_stat_len: | + -- field_stat_len {table} + select + '{schema}' as schema_nm, + '{table}' as table_nm, + '{field}' as field, + '{type}' as type, + count(*) as tot_cnt, + min(char_length({field})) as f_min_len, + max(char_length({field})) as f_max_len + from `{schema}`.`{table}` + + field_stat_deep: | + select + '{schema}' as schema_nm, + '{table}' as table_nm, + '{field}' as field, + count(*) as tot_cnt, + count({field}) as f_cnt, + count(*) - count({field}) as f_null_cnt, + round(100.0 * (count(*) - count({field})) / count(*),1) as f_null_prct, + count(distinct {field}) as f_dstct_cnt, + round(100.0 * count(distinct {field}) / count(*),1) as f_dstct_prct, + count(*) - count(distinct {field}) as f_dup_cnt, + min({field}) as f_min, + max({field}) as f_max, + min(char_length(cast({field} as text))) as f_min_len, + max(char_length(cast({field} as text))) as f_max_len + from `{schema}`.`{table}` + + distro_field: | + with t1 as ( + select + '{field}'::text as field, + {field}, + count(*) cnt + from `{schema}`.`{table}` + group by {field} + order by count(*) desc + ) + , t2 as ( + select + '{field}'::text as field, + count(*) ttl_cnt + from `{schema}`.`{table}` + ) + select + '{table}' as table_nm, + t1.field, + {field} as value, + cnt, + round(100.0 * cnt / ttl_cnt, 2) as prct + from t1 + join t2 + on t1.field = t2.field + order by cnt desc + + distro_field_group: | + with t1 as ( + select + '{field}'::text as field, + {group_expr} as group_exp, + {field}, + count(*) cnt + from `{schema}`.`{table}` + group by {field}, {group_expr} + order by count(*) desc + ) + , t2 as ( + select + '{field}'::text as field, + count(*) ttl_cnt + from `{schema}`.`{table}` + ) + select + '{table}' as table_nm, + t1.field, + t1.group_exp, + {field} as value, + cnt, + round(100.0 * cnt / ttl_cnt, 2) as prct + from t1 + join t2 + on t1.field = t2.field + order by cnt desc + + distro_field_date: | + with t1 as ( + select + '{field}'::text as field, + extract(year from {field}) as year, + extract(month from {field}) as month, + count(*) cnt + from `{schema}`.`{table}` + group by extract(year from {field}), extract(month from {field}) + order by extract(year from {field}), extract(month from {field}) + ) + , t2 as ( + select '{field}'::text as field, count(*) ttl_cnt + from `{schema}`.`{table}` + ) + select + '{schema}' as schema_nm, + '{table}' as table_nm, + t1.field, + t1.year, + t1.month, + cnt, + round(100.0 * cnt / ttl_cnt, 2) as prct + from t1 + join t2 + on t1.field = t2.field + order by t1.year, t1.month + +function: + truncate_f: round({field}, 2, 1) + truncate_datef: CONVERT(DATETIME, CONVERT(DATE, {field})) + checksum_string: char_length({field}) + checksum_datetime: toUnixTimestamp64Nano(toDateTime64({field}, 6)) / 1000 + # checksum_datetime: toUnixTimestamp64Nano(toDateTime64({field}, 6)) / 1000 + checksum_decimal: ABS(CAST({field} as Nullable(Int64))) + + +variable: + # bind_string: "@p{c}" + batch_rows: 200 + batch_values: 2000 + bool_as: string + error_filter_table_exists: already + quote_char: '`' + timestamp_layout: '2006-01-02 15:04:05.000000 -07' + timestamp_layout_str: parseDateTime64BestEffortOrNull('{value}') \ No newline at end of file diff --git a/core/dbio/templates/snowflake.yaml b/core/dbio/templates/snowflake.yaml index 61008fb02..ec9dda7ac 100755 --- a/core/dbio/templates/snowflake.yaml +++ b/core/dbio/templates/snowflake.yaml @@ -21,7 +21,7 @@ core: ESCAPE_UNENCLOSED_FIELD = NONE FIELD_OPTIONALLY_ENCLOSED_BY='0x22' EMPTY_FIELD_AS_NULL=TRUE - NULL_IF = '' + NULL_IF = '\\N' SKIP_HEADER=1 REPLACE_INVALID_CHARACTERS=TRUE ) @@ -39,7 +39,7 @@ core: ESCAPE_UNENCLOSED_FIELD = NONE FIELD_OPTIONALLY_ENCLOSED_BY='0x22' EMPTY_FIELD_AS_NULL=TRUE - NULL_IF = '' + NULL_IF = '\\N' SKIP_HEADER=1 REPLACE_INVALID_CHARACTERS=TRUE ) @@ -56,7 +56,7 @@ core: ESCAPE_UNENCLOSED_FIELD = NONE FIELD_OPTIONALLY_ENCLOSED_BY='0x22' EMPTY_FIELD_AS_NULL=TRUE - NULL_IF = '' + NULL_IF = '\\N' SKIP_HEADER=1 REPLACE_INVALID_CHARACTERS=TRUE ) @@ -67,8 +67,7 @@ core: FILE_FORMAT = ( TYPE = CSV RECORD_DELIMITER = '\n' - EMPTY_FIELD_AS_NULL = TRUE - NULL_IF = '' + NULL_IF = '\\N' COMPRESSION = GZIP ESCAPE_UNENCLOSED_FIELD = NONE FIELD_OPTIONALLY_ENCLOSED_BY='0x22' @@ -84,8 +83,7 @@ core: FILE_FORMAT = ( TYPE = CSV RECORD_DELIMITER = '\n' - EMPTY_FIELD_AS_NULL = TRUE - NULL_IF = '' + NULL_IF = '\\N' COMPRESSION = GZIP ESCAPE_UNENCLOSED_FIELD = NONE FIELD_OPTIONALLY_ENCLOSED_BY='0x22' @@ -100,8 +98,7 @@ core: FILE_FORMAT = ( TYPE = CSV RECORD_DELIMITER = '\n' - EMPTY_FIELD_AS_NULL = TRUE - NULL_IF = '' + NULL_IF = '\\N' COMPRESSION = GZIP ESCAPE_UNENCLOSED_FIELD = NONE FIELD_OPTIONALLY_ENCLOSED_BY='0x22' diff --git a/core/dbio/templates/types_native_to_general.tsv b/core/dbio/templates/types_native_to_general.tsv index 252969116..c33449bdf 100755 --- a/core/dbio/templates/types_native_to_general.tsv +++ b/core/dbio/templates/types_native_to_general.tsv @@ -238,6 +238,7 @@ oracle blob text col_blob blob FALSE FALSE Unstructured binary data. oracle char string col_char char(17) TRUE TRUE Fixed-length character data of length size bytes. oracle clob text col_clob clob TRUE TRUE Single-byte character data. oracle date datetime col_date date TRUE TRUE Fixed-length date and time data, ranging from Jan. 1, 4712 B.C.E. to Dec. 31, 4712 C.E. +oracle datetime datetime col_date datetime TRUE TRUE Fixed-length date and time data, ranging from Jan. 1, 4712 B.C.E. to Dec. 31, 4712 C.E. oracle float float col_float float TRUE TRUE oracle json json col_json json oracle long string col_long long TRUE FALSE Variable-length raw binary data. @@ -345,6 +346,32 @@ postgres boolean[] json FALSE FALSE Steampipe Data Type postgres double precision[] json FALSE FALSE Steampipe Data Type postgres regtype string postgres void FALSE FALSE +proton ipv6 string col_enum8 json FALSE FALSE +proton array json col_array array FALSE FALSE +proton uuid string col_uuid array FALSE FALSE +proton date date col_date date TRUE TRUE +proton datetime datetime col_datetime datetime TRUE TRUE +proton datetime64 datetime col_datetime64 datetime64 TRUE TRUE +proton decimal decimal col_decimal decimal TRUE TRUE +proton enum string col_enum enum FALSE FALSE +proton fixedstring text col_fixedstring fixedstring TRUE TRUE +proton float32 float col_float32 float32 TRUE TRUE +proton float64 float col_float64 float64 TRUE TRUE +proton int16 smallint col_int16 int16 TRUE TRUE +proton int32 bigint col_int32 int32 TRUE TRUE +proton int64 bigint col_int64 int64 TRUE TRUE +proton int8 integer col_int8 int8 TRUE TRUE +proton string text col_string string TRUE TRUE +proton tuple string col_tuple tuple TRUE TRUE +proton uint16 integer col_uint16 uint16 TRUE TRUE +proton uint32 bigint col_uint32 uint32 TRUE TRUE +proton uint64 decimal(28,0) col_uint64 uint64 TRUE TRUE +proton uint8 integer col_uint8 uint8 TRUE TRUE +proton json json col_json json FALSE FALSE +proton map json col_map json FALSE FALSE +proton lowcardinality string col_lowcardinality json FALSE FALSE +proton enum8 string col_enum8 json FALSE FALSE +proton ipv6 string col_enum8 json FALSE FALSE redshift bigint bigint col_bigint bigint TRUE TRUE signed eight-byte integer redshift boolean bool col_boolean boolean TRUE FALSE logical boolean (true/false) redshift bool bool col_bool bool TRUE FALSE logical boolean (true/false) diff --git a/core/sling/config.go b/core/sling/config.go index d6d0c414f..1b892882c 100644 --- a/core/sling/config.go +++ b/core/sling/config.go @@ -4,6 +4,7 @@ import ( "database/sql/driver" "io" "os" + "path/filepath" "regexp" "strings" "time" @@ -114,7 +115,7 @@ func (cfg *Config) SetDefault() { case dbio.TypeDbBigQuery, dbio.TypeDbBigTable: cfg.Source.Options.MaxDecimals = g.Int(9) cfg.Target.Options.MaxDecimals = g.Int(9) - case dbio.TypeDbClickhouse: + case dbio.TypeDbClickhouse, dbio.TypeDbProton: cfg.Source.Options.MaxDecimals = g.Int(11) cfg.Target.Options.MaxDecimals = g.Int(11) } @@ -145,7 +146,7 @@ func (cfg *Config) SetDefault() { } if val := os.Getenv("SLING_LOADED_AT_COLUMN"); val != "" { - cfg.MetadataLoadedAt = cast.ToBool(val) + cfg.MetadataLoadedAt = g.Bool(cast.ToBool(val)) } if val := os.Getenv("SLING_STREAM_URL_COLUMN"); val != "" { cfg.MetadataStreamURL = cast.ToBool(val) @@ -212,7 +213,11 @@ func (cfg *Config) Unmarshal(cfgStr string) error { // add config path if g.PathExists(cfgStr) && !cfg.ReplicationMode { - cfg.Env["SLING_CONFIG_PATH"] = cfgStr + fp, err := filepath.Abs(cfgStr) + if err != nil { + fp = cfgStr + } + cfg.Env["SLING_CONFIG_PATH"] = fp } return nil @@ -270,7 +275,7 @@ func (cfg *Config) DetermineType() (Type JobType, err error) { } } else if srcFileProvided && cfg.Source.UpdateKey == slingLoadedAtColumn { // need to loaded_at column for file incremental - cfg.MetadataLoadedAt = true + cfg.MetadataLoadedAt = g.Bool(true) } else if cfg.Source.UpdateKey == "" && len(cfg.Source.PrimaryKey()) == 0 { err = g.Error("must specify value for 'update_key' and/or 'primary_key' for incremental mode. See docs for more details: https://docs.slingdata.io/sling-cli/run/configuration") if args := os.Getenv("SLING_CLI_ARGS"); strings.Contains(args, "-src-conn") || strings.Contains(args, "-tgt-conn") { @@ -294,7 +299,7 @@ func (cfg *Config) DetermineType() (Type JobType, err error) { return } } else if cfg.Mode == SnapshotMode { - cfg.MetadataLoadedAt = true // needed for snapshot mode + cfg.MetadataLoadedAt = g.Bool(true) // needed for snapshot mode } if srcDbProvided && tgtDbProvided { @@ -658,10 +663,10 @@ func (cfg *Config) GetFormatMap() (m map[string]any, err error) { } } if table.Schema != "" { - m["stream_schema"] = table.Schema + m["stream_schema"] = strings.ToLower(table.Schema) } if table.Name != "" { - m["stream_table"] = table.Name + m["stream_table"] = strings.ToLower(table.Name) } if cfg.StreamName != "" { @@ -806,10 +811,10 @@ type Config struct { IncrementalVal string `json:"-" yaml:"-"` ReplicationMode bool `json:"-" yaml:"-"` - MetadataLoadedAt bool `json:"-" yaml:"-"` - MetadataStreamURL bool `json:"-" yaml:"-"` - MetadataRowNum bool `json:"-" yaml:"-"` - MetadataRowID bool `json:"-" yaml:"-"` + MetadataLoadedAt *bool `json:"-" yaml:"-"` + MetadataStreamURL bool `json:"-" yaml:"-"` + MetadataRowNum bool `json:"-" yaml:"-"` + MetadataRowID bool `json:"-" yaml:"-"` } // Scan scan value into Jsonb, implements sql.Scanner interface @@ -999,7 +1004,7 @@ var SourceFileOptionsDefault = SourceOptions{ } var SourceDBOptionsDefault = SourceOptions{ - EmptyAsNull: g.Bool(true), + EmptyAsNull: g.Bool(false), NullIf: g.String("NULL"), DatetimeFormat: "AUTO", MaxDecimals: g.Int(-1), diff --git a/core/sling/replication.go b/core/sling/replication.go index 3b352b27b..76f2d684d 100644 --- a/core/sling/replication.go +++ b/core/sling/replication.go @@ -5,6 +5,7 @@ import ( "database/sql/driver" "io" "os" + "path/filepath" "strings" "github.com/flarco/g" @@ -504,7 +505,12 @@ func LoadReplicationConfig(cfgPath string) (config ReplicationConfig, err error) return } - config.Env["SLING_CONFIG_PATH"] = cfgPath + // get file path + fp, err := filepath.Abs(cfgPath) + if err != nil { + fp = cfgPath + } + config.Env["SLING_CONFIG_PATH"] = fp return } diff --git a/core/sling/task.go b/core/sling/task.go index 1f763e6ee..ddcfd9f55 100644 --- a/core/sling/task.go +++ b/core/sling/task.go @@ -18,7 +18,8 @@ import ( ) // Set in the store/store.go file for history keeping -var StoreInsert, StoreUpdate func(t *TaskExecution) +var StoreInsert = func(t *TaskExecution) {} +var StoreUpdate = func(t *TaskExecution) {} // TaskExecution is a sling ELT task run, synonymous to an execution type TaskExecution struct { @@ -246,6 +247,11 @@ func (t *TaskExecution) GetCount() (count uint64) { return t.df.Count() } +// Df return the dataflow object +func (t *TaskExecution) Df() *iop.Dataflow { + return t.df +} + // GetRate return the speed of flow (rows / sec and bytes / sec) // secWindow is how many seconds back to measure (0 is since beginning) func (t *TaskExecution) GetRate(secWindow int) (rowRate, byteRate int64) { @@ -280,8 +286,8 @@ func (t *TaskExecution) GetRate(secWindow int) (rowRate, byteRate int64) { } func (t *TaskExecution) setGetMetadata() (metadata iop.Metadata) { - // need to loaded_at column for file incremental - if t.Config.MetadataLoadedAt || t.Type == FileToDB { + if (t.Config.MetadataLoadedAt != nil && *t.Config.MetadataLoadedAt) || + (t.Config.MetadataLoadedAt == nil && t.Type == FileToDB) { metadata.LoadedAt.Key = slingLoadedAtColumn metadata.LoadedAt.Value = t.StartTime.Unix() } diff --git a/core/sling/task_func.go b/core/sling/task_func.go index 1c6437052..b2613e095 100644 --- a/core/sling/task_func.go +++ b/core/sling/task_func.go @@ -231,16 +231,20 @@ func getIncrementalValue(cfg *Config, tgtConn database.Connection, srcConnVarMap value := data.Rows[0][0] colType := data.Columns[0].Type - if colType.IsDatetime() { - val = g.R( - srcConnVarMap["timestamp_layout_str"], - "value", cast.ToTime(value).Format(srcConnVarMap["timestamp_layout"]), - ) - } else if colType == iop.DateType { + + // oracle's DATE type is mapped to datetime, but needs to use the TO_DATE function + isOracleDate := data.Columns[0].DbType == "DATE" && tgtConn.GetType() == dbio.TypeDbOracle + + if colType.IsDate() || isOracleDate { val = g.R( srcConnVarMap["date_layout_str"], "value", cast.ToTime(value).Format(srcConnVarMap["date_layout"]), ) + } else if colType.IsDatetime() { + val = g.R( + srcConnVarMap["timestamp_layout_str"], + "value", cast.ToTime(value).Format(srcConnVarMap["timestamp_layout"]), + ) } else if colType.IsNumber() { val = cast.ToString(value) } else { diff --git a/core/sling/task_run_read.go b/core/sling/task_run_read.go index d53c14040..e0e1e7872 100644 --- a/core/sling/task_run_read.go +++ b/core/sling/task_run_read.go @@ -133,12 +133,15 @@ func (t *TaskExecution) ReadFromDB(cfg *Config, srcConn database.Connection) (df startValue := rangeArr[0] endValue := rangeArr[1] - if updateCol.IsDatetime() { - timestampTemplate := srcConn.GetTemplateValue("variable.timestamp_layout_str") + // oracle's DATE type is mapped to datetime, but needs to use the TO_DATE function + isOracleDate := updateCol.DbType == "DATE" && srcConn.GetType() == dbio.TypeDbOracle + + if updateCol.IsDate() || isOracleDate { + timestampTemplate := srcConn.GetTemplateValue("variable.date_layout_str") startValue = g.R(timestampTemplate, "value", startValue) endValue = g.R(timestampTemplate, "value", endValue) - } else if updateCol.IsDate() { - timestampTemplate := srcConn.GetTemplateValue("variable.date_layout_str") + } else if updateCol.IsDatetime() { + timestampTemplate := srcConn.GetTemplateValue("variable.timestamp_layout_str") startValue = g.R(timestampTemplate, "value", startValue) endValue = g.R(timestampTemplate, "value", endValue) } else if updateCol.IsString() { diff --git a/core/sling/task_run_write.go b/core/sling/task_run_write.go index c10de365d..8e9fe2316 100644 --- a/core/sling/task_run_write.go +++ b/core/sling/task_run_write.go @@ -378,7 +378,7 @@ func (t *TaskExecution) WriteToDb(cfg *Config, df *iop.Dataflow, tgtConn databas switch tgtConn.GetType() { case dbio.TypeDbSnowflake, dbio.TypeDbDuckDb: txOptions = sql.TxOptions{} - case dbio.TypeDbClickhouse, dbio.TypeDbOracle: + case dbio.TypeDbClickhouse, dbio.TypeDbProton, dbio.TypeDbOracle: txOptions = sql.TxOptions{Isolation: sql.LevelDefault} } err = tgtConn.BeginContext(df.Context.Ctx, &txOptions) diff --git a/core/sling/types.go b/core/sling/types.go index 07ce5f1ff..375a34bce 100644 --- a/core/sling/types.go +++ b/core/sling/types.go @@ -27,6 +27,20 @@ const FileToFile JobType = "file-file" // DbSQL is for a db sql query const DbSQL JobType = "db-sql" +var AllJobType = []struct { + Value JobType + TSName string +}{ + {ConnTest, "ConnTest"}, + {ConnDiscover, "ConnDiscover"}, + {ConnExec, "ConnExec"}, + {DbToDb, "DbToDb"}, + {FileToDB, "FileToDB"}, + {DbToFile, "DbToFile"}, + {FileToFile, "FileToFile"}, + {DbSQL, "DbSQL"}, +} + // ExecStatus is the status of an execution type ExecStatus string @@ -55,6 +69,23 @@ const ( ExecStatusStalled ExecStatus = "stalled" ) +var AllExecStatus = []struct { + Value ExecStatus + TSName string +}{ + {ExecStatusCreated, "ExecStatusCreated"}, + {ExecStatusQueued, "ExecStatusQueued"}, + {ExecStatusStarted, "ExecStatusStarted"}, + {ExecStatusRunning, "ExecStatusRunning"}, + {ExecStatusSuccess, "ExecStatusSuccess"}, + {ExecStatusTerminated, "ExecStatusTerminated"}, + {ExecStatusInterrupted, "ExecStatusInterrupted"}, + {ExecStatusTimedOut, "ExecStatusTimedOut"}, + {ExecStatusError, "ExecStatusError"}, + {ExecStatusSkipped, "ExecStatusSkipped"}, + {ExecStatusStalled, "ExecStatusStalled"}, +} + // IsRunning returns true if an execution is running func (s ExecStatus) IsRunning() bool { switch s { diff --git a/core/store/db.go b/core/store/db.go index 92c053b35..cae6bb81b 100644 --- a/core/store/db.go +++ b/core/store/db.go @@ -50,21 +50,29 @@ func InitDB() { &Replication{}, } + // manual migrations + migrate() + for _, table := range allTables { dryDB := Db.Session(&gorm.Session{DryRun: true}) tableName := dryDB.Find(table).Statement.Table if DropAll { Db.Exec(g.F(`drop table if exists "%s"`, tableName)) } - g.Trace("Creating table: " + tableName) err = Db.AutoMigrate(table) if err != nil { g.Debug("error AutoMigrating table for local .sling.db. => %s\n%s", tableName, err.Error()) return } } +} + +func migrate() { + // migrations + Db.Migrator().RenameColumn(&Task{}, "task", "config") // rename column for consistency + Db.Migrator().RenameColumn(&Replication{}, "replication", "config") // rename column for consistency - // fix bad unique index + // fix bad unique index on Execution.ExecID data, _ := Conn.Query(`SELECT name FROM sqlite_master WHERE type = 'index' AND sql LIKE '%UNIQUE%' /* nD */`) if len(data.Rows) > 0 { Db.Exec(g.F("drop index if exists %s", data.Rows[0][0])) diff --git a/core/store/store.go b/core/store/store.go index 704740dbb..d4de108ce 100644 --- a/core/store/store.go +++ b/core/store/store.go @@ -1,13 +1,11 @@ package store import ( - "net/http" "os" "strings" "time" "github.com/flarco/g" - "github.com/flarco/g/net" "github.com/slingdata-io/sling-cli/core" "github.com/slingdata-io/sling-cli/core/dbio/connection" "github.com/slingdata-io/sling-cli/core/sling" @@ -20,6 +18,8 @@ func init() { sling.StoreUpdate = StoreUpdate } +var syncStatus = func(t sling.TaskExecution) {} + // Execution is a task execute in the store. PK = exec_id + stream_id type Execution struct { // ID auto-increments @@ -28,7 +28,7 @@ type Execution struct { ExecID string `json:"exec_id,omitempty" gorm:"index"` // StreamID represents the stream inside the replication that is running. - // Is an MD5 construct:`md5(Source, Target, Stream)`. + // Is an MD5 construct:`md5(Source, Target, Stream, Object)`. StreamID string `json:"stream_id,omitempty" sql:"not null" gorm:"index"` // ConfigMD5 points to config table. not null @@ -73,7 +73,7 @@ type Task struct { Type sling.JobType `json:"type" gorm:"index"` - Task sling.Config `json:"task"` + Config sling.Config `json:"config"` CreatedDt time.Time `json:"created_dt" gorm:"autoCreateTime"` UpdatedDt time.Time `json:"updated_dt" gorm:"autoUpdateTime"` @@ -89,7 +89,7 @@ type Replication struct { Type sling.JobType `json:"type" gorm:"index"` - Replication sling.ReplicationConfig `json:"replication"` + Config sling.ReplicationConfig `json:"config"` CreatedDt time.Time `json:"created_dt" gorm:"autoCreateTime"` UpdatedDt time.Time `json:"updated_dt" gorm:"autoUpdateTime"` @@ -102,7 +102,7 @@ func ToExecutionObject(t *sling.TaskExecution) *Execution { exec := Execution{ ExecID: t.ExecID, - StreamID: g.MD5(t.Config.Source.Conn, t.Config.Target.Conn, t.Config.Source.Stream), + StreamID: g.MD5(t.Config.Source.Conn, t.Config.Target.Conn, t.Config.StreamName, t.Config.Target.Object), Status: t.Status, StartTime: t.StartTime, EndTime: t.EndTime, @@ -125,10 +125,10 @@ func ToExecutionObject(t *sling.TaskExecution) *Execution { } } - if t.Replication != nil && t.Replication.Env["SLING_CONFIG_PATH"] != nil { + if fileName := os.Getenv("SLING_REPLICATION_NAME"); fileName != "" { + exec.FilePath = g.String(fileName) + } else if t.Replication != nil && t.Replication.Env["SLING_CONFIG_PATH"] != nil { exec.FilePath = g.String(cast.ToString(t.Replication.Env["SLING_CONFIG_PATH"])) - } else if fileID := os.Getenv("SLING_REPLICATION_ID"); fileID != "" { - exec.FilePath = g.String(fileID) } return &exec @@ -140,8 +140,8 @@ func ToConfigObject(t *sling.TaskExecution) (task *Task, replication *Replicatio } task = &Task{ - Type: t.Type, - Task: *t.Config, + Type: t.Type, + Config: *t.Config, } projID := t.Config.Env["SLING_PROJECT_ID"] @@ -151,10 +151,10 @@ func ToConfigObject(t *sling.TaskExecution) (task *Task, replication *Replicatio if t.Replication != nil { replication = &Replication{ - Name: t.Config.Env["SLING_CONFIG_PATH"], - Type: t.Type, - MD5: t.Replication.MD5(), - Replication: *t.Replication, + Name: t.Config.Env["SLING_CONFIG_PATH"], + Type: t.Type, + MD5: t.Replication.MD5(), + Config: *t.Replication, } if projID != "" { @@ -163,24 +163,24 @@ func ToConfigObject(t *sling.TaskExecution) (task *Task, replication *Replicatio } // clean up - if strings.Contains(task.Task.Source.Conn, "://") { - task.Task.Source.Conn = strings.Split(task.Task.Source.Conn, "://")[0] + "://" + if strings.Contains(task.Config.Source.Conn, "://") { + task.Config.Source.Conn = strings.Split(task.Config.Source.Conn, "://")[0] + "://" } - if strings.Contains(task.Task.Target.Conn, "://") { - task.Task.Target.Conn = strings.Split(task.Task.Target.Conn, "://")[0] + "://" + if strings.Contains(task.Config.Target.Conn, "://") { + task.Config.Target.Conn = strings.Split(task.Config.Target.Conn, "://")[0] + "://" } - task.Task.Source.Data = nil - task.Task.Target.Data = nil + task.Config.Source.Data = nil + task.Config.Target.Data = nil - task.Task.SrcConn = connection.Connection{} - task.Task.TgtConn = connection.Connection{} + task.Config.SrcConn = connection.Connection{} + task.Config.TgtConn = connection.Connection{} - task.Task.Prepared = false + task.Config.Prepared = false - delete(task.Task.Env, "SLING_PROJECT_ID") - delete(task.Task.Env, "SLING_CONFIG_PATH") + delete(task.Config.Env, "SLING_PROJECT_ID") + delete(task.Config.Env, "SLING_CONFIG_PATH") // set md5 task.MD5 = t.Config.MD5() @@ -228,8 +228,8 @@ func StoreInsert(t *sling.TaskExecution) { t.ExecID = exec.ExecID - // send status - sendStatus(*exec) + // sync status + syncStatus(*t) } // Store saves the task into the local sqlite @@ -260,20 +260,6 @@ func StoreUpdate(t *sling.TaskExecution) { return } - // send status - sendStatus(*exec) -} - -func sendStatus(exec Execution) { - if os.Getenv("SLING_STATUS_URL") == "" { - return - } - - headers := map[string]string{"Content-Type": "application/json"} - exec.Output = "" // no need for output - payload := g.Marshal(exec) - net.ClientDo( - http.MethodPost, os.Getenv("SLING_STATUS_URL"), - strings.NewReader(payload), headers, 3, - ) + // sync status + syncStatus(*t) } diff --git a/go.mod b/go.mod index eae66bccc..cb71f81d9 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ module github.com/slingdata-io/sling-cli -go 1.21 - -toolchain go1.21.1 +go 1.21.1 require ( cloud.google.com/go v0.112.1 @@ -20,7 +18,7 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.16.0 github.com/flarco/bigquery v0.0.9 - github.com/flarco/g v0.1.96 + github.com/flarco/g v0.1.97 github.com/getsentry/sentry-go v0.27.0 github.com/go-sql-driver/mysql v1.7.1 github.com/gobwas/glob v0.2.3 @@ -36,7 +34,7 @@ require ( github.com/kshedden/datareader v0.0.0-20210325133423-816b6ffdd011 github.com/lib/pq v1.10.2 github.com/linkedin/goavro/v2 v2.12.0 - github.com/mattn/go-sqlite3 v1.14.16 + github.com/mattn/go-sqlite3 v1.14.22 github.com/microsoft/go-mssqldb v1.7.0 github.com/nqd/flat v0.1.1 github.com/parquet-go/parquet-go v0.20.0 @@ -51,23 +49,26 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible github.com/shopspring/decimal v1.3.1 github.com/sijms/go-ora/v2 v2.8.10-0.20240228213529-2ce633cb669f + github.com/slingdata-io/sling v0.0.0-20240426022644-3c31b1eb088e github.com/snowflakedb/gosnowflake v1.8.0 github.com/spf13/cast v1.5.0 github.com/stretchr/testify v1.9.0 + github.com/timeplus-io/proton-go-driver/v2 v2.0.17 github.com/trinodb/trino-go-client v0.313.0 + github.com/wailsapp/wails/v2 v2.8.1 github.com/xo/dburl v0.3.0 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a go.mongodb.org/mongo-driver v1.14.0 - golang.org/x/crypto v0.21.0 + golang.org/x/crypto v0.22.0 golang.org/x/oauth2 v0.18.0 golang.org/x/text v0.14.0 google.golang.org/api v0.167.0 gopkg.in/cheggaaa/pb.v2 v2.0.7 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 - gorm.io/driver/postgres v1.0.5 - gorm.io/driver/sqlite v1.1.4 - gorm.io/gorm v1.20.7 + gorm.io/driver/postgres v1.5.7 + gorm.io/driver/sqlite v1.5.5 + gorm.io/gorm v1.25.9 syreclabs.com/go/faker v1.2.2 ) @@ -87,20 +88,21 @@ require ( github.com/apache/arrow/go/v14 v14.0.2 // indirect github.com/apache/thrift v0.19.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2 v1.17.7 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.18 // indirect - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.59 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0 // indirect - github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0 // indirect - github.com/aws/smithy-go v1.20.1 // indirect + github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.11 // indirect + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1 // indirect + github.com/aws/smithy-go v1.20.2 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bep/debounce v1.2.1 // indirect github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect @@ -110,6 +112,7 @@ require ( github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/envoyproxy/go-control-plane v0.12.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect + github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect github.com/francoispqt/gojay v1.2.13 // indirect @@ -123,28 +126,30 @@ require ( github.com/go-openapi/strfmt v0.22.0 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/flatbuffers v24.3.7+incompatible // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.2 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/imdario/mergo v0.3.13 // indirect - github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.11.0 // indirect - github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.2.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect - github.com/jackc/pgtype v1.10.0 // indirect - github.com/jackc/pgx/v4 v4.15.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect + github.com/jackc/pgx/v5 v5.5.5 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect + github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect github.com/jcmturner/aescts/v2 v2.0.0 // indirect github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect github.com/jcmturner/gofork v1.7.6 // indirect @@ -152,11 +157,18 @@ require ( github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect github.com/jcmturner/rpc/v2 v2.0.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.4 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/klauspost/asmfmt v1.3.2 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/kr/fs v0.1.0 // indirect + github.com/labstack/echo/v4 v4.10.2 // indirect + github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61 // indirect + github.com/labstack/gommon v0.4.0 // indirect + github.com/leaanthony/go-ansi-parser v1.6.0 // indirect + github.com/leaanthony/gosod v1.0.3 // indirect + github.com/leaanthony/slicer v1.6.0 // indirect + github.com/leaanthony/u v1.1.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -174,6 +186,7 @@ require ( github.com/oklog/ulid v1.3.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/paulmach/orb v0.11.1 // indirect + github.com/pborman/uuid v1.2.1 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect @@ -182,15 +195,22 @@ require ( github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_model v0.6.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/rivo/uniseg v0.2.0 // indirect + github.com/rivo/uniseg v0.4.4 // indirect + github.com/robfig/cron v1.2.0 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/segmentio/encoding v0.3.6 // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect + github.com/tkrajina/go-reflector v0.5.6 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect github.com/viant/xunsafe v0.8.0 // indirect + github.com/wailsapp/go-webview2 v1.0.10 // indirect + github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect @@ -202,19 +222,21 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.temporal.io/api v1.29.1 // indirect + go.temporal.io/sdk v1.26.0 // indirect golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect golang.org/x/mod v0.16.0 // indirect golang.org/x/net v0.22.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/term v0.19.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.19.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240304161311-37d4d3c04a78 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8 // indirect google.golang.org/grpc v1.62.1 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/VividCortex/ewma.v1 v1.1.1 // indirect @@ -231,3 +253,5 @@ require ( ) replace github.com/flarco/g => ../g + +replace github.com/slingdata-io/sling => ../sling diff --git a/go.sum b/go.sum index ef7e5ad2c..684499648 100644 --- a/go.sum +++ b/go.sum @@ -54,8 +54,6 @@ github.com/ClickHouse/clickhouse-go/v2 v2.20.0 h1:bvlLQ31XJfl7MxIqAq2l1G6JhHYzqE github.com/ClickHouse/clickhouse-go/v2 v2.20.0/go.mod h1:VQfyA+tCwCRw2G7ogfY8V0fq/r0yJWzy8UDrjiP/Lbs= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= @@ -77,48 +75,49 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.51.1 h1:AFvTihcDPanvptoKS09a4yYmNtPm3+pXlk6uYHmZiFk= github.com/aws/aws-sdk-go v1.51.1/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.17.7 h1:CLSjnhJSTSogvqUGhIC6LqFKATMRexcxLZ0i/Nzk9Eg= -github.com/aws/aws-sdk-go-v2 v1.17.7/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= -github.com/aws/aws-sdk-go-v2/config v1.18.19 h1:AqFK6zFNtq4i1EYu+eC7lcKHYnZagMn6SW171la0bGw= -github.com/aws/aws-sdk-go-v2/config v1.18.19/go.mod h1:XvTmGMY8d52ougvakOv1RpiTLPz9dlG/OQHsKU/cMmY= -github.com/aws/aws-sdk-go-v2/credentials v1.13.18 h1:EQMdtHwz0ILTW1hoP+EwuWhwCG1hD6l3+RWFQABET4c= -github.com/aws/aws-sdk-go-v2/credentials v1.13.18/go.mod h1:vnwlwjIe+3XJPBYKu1et30ZPABG3VaXJYr8ryohpIyM= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 h1:gt57MN3liKiyGopcqgNzJb2+d9MJaKT/q1OksHNXVE4= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1/go.mod h1:lfUx8puBRdM5lVVMQlwt2v+ofiG/X6Ms+dy0UkG/kXw= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.59 h1:E3Y+OfzOK1+rmRo/K2G0ml8Vs+Xqk0kOnf4nS0kUtBc= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.59/go.mod h1:1M4PLSBUVfBI0aP+C9XI7SM6kZPCGYyI6izWz0TGprE= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 h1:sJLYcS+eZn5EeNINGHSCRAwUJMFVqklwkH36Vbyai7M= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31/go.mod h1:QT0BqUvX1Bh2ABdTGnjqEjvjzrCfIniM9Sc8zn9Yndo= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 h1:1mnRASEKnkqsntcxHaysxwgVoUUp5dkiB+l3llKnqyg= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25/go.mod h1:zBHOPwhBc3FlQjQJE/D3IfPWiWaQmT06Vq9aNukDo0k= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 h1:p5luUImdIqywn6JpQsW3tq5GNOxKmOnEpybzPx+d1lk= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32/go.mod h1:XGhIBZDEgfqmFIugclZ6FU7v75nHhBDtzuB4xB/tEi4= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 h1:DWYZIsyqagnWL00f8M/SOr9fN063OEQWn9LLTbdYXsk= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23/go.mod h1:uIiFgURZbACBEQJfqTZPb/jxO7R+9LeoHUFudtIdeQI= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26 h1:CeuSeq/8FnYpPtnuIeLQEEvDv9zUjneuYi8EghMBdwQ= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26/go.mod h1:2UqAAwMUXKeRkAHIlDJqvMVgOWkUi/AUXPk/YIe+Dg4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 h1:5LHn8JQ0qvjD9L9JhMtylnkcw7j05GDZqM9Oin6hpr0= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25/go.mod h1:/95IA+0lMnzW6XzqYJRpjjsAbKEORVeO0anQqjd2CNU= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0 h1:e2ooMhpYGhDnBfSvIyusvAwX7KexuZaHbQY2Dyei7VU= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0/go.mod h1:bh2E0CXKZsQN+faiKVqC40vfNMAWheoULBCnEgO9K+8= -github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0 h1:B1G2pSPvbAtQjilPq+Y7jLIzCOwKzuVEl+aBBaNG0AQ= -github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0/go.mod h1:ncltU6n4Nof5uJttDtcNQ537uNuwYqsZZQcpkd2/GUQ= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 h1:5V7DWLBd7wTELVz5bPpwzYy/sikk0gsgZfj40X+l5OI= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.6/go.mod h1:Y1VOmit/Fn6Tz1uFAeCO6Q7M2fmfXSCLeL5INVYsLuY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 h1:B8cauxOH1W1v7rd8RdI/MWnoR4Ze0wIHWrb90qczxj4= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6/go.mod h1:Lh/bc9XUf8CfOY6Jp5aIkQtN+j1mc+nExc+KXj9jx2s= -github.com/aws/aws-sdk-go-v2/service/sts v1.18.7 h1:bWNgNdRko2x6gqa0blfATqAZKZokPIeM1vfmQt2pnvM= -github.com/aws/aws-sdk-go-v2/service/sts v1.18.7/go.mod h1:JuTnSoeePXmMVe9G8NcjjwgOKEfZ4cOjMuT2IBT/2eI= -github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw= -github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA= +github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg= +github.com/aws/aws-sdk-go-v2/config v1.27.11 h1:f47rANd2LQEYHda2ddSCKYId18/8BhSRM4BULGmfgNA= +github.com/aws/aws-sdk-go-v2/config v1.27.11/go.mod h1:SMsV78RIOYdve1vf36z8LmnszlRWkwMQtomCAI0/mIE= +github.com/aws/aws-sdk-go-v2/credentials v1.17.11 h1:YuIB1dJNf1Re822rriUOTxopaHHvIq0l/pX3fwO+Tzs= +github.com/aws/aws-sdk-go-v2/credentials v1.17.11/go.mod h1:AQtFPsDH9bI2O+71anW6EKL+NcD7LG3dpKGMV4SShgo= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15 h1:7Zwtt/lP3KNRkeZre7soMELMGNoBrutx8nobg1jKWmo= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15/go.mod h1:436h2adoHb57yd+8W+gYPrrA9U/R/SuAuOO42Ushzhw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5 h1:81KE7vaZzrl7yHBYHVEzYB8sypz11NMOZ40YlWvPxsU= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5/go.mod h1:LIt2rg7Mcgn09Ygbdh/RdIm0rQ+3BNkbP1gyVMFtRK0= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7 h1:ZMeFZ5yk+Ek+jNr1+uwCd2tG89t6oTS5yVWpa6yy2es= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7/go.mod h1:mxV05U+4JiHqIpGqqYXOHLPKUC6bDXC44bsUhNjOEwY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5 h1:f9RyWNtS8oH7cZlbn+/JNPpjUk5+5fLd5lM9M0i49Ys= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5/go.mod h1:h5CoMZV2VF297/VLhRhO1WF+XYWOzXo+4HsObA4HjBQ= +github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1 h1:6cnno47Me9bRykw9AEv9zkXE+5or7jz8TsskTTccbgc= +github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1/go.mod h1:qmdkIIAC+GCLASF7R2whgNrJADz0QZPX+Seiw/i4S3o= +github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 h1:vN8hEbpRnL7+Hopy9dzmRle1xmDc7o8tmY0klsr175w= +github.com/aws/aws-sdk-go-v2/service/sso v1.20.5/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 h1:Jux+gDDyi1Lruk+KHF91tK2KCuY61kzoCpvtvJJBtOE= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak= +github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 h1:cwIxeBttqPN3qkaAjcEcsh8NYr8n2HZPkcKgPAi1phU= +github.com/aws/aws-sdk-go-v2/service/sts v1.28.6/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw= +github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= +github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= +github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/c-bata/go-prompt v0.2.6 h1:POP+nrHE+DfLYx370bedwNhsqmpCUynWPxuHi0C5vZI= @@ -137,14 +136,10 @@ github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= -github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -175,6 +170,8 @@ github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/Ir github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw= +github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -202,8 +199,8 @@ github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw= github.com/go-faster/errors v0.7.1 h1:MkJTnDoEdi9pDabt1dpWf7AA8/BaSYZqibYyhZ20AYg= github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -225,13 +222,12 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= @@ -245,9 +241,12 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -257,8 +256,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -276,7 +275,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -288,11 +286,11 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -308,7 +306,11 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+ github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -326,71 +328,16 @@ github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/integrii/flaggy v1.5.2 h1:bWV20MQEngo4hWhno3i5Z9ISPxLPKj9NOGNwTWb/8IQ= github.com/integrii/flaggy v1.5.2/go.mod h1:dO13u7SYuhk910nayCJ+s1DeAAGC1THCMj1uSFmwtQ8= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.7.0/go.mod h1:sF/lPpNEMEOp+IYhyQGdAvrG20gWf6A1tKlr0v7JMeA= -github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= -github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.11.0 h1:HiHArx4yFbwl91X3qqIHtUFoiIfLNJXCQRsnzkiwwaQ= -github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= -github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.5/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns= -github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.5.0/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= -github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.10.0 h1:ILnBWrRMSXGczYvmkYD6PsYyVFUNLTnIUJHHDLmqk38= -github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.9.0/go.mod h1:MNGWmViCgqbZck9ujOOBN63gK9XVGILXWCvKLGKmnms= -github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.15.0 h1:B7dTkXsdILD3MF987WGGCcg+tvLW6bZJdEcqVFeU//w= -github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw= -github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.2/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= +github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= +github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= @@ -408,9 +355,8 @@ github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4Fw github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= -github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jlaffaye/ftp v0.2.0 h1:lXNvW7cBu7R/68bknOX3MrRIIqZ61zELs1P2RAiA3lg= github.com/jlaffaye/ftp v0.2.0/go.mod h1:is2Ds5qkhceAPy2xD6RLI6hmp/qysSoymZ+Z2uTnspI= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= @@ -437,15 +383,14 @@ github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ib github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -453,10 +398,24 @@ github.com/kshedden/datareader v0.0.0-20210325133423-816b6ffdd011 h1:PNO6bcxsCMs github.com/kshedden/datareader v0.0.0-20210325133423-816b6ffdd011/go.mod h1:oTL9FJaM6f+gPQyrBN/Dd274KKAEkHw9ATjZ+7GD86U= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M= +github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= +github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61 h1:FwuzbVh87iLiUQj1+uQUsuw9x5t9m5n5g7rG7o4svW4= +github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61/go.mod h1:paQfF1YtHe+GrGg5fOgjsjoCX/UKDr9bc1DoWpZfns8= +github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= +github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc= +github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA= +github.com/leaanthony/go-ansi-parser v1.6.0 h1:T8TuMhFB6TUMIUm0oRrSbgJudTFw9csT3ZK09w0t4Pg= +github.com/leaanthony/go-ansi-parser v1.6.0/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= +github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ= +github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4= +github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= +github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js= +github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8= +github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI= +github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/linkedin/goavro/v2 v2.12.0 h1:rIQQSj8jdAUlKQh6DttK8wCRv4t4QO09g1C4aBWXslg= @@ -465,19 +424,17 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -486,10 +443,9 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= -github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -534,6 +490,7 @@ github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/ github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg= @@ -542,6 +499,8 @@ github.com/parquet-go/parquet-go v0.20.0/go.mod h1:4YfUo8TkoGoqwzhA/joZKZ8f77wSM github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU= github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= +github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= +github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= @@ -576,20 +535,19 @@ github.com/psanford/sqlite3vfs v0.0.0-20220823065410-bd28ac7ee3c2 h1:S7ikYUpctxi github.com/psanford/sqlite3vfs v0.0.0-20220823065410-bd28ac7ee3c2/go.mod h1:iW4cSew5PAb1sMZiTEkVJAIBNrepaB6jTYjeP47WtI0= github.com/psanford/sqlite3vfshttp v0.0.0-20220827153928-a19f096e6eb4 h1:ea/vBgpSGRKEdguoxGNiGz8byJNyVXPNVg8pPFsVbWc= github.com/psanford/sqlite3vfshttp v0.0.0-20220827153928-a19f096e6eb4/go.mod h1:5s4abpgrv1UTVgYqZOyd+7lLiFtOIytXnuhZI0m4NWo= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= +github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs= github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= @@ -606,9 +564,6 @@ github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFt github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= @@ -635,7 +590,6 @@ github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYED github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sijms/go-ora/v2 v2.8.10-0.20240228213529-2ce633cb669f h1:M7oLjs0V0zBlHZ3PHv5nRcjiER7fsmVo0U+FkschpT8= github.com/sijms/go-ora/v2 v2.8.10-0.20240228213529-2ce633cb669f/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl4FWlH6xk= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -647,7 +601,6 @@ github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= @@ -656,7 +609,6 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -668,16 +620,31 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/timeplus-io/proton-go-driver/v2 v2.0.17 h1:rXPT21/9FgQYFntSgLvJRL/7pgPAfTXWIZKp5UG+vQ0= +github.com/timeplus-io/proton-go-driver/v2 v2.0.17/go.mod h1:rUs4zvXvKsmuyFpzdJnnid6p8IvRJTa/n/jNQ2B6Dfw= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE= +github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4= github.com/trinodb/trino-go-client v0.313.0 h1:lp8N9JKTqMuZ9LlAwLjgUtkwDnJc8fjpJmunpZ3afjk= github.com/trinodb/trino-go-client v0.313.0/go.mod h1:YpZf2WAClFhU+n0ZhdkmMbugYaMRM/mjywiQru0wpeQ= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/viant/xunsafe v0.8.0 h1:hDavbYhEaZ2A1QMrgriN3Hqyc/JUzGfPYPdL+GVwmM8= github.com/viant/xunsafe v0.8.0/go.mod h1:niyYv07oGkqPJirAda2yz+yqt5G+eM275y179yVaS3s= +github.com/wailsapp/go-webview2 v1.0.10 h1:PP5Hug6pnQEAhfRzLCoOh2jJaPdrqeRgJKZhyYyDV/w= +github.com/wailsapp/go-webview2 v1.0.10/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo= +github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= +github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= +github.com/wailsapp/wails/v2 v2.8.1 h1:KAudNjlFaiXnDfFEfSNoLoibJ1ovoutSrJ8poerTPW0= +github.com/wailsapp/wails/v2 v2.8.1/go.mod h1:EFUGWkUX3KofO4fmKR/GmsLy3HhPH7NbyOEaMt8lBF0= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= @@ -699,6 +666,7 @@ github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqTosly github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= @@ -706,7 +674,6 @@ github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= @@ -725,39 +692,27 @@ go.opentelemetry.io/otel/sdk v1.23.1 h1:O7JmZw0h76if63LQdsBMKQDWNb5oEcOThG9Irxsc go.opentelemetry.io/otel/sdk v1.23.1/go.mod h1:LzdEVR5am1uKOOwfBWFef2DCi1nu3SA8XQxx2IerWFk= go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.temporal.io/api v1.29.1 h1:L722DCy3xCzpTe3Rvh1sFC9kcSaMJXqvodCF+swHGtQ= +go.temporal.io/api v1.29.1/go.mod h1:wZtsUJ3PySASGWbpXBWYVKJ4aHB2ZODEn/xNcTr9HRs= +go.temporal.io/sdk v1.26.0 h1:QAi7irgKvJI+5cKmvy+1lkdCDJJDDNpIQAoXdr3dcyM= +go.temporal.io/sdk v1.26.0/go.mod h1:rcAf1YWlbWgMsjJEuz7XiQd6UYxTQDOk2AqRRIDwq/U= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= @@ -765,11 +720,9 @@ golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= @@ -785,13 +738,14 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= @@ -814,34 +768,35 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -853,19 +808,16 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= @@ -882,22 +834,15 @@ golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -923,13 +868,14 @@ google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto/googleapis/api v0.0.0-20240304161311-37d4d3c04a78 h1:SzXBGiWM1LNVYLCRP3e0/Gsze804l4jGoJ5lYysEO5I= -google.golang.org/genproto/googleapis/api v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641 h1:DKU1r6Tj5s1vlU/moGhuGz7E3xRfwjdAfDzbsaQJtEY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= +google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 h1:8eadJkXbwDEMNwcB5O0s5Y5eCfyuCLdvaiOIaGTrWmQ= +google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8 h1:IR+hp6ypxjH24bkMfEJ0yHR21+gwPWdV+/IBrPQyn3k= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -937,6 +883,7 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= @@ -965,12 +912,10 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v2 v2.0.7 h1:beaAg8eacCdMQS9Y7obFEtkY7gQl0uZ6Zayb3ry41VY= gopkg.in/cheggaaa/pb.v2 v2.0.7/go.mod h1:0CiZ1p8pvtxBlQpLXkHuUTpdJ1shm3OqCF1QugkjHL4= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fatih/color.v1 v1.7.0 h1:bYGjb+HezBM6j/QmgBfgm1adxHpzzrss6bj4r9ROppk= gopkg.in/fatih/color.v1 v1.7.0/go.mod h1:P7yosIhqIl/sX8J8UypY5M+dDpD2KmyfP5IRs5v/fo0= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/jcmturner/aescts.v1 v1.0.1 h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hrEw= gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= @@ -995,22 +940,21 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/postgres v1.0.5 h1:raX6ezL/ciUmaYTvOq48jq1GE95aMC0CmxQYbxQ4Ufw= -gorm.io/driver/postgres v1.0.5/go.mod h1:qrD92UurYzNctBMVCJ8C3VQEjffEuphycXtxOudXNCA= -gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM= -gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw= -gorm.io/gorm v1.20.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= -gorm.io/gorm v1.20.7 h1:rMS4CL3pNmYq1V5/X+nHHjh1Dx6dnf27+Cai5zabo+M= -gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= +gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= +gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= +gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E= +gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE= +gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8= +gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 6a930ecee..89f23bd66 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -1,5 +1,6 @@ go mod edit -dropreplace='github.com/flarco/g' go.mod +go mod edit -dropreplace='github.com/slingdata-io/sling' go.mod go mod tidy go build -o sling.exe github.com/slingdata-io/sling-cli/cmd/sling \ No newline at end of file diff --git a/scripts/build.sh b/scripts/build.sh index dc0731513..568a3be29 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,6 +1,7 @@ # local build go mod edit -dropreplace='github.com/flarco/g' go.mod +go mod edit -dropreplace='github.com/slingdata-io/sling' go.mod go mod tidy go build -o sling cmd/sling/*.go \ No newline at end of file diff --git a/scripts/ci/build.linux.sh b/scripts/ci/build.linux.sh index fe4bec16a..191ce42a9 100755 --- a/scripts/ci/build.linux.sh +++ b/scripts/ci/build.linux.sh @@ -7,6 +7,7 @@ mkdir -p $TMPDIR echo "Building sling-linux" go mod edit -dropreplace='github.com/flarco/g' go.mod +go mod edit -dropreplace='github.com/slingdata-io/sling' go.mod go mod tidy export VERSION=$1 diff --git a/scripts/ci/build.mac.sh b/scripts/ci/build.mac.sh index c7490e3ea..c893f4a32 100755 --- a/scripts/ci/build.mac.sh +++ b/scripts/ci/build.mac.sh @@ -7,6 +7,7 @@ mkdir -p $TMPDIR echo "Building sling-mac" go mod edit -dropreplace='github.com/flarco/g' go.mod +go mod edit -dropreplace='github.com/slingdata-io/sling' go.mod go mod tidy export VERSION=$1 diff --git a/scripts/ci/build.win.ps1 b/scripts/ci/build.win.ps1 index f502f3b35..fe38125d2 100644 --- a/scripts/ci/build.win.ps1 +++ b/scripts/ci/build.win.ps1 @@ -14,6 +14,7 @@ echo "version -> $version" echo "VERSION -> $env:VERSION" go mod edit -dropreplace='github.com/flarco/g' go.mod +go mod edit -dropreplace='github.com/slingdata-io/sling' go.mod go mod tidy (Get-Content core/version.go).replace('dev', "$env:VERSION") | Set-Content core/version.go diff --git a/scripts/prep.gomod.sh b/scripts/prep.gomod.sh index 21ec00707..07125ae72 100644 --- a/scripts/prep.gomod.sh +++ b/scripts/prep.gomod.sh @@ -2,6 +2,5 @@ set -e # exit on error echo 'prep.gomod.sh' go mod edit -dropreplace='github.com/flarco/g' go.mod -# go get github.com/flarco/g@HEAD -# go get github.com/slingdata-io/sling-cli/core/dbio@HEAD +go mod edit -dropreplace='github.com/slingdata-io/sling' go.mod go mod tidy \ No newline at end of file diff --git a/scripts/test.sh b/scripts/test.sh index 7c986f4c2..637d9af4e 100644 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -6,8 +6,8 @@ shopt -s expand_aliases # export _DEBUG=LOW # export _DEBUG_CALLER_LEVEL=2 cd cmd/sling -go test -parallel 2 -run TestSuiteFile -go test -parallel 4 -timeout 15m -run TestSuiteDatabase +go test -parallel 3 -run 'TestSuiteFile|TestSuiteDatabaseClickhouse' +SKIP_CLICKHOUSE=TRUE go test -parallel 4 -timeout 15m -run TestSuiteDatabase cd - @@ -45,8 +45,10 @@ sling run --src-stream file://cmd/sling/tests/files/binary/test.bytes.csv --tgt- SLING_ROW_CNT=1 sling conns exec postgres "select 1 from "postgres"."public"."my_table_bytes" where byte_val::bytea::text like '%89504e470d0a1a0a0000000d%'" # test _sling_stream_url -SLING_STREAM_URL_COLUMN=true sling run --src-stream file://core/dbio/filesys/test/test1/json --tgt-conn postgres --tgt-object public.many_jsons --mode full-refresh +SLING_LOADED_AT_COLUMN=false SLING_STREAM_URL_COLUMN=true SLING_ROW_NUM_COLUMN=true sling run --src-stream file://core/dbio/filesys/test/test1/json --tgt-conn postgres --tgt-object public.many_jsons --mode full-refresh SLING_ROW_CNT=4 sling conns exec postgres "select distinct _sling_stream_url from public.many_jsons" +SLING_ROW_CNT=3 sling conns exec postgres "select _sling_stream_url from public.many_jsons where _sling_row_num = 18" # should show different file names +SLING_ROW_CNT=2 sling conns exec postgres "select column_name from information_schema.columns where table_schema = 'public' and table_name = 'many_jsons' and column_name like '_sling%'" # should not have _sling_loaded_at sling conns test POSTGRES sling conns exec POSTGRES 'select count(1) from public.my_table'