<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>SQLite on Clément Joly – Open-Source, Rust &amp; SQLite</title><link>https://cj.rs/tags/sqlite/</link><description>Recent content in SQLite on Clément Joly – Open-Source, Rust &amp; SQLite</description><image><title>Clément Joly – Open-Source, Rust &amp; SQLite</title><url>https://cj.rs/images/open-graph-pages.jpg</url><link>https://cj.rs/images/open-graph-pages.jpg</link></image><generator>Hugo</generator><language>en</language><copyright>Clément Joly</copyright><lastBuildDate>Mon, 04 May 2026 19:41:10 +0100</lastBuildDate><atom:link href="https://cj.rs/tags/sqlite/index.xml" rel="self" type="application/rss+xml"/><item><title>Rusqlite Snapshot Testing</title><link>https://cj.rs/rusqlite-snapshot-testing/</link><pubDate>Sat, 29 Mar 2025 17:32:05 +0000</pubDate><guid>https://cj.rs/rusqlite-snapshot-testing/</guid><description>Snapshot testing tool for rusqlite</description><content:encoded><![CDATA[
<p style="display: flex; justify-content: space-between">
  <a href="https://github.com/cljoly/rusqlite-snapshot-testing" data-goatcounter-click="ext-github-rusqlite-snapshot-testing" data-goatcounter-title="cljoly/rusqlite-snapshot-testing">
    <span class="svgicon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
    stroke-linecap="round" stroke-linejoin="round">
    <path
        d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22">
    </path>
</svg></span>&nbsp;cljoly/rusqlite-snapshot-testing
  </a>
  <a class="badges" href="https://github.com/cljoly/rusqlite-snapshot-testing" data-goatcounter-click="ext-stargithub-rusqlite-snapshot-testing" data-goatcounter-title="stars cljoly/rusqlite-snapshot-testing">
    <img src="https://img.shields.io/github/stars/cljoly/rusqlite-snapshot-testing?style=social" alt="Github stars for rusqlite-snapshot-testing">
  </a>
</p>


<div class="badges">

<p><a href="https://docs.rs/rusqlite-snapshot-testing">
<img alt="docs.rs" loading="lazy" src="https://img.shields.io/docsrs/rusqlite-snapshot-testing"></a>
<a href="https://crates.io/crates/rusqlite-snapshot-testing">
<img alt="Crates.io" loading="lazy" src="https://img.shields.io/crates/v/rusqlite-snapshot-testing"></a>

</div>
</p>
<p>Tool to perform snapshot testing on an SQLite database, using <a href="https://crates.io/crates/rusqlite">rusqlite</a>.</p>
<p>The goal is to expose both data and the schema in the snapshots. It is also compatible with <a href="https://insta.rs">Insta Snapshots</a></p>
<p><strong>This is experimental software, expect breaking changes between 0.x versions, consistent with the semver rules for Rust.</strong></p>
<h2 id="background-reading-on-snapshot-testing">Background reading on snapshot testing.</h2>
<ul>
<li><a href="https://ianthehenry.com/posts/my-kind-of-repl/">https://ianthehenry.com/posts/my-kind-of-repl/</a></li>
<li><a href="https://tigerbeetle.com/blog/2024-05-14-snapshot-testing-for-the-masses/">https://tigerbeetle.com/blog/2024-05-14-snapshot-testing-for-the-masses/</a></li>
<li><a href="https://blog.janestreet.com/the-joy-of-expect-tests/">https://blog.janestreet.com/the-joy-of-expect-tests/</a></li>
</ul>
]]></content:encoded></item><item><title>Rusqlite Changelog</title><link>https://cj.rs/rusqlite_migration_docs/changelog/</link><pubDate>Mon, 24 Mar 2025 20:32:05 +0000</pubDate><guid>https://cj.rs/rusqlite_migration_docs/changelog/</guid><description>&lt;p&gt;Release notes for the &lt;a href="https://cj.rs/rusqlite_migration"&gt;rusqlite_migration library&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="version-250"&gt;Version 2.5.0&lt;/h2&gt;
&lt;h3 id="dependencies"&gt;Dependencies&lt;/h3&gt;
&lt;p&gt;Rusqlite was updated from 0.38.0 to 0.39.0.
Please see &lt;a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.39.0"&gt;the release notes for 0.39.0&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Update other dev dependencies, see git history for details.&lt;/p&gt;
&lt;h2 id="version-241"&gt;Version 2.4.1&lt;/h2&gt;
&lt;h3 id="documentation"&gt;Documentation&lt;/h3&gt;
&lt;p&gt;Attempt to fix the docs.rs build which started failing in 2.4.0.&lt;/p&gt;
&lt;h3 id="dependencies-1"&gt;Dependencies&lt;/h3&gt;
&lt;p&gt;Update some dev dependencies, see git history for details.&lt;/p&gt;
&lt;h2 id="version-240"&gt;Version 2.4.0&lt;/h2&gt;
&lt;h3 id="dependencies-2"&gt;Dependencies&lt;/h3&gt;
&lt;p&gt;Rusqlite was updated from 0.37.0 to 0.38.0.
Please see &lt;a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.38.0"&gt;the release notes for 0.38.0&lt;/a&gt;, there are a few breaking changes in this one.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Release notes for the <a href="https://cj.rs/rusqlite_migration">rusqlite_migration library</a>.</p>
<h2 id="version-250">Version 2.5.0</h2>
<h3 id="dependencies">Dependencies</h3>
<p>Rusqlite was updated from 0.38.0 to 0.39.0.
Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.39.0">the release notes for 0.39.0</a>.</p>
<p>Update other dev dependencies, see git history for details.</p>
<h2 id="version-241">Version 2.4.1</h2>
<h3 id="documentation">Documentation</h3>
<p>Attempt to fix the docs.rs build which started failing in 2.4.0.</p>
<h3 id="dependencies-1">Dependencies</h3>
<p>Update some dev dependencies, see git history for details.</p>
<h2 id="version-240">Version 2.4.0</h2>
<h3 id="dependencies-2">Dependencies</h3>
<p>Rusqlite was updated from 0.37.0 to 0.38.0.
Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.38.0">the release notes for 0.38.0</a>, there are a few breaking changes in this one.</p>
<p>Update other dev dependencies, see git history for details.</p>
<h3 id="features">Features</h3>
<p>Rusqlite 0.38 makes the cache statement optional. This feature was used for <a href="https://docs.rs/rusqlite_migration/2.3.0/rusqlite_migration/struct.M.html#method.foreign_key_check">foreign key checks</a>. The <code>rusqlite_migration</code> library does not enable any features from rusqlite, not even the default one. This way, downstream users can freely chose which feature to enable based on their needs. As a result, <code>rusqlite_migration</code> now handles statement caching for foreign key checks internally now. As side benefit, this also makes caching more efficient: the prepared statement is kept for the minimum time where it is needed and freed immediately, without taking space in the global cache used by rusqlite.</p>
<h3 id="other">Other</h3>
<ul>
<li>Use scoped GitHub tokens in actions, with as little privileges as possible.</li>
<li>Improve test build time by removing some unused optional deps.</li>
<li>Update most dependencies after a cooldown (this does not apply to security updates).</li>
<li>Errors don’t use debug output anymore, they should be more friendly to humans. This is not considered a breaking change because <code>Dislay</code> of errors is meant for human consuption and not for flow control in the program.</li>
</ul>
<h2 id="version-230">Version 2.3.0</h2>
<h3 id="dependencies-3">Dependencies</h3>
<p>Rusqlite was updated from 0.36.0 to 0.37.0.
Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.37.0">the release notes for 0.37.0</a>.</p>
<h3 id="other-1">Other</h3>
<ul>
<li>Misc. clippy fixes</li>
<li>Minor improvements to the example in the Readme</li>
</ul>
<h2 id="version-220">Version 2.2.0</h2>




  
  
  
  

  <div class="alert alert-note">
    <p class="alert-heading">
      ℹ️
      
        Note
      
    </p>
    <p>The code of this version is identical to <a href="#version-220-beta-1">Version 2.2.0 Beta 1</a></p>
  </div>



