<?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/"
	xmlns:series="http://unfoldingneurons.com/"
	>

<channel>
	<title>DbTracer</title>
	<atom:link href="http://blog.dbtracer.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.dbtracer.org</link>
	<description>Database Comparison and Deployment</description>
	<lastBuildDate>Wed, 28 Dec 2011 14:56:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Database Deployment Patterns (Introduction)</title>
		<link>http://blog.dbtracer.org/2011/10/31/database-deployment-patterns-introduction/</link>
		<comments>http://blog.dbtracer.org/2011/10/31/database-deployment-patterns-introduction/#comments</comments>
		<pubDate>Sun, 30 Oct 2011 23:01:47 +0000</pubDate>
		<dc:creator>Petr Kozelek</dc:creator>
				<category><![CDATA[Database Continuous Integration]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[database]]></category>

		<guid isPermaLink="false">http://blog.dbtracer.org/?p=231</guid>
		<description><![CDATA[In the previous post I described general approaches how to define database deployment steps. Now I focus more deeply on analysis of individual steps and on identification of deployment patterns &#8211; I replace here a more familiar term database refactorings since I want to focus on database deployment instead of database redesign. However, there can [...]
Related posts:<ol>
<li><a href='http://blog.dbtracer.org/2011/10/21/database-deployment-approaches/' rel='bookmark' title='Database Deployment Approaches'>Database Deployment Approaches</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>In the <a href="/2011/10/21/database-deployment-approaches/">previous post</a> I described general approaches how to define database deployment steps. Now I focus more deeply on analysis of individual steps and on identification of <em>deployment patterns</em> &#8211; I replace here a more familiar term <a href="http://databaserefactoring.com">database refactorings</a> since I want to focus on database deployment instead of database redesign. However, there can be slight overlap between the two.</p>
<p>Deployment patterns are of two basic types, regarding database changes that they cover:</p>
<ul>
<li><em>Schema deployment patterns</em> cover any modifications in database schema. They can be divided further into two disjunctive groups:</li>
<ul>
<li><em>Data-independent patterns </em>are applied without requirements to modify existing data. In other words, when I need to apply data-independent pattern, I do not require to affect data being hold in existing tables. They are always deterministic (see below)<br />
Examples: add/drop views, functions or stored procedures, drop foreign key or column constraint</li>
<li><em>Data-dependent patterns </em>require existing data to be modified. The reason for modifications can be, for example, improving data quality before the pattern can be applied.<br />
Examples: add foreign key, add column constraint</li>
</ul>
<li><em>Data deployment patterns</em> modify purely the data and they keep the schema unchanged. Usually they follow schema deployment patterns in order to insert data into newly introduced tables/columns. They are deterministic or dependent (see below).</li>
</ul>
<p>Deployment patterns are of different clarity, depending on how straightforward it is to apply the pattern.</p>
<ul>
<li><em>Deterministic patterns</em> include deployment of changes for which there is only one way how to deploy them. Sometimes, the particular pattern can be applied repeatably without negative impact on a database schema and data itself. E.g. deployment of <em>Modify view pattern</em> is pretty straightforward &#8211; just execute <code>ALTER VIEW...</code> and you are done. When you execute it twice, it does not cause a problem. Well, modifying the view might break a dependent application, of course, but regarding the database layer, there is neither a risk nor uncertainty in applying it.</li>
<li><em>Ambiguous patterns</em> are the ones for which it is not clear how to apply them. For instance, <a href="http://databaserefactoring.com/SplitColumns.html">Split column pattern</a> includes a recipe defining the way how to split one column into the two (imagine splitting <code>FullName</code> into <code>FirstName</code>, <code>LastName</code>). How should it be done? Split by spaces? What if <code>FullName</code> includes academic titles? Get rid of them? Make them a part of the <code>FirstName</code>? These questions have to be answered by a developer who knows data quality. Moreover, ambiguous patterns usually depend on existing data and they usually are not repeatable.</li>
</ul>
<p>Ambiguities are the biggest obstacle for adopting automatic database deployment. If you succeed with reducing the number of ambiguous deployment patterns you will feel less pain in introducing continuous database deployment. There are less ambiguities when deployment patterns are small, e.g. <a href="http://databaserefactoring.com/IntroduceNewColumn.html">introduce column</a> pattern. On the contrary, when database deployment requires complex patterns (e.g. <a href="http://databaserefactoring.com/ReplaceOneToMany.html">Introduce Associative Table</a>) to be applied then the number of ambiguities increases.</p>
<p>The main question is: <em>How to reduce the number of ambiguities?</em></p>
<ul>
<li>Deploy database changes often. Then there is smaller chance for introducing complexities between the original and the new database version.</li>
<li>Use the right tools. Although the existing tools cannot solve all problems connected with database deployment they can provide significant help. They should detect differences between database versions. Consequently, they should assist a developer in classifying database deployment patterns. Of course, the tools should automatically resolve differences for which deterministic patterns can be applied so that the developer can focus on ambiguous problems.</li>
</ul>
<p>Related posts:<ol>
<li><a href='http://blog.dbtracer.org/2011/10/21/database-deployment-approaches/' rel='bookmark' title='Database Deployment Approaches'>Database Deployment Approaches</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.dbtracer.org/2011/10/31/database-deployment-patterns-introduction/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<series:name><![CDATA[Database Deployment]]></series:name>
	</item>
		<item>
		<title>Database Deployment Approaches</title>
		<link>http://blog.dbtracer.org/2011/10/21/database-deployment-approaches/</link>
		<comments>http://blog.dbtracer.org/2011/10/21/database-deployment-approaches/#comments</comments>
		<pubDate>Fri, 21 Oct 2011 10:10:32 +0000</pubDate>
		<dc:creator>Petr Kozelek</dc:creator>
				<category><![CDATA[Database Continuous Integration]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[DbTracer]]></category>

		<guid isPermaLink="false">http://blog.dbtracer.org/?p=187</guid>
		<description><![CDATA[There are two main categories of database deployment tools. The first one supports deployment of software that follows Application-Driven Database Design (ADD). It means that a database is a persistence layer for a particular application. It is the application itself, its features and the need them to be persisted that drives database design. A typical [...]
Related posts:<ol>
<li><a href='http://blog.dbtracer.org/2011/10/31/database-deployment-patterns-introduction/' rel='bookmark' title='Database Deployment Patterns (Introduction)'>Database Deployment Patterns (Introduction)</a></li>
<li><a href='http://blog.dbtracer.org/2010/01/12/database-continuous-integration-with-dbtracer/' rel='bookmark' title='Database Continuous Integration with DbTracer'>Database Continuous Integration with DbTracer</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>There are two main categories of database deployment tools. The first one supports deployment of software that follows<em> Application-Driven Database Design (ADD)</em>. It means that a database is a persistence layer for a particular application. It is the application itself, its features and the need them to be persisted that drives database design. A typical reprezentant here is web application development.</p>
<p>On the other hand, applications that are oriented strictly on database development (and deployment) follow (as  I call such a development approach) <em>Independent Database Design (IDD)</em>. Thus, the major determinant for introducing database schema changes is the need for extending or modifying a nature of the data. This category typically includes data warehouses and high load/performance critical database processes.</p>
<p>It should be clear that <em>IDD</em> is simpler than <em>ADD</em> because a database developer cares just about development and deployment of one layer. But when an application developer takes care of two software layers and their mutual interconnection then he has more complex responsibility. It is natural that deployment of two dependent layers is more complex task than deployment of only one. The situation becomes even more complex when responsibilities for application layer development and database layer development are spread across different teams because of communication issues.</p>
<p>First I focus on <em>IDD</em> because it seems it is simpler than <em>ADD</em>, as if <em>ADD</em> was just extension to <em>IDD</em>. Later in this article I will explain that <em>IID</em> can be significantly different from <em>ADD</em>.</p>
<h3>Independent Database Design</h3>
<p>If a developer is responsible for development of just a database layer then his task to create deployment strategy is quite straightforward. Once the development phase within an iteration is over he is expected to define a deployment strategy for new version of database schema. The strategy usually is defined in a database deployment script. It includes <span title="Data Definition Language">DDL</span> commands for inserting/modifying/deleting columns in tables and etc. The deployment script often defines also <span title="Data Modification Language">DML</span> commands like inserting initial data to newly created tables. The two general questions come up when thinking about how to define database deployment process:</p>
<ol>
<li>How does the developer identifies what should be deployed into target environment?</li>
<li>How does the developer define the deployment process of the database?</li>
</ol>
<p>The answer to the first question is <em>Database Comparison Tool</em>. There is a number of them in the market. They can compare both database schema and data themselves. When the developer needs to identify what should be deployed he usually works in the following scenario:</p>
<ol>
<li>Compare the target database schema with current development database schema.</li>
<li>Identify schema differences</li>
<li>Identify which data should be deployed into target database. Database data comparison can help here.</li>
</ol>
<p>Identifying schema and data differences is quite simple thanks to the mature database comparison tools. The more difficult part come up with the second question. <em>How to define a deployment process?</em> Regardless of whether or not the developer uses some database deployment software the final result is always the same &#8211; a deployment SQL script. So, in order to answer the second question related to defining deployment process, the developer has to do the following steps:</p>
<ol>
<li>Create a database schema deployment script. It usually contains only DDL commands.</li>
<li>Create database data modification script. It usually contains only DML commands.</li>
</ol>
<p>Of course, the tools could help here, too. However, the whole process of transforming the identified database differences into the deployment script can be very complex. There can be mutual dependencies among database objects &#8211; both schema and data dependencies.</p>
<p>Consider the following example: In a target database there is a table <code>Person</code> with columns <code>Id</code>, <code>FullName</code>. In a development database that I want to deploy to target there is a table <code>Person</code> with columns <code>Id</code>, <code>FirstName</code>, <code>LastName</code>. How should I deploy the development database into target database? Simply with this deployment script?</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="sql"><pre class="de1"><span class="kw1">ALTER</span> <span class="kw1">TABLE</span> Person <span class="kw1">ADD</span> <span class="kw1">COLUMN</span> FirstName <span class="kw1">VARCHAR</span><span class="br0">&#40;</span><span class="nu0">50</span><span class="br0">&#41;</span>;
<span class="kw1">ALTER</span> <span class="kw1">TABLE</span> Person <span class="kw1">ADD</span> <span class="kw1">COLUMN</span> LastName <span class="kw1">VARCHAR</span><span class="br0">&#40;</span><span class="nu0">50</span><span class="br0">&#41;</span>;
<span class="kw1">ALTER</span> <span class="kw1">TABLE</span> Person <span class="kw1">DROP</span> <span class="kw1">COLUMN</span> FullName; <span class="co1">-- data gets lost!</span></pre></div></div></div></div></div></div></div>


<p>Opps! I lost all my data related to person names! Let us try better approach:</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="sql"><pre class="de1"><span class="kw1">ALTER</span> <span class="kw1">TABLE</span> Person <span class="kw1">ADD</span> <span class="kw1">COLUMN</span> FirstName <span class="kw1">VARCHAR</span><span class="br0">&#40;</span><span class="nu0">50</span><span class="br0">&#41;</span>;
<span class="kw1">ALTER</span> <span class="kw1">TABLE</span> Person <span class="kw1">ADD</span> <span class="kw1">COLUMN</span> LastName <span class="kw1">VARCHAR</span><span class="br0">&#40;</span><span class="nu0">50</span><span class="br0">&#41;</span>;
<span class="kw1">UPDATE</span> Person <span class="kw1">SET</span> FirstName<span class="sy0">=</span>ExtractFirstName<span class="br0">&#40;</span>FullName<span class="br0">&#41;</span><span class="sy0">,</span> ExtractLastName<span class="br0">&#40;</span>FullName<span class="br0">&#41;</span>;
<span class="kw1">ALTER</span> <span class="kw1">TABLE</span> Person <span class="kw1">DROP</span> <span class="kw1">COLUMN</span> FullName;</pre></div></div></div></div></div></div></div>


<p>Here functions <code>ExtractFirstName</code>, <code>ExtractLastName</code> represent some (potentially complex) transformations defining the process how to retrieve particular parts of the name from its full represennation.</p>
<p>The situation gets more complex if new columns have constraints. For example, <code>FirstName</code> and <code>LastName</code> should not be null. It such a case you are not even able to add a column until you do not specify a default values for the columns being added.</p>
<p>The examples above demonstrates that there is not always a straightforward way how to deploy a new version of database to target environment. If there was then it would be relatively easy to automate creation od a deployment script.</p>
<p>Although nowadays tools can help a developer to pre-generate a deployment script, the developer still is required to manually double-check and fix it if needed. All in all, the whole process of defining a deployment script requires rather a lot of manual work.</p>
<h3>Application-Driven Database Design</h3>
<p>It might seem that <em>ADD</em> extends <em>IDD</em> approach however it is true only to some extent. In case a developer is creating an application which uses a database only as persistent storage then the database design is driven by application features. If the application stores a property FullName of an entity Person then a table Person with a column FullName has to be modeled in the database.</p>
<p>Later on, when the need for two independent properties FirstName, LastName arises then it has to be reflected in the database as well. Deployment of the application layer is simple since it is stateless &#8211; I can simply get rid of the old version of the application that supports only FullName property and replace it completely with new version of the entire application (I simplified it here since I do not count with introducing breaking changes in case other applications depend on the application being deployed). Definition of a deployment script can be simple SQL as in <em>IDD</em> approach.</p>
<p>However, unless the database design is strictly driven by the application then it is possible (at least to some extent) to define a recipe for database deployment directly in the application layer in the language the application layer is written in. Here is an example for <a href="http://guides.rubyonrails.org/migrations.html">migration in Ruby</a>:</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="ruby"><pre class="de1"><span class="kw1">class</span> AddFirstNameAndLastNameToPersons <span class="sy0">&lt;</span> <span class="re2">ActiveRecord::Migration</span>
  <span class="kw1">def</span> change
    add_column <span class="re3">:FirstName</span>, <span class="re3">:LastName</span>, :<span class="kw3">string</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></pre></div></div></div></div></div></div></div>


<p>Of course it is just a wrapper that generates good old SQL at deployment time. But with this approach of defining migrations with simple DSL you get greater level of control over deployment process because you can use full power of object-oriented language. You can programmatically combine migrations together, you can programmatically enable/disable them, you can run pre-tests validating that particular migration is even possible to be run, etc.</p>
<p>One of the most popular deployment tools of this kind is <a href="http://www.liquibase.org/">Liquibase</a>. Written in Java, it uses special DSL for migrations recipes:</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="xml"><pre class="de1"><span class="sc3"><span class="re1">&lt;changeSet</span> <span class="re0">id</span>=<span class="st0">&quot;1&quot;</span> <span class="re0">author</span>=<span class="st0">&quot;bob&quot;</span><span class="re2">&gt;</span></span>
    <span class="sc3"><span class="re1">&lt;addColumn</span> <span class="re0">tableName</span>=<span class="st0">&quot;Person&quot;</span><span class="re2">&gt;</span></span>
        <span class="sc3"><span class="re1">&lt;column</span> <span class="re0">name</span>=<span class="st0">&quot;FirstName&quot;</span> <span class="re0">type</span>=<span class="st0">&quot;varchar(50)&quot;</span><span class="re2">/&gt;</span></span>
    <span class="sc3"><span class="re1">&lt;/addColumn<span class="re2">&gt;</span></span></span>
    <span class="sc3"><span class="re1">&lt;addColumn</span> <span class="re0">tableName</span>=<span class="st0">&quot;Person&quot;</span><span class="re2">&gt;</span></span>
        <span class="sc3"><span class="re1">&lt;column</span> <span class="re0">name</span>=<span class="st0">&quot;LastName&quot;</span> <span class="re0">type</span>=<span class="st0">&quot;varchar(50)&quot;</span><span class="re2">/&gt;</span></span>
    <span class="sc3"><span class="re1">&lt;/addColumn<span class="re2">&gt;</span></span></span>
    <span class="sc3"><span class="re1">&lt;sql<span class="re2">&gt;</span></span></span>UPDATE Person SET FirstName=ExtractFirstName(FullName), ExtractLastName(FullName)<span class="sc3"><span class="re1">&lt;/sql<span class="re2">&gt;</span></span></span>
    <span class="sc3"><span class="re1">&lt;dropColumn</span> <span class="re0">tableName</span>=<span class="st0">&quot;Person&quot;</span> <span class="re0">columnName</span>=<span class="st0">&quot;FullName&quot;</span><span class="re2">/&gt;</span></span>
    <span class="sc3"><span class="re1">&lt;rollback<span class="re2">&gt;</span></span></span>
        <span class="sc3"><span class="re1">&lt;addColumn</span> <span class="re0">tableName</span>=<span class="st0">&quot;Person&quot;</span><span class="re2">&gt;</span></span>
            <span class="sc3"><span class="re1">&lt;column</span> <span class="re0">name</span>=<span class="st0">&quot;FullName&quot;</span> <span class="re0">type</span>=<span class="st0">&quot;varchar(100)&quot;</span><span class="re2">/&gt;</span></span>
        <span class="sc3"><span class="re1">&lt;/addColumn<span class="re2">&gt;</span></span></span>
    <span class="sc3"><span class="re1">&lt;sql<span class="re2">&gt;</span></span></span>UPDATE Person SET FullName=CreateFullName(FirstName, LastName)<span class="sc3"><span class="re1">&lt;/sql<span class="re2">&gt;</span></span></span>
    <span class="sc3"><span class="re1">&lt;dropColumn</span> <span class="re0">tableName</span>=<span class="st0">&quot;Person&quot;</span> <span class="re0">columnName</span>=<span class="st0">&quot;LastName&quot;</span><span class="re2">/&gt;</span></span>
    <span class="sc3"><span class="re1">&lt;dropColumn</span> <span class="re0">tableName</span>=<span class="st0">&quot;Person&quot;</span> <span class="re0">columnName</span>=<span class="st0">&quot;FirstName&quot;</span><span class="re2">/&gt;</span></span>
    <span class="sc3"><span class="re1">&lt;/rollback<span class="re2">&gt;</span></span></span>
<span class="sc3"><span class="re1">&lt;/changeSet<span class="re2">&gt;</span></span></span></pre></div></div></div></div></div></div></div>


<p>During deployment, the tool is responsible for translating migrations written in XML into SQL of target database server. Liquibase comes with an interesting feature of a rollback deployment in case a business decision to go back to previous version arises. In some cases the rollback does not have to be defined (add column, remove column) since a recipe for rollback can be inherited from the migration definition. But for a more advanced migration like in the example above the rollback recipe has to be defined manually.</p>
<h3>Conclusion</h3>
<p>Regardless of what approach the development team chooses for database migrations it always results in creating of a database change script. In simple case, the script is first generated by a database comparison tool, then a developer manuall reviews in and corrects conflicting changes. <a href="https://github.com/chucknorris/roundhouse/wiki">RoundhousE</a> or <a href="http://www.liquibase.org/">Liquibase</a> represent such a family of tools.</p>
<p>Advanced tools use custom DSL for defining database migrations. They can be written in application original language (<a href="http://guides.rubyonrails.org/migrations.html">Ruby migrations</a>, <a href="https://github.com/schambers/fluentmigrator/wiki">FluentMigrator</a>).</p>
<p>There are also mature commercial products that include both database comparison and deployment features in one tool. <a href="http://www.red-gate.com/products/sql-development/sql-data-compare/">SQL Data Compare</a> and <a href="http://www.nextep-softwares.com/">NeXtep Open Designer</a> are promising tools for database deployment automation.</p>
<p>Related posts:<ol>
<li><a href='http://blog.dbtracer.org/2011/10/31/database-deployment-patterns-introduction/' rel='bookmark' title='Database Deployment Patterns (Introduction)'>Database Deployment Patterns (Introduction)</a></li>
<li><a href='http://blog.dbtracer.org/2010/01/12/database-continuous-integration-with-dbtracer/' rel='bookmark' title='Database Continuous Integration with DbTracer'>Database Continuous Integration with DbTracer</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.dbtracer.org/2011/10/21/database-deployment-approaches/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<series:name><![CDATA[Database Deployment]]></series:name>
	</item>
		<item>
		<title>Inconclusive Tests in TFS Build Should Not Break the Build</title>
		<link>http://blog.dbtracer.org/2011/02/27/inconclusive-tests-in-tfs-build-should-not-break-the-build/</link>
		<comments>http://blog.dbtracer.org/2011/02/27/inconclusive-tests-in-tfs-build-should-not-break-the-build/#comments</comments>
		<pubDate>Sun, 27 Feb 2011 20:38:19 +0000</pubDate>
		<dc:creator>Petr Kozelek</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[MsBuild]]></category>
		<category><![CDATA[MsTest]]></category>
		<category><![CDATA[TFS]]></category>

		<guid isPermaLink="false">http://blog.dbtracer.org/?p=144</guid>
		<description><![CDATA[I work in a company where we use MsTest as testing framework. TFS is our integration platform. For a long time we have been struggling with a problem that inconclusive tests are breaking the whole team build because mstest.exe returns exit code -1. My friend asked a question in StackOverflow where he summarized our requirements: [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>I work in a company where we use MsTest as testing framework. <span class="about" title="Team Foundation Server">TFS</span> is our integration platform. For a long time we have been struggling with a problem that inconclusive tests are breaking the whole team build because <code>mstest.exe</code> returns exit code -1. My friend asked a <a href="http://stackoverflow.com/questions/4733592/assert-inconclusive-and-ignoreattribute">question</a> in StackOverflow where he summarized our requirements:</p>
<blockquote><p>We are using <code>Assert.Inconclusive</code> mainly for tests which are:</p>
<ul>
<li>Not implemented yet</li>
<li>Somehow broken or incomplete = requires futher attention</li>
<li>When test body is for any reason commented out</li>
</ul>
<p>We are doing this because:</p>
<ul>
<li>Inconclusive test can have message</li>
<li>We want to see such tests in test results on TFS</li>
</ul>
</blockquote>
<p>I did not find any simple way how to make TFS build understand that inconclusive tests should not break the build. Finally,  I found a workaround.  It is based on analysis of trx file after completing test phase of the build. Trx is the XML file containing all details about the test run. Among others, it contains a node <code>&lt;ResultSummary&gt;</code>:</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="xml"><pre class="de1"><span class="sc3"><span class="re1">&lt;?xml</span> <span class="re0">version</span>=<span class="st0">&quot;1.0&quot;</span> <span class="re0">encoding</span>=<span class="st0">&quot;UTF-8&quot;</span><span class="re2">?&gt;</span></span>
<span class="sc3"><span class="re1">&lt;TestRun</span> <span class="re0">id</span>=<span class="st0">&quot;2811e37a-3c6e-4e9f-90a0-6cf0d6e7f44c&quot;</span></span>
<span class="sc3"> <span class="re0">name</span>=<span class="st0">&quot;TestResults&quot;</span> <span class="re0">runUser</span>=<span class="st0">&quot;MACHINE\user&quot;</span></span>
<span class="sc3"> <span class="re0">xmlns</span>=<span class="st0">&quot;http://microsoft.com/schemas/VisualStudio/TeamTest/2010&quot;</span><span class="re2">&gt;</span></span>
 ...
 <span class="sc3"><span class="re1">&lt;ResultSummary</span> <span class="re0">outcome</span>=<span class="st0">&quot;Inconclusive&quot;</span><span class="re2">&gt;</span></span>
   <span class="sc3"><span class="re1">&lt;Counters</span> <span class="re0">total</span>=<span class="st0">&quot;487&quot;</span> <span class="re0">executed</span>=<span class="st0">&quot;487&quot;</span> <span class="re0">passed</span>=<span class="st0">&quot;485&quot;</span></span>
<span class="sc3">     <span class="re0">error</span>=<span class="st0">&quot;0&quot;</span> <span class="re0">failed</span>=<span class="st0">&quot;0&quot;</span> <span class="re0">timeout</span>=<span class="st0">&quot;0&quot;</span> <span class="re0">aborted</span>=<span class="st0">&quot;0&quot;</span></span>
<span class="sc3">     <span class="re0">inconclusive</span>=<span class="st0">&quot;2&quot;</span> <span class="re0">passedButRunAborted</span>=<span class="st0">&quot;0&quot;</span></span>
<span class="sc3">     <span class="re0">notRunnable</span>=<span class="st0">&quot;0&quot;</span> <span class="re0">notExecuted</span>=<span class="st0">&quot;0&quot;</span> <span class="re0">disconnected</span>=<span class="st0">&quot;0&quot;</span></span>
<span class="sc3">     <span class="re0">warning</span>=<span class="st0">&quot;0&quot;</span> <span class="re0">completed</span>=<span class="st0">&quot;0&quot;</span> <span class="re0">inProgress</span>=<span class="st0">&quot;0&quot;</span> <span class="re0">pending</span>=<span class="st0">&quot;0&quot;</span> <span class="re2">/&gt;</span></span>
 <span class="sc3"><span class="re1">&lt;/ResultSummary<span class="re2">&gt;</span></span></span>
 ...
<span class="sc3"><span class="re1">&lt;/TestRun<span class="re2">&gt;</span></span></span></pre></div></div></div></div></div></div></div>


<p>If there are any inconclusive tests and no other tests failed then the attribute <code>outcome</code> will have value <code>Inconclusive</code>. Analysis of the <code>trx</code> file in the build script was implemented with <a href="http://msbuildtasks.tigris.org">MsBuld community tasks</a>:</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="xml"><pre class="de1"><span class="sc3"><span class="re1">&lt;Target</span> <span class="re0">Name</span>=<span class="st0">&quot;AnalyzeTestResultsFile&quot;</span><span class="re2">&gt;</span></span>
 <span class="sc3"><span class="re1">&lt;ItemGroup<span class="re2">&gt;</span></span></span>
   <span class="sc3"><span class="re1">&lt;TrxFilePath</span> <span class="re0">Include</span>=<span class="st0">&quot;$(TestResultsRoot)\*.trx&quot;</span> <span class="re2">/&gt;</span></span>
 <span class="sc3"><span class="re1">&lt;/ItemGroup<span class="re2">&gt;</span></span></span>
 <span class="sc-1">&lt;!-- Namespace should be specific for MsTest version --&gt;</span>
 <span class="sc3"><span class="re1">&lt;XmlRead</span> <span class="re0">Prefix</span>=<span class="st0">&quot;n&quot;</span></span>
<span class="sc3">   <span class="re0">Namespace</span>=<span class="st0">&quot;http://microsoft.com/schemas/VisualStudio/TeamTest/2010&quot;</span></span>
<span class="sc3">   <span class="re0">XPath</span>=<span class="st0">&quot;/n:TestRun/n:ResultSummary/@outcome&quot;</span></span>
<span class="sc3">   <span class="re0">XmlFileName</span>=<span class="st0">&quot;@(TrxFilePath)&quot;</span><span class="re2">&gt;</span></span>
     <span class="sc3"><span class="re1">&lt;Output</span> <span class="re0">TaskParameter</span>=<span class="st0">&quot;Value&quot;</span> <span class="re0">PropertyName</span>=<span class="st0">&quot;TestOutcome&quot;</span> <span class="re2">/&gt;</span></span>
   <span class="sc3"><span class="re1">&lt;/XmlRead<span class="re2">&gt;</span></span></span>
   <span class="sc3"><span class="re1">&lt;Error</span> <span class="re0">Text</span>=<span class="st0">&quot;Test outcome was $(TestOutcome).&quot;</span> <span class="re0">Condition</span>=<span class="st0">&quot;'$(TestOutcome)' == 'Error' or '$(TestOutcome)' == 'Failed' or '$(TestOutcome)' == 'Timeout' or '$(TestOutcome)' == 'Aborted'&quot;</span> <span class="re2">/&gt;</span></span>
 <span class="sc3"><span class="re1">&lt;/Target<span class="re2">&gt;</span></span></span></pre></div></div></div></div></div></div></div>


<p>If you want to have such behavior  in all your builds the the simplest way is to create a file in <code>$(MsBuildExtensionPath)</code> (usually <code>C:\Program Files\MSBuild\</code>):</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="xml"><pre class="de1"><span class="sc3"><span class="re1">&lt;?xml</span> <span class="re0">version</span>=<span class="st0">&quot;1.0&quot;</span> <span class="re0">encoding</span>=<span class="st0">&quot;utf-8&quot;</span> <span class="re2">?&gt;</span></span>
<span class="sc3"><span class="re1">&lt;Project</span> <span class="re0">xmlns</span>=<span class="st0">&quot;http://schemas.microsoft.com/developer/msbuild/2003&quot;</span><span class="re2">&gt;</span></span>
 <span class="sc3"><span class="re1">&lt;Import</span> <span class="re0">Project</span>=<span class="st0">&quot;$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets&quot;</span></span>
<span class="sc3">   <span class="re0">Condition</span>=<span class="st0">&quot; '$(TeamBuildVersion)' == '' &quot;</span><span class="re2">/&gt;</span></span>
 <span class="sc3"><span class="re1">&lt;Import</span> <span class="re0">Project</span>=<span class="st0">&quot;$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets&quot;</span></span>
<span class="sc3">   <span class="re0">Condition</span>=<span class="st0">&quot; '$(MSBuildCommunityTasksLib)' == '' &quot;</span> <span class="re2">/&gt;</span></span>
&nbsp;
 <span class="sc3"><span class="re1">&lt;PropertyGroup<span class="re2">&gt;</span></span></span>
   <span class="sc3"><span class="re1">&lt;TestConfigurationDependsOn<span class="re2">&gt;</span></span></span>
     ResetTestWorkspace;
     $(TestConfigurationDependsOn);
     AnalyzeTestResultsFile;
   <span class="sc3"><span class="re1">&lt;/TestConfigurationDependsOn<span class="re2">&gt;</span></span></span>
 <span class="sc3"><span class="re1">&lt;/PropertyGroup<span class="re2">&gt;</span></span></span>
&nbsp;
 <span class="sc3"><span class="re1">&lt;Target</span> <span class="re0">Name</span>=<span class="st0">&quot;ResetTestWorkspace&quot;</span><span class="re2">&gt;</span></span>
   <span class="sc3"><span class="re1">&lt;RemoveDir</span> <span class="re0">Directories</span>=<span class="st0">&quot;$(TestResultsRoot)&quot;</span> <span class="re2">/&gt;</span></span>    
   <span class="sc3"><span class="re1">&lt;PropertyGroup<span class="re2">&gt;</span></span></span>
     <span class="sc3"><span class="re1">&lt;StopOnTestFailure<span class="re2">&gt;</span></span></span>false<span class="sc3"><span class="re1">&lt;/StopOnTestFailure<span class="re2">&gt;</span></span></span>
   <span class="sc3"><span class="re1">&lt;/PropertyGroup<span class="re2">&gt;</span></span></span>
 <span class="sc3"><span class="re1">&lt;/Target<span class="re2">&gt;</span></span></span>
&nbsp;
 <span class="sc3"><span class="re1">&lt;Target</span> <span class="re0">Name</span>=<span class="st0">&quot;AnalyzeTestResultsFile&quot;</span><span class="re2">&gt;</span></span>
   <span class="sc3"><span class="re1">&lt;ItemGroup<span class="re2">&gt;</span></span></span>
     <span class="sc3"><span class="re1">&lt;TrxFilePath</span> <span class="re0">Include</span>=<span class="st0">&quot;$(TestResultsRoot)\*.trx&quot;</span> <span class="re2">/&gt;</span></span>
   <span class="sc3"><span class="re1">&lt;/ItemGroup<span class="re2">&gt;</span></span></span>
   <span class="sc-1">&lt;!-- Namespace should be specific for MsTest version --&gt;</span>
   <span class="sc3"><span class="re1">&lt;XmlRead</span> <span class="re0">Prefix</span>=<span class="st0">&quot;n&quot;</span></span>
<span class="sc3">     <span class="re0">Namespace</span>=<span class="st0">&quot;http://microsoft.com/schemas/VisualStudio/TeamTest/2010&quot;</span></span>
<span class="sc3">     <span class="re0">XPath</span>=<span class="st0">&quot;/n:TestRun/n:ResultSummary/@outcome&quot;</span></span>
<span class="sc3">     <span class="re0">XmlFileName</span>=<span class="st0">&quot;@(TrxFilePath)&quot;</span><span class="re2">&gt;</span></span>
     <span class="sc3"><span class="re1">&lt;Output</span> <span class="re0">TaskParameter</span>=<span class="st0">&quot;Value&quot;</span> <span class="re0">PropertyName</span>=<span class="st0">&quot;TestOutcome&quot;</span> <span class="re2">/&gt;</span></span>
   <span class="sc3"><span class="re1">&lt;/XmlRead<span class="re2">&gt;</span></span></span>
   <span class="sc3"><span class="re1">&lt;Error</span> <span class="re0">Text</span>=<span class="st0">&quot;Test outcome was $(TestOutcome).&quot;</span> <span class="re0">Condition</span>=<span class="st0">&quot;'$(TestOutcome)' == 'Error' or '$(TestOutcome)' == 'Failed' or '$(TestOutcome)' == 'Timeout' or '$(TestOutcome)' == 'Aborted'&quot;</span> <span class="re2">/&gt;</span></span>
 <span class="sc3"><span class="re1">&lt;/Target<span class="re2">&gt;</span></span></span>
<span class="sc3"><span class="re1">&lt;/Project<span class="re2">&gt;</span></span></span></pre></div></div></div></div></div></div></div>


<p>I redefined property <code>$(TestConfigurationDependsOn</code>) so that target <code>ResetTestWorkspace</code> is automatically called right before test run is invoked. Target <code>AnalyzeTestResultsFile</code> is called after test run when <code>trx</code> file is already available.</p>
<p>With this TFS template all your builds will not fail when you have some tests inconclusive.</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.dbtracer.org/2011/02/27/inconclusive-tests-in-tfs-build-should-not-break-the-build/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Audit Trail – Tracing Data Changes in Database</title>
		<link>http://blog.dbtracer.org/2010/08/30/audit-trail-%e2%80%93-tracing-data-changes-in-database/</link>
		<comments>http://blog.dbtracer.org/2010/08/30/audit-trail-%e2%80%93-tracing-data-changes-in-database/#comments</comments>
		<pubDate>Mon, 30 Aug 2010 20:41:00 +0000</pubDate>
		<dc:creator>Petr Kozelek</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.dbtracer.org/?p=127</guid>
		<description><![CDATA[The common requirement in many enterprise applications is logging of data changes in a database – what data has changed, who changed them and when (audit logging). Bloggers published many articles about this old problem but there is only few general approaches how to do that in relational databases. Promiscuous Women Cause Problems for Database [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>The common requirement in many enterprise applications is logging of  data changes  in a database – what data has changed, who changed them  and when (<a href="http://en.wikipedia.org/wiki/Audit_trail">audit logging</a>).   Bloggers published many articles about this old problem but there is  only few general approaches how to do that in relational databases.<span id="more-127"></span></p>
<h2>Promiscuous Women Cause Problems for Database Administrators</h2>
<p>This is a fiction story that never happened:</p>
<p>Juliet Capulet meets Paul Smith; they fell in love and marry on 25th  August 2009. When Juliet is back at work she asks the db admin to change  her name in a company database. The admin is not happy to have  additional work with this stuff but he does it for her.</p>
<p>Juliet’s and Paul’s marriage is not going well and Juliet divorces  Paul after a short period. Soon Juliet feels alone, she meets Romeo  Montague and, of course, falls in desperate love with him. Logically,  another wedding is arranged and Juliet asks db admin to change her name  again on 10th January 2010.</p>
<p>The tragedy of all Juliet’s love relationships finishes when she  finds her husband Romeo as a roulette player spending all their money.  She divorces again and changes her name to Juliet Singleton on 21st July  2010 with the vision not to marry anybody again. Needless to say, the  db admin is close to committing suicide because his database does not  allow changing the name more than twice.</p>
<p>What would you suggest the database admin to do better in his next life?</p>
<h2>Problem description</h2>
<p>Let us summarize what the db admin was asked to do with Juliet’s personal data:</p>
<ul>
<li>Juliet Capulet gets the job on 2005-03-01</li>
<li>Name Juliet Capulet changes to Juliet Smith on 2009-08-25</li>
<li>Name Juliet Smith changes to Juliet Montague on 2010-01-10</li>
<li>Name Juliet Montague changes to Julie Singleton on 2010-07-21</li>
</ul>
<h2>Solution No.1: Roll off Out-dated data</h2>
<p>The simplest solution for keeping historical data in the database is  to create a duplicated record before update. After that we can update  the requested data. In case of tracing Juliet’s name  we get these data  in the database table:</p>
<table>
<tbody>
<tr>
<td>id</td>
<td>name</td>
<td>created_date</td>
<td>created _by</td>
</tr>
<tr>
<td>124</td>
<td>Juliet Capulet</td>
<td>2005-03-01</td>
<td>admin</td>
</tr>
<tr>
<td>124</td>
<td>Juliet Smith</td>
<td>2009-08-25</td>
<td>admin</td>
</tr>
<tr>
<td>124</td>
<td>Juliet Montague</td>
<td>2010-01-10</td>
<td>admin</td>
</tr>
<tr>
<td>124</td>
<td>Juliet Singleton</td>
<td>2010-07-21</td>
<td>admin</td>
</tr>
</tbody>
</table>
<p>In real database schema, id is primary key and has to be unique. So  we need extra column containing information about row id from which data  were rolled off. Additionally, it would be helpful to have a column  representing status of the record. Because situation gets more complex  here I show how data evolve in database:</p>
<p>Juliet Capulet gets the job on 2005-03-01.</p>
<table>
<tbody>
<tr>
<td>id</td>
<td>original_id</td>
<td>status</td>
<td>name</td>
<td>created_date</td>
<td>created _by</td>
</tr>
<tr>
<td>124</td>
<td>124</td>
<td>active</td>
<td>Juliet Capulet</td>
<td>2005-03-01</td>
<td>admin</td>
</tr>
</tbody>
</table>
<p>Name Juliet Capulet changes to Juliet Smith on 2009-08-25.</p>
<table>
<tbody>
<tr>
<td>id</td>
<td>original_id</td>
<td>status</td>
<td>name</td>
<td>created_date</td>
<td>created _by</td>
</tr>
<tr>
<td>124</td>
<td>124</td>
<td>active</td>
<td>Juliet Smith</td>
<td>2009-08-25</td>
<td>admin</td>
</tr>
<tr>
<td>254</td>
<td>124</td>
<td>history</td>
<td>Juliet Capulet</td>
<td>2005-03-01</td>
<td>admin</td>
</tr>
</tbody>
</table>
<p>Name Juliet Smith changes to Juliet Montague on 2010-01-10.</p>
<table>
<tbody>
<tr>
<td>id</td>
<td>original_id</td>
<td>status</td>
<td>name</td>
<td>created_date</td>
<td>created _by</td>
</tr>
<tr>
<td>124</td>
<td>124</td>
<td>active</td>
<td>Juliet Montague</td>
<td>2010-01-10</td>
<td>admin</td>
</tr>
<tr>
<td>254</td>
<td>124</td>
<td>history</td>
<td>Juliet Capulet</td>
<td>2005-03-01</td>
<td>admin</td>
</tr>
<tr>
<td>347</td>
<td>124</td>
<td>history</td>
<td>Juliet Smith</td>
<td>2009-08-25</td>
<td>admin</td>
</tr>
</tbody>
</table>
<p>Name Juliet Montague changes to Julie Singleton on 2010-07-21.</p>
<table>
<tbody>
<tr>
<td>id</td>
<td>original_id</td>
<td>status</td>
<td>name</td>
<td>created_date</td>
<td>created _by</td>
</tr>
<tr>
<td>124</td>
<td>124</td>
<td>active</td>
<td>Juliet Singleton</td>
<td>2010-07-21</td>
<td>admin</td>
</tr>
<tr>
<td>254</td>
<td>124</td>
<td>history</td>
<td>Juliet Capulet</td>
<td>2005-03-01</td>
<td>admin</td>
</tr>
<tr>
<td>347</td>
<td>124</td>
<td>history</td>
<td>Juliet Smith</td>
<td>2009-08-25</td>
<td>admin</td>
</tr>
<tr>
<td>489</td>
<td>124</td>
<td>history</td>
<td>Juliet Montague</td>
<td>2010-01-10</td>
<td>admin</td>
</tr>
</tbody>
</table>
<p>You can see that each change to the record with id=124 invokes a)  creating duplicated row with status=history and b) updating the column  name to a requested value with created_date set to current date. When  the active record is going to be “deleted” then only the status flag  changes the value from active to history.</p>
<h3>Advantages</h3>
<p>It is simple to implement audit logging based on rolling out old  data. You do not need additional tables. Maintenance is simple, too. If  you decide to remove old data then it is the matter of one SQL.</p>
<h3>Disadvantages</h3>
<p>But what if you need to implement audit logging in more tables? You  need to add columns original_id, status, created_date and created_by.  And you have to implement previously introduced roll-off logic, either  to database directly (usually with table triggers) or in the  application.</p>
<p>The problem can be that when data changes then the whole record is  copied, i.e. also data which do not change. It causes data duplication  and, potentially, database disk space can increase markedly if changes  occur frequently. For example, if table persons has a column photo with  binary data containing the photography then each and every time Juliet’s  name changes the whole record (including the photo) is copied to  rolled-off record.</p>
<p>Another disadvantage is that the complexity of each table supporting  audit logging increases. You must have in mind all the time that  retrieving the records is not simple. You always have to use the SELECT  clause with condition</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="sql"><pre class="de1"><span class="kw1">SELECT</span> <span class="sy0">*</span> <span class="kw1">FROM</span> persons <span class="kw1">WHERE</span> <span class="kw1">STATUS</span><span class="sy0">=</span><span class="st0">'active'</span></pre></div></div></div></div></div></div></div>


<p>When you need to roll back historical data for a particular record  you have to copy all columns from the historical record to the active  record. It would be easier just to switch status value from “history” to  “active” but it would break reference integrity if the record was  referenced in other tables.</p>
<h2>Solution No.2: Dedicated Data-Tracing Table</h2>
<p>Another approach is based on separate audit log table that is  dedicated to logging data changes coming from all tables having audit  log feature:</p>
<table>
<tbody>
<tr>
<td>id</td>
<td>table</td>
<td>column</td>
<td>row</td>
<td>changed_date</td>
<td>changed_by</td>
<td>old_value</td>
<td>new_value</td>
</tr>
<tr>
<td>1241</td>
<td>persons</td>
<td>name</td>
<td>124</td>
<td>2005-03-01</td>
<td>admin</td>
<td>Juliet Capulet</td>
<td>Juliet Capulet</td>
</tr>
<tr>
<td>1654</td>
<td>persons</td>
<td>name</td>
<td>124</td>
<td>2009-08-25</td>
<td>admin</td>
<td>Juliet Capulet</td>
<td>Juliet Smith</td>
</tr>
<tr>
<td>2547</td>
<td>persons</td>
<td>name</td>
<td>124</td>
<td>2010-01-10</td>
<td>admin</td>
<td>Juliet Smith</td>
<td>Juliet Montague</td>
</tr>
<tr>
<td>3645</td>
<td>persons</td>
<td>name</td>
<td>124</td>
<td>2010-07-21</td>
<td>admin</td>
<td>Juliet Montague</td>
<td>Juliet Singleton</td>
</tr>
</tbody>
</table>
<h3>Advantages</h3>
<p>This solutions separates the concerns much better. There is only one  common data store for all historical data. Further, you have to  implement audit log feature only once for all tables which should  support it.</p>
<p>Compared to the previous solution, when the record changes only the  changed data are logged. Thus it is expected to be a little bit faster  but I did not do any tests so I cannot prove it exactly. The real  advantage is that you need lower disk space to store data changes. You  can improve the table structure when you normalize the log table and you  put just integer references to “table” and “column”.</p>
<p>You can easily retrieve user activity just by the query</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="sql"><pre class="de1"><span class="kw1">SELECT</span> <span class="sy0">*</span> <span class="kw1">FROM</span> audit_log <span class="kw1">WHERE</span> changed_by<span class="sy0">=</span><span class="st0">'admin'</span></pre></div></div></div></div></div></div></div>


<h3>Disadvantages</h3>
<p>All data changes are logged in a common table so old and new values  stored there must be of some generic type. For example, in MS SQL it can  be “sql_variant”. Or you can convert the values to “varchar” before  storing them in the log table.</p>
<p>Rollback is rather difficult task to be implemented. If you want to roll data back to 3rd March 21010 you have to use query</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="sql"><pre class="de1"><span class="kw1">SELECT</span> <span class="br0">&#91;</span><span class="kw1">TABLE</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="br0">&#91;</span><span class="kw1">COLUMN</span><span class="br0">&#93;</span><span class="sy0">,</span> old_value<span class="sy0">,</span> new_value <span class="kw1">FROM</span> audit_log <span class="kw1">WHERE</span> <span class="br0">&#91;</span><span class="kw1">TABLE</span><span class="br0">&#93;</span><span class="sy0">=</span><span class="st0">'persons'</span> <span class="kw1">AND</span> <span class="kw1">ROW</span><span class="sy0">=</span><span class="nu0">124</span> <span class="kw1">AND</span> changed_date <span class="sy0">&gt;</span> <span class="st0">'2010-03-01'</span> <span class="kw1">ORDER</span> <span class="kw1">BY</span> changed_date</pre></div></div></div></div></div></div></div>


<p>and then you iterate through the result set and build the dynamic  query because table and column info is in the result. It is more  complicated compared to the previous solution. However, the feature has to be implemented only once and then it is reused across the whole application.</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.dbtracer.org/2010/08/30/audit-trail-%e2%80%93-tracing-data-changes-in-database/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Speed Up Typing Text with WatiN</title>
		<link>http://blog.dbtracer.org/2010/08/05/speed-up-typing-text-with-watin/</link>
		<comments>http://blog.dbtracer.org/2010/08/05/speed-up-typing-text-with-watin/#comments</comments>
		<pubDate>Thu, 05 Aug 2010 20:49:28 +0000</pubDate>
		<dc:creator>Petr Kozelek</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.dbtracer.org/?p=134</guid>
		<description><![CDATA[I use WatiN for UA testing and I was facing the problem that WatiN is slow while typing text into text field with TextField.TypeText(string) method. TypeText(string) is slow because during run it fires sequences of key events: KeyDown(char), KeyPress(char), KeyUp(char). The sequence is invoked as many times as the length of the input string is. As the [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>I use <a href="http://watin.org/">WatiN</a> for UA  testing and I was facing the problem that WatiN is slow while typing  text into text field with TextField.TypeText(string) method.</p>
<p>TypeText(string) is slow because during run it fires sequences of key  events: KeyDown(char), KeyPress(char), KeyUp(char). The sequence is  invoked as many times as the length of the input string is. As the  result, the input text is typed to the text field one by one char. It is  slow and when you have hundreds of tests then you wait tens of minutes  for their execution! I created simple extension method to speed up  typing of text markedly – for a string 10 chars long the performance of  typing is around 30 times higher.</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="csharp"><pre class="de1"><span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">class</span> WatiNExtensions
<span class="br0">&#123;</span>
    <span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">void</span> TypeTextQuickly<span class="br0">&#40;</span><span class="kw1">this</span> TextField textField, <span class="kw4">string</span> text<span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        textField<span class="sy0">.</span><span class="me1">SetAttributeValue</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span>, text<span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div></div></div></div></div></div>


<p>In my solution I do not use simulated key events. I use direct  setting of value attribute in text field. The limitation of this  solution is that it does not raise focus and blur events. Additionally,  no key events are fired.</p>
<p>Usage is simple:</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="csharp"><pre class="de1">var browser <span class="sy0">=</span> <span class="kw3">new</span> IE<span class="br0">&#40;</span><span class="st0">&quot;http://google.com&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
browser<span class="sy0">.</span><span class="me1">TextField</span><span class="br0">&#40;</span><span class="st0">&quot;q&quot;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">TypeTextQuickly</span><span class="br0">&#40;</span><span class="st0">&quot;WatiN&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// fast - raises neither key events nor focus and blur on text field</span>
<span class="co1">// browser.TextField(&quot;q&quot;).TypeText(&quot;WatiN&quot;); // slow - raises key events</span></pre></div></div></div></div></div></div></div>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.dbtracer.org/2010/08/05/speed-up-typing-text-with-watin/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Porting a Subversion to a Git Repository with an Error &#8220;Permission denied: Can&#8217;t open &#8216;/tmp/report.tmp&#8217;&#8221;</title>
		<link>http://blog.dbtracer.org/2010/01/20/porting-subversion-git-with-error/</link>
		<comments>http://blog.dbtracer.org/2010/01/20/porting-subversion-git-with-error/#comments</comments>
		<pubDate>Wed, 20 Jan 2010 17:02:27 +0000</pubDate>
		<dc:creator>Petr Kozelek</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[solutions]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://petrkozelek.e-blog.cz/?p=102</guid>
		<description><![CDATA[I was dealing with a problem of converting existing Subversion repository to a new git repository on my local Windows XP station.I carefully followed steps described here: C:\Program Files\Git\bin&#62;git svn init -s file:///D:/path/to/svn/repository Initialized empty Git repository in C:/Program Files/Git/bin/.git/ But Ooops! Error occurred when I tried to fetch all the history to Git repository: [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>I was dealing with a problem of converting existing Subversion repository to a new git repository on my local Windows XP station.<span id="more-102"></span>I carefully followed steps described <a href="http://blog.romansklenar.cz/porting-a-subversion-repository-into-git/">here</a>:</p>
<pre>C:\Program Files\Git\bin&gt;git svn init -s file:///D:/path/to/svn/repository
Initialized empty Git repository in C:/Program Files/Git/bin/.git/</pre>
<p>But Ooops! Error occurred when I tried to fetch all the history to Git repository:</p>
<pre>C:\Program Files\Git\bin&gt;git svn fetch
 A       notes.txt
 A       pages.txt
 A       settings.config
r7 = f3dba0984f11e2f358923c23d89440789eb4591b (refs/remotes/references)
<strong>Permission denied: Can't open '/tmp/report.tmp': Permission denied at C:\Program Files\Git/libexec/git-core/git-svn line 2723</strong></pre>
<p>It was an misguiding error since I had neither a &#8220;tmp&#8221; directory in the original <kbd>svn</kbd> repository nor &#8220;report.tmp&#8221; directory<strong><strong>.</strong></strong> For my surprise the problem was caused by different formats used by in original Subversion repository and by Subversion module included in my Git instance that probably uses older Subversion format. I use Git 1.6.5.1.1367.gcd48 that probably has Subversion module supporting format 4 but my Subversion repository was in format 5.</p>
<h2>Solution</h2>
<p>Luckily the solution for such WTF <a href="http://code.google.com/p/msysgit/issues/detail?id=298#c5">exists</a>. If I access Subversion repository via SVN server instead of directly via file path problem will not occur. Thus, at first it is necessary to run SVN server:</p>
<pre>svnserve.exe -d -r D:/parent/path/to/repository/</pre>
<p>And then you can access Subversion repository via its server:</p>
<pre>git.exe svn init -s "<strong>svn://localhost</strong>/relative/path/to/subversion/repository"</pre>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.dbtracer.org/2010/01/20/porting-subversion-git-with-error/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Database Continuous Integration with DbTracer</title>
		<link>http://blog.dbtracer.org/2010/01/12/database-continuous-integration-with-dbtracer/</link>
		<comments>http://blog.dbtracer.org/2010/01/12/database-continuous-integration-with-dbtracer/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 23:55:37 +0000</pubDate>
		<dc:creator>Petr Kozelek</dc:creator>
				<category><![CDATA[Database Continuous Integration]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[DbTracer]]></category>

		<guid isPermaLink="false">http://petrkozelek.e-blog.cz/?p=77</guid>
		<description><![CDATA[In my company we use principles of continuous integration in our C#.Net+MS SQL development. We use Subversion for source control management and CruiseControl.Net as integration server. The problem came when we needed to choose a tool for continuous integration of database changes since we did not find any open-source alternative. The common repository for all [...]
Related posts:<ol>
<li><a href='http://blog.dbtracer.org/2011/10/21/database-deployment-approaches/' rel='bookmark' title='Database Deployment Approaches'>Database Deployment Approaches</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a title="DBTracker" href="http://code.google.com/p/dbtracker/"><img class="alignleft size-full wp-image-121" title="DBTracker" src="http://petrkozelek.e-blog.cz/wp-content/uploads/dbt-logo1.png" alt="" width="104" height="55" /></a><br />
In my company we use principles of continuous integration in our C#.Net+MS SQL development. We use Subversion for source control management and CruiseControl.Net as integration server. The problem came when we needed to choose a tool for continuous integration of database changes since we did not find any open-source alternative.</p>
<p><span id="more-77"></span></p>
<p>The common repository for all source code changes is Subversion (currently we think of migrating to <a href="http://git-scm.com/">Git</a>, anyway). For tracking changes of database schema changes we use Subversion, too.</p>
<p>In our team each developer has his own database server installed on his PC and he is an administrator of his own database server. The core of everything is the SCM. Developers check out latest code from there, integration server uses it as well to get code base and integration tests. The idea connected with tracking changes of database schema was to include changes under version control. Then both developers and integration server were able to retrieve database schema changes and to handle them.</p>
<h2>Database Change Scripts</h2>
<p>If a developer wishes to do some changes in database schema, he can freely do that on his local database without fear to influence work of the others. As the result of his work he is expected to create a <em>database change script</em> that includes all schema changes needed to be implemented. Let&#8217;s say we need to add a column to the table. The change script will contain these SQL commands:</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="sql"><pre class="de1"><span class="kw1">ALTER</span> <span class="kw1">TABLE</span> <span class="kw1">ORDER</span>
<span class="kw1">ADD</span> <span class="kw1">STATUS</span> <span class="kw1">INT</span> <span class="kw1">NOT</span> <span class="kw1">NULL</span> <span class="kw1">DEFAULT</span> <span class="nu0">0</span>
<span class="kw1">GO</span></pre></div></div></div></div></div></div></div>


<p>The script will add a column &#8220;Status&#8221; to a table &#8220;Order&#8221;. You can feel it would be very annoying for a developer to change database schema only via change scripts in regular daily work. We established a helpful practice how to make things easier for the developer. The change script should be the result of his work that he wish to be integrated. We work as follows:</p>
<ol>
<li>When developer is going to do schema changes (on his local machine, of course), first he creates a clone of database version that was already fully integrated to source control. Let&#8217;s say that database is in version 1.5 so he creates a clone of it with help of <a href="http://code.google.com/p/dbtracker/">DbTracer</a>:
<pre>cmd&gt; dbt create /database=reference_db_v_1_5 /db-version=1.5 /connection=(local)</pre>
</li>
<li>At this point he has a reference database that will serve him as a reference point when he will compare it with his test database. The test database is created in the same way as reference one:
<pre>cmd&gt; dbt create /database=test /connection=(local) /db-version=1.5 /override-if-exists</pre>
</li>
<li>Now the developer is ready to do whatever he wants in the &#8220;test&#8221; database. For example he can add a column &#8220;Status&#8221; to a table &#8220;Order&#8221;. Of course you are not limited to add only one schema change to one change script.</li>
<li>When he is ready with schema changes he compares the test database with a reference database &#8220;reference_db_v_1_5&#8243;. Tools for comparing databases are very much helpful here. In my team we use <a href="http://sqlmanager.net/products/mssql/dbcomparer">EMS DB Comparer</a>.</li>
<li>The tool generates a change script. It is possible to modify it manually if we are not satisfied with the result. After that, the change script is ready to be checked in to version control.</li>
</ol>
<h3>Change Script Names</h3>
<p>We use the following convention for our change scripts:</p>
<pre>&lt;major_version&gt;.&lt;minor_version&gt;.&lt;revision&gt;-&lt;some description of change script&gt;.UP.sql</pre>
<p>For example:</p>
<pre>003.012.0541-add column Status to table Order.UP.sql</pre>
<p>In this example the change script lies within database major version=3, minor version=12 and its revision=541. There is also a short description &#8220;add column Status to table Order&#8221; defining what is inside the change script. Additionally, the keyword &#8220;UP&#8221; in the change script is reserved for future when we will need to distinguish between <em>upgrade change scripts </em>and <em>downgrade change scripts</em>.</p>
<p>Now the change script is ready to go to version control.</p>
<h2>Our Solution &#8211; DbTracer</h2>
<p>We searched for a simple tool that would maintain a our database migration scripts. Additionally, it should provide following features:</p>
<ul>
<li>command line interface</li>
<li>storing SQL database version in the database itself</li>
</ul>
<p>Unfortunately, no such tool existed that would have been acceptable. Hence, we inspired by <a href="http://wildbit.com/blog/2008/03/24/database-continuous-integration-in-net/">Alexander Kleshchevnikov</a> and wrote our own tool <a href="http://code.google.com/p/dbtracker/">DbTracer</a>. Currently it is in experimental phase for public. We use it internally in our team but still API changes are going on.</p>
<h2>Further Reading</h2>
<ul>
<li><a href="http://odetocode.com/Blogs/scott/archive/2008/01/31/three-rules-for-database-work.aspx">Three Rules for Database Work</a></li>
<li><a href="http://wildbit.com/blog/2008/03/24/database-continuous-integration-in-net/">Database Continuous Integration in .NET</a></li>
<li><a href="http://martinfowler.com/articles/evodb.html">Evolutionary Database Design</a></li>
</ul>
<p>Related posts:<ol>
<li><a href='http://blog.dbtracer.org/2011/10/21/database-deployment-approaches/' rel='bookmark' title='Database Deployment Approaches'>Database Deployment Approaches</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.dbtracer.org/2010/01/12/database-continuous-integration-with-dbtracer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

