Merge remote-tracking branch 'origin/master' into aaron/dbfactory-grpc-dialer-through-params

This commit is contained in:
Aaron Son
2021-09-10 10:41:52 -07:00
15 changed files with 202 additions and 85 deletions

View File

@@ -31,7 +31,7 @@ jobs:
run: |
latest=$(git rev-parse HEAD)
echo "::set-output name=commitish::$latest"
GO_BUILD_VERSION=1.15.11 go/utils/publishrelease/buildbinaries.sh
GO_BUILD_VERSION=1.17.1 go/utils/publishrelease/buildbinaries.sh
- name: Create Release
id: create_release
uses: actions/create-release@v1

View File

@@ -39,7 +39,7 @@ jobs:
- name: Setup Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.15
go-version: ^1.17
id: go
- name: Setup Python 3.x
uses: actions/setup-python@v2

View File

@@ -84,7 +84,7 @@ jobs:
- name: Setup Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.15
go-version: ^1.17
id: go
- name: Setup Python 3.x
uses: actions/setup-python@v2

View File

@@ -12,7 +12,7 @@ jobs:
- name: Setup Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.15
go-version: ^1.17
- uses: actions/checkout@v2
- name: Check all
working-directory: ./go

View File

@@ -16,7 +16,7 @@ jobs:
- name: Setup Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.13
go-version: ^1.17
id: go
- uses: actions/checkout@v2
- uses: actions/setup-node@v1

View File

@@ -12,7 +12,7 @@ jobs:
- name: Setup Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.15
go-version: ^1.17
- uses: actions/checkout@v2
with:
token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}

View File

@@ -22,7 +22,7 @@ jobs:
- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.15
go-version: ^1.17
id: go
- uses: actions/checkout@v2
- name: Test All
@@ -69,7 +69,7 @@ jobs:
- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.15
go-version: ^1.17
id: go
- uses: actions/checkout@v2
- name: Test All

View File