<h3 id="features-1">Features</h3>
<ul>
<li>Implement the <code>Display</code> trait for <code>M</code>. This makes it easier to print errors pertaining to a particular migration (this feature is planned for the future, in the context of more extensive migration checks)</li>
</ul>
<h3 id="dependencies-4">Dependencies</h3>
<p>Rusqlite was updated from 0.35.0 to 0.36.0.
Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.36.0">the release notes for 0.36.0</a>.</p>
<h3 id="other-2">Other</h3>
<ul>
<li>Update development dependencies</li>
<li>Improve tests to cover more cases, in particular around downward migrations</li>
<li>Add docs.rs link to Cargo metadata</li>
<li>Fix clippy warning in rust 1.87.0</li>
</ul>
<h2 id="version-220-beta-1">Version 2.2.0 Beta 1</h2>
<h3 id="features-2">Features</h3>
<ul>
<li>Implement the <code>Display</code> trait for <code>M</code>. This makes it easier to print errors pertaining to a particular migration (this feature is planned for the future, in the context of more extensive migration checks)</li>
</ul>
<h3 id="dependencies-5">Dependencies</h3>
<p>Rusqlite was updated from 0.35.0 to 0.36.0.
Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.36.0">the release notes for 0.36.0</a>.</p>
<h3 id="other-3">Other</h3>
<ul>
<li>Update development dependencies</li>
<li>Improve tests to cover more cases, in particular around downward migrations</li>
<li>Add docs.rs link to Cargo metadata</li>
<li>Fix clippy warning in rust 1.87.0</li>
</ul>
<h2 id="version-210">Version 2.1.0</h2>
<h3 id="dependencies-6">Dependencies</h3>
<p>Rusqlite was updated from 0.34.0 to 0.34.0.
Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.35.0">the release notes for 0.35.0</a>.</p>
<h2 id="version-200">Version 2.0.0</h2>
<h3 id="breaking-changes">Breaking changes</h3>
<h4 id="remove-the-alpha-async-tokio-rusqlite-feature">Remove the <code>alpha-async-tokio-rusqlite</code> Feature</h4>
<p>As the name of the feature suggest, we have had experimental support for async using tokio for a while now. Supporting that feature has been quite a big burden, introducing some duplicated code in the <code>AsyncMigrations</code> struct in particular, as well as a whole set of very similar tests. Plus the benefit of async is limited here, because everything gets executed in a blocking fashion in sqlite anyway.</p>
<p>It turns out that we don’t need the async support in rusqlite_migration for folks to use async libraries. For instance, with tokio-rusqlite, you can define migrations like in the sync context and run:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span>    <span style="color:#e06c75">async_conn</span>
</span></span><span style="display:flex;"><span>        .<span style="color:#e06c75">call_unwrap</span>(<span style="color:#56b6c2">|</span><span style="color:#e06c75">conn</span><span style="color:#56b6c2">|</span> <span style="color:#e06c75">MIGRATIONS</span>.<span style="color:#e06c75">to_latest</span>(<span style="color:#e06c75">conn</span>))
</span></span><span style="display:flex;"><span>        .<span style="color:#c678dd">await</span><span style="color:#56b6c2">?</span>;
</span></span></code></pre></div><p>See <a href="https://github.com/cljoly/rusqlite_migration/blob/master/examples/async/src/main.rs">the updated async example</a> for details, in particular why it’s fine to call <a href="https://docs.rs/tokio-rusqlite/0.6.0/tokio_rusqlite/struct.Connection.html#method.call_unwrap">a method</a> with unwrap in its name.</p>
<h4 id="make-the-builder-finalizer-method-not-generic">Make the Builder <code>Finalizer</code> Method Not Generic</h4>
<p>On a related note, now that we have removed the <code>AsyncMigrations</code> (see the section right above) struct, we only have <code>Migrations</code> so there is no need for the <code>MigrationsBuilder.finalize</code> method to be generic. Thus we removed the generic argument. To update your code, you can just do this:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span><span style="color:#e06c75">-        .finalize::&lt;Migrations&gt;());
</span></span></span><span style="display:flex;"><span><span style="color:#98c379;font-weight:bold">+        .finalize());
</span></span></span></code></pre></div><h4 id="remove-migrationsnew_iter">Remove <code>Migrations::new_iter</code></h4>
<p>This function has been deprecated for a while now, remove it as a part of the major version bump. You can use the standard <code>FromIter</code> trait implementation instead.</p>
<h3 id="behavior-change">Behavior Change</h3>
<ul>
<li>When the <a href="https://www.sqlite.org/fileformat.html#user_version_number">user version field</a> is altered by other code in your application, we are now returning an explicit error (<code>Error::InvalidUserVersion</code>) when this can be detected. Previously, the library would silently misbehave.</li>
</ul>
<h3 id="features-3">Features</h3>
<ul>
<li>Add the new <a href="https://docs.rs/rusqlite_migration/2.0.0-beta.1/rusqlite_migration/struct.Migrations.html#method.from_slice"><code>Migrations::from_slice</code></a> constructor, which is <code>const</code> and takes a slice, so that it can be constructed in global constant, without using <code>LazyLock</code> or similar. Internally, this is possible because we now use a <a href="https://doc.rust-lang.org/std/borrow/enum.Cow.html"><code>Cow</code></a> structure to hold migrations.</li>
<li>Add <a href="https://docs.rs/rusqlite_migration/2.0.0-beta.1/rusqlite_migration/struct.Migrations.html#method.pending_migrations"><code>Migrations::pending_migrations</code></a> which returns the number of migrations that would be applied. This is mostly useful to take a backup of the database prior to applying migrations (and do nothing if no migrations will be applied).</li>
</ul>
<h3 id="dependencies-7">Dependencies</h3>
<p>Rusqlite was updated from 0.32.1 to 0.34.0.
Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.34.0">the release notes for 0.34.0</a> and
<a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.33.0">the release notes for 0.33.0</a>.
Tokio Rusqlite was removed as a dependency.</p>
<h3 id="minimum-rust-version">Minimum Rust Version</h3>
<p>Rust 1.84.</p>
<p>Moving forward, we expect to keep this aligned with rusqlite itself, now that it has a <a href="https://github.com/rusqlite/rusqlite?tab=readme-ov-file#minimum-supported-rust-version-msrv">policy</a> (introduced in <a href="https://github.com/rusqlite/rusqlite/pull/1576">october 2024</a>).</p>
<h2 id="version-200-beta-1">Version 2.0.0 Beta 1</h2>
<h3 id="features-4">Features</h3>
<ul>
<li>Add the new <a href="https://docs.rs/rusqlite_migration/2.0.0-beta.1/rusqlite_migration/struct.Migrations.html#method.from_slice"><code>Migrations::from_slice</code></a> constructor, which is <code>const</code> and takes a slice, so that it can be constructed in global constant, without using <code>LazyLock</code> or similar. Internally, this is possible because we now use a <a href="https://doc.rust-lang.org/std/borrow/enum.Cow.html"><code>Cow</code></a> structure to hold migrations.</li>
<li>Add <a href="https://docs.rs/rusqlite_migration/2.0.0-beta.1/rusqlite_migration/struct.Migrations.html#method.pending_migrations"><code>Migrations::pending_migrations</code></a> which returns the number of migrations that would be applied. This is mostly useful to take a backup of the database prior to applying migrations (and do nothing if no migrations will be applied).</li>
</ul>
<h2 id="version-200-alpha-1">Version 2.0.0 Alpha 1</h2>
<h3 id="breaking-changes-1">Breaking changes</h3>
<h4 id="remove-the-alpha-async-tokio-rusqlite-feature-1">Remove the <code>alpha-async-tokio-rusqlite</code> Feature</h4>
<p>As the name of the feature suggest, we have had experimental support for async using tokio for a while now. Supporting that feature has been quite a big burden, introducing some duplicated code in the <code>AsyncMigrations</code> struct in particular, as well as a whole set of very similar tests. Plus the benefit of async is limited here, because everything gets executed in a blocking fashion in sqlite anyway.</p>
<p>It turns out that we don’t need the async support in rusqlite_migration for folks to use async libraries. For instance, with tokio-rusqlite, you can define migrations like in the sync context and run:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span>    <span style="color:#e06c75">async_conn</span>
</span></span><span style="display:flex;"><span>        .<span style="color:#e06c75">call_unwrap</span>(<span style="color:#56b6c2">|</span><span style="color:#e06c75">conn</span><span style="color:#56b6c2">|</span> <span style="color:#e06c75">MIGRATIONS</span>.<span style="color:#e06c75">to_latest</span>(<span style="color:#e06c75">conn</span>))
</span></span><span style="display:flex;"><span>        .<span style="color:#c678dd">await</span><span style="color:#56b6c2">?</span>;
</span></span></code></pre></div><p>See <a href="https://github.com/cljoly/rusqlite_migration/blob/master/examples/async/src/main.rs">the updated async example</a> for details, in particular why it’s fine to call <a href="https://docs.rs/tokio-rusqlite/0.6.0/tokio_rusqlite/struct.Connection.html#method.call_unwrap">a method</a> with unwrap in its name.</p>
<h4 id="make-the-builder-finalizer-method-not-generic-1">Make the Builder <code>Finalizer</code> Method Not Generic</h4>
<p>On a related note, now that we have removed the <code>AsyncMigrations</code> (see the section right above) struct, we only have <code>Migrations</code> so there is no need for the <code>MigrationsBuilder.finalize</code> method to be generic. Thus we removed the generic argument. To update your code, you can just do this:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span><span style="color:#e06c75">-        .finalize::&lt;Migrations&gt;());
</span></span></span><span style="display:flex;"><span><span style="color:#98c379;font-weight:bold">+        .finalize());
</span></span></span></code></pre></div><h4 id="remove-migrationsnew_iter-1">Remove <code>Migrations::new_iter</code></h4>
<p>This function has been deprecated for a while now, remove it as a part of the major version bump. You can use the standard <code>FromIter</code> trait implementation instead.</p>
<h3 id="behavior-change-1">Behavior Change</h3>
<ul>
<li>When the <a href="https://www.sqlite.org/fileformat.html#user_version_number">user version field</a> is altered by other code in your application, we are now returning an explicit error (<code>Error::InvalidUserVersion</code>) when this can be detected. Previously, the library would silently misbehave.</li>
</ul>
<h3 id="dependencies-8">Dependencies</h3>
<p>Rusqlite was updated from 0.32.1 to 0.34.0.
Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.34.0">the release notes for 0.34.0</a> and
<a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.33.0">the release notes for 0.33.0</a>.
Tokio Rusqlite was removed as a dependency.</p>
<h3 id="features-5">Features</h3>
<ul>
<li><code>Migrations::new</code> is now <code>const</code></li>
</ul>
<h3 id="minimum-rust-version-1">Minimum Rust Version</h3>
<p>Rust 1.84.</p>
<p>Moving forward, we expect to keep this aligned with rusqlite itself, now that it has a <a href="https://github.com/rusqlite/rusqlite?tab=readme-ov-file#minimum-supported-rust-version-msrv">policy</a> (introduced in <a href="https://github.com/rusqlite/rusqlite/pull/1576">october 2024</a>).</p>
<h2 id="version-131">Version 1.3.1</h2>
<p>The only change is a fix to the deps.rs badge in the documentation.</p>
<h2 id="version-130">Version 1.3.0</h2>




  
  
  
  

  <div class="alert alert-note">
    <p class="alert-heading">
      ℹ️
      
        Note
      
    </p>
    <p>The code of this version is identical to <a href="#version-130-beta-1">Version 1.3.0 Beta 1</a></p>
  </div>



