diff --git a/go/cmd/dolt/cli/documentation_helper.go b/go/cmd/dolt/cli/documentation_helper.go
index 0c4c243a09d..d479325d040 100644
--- a/go/cmd/dolt/cli/documentation_helper.go
+++ b/go/cmd/dolt/cli/documentation_helper.go
@@ -217,6 +217,9 @@ var CliFormat = docFormat{"<", ">", "", ""}
// Synopsis is an mdx format, but already inside a code block
var SynopsisMarkdownFormat = docFormat{"<", ">", "`", "`"}
+// Format that deletes all template options
+var EmptyFormat = docFormat{"", "", "", ""}
+
func transformSynopsisToMarkdown(commandStr string, synopsis []string) string {
if len(synopsis) == 0 {
return ""
diff --git a/go/cmd/dolt/cli/help.go b/go/cmd/dolt/cli/help.go
index 2e35195ae4a..c2e9cd6c47f 100644
--- a/go/cmd/dolt/cli/help.go
+++ b/go/cmd/dolt/cli/help.go
@@ -166,21 +166,35 @@ func terminalSize() (width, height int) {
func OptionsUsage(ap *argparser.ArgParser, indent string, lineLen int) string {
var lines []string
- for _, kvTuple := range ap.ArgListHelp {
- k, v := kvTuple[0], kvTuple[1]
- lines = append(lines, "<"+k+">")
- l, err := templateDocStringHelper(v, CliFormat)
- if err != nil {
- panic(err)
- }
- l = embolden(l)
- descLines := toParagraphLines(l, lineLen)
+ for _, usage := range OptionsUsageList(ap, CliFormat) {
+ name, description := usage[0], usage[1]
+
+ lines = append(lines, name)
+
+ descLines := toParagraphLines(description, lineLen)
descLines = indentLines(descLines, " ")
descLines = append(descLines, "")
lines = append(lines, descLines...)
}
+ lines = indentLines(lines, indent)
+ return strings.Join(lines, "\n")
+}
+
+// OptionsUsageList returns a pair of strings for each option/argument in |ap|, where the first string
+// is the name of the option/argument and the second string is the description of the option/argument.
+func OptionsUsageList(ap *argparser.ArgParser, docFormat docFormat) [][2]string {
+ res := [][2]string{}
+
+ for _, help := range ap.ArgListHelp {
+ name, description := help[0], help[1]
+
+ nameFormatted := "<" + name + ">"
+
+ res = append(res, [2]string{nameFormatted, description})
+ }
+
for _, supOpt := range ap.Supported {
argHelpFmt := "--%[2]s"
@@ -192,22 +206,22 @@ func OptionsUsage(ap *argparser.ArgParser, indent string, lineLen int) string {
argHelpFmt = "--%[2]s=<%[3]s>"
}
- lines = append(lines, fmt.Sprintf(argHelpFmt, supOpt.Abbrev, supOpt.Name, supOpt.ValDesc))
+ nameFormatted := fmt.Sprintf(argHelpFmt, supOpt.Abbrev, supOpt.Name, supOpt.ValDesc)
- l, err := templateDocStringHelper(supOpt.Desc, CliFormat)
+ res = append(res, [2]string{nameFormatted, supOpt.Desc})
+ }
+
+ for i := range res {
+ descriptionFormatted, err := templateDocStringHelper(res[i][1], docFormat)
if err != nil {
panic(err)
}
- l = embolden(l)
- descLines := toParagraphLines(l, lineLen)
- descLines = indentLines(descLines, " ")
- descLines = append(descLines, "")
+ descriptionFormatted = embolden(descriptionFormatted)
- lines = append(lines, descLines...)
+ res[i][1] = descriptionFormatted
}
- lines = indentLines(lines, indent)
- return strings.Join(lines, "\n")
+ return res
}
func ToIndentedParagraph(inStr, indent string, lineLen int) string {
diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go
index 9c89eb4fdbd..489e3c41fbf 100644
--- a/go/cmd/dolt/dolt.go
+++ b/go/cmd/dolt/dolt.go
@@ -44,15 +44,13 @@ import (
"github.com/dolthub/dolt/go/cmd/dolt/commands"
"github.com/dolthub/dolt/go/cmd/dolt/commands/admin"
"github.com/dolthub/dolt/go/cmd/dolt/commands/ci"
- "github.com/dolthub/dolt/go/cmd/dolt/commands/cnfcmds"
"github.com/dolthub/dolt/go/cmd/dolt/commands/credcmds"
"github.com/dolthub/dolt/go/cmd/dolt/commands/cvcmds"
"github.com/dolthub/dolt/go/cmd/dolt/commands/docscmds"
"github.com/dolthub/dolt/go/cmd/dolt/commands/indexcmds"
"github.com/dolthub/dolt/go/cmd/dolt/commands/schcmds"
"github.com/dolthub/dolt/go/cmd/dolt/commands/sqlserver"
- "github.com/dolthub/dolt/go/cmd/dolt/commands/stashcmds"
- "github.com/dolthub/dolt/go/cmd/dolt/commands/tblcmds"
+ "github.com/dolthub/dolt/go/cmd/dolt/doltcmd"
"github.com/dolthub/dolt/go/cmd/dolt/doltversion"
"github.com/dolthub/dolt/go/libraries/doltcore/dbfactory"
"github.com/dolthub/dolt/go/libraries/doltcore/dconfig"
@@ -60,6 +58,7 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/env"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dfunctions"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
+ "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dtables"
"github.com/dolthub/dolt/go/libraries/events"
"github.com/dolthub/dolt/go/libraries/utils/argparser"
"github.com/dolthub/dolt/go/libraries/utils/config"
@@ -71,65 +70,6 @@ import (
var dumpDocsCommand = &commands.DumpDocsCmd{}
var dumpZshCommand = &commands.GenZshCompCmd{}
-var doltSubCommands = []cli.Command{
- commands.InitCmd{},
- commands.StatusCmd{},
- commands.AddCmd{},
- commands.DiffCmd{},
- commands.ResetCmd{},
- commands.CleanCmd{},
- commands.CommitCmd{},
- commands.SqlCmd{VersionStr: doltversion.Version},
- admin.Commands,
- sqlserver.SqlServerCmd{VersionStr: doltversion.Version},
- commands.LogCmd{},
- commands.ShowCmd{},
- commands.BranchCmd{},
- commands.CheckoutCmd{},
- commands.MergeCmd{},
- cnfcmds.Commands,
- commands.CherryPickCmd{},
- commands.RevertCmd{},
- commands.CloneCmd{},
- commands.FetchCmd{},
- commands.PullCmd{},
- commands.PushCmd{},
- commands.ConfigCmd{},
- commands.RemoteCmd{},
- commands.BackupCmd{},
- commands.LoginCmd{},
- credcmds.Commands,
- commands.LsCmd{},
- schcmds.Commands,
- tblcmds.Commands,
- commands.TagCmd{},
- commands.BlameCmd{},
- cvcmds.Commands,
- commands.SendMetricsCmd{},
- commands.MigrateCmd{},
- indexcmds.Commands,
- commands.ReadTablesCmd{},
- commands.GarbageCollectionCmd{},
- commands.FsckCmd{},
- commands.FilterBranchCmd{},
- commands.MergeBaseCmd{},
- commands.RootsCmd{},
- commands.VersionCmd{VersionStr: doltversion.Version},
- commands.DumpCmd{},
- commands.InspectCmd{},
- dumpDocsCommand,
- dumpZshCommand,
- docscmds.Commands,
- stashcmds.StashCommands,
- &commands.Assist{},
- commands.ProfileCmd{},
- commands.QueryDiff{},
- commands.ReflogCmd{},
- commands.RebaseCmd{},
- commands.ArchiveCmd{},
- ci.Commands,
-}
-
var commandsWithoutCliCtx = []cli.Command{
admin.Commands,
commands.CloneCmd{},
@@ -204,7 +144,7 @@ func needsWriteAccess(commandName string) bool {
return true
}
-var doltCommand = cli.NewSubCommandHandler("dolt", "it's git for data", doltSubCommands)
+var doltCommand = doltcmd.DoltCommand
var globalArgParser = cli.CreateGlobalArgParser("dolt")
var globalDocs = cli.CommandDocsForCommandString("dolt", doc, globalArgParser)
@@ -226,6 +166,8 @@ func init() {
if _, ok := os.LookupEnv(disableEventFlushEnvVar); ok {
eventFlushDisabled = true
}
+
+ dtables.DoltCommand = doltCommand
}
const pprofServerFlag = "--pprof-server"
diff --git a/go/cmd/dolt/doltcmd/doltcmd.go b/go/cmd/dolt/doltcmd/doltcmd.go
new file mode 100644
index 00000000000..1b00ad7d229
--- /dev/null
+++ b/go/cmd/dolt/doltcmd/doltcmd.go
@@ -0,0 +1,120 @@
+// Copyright 2025 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 doltcmd
+
+import (
+ "github.com/dolthub/dolt/go/cmd/dolt/cli"
+ "github.com/dolthub/dolt/go/cmd/dolt/commands"
+ "github.com/dolthub/dolt/go/cmd/dolt/commands/admin"
+ "github.com/dolthub/dolt/go/cmd/dolt/commands/ci"
+ "github.com/dolthub/dolt/go/cmd/dolt/commands/cnfcmds"
+ "github.com/dolthub/dolt/go/cmd/dolt/commands/credcmds"
+ "github.com/dolthub/dolt/go/cmd/dolt/commands/cvcmds"
+ "github.com/dolthub/dolt/go/cmd/dolt/commands/docscmds"
+ "github.com/dolthub/dolt/go/cmd/dolt/commands/indexcmds"
+ "github.com/dolthub/dolt/go/cmd/dolt/commands/schcmds"
+ "github.com/dolthub/dolt/go/cmd/dolt/commands/sqlserver"
+ "github.com/dolthub/dolt/go/cmd/dolt/commands/stashcmds"
+ "github.com/dolthub/dolt/go/cmd/dolt/commands/tblcmds"
+ "github.com/dolthub/dolt/go/cmd/dolt/doltversion"
+)
+
+var dumpDocsCommand = &commands.DumpDocsCmd{}
+var dumpZshCommand = &commands.GenZshCompCmd{}
+
+var doltSubCommands = []cli.Command{
+ commands.InitCmd{},
+ commands.StatusCmd{},
+ commands.AddCmd{},
+ commands.DiffCmd{},
+ commands.ResetCmd{},
+ commands.CleanCmd{},
+ commands.CommitCmd{},
+ commands.SqlCmd{VersionStr: doltversion.Version},
+ admin.Commands,
+ sqlserver.SqlServerCmd{VersionStr: doltversion.Version},
+ commands.LogCmd{},
+ commands.ShowCmd{},
+ commands.BranchCmd{},
+ commands.CheckoutCmd{},
+ commands.MergeCmd{},
+ cnfcmds.Commands,
+ commands.CherryPickCmd{},
+ commands.RevertCmd{},
+ commands.CloneCmd{},
+ commands.FetchCmd{},
+ commands.PullCmd{},
+ commands.PushCmd{},
+ commands.ConfigCmd{},
+ commands.RemoteCmd{},
+ commands.BackupCmd{},
+ commands.LoginCmd{},
+ credcmds.Commands,
+ commands.LsCmd{},
+ schcmds.Commands,
+ tblcmds.Commands,
+ commands.TagCmd{},
+ commands.BlameCmd{},
+ cvcmds.Commands,
+ commands.SendMetricsCmd{},
+ commands.MigrateCmd{},
+ indexcmds.Commands,
+ commands.ReadTablesCmd{},
+ commands.GarbageCollectionCmd{},
+ commands.FsckCmd{},
+ commands.FilterBranchCmd{},
+ commands.MergeBaseCmd{},
+ commands.RootsCmd{},
+ commands.VersionCmd{VersionStr: doltversion.Version},
+ commands.DumpCmd{},
+ commands.InspectCmd{},
+ dumpDocsCommand,
+ dumpZshCommand,
+ docscmds.Commands,
+ stashcmds.StashCommands,
+ &commands.Assist{},
+ commands.ProfileCmd{},
+ commands.QueryDiff{},
+ commands.ReflogCmd{},
+ commands.RebaseCmd{},
+ commands.ArchiveCmd{},
+ ci.Commands,
+}
+
+var DoltCommand = cli.NewSubCommandHandler("dolt", "it's git for data", doltSubCommands)
+
+var globalArgParser = cli.CreateGlobalArgParser("dolt")
+
+var doc = cli.CommandDocumentationContent{
+ ShortDesc: "Dolt is git for data",
+ LongDesc: `Dolt comprises of multiple subcommands that allow users to import, export, update, and manipulate data with SQL.`,
+
+ Synopsis: []string{
+ "[global flags] subcommand [subcommand arguments]",
+ },
+}
+var globalDocs = cli.CommandDocsForCommandString("dolt", doc, globalArgParser)
+
+var globalSpecialMsg = `
+Dolt subcommands are in transition to using the flags listed below as global flags.
+Not all subcommands use these flags. If your command accepts these flags without error, then they are supported.
+`
+
+func init() {
+ dumpDocsCommand.DoltCommand = DoltCommand
+ dumpDocsCommand.GlobalDocs = globalDocs
+ dumpDocsCommand.GlobalSpecialMsg = globalSpecialMsg
+ dumpZshCommand.DoltCommand = DoltCommand
+}
diff --git a/go/libraries/doltcore/doltdb/system_table.go b/go/libraries/doltcore/doltdb/system_table.go
index 7f560799022..e3eae4ea1c2 100644
--- a/go/libraries/doltcore/doltdb/system_table.go
+++ b/go/libraries/doltcore/doltdb/system_table.go
@@ -217,6 +217,7 @@ var getGeneratedSystemTables = func() []string {
GetCommitAncestorsTableName(),
GetStatusTableName(),
GetRemotesTableName(),
+ GetHelpTableName(),
}
}
@@ -380,6 +381,11 @@ var GetTagsTableName = func() string {
return TagsTableName
}
+// GetHelpTableName returns the help table name
+var GetHelpTableName = func() string {
+ return HelpTableName
+}
+
const (
// LogTableName is the log system table name
LogTableName = "dolt_log"
@@ -585,3 +591,7 @@ const (
// was originally defined. Mode settings, such as ANSI_QUOTES, are needed to correctly parse the fragment.
ProceduresTableSqlModeCol = "sql_mode"
)
+
+const (
+ HelpTableName = "dolt_help"
+)
diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go
index 390f2e0c384..8f2c3fba880 100644
--- a/go/libraries/doltcore/sqle/database.go
+++ b/go/libraries/doltcore/sqle/database.go
@@ -714,6 +714,14 @@ func (db Database) getTableInsensitive(ctx *sql.Context, head *doltdb.Commit, ds
return nil, false, err
}
dt = NewSchemaTable(backingTable)
+ case doltdb.GetHelpTableName(), doltdb.HelpTableName:
+ isDoltgresSystemTable, err := resolve.IsDoltgresSystemTable(ctx, tname, root)
+ if err != nil {
+ return nil, false, err
+ }
+ if !resolve.UseSearchPath || isDoltgresSystemTable {
+ dt, found = dtables.NewHelpTable(ctx, db.Name(), lwrName), true
+ }
}
if found {
diff --git a/go/libraries/doltcore/sqle/dtables/help_table.go b/go/libraries/doltcore/sqle/dtables/help_table.go
new file mode 100644
index 00000000000..d7a70967c01
--- /dev/null
+++ b/go/libraries/doltcore/sqle/dtables/help_table.go
@@ -0,0 +1,225 @@
+// Copyright 2025 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 dtables
+
+import (
+ "encoding/json"
+ "io"
+ "strings"
+
+ "github.com/dolthub/dolt/go/cmd/dolt/cli"
+ "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dprocedures"
+ "github.com/dolthub/dolt/go/libraries/doltcore/sqle/index"
+ "github.com/dolthub/go-mysql-server/sql"
+ sqlTypes "github.com/dolthub/go-mysql-server/sql/types"
+)
+
+type HelpTable struct {
+ dbName string
+ tableName string
+}
+
+var HelpTableTypes = []string{
+ "system_table",
+ "procedure",
+ "function",
+ "variable",
+}
+
+// NewHelpTable creates a HelpTable
+func NewHelpTable(_ *sql.Context, dbName, tableName string) sql.Table {
+ return &HelpTable{dbName: dbName, tableName: tableName}
+}
+
+// Name is a sql.Table interface function which returns the name of the table.
+func (ht *HelpTable) Name() string {
+ return ht.tableName
+}
+
+// String is a sql.Table interface function which returns the name of the table.
+func (ht *HelpTable) String() string {
+ return ht.tableName
+}
+
+// Schema is a sql.Table interface function that gets the sql.Schema of the help system table.
+func (ht *HelpTable) Schema() sql.Schema {
+ return []*sql.Column{
+ {
+ Name: "name",
+ Type: sqlTypes.TinyText,
+ Source: ht.tableName,
+ PrimaryKey: true,
+ DatabaseSource: ht.dbName,
+ },
+ {
+ Name: "type",
+ Type: sqlTypes.MustCreateEnumType(HelpTableTypes, sql.Collation_Default),
+ Source: ht.tableName,
+ PrimaryKey: false,
+ DatabaseSource: ht.dbName,
+ },
+ {
+ Name: "synopsis",
+ Type: sqlTypes.LongText,
+ Source: ht.tableName,
+ PrimaryKey: false,
+ DatabaseSource: ht.dbName,
+ },
+ {
+ Name: "short_description",
+ Type: sqlTypes.LongText,
+ Source: ht.tableName,
+ PrimaryKey: false,
+ DatabaseSource: ht.dbName,
+ },
+ {
+ Name: "long_description",
+ Type: sqlTypes.LongText,
+ Source: ht.tableName,
+ PrimaryKey: false,
+ DatabaseSource: ht.dbName,
+ },
+ {
+ Name: "arguments",
+ Type: sqlTypes.JSON,
+ Source: ht.tableName,
+ PrimaryKey: false,
+ DatabaseSource: ht.dbName,
+ },
+ }
+}
+
+// Collation implements the sql.Table interface.
+func (ht *HelpTable) Collation() sql.CollationID {
+ return sql.Collation_Default
+}
+
+// Partitions is a sql.Table interface function that returns a partition
+// of the data. Currently the data is unpartitioned.
+func (ht *HelpTable) Partitions(*sql.Context) (sql.PartitionIter, error) {
+ return index.SinglePartitionIterFromNomsMap(nil), nil
+}
+
+// PartitionRows is a sql.Table interface function that gets a row iterator for a partition.
+func (ht *HelpTable) PartitionRows(_ *sql.Context, _ sql.Partition) (sql.RowIter, error) {
+ return NewHelpRowIter(), nil
+}
+
+type HelpRowIter struct {
+ idx int
+ rows []sql.Row
+}
+
+func NewHelpRowIter() *HelpRowIter {
+ return &HelpRowIter{}
+}
+
+// DoltCommand is set in cmd/dolt/dolt.go to avoid circular dependency.
+var DoltCommand cli.SubCommandHandler
+
+func (itr *HelpRowIter) Next(_ *sql.Context) (sql.Row, error) {
+ if itr.rows == nil {
+ var err error
+ itr.rows, err = generateProcedureHelpRows(DoltCommand.Name(), DoltCommand)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if itr.idx >= len(itr.rows) {
+ return nil, io.EOF
+ }
+
+ row := itr.rows[itr.idx]
+ itr.idx++
+
+ return row, nil
+}
+
+func (itr *HelpRowIter) Close(_ *sql.Context) error {
+ return nil
+}
+
+// generateProcedureHelpRows generates a sql row for each procedure that has an equivalent CLI command.
+func generateProcedureHelpRows(cmdStr string, cmd cli.Command) ([]sql.Row, error) {
+ if hidCmd, ok := cmd.(cli.HiddenCommand); ok && hidCmd.Hidden() {
+ return []sql.Row{}, nil
+ }
+
+ rows := []sql.Row{}
+
+ procedureName := strings.ReplaceAll(cmdStr, "-", "_")
+ docs := cmd.Docs()
+ if procedureExists(procedureName) && docs != nil {
+ argsMap := map[string]string{}
+ for _, usage := range cli.OptionsUsageList(docs.ArgParser, cli.EmptyFormat) {
+ argsMap[usage[0]] = usage[1]
+ }
+
+ argsJson, err := json.Marshal(argsMap)
+ if err != nil {
+ return nil, err
+ }
+
+ synopsis, err := docs.GetSynopsis(cli.CliFormat)
+ if err != nil {
+ return nil, err
+ }
+
+ synopsisWithCommand := make([]string, len(synopsis))
+ cliName := strings.ReplaceAll(cmdStr, "_", " ")
+ for i := range synopsis {
+ synopsisWithCommand[i] = cliName + " " + synopsis[i]
+ }
+
+ shortDesc := docs.GetShortDesc()
+
+ longDesc, err := docs.GetLongDesc(cli.CliFormat)
+ if err != nil {
+ return nil, err
+ }
+
+ rows = append(rows, sql.NewRow(
+ procedureName,
+ "procedure",
+ strings.Join(synopsisWithCommand, "\n"),
+ shortDesc,
+ longDesc,
+ string(argsJson),
+ ))
+ }
+
+ if subCmdHandler, ok := cmd.(cli.SubCommandHandler); ok {
+ for _, subCmd := range subCmdHandler.Subcommands {
+ newRows, err := generateProcedureHelpRows(cmdStr+"_"+subCmd.Name(), subCmd)
+ if err != nil {
+ return nil, err
+ }
+ rows = append(rows, newRows...)
+ }
+ }
+
+ return rows, nil
+}
+
+// procedureExists returns whether |procedureName| is the name of a dolt procedure.
+func procedureExists(procedureName string) bool {
+ for _, procedure := range dprocedures.DoltProcedures {
+ if procedure.Name == procedureName {
+ return true
+ }
+ }
+ return false
+}
diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go
index 20043743b26..713c0dfa328 100644
--- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go
+++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go
@@ -2052,3 +2052,9 @@ func TestDoltWorkspace(t *testing.T) {
harness := newDoltEnginetestHarness(t)
RunDoltWorkspaceTests(t, harness)
}
+
+func TestDoltHelpSystemTable(t *testing.T) {
+ harness := newDoltHarness(t)
+ defer harness.Close()
+ RunDoltHelpSystemTableTests(t, harness)
+}
diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go
index 0e83de5cca9..efd221635f4 100755
--- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go
+++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go
@@ -35,10 +35,12 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/dolthub/dolt/go/cmd/dolt/doltcmd"
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
+ "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dtables"
"github.com/dolthub/dolt/go/store/datas"
"github.com/dolthub/dolt/go/store/types"
)
@@ -1985,3 +1987,15 @@ func RunDoltWorkspaceTests(t *testing.T, h DoltEnginetestHarness) {
}()
}
}
+
+func RunDoltHelpSystemTableTests(t *testing.T, harness DoltEnginetestHarness) {
+ dtables.DoltCommand = doltcmd.DoltCommand
+
+ for _, script := range DoltHelpScripts {
+ t.Run(script.Name, func(t *testing.T) {
+ harness = harness.NewHarness(t)
+ defer harness.Close()
+ enginetest.TestScript(t, harness, script)
+ })
+ }
+}
diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go
index 7197c182af0..fd0aa37e0c3 100644
--- a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go
+++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go
@@ -7565,6 +7565,7 @@ var DoltSystemVariables = []queries.ScriptTest{
{"dolt_constraint_violations"},
{"dolt_constraint_violations_test"},
{"dolt_diff_test"},
+ {"dolt_help"},
{"dolt_history_test"},
{"dolt_log"},
{"dolt_remote_branches"},
diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries_help.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries_help.go
new file mode 100644
index 00000000000..6862ec1a5dc
--- /dev/null
+++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries_help.go
@@ -0,0 +1,191 @@
+// Copyright 2024 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 enginetest
+
+import (
+ "github.com/dolthub/go-mysql-server/enginetest/queries"
+ "github.com/dolthub/go-mysql-server/sql"
+)
+
+var DoltHelpScripts = []queries.ScriptTest{
+ {
+ Name: "dolt_help arguments are valid json",
+ SetUpScript: []string{},
+ Query: "select * from dolt_help where json_valid(arguments)=false;",
+ Expected: []sql.Row{},
+ },
+ {
+ Name: "dolt_help synopsis remains the same after multiple queries",
+ SetUpScript: []string{
+ "set @InitialSynopsis=(select synopsis from dolt_help where name='dolt_branch')",
+ },
+ Query: "select * from dolt_help where name='dolt_branch' and synopsis!=@InitialSynopsis",
+ Expected: []sql.Row{},
+ },
+ {
+ Name: "dolt_help names are correct",
+ SetUpScript: []string{},
+ Query: "select name from dolt_help",
+ Expected: []sql.Row{
+ {"dolt_add"},
+ {"dolt_reset"},
+ {"dolt_clean"},
+ {"dolt_commit"},
+ {"dolt_branch"},
+ {"dolt_checkout"},
+ {"dolt_merge"},
+ {"dolt_conflicts_resolve"},
+ {"dolt_cherry_pick"},
+ {"dolt_revert"},
+ {"dolt_clone"},
+ {"dolt_fetch"},
+ {"dolt_pull"},
+ {"dolt_push"},
+ {"dolt_remote"},
+ {"dolt_backup"},
+ {"dolt_tag"},
+ {"dolt_gc"},
+ {"dolt_rebase"},
+ },
+ },
+ {
+ Name: "dolt_help types are correct",
+ SetUpScript: []string{},
+ Assertions: []queries.ScriptTestAssertion{
+ {
+ Query: "select type from dolt_help where name='dolt_rebase'",
+ Expected: []sql.Row{
+ {"procedure"},
+ },
+ },
+ {
+ Query: "select type from dolt_help where name='dolt_gc'",
+ Expected: []sql.Row{
+ {"procedure"},
+ },
+ },
+ {
+ Query: "select type from dolt_help where name='dolt_tag'",
+ Expected: []sql.Row{
+ {"procedure"},
+ },
+ },
+ },
+ },
+ {
+ Name: "dolt_help synopses are correct",
+ SetUpScript: []string{},
+ Assertions: []queries.ScriptTestAssertion{
+ {
+ Query: "select count(*) from dolt_help where name='dolt_conflicts_resolve' and synopsis like '%dolt conflicts resolve%table%'",
+ Expected: []sql.Row{
+ {1},
+ },
+ },
+ {
+ Query: "select count(*) from dolt_help where name='dolt_merge' and synopsis like '%dolt merge%branch%'",
+ Expected: []sql.Row{
+ {1},
+ },
+ },
+ {
+ Query: "select count(*) from dolt_help where name='dolt_branch' and synopsis like '%dolt branch%--list%'",
+ Expected: []sql.Row{
+ {1},
+ },
+ },
+ },
+ },
+ {
+ Name: "dolt_help short descriptions are correct",
+ SetUpScript: []string{},
+ Assertions: []queries.ScriptTestAssertion{
+ {
+ Query: "select short_description from dolt_help where name='dolt_clean'",
+ Expected: []sql.Row{
+ {"Deletes untracked working tables"},
+ },
+ },
+ {
+ Query: "select short_description from dolt_help where name='dolt_checkout'",
+ Expected: []sql.Row{
+ {"Switch branches or restore working tree tables"},
+ },
+ },
+ {
+ Query: "select short_description from dolt_help where name='dolt_fetch'",
+ Expected: []sql.Row{
+ {"Download objects and refs from another repository"},
+ },
+ },
+ },
+ },
+
+ {
+ Name: "dolt_help long descriptions are correct",
+ SetUpScript: []string{},
+ Assertions: []queries.ScriptTestAssertion{
+ {
+ Query: "select count(*) from dolt_help where name='dolt_add' and long_description like '%updates the list of tables%'",
+ Expected: []sql.Row{
+ {1},
+ },
+ },
+ {
+ Query: "select count(*) from dolt_help where name='dolt_cherry_pick' and long_description like '%Applies the changes from an existing commit%'",
+ Expected: []sql.Row{
+ {1},
+ },
+ },
+ {
+ Query: "select count(*) from dolt_help where name='dolt_revert' and long_description like '%Removes the changes made in a commit%'",
+ Expected: []sql.Row{
+ {1},
+ },
+ },
+ },
+ },
+
+ {
+ Name: "dolt_help arguments are correct",
+ SetUpScript: []string{},
+ Assertions: []queries.ScriptTestAssertion{
+ {
+ Query: "select count(*) from dolt_help where name='dolt_commit' and arguments like '%--amend%Amend previous commit%'",
+ Expected: []sql.Row{
+ {1},
+ },
+ },
+ {
+ Query: "select count(*) from dolt_help where name='dolt_commit' and arguments like '%--skip-empty%Only create a commit if there are staged changes%'",
+ Expected: []sql.Row{
+ {1},
+ },
+ },
+ {
+ Query: "select count(*) from dolt_help where name='dolt_rebase' and arguments like '%--continue%Continue an interactive rebase%'",
+ Expected: []sql.Row{
+ {1},
+ },
+ },
+ {
+ Query: "select count(*) from dolt_help where name='dolt_revert' and arguments like '%--author%Specify an explicit author%'",
+ Expected: []sql.Row{
+ {1},
+ },
+ },
+ },
+ },
+}
diff --git a/integration-tests/bats/ls.bats b/integration-tests/bats/ls.bats
index 6841f4d3749..28f3c53eeb6 100755
--- a/integration-tests/bats/ls.bats
+++ b/integration-tests/bats/ls.bats
@@ -60,7 +60,7 @@ teardown() {
@test "ls: --system shows system tables" {
run dolt ls --system
[ "$status" -eq 0 ]
- [ "${#lines[@]}" -eq 22 ]
+ [ "${#lines[@]}" -eq 23 ]
[[ "$output" =~ "System tables:" ]] || false
[[ "$output" =~ "dolt_status" ]] || false
[[ "$output" =~ "dolt_commits" ]] || false
@@ -71,6 +71,7 @@ teardown() {
[[ "$output" =~ "dolt_remotes" ]] || false
[[ "$output" =~ "dolt_branches" ]] || false
[[ "$output" =~ "dolt_remote_branches" ]] || false
+ [[ "$output" =~ "dolt_help" ]] || false
[[ "$output" =~ "dolt_constraint_violations_table_one" ]] || false
[[ "$output" =~ "dolt_history_table_one" ]] || false
[[ "$output" =~ "dolt_conflicts_table_one" ]] || false
diff --git a/integration-tests/bats/system-tables.bats b/integration-tests/bats/system-tables.bats
index 95e0455f298..5ed19accf29 100644
--- a/integration-tests/bats/system-tables.bats
+++ b/integration-tests/bats/system-tables.bats
@@ -36,6 +36,7 @@ teardown() {
[[ "$output" =~ "dolt_remote_branches" ]] || false
[[ "$output" =~ "dolt_remotes" ]] || false
[[ "$output" =~ "dolt_status" ]] || false
+ [[ "$output" =~ "dolt_help" ]] || false
[[ "$output" =~ "test" ]] || false
dolt add test
@@ -620,3 +621,33 @@ SQL
[ "$status" -eq 0 ]
[ "$output" = "" ]
}
+
+@test "system-tables: query dolt_help system table" {
+ run dolt sql -q "select type from dolt_help where name='dolt_rebase'"
+ [ "$status" -eq 0 ]
+ [[ "$output" =~ "procedure" ]] || false
+
+ run dolt sql -q "select synopsis from dolt_help where name='dolt_backup'"
+ [ "$status" -eq 0 ]
+ [[ "$output" =~ "dolt backup [-v | --verbose]" ]] || false
+ [[ "$output" =~ "dolt backup restore [--force] " ]] || false
+
+ run dolt sql -q "select short_description from dolt_help where name='dolt_commit'"
+ [ "$status" -eq 0 ]
+ [[ "$output" =~ "Record changes to the database" ]] || false
+
+ run dolt sql -q "select long_description from dolt_help where name='dolt_add'"
+ [ "$status" -eq 0 ]
+ [[ "$output" =~ "This command updates the list of tables using the current content found in the working root" ]] || false
+ [[ "$output" =~ "This command can be performed multiple times before a commit." ]] || false
+
+ run dolt sql -q "select arguments from dolt_help where name='dolt_pull'"
+ [ "$status" -eq 0 ]
+ [[ "$output" =~ "".*"The name of the remote to pull from." ]] || false
+ [[ "$output" =~ "".*"The name of a branch on the specified remote to be merged into the current working set." ]] || false
+ [[ "$output" =~ "-f, --force".*"Update from the remote HEAD even if there are errors." ]] || false
+
+ run dolt sql -q "select arguments from dolt_help where name='dolt_tag'"
+ [ "$status" -eq 0 ]
+ [[ "$output" =~ "-m , --message=".*"Use the given msg as the tag message." ]] || false
+}