<p>Grove 1.7.0 adds exactly one thing. The changelog says so in its first line — one addition: a fourth bundled database; everything else from 1.6.0 stands — and I'd like to keep that honesty here, because the interesting part of this release isn't the feature. It's what the feature turned up.</p><h2>Why a fourth database</h2><p>Grove already downloads and supervises PostgreSQL, MySQL and Redis for you. You run <code>grove service install mysql</code>, Grove fetches the binary, verifies it, and from then on it's a service that starts with your machine and shows up in <code>grove status</code>. No Homebrew formulae, no version drift between laptops, nothing to remember.</p><p>ElyraSQL is our own MySQL-compatible server: a single static binary, the whole database in one crash-safe ACID file, the MySQL wire protocol so your existing drivers work unchanged, plus vector search and parallel OLAP aggregation on top. It has been the odd one out — you could point a Grove site at an ElyraSQL you'd started yourself, but Grove didn't know it was there, and so nothing that makes Grove pleasant (snapshots, the migration sandbox, <code>grove env</code>) knew either.</p><p>1.7.0 closes that gap. ElyraSQL becomes a service like the others:</p><pre><code class="language-text">$ grove service install elyrasql
  ↓ elyrasql-1.11.2-macos-aarch64.tar.gz  (7.9 MB)
  ✓ SHA-256 matches the published checksum
  ✓ installed 1.11.2, listening on 127.0.0.1:3307
</code></pre><p>Two details in those three lines are deliberate. The checksum is verified against what upstream published, not computed and admired — a download that matches nothing has proven nothing. And it lands on 3307, not 3306, so it lives beside MySQL rather than fighting it for the port. You can run both, and many people will: MySQL for the project that has to match production, ElyraSQL for the one where you want vector search without a second service.</p><h2>How your app sees it</h2><p>It doesn't, really — and that's the point. ElyraSQL speaks MySQL, so your app keeps the MySQL driver:</p><pre><code class="language-text">$ grove env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3307
DB_DATABASE=elyra
DB_USERNAME=root
DB_PASSWORD=
</code></pre><p>Paste that into <code>.env</code>, run your migrations, and Laravel — or anything else with a MySQL driver — is talking to ElyraSQL without knowing it. Grove tells an ElyraSQL site from a MySQL one by the port it connects to, which is a small thing that matters: the agent-safe migration sandbox and <code>grove bundle</code> need to snapshot the right server, and they do.</p><p>Snapshots work the way they do for the others, with one difference underneath:</p><pre><code class="language-text">$ grove db snapshot --engine elyrasql --name before-vectors
  ✓ BACKUP TO … (hot, consistent, 42 MB)

$ php artisan migrate      # oh no
$ grove db restore before-vectors
  ✓ restored in 0.3s
</code></pre><p>Because ElyraSQL's database is one file, a snapshot is a hot, consistent copy of that file taken through <code>BACKUP TO</code> while the server keeps serving. Restore puts it back. Undoing a bad migration takes the time it takes to copy a file.</p><p>The <code>convert</code> tool takes ElyraSQL as a source or a target too, so moving a project from MySQL to ElyraSQL — or back — is one command rather than a dump-and-hope.</p><p>Platforms: macOS on Apple silicon and Linux. Upstream publishes no Intel macOS build, so Grove doesn't pretend to offer one.</p><h2>The bug it found</h2><p>Here's the part worth the article.</p><p>Grove is written in Rust, and its <code>convert</code> tool talks to databases through sqlx, the driver most Rust applications sit on. When we pointed <code>convert</code> at the freshly bundled ElyraSQL 1.11.1, it couldn't connect. Not "couldn't run a query" — couldn't connect at all.</p><p>The reason is a statement sqlx-mysql runs on every new connection, before your application gets a word in:</p><pre><code class="language-sql">SET sql_mode=(SELECT CONCAT(@@sql_mode, ',PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION')),
    time_zone='+00:00'
</code></pre><p>ElyraSQL refused both halves. A scalar subquery wasn't a valid value for <code>SET</code>, and <code>time_zone</code> wasn't a recognised session variable. Error 1235, connection over. Anything built on sqlx — including anything generic over <code>AnyPool</code>, which has no way to switch the statement off — got exactly nowhere.</p><p>And the ElyraSQL documentation said sqlx worked out of the box.</p><p>It did not. Nobody had noticed because nobody had tried: the Laravel and PDO paths were well-trodden, the Python and Node drivers had been checked, and "Rust (sqlx)" sat in the list of supported clients on the strength of speaking MySQL. Speaking MySQL and having been connected to by sqlx turned out to be different claims.</p><p>So ElyraSQL 1.11.2 shipped the same day, and Grove 1.7.0 requires it. What changed:</p><ul><li><p>A <code>(SELECT …)</code> in a <code>SET</code> value now runs as a query and must return exactly one row and one column, as in MySQL.</p></li><li><p><code>time_zone</code> is a session variable, echoed by <code>@@time_zone</code> and <code>@@session.time_zone</code>, while <code>@@global.time_zone</code> stays <code>SYSTEM</code> — exactly as MySQL 8.4 reports it.</p></li><li><p>Only spellings of <code>time_zone</code> that mean UTC are accepted: <code>+00:00</code>, <code>SYSTEM</code>, <code>UTC</code>. ElyraSQL already evaluates every temporal function in UTC, so <code>+00:00</code> is honoured exactly — which is what sqlx's <code>chrono</code> and <code>time</code> types assume. A non-zero offset is refused with a reason, rather than stored and silently not honoured. A setting that is accepted and ignored is worse than one that's rejected; you find out about the second one.</p></li><li><p>A duplicated <code>@@sql_mode</code> flag that the same statement produced is deduplicated, because <code>sql_mode</code> is a set, not a list.</p></li></ul><p>Two neighbouring gaps the same measurement surfaced — <code>UTC_TIMESTAMP()</code> / <code>CONVERT_TZ()</code> aren't implemented, and <code>||</code> isn't concatenation even with <code>PIPES_AS_CONCAT</code> — are filed as issues rather than papered over. They're real; they're just not this release.</p><h2>Why we're telling you</h2><p>We could have written "Grove 1.7.0 bundles ElyraSQL (requires 1.11.2)" and moved on. The version floor would have looked arbitrary, and the sqlx fix would have been a line in another product's changelog.</p><p>But the whole reason to bundle your own database into your own dev environment is that you become the first person to trip over the gaps between them. That's not a cost of dogfooding; it's the return on it. A claim in the docs that had been true-by-inference for a year got tested by accident and turned out to be false, and now it's true by measurement. The Grove page and the ElyraSQL page on <a target="_blank" rel="noopener noreferrer nofollow" href="http://elyracode.com">elyracode.com</a> both say so, in those words, because a card that quietly updates its claim is indistinguishable from one that was always right.</p><h2>Try it</h2><pre><code class="language-bash">grove service install elyrasql
grove env &gt;&gt; .env          # then set DB_DATABASE to something you like
php artisan migrate
grove db snapshot --engine elyrasql --name clean
</code></pre><p>Then break something, and restore it. That's the feature. The bug was a bonus.</p>