<p>Rusqlite was updated from 0.31.0 to 0.32.1.
Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.32.0">the release notes for 0.32.0</a> and
<a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.32.1">for 0.32.1</a>.
Tokio Rusqlite was updated from 0.5.1 to 0.6.0.
Please see the <a href="https://github.com/programatik29/tokio-rusqlite/releases/tag/v0.6.0">release notes</a>.</p>
<h3 id="minimum-rust-version-2">Minimum Rust Version</h3>
<p>Rust 1.77</p>
<h3 id="documentation-1">Documentation</h3>
<p>Various documentation improvements and clarification. In particular, call out that if a rusqlite error is encountered during a migration, the next migrations in the list are not applied.</p>
<h3 id="other-4">Other</h3>
<ul>
<li>Apply minor or patch updates to the dependencies</li>
<li>Update development dependencies</li>
<li>Make CI testing more reproducible by forcing the use of Cargo.lock</li>
</ul>
<h2 id="version-130-beta-1">Version 1.3.0 Beta 1</h2>
<p>This reintroduces the async features temporarily removed from <a href="#version-130-alpha-without-tokio-1">Version 1.3.0 Alpha-Without-Tokio 1</a></p>
<p>Rusqlite was updated from 0.31.0 to 0.32.1.
Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.32.0">the release notes for 0.32.0</a> and
<a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.32.1">for 0.32.1</a>.
Tokio Rusqlite was updated from 0.5.1 to 0.6.0.
Please see the <a href="https://github.com/programatik29/tokio-rusqlite/releases/tag/v0.6.0">release notes</a>.</p>
<h3 id="minimum-rust-version-3">Minimum Rust Version</h3>
<p>Rust 1.77</p>
<h3 id="documentation-2">Documentation</h3>
<p>Various documentation improvements and clarification. In particular, call out that if a rusqlite error is encountered during a migration, the next migrations in the list are not applied.</p>
<h3 id="other-5">Other</h3>
<ul>
<li>Apply minor or patch updates to the dependencies</li>
<li>Update development dependencies</li>
<li>Make CI testing more reproducible by forcing the use of Cargo.lock</li>
</ul>
<h2 id="version-130-alpha-without-tokio-1">Version 1.3.0 Alpha-Without-Tokio 1</h2>
<h3 id="major-changes">Major Changes</h3>
<p>This is an alpha version to start integrating rusqlite 0.32.1. Unfortunately, at this time, tokio-rusqlite is did not update to rusqlite 0.32.1. So we are temporarily removing the async features, while we figure out a way to bring them back. <strong>To be clear, we intend to support the async features going forward, this is a temporary change in a specifically tagged version</strong>.</p>
<p>Rusqlite was updated from 0.31.0 to 0.32.1. Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.32.0">the release notes for 0.32.0</a> and
<a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.32.1">for 0.32.1</a></p>
<h3 id="minimum-rust-version-4">Minimum Rust Version</h3>
<p>Rust 1.77</p>
<h3 id="documentation-3">Documentation</h3>
<p>Various documentation improvements and clarification. In particular, call out that if a rusqlite error is encountered during a migration, the next migrations in the list are not applied.</p>
<h3 id="other-6">Other</h3>
<ul>
<li>Apply minor or patch updates to the dependencies</li>
<li>Update development dependencies</li>
<li>Make CI testing more reproducible by forcing the use of Cargo.lock</li>
</ul>
<h2 id="version-120">Version 1.2.0</h2>
<p><em>Same code as version 1.2.0-beta.1</em></p>
<h3 id="documentation-4">Documentation</h3>
<ul>
<li>Improved the badges a little bit</li>
</ul>
<h2 id="version-120-beta-1">Version 1.2.0 Beta 1</h2>
<p>Small release, mainly to update dependencies.</p>
<h3 id="minimum-rust-version-5">Minimum Rust Version</h3>
<p>Now using edition 2021, but the minimum rust version is still 1.70</p>
<h3 id="new-features">New Features</h3>
<p>No new features.</p>
<h3 id="other-7">Other</h3>
<ul>
<li>Update rusqlite to 0.31</li>
<li>Update various development dependencies</li>
<li>Improve CI build time</li>
<li>Impove documentation</li>
<li>Fix some broken examples</li>
</ul>
<h3 id="see-also">See also</h3>
<p>Rusqlite was updated from 0.30 to 0.31. Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.31.0">its release notes</a></p>
<h2 id="version-110">Version 1.1.0</h2>
<p><em>Same code as version 1.1.0-beta.1</em></p>
<h3 id="minimum-rust-version-6">Minimum Rust Version</h3>
<p>Rust 1.70</p>
<h3 id="new-features-1">New Features</h3>
<ul>
<li>Support for tokio-rusqlite behind the feature named <code>alpha-async-tokio-rusqlite</code>thanks to <a href="https://github.com/czocher">@czocher</a>. See <a href="https://github.com/cljoly/rusqlite_migration/tree/c54951d22691432fbfd511cc68f1c5b8a2306737/examples/async">the example</a>. This feature is alpha, meaning that compatibility in future minor versions is not guaranteed.</li>
<li>Create migrations from directories holding SQL files thanks to <a href="https://github.com/czocher">@czocher</a>. See <a href="https://github.com/cljoly/rusqlite_migration/tree/af4da527ff75e3b8c089d2300cab7fbe66096411/examples/from-directory">the example</a>.</li>
<li>Add up/down hooks to run custom Rust code during migrations (<a href="https://github.com/cljoly/rusqlite_migration/pull/28">PR</a> thanks to <a href="https://github.com/matze">@matze</a>)</li>
<li>Add foreign_key_check method to migrations (<a href="https://github.com/cljoly/rusqlite_migration/pull/20">PR</a> thanks to <a href="https://github.com/Jokler">@Jokler</a>)</li>
<li>Make <code>Migration</code> functions const (<a href="https://github.com/cljoly/rusqlite_migration/pull/19">PR</a> thanks to <a href="https://github.com/fkaa">@fkaa</a>)</li>
<li>Make <code>Migrations</code> serializable (using the Debug serializer) with <a href="https://insta.rs">insta</a>.</li>
</ul>
<h3 id="depreciation">Depreciation</h3>
<ul>
<li>Mark <code>Migrations::from_iter</code> as deprecated</li>
</ul>
<h3 id="other-8">Other</h3>
<ul>
<li>Documentation improvements
<ul>
<li>Repository metadata improvements</li>
</ul>
</li>
<li>Code quality improvements
<ul>
<li>Introduce cargo mutants &amp; fix bugs found</li>
<li>Clippy warning fixes and other linter improvements</li>
<li>Report on test coverage &amp; improve test coverage</li>
<li>Add benchmarks</li>
</ul>
</li>
<li>Made errors returned more precise</li>
<li>Updated dependencies</li>
</ul>
<h3 id="see-also-1">See also</h3>
<p>Rusqlite was updated from 0.29.0 to 0.30.0. Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.30.0">its release notes</a></p>
<h2 id="version-110-beta-1">Version 1.1.0 Beta 1</h2>
<p><strong>⚠️ The APIs exposed in this version may be unstable.</strong></p>
<p>Summing up all the changes from the previous Alpha versions.</p>
<h3 id="minimum-rust-version-7">Minimum Rust Version</h3>
<p>Rust 1.70</p>
<h3 id="new-features-2">New Features</h3>
<ul>
<li>Support for tokio-rusqlite behind the feature named <code>alpha-async-tokio-rusqlite</code>thanks to <a href="https://github.com/czocher">@czocher</a>. See <a href="https://github.com/cljoly/rusqlite_migration/tree/c54951d22691432fbfd511cc68f1c5b8a2306737/examples/async">the example</a>. This feature is alpha, meaning that compatibility in future minor versions is not guaranteed.</li>
<li>Create migrations from directories holding SQL files thanks to <a href="https://github.com/czocher">@czocher</a>. See <a href="https://github.com/cljoly/rusqlite_migration/tree/af4da527ff75e3b8c089d2300cab7fbe66096411/examples/from-directory">the example</a>.</li>
<li>Add up/down hooks to run custom Rust code during migrations (<a href="https://github.com/cljoly/rusqlite_migration/pull/28">PR</a> thanks to <a href="https://github.com/matze">@matze</a>)</li>
<li>Add foreign_key_check method to migrations (<a href="https://github.com/cljoly/rusqlite_migration/pull/20">PR</a> thanks to <a href="https://github.com/Jokler">@Jokler</a>)</li>
<li>Make <code>Migration</code> functions const (<a href="https://github.com/cljoly/rusqlite_migration/pull/19">PR</a> thanks to <a href="https://github.com/fkaa">@fkaa</a>)</li>
<li>Make <code>Migrations</code> serializable (using the Debug serializer) with <a href="https://insta.rs">insta</a>.</li>
</ul>
<h3 id="depreciation-1">Depreciation</h3>
<ul>
<li>Mark <code>Migrations::from_iter</code> as deprecated</li>
</ul>
<h3 id="other-9">Other</h3>
<ul>
<li>Documentation improvements
<ul>
<li>Repository metadata improvements</li>
</ul>
</li>
<li>Code quality improvements
<ul>
<li>Introduce cargo mutants &amp; fix bugs found</li>
<li>Clippy warning fixes and other linter improvements</li>
<li>Report on test coverage &amp; improve test coverage</li>
<li>Add benchmarks</li>
</ul>
</li>
<li>Made errors returned more precise</li>
<li>Updated dependencies</li>
</ul>
<h3 id="see-also-2">See also</h3>
<p>Rusqlite was updated from 0.29.0 to 0.30.0. Please see <a href="https://github.com/rusqlite/rusqlite/releases/tag/v0.30.0">its release notes</a></p>
<h2 id="version-110-alpha-2">Version 1.1.0 Alpha 2</h2>
<p><strong>⚠️ The APIs exposed in this version may be unstable.</strong></p>
<h3 id="minimum-rust-version-8">Minimum Rust Version</h3>
<p>Rust 1.64</p>
<h3 id="new-features-3">New Features</h3>
<ul>
<li>Create migrations from directories holding SQL files. See <a href="https://github.com/cljoly/rusqlite_migration/tree/af4da527ff75e3b8c089d2300cab7fbe66096411/examples/from-directory">the example</a>.</li>
</ul>
<h3 id="depreciation-2">Depreciation</h3>
<ul>
<li>Mark <code>Migrations::from_iter</code> as deprecated</li>
</ul>
<h3 id="other-10">Other</h3>
<ul>
<li>Documentation improvements</li>
<li>Code quality improvements
<ul>
<li>Introduce cargo mutants &amp; fix bugs found</li>
<li>Clippy warning fixes</li>
<li>Report on test coverage &amp; improve test coverage</li>
<li>Add benchmarks</li>
</ul>
</li>
<li>Made errors returned more precise</li>
<li>Update dependencies</li>
</ul>
<h2 id="version-110-alpha-1">Version 1.1.0 Alpha 1</h2>
<p><strong>⚠️ The APIs exposed in this version may be unstable.</strong></p>
<h3 id="minimum-rust-version-9">Minimum Rust Version</h3>
<p>Rust 1.61</p>
<h3 id="new-features-4">New Features</h3>
<ul>
<li>Add up/down hooks to run custom Rust code during migrations (<a href="https://github.com/cljoly/rusqlite_migration/pull/28">PR</a> thanks to <a href="https://github.com/matze">@matze</a>)
<ul>
<li>The purpose of this release is to get feedback on the new API. Please feel free to comment on <a href="https://github.com/cljoly/rusqlite_migration/discussions/36">this discussion</a>!</li>
</ul>
</li>
<li>Add foreign_key_check method to migrations (<a href="https://github.com/cljoly/rusqlite_migration/pull/20">PR</a> thanks to <a href="https://github.com/Jokler">@Jokler</a>)
<ul>
<li>Please beware of the <a href="https://github.com/cljoly/rusqlite_migration/issues/4#issuecomment-1166363260">follow up work needed on this</a></li>
</ul>
</li>
<li>Make <code>Migration</code> functions const (<a href="https://github.com/cljoly/rusqlite_migration/pull/19">PR</a> thanks to <a href="https://github.com/fkaa">@fkaa</a>)</li>
</ul>
<h3 id="other-11">Other</h3>
<ul>
<li>CI improvements</li>
<li>Linter improvements</li>
<li>Repository metadata improvements</li>
<li>Documentation improvements</li>
<li>Dev dependencies update (not dependencies of the library when used in another crate)</li>
</ul>
<h2 id="version-102">Version 1.0.2</h2>
<h3 id="bug-fix">Bug fix</h3>
<ul>
<li>fix: adapt to rusqlite 0.29 and tighten dependency requirements for rusqlite (see <a href="https://github.com/cljoly/rusqlite_migration/issues/68#issuecomment-1485795284">this discussion</a>)</li>
</ul>
<h2 id="version-101">Version 1.0.1</h2>
<h3 id="bug-fix-1">Bug Fix</h3>
<ul>
<li>fix: error instead of panicking on higher migration level (see commit ad57d92d1677420eb81c4e25635be1884f9b7ce7)</li>
</ul>
<h3 id="other-12">Other</h3>
<ul>
<li>Documentation improvements</li>
</ul>
<h2 id="version-100">Version 1.0.0</h2>
<h3 id="breaking-changes-2">Breaking changes</h3>
<ul>
<li>Remove deprecated symbols (<code>Migrations.latest</code>, <code>SchemaVersionError::MigrateToLowerNotSupported</code>)</li>
</ul>
<h3 id="other-13">Other</h3>
<ul>
<li>Documentation improvements</li>
</ul>
<h2 id="version-051">Version 0.5.1</h2>
<h3 id="potentially-breaking-changes">Potentially Breaking Changes</h3>
<ul>
<li>Update the <code>rusqlite</code> crate (to protect agaisnt <a href="https://rustsec.org/advisories/RUSTSEC-2020-0014.html">RUSTSEC-2020-0014</a>)</li>
</ul>
<h3 id="other-14">Other</h3>
<ul>
<li>Improve the documentation</li>
</ul>
<h2 id="version-050">Version 0.5.0</h2>
<ul>
<li>Update the <code>env_logger</code> dependency</li>
<li>Improve the documentation</li>
</ul>
<h2 id="version-041--042">Version 0.4.1 / 0.4.2</h2>
<ul>
<li>Update documentation</li>
</ul>
<h2 id="version-040">Version 0.4.0</h2>
<h3 id="new-features-5">New features</h3>
<ul>
<li>Add downward migrations, i.e. migrations to go to past schema version of the database. Thanks @MightyPork!</li>
<li>Unsafe code is now forbidden.</li>
</ul>
<h3 id="breaking-changes-3">Breaking changes</h3>
<ul>
<li>Rename <code>latest</code> to <code>to_latest</code>. The old symbol is deprecated and will be removed eventually.</li>
<li>An error is now returned when a migration is attempted while no migrations exist.</li>
</ul>
<h3 id="other-15">Other</h3>
<ul>
<li>Improve general rust API documentation.</li>
<li>Generate parts of the readme based on rust comments, for increased consistency with the docs.rs content.</li>
<li>Various refactoring and clean-ups.</li>
</ul>
<h2 id="version-031">Version 0.3.1</h2>
<p>Fix in readme, for crates.io</p>
<h2 id="version-03">Version 0.3</h2>
<h3 id="new-features-6">New features</h3>
<ul>
<li>Multi line sql statements like:
<pre tabindex="0"><code>M::up(r#&#34;
CREATE TABLE t1(a, b);
CREATE TABLE t2(a, b);
&#34;#)
</code></pre>are now fully supported</li>
</ul>
<h3 id="other-16">Other</h3>
<ul>
<li>Various doc &amp; CI improvements</li>
<li>Fix a case of failure with silent errors.</li>
</ul>
]]></content:encoded></item><item><title>Rusqlite Migration</title><link>https://cj.rs/rusqlite_migration/</link><pubDate>Sat, 21 Aug 2021 15:32:05 +0100</pubDate><guid>https://cj.rs/rusqlite_migration/</guid><description>↕️ Simple database schema migration library for rusqlite, written with performance in mind.</description><content:encoded><![CDATA[
<p style="display: flex; justify-content: space-between">
  <a href="https://github.com/cljoly/rusqlite_migration" data-goatcounter-click="ext-github-rusqlite_migration" data-goatcounter-title="cljoly/rusqlite_migration">
    <span class="svgicon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
    stroke-linecap="round" stroke-linejoin="round">
    <path
        d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22">
    </path>
