summaryrefslogtreecommitdiff
path: root/.html/dev/liquibase.html
blob: 64b19c535facaa8cc556fc88d511a7c94b5db14d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<!DOCTYPE html>
<html>
<head>
	<title>
		The Codex » 
		Liquibase
	</title>

	<link
		rel='stylesheet'
		type='text/css'
		href='http://fonts.googleapis.com/css?family=Buenard:400,700&amp;subset=latin,latin-ext'>
	<link
		rel="stylesheet"
		type="text/css"
		href="../media/css/reset.css">
	<link
		rel="stylesheet"
		type="text/css"
		href="../media/css/grimoire.css">
</head>
<body>

<div id="shell">
	
		<ol id="breadcrumbs">
			
				<li class="crumb-0 not-last">
					
						<a href="../">index</a>
					
				</li>
			
				<li class="crumb-1 not-last">
					
						<a href="./">dev</a>
					
				</li>
			
				<li class="crumb-2 last">
					
						liquibase
					
				</li>
			
		</ol>
	

	
	<div id="article">
		<h1 id="liquibase">Liquibase</h1>
<p>Note to self: I think this (a) needs an outline and (b) wants to become a “how
to automate db upgrades for dummies” page. Also, this is really old (~2008)
and many things have changed: database migration tools are more
widely-available and mature now. On the other hand, I still see a lot of
questions on IRC that are based on not even knowing these tools exist.</p>
<hr>
<p>Successful software projects are characterized by extensive automation and
supporting tools. For source code, we have version control tools that support
tracking and reviewing changes, marking particular states for release, and
automating builds. For databases, the situation is rather less advanced in a
lot of places: outside of Rails, which has some rather nice
<a href="http://wiki.rubyonrails.org/rails/pages/understandingmigrations">migration</a>
support, and <a href="http://code.google.com/p/django-evolution/">evolutions</a> or
<a href="http://south.aeracode.org">South</a> for Django, there are few tools that
actually track changes to the database or to the model in a reproducible way.</p>
<p>While I was exploring the problem by writing some scripts for my own projects,
I came to a few conclusions. You need to keep a receipt for the changes a
database has been exposed to in the database itself so that the database can
be reproduced later. You only need scripts to go forward from older versions
to newer versions. Finally, you need to view <abbr title="Data Definition Language">DDL</abbr> statements as a degenerate
form of diff, between two database states, that's not combinable the way
textual diff is except by concatenation.</p>
<p>Someone on IRC mentioned <a href="http://www.liquibase.org/">Liquibase</a> and
<a href="http://migrate4j.sourceforge.net/">migrate4j</a> to me. Since I was already in
the middle of writing a second version of my own scripts to handle the issues
I found writing the first version, I stopped and compared notes.</p>
<p>Liquibase is essentially the tool I was trying to write, only with two years
of relatively talented developer time poured into it rather than six weeks.</p>
<p>Liquibase operates off of a version table it maintains in the database itself,
which tracks what changes have been applied to the database, and off of a
configuration file listing all of the database changes. Applying new changes
to a database is straightforward: by default, it goes through the file and
applies all the changes that are in the file that are not already in the
database, in order. This ensures that incremental changes during development
are reproduced in exactly the same way during deployment, something lots of
model-to-database migration tools have a problem with.</p>
<p>The developers designed the configuraton file around some of the ideas from
<a href="http://www.amazon.com/Refactoring-Databases-Evolutionary-Addison-Wesley-Signature/dp/0321293533">Refactoring
Databases</a>,
and provided an <a href="http://www.liquibase.org/manual/home#available_database_refactorings">extensive list of canned
changes</a>
as primitives in the database change scripts. However, it's also possible to
insert raw SQL commands (either <abbr title="Data Definition Language">DDL</abbr>, or <abbr title="Data Manipulation Language">DML</abbr> queries like <code>SELECT</code>s and
<code>INSERT</code>s) at any point in the change sequence if some change to the database
can't be accomplished with its set of refactorings. For truly hairy databases,
you can use either a Java class implementing your change logic or a shell
script alongside the configuration file.</p>
<p>The tools for applying database changes to databases are similarly flexible:
out of the box, liquibase can be embedded in a fairly wide range of Java
applications using servlet context listeners, a Spring adapter, or a Grails
adapter; it can also be run from an ant or maven build, or as a standalone
tool.</p>
<p>My biggest complaint is that liquibase is heavily Java-centric; while the
developers are planning .Net support, it'd be nice to use it for Python apps
as well. Triggering liquibase upgrades from anything other than a Java program
involves either shelling out to the <code>java</code> command or creating a JVM and
writing native glue to control the upgrade process, which are both pretty
painful. I'm also less than impressed with the javadoc documentation; while
the manual is excellent, the javadocs are fairly incomplete, making it hard to
write customized integrations.</p>
<p>The liquibase developers deserve a lot of credit for solving a hard problem
very cleanly.</p>
	</div>


	
<div id="comments">
<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>
</div>


	
	<div id="footer">
		<p>
			
				The Codex —
			
			Powered by <a href="http://markdoc.org/">Markdoc</a>.
			
<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/dev/liquibase.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/dev/liquibase.md">history</a>).

		</p>
	</div>
	
</div>
</body>
</html>