<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hacker News: SQLite</title><link>https://news.ycombinator.com/user?id=SQLite</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Tue, 08 Sep 2026 17:04:53 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=SQLite" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by SQLite in "uv: Deduplicate all files in the wheel cache"]]></title><description><![CDATA[
<p>Checksums use CPU cycles.  SQLite will do checksums with an extension (<a href="https://sqlite.org/cksumvfs.html" rel="nofollow">https://sqlite.org/cksumvfs.html</a>) but that is off by default since an overwhelming majority of developers are more interested in day-to-day performance than detecting (very rare) storage malfunctions.</p>
]]></description><pubDate>Mon, 31 Aug 2026 14:55:20 +0000</pubDate><link>https://news.ycombinator.com/item?id=49510548</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=49510548</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49510548</guid></item><item><title><![CDATA[New comment by SQLite in "GIMP Development Update"]]></title><description><![CDATA[
<p>SQLite file format spec: <<a href="https://sqlite.org/fileformat.html" rel="nofollow">https://sqlite.org/fileformat.html</a>></p>
]]></description><pubDate>Mon, 17 Aug 2026 10:18:30 +0000</pubDate><link>https://news.ycombinator.com/item?id=49328716</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=49328716</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49328716</guid></item><item><title><![CDATA[New comment by SQLite in "SQLite: The WAL-Reset Bug"]]></title><description><![CDATA[
<p>Correct.<p>You will have great difficulty hitting this problem, even if you deliberately try.<p>The only app I've ever known to hit this problem was Tailscale, and that was because they were running sqlite3_wal_checkpoint() four times per second on a separate connection in a separate thread, and then they would hit the problem on one or two of their many servers about once a month.  We were never able to reproduce this problem ourselves, until after we introduced new debugging code to deliberately force the problem.<p>After the problem was fixed, we gave Tailscale a modified version of SQLite that invoked sqlite3_log() with a warning whenever circumstances were such that the bug would have occurred had we not already fixed it.  It took them a couple of months before they finally observed that log message.  I'm not sure why it took that long - maybe the fix changed the timing just enough that the race became tighter and less likely to occur.</p>
]]></description><pubDate>Thu, 13 Aug 2026 16:28:57 +0000</pubDate><link>https://news.ycombinator.com/item?id=49288409</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=49288409</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49288409</guid></item><item><title><![CDATA[New comment by SQLite in "Honker – Durable queues, streams, pub/sub, and cron scheduler in a SQLite file"]]></title><description><![CDATA[
<p>SQLite allows multiple writers.  The constraint is that only one of how writers can be actively writing at any moment in time.  If there are multiple processes wanting to write, they take turns.  SQLite prevents two or more writes from running concurrently, so there is nothing the application needs to do to implement this, other than responding to SQLITE_BUSY replies from failed (concurrent) write attempts and retrying after a short delay.<p>Why this constraint?  Because SQLite is serverless. There is no central server available to coordinate concurrent writes.<p>At the lowest level of the stack, every database engine has this same constraint, as there is only one wire connecting the CPU to the SSD, and you cannot send multiple writes over the same wire at the same time.  But in a client/server database, the server (in cooperation with the filesystem) is at hand to serialize the writes and prevent problems in ways that are not possible without a server.  The server creates the illusion of concurrent writes by multiplexing the single write wire efficiently and making that multiplexing transparent to the application.</p>
]]></description><pubDate>Fri, 01 May 2026 10:27:23 +0000</pubDate><link>https://news.ycombinator.com/item?id=47973103</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=47973103</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47973103</guid></item><item><title><![CDATA[New comment by SQLite in "Modern SQLite: Features You Didn't Know It Had"]]></title><description><![CDATA[
<p>Checking the datatype is not the same as validating.  There is lots of data out there that is invalid, and yet still has the correct type.  In fact, that is the common case.<p>I dare say you will be hard pressed to find a dataset of significant size that doesn't have at least one invalid entry somewhere.  Increasingly strict type rules will not fix that.</p>
]]></description><pubDate>Thu, 02 Apr 2026 22:04:55 +0000</pubDate><link>https://news.ycombinator.com/item?id=47620776</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=47620776</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47620776</guid></item><item><title><![CDATA[New comment by SQLite in "Modern SQLite: Features You Didn't Know It Had"]]></title><description><![CDATA[
<p>No, I think that people can use SQLite anyway they want.  I'm glad people find it useful.<p>I do remain perplexed, though, about how people continue to think that rigid typing helps reliability in a scripting language (like SQL or JSON) where all values are subclasses of a single superclass.  I have never seen that in my own practice.  I don't know of any objective research that supports the idea that rigid typing is helpful in that context.  Maybe I missed something...</p>
]]></description><pubDate>Thu, 02 Apr 2026 21:51:40 +0000</pubDate><link>https://news.ycombinator.com/item?id=47620644</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=47620644</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47620644</guid></item><item><title><![CDATA[New comment by SQLite in "Modern SQLite: Features You Didn't Know It Had"]]></title><description><![CDATA[
<p>Flexible typing works really well with JSON, which is also flexibly typed. Are you familiar with the ->> operator that extracts a value from JSON object or array?  If jjj is a column that holds a JSON object, then jjj->>'xyz' is the value of the "xyz" field of that object.<p>I copied the idea for the ->> operator from PostgreSQL.  But in PostgreSQL, the ->> operator always returns a text rendering of the value from the JSON, even if the value is really an integer or floating point number.  PG is rigidly typed, so that's all it can do.  But SQLite is flexibly typed, so the ->> operator can return anything - text, integer, floating-point, NULL - whatever value if finds in the JSON.</p>
]]></description><pubDate>Thu, 02 Apr 2026 21:37:34 +0000</pubDate><link>https://news.ycombinator.com/item?id=47620531</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=47620531</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47620531</guid></item><item><title><![CDATA[New comment by SQLite in "The Cognitive Dark Forest"]]></title><description><![CDATA[
<p>Minor correction:  SQLite is not closed to contributions.  It just has an unusually high bar to accepting contributions.  The project does not commonly accept pull requests from random passers-by on the internet.  But SQLite does accept outside contributed code from time to time.  Key gates include that paperwork is in place to verify that the contributed code is in the public domain and that the code meets certain high quality standards.</p>
]]></description><pubDate>Mon, 30 Mar 2026 09:54:22 +0000</pubDate><link>https://news.ycombinator.com/item?id=47572367</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=47572367</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47572367</guid></item><item><title><![CDATA[New comment by SQLite in "SQLite Release 3.51.3"]]></title><description><![CDATA[
<p>As long as you are not using indexes on expressions where the expression value is a floating point number that is computed using one or more text->binary conversions, then you should be fine.</p>
]]></description><pubDate>Fri, 13 Mar 2026 20:46:12 +0000</pubDate><link>https://news.ycombinator.com/item?id=47369639</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=47369639</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47369639</guid></item><item><title><![CDATA[New comment by SQLite in "Building SQLite with a small swarm"]]></title><description><![CDATA[
<p>You do not recall correctly.  There is more than 500K SLOC of test code in the public source tree.  If you "make releasetest" from the public source tarball on Linux, it runs more than 15 million test cases.<p>It is true that the half-million lines of test code found in the public source tree are not the entirety of the SQLite test suite.  There are other parts that are not open-source.  But the part that is public is a big chunk of the total.</p>
]]></description><pubDate>Mon, 16 Feb 2026 10:48:28 +0000</pubDate><link>https://news.ycombinator.com/item?id=47033503</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=47033503</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47033503</guid></item><item><title><![CDATA[New comment by SQLite in "I made my own Git"]]></title><description><![CDATA[
<p>The Common Table Expression feature of SQL is very good at walking graphs.  See, for example <<a href="https://sqlite.org/lang_with.html#queries_against_a_graph" rel="nofollow">https://sqlite.org/lang_with.html#queries_against_a_graph</a>>.</p>
]]></description><pubDate>Wed, 28 Jan 2026 00:42:20 +0000</pubDate><link>https://news.ycombinator.com/item?id=46789427</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=46789427</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46789427</guid></item><item><title><![CDATA[New comment by SQLite in "Zpdf: PDF text extraction in Zig"]]></title><description><![CDATA[
<p>If an I/O error happens with read()/write(), you get back an error code, which SQLite can deal with and pass back up to the application, perhaps accompanied by a reasonable error message.  But if you get an I/O error with mmap, you get a signal.  SQLite itself ought not be setting signal handlers, as that is the domain of the application and SQLite is just a lowly library.  And even if SQLite could set signal handlers, it would be difficult to associate a signal with a particular I/O operation. So there isn't a good way to deal with I/O errors when using mmap().  With mmap(), you just have to assume that the filesystem/mass-storage works flawlessly and never runs out of space.<p>SQLite can use mmap().  That is a tested and supported capability.  But we don't advocate it because of the inability to precisely identify I/O errors and report them back up into the application.</p>
]]></description><pubDate>Thu, 01 Jan 2026 00:05:27 +0000</pubDate><link>https://news.ycombinator.com/item?id=46449709</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=46449709</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46449709</guid></item><item><title><![CDATA[New comment by SQLite in "Show HN: 22 GB of Hacker News in SQLite"]]></title><description><![CDATA[
<p>That depends on the query.  SQLite tries to use LIMIT to restrict the amount of reading that it does.  It is often successful at that.  But some queries, by their very nature, logically require reading the whole input in order to compute the correct answer, regardless of whether or not there is a LIMIT clause.</p>
]]></description><pubDate>Wed, 31 Dec 2025 10:47:22 +0000</pubDate><link>https://news.ycombinator.com/item?id=46443074</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=46443074</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46443074</guid></item><item><title><![CDATA[New comment by SQLite in "Show HN: Vibe coding a bookshelf with Claude Code"]]></title><description><![CDATA[
<p>Website updated with more precise wording.  Sorry for the confusion.</p>
]]></description><pubDate>Tue, 30 Dec 2025 14:02:59 +0000</pubDate><link>https://news.ycombinator.com/item?id=46433409</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=46433409</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46433409</guid></item><item><title><![CDATA[New comment by SQLite in "Show HN: Vibe coding a bookshelf with Claude Code"]]></title><description><![CDATA[
<p>No, Simon, we don't "refuse".  We are just very selective and there is a lot of paperwork involved to confirm the contribution is in the public domain and does not contaminate the SQLite core with licensed code.  Please put the false narrative that "SQLite refuses outside contributions" to rest.  The bar is high to get there, but the SQLite code base does contain contributed code.</p>
]]></description><pubDate>Mon, 29 Dec 2025 19:13:18 +0000</pubDate><link>https://news.ycombinator.com/item?id=46424225</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=46424225</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46424225</guid></item><item><title><![CDATA[New comment by SQLite in "How SQLite is tested"]]></title><description><![CDATA[
<p>The story of Fossil:<p>Something better than CVS was needed.  (I'm not being critical of CVS.  I had to use the VCSes that can before, and CVS was amazing compared to them.)  Monochrome gave me the idea of doing a distributed VCS and storing content in SQLite, but Monochrome didn't support sync over HTTP, which I definitely wanted.  Git had just appeared, and was really bad back in those early years.  (It still isn't great, IMO, though people who have never used anything other than Git are quick to dispute that claim.)  Mercurial was... Mercurial.  So I decided to write my own DVCS.<p>This turned out to be a good thing, though not in the way I expected.  Since Fossil is built on top of SQLite,  Fossil became a test platform for SQLite.  Furthermore, when I work on Fossil, I see SQLite from the point of view of an application developer using SQLite, rather than in my usual role of a developer of SQLite.  That change in perspective has helps me to make SQLite better.  Being the primary developer of the DVCS for SQLite in addition to SQLite itself also give me the freedom to adapt the DVCS to the specific needs of the SQLite project, which I have done on many occasions.  People make fun of me for writing my own DVCS for SQLite, but in the balance it was a good move.<p>Note that Fossil is like Git in that it stores check-ins an a directed acyclic graph (DAG), though the details of each node are different.  The key difference is that Fossil stores the DAG in a relational database (SQLite) whereas Git uses a custom "packfile" key/value store.  Since the content is in a relational database, it is really easy to add features like tickets, and wiki, and a forum, and chat - you've got an RDBMS sitting there, so why not use it?  Even without those bonus features, you also have the benefit of being about to query the DAG using SQL to get useful information that is difficult to obtain from Git.  "Detached heads" are not possible in Fossil, for example.  Tags are not limited by filesystem filename restrictions.  You can tag multiple check-ins with the same tag (ex: all releases are tagged "release".)  If you reference an older check-in in the check-in comment of a newer check-in, then go back and look at the older check-in (perhaps you bisected there), it will give a forward reference to the newer one.  And so forth.</p>
]]></description><pubDate>Wed, 17 Dec 2025 21:25:48 +0000</pubDate><link>https://news.ycombinator.com/item?id=46305720</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=46305720</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46305720</guid></item><item><title><![CDATA[New comment by SQLite in "Notes by djb on using Fil-C"]]></title><description><![CDATA[
<p>SQLite runs about 5 times faster compiled with GCC (13.3.0) than it does when compiled with FIL-C.  And the resulting compiled binary from GCC is 13 times smaller.</p>
]]></description><pubDate>Mon, 03 Nov 2025 10:49:53 +0000</pubDate><link>https://news.ycombinator.com/item?id=45797756</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=45797756</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45797756</guid></item><item><title><![CDATA[New comment by SQLite in "Subtleties of SQLite Indexes"]]></title><description><![CDATA[
<p>The top-level routine is here: <<a href="https://sqlite.org/src/info/aae36a5fbd17?ln=6767-6818" rel="nofollow">https://sqlite.org/src/info/aae36a5fbd17?ln=6767-6818</a>>.  Small (32-bit) integer literals are compared numerically, here: <<a href="https://sqlite.org/src/info/aae36a5fbd17?ln=6526" rel="nofollow">https://sqlite.org/src/info/aae36a5fbd17?ln=6526</a>>.  They don't have to exactly match.  So if you say "x=0x123" in the WHERE clause of the partial index and "x=291" in the WHERE clause of the query, and that will still work.  However, 64-bit integer literals and floating-point literals are compared using strcmp(), here: <<a href="https://sqlite.org/src/info/aae36a5fbd17?ln=6570" rel="nofollow">https://sqlite.org/src/info/aae36a5fbd17?ln=6570</a>>, so they do need to match exactly, at least in the current implementation.  Maybe that is something I should work on...</p>
]]></description><pubDate>Tue, 30 Sep 2025 02:29:44 +0000</pubDate><link>https://news.ycombinator.com/item?id=45421324</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=45421324</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45421324</guid></item><item><title><![CDATA[New comment by SQLite in "Subtleties of SQLite Indexes"]]></title><description><![CDATA[
<p>Yeah, but who ever writes "x=0.9" as a constraint on a partial index?  Really?  Don't you know you aren't suppose to compare floating point quantities for equality?<p>If P is the expression on the partial index and Q is the WHERE clause of the query, then the partial index is only usable if Q implies P for all possible assignments of variables.  A theorem prover is needed to establish this.  Every RDBMS has one.  The one inside SQLite is not terribly bright, true enough.  It leans toward usually little memory and few CPU cycles.  It does not do a good job if P contains "x=0.9".  On the other hand, SQLite's theorem prover is decent if P contains "x IS NOT NULL", because in actual practice, probably about 90% of partial index WHERE clauses are some variation on "x IS NOT NULL".<p>The partial index expression does not always have to be <i>exactly</i> the same as what is in the WHERE clause of the query.  SQLite will always find the match if P is a subset of Q; if Q can be rewritten as "R AND P".  But if P is "x IS NOT NULL" and Q does anything that restricts x from being NULL, for example if Q contains "x>0", then SQLite's theorem prover will find that match too, even if "IS NOT NULL" never appears in Q.<p>Will the theorem prover in SQLite get better someday?  Perhaps.  It has gotten better over the years.  The question becomes, how much more code space and query-planning CPU cycles are you willing to spend to get a slightly better query planner?  This trade-off is different for a client/server database engine.  With SQLite being embedded, the trade-off tends to fall more on the side of "keep it simple".  If you have followed SQLite over many years, you might have noticed it is shifting toward more complex decision making as memory becomes cheaper and CPUs get faster.  It's a tricky balancing act to find the sweet spot.</p>
]]></description><pubDate>Tue, 30 Sep 2025 00:34:43 +0000</pubDate><link>https://news.ycombinator.com/item?id=45420631</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=45420631</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45420631</guid></item><item><title><![CDATA[New comment by SQLite in "Use singular nouns for database table names"]]></title><description><![CDATA[
<p>I think (I hope!) we are probably done adding keywords to SQLite.  Furthermore, all of the more recently added keywords (ex: WITHIN, RETURNING, MATERIALIZED) make use of special capabilities in SQLite's parser that allows keywords to be used as identifiers as long as the identifier usage does not occur in a context where the keyword is allowed.<p>So, for example, you can used MATERIALIZED as a keyword in a common-table expression ("WITH xyzzy(a,b) AS MATERIALIZED (...)") but MATERIALIZED can also be used as a column or table name.  Hence, the following SQL actually works in SQLite:<p><pre><code>   WITH xyz(MATERIALIZED) AS MATERIALIZED(
     VALUES(1),(2),(3)
   )
   SELECT * FROM xyz;</code></pre></p>
]]></description><pubDate>Tue, 09 Sep 2025 13:59:29 +0000</pubDate><link>https://news.ycombinator.com/item?id=45182025</link><dc:creator>SQLite</dc:creator><comments>https://news.ycombinator.com/item?id=45182025</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45182025</guid></item></channel></rss>