add dolt_cherry_pick procedure (#5233)

This commit is contained in:
jennifersp
2023-01-30 10:46:28 -08:00
committed by GitHub
parent 699174a286
commit e956ba9516
22 changed files with 655 additions and 33 deletions

View File

@@ -88,7 +88,7 @@ func (cmd CherryPickCmd) Exec(ctx context.Context, commandStr string, args []str
usage()
return 1
} else if apr.NArg() > 1 {
return HandleVErrAndExitCode(errhand.BuildDError("multiple commits not supported yet.").SetPrintUsage().Build(), usage)
return HandleVErrAndExitCode(errhand.BuildDError("cherry-picking multiple commits is not supported yet").SetPrintUsage().Build(), usage)
}
cherryStr := apr.Arg(0)
@@ -97,17 +97,12 @@ func (cmd CherryPickCmd) Exec(ctx context.Context, commandStr string, args []str
return HandleVErrAndExitCode(verr, usage)
}
authorStr := ""
if as, ok := apr.GetValue(cli.AuthorParam); ok {
authorStr = as
}
verr := cherryPick(ctx, dEnv, cherryStr, authorStr)
verr := cherryPick(ctx, dEnv, cherryStr)
return HandleVErrAndExitCode(verr, usage)
}
// cherryPick returns error if any step of cherry-picking fails. It receives cherry-picked commit and performs cherry-picking and commits.
func cherryPick(ctx context.Context, dEnv *env.DoltEnv, cherryStr, authorStr string) errhand.VerboseError {
func cherryPick(ctx context.Context, dEnv *env.DoltEnv, cherryStr string) errhand.VerboseError {
// check for clean working state
headRoot, err := dEnv.HeadRoot(ctx)
if err != nil {
@@ -166,12 +161,7 @@ func cherryPick(ctx context.Context, dEnv *env.DoltEnv, cherryStr, authorStr str
return errhand.BuildDError("dolt add failed").AddCause(err).Build()
}
// Pass in the final parameters for the author string.
commitParams := []string{"-m", commitMsg}
if authorStr != "" {
commitParams = append(commitParams, "--author", authorStr)
}
res = CommitCmd{}.Exec(ctx, "commit", commitParams, dEnv)
if res != 0 {
return errhand.BuildDError("dolt commit failed").AddCause(err).Build()

View File

@@ -45,9 +45,9 @@ const (
EncodingBytesAddr Encoding = 21
EncodingCommitAddr Encoding = 22
EncodingStringAddr Encoding = 23
EncodingJSONAddr Encoding = 24
EncodingCell Encoding = 25
EncodingString Encoding = 128
EncodingJSONAddr Encoding = 24
EncodingCell Encoding = 25
EncodingString Encoding = 128
EncodingBytes Encoding = 129
EncodingDecimal Encoding = 130
EncodingJSON Encoding = 131

View File

@@ -25,7 +25,7 @@ import (
"github.com/dolthub/go-mysql-server/sql"
)
// doltAdd is the stored procedure version of the function `dolt_add`.
// doltAdd is the stored procedure version for the CLI command `dolt add`.
func doltAdd(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltAdd(ctx, args)
if err != nil {

View File

@@ -37,7 +37,7 @@ const (
statusErr = 0
)
// doltBackup is the stored procedure version of the function `dolt_backup`.
// doltBackup is the stored procedure version for the CLI command `dolt backup`.
func doltBackup(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltBackup(ctx, args)
if err != nil {

View File

@@ -37,7 +37,7 @@ var (
InvalidArgErr = errors.New("error: invalid usage")
)
// doltBranch is the stored procedure version of the function `dolt_branch`.
// doltBranch is the stored procedure version for the CLI command `dolt branch`.
func doltBranch(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltBranch(ctx, args)
if err != nil {

View File

@@ -32,7 +32,7 @@ import (
var ErrEmptyBranchName = errors.New("error: cannot checkout empty string")
// doltCheckout is the stored procedure version of the function `dolt_checkout`.
// doltCheckout is the stored procedure version for the CLI command `dolt checkout`.
func doltCheckout(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltCheckout(ctx, args)
if err != nil {

View File

@@ -0,0 +1,206 @@
// Copyright 2023 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dprocedures
import (
"errors"
"fmt"
"strings"
"github.com/dolthub/go-mysql-server/sql"
"github.com/dolthub/dolt/go/cmd/dolt/cli"
"github.com/dolthub/dolt/go/libraries/doltcore/branch_control"
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
"github.com/dolthub/dolt/go/libraries/doltcore/merge"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
)
var ErrEmptyCherryPick = errors.New("cannot cherry-pick empty string")
var ErrCherryPickUncommittedChanges = errors.New("cannot cherry-pick with uncommitted changes")
// doltCherryPick is the stored procedure version for the CLI command `dolt cherry-pick`.
func doltCherryPick(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltCherryPick(ctx, args)
if err != nil {
return nil, err
}
return rowToIter(res), nil
}
func doDoltCherryPick(ctx *sql.Context, args []string) (string, error) {
// Get the information for the sql context.
dbName := ctx.GetCurrentDatabase()
if len(dbName) == 0 {
return "", fmt.Errorf("error: empty database name")
}
if err := branch_control.CheckAccess(ctx, branch_control.Permissions_Write); err != nil {
return "", err
}
apr, err := cli.CreateCherryPickArgParser().Parse(args)
if err != nil {
return "", err
}
// we only support cherry-picking a single commit for now.
if apr.NArg() == 0 {
return "", ErrEmptyCherryPick
} else if apr.NArg() > 1 {
return "", fmt.Errorf("cherry-picking multiple commits is not supported yet")
}
cherryStr := apr.Arg(0)
if len(cherryStr) == 0 {
return "", ErrEmptyCherryPick
}
dSess := dsess.DSessFromSess(ctx.Session)
roots, ok := dSess.GetRoots(ctx, dbName)
if !ok {
return "", sql.ErrDatabaseNotFound.New(dbName)
}
newWorkingRoot, commitMsg, err := cherryPick(ctx, dSess, roots, dbName, cherryStr)
if err != nil {
return "", err
}
err = dSess.SetRoot(ctx, dbName, newWorkingRoot)
if err != nil {
return "", err
}
res, err := doDoltAdd(ctx, []string{"-A"})
if err != nil {
return "", err
}
if res != 0 {
return "", fmt.Errorf("dolt add failed")
}
return doDoltCommit(ctx, []string{"-m", commitMsg})
}
// cherryPick checks that the current working set is clean, verifies the cherry-pick commit is not a merge commit
// or a commit without parent commit, performs merge and returns the new working set root value and
// the commit message of cherry-picked commit as the commit message of the new commit created during this command.
func cherryPick(ctx *sql.Context, dSess *dsess.DoltSession, roots doltdb.Roots, dbName, cherryStr string) (*doltdb.RootValue, string, error) {
// check for clean working set
headRootHash, err := roots.Head.HashOf()
if err != nil {
return nil, "", err
}
workingRootHash, err := roots.Working.HashOf()
if err != nil {
return nil, "", err
}
if workingRootHash != headRootHash {
return nil, "", ErrCherryPickUncommittedChanges
}
stagedRootHash, err := roots.Staged.HashOf()
if err != nil {
return nil, "", err
}
if stagedRootHash != headRootHash {
return nil, "", ErrCherryPickUncommittedChanges
}
doltDB, ok := dSess.GetDoltDB(ctx, dbName)
if !ok {
return nil, "", fmt.Errorf("failed to get DoltDB")
}
dbData, ok := dSess.GetDbData(ctx, dbName)
if !ok {
return nil, "", fmt.Errorf("failed to get dbData")
}
cherryCommitSpec, err := doltdb.NewCommitSpec(cherryStr)
if err != nil {
return nil, "", err
}
cherryCommit, err := doltDB.Resolve(ctx, cherryCommitSpec, dbData.Rsr.CWBHeadRef())
if err != nil {
return nil, "", err
}
if len(cherryCommit.DatasParents()) > 1 {
return nil, "", fmt.Errorf("cherry-picking a merge commit is not supported")
}
if len(cherryCommit.DatasParents()) == 0 {
return nil, "", fmt.Errorf("cherry-picking a commit without parents is not supported")
}
cherryRoot, err := cherryCommit.GetRootValue(ctx)
if err != nil {
return nil, "", err
}
parentCommit, err := doltDB.ResolveParent(ctx, cherryCommit, 0)
if err != nil {
return nil, "", err
}
parentRoot, err := parentCommit.GetRootValue(ctx)
if err != nil {
return nil, "", err
}
dbState, ok, err := dSess.LookupDbState(ctx, dbName)
if err != nil {
return nil, "", err
} else if !ok {
return nil, "", sql.ErrDatabaseNotFound.New(dbName)
}
// use parent of cherry-pick as ancestor root to merge
mo := merge.MergeOpts{IsCherryPick: true}
mergedRoot, mergeStats, err := merge.MergeRoots(ctx, roots.Working, cherryRoot, parentRoot, cherryCommit, parentCommit, dbState.EditOpts(), mo)
if err != nil {
return nil, "", err
}
var tablesWithConflict []string
for tbl, stats := range mergeStats {
if stats.Conflicts > 0 {
tablesWithConflict = append(tablesWithConflict, tbl)
}
}
if len(tablesWithConflict) > 0 {
tblNames := strings.Join(tablesWithConflict, "', '")
return nil, "", fmt.Errorf("conflicts in table {'%s'}", tblNames)
}
workingRootHash, err = mergedRoot.HashOf()
if err != nil {
return nil, "", err
}
if headRootHash.Equal(workingRootHash) {
return nil, "", fmt.Errorf("no changes were made, nothing to commit")
}
cherryCommitMeta, err := cherryCommit.GetCommitMeta(ctx)
if err != nil {
return nil, "", err
}
return mergedRoot, cherryCommitMeta.Description, nil
}

View File

@@ -25,7 +25,7 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
)
// doltClean is the stored procedure version of the function `dolt_clean`.
// doltClean is the stored procedure version for the CLI command `dolt clean`.
func doltClean(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltClean(ctx, args)
if err != nil {

View File

@@ -28,7 +28,7 @@ import (
"github.com/dolthub/dolt/go/libraries/utils/earl"
)
// doltClone is a stored procedure to clone a database from a remote
// doltClone is the stored procedure version for the CLI command `dolt clone`.
func doltClone(ctx *sql.Context, args ...string) (sql.RowIter, error) {
ap := cli.CreateCloneArgParser()
apr, err := ap.Parse(args)

View File

@@ -30,7 +30,7 @@ import (
var hashType = types.MustCreateString(query.Type_TEXT, 32, sql.Collation_ascii_bin)
// doltCommit is the stored procedure version for the CLI function `commit`.
// doltCommit is the stored procedure version for the CLI command `dolt commit`.
func doltCommit(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltCommit(ctx, args)
if err != nil {

View File

@@ -42,7 +42,7 @@ import (
var ErrConfSchIncompatible = errors.New("the conflict schema's columns are not equal to the current schema's columns, please resolve manually")
// doltConflictsResolve is the stored procedure version of the function `dolt conflict resolve`.
// doltConflictsResolve is the stored procedure version for the CLI command `dolt conflict resolve`.
func doltConflictsResolve(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := DoDoltConflictsResolve(ctx, args)
if err != nil {

View File

@@ -27,7 +27,7 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
)
// doltFetch is the stored procedure version of the function `dolt_fetch`.
// doltFetch is the stored procedure version for the CLI command `dolt fetch`.
func doltFetch(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltFetch(ctx, args)
if err != nil {

View File

@@ -46,7 +46,7 @@ const (
var ErrUncommittedChanges = goerrors.NewKind("cannot merge with uncommitted changes")
// doltMerge is the stored procedure version of the functions `merge` and `dolt_merge`.
// doltMerge is the stored procedure version for the CLI command `dolt merge`.
func doltMerge(ctx *sql.Context, args ...string) (sql.RowIter, error) {
hasConflicts, ff, err := doDoltMerge(ctx, args)
if err != nil {

View File

@@ -32,7 +32,7 @@ import (
"github.com/dolthub/dolt/go/store/datas/pull"
)
// doltPull is the stored procedure version of the function `dolt_pull`.
// doltPull is the stored procedure version for the CLI command `dolt pull`.
func doltPull(ctx *sql.Context, args ...string) (sql.RowIter, error) {
conflicts, ff, err := doDoltPull(ctx, args)
if err != nil {

View File

@@ -29,7 +29,7 @@ import (
"github.com/dolthub/dolt/go/store/datas"
)
// doltPush is the stored procedure version of the function `dolt_push`.
// doltPush is the stored procedure version for the CLI command `dolt push`.
func doltPush(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltPush(ctx, args)
if err != nil {

View File

@@ -31,7 +31,7 @@ import (
"github.com/dolthub/dolt/go/libraries/utils/config"
)
// doltRemote is the stored procedure version of the CLI `dolt remote` command
// doltRemote is the stored procedure version for the CLI command `dolt remote`.
func doltRemote(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltRemote(ctx, args)
if err != nil {

View File

@@ -26,7 +26,7 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
)
// doltReset is the stored procedure version of the function `dolt_reset`.
// doltReset is the stored procedure version for the CLI command `dolt reset`.
func doltReset(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltReset(ctx, args)
if err != nil {

View File

@@ -28,7 +28,7 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
)
// doltRevert is the stored procedure version of the function `revert` and `dolt_revert`.
// doltRevert is the stored procedure version for the CLI command `dolt revert`.
func doltRevert(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltRevert(ctx, args)
if err != nil {

View File

@@ -24,7 +24,7 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
)
// doltTag is the stored procedure version of the CLI `dolt tag` command
// doltTag is the stored procedure version for the CLI command `dolt tag`.
func doltTag(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltTag(ctx, args)
if err != nil {

View File

@@ -25,7 +25,7 @@ import (
"github.com/dolthub/dolt/go/libraries/utils/set"
)
// doltVerifyConstraints is the stored procedure version of the function `constraints_verify`.
// doltVerifyConstraints is the stored procedure version for the CLI command `dolt constraints verify`.
func doltVerifyConstraints(ctx *sql.Context, args ...string) (sql.RowIter, error) {
res, err := doDoltConstraintsVerify(ctx, args)
if err != nil {

View File

@@ -24,6 +24,7 @@ var DoltProcedures = []sql.ExternalStoredProcedureDetails{
{Name: "dolt_backup", Schema: int64Schema("success"), Function: doltBackup},
{Name: "dolt_branch", Schema: int64Schema("status"), Function: doltBranch},
{Name: "dolt_checkout", Schema: int64Schema("status"), Function: doltCheckout},
{Name: "dolt_cherry_pick", Schema: stringSchema("hash"), Function: doltCherryPick},
{Name: "dolt_clean", Schema: int64Schema("status"), Function: doltClean},
{Name: "dolt_clone", Schema: int64Schema("status"), Function: doltClone},
{Name: "dolt_commit", Schema: stringSchema("hash"), Function: doltCommit},
@@ -41,9 +42,11 @@ var DoltProcedures = []sql.ExternalStoredProcedureDetails{
{Name: "dolt_verify_constraints", Schema: int64Schema("violations"), Function: doltVerifyConstraints},
// Dolt stored procedure aliases
// TODO: Add new procedure aliases in doltProcedureAliasSet in go-mysql-server/sql/information_schema/routines.go file
{Name: "dadd", Schema: int64Schema("status"), Function: doltAdd},
{Name: "dbranch", Schema: int64Schema("status"), Function: doltBranch},
{Name: "dcheckout", Schema: int64Schema("status"), Function: doltCheckout},
{Name: "dcherry_pick", Schema: stringSchema("hash"), Function: doltCherryPick},
{Name: "dclean", Schema: int64Schema("status"), Function: doltClean},
{Name: "dclone", Schema: int64Schema("status"), Function: doltClone},
{Name: "dcommit", Schema: stringSchema("hash"), Function: doltCommit},

View File

@@ -0,0 +1,423 @@
#!/usr/bin/env bats
load $BATS_TEST_DIRNAME/helper/common.bash
setup() {
setup_common
dolt sql -q "CREATE TABLE test(pk BIGINT PRIMARY KEY, v varchar(10))"
dolt add .
dolt commit -am "Created table"
dolt checkout -b branch1
dolt sql -q "INSERT INTO test VALUES (1, 'a')"
dolt commit -am "Inserted 1"
dolt sql -q "INSERT INTO test VALUES (2, 'b')"
dolt commit -am "Inserted 2"
dolt sql -q "INSERT INTO test VALUES (3, 'c')"
dolt commit -am "Inserted 3"
run dolt sql -q "SELECT * FROM test" -r csv
[[ "$output" =~ "1,a" ]] || false
[[ "$output" =~ "2,b" ]] || false
[[ "$output" =~ "3,c" ]] || false
}
teardown() {
assert_feature_version
teardown_common
}
@test "sql-cherry-pick: simple cherry pick with the latest commit" {
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test" -r csv
[[ ! "$output" =~ "1,a" ]] || false
[[ ! "$output" =~ "2,b" ]] || false
[[ "$output" =~ "3,c" ]] || false
}
@test "sql-cherry-pick: multiple simple cherry-picks" {
dolt sql <<SQL
UPDATE test SET v = 'x' WHERE pk = 2;
INSERT INTO test VALUES (5, 'g'), (8, 'u');
CALL DOLT_COMMIT('-am','Updated 2b to 2x and inserted more rows');
CALL DOLT_CHECKOUT('main');
CALL DOLT_CHERRY_PICK('branch1~2');
SQL
# we are still on branch1
run dolt sql -q "SELECT * FROM test" -r csv
[[ "$output" =~ "1,a" ]] || false
[[ "$output" =~ "2,x" ]] || false
[[ "$output" =~ "3,c" ]] || false
[[ "$output" =~ "5,g" ]] || false
[[ "$output" =~ "8,u" ]] || false
dolt checkout main
run dolt sql -q "SELECT * FROM test" -r csv
[[ "$output" =~ "2,b" ]] || false
[[ ! "$output" =~ "1,a" ]] || false
[[ ! "$output" =~ "2,x" ]] || false
[[ ! "$output" =~ "3,c" ]] || false
run dolt sql -q "CALL DCHERRY_PICK('branch1')"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test" -r csv
[[ ! "$output" =~ "1,a" ]] || false
[[ "$output" =~ "2,x" ]] || false
[[ ! "$output" =~ "3,c" ]] || false
[[ "$output" =~ "5,g" ]] || false
[[ "$output" =~ "8,u" ]] || false
}
@test "sql-cherry-pick: too far back" {
run dolt sql<<SQL
CALL DCHECKOUT('main');
CALL DCHERRY_PICK('branch1~10');
SQL
[ "$status" -eq "1" ]
[[ "$output" =~ "ancestor" ]] || false
}
@test "sql-cherry-pick: no changes" {
run dolt sql<<SQL
CALL DOLT_COMMIT('--allow-empty', '-m', 'empty commit');
CALL DOLT_CHECKOUT('main');
CALL DOLT_CHERRY_PICK('branch1');
SQL
[ "$status" -eq "1" ]
[[ "$output" =~ "no changes were made, nothing to commit" ]] || false
}
@test "sql-cherry-pick: invalid hash" {
run dolt sql -q "CALL DOLT_CHERRY_PICK('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')"
[ "$status" -eq "1" ]
[[ "$output" =~ "target commit not found" ]] || false
}
@test "sql-cherry-pick: has changes in the working set" {
dolt checkout main
dolt sql -q "INSERT INTO test VALUES (4, 'f')"
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1~2')"
[ "$status" -eq "1" ]
[[ "$output" =~ "cannot cherry-pick with uncommitted changes" ]] || false
}
@test "sql-cherry-pick: staged changes" {
dolt checkout main
dolt sql -q "INSERT INTO test VALUES (4, 'f')"
dolt add -A
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1~2')"
[ "$status" -eq "1" ]
[[ "$output" =~ "cannot cherry-pick with uncommitted changes" ]] || false
}
@test "sql-cherry-pick: insert, update, delete rows and schema changes on non existent table in working set" {
dolt sql -q "CREATE TABLE branch1table (id int primary key, col1 int)"
dolt add .
dolt sql -q "INSERT INTO branch1table VALUES (9,8),(7,6),(5,4)"
dolt commit -am "create table with rows"
dolt sql -q "INSERT INTO branch1table VALUES (1,2)"
dolt commit -am "Insert a row"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "conflict: table with same name deleted and modified" ]] || false
run dolt sql -q "SHOW TABLES" -r csv
[[ ! "$output" =~ "branch1table" ]] || false
dolt checkout branch1
dolt sql -q "UPDATE branch1table SET col1 = 0 WHERE id > 6"
dolt commit -am "Update a rows"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "conflict: table with same name deleted and modified" ]] || false
run dolt sql -q "SHOW TABLES" -r csv
[[ ! "$output" =~ "branch1table" ]] || false
dolt checkout branch1
dolt sql -q "DELETE FROM branch1table WHERE id > 8"
dolt commit -am "Update and delete rows"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "conflict: table with same name deleted and modified" ]] || false
run dolt sql -q "SHOW TABLES" -r csv
[[ ! "$output" =~ "branch1table" ]] || false
dolt checkout branch1
dolt sql -q "ALTER TABLE branch1table ADD COLUMN col2 int"
dolt commit -am "Alter table add column"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "conflict: table with same name deleted and modified" ]] || false
run dolt sql -q "SHOW TABLES" -r csv
[[ ! "$output" =~ "branch1table" ]] || false
}
@test "sql-cherry-pick: row data conflict, leave working set clean" {
dolt sql -q "CREATE TABLE other (pk int primary key, v int)"
dolt add .
dolt sql -q "INSERT INTO other VALUES (1, 2)"
dolt sql -q "INSERT INTO test VALUES (4,'f')"
dolt commit -am "add other table"
dolt checkout main
dolt sql -q "CREATE TABLE other (pk int primary key, v int)"
dolt add .
dolt sql -q "INSERT INTO other VALUES (1, 3)"
dolt sql -q "INSERT INTO test VALUES (4,'k')"
dolt commit -am "add other table with conflict and test with conflict"
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "conflicts in table" ]] || false
run dolt status
[[ "$output" =~ "nothing to commit, working tree clean" ]] || false
}
@test "sql-cherry-pick: commit with CREATE TABLE" {
dolt sql -q "CREATE TABLE table_a (pk BIGINT PRIMARY KEY, v varchar(10))"
dolt add .
dolt sql -q "INSERT INTO table_a VALUES (11, 'aa'), (22, 'ab'), (33, 'ac')"
dolt sql -q "DELETE FROM test WHERE pk = 2"
dolt commit -am "Added table_a with rows and delete pk=2 from test"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "0" ]
run dolt sql -q "SHOW TABLES" -r csv
[[ "$output" =~ "table_a" ]] || false
run dolt sql -q "SELECT * FROM test" -r csv
[[ ! "$output" =~ "1,a" ]] || false
[[ ! "$output" =~ "2,b" ]] || false
[[ ! "$output" =~ "3,c" ]] || false
run dolt sql -q "SELECT * FROM table_a" -r csv
[[ "$output" =~ "11,aa" ]] || false
[[ "$output" =~ "22,ab" ]] || false
[[ "$output" =~ "33,ac" ]] || false
}
@test "sql-cherry-pick: commit with DROP TABLE" {
skip # drop or rename case
dolt sql -q "DROP TABLE test"
dolt commit -am "Drop table test"
run dolt sql -q "SHOW TABLES" -r csv
[[ ! "$output" =~ "test" ]] || false
dolt checkout main
run dolt sql -q "SHOW TABLES" -r csv
[[ "$output" =~ "test" ]] || false
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "table was renamed or dropped" ]] || false
run dolt sql -q "SHOW TABLES" -r csv
[[ "$output" =~ "test" ]] || false
}
@test "sql-cherry-pick: commit with ALTER TABLE rename table name" {
dolt sql -q "ALTER TABLE test RENAME TO new_name"
dolt add .
dolt commit -am "rename table name"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "table was renamed or dropped" ]] || false
}
@test "sql-cherry-pick: cherry-pick commit is a merge commit" {
dolt checkout -b branch2
dolt sql -q "INSERT INTO test VALUES (4, 'd'), (5, 'e')"
dolt commit -am "add more rows in branch2"
dolt checkout branch1
dolt sql -q "INSERT INTO test VALUES (6, 'f'), (7, 'g')"
dolt commit -am "add more rows in branch1"
dolt merge branch2 -m "merge branch2"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "cherry-picking a merge commit is not supported" ]] || false
}
@test "sql-cherry-pick: cherry-pick commit is a cherry-picked commit" {
dolt checkout -b branch2
dolt sql -q "INSERT INTO test VALUES (4, 'd'), (5, 'e')"
dolt commit -am "add more rows in branch2"
dolt checkout branch1
dolt sql -q "INSERT INTO test VALUES (6, 'f'), (7, 'g')"
dolt commit -am "add more rows in branch1"
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch2')"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test" -r csv
[[ "$output" =~ "4,d" ]] || false
[[ "$output" =~ "5,e" ]] || false
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test" -r csv
[[ "$output" =~ "4,d" ]] || false
[[ "$output" =~ "5,e" ]] || false
}
@test "sql-cherry-pick: add triggers" {
dolt sql -q "CREATE TRIGGER trigger1 BEFORE INSERT ON test FOR EACH ROW SET new.v = concat(new.v, ' inserted')"
dolt sql -q "INSERT INTO test VALUES (4,'z')"
run dolt sql -q "SELECT * FROM test"
[[ "$output" =~ "z inserted" ]] || false
dolt add .
dolt commit -am "add trigger"
dolt checkout main
run dolt sql -q "SHOW TRIGGERS"
[[ ! "$output" =~ "trigger1" ]] || false
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test"
[[ "$output" =~ "z inserted" ]] || false
run dolt sql -q "SHOW TRIGGERS"
[[ "$output" =~ "trigger1" ]] || false
dolt checkout branch1
dolt sql -q "DROP TRIGGER trigger1"
dolt commit -am "drop trigger"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "0" ]
run dolt sql -q "SHOW TRIGGERS"
[[ ! "$output" =~ "trigger1" ]] || false
}
@test "sql-cherry-pick: add procedures" {
dolt sql -q "CREATE PROCEDURE proc1 (in x int) select x from dual"
run dolt sql -q "CALL proc1(434)"
[[ "$output" =~ "434" ]] || false
dolt add .
dolt commit -am "add procedure"
dolt checkout main
run dolt sql -q "SHOW PROCEDURE STATUS"
[[ ! "$output" =~ "proc1" ]] || false
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "0" ]
run dolt sql -q "SHOW PROCEDURE STATUS"
[[ "$output" =~ "proc1" ]] || false
run dolt sql -q "CALL proc1(434)"
[[ "$output" =~ "434" ]] || false
}
@test "sql-cherry-pick: keyless table" {
dolt checkout main
dolt sql -q "CREATE TABLE keyless (id int, name varchar(10))"
dolt add .
dolt commit -am "add keyless table"
dolt checkout -b branch2
dolt sql -q "INSERT INTO keyless VALUES (1,'1'), (2,'3')"
dolt commit -am "insert into keyless table"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "0" ]
dolt sql -q "SELECT * FROM keyless" -r csv
[[ ! "$output" =~ "1,1" ]] || false
[[ ! "$output" =~ "2,3" ]] || false
}
@test "sql-cherry-pick: commit with ALTER TABLE add column" {
dolt sql -q "ALTER TABLE test ADD COLUMN c int"
dolt commit -am "alter table test add column c"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "table schema does not match in current HEAD and cherry-pick commit" ]] || false
}
@test "sql-cherry-pick: commit with ALTER TABLE change column" {
dolt sql -q "ALTER TABLE test CHANGE COLUMN v c varchar(100)"
dolt commit -am "alter table test change column v"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "table schema does not match in current HEAD and cherry-pick commit" ]] || false
}
@test "sql-cherry-pick: commit with ALTER TABLE modify column" {
dolt sql -q "UPDATE test SET v = '1' WHERE pk < 4"
dolt sql -q "ALTER TABLE test MODIFY COLUMN v int"
dolt commit -am "alter table test modify column v"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "table schema does not match in current HEAD and cherry-pick commit" ]] || false
}
@test "sql-cherry-pick: commit with ALTER TABLE drop column" {
dolt sql -q "ALTER TABLE test DROP COLUMN v"
dolt commit -am "alter table test drop column v"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "table schema does not match in current HEAD and cherry-pick commit" ]] || false
}
@test "sql-cherry-pick: commit with ALTER TABLE rename column" {
dolt sql -q "ALTER TABLE test RENAME COLUMN v TO c"
dolt commit -am "alter table test rename column v"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "table schema does not match in current HEAD and cherry-pick commit" ]] || false
}
@test "sql-cherry-pick: commit with ALTER TABLE drop and add primary key" {
dolt sql -q "ALTER TABLE test DROP PRIMARY KEY, ADD PRIMARY KEY (pk, v)"
dolt commit -am "alter table test drop and add primary key"
dolt checkout main
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
[ "$status" -eq "1" ]
[[ "$output" =~ "table schema does not match in current HEAD and cherry-pick commit" ]] || false
}