From c1ed1817e6e49884f1e701336ebec0889ef5fca1 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 10 Jul 2026 11:53:40 -0700 Subject: [PATCH 1/3] Fix for CREATE DATABASE initialization race present in sql-driver-tests in CI --- .../go-sql-server-driver/driver/cmd.go | 68 +++++++++- .../go-sql-server-driver/driver/cmd_unix.go | 7 + .../driver/cmd_windows.go | 8 ++ server/server.go | 50 +++++-- server/startup_gate.go | 125 ++++++++++++++++++ 5 files changed, 243 insertions(+), 15 deletions(-) create mode 100644 server/startup_gate.go diff --git a/integration-tests/go-sql-server-driver/driver/cmd.go b/integration-tests/go-sql-server-driver/driver/cmd.go index 8e4756efe9..bc3703efe3 100644 --- a/integration-tests/go-sql-server-driver/driver/cmd.go +++ b/integration-tests/go-sql-server-driver/driver/cmd.go @@ -20,6 +20,7 @@ import ( "context" "database/sql" "database/sql/driver" + "errors" "fmt" "io" "log" @@ -206,26 +207,79 @@ func (rs RepoStore) initDatabase(name string, fn func(db *sql.DB) error) error { if err := cmd.Start(); err != nil { return err } + + stopped := false + stopServer := func() error { + if stopped { + return nil + } + stopped = true + if err := interruptCmd(cmd); err != nil && !errors.Is(err, os.ErrProcessDone) { + return fmt.Errorf("could not interrupt init server for %s: %w (output: %s)", name, err, output.String()) + } + if err := cmd.Wait(); err != nil { + return fmt.Errorf("init server for %s did not exit cleanly: %w (output: %s)", name, err, output.String()) + } + return nil + } + // Best-effort shutdown on error paths; the success path below calls + // stopServer explicitly and checks its result. defer func() { - _ = cmd.Process.Signal(os.Interrupt) - _, _ = cmd.Process.Wait() + _ = stopServer() }() - db, err := ConnectDB("postgres", "password", name, "127.0.0.1", port, nil) + db, err := ConnectDB("postgres", "password", "", "127.0.0.1", port, nil) if err != nil { return fmt.Errorf("could not connect to init server for %s: %w (output: %s)", name, err, output.String()) } - defer db.Close() - - if _, err := db.Exec(fmt.Sprintf(`CREATE DATABASE IF NOT EXISTS %s`, name)); err != nil { + _, err = db.Exec(fmt.Sprintf(`CREATE DATABASE IF NOT EXISTS %s`, name)) + db.Close() + if err != nil { return err } + + // Connect to the new database, wait for its initialization to fully + // complete, and run any additional setup. + db, err = ConnectDB("postgres", "password", name, "127.0.0.1", port, nil) + if err != nil { + return fmt.Errorf("could not connect to database %s on init server: %w (output: %s)", name, err, output.String()) + } + defer db.Close() + if err := waitForDatabaseInit(db); err != nil { + return fmt.Errorf("database %s was not fully initialized: %w (output: %s)", name, err, output.String()) + } + + // Complete any requested setup if fn != nil { if err := fn(db); err != nil { return err } } - return nil + + // Finally shutdown the server now that initialization is complete + return stopServer() +} + +// waitForDatabaseInit blocks until the database that |db| is connected to has +// been fully initialized. +func waitForDatabaseInit(db *sql.DB) error { + var lastErr error + for i := 0; i < ConnectAttempts; i++ { + if i != 0 { + time.Sleep(RetrySleepDuration) + } + var n int + err := db.QueryRow(`SELECT count(*) FROM dolt_log WHERE message = 'CREATE DATABASE'`).Scan(&n) + if err != nil { + lastErr = err + continue + } + if n > 0 { + return nil + } + lastErr = errors.New("no CREATE DATABASE commit found in dolt_log") + } + return lastErr } func sanitize(s string) string { diff --git a/integration-tests/go-sql-server-driver/driver/cmd_unix.go b/integration-tests/go-sql-server-driver/driver/cmd_unix.go index 6e795c1258..ba1d6be102 100644 --- a/integration-tests/go-sql-server-driver/driver/cmd_unix.go +++ b/integration-tests/go-sql-server-driver/driver/cmd_unix.go @@ -18,6 +18,7 @@ package driver import ( + "os" "os/exec" "syscall" ) @@ -26,6 +27,12 @@ func ApplyCmdAttributes(cmd *exec.Cmd) { // nothing to do on unix / darwin } +// interruptCmd requests that |cmd| shut down gracefully, the same way a user +// pressing Ctrl-C would. +func interruptCmd(cmd *exec.Cmd) error { + return cmd.Process.Signal(os.Interrupt) +} + func (s *SqlServer) GracefulStop() error { select { case <-s.Done: diff --git a/integration-tests/go-sql-server-driver/driver/cmd_windows.go b/integration-tests/go-sql-server-driver/driver/cmd_windows.go index 4f8f0cb4e2..3a5cb46b13 100644 --- a/integration-tests/go-sql-server-driver/driver/cmd_windows.go +++ b/integration-tests/go-sql-server-driver/driver/cmd_windows.go @@ -29,6 +29,14 @@ func ApplyCmdAttributes(cmd *exec.Cmd) { } } +// interruptCmd requests that |cmd| shut down gracefully, the same way a user +// pressing Ctrl-C would. os.Interrupt cannot be sent with Process.Signal on +// Windows, so a console ctrl-break event is used instead (the process was +// placed in its own process group by ApplyCmdAttributes). +func interruptCmd(cmd *exec.Cmd) error { + return windows.GenerateConsoleCtrlEvent(windows.CTRL_BREAK_EVENT, uint32(cmd.Process.Pid)) +} + func (s *SqlServer) GracefulStop() error { err := windows.GenerateConsoleCtrlEvent(windows.CTRL_BREAK_EVENT, uint32(s.Cmd.Process.Pid)) if err != nil { diff --git a/server/server.go b/server/server.go index 25a03380da..8f9ef6bfc9 100644 --- a/server/server.go +++ b/server/server.go @@ -17,9 +17,11 @@ package server import ( "context" "fmt" + "net" _ "net/http/pprof" "os" "path/filepath" + "time" "github.com/cockroachdb/errors" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -148,6 +150,16 @@ func runServer(ctx context.Context, cfg *servercfg.DoltgresConfig, dEnv *env.Dol return true, nil }) + // When we need to create the default database, gate the listener so that no external connections are accepted until + // that creation has fully completed. This is necessary due to the fact that `CREATE DATABASE` is non-transactional + // and non-atomic, so other clients could connect to a partially-created database otherwise. This problem exists in + // Dolt as well, but Dolt doesn't auto-create a database on init. + var gate *startupGate + if initializeDefaultDatabase { + gate = newStartupGate() + protocolListenerFactory = gate.gatedListenerFactory(protocolListenerFactory) + } + controller := svcs.NewController() newCtx, cancelF := context.WithCancel(ctx) go func() { @@ -180,32 +192,54 @@ func runServer(ctx context.Context, cfg *servercfg.DoltgresConfig, dEnv *env.Dol } if initializeDefaultDatabase { - err = createDefaultDatabase(ssCfg) + err = createDefaultDatabase(ssCfg, gate) if err != nil { + controller.Stop() return nil, err } + // Release the startup gate to accept external connections now that init is finished + gate.Release() } // TODO: shutdown replication cleanly when we stop the server _, err = startReplication(cfg, ssCfg) if err != nil { + controller.Stop() return nil, err } return controller, nil } -// createDefaultDatabase creates the database named on the local server using the configuration values to connect, returning -// any error -func createDefaultDatabase(cfg doltservercfg.ServerConfig) error { +// createDefaultDatabaseTimeout bounds first-run creation of the default +// database. The internal connection is served by the same accept loop that +// serves clients, so if the server fails to start its accept loop the dial +// would otherwise block forever. +const createDefaultDatabaseTimeout = 2 * time.Minute + +// createDefaultDatabase creates the database named on the local server, returning any error. The connection used is an +// internal in-memory connection provided by |gate|; the server does not accept external connections until the gate is +// released, which the caller does only after this function succeeds. +func createDefaultDatabase(cfg doltservercfg.ServerConfig, gate *startupGate) error { user, password := auth.GetSuperUserAndPassword() dbName := getDefaultDatabaseName(user) - dsn := fmt.Sprintf("postgres://%s:%s@localhost:%d", user, password, cfg.Port()) + // The host and port here are only used for display purposes: DialFunc below routes the connection through the + // gate's in-memory pipe. TLS is disabled because it is unnecessary for an in-process connection. + dsn := fmt.Sprintf("postgres://%s:%s@localhost:%d/?sslmode=disable", user, password, cfg.Port()) - // Connect to the server and create the default database with the given name. - ctx := context.Background() - conn, err := pgx.Connect(ctx, dsn) + ctx, cancel := context.WithTimeout(context.Background(), createDefaultDatabaseTimeout) + defer cancel() + + connConfig, err := pgx.ParseConfig(dsn) + if err != nil { + return err + } + connConfig.DialFunc = func(ctx context.Context, network, addr string) (net.Conn, error) { + return gate.Dial(ctx) + } + + conn, err := pgx.ConnectConfig(ctx, connConfig) if err != nil { return err } diff --git a/server/startup_gate.go b/server/startup_gate.go new file mode 100644 index 0000000000..159d98d876 --- /dev/null +++ b/server/startup_gate.go @@ -0,0 +1,125 @@ +// Copyright 2026 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 server + +import ( + "context" + "net" + "sync" + + "github.com/dolthub/go-mysql-server/server" + "github.com/dolthub/vitess/go/mysql" +) + +// startupGate delays acceptance of external client connections until first-run +// initialization (creation of the default database) is complete. Before the +// gate is released, only internal connections created through Dial are served. +type startupGate struct { + conns chan net.Conn + released chan struct{} + once sync.Once +} + +func newStartupGate() *startupGate { + return &startupGate{ + conns: make(chan net.Conn), + released: make(chan struct{}), + } +} + +// Dial returns the client half of an in-memory connection. The server half is +// handed to the gated listener's accept loop and served through the standard +// connection-handling stack, exactly as a network connection would be. +func (g *startupGate) Dial(ctx context.Context) (net.Conn, error) { + client, srvr := net.Pipe() + select { + case g.conns <- srvr: + return client, nil + case <-ctx.Done(): + _ = client.Close() + _ = srvr.Close() + return nil, ctx.Err() + } +} + +// Release opens the gate: listeners gated on this startupGate begin accepting +// external connections. Safe to call more than once. +func (g *startupGate) Release() { + g.once.Do(func() { + close(g.released) + }) +} + +// gatedListenerFactory wraps |inner| so that the listeners it produces serve +// only the gate's internal connections until |gate| is released, after which +// they delegate to the wrapped listener's normal accept loop. +func (g *startupGate) gatedListenerFactory(inner server.ProtocolListenerFunc) server.ProtocolListenerFunc { + return func(cfg server.Config, listenerCfg mysql.ListenerConfig, sel server.ServerEventListener) (server.ProtocolListener, error) { + pl, err := inner(cfg, listenerCfg, sel) + if err != nil { + return nil, err + } + return &gatedProtocolListener{ + inner: pl, + gate: g, + cfg: listenerCfg, + sel: sel, + quit: make(chan struct{}), + }, nil + } +} + +// gatedProtocolListener is a server.ProtocolListener that serves a +// startupGate's internal connections until the gate is released, then hands +// control to the wrapped listener. +type gatedProtocolListener struct { + inner server.ProtocolListener + gate *startupGate + cfg mysql.ListenerConfig + sel server.ServerEventListener + quit chan struct{} + closeOnce sync.Once +} + +var _ server.ProtocolListener = (*gatedProtocolListener)(nil) + +// Accept implements server.ProtocolListener. +func (l *gatedProtocolListener) Accept() { + for { + select { + case conn := <-l.gate.conns: + connectionHandler := NewConnectionHandler(conn, l.cfg.Handler, l.sel) + go connectionHandler.HandleConnection() + case <-l.gate.released: + l.inner.Accept() + return + case <-l.quit: + return + } + } +} + +// Close implements server.ProtocolListener. +func (l *gatedProtocolListener) Close() { + l.closeOnce.Do(func() { + close(l.quit) + }) + l.inner.Close() +} + +// Addr implements server.ProtocolListener. +func (l *gatedProtocolListener) Addr() net.Addr { + return l.inner.Addr() +} From b4cc661a89294d666b4acadc1553ef3a424e6abd Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 10 Jul 2026 12:48:29 -0700 Subject: [PATCH 2/3] better approach: init the engine during service init --- server/server.go | 73 +++++++++--------------- server/startup_gate.go | 125 ----------------------------------------- 2 files changed, 27 insertions(+), 171 deletions(-) delete mode 100644 server/startup_gate.go diff --git a/server/server.go b/server/server.go index 8f9ef6bfc9..8aadc7b33e 100644 --- a/server/server.go +++ b/server/server.go @@ -17,14 +17,13 @@ package server import ( "context" "fmt" - "net" _ "net/http/pprof" "os" "path/filepath" - "time" "github.com/cockroachdb/errors" "github.com/dolthub/dolt/go/cmd/dolt/cli" + "github.com/dolthub/dolt/go/cmd/dolt/commands/engine" "github.com/dolthub/dolt/go/cmd/dolt/commands/sqlserver" "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" "github.com/dolthub/dolt/go/libraries/doltcore/env" @@ -39,7 +38,6 @@ import ( "github.com/dolthub/dolt/go/store/util/tempfiles" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" - "github.com/jackc/pgx/v5" "github.com/dolthub/doltgresql/server/auth" "github.com/dolthub/doltgresql/server/initialization" @@ -150,14 +148,13 @@ func runServer(ctx context.Context, cfg *servercfg.DoltgresConfig, dEnv *env.Dol return true, nil }) - // When we need to create the default database, gate the listener so that no external connections are accepted until - // that creation has fully completed. This is necessary due to the fact that `CREATE DATABASE` is non-transactional - // and non-atomic, so other clients could connect to a partially-created database otherwise. This problem exists in - // Dolt as well, but Dolt doesn't auto-create a database on init. - var gate *startupGate + // When we need to create the default database, do so via an engine initializer, which runs after the engine is + // constructed but before the server accepts any connections. This is necessary due to the fact that + // `CREATE DATABASE` is non-transactional and non-atomic, so other clients could connect to a partially-created + // database otherwise. This problem exists in Dolt as well, but Dolt doesn't auto-create a database on init. + var engineInitializer sqlserver.EngineInitializer if initializeDefaultDatabase { - gate = newStartupGate() - protocolListenerFactory = gate.gatedListenerFactory(protocolListenerFactory) + engineInitializer = defaultDatabaseInitializer{} } controller := svcs.NewController() @@ -183,6 +180,7 @@ func runServer(ctx context.Context, cfg *servercfg.DoltgresConfig, dEnv *env.Dol DoltEnv: dEnv, ProtocolListenerFactory: protocolListenerFactory, ProviderFactory: DoltgresProviderFactory{}, + EngineInitializer: engineInitializer, }) go controller.Start(newCtx) @@ -191,16 +189,6 @@ func runServer(ctx context.Context, cfg *servercfg.DoltgresConfig, dEnv *env.Dol return nil, err } - if initializeDefaultDatabase { - err = createDefaultDatabase(ssCfg, gate) - if err != nil { - controller.Stop() - return nil, err - } - // Release the startup gate to accept external connections now that init is finished - gate.Release() - } - // TODO: shutdown replication cleanly when we stop the server _, err = startReplication(cfg, ssCfg) if err != nil { @@ -211,41 +199,34 @@ func runServer(ctx context.Context, cfg *servercfg.DoltgresConfig, dEnv *env.Dol return controller, nil } -// createDefaultDatabaseTimeout bounds first-run creation of the default -// database. The internal connection is served by the same accept loop that -// serves clients, so if the server fails to start its accept loop the dial -// would otherwise block forever. -const createDefaultDatabaseTimeout = 2 * time.Minute - -// createDefaultDatabase creates the database named on the local server, returning any error. The connection used is an -// internal in-memory connection provided by |gate|; the server does not accept external connections until the gate is -// released, which the caller does only after this function succeeds. -func createDefaultDatabase(cfg doltservercfg.ServerConfig, gate *startupGate) error { - user, password := auth.GetSuperUserAndPassword() - dbName := getDefaultDatabaseName(user) +// defaultDatabaseInitializer creates the default database on a first run against an empty data dir. It runs via +// sqlserver.Config.EngineInitializer, after the engine has been constructed but before the server accepts any +// connections, so no client can observe (or interfere with) a partially created default database. +type defaultDatabaseInitializer struct{} - // The host and port here are only used for display purposes: DialFunc below routes the connection through the - // gate's in-memory pipe. TLS is disabled because it is unnecessary for an in-process connection. - dsn := fmt.Sprintf("postgres://%s:%s@localhost:%d/?sslmode=disable", user, password, cfg.Port()) +var _ sqlserver.EngineInitializer = defaultDatabaseInitializer{} - ctx, cancel := context.WithTimeout(context.Background(), createDefaultDatabaseTimeout) - defer cancel() +// InitializeEngine implements sqlserver.EngineInitializer. +func (defaultDatabaseInitializer) InitializeEngine(ctx context.Context, se *engine.SqlEngine) error { + user, _ := auth.GetSuperUserAndPassword() + dbName := getDefaultDatabaseName(user) - connConfig, err := pgx.ParseConfig(dsn) + sqlCtx, err := se.NewDefaultContext(ctx) if err != nil { return err } - connConfig.DialFunc = func(ctx context.Context, network, addr string) (net.Conn, error) { - return gate.Dial(ctx) - } - - conn, err := pgx.ConnectConfig(ctx, connConfig) + // The session must run as the doltgres superuser: unlike Dolt, doltgres has + // no "root" user, so NewLocalContext's default client would be rejected. + sqlCtx.Session.SetClient(sql.Client{User: user, Address: "localhost", Capabilities: 0}) + defer sql.SessionEnd(sqlCtx.Session) + sql.SessionCommandBegin(sqlCtx.Session) + defer sql.SessionCommandEnd(sqlCtx.Session) + + _, iter, _, err := se.Query(sqlCtx, fmt.Sprintf("CREATE DATABASE %s;", dbName)) if err != nil { return err } - defer conn.Close(ctx) - - _, err = conn.Exec(ctx, fmt.Sprintf("CREATE DATABASE %s;", dbName)) + _, err = sql.RowIterToRows(sqlCtx, iter) return err } diff --git a/server/startup_gate.go b/server/startup_gate.go deleted file mode 100644 index 159d98d876..0000000000 --- a/server/startup_gate.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2026 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 server - -import ( - "context" - "net" - "sync" - - "github.com/dolthub/go-mysql-server/server" - "github.com/dolthub/vitess/go/mysql" -) - -// startupGate delays acceptance of external client connections until first-run -// initialization (creation of the default database) is complete. Before the -// gate is released, only internal connections created through Dial are served. -type startupGate struct { - conns chan net.Conn - released chan struct{} - once sync.Once -} - -func newStartupGate() *startupGate { - return &startupGate{ - conns: make(chan net.Conn), - released: make(chan struct{}), - } -} - -// Dial returns the client half of an in-memory connection. The server half is -// handed to the gated listener's accept loop and served through the standard -// connection-handling stack, exactly as a network connection would be. -func (g *startupGate) Dial(ctx context.Context) (net.Conn, error) { - client, srvr := net.Pipe() - select { - case g.conns <- srvr: - return client, nil - case <-ctx.Done(): - _ = client.Close() - _ = srvr.Close() - return nil, ctx.Err() - } -} - -// Release opens the gate: listeners gated on this startupGate begin accepting -// external connections. Safe to call more than once. -func (g *startupGate) Release() { - g.once.Do(func() { - close(g.released) - }) -} - -// gatedListenerFactory wraps |inner| so that the listeners it produces serve -// only the gate's internal connections until |gate| is released, after which -// they delegate to the wrapped listener's normal accept loop. -func (g *startupGate) gatedListenerFactory(inner server.ProtocolListenerFunc) server.ProtocolListenerFunc { - return func(cfg server.Config, listenerCfg mysql.ListenerConfig, sel server.ServerEventListener) (server.ProtocolListener, error) { - pl, err := inner(cfg, listenerCfg, sel) - if err != nil { - return nil, err - } - return &gatedProtocolListener{ - inner: pl, - gate: g, - cfg: listenerCfg, - sel: sel, - quit: make(chan struct{}), - }, nil - } -} - -// gatedProtocolListener is a server.ProtocolListener that serves a -// startupGate's internal connections until the gate is released, then hands -// control to the wrapped listener. -type gatedProtocolListener struct { - inner server.ProtocolListener - gate *startupGate - cfg mysql.ListenerConfig - sel server.ServerEventListener - quit chan struct{} - closeOnce sync.Once -} - -var _ server.ProtocolListener = (*gatedProtocolListener)(nil) - -// Accept implements server.ProtocolListener. -func (l *gatedProtocolListener) Accept() { - for { - select { - case conn := <-l.gate.conns: - connectionHandler := NewConnectionHandler(conn, l.cfg.Handler, l.sel) - go connectionHandler.HandleConnection() - case <-l.gate.released: - l.inner.Accept() - return - case <-l.quit: - return - } - } -} - -// Close implements server.ProtocolListener. -func (l *gatedProtocolListener) Close() { - l.closeOnce.Do(func() { - close(l.quit) - }) - l.inner.Close() -} - -// Addr implements server.ProtocolListener. -func (l *gatedProtocolListener) Addr() net.Addr { - return l.inner.Addr() -} From 99bb7c9914b9d632f465b117be096b1caaa88981 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 10 Jul 2026 12:52:24 -0700 Subject: [PATCH 3/3] new dolt --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b9ed822799..296af1ea24 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/PuerkitoBio/goquery v1.8.1 github.com/cockroachdb/apd/v3 v3.2.3 github.com/cockroachdb/errors v1.7.5 - github.com/dolthub/dolt/go v0.40.5-0.20260710160803-b101e404aa74 + github.com/dolthub/dolt/go v0.40.5-0.20260710195005-67fd372af00e github.com/dolthub/eventsapi_schema v0.0.0-20260310172945-37a9265ade69 github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 github.com/dolthub/go-mysql-server v0.20.1-0.20260709224106-fecf6bb54eb0 diff --git a/go.sum b/go.sum index 9be106897b..02a4303e77 100644 --- a/go.sum +++ b/go.sum @@ -246,8 +246,8 @@ github.com/dolthub/aws-sdk-go-ini-parser v0.0.0-20250305001723-2821c37f6c12 h1:I github.com/dolthub/aws-sdk-go-ini-parser v0.0.0-20250305001723-2821c37f6c12/go.mod h1:rN7X8BHwkjPcfMQQ2QTAq/xM3leUSGLfb+1Js7Y6TVo= github.com/dolthub/dolt-mcp v0.3.4 h1:AyG5cw+fNWXDHXujtQnqUPZrpWtPg6FN6yYtjv1pP44= github.com/dolthub/dolt-mcp v0.3.4/go.mod h1:bCZ7KHvDYs+M0e+ySgmGiNvLhcwsN7bbf5YCyillLrk= -github.com/dolthub/dolt/go v0.40.5-0.20260710160803-b101e404aa74 h1:7sMiWh9QW8mdvlO5VoZ2Kh/QABlOpXRmxumqwVscCiA= -github.com/dolthub/dolt/go v0.40.5-0.20260710160803-b101e404aa74/go.mod h1:9BHm5IeGCRju3T86BtqT671Iv189t9A4JZwy/rpu7cA= +github.com/dolthub/dolt/go v0.40.5-0.20260710195005-67fd372af00e h1:oqowLp7vIKiI8WRcXabfeYSijJs6ATs+xv+SZv/cSwY= +github.com/dolthub/dolt/go v0.40.5-0.20260710195005-67fd372af00e/go.mod h1:9BHm5IeGCRju3T86BtqT671Iv189t9A4JZwy/rpu7cA= github.com/dolthub/eventsapi_schema v0.0.0-20260310172945-37a9265ade69 h1:JShhbqMw26nKx3pqqu/cFxOpzBkN+4elVhzuUfgDw2k= github.com/dolthub/eventsapi_schema v0.0.0-20260310172945-37a9265ade69/go.mod h1:SSLraQS/jGLYFgff3vuZ+JbVUct6vyEeMzjLBqWqoyM= github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 h1:u3PMzfF8RkKd3lB9pZ2bfn0qEG+1Gms9599cr0REMww=