</svg></span>&nbsp;cljoly/rusqlite_migration
  </a>
  <a class="badges" href="https://github.com/cljoly/rusqlite_migration" data-goatcounter-click="ext-stargithub-rusqlite_migration" data-goatcounter-title="stars cljoly/rusqlite_migration">
    <img src="https://img.shields.io/github/stars/cljoly/rusqlite_migration?style=social" alt="Github stars for rusqlite_migration">
  </a>
</p>


<div class="badges">

<p><a href="https://docs.rs/rusqlite_migration">
<img alt="docs.rs" loading="lazy" src="https://img.shields.io/docsrs/rusqlite_migration"></a>
<a href="https://crates.io/crates/rusqlite_migration">
<img alt="Crates.io" loading="lazy" src="https://img.shields.io/crates/v/rusqlite_migration"></a>
<a href="https://cj.rs/rusqlite_migration/changelog">

  <img alt="Changelog" loading="lazy" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2OSIgaGVpZ2h0PSIyMCIgcm9sZT0iaW1nIiBhcmlhLWxhYmVsPSJDaGFuZ2Vsb2ciPjx0aXRsZT5DaGFuZ2Vsb2c8L3RpdGxlPjxsaW5lYXJHcmFkaWVudCBpZD0icyIgeDI9IjAiIHkyPSIxMDAlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNiYmIiIHN0b3Atb3BhY2l0eT0iLjEiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3Atb3BhY2l0eT0iLjEiLz48L2xpbmVhckdyYWRpZW50PjxjbGlwUGF0aCBpZD0iciI+PHJlY3Qgd2lkdGg9IjY5IiBoZWlnaHQ9IjIwIiByeD0iMyIgZmlsbD0iI2ZmZiIvPjwvY2xpcFBhdGg+PGcgY2xpcC1wYXRoPSJ1cmwoI3IpIj48cmVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIyMCIgZmlsbD0icHVycGxlIi8+PHJlY3QgeD0iMCIgd2lkdGg9IjY5IiBoZWlnaHQ9IjIwIiBmaWxsPSJwdXJwbGUiLz48cmVjdCB3aWR0aD0iNjkiIGhlaWdodD0iMjAiIGZpbGw9InVybCgjcykiLz48L2c+PGcgZmlsbD0iI2ZmZiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1mYW1pbHk9IlZlcmRhbmEsR2VuZXZhLERlamFWdSBTYW5zLHNhbnMtc2VyaWYiIHRleHQtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iIGZvbnQtc2l6ZT0iMTEwIj48dGV4dCBhcmlhLWhpZGRlbj0idHJ1ZSIgeD0iMzQ1IiB5PSIxNTAiIGZpbGw9IiMwMTAxMDEiIGZpbGwtb3BhY2l0eT0iLjMiIHRyYW5zZm9ybT0ic2NhbGUoLjEpIiB0ZXh0TGVuZ3RoPSI1OTAiPkNoYW5nZWxvZzwvdGV4dD48dGV4dCB4PSIzNDUiIHk9IjE0MCIgdHJhbnNmb3JtPSJzY2FsZSguMSkiIGZpbGw9IiNmZmYiIHRleHRMZW5ndGg9IjU5MCI+Q2hhbmdlbG9nPC90ZXh0PjwvZz48L3N2Zz4="></a>
