<?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>Floorplanner Tech Blog &#187; Databases</title>
	<atom:link href="http://techblog.floorplanner.com/category/databases/feed/" rel="self" type="application/rss+xml" />
	<link>http://techblog.floorplanner.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Thu, 19 Nov 2009 04:00:57 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Request-log-analyzer 1.5.0</title>
		<link>http://techblog.floorplanner.com/2009/11/18/request-log-analyzer-1-5-0/</link>
		<comments>http://techblog.floorplanner.com/2009/11/18/request-log-analyzer-1-5-0/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 17:51:42 +0000</pubDate>
		<dc:creator>Willem van Bergen</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[request-log-analyzer]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[slow query log]]></category>

		<guid isPermaLink="false">http://techblog.floorplanner.com/?p=801</guid>
		<description><![CDATA[Bart and I just released request-log-analyzer version 1.5.0. New features include:

MySQL slow query log format support to analyze what queries are slowing down your database.
Format autodetection: with all those supported file formats, remembering the right --format parameter gets tricky. With format autodetection, this usually is not needed anymore!

As always, run the following command to install [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2009%2F11%2F18%2Frequest-log-analyzer-1-5-0%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2009%2F11%2F18%2Frequest-log-analyzer-1-5-0%2F" height="61" width="51" /></a></div><p>Bart and I just released <a href="http://github.com/wvanbergen/request-log-analyzer">request-log-analyzer</a> version 1.5.0. New features include:</p>
<ul>
<li><a href="http://wiki.github.com/wvanbergen/request-log-analyzer/mysql-slow-query-log">MySQL slow query log</a> format support to analyze what queries are slowing down your database.</li>
<li><strong>Format autodetection:</strong> with all those supported file formats, remembering the right <code style="white-space: nowrap">--format</code> parameter gets tricky. With format autodetection, this usually is not needed anymore!</li>
</ul>
<p>As always, run the following command to install or upgrade to the latest version:</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family: Monaco,monospace;">$ gem install request-log-analyzer</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://techblog.floorplanner.com/2009/11/18/request-log-analyzer-1-5-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Case-insensitive validates_uniqueness_of slowness</title>
		<link>http://techblog.floorplanner.com/2009/11/17/case-insensitive-validates_uniqueness_of-slowness/</link>
		<comments>http://techblog.floorplanner.com/2009/11/17/case-insensitive-validates_uniqueness_of-slowness/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 14:01:02 +0000</pubDate>
		<dc:creator>Willem van Bergen</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[case insensitive]]></category>
		<category><![CDATA[index]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[validates_uniqueness_of]]></category>

		<guid isPermaLink="false">http://techblog.floorplanner.com/?p=787</guid>
		<description><![CDATA[Watch out when using validates_uniqueness_of :field, :case_sensitive => false. Rails transforms this in a query that cannot be supported by an index, which will really slow validation down if the underlying table grows larger.
For example, we use validates_uniqueness_of to check for duplicate e-mail addresses. Because email addresses are case-insensitive, adding :case_sensitive => false seems like [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2009%2F11%2F17%2Fcase-insensitive-validates_uniqueness_of-slowness%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2009%2F11%2F17%2Fcase-insensitive-validates_uniqueness_of-slowness%2F" height="61" width="51" /></a></div><p>Watch out when using <code>validates_uniqueness_of :field, :case_sensitive => false</code>. Rails transforms this in a query that cannot be supported by an index, which will really slow validation down if the underlying table grows larger.</p>
<p>For example, we use <code>validates_uniqueness_of</code> to check for duplicate e-mail addresses. Because email addresses are case-insensitive, adding <code>:case_sensitive => false</code> seems like a natural choice. However, this results in the following queries:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family: Monaco,monospace;"><span style="color: #808080; font-style: italic;"># For a new User instance:</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> id <span style="color: #993333; font-weight: bold;">FROM</span> users 
 <span style="color: #993333; font-weight: bold;">WHERE</span> LOWER<span style="color: #66cc66;">&#40;</span>users<span style="color: #66cc66;">.</span>email<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #993333; font-weight: bold;">BINARY</span> <span style="color: #ff0000;">'user@example.com'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># For an existing User instance:</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> id <span style="color: #993333; font-weight: bold;">FROM</span> users 
 <span style="color: #993333; font-weight: bold;">WHERE</span> LOWER<span style="color: #66cc66;">&#40;</span>users<span style="color: #66cc66;">.</span>email<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #993333; font-weight: bold;">BINARY</span> <span style="color: #ff0000;">'user@example.com'</span> 
   <span style="color: #993333; font-weight: bold;">AND</span> users<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">&lt;&gt;</span> <span style="color: #cc66cc;">42</span></pre></div></div>

<p>This query cannot be optimized by a (unique) index on the email field and thus has to scan the full table. As our users table grew larger, these queries started to show up in our slow query log. </p>
<p>However, MySQL uses case-insensitive comparison by default. (To be exact, case-sensitiveness depends on the current collation, which can vary. Rails generates the weird query to make sure the check works, regardless of the current collation.) The conversion to lowercase therefore is not necessary for a uniqueness check (as long as the field has a case-insensitive collation like <code>utf8_general_ci</code>). I decided to write my own validation method that issues a query that can be optimized by a query.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family: Monaco,monospace;">  <span style="color:#008000; font-style:italic;"># Alternative for validates_uniqueness_of :email, :case_sensitive =&gt; false</span>
  validate <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>user<span style="color:#006600; font-weight:bold;">|</span>
    conditions = <span style="color:#996600;">&quot;users.email = :email&quot;</span>
    conditions <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#996600;">&quot; AND users.id != :id&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> user.<span style="color:#9900CC;">new_record</span>?
    conditions = <span style="color:#006600; font-weight:bold;">&#91;</span>conditions, <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:email</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> user.<span style="color:#9900CC;">email</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> user.<span style="color:#9900CC;">id</span> <span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> User.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:first</span>, <span style="color:#ff3333; font-weight:bold;">:select</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:id</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> conditions<span style="color:#006600; font-weight:bold;">&#41;</span>
      user.<span style="color:#9900CC;">errors</span>.<span style="color:#9900CC;">add</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:email</span>, <span style="color:#996600;">'Already in use'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>There is <a href="https://rails.lighthouseapp.com/projects/8994/tickets/2503-validates_uniqueness_of-is-horribly-inefficient-in-mysql">a ticket for this issue in Rails&#8217;s Lighthouse</a>, but as of yet this issue is unresolved. For now, this solution works to keep our slow query log nice and quiet!</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.floorplanner.com/2009/11/17/case-insensitive-validates_uniqueness_of-slowness/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Database replication in 5 easy steps</title>
		<link>http://techblog.floorplanner.com/2009/11/09/database-replication-in-5-easy-steps/</link>
		<comments>http://techblog.floorplanner.com/2009/11/09/database-replication-in-5-easy-steps/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 13:34:00 +0000</pubDate>
		<dc:creator>Gert-Jan</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[database replication mysql]]></category>

		<guid isPermaLink="false">http://techblog.floorplanner.com/?p=753</guid>
		<description><![CDATA[Running an online service like Floorplanner is not without risks. There are a lot of things that can go wrong. One of them is downtime of your service due to a crashing system. It doesn&#8217;t have to happen of course, but when it does, it can have some nasty consequences. A good way to reduce [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2009%2F11%2F09%2Fdatabase-replication-in-5-easy-steps%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2009%2F11%2F09%2Fdatabase-replication-in-5-easy-steps%2F" height="61" width="51" /></a></div><p>Running an online service like <a href="http://floorplanner.com">Floorplanner</a> is not without risks. There are a lot of things that can go wrong. One of them is downtime of your service due to a crashing system. It doesn&#8217;t have to happen of course, but when it does, it can have some nasty consequences. A good way to reduce the risk of a crashing system is to set up a redundant system.</p>
<p>In short, a redundant system is an exact copy of your main system. When your main system goes down (for whatever reason), the redundant system can take over. One of the most important parts of any online service is the database. A way to maintain an exact copy of your database is setting up database replication. This post gives you the basics on how to set up database replication using a MySQL database.</p>
<p>Database replication isn&#8217;t probably something you&#8217;d setup right from the start. This means that you have to work with a running system when you decide to do so. From past experience we know that it&#8217;s not a good idea to replicate your database to the same machine, let alone to the same disk. To make this work, you need a separate machine with MySQL installed. This is your slave machine and database.</p>
<p>Let&#8217;s get down to business. These are the steps for setting up database replication:</p>
<ol>
<li>Enable binary logging on master database</li>
<li>Create a backup of master database</li>
<li>Transfer backup to slave machine</li>
<li>Import backup to slave database</li>
<li>Start slave database</li>
</ol>
<h3>1. Enable binary logging on master database</h3>
<blockquote><p><em>The binary log contains all statements that update data [..]. Statements are stored in the form of “events” that describe the modifications. The binary log also contains information about how long each statement took that updated data.</em></p></blockquote>
<p>Every write action that&#8217;s performed on your database, like an insert or an update, is stored in these binary logs (bin logs). The master dumps all actions in these logs and the slave database can read them  and perform the same actions. This way your master and slave databases will always have the same data.</p>
<p>To enable binary logging you have to create a config file, for example master.cnf. An important thing here is the server-id, which is needed for replication to work. Then there is log-bin which specifies base name of binary logs, and finally binlog-do-db, which specifies which databases should be bin logged.</p>

<div class="wp_syntax"><div class="code"><pre class="cnf" style="font-family: Monaco,monospace;">[mysqld]
datadir=/home/yourname/mysql/myisam/data
basedir=/usr/local/mysql
port=3306
server-id=1
log-bin=mysql-bin
binlog-do-db=my_fat_db1
binlog-do-db=ma_other_fat_db</pre></div></div>

<p>Then start (or restart) the master database using the config file:</p>

<div class="wp_syntax"><div class="code"><pre class="cnf" style="font-family: Monaco,monospace;">~ $ mysqld --defaults-file=master.cnf&amp;amp;</pre></div></div>

<p>The slave database needs a userid/password in order to access the master machine. It&#8217;s best practice create a dedicated user with just the required privileges. This can be done with the following SQL statement.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family: Monaco,monospace;"><span style="color: #993333; font-weight: bold;">GRANT</span> replication slave <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #66cc66;">*.*</span> <span style="color: #993333; font-weight: bold;">TO</span> <span style="color: #ff0000;">'repl'</span>@<span style="color: #ff0000;">'slave-ip-here'</span></pre></div></div>

<h3>2. Create a backup of master database</h3>
<p>The next step it to create a backup of your master database. The type of your database is very important for this action. If you use MyISAM, you need to schedule some downtime to dump your database. Otherwise the dumped data isn&#8217;t consistent and therefor useless. <span style="background-color:#FFE789">With InnoDB it&#8217;s possible to dump a consistent backup of your database while keeping it up and running</span>. We stumbled on this feature by accident, but we haven&#8217;t been able to in the official documentation.</p>
<p>MyISAM</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family: Monaco,monospace;">~ $ mysqldump --lock-all-tables</pre></div></div>

<p>InnoDB</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family: Monaco,monospace;">~ $ mysqldump --single-transaction</pre></div></div>

<h3>3. Transfer backup to slave machine</h3>
<p>Now that the backup is created on the master machine, it needs to be transferred to the slave machine.</p>
<h3>4. Import backup to slave database</h3>
<p>Once the backup is present on the slave machine, it can be imported into the slave database:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family: Monaco,monospace;">~ $ mysql &amp;lt; filename</pre></div></div>

<h3>5. Start slave database</h3>
<p>The last step is to tell the database that it&#8217;s a slave database. First we have to give it an server id. We use a config file for this, slave.cnf:</p>

<div class="wp_syntax"><div class="code"><pre class="cnf" style="font-family: Monaco,monospace;">[mysqld]
datadir=/home/yourname/mysql/myisam/data
basedir=/usr/local/mysql
port=3306
server-id=2
replicate-do-db=my_fat_db1
replicate-do-db=my_other_fat_db</pre></div></div>

<p>Then we start the database with this config file:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family: Monaco,monospace;">~ $ mysqld --defaults-file=slave.cnf&amp;amp;</pre></div></div>

<p>and we issue the following SQL statement:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family: Monaco,monospace;"><span style="color: #993333; font-weight: bold;">CHANGE</span> MASTER <span style="color: #993333; font-weight: bold;">TO</span>
<span style="color: #66cc66;">-</span>&amp;gt; MASTER_HOST<span style="color: #66cc66;">=</span><span style="color: #ff0000;">'master-ip-here'</span><span style="color: #66cc66;">,</span>
<span style="color: #66cc66;">-</span>&amp;gt; MASTER_PORT<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">3306</span><span style="color: #66cc66;">,</span>
<span style="color: #66cc66;">-</span>&amp;gt; MASTER_USER<span style="color: #66cc66;">=</span><span style="color: #ff0000;">'repl'</span><span style="color: #66cc66;">,</span>
<span style="color: #66cc66;">-</span>&amp;gt; MASTER_PASSWORD<span style="color: #66cc66;">=</span><span style="color: #ff0000;">'repl'</span><span style="color: #66cc66;">,</span>
<span style="color: #66cc66;">-</span>&amp;gt; MASTER_LOG_FILE<span style="color: #66cc66;">=</span><span style="color: #ff0000;">'bin-log-filename-here'</span><span style="color: #66cc66;">,</span>
<span style="color: #66cc66;">-</span>&amp;gt; MASTER_LOG_POS<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">4</span>;</pre></div></div>

<p>It&#8217;s hard to predict the MASTER_LOG_POS. You can find this number by issuing the following SQL statement on the <strong>master</strong> database:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family: Monaco,monospace;"><span style="color: #993333; font-weight: bold;">SHOW</span> MASTER <span style="color: #993333; font-weight: bold;">STATUS</span>\G;</pre></div></div>

<p>Once the slave is configured correctly it will get the bin logs from the master machine, parse them and execute each action. It takes some time to have an exact copy of the master database, depending on the size and number of bin logs. To get an idea about the delay, issue the following query:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family: Monaco,monospace;"><span style="color: #993333; font-weight: bold;">SHOW</span> SLAVE <span style="color: #993333; font-weight: bold;">STATUS</span>\G;</pre></div></div>

<p>With this post we hope to contribute to a less riskier world and more peaceful state of mind for the sys admins out there <img src='http://techblog.floorplanner.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' />  </p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.floorplanner.com/2009/11/09/database-replication-in-5-easy-steps/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to remove hidden tab characters</title>
		<link>http://techblog.floorplanner.com/2008/12/17/how-to-remove-hidden-tab-characters/</link>
		<comments>http://techblog.floorplanner.com/2008/12/17/how-to-remove-hidden-tab-characters/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 13:31:37 +0000</pubDate>
		<dc:creator>Gert-Jan</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[tab character]]></category>

		<guid isPermaLink="false">http://techblog.floorplanner.com/?p=367</guid>
		<description><![CDATA[At this moment, all the language translations of the Floorplanner 2D app are stored in a database table. Today we discovered that a couple of these translations didn&#8217;t align properly in the interface. After some investigation we discovered that they all contained a hidden tab character at the end of  each string. This was probably [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2008%2F12%2F17%2Fhow-to-remove-hidden-tab-characters%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2008%2F12%2F17%2Fhow-to-remove-hidden-tab-characters%2F" height="61" width="51" /></a></div><p>At this moment, all the language translations of the Floorplanner 2D app are stored in a database table. Today we discovered that a couple of these translations didn&#8217;t align properly in the interface. After some investigation we discovered that they all contained a hidden tab character at the end of  each string. This was probably caused by importing a malformed CSV file.</p>
<p>I thought a simple <strong>REPLACE</strong> query would fix this problem, but (as usual) it was a little more complicated than that. First I had to find the fields with the tab character&#8230; <a href="http://twitter.com/wvanbergen/status/1060635881" target="_blank">Willem</a> pointed me to the right direction with his favorite weapon of choice <strong>REGEXP</strong>. According to the <a href="http://dev.mysql.com/doc/refman/5.1/en/regexp.html" target="_blank">MySQL docs</a> I could find tab characters with something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family: Monaco,monospace;">SELECT <span style="color: #339933;">*</span> FROM table WHERE field REGEXP <span style="color: #0000ff;">'[[.LF.]]'</span></pre></div></div>

<p>The next step was to remove the tab characters. My first thought was to do this by replacing them with an empty string. It turns out you can&#8217;t combine a <strong>REPLACE</strong> with a <strong>REGEXP</strong> in a query. So I used good ol&#8217; PHP for the job. A nice advantage was that I didn&#8217;t have to do any replacing, I could just use the <em>trim()</em> function.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family: Monaco,monospace;"><span style="color: #000088;">$res</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SELECT id, field FROM table WHERE field REGEXP '[[.LF.]]'&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$res</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_assoc</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$res</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$field</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'field'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;UPDATE table SET field = '<span style="color: #006699; font-weight: bold;">$field</span>' WHERE id = <span style="color: #006699; font-weight: bold;">$id</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Rather simple, when you know what to do&#8230; Another bug bites the dust!</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.floorplanner.com/2008/12/17/how-to-remove-hidden-tab-characters/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Active OLAP released</title>
		<link>http://techblog.floorplanner.com/2008/07/29/active-olap-released/</link>
		<comments>http://techblog.floorplanner.com/2008/07/29/active-olap-released/#comments</comments>
		<pubDate>Tue, 29 Jul 2008 16:13:10 +0000</pubDate>
		<dc:creator>Willem van Bergen</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[active_olap]]></category>
		<category><![CDATA[OLAP]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://techblog.floorplanner.com/?p=119</guid>
		<description><![CDATA[Remember my post about easy OLAP queries in Rails? I rewrote it almost completely and published is as a Rails plugin for anyone to use on github! It is now called: Active OLAP.
Although it is a complete rewrite, the API I demoed in my previous post should still work with some small changes. The most [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2008%2F07%2F29%2Factive-olap-released%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2008%2F07%2F29%2Factive-olap-released%2F" height="61" width="51" /></a></div><p>Remember my post about easy <a href="http://techblog.floorplanner.com/2008/07/14/easy-olap-queries-in-activerecord/">OLAP queries in Rails</a>? I rewrote it almost completely and published is as a Rails plugin for anyone to use on github! It is now called: <a href="http://github.com/wvanbergen/active_olap">Active OLAP</a>.</p>
<p>Although it is a complete rewrite, the API I demoed in my previous post should still work with some small changes. The most important: you have to enable it for every class you want to use it on with the <code>enable_active_olap</code> method. You can provide a block to this method with dimension definitions, but is not mandatory:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family: Monaco,monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
&nbsp;
  enable_active_olap <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>olap<span style="color:#006600; font-weight:bold;">|</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># create a simple dimension on the account_type field</span>
    olap.<span style="color:#9900CC;">dimension</span> <span style="color:#ff3333; font-weight:bold;">:account_type</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># create a dimension with custom categories</span>
    <span style="color:#008000; font-style:italic;"># the order of the categories will be kept in the results </span>
    <span style="color:#008000; font-style:italic;"># if you use an array to define the categories.</span>
    olap.<span style="color:#9900CC;">dimension</span> <span style="color:#ff3333; font-weight:bold;">:nationality</span>, <span style="color:#ff3333; font-weight:bold;">:categories</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span>
      <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:usa</span>, <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:country</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'US'</span> <span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:china</span>, <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:country</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'CN'</span> <span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#008000; font-style:italic;"># other is automatically added</span>
    <span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># Easily create a trend dimension</span>
    olap.<span style="color:#9900CC;">dimension</span> <span style="color:#ff3333; font-weight:bold;">:created_daily</span>, <span style="color:#ff3333; font-weight:bold;">:trend</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
      <span style="color:#ff3333; font-weight:bold;">:timestamp_field</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:created_at</span>,
      <span style="color:#ff3333; font-weight:bold;">:period_length</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> 1.<span style="color:#9900CC;">day</span>, 
      <span style="color:#ff3333; font-weight:bold;">:period_count</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">20</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now, we can use these dimensions for our OLAP queries. Multiple dimensions are supported too!</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family: Monaco,monospace;"><span style="color:#008000; font-style:italic;"># simple query</span>
<span style="color:#0066ff; font-weight:bold;">@result</span> = User.<span style="color:#9900CC;">olap_query</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:nationality</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#008000; font-style:italic;"># @result[:usa] == 123, @result[:china] == 456, @result[:other] = 789</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># do drilldown using will_paginate to paginate the results</span>
<span style="color:#008000; font-style:italic;"># olap_drilldown is implemented as a named_scope</span>
<span style="color:#0066ff; font-weight:bold;">@users</span> = User.<span style="color:#9900CC;">olap_drilldown</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:nationality</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:china</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">paginate</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:page</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># multiple dimensions!</span>
<span style="color:#0066ff; font-weight:bold;">@result</span> = User.<span style="color:#9900CC;">olap_query</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:nationality</span>, <span style="color:#ff3333; font-weight:bold;">:created_daily</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#0066ff; font-weight:bold;">@users</span> = User.<span style="color:#9900CC;">olap_drilldown</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:nationality</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:china</span>, 
                        <span style="color:#ff3333; font-weight:bold;">:created_daily</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:period_19</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>I am working on a generic controller that can easily be added to your Rails project. Just define dimensions for your models and the controller will let you execute OLAP queries and display the results as a table or a graph. </p>
<p>Keep an eye on this weblog or the <a href="http://github.com/wvanbergen/active_olap">github project</a> if you want to stay up-to-date! Or, contact me if you have questions, suggestions or want to help out.</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.floorplanner.com/2008/07/29/active-olap-released/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Easy OLAP queries in ActiveRecord</title>
		<link>http://techblog.floorplanner.com/2008/07/14/easy-olap-queries-in-activerecord/</link>
		<comments>http://techblog.floorplanner.com/2008/07/14/easy-olap-queries-in-activerecord/#comments</comments>
		<pubDate>Mon, 14 Jul 2008 20:42:18 +0000</pubDate>
		<dc:creator>Willem van Bergen</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[active_olap]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[OLAP]]></category>
		<category><![CDATA[statistics]]></category>

		<guid isPermaLink="false">http://techblog.floorplanner.com/?p=96</guid>
		<description><![CDATA[Because I love statistics so much, I decided to add some neat statistics functionality to the Floorplanner administration interface, so we can get better insight in what is going on. Instead of writing complete OLAP SQL queries myself and adding a custom interface for each one of them so our management can use them (yes [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2008%2F07%2F14%2Feasy-olap-queries-in-activerecord%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2008%2F07%2F14%2Feasy-olap-queries-in-activerecord%2F" height="61" width="51" /></a></div><p>Because I love statistics so much, I decided to add some neat statistics functionality to the Floorplanner administration interface, so we can get better insight in what is going on. Instead of writing complete OLAP SQL queries myself and adding a custom interface for each one of them so our management can use them (yes Jeroen, that means you!), I built an ActiveRecord extension to ease the work. Right now, I only have to define some categories, and it automagically generates the right SQL query to generate charts and tables with the number of records that fall in each category. Moreover, by clicking on these numbers, I can drill down to the individual records.</p>
<p>I can define the categories like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family: Monaco,monospace;">olap_definition = <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:categories</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
  <span style="color:#ff3333; font-weight:bold;">:project_is_private</span>   <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:public</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">false</span>, <span style="color:#ff3333; font-weight:bold;">:publishd_at</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">nil</span> <span style="color:#006600; font-weight:bold;">&#125;</span>,
  <span style="color:#ff3333; font-weight:bold;">:project_is_public</span>    <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:public</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>,  <span style="color:#ff3333; font-weight:bold;">:publishd_at</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">nil</span> <span style="color:#006600; font-weight:bold;">&#125;</span>,
  <span style="color:#ff3333; font-weight:bold;">:project_is_published</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'projects.published_at IS NOT NULL'</span>
<span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>Not too hard, was it? Now, I can easily feed this to <code>Project.olap_query</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family: Monaco,monospace;"><span style="color:#0066ff; font-weight:bold;">@query_result</span> = Project.<span style="color:#9900CC;">olap_query</span><span style="color:#006600; font-weight:bold;">&#40;</span>olap_definition<span style="color:#006600; font-weight:bold;">&#41;</span> 
<span style="color:#008000; font-style:italic;"># @query_result == {</span>
<span style="color:#008000; font-style:italic;">#   :project_is_private   =&gt; 123,</span>
<span style="color:#008000; font-style:italic;">#   :project_is_public    =&gt; 456,</span>
<span style="color:#008000; font-style:italic;">#   :project_is_published =&gt; 3,</span>
<span style="color:#008000; font-style:italic;">#   :other                =&gt; 2</span>
<span style="color:#008000; font-style:italic;"># }</span></pre></div></div>

<p>Note that the category <em>other</em> is added automatically, but can be omitted if you wish. (I found that the other-category is nice to spot data integrity problems in your dataset you didn&#8217;t think of beforehand). The result can be used to create a table with the results, plot a pie chart with the Google Charts API. Because this setup is completely generic, this functionality only has to be written once. DRY!</p>
<p>The SQL for other-category is &#8220;calculated&#8221; by OR-ing all the categories and checking whether the result is <code>false</code>, or <code>NULL</code>. The check for <code>NULL</code> is necessary if you have <code>NULL</code>-values in your table: this is a weird characteristic of SQL that defines that <code>TRUE AND NULL</code> equals <code>NULL</code> (see <a href="http://en.wikipedia.org/wiki/Null_(SQL)#Three-valued_logic_.283VL.29">Wikipedia</a>).</p>
<p>The actual SQL query for this example would be:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family: Monaco,monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> 
  SUM<span style="color: #66cc66;">&#40;</span>projects<span style="color: #66cc66;">.</span>public <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span> <span style="color: #993333; font-weight: bold;">AND</span> projects<span style="color: #66cc66;">.</span>published_at <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> project_is_private<span style="color: #66cc66;">,</span>
  SUM<span style="color: #66cc66;">&#40;</span>projects<span style="color: #66cc66;">.</span>public <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AND</span> projects<span style="color: #66cc66;">.</span>published_at <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> project_is_public<span style="color: #66cc66;">,</span>
  SUM<span style="color: #66cc66;">&#40;</span>projects<span style="color: #66cc66;">.</span>published_at <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> project_is_published<span style="color: #66cc66;">,</span>
  SUM<span style="color: #66cc66;">&#40;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #66cc66;">&#40;</span>
    <span style="color: #66cc66;">&#40;</span>projects<span style="color: #66cc66;">.</span>public <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span> <span style="color: #993333; font-weight: bold;">AND</span> projects<span style="color: #66cc66;">.</span>published_at <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">OR</span>
    <span style="color: #66cc66;">&#40;</span>projects<span style="color: #66cc66;">.</span>public <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AND</span> projects<span style="color: #66cc66;">.</span>published_at <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">OR</span>
    <span style="color: #66cc66;">&#40;</span>projects<span style="color: #66cc66;">.</span>published_at <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #66cc66;">&#40;</span>
    <span style="color: #66cc66;">&#40;</span>projects<span style="color: #66cc66;">.</span>public <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span> <span style="color: #993333; font-weight: bold;">AND</span> projects<span style="color: #66cc66;">.</span>published_at <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">OR</span>
    <span style="color: #66cc66;">&#40;</span>projects<span style="color: #66cc66;">.</span>public <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AND</span> projects<span style="color: #66cc66;">.</span>published_at <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">OR</span>
    <span style="color: #66cc66;">&#40;</span>projects<span style="color: #66cc66;">.</span>published_at <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> other
<span style="color: #993333; font-weight: bold;">FROM</span> projects</pre></div></div>

<p>Some notes about this query:</p>
<ul>
<li>It is complety built using the fragments from the categories. The fragment for the other-cagegory is a little verbose, but what do I care? It works and is generated automatically! <img src='http://techblog.floorplanner.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
<li>Note that a record can be in multiple categories, depending on the category definitions. The other category only contains records that conform to none of the provided categories.</li>
<li><code>SUM</code> is used in stead of <code>COUNT</code>. This way, I can query all the categories at once and it solves the problems with <code>NULL</code>-values, while keeping my <code>WHERE</code> and <code>GROUP BY</code> clause nice and clean <img src='http://techblog.floorplanner.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  </li>
<li>The query is built completely using ActiveRecords <code>find</code> method by using <a href="http://railscasts.com/episodes/112">anonymous scopes</a>. Therefore, Rails 2.1 is required, but this makes some neat tricks possible as well.
</ul>
<p>I also have a <code>Project.olap_drilldown</code> method that I can use to find the individual projects in a category:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family: Monaco,monospace;"><span style="color:#0066ff; font-weight:bold;">@projects</span> = Project.<span style="color:#9900CC;">olap_drilldown</span><span style="color:#006600; font-weight:bold;">&#40;</span>olap_definition, <span style="color:#ff3333; font-weight:bold;">:project_is_public</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#008000; font-style:italic;"># SELECT projects.* FROM projects </span>
<span style="color:#008000; font-style:italic;"># WHERE (projects.public = 1 AND projects.published_at IS NULL)</span>
&nbsp;
<span style="color:#0066ff; font-weight:bold;">@projects</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>project<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> project.<span style="color:#9900CC;">name</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Because this functionality is built on anonymous scopes, it offers some interesting additional functionality. You can use your own scopes to limit the input dataset</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family: Monaco,monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Project <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  named_scope <span style="color:#ff3333; font-weight:bold;">:recent</span>, <span style="color:#CC0066; font-weight:bold;">lambda</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> 
              <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'created_at &gt; ?'</span>, <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span> <span style="color:#006600; font-weight:bold;">-</span> 7.<span style="color:#9900CC;">days</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
  ...
<span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#008000; font-style:italic;"># This will add a WHERE-clause to the OLAP query</span>
results = Project.<span style="color:#9900CC;">recent</span>.<span style="color:#9900CC;">olap_query</span><span style="color:#006600; font-weight:bold;">&#40;</span>olap_definition<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Or, use :conditions for the same effect</span>
results = Project.<span style="color:#9900CC;">olap_query</span><span style="color:#006600; font-weight:bold;">&#40;</span>olap_definition.<span style="color:#9900CC;">merge</span><span style="color:#006600; font-weight:bold;">&#40;</span>
            <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'created_at &gt; ?'</span>, <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span> <span style="color:#006600; font-weight:bold;">-</span> 7.<span style="color:#9900CC;">days</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>As I noted before, the <code>GROUP BY</code>-clause is not used. I already built an extension to use the <code>GROUP BY</code> clause to group the results in periods of a given timestamp field of the model (e.g. <code>created_by</code>). When I pass the result of such a query to the Google Chart API, I can generate trend graphs to see how my dataset is evolving.</p>
<p>If I have time and there is any interest, I may release this extension as a gem or Rails plugin.</p>
<p><strong>UPDATE:</strong> I <a href="http://techblog.floorplanner.com/2008/07/29/active-olap-released/">rewrote it</a> and released this project on <a href="http://github.com/wvanbergen/active_olap/">github</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.floorplanner.com/2008/07/14/easy-olap-queries-in-activerecord/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Raise by one SQL statement</title>
		<link>http://techblog.floorplanner.com/2007/10/17/raise-by-one-sql-statement/</link>
		<comments>http://techblog.floorplanner.com/2007/10/17/raise-by-one-sql-statement/#comments</comments>
		<pubDate>Wed, 17 Oct 2007 17:29:18 +0000</pubDate>
		<dc:creator>Gert-Jan</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[increment]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://www.suite75.net/blog/dev/raise-by-one-sql-statement.html</guid>
		<description><![CDATA[Today I discovered that it&#8217;s very easy to raise a value by one (or any other number) when you&#8217;re using a MySQL database. This is all:

UPDATE tablename SET value = value + 1 WHERE ...

]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2007%2F10%2F17%2Fraise-by-one-sql-statement%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2007%2F10%2F17%2Fraise-by-one-sql-statement%2F" height="61" width="51" /></a></div><p>Today I discovered that it&#8217;s very easy to raise a value by one (or any other number) when you&#8217;re using a MySQL database. This is all:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family: Monaco,monospace;"><span style="color: #993333; font-weight: bold;">UPDATE</span> tablename <span style="color: #993333; font-weight: bold;">SET</span> value <span style="color: #66cc66;">=</span> value <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">...</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://techblog.floorplanner.com/2007/10/17/raise-by-one-sql-statement/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Multiple relations between 2 tables in Rails</title>
		<link>http://techblog.floorplanner.com/2007/07/11/multiple-relations-between-2-tables-in-rails/</link>
		<comments>http://techblog.floorplanner.com/2007/07/11/multiple-relations-between-2-tables-in-rails/#comments</comments>
		<pubDate>Wed, 11 Jul 2007 13:29:19 +0000</pubDate>
		<dc:creator>Gert-Jan</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.suite75.net/blog/dev/?p=51</guid>
		<description><![CDATA[Just a small post about something I figured out recently&#8230;
If 2 database tables have a relation, in Rails you model it using the belongs_to and the has_one (has_many) attributes. Rails guesses the foreign key based on the names of the tables and its field names. In my setup I had 4 relations between 2 tables, [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2007%2F07%2F11%2Fmultiple-relations-between-2-tables-in-rails%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Ftechblog.floorplanner.com%2F2007%2F07%2F11%2Fmultiple-relations-between-2-tables-in-rails%2F" height="61" width="51" /></a></div><p>Just a small post about something I figured out recently&#8230;</p>
<p>If 2 database tables have a relation, in Rails you model it using the belongs_to and the has_one (has_many) attributes. Rails guesses the foreign key based on the names of the tables and its field names. In my setup I had 4 relations between 2 tables, so Rails couldn&#8217;t guess the foreign key&#8217;s by itself. All I had to do to make it work, was to specify the foreign keys and the related class:</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family: Monaco,monospace;">  belongs_to <span style="color:#ff3333; font-weight:bold;">:var_1</span>, <span style="color:#ff3333; font-weight:bold;">:foreign_key</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;id_1&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:class_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;RelatedClass&quot;</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:var_2</span>, <span style="color:#ff3333; font-weight:bold;">:foreign_key</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;id_2&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:class_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;RelatedClass&quot;</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:var_3</span>, <span style="color:#ff3333; font-weight:bold;">:foreign_key</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;id_3&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:class_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;RelatedClass&quot;</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:var_4</span>, <span style="color:#ff3333; font-weight:bold;">:foreign_key</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;id_4&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:class_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;RelatedClass</span></pre></div></div>
</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.floorplanner.com/2007/07/11/multiple-relations-between-2-tables-in-rails/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
