diff --git a/go/libraries/doltcore/sqle/dolt_diff_summary_table_function.go b/go/libraries/doltcore/sqle/dolt_diff_summary_table_function.go index c0cdf58ea8..f92e41c682 100644 --- a/go/libraries/doltcore/sqle/dolt_diff_summary_table_function.go +++ b/go/libraries/doltcore/sqle/dolt_diff_summary_table_function.go @@ -18,6 +18,7 @@ import ( "fmt" "io" "math" + "strings" "github.com/dolthub/go-mysql-server/sql" @@ -34,6 +35,7 @@ type DiffSummaryTableFunction struct { fromCommitExpr sql.Expression toCommitExpr sql.Expression + dotCommitExpr sql.Expression tableNameExpr sql.Expression database sql.Database } @@ -84,16 +86,29 @@ func (ds *DiffSummaryTableFunction) FunctionName() string { return "dolt_diff_summary" } -// Resolved implements the sql.Resolvable interface -func (ds *DiffSummaryTableFunction) Resolved() bool { - if ds.tableNameExpr != nil { - return ds.fromCommitExpr.Resolved() && ds.toCommitExpr.Resolved() && ds.tableNameExpr.Resolved() +func (ds *DiffSummaryTableFunction) commitsResolved() bool { + if ds.dotCommitExpr != nil { + return ds.dotCommitExpr.Resolved() } return ds.fromCommitExpr.Resolved() && ds.toCommitExpr.Resolved() } +// Resolved implements the sql.Resolvable interface +func (ds *DiffSummaryTableFunction) Resolved() bool { + if ds.tableNameExpr != nil { + return ds.commitsResolved() && ds.tableNameExpr.Resolved() + } + return ds.commitsResolved() +} + // String implements the Stringer interface func (ds *DiffSummaryTableFunction) String() string { + if ds.dotCommitExpr != nil { + if ds.tableNameExpr != nil { + return fmt.Sprintf("DOLT_DIFF_SUMMARY(%s, %s)", ds.dotCommitExpr.String(), ds.tableNameExpr.String()) + } + return fmt.Sprintf("DOLT_DIFF_SUMMARY(%s)", ds.dotCommitExpr.String()) + } if ds.tableNameExpr != nil { return fmt.Sprintf("DOLT_DIFF_SUMMARY(%s, %s, %s)", ds.fromCommitExpr.String(), ds.toCommitExpr.String(), ds.tableNameExpr.String()) } @@ -154,7 +169,12 @@ func (ds *DiffSummaryTableFunction) CheckPrivileges(ctx *sql.Context, opChecker // Expressions implements the sql.Expressioner interface. func (ds *DiffSummaryTableFunction) Expressions() []sql.Expression { - exprs := []sql.Expression{ds.fromCommitExpr, ds.toCommitExpr} + exprs := []sql.Expression{} + if ds.dotCommitExpr != nil { + exprs = append(exprs, ds.dotCommitExpr) + } else { + exprs = append(exprs, ds.fromCommitExpr, ds.toCommitExpr) + } if ds.tableNameExpr != nil { exprs = append(exprs, ds.tableNameExpr) } @@ -163,8 +183,8 @@ func (ds *DiffSummaryTableFunction) Expressions() []sql.Expression { // WithExpressions implements the sql.Expressioner interface. func (ds *DiffSummaryTableFunction) WithExpressions(expression ...sql.Expression) (sql.Node, error) { - if len(expression) < 2 || len(expression) > 3 { - return nil, sql.ErrInvalidArgumentNumber.New(ds.FunctionName(), "2 or 3", len(expression)) + if len(expression) < 1 { + return nil, sql.ErrInvalidArgumentNumber.New(ds.FunctionName(), "1 to 3", len(expression)) } for _, expr := range expression { @@ -173,19 +193,37 @@ func (ds *DiffSummaryTableFunction) WithExpressions(expression ...sql.Expression } } - ds.fromCommitExpr = expression[0] - ds.toCommitExpr = expression[1] - if len(expression) == 3 { - ds.tableNameExpr = expression[2] + if strings.Contains(expression[0].String(), "..") { + if len(expression) < 1 || len(expression) > 2 { + return nil, sql.ErrInvalidArgumentNumber.New(ds.FunctionName(), "1 or 2", len(expression)) + } + ds.dotCommitExpr = expression[0] + if len(expression) == 2 { + ds.tableNameExpr = expression[1] + } + } else { + if len(expression) < 2 || len(expression) > 3 { + return nil, sql.ErrInvalidArgumentNumber.New(ds.FunctionName(), "2 or 3", len(expression)) + } + ds.fromCommitExpr = expression[0] + ds.toCommitExpr = expression[1] + if len(expression) == 3 { + ds.tableNameExpr = expression[2] + } } // validate the expressions - if !sql.IsText(ds.fromCommitExpr.Type()) { - return nil, sql.ErrInvalidArgumentDetails.New(ds.FunctionName(), ds.fromCommitExpr.String()) - } - - if !sql.IsText(ds.toCommitExpr.Type()) { - return nil, sql.ErrInvalidArgumentDetails.New(ds.FunctionName(), ds.toCommitExpr.String()) + if ds.dotCommitExpr != nil { + if !sql.IsText(ds.dotCommitExpr.Type()) { + return nil, sql.ErrInvalidArgumentDetails.New(ds.FunctionName(), ds.dotCommitExpr.String()) + } + } else { + if !sql.IsText(ds.fromCommitExpr.Type()) { + return nil, sql.ErrInvalidArgumentDetails.New(ds.FunctionName(), ds.fromCommitExpr.String()) + } + if !sql.IsText(ds.toCommitExpr.Type()) { + return nil, sql.ErrInvalidArgumentDetails.New(ds.FunctionName(), ds.toCommitExpr.String()) + } } if ds.tableNameExpr != nil { @@ -199,7 +237,7 @@ func (ds *DiffSummaryTableFunction) WithExpressions(expression ...sql.Expression // RowIter implements the sql.Node interface func (ds *DiffSummaryTableFunction) RowIter(ctx *sql.Context, row sql.Row) (sql.RowIter, error) { - fromCommitVal, toCommitVal, tableName, err := ds.evaluateArguments() + fromCommitVal, toCommitVal, dotCommitVal, tableName, err := ds.evaluateArguments() if err != nil { return nil, err } @@ -209,13 +247,18 @@ func (ds *DiffSummaryTableFunction) RowIter(ctx *sql.Context, row sql.Row) (sql. return nil, fmt.Errorf("unexpected database type: %T", ds.database) } - sess := dsess.DSessFromSess(ctx.Session) - fromRoot, _, err := sess.ResolveRootForRef(ctx, sqledb.Name(), fromCommitVal) + fromCommitStr, toCommitStr, err := loadCommitStrings(ctx, fromCommitVal, toCommitVal, dotCommitVal, sqledb) if err != nil { return nil, err } - toRoot, _, err := sess.ResolveRootForRef(ctx, sqledb.Name(), toCommitVal) + sess := dsess.DSessFromSess(ctx.Session) + fromRoot, _, err := sess.ResolveRootForRef(ctx, sqledb.Name(), fromCommitStr) + if err != nil { + return nil, err + } + + toRoot, _, err := sess.ResolveRootForRef(ctx, sqledb.Name(), toCommitStr) if err != nil { return nil, err } @@ -256,42 +299,43 @@ func (ds *DiffSummaryTableFunction) RowIter(ctx *sql.Context, row sql.Row) (sql. return NewDiffSummaryTableFunctionRowIter(diffSummaries), nil } -// evaluateArguments returns fromCommitValStr, toCommitValStr and tableName. -// It evaluates the argument expressions to turn them into values this DiffTableFunction +// evaluateArguments returns fromCommitVal, toCommitVal, dotCommitVal, and tableName. +// It evaluates the argument expressions to turn them into values this DiffSummaryTableFunction // can use. Note that this method only evals the expressions, and doesn't validate the values. -func (ds *DiffSummaryTableFunction) evaluateArguments() (string, string, string, error) { +func (ds *DiffSummaryTableFunction) evaluateArguments() (interface{}, interface{}, interface{}, string, error) { var tableName string if ds.tableNameExpr != nil { tableNameVal, err := ds.tableNameExpr.Eval(ds.ctx, nil) if err != nil { - return "", "", "", err + return nil, nil, nil, "", err } tn, ok := tableNameVal.(string) if !ok { - return "", "", "", ErrInvalidTableName.New(ds.tableNameExpr.String()) + return nil, nil, nil, "", ErrInvalidTableName.New(ds.tableNameExpr.String()) } tableName = tn } + if ds.dotCommitExpr != nil { + dotCommitVal, err := ds.dotCommitExpr.Eval(ds.ctx, nil) + if err != nil { + return nil, nil, nil, "", err + } + + return nil, nil, dotCommitVal, tableName, nil + } + fromCommitVal, err := ds.fromCommitExpr.Eval(ds.ctx, nil) if err != nil { - return "", "", "", err - } - fromCommitValStr, ok := fromCommitVal.(string) - if !ok { - return "", "", "", fmt.Errorf("received '%v' when expecting commit hash string", fromCommitVal) + return nil, nil, nil, "", err } toCommitVal, err := ds.toCommitExpr.Eval(ds.ctx, nil) if err != nil { - return "", "", "", err - } - toCommitValStr, ok := toCommitVal.(string) - if !ok { - return "", "", "", fmt.Errorf("received '%v' when expecting commit hash string", toCommitVal) + return nil, nil, nil, "", err } - return fromCommitValStr, toCommitValStr, tableName, nil + return fromCommitVal, toCommitVal, nil, tableName, nil } // getDiffSummaryNodeFromDelta returns diffSummaryNode object and whether there is data diff or not. It gets tables diff --git a/go/libraries/doltcore/sqle/dolt_diff_table_function.go b/go/libraries/doltcore/sqle/dolt_diff_table_function.go index 14e9803647..6e1643dfc4 100644 --- a/go/libraries/doltcore/sqle/dolt_diff_table_function.go +++ b/go/libraries/doltcore/sqle/dolt_diff_table_function.go @@ -21,6 +21,8 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/diff" "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" + "github.com/dolthub/dolt/go/libraries/doltcore/merge" + "github.com/dolthub/dolt/go/libraries/doltcore/ref" "github.com/dolthub/dolt/go/libraries/doltcore/rowconv" "github.com/dolthub/dolt/go/libraries/doltcore/schema" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" @@ -40,6 +42,7 @@ type DiffTableFunction struct { ctx *sql.Context fromCommitExpr sql.Expression toCommitExpr sql.Expression + dotCommitExpr sql.Expression tableNameExpr sql.Expression database sql.Database sqlSch sql.Schema @@ -79,6 +82,11 @@ func (dtf *DiffTableFunction) WithDatabase(database sql.Database) (sql.Node, err // Expressions implements the sql.Expressioner interface func (dtf *DiffTableFunction) Expressions() []sql.Expression { + if dtf.dotCommitExpr != nil { + return []sql.Expression{ + dtf.dotCommitExpr, dtf.tableNameExpr, + } + } return []sql.Expression{ dtf.fromCommitExpr, dtf.toCommitExpr, dtf.tableNameExpr, } @@ -86,8 +94,8 @@ func (dtf *DiffTableFunction) Expressions() []sql.Expression { // WithExpressions implements the sql.Expressioner interface func (dtf *DiffTableFunction) WithExpressions(expression ...sql.Expression) (sql.Node, error) { - if len(expression) != 3 { - return nil, sql.ErrInvalidArgumentNumber.New(dtf.FunctionName(), 3, len(expression)) + if len(expression) < 2 { + return nil, sql.ErrInvalidArgumentNumber.New(dtf.FunctionName(), "2 to 3", len(expression)) } // TODO: For now, we will only support literal / fully-resolved arguments to the @@ -99,16 +107,27 @@ func (dtf *DiffTableFunction) WithExpressions(expression ...sql.Expression) (sql } } - dtf.fromCommitExpr = expression[0] - dtf.toCommitExpr = expression[1] - dtf.tableNameExpr = expression[2] + if strings.Contains(expression[0].String(), "..") { + if len(expression) != 2 { + return nil, sql.ErrInvalidArgumentNumber.New(fmt.Sprintf("%v with .. or ...", dtf.FunctionName()), 2, len(expression)) + } + dtf.dotCommitExpr = expression[0] + dtf.tableNameExpr = expression[1] + } else { + if len(expression) != 3 { + return nil, sql.ErrInvalidArgumentNumber.New(dtf.FunctionName(), 3, len(expression)) + } + dtf.fromCommitExpr = expression[0] + dtf.toCommitExpr = expression[1] + dtf.tableNameExpr = expression[2] + } - fromCommitVal, toCommitVal, tableName, err := dtf.evaluateArguments() + fromCommitVal, toCommitVal, dotCommitVal, tableName, err := dtf.evaluateArguments() if err != nil { return nil, err } - err = dtf.generateSchema(dtf.ctx, fromCommitVal, toCommitVal, tableName) + err = dtf.generateSchema(dtf.ctx, fromCommitVal, toCommitVal, dotCommitVal, tableName) if err != nil { return nil, err } @@ -127,29 +146,29 @@ func (dtf *DiffTableFunction) RowIter(ctx *sql.Context, _ sql.Row) (sql.RowIter, // TODO: When we add support for joining on table functions, we'll need to evaluate this against the // specified row. That row is what has the left_table context in a join query. // This will expand the test cases we need to cover significantly. - fromCommit, toCommit, _, err := dtf.evaluateArguments() + fromCommitVal, toCommitVal, dotCommitVal, _, err := dtf.evaluateArguments() if err != nil { return nil, err } - fromHash, fromOk := fromCommit.(string) - toHash, toOk := toCommit.(string) - if !fromOk || !toOk { - return nil, fmt.Errorf("expected strings for from and to revisions, got: %v, %v", fromHash, toHash) - } - sqledb, ok := dtf.database.(Database) if !ok { - panic("unable to get dolt database") + return nil, fmt.Errorf("unable to get dolt database") } - ddb := sqledb.GetDoltDB() - dp := dtables.NewDiffPartition(dtf.tableDelta.ToTable, dtf.tableDelta.FromTable, toHash, fromHash, dtf.toDate, dtf.fromDate, dtf.tableDelta.ToSch, dtf.tableDelta.FromSch) + fromCommitStr, toCommitStr, err := loadCommitStrings(ctx, fromCommitVal, toCommitVal, dotCommitVal, sqledb) + if err != nil { + return nil, err + } + + ddb := sqledb.GetDoltDB() + dp := dtables.NewDiffPartition(dtf.tableDelta.ToTable, dtf.tableDelta.FromTable, toCommitStr, fromCommitStr, dtf.toDate, dtf.fromDate, dtf.tableDelta.ToSch, dtf.tableDelta.FromSch) return NewDiffTableFunctionRowIterForSinglePartition(*dp, ddb, dtf.joiner), nil } -// findMatchingDelta returns the best matching table delta for the table name given, taking renames into account +// findMatchingDelta returns the best matching table delta for the table name +// given, taking renames into account func findMatchingDelta(deltas []diff.TableDelta, tableName string) diff.TableDelta { tableName = strings.ToLower(tableName) for _, d := range deltas { @@ -168,25 +187,132 @@ func findMatchingDelta(deltas []diff.TableDelta, tableName string) diff.TableDel return diff.TableDelta{} } -// loadDetailsForRef loads the root, hash, and timestamp for the specified ref value -func loadDetailsForRef( - ctx *sql.Context, - ref interface{}, - ddb Database, -) (*doltdb.RootValue, string, *types.Timestamp, error) { - hashStr, ok := ref.(string) - if !ok { - return nil, "", nil, fmt.Errorf("received '%v' when expecting commit hash string", ref) +type refDetails struct { + root *doltdb.RootValue + hashStr string + commitTime *types.Timestamp +} + +// loadDetailsForRef loads the root, hash, and timestamp for the specified from +// and to ref values +func loadDetailsForRefs(ctx *sql.Context, fromRef, toRef, dotRef interface{}, db Database) (*refDetails, *refDetails, error) { + fromCommitStr, toCommitStr, err := loadCommitStrings(ctx, fromRef, toRef, dotRef, db) + if err != nil { + return nil, nil, err } sess := dsess.DSessFromSess(ctx.Session) - root, commitTime, err := sess.ResolveRootForRef(ctx, ddb.Name(), hashStr) + fromDetails, err := resolveRoot(ctx, sess, db.Name(), fromCommitStr) if err != nil { - return nil, "", nil, err + return nil, nil, err } - return root, hashStr, commitTime, nil + toDetails, err := resolveRoot(ctx, sess, db.Name(), toCommitStr) + if err != nil { + return nil, nil, err + } + + return fromDetails, toDetails, nil +} + +func resolveCommitStrings(ctx *sql.Context, fromRef, toRef, dotRef interface{}, db Database) (string, string, error) { + if dotRef != nil { + dotStr, err := interfaceToString(dotRef) + if err != nil { + return "", "", err + } + + sess := dsess.DSessFromSess(ctx.Session) + + if strings.Contains(dotStr, "...") { + refs := strings.Split(dotStr, "...") + + headRef, err := sess.CWBHeadRef(ctx, db.Name()) + if err != nil { + return "", "", err + } + + rightCm, err := resolveCommit(ctx, db.ddb, headRef, refs[0]) + if err != nil { + return "", "", err + } + + leftCm, err := resolveCommit(ctx, db.ddb, headRef, refs[1]) + if err != nil { + return "", "", err + } + + mergeBase, err := merge.MergeBase(ctx, rightCm, leftCm) + if err != nil { + return "", "", err + } + + return mergeBase.String(), refs[1], nil + } else { + refs := strings.Split(dotStr, "..") + return refs[0], refs[1], nil + } + } + + fromStr, err := interfaceToString(fromRef) + if err != nil { + return "", "", err + } + + toStr, err := interfaceToString(toRef) + if err != nil { + return "", "", err + } + + return fromStr, toStr, nil +} + +// loadCommitStrings gets the to and from commit strings, using the common +// ancestor as the from commit string for three dot diff +func loadCommitStrings(ctx *sql.Context, fromRef, toRef, dotRef interface{}, db Database) (string, string, error) { + fromStr, toStr, err := resolveCommitStrings(ctx, fromRef, toRef, dotRef, db) + if err != nil { + return "", "", err + } + + if len(fromStr) == 0 || len(toStr) == 0 { + return "", "", fmt.Errorf("expected strings for from and to revisions, got: %v, %v", fromStr, toStr) + } + + return fromStr, toStr, nil +} + +// interfaceToString converts an interface to a string +func interfaceToString(r interface{}) (string, error) { + str, ok := r.(string) + if !ok { + return "", fmt.Errorf("received '%v' when expecting commit hash string", str) + } + return str, nil +} + +func resolveRoot(ctx *sql.Context, sess *dsess.DoltSession, dbName, hashStr string) (*refDetails, error) { + root, commitTime, err := sess.ResolveRootForRef(ctx, dbName, hashStr) + if err != nil { + return nil, err + } + + return &refDetails{root, hashStr, commitTime}, nil +} + +func resolveCommit(ctx *sql.Context, ddb *doltdb.DoltDB, headRef ref.DoltRef, cSpecStr string) (*doltdb.Commit, error) { + rightCs, err := doltdb.NewCommitSpec(cSpecStr) + if err != nil { + return nil, err + } + + rightCm, err := ddb.Resolve(ctx, rightCs, headRef) + if err != nil { + return nil, err + } + + return rightCm, nil } // WithChildren implements the sql.Node interface @@ -199,7 +325,7 @@ func (dtf *DiffTableFunction) WithChildren(node ...sql.Node) (sql.Node, error) { // CheckPrivileges implements the sql.Node interface func (dtf *DiffTableFunction) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { - _, _, tableName, err := dtf.evaluateArguments() + _, _, _, tableName, err := dtf.evaluateArguments() if err != nil { return false } @@ -211,46 +337,58 @@ func (dtf *DiffTableFunction) CheckPrivileges(ctx *sql.Context, opChecker sql.Pr // evaluateArguments evaluates the argument expressions to turn them into values this DiffTableFunction // can use. Note that this method only evals the expressions, and doesn't validate the values. -func (dtf *DiffTableFunction) evaluateArguments() (interface{}, interface{}, string, error) { +func (dtf *DiffTableFunction) evaluateArguments() (interface{}, interface{}, interface{}, string, error) { if !dtf.Resolved() { - return nil, nil, "", nil + return nil, nil, nil, "", nil } if !sql.IsText(dtf.tableNameExpr.Type()) { - return nil, nil, "", sql.ErrInvalidArgumentDetails.New(dtf.FunctionName(), dtf.tableNameExpr.String()) - } - - if !sql.IsText(dtf.fromCommitExpr.Type()) { - return nil, nil, "", sql.ErrInvalidArgumentDetails.New(dtf.FunctionName(), dtf.fromCommitExpr.String()) - } - - if !sql.IsText(dtf.toCommitExpr.Type()) { - return nil, nil, "", sql.ErrInvalidArgumentDetails.New(dtf.FunctionName(), dtf.toCommitExpr.String()) + return nil, nil, nil, "", sql.ErrInvalidArgumentDetails.New(dtf.FunctionName(), dtf.tableNameExpr.String()) } tableNameVal, err := dtf.tableNameExpr.Eval(dtf.ctx, nil) if err != nil { - return nil, nil, "", err + return nil, nil, nil, "", err } + tableName, ok := tableNameVal.(string) if !ok { - return nil, nil, "", ErrInvalidTableName.New(dtf.tableNameExpr.String()) + return nil, nil, nil, "", ErrInvalidTableName.New(dtf.tableNameExpr.String()) + } + + if dtf.dotCommitExpr != nil { + if !sql.IsText(dtf.dotCommitExpr.Type()) { + return nil, nil, nil, "", sql.ErrInvalidArgumentDetails.New(dtf.FunctionName(), dtf.dotCommitExpr.String()) + } + + dotCommitVal, err := dtf.dotCommitExpr.Eval(dtf.ctx, nil) + if err != nil { + return nil, nil, nil, "", err + } + + return nil, nil, dotCommitVal, tableName, nil + } + + if !sql.IsText(dtf.fromCommitExpr.Type()) { + return nil, nil, nil, "", sql.ErrInvalidArgumentDetails.New(dtf.FunctionName(), dtf.fromCommitExpr.String()) + } + if !sql.IsText(dtf.toCommitExpr.Type()) { + return nil, nil, nil, "", sql.ErrInvalidArgumentDetails.New(dtf.FunctionName(), dtf.toCommitExpr.String()) } fromCommitVal, err := dtf.fromCommitExpr.Eval(dtf.ctx, nil) if err != nil { - return nil, nil, "", err + return nil, nil, nil, "", err } toCommitVal, err := dtf.toCommitExpr.Eval(dtf.ctx, nil) if err != nil { - return nil, nil, "", err + return nil, nil, nil, "", err } - - return fromCommitVal, toCommitVal, tableName, nil + return fromCommitVal, toCommitVal, nil, tableName, nil } -func (dtf *DiffTableFunction) generateSchema(ctx *sql.Context, fromCommitVal, toCommitVal interface{}, tableName string) error { +func (dtf *DiffTableFunction) generateSchema(ctx *sql.Context, fromCommitVal, toCommitVal, dotCommitVal interface{}, tableName string) error { if !dtf.Resolved() { return nil } @@ -260,7 +398,7 @@ func (dtf *DiffTableFunction) generateSchema(ctx *sql.Context, fromCommitVal, to return fmt.Errorf("unexpected database type: %T", dtf.database) } - delta, err := dtf.cacheTableDelta(ctx, fromCommitVal, toCommitVal, tableName, sqledb) + delta, err := dtf.cacheTableDelta(ctx, fromCommitVal, toCommitVal, dotCommitVal, tableName, sqledb) if err != nil { return err } @@ -308,22 +446,18 @@ func (dtf *DiffTableFunction) generateSchema(ctx *sql.Context, fromCommitVal, to // cacheTableDelta caches and returns an appropriate table delta for the table name given, taking renames into // consideration. Returns a sql.ErrTableNotFound if the given table name cannot be found in either revision. -func (dtf *DiffTableFunction) cacheTableDelta(ctx *sql.Context, fromCommitVal interface{}, toCommitVal interface{}, tableName string, db Database) (diff.TableDelta, error) { - fromRoot, _, fromDate, err := loadDetailsForRef(ctx, fromCommitVal, db) +func (dtf *DiffTableFunction) cacheTableDelta(ctx *sql.Context, fromCommitVal, toCommitVal, dotCommitVal interface{}, tableName string, db Database) (diff.TableDelta, error) { + fromRefDetails, toRefDetails, err := loadDetailsForRefs(ctx, fromCommitVal, toCommitVal, dotCommitVal, db) if err != nil { return diff.TableDelta{}, err } - toRoot, _, toDate, err := loadDetailsForRef(ctx, toCommitVal, db) + fromTable, _, fromTableExists, err := fromRefDetails.root.GetTableInsensitive(ctx, tableName) if err != nil { return diff.TableDelta{}, err } - fromTable, _, fromTableExists, err := fromRoot.GetTableInsensitive(ctx, tableName) - if err != nil { - return diff.TableDelta{}, err - } - toTable, _, toTableExists, err := toRoot.GetTableInsensitive(ctx, tableName) + toTable, _, toTableExists, err := toRefDetails.root.GetTableInsensitive(ctx, tableName) if err != nil { return diff.TableDelta{}, err } @@ -333,13 +467,13 @@ func (dtf *DiffTableFunction) cacheTableDelta(ctx *sql.Context, fromCommitVal in } // TODO: it would be nice to limit this to just the table under consideration, not all tables with a diff - deltas, err := diff.GetTableDeltas(ctx, fromRoot, toRoot) + deltas, err := diff.GetTableDeltas(ctx, fromRefDetails.root, toRefDetails.root) if err != nil { return diff.TableDelta{}, err } - dtf.fromDate = fromDate - dtf.toDate = toDate + dtf.fromDate = fromRefDetails.commitTime + dtf.toDate = toRefDetails.commitTime delta := findMatchingDelta(deltas, tableName) @@ -389,11 +523,19 @@ func (dtf *DiffTableFunction) Schema() sql.Schema { // Resolved implements the sql.Resolvable interface func (dtf *DiffTableFunction) Resolved() bool { + if dtf.dotCommitExpr != nil { + return dtf.tableNameExpr.Resolved() && dtf.dotCommitExpr.Resolved() + } return dtf.tableNameExpr.Resolved() && dtf.fromCommitExpr.Resolved() && dtf.toCommitExpr.Resolved() } // String implements the Stringer interface func (dtf *DiffTableFunction) String() string { + if dtf.dotCommitExpr != nil { + return fmt.Sprintf("DOLT_DIFF(%s, %s)", + dtf.dotCommitExpr.String(), + dtf.tableNameExpr.String()) + } return fmt.Sprintf("DOLT_DIFF(%s, %s, %s)", dtf.fromCommitExpr.String(), dtf.toCommitExpr.String(), diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go index f161d3d3a4..09da6a4f13 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go @@ -767,6 +767,13 @@ var DoltUserPrivTests = []queries.UserPrivilegeTest{ Query: "SELECT * FROM dolt_diff('main~', 'main', 'test');", ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, }, + { + // Without access to the database, dolt_diff with dots should fail with a database access error + User: "tester", + Host: "localhost", + Query: "SELECT * FROM dolt_diff('main~..main', 'test');", + ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, + }, { // Without access to the database, dolt_diff_summary should fail with a database access error User: "tester", @@ -774,6 +781,13 @@ var DoltUserPrivTests = []queries.UserPrivilegeTest{ Query: "SELECT * FROM dolt_diff_summary('main~', 'main', 'test');", ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, }, + { + // Without access to the database, dolt_diff_summary with dots should fail with a database access error + User: "tester", + Host: "localhost", + Query: "SELECT * FROM dolt_diff_summary('main~..main', 'test');", + ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, + }, { // Without access to the database, dolt_log should fail with a database access error User: "tester", @@ -795,6 +809,13 @@ var DoltUserPrivTests = []queries.UserPrivilegeTest{ Query: "SELECT COUNT(*) FROM dolt_diff('main~', 'main', 'test');", Expected: []sql.Row{{1}}, }, + { + // After granting access to mydb.test, dolt_diff with dots should work + User: "tester", + Host: "localhost", + Query: "SELECT COUNT(*) FROM dolt_diff('main~..main', 'test');", + Expected: []sql.Row{{1}}, + }, { // With access to the db, but not the table, dolt_diff should fail User: "tester", @@ -802,6 +823,13 @@ var DoltUserPrivTests = []queries.UserPrivilegeTest{ Query: "SELECT * FROM dolt_diff('main~', 'main', 'test2');", ExpectedErr: sql.ErrPrivilegeCheckFailed, }, + { + // With access to the db, but not the table, dolt_diff with dots should fail + User: "tester", + Host: "localhost", + Query: "SELECT * FROM dolt_diff('main~..main', 'test2');", + ExpectedErr: sql.ErrPrivilegeCheckFailed, + }, { // With access to the db, but not the table, dolt_diff_summary should fail User: "tester", @@ -809,6 +837,13 @@ var DoltUserPrivTests = []queries.UserPrivilegeTest{ Query: "SELECT * FROM dolt_diff_summary('main~', 'main', 'test2');", ExpectedErr: sql.ErrPrivilegeCheckFailed, }, + { + // With access to the db, but not the table, dolt_diff_summary with dots should fail + User: "tester", + Host: "localhost", + Query: "SELECT * FROM dolt_diff_summary('main~...main', 'test2');", + ExpectedErr: sql.ErrPrivilegeCheckFailed, + }, { // With access to the db, dolt_diff_summary should fail for all tables if no access any of tables User: "tester", @@ -816,6 +851,13 @@ var DoltUserPrivTests = []queries.UserPrivilegeTest{ Query: "SELECT * FROM dolt_diff_summary('main~', 'main');", ExpectedErr: sql.ErrPrivilegeCheckFailed, }, + { + // With access to the db, dolt_diff_summary with dots should fail for all tables if no access any of tables + User: "tester", + Host: "localhost", + Query: "SELECT * FROM dolt_diff_summary('main~...main');", + ExpectedErr: sql.ErrPrivilegeCheckFailed, + }, { // Revoke select on mydb.test User: "root", @@ -830,6 +872,13 @@ var DoltUserPrivTests = []queries.UserPrivilegeTest{ Query: "SELECT * FROM dolt_diff('main~', 'main', 'test');", ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, }, + { + // After revoking access, dolt_diff with dots should fail + User: "tester", + Host: "localhost", + Query: "SELECT * FROM dolt_diff('main~..main', 'test');", + ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, + }, { // Grant multi-table access for all of mydb User: "root", @@ -844,6 +893,13 @@ var DoltUserPrivTests = []queries.UserPrivilegeTest{ Query: "SELECT COUNT(*) FROM dolt_diff('main~', 'main', 'test');", Expected: []sql.Row{{1}}, }, + { + // After granting access to the entire db, dolt_diff should work + User: "tester", + Host: "localhost", + Query: "SELECT COUNT(*) FROM dolt_diff('main~..main', 'test');", + Expected: []sql.Row{{1}}, + }, { // After granting access to the entire db, dolt_diff_summary should work User: "tester", @@ -851,6 +907,13 @@ var DoltUserPrivTests = []queries.UserPrivilegeTest{ Query: "SELECT COUNT(*) FROM dolt_diff_summary('main~', 'main');", Expected: []sql.Row{{1}}, }, + { + // After granting access to the entire db, dolt_diff_summary with dots should work + User: "tester", + Host: "localhost", + Query: "SELECT COUNT(*) FROM dolt_diff_summary('main~...main');", + Expected: []sql.Row{{1}}, + }, { // After granting access to the entire db, dolt_log should work User: "tester", @@ -872,6 +935,13 @@ var DoltUserPrivTests = []queries.UserPrivilegeTest{ Query: "SELECT * FROM dolt_diff('main~', 'main', 'test');", ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, }, + { + // After revoking access, dolt_diff with dots should fail + User: "tester", + Host: "localhost", + Query: "SELECT * FROM dolt_diff('main~...main', 'test');", + ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, + }, { // After revoking access, dolt_diff_summary should fail User: "tester", @@ -900,6 +970,13 @@ var DoltUserPrivTests = []queries.UserPrivilegeTest{ Query: "SELECT COUNT(*) FROM dolt_diff('main~', 'main', 'test');", Expected: []sql.Row{{1}}, }, + { + // After granting global access to *.*, dolt_diff should work + User: "tester", + Host: "localhost", + Query: "SELECT COUNT(*) FROM dolt_diff('main~...main', 'test');", + Expected: []sql.Row{{1}}, + }, { // Revoke global access User: "root", @@ -914,6 +991,13 @@ var DoltUserPrivTests = []queries.UserPrivilegeTest{ Query: "SELECT * FROM dolt_diff('main~', 'main', 'test');", ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, }, + { + // After revoking global access, dolt_diff with dots should fail + User: "tester", + Host: "localhost", + Query: "SELECT * FROM dolt_diff('main~..main', 'test');", + ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, + }, }, }, } @@ -4418,6 +4502,10 @@ var DiffTableFunctionScriptTests = []queries.ScriptTest{ "set @Commit2 = dolt_commit('-am', 'inserting into t');", }, Assertions: []queries.ScriptTestAssertion{ + { + Query: "SELECT * from dolt_diff();", + ExpectedErr: sql.ErrInvalidArgumentNumber, + }, { Query: "SELECT * from dolt_diff('t');", ExpectedErr: sql.ErrInvalidArgumentNumber, @@ -4470,6 +4558,43 @@ var DiffTableFunctionScriptTests = []queries.ScriptTest{ Query: "SELECT * from dolt_diff(hashof('main'), @Commit2, LOWER('T'));", ExpectedErr: sqle.ErrInvalidNonLiteralArgument, }, + + { + Query: "SELECT * from dolt_diff('main..main~');", + ExpectedErr: sql.ErrInvalidArgumentNumber, + }, + { + Query: "SELECT * from dolt_diff('main..main~', 'extra', 't');", + ExpectedErr: sql.ErrInvalidArgumentNumber, + }, + { + Query: "SELECT * from dolt_diff('main..main^', 123);", + ExpectedErr: sql.ErrInvalidArgumentDetails, + }, + { + Query: "SELECT * from dolt_diff('main..main~', 'doesnotexist');", + ExpectedErr: sql.ErrTableNotFound, + }, + { + Query: "SELECT * from dolt_diff('fakefakefakefakefakefakefakefake..main', 't');", + ExpectedErrStr: "target commit not found", + }, + { + Query: "SELECT * from dolt_diff('main..fakefakefakefakefakefakefakefake', 't');", + ExpectedErrStr: "target commit not found", + }, + { + Query: "SELECT * from dolt_diff('fakefakefakefakefakefakefakefake...main', 't');", + ExpectedErrStr: "target commit not found", + }, + { + Query: "SELECT * from dolt_diff('main...fakefakefakefakefakefakefakefake', 't');", + ExpectedErrStr: "target commit not found", + }, + { + Query: "SELECT * from dolt_diff('main..main~', LOWER('T'));", + ExpectedErr: sqle.ErrInvalidNonLiteralArgument, + }, }, }, { @@ -4573,6 +4698,14 @@ var DiffTableFunctionScriptTests = []queries.ScriptTest{ {nil, nil, nil, 3, "five", "six", "added"}, }, }, + { + Query: "SELECT from_pk, from_c1, from_c2, to_pk, to_c1, to_c2, diff_type from dolt_diff('STAGED..WORKING', 't') order by coalesce(from_pk, to_pk);", + Expected: []sql.Row{ + {1, "one", "two", 1, "one", "100", "modified"}, + {2, "three", "four", nil, nil, nil, "removed"}, + {nil, nil, nil, 3, "five", "six", "added"}, + }, + }, { Query: "SELECT from_pk, from_c1, from_c2, to_pk, to_c1, to_c2, diff_type from dolt_diff('WORKING', 'STAGED', 't') order by coalesce(from_pk, to_pk);", Expected: []sql.Row{ @@ -4585,6 +4718,10 @@ var DiffTableFunctionScriptTests = []queries.ScriptTest{ Query: "SELECT from_pk, from_c1, from_c2, to_pk, to_c1, to_c2, diff_type from dolt_diff('WORKING', 'WORKING', 't') order by coalesce(from_pk, to_pk);", Expected: []sql.Row{}, }, + { + Query: "SELECT from_pk, from_c1, from_c2, to_pk, to_c1, to_c2, diff_type from dolt_diff('WORKING..WORKING', 't') order by coalesce(from_pk, to_pk);", + Expected: []sql.Row{}, + }, { Query: "SELECT from_pk, from_c1, from_c2, to_pk, to_c1, to_c2, diff_type from dolt_diff('STAGED', 'STAGED', 't') order by coalesce(from_pk, to_pk);", Expected: []sql.Row{}, @@ -4639,6 +4776,13 @@ var DiffTableFunctionScriptTests = []queries.ScriptTest{ {2, "two", 2, "two", "three", "modified"}, }, }, + { + Query: "SELECT to_pk, to_c1, from_pk, from_c1, from_c2, diff_type from dolt_diff('main..branch1', 't');", + Expected: []sql.Row{ + {nil, nil, 1, "one", "two", "removed"}, + {2, "two", 2, "two", "three", "modified"}, + }, + }, { Query: "SELECT to_pk, to_c1, to_c2, from_pk, from_c1, diff_type from dolt_diff('branch1', 'main', 't');", Expected: []sql.Row{ @@ -4646,6 +4790,13 @@ var DiffTableFunctionScriptTests = []queries.ScriptTest{ {2, "two", "three", 2, "two", "modified"}, }, }, + { + Query: "SELECT to_pk, to_c1, to_c2, from_pk, from_c1, diff_type from dolt_diff('branch1..main', 't');", + Expected: []sql.Row{ + {1, "one", "two", nil, nil, "added"}, + {2, "two", "three", 2, "two", "modified"}, + }, + }, { Query: "SELECT to_pk, to_c1, from_pk, from_c1, from_c2, diff_type from dolt_diff('main~', 'branch1', 't');", Expected: []sql.Row{ @@ -4653,6 +4804,41 @@ var DiffTableFunctionScriptTests = []queries.ScriptTest{ {2, "two", nil, nil, nil, "added"}, }, }, + { + Query: "SELECT to_pk, to_c1, from_pk, from_c1, from_c2, diff_type from dolt_diff('main~..branch1', 't');", + Expected: []sql.Row{ + {nil, nil, 1, "one", "two", "removed"}, + {2, "two", nil, nil, nil, "added"}, + }, + }, + + // Three dot + { + Query: "SELECT to_pk, to_c1, from_pk, from_c1, from_c2, diff_type from dolt_diff('main...branch1', 't');", + Expected: []sql.Row{ + {nil, nil, 1, "one", "two", "removed"}, + {2, "two", nil, nil, nil, "added"}, + }, + }, + { + Query: "SELECT to_pk, to_c1, to_c2, from_pk, from_c1, diff_type from dolt_diff('branch1...main', 't');", + Expected: []sql.Row{ + {2, "two", "three", nil, nil, "added"}, + }, + }, + { + Query: "SELECT to_pk, to_c1, from_pk, from_c1, from_c2, diff_type from dolt_diff('main~...branch1', 't');", + Expected: []sql.Row{ + {nil, nil, 1, "one", "two", "removed"}, + {2, "two", nil, nil, nil, "added"}, + }, + }, + { + Query: "SELECT to_pk, to_c1, from_pk, from_c1, from_c2, diff_type from dolt_diff('main...branch1~', 't');", + Expected: []sql.Row{ + {nil, nil, 1, "one", "two", "removed"}, + }, + }, }, }, { @@ -4880,6 +5066,10 @@ var DiffTableFunctionScriptTests = []queries.ScriptTest{ Query: "select from_a, from_b, from_commit, to_commit, diff_type from dolt_diff('HEAD~', 'HEAD', 't1')", Expected: []sql.Row{{1, 2, "HEAD~", "HEAD", "removed"}}, }, + { + Query: "select from_a, from_b, from_commit, to_commit, diff_type from dolt_diff('HEAD~..HEAD', 't1')", + Expected: []sql.Row{{1, 2, "HEAD~", "HEAD", "removed"}}, + }, }, }, { @@ -4899,6 +5089,10 @@ var DiffTableFunctionScriptTests = []queries.ScriptTest{ Query: "select to_a, to_b, from_commit, to_commit, diff_type from dolt_diff('HEAD~', 'HEAD', 't2')", Expected: []sql.Row{{3, 4, "HEAD~", "HEAD", "added"}}, }, + { + Query: "select to_a, to_b, from_commit, to_commit, diff_type from dolt_diff('HEAD~..HEAD', 't2')", + Expected: []sql.Row{{3, 4, "HEAD~", "HEAD", "added"}}, + }, { // Maybe confusing? We match the old table name as well Query: "select to_a, to_b, from_commit, to_commit, diff_type from dolt_diff('HEAD~', 'HEAD', 't1')", @@ -4928,10 +5122,18 @@ var DiffTableFunctionScriptTests = []queries.ScriptTest{ Query: "select to_pk2, to_col1, from_pk, from_col1, diff_type from dolt_diff('HEAD~', 'HEAD', 't1')", Expected: []sql.Row{{1, 100, 1, 1, "modified"}}, }, + { + Query: "select to_pk2, to_col1, from_pk, from_col1, diff_type from dolt_diff('HEAD~..HEAD', 't1')", + Expected: []sql.Row{{1, 100, 1, 1, "modified"}}, + }, { Query: "select to_pk2a, to_pk2b, to_col1, from_pk1a, from_pk1b, from_col1, diff_type from dolt_diff('HEAD~', 'HEAD', 't2');", Expected: []sql.Row{{1, 1, 100, 1, 1, 1, "modified"}}, }, + { + Query: "select to_pk2a, to_pk2b, to_col1, from_pk1a, from_pk1b, from_col1, diff_type from dolt_diff('HEAD~..HEAD', 't2');", + Expected: []sql.Row{{1, 1, 100, 1, 1, 1, "modified"}}, + }, }, }, } @@ -5451,6 +5653,10 @@ var DiffSummaryTableFunctionScriptTests = []queries.ScriptTest{ "set @Commit2 = dolt_commit('-am', 'inserting into t');", }, Assertions: []queries.ScriptTestAssertion{ + { + Query: "SELECT * from dolt_diff_summary();", + ExpectedErr: sql.ErrInvalidArgumentNumber, + }, { Query: "SELECT * from dolt_diff_summary('t');", ExpectedErr: sql.ErrInvalidArgumentNumber, @@ -5479,14 +5685,26 @@ var DiffSummaryTableFunctionScriptTests = []queries.ScriptTest{ Query: "SELECT * from dolt_diff_summary('fake-branch', @Commit2, 't');", ExpectedErrStr: "branch not found: fake-branch", }, + { + Query: "SELECT * from dolt_diff_summary('fake-branch..main', 't');", + ExpectedErrStr: "branch not found: fake-branch", + }, { Query: "SELECT * from dolt_diff_summary(@Commit1, 'fake-branch', 't');", ExpectedErrStr: "branch not found: fake-branch", }, + { + Query: "SELECT * from dolt_diff_summary('main..fake-branch', 't');", + ExpectedErrStr: "branch not found: fake-branch", + }, { Query: "SELECT * from dolt_diff_summary(@Commit1, @Commit2, 'doesnotexist');", ExpectedErr: sql.ErrTableNotFound, }, + { + Query: "SELECT * from dolt_diff_summary('main^..main', 'doesnotexist');", + ExpectedErr: sql.ErrTableNotFound, + }, { Query: "SELECT * from dolt_diff_summary(@Commit1, concat('fake', '-', 'branch'), 't');", ExpectedErr: sqle.ErrInvalidNonLiteralArgument, @@ -5499,6 +5717,10 @@ var DiffSummaryTableFunctionScriptTests = []queries.ScriptTest{ Query: "SELECT * from dolt_diff_summary(@Commit1, @Commit2, LOWER('T'));", ExpectedErr: sqle.ErrInvalidNonLiteralArgument, }, + { + Query: "SELECT * from dolt_diff_summary('main..main~', LOWER('T'));", + ExpectedErr: sqle.ErrInvalidNonLiteralArgument, + }, }, }, { @@ -5702,6 +5924,10 @@ var DiffSummaryTableFunctionScriptTests = []queries.ScriptTest{ Query: "SELECT * from dolt_diff_summary('STAGED', 'WORKING', 't')", Expected: []sql.Row{{"t", 0, 1, 1, 1, 3, 3, 1, 2, 2, 6, 6}}, }, + { + Query: "SELECT * from dolt_diff_summary('STAGED..WORKING', 't')", + Expected: []sql.Row{{"t", 0, 1, 1, 1, 3, 3, 1, 2, 2, 6, 6}}, + }, { Query: "SELECT * from dolt_diff_summary('WORKING', 'STAGED', 't')", Expected: []sql.Row{{"t", 0, 1, 1, 1, 3, 3, 1, 2, 2, 6, 6}}, @@ -5710,6 +5936,10 @@ var DiffSummaryTableFunctionScriptTests = []queries.ScriptTest{ Query: "SELECT * from dolt_diff_summary('WORKING', 'WORKING', 't')", Expected: []sql.Row{}, }, + { + Query: "SELECT * from dolt_diff_summary('WORKING..WORKING', 't')", + Expected: []sql.Row{}, + }, { Query: "SELECT * from dolt_diff_summary('STAGED', 'STAGED', 't')", Expected: []sql.Row{}, @@ -5751,20 +5981,83 @@ var DiffSummaryTableFunctionScriptTests = []queries.ScriptTest{ "select dolt_checkout('main');", "insert into t values (2, 'two', 'three');", "set @Commit6 = dolt_commit('-am', 'inserting row 2 in main');", + + "create table newtable (pk int primary key);", + "insert into newtable values (1), (2);", + "set @Commit7 = dolt_commit('-Am', 'new table newtable');", }, Assertions: []queries.ScriptTestAssertion{ { Query: "SELECT * from dolt_diff_summary('main', 'branch1', 't');", Expected: []sql.Row{{"t", 0, 0, 1, 1, 0, 4, 0, 2, 1, 6, 2}}, }, + { + Query: "SELECT * from dolt_diff_summary('main..branch1', 't');", + Expected: []sql.Row{{"t", 0, 0, 1, 1, 0, 4, 0, 2, 1, 6, 2}}, + }, + { + Query: "SELECT * from dolt_diff_summary('main', 'branch1');", + Expected: []sql.Row{ + {"t", 0, 0, 1, 1, 0, 4, 0, 2, 1, 6, 2}, + {"newtable", 0, 0, 2, 0, 0, 2, 0, 2, 0, 2, 0}, + }, + }, + { + Query: "SELECT * from dolt_diff_summary('main..branch1');", + Expected: []sql.Row{ + {"t", 0, 0, 1, 1, 0, 4, 0, 2, 1, 6, 2}, + {"newtable", 0, 0, 2, 0, 0, 2, 0, 2, 0, 2, 0}, + }, + }, { Query: "SELECT * from dolt_diff_summary('branch1', 'main', 't');", Expected: []sql.Row{{"t", 0, 1, 0, 1, 4, 0, 1, 1, 2, 2, 6}}, }, { - Query: "SELECT * from dolt_diff_summary('main~', 'branch1', 't');", + Query: "SELECT * from dolt_diff_summary('branch1..main', 't');", + Expected: []sql.Row{{"t", 0, 1, 0, 1, 4, 0, 1, 1, 2, 2, 6}}, + }, + { + Query: "SELECT * from dolt_diff_summary('main~2', 'branch1', 't');", Expected: []sql.Row{{"t", 0, 1, 1, 0, 2, 3, 0, 1, 1, 3, 2}}, }, + { + Query: "SELECT * from dolt_diff_summary('main~2..branch1', 't');", + Expected: []sql.Row{{"t", 0, 1, 1, 0, 2, 3, 0, 1, 1, 3, 2}}, + }, + + // Three dot + { + Query: "SELECT * from dolt_diff_summary('main...branch1', 't');", + Expected: []sql.Row{{"t", 0, 1, 1, 0, 2, 3, 0, 1, 1, 3, 2}}, + }, + { + Query: "SELECT * from dolt_diff_summary('main...branch1');", + Expected: []sql.Row{{"t", 0, 1, 1, 0, 2, 3, 0, 1, 1, 3, 2}}, + }, + { + Query: "SELECT * from dolt_diff_summary('branch1...main', 't');", + Expected: []sql.Row{{"t", 1, 1, 0, 0, 3, 0, 0, 1, 2, 3, 6}}, + }, + { + Query: "SELECT * from dolt_diff_summary('branch1...main');", + Expected: []sql.Row{ + {"t", 1, 1, 0, 0, 3, 0, 0, 1, 2, 3, 6}, + {"newtable", 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 2}, + }, + }, + { + Query: "SELECT * from dolt_diff_summary('branch1...main^');", + Expected: []sql.Row{{"t", 1, 1, 0, 0, 3, 0, 0, 1, 2, 3, 6}}, + }, + { + Query: "SELECT * from dolt_diff_summary('branch1...main', 'newtable');", + Expected: []sql.Row{{"newtable", 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 2}}, + }, + { + Query: "SELECT * from dolt_diff_summary('main...main', 'newtable');", + Expected: []sql.Row{}, + }, }, }, { @@ -5922,11 +6215,20 @@ var DiffSummaryTableFunctionScriptTests = []queries.ScriptTest{ Query: "select * from dolt_diff_summary('HEAD~', 'HEAD', 't2')", Expected: []sql.Row{{"t2", 1, 1, 0, 0, 2, 0, 0, 1, 2, 2, 4}}, }, + { + Query: "select * from dolt_diff_summary('HEAD~..HEAD', 't2')", + Expected: []sql.Row{{"t2", 1, 1, 0, 0, 2, 0, 0, 1, 2, 2, 4}}, + }, { // Old table name can be matched as well Query: "select * from dolt_diff_summary('HEAD~', 'HEAD', 't1')", Expected: []sql.Row{{"t1", 1, 1, 0, 0, 2, 0, 0, 1, 2, 2, 4}}, }, + { + // Old table name can be matched as well + Query: "select * from dolt_diff_summary('HEAD~..HEAD', 't1')", + Expected: []sql.Row{{"t1", 1, 1, 0, 0, 2, 0, 0, 1, 2, 2, 4}}, + }, }, }, {