<a href="https://github.com/rust-secure-code/safety-dance/">

  <img alt="unsafe forbidden" loading="lazy" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMTAiIGhlaWdodD0iMjAiIHJvbGU9ImltZyIgYXJpYS1sYWJlbD0idW5zYWZlOiBmb3JiaWRkZW4iPjx0aXRsZT51bnNhZmU6IGZvcmJpZGRlbjwvdGl0bGU+PGxpbmVhckdyYWRpZW50IGlkPSJzIiB4Mj0iMCIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2JiYiIgc3RvcC1vcGFjaXR5PSIuMSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1vcGFjaXR5PSIuMSIvPjwvbGluZWFyR3JhZGllbnQ+PGNsaXBQYXRoIGlkPSJyIj48cmVjdCB3aWR0aD0iMTEwIiBoZWlnaHQ9IjIwIiByeD0iMyIgZmlsbD0iI2ZmZiIvPjwvY2xpcFBhdGg+PGcgY2xpcC1wYXRoPSJ1cmwoI3IpIj48cmVjdCB3aWR0aD0iNDciIGhlaWdodD0iMjAiIGZpbGw9IiM1NTUiLz48cmVjdCB4PSI0NyIgd2lkdGg9IjYzIiBoZWlnaHQ9IjIwIiBmaWxsPSIjNGMxIi8+PHJlY3Qgd2lkdGg9IjExMCIgaGVpZ2h0PSIyMCIgZmlsbD0idXJsKCNzKSIvPjwvZz48ZyBmaWxsPSIjZmZmIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LWZhbWlseT0iVmVyZGFuYSxHZW5ldmEsRGVqYVZ1IFNhbnMsc2Fucy1zZXJpZiIgdGV4dC1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiIgZm9udC1zaXplPSIxMTAiPjx0ZXh0IGFyaWEtaGlkZGVuPSJ0cnVlIiB4PSIyNDUiIHk9IjE1MCIgZmlsbD0iIzAxMDEwMSIgZmlsbC1vcGFjaXR5PSIuMyIgdHJhbnNmb3JtPSJzY2FsZSguMSkiIHRleHRMZW5ndGg9IjM3MCI+dW5zYWZlPC90ZXh0Pjx0ZXh0IHg9IjI0NSIgeT0iMTQwIiB0cmFuc2Zvcm09InNjYWxlKC4xKSIgZmlsbD0iI2ZmZiIgdGV4dExlbmd0aD0iMzcwIj51bnNhZmU8L3RleHQ+PHRleHQgYXJpYS1oaWRkZW49InRydWUiIHg9Ijc3NSIgeT0iMTUwIiBmaWxsPSIjMDEwMTAxIiBmaWxsLW9wYWNpdHk9Ii4zIiB0cmFuc2Zvcm09InNjYWxlKC4xKSIgdGV4dExlbmd0aD0iNTMwIj5mb3JiaWRkZW48L3RleHQ+PHRleHQgeD0iNzc1IiB5PSIxNDAiIHRyYW5zZm9ybT0ic2NhbGUoLjEpIiBmaWxsPSIjZmZmIiB0ZXh0TGVuZ3RoPSI1MzAiPmZvcmJpZGRlbjwvdGV4dD48L2c+PC9zdmc+"></a>
