<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>occasionally useful &#187; html5</title>
	<atom:link href="http://blog.maxaller.name/category/web-20/html5/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.maxaller.name</link>
	<description>ruby, ubuntu, etc</description>
	<lastBuildDate>Thu, 02 Sep 2010 07:00:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>HTML5 Web SQL Database &#8211; Intro to Versioning and Migrations</title>
		<link>http://blog.maxaller.name/2010/03/html5-web-sql-database-intro-to-versioning-and-migrations/</link>
		<comments>http://blog.maxaller.name/2010/03/html5-web-sql-database-intro-to-versioning-and-migrations/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 02:47:50 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[html5]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.maxaller.name/?p=263</guid>
		<description><![CDATA[An introduction to HTML5 Web SQL Database version management and schema migrations.]]></description>
			<content:encoded><![CDATA[<p>I've been dabbling a bit with Chrome extensions, which have at their disposal HTML5 <a href="http://dev.w3.org/html5/webstorage/#the-localstorage-attribute" target="_blank">localStorage</a> and <a href="http://dev.w3.org/html5/webdatabase/" target="_blank">Web SQL Database</a>.  And...the web sql database especially is pretty cool.  But one thing was bothering me -- if I have a database on the client, how do I maintain the schema?  The (simplest) answer is in changeVersion.<br />
<span id="more-263"></span><br />
First a little background -- each database has an "version" property stored in the metadata of the database.  This basically safeguards you from the following scenario:</p>
<ol>
<li>Webmaster creates Javascript that requires database with schema A</li>
<li>User goes to website and a local database with schema A is created</li>
<li>Webmaster updates Javascript to use schema B</li>
<li>User goes to another page -- but what now?  User's database is using schema A but the javascript expects schema B</li>
</ol>
<p>How does the webmaster update from A to B?  Or create the initial schema, for that matter?  changeVersion.</p>
<p>Here's how you migrate the original schema, A in our case:<script src="http://gist.github.com/324073.js?file=1-Initial+schema.js"></script></p>
<p>That works...but already there's a problem.  If a user revisits a page, that changeVersion line will attempt to execute again.  Easy enough to fix: <script src="http://gist.github.com/324073.js?file=2-Repeat+visits+possible.js"></script> </p>
<p>(Note: the second argument to openDatabase is the "expected version" of the database.  If you specify it, the openDatabase method will <em>fail</em> unless the database matches the version you provided, without chance to recover.  I haven't found a use for this yet, so you'll always see the expected version as empty string from me.  Also note: this particular problem could be solved by setting the initial schema in the openDatabase callback, but you'd still hit it later when you add your first schema alteration)</p>
<p>Now users can view and refresh a page without the database connection erroring out.  Gooood.  But wait, I need to modify the schema again.  What now? Let's try this: <script src="http://gist.github.com/324073.js?file=3-Migrations+v1.js"></script></p>
<p>This...actually doesn't work at all (except within the scope of web workers, perhaps), because within the "regular" web sql database (window.openDatabase), <em>everything is asynchronous</em>.  Which is awesome for performance, but a pain if you're trying to do what we're trying to do right now.  Also, changeVersion only changes the version after the callback has run, successfully.  In other words, for a user new to the site with no schema, the "if db version == 1" line will get executed before the database has been updated to version 1!  If you refresh the page a few times this might work, but...that's obviously not acceptable.  But we're getting closer: <script src="http://gist.github.com/324073.js?file=4-Migrations+v2-v3.js"></script></p>
<p>Alright, this actually works, but it's cumbersome and still has a fair bit of code duplication (less in the second version...).</p>
<p><strong>And now for the punch line</strong> -- what if we take that "v3" migration, stash all the migrations in an array, and...say, put it in a class, maybe called Migrator?  And that's what I've done: <script src="http://gist.github.com/324073.js?file=Migrator.js"></script> And usage example: <script src="http://gist.github.com/324073.js?file=Migrator-usage.js"></script></p>
<p>Granted, it is small and fairly simple (and uh, disclaimer, not tested super thoroughly), but if nothing else it should be a good starter for your own migration scripts.</p>
<p>Thanks for reading!</p>
<p>UPDATE on June 5, 2010:<br />
I've created a github project with a more recent version (one that works with Safari/Webkit), available <a href="http://github.com/nanodeath/JS-Migrator" target="_blank">here</a>.  It does this by using a schema table to track state instead of relying on changeVersion.  While sort of a hack, the changeVersion design is rather poor anyway (pretty much the only useful openDatabase version string is "", since everything else could throw an exception).  Additionally, I added some logging, an example, and what I discovered to be a much-needed feature: callbacks, which let you execute further SQL with confidence that the migrations have already occurred.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.maxaller.name/2010/03/html5-web-sql-database-intro-to-versioning-and-migrations/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
