Merged PRs
dolt
- 12429: Add store hooks for Dolt Enterprise to nbs
Stacked on #12418. Replaces #12419 with a much smaller change.
Dolt Enterprise's encryption at rest editsnbs/store.goin 14 places today. Dolt changes that file often, so those edits cause most of Enterprise's merge conflicts. This PR adds the hooks those edits need, so Enterprise no longer editsstore.go.What changes
NomsBlockStorekeeps itsstoreOptionsin a newoptsfield.store_options.go(added in #12418) gains a no-op method for each place where a store's options take effect.store.gocalls them:- manifest checks in
rebaseandupdateManifest; - a check before writes in
addChunk; - a check of added files in
updateManifestAddFiles, plus the open of added files; - the journaling store's format, and its table persister;
- the GC check and GC copier;
- the table file split offsets in
WriteTableFileandnewTableFile; - whether
addTableFilesToManifestcan read the added chunks to check their refs. openChunkSourcesForManifestUpdateAndRebasecalls the open hook, whose default is the old body, nowopenChunkSourcesForManifestUpdate.
Dolt defines no store options, so every hook does nothing and behavior is unchanged. Enterprise replacesstore_options.gowith its own version.
Size
77 changed lines in two files: 40 instore.goand 37 instore_options.go. No new tests, since the defaults change nothing.
Dolt Enterprise built on this and #12418 passes its encryption tests. Weighting each hunk by how often Dolt changed its file in the past year, its risk of a merge conflict falls by 54%.
🤖 Generated with Claude Code - 12423: multi-merge same table added
Fixes: #12421 - 12420: Fix ssh remotes whose path contains ..
A push to or clone from an ssh remote whose path has a..component fails:
The ssh client sends the URL's path to$ dolt remote add origin "ssh://localhost$PWD/../bare" $ dolt push origin main failed to get remote db; ... failed to create chunk store: remote: server error: EOFdolt transferas the repository path, and the server refuses a path with a..component (ValidateRepoPath). The same repository works when it's named by an absolute path.Fix
The client now sends the cleaned path. The transfer server serves only the repository that--data-dirnames, so this path just has to pass validation.--data-dirstill gets the path as written, so the remote host resolves it as before, including through symlinks.Testing
- A unit test covers the cleaned paths.
- A new
ssh-transfer.batstest pushes to and clones from a path containing... It fails onmainand passes here. - The rest of
ssh-transfer.batspasses.
🤖 Generated with Claude Code
- 12414: Defer materializing table writer edits until the working set is read
#12184 rebased onto the session lifecycle stack (#12413). Table writers leave the edits of completed statements pending, and they're materialized when the working set is read or the transaction commits.- Port of #12184 (first commit, squashed). A write session's owner now holds its working set, so materializing publishes to the owner.
detach/carryOverPendingare gone: a branch state can't be dropped with open writers (#12400).IsWritingDatabasecounts pending edits, which #12376's restore check needs. - Reading the working set materializes.
branchState.WorkingSet(ctx)materializes pending edits, soGetRoot,GetRoots,GetWorkingSetand the root setters see them without an explicit call. Table resolution and schema reads opt out throughSessionState.UnmaterializedWorkingRoot(schemaRoot,DoltTable.workingRoot), which takes the explicit materialize call sites from 26 to 3. A missed opt-out costs performance rather than reading stale rows;TestReadsLeaveEditsPendingpins that ordinary statements stay deferred. - Deferral regardless of autocommit. The autocommit gate worked around the #7737 stale-writer bug, which ER 1422 and #12400 rule out. Every write in the engine tests now runs deferred.
- Reading pending edits while they're being materialized is an error (a panic under dynamic asserts) instead of a silent stale read.
SequenceTracker.validateBoundsdid this and deadlocked once the read materialized; it now reads only the schema.
Tested locally with dynamic asserts: the sqle, merge and prolly Go suites pass. Bats, go-sql-server-driver and Doltgres haven't been run. Not done yet: the GC hazards from the #12184 review, a system variable to turn deferral off, and a TPCC run.
- Port of #12184 (first commit, squashed). A write session's owner now holds its working set, so materializing publishes to the owner.
- 12413: Read a branch state's working set only through methods that take a context
Reads of a branch state's working set go throughWorkingSet(ctx),WorkingRoot(ctx)androots(ctx). Only setters, GC and metadata reads (workingSetRef(), a detached head) use the field directly. Deferred write materialization (#12184) can then materialize in that read path, so every read sees pending edits unless it opts out.
SessionState'sWorkingSetandWorkingRootnow take a context and return an error. Doltgres needs a two-line change (core/context.go,core/relations.go) with the bump. - 12412: Have a DoltTransaction own the branch states it loads
EachDoltTransactionholds the branch states it loads. Those loaded while the session's transaction isn't aDoltTransaction(between transactions under autocommit, afterdolt_commitends one partway through a statement,TransactionsDisabled) go in the session'snoTxBranches.DoltSession.SetTransactionis the one place they're dropped, and it checks that none has open table writers.clear()is gone.- Between transactions, lookups load from the database instead of reusing the last transaction's branch states.
commitBranchStates' refresh loop was dead and is removed: GMS starts a new transaction before each procedure statement after a commit.- A database's temp table directory and its temp tables' GC roots come from the session-scoped
DatabaseSessionState(tmpFileDir, newddb), so they don't depend on a branch state being loaded. #12403 adds the sameddbfield onmain.
The first commit is #12410, which the stricter drop check needs. Doltgres's regression suite is clean against this with doltgresql#3799 and go-mysql-server#4136.
- 12411: Keep a session's branch states in a container that each transaction replaces
Moves the per-database branch state maps out ofDatabaseSessionStateinto abranchStatescontainer.DatabaseSessionStatekeeps only what lasts the whole session (checkedOutRevSpec,headCache,tmpFileDir,globalState).clear()swaps in a new container instead of deleting entries, and a branch state is current only while it's in the session's container.
No behavior change. The next PR moves the container ontoDoltTransaction. - 12410: Drain TestDropPks's setup queries
They were never run, and the setup INSERT's table writer stayed open. - 12408: go/cmd/dolt: Stop opening sql-server databases in runMain.
Part of removing the process-global store cache indbfactory/file.go, so that everyDoltDBhas one owner that closes it. This change stands alone.
runMainbuilt aMultiRepoEnvfor every command, so forsql-servereach database was opened once there and again by the server's ownMultiRepoEnv. The second open only worked through the singleton cache.sql-servernow joinscommandsSkippingDBLoad, andbuildLateBinderreturns a binder that errors if a command that skipped the load tries to run a query (sql-servernever does).
Release note:dolt --use-db <db> sql-serverno longer errors when<db>does not exist; the server starts, as it does without--use-db. Behaviour is otherwise unchanged across--help, no repo in cwd, configdata_dir,--data-dir, root plus sub-databases, and corrupt databases.
Tests: go-sql-server-driverTestServerInMultiDatabaseDirectorystarts a server in a directory with several databases and no root.doltand writes to each. With the cache disabled it fails without this change. - 12407: go/libraries/doltcore/sqle/dprocedures: Read config without opening a database in loadConfig.
Part of removing the process-global store cache indbfactory/file.go, so that everyDoltDBhas one owner that closes it. This change stands alone.
loadConfig, used bydolt_push,dolt_branchanddolt_checkoutof a remote branch, calledenv.Loadon the process cwd just to read config. That opened (and leaked) the store in the cwd whenever there was one, and only the singleton cache kept it from waiting 100ms on the journal lock and falling back to read-only. Its callers use only.Config, so it now usesenv.LoadWithoutDB.
Release note:dolt_push,dolt_branchanddolt_checkoutno longer open the database in the server's working directory to read its config.
Tests:TestLoadConfigDoesNotOpenDatabasechecks the config is read and nothing is written under.dolt/noms. - 12404: go: Continue system variable refactoring. Migrate off deprecated
AssignSystemVariablesandAssignValuesWithContextcalls. - 12403: Keep temporary tables' GC roots after ROLLBACK
visitTempTableGCRoots took the database's DoltDB from a loaded branch state, and ROLLBACK leaves none until the session's next statement. - 12401: Have write sessions use their branch state's working set instead of a copy
A branch's write session kept its own copy of the working set, synced bySetWorkingSet, and flushed through a setter that looked up its branch state by name. So after a transaction boundary it could write into a different branch state. It now reads and writes its branch state's working set directly.DoltSession.SetWorkingSetresets the writers when the working root changes.- Table rewrites and the workspace table start ahead of the branch state. They get a fork from
DoltSession.ForkWorkingSet, which is bound to the branch state it was created from. A flush into a dropped branch state fails, and so does a flush into one that changed since the fork, because the fork replaces the whole root. - Temp tables and the binlog applier keep a private copy via
NewDetachedWriteSession. - User-space system tables (
dolt_ignore,dolt_docs, ...) create their table through the writer instead of pushing the write session ahead, so a failed first write no longer leaves an empty table for the next flush to publish.
- Table rewrites and the workspace table start ahead of the branch state. They get a fork from
- 12400: Refuse to drop a branch state while its write session has open table writers
Dropping a branch state (clear(),RemoveDbState,RemoveBranchState) while one of its table writers is still open would lose that writer's edits or flush them into the next transaction. This returnsErrOpenTableWritersinstead, and panics under dynamic asserts. A writer is open fromGetTableWriteruntilClose. The forceddolt_backuprestore check from #12376 now checks for open writers.
After ER 1422 (previous PR), no SQL path should reach this state. With dynamic asserts on, the sqle suites, bats and go-sql-server-driver don't trip it. The first commit fixes the one leak it found, in auto_increment bookkeeping. - 12399: Reject calls in triggers to Dolt procedures that end the transaction
Dolt's half of dolthub/go-mysql-server#4131. The Dolt procedures that end the transaction (dolt_commit,dolt_branch,dolt_merge, ...) are markedNotAllowedInSubStatement, so calling one from a trigger, directly or through a procedure, fails with ER 1422 instead of losing the firing statement's rows. Committing from a sub-statement also fails, as a backstop.
The skipped #7737 test now asserts ER 1422. Also adds regression tests for #12356. - 12398: Fix main build: pass valDesc to NewMergeArtifactSerializer in ArtifactFlusher
#12334 added a value descriptor parameter tomessage.NewMergeArtifactSerializer. #12335 merged after it with a call that still used the old signature, sogo/store/prollydoesn't compile onmain. This passesmut.valDesc, as the other call sites do. - 12397: sqle: use AliasedName and Revision instead of re-splitting database names
Sites that hold a database now read its base name and revision from the accessors rather than parsing them back out of RevisionQualifiedName or Name. - 12396: dtablefunctions: name databases in CheckAuth with plan.CheckPrivilegeNameForDatabase
Use the same privilege database name GMS uses for its own nodes instead of re-splitting the revision-qualified name. - 12393: statspro: ANALYZE TABLE takes the database and revision from the table
GMS passes the session's current database rather than the table's, so revision-qualified tables likemydb/feature.t were analyzed on the session's branch instead. - 12392: dprocedures: dolt_commit_all uses the revision database's branch when nothing is dirty
Previously it passed the revision-qualified name to CurrentHead, which errored with a detached head. - 12391: branch_control: strip @-delimited revisions from database names
Branch control only stripped/revisions, so onmydb@branchnamespace checks matched no rules and let any user create restricted branches, while access checks wrongly denied permitted writes. - 12386: Don't flush table writers with no edits on close
An unedited writer still hands its write session's root to the session, since a table rewrite's write session starts ahead of it. - 12376: Refuse a forced dolt_backup restore over a database the transaction is writing to
A trigger could restore over its own database while the firing statement's writer was still open, and the statement then failed on chunks missing from the restored database. Also check that the backup exists before dropping anything, so that a forced restore from a missing backup no longer replaces the database with an empty one. - 12375: Start the import transaction before the insert takes its table writers
Start the import transaction before the insert takes its table writers - 12372: go/store/nbs: Spool git remote table files on their first chunk read.
#12328. Delays spooling until a table's chunks are first read. - 12371: go/cmd/dolt: Clean up git remote spools when the process starts.
#12328. Cleans spools when thedoltprocess starts, which is what removes spools left by dead processes. - 12370: go/store/util/tempfiles: Give up a LockedDir when its git remote store closes.
#12328. Removes a store's spool directory and gives up its lock when the store closes, so a database can be deleted while the process keeps running.GitBlobstore.Closecloses itsLockedDir, sodbfactoryhas no release calls. - 12369: go/store/util/tempfiles: Add LockedDir, and use it for git remote spools.
#12328. Lays the groundwork for removing spools left by dead processes.
Spool files are only removed when their reader closes or at a clean exit, so an OOM kill or SIGKILL strands them.tempfiles.LockedDiris a directory of temp files whose owner holds an exclusive lock on the lock file next to it, which the kernel drops however the process exits:spools/locked-123.lock spools/locked-123/nbs-spool-*dbfactorymakes one for each git remote store and passes it toGitBlobstorethroughGitBlobstoreOptions.SpoolDir.
tempfiles.CleanDirtries once to take each lock. If it gets one, the owner is gone, so it removes that directory and then the lock file. If not, the owner is alive and it moves on without waiting, so one live process does not keep a dead one's spools around. - 12368: go/store/nbs: Spool git remote table files under the git cache root.
#12328. Moves git remote spool files out of the system temp directory.
Spools now go in.dolt/git-remote-cache/spools. The blobstore gets aSpoolDiroption, set byGitRemoteFactory.CreateDB. Spooling with no directory is an error rather than a fallback to the temp directory. - 12346: Require permissions on the rebased branch for its rebase working branch.
While a rebase is active, a user with write access to the dolt_rebase_ working branch, but not to itself, could edit the rebase plan, commit to the working branch, continue or abort the rebase, or delete the working branch. Branch control checks on the working branch now also require the same permissions on the branch being rebased. - 12338: Narrow GC roots visitors to func(hash.Hash) and check the keeper once in the safepoint controller.
Narrow GC roots visitors to func(hash.Hash) and check the keeper once in the safepoint controller. - 12336: go: store/prolly/tree: WalkNodes, WalkAddresses: Only descend into child refs of internal nodes.
ProllyMap internal nodes also carry key-embedded addresses, such as commit addresses, which are not child nodes. - 12335: go: store/prolly: Use a MergeArtifacts flusher for ArtifactsEditor.
Edits that spilled out of the editor's pending buffer were written as ProllyTreeNode messages, leaving artifact maps with mixed node types and history-dependent hashes. A spill on the final edit produced a ProllyTreeNode root, which artifactIndexFromAddr rejects on load. - 12331: Fix dolt_commit_all --skip-empty panic with skipped branches
Fixes a panic indolt_commit_all('--skip-empty')when a skipped branch sorts before a committed one.
Fixes #12301 - 12326: Verified constraints for tables on the search path
- 12325: Matched diff table function names by schema
- 12316: Fix storage bounds checks, leaked handles and a few races
Eleven small fixes. Each has a test that fails without it, except the one-line git remote cache fix. The Windows mmap test only fails on Windows, and the archive index mapping check only runs on Linux.- Windows mmap alignment. Views are mapped at the 64KB allocation granularity, not the page size.
- Editor temp file.
OpenTempEditorcreates its file with mode 0600 and removes it when the editor exits. - Leaked file handles.
GetStorageMetadatacloses both manifest readers and an archive's reader and unmaps its index, andnewTableFileMetadatacloses its file. - Corrupt archive indexes.
iteratereturnsErrCorruptArchiveIndexinstead of panicking.- Reads bounds-check span and chunk references before using them.
- Journal bounds. A record whose fixed-size field overruns it, an index lookup longer than any record, and a read of a corrupt lookup's range are reported as errors instead of panicking or being trusted. The index batch checksum covers only addresses, so a corrupt offset or length got past it.
journalChunkSource.getRecordRanges. It marked found requests on a loop copy, so a chunk in the journal was also located in a table file.- Git remote cache race. The store a
CreateDBopens and loses the cache race with is now closed. - Cluster replication. After a failed push, the hook closes its standby database handle, so the next attempt reopens it.
- Stats rotation. A failed rotation left the closed stats database in place, to be flushed to and closed again.
- Archive dictionaries over remotes. A dictionary that fails to download or parse now fails the chunks waiting on it, instead of leaving them blocked forever.
- Fake S3.
UploadPartCopyparses copy sources whose keys contain/.
🤖 Generated with Claude Code
- 12314: go: sqle: binlogreplication: Stream unexecuted binlog tail after a restart rotation
Problem
When a Dolt primary restarts, it rotates to a new binlog file, which holds
only a Format Description and a Previous GTIDs event until the next write. If
a replica reconnects in that window,findLogFileForPositionskips the new
file (it has no GTID event), finds every first GTID already executed, and
returns the current file. GTIDs at the end of the previous file that the
replica has not executed are never streamed. Thefiles[i-1]branch has the
same flaw when a file without GTIDs sits between two files that have them.
We hit this with Debezium 3.1.1.Final (mysql-binlog-connector-java 0.40.2)
against Dolt 2.6.2 on ARM64 Linux, after restarting Dolt and Debezium together:- Debezium resumed with GTID set
<uuid>:1-5and saved skip counts
(2 events, 1 row) for GTID 6. - Dolt sent a rotate to
binlog-main.000002, then GTID 7. GTID 6, still in
binlog-main.000001, was never sent. - Debezium applied its skip counts to GTID 7 and dropped that row change with
no error. - This reproduced in 2 of 2 runs, confirmed with a metadata-only protocol
trace, the physical binlog files, and Debezium's log.
TestBinlogPrimary_ReplicaAndPrimaryRestartdoesn't cover this: its replica
reconnects after new writes reach the rotated file, so thefiles[i-1]path
handles it.
Related
This path became reachable for Debezium in 2.6.2.
mysql-binlog-connector-java sendsCOM_BINLOG_DUMP_GTIDwith flags0, and
before 2.6.2 Dolt ignored the GTID set in that case (#12241). Dolt then replayed
from the first file, andfindLogFileForPositionnever saw a non-empty
executed set. dolthub/vitess#502, pulled in by 2.6.2, now honours the set, which
exposes the start-file selection fixed here. #12241 still appears open, although
that fix has shipped.Change
Track the last file whose first GTID the replica has executed, and start
there. This also handles a GTID-less file in the middle. The streamer already
skips executed GTIDs (binlog_primary_streamer.go), and earlier files end
with a Rotate event, so the only cost is rescanning that one file. Behaviour
without GTID-less files is unchanged.Tests
TestFindLogFileForPosition: six table cases, two for this bug and four
pinning existing behaviour. Uses the existingnewFileBackedStreamerManager
fixture.TestBinlogStreamResumesTailBeforeRestartRotation: runs the real streaming
path over TCP. It requires the unexecuted tail GTID to arrive, and then a
GTID written to the rotated file after the client connects.
Validation
- Both tests fail on v2.6.2 without the fix and pass with it, 5 runs under
-race.go vetandgofmtare clean. - The other package tests that need no
mysqldpass. mysqldintegration tests: not run locally. Only MySQL 8.4 was available, and it
rejects the harness's--default-authentication-plugin, so I'm relying on CI.- End to end: a binary built from this branch, run behind Debezium 3.1.1 and
NATS, delivered the post-restart change that stock 2.6.2 dropped.
Debezium-only restarts and VIRTUAL generated columns were also checked.
- Debezium resumed with GTID set
- 11853: Handle unknown download sizes in clone progress
Displays unknown download sizes without calculating negative clone progress percentages.
Fixes #5359 - 11850: Resolve HEAD to the current branch when pushing
Resolves HEAD push sources to the current branch while preserving explicit destination refs.
Fixes #2480 - 11848: Show the login hint for permission-denied push errors
Preserves wrapped push errors so permission failures display the login hint and RPC diagnostics.
Fixes #783 - 11847: Preserve configured identity when login returns empty values
Preserves configured names and email addresses when login returns empty identity fields.
Fixes #425
go-mysql-server
- 4141: Fix StoredProcParam referencing stale values
Stored Procedure parameters were incorrectly getting preserved acrossCALLs.
This PR makes it so new parameters properly override any existing values in the session. - 4138: Preserve fractional precision in TIME, LEAST, and GREATEST
Preserve six fractional digits for floating-pointTIME()inputs and infer string precision whenLEAST()/GREATEST()compare datetimes, preventing rounding from changing the selected value. Dynamic strings use maximum precision, and invalid datetime minima preserve MySQL's string fallback.
These are the last cases left to cover from #11944
Fixes #11944 - 4136: Leave a statement's autocommit transaction to that statement
A failed query run from an interpreted function no longer ends the autocommit transaction, which belongs to the statement running the function. In its place, an autocommit transaction whose statement failed rolls back, after the statement's iterators are closed. Before, a failing nested query ended the outer statement's transaction while that statement's table writers were still open. And a statement that failed while closing left its transaction open for the next statement. - 4132: Open foreign key editors when a plan runs, not when it's analyzed
A plan's foreign key graph now names the tables it edits and reads by slot, and each execution of a ForeignKeyHandler opens and closes its own editors for them, so a plan that never runs, such as EXPLAIN or a trigger that doesn't fire, holds none.
Also closes editors that leaked elsewhere: the one ResolveForeignKey checks rows with, an update join's updaters when one fails to close or when only its table names are needed, and those DML and DDL builders take before failing. Memory engine tests now fail a transaction that starts with table editors open. - 4131: Reject transaction control in triggers with ER 1422
As in MySQL, a trigger and any procedure it calls can't commit, run a statement that commits implicitly, set autocommit, or call an external procedure marked NotAllowedInSubStatement. CREATE TRIGGER rejects such a body and a CALL from a trigger fails before the procedure runs; triggers stored before this fail only when they reach the statement.
DoltgreSQL companion: dolthub/doltgresql#3783 (skips the new MySQL-syntax procedure tests). - 4130: Return SQL NULL for JSON_EXTRACT wildcard misses
JSON_EXTRACT errors on an empty-array wildcard and returns [] when a wildcard property lookup has no matches. Update jsonpath to131d88a5ca62, picking up two merged fixes so both cases return SQL NULL. Adds regression tests for jsonpath wildcards.
Reports: empty-array wildcard, missing wildcard properties.
Depends on: jsonpath #9, jsonpath #10 (both merged). - 4127: JSON_TYPE(null) evaluates to null, not "NULL"
Fixes #12339
The documentation for JSON_TYPE in MySQL is ambiguous, and we misinterpreted it to mean that JSON_TYPE always returns a string, and that both JSON NULL and SQL NULL as inputs evaluate to the string "NULL". This is incorrect, and passing SQL NULL as an input should evaluate to SQL NULL. - 4126: Remove unnecessary filter conditions from semijoin plans
This PR fixes an issue where after optimizing some join expressions, we would not remove the now-redundant filter conditions. Those filter conditions are implicitly expressed by the new join plan, and can be safely removed.
Fixes some (but not all) of #11231 - 4123: Preserve caller transactions when executing stored procedures
CALLcurrently clears the caller's transaction before executing a stored procedure, causing Dolt to discard earlier uncommitted row changes.
This fix preserves two boundaries:- A normal CALL uses the caller's existing transaction. It must not clear that transaction and lose earlier changes. Explicit COMMIT or ROLLBACK inside the procedure remains effective.
- A trigger belongs to the statement that fires it. Procedures called by the trigger must finish within that statement's transaction.
The interpreter no longer saves, clears, and restores the transaction around CALL. Trigger execution temporarily suppresses automatic commits, including while its inner iterator closes, then restores the caller's previous setting on success or error. This prevents procedure-body statements from committing or clearing the outer insert/delete transaction before that statement finishes.
Fixes Dolt issue #12356
- 4121: Improve functional dependency analysis for inner joins when tables don't have a primary key
This is a similar fix to #4064, except that #4064 only updated the logic for cross joins, whereas this handles inner joins.
The modified plan is interesting: it no longer generates a unnecessary Project, but now it generates an unnecessary join filter instead. I've not yet determined why this is the case. - 4112: Preserve datetime precision in INTERVAL arithmetic
DATETIME(6) +/- INTERVALcurrently converts the datetime operand toDATETIME(0)before applying the interval. For example, adding one microsecond to2026-01-02 12:34:56.527248returns2026-01-02 12:34:57, which can also move a WHERE clause's time-window boundary.
Preserve the temporal operand's fractional precision, promoting the result to precision 6 for microsecond intervals. Both operand orders use the same inference, TIMESTAMP operands still produce DATETIME results, and externalTimeDeltaExpressionimplementations retain microsecond precision. The reported addition and subtraction now return2026-01-02 12:34:56.527249and2026-01-02 00:34:56.527248.
Regression coverage checks evaluated values, serialization, result-column types, zero/millisecond/microsecond precision, carry and borrow across days, NULL columns, reversed and nested arithmetic, a one-microsecond WHERE window, and materialized schema precision.
Addresses the precision-loss report in #11944 (comment) (not the original TIME/LEAST/GREATEST report).
Validation:- The new precision unit regression fails against unmodified upstream main.
GOWORK=off go test ./...and the complete expression package pass.GOWORK=off go test -race ./...passes.- Built Dolt main with this engine through an external Go workspace; Dolt's
TestTimeQueriespasses. - The resulting Dolt CLI passes the exact report, a stored DATETIME(6) time-window predicate, and CTAS values/precision reopened in separate processes.
The temporal precision rule was checked against MySQL 8.0'sItem_date_add_interval::resolve_type; no live MySQL comparison was run. This change retains existing result-family inference and does not change fractional SECOND interval evaluation. No dependency bumps or local module overrides are included.
- 4110: Fix JSON_TYPE SQL NULL propagation
JSON_TYPE(NULL) and JSON_TYPE applied to a missing JSON_EXTRACT path currently return the string 'NULL', causing type filters to match SQL NULL and missing values as if they were explicit JSON null. Return SQL NULL for a nil document while preserving the 'NULL' type label for explicit JSON null.
Correct the unit expectation and add engine regressions for the issue's predicate queries, nullable JSON columns, and IS NULL / = 'NULL' filters.
Fixes #12339.
Validation:- Confirmed the unit and new engine regressions fail before the fix.
GOWORK=off go test ./sql/expression/function/json/... -count=1GOWORK=off go test ./sql/expression/function/json/... ./enginetest -run 'TestJSON|TestJson' -count=1- Built Dolt at 325e1a6 with this GMS worktree through an external Go workspace, then passed
go test ./libraries/doltcore/sqle/enginetest -run '^TestJsonScripts$' -count=1. - Passed eight CLI assertions covering the reported predicates and filters over persisted nullable JSON rows, reopening the database for each query.
No dependency overrides or version bumps are included.
- 4084: Truncate strings to the column length under
INSERT IGNOREandUPDATE IGNORE
TheIGNOREmodifier requires strings that are too long for a column to be truncated to the column length. String conversion now returns the truncated value with its error, allowingINSERT IGNORE,UPDATE IGNOREandON DUPLICATE KEY UPDATEto use the otherwise internally discarded value.- A column length for truncation is now determined by its charset.
- Add
CharSetHandler.MaxByteLengthto calculate the byte length of a string without splitting multibyte characters. - Amend
ConvertToBytesandConvertToStringto follow existing conversion functions return structure.
Fix #12218
Close #4079
- 3980: Fix INSTR collation handling and wrapped substrings
Fixes INSTR collation handling, binary positions, and wrapped substring evaluation.
Fixes dolthub/go-mysql-server#3650
vitess
- 506: sqlparser: accept boolean expressions in generated columns
Accept full expressions in generated-column definitions soAS (value < 8)works without an extra pair of parentheses. Preserve the outerParenExprneeded for DDL formatting and the original regression coverage across CREATE/ALTER, abbreviated/full syntax, and virtual/stored columns.
Supersedes dolthub/vitess#503 by @sciyoshi, preserving the original commit authorship. Applied on current main and regeneratedsql.goto resolve the generated-parser merge conflict.
The fullsqlparsertest suite andtools/check_make_parser.shpass. Parser generation reports zero shift/reduce and zero reduce/reduce conflicts.
Fixes #12343. - 505: sqlparser: left-recurse comparisons so chains group left
Fix #12345
Close #504
Block dolthub/go-mysql-server#4118
Closed Issues
- 12341: CAST to DATETIME and DAY return NULL for a valid JSON string from JSON_EXTRACT
- 10648: Panic during binlog replication
- 12421: Merge fails with "table with same name added in 2 commits" when two merge bases each created the table
- 11084: Implement Lazy Flush
- 11944: MySQL is able to infer Temporal precisions
- 12328: sql-server with a git remote: nbs-spool-* temp files are never cleaned after an unclean stop, and the live set holds a full copy of the remote
- 12218: INSERT IGNORE / UPDATE IGNORE drops the connection when a DATETIME, integer or binary value is too long for a VARCHAR column
- 11439: dump panics with "index out of range" on a table with a generated column
- 12357: Same primary-key change on both sides fails to merge when there are two merge bases
- 12343: Boolean generated column expression requires an extra pair of parentheses
- 12339: JSON_TYPE(SQL NULL) returns the string 'NULL' instead of SQL NULL
- 425: Dolt login overwrites config with bad values
- 783: Prompt user to run "dolt login" on PermissionDenied error on "dolt push"
- 2480:
dolt push origin HEADpushesHEADinstead of the current branch - 7031: Deleting from
dolt_conflicts_can cause a panic when there's a schema change. - 5325: Dolt should support file remotes pointing to dolt checkouts.
- 5359: Dolt prints incorrect table file download percentage when cloning from DoltLab
- 12301: dolt_commit_all('--skip-empty') panics when a skipped branch sorts before a committed one
- 3650: INSTR: case-sensitive for nonbinary strings (should fold), and StringWrapper substring clobbers haystack (returns 1)