<a href="https://coveralls.io/github/cljoly/rusqlite_migration">
<img alt="Coveralls" loading="lazy" src="https://img.shields.io/coverallsCoverage/github/cljoly/rusqlite_migration"></a></p>

</div>

<p>Rusqlite Migration is a performant and simple schema migration library for <a href="https://crates.io/crates/rusqlite">rusqlite</a>.</p>
<ul>
<li><strong>Performance</strong>:
<ul>
<li><em>Fast database opening</em>: to keep track of the current migration state, most tools create one or more tables in the database. These tables require parsing by SQLite and are queried with SQL statements. This library uses the <a href="https://sqlite.org/pragma.html#pragma_user_version"><code>user_version</code></a> value instead. It’s much lighter as it is just an integer at a <a href="https://www.sqlite.org/fileformat.html#user_version_number">fixed offset</a> in the SQLite file.</li>
<li><em>Fast compilation</em>: this crate is very small and does not use macros to define the migrations.</li>
</ul>
</li>
<li><strong>Simplicity</strong>: this crate strives for simplicity. Just define a set of SQL statements as strings in your Rust code. Add more SQL statements over time as needed. No external CLI required. Additionally, rusqlite_migration works especially well with other small libraries complementing rusqlite, like <a href="https://crates.io/crates/serde_rusqlite">serde_rusqlite</a>.</li>
</ul>
<h2 id="example">Example</h2>
<p>Here, we define SQL statements to run with <a href="https://docs.rs/rusqlite_migration/latest/rusqlite_migration/struct.Migrations.html#method.new"><code>Migrations::new()</code></a> and run these (if necessary) with <a href="https://docs.rs/rusqlite_migration/latest/rusqlite_migration/struct.Migrations.html#method.to_latest"><code>Migrations::to_latest()</code></a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#c678dd">use</span> <span style="color:#e06c75">rusqlite</span>::{<span style="color:#e06c75">params</span>, <span style="color:#e06c75">Connection</span>};
</span></span><span style="display:flex;"><span><span style="color:#c678dd">use</span> <span style="color:#e06c75">rusqlite_migration</span>::{<span style="color:#e06c75">Migrations</span>, <span style="color:#e06c75">M</span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#7f848e">// 1️⃣ Define migrations
</span></span></span><span style="display:flex;"><span><span style="color:#c678dd">const</span> <span style="color:#e06c75">MIGRATIONS_SLICE</span>: <span style="color:#c678dd">&amp;</span>[<span style="color:#e06c75">M</span><span style="color:#56b6c2">&lt;</span><span style="color:#e5c07b">&#39;_</span><span style="color:#56b6c2">&gt;</span>] <span style="color:#56b6c2">=</span> <span style="color:#56b6c2">&amp;</span>[
</span></span><span style="display:flex;"><span>    <span style="color:#e06c75">M</span>::<span style="color:#e06c75">up</span>(<span style="color:#98c379">&#34;CREATE TABLE friend(name TEXT NOT NULL);&#34;</span>),
</span></span><span style="display:flex;"><span>    <span style="color:#7f848e">// In the future, add more migrations here:
</span></span></span><span style="display:flex;"><span>    <span style="color:#7f848e">//M::up(&#34;ALTER TABLE friend ADD COLUMN email TEXT;&#34;),
</span></span></span><span style="display:flex;"><span>];
</span></span><span style="display:flex;"><span><span style="color:#c678dd">const</span> <span style="color:#e06c75">MIGRATIONS</span>: <span style="color:#e5c07b">Migrations</span><span style="color:#56b6c2">&lt;</span><span style="color:#e5c07b">&#39;_</span><span style="color:#56b6c2">&gt;</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">Migrations</span>::<span style="color:#e06c75">from_slice</span>(<span style="color:#e06c75">MIGRATIONS_SLICE</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#c678dd">fn</span> <span style="color:#61afef;font-weight:bold">main</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#c678dd">let</span> <span style="color:#c678dd">mut</span> <span style="color:#e06c75">conn</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">Connection</span>::<span style="color:#e06c75">open_in_memory</span>().<span style="color:#e06c75">unwrap</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#7f848e">// Apply some PRAGMA, often better to do it outside of migrations
</span></span></span><span style="display:flex;"><span>    <span style="color:#e06c75">conn</span>.<span style="color:#e06c75">pragma_update_and_check</span>(<span style="color:#e5c07b">None</span>, <span style="color:#98c379">&#34;journal_mode&#34;</span>, <span style="color:#56b6c2">&amp;</span><span style="color:#98c379">&#34;WAL&#34;</span>, <span style="color:#56b6c2">|</span><span style="color:#e06c75">_</span><span style="color:#56b6c2">|</span> <span style="color:#e5c07b">Ok</span>(()))
</span></span><span style="display:flex;"><span>        .<span style="color:#e06c75">unwrap</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#7f848e">// 2️⃣ Update the database schema, atomically
</span></span></span><span style="display:flex;"><span>    <span style="color:#e06c75">MIGRATIONS</span>.<span style="color:#e06c75">to_latest</span>(<span style="color:#56b6c2">&amp;</span><span style="color:#c678dd">mut</span> <span style="color:#e06c75">conn</span>).<span style="color:#e06c75">unwrap</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#7f848e">// 3️⃣ Use the database 🥳
</span></span></span><span style="display:flex;"><span>    <span style="color:#e06c75">conn</span>.<span style="color:#e06c75">execute</span>(<span style="color:#98c379">&#34;INSERT INTO friend (name) VALUES (?1)&#34;</span>, <span style="color:#56b6c2;font-weight:bold">params!</span>[<span style="color:#98c379">&#34;John&#34;</span>])
</span></span><span style="display:flex;"><span>        .<span style="color:#e06c75">unwrap</span>();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Please see the <a href="https://github.com/cljoly/rusqlite_migrate/tree/master/examples">examples</a> folder for more, in particular:</p>
<ul>
<li>migrations with multiple SQL statements (using for instance <code>r#&quot;…&quot;</code> or <code>include_str!(…)</code>)</li>
<li>migrations defined <a href="https://github.com/cljoly/rusqlite_migration/tree/master/examples/from-directory">from a directory</a> with SQL files</li>
<li>migrations to <a href="https://github.com/cljoly/rusqlite_migration/blob/master/examples/simple/src/main.rs">previous versions (downward migrations)</a></li>
<li>migrations <a href="https://github.com/cljoly/rusqlite_migration/blob/master/examples/async/src/main.rs">when using <code>async</code></a></li>
</ul>
<p>I’ve also made a <a href="https://cj.rs/blog/sqlite-pragma-cheatsheet-for-performance-and-consistency/">cheatsheet of SQLite pragma for improved performance and consistency</a>.</p>
<h3 id="built-in-tests">Built-in tests</h3>
<p>To test that the migrations are working, you can add this in your test module:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#7f848e">#[test]</span>
</span></span><span style="display:flex;"><span><span style="color:#c678dd">fn</span> <span style="color:#61afef;font-weight:bold">migrations_test</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#56b6c2;font-weight:bold">assert!</span>(<span style="color:#e06c75">MIGRATIONS</span>.<span style="color:#e06c75">validate</span>().<span style="color:#e06c75">is_ok</span>());
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The migrations object is also suitable for serialisation with <a href="https://insta.rs/">insta</a>, using the <code>Debug</code> serialisation. You can store a snapshot of your migrations like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#7f848e">#[test]</span>
</span></span><span style="display:flex;"><span><span style="color:#c678dd">fn</span> <span style="color:#61afef;font-weight:bold">migrations_insta_snapshot</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#c678dd">let</span> <span style="color:#e06c75">migrations</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">Migrations</span>::<span style="color:#e06c75">new</span>(<span style="color:#56b6c2;font-weight:bold">vec!</span>[
</span></span><span style="display:flex;"><span>        <span style="color:#7f848e">// ...
</span></span></span><span style="display:flex;"><span>    ]);
</span></span><span style="display:flex;"><span>    <span style="color:#e06c75">insta</span>::<span style="color:#56b6c2;font-weight:bold">assert_debug_snapshot!</span>(<span style="color:#e06c75">migrations</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="optional-features">Optional Features</h2>
<p>Rusqlite migration provides several <a href="https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section">Cargo features</a>. They are:</p>
<ul>
<li><code>from-directory</code>: enable loading migrations from *.sql files in a given directory</li>
</ul>
<h2 id="active-users">Active Users</h2>

<div class="badges">

<p><a href="https://crates.io/crates/rusqlite_migration">
<img alt="Crates.io Downloads" loading="lazy" src="https://img.shields.io/crates/d/rusqlite_migration?style=social"></a> <a href="https://crates.io/crates/rusqlite_migration">
<img alt="Crates.io Downloads (recent)" loading="lazy" src="https://img.shields.io/crates/dr/rusqlite_migration?style=social"></a></p>

</div>

<p>This crate is actively used in a number of projects. You can find up-to-date list of those on:</p>
<ul>
<li><a href="https://crates.io/crates/rusqlite_migration/reverse_dependencies">crates.io</a> / <a href="https://lib.rs/crates/rusqlite_migration/rev">lib.rs</a></li>
<li><a href="https://github.com/cljoly/rusqlite_migration/network/dependents?dependent_type=REPOSITORY">GitHub’s list of dependent repositories</a></li>
</ul>
<p>A number of contributors are also reporting issues as they arise, another indicator of active use.</p>
<h2 id="minimum-supported-rust-version-msrv">Minimum Supported Rust Version (MSRV)</h2>
<p>This crate extends rusqlite and as such is tightly integrated with it. Thus, it supports the <a href="https://github.com/rusqlite/rusqlite?tab=readme-ov-file#minimum-supported-rust-version-msrv">same MSRV</a> as rusqlite. At the time of writing, this means:</p>




  <figure>
    <blockquote >
      <p>Latest stable Rust version at the time of release. It might compile with older versions.</p>

    </blockquote>
    
  </figure>



<h2 id="limits">Limits</h2>
<ol>
<li>
<p>Since this crate uses the <a href="https://www.sqlite.org/fileformat.html#user_version_number"><code>user_version</code></a> field, if your program or any other library changes it, this library will behave in an unspecified way: it may return an error, apply the wrong set of migrations, do nothing at all&hellip;</p>
</li>
<li>
<p>The <a href="https://www.sqlite.org/fileformat.html#user_version_number"><code>user_version</code></a> field is effectively a i32, so there is a theoretical limit (about two billion) on the number of migrations that can be applied by this library. You are likely to hit memory limits well before that though, so in practice, you can think of the number of migrations as limitless. And you would need to create 10 000 new migrations, every day, for over 5 centuries, before getting close to the limit.</p>
</li>
</ol>
<h2 id="contributing">Contributing</h2>
<p>Contributions (documentation or code improvements in particular) are welcome, see <a href="https://cj.rs/docs/contribute/">contributing</a>!</p>
<p>We use various tools for testing that you may find helpful to install locally (e.g. to fix failing CI checks):</p>
<ul>
<li><a href="https://crates.io/crates/cargo-insta">cargo-insta</a></li>
<li><a href="https://mutants.rs/installation.html">cargo-mutants</a></li>
</ul>
<h2 id="acknowledgments">Acknowledgments</h2>
<p>I would like to thank all the contributors, as well as the authors of the dependencies this crate uses.</p>
<p>Thanks to <a href="https://www.migadu.com/">Migadu</a> for offering a discounted service to support this project. It is not an endorsement by Migadu though.</p>
]]></content:encoded></item><item><title>SQLite Pragma Cheatsheet for Performance and Consistency</title><link>https://cj.rs/blog/sqlite-pragma-cheatsheet-for-performance-and-consistency/</link><pubDate>Fri, 07 May 2021 17:33:23 +0000</pubDate><guid>https://cj.rs/blog/sqlite-pragma-cheatsheet-for-performance-and-consistency/</guid><description>Last updated: March 18, 2024.</description><content:encoded><![CDATA[



  
  
  
  

  <div class="alert alert-tldr">
    <p class="alert-heading">
      ⚡
      
        TL;DR
      
    </p>
    <h3 id="when-opening-the-db">When Opening the DB</h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">journal_mode</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">wal</span>; <span style="color:#7f848e">-- different implementation of the atomicity properties
</span></span></span><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">synchronous</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">normal</span>; <span style="color:#7f848e">-- synchronise less often to the filesystem
</span></span></span><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">foreign_keys</span> <span style="color:#56b6c2">=</span> <span style="color:#c678dd">on</span>; <span style="color:#7f848e">-- check foreign key reference, slightly worst performance
</span></span></span></code></pre></div><p>And check <code>user_version</code> to apply any migrations, for instance with this <a href="https://cj.rs/rusqlite_migration/">Rust library</a>.</p>
<h3 id="when-closing-the-db">When Closing the DB</h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">analysis_limit</span><span style="color:#56b6c2">=</span><span style="color:#d19a66">400</span>; <span style="color:#7f848e">-- make sure pragma optimize does not take too long
</span></span></span><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">optimize</span>; <span style="color:#7f848e">-- gather statistics to improve query optimization
</span></span></span></code></pre></div>
  </div>



<h2 id="introduction">Introduction</h2>
<p>SQL pragma are statements (like <code>SELECT …</code> or <code>CREATE TABLE …</code>) that change the database behaviors or call a special functions. This post is a short list of <a href="https://sqlite.org">SQLite</a> pragma I use in my projects built on SQLite, to get better performance and more consistency.</p>
<h2 id="performance">Performance</h2>
<h3 id="file-system-interactions">File system Interactions</h3>
<p>The following pragma statements set the way SQLite deals with the file system.</p>
<h4 id="journal_mode-wal">journal_mode wal</h4>
<p>By default, when applying changes, SQLite uses a rollback journal, which is basically a copy of the data before the changes. Changing the <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a> to “Write-Ahead Log” is known to bring significantly better performance in most cases. It also allows concurrent readers with one writer. To activate it, run:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">journal_mode</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">wal</span>;
</span></span></code></pre></div><p>Some less common use cases are incompatible with this journal mode, for instance having a database on a network file system. The full list of drawbacks is <a href="https://sqlite.org/wal.html">listed in the documentation</a><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<h4 id="synchronous-normal">synchronous normal</h4>
<p>To ensure integrity of the database, one of the mechanism SQLite uses is the file system synchronization operations. However, these synchronizations are quite costly. With WAL journal mode enabled, your database will still be consistent while synchronizing less often:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">synchronous</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">normal</span>;
</span></span></code></pre></div><p>Compared to the default <a href="https://sqlite.org/pragma.html#pragma_synchronous"><code>synchronous = full</code></a>, committed transactions could be rolled back if there is a power loss (although not if the application crashes).</p>
<h3 id="optimize">Optimize</h3>
<p>To execute statement as efficiently as possible, SQLite has a <a href="https://sqlite.org/queryplanner.html">query planner</a>, which tries to read the tables to provide good performance (for instance by evaluating the <code>WHERE</code> clauses that select the fewest rows first).</p>
<p>This query planner sometimes needs to know whether a column has many values or only a few, repeated values (like a boolean column would). To know this, it can’t read the whole table, as that may prove as costly as running the part of the query that is being optimized, so it uses some statistics collected in internal tables.</p>
<p>Using <a href="https://sqlite.org/pragma.html#pragma_optimize">optimize</a> right before closing the database connexion collects the statistics for some table columns. These columns are chosen mainly based on the queries executed during the connexion: if a query had benefited from more accurate statistics, the corresponding columns are analyzed.</p>
<p>For instance:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">analysis_limit</span><span style="color:#56b6c2">=</span><span style="color:#d19a66">400</span>;
</span></span><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">optimize</span>;
</span></span></code></pre></div><p>In the above example, pragma <a href="https://sqlite.org/pragma.html#pragma_analysis_limit">analysis_limit</a> ensures that <code>optimize</code> won’t run for too long, by limiting the number of rows read.</p>
<h3 id="allow-using-more-memory">Allow Using More Memory</h3>
<p>These two pragma <em>could</em> result in better performance, depending on your hardware and software configuration.</p>
<ul>
<li>Keep temporary storage in memory: <a href="https://sqlite.org/pragma.html#pragma_temp_store"><code>PRAGMA temp_store = 2</code></a>. However, setting this pragma does not guarantee that the temporary storage will be held in memory. Please refer to the documentation for other parameters that may change the final outcome.</li>
<li>Keep more of the database pages in memory: for instance, use 32 MiB of memory for this purpose with <a href="https://sqlite.org/pragma.html#pragma_cache_size"><code>PRAGMA cache_size = -32000</code></a>. Note that the OS cache is already keeping parts of the database file in RAM, so this might end up wasting memory.</li>
</ul>
<h2 id="consistency">Consistency</h2>
<h3 id="user_version">user_version</h3>
<p>The database&rsquo;s schema can evolve over time. Your application could start with a <code>car</code> table to represent a car but later on, you realize you want to represent bicycles, so you add a <code>bicycle</code> table.</p>
<p>To keep track of the different versions of the schema, some libraries maintain an internal table with a single row with a version number. It then performs migrations as needed. In our example, version 1 would have only the <code>car</code> table and version 2, also the <code>bicycle</code> table. The migration from version 1 to version 2 add the <code>bicycle</code> table.</p>
<p>SQLite offers the <a href="https://sqlite.org/pragma.html#pragma_user_version">user_version</a> pragma, to keep track of these versions. It is an integer <a href="https://sqlite.org/fileformat2.html#user_version_number">at a fixed offset</a> in the database file. It is simpler and more efficient than maintaining a table with versions, in particular because the table has to be found in the database file while the integer is available right away.</p>
<p>The drawback is that this is not portable between database engines. If you only use SQLite though, it is almost always the best option. To use it, you can write some code to check the value of the <code>user_version</code> pragma value right after opening the database. If it is lower than expected, then atomically 1) run the necessary migrations and 2) increment the <code>user_version</code> pragma value. I wrote a library to ease this task in <a href="https://cj.rs/rusqlite_migration/">rust</a> and here is an <a href="https://levlaz.org/sqlite-db-migrations-with-pragma-user_version/">example in python</a>.</p>
<h3 id="foreign_keys-on">foreign_keys on</h3>
<p>This may come as a surprise for folks with experience with other database system, but SQLite does not enforce foreign key constraints by default. Consequently, a foreign key can point to a row that does not exist.</p>
<p>This can be fixed with pragma <a href="https://sqlite.org/pragma.html#pragma_foreign_keys">foreign_keys</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">foreign_keys</span> <span style="color:#56b6c2">=</span> <span style="color:#c678dd">ON</span>;
</span></span></code></pre></div><p>This comes at a performance cost however, because more checks are performed when inserting values with foreign keys. The cost is usually negligible but your mileage may vary.</p>
<p><em>Note</em>: pragma <a href="https://sqlite.org/pragma.html#pragma_foreign_key_check">foreign_key_check</a> can be used to check a particular table for violated foreign key constraint. This can be useful before enabling <code>foreign_keys</code> on a database with existing data.</p>
<h3 id="strict">STRICT</h3>




  
  
  
  

  <div class="alert alert-important">
    <p class="alert-heading">
      🟣
      
        Important
      
    </p>
    <p>Requires SQLite version <a href="https://www.sqlite.org/releaselog/3_37_1.html">3.37.0 (2021-11-27)</a></p>
  </div>



