Merge remote-tracking branch 'origin/main' into steph/clone-branch

This commit is contained in:
Stephanie You
2023-12-05 10:38:32 -08:00
33 changed files with 814 additions and 275 deletions

View File

@@ -281,6 +281,12 @@ func CreateCountCommitsArgParser() *argparser.ArgParser {
return ap
}
func CreateReflogArgParser() *argparser.ArgParser {
ap := argparser.NewArgParserWithMaxArgs("reflog", 1)
ap.SupportsFlag(AllFlag, "", "Show all refs, including hidden refs, such as DoltHub workspace refs")
return ap
}
func CreateGlobalArgParser(name string) *argparser.ArgParser {
ap := argparser.NewArgParserWithVariableArgs(name)
if name == "dolt" {

View File

@@ -16,9 +16,6 @@ package commands
import (
"context"
"errors"
"github.com/fatih/color"
"github.com/dolthub/dolt/go/cmd/dolt/cli"
"github.com/dolthub/dolt/go/cmd/dolt/errhand"
@@ -82,48 +79,39 @@ func (cmd GarbageCollectionCmd) EventType() eventsapi.ClientEventType {
// Version displays the version of the running dolt client
// Exec executes the command
func (cmd GarbageCollectionCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
var verr errhand.VerboseError
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, gcDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
// We assert this here simply because the implementation of GC can
// delay actually trying to write to the chunk store for a long time
// after doing a lot or work. It's better to fail early.
if dEnv.IsAccessModeReadOnly() {
return HandleVErrAndExitCode(errhand.VerboseErrorFromError(env.ErrDatabaseIsLocked), help)
queryist, sqlCtx, closeFunc, err := cliCtx.QueryEngine(ctx)
if err != nil {
return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage)
}
if closeFunc != nil {
defer closeFunc()
}
var err error
query, err := constructDoltGCQuery(apr)
if err != nil {
return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage)
}
_, _, err = queryist.Query(sqlCtx, query)
if err != nil && err != chunks.ErrNothingToCollect {
return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage)
}
return HandleVErrAndExitCode(nil, usage)
}
// constructDoltGCQuery generates the sql query necessary to call DOLT_GC()
func constructDoltGCQuery(apr *argparser.ArgParseResults) (string, error) {
query := "call DOLT_GC("
if apr.Contains(cli.ShallowFlag) {
err = dEnv.DoltDB.ShallowGC(ctx)
if err != nil {
if err == chunks.ErrUnsupportedOperation {
verr = errhand.BuildDError("this database does not support shallow garbage collection").Build()
return HandleVErrAndExitCode(verr, usage)
}
verr = errhand.BuildDError("an error occurred during garbage collection").AddCause(err).Build()
}
} else {
// full gc
dEnv, err = MaybeMigrateEnv(ctx, dEnv)
if err != nil {
verr = errhand.BuildDError("could not load manifest for gc").AddCause(err).Build()
return HandleVErrAndExitCode(verr, usage)
}
err = dEnv.DoltDB.GC(ctx, nil)
if err != nil {
if errors.Is(err, chunks.ErrNothingToCollect) {
cli.PrintErrln(color.YellowString("Nothing to collect."))
} else {
verr = errhand.BuildDError("an error occurred during garbage collection").AddCause(err).Build()
}
}
query += "'--shallow'"
}
return HandleVErrAndExitCode(verr, usage)
query += ")"
return query, nil
}
func MaybeMigrateEnv(ctx context.Context, dEnv *env.DoltEnv) (*env.DoltEnv, error) {

View File

@@ -32,7 +32,7 @@ import (
var lsDocs = cli.CommandDocumentationContent{
ShortDesc: "List tables",
LongDesc: `With no arguments lists the tables in the current working set but if a commit is specified it will list the tables in that commit. If the {{.EmphasisLeft}}--verbose{{.EmphasisRight}} flag is provided a row count and a hash of the table will also be displayed.
LongDesc: `With no arguments lists the tables in the current working set but if a commit is specified it will list the tables in that commit. If the {{.EmphasisLeft}}--verbose{{.EmphasisRight}} flag is provided a row count of the table will also be displayed.
If the {{.EmphasisLeft}}--system{{.EmphasisRight}} flag is supplied this will show the dolt system tables which are queryable with SQL.

View File

@@ -55,7 +55,7 @@ func (q QueryDiff) Name() string {
}
func (q QueryDiff) Description() string {
return "description"
return "Shows table diff between two queries."
}
func (q QueryDiff) Docs() *cli.CommandDocumentation {

View File

@@ -0,0 +1,197 @@
// 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 commands
import (
"context"
"fmt"
"strings"
"github.com/dolthub/go-mysql-server/sql"
"github.com/gocraft/dbr/v2"
"github.com/gocraft/dbr/v2/dialect"
"github.com/dolthub/dolt/go/cmd/dolt/cli"
"github.com/dolthub/dolt/go/cmd/dolt/errhand"
eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1"
"github.com/dolthub/dolt/go/libraries/doltcore/env"
"github.com/dolthub/dolt/go/libraries/utils/argparser"
"github.com/dolthub/dolt/go/store/util/outputpager"
)
var reflogDocs = cli.CommandDocumentationContent{
ShortDesc: "Shows a history of named refs",
LongDesc: `Shows the history of named refs (e.g. branches and tags), which is useful for understanding how a branch
or tag changed over time to reference different commits, particularly for information not surfaced through {{.EmphasisLeft}}dolt log{{.EmphasisRight}}.
The data from Dolt's reflog comes from [Dolt's journaling chunk store](https://www.dolthub.com/blog/2023-03-08-dolt-chunk-journal/).
This data is local to a Dolt database and never included when pushing, pulling, or cloning a Dolt database. This means when you clone a Dolt database, it will not have any reflog data until you perform operations that change what commit branches or tags reference.
Dolt's reflog is similar to [Git's reflog](https://git-scm.com/docs/git-reflog), but there are a few differences:
- The Dolt reflog currently only supports named references, such as branches and tags, and not any of Git's special refs (e.g. {{.EmphasisLeft}}HEAD{{.EmphasisRight}}, {{.EmphasisLeft}}FETCH-HEAD{{.EmphasisRight}}, {{.EmphasisLeft}}MERGE-HEAD{{.EmphasisRight}}).
- The Dolt reflog can be queried for the log of references, even after a reference has been deleted. In Git, once a branch or tag is deleted, the reflog for that ref is also deleted and to find the last commit a branch or tag pointed to you have to use Git's special {{.EmphasisLeft}}HEAD{{.EmphasisRight}} reflog to find the commit, which can sometimes be challenging. Dolt makes this much easier by allowing you to see the history for a deleted ref so you can easily see the last commit a branch or tag pointed to before it was deleted.`,
Synopsis: []string{
`[--all] {{.LessThan}}ref{{.GreaterThan}}`,
},
}
type ReflogCmd struct{}
// Name is returns the name of the Dolt cli command. This is what is used on the command line to invoke the command
func (cmd ReflogCmd) Name() string {
return "reflog"
}
// Description returns a description of the command
func (cmd ReflogCmd) Description() string {
return "Show history of named refs."
}
// EventType returns the type of the event to log
func (cmd ReflogCmd) EventType() eventsapi.ClientEventType {
return eventsapi.ClientEventType_REFLOG
}
func (cmd ReflogCmd) Docs() *cli.CommandDocumentation {
ap := cmd.ArgParser()
return cli.NewCommandDocumentation(reflogDocs, ap)
}
func (cmd ReflogCmd) ArgParser() *argparser.ArgParser {
return cli.CreateReflogArgParser()
}
func (cmd ReflogCmd) RequiresRepo() bool {
return false
}
// Exec executes the command
func (cmd ReflogCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, reflogDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
queryist, sqlCtx, closeFunc, err := cliCtx.QueryEngine(ctx)
if err != nil {
return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage)
}
if closeFunc != nil {
defer closeFunc()
}
query, err := constructInterpolatedDoltReflogQuery(apr)
if err != nil {
return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage)
}
rows, err := GetRowsForSql(queryist, sqlCtx, query)
if err != nil {
return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage)
}
return printReflog(rows, queryist, sqlCtx)
}
// constructInterpolatedDoltReflogQuery generates the sql query necessary to call the DOLT_REFLOG() function.
// Also interpolates this query to prevent sql injection
func constructInterpolatedDoltReflogQuery(apr *argparser.ArgParseResults) (string, error) {
var params []interface{}
var args []string
if apr.NArg() == 1 {
params = append(params, apr.Arg(0))
args = append(args, "?")
}
if apr.Contains(cli.AllFlag) {
args = append(args, "'--all'")
}
query := fmt.Sprintf("SELECT ref, commit_hash, commit_message FROM DOLT_REFLOG(%s)", strings.Join(args, ", "))
interpolatedQuery, err := dbr.InterpolateForDialect(query, params, dialect.MySQL)
if err != nil {
return "", err
}
return interpolatedQuery, nil
}
type ReflogInfo struct {
ref string
commitHash string
commitMessage string
}
// printReflog takes a list of sql rows with columns ref, commit hash, commit message. Prints the reflog to stdout
func printReflog(rows []sql.Row, queryist cli.Queryist, sqlCtx *sql.Context) int {
var reflogInfo []ReflogInfo
// Get the hash of HEAD for the `HEAD ->` decoration
headHash := ""
res, err := GetRowsForSql(queryist, sqlCtx, "SELECT hashof('HEAD')")
if err == nil {
// still print the reflog even if we can't get the hash
headHash = res[0][0].(string)
}
for _, row := range rows {
ref := row[0].(string)
commitHash := row[1].(string)
commitMessage := row[2].(string)
reflogInfo = append(reflogInfo, ReflogInfo{ref, commitHash, commitMessage})
}
reflogToStdOut(reflogInfo, headHash)
return 0
}
// reflogToStdOut takes a list of ReflogInfo and prints the reflog to stdout
func reflogToStdOut(reflogInfo []ReflogInfo, headHash string) {
if cli.ExecuteWithStdioRestored == nil {
return
}
cli.ExecuteWithStdioRestored(func() {
pager := outputpager.Start()
defer pager.Stop()
for _, info := range reflogInfo {
// TODO: use short hash instead
line := []string{fmt.Sprintf("\033[33m%s\033[0m", info.commitHash)} // commit hash in yellow (33m)
processedRef := processRefForReflog(info.ref)
if headHash != "" && headHash == info.commitHash {
line = append(line, fmt.Sprintf("\033[33m(\033[36;1mHEAD -> %s\033[33m)\033[0m", processedRef)) // HEAD in cyan (36;1)
} else {
line = append(line, fmt.Sprintf("\033[33m(%s\033[33m)\033[0m", processedRef)) // () in yellow (33m)
}
line = append(line, fmt.Sprintf("%s\n", info.commitMessage))
pager.Writer.Write([]byte(strings.Join(line, " ")))
}
})
}
// processRefForReflog takes a full ref (e.g. refs/heads/master) or tag name and returns the ref name (e.g. master) with relevant decoration.
func processRefForReflog(fullRef string) string {
if strings.HasPrefix(fullRef, "refs/heads/") {
return fmt.Sprintf("\033[32;1m%s\033[0m", strings.TrimPrefix(fullRef, "refs/heads/")) // branch in green (32;1m)
} else if strings.HasPrefix(fullRef, "refs/tags/") {
return fmt.Sprintf("\033[33mtag: %s\033[0m", strings.TrimPrefix(fullRef, "refs/tags/")) // tag in yellow (33m)
} else if strings.HasPrefix(fullRef, "refs/remotes/") {
return fmt.Sprintf("\033[31;1m%s\033[0m", strings.TrimPrefix(fullRef, "refs/remotes/")) // remote in red (31;1m)
} else if strings.HasPrefix(fullRef, "refs/workspaces/") {
return fmt.Sprintf("\033[35;1mworkspace: %s\033[0m", strings.TrimPrefix(fullRef, "refs/workspaces/")) // workspace in magenta (35;1m)
} else {
return fullRef
}
}

View File

@@ -96,7 +96,7 @@ func FindAndLoadLocalCreds(fs filesys.Filesys) (creds *LocalCreds, err error) {
if err != nil {
return nil, err
}
for root != "" && root[len(root)-1] != '/' {
for root != "" && root[len(root)-1] != filepath.Separator {
creds, err := LoadLocalCreds(fs)
if err == nil {
return creds, err

View File

@@ -122,6 +122,7 @@ var doltSubCommands = []cli.Command{
&commands.Assist{},
commands.ProfileCmd{},
commands.QueryDiff{},
commands.ReflogCmd{},
}
var commandsWithoutCliCtx = []cli.Command{
@@ -138,7 +139,6 @@ var commandsWithoutCliCtx = []cli.Command{
commands.MigrateCmd{},
indexcmds.Commands,
commands.ReadTablesCmd{},
commands.GarbageCollectionCmd{},
commands.FilterBranchCmd{},
commands.RootsCmd{},
commands.VersionCmd{VersionStr: Version},

View File

@@ -155,6 +155,7 @@ const (
ClientEventType_STASH_POP ClientEventType = 60
ClientEventType_SHOW ClientEventType = 61
ClientEventType_PROFILE ClientEventType = 62
ClientEventType_REFLOG ClientEventType = 63
)
// Enum value maps for ClientEventType.

View File

@@ -59,7 +59,7 @@ require (
github.com/cespare/xxhash v1.1.0
github.com/creasty/defaults v1.6.0
github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2
github.com/dolthub/go-mysql-server v0.17.1-0.20231201192511-a3ee71b20029
github.com/dolthub/go-mysql-server v0.17.1-0.20231201211641-8889517a6d60
github.com/dolthub/swiss v0.1.0
github.com/goccy/go-json v0.10.2
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510

View File

@@ -181,8 +181,8 @@ github.com/dolthub/fslock v0.0.3 h1:iLMpUIvJKMKm92+N1fmHVdxJP5NdyDK5bK7z7Ba2s2U=
github.com/dolthub/fslock v0.0.3/go.mod h1:QWql+P17oAAMLnL4HGB5tiovtDuAjdDTPbuqx7bYfa0=
github.com/dolthub/go-icu-regex v0.0.0-20230524105445-af7e7991c97e h1:kPsT4a47cw1+y/N5SSCkma7FhAPw7KeGmD6c9PBZW9Y=
github.com/dolthub/go-icu-regex v0.0.0-20230524105445-af7e7991c97e/go.mod h1:KPUcpx070QOfJK1gNe0zx4pA5sicIK1GMikIGLKC168=
github.com/dolthub/go-mysql-server v0.17.1-0.20231201192511-a3ee71b20029 h1:Y8fx0dGnjI6QU+SAzyytzExQQP53dpcedMdwFNxIcxc=
github.com/dolthub/go-mysql-server v0.17.1-0.20231201192511-a3ee71b20029/go.mod h1:vXlRKS39WHav9N51VsfYphKhmSA2t5FkhHmW3BtwH5I=
github.com/dolthub/go-mysql-server v0.17.1-0.20231201211641-8889517a6d60 h1:4oj5xEB5anIEfFa2PXSMnb2jELIcnB4mexIeozmKyZM=
github.com/dolthub/go-mysql-server v0.17.1-0.20231201211641-8889517a6d60/go.mod h1:vXlRKS39WHav9N51VsfYphKhmSA2t5FkhHmW3BtwH5I=
github.com/dolthub/ishell v0.0.0-20221214210346-d7db0b066488 h1:0HHu0GWJH0N6a6keStrHhUAK5/o9LVfkh44pvsV4514=
github.com/dolthub/ishell v0.0.0-20221214210346-d7db0b066488/go.mod h1:ehexgi1mPxRTk0Mok/pADALuHbvATulTh6gzr7NzZto=
github.com/dolthub/jsonpath v0.0.2-0.20230525180605-8dc13778fd72 h1:NfWmngMi1CYUWU4Ix8wM+USEhjc+mhPlT9JUR/anvbQ=

View File

@@ -130,7 +130,12 @@ func mergeProllyTableData(ctx *sql.Context, tm *TableMerger, finalSch schema.Sch
keyless := schema.IsKeyless(tm.leftSch)
pri, err := newPrimaryMerger(leftEditor, tm, valueMerger, finalSch, mergeInfo)
defaults, err := resolveDefaults(ctx, tm.name, finalSch, tm.leftSch)
if err != nil {
return nil, nil, err
}
pri, err := newPrimaryMerger(leftEditor, tm, valueMerger, finalSch, mergeInfo, defaults)
if err != nil {
return nil, nil, err
}
@@ -1045,15 +1050,17 @@ type primaryMerger struct {
tableMerger *TableMerger
finalSch schema.Schema
mergeInfo MergeInfo
defaults []sql.Expression
}
func newPrimaryMerger(leftEditor *prolly.MutableMap, tableMerger *TableMerger, valueMerger *valueMerger, finalSch schema.Schema, mergeInfo MergeInfo) (*primaryMerger, error) {
func newPrimaryMerger(leftEditor *prolly.MutableMap, tableMerger *TableMerger, valueMerger *valueMerger, finalSch schema.Schema, mergeInfo MergeInfo, defaults []sql.Expression) (*primaryMerger, error) {
return &primaryMerger{
mut: leftEditor,
valueMerger: valueMerger,
tableMerger: tableMerger,
finalSch: finalSch,
mergeInfo: mergeInfo,
defaults: defaults,
}, nil
}
@@ -1150,13 +1157,8 @@ func (m *primaryMerger) merge(ctx *sql.Context, diff tree.ThreeWayDiff, sourceSc
return fmt.Errorf("cannot merge keyless tables with reordered columns")
}
} else {
defaults, err := resolveDefaults(ctx, m.tableMerger.name, m.finalSch, m.tableMerger.leftSch)
if err != nil {
return err
}
tempTupleValue, err := remapTupleWithColumnDefaults(ctx, diff.Key, newTupleValue, sourceSch.GetValueDescriptor(),
m.valueMerger.leftMapping, m.tableMerger, m.tableMerger.leftSch, m.finalSch, defaults, m.valueMerger.syncPool, false)
m.valueMerger.leftMapping, m.tableMerger, m.tableMerger.leftSch, m.finalSch, m.defaults, m.valueMerger.syncPool, false)
if err != nil {
return err
}

View File

@@ -45,8 +45,6 @@ type DiffStatTableFunction struct {
dotCommitExpr sql.Expression
tableNameExpr sql.Expression
database sql.Database
tabId sql.TableId
colset sql.ColSet
}
var diffStatTableSchema = sql.Schema{
@@ -79,26 +77,6 @@ func (ds *DiffStatTableFunction) NewInstance(ctx *sql.Context, db sql.Database,
return node, nil
}
func (ds *DiffStatTableFunction) WithId(id sql.TableId) sql.TableIdNode {
ret := *ds
ret.tabId = id
return &ret
}
func (ds *DiffStatTableFunction) Id() sql.TableId {
return ds.tabId
}
func (ds *DiffStatTableFunction) WithColumns(set sql.ColSet) sql.TableIdNode {
ret := *ds
ds.colset = set
return &ret
}
func (ds *DiffStatTableFunction) Columns() sql.ColSet {
return ds.colset
}
func (ds *DiffStatTableFunction) DataLength(ctx *sql.Context) (uint64, error) {
numBytesPerRow := schema.SchemaAvgLength(ds.Schema())
numRows, _, err := ds.RowCount(ctx)

View File

@@ -42,8 +42,6 @@ type DiffSummaryTableFunction struct {
dotCommitExpr sql.Expression
tableNameExpr sql.Expression
database sql.Database
tabId sql.TableId
colset sql.ColSet
}
var diffSummaryTableSchema = sql.Schema{
@@ -69,26 +67,6 @@ func (ds *DiffSummaryTableFunction) NewInstance(ctx *sql.Context, db sql.Databas
return node, nil
}
func (ds *DiffSummaryTableFunction) WithId(id sql.TableId) sql.TableIdNode {
ret := *ds
ret.tabId = id
return &ret
}
func (ds *DiffSummaryTableFunction) Id() sql.TableId {
return ds.tabId
}
func (ds *DiffSummaryTableFunction) WithColumns(set sql.ColSet) sql.TableIdNode {
ret := *ds
ret.colset = set
return &ret
}
func (ds *DiffSummaryTableFunction) Columns() sql.ColSet {
return ds.colset
}
func (ds *DiffSummaryTableFunction) DataLength(ctx *sql.Context) (uint64, error) {
numBytesPerRow := schema.SchemaAvgLength(ds.Schema())
numRows, _, err := ds.RowCount(ctx)

View File

@@ -54,29 +54,6 @@ type DiffTableFunction struct {
tableDelta diff.TableDelta
fromDate *types.Timestamp
toDate *types.Timestamp
tabId sql.TableId
colset sql.ColSet
}
func (dtf *DiffTableFunction) WithId(id sql.TableId) sql.TableIdNode {
ret := *dtf
ret.tabId = id
return &ret
}
func (dtf *DiffTableFunction) Id() sql.TableId {
return dtf.tabId
}
func (dtf *DiffTableFunction) WithColumns(set sql.ColSet) sql.TableIdNode {
ret := *dtf
ret.colset = set
return &ret
}
func (dtf *DiffTableFunction) Columns() sql.ColSet {
return dtf.colset
}
// NewInstance creates a new instance of TableFunction interface

View File

@@ -48,9 +48,6 @@ type LogTableFunction struct {
showParents bool
decoration string
tabId sql.TableId
colset sql.ColSet
database sql.Database
}
@@ -77,26 +74,6 @@ func (ltf *LogTableFunction) NewInstance(ctx *sql.Context, db sql.Database, expr
return node, nil
}
func (ltf *LogTableFunction) WithId(id sql.TableId) sql.TableIdNode {
ret := *ltf
ret.tabId = id
return &ret
}
func (ltf *LogTableFunction) Id() sql.TableId {
return ltf.tabId
}
func (ltf *LogTableFunction) WithColumns(set sql.ColSet) sql.TableIdNode {
ret := *ltf
ret.colset = set
return &ret
}
func (ltf *LogTableFunction) Columns() sql.ColSet {
return ltf.colset
}
// Database implements the sql.Databaser interface
func (ltf *LogTableFunction) Database() sql.Database {
return ltf.database

View File

@@ -74,28 +74,6 @@ type PatchTableFunction struct {
dotCommitExpr sql.Expression
tableNameExpr sql.Expression
database sql.Database
tabId sql.TableId
colset sql.ColSet
}
func (p *PatchTableFunction) WithId(id sql.TableId) sql.TableIdNode {
ret := *p
ret.tabId = id
return &ret
}
func (p *PatchTableFunction) Id() sql.TableId {
return p.tabId
}
func (p *PatchTableFunction) WithColumns(set sql.ColSet) sql.TableIdNode {
ret := *p
ret.colset = set
return &ret
}
func (p *PatchTableFunction) Columns() sql.ColSet {
return p.colset
}
func (p *PatchTableFunction) DataLength(ctx *sql.Context) (uint64, error) {

View File

@@ -45,29 +45,6 @@ type QueryDiffTableFunction struct {
rowIter2 sql.RowIter
schema1 sql.Schema
schema2 sql.Schema
tabId sql.TableId
colset sql.ColSet
}
func (tf *QueryDiffTableFunction) WithId(id sql.TableId) sql.TableIdNode {
ret := *tf
ret.tabId = id
return &ret
}
func (tf *QueryDiffTableFunction) Id() sql.TableId {
return tf.tabId
}
func (tf *QueryDiffTableFunction) WithColumns(set sql.ColSet) sql.TableIdNode {
ret := *tf
ret.colset = set
return &ret
}
func (tf *QueryDiffTableFunction) Columns() sql.ColSet {
return tf.colset
}
// NewInstance creates a new instance of TableFunction interface

View File

@@ -60,9 +60,6 @@ type SchemaDiffTableFunction struct {
tableNameExpr sql.Expression
database sql.Database
tabId sql.TableId
colset sql.ColSet
}
var schemaDiffTableSchema = sql.Schema{
@@ -87,25 +84,6 @@ func (ds *SchemaDiffTableFunction) NewInstance(ctx *sql.Context, db sql.Database
return node, nil
}
func (ds *SchemaDiffTableFunction) WithId(id sql.TableId) sql.TableIdNode {
//TODO implement me
panic("implement me")
}
func (ds *SchemaDiffTableFunction) Id() sql.TableId {
return ds.tabId
}
func (ds *SchemaDiffTableFunction) WithColumns(set sql.ColSet) sql.TableIdNode {
ret := *ds
ds.colset = set
return &ret
}
func (ds *SchemaDiffTableFunction) Columns() sql.ColSet {
return ds.colset
}
func (ds *SchemaDiffTableFunction) DataLength(ctx *sql.Context) (uint64, error) {
numBytesPerRow := schema.SchemaAvgLength(ds.Schema())
numRows, _, err := ds.RowCount(ctx)

View File

@@ -1984,7 +1984,7 @@ func TestBrokenSystemTableQueries(t *testing.T) {
}
func TestHistorySystemTable(t *testing.T) {
harness := newDoltHarness(t).WithParallelism(1)
harness := newDoltHarness(t).WithParallelism(2)
defer harness.Close()
harness.Setup(setup.MydbData)
for _, test := range HistorySystemTableScriptTests {

View File

@@ -4317,7 +4317,7 @@ var DoltReflogTestScripts = []queries.ScriptTest{
Assertions: []queries.ScriptTestAssertion{
{
Query: "select * from dolt_reflog('foo', 'bar');",
ExpectedErrStr: "function 'dolt_reflog' expected 0 or 1 arguments, 2 received",
ExpectedErrStr: "error: dolt_reflog has too many positional arguments. Expected at most 1, found 2: ['foo' 'bar']",
},
{
Query: "select * from dolt_reflog(NULL);",

View File

@@ -419,7 +419,6 @@ func (ht *HistoryTable) Collation() sql.CollationID {
// Partitions returns a PartitionIter which will be used in getting partitions each of which is used to create RowIter.
func (ht *HistoryTable) Partitions(ctx *sql.Context) (sql.PartitionIter, error) {
// TODO reset ht.cmItr on close
iter, err := ht.filterIter(ctx, ht.cmItr)
if err != nil {
return nil, err

View File

@@ -29,11 +29,9 @@ import (
)
type ReflogTableFunction struct {
ctx *sql.Context
database sql.Database
refExpr sql.Expression
tabId sql.TableId
colset sql.ColSet
ctx *sql.Context
database sql.Database
refAndArgExprs []sql.Expression
}
var _ sql.TableFunction = (*ReflogTableFunction)(nil)
@@ -60,26 +58,6 @@ func (rltf *ReflogTableFunction) NewInstance(ctx *sql.Context, database sql.Data
return node, nil
}
func (rltf *ReflogTableFunction) WithId(id sql.TableId) sql.TableIdNode {
ret := *rltf
ret.tabId = id
return &ret
}
func (rltf *ReflogTableFunction) Id() sql.TableId {
return rltf.tabId
}
func (rltf *ReflogTableFunction) WithColumns(set sql.ColSet) sql.TableIdNode {
ret := *rltf
ret.colset = set
return &ret
}
func (rltf *ReflogTableFunction) Columns() sql.ColSet {
return rltf.colset
}
func (rltf *ReflogTableFunction) RowIter(ctx *sql.Context, row sql.Row) (sql.RowIter, error) {
sqlDb, ok := rltf.database.(dsess.SqlDatabase)
if !ok {
@@ -87,17 +65,30 @@ func (rltf *ReflogTableFunction) RowIter(ctx *sql.Context, row sql.Row) (sql.Row
}
var refName string
if rltf.refExpr != nil {
target, err := rltf.refExpr.Eval(ctx, row)
showAll := false
for _, expr := range rltf.refAndArgExprs {
target, err := expr.Eval(ctx, row)
if err != nil {
return nil, fmt.Errorf("error evaluating expression (%s): %s",
rltf.refExpr.String(), err.Error())
expr.String(), err.Error())
}
refName, ok = target.(string)
targetStr, ok := target.(string)
if !ok {
return nil, fmt.Errorf("argument (%v) is not a string value, but a %T", target, target)
}
if targetStr == "--all" {
if showAll {
return nil, fmt.Errorf("error: multiple values provided for `all`")
}
showAll = true
} else {
if refName != "" {
return nil, fmt.Errorf("error: %s has too many positional arguments. Expected at most %d, found %d: %s",
rltf.Name(), 1, 2, rltf.refAndArgExprs)
}
refName = targetStr
}
}
ddb := sqlDb.DbData().Ddb
@@ -131,9 +122,15 @@ func (rltf *ReflogTableFunction) RowIter(ctx *sql.Context, row sql.Row) (sql.Row
if doltRef.GetType() == ref.InternalRefType {
return nil
}
// skip workspace refs by default
if doltRef.GetType() == ref.WorkspaceRefType {
if !showAll {
return nil
}
}
// If a ref expression to filter on was specified, see if we match the current ref
if rltf.refExpr != nil {
if refName != "" {
// If the caller has supplied a branch or tag name, without the fully qualified ref path,
// take the first match and use that as the canonical ref to filter on
if strings.HasSuffix(strings.ToLower(id), "/"+strings.ToLower(refName)) {
@@ -194,14 +191,21 @@ func (rltf *ReflogTableFunction) Schema() sql.Schema {
}
func (rltf *ReflogTableFunction) Resolved() bool {
if rltf.refExpr != nil {
return rltf.refExpr.Resolved()
for _, expr := range rltf.refAndArgExprs {
if !expr.Resolved() {
return false
}
}
return true
}
func (rltf *ReflogTableFunction) String() string {
return fmt.Sprintf("DOLT_REFLOG(%s)", rltf.refExpr.String())
var args []string
for _, expr := range rltf.refAndArgExprs {
args = append(args, expr.String())
}
return fmt.Sprintf("DOLT_REFLOG(%s)", strings.Join(args, ", "))
}
func (rltf *ReflogTableFunction) Children() []sql.Node {
@@ -226,21 +230,17 @@ func (rltf *ReflogTableFunction) IsReadOnly() bool {
}
func (rltf *ReflogTableFunction) Expressions() []sql.Expression {
if rltf.refExpr != nil {
return []sql.Expression{rltf.refExpr}
}
return []sql.Expression{}
return rltf.refAndArgExprs
}
func (rltf *ReflogTableFunction) WithExpressions(expression ...sql.Expression) (sql.Node, error) {
if len(expression) > 1 {
return nil, sql.ErrInvalidArgumentNumber.New(rltf.Name(), "0 or 1", len(expression))
if len(expression) > 2 {
return nil, sql.ErrInvalidArgumentNumber.New(rltf.Name(), "0 to 2", len(expression))
}
new := *rltf
if len(expression) > 0 {
new.refExpr = expression[0]
}
new.refAndArgExprs = expression
return &new, nil
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
5:__DOLT__:4t8rtld9ul7l137jac93phj1o6qinq6o:8ep2ilbq0lb461mqibkqp80nd0skdend:00000000000000000000000000000000:vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv:3722

View File

@@ -0,0 +1,6 @@
{
"head": "refs/heads/full",
"remotes": {},
"backups": {},
"branches": {}
}

View File

@@ -0,0 +1,153 @@
#!/usr/bin/env bats
load $BATS_TEST_DIRNAME/helper/common.bash
# This BATS test attempts to detect performance regressions when using standard workflows on large datasets.
# Please note that this is a rough approach that is not designed to detect all performance issues, merely an extra
# safeguard against bugs that cause large (order-of-magnitude+) regressions.
# BATS_TEST_TIMEOUT is measured in seconds and is chosen to be high enough that all tests in this suite pass
# when running on GitHub's CI, but low enough that an order-of magnitude regression will cause them to fail.
BATS_TEST_TIMEOUT=50
# This function was used to create the dolt repo used for this test. It is not run during testing.
create_repo() {
dolt init
dolt checkout -b full
dolt sql -q 'create table t (pk int primary key, c0 text default "1", c3 text default "2", c4 text default "3", c5 text default "4", c6 text default "5", c7 text default "6");'
dolt commit -Am "new table t"
echo "insert into t(pk) values" > import.sql
for i in {1..100000}
do
echo " ($i)," >> import.sql
done
echo " (104857);" >> import.sql
dolt sql < import.sql
dolt add .
dolt commit -m "Add all rows"
}
setup() {
cp -r $BATS_TEST_DIRNAME/performance-repo/ $BATS_TMPDIR/dolt-repo-$$
cd $BATS_TMPDIR/dolt-repo-$$
}
@test "performance: merge with no schema change and no conflict" {
dolt checkout full
dolt checkout -b mod2
dolt reset --soft HEAD^
dolt sql -q "delete from t where pk % 2 = 0"
dolt add .
dolt commit -m "Add mod2 rows"
dolt checkout full
dolt checkout -b mod3
dolt reset --soft HEAD^
dolt sql -q "delete from t where pk % 3 = 0"
dolt add .
dolt commit -m "Add mod3 rows"
run dolt merge mod2
log_status_eq 0
}
@test "performance: merge with no schema change and conflict" {
dolt checkout full
dolt checkout -b mod2
dolt reset --soft HEAD^
dolt sql -q "delete from t where pk % 2 = 0"
dolt add .
dolt commit -m "Add mod2 rows"
dolt checkout full
dolt checkout -b mod3
dolt reset --soft HEAD^
dolt sql -q "delete from t where pk % 3 = 0"
dolt sql -q 'update t set c0 = "conflict" where pk = 91'
dolt add .
dolt commit -m "Add mod3 rows"
run dolt merge mod2
log_status_eq 1
[[ "$output" =~ "Merge conflict in t" ]] || false
dolt conflicts resolve --ours t
BATS_TEST_TIMEOUT=1
}
@test "performance: merge with schema change and no conflict" {
dolt checkout full
dolt checkout -b mod2
dolt reset --soft HEAD^
dolt sql -q "delete from t where pk % 2 = 0"
dolt add .
dolt commit -m "Add mod2 rows"
dolt sql -q "alter table t add column c1 int default 1"
dolt add .
dolt commit -m "Add column c1"
dolt checkout full
dolt checkout -b mod3
dolt reset --soft HEAD^
dolt sql -q "delete from t where pk % 3 = 0"
dolt add .
dolt commit -m "Add mod3 rows"
dolt sql -q "alter table t add column c2 int default 2"
dolt add .
dolt commit -m "Add column c2"
run dolt merge mod2
log_status_eq 0
}
@test "performance: merge with schema change and conflict" {
dolt checkout full
dolt checkout -b mod2
dolt reset --soft HEAD^
dolt sql -q "delete from t where pk % 2 = 0"
dolt add .
dolt commit -m "Add mod2 rows"
dolt sql -q "alter table t add column c1 int default 1"
dolt add .
dolt commit -m "Add column c1"
dolt checkout full
dolt checkout -b mod3
dolt reset --soft HEAD^
dolt sql -q "delete from t where pk % 3 = 0"
dolt sql -q 'update t set c0 = "conflict" where pk = 91'
dolt add .
dolt commit -m "Add mod3 rows"
dolt sql -q "alter table t add column c2 int default 2"
dolt add .
dolt commit -m "Add column c2"
run dolt merge mod2
log_status_eq 1
dolt conflicts resolve --ours t
}

254
integration-tests/bats/reflog.bats Normal file → Executable file
View File

@@ -6,40 +6,27 @@ teardown() {
teardown_common
}
# Asserts that when DOLT_DISABLE_REFLOG is set, the dolt_reflog() table
# function returns an empty result set with no error.
# Asserts that when DOLT_DISABLE_REFLOG is set, dolt reflog returns nothing with no error.
@test "reflog: disabled with DOLT_DISABLE_REFLOG" {
export DOLT_DISABLE_REFLOG=true
setup_common
setup_common # need to set env vars before setup_common for remote tests
dolt sql -q "create table t (i int primary key, j int);"
dolt sql -q "insert into t values (1, 1), (2, 2), (3, 3)";
dolt commit -Am "initial commit"
dolt commit --allow-empty -m "test commit 1"
run dolt sql -q "select * from dolt_reflog();"
run dolt reflog
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 0 ]
}
# Sanity check for the most basic case of querying the Dolt reflog
@test "reflog: enabled by default" {
setup_common
dolt sql -q "create table t (i int primary key, j int);"
dolt sql -q "insert into t values (1, 1), (2, 2), (3, 3)";
dolt commit -Am "initial commit"
run dolt sql -q "select * from dolt_reflog();"
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 6 ]
[[ "$output" =~ "initial commit" ]] || false
[[ "$output" =~ "Initialize data repository" ]] || false
}
# Asserts that when DOLT_REFLOG_RECORD_LIMIT has been set, the reflog only contains the
# most recent entries and is limited by the env var's value.
@test "reflog: set DOLT_REFLOG_RECORD_LIMIT" {
export DOLT_REFLOG_RECORD_LIMIT=2
setup_common
setup_common # need to set env vars before setup_common for remote tests
dolt sql -q "create table t (i int primary key, j int);"
dolt sql -q "insert into t values (1, 1), (2, 2), (3, 3)";
dolt commit -Am "initial commit"
@@ -47,10 +34,237 @@ teardown() {
dolt commit --allow-empty -m "test commit 2"
# Only the most recent two ref changes should appear in the log
run dolt sql -q "select * from dolt_reflog();"
run dolt reflog
[ "$status" -eq 0 ]
[[ "$output" =~ "test commit 1" ]] || false
[[ "$output" =~ "test commit 2" ]] || false
[[ ! "$output" =~ "initial commit" ]] || false
[[ ! "$output" =~ "Initialize data repository" ]] || false
}
@test "reflog: simple reflog" {
setup_common
dolt sql -q "create table t (i int primary key, j int);"
dolt sql -q "insert into t values (1, 1), (2, 2), (3, 3)";
dolt commit -Am "initial commit"
run dolt reflog
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 2 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(HEAD -> main) initial commit" ]] || false
[[ "$out" =~ "Initialize data repository" ]] || false
}
@test "reflog: reflog with ref given" {
setup_common
dolt sql <<SQL
create table t1(pk int primary key);
call dolt_commit('-Am', 'creating table t1');
insert into t1 values(1);
call dolt_commit('-Am', 'inserting row 1');
call dolt_tag('tag1');
call dolt_checkout('-b', 'branch1');
insert into t1 values(2);
call dolt_commit('-Am', 'inserting row 2');
insert into t1 values(3);
call dolt_commit('-Am', 'inserting row 3');
call dolt_tag('-d', 'tag1');
call dolt_tag('tag1');
SQL
run dolt reflog refs/heads/main
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 3 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(HEAD -> main) inserting row 1" ]] || false
[[ "$out" =~ "creating table t1" ]] || false
[[ "$out" =~ "Initialize data repository" ]] || false
# ref is case-insensitive
run dolt reflog rEFs/heAdS/MAIN
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 3 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(HEAD -> main) inserting row 1" ]] || false
[[ "$out" =~ "creating table t1" ]] || false
[[ "$out" =~ "Initialize data repository" ]] || false
run dolt reflog main
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 3 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(HEAD -> main) inserting row 1" ]] || false
[[ "$out" =~ "creating table t1" ]] || false
[[ "$out" =~ "Initialize data repository" ]] || false
# ref is case-insensitive
run dolt reflog MaIn
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 3 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(HEAD -> main) inserting row 1" ]] || false
[[ "$out" =~ "creating table t1" ]] || false
[[ "$out" =~ "Initialize data repository" ]] || false
run dolt reflog refs/heads/branch1
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 3 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(branch1) inserting row 3" ]] || false
[[ "$out" =~ "inserting row 2" ]] || false
[[ "$out" =~ "inserting row 1" ]] || false
run dolt reflog branch1
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 3 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(branch1) inserting row 3" ]] || false
[[ "$out" =~ "inserting row 2" ]] || false
[[ "$out" =~ "inserting row 1" ]] || false
run dolt reflog refs/tags/tag1
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 2 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(tag: tag1) inserting row 3" ]] || false
[[ "$out" =~ "inserting row 1" ]] || false
# ref is case-insensitive
run dolt reflog Refs/tAGs/TaG1
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 2 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(tag: tag1) inserting row 3" ]] || false
[[ "$out" =~ "inserting row 1" ]] || false
run dolt reflog tag1
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 2 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(tag: tag1) inserting row 3" ]] || false
[[ "$out" =~ "inserting row 1" ]] || false
# ref is case-insensitive
run dolt reflog TAg1
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 2 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(tag: tag1) inserting row 3" ]] || false
[[ "$out" =~ "inserting row 1" ]] || false
dolt branch -D branch1
run dolt reflog branch1
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 3 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(branch1) inserting row 3" ]] || false
[[ "$out" =~ "inserting row 2" ]] || false
[[ "$out" =~ "inserting row 1" ]] || false
dolt tag -d tag1
run dolt reflog tag1
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 2 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(tag: tag1) inserting row 3" ]] || false
[[ "$out" =~ "inserting row 1" ]] || false
}
@test "reflog: garbage collection with no newgen data" {
setup_common
run dolt reflog
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 1 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(HEAD -> main) Initialize data repository" ]] || false
dolt gc
run dolt reflog
[ "$status" -eq 0 ]
if [ "$SQL_ENGINE" = "remote-engine" ]; then
[ "${#lines[@]}" -eq 1 ]
[[ "$output" =~ "Initialize data repository" ]] || false
else
[ "${#lines[@]}" -eq 0 ]
fi
}
@test "reflog: garbage collection with newgen data" {
setup_common
dolt sql <<SQL
create table t1(pk int primary key);
call dolt_commit('-Am', 'creating table t1');
insert into t1 values(1);
call dolt_commit('-Am', 'inserting row 1');
call dolt_tag('tag1');
insert into t1 values(2);
call dolt_commit('-Am', 'inserting row 2');
SQL
run dolt reflog main
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 4 ]
out=$(echo "$output" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$out" =~ "(HEAD -> main) inserting row 2" ]] || false
[[ "$out" =~ "inserting row 1" ]] || false
[[ "$out" =~ "creating table t1" ]] || false
[[ "$out" =~ "Initialize data repository" ]] || false
dolt gc
run dolt reflog main
[ "$status" -eq 0 ]
if [ "$SQL_ENGINE" = "remote-engine" ]; then
[ "${#lines[@]}" -eq 1 ]
[[ "$output" =~ "inserting row 2" ]] || false
else
[ "${#lines[@]}" -eq 0 ]
fi
}
@test "reflog: too many arguments given" {
setup_common
run dolt reflog foo bar
[ "$status" -eq 1 ]
[[ "$output" =~ "error: reflog has too many positional arguments" ]] || false
}
@test "reflog: unknown ref returns nothing" {
setup_common
dolt sql -q "create table t (i int primary key, j int);"
dolt sql -q "insert into t values (1, 1), (2, 2), (3, 3)";
dolt commit -Am "initial commit"
run dolt reflog foo
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 0 ]
}
@test "reflog: 'HEAD -> ' decoration only appears on HEAD entries" {
setup_common
dolt sql -q "create table t (i int primary key, j int);"
dolt sql -q "insert into t values (1, 1), (2, 2), (3, 3)";
dolt commit -Am "initial commit"
run dolt reflog
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 2 ]
line1=$(echo "${lines[0]}" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
line2=$(echo "${lines[1]}" | sed -E 's/\x1b\[[0-9;]*m//g') # remove special characters for color
[[ "$line1" =~ "(HEAD -> main) initial commit" ]] || false
[[ "$line2" =~ "Initialize data repository" ]] || false
[[ ! "$line2" =~ "HEAD" ]] || false
}

View File

@@ -1270,3 +1270,71 @@ SQL
[[ "$localOutput" == "$remoteOutput" ]] || false
}
@test "sql-local-remote: verify dolt reflog behavior" {
cd altDB
dolt sql -q "create table t (i int primary key, j int);"
dolt sql -q "insert into t values (1, 1), (2, 2), (3, 3)";
dolt commit -Am "initial commit"
run dolt --verbose-engine-setup reflog
[ $status -eq 0 ]
[[ "$output" =~ "starting local mode" ]] || false
[[ "$output" =~ "initial commit" ]] || false
run dolt reflog
localOutput=$output
start_sql_server altDB
run dolt --verbose-engine-setup reflog
[ $status -eq 0 ]
[[ "$output" =~ "starting remote mode" ]] || false
[[ "$output" =~ "initial commit" ]] || false
run dolt reflog
remoteOutput=$output
[[ "$localOutput" == "$remoteOutput" ]] || false
}
@test "sql-local-remote: verify dolt gc behavior" {
cd altDB
dolt sql <<SQL
CREATE TABLE test (pk int PRIMARY KEY);
INSERT INTO test VALUES
(1),(2),(3),(4),(5);
SQL
run dolt sql -q 'select count(*) from test' -r csv
[ "$status" -eq "0" ]
[[ "$output" =~ "5" ]] || false
run dolt --verbose-engine-setup gc
[ $status -eq 0 ]
[[ "$output" =~ "starting local mode" ]] || false
run dolt sql -q 'select count(*) from test' -r csv
[ "$status" -eq "0" ]
[[ "$output" =~ "5" ]] || false
start_sql_server altDB
dolt sql <<SQL
CREATE TABLE test2 (pk int PRIMARY KEY);
INSERT INTO test2 VALUES
(1),(2),(3),(4),(5);
SQL
run dolt sql -q 'select count(*) from test' -r csv
[ "$status" -eq "0" ]
[[ "$output" =~ "5" ]] || false
run dolt sql -q 'select count(*) from test2' -r csv
[ "$status" -eq "0" ]
[[ "$output" =~ "5" ]] || false
run dolt --verbose-engine-setup gc
[ $status -eq 0 ]
[[ "$output" =~ "starting remote mode" ]] || false
run dolt sql -q 'select count(*) from test' -r csv
[ "$status" -eq "0" ]
[[ "$output" =~ "5" ]] || false
run dolt sql -q 'select count(*) from test2' -r csv
[ "$status" -eq "0" ]
[[ "$output" =~ "5" ]] || false
}

View File

@@ -0,0 +1,59 @@
#!/usr/bin/env bats
load $BATS_TEST_DIRNAME/helper/common.bash
teardown() {
assert_feature_version
teardown_common
}
# Asserts that when DOLT_DISABLE_REFLOG is set, the dolt_reflog() table
# function returns an empty result set with no error.
@test "sql-reflog: disabled with DOLT_DISABLE_REFLOG" {
export DOLT_DISABLE_REFLOG=true
setup_common # need to set env vars before setup_common for remote tests
dolt sql -q "create table t (i int primary key, j int);"
dolt sql -q "insert into t values (1, 1), (2, 2), (3, 3)";
dolt commit -Am "initial commit"
dolt commit --allow-empty -m "test commit 1"
run dolt sql -q "select * from dolt_reflog();"
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 0 ]
}
# Sanity check for the most basic case of querying the Dolt reflog
@test "sql-reflog: enabled by default" {
setup_common
dolt sql -q "create table t (i int primary key, j int);"
dolt sql -q "insert into t values (1, 1), (2, 2), (3, 3)";
dolt commit -Am "initial commit"
run dolt sql -q "select * from dolt_reflog();"
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 6 ]
[[ "$output" =~ "initial commit" ]] || false
[[ "$output" =~ "Initialize data repository" ]] || false
}
# Asserts that when DOLT_REFLOG_RECORD_LIMIT has been set, the reflog only contains the
# most recent entries and is limited by the env var's value.
@test "sql-reflog: set DOLT_REFLOG_RECORD_LIMIT" {
export DOLT_REFLOG_RECORD_LIMIT=2
setup_common # need to set env vars before setup_common for remote tests
dolt sql -q "create table t (i int primary key, j int);"
dolt sql -q "insert into t values (1, 1), (2, 2), (3, 3)";
dolt commit -Am "initial commit"
dolt commit --allow-empty -m "test commit 1"
dolt commit --allow-empty -m "test commit 2"
# Only the most recent two ref changes should appear in the log
run dolt sql -q "select * from dolt_reflog();"
[ "$status" -eq 0 ]
[[ "$output" =~ "test commit 1" ]] || false
[[ "$output" =~ "test commit 2" ]] || false
[[ ! "$output" =~ "initial commit" ]] || false
[[ ! "$output" =~ "Initialize data repository" ]] || false
}

View File

@@ -92,6 +92,7 @@ enum ClientEventType {
STASH_POP = 60;
SHOW = 61;
PROFILE = 62;
REFLOG = 63;
}
enum MetricID {