Skip to content

2.2.3

Latest

Choose a tag to compare

@github-actions github-actions released this 30 Jul 00:39

Merged PRs

dolt

  • 11366: Include full table scan in index statistics
    Have StatsController also create an "empty" statistic entry to indicate no index for costing.
  • 11365: Add dolt_squash_history procedure
    This new procedure will take the content of HEAD, and squash history before it. Default behavior is to squash every commit from height 2 (commit right after initial commit) to HEAD. It is impossible to rewrite the initial commit.
    This will be much faster than rebasing all history.
  • 11358: Fix left outer merge join wrong results with residual filters
    Tests added in dolthub/go-mysql-server#3655
    Fixes #11350
    Based on #11351
  • 11354: add missing execution call for sqlparser.Execute statements
    We were missing calls to iter.Next() and iter.Close(), when executing prepared statements through dolt sql -q "...",
    some tests in: dolthub/go-mysql-server#3653
    fixes: #11345
  • 11351: kvexec: fix left outer merge join wrong results with residual filters
    Fixes #11350 — wrong results from mergeJoinKvIter for left outer merge joins whose key runs contain duplicates and whose join condition carries a residual (non-merge-key) filter.
    Two one-line-class defects, both in the match: loop:
    1. l.matchedLeft = ok overwrote earlier successes. A left row that matched mid-run was re-flagged unmatched by a later failed pairing in the same run, so the run transition emitted a spurious null-extended row for it. Changed to l.matchedLeft = l.matchedLeft || ok; the run-transition reset remains the sole reset point.
    2. io.EOF during the left advance dropped the final owed null-extension. The compare: loop handles left-EOF via oldLeftKey; the match: loop's advance branch returned the error immediately, losing the null-extended row for a final unmatched left row. Now it emits that row (when isLeftJoin && !matchedLeft) before surfacing EOF.
      Minimal repro (returns fr:app|NULL instead of nl:app|NULL before this patch):
    create table b2 (cat varchar(50) not null, code varchar(16) not null, lang varchar(20) not null,
    primary key(cat, code, lang), key(code));
    create table t2 (id varchar(36) primary key, code varchar(16), lang varchar(16), key(code, lang));
    insert into b2 values ('cat0','P1','de:app'),('cat1','P1','fr:app'),('cat2','P1','nl:app');
    insert into t2 values ('t1','P1','de'),('t2','P1','es'),('t3','P1','fr');
    select /*+ MERGE_JOIN(p,w) */ p.lang, w.lang
    from b2 p left join t2 w on w.code = p.code and w.lang = substring_index(p.lang, ':', 1);
    The regression test registers the kvexec ExecBuilder on the test engine (as the CLI/server engines do) so the kvexec iterator — not the GMS fallback, which was already correct — is what's exercised; the new test fails 7 assertions without the fix and passes with it. kvexec suite and enginetest TestJoinQueries/TestJoinOps pass. Also verified against a 15k-row synthetic (anti-join now agrees exactly with NOT EXISTS: 5,000) and the production database where this was found (197-row orphan audit no longer inflates to ~15k when the planner picks the merge join path).
    🤖 Generated with Claude Code
    https://claude.ai/code/session_01VpTxMfzCXHoM8ojJn5aQiv
  • 11344: Fail amend commits when branch head has moved
    When a SQL transaction ran CALL DOLT_COMMIT('--amend') after another connection had added a commit or merged a branch, the amend silently replaced the transaction HEAD commit up to the new HEAD commit. The data from the erased commits survived, but the commit itself, including merge records we're gone.
    • datas.CommitOptions.Amend is replaced with AmendedCommit (hash.Hash), the address of the commit an amend replaces.
    • datas.BuildNewCommit rejects an amend unless AmendedCommit is still the dataset HEAD, relying on the CAS in CommitWithWorkingSet` for atomic comparison.
    • dsess.doCommit runs validateAmendedHead before the working set merge to specify the head conflict over a row conflict.
    • Amend is refused mid merge, cherry-pick, in parity with git and revert, a Dolt-specific addition because it follows the same merge state.
    • The admin createchunk command's HEAD check bypass moves from the Amend flag to a new explicit CommitOptions.Force field.
      Fix #9072
  • 11343: Add retries to branch creation on ErrOptimisticLockFailed errors
    Adds a retry loop to NewBranchAtCommit so branch creation can recover from a concurrent optimistic-lock conflict on the working set (e.g. from a background auto-GC cycle). This matches the existing retry behavior of other write paths (e.g. SQL transaction commit).
  • 11333: Bug fixes for secondary indexes using virtual columns
    When a virtual generated column is used in a secondary index, rebuilding the index can generate incorrect index data in some situations. For example, dropping a column in the table will trigger a table rewrite as well a rebuilding the secondary indexes. In this case, the virtual generated column expressions were not properly being evaluated to store the correct data in the index.

go-mysql-server

  • 3657: check stats prov for empty stat
    Instead of creating the (potentially same) empty stat every time, we should check if it has already been made in the StatsProvider.

  • 3656: Bug fix for CASE expressions with ExtendedType instances
    Related to: dolthub/doltgresql#2980
    Doltgres fix: dolthub/doltgresql#2987

  • 3653: adding prepare tests for insert and update

  • 3652: Allow aliasing column names in a table function

    Depends on: dolthub/vitess#477

  • 3644: add ExtendedTableFunction interface to support table function schema …
    …on OUT parameters

  • 3643: Use buildScalar to get GetField expression for ON UPDATE columns
    fixes #11346
    Building the GetField expression for a column using its index in a table was causing indexing issues when there was also a CTE. Instead, we need to build the the GetField using buildScalar to properly resolve the column within the scope.

  • 3641: Bug fix for a panic when calling a stored procedure without a database selected

  • 3639: have coster consider not picking secondary indexes
    This PR adds a "no index" option to the coster and some additional heuristics for index costing.
    Before, we would always pick any available index, which would sometimes be sub-optimal, especially if the index is a non-covering secondary index.
    Additionally, the normal_dist and exp_dist tables are now seeded to reduce random variability between test runs.
    Benchmarks:
    #11336 (comment)

  • 3638: Bug fixes for secondary indexes using virtual columns
    When updating a row in a secondary index, any virtual generated columns need their generation expression evaluated to get the correct data stored in the secondary index. There were a few edge case with virtual columns and secondary indexes where this evaluation wasn't happening. This PR closes those gaps.
    The first case is when a table rewrite is performed and secondary indexes are rebuilt (e.g. when dropping a column on a table). Not properly evaluating a virtual column's expression caused incorrect data to be stored in the index when it was rebuilt.
    A second case is for referential actions on a foreign key that update a table and its secondary index. Not properly evaluating a virtual column's expression here can also cause incorrect data to be written to the secondary index.
    Fix for failing Dolt CI integration test in: #11333

  • 3634: Add support for multiple expressions in functional indexes

  • 3623: memory: use stable sort for secondary index ordering
    memory.TableData.sortSecondaryIndexes sorted secondary index storage with sort.Slice, which uses Go's unstable pdqsort algorithm. Rows that tie on the indexed columns (same key, different primary key) could be reordered relative to each other on every sort, so repeated index rebuilds of the same data could produce different physical row orders.
    This PR switches to sort.SliceStable, which preserves the relative (insertion) order of tied rows, making secondary index storage ordering deterministic across rebuilds.
    Fixes #2877

  • 3618: Error on SELECT @@SESSION., matching MySQL
    GMS silently returned the global value when a GLOBAL-only system variable was read with an explicitly-qualified SESSION/LOCAL scope (e.g. SELECT @@SESSION.innodb_autoinc_lock_mode), instead of raising MySQL's ERROR 1238 (ErrSystemVariableGlobalOnly).
    buildSysVar's case for SetScope_None/SetScope_Session already carries specifiedScope, which is empty for a bare @@foo reference and non-empty ("session"/"local") only when the scope was explicitly written in the query. This change uses that existing signal to raise ErrSystemVariableGlobalOnly when a global-only variable's scope is explicitly specified as session/local, while leaving the bare @@foo fallback-to-global behavior untouched (MySQL allows that case).
    Also un-skips a pre-existing enginetest case in variable_queries.go that already asserted this exact error — the test was written in anticipation of this fix (Skip: true) and now passes.
    Fixes #6722

  • 3584: Add LockSubsystem.TryLock for non-blocking lock acquisition
    Extract the single CAS attempt from Lock into a private tryLock helper and expose it as a public TryLock method that returns immediately if the lock is held by another session.
    Callers no longer need to pass a short timeout to Lock and treat ErrLockTimeout as a false return. Referenced by a TODO in dolthub/doltgresql.

vitess

  • 477: Adding Columns field to TableFuncExpr
    Allows aliasing columns from a table function.
    Needed primarily for Doltgres, which supports more expressive table functions than MySQL.
  • 476: Small fixes for functional indexes
    • adds test coverage for multi column function indexes
    • fixes Walk() to walk index fields
  • 474: go/mysql: add Conn.WaitForClientActivity to detect a departed client
    On context cancelation, the function returns with a nil error. If the client unexpectedly writes to the connection or closes it, then this method will return a non-nil error.
    Unlike the first attempt at this method, this new implementation accounts for LoadDataInFile. It uses a preempt-able read lease to let the handler read from the client socket even while WaitForClientActivity is outstanding. The Peek becomes active once again after the reads are issued and completed.

Closed Issues

  • 11350: kvexec: left outer merge join with residual filter emits spurious null-extended rows and drops final unmatched left row (wrong anti-join results)
  • 11345: dolt sql -q/-f: EXECUTE of a prepared DML statement (UPDATE/INSERT) silently applies nothing
  • 11087: Optimize Git remote backend object reads to avoid many git cat-file subprocesses
  • 11346: WITH ... UPDATE fails with 'attempted to write non-string value to string field' when the table has ON UPDATE CURRENT_TIMESTAMP
  • 11317: panic: index out of range in prolly index writer during ON DELETE CASCADE on a table with an indexed generated column (2.2.0)
  • 6722: Dolt differs from MySQL on allowing query global only system variable with session scope
  • 2877: MemoryDB: Building non-unique indexes is nondeterministic