Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci-compatibility-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ jobs:
working-directory: ./integration-tests/compatibility
env:
DOLT_USE_ADAPTIVE_ENCODING: ${{ matrix.adaptive_encoding }}
BATS_PRINT_OUTPUT_ON_FAILURE: "1"
2 changes: 1 addition & 1 deletion go/cmd/dolt/commands/assist.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ func getInitialPrompt(ctx *sql.Context, sqlEngine *engine.SqlEngine, dEnv *env.D
return nil, err
}

responseJson, err = json.Marshal(map[string]string{"action": "ANSWER", "content": fmt.Sprintf("The most recent commit was written by %s", cm.Name)})
responseJson, err = json.Marshal(map[string]string{"action": "ANSWER", "content": fmt.Sprintf("The most recent commit was written by %s", cm.Author.Name)})
if err != nil {
return nil, err
}
Expand Down
35 changes: 19 additions & 16 deletions go/cmd/dolt/commands/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ func performCommit(ctx context.Context, commandStr string, args []string, cliCtx
}

commit, err := getCommitInfo(queryist.Context, queryist.Queryist, "HEAD")
if err != nil {
cli.Printf("Commit completed, but failure to get commit details occurred: %s\n", err.Error())
return 0, false
}
if cli.ExecuteWithStdioRestored != nil {
cli.ExecuteWithStdioRestored(func() {
pager := outputpager.Start()
Expand All @@ -186,8 +190,11 @@ func performCommit(ctx context.Context, commandStr string, args []string, cliCtx
return 0, false
}

// constructParametrizedDoltCommitQuery generates the sql query necessary to call the DOLT_COMMIT() stored procedure with placeholders
// for arg input. Also returns a list of the inputs in the order in which they appear in the query.
// constructParametrizedDoltCommitQuery builds the CALL DOLT_COMMIT query the CLI sends to the
// engine, returning the query text with placeholders and the ordered parameter list. |msg| is
// the commit message and |apr| supplies the parsed CLI flags. When --author is not passed,
// the server resolves author and committer from the identity session variables on the
// connection. Returns an error when |cliCtx| has no configured user.name or user.email.
func constructParametrizedDoltCommitQuery(msg string, apr *argparser.ArgParseResults, cliCtx cli.CliContext) (string, []interface{}, error) {
var params []interface{}
var param bool
Expand Down Expand Up @@ -235,20 +242,16 @@ func constructParametrizedDoltCommitQuery(msg string, apr *argparser.ArgParseRes
writeToBuffer("-f")
}

writeToBuffer("--author")
param = true
writeToBuffer("?")
var author string
if _, _, err := env.GetNameAndEmail(cliCtx.Config()); err != nil {
return "", nil, err
}
if apr.Contains(cli.AuthorParam) {
author, _ = apr.GetValue(cli.AuthorParam)
} else {
name, email, err := env.GetNameAndEmail(cliCtx.Config())
if err != nil {
return "", nil, err
}
author = name + " <" + email + ">"
writeToBuffer("--author")
param = true
writeToBuffer("?")
author, _ := apr.GetValue(cli.AuthorParam)
params = append(params, author)
}
params = append(params, author)

if apr.Contains(cli.AllFlag) {
writeToBuffer("-a")
Expand Down Expand Up @@ -291,15 +294,15 @@ func handleCommitErr(sqlCtx *sql.Context, queryist cli.Queryist, err error, usag
return 0
}

if err == datas.ErrNameNotConfigured {
if datas.ErrNameNotConfigured.Is(err) {
bdr := errhand.BuildDError("Could not determine %s.", config.UserNameKey)
bdr.AddDetails("Log into DoltHub: dolt login")
bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", config.UserNameKey)

return HandleVErrAndExitCode(bdr.Build(), usage)
}

if err == datas.ErrEmailNotConfigured {
if datas.ErrEmailNotConfigured.Is(err) {
bdr := errhand.BuildDError("Could not determine %s.", config.UserEmailKey)
bdr.AddDetails("Log into DoltHub: dolt login")
bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", config.UserEmailKey)
Expand Down
91 changes: 91 additions & 0 deletions go/cmd/dolt/commands/engine/sqlengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package engine

import (
"context"
"fmt"
"maps"
"os"
"strconv"
Expand Down Expand Up @@ -595,6 +596,96 @@ func doltSessionFactory(
}
}

var ErrFailedToInitCommitIdent = fmt.Errorf("failed to initialize commit identity session variables from environment")

// envSessionVar pairs an environment variable with the session variable it populates when non-empty.
type envSessionVar struct {
envVar string
sessionVar string
}

// commitIdentEnvOverrides lists the DOLT_AUTHOR_* and DOLT_COMMITTER_* environment variables
// that [InitCommitIdentSessionConfig] maps to their corresponding session variables.
var commitIdentEnvOverrides = []envSessionVar{
{dconfig.EnvDoltAuthorName, dsess.DoltAuthorName},
{dconfig.EnvDoltAuthorEmail, dsess.DoltAuthorEmail},
{dconfig.EnvDoltAuthorDate, dsess.DoltAuthorDate},
{dconfig.EnvDoltCommitterName, dsess.DoltCommitterName},
{dconfig.EnvDoltCommitterEmail, dsess.DoltCommitterEmail},
{dconfig.EnvDoltCommitterDate, dsess.DoltCommitterDate},
}

// InitCommitIdentSessionConfig seeds the DOLT_ author and committer session variables on the
// current session so later DOLT_COMMIT calls attribute the commit correctly. |name| and |email|
// supply the default identity for both author and committer; any non-empty DOLT_AUTHOR_* or
// DOLT_COMMITTER_* environment variable overrides the matching field. Must run after
// [sql.SessionCommandBegin] so the session is ready to accept SET statements. Silently skips
// variables not recognised by |queryist|, so older servers remain usable.
func InitCommitIdentSessionConfig(queryist cli.Queryist, sqlCtx *sql.Context, name, email string) error {
sessionVars := map[string]string{
dsess.DoltAuthorName: name,
dsess.DoltAuthorEmail: email,
dsess.DoltCommitterName: name,
dsess.DoltCommitterEmail: email,
}

for _, pair := range commitIdentEnvOverrides {
if val := os.Getenv(pair.envVar); val != "" {
sessionVars[pair.sessionVar] = val
}
}

var showQuery strings.Builder
showQuery.WriteString("SHOW VARIABLES WHERE Variable_name IN (")
hasVariableNames := false
for variableName, value := range sessionVars {
if value == "" {
continue
}
if hasVariableNames {
showQuery.WriteByte(',')
}
showQuery.WriteByte('\'')
showQuery.WriteString(variableName)
showQuery.WriteByte('\'')
hasVariableNames = true
}
if !hasVariableNames {
return nil
}
showQuery.WriteByte(')')
variableRows, err := cli.GetRowsForSql(queryist, sqlCtx, showQuery.String())
if err != nil {
return fmt.Errorf("%w: %v", ErrFailedToInitCommitIdent, err)
}

var setStatement strings.Builder
setStatement.WriteString("SET ")
hasAssignments := false
for _, row := range variableRows {
variableName, ok := row[0].(string)
if !ok {
continue
}
value, ok := sessionVars[strings.ToLower(variableName)]
if !ok {
continue
}
if hasAssignments {
setStatement.WriteString(", ")
}
fmt.Fprintf(&setStatement, "@@SESSION.%s = %q", variableName, value)
hasAssignments = true
}
if !hasAssignments {
return nil
}
if _, _, _, err := queryist.Query(sqlCtx, setStatement.String()); err != nil {
return fmt.Errorf("%w: %v", ErrFailedToInitCommitIdent, err)
}
return nil
}

type ConfigOption func(*SqlEngineConfig)

// NewSqlEngineForEnv returns a SqlEngine configured for the environment provided, with a single root user.
Expand Down
2 changes: 1 addition & 1 deletion go/cmd/dolt/commands/log_graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ func printCommitMetadata(graph [][]string, pager *outputpager.Pager, row, col in
printLine(graph, col, row+1, pager, color.WhiteString("Merge: %s", strings.Join(commit.Commit.parentHashes, " ")), commit.Commit, "no")
}

printLine(graph, col, row+1+printMergeInfo, pager, color.WhiteString("Author: %s <%s>", commit.Commit.commitMeta.Name, commit.Commit.commitMeta.Email), commit.Commit, "no")
printLine(graph, col, row+1+printMergeInfo, pager, color.WhiteString("Author: %s <%s>", commit.Commit.commitMeta.Author.Name, commit.Commit.commitMeta.Author.Email), commit.Commit, "no")

printLine(graph, col, row+2+printMergeInfo, pager, color.WhiteString("Date: %s", commit.Commit.commitMeta.FormatTS()), commit.Commit, "no")

Expand Down
4 changes: 2 additions & 2 deletions go/cmd/dolt/commands/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestLog(t *testing.T) {
commit, _ := opt.ToCommit()

meta, _ := commit.GetCommitMeta(context.Background())
require.Equal(t, "Bill Billerson", meta.Name)
require.Equal(t, "Bill Billerson", meta.Author.Name)
}

func TestLogSigterm(t *testing.T) {
Expand Down Expand Up @@ -79,7 +79,7 @@ func TestLogSigterm(t *testing.T) {

for i := 0; i < 5; i++ {
pager.Writer.Write([]byte(fmt.Sprintf("\033[1;33mcommit %s \033[0m", chStr)))
pager.Writer.Write([]byte(fmt.Sprintf("\nAuthor: %s <%s>", cMeta.Name, cMeta.Email)))
pager.Writer.Write([]byte(fmt.Sprintf("\nAuthor: %s <%s>", cMeta.Author.Name, cMeta.Author.Email)))

timeStr := cMeta.FormatTS()
pager.Writer.Write([]byte(fmt.Sprintf("\nDate: %s", timeStr)))
Expand Down
1 change: 0 additions & 1 deletion go/cmd/dolt/commands/revert.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ func revert(ctx context.Context, apr *argparser.ArgParseResults, cliCtx cli.CliC
return 0
}

// Check conflict counts from the result row.
if len(rows) > 0 {
row := rows[0]
dataConflicts, err := cli.QueryValueAsInt64(row[1])
Expand Down
20 changes: 5 additions & 15 deletions go/cmd/dolt/commands/schcmds/copy-tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
"github.com/dolthub/dolt/go/libraries/utils/argparser"
"github.com/dolthub/dolt/go/libraries/utils/config"
"github.com/dolthub/dolt/go/store/datas"
)

Expand Down Expand Up @@ -272,22 +271,13 @@ func doltCommitUpdatedTags(ctx *sql.Context, tableResolver doltdb.TableResolver,
workingSet = workingSet.WithWorkingRoot(workingRoot)
workingSet = workingSet.WithStagedRoot(workingRoot)

email, err := dEnv.Config.GetString(config.UserEmailKey)
if err != nil {
return err
}

name, err := dEnv.Config.GetString(config.UserNameKey)
doltDB := dEnv.DoltDB(ctx)
commitStagedProps, err := dsess.NewCommitStagedProps(ctx, "Syncing column tags from "+fromBranchName+" branch")
if err != nil {
return err
}

doltDB := dEnv.DoltDB(ctx)
pendingCommit, err := actions.GetCommitStaged(ctx, tableResolver, roots, workingSet, nil, doltDB, actions.CommitStagedProps{
Name: name,
Email: email,
Message: "Syncing column tags from " + fromBranchName + " branch",
})
pendingCommit, err := actions.GetCommitStaged(ctx, tableResolver, roots, workingSet, nil, doltDB, commitStagedProps)
if err != nil {
return err
}
Expand All @@ -302,8 +292,8 @@ func doltCommitUpdatedTags(ctx *sql.Context, tableResolver doltdb.TableResolver,
}

_, err = doltDB.CommitWithWorkingSet(ctx, headRef, workingSet.Ref(), pendingCommit, workingSet, prevHash, &datas.WorkingSetMeta{
Name: name,
Email: email,
Name: commitStagedProps.Committer.Name,
Email: commitStagedProps.Committer.Email,
}, nil)
return err
}
Expand Down
41 changes: 38 additions & 3 deletions go/cmd/dolt/commands/sqlserver/queryist_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
sql2 "database/sql"
"fmt"
"io"
"net"
"regexp"
"strings"

Expand All @@ -30,6 +31,7 @@ import (
"github.com/gocraft/dbr/v2/dialect"

"github.com/dolthub/dolt/go/cmd/dolt/cli"
"github.com/dolthub/dolt/go/cmd/dolt/commands/engine"
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
"github.com/dolthub/dolt/go/libraries/doltcore/servercfg"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/sqlutil"
Expand Down Expand Up @@ -61,9 +63,32 @@ const (
QueryistTLSMode_NoVerify_FallbackToPlaintext
)

// BuildConnectionStringQueryist returns a Queryist that connects to the server specified by the given server config. Presence in this
// module isn't ideal, but it's the only way to get the server config into the queryist.
func BuildConnectionStringQueryist(ctx context.Context, cwdFS filesys.Filesys, creds *cli.UserPassword, apr *argparser.ArgParseResults, host string, port int, tlsMode QueryistTLSMode, dbRev string) (cli.LateBindQueryist, error) {
// nameEmailFromCurrentUser queries CURRENT_USER() and returns the username as the name and
// the full user@host grant string as the email.
func nameEmailFromCurrentUser(queryist cli.Queryist, sqlCtx *sql.Context) (name, email string) {
_, rowIter, _, err := queryist.Query(sqlCtx, "SELECT CURRENT_USER()")
if err != nil {
return "", ""
}
defer rowIter.Close(sqlCtx)
row, err := rowIter.Next(sqlCtx)
if err != nil || len(row) == 0 || row[0] == nil {
return "", ""
}
currentUser, ok := row[0].(string)
if !ok {
return "", ""
}
name, _, _ = strings.Cut(currentUser, "@")
return name, currentUser
}

// BuildConnectionStringQueryist returns a [cli.LateBindQueryist] that opens a connection to the
// server at |host|:|port| using |creds| and |tlsMode|, and selects |dbRev| as the default
// database. |configName| and |configEmail| are used as the commit identity when the client
// connects over a loopback address; non-loopback connections read the identity from
// CURRENT_USER() so the grant host matches whatever the server assigned.
func BuildConnectionStringQueryist(_ context.Context, cwdFS filesys.Filesys, creds *cli.UserPassword, apr *argparser.ArgParseResults, host string, port int, tlsMode QueryistTLSMode, dbRev string, configName, configEmail string) (cli.LateBindQueryist, error) {
clientConfig, err := GetClientConfig(cwdFS, creds, apr)
if err != nil {
return nil, err
Expand Down Expand Up @@ -101,6 +126,16 @@ func BuildConnectionStringQueryist(ctx context.Context, cwdFS filesys.Filesys, c
var lateBind cli.LateBindQueryist = func(ctx context.Context, opts ...cli.LateBindQueryistOption) (res cli.LateBindQueryistResult, err error) {
sqlCtx := sql.NewContext(ctx)
sqlCtx.SetCurrentDatabase(dbRev)

name, email := configName, configEmail
ip := net.ParseIP(host)
if !(host == "localhost" || (ip != nil && ip.IsLoopback())) {
name, email = nameEmailFromCurrentUser(queryist, sqlCtx)
}
if err := engine.InitCommitIdentSessionConfig(queryist, sqlCtx, name, email); err != nil {
cli.PrintErr(err.Error())
}

res.Queryist = queryist
res.Context = sqlCtx
res.Closer = func() {
Expand Down
9 changes: 4 additions & 5 deletions go/cmd/dolt/commands/sqlserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -1168,27 +1168,26 @@ func newSessionBuilder(se *engine.SqlEngine, config servercfg.ServerConfig) serv
return nil, err
}

dsess, err := se.NewDoltSession(ctx, baseSession)
dSess, err := se.NewDoltSession(ctx, baseSession)
if err != nil {
return nil, err
}

varsForUser := userToSessionVars[conn.User]
if len(varsForUser) > 0 {
sqlCtx, err := se.NewContext(ctx, dsess)
sqlCtx, err := se.NewContext(ctx, dSess)
if err != nil {
return nil, err
}

for key, val := range varsForUser {
err = dsess.InitSessionVariable(sqlCtx, key, val)
if err != nil {
if err = dSess.InitSessionVariable(sqlCtx, key, val); err != nil {
return nil, err
}
}
}

return dsess, nil
return dSess, nil
}
}

Expand Down
Loading
Loading