<p>Another peculiarity of SQLite is dynamic typing through <a href="https://www.sqlite.org/datatype3.html">type affinity</a>. When you define a column of type <code>INTEGER</code> in most other database engines, a value of type <code>TEXT</code> inserted in that column will be converted or return an error. But with SQLite, type <a href="https://www.sqlite.org/datatype3.html#type_affinity">affinities</a> mean that if the value is not of the expected type, it will be converted if possible or stored with a different type if necessary. That’s handy when prototyping, but you may want a stricter behavior for consistency with other major SQL databases or when working with strictly typed languages.</p>
<p>To this end, SQLite supports the <a href="https://www.sqlite.org/stricttables.html">STRICT</a> keyword at table creation. For instance, if a table <code>t</code> is created like so:</p>
<pre tabindex="0"><code>CREATE TABLE t(a INTEGER) STRICT;
</code></pre><p>then</p>
<pre tabindex="0"><code>INSERT INTO t VALUES(1);
INSERT INTO t VALUES(&#39;1&#39;);
</code></pre><p>are successful but</p>
<pre tabindex="0"><code>INSERT INTO t VALUES(&#39;f&#39;);
</code></pre><p>is not and returns <code>Runtime error: cannot store TEXT value in INTEGER column t.a (19)</code>.</p>
<p><strong>Note</strong>: Without the <code>STRICT</code> keyword at table creation, this last <code>INSERT INTO …</code> statement would have been successful and would have just returned a string.</p>
<h2 id="go-deeper">Go deeper</h2>
<p>The full list of supported pragma with detailed descriptions is available in the <a href="https://sqlite.org/pragma.html">documentation</a>. Some <a href="https://kerkour.com/sqlite-for-servers">more options</a> can be tweaked for the specific scenario of running a SQLite for a server.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>A significant improvement to WAL mode is <a href="https://www.sqlite.org/cgi/src/doc/wal2/doc/wal2.md">being developped</a>, where the WAL file won’t grow to unbound sizes.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item></channel></rss>