@@ -16,7 +16,10 @@ package cli
import (
"context"
"os"
"os/signal"
"strings"
"syscall"
"github.com/fatih/color"
@@ -54,7 +57,7 @@ func hasHelpFlag(args []string) bool {
// Command is the interface which defines a Dolt cli command
type Command interface {
// Name is returns the name of the Dolt cli command. This is what is used on the command line to invoke the command
// Name returns the name of the Dolt cli command. This is what is used on the command line to invoke the command
Name() string
// Description returns a description of the command
Description() string
@@ -64,6 +67,15 @@ type Command interface {
CreateMarkdown(fs filesys.Filesys, path, commandStr string) error
}
// SignalCommand is an extension of Command that allows commands to install their own signal handlers, rather than use
// the global one (which cancels the global context).
type SignalCommand interface {
Command
// InstallsSignalHandlers returns whether this command manages its own signal handlers for interruption / termination.
InstallsSignalHandlers() bool
}
// This type is to store the content of a documented command, elsewhere we can transform this struct into
// other structs that are used to generate documentation at the command line and in markdown files.
type CommandDocumentationContent struct {
@@ -153,6 +165,7 @@ func (hc SubCommandHandler) Exec(ctx context.Context, commandStr string, args []
if len(args) > 0 {
subCommandStr = strings.ToLower(strings.TrimSpace(args[0]))
}
for _, cmd := range hc.Subcommands {
lwrName := strings.ToLower(cmd.Name())
if lwrName == subCommandStr {
@@ -190,6 +203,14 @@ func (hc SubCommandHandler) handleCommand(ctx context.Context, commandStr string
ctx = events.NewContextForEvent(ctx, evt)
}
// Certain commands cannot tolerate a top-level signal handler (which cancels the root context) but need to manage
// their own interrupt semantics.
if signalCmd, ok := cmd.(SignalCommand); !ok || !signalCmd.InstallsSignalHandlers() {
var stop context.CancelFunc
ctx, stop = signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM)
defer stop()
}
ret := cmd.Exec(ctx, commandStr, args, dEnv)
if evt != nil {

View File

@@ -19,10 +19,12 @@ import (
"fmt"
"io"
"os"
"os/signal"
"path/filepath"
"regexp"
"runtime"
"strings"
"syscall"
"github.com/abiosoft/readline"
sqle "github.com/dolthub/go-mysql-server"
@@ -121,6 +123,13 @@ type SqlCmd struct {
VersionStr string
}
// The SQL shell installs its own signal handlers so that you can cancel a running query without and still run a new one.
func (cmd SqlCmd) InstallsSignalHandlers() bool {
return true
}
var _ cli.SignalCommand = SqlCmd{}
// Name returns the name of the Dolt cli command. This is what is used on the command line to invoke the command
func (cmd SqlCmd) Name() string {
return "sql"
@@ -368,12 +377,12 @@ func execShell(
format resultFormat,
) errhand.VerboseError {
dbs := CollectDBs(mrEnv)
se, sqlCtx, err := newSqlEngine(ctx, dEnv, mrEnv, roots, readOnly, format, dbs...)
se, err := newSqlEngine(ctx, dEnv, mrEnv, roots, readOnly, format, dbs...)
if err != nil {
return errhand.VerboseErrorFromError(err)
}
err = runShell(sqlCtx, se, mrEnv, roots)
err = runShell(ctx, se, mrEnv, roots)
if err != nil {
return errhand.BuildDError(err.Error()).Build()
}
@@ -391,7 +400,12 @@ func execBatch(
format resultFormat,
) errhand.VerboseError {
dbs := CollectDBs(mrEnv)
se, sqlCtx, err := newSqlEngine(ctx, dEnv, mrEnv, roots, readOnly, format, dbs...)
se, err := newSqlEngine(ctx, dEnv, mrEnv, roots, readOnly, format, dbs...)
if err != nil {
return errhand.VerboseErrorFromError(err)
}
sqlCtx, err := se.newContext(ctx)
if err != nil {
return errhand.VerboseErrorFromError(err)
}
@@ -428,7 +442,12 @@ func execMultiStatements(
format resultFormat,
) errhand.VerboseError {
dbs := CollectDBs(mrEnv)
se, sqlCtx, err := newSqlEngine(ctx, dEnv, mrEnv, roots, readOnly, format, dbs...)
se, err := newSqlEngine(ctx, dEnv, mrEnv, roots, readOnly, format, dbs...)
if err != nil {
return errhand.VerboseErrorFromError(err)
}
sqlCtx, err := se.newContext(ctx)
if err != nil {
return errhand.VerboseErrorFromError(err)
}
@@ -459,7 +478,12 @@ func execQuery(
format resultFormat,
) errhand.VerboseError {
dbs := CollectDBs(mrEnv)
se, sqlCtx, err := newSqlEngine(ctx, dEnv, mrEnv, roots, readOnly, format, dbs...)
se, err := newSqlEngine(ctx, dEnv, mrEnv, roots, readOnly, format, dbs...)
if err != nil {
return errhand.VerboseErrorFromError(err)
}
sqlCtx, err := se.newContext(ctx)
if err != nil {
return errhand.VerboseErrorFromError(err)
}
@@ -742,14 +766,19 @@ func runBatchMode(ctx *sql.Context, se *sqlEngine, input io.Reader, continueOnEr
// runShell starts a SQL shell. Returns when the user exits the shell. The Root of the sqlEngine may
// be updated by any queries which were processed.
func runShell(ctx *sql.Context, se *sqlEngine, mrEnv env.MultiRepoEnv, initialRoots map[string]*doltdb.RootValue) error {
func runShell(ctx context.Context, se *sqlEngine, mrEnv env.MultiRepoEnv, initialRoots map[string]*doltdb.RootValue) error {
_ = iohelp.WriteLine(cli.CliOut, welcomeMsg)
currentDB := ctx.Session.GetCurrentDatabase()
sqlCtx, err := se.newContext(ctx)
if err != nil {
return err
}
currentDB := sqlCtx.Session.GetCurrentDatabase()
currEnv := mrEnv[currentDB]
// start the doltsql shell
historyFile := filepath.Join(".sqlhistory") // history file written to working dir
initialPrompt := fmt.Sprintf("%s> ", ctx.GetCurrentDatabase())
initialPrompt := fmt.Sprintf("%s> ", sqlCtx.GetCurrentDatabase())
initialMultilinePrompt := fmt.Sprintf(fmt.Sprintf("%%%ds", len(initialPrompt)), "-> ")
rlConf := readline.Config{
@@ -783,6 +812,8 @@ func runShell(ctx *sql.Context, se *sqlEngine, mrEnv env.MultiRepoEnv, initialRo
c.Stop()
})
// The shell's interrupt handler handles an interrupt that occurs when it's accepting input. We also install our own
// that handles interrupts during query execution or result printing, see below.
shell.Interrupt(func(c *ishell.Context, count int, input string) {
if count > 1 {
c.Stop()
@@ -791,7 +822,6 @@ func runShell(ctx *sql.Context, se *sqlEngine, mrEnv env.MultiRepoEnv, initialRo
}
})
var returnedVerr errhand.VerboseError = nil // Verr that cannot be just printed but needs to be returned.
shell.Uninterpreted(func(c *ishell.Context) {
query := c.Args[0]
if len(strings.TrimSpace(query)) == 0 {
@@ -809,44 +839,58 @@ func runShell(ctx *sql.Context, se *sqlEngine, mrEnv env.MultiRepoEnv, initialRo
shell.Println(color.RedString(err.Error()))
}
shouldProcessQuery := true
//TODO: Handle comments and enforce the current line terminator
if matches := delimiterRegex.FindStringSubmatch(query); len(matches) == 3 {
// If we don't match from anything, then we just pass to the SQL engine and let it complain.
shell.SetLineTerminator(matches[1])
shouldProcessQuery = false
return
}
if shouldProcessQuery {
var sqlSch sql.Schema
var rowIter sql.RowIter
var err error
var nextPrompt string
var sqlSch sql.Schema
var rowIter sql.RowIter
// The SQL parser does not understand any other terminator besides semicolon, so we remove it.
if shell.LineTerminator() != ";" && strings.HasSuffix(query, shell.LineTerminator()) {
query = query[:len(query)-len(shell.LineTerminator())]
// The SQL parser does not understand any other terminator besides semicolon, so we remove it.
if shell.LineTerminator() != ";" && strings.HasSuffix(query, shell.LineTerminator()) {
query = query[:len(query)-len(shell.LineTerminator())]
}
cont := func() bool {
subCtx, stop := signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM)
defer stop()
sqlCtx, err = se.newContext(subCtx)
if err != nil {
shell.Println(color.RedString(err.Error()))
return false
}
if sqlSch, rowIter, err = processQuery(ctx, query, se); err != nil {
if sqlSch, rowIter, err = processQuery(sqlCtx, query, se); err != nil {
verr := formatQueryError("", err)
shell.Println(verr.Verbose())
} else if rowIter != nil {
err = PrettyPrintResults(ctx, se.resultFormat, sqlSch, rowIter, HasTopLevelOrderByClause(query))
err = PrettyPrintResults(sqlCtx, se.resultFormat, sqlSch, rowIter, HasTopLevelOrderByClause(query))
if err != nil {
shell.Println(color.RedString(err.Error()))
}
}
nextPrompt = fmt.Sprintf("%s> ", sqlCtx.GetCurrentDatabase())
return true
}()
if !cont {
return
}
currPrompt := fmt.Sprintf("%s> ", ctx.GetCurrentDatabase())
shell.SetPrompt(currPrompt)
shell.SetMultiPrompt(fmt.Sprintf(fmt.Sprintf("%%%ds", len(currPrompt)), "-> "))
shell.SetPrompt(nextPrompt)
shell.SetMultiPrompt(fmt.Sprintf(fmt.Sprintf("%%%ds", len(nextPrompt)), "-> "))
})
shell.Run()
_ = iohelp.WriteLine(cli.CliOut, "Bye")
return returnedVerr
return nil
}
// Returns a new auto completer with table names, column names, and SQL keywords.
@@ -1349,10 +1393,12 @@ func mergeResultIntoStats(statement sqlparser.Statement, rowIter sql.RowIter, s
}
type sqlEngine struct {
dbs map[string]dsqle.Database
mrEnv env.MultiRepoEnv
engine *sqle.Engine
resultFormat resultFormat
dbs map[string]dsqle.Database
mrEnv env.MultiRepoEnv
sess *dsess.Session
contextFactory func(ctx context.Context) (*sql.Context, error)
engine *sqle.Engine
resultFormat resultFormat
}
var ErrDBNotFoundKind = errors.NewKind("database '%s' not found")
@@ -1366,7 +1412,7 @@ func newSqlEngine(
readOnly bool,
format resultFormat,
dbs ...dsqle.Database,
) (*sqlEngine, *sql.Context, error) {
) (*sqlEngine, error) {
var au auth.Auth
if readOnly {
@@ -1381,7 +1427,7 @@ func newSqlEngine(
err := cat.Register(dfunctions.DoltFunctions...)
if err != nil {
return nil, nil, err
return nil, err
}
engine := sqle.New(cat, analyzer.NewBuilder(cat).WithParallelism(parallelism).Build(), &sqle.Config{Auth: au})
@@ -1405,7 +1451,7 @@ func newSqlEngine(
// since it isn't a current HEAD.
dbState, err := getDbState(ctx, db, mrEnv)
if err != nil {
return nil, nil, err
return nil, err
}
dbStates = append(dbStates, dbState)
@@ -1416,41 +1462,50 @@ func newSqlEngine(
email := *dEnv.Config.GetStringOrDefault(env.UserEmailKey, "")
sess, err := dsess.NewSession(sql.NewEmptyContext(), sql.NewBaseSession(), pro, username, email, dbStates...)
sqlCtx := sql.NewContext(ctx,
sql.WithSession(sess),
sql.WithIndexRegistry(sql.NewIndexRegistry()),
sql.WithViewRegistry(sql.NewViewRegistry()),
sql.WithTracer(tracing.Tracer(ctx)))
for _, db := range dbsAsDSQLDBs(cat.AllDatabases()) {
root, err := db.GetRoot(sqlCtx)
if err != nil {
return nil, nil, err
}
err = dsqle.RegisterSchemaFragments(sqlCtx, db, root)
if err != nil {
return nil, nil, err
}
}
err = sqlCtx.SetSessionVariable(sqlCtx, sql.AutoCommitSessionVar, true)
// TODO: this should just be the session default like it is with MySQL
err = sess.SetSessionVariable(sql.NewContext(ctx), sql.AutoCommitSessionVar, true)
if err != nil {
return nil, nil, err
return nil, err
}
initialRoots, err := mrEnv.GetWorkingRoots(ctx)
if err != nil {
return nil, nil, err
}
return &sqlEngine{
dbs: nameToDB,
mrEnv: mrEnv,
sess: sess,
contextFactory: newSqlContext(sess, cat),
engine: engine,
resultFormat: format,
}, nil
}
if len(initialRoots) == 1 {
for name := range initialRoots {
sqlCtx.SetCurrentDatabase(name)
func newSqlContext(sess *dsess.Session, cat *sql.Catalog) func(ctx context.Context) (*sql.Context, error) {
return func(ctx context.Context) (*sql.Context, error) {
sqlCtx := sql.NewContext(ctx,
sql.WithSession(sess),
sql.WithIndexRegistry(sql.NewIndexRegistry()),
sql.WithViewRegistry(sql.NewViewRegistry()),
sql.WithTracer(tracing.Tracer(ctx)))
seenOne := false
for _, db := range dbsAsDSQLDBs(cat.AllDatabases()) {
root, err := db.GetRoot(sqlCtx)
if err != nil {
return nil, err
}
err = dsqle.RegisterSchemaFragments(sqlCtx, db, root)
if err != nil {
return nil, err
}
if !seenOne {
sqlCtx.SetCurrentDatabase(db.Name())
seenOne = true
}
}
}
return &sqlEngine{nameToDB, mrEnv, engine, format}, sqlCtx, nil
return sqlCtx, nil
}
}
func dbsAsDSQLDBs(dbs []sql.Database) []dsqle.Database {
@@ -1546,6 +1601,10 @@ func (se *sqlEngine) getRoots(sqlCtx *sql.Context) (map[string]*doltdb.RootValue
return newRoots, nil
}
func (se *sqlEngine) newContext(ctx context.Context) (*sql.Context, error) {
return se.contextFactory(ctx)
}
// Execute a SQL statement and return values for printing.
func (se *sqlEngine) query(ctx *sql.Context, query string) (sql.Schema, sql.RowIter, error) {
return se.engine.Query(ctx, query)

View File

@@ -21,10 +21,8 @@ import (
_ "net/http/pprof"
"os"
"os/exec"
"os/signal"
"strconv"
"strings"
"syscall"
"time"
"github.com/fatih/color"
@@ -226,14 +224,7 @@ func runMain() int {
warnIfMaxFilesTooLow()
ctx, cancelF := context.WithCancel(context.Background())
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
cancelF()
}()
ctx := context.Background()
dEnv := env.Load(ctx, env.GetCurrentUserHomeDir, filesys.LocalFS, doltdb.LocalDirDoltDB, Version)
if dEnv.DBLoadError == nil && commandNeedsMigrationCheck(args) {

View File

@@ -1,12 +1,14 @@
module github.com/dolthub/dolt/go
require (
cloud.google.com/go v0.66.0 // indirect
cloud.google.com/go/storage v1.12.0
github.com/BurntSushi/toml v0.3.1
github.com/HdrHistogram/hdrhistogram-go v1.0.0
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
@@ -15,7 +17,9 @@ require (
github.com/bcicen/jstream v1.0.0
github.com/boltdb/bolt v1.3.1
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/cespare/xxhash v1.1.0 // indirect
github.com/codahale/blake2 v0.0.0-20150924215134-8d10d0420cbf
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/denisbrodbeck/machineid v1.0.1
github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi v0.0.0-20201005193433-3ee972b1d078
github.com/dolthub/fslock v0.0.3
@@ -28,29 +32,39 @@ require (
github.com/fatih/color v1.9.0
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568
github.com/go-kit/kit v0.10.0 // indirect
github.com/go-ole/go-ole v1.2.1 // indirect
github.com/go-openapi/errors v0.19.6 // indirect
github.com/go-openapi/strfmt v0.19.5 // indirect
github.com/go-sql-driver/mysql v1.6.0
github.com/go-stack/stack v1.8.0 // indirect
github.com/gocraft/dbr/v2 v2.7.0
github.com/golang/glog v0.0.0-20210429001901-424d2337a529 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/protobuf v1.5.2
github.com/golang/snappy v0.0.1
github.com/google/go-cmp v0.5.5
github.com/google/uuid v1.2.0
github.com/googleapis/gax-go/v2 v2.0.5 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jedib0t/go-pretty v4.3.1-0.20191104025401-85fe5d6a7c4d+incompatible
github.com/jmespath/go-jmespath v0.3.0 // indirect
github.com/jpillora/backoff v1.0.0
github.com/jstemmer/go-junit-report v0.9.1 // indirect
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d
github.com/kch42/buzhash v0.0.0-20160816060738-9bdec3dec7c6
github.com/lestrrat-go/strftime v1.0.4 // indirect
github.com/mattn/go-colorable v0.1.7 // indirect
github.com/mattn/go-isatty v0.0.12
github.com/mattn/go-runewidth v0.0.9
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
github.com/mitchellh/hashstructure v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.3.2 // indirect
github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 // indirect
github.com/opentracing/opentracing-go v1.2.0
github.com/pkg/errors v0.9.1
github.com/pkg/profile v1.5.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.1.0
github.com/sergi/go-diff v1.1.0 // indirect
github.com/shirou/gopsutil v3.21.2+incompatible
@@ -59,19 +73,32 @@ require (
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/cobra v1.0.0
github.com/spf13/pflag v1.0.5 // indirect
github.com/src-d/go-oniguruma v1.1.0 // indirect
github.com/stretchr/testify v1.7.0
github.com/tealeg/xlsx v1.0.5
github.com/tidwall/pretty v1.0.1 // indirect
github.com/tklauser/go-sysconf v0.3.5 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect
github.com/uber/jaeger-client-go v2.25.0+incompatible
github.com/uber/jaeger-lib v2.4.0+incompatible // indirect
go.mongodb.org/mongo-driver v1.7.0 // indirect
go.opencensus.io v0.22.4 // indirect
go.uber.org/atomic v1.6.0 // indirect
go.uber.org/multierr v1.5.0 // indirect
go.uber.org/zap v1.15.0
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect
golang.org/x/mod v0.3.0 // indirect
golang.org/x/net v0.0.0-20210505214959-0714010a04ed
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6
golang.org/x/text v0.3.6 // indirect
golang.org/x/tools v0.1.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/api v0.32.0
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20210506142907-4a47615972c2 // indirect
google.golang.org/grpc v1.37.0
google.golang.org/protobuf v1.26.0
@@ -83,4 +110,4 @@ require (
replace github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi => ./gen/proto/dolt/services/eventsapi
go 1.15
go 1.17

View File

@@ -144,8 +144,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dolthub/fslock v0.0.3 h1:iLMpUIvJKMKm92+N1fmHVdxJP5NdyDK5bK7z7Ba2s2U=
github.com/dolthub/fslock v0.0.3/go.mod h1:QWql+P17oAAMLnL4HGB5tiovtDuAjdDTPbuqx7bYfa0=
github.com/dolthub/go-mysql-server v0.10.1-0.20210902175808-c05838e8d173 h1:gM1YsiCfQMVcaSQrj9ZZMvJStGi0/TZc7zwsf9KbweI=
github.com/dolthub/go-mysql-server v0.10.1-0.20210902175808-c05838e8d173/go.mod h1:cPg39xeFH8/+McnJxncb79SgUuREeIqR+eTvxE6OmXc=
github.com/dolthub/go-mysql-server v0.10.1-0.20210903190613-4c25c32c3883 h1:IfpwAn8PtCr1roskOckNiNxj2Iqly0yTtWeWkgla0YM=
github.com/dolthub/go-mysql-server v0.10.1-0.20210903190613-4c25c32c3883/go.mod h1:cPg39xeFH8/+McnJxncb79SgUuREeIqR+eTvxE6OmXc=
github.com/dolthub/ishell v0.0.0-20210205014355-16a4ce758446 h1:0ol5pj+QlKUKAtqs1LiPM3ZJKs+rHPgLSsMXmhTrCAM=

View File

@@ -201,7 +201,7 @@ func findInvalidCol(r Row, sch schema.Schema) (*schema.Column, schema.ColConstra
if !col.TypeInfo.IsValid(val) {
badCol = &col
return true, fmt.Errorf(`"%v" is not valid for "%v"`, val, col.TypeInfo.String())
return true, fmt.Errorf(`"%v" is not valid for column "%s" (type "%s")`, val, col.Name, col.TypeInfo.ToSqlType().String())
}
if len(col.Constraints) > 0 {

View File

@@ -75,7 +75,6 @@ func main() {
func waitForSignal() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill)
<-c
}

View File

@@ -14,6 +14,14 @@ CREATE TABLE test (
c5 BIGINT COMMENT 'tag:5',
PRIMARY KEY (pk)
);
SQL
cat <<SQL > 1pk1col-char-sch.sql
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
c CHAR(5) COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
cat <<DELIM > 1pk5col-ints.csv
@@ -186,6 +194,20 @@ SQL
[[ "${lines[6]}" =~ "end date" ]] || false
}
@test "import-update-tables: update table with incorrect length char throws bad row error" {
cat <<DELIM > 1pk1col-rpt-chars.csv
pk,c
1,"123456"
DELIM
dolt sql < 1pk1col-char-sch.sql
run dolt table import -u test 1pk1col-rpt-chars.csv
[ "$status" -eq 1 ]
[[ "$output" =~ "A bad row was encountered while moving data" ]] || false
[[ "$output" =~ "Bad Row:" ]] || false
[[ "$output" =~ '"123456" is not valid for column "c" (type "CHAR(5)")' ]] || false
}
@test "import-update-tables: update table with repeat pk in csv throws error" {
cat <<DELIM > 1pk5col-rpt-ints.csv
pk,c1,c2,c3,c4,c5