Merge remote-tracking branch 'remotes/origin/main' into bh/signed-commits

This commit is contained in:
Brian Hendriks
2024-09-16 09:40:32 -07:00
19 changed files with 681 additions and 119 deletions

View File

@@ -21,10 +21,10 @@ import (
"fmt"
"io"
"sort"
"strconv"
"strings"
"github.com/dolthub/go-mysql-server/sql"
gmstypes "github.com/dolthub/go-mysql-server/sql/types"
"github.com/dolthub/ishell"
"github.com/fatih/color"
"golang.org/x/exp/slices"
@@ -164,7 +164,9 @@ func (cmd AddCmd) Exec(ctx context.Context, commandStr string, args []string, _
}
func patchWorkflow(sqlCtx *sql.Context, queryist cli.Queryist, tables []string) int {
if len(tables) == 0 {
if len(tables) == 0 || (len(tables) == 1 && tables[0] == ".") {
tables = tables[:0] // in the event that the user specified '.' as the only argument, we want to clear the list of tables
// Get the list of tables to patch
_, rowIter, _, err := queryist.Query(sqlCtx, "select table_name from dolt_status where not staged")
if err != nil {
@@ -183,6 +185,12 @@ func patchWorkflow(sqlCtx *sql.Context, queryist cli.Queryist, tables []string)
tables = append(tables, tbl)
}
}
if len(tables) == 0 {
cli.Println("No changes.")
return 0
}
sort.Strings(tables)
runAddPatchShell(sqlCtx, queryist, tables)
@@ -224,12 +232,12 @@ func runAddPatchShell(sqlCtx *sql.Context, queryist cli.Queryist, tables []strin
shell.AddCmd(&ishell.Cmd{
Name: "y",
Help: "stage the current change",
Func: state.opYes,
Func: state.stageCurrentChange,
})
shell.AddCmd(&ishell.Cmd{
Name: "n",
Help: "do not stage the current change",
Func: state.opNo,
Func: state.skipCurrentChange,
})
shell.AddCmd(&ishell.Cmd{
Name: "q",
@@ -241,12 +249,12 @@ func runAddPatchShell(sqlCtx *sql.Context, queryist cli.Queryist, tables []strin
shell.AddCmd(&ishell.Cmd{
Name: "a",
Help: "add all changes in this table",
Func: state.opAddAllOfTable,
Func: state.addRemainingInTable,
})
shell.AddCmd(&ishell.Cmd{
Name: "d",
Help: "do not stage any further changes in this table",
Func: state.opSkipTable,
Func: state.skipRemainingInTable,
})
shell.AddCmd(&ishell.Cmd{
Name: "s",
@@ -287,7 +295,7 @@ func queryForUnstagedChanges(sqlCtx *sql.Context, queryist cli.Queryist, tables
}
if len(rows) == 0 {
// This can happen if the user has added all changes in a table, thn restarted the workflow.
// This can happen if the user has added all changes in a table, then restarted the workflow.
continue
}
@@ -353,20 +361,11 @@ func queryForUnstagedChanges(sqlCtx *sql.Context, queryist cli.Queryist, tables
}
func coerceToInt(val interface{}) (int, error) {
switch v := val.(type) {
case int:
return v, nil
case int64:
return int(v), nil
case string:
i, err := strconv.Atoi(v)
if err != nil {
return 0, err
}
return i, nil
default:
return 0, errors.New("Expected int, int64 or string")
val, _, err := gmstypes.Int32.Convert(val)
if err != nil {
return 0, err
}
return int(val.(int32)), nil
}
// queryForSingleChange queries the dolt_workspace_* table for the row with the given ID.
@@ -412,8 +411,8 @@ type patchState struct {
err error
}
// opYes stages the current change. "a" command.
func (ps *patchState) opYes(c *ishell.Context) {
// stageCurrentChange stages the current change. "a" command.
func (ps *patchState) stageCurrentChange(c *ishell.Context) {
qry := fmt.Sprintf("UPDATE dolt_workspace_%s SET staged = TRUE WHERE id = %d", ps.currentTable, ps.currentRowId)
_, iter, _, err := ps.queryist.Query(ps.sqlCtx, qry)
if err != nil {
@@ -422,7 +421,7 @@ func (ps *patchState) opYes(c *ishell.Context) {
return
}
// The Update operation doesn't return any rows, but we need to itterate over it to ensure that the update
// The Update operation doesn't return any rows, but we need to iterate over it to ensure that the update
// is made when the queryist we are using for a local query engine.
for {
_, err = iter.Next(ps.sqlCtx)
@@ -451,8 +450,8 @@ func (ps *patchState) opYes(c *ishell.Context) {
}
}
// opNo does not stage the current change. "n" command.
func (ps *patchState) opNo(c *ishell.Context) {
// skipCurrentChange does not stage the current change. "n" command.
func (ps *patchState) skipCurrentChange(c *ishell.Context) {
ps.currentRowId++
if ps.currentRowId <= ps.currentTableLastRowId {
ps.setCurrentRowState(c)
@@ -461,13 +460,13 @@ func (ps *patchState) opNo(c *ishell.Context) {
}
}
// opSkipTable skips the current table. "d" command.
func (ps *patchState) opSkipTable(c *ishell.Context) {
// skipRemainingInTable skips the current table. "d" command.
func (ps *patchState) skipRemainingInTable(c *ishell.Context) {
ps.nextTable(c)
}
// opAddAllOfTable adds all changes in the current table. "a" command.
func (ps *patchState) opAddAllOfTable(c *ishell.Context) {
// addRemainingInTable adds all changes in the current table. "a" command.
func (ps *patchState) addRemainingInTable(c *ishell.Context) {
// grab the row id.
id, err := coerceToInt(ps.currentRow[0])
if err != nil {
@@ -575,7 +574,9 @@ func (ps *patchState) nextTable(c *ishell.Context) {
ps.setCurrentRowState(c)
} else {
c.Stop()
if c != nil {
c.Stop()
}
}
}
@@ -671,7 +672,7 @@ func printTableSummary(tables []string, counts map[string]*tablePatchInfo) {
for _, tbl := range tables {
c := counts[tbl]
if c == nil {
// This can happen if the user has added all changes in a table, thn restarted the workflow.
// This can happen if the user has added all changes in a table, then restarted the workflow.
continue
}
@@ -684,7 +685,7 @@ func printTableSummary(tables []string, counts map[string]*tablePatchInfo) {
totalChgCount += c.total()
}
// If the user has a lot of changes, we want to inform the user them may have better options.
// If the user has a lot of changes, we want to inform the user they may have better options.
if totalChgCount > 25 {
warning := `You have %d changes in total. Consider updating dolt_workspace_* tables directly as
'add --patch' requires you to individually evaluate each changed row.

View File

@@ -16,5 +16,5 @@
package doltversion
const (
Version = "1.42.19"
Version = "1.42.20"
)

View File

@@ -15,7 +15,7 @@ require (
github.com/dolthub/fslock v0.0.3
github.com/dolthub/ishell v0.0.0-20240701202509-2b217167d718
github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81
github.com/dolthub/vitess v0.0.0-20240910182452-9291457d0a98
github.com/dolthub/vitess v0.0.0-20240913073519-a282f4c775fc
github.com/dustin/go-humanize v1.0.1
github.com/fatih/color v1.16.0
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568
@@ -57,7 +57,7 @@ require (
github.com/cespare/xxhash/v2 v2.2.0
github.com/creasty/defaults v1.6.0
github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2
github.com/dolthub/go-mysql-server v0.18.2-0.20240912201416-87cdecf51cd1
github.com/dolthub/go-mysql-server v0.18.2-0.20240913084037-b11701419243
github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63
github.com/dolthub/swiss v0.1.0
github.com/goccy/go-json v0.10.2

View File

@@ -183,8 +183,8 @@ 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-icu-regex v0.0.0-20230524105445-af7e7991c97e h1:kPsT4a47cw1+y/N5SSCkma7FhAPw7KeGmD6c9PBZW9Y=
github.com/dolthub/go-icu-regex v0.0.0-20230524105445-af7e7991c97e/go.mod h1:KPUcpx070QOfJK1gNe0zx4pA5sicIK1GMikIGLKC168=
github.com/dolthub/go-mysql-server v0.18.2-0.20240912201416-87cdecf51cd1 h1:w2C4QGnyXtoqya+Ug3G8v63gBLLYGF5HBsEujLVgCtQ=
github.com/dolthub/go-mysql-server v0.18.2-0.20240912201416-87cdecf51cd1/go.mod h1:qG/flwaEzJaI/ZvwlEZyNljSU9UOO54r1Yhv0GnxNgk=
github.com/dolthub/go-mysql-server v0.18.2-0.20240913084037-b11701419243 h1:o1Dz7IKnNdypk8XpvWhgG4lmexggxptFZ1a8baHgpyI=
github.com/dolthub/go-mysql-server v0.18.2-0.20240913084037-b11701419243/go.mod h1:Qw0rloOdFuqoKMJIHtAcThfvJ5OCjG/nEQgoZ0xwbcs=
github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63 h1:OAsXLAPL4du6tfbBgK0xXHZkOlos63RdKYS3Sgw/dfI=
github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63/go.mod h1:lV7lUeuDhH5thVGDCKXbatwKy2KW80L4rMT46n+Y2/Q=
github.com/dolthub/ishell v0.0.0-20240701202509-2b217167d718 h1:lT7hE5k+0nkBdj/1UOSFwjWpNxf+LCApbRHgnCA17XE=
@@ -197,8 +197,8 @@ github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81 h1:7/v8q9X
github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81/go.mod h1:siLfyv2c92W1eN/R4QqG/+RjjX5W2+gCTRjZxBjI3TY=
github.com/dolthub/swiss v0.1.0 h1:EaGQct3AqeP/MjASHLiH6i4TAmgbG/c4rA6a1bzCOPc=
github.com/dolthub/swiss v0.1.0/go.mod h1:BeucyB08Vb1G9tumVN3Vp/pyY4AMUnr9p7Rz7wJ7kAQ=
github.com/dolthub/vitess v0.0.0-20240910182452-9291457d0a98 h1:f4Y0ZUO3SPsgS88w5X377tYSHVLlA8JzvKbNu2C5uks=
github.com/dolthub/vitess v0.0.0-20240910182452-9291457d0a98/go.mod h1:uBvlRluuL+SbEWTCZ68o0xvsdYZER3CEG/35INdzfJM=
github.com/dolthub/vitess v0.0.0-20240913073519-a282f4c775fc h1:vOtgyBF27SgUQzkaQbFyuaouK0uEWG3ZOC3l8h2K6vs=
github.com/dolthub/vitess v0.0.0-20240913073519-a282f4c775fc/go.mod h1:uBvlRluuL+SbEWTCZ68o0xvsdYZER3CEG/35INdzfJM=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=

View File

@@ -15,6 +15,7 @@
package dfunctions
import (
"errors"
"fmt"
"github.com/dolthub/go-mysql-server/sql"
@@ -39,13 +40,6 @@ func NewMergeBase(left, right sql.Expression) sql.Expression {
// Eval implements the sql.Expression interface.
func (d MergeBase) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
if _, ok := d.Left().Type().(sql.StringType); !ok {
return nil, sql.ErrInvalidType.New(d.Left().Type())
}
if _, ok := d.Right().Type().(sql.StringType); !ok {
return nil, sql.ErrInvalidType.New(d.Right().Type())
}
leftSpec, err := d.Left().Eval(ctx, row)
if err != nil {
return nil, err
@@ -59,7 +53,17 @@ func (d MergeBase) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
return nil, nil
}
left, right, err := resolveRefSpecs(ctx, leftSpec.(string), rightSpec.(string))
leftStr, ok := leftSpec.(string)
if !ok {
return nil, errors.New("left value is not a string")
}
rightStr, ok := rightSpec.(string)
if !ok {
return nil, errors.New("right value is not a string")
}
left, right, err := resolveRefSpecs(ctx, leftStr, rightStr)
if err != nil {
return nil, err
}

View File

@@ -147,8 +147,6 @@ func (p *Provider) Load(ctx *sql.Context, fs filesys.Filesys, db dsess.SqlDataba
}
}
p.mu.Lock()
defer p.mu.Unlock()
p.setStatDb(strings.ToLower(db.Name()), statsDb)
return
}

View File

@@ -37,15 +37,15 @@ func NewStatsInitDatabaseHook(
denv *env.DoltEnv,
db dsess.SqlDatabase,
) error {
statsDb, err := statsProv.sf.Init(ctx, db, statsProv.pro, denv.FS, env.GetCurrentUserHomeDir)
if err != nil {
ctx.GetLogger().Debugf("statistics load error: %s", err.Error())
return nil
dbName := strings.ToLower(db.Name())
if _, ok := statsProv.getStatDb(dbName); !ok {
statsDb, err := statsProv.sf.Init(ctx, db, statsProv.pro, denv.FS, env.GetCurrentUserHomeDir)
if err != nil {
ctx.GetLogger().Debugf("statistics load error: %s", err.Error())
return nil
}
statsProv.setStatDb(dbName, statsDb)
}
statsProv.mu.Lock()
statsProv.setStatDb(strings.ToLower(db.Name()), statsDb)
statsProv.mu.Unlock()
ctx.GetLogger().Debugf("statistics refresh: initialize %s", name)
return statsProv.InitAutoRefresh(ctxFactory, name, bThreads)
}

View File

@@ -186,6 +186,8 @@ func (p *Provider) GetTableDoltStats(ctx *sql.Context, branch, db, table string)
}
func (p *Provider) setStatDb(name string, db Database) {
p.mu.Lock()
defer p.mu.Unlock()
p.statDbs[name] = db
}

View File

@@ -0,0 +1,18 @@
#!/usr/bin/expect
set timeout 5
set env(NO_COLOR) 1
source "$env(BATS_CWD)/helper/common_expect_functions.tcl"
# Specify tables
spawn dolt add -p coordinates colors
# colors table will be first (alpha order). Add everything.
expect_with_defaults_2 { Yellow | 255 | 255 } {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "a\r"; }
# coordinates table is next.
expect_with_defaults_2 {| - | 2 | 3.3 | 4.4 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "d\r"; }
expect eof
exit

View File

@@ -0,0 +1,15 @@
#!/usr/bin/expect
set timeout 5
set env(NO_COLOR) 1
source "$env(BATS_CWD)/helper/common_expect_functions.tcl"
spawn dolt add -p
expect_with_defaults {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "?\r"; }
expect_with_defaults_2 {\? - show this help} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "q\r"; }
expect eof
exit

View File

@@ -0,0 +1,22 @@
#!/usr/bin/expect
set timeout 5
set env(NO_COLOR) 1
source "$env(BATS_CWD)/helper/common_expect_functions.tcl"
spawn dolt add --patch
# Header Regex for:
# Table Added / Modified / Removed
# ===== ===== ======== =======
# keyless 1 1 1
set header {.*Table\s+Added\s+/\s+Modified\s+/\s+Removed\s+=+\s+=+\s+=+\s+=+\s+keyless\s+2\s+0\s+2.*}
expect_with_defaults_2 $header {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 1 | 1 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect_with_defaults_2 {| \+ | 4 | 4 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| \+ | 4 | 4 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect eof
exit

View File

@@ -0,0 +1,25 @@
#!/usr/bin/expect
set timeout 5
set env(NO_COLOR) 1
source "$env(BATS_CWD)/helper/common_expect_functions.tcl"
spawn dolt add -p
# This test will reject the first change for each of the 3 tables, then accept the rest.
expect_with_defaults_2 {| \+ | 0 | Yellow | 255 | 255 | 0 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect_with_defaults_2 {| - | 2 | Green | 0 | 255 | 0 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "a\r"; }
expect_with_defaults_2 {| - | 2 | 3.3 | 4.4 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect_with_defaults_2 {| < | 3 | 5.5 | 6.6 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "a\r"; }
expect_with_defaults_2 {| < | 1 | neil |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect_with_defaults_2 {| - | 2 | sami |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "a\r"; }
expect eof
exit

View File

@@ -0,0 +1,43 @@
#!/usr/bin/expect
set timeout 5
set env(NO_COLOR) 1
source "$env(BATS_CWD)/helper/common_expect_functions.tcl"
spawn dolt add --patch
# This is a long script, but the idea is simple. Input y,n,y,s repeatedly and ensure that the right prompts are seen
expect_with_defaults_2 {| \+ | 0 | Yellow | 255 | 255 | 0 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 2 | Green | 0 | 255 | 0 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect_with_defaults_2 {| > | 3 | SkyBlue | 0 | 128 | 255 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 2 | 3.3 | 4.4 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "s\r"; }
expect_with_defaults_2 {| - | 2 | Green | 0 | 255 | 0 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 2 | 3.3 | 4.4 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect_with_defaults_2 {| > | 3 | 5.5 | 100.001 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| \+ | 4 | 42.24 | 23.32 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "s\r"; }
expect_with_defaults_2 {| - | 2 | 3.3 | 4.4 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| \+ | 4 | 42.24 | 23.32 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect_with_defaults_2 {| > | 1 | joey |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 2 | sami |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "s\r"; }
expect_with_defaults_2 {| \+ | 4 | 42.24 | 23.32 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 2 | sami |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect_with_defaults_2 {| \+ | 4 | john |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect eof
exit

View File

@@ -0,0 +1,60 @@
#!/usr/bin/expect
set timeout 5
set env(NO_COLOR) 1
source "$env(BATS_CWD)/helper/common_expect_functions.tcl"
spawn dolt add --patch
# Header Regex for:
# Table Added / Modified / Removed
# ===== ===== ======== =======
# colors 1 1 1
# coordinates 1 1 1
# names 1 1 1
set header {.*Table\s+Added\s+/\s+Modified\s+/\s+Removed\s+=+\s+=+\s+=+\s+=+\s+colors\s+1\s+1\s+1\s+coordinates\s+1\s+1\s+1\s+names\s+1\s+1\s+1.*}
expect_with_defaults_2 $header {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 2 | Green | 0 | 255 | 0 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect_with_defaults_2 {| > | 3 | SkyBlue | 0 | 128 | 255 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 2 | 3.3 | 4.4 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "s\r"; }
# Regex to match updated counts.
# Table Added / Modified / Removed
# ===== ===== ======== =======
# colors 0 0 1
# coordinates 1 1 1
# names 1 1 1
set header {.*Table\s+Added\s+/\s+Modified\s+/\s+Removed\s+=+\s+=+\s+=+\s+=+\s+colors\s+0\s+0\s+1\s+coordinates\s+1\s+1\s+1\s+names\s+1\s+1\s+1.*}
expect_with_defaults_2 $header {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 2 | 3.3 | 4.4 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect_with_defaults_2 {| > | 3 | 5.5 | 100.001 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| \+ | 4 | 42.24 | 23.32 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "s\r"; }
# Regex to match updated counts, and no colors table:
# Table Added / Modified / Removed
# ===== ===== ======== =======
# coordinates 1 0 1
# names 1 1 1
set header {.*Table\s+Added\s+/\s+Modified\s+/\s+Removed\s+=+\s+=+\s+=+\s+=+\s+coordinates\s+1\s+0\s+1\s+names\s+1\s+1\s+1.*}
expect_with_defaults_2 $header {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| \+ | 4 | 42.24 | 23.32 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect_with_defaults_2 {| > | 1 | joey |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 2 | sami |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "s\r"; }
# Regex for:
# Table Added / Modified / Removed
# ===== ===== ======== =======
# coordinates 1 0 0
# names 1 0 1
set header {.*Table\s+Added\s+/\s+Modified\s+/\s+Removed\s+=+\s+=+\s+=+\s+=+\s+coordinates\s+1\s+0\s+0\s+names\s+1\s+0\s+1.*}
expect_with_defaults_2 $header {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 2 | sami |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "n\r"; }
expect_with_defaults_2 {| \+ | 4 | john |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect eof
exit

View File

@@ -0,0 +1,26 @@
#!/usr/bin/expect
set timeout 5
set env(NO_COLOR) 1
source "$env(BATS_CWD)/helper/common_expect_functions.tcl"
# Verify add -p . gets all the tables.
spawn dolt add -p .
# This test will accept the first change for each of the 3 tables, then skip the rest.
expect_with_defaults_2 {| \+ | 0 | Yellow | 255 | 255 | 0 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 2 | Green | 0 | 255 | 0 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "d\r"; }
expect_with_defaults_2 {| - | 2 | 3.3 | 4.4 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| < | 3 | 5.5 | 6.6 |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "d\r"; }
expect_with_defaults_2 {| < | 1 | neil |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "y\r"; }
expect_with_defaults_2 {| - | 2 | sami |} {Stage this row \[y,n,q,a,d,s,\?\]\? } { send "d\r"; }
expect eof
exit

View File

@@ -0,0 +1,326 @@
#! /usr/bin/env bats
load $BATS_TEST_DIRNAME/helper/common.bash
setup() {
skiponwindows "Need to install expect and make this script work on windows."
setup_common
dolt sql <<SQL
CREATE TABLE names (pk int primary key, name varchar(8));
CREATE TABLE colors (pk int primary key, name varchar(8), red int, green int, blue int);
CREATE TABLE coordinates (pk int primary key, x float, y float);
INSERT INTO names VALUES (1, 'neil');
INSERT INTO names VALUES (2, 'sami');
INSERT INTO names VALUES (3, 'jane');
INSERT INTO colors VALUES (1, 'Red', 255, 0, 0);
INSERT INTO colors VALUES (2, 'Green', 0, 255, 0);
INSERT INTO colors VALUES (3, 'Blue', 0, 0, 255);
INSERT INTO coordinates VALUES (1, 1.1, 2.2);
INSERT INTO coordinates VALUES (2, 3.3, 4.4);
INSERT INTO coordinates VALUES (3, 5.5, 6.6);
CALL dolt_commit('-Am', 'main commit 1');
UPDATE names SET name = 'joey' WHERE pk = 1;
UPDATE colors SET name = 'SkyBlue', red = 0, green = 128, blue = 255 WHERE pk = 3;
UPDATE coordinates SET y = 100.001 WHERE pk = 3;
INSERT INTO names VALUES (4,'john');
INSERT INTO colors VALUES (0, 'Yellow', 255, 255, 0); // use 0 pk to ensure ordering is different from other tables.
INSERT INTO coordinates VALUES (4, 42.24, 23.32);
DELETE FROM names WHERE pk = 2;
DELETE FROM colors WHERE pk = 2;
DELETE FROM coordinates WHERE pk = 2;
SQL
# The default setup has three tables, at this stage there have the a single update, insert, and delete
# on each table. In addition, each contains an unmodified row. Finally, the diff shows that the updates
# to each table are in different orders based on the primary key.
#
# diff --dolt a/colors b/colors
# --- a/colors
# +++ b/colors
# +---+----+---------+-----+-------+------+
# | | pk | name | red | green | blue |
# +---+----+---------+-----+-------+------+
# | + | 0 | Yellow | 255 | 255 | 0 |
# | - | 2 | Green | 0 | 255 | 0 |
# | < | 3 | Blue | 0 | 0 | 255 |
# | > | 3 | SkyBlue | 0 | 128 | 255 |
# +---+----+---------+-----+-------+------+
# diff --dolt a/coordinates b/coordinates
# --- a/coordinates
# +++ b/coordinates
# +---+----+-------+---------+
# | | pk | x | y |
# +---+----+-------+---------+
# | - | 2 | 3.3 | 4.4 |
# | < | 3 | 5.5 | 6.6 |
# | > | 3 | 5.5 | 100.001 |
# | + | 4 | 42.24 | 23.32 |
# +---+----+-------+---------+
# diff --dolt a/names b/names
# --- a/names
# +++ b/names
# +---+----+------+
# | | pk | name |
# +---+----+------+
# | < | 1 | neil |
# | > | 1 | joey |
# | - | 2 | sami |
# | + | 4 | john |
# +---+----+------+
#
}
teardown() {
teardown_common
}
# bats test_tags=no_lambda
@test "add-patch: clean workspace" {
dolt reset --hard
run dolt add --patch
[ "$status" -eq 0 ]
[[ "$output" =~ "No changes." ]] || false
}
# bats test_tags=no_lambda
@test "add-patch: all changes staged" {
dolt add .
run dolt add --patch
[ "$status" -eq 0 ]
[[ "$output" =~ "No changes." ]] || false
}
# bats test_tags=no_lambda
@test "add-patch: help and quit" {
run dolt sql -r csv -q "select dolt_hashof_db()"
[ $status -eq 0 ]
ORIG_DB_HASH=$(echo "$output" | awk 'NR==2')
run $BATS_TEST_DIRNAME/add-patch-expect/help_quit.expect
[ $status -eq 0 ]
run dolt sql -r csv -q "select dolt_hashof_db()"
[ $status -eq 0 ]
DB_HASH=$(echo "$output" | awk 'NR==2')
# Verify that the state of the database hasn't changed.
[[ "$DB_HASH" == "$ORIG_DB_HASH" ]] || false
}
# bats test_tags=no_lambda
@test "add-patch: a then d for two tables" {
# This test does: `add -p coordinates colors` -> 'a' -> 'd'
run $BATS_TEST_DIRNAME/add-patch-expect/all_none.expect
[ $status -eq 0 ]
run dolt sql -q "select name from colors AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "Red" ]] || false
[[ "$output" =~ "SkyBlue" ]] || false
[[ "$output" =~ "Yellow" ]] || false
[[ ! "$output" =~ "Green" ]] || false
# Should be no changes on coordinates.
run dolt sql -q "select pk, y from coordinates AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 1 | 2.2 |" ]] || false
[[ "$output" =~ "| 2 | 4.4 |" ]] || false
[[ "$output" =~ "| 3 | 6.6 |" ]] || false
[[ ! "$output" =~ "23.32" ]] || false # Value for inserted row - should not be there.
# Should be no changes on names.
run dolt sql -q "select pk, name from names AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 1 | neil |" ]] || false
[[ "$output" =~ "| 2 | sami |" ]] || false
[[ "$output" =~ "| 3 | jane |" ]] || false
[[ ! "$output" =~ "john" ]] || false # Value for inserted row - should not be there.
}
# bats test_tags=no_lambda
@test "add-patch: y/n repeatedly with restarts" {
# This test repeatedly does 'y/n/y/s' until the program exits.
run $BATS_TEST_DIRNAME/add-patch-expect/restart_multiple_times.expect
[ $status -eq 0 ]
run dolt sql -q "select name from colors AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "Red" ]] || false
[[ "$output" =~ "SkyBlue" ]] || false
[[ "$output" =~ "Yellow" ]] || false
[[ ! "$output" =~ "Green" ]] || false
run dolt sql -q "select pk, y from coordinates AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 1 | 2.2 |" ]] || false
[[ "$output" =~ "| 3 | 100.001 |" ]] || false
[[ "$output" =~ "| 4 | 23.32 |" ]] || false
run dolt sql -q "select pk, name from names AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 1 | joey |" ]] || false
[[ "$output" =~ "| 2 | sami |" ]] || false
[[ "$output" =~ "| 3 | jane |" ]] || false
[[ "$output" =~ "| 4 | john |" ]] || false
}
# bats test_tags=no_lambda
@test "add-patch: summary updates are correct" {
# Similar to the previous test, but this time we're ensuring that the summary updates are correct.
run $BATS_TEST_DIRNAME/add-patch-expect/summary_updates.expect
[ $status -eq 0 ]
# Status should be identical to the previous test.
run dolt sql -q "select name from colors AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "Red" ]] || false
[[ "$output" =~ "SkyBlue" ]] || false
[[ "$output" =~ "Yellow" ]] || false
[[ ! "$output" =~ "Green" ]] || false
run dolt sql -q "select pk, y from coordinates AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 1 | 2.2 |" ]] || false
[[ "$output" =~ "| 3 | 100.001 |" ]] || false
[[ "$output" =~ "| 4 | 23.32 |" ]] || false
run dolt sql -q "select pk, name from names AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 1 | joey |" ]] || false
[[ "$output" =~ "| 2 | sami |" ]] || false
[[ "$output" =~ "| 3 | jane |" ]] || false
[[ "$output" =~ "| 4 | john |" ]] || false
}
# bats test_tags=no_lambda
@test "add-patch: y then d" {
# Accept the first change for each table, then skip the rest.
run $BATS_TEST_DIRNAME/add-patch-expect/yes_then_d.expect
[ $status -eq 0 ]
run dolt sql -q "select pk,name from colors AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "0 | Yellow" ]] || false
[[ "$output" =~ "1 | Red" ]] || false
[[ "$output" =~ "2 | Green" ]] || false
[[ "$output" =~ "3 | Blue" ]] || false
# verify no extra rows in table we didn't look for.
run dolt sql -q "select sum(pk) as s from colors AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 6 |" ]] || false # Yellow added as pk=0, so 0+1+2+3
run dolt sql -q "select pk, y from coordinates AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 1 | 2.2 |" ]] || false
[[ "$output" =~ "| 3 | 6.6 |" ]] || false
# verify no extra rows in table we didn't look for.
run dolt sql -q "select sum(pk) as s from coordinates AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 4 |" ]] || false
run dolt sql -q "select pk, name from names AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 1 | joey |" ]] || false
[[ "$output" =~ "| 2 | sami |" ]] || false
[[ "$output" =~ "| 3 | jane |" ]] || false
run dolt sql -q "select sum(pk) as s from names AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 6 |" ]] || false
}
# bats test_tags=no_lambda
@test "add-patch: n then a" {
# Accept the reject fir change, then accept the rest.
run $BATS_TEST_DIRNAME/add-patch-expect/no_then_a.expect
[ $status -eq 0 ]
run dolt sql -q "select pk,name from colors AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 1 | Red |" ]] || false
[[ "$output" =~ "| 3 | SkyBlue |" ]] || false
# verify no extra rows in table we didn't look for.
run dolt sql -q "select sum(pk) as s from colors AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 4 |" ]] || false
run dolt sql -q "select pk, y from coordinates AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 1 | 2.2 |" ]] || false
[[ "$output" =~ "| 2 | 4.4 |" ]] || false
[[ "$output" =~ "| 3 | 100.001 |" ]] || false
[[ "$output" =~ "| 4 | 23.32 |" ]] || false
# verify no extra rows in table we didn't look for.
run dolt sql -q "select sum(pk) as s from coordinates AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 10 |" ]] || false
run dolt sql -q "select pk, name from names AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 1 | neil |" ]] || false
[[ "$output" =~ "| 3 | jane |" ]] || false
[[ "$output" =~ "| 4 | john |" ]] || false
run dolt sql -q "select sum(pk) as s from names AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "| 8 |" ]] || false
}
# bats test_tags=no_lambda
@test "add-patch: keyless table" {
dolt add .
dolt commit -m "make clean workspace"
dolt sql -q "create table keyless (x int, y int)"
dolt sql -q "insert into keyless values (1,1), (2,2), (3,3), (1,1), (2,2), (3,3)"
dolt commit -A -m "add keyless table with data."
# This update, while it updates "all rows", the diff will be:
# diff --dolt a/keyless b/keyless
# --- a/keyless
# +++ b/keyless
# +---+---+---+
# | | x | y |
# +---+---+---+
# | - | 1 | 1 |
# | - | 1 | 1 |
# | + | 4 | 4 |
# | + | 4 | 4 |
# +---+---+---+
dolt sql -q "update keyless set x = x + 1, y = y + 1"
run $BATS_TEST_DIRNAME/add-patch-expect/keyless.expect
[ $status -eq 0 ]
run dolt sql -q "select * from keyless AS OF STAGED"
# Output should be:
# +---+---+
# | x | y |
# +---+---+
# | 3 | 3 |
# | 3 | 3 |
# | 2 | 2 |
# | 2 | 2 |
# | 1 | 1 |
# | 4 | 4 |
# +---+---+
[ $status -eq 0 ]
[[ "$output" =~ "3 | 3" ]] || false
[[ "$output" =~ "2 | 2" ]] || false
[[ "$output" =~ "1 | 1" ]] || false
[[ "$output" =~ "4 | 4" ]] || false
# verify no extra rows in table we didn't look for. 3 + 3 + 2 + 2 + 1 + 4 = 15
run dolt sql -q "select sum(x) as s from keyless AS OF STAGED"
[ $status -eq 0 ]
[[ "$output" =~ "15" ]] || false
}

View File

@@ -0,0 +1,62 @@
proc expect_with_defaults {pattern action} {
expect {
-re $pattern {
# puts "Matched pattern: $pattern"
eval $action
}
timeout {
puts "<<Timeout>>";
exit 1
}
eof {
puts "<<End of File reached>>";
exit 1
}
failed {
puts "<<Failed>>";
exit 1
}
}
}
proc expect_with_defaults_2 {patternA patternB action} {
# First, match patternA
expect {
-re $patternA {
puts "<<Matched expected pattern A: $patternA>>"
# Now match patternB
expect {
-re $patternB {
puts "<<Matched expected pattern B: $patternB>>"
eval $action
}
timeout {
puts "<<Timeout waiting for pattern B>>"
exit 1
}
eof {
puts "<<End of File reached while waiting for pattern B>>"
exit 1
}
failed {
puts "<<Failed while waiting for pattern B>>"
exit 1
}
}
}
timeout {
puts "<<Timeout waiting for pattern A>>"
exit 1
}
eof {
puts "<<End of File reached while waiting for pattern A>>"
exit 1
}
failed {
puts "<<Failed while waiting for pattern A>>"
exit 1
}
}
}

View File

@@ -3,68 +3,7 @@
set timeout 5
set env(NO_COLOR) 1
proc expect_with_defaults {pattern action} {
expect {
-re $pattern {
# puts "Matched pattern: $pattern"
eval $action
}
timeout {
puts "<<Timeout>>";
exit 1
}
eof {
puts "<<End of File reached>>";
exit 1
}
failed {
puts "<<Failed>>";
exit 1
}
}
}
proc expect_with_defaults_2 {patternA patternB action} {
# First, match patternA
expect {
-re $patternA {
puts "<<Matched expected pattern A: $patternA>>"
# Now match patternB
expect {
-re $patternB {
puts "<<Matched expected pattern B: $patternB>>"
eval $action
}
timeout {
puts "<<Timeout waiting for pattern B>>"
exit 1
}
eof {
puts "<<End of File reached while waiting for pattern B>>"
exit 1
}
failed {
puts "<<Failed while waiting for pattern B>>"
exit 1
}
}
}
timeout {
puts "<<Timeout waiting for pattern A>>"
exit 1
}
eof {
puts "<<End of File reached while waiting for pattern A>>"
exit 1
}
failed {
puts "<<Failed while waiting for pattern A>>"
exit 1
}
}
}
source "$env(BATS_CWD)/helper/common_expect_functions.tcl"
spawn dolt sql

View File

@@ -130,6 +130,26 @@ teardown() {
[ "$status" -eq 1 ]
}
@test "stats: restart in shell doesn't drop db, issue#8345" {
cd repo2
dolt sql -q "insert into xy values (0,0), (1,1), (2,2), (3,3), (4,4)"
dolt sql -q "insert into ab values (0,0), (1,1), (2,2), (3,3), (4,4)"
dolt sql -q "ANALYZE table xy, ab"
run dolt sql -r csv <<EOF
select count(*) from dolt_statistics;
set @@GLOBAL.dolt_stats_auto_refresh_interval = 2;
call dolt_stats_restart();
select count(*) from dolt_statistics;
select sleep(3);
select count(*) from dolt_statistics;
EOF
[ "${lines[1]}" = "4" ]
[ "${lines[5]}" = "4" ]
[ "${lines[9]}" = "4" ]
[ "$status" -eq 0 ]
}
@test "stats: stats roundtrip restart" {
cd repo2
@@ -383,6 +403,7 @@ SQL
dolt sql <<SQL
use repo2;
insert into xy values (0,0);
analyze table xy;
SQL
sleep 1