Files
2026-07-13 12:32:25 +08:00

3363 lines
142 KiB
Go
Executable File

// 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 _go
import (
"testing"
"github.com/dolthub/go-mysql-server/sql"
)
// TestDoltAdd includes a multitude of items to ensure that adding them all does not cause any errors.
func TestDoltAdd(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Add all using dot",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 'f';",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT DOLT_ADD('.');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 't';",
Expected: []sql.Row{{16}},
},
},
},
{
Name: "Add all using -A",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 'f';",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT DOLT_ADD('-A');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 't';",
Expected: []sql.Row{{16}},
},
},
},
{
Name: "Add all individually",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 'f';",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT DOLT_ADD('t_simple','t_composite','t_array','t_serial','t_default_simple'," +
"'t_checked','t_fk_parent','t_fk_child','t_unique','t_generated','t_trigger','t_default_func');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 't';",
Expected: []sql.Row{{12}},
},
{
Query: "SELECT DOLT_ADD('f_trigger()','f_default()');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 't';",
Expected: []sql.Row{{14}},
},
{
Query: "SELECT DOLT_ADD('t_serial_pk_seq','t_trigger.trig_trigger');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 't';",
Expected: []sql.Row{{16}},
},
},
},
})
}
// TestDoltBranch includes a multitude of items to ensure that creating branches with them does not cause any errors.
func TestDoltBranch(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "All branch options",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT DOLT_ADD('-A');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT length(DOLT_COMMIT('-m', 'initial')::text) = 34;",
Expected: []sql.Row{{"t"}},
},
{
Query: "SELECT DOLT_BRANCH('original');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "INSERT INTO t_simple VALUES (4);",
Expected: []sql.Row{},
},
{
Query: "SELECT DOLT_ADD('-A');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT length(DOLT_COMMIT('-m', 'initial')::text) = 34;",
Expected: []sql.Row{{"t"}},
},
{
Query: "SELECT DOLT_BRANCH('-c', 'main', 'copy');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT DOLT_BRANCH('-c', '-f', 'original', 'forcecopy');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}, {4}},
},
{
Query: `SELECT DOLT_CHECKOUT('main')`,
Expected: []sql.Row{{`{0,"Already on branch 'main'"}`}},
},
{
Query: `SELECT DOLT_CHECKOUT('original')`,
Expected: []sql.Row{{`{0,"Switched to branch 'original'"}`}},
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}},
},
{
Query: `SELECT DOLT_CHECKOUT('copy')`,
Expected: []sql.Row{{`{0,"Switched to branch 'copy'"}`}},
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}, {4}},
},
{
Query: `SELECT DOLT_CHECKOUT('forcecopy')`,
Expected: []sql.Row{{`{0,"Switched to branch 'forcecopy'"}`}},
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}},
},
{
Query: `SELECT DOLT_BRANCH('-d', 'forcecopy')`,
ExpectedErr: `Cannot delete checked out branch 'forcecopy'`,
},
{
Query: `SELECT DOLT_BRANCH('-d', 'original')`,
Expected: []sql.Row{{`{0}`}},
},
{
Query: `SELECT DOLT_BRANCH('-m','copy','renamedcopy')`,
Expected: []sql.Row{{`{0}`}},
},
{
Query: `SELECT DOLT_CHECKOUT('original')`,
ExpectedErr: `'original' did not match any table`,
},
{
Query: `SELECT DOLT_CHECKOUT('copy')`,
ExpectedErr: `'copy' did not match any table`,
},
{
Query: `SELECT DOLT_CHECKOUT('renamedcopy')`,
Expected: []sql.Row{{`{0,"Switched to branch 'renamedcopy'"}`}},
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}, {4}},
},
},
},
})
}
func TestDoltBranchStatus(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Smoke test",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"SELECT DOLT_ADD('-A');",
"SELECT length(DOLT_COMMIT('-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('original');",
"INSERT INTO t_simple VALUES (4);",
"SELECT DOLT_ADD('-A');",
"SELECT length(DOLT_COMMIT('-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM DOLT_BRANCH_STATUS('main', 'original');",
Expected: []sql.Row{{"original", Numeric("0"), Numeric("1")}},
},
{
Query: "SELECT * FROM DOLT_BRANCH_STATUS('original', 'main');",
Expected: []sql.Row{{"main", Numeric("1"), Numeric("0")}},
},
},
},
})
}
// TestDoltCheckout includes a multitude of items to ensure that switching branches with them does not cause any errors.
func TestDoltCheckout(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "All checkout options",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT DOLT_ADD('-A');",
"SELECT length(DOLT_COMMIT('-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('original');",
"INSERT INTO t_simple VALUES (4);",
"INSERT INTO t_composite VALUES (3, 100);",
"INSERT INTO t_array VALUES (ARRAY['stu']);",
"INSERT INTO t_serial VALUES (DEFAULT);",
"INSERT INTO t_default_simple VALUES (98, 8);",
"INSERT INTO t_checked VALUES (99);",
"INSERT INTO t_fk_parent VALUES (40);",
"INSERT INTO t_fk_child VALUES (30);",
"INSERT INTO t_unique VALUES (10);",
"INSERT INTO t_generated (v1) VALUES (11);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger (v1) VALUES (2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (v2) VALUES (3);",
"SELECT DOLT_ADD('-A');",
"SELECT length(DOLT_COMMIT('-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT DOLT_CHECKOUT('-b', 'checkoutbranch');",
Expected: []sql.Row{{`{0,"Switched to branch 'checkoutbranch'"}`}},
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}, {4}},
},
{
Query: "SELECT DOLT_CHECKOUT('checkoutbranch');",
Expected: []sql.Row{{`{0,"Already on branch 'checkoutbranch'"}`}},
},
{
Query: `SELECT DOLT_CHECKOUT('main')`,
Expected: []sql.Row{{`{0,"Switched to branch 'main'"}`}},
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}, {4}},
},
{
Query: `SELECT DOLT_CHECKOUT('original')`,
Expected: []sql.Row{{`{0,"Switched to branch 'original'"}`}},
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}},
},
},
},
})
}
// TestDoltCherryPick includes a multitude of items to ensure that cherry picking them does not cause any errors.
func TestDoltCherryPick(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Smoke test",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT DOLT_ADD('-A');",
"SELECT length(DOLT_COMMIT('-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('original');",
"INSERT INTO t_simple VALUES (4);",
"INSERT INTO t_composite VALUES (3, 100);",
"INSERT INTO t_array VALUES (ARRAY['stu']);",
"INSERT INTO t_serial VALUES (DEFAULT);",
"INSERT INTO t_default_simple VALUES (98, 8);",
"INSERT INTO t_checked VALUES (99);",
"INSERT INTO t_fk_parent VALUES (40);",
"INSERT INTO t_fk_child VALUES (30);",
"INSERT INTO t_unique VALUES (10);",
"INSERT INTO t_generated (v1) VALUES (11);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger (v1) VALUES (2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (v2) VALUES (3);",
"SELECT DOLT_ADD('-A');",
"SELECT length(DOLT_COMMIT('-m', 'initial')::text) = 34;",
`SELECT DOLT_CHECKOUT('original')`,
},
Assertions: []ScriptTestAssertion{
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}},
},
{ // This returns a hash, so we need to take the consistent substring portion for testing
Query: `SELECT substring(DOLT_CHERRY_PICK('main')::text, 34);`,
Expected: []sql.Row{{",0,0,0}"}},
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}, {4}},
},
},
},
})
}
// TestDoltClean includes a multitude of items to ensure that they're all properly cleaned up.
func TestDoltClean(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Clean all",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT DOLT_CLEAN();",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{0}},
},
},
},
{
Name: "Clean all except one",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT DOLT_ADD('t_simple');",
"SELECT length(DOLT_COMMIT('-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{15}},
},
{
Query: "SELECT DOLT_CLEAN();",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{0}},
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}},
},
},
},
{
Name: "Clean all by name",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT DOLT_CLEAN('t_simple','t_composite','t_array','t_serial','t_default_simple'," +
"'t_checked','t_fk_parent','t_fk_child','t_unique','t_generated','t_trigger','t_default_func'," +
"'f_trigger()','f_default()');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{0}},
},
},
},
{
Name: "Dry run",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT DOLT_CLEAN('--dry-run');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{16}},
},
},
},
})
}
// TestDoltCommit includes a multitude of items to ensure that committing with them does not cause any errors.
func TestDoltCommit(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Stage all then commit",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT DOLT_ADD('-A');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT length(DOLT_COMMIT('-m', 'initial')::text) = 34;",
Expected: []sql.Row{{"t"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{0}},
},
},
},
{
Name: "Commit with staging all",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
Expected: []sql.Row{{"t"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{0}},
},
},
},
{
Name: "Commit with staging modifications",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT DOLT_ADD('t_simple','t_composite','t_array');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT length(DOLT_COMMIT('-m', 'initial')::text) = 34;",
Expected: []sql.Row{{"t"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{13}},
},
{
Query: "INSERT INTO t_simple VALUES (4);",
Expected: []sql.Row{},
},
{
Query: "INSERT INTO t_composite VALUES (3, 100);",
Expected: []sql.Row{},
},
{
Query: "INSERT INTO t_array VALUES (ARRAY['stu']);",
Expected: []sql.Row{},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT length(DOLT_COMMIT('-a', '-m', 'initial')::text) = 34;",
Expected: []sql.Row{{"t"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{13}},
},
},
},
{
Name: "Allow and skip empty",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
Expected: []sql.Row{{"t"}},
},
{
Query: "SELECT DOLT_COMMIT('-m', 'should_error');",
ExpectedErr: "nothing to commit",
},
{
Query: "SELECT DOLT_COMMIT('--skip-empty', '-m', 'should_error');",
Expected: []sql.Row{{nil}},
},
{
Query: "SELECT length(DOLT_COMMIT('--allow-empty', '-m', 'initial')::text) = 34;",
Expected: []sql.Row{{"t"}},
},
},
},
})
}
var simpleConflictResolveSetupScript = []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY, v1 INT4);",
"INSERT INTO t_simple VALUES (1, 1);",
"SELECT DOLT_COMMIT('-Am', 'initial')",
"SELECT DOLT_BRANCH('other');",
"INSERT INTO t_simple VALUES (2, 2);",
"SELECT DOLT_COMMIT('-Am', 'second row on main')",
"SELECT DOLT_CHECKOUT('other');",
"INSERT INTO t_simple VALUES (2, 3);",
"SELECT DOLT_COMMIT('-Am', 'conflicted row on other')",
"SELECT DOLT_CHECKOUT('main');",
}
// TestDoltConflictsResolve includes a multitude of items to ensure that we properly handle conflict resolution for all
// of them.
func TestDoltConflictsResolve(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Simple conflicts resolve all using --ours",
SetUpScript: simpleConflictResolveSetupScript,
Assertions: []ScriptTestAssertion{
{
Query: "BEGIN;",
Expected: []sql.Row{},
},
{
Query: "SELECT DOLT_MERGE('other', '--no-ff');",
Expected: []sql.Row{{`{"",0,1,"conflicts found"}`}},
},
{
Query: "SELECT * FROM dolt_conflicts;",
Expected: []sql.Row{{"t_simple", Numeric("1")}},
},
{
Query: "SELECT DOLT_CONFLICTS_RESOLVE('--ours', '.');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT DOLT_COMMIT('-Am', 'commit merge');",
SkipResultsCheck: true,
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1, 1}, {2, 2}},
},
},
},
{
Name: "Simple conflicts resolve all using --theirs",
SetUpScript: simpleConflictResolveSetupScript,
Assertions: []ScriptTestAssertion{
{
Query: "BEGIN;",
Expected: []sql.Row{},
},
{
Query: "SELECT DOLT_MERGE('other', '--no-ff');",
Expected: []sql.Row{{`{"",0,1,"conflicts found"}`}},
},
{
Query: "SELECT * FROM dolt_conflicts;",
Expected: []sql.Row{{"t_simple", Numeric("1")}},
},
{
Query: "SELECT DOLT_CONFLICTS_RESOLVE('--theirs', '.');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT DOLT_COMMIT('-Am', 'commit merge');",
SkipResultsCheck: true,
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1, 1}, {2, 3}},
},
},
},
{
Name: "Simple conflicts resolve table using --ours",
SetUpScript: simpleConflictResolveSetupScript,
Assertions: []ScriptTestAssertion{
{
Query: "BEGIN;",
Expected: []sql.Row{},
},
{
Query: "SELECT DOLT_MERGE('other', '--no-ff');",
Expected: []sql.Row{{`{"",0,1,"conflicts found"}`}},
},
{
Query: "SELECT * FROM dolt_conflicts;",
Expected: []sql.Row{{"t_simple", Numeric("1")}},
},
{
Query: "SELECT DOLT_CONFLICTS_RESOLVE('--ours', 't_simple');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT DOLT_COMMIT('-Am', 'commit merge');",
SkipResultsCheck: true,
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1, 1}, {2, 2}},
},
},
},
{
Name: "Simple conflicts resolve table using --theirs",
Skip: true,
SetUpScript: simpleConflictResolveSetupScript,
Assertions: []ScriptTestAssertion{
{
Query: "BEGIN;",
Expected: []sql.Row{},
},
{
Query: "SELECT DOLT_MERGE('other', '--no-ff');",
Expected: []sql.Row{{`{"",0,1,"conflicts found"}`}},
},
{
Query: "SELECT * FROM dolt_conflicts;",
Expected: []sql.Row{{"t_simple", Numeric("1")}},
},
{
Query: "SELECT DOLT_CONFLICTS_RESOLVE('--theirs', 't_simple');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT DOLT_COMMIT('-Am', 'commit merge');",
SkipResultsCheck: true,
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1, 1}, {2, 3}},
},
},
},
{
Name: "Resolve all using --ours",
Skip: true, // TODO: attempting a merge with generated columns causes a panic
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, v1 INT4, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_generated (pk INT8 PRIMARY KEY, v1 INT4, v2 INT8 GENERATED ALWAYS AS (pk * 1000) STORED);",
"CREATE TABLE t_trigger (pk INT4 PRIMARY KEY, v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (pk INT4 PRIMARY KEY, v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1, 1);",
"INSERT INTO t_composite VALUES (1, 1, 1);",
"INSERT INTO t_array VALUES (ARRAY['abc'], 1);",
"INSERT INTO t_serial VALUES (DEFAULT, 1);",
"INSERT INTO t_generated (pk, v1) VALUES (1, 1);",
"INSERT INTO t_trigger VALUES (1, 1);",
"INSERT INTO t_default_func (pk, v2) VALUES (1, 1);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('other');",
"INSERT INTO t_simple VALUES (2, 2);",
"INSERT INTO t_composite VALUES (2, 2, 2);",
"INSERT INTO t_array VALUES (ARRAY['def'], 2);",
"INSERT INTO t_serial VALUES (DEFAULT, 2);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_CHECKOUT('other');",
"INSERT INTO t_simple VALUES (2, 3);",
"INSERT INTO t_composite VALUES (2, 2, 3);",
"INSERT INTO t_array VALUES (ARRAY['def'], 3);",
"INSERT INTO t_serial VALUES (DEFAULT, 3);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 3);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 34; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 3);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 35; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT DOLT_MERGE('main');",
Expected: []sql.Row{{}},
},
// TODO: finish adding these
},
},
{
Name: "Resolve all using --theirs",
Skip: true, // TODO: attempting a merge with generated columns causes a panic
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, v1 INT4, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_generated (pk INT8 PRIMARY KEY, v1 INT4, v2 INT8 GENERATED ALWAYS AS (pk * 1000) STORED);",
"CREATE TABLE t_trigger (pk INT4 PRIMARY KEY, v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (pk INT4 PRIMARY KEY, v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1, 1);",
"INSERT INTO t_composite VALUES (1, 1, 1);",
"INSERT INTO t_array VALUES (ARRAY['abc'], 1);",
"INSERT INTO t_serial VALUES (DEFAULT, 1);",
"INSERT INTO t_generated (pk, v1) VALUES (1, 1);",
"INSERT INTO t_trigger VALUES (1, 1);",
"INSERT INTO t_default_func (pk, v2) VALUES (1, 1);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('other');",
"INSERT INTO t_simple VALUES (2, 2);",
"INSERT INTO t_composite VALUES (2, 2, 2);",
"INSERT INTO t_array VALUES (ARRAY['def'], 2);",
"INSERT INTO t_serial VALUES (DEFAULT, 2);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_CHECKOUT('other');",
"INSERT INTO t_simple VALUES (2, 3);",
"INSERT INTO t_composite VALUES (2, 2, 3);",
"INSERT INTO t_array VALUES (ARRAY['def'], 3);",
"INSERT INTO t_serial VALUES (DEFAULT, 3);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 3);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 34; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 3);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 35; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT DOLT_MERGE('main');",
Expected: []sql.Row{{}},
},
// TODO: finish adding these
},
},
{
Name: "Resolve individual items",
Skip: true, // TODO: attempting a merge with generated columns causes a panic
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, v1 INT4, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_generated (pk INT8 PRIMARY KEY, v1 INT4, v2 INT8 GENERATED ALWAYS AS (pk * 1000) STORED);",
"CREATE TABLE t_trigger (pk INT4 PRIMARY KEY, v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (pk INT4 PRIMARY KEY, v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1, 1);",
"INSERT INTO t_composite VALUES (1, 1, 1);",
"INSERT INTO t_array VALUES (ARRAY['abc'], 1);",
"INSERT INTO t_serial VALUES (DEFAULT, 1);",
"INSERT INTO t_generated (pk, v1) VALUES (1, 1);",
"INSERT INTO t_trigger VALUES (1, 1);",
"INSERT INTO t_default_func (pk, v2) VALUES (1, 1);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('other');",
"INSERT INTO t_simple VALUES (2, 2);",
"INSERT INTO t_composite VALUES (2, 2, 2);",
"INSERT INTO t_array VALUES (ARRAY['def'], 2);",
"INSERT INTO t_serial VALUES (DEFAULT, 2);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_CHECKOUT('other');",
"INSERT INTO t_simple VALUES (2, 3);",
"INSERT INTO t_composite VALUES (2, 2, 3);",
"INSERT INTO t_array VALUES (ARRAY['def'], 3);",
"INSERT INTO t_serial VALUES (DEFAULT, 3);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 3);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 34; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 3);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 35; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT DOLT_MERGE('main');",
Expected: []sql.Row{{16}},
},
// TODO: finish adding these
},
},
})
}
// TestDoltDiff includes a multitude of items to ensure that they all produce diffs without error.
func TestDoltDiff(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Single commit",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('original');",
"INSERT INTO t_simple VALUES (4);",
"INSERT INTO t_composite VALUES (3, 100);",
"INSERT INTO t_array VALUES (ARRAY['stu']);",
"INSERT INTO t_serial VALUES (DEFAULT);",
"INSERT INTO t_default_simple VALUES (98, 8);",
"INSERT INTO t_checked VALUES (99);",
"INSERT INTO t_fk_parent VALUES (40);",
"INSERT INTO t_fk_child VALUES (30);",
"INSERT INTO t_unique VALUES (10);",
"INSERT INTO t_generated (v1) VALUES (11);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger (v1) VALUES (2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (v2) VALUES (3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT from_pk FROM DOLT_DIFF('main', 'original', 't_simple');",
Expected: []sql.Row{{4}},
},
{
Query: "SELECT from_pk1, from_pk2 FROM DOLT_DIFF('main', 'original', 't_composite');",
Expected: []sql.Row{{3, 100}},
},
{
Query: "SELECT from_pk FROM DOLT_DIFF('main', 'original', 't_array');",
Expected: []sql.Row{{`{stu}`}},
},
{
Query: "SELECT from_pk FROM DOLT_DIFF('main', 'original', 't_serial');",
Expected: []sql.Row{{4}},
},
{
Query: "SELECT from_v1, from_v2 FROM DOLT_DIFF('main', 'original', 't_default_simple');",
Expected: []sql.Row{{98, 8}},
},
{
Query: "SELECT from_v1 FROM DOLT_DIFF('main', 'original', 't_checked');",
Expected: []sql.Row{{Numeric("99")}},
},
{
Query: "SELECT from_pk FROM DOLT_DIFF('main', 'original', 't_fk_parent');",
Expected: []sql.Row{{40}},
},
{
Query: "SELECT from_pk FROM DOLT_DIFF('main', 'original', 't_fk_child');",
Expected: []sql.Row{{30}},
},
{
Query: "SELECT from_v1 FROM DOLT_DIFF('main', 'original', 't_unique');",
Expected: []sql.Row{{10}},
},
{
Query: "SELECT from_v1, from_v2 FROM DOLT_DIFF('main', 'original', 't_generated');",
Expected: []sql.Row{{11, 11000}},
},
{
Query: "SELECT from_v1 FROM DOLT_DIFF('main', 'original', 't_trigger');",
Expected: []sql.Row{{66}},
},
{
Query: "SELECT from_v1, from_v2 FROM DOLT_DIFF('main', 'original', 't_default_func');",
Expected: []sql.Row{{34, 3}},
},
{
Query: "SELECT * FROM DOLT_DIFF('main', 'original', 'f_trigger()');",
Skip: true, // TODO: need to implement for functions
Expected: []sql.Row{{}},
},
{
Query: "SELECT * FROM DOLT_DIFF('main', 'original', 'f_default()');",
Skip: true, // TODO: need to implement for functions
Expected: []sql.Row{{}},
},
{
Query: "SELECT * FROM DOLT_DIFF('main', 'original', 't_trigger.trig_trigger');",
Skip: true, // TODO: need to implement for triggers
Expected: []sql.Row{{}},
},
{
Query: "SELECT * FROM DOLT_DIFF('main', 'original', 't_serial_pk_seq');",
Skip: true, // TODO: need to implement for sequences
Expected: []sql.Row{{}},
},
},
},
})
}
// TestDoltDiffStat includes a multitude of items to ensure that they all produce diff stats without error.
func TestDoltDiffStat(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Single commit",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('original');",
"INSERT INTO t_simple VALUES (4);",
"INSERT INTO t_composite VALUES (3, 100);",
"INSERT INTO t_array VALUES (ARRAY['stu']);",
"INSERT INTO t_serial VALUES (DEFAULT);",
"INSERT INTO t_default_simple VALUES (98, 8);",
"INSERT INTO t_checked VALUES (99);",
"INSERT INTO t_fk_parent VALUES (40);",
"INSERT INTO t_fk_child VALUES (30);",
"INSERT INTO t_unique VALUES (10);",
"INSERT INTO t_generated (v1) VALUES (11);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger (v1) VALUES (2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (v2) VALUES (3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM DOLT_DIFF_STAT('main', 'original');",
Expected: []sql.Row{{15}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_simple');",
Expected: []sql.Row{{"public.t_simple"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_composite');",
Expected: []sql.Row{{"public.t_composite"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_array');",
Expected: []sql.Row{{"public.t_array"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_serial');",
Expected: []sql.Row{{"public.t_serial"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_default_simple');",
Expected: []sql.Row{{"public.t_default_simple"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_checked');",
Expected: []sql.Row{{"public.t_checked"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_fk_parent');",
Expected: []sql.Row{{"public.t_fk_parent"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_fk_child');",
Expected: []sql.Row{{"public.t_fk_child"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_unique');",
Expected: []sql.Row{{"public.t_unique"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_generated');",
Expected: []sql.Row{{"public.t_generated"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_trigger');",
Expected: []sql.Row{{"public.t_trigger"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_default_func');",
Expected: []sql.Row{{"public.t_default_func"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 'f_trigger()');",
Expected: []sql.Row{{"public.f_trigger()"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 'f_default()');",
Expected: []sql.Row{{"public.f_default()"}},
},
{
Query: "SELECT table_name FROM DOLT_DIFF_STAT('main', 'original', 't_serial_pk_seq');",
Expected: []sql.Row{{"public.t_serial_pk_seq"}},
},
},
},
})
}
// TestDoltDiffSummary includes a multitude of items to ensure that they all produce diff summaries without error.
func TestDoltDiffSummary(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Single commit",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('original');",
"INSERT INTO t_simple VALUES (4);",
"INSERT INTO t_composite VALUES (3, 100);",
"INSERT INTO t_array VALUES (ARRAY['stu']);",
"INSERT INTO t_serial VALUES (DEFAULT);",
"INSERT INTO t_default_simple VALUES (98, 8);",
"INSERT INTO t_checked VALUES (99);",
"INSERT INTO t_fk_parent VALUES (40);",
"INSERT INTO t_fk_child VALUES (30);",
"INSERT INTO t_unique VALUES (10);",
"INSERT INTO t_generated (v1) VALUES (11);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger (v1) VALUES (2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (v2) VALUES (3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM DOLT_DIFF_SUMMARY('main', 'original');",
Expected: []sql.Row{{15}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_simple');",
Expected: []sql.Row{{"public.t_simple"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_composite');",
Expected: []sql.Row{{"public.t_composite"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_array');",
Expected: []sql.Row{{"public.t_array"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_serial');",
Expected: []sql.Row{{"public.t_serial"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_default_simple');",
Expected: []sql.Row{{"public.t_default_simple"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_checked');",
Expected: []sql.Row{{"public.t_checked"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_fk_parent');",
Expected: []sql.Row{{"public.t_fk_parent"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_fk_child');",
Expected: []sql.Row{{"public.t_fk_child"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_unique');",
Expected: []sql.Row{{"public.t_unique"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_generated');",
Expected: []sql.Row{{"public.t_generated"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_trigger');",
Expected: []sql.Row{{"public.t_trigger"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_default_func');",
Expected: []sql.Row{{"public.t_default_func"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 'f_trigger()');",
Expected: []sql.Row{{"public.f_trigger()"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 'f_default()');",
Expected: []sql.Row{{"public.f_default()"}},
},
{
Query: "SELECT from_table_name FROM DOLT_DIFF_SUMMARY('main', 'original', 't_serial_pk_seq');",
Expected: []sql.Row{{"public.t_serial_pk_seq"}},
},
},
},
})
}
// TestDoltGC includes a multitude of items to ensure that GC does not cause any errors when they're in the repository.
func TestDoltGC(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Full",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('original');",
"INSERT INTO t_simple VALUES (4);",
"INSERT INTO t_composite VALUES (3, 100);",
"INSERT INTO t_array VALUES (ARRAY['stu']);",
"INSERT INTO t_serial VALUES (DEFAULT);",
"INSERT INTO t_default_simple VALUES (98, 8);",
"INSERT INTO t_checked VALUES (99);",
"INSERT INTO t_fk_parent VALUES (40);",
"INSERT INTO t_fk_child VALUES (30);",
"INSERT INTO t_unique VALUES (10);",
"INSERT INTO t_generated (v1) VALUES (11);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger (v1) VALUES (2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (v2) VALUES (3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT DOLT_GC();",
Expected: []sql.Row{{"{0}"}},
},
},
},
{
Name: "Shallow",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('original');",
"INSERT INTO t_simple VALUES (4);",
"INSERT INTO t_composite VALUES (3, 100);",
"INSERT INTO t_array VALUES (ARRAY['stu']);",
"INSERT INTO t_serial VALUES (DEFAULT);",
"INSERT INTO t_default_simple VALUES (98, 8);",
"INSERT INTO t_checked VALUES (99);",
"INSERT INTO t_fk_parent VALUES (40);",
"INSERT INTO t_fk_child VALUES (30);",
"INSERT INTO t_unique VALUES (10);",
"INSERT INTO t_generated (v1) VALUES (11);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger (v1) VALUES (2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (v2) VALUES (3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT DOLT_GC('--shallow');",
Expected: []sql.Row{{"{0}"}},
},
},
},
})
}
func TestDoltLog(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Smoke test",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('original');",
"INSERT INTO t_simple VALUES (4);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM DOLT_LOG('main');",
Expected: []sql.Row{{4}},
},
{
Query: "SELECT COUNT(*) FROM DOLT_LOG('original');",
Expected: []sql.Row{{3}},
},
},
},
})
}
// TestDoltMerge includes a multitude of items to ensure that they're all able to merge without errors.
func TestDoltMerge(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Merge without conflicts",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, v1 INT4, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_generated (pk INT8 PRIMARY KEY, v1 INT4, v2 INT8 GENERATED ALWAYS AS (pk * 1000) STORED);",
"CREATE TABLE t_trigger (pk INT4 PRIMARY KEY, v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (pk INT4 PRIMARY KEY, v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1, 1);",
"INSERT INTO t_composite VALUES (1, 1, 1);",
"INSERT INTO t_array VALUES (ARRAY['abc'], 1);",
"INSERT INTO t_serial VALUES (DEFAULT, 1);",
"INSERT INTO t_generated (pk, v1) VALUES (1, 1);",
"INSERT INTO t_trigger VALUES (1, 1);",
"INSERT INTO t_default_func (pk, v2) VALUES (1, 1);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('other');",
"INSERT INTO t_simple VALUES (2, 2);",
"INSERT INTO t_composite VALUES (2, 2, 2);",
"INSERT INTO t_array VALUES (ARRAY['def'], 2);",
"INSERT INTO t_serial VALUES (DEFAULT, 2);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_CHECKOUT('other');",
"INSERT INTO t_simple VALUES (3, 3);",
"INSERT INTO t_composite VALUES (3, 2, 3);",
"INSERT INTO t_array VALUES (ARRAY['dfe'], 3);",
"INSERT INTO t_serial VALUES (4, 3);",
"INSERT INTO t_generated (pk, v1) VALUES (3, 3);",
"INSERT INTO t_trigger VALUES (3, 3);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT4 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (3, 3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT strpos(DOLT_MERGE('main')::text, '0,0,\"merge successful\"') > 1;",
Expected: []sql.Row{{"t"}},
},
},
},
{
Name: "Merge with conflicts",
Skip: true, // TODO: attempting a merge with generated columns causes a panic
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, v1 INT4, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_generated (pk INT8 PRIMARY KEY, v1 INT4, v2 INT8 GENERATED ALWAYS AS (pk * 1000) STORED);",
"CREATE TABLE t_trigger (pk INT4 PRIMARY KEY, v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (pk INT4 PRIMARY KEY, v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1, 1);",
"INSERT INTO t_composite VALUES (1, 1, 1);",
"INSERT INTO t_array VALUES (ARRAY['abc'], 1);",
"INSERT INTO t_serial VALUES (DEFAULT, 1);",
"INSERT INTO t_generated (pk, v1) VALUES (1, 1);",
"INSERT INTO t_trigger VALUES (1, 1);",
"INSERT INTO t_default_func (pk, v2) VALUES (1, 1);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('other');",
"INSERT INTO t_simple VALUES (2, 2);",
"INSERT INTO t_composite VALUES (2, 2, 2);",
"INSERT INTO t_array VALUES (ARRAY['def'], 2);",
"INSERT INTO t_serial VALUES (DEFAULT, 2);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_CHECKOUT('other');",
"INSERT INTO t_simple VALUES (2, 3);",
"INSERT INTO t_composite VALUES (2, 2, 3);",
"INSERT INTO t_array VALUES (ARRAY['def'], 3);",
"INSERT INTO t_serial VALUES (DEFAULT, 3);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 3);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 34; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 3);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 35; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT DOLT_MERGE('main');",
Expected: []sql.Row{{}},
},
},
},
{
Name: "Fast forward",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('original');",
"INSERT INTO t_simple VALUES (4);",
"INSERT INTO t_composite VALUES (3, 100);",
"INSERT INTO t_array VALUES (ARRAY['stu']);",
"INSERT INTO t_serial VALUES (DEFAULT);",
"INSERT INTO t_default_simple VALUES (98, 8);",
"INSERT INTO t_checked VALUES (99);",
"INSERT INTO t_fk_parent VALUES (40);",
"INSERT INTO t_fk_child VALUES (30);",
"INSERT INTO t_unique VALUES (10);",
"INSERT INTO t_generated (v1) VALUES (11);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger (v1) VALUES (2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (v2) VALUES (3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_CHECKOUT('original');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT strpos(DOLT_MERGE('main')::text, '1,0,\"merge successful\"') > 1;",
Expected: []sql.Row{{"t"}},
},
},
},
{
Name: "--no-ff",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('original');",
"INSERT INTO t_simple VALUES (4);",
"INSERT INTO t_composite VALUES (3, 100);",
"INSERT INTO t_array VALUES (ARRAY['stu']);",
"INSERT INTO t_serial VALUES (DEFAULT);",
"INSERT INTO t_default_simple VALUES (98, 8);",
"INSERT INTO t_checked VALUES (99);",
"INSERT INTO t_fk_parent VALUES (40);",
"INSERT INTO t_fk_child VALUES (30);",
"INSERT INTO t_unique VALUES (10);",
"INSERT INTO t_generated (v1) VALUES (11);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger (v1) VALUES (2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (v2) VALUES (3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_CHECKOUT('original');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT strpos(DOLT_MERGE('main', '--no-ff', '-m', 'merge_commit')::text, 'merge successful') > 1;",
Expected: []sql.Row{{"t"}},
},
},
},
})
}
// TestDoltPreviewMergeConflicts includes a multitude of items to ensure that we're able to preview all item types.
func TestDoltPreviewMergeConflicts(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Preview conflicts",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, v1 INT4, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_generated (pk INT8 PRIMARY KEY, v1 INT4, v2 INT8 GENERATED ALWAYS AS (pk * 1000) STORED);",
"CREATE TABLE t_trigger (pk INT4 PRIMARY KEY, v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (pk INT4 PRIMARY KEY, v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1, 1);",
"INSERT INTO t_composite VALUES (1, 1, 1);",
"INSERT INTO t_array VALUES (ARRAY['abc'], 1);",
"INSERT INTO t_serial VALUES (DEFAULT, 1);",
"INSERT INTO t_generated (pk, v1) VALUES (1, 1);",
"INSERT INTO t_trigger VALUES (1, 1);",
"INSERT INTO t_default_func (pk, v2) VALUES (1, 1);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('other');",
"INSERT INTO t_simple VALUES (2, 2);",
"INSERT INTO t_composite VALUES (2, 2, 2);",
"INSERT INTO t_array VALUES (ARRAY['def'], 2);",
"INSERT INTO t_serial VALUES (DEFAULT, 2);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_CHECKOUT('other');",
"INSERT INTO t_simple VALUES (2, 3);",
"INSERT INTO t_composite VALUES (2, 2, 3);",
"INSERT INTO t_array VALUES (ARRAY['def'], 3);",
"INSERT INTO t_serial VALUES (DEFAULT, 3);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 3);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 34; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 3);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 35; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'other', 't_simple');",
Expected: []sql.Row{{1}},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'other', 't_composite');",
Expected: []sql.Row{{1}},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'other', 't_array');",
Expected: []sql.Row{{1}},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'other', 't_serial');",
Expected: []sql.Row{{1}},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'other', 't_generated');",
Expected: []sql.Row{{1}},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'other', 't_trigger');",
Expected: []sql.Row{{1}},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'other', 't_default_func');",
Expected: []sql.Row{{1}},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'other', 'f_default()');",
Skip: true, // TODO: implement for functions
Expected: []sql.Row{{1}},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'other', 'f_trigger()');",
Skip: true, // TODO: implement for functions
Expected: []sql.Row{{1}},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'other', 't_serial_pk_seq');",
Skip: true, // TODO: implement for sequences
Expected: []sql.Row{{1}},
},
},
},
})
}
// TestDoltPreviewMergeConflictsSummary includes a multitude of items to ensure that we're able to summarize all item types.
func TestDoltPreviewMergeConflictsSummary(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Preview summary",
Skip: true, // TODO: attempting to preview with interpreted functions causes a panic
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, v1 INT4, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY, v1 INT4);",
"CREATE TABLE t_generated (pk INT8 PRIMARY KEY, v1 INT4, v2 INT8 GENERATED ALWAYS AS (pk * 1000) STORED);",
"CREATE TABLE t_trigger (pk INT4 PRIMARY KEY, v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (pk INT4 PRIMARY KEY, v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1, 1);",
"INSERT INTO t_composite VALUES (1, 1, 1);",
"INSERT INTO t_array VALUES (ARRAY['abc'], 1);",
"INSERT INTO t_serial VALUES (DEFAULT, 1);",
"INSERT INTO t_generated (pk, v1) VALUES (1, 1);",
"INSERT INTO t_trigger VALUES (1, 1);",
"INSERT INTO t_default_func (pk, v2) VALUES (1, 1);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('other');",
"INSERT INTO t_simple VALUES (2, 2);",
"INSERT INTO t_composite VALUES (2, 2, 2);",
"INSERT INTO t_array VALUES (ARRAY['def'], 2);",
"INSERT INTO t_serial VALUES (DEFAULT, 2);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_CHECKOUT('other');",
"INSERT INTO t_simple VALUES (2, 3);",
"INSERT INTO t_composite VALUES (2, 2, 3);",
"INSERT INTO t_array VALUES (ARRAY['def'], 3);",
"INSERT INTO t_serial VALUES (DEFAULT, 3);",
"INSERT INTO t_generated (pk, v1) VALUES (2, 3);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 34; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger VALUES (2, 3);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 35; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (pk, v2) VALUES (2, 3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('main', 'other');",
Expected: []sql.Row{{9}},
},
},
},
})
}
func TestDoltQueryDiff(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Smoke test",
Skip: true, // TODO: AS OF seems to not be implemented yet
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY, v1 INT4);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('other');",
"INSERT INTO t_simple VALUES (1, 1), (2, 1);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'next')::text) = 34;",
"SELECT DOLT_CHECKOUT('other');",
"INSERT INTO t_simple VALUES (1, 2), (2, 2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'next')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM DOLT_QUERY_DIFF('SELECT * FROM t_simple AS OF main', 'SELECT * FROM t_simple AS OF other');",
Expected: []sql.Row{{}},
},
},
},
})
}
// TestDoltReset includes a multitude of items to ensure that we're able to reset all item types.
func TestDoltReset(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Hard",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT DOLT_RESET('--hard', 'HEAD~1');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT * FROM dolt_status;",
Skip: true, // TODO: need to implement root object support
Expected: []sql.Row{{0}},
},
},
},
{
Name: "Soft",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT DOLT_ADD('-A');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 't';",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT DOLT_RESET('--soft', 'HEAD');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 'f';",
// |--soft| moves only HEAD and leaves the staging area unchanged, so no items are unstaged.
Expected: []sql.Row{{0}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 't';",
Expected: []sql.Row{{16}},
},
},
},
})
}
// TestDoltRevert includes a multitude of items to ensure that we're able to revert all item types.
func TestDoltRevert(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Revert a single commit",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"INSERT INTO t_simple VALUES (4);",
"INSERT INTO t_composite VALUES (3, 100);",
"INSERT INTO t_array VALUES (ARRAY['stu']);",
"INSERT INTO t_serial VALUES (DEFAULT);",
"INSERT INTO t_default_simple VALUES (98, 8);",
"INSERT INTO t_checked VALUES (99);",
"INSERT INTO t_fk_parent VALUES (40);",
"INSERT INTO t_fk_child VALUES (30);",
"INSERT INTO t_unique VALUES (10);",
"INSERT INTO t_generated (v1) VALUES (11);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger (v1) VALUES (2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (v2) VALUES (3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}, {4}},
},
{
Query: `SELECT f_default();`,
Expected: []sql.Row{{34}},
},
{
// This returns a hash, so we need to take the consistent substring portion for testing
Query: `SELECT substring(DOLT_REVERT('HEAD')::text, 34);`,
Expected: []sql.Row{{",0,0,0}"}},
},
{
Query: `SELECT * FROM t_simple;`,
Expected: []sql.Row{{1}, {2}, {3}},
},
{
Query: `SELECT f_default();`,
Expected: []sql.Row{{33}},
},
},
},
})
}
// TestDoltRM includes a multitude of items to ensure that we're able to handle all item types with "rm".
func TestDoltRM(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Cached only",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT DOLT_ADD('-A');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 't';",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT DOLT_RM('--cached', 't_simple','t_composite','t_array','t_serial','t_default_simple'," +
"'t_checked','t_fk_parent','t_fk_child','t_unique','t_generated','t_trigger','t_default_func'," +
"'f_trigger()','f_default()','t_serial_pk_seq','t_trigger.trig_trigger');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status WHERE staged = 'f';",
Expected: []sql.Row{{16}},
},
},
},
// TODO: figure out how the non-cached version is supposed to work, as the example doesn't even work
})
}
// TestDoltSchemaDiff includes a multitude of items to ensure that the presence of each item type does not cause any
// errors when looking at schema diffs for tables.
func TestDoltSchemaDiff(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Single commit",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"SELECT DOLT_BRANCH('original');",
"INSERT INTO t_simple VALUES (4);",
"INSERT INTO t_composite VALUES (3, 100);",
"INSERT INTO t_array VALUES (ARRAY['stu']);",
"INSERT INTO t_serial VALUES (DEFAULT);",
"INSERT INTO t_default_simple VALUES (98, 8);",
"INSERT INTO t_checked VALUES (99);",
"INSERT INTO t_fk_parent VALUES (40);",
"INSERT INTO t_fk_child VALUES (30);",
"INSERT INTO t_unique VALUES (10);",
"INSERT INTO t_generated (v1) VALUES (11);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger (v1) VALUES (2);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (v2) VALUES (3);",
"ALTER TABLE t_simple RENAME COLUMN pk TO rcol;",
"ALTER TABLE t_composite RENAME COLUMN pk1 TO rcol;",
"ALTER TABLE t_array RENAME COLUMN pk TO rcol;",
"ALTER TABLE t_serial RENAME COLUMN pk TO rcol;",
"ALTER TABLE t_default_simple RENAME COLUMN v1 TO rcol;",
"ALTER TABLE t_generated RENAME COLUMN v1 TO rcol;",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM DOLT_SCHEMA_DIFF('main', 'original');",
Expected: []sql.Row{{6}},
},
},
},
})
}
// TestDoltStash includes a multitude of items to ensure that we're able to stash all item types.
func TestDoltStash(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Push and pop all untracked",
Skip: true, // TODO: errors with "dolt_procedures: unsupported type int", which seems like the Doltgres->Dolt layer is erroring
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{16}},
},
{
Query: "SELECT DOLT_STASH('push', 'dgstash', '--all');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{0}},
},
{
Query: "SELECT DOLT_STASH('pop', 'dgstash');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{16}},
},
},
},
{
Name: "Push and pop tracked",
Skip: true, // TODO: errors with "dolt_procedures: unsupported type int", which seems like the Doltgres->Dolt layer is erroring
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_composite (pk1 INT2, pk2 INT8, PRIMARY KEY(pk1, pk2));",
"CREATE TABLE t_array (pk TEXT[] PRIMARY KEY);",
"CREATE TABLE t_serial (pk SERIAL PRIMARY KEY);",
"CREATE TABLE t_default_simple (v1 INT8 DEFAULT 22, v2 INT8);",
"CREATE TABLE t_checked (v1 NUMERIC CHECK (v1 > 0 AND v1 <= 100));",
"CREATE TABLE t_fk_parent (pk INT4 PRIMARY KEY);",
"CREATE TABLE t_fk_child (pk INT4 REFERENCES t_fk_parent(pk), PRIMARY KEY(pk));",
"CREATE TABLE t_unique (v1 INT4 UNIQUE);",
"CREATE TABLE t_generated (v1 INT8, v2 INT8 GENERATED ALWAYS AS (v1 * 1000) STORED);",
"CREATE TABLE t_trigger (v1 INT8);",
"CREATE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 3; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"CREATE TRIGGER trig_trigger BEFORE INSERT OR UPDATE ON t_trigger FOR EACH ROW EXECUTE FUNCTION f_trigger();",
"CREATE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 33; END; $$ LANGUAGE plpgsql;",
"CREATE TABLE t_default_func (v1 INT8 DEFAULT f_default(), v2 INT8);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"INSERT INTO t_composite VALUES (1, 100), (1, 101), (2, 100), (2, 101);",
"INSERT INTO t_array VALUES (ARRAY['abc']), (ARRAY['def','ghi']), (ARRAY['jkl','mno','pqr']);",
"INSERT INTO t_serial VALUES (DEFAULT), (DEFAULT), (DEFAULT);",
"INSERT INTO t_default_simple VALUES (DEFAULT, 5), (99, 6), (DEFAULT, 7);",
"INSERT INTO t_checked VALUES (1), (50), (100);",
"INSERT INTO t_fk_parent VALUES (10), (20), (30);",
"INSERT INTO t_fk_child VALUES (10), (20);",
"INSERT INTO t_unique VALUES (7), (8), (9);",
"INSERT INTO t_generated (v1) VALUES (1), (2), (10);",
"CREATE OR REPLACE FUNCTION f_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.v1 := NEW.v1 * 33; RETURN NEW; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_trigger (v1) VALUES (5), (10), (0);",
"CREATE OR REPLACE FUNCTION f_default() RETURNS INT8 AS $$ BEGIN RETURN 34; END; $$ LANGUAGE plpgsql;",
"INSERT INTO t_default_func (v2) VALUES (1), (2);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{15}},
},
{
Query: "SELECT DOLT_STASH('push', 'dgstash');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{0}},
},
{
Query: "SELECT DOLT_STASH('pop', 'dgstash');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT COUNT(*) FROM dolt_status;",
Expected: []sql.Row{{15}},
},
},
},
})
}
func TestDoltTag(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Smoke test",
SetUpScript: []string{
"CREATE TABLE t_simple (pk INT4 PRIMARY KEY);",
"INSERT INTO t_simple VALUES (1), (2), (3);",
"SELECT length(DOLT_COMMIT('-A', '-m', 'initial')::text) = 34;",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT DOLT_TAG('tagged_commit', 'HEAD');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT DOLT_CHECKOUT('tagged_commit');",
ExpectedErr: "detached head",
},
},
},
})
}
func TestDoltFunctionSmokeTests(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "smoke test select dolt_add and dolt_commit",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key);",
},
Assertions: []ScriptTestAssertion{
{
Query: "select dolt_add('.')",
Expected: []sql.Row{
{"{0}"},
},
},
{
Query: "select dolt_commit('-am', 'new table')",
SkipResultsCheck: true,
},
{
Query: "select count(*) from dolt.log",
Expected: []sql.Row{
{3}, // initial commit, CREATE DATABASE commit, CREATE TABLE commit
},
},
{
Query: "select message from dolt.log order by date desc limit 1",
Expected: []sql.Row{
{"new table"},
},
},
},
},
{
Name: "smoke test select dolt_merge",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key);",
"SELECT DOLT_COMMIT('-Am', 'new table');",
"SELECT DOLT_CHECKOUT('-b', 'new-branch');",
"CREATE TABLE t2 (pk int primary key);",
"SELECT DOLT_COMMIT('-Am', 'new table on new branch');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT DOLT_MERGE_BASE('main', 'new-branch');",
SkipResultsCheck: true,
},
{
Query: "SELECT DOLT_CHECKOUT('main');",
Expected: []sql.Row{
{"{0,\"Switched to branch 'main'\"}"},
},
},
{
Query: "select count(*) from dolt.log",
Expected: []sql.Row{
{3}, // initial commit, CREATE DATABASE commit, CREATE TABLE commit
},
},
{
Query: "SELECT DOLT_MERGE('new-branch', '--no-ff', '-m', 'merge new-branch into main');",
SkipResultsCheck: true,
},
{
Query: "select count(*) from dolt.log",
Expected: []sql.Row{
{5}, // initial commit, CREATE DATABASE commit, CREATE TABLE t1 commit, new CREATE TABLE t2 commit, merge commit
},
},
},
},
{
Name: "smoke test select dolt_merge dirty working set, same table",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key);",
"SELECT DOLT_COMMIT('-Am', 'new table');",
"INSERT INTO t1 VALUES (1);",
"SELECT DOLT_CHECKOUT('-b', 'new-branch');",
"INSERT INTO t1 VALUES (2);",
"SELECT DOLT_COMMIT('-Am', 'new row on new branch');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT DOLT_MERGE_BASE('main', 'new-branch');",
SkipResultsCheck: true,
},
{
Query: "SELECT DOLT_CHECKOUT('main');",
Expected: []sql.Row{
{"{0,\"Switched to branch 'main'\"}"},
},
},
{
Query: "SELECT * FROM dolt.status",
Expected: []sql.Row{
{"public.t1", "f", "modified"},
},
},
{
Query: "SELECT DOLT_MERGE('new-branch', '--no-ff', '-m', 'merge new-branch into main');",
ExpectedErr: "error: local changes would be stomped by merge",
},
{
Query: "SELECT * FROM dolt.status",
Expected: []sql.Row{
{"public.t1", "f", "modified"},
},
},
},
},
{
Name: "smoke test select dolt_merge dirty working set, different tables",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key);",
"SELECT DOLT_COMMIT('-Am', 'new table');",
"INSERT INTO t1 VALUES (1);",
"SELECT DOLT_CHECKOUT('-b', 'new-branch');",
"CREATE TABLE t2 (pk int primary key);",
"SELECT DOLT_COMMIT('-Am', 'new row on new branch');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT DOLT_MERGE_BASE('main', 'new-branch');",
SkipResultsCheck: true,
},
{
Query: "SELECT DOLT_CHECKOUT('main');",
Expected: []sql.Row{
{"{0,\"Switched to branch 'main'\"}"},
},
},
{
Query: "SELECT * FROM dolt.status",
Expected: []sql.Row{
{"public.t1", "f", "modified"},
},
},
{
Query: "SELECT DOLT_MERGE('new-branch', '--no-ff', '-m', 'merge new-branch into main');",
SkipResultsCheck: true,
},
{
Query: "SELECT * FROM dolt.status",
Expected: []sql.Row{
{"public.t1", "f", "modified"},
},
},
},
},
{
Name: "smoke test select dolt_reset",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key);",
"INSERT INTO t1 VALUES (1);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM dolt.status;",
Expected: []sql.Row{
{"public.t1", "f", "new table"},
},
},
{
Query: "SELECT DOLT_ADD('t1');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT * FROM dolt.status;",
Expected: []sql.Row{
{"public.t1", "t", "new table"},
},
},
{
Query: "SELECT DOLT_RESET('t1');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT * FROM dolt.status;",
Expected: []sql.Row{
{"public.t1", "f", "new table"},
},
},
},
},
{
Name: "smoke test select dolt_clean",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key);",
"INSERT INTO t1 VALUES (1);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM dolt.status;",
Expected: []sql.Row{
{"public.t1", "f", "new table"},
},
},
{
Query: "SELECT DOLT_CLEAN('t1');",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT * FROM dolt.status;",
Expected: []sql.Row{},
},
{
Query: "CREATE TABLE t1 (pk int primary key);",
Expected: []sql.Row{},
},
{
Query: "SELECT DOLT_CLEAN();",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT * FROM dolt.status;",
Expected: []sql.Row{},
},
{
Query: "CREATE TABLE t1 (pk int primary key);",
Expected: []sql.Row{},
},
{
Query: "SELECT * FROM dolt.status;",
Expected: []sql.Row{
{"public.t1", "f", "new table"},
},
},
{
Query: "SELECT DOLT_CLEAN();",
Expected: []sql.Row{{"{0}"}},
},
{
Query: "SELECT * FROM dolt.status;",
Expected: []sql.Row{},
},
},
},
{
Name: "smoke test select dolt_checkout(table)",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key);",
"INSERT INTO t1 VALUES (1);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM dolt.status;",
Expected: []sql.Row{
{"public.t1", "f", "new table"},
},
},
{
Query: "SELECT DOLT_CHECKOUT('t1');",
Expected: []sql.Row{{`{0,""}`}},
},
{
Query: "SELECT * FROM dolt.status;",
Expected: []sql.Row{},
},
},
},
{
Name: "smoke test select dolt diff functions and tables",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key);",
"INSERT INTO t1 VALUES (1);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM dolt_diff_stat('HEAD', 'WORKING')",
Expected: []sql.Row{
{"public.t1", 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1},
},
},
{
Query: "SELECT * FROM dolt_diff_stat('HEAD', 'WORKING', 't1')",
Expected: []sql.Row{
{"public.t1", 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1},
},
},
{
Query: "SELECT * FROM dolt_diff_summary('HEAD', 'WORKING')",
Expected: []sql.Row{
{"", "public.t1", "added", "t", "t"},
},
},
{
Query: "SELECT * FROM dolt_diff_summary('HEAD', 'WORKING', 't1')",
Expected: []sql.Row{
{"", "public.t1", "added", "t", "t"},
},
},
{
Query: "SELECT diff_type, from_pk, to_pk FROM dolt_diff('HEAD', 'WORKING', 't1')",
Expected: []sql.Row{
{"added", nil, 1},
},
},
{
Query: "SELECT diff_type, from_pk, to_pk FROM dolt_diff('HEAD', 'WORKING', 't1')",
Expected: []sql.Row{
{"added", nil, 1},
},
},
{
Skip: true, // TODO: dolt_commit_diff_* tables must be filtered to a single 'to_commit'
Query: "SELECT diff_type, from_pk, to_pk FROM dolt_commit_diff_t1 WHERE to_commit=HASHOF('main') AND from_commit='WORKING'",
Expected: []sql.Row{
{"added", nil, 1},
},
},
{
Query: "SELECT * FROM dolt.diff",
Expected: []sql.Row{
{"WORKING", "public.t1", nil, nil, nil, nil, "t", "t", nil, nil, nil},
},
},
{
Query: "SELECT statement_order, table_name, diff_type, statement FROM dolt_patch('HEAD', 'WORKING')",
Expected: []sql.Row{
{Numeric("1"), "public.t1", "schema", "CREATE TABLE \"t1\" (\n \"pk\" integer NOT NULL,\n PRIMARY KEY (\"pk\")\n);"},
{Numeric("2"), "public.t1", "data", "INSERT INTO \"t1\" (\"pk\") VALUES (1);"},
},
},
{
Query: "SELECT statement_order, table_name, diff_type, statement FROM dolt_patch('HEAD', 'WORKING', 't1')",
Expected: []sql.Row{
{Numeric("1"), "public.t1", "schema", "CREATE TABLE \"t1\" (\n \"pk\" integer NOT NULL,\n PRIMARY KEY (\"pk\")\n);"},
{Numeric("2"), "public.t1", "data", "INSERT INTO \"t1\" (\"pk\") VALUES (1);"},
},
},
{
Query: "SELECT * FROM dolt_schema_diff('HEAD', 'WORKING')",
Expected: []sql.Row{
{"", "public.t1", "", "CREATE TABLE \"t1\" (\n \"pk\" integer NOT NULL,\n PRIMARY KEY (\"pk\")\n);"},
},
},
{
Query: "SELECT * FROM dolt_schema_diff('HEAD', 'WORKING', 't1')",
Expected: []sql.Row{
{"", "public.t1", "", "CREATE TABLE \"t1\" (\n \"pk\" integer NOT NULL,\n PRIMARY KEY (\"pk\")\n);"},
},
},
{
Skip: true, // ERROR: table not found: t1
Query: "SELECT * FROM dolt_query_diff('select * from t1 as of main', 'select * from t1')",
Expected: []sql.Row{
{"", "t1", "added", 1, 1},
},
},
},
},
{
Name: "smoke test select dolt diff functions and tables for multiple schemas",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key);",
"INSERT INTO t1 VALUES (1);",
"CREATE SCHEMA testschema;",
"CREATE TABLE testschema.t2 (pk int primary key);",
"INSERT INTO testschema.t2 VALUES (1);",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM dolt.status;",
Expected: []sql.Row{
{"public.t1", "f", "new table"},
{"testschema.t2", "f", "new table"},
{"testschema", "f", "new schema"},
},
},
{
Query: "SELECT * FROM dolt_diff_stat('HEAD', 'WORKING')",
Expected: []sql.Row{
{"public.t1", 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1},
{"testschema.t2", 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1},
},
},
{
Query: "SELECT * FROM dolt_diff_stat('HEAD', 'WORKING', 't1')",
Expected: []sql.Row{
{"public.t1", 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1},
},
},
{
Query: "SELECT * FROM dolt_diff_stat('HEAD', 'WORKING', 't2')",
Expected: []sql.Row{
{"testschema.t2", 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1},
},
},
{
Query: "SELECT * FROM dolt_diff_summary('HEAD', 'WORKING')",
Expected: []sql.Row{
{"", "public.t1", "added", "t", "t"},
{"", "testschema.t2", "added", "t", "t"},
},
},
{
Query: "SELECT * FROM dolt_diff_summary('HEAD', 'WORKING', 't1')",
Expected: []sql.Row{
{"", "public.t1", "added", "t", "t"},
},
},
{
Query: "SELECT * FROM dolt_diff_summary('HEAD', 'WORKING', 't2')",
Expected: []sql.Row{
{"", "testschema.t2", "added", "t", "t"},
},
},
{
Query: "SELECT diff_type, from_pk, to_pk FROM dolt_diff('HEAD', 'WORKING', 't1')",
Expected: []sql.Row{
{"added", nil, 1},
},
},
{
Query: "SELECT diff_type, from_pk, to_pk FROM dolt_diff('HEAD', 'WORKING', 't2')",
Expected: []sql.Row{
{"added", nil, 1},
},
},
{
Skip: true, // TODO: dolt_commit_diff_* tables must be filtered to a single 'to_commit'
Query: "SELECT diff_type, from_pk, to_pk FROM dolt_commit_diff_t1 WHERE to_commit=HASHOF('main') AND from_commit='WORKING'",
Expected: []sql.Row{
{"added", nil, 1},
},
},
{
Query: "SELECT * FROM dolt.diff",
Expected: []sql.Row{
{"WORKING", "public.t1", nil, nil, nil, nil, "t", "t", nil, nil, nil},
{"WORKING", "testschema.t2", nil, nil, nil, nil, "t", "t", nil, nil, nil},
},
},
{
Query: "SELECT statement_order, table_name, diff_type, statement FROM dolt_patch('HEAD', 'WORKING')",
Expected: []sql.Row{
{Numeric("1"), "public.t1", "schema", "CREATE TABLE \"t1\" (\n \"pk\" integer NOT NULL,\n PRIMARY KEY (\"pk\")\n);"},
{Numeric("2"), "public.t1", "data", "INSERT INTO \"t1\" (\"pk\") VALUES (1);"},
{Numeric("3"), "testschema.t2", "schema", "CREATE TABLE \"t2\" (\n \"pk\" integer NOT NULL,\n PRIMARY KEY (\"pk\")\n);"},
{Numeric("4"), "testschema.t2", "data", "INSERT INTO \"t2\" (\"pk\") VALUES (1);"},
},
},
{
Query: "SELECT statement_order, table_name, diff_type, statement FROM dolt_patch('HEAD', 'WORKING', 't1')",
Expected: []sql.Row{
{Numeric("1"), "public.t1", "schema", "CREATE TABLE \"t1\" (\n \"pk\" integer NOT NULL,\n PRIMARY KEY (\"pk\")\n);"},
{Numeric("2"), "public.t1", "data", "INSERT INTO \"t1\" (\"pk\") VALUES (1);"},
},
},
{
Query: "SELECT statement_order, table_name, diff_type, statement FROM dolt_patch('HEAD', 'WORKING', 't2')",
Expected: []sql.Row{
{Numeric("1"), "testschema.t2", "schema", "CREATE TABLE \"t2\" (\n \"pk\" integer NOT NULL,\n PRIMARY KEY (\"pk\")\n);"},
{Numeric("2"), "testschema.t2", "data", "INSERT INTO \"t2\" (\"pk\") VALUES (1);"},
},
},
{
Query: "SELECT * FROM dolt_schema_diff('HEAD', 'WORKING')",
Expected: []sql.Row{
{"", "public.t1", "", "CREATE TABLE \"t1\" (\n \"pk\" integer NOT NULL,\n PRIMARY KEY (\"pk\")\n);"},
{"", "testschema.t2", "", "CREATE TABLE \"t2\" (\n \"pk\" integer NOT NULL,\n PRIMARY KEY (\"pk\")\n);"},
},
},
{
Query: "SELECT * FROM dolt_schema_diff('HEAD', 'WORKING', 't1')",
Expected: []sql.Row{
{"", "public.t1", "", "CREATE TABLE \"t1\" (\n \"pk\" integer NOT NULL,\n PRIMARY KEY (\"pk\")\n);"},
},
},
{
Query: "SELECT * FROM dolt_schema_diff('HEAD', 'WORKING', 't2')",
Expected: []sql.Row{
{"", "testschema.t2", "", "CREATE TABLE \"t2\" (\n \"pk\" integer NOT NULL,\n PRIMARY KEY (\"pk\")\n);"},
},
},
{
Skip: true, // ERROR: table not found: t1
Query: "SELECT * FROM dolt_query_diff('select * from t1 as of main', 'select * from t1')",
Expected: []sql.Row{
{"", "public.t1", "added", 1, 1},
},
},
{
Skip: true, // ERROR: table not found: t2
Query: "SELECT * FROM dolt_query_diff('select * from t2 as of main', 'select * from t2')",
Expected: []sql.Row{
{"", "public.t1", "added", 1, 1},
},
},
},
},
{
Name: "dolt_patch works with JSONB columns",
SetUpScript: []string{
"CREATE TABLE repro (pk int primary key, data jsonb);",
"INSERT INTO repro VALUES (1, '{\"text\": \"hello\"}');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT statement_order, table_name, diff_type, statement FROM dolt_patch('HEAD', 'WORKING', 'repro')",
Expected: []sql.Row{
{Numeric("1"), "public.repro", "schema", "CREATE TABLE \"repro\" (\n \"pk\" integer NOT NULL,\n \"data\" jsonb,\n PRIMARY KEY (\"pk\")\n);"},
{Numeric("2"), "public.repro", "data", "INSERT INTO \"repro\" (\"pk\",\"data\") VALUES (1,'{\\\"text\\\": \\\"hello\\\"}');"},
},
},
{
Query: "SELECT diff_type, from_pk, to_pk FROM dolt_diff('HEAD', 'WORKING', 'repro')",
Expected: []sql.Row{
{"added", nil, 1},
},
},
},
},
{
Name: "DOLT_PREVIEW_MERGE_CONFLICTS basic functionality",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key, c1 int);",
"INSERT INTO t1 VALUES (1, 10), (2, 20);",
"SELECT DOLT_COMMIT('-Am', 'initial commit');",
"SELECT DOLT_CHECKOUT('-b', 'branch1');",
"UPDATE t1 SET c1 = 100 WHERE pk = 1;",
"SELECT DOLT_COMMIT('-am', 'update on branch1');",
"SELECT DOLT_CHECKOUT('main');",
"UPDATE t1 SET c1 = 200 WHERE pk = 1;",
"SELECT DOLT_COMMIT('-am', 'update on main');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('main', 'branch1')",
Expected: []sql.Row{
{"public.t1", Numeric("1"), Numeric("0")},
},
},
{
Query: "SELECT base_pk, base_c1, our_pk, our_c1, our_diff_type, their_pk, their_c1, their_diff_type FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 't1')",
Expected: []sql.Row{
{1, 10, 1, 200, "modified", 1, 100, "modified"},
},
},
},
},
{
Name: "DOLT_PREVIEW_MERGE_CONFLICTS with no conflicts",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key, c1 int);",
"INSERT INTO t1 VALUES (1, 10), (2, 20);",
"SELECT DOLT_COMMIT('-Am', 'initial commit');",
"SELECT DOLT_CHECKOUT('-b', 'branch1');",
"INSERT INTO t1 VALUES (3, 30);",
"SELECT DOLT_COMMIT('-am', 'insert on branch1');",
"SELECT DOLT_CHECKOUT('main');",
"INSERT INTO t1 VALUES (4, 40);",
"SELECT DOLT_COMMIT('-am', 'insert on main');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('main', 'branch1')",
Expected: []sql.Row{},
},
{
Query: "SELECT base_pk, base_c1, our_pk, our_c1, our_diff_type, their_pk, their_c1, their_diff_type FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 't1')",
Expected: []sql.Row{},
},
},
},
{
Name: "DOLT_PREVIEW_MERGE_CONFLICTS with multiple tables",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key, c1 int);",
"CREATE TABLE t2 (pk int primary key, c1 varchar(20));",
"INSERT INTO t1 VALUES (1, 10);",
"INSERT INTO t2 VALUES (1, 'initial');",
"SELECT DOLT_COMMIT('-Am', 'initial commit');",
"SELECT DOLT_CHECKOUT('-b', 'branch1');",
"UPDATE t1 SET c1 = 100 WHERE pk = 1;",
"UPDATE t2 SET c1 = 'branch1' WHERE pk = 1;",
"SELECT DOLT_COMMIT('-am', 'updates on branch1');",
"SELECT DOLT_CHECKOUT('main');",
"UPDATE t1 SET c1 = 200 WHERE pk = 1;",
"UPDATE t2 SET c1 = 'main' WHERE pk = 1;",
"SELECT DOLT_COMMIT('-am', 'updates on main');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('main', 'branch1') ORDER BY 'table'",
Expected: []sql.Row{
{"public.t1", Numeric("1"), Numeric("0")},
{"public.t2", Numeric("1"), Numeric("0")},
},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 't1')",
Expected: []sql.Row{
{1},
},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 't2')",
Expected: []sql.Row{
{1},
},
},
},
},
{
Name: "DOLT_PREVIEW_MERGE_CONFLICTS with schema conflicts",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key, c1 int);",
"INSERT INTO t1 VALUES (1, 10);",
"SELECT DOLT_COMMIT('-Am', 'initial commit');",
"SELECT DOLT_CHECKOUT('-b', 'branch1');",
"ALTER TABLE t1 ADD COLUMN c2 varchar(50);",
"SELECT DOLT_COMMIT('-am', 'add column on branch1');",
"SELECT DOLT_CHECKOUT('main');",
"ALTER TABLE t1 ADD COLUMN c2 int;",
"SELECT DOLT_COMMIT('-am', 'add same column different type on main');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('main', 'branch1')",
Expected: []sql.Row{
{"public.t1", nil, Numeric("1")},
},
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 't1')",
ExpectedErr: "schema conflicts found: 1",
},
},
},
{
Name: "DOLT_PREVIEW_MERGE_CONFLICTS with multiple schemas",
SetUpScript: []string{
"CREATE SCHEMA test_schema;",
"CREATE TABLE t1 (pk int primary key, c1 int);",
"CREATE TABLE test_schema.t2 (pk int primary key, c1 int);",
"INSERT INTO t1 VALUES (1, 10);",
"INSERT INTO test_schema.t2 VALUES (1, 20);",
"SELECT DOLT_COMMIT('-Am', 'initial commit');",
"SELECT DOLT_CHECKOUT('-b', 'branch1');",
"UPDATE t1 SET c1 = 100 WHERE pk = 1;",
"UPDATE test_schema.t2 SET c1 = 200 WHERE pk = 1;",
"SELECT DOLT_COMMIT('-am', 'updates on branch1');",
"SELECT DOLT_CHECKOUT('main');",
"UPDATE t1 SET c1 = 300 WHERE pk = 1;",
"UPDATE test_schema.t2 SET c1 = 400 WHERE pk = 1;",
"SELECT DOLT_COMMIT('-am', 'updates on main');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('main', 'branch1') ORDER BY 'table'",
Expected: []sql.Row{
{"public.t1", Numeric("1"), Numeric("0")},
{"test_schema.t2", Numeric("1"), Numeric("0")},
},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 't1')",
Expected: []sql.Row{
{1},
},
},
{
Query: "SELECT COUNT(*) FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 't2')",
Expected: []sql.Row{
{1},
},
},
},
},
{
Name: "DOLT_PREVIEW_MERGE_CONFLICTS with multiple schemas, same name",
SetUpScript: []string{
"CREATE SCHEMA test_schema;",
"CREATE TABLE t1 (pk int primary key, c1 int);",
"CREATE TABLE test_schema.t1 (pk int primary key, c2 int);",
"INSERT INTO t1 VALUES (1, 10);",
"INSERT INTO test_schema.t1 VALUES (1, 20);",
"SELECT DOLT_COMMIT('-Am', 'initial commit');",
"SELECT DOLT_CHECKOUT('-b', 'branch1');",
"UPDATE t1 SET c1 = 100 WHERE pk = 1;",
"UPDATE test_schema.t1 SET c2 = 200 WHERE pk = 1;",
"SELECT DOLT_COMMIT('-am', 'updates on branch1');",
"SELECT DOLT_CHECKOUT('main');",
"UPDATE t1 SET c1 = 300 WHERE pk = 1;",
"UPDATE test_schema.t1 SET c2 = 400 WHERE pk = 1;",
"SELECT DOLT_COMMIT('-am', 'updates on main');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('main', 'branch1') ORDER BY 'table'",
Expected: []sql.Row{
{"public.t1", Numeric("1"), Numeric("0")},
{"test_schema.t1", Numeric("1"), Numeric("0")},
},
},
{
Query: "SELECT base_c1 FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 't1')",
Expected: []sql.Row{
{10},
},
},
{
Query: "SELECT base_c2 FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 't1')",
ExpectedErr: "column \"base_c2\" could not be found in any table in scope",
},
{
Query: "SET search_path TO test_schema;",
Expected: []sql.Row{},
},
{
Query: "SELECT base_c2 FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 't1')",
Expected: []sql.Row{
{20},
},
},
{
Query: "SELECT base_c1 FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 't1')",
ExpectedErr: "column \"base_c1\" could not be found in any table in scope",
},
},
},
{
Name: "DOLT_PREVIEW_MERGE_CONFLICTS error cases",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key, c1 int);",
"SELECT DOLT_COMMIT('-Am', 'initial commit');",
"SELECT DOLT_CHECKOUT('-b', 'branch1');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('nonexistent-branch', 'main')",
ExpectedErr: "branch not found: nonexistent-branch",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('main', 'branch1', 'table')",
ExpectedErr: "function 'dolt_preview_merge_conflicts_summary' expected 2 arguments, 3 received",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('main', 'nonexistent-branch')",
ExpectedErr: "branch not found: nonexistent-branch",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('', 'main')",
ExpectedErr: "branch name cannot be empty",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('main', '')",
ExpectedErr: "branch name cannot be empty",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY(NULL, 'main')",
ExpectedErr: "Invalid argument to dolt_preview_merge_conflicts_summary: NULL",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('main', NULL)",
ExpectedErr: "Invalid argument to dolt_preview_merge_conflicts_summary: NULL",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('nonexistent-branch', 'main', 't1')",
ExpectedErr: "branch not found: nonexistent-branch",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'nonexistent-branch', 't1')",
ExpectedErr: "branch not found: nonexistent-branch",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1')",
ExpectedErr: "function 'dolt_preview_merge_conflicts' expected 3 arguments, 2 received",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 't1', 'extra')",
ExpectedErr: "function 'dolt_preview_merge_conflicts' expected 3 arguments, 4 received",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('', 'main', 't1')",
ExpectedErr: "string is not a valid branch or hash",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', '', 't1')",
ExpectedErr: "string is not a valid branch or hash",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS(NULL, 'main', 't1')",
ExpectedErr: "Invalid argument to dolt_preview_merge_conflicts: NULL",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', NULL, 't1')",
ExpectedErr: "Invalid argument to dolt_preview_merge_conflicts: NULL",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', NULL)",
ExpectedErr: "Invalid argument to dolt_preview_merge_conflicts: NULL",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', 'nonexistent_table')",
ExpectedErr: "table not found: public.nonexistent_table",
},
{
Query: "SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'branch1', '')",
ExpectedErr: "table name cannot be empty",
},
},
},
})
}