<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-31748626</id><updated>2012-02-16T05:06:25.248-05:00</updated><category term='drysql'/><category term='mysql'/><category term='ruby-smalltalk'/><category term='ORM'/><category term='database'/><title type='text'>All Your Database Are Belong To Me</title><subtitle type='html'>Discoveries, Open Source Projects, Rants, HowTo</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://allyourdatabase.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://allyourdatabase.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Bryan Evans</name><uri>http://www.blogger.com/profile/17994955569354693357</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://photos1.blogger.com/blogger/7063/3458/1600/bry_mic2.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-31748626.post-8997202907357409027</id><published>2007-08-25T16:14:00.000-04:00</published><updated>2007-08-26T23:16:07.950-04:00</updated><title type='text'>Merits of Defining your DB Schema in your Application?</title><content type='html'>Late last year I developed and released a Ruby plugin called &lt;a href="http://drysql.rubyforge.org"&gt;DrySQL&lt;/a&gt; that aims to eliminate any traces of DB schema re-definition in your application. The philosophy behind this effort is that the DB is indeed the place that table structures, constraints, and relationships should be defined, and that it is redundant to re-define any of these artifacts in an application or anywhere else.&lt;br /&gt;&lt;br /&gt;While my colleagues in the enterprise space generally shared my philosophy, I have heard some suggest that &lt;a href="http://drysql.rubyforge.org"&gt;DrySQL&lt;/a&gt;'s approach "sounded backwards" and I know of at least one project out there that aims to do exactly the opposite of what &lt;a href="http://drysql.rubyforge.org"&gt;DrySQL&lt;/a&gt; does: it aims to support defining the DB schema entirely on the application side rather than on the DB.&lt;br /&gt;&lt;br /&gt;I don't yet understand the attraction of this approach, but I'll be interested to hear the opinions of those who support it. I have difficulty grasping the logic behind ignoring established best practices, no matter how small your business is, but I suppose that just about anything could make sense given the right (or wrong) set of requirements and restrictions. &lt;br /&gt;&lt;br /&gt;In considering my case for the DB schema living on the DB and nowhere else, my goal is to satisfy 2 main concerns.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1) Controlling The Cost of Change&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To &lt;i&gt;maximally&lt;/i&gt; reduce the cost of change in an environment consisting of one or more applications interacting with one or more databases, each database schema should be defined in one place only. If the schema is defined in more than one place, schema changes become more difficult (and thus more unattractive) to perform, as they must be cascaded across multiple definitions. If synchronizing multiple definitions requires human intervention, this approach is obviously prone to human error, not to mention tedium and annoyance. This situation is described as "inviting a maintenance nightmare" in The Pragmatic Programmer. Minimizing barriers to change is important to me because I want my software infrastructure to support evolution, and even encourage it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2) Maintaining Data Integrity&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Given that the DB schema is to live in one place only, what place can guarantee the integrity of your data? Only the database itself. There are no back doors through the constraints defined on your database (except perhaps a bug in your DBMS if you are incredibly unlucky). Constraints defined elsewhere cannot be guaranteed to be enforced before data is written to your DB. Even in an environment where only one application interacts with your DB, it would be naive to think that your data would be safe without constraints on the DB. All it takes is one developer or tester (maybe even you?) to take a shortcut, execute a few "harmless" SQL queries through your database's command line interface (or any other interface for that matter), and your data is corrupted. The worst part of all is that the corruption might not be obvious immediately. Sure, an adequate backup schedule and a DB with some decent rollback/rollforward functionality will let you re-stabilize your data, but why pass up a frontline data protection mechanism that is so effective and accessible?&lt;br /&gt;&lt;br /&gt;If you have an opinion on this subject -- particularly if it differs from mine -- please share it with me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31748626-8997202907357409027?l=allyourdatabase.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://allyourdatabase.blogspot.com/feeds/8997202907357409027/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31748626&amp;postID=8997202907357409027' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/8997202907357409027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/8997202907357409027'/><link rel='alternate' type='text/html' href='http://allyourdatabase.blogspot.com/2007/08/merits-of-defining-your-db-schema-in.html' title='Merits of Defining your DB Schema in your Application?'/><author><name>Bryan Evans</name><uri>http://www.blogger.com/profile/17994955569354693357</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://photos1.blogger.com/blogger/7063/3458/1600/bry_mic2.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31748626.post-6421685397286021584</id><published>2007-02-01T16:29:00.000-05:00</published><updated>2007-05-29T21:37:45.954-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='drysql'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby-smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>DB2 iSeries Adapter for Rails</title><content type='html'>I recently released a new version of &lt;a href="http://drysql.rubyforge.org/"&gt;DrySQL&lt;/a&gt; (a Ruby plug-in) that supports DB2 iSeries. I didn't feel it was appropriate to post this on IBM's DB2 Rails Forum, so hopefully people who are interested in trying out this functionality will find this post.&lt;br /&gt;&lt;br /&gt;iSeries is not currently supported by IBM's DB2 Rails adapter, so I created extensions to the IBM adapter and released them as part of DrySQL. As far as I know, this is the only generally available iSeries adapter for Ruby at the moment. Those who do not care to use the DrySQL plug-in can simply unpack the gem, pull out the DB2 adapter extensions, and use them however they wish to. I expect to add the code to the DrySQL SVN repository on RubyForge shortly, which should make this easier.&lt;br /&gt;&lt;br /&gt;Note that you will need to install DB2 Connect and the IBM DB2 Rails adapter in order to use this functionality.&lt;br /&gt;&lt;br /&gt;You can find more information about this on the &lt;a href="http://drysql.rubyforge.org/"&gt;DrySQL homepage&lt;/a&gt;. If anyone needs help getting it up and running or wants to report bugs, please reply to this post and/or post to the &lt;a href="http://rubyforge.org/forum/?group_id=2438"&gt;DrySQL forums&lt;/a&gt; on RubyForge.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="font-weight: bold;"&gt;Update (May 29, 2007):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;IBM's ibm_db adapter now supports iSeries, so I have removed the custom support from DrySQL. The latest code from the DrySQL SVN repository on RubyForge works correctly with the ibm_db adapter.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31748626-6421685397286021584?l=allyourdatabase.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://allyourdatabase.blogspot.com/feeds/6421685397286021584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31748626&amp;postID=6421685397286021584' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/6421685397286021584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/6421685397286021584'/><link rel='alternate' type='text/html' href='http://allyourdatabase.blogspot.com/2007/02/db2-iseries-adapter-for-rails.html' title='DB2 iSeries Adapter for Rails'/><author><name>Bryan Evans</name><uri>http://www.blogger.com/profile/17994955569354693357</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://photos1.blogger.com/blogger/7063/3458/1600/bry_mic2.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31748626.post-6896169362917946406</id><published>2006-11-17T14:12:00.000-05:00</published><updated>2006-11-22T11:42:47.057-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>Multiple Cascade Paths Error in SQL Server</title><content type='html'>Working on &lt;a href="http://drysql.rubyforge.org/"&gt;DrySQL&lt;/a&gt; has given me an opportunity to learn about the subtle differences between many DBMSs.&lt;br /&gt;&lt;br /&gt;As my project is designed to run on a number of DBMSs, I crafted a reasonably complex test DB schema that I create on each DBMS in order to run my unit tests.&lt;br /&gt;&lt;br /&gt;Though my test schema can be created without error on MySQL, PostgreSQL, and DB2, when I attempted to create it on SQL Server Express 2005 recently, it errored on the attempted creation of a FOREIGN KEY constraint with cascaded deletes and updates:&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;Server: Msg 1785, Level 16, State 1, Line 1 Introducing FOREIGN KEY constraint 'PAYMT_APP_FK2' on table 'PAYMENT_APPLICATION' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Server: Msg 1750, Level 16, State 1, Line 1 Could not create constraint. See previous errors.&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;I'll explain the error using the following table layout.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger2/4626/3875/1600/687853/AR_Tables_blog.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://photos1.blogger.com/x/blogger2/4626/3875/320/54891/AR_Tables_blog.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Note that all the FOREIGN KEYs were created with cascaded delete and update options.&lt;br /&gt;&lt;br /&gt;The constraint definition that produced the error above was in my &lt;code&gt;CREATE TABLE&lt;/code&gt; statement for the &lt;code&gt;PAYMENT_APPLICATION&lt;/code&gt; table.&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;[PAYMENT_APPLICATION.BILL_ID...]FOREIGN KEY REFERENCES MONTHLY_BILL.ID CASCADE DELETE CASCADE UPDATE&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;According to &lt;a href="http://support.microsoft.com/kb/321843"&gt;Microsoft&lt;/a&gt; the above error occurs because "a table cannot appear more than one time in a list of all the cascading referential actions that are started by either a DELETE or an UPDATE statement". So, my constraint definition produces an error because the cascading delete path for INVOICE would like this if the constraint were defined:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger2/4626/3875/1600/898917/CascadingDeletePath.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://photos1.blogger.com/x/blogger2/4626/3875/320/124135/CascadingDeletePath.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;My &lt;code&gt;PAYMENT_APPLICATION&lt;/code&gt; table will appear twice on &lt;code&gt;INVOICE&lt;/code&gt;'s cascading delete/update path:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;PAYMENT_APPLICATION&lt;/code&gt; has an FK reference to &lt;code&gt;INVOICE&lt;/code&gt; with cascading delete/update options&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;PAYMENT_APPLICATION&lt;/code&gt; has an FK reference to &lt;code&gt;MONTHLY_BILL&lt;/code&gt; with cascading delete/update options, and &lt;code&gt;MONTHLY_BILL&lt;/code&gt; has an FK reference to &lt;code&gt;INVOICE&lt;/code&gt; with cascading delete/update options&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;As I mentioned earlier, SQL Server stands alone (to my knowledge) as the only DBMS that considers such constraints to be illegal. A simple solution to my problem would be to remove the cascade options from my &lt;code&gt;PAYMENT_APPLICATION--&gt;INVOICE&lt;/code&gt; Foreign Key constraint. The deletion/update of a referenced &lt;code&gt;INVOICE&lt;/code&gt; or &lt;code&gt;MONTHLY_BILL&lt;/code&gt; will still trigger a cascade onto the related &lt;code&gt;PAYMENT_APPLICATION&lt;/code&gt; record, which is ultimately the behaviour that I want.&lt;br /&gt;&lt;br /&gt;I can still create a DB schema that meets my needs in SQL Server, but it's annoying that I need to define my constraints differently than I do with other databases (although fairly typical of Microsoft software). I can't help wondering if this is a feature or a limitation.&lt;br /&gt;&lt;br /&gt;If anyone else has an opinion about this, I'll be interested to hear it. &lt;br /&gt;...And if anyone else experiences this error and struggles to figure out why, hopefully you find this explanantion helpful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31748626-6896169362917946406?l=allyourdatabase.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://allyourdatabase.blogspot.com/feeds/6896169362917946406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31748626&amp;postID=6896169362917946406' title='19 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/6896169362917946406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/6896169362917946406'/><link rel='alternate' type='text/html' href='http://allyourdatabase.blogspot.com/2006/11/multiple-cascade-paths-error-in-sql.html' title='Multiple Cascade Paths Error in SQL Server'/><author><name>Bryan Evans</name><uri>http://www.blogger.com/profile/17994955569354693357</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://photos1.blogger.com/blogger/7063/3458/1600/bry_mic2.jpg'/></author><thr:total>19</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31748626.post-2668715321081323285</id><published>2006-11-07T13:13:00.000-05:00</published><updated>2006-11-08T10:49:10.792-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='drysql'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby-smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><category scheme='http://www.blogger.com/atom/ns#' term='ORM'/><title type='text'>Generating ActiveRecord Data Validations Automatically</title><content type='html'>Having recently released &lt;a href="http://drysql.rubyforge.org/"&gt;DrySQL&lt;/a&gt;, which automatically generates validations for ActiveRecord data classes that enforce the constraints declared on your DB, I thought it might be useful to start a discussion about how this works (or should work).&lt;br /&gt;&lt;br /&gt;My (possibly naive) belief is that the value of application-side validations that enforce DB constraints is twofold:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;Allows the application to provide immediate feedback to UI/forms/whatever about validity of input without the performance overhead of querying the DB&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;Avoids wasting application and DB cycles trying to save/update invalid records&lt;/li&gt;&lt;/ul&gt;That said, let's look at the ActiveRecord validation methods, how they apply to enforcing DB constraints, and how &lt;a href="http://drysql.rubyforge.org/"&gt;DrySQL&lt;/a&gt; generates them automatically.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;validates_uniqueness_of&lt;br /&gt;&lt;/span&gt;I don't understand how this validation is useful, but will be interested to hear others' opinions about it. To validate that a particular value is unique in a particular table requires a DB query. Why do this on the application side rather than just letting the DB perform the validation and handling the duplicate key error your DB returns? This validation can be generated automatically based on the unique key information in the DB's information schema, but I'm not sure that it should be.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;validates_length_of&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;validates_numericality_of&lt;/span&gt;&lt;br /&gt;These validations can be generated automatically by querying the information schema's columns table. The columns table contains the restrictions that were declared for the column when it was defined.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;validates_inclusion_of&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;validates_exclusion_of&lt;/span&gt;&lt;br /&gt;These validations can be generated automatically for databases that support check constraints, but &lt;a href="http://drysql.rubyforge.org/"&gt;DrySQL&lt;/a&gt; does not yet implement this. Currently, &lt;code&gt;validates_inclusion_of&lt;/code&gt; is generated automatically only for boolean columns since we know the value must be in the set [true, false].&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;validates_presence_of&lt;/span&gt;&lt;br /&gt;This validation can be generated automatically by querying the information schema's columns table and checking the column's NOT NULL constraint. Unfortunately, the implementation of this validation in ActiveRecord does not accurately mirror the DB's NOT NULL constraint. In situations where the column contains character data and has the NOT NULL constraint set, &lt;code&gt;validates_presence_of&lt;/code&gt; will reject an empty string value even though the DB would consider this value to be valid. &lt;a href="http://drysql.rubyforge.org/"&gt;DrySQL&lt;/a&gt; does not generate this validation, but rather generates a new validation, &lt;code&gt;validates_nullability_of&lt;/code&gt;, where appropriate.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;validates_nullability_of&lt;/span&gt;&lt;br /&gt;This constraint is new, and was developed as part of &lt;a href="http://drysql.rubyforge.org/"&gt;DrySQL&lt;/a&gt;. It mirrors your DB's handling of NOT NULL constraints. This validation will reject a null value unless the column is autogenerated or has a default value specified, because your DB wouldn't reject a NULL in these situations either.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31748626-2668715321081323285?l=allyourdatabase.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://allyourdatabase.blogspot.com/feeds/2668715321081323285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31748626&amp;postID=2668715321081323285' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/2668715321081323285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/2668715321081323285'/><link rel='alternate' type='text/html' href='http://allyourdatabase.blogspot.com/2006/11/generating-activerecord-data.html' title='Generating ActiveRecord Data Validations Automatically'/><author><name>Bryan Evans</name><uri>http://www.blogger.com/profile/17994955569354693357</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://photos1.blogger.com/blogger/7063/3458/1600/bry_mic2.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31748626.post-8512187109656781504</id><published>2006-11-04T00:24:00.000-05:00</published><updated>2006-11-04T00:38:03.277-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='drysql'/><title type='text'>DrySQL: Answering the Challenge</title><content type='html'>After developing &lt;a href="http://drysql.rubyforge.org/"&gt;DrySQL&lt;/a&gt; to support some DB tooling at the financial organization that employs me, I was happy to learn that the functionality provided by &lt;a href="http://drysql.rubyforge.org/"&gt;DrySQL&lt;/a&gt; is actually the subject of Dave Thomas's (of Pragmatic fame) challenge to the Rails community at RailsConf 2006.&lt;br /&gt;&lt;br /&gt;The video of the keynote is available &lt;a href="http://blog.scribestudio.com/articles/2006/06/30/railsconf-2006-keynote-series-dave-thomas"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Leon Katsnelson, who is involved with the development of the official &lt;a href="http://www.alphaworks.ibm.com/tech/db2onrails"&gt;IBM Rails DB2 adapter&lt;/a&gt;, has also expressed the desire for this functionality on the DB2onRails blog &lt;a href="http://db2onrails.com/articles/2006/06/24/db2-on-rails-at-railsconf-day-one-dave-thomass-keynote"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Leon and Dave, if you ever happen to visit my blog or come across &lt;a href="http://drysql.rubyforge.org/"&gt;DrySQL&lt;/a&gt; somehow, I will be interested to hear your feedback about it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31748626-8512187109656781504?l=allyourdatabase.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://allyourdatabase.blogspot.com/feeds/8512187109656781504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31748626&amp;postID=8512187109656781504' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/8512187109656781504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/8512187109656781504'/><link rel='alternate' type='text/html' href='http://allyourdatabase.blogspot.com/2006/11/drysql-answering-challenge.html' title='DrySQL: Answering the Challenge'/><author><name>Bryan Evans</name><uri>http://www.blogger.com/profile/17994955569354693357</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://photos1.blogger.com/blogger/7063/3458/1600/bry_mic2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31748626.post-2990640179589996432</id><published>2006-11-03T18:28:00.000-05:00</published><updated>2006-11-03T19:39:33.356-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='drysql'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby-smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><category scheme='http://www.blogger.com/atom/ns#' term='ORM'/><title type='text'>Introducing DrySQL</title><content type='html'>After complaining about Object-Relational Mapping frameworks for years, I finally decided to do something about it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;u&gt;The Problem&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;My primary problem with today's ORM frameworks is that I end up defining my DB schema &lt;span style="font-style: italic;"&gt;twice&lt;/span&gt;: once on my DB itself, and once again in my application either in class definitions or ORM config files. Obviously, if I make structural changes to my DB I need to make corresponding changes in my application code or config files. I know that there are round-trip engineering solutions out there, as I mentioned in &lt;a href="http://allyourdatabase.blogspot.com/2006/10/or-mapping-frameworks.html"&gt;my previous ORM rant&lt;/a&gt;, but I have yet to come across a solution that I consider clean, efficient, simple, or remotely DRY (I would be interested in hearing about some though).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;u&gt;The Solution: ActiveRecord?&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;After experimenting with ActiveRecord and Ruby, I became convinced that I was onto something.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Mapping Classes to Tables &amp; Instvars to Columns&lt;/span&gt;&lt;br /&gt;ActiveRecord does the work of mapping classes to tables and instance variables to columns dynamically. If I change the columns in my table, my ActiveRecord-enabled app picks up these changes on restart. This is a step in the right direction (for my needs).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Associations&lt;/span&gt;&lt;br /&gt;ActiveRecord also provides support for developer-specified associations, which are basically smart accessor methods on your class that will retrieve associated objects through join queries.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Validations&lt;/span&gt;&lt;br /&gt;Lastly, ActiveRecord provides support for developer-specified validations, which are basically application-side enforcement of DB constraints. These are useful for providing feedback to a UI without querying the DB (and taking a performance hit for DB I/O, and wasting DB cycles).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What's Missing?&lt;/span&gt;&lt;br /&gt;ActiveRecord is fantastic (I might go so far as to call it groundbreaking), but unfortunately it doesn't quite meet my needs. AR makes assumptions about naming conventions for tables, primary keys, foreign keys, and breaks down in numerous situations when the DB schema is complex.&lt;br /&gt;AR does provide support for explicitly declaring my table names, keys, etc., but I have a fundamental problem with declaring these things in my application code when they are already declared in my DB schema. As well, I don't want to write code to specify relationships between DB records or constraints on them, as I have already done this on my DB itself.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;u&gt;DrySQL&lt;/u&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;DrySQL is an extension to ActiveRecord that provides a truly DRY Object-Relational Mapping solution. As long as DrySQL is able to map your class to a table (either using AR naming conventions, or a call to set_table_name inside your class definition), you need not define any properties of your table. DrySQL will query the DB's information schema and automatically identify keys &amp; constraints, and generate your class's associations and validations. It then delegates the instvar-column mapping duties to ActiveRecord. The result is that all the Object-Relational Mapping logic is abstracted away from your application, and is completely dynamic. Any changes you make to the structure and behaviour of your DB are dynamically picked up by your application at startup.&lt;br /&gt;&lt;br /&gt;DrySQL doesn't make assumptions about your naming conventions, or the nature of your application (Rails web app, Ruby desktop, etc). As a result, "legacy" DB tables can get the benefit of DrySQL's ORM magic, and DrySQL can be used in any Ruby application.&lt;br /&gt;&lt;br /&gt;If you do have the freedom to follow ActiveRecord's naming conventions in your DB, there is no need to even define your data classes. DrySQL will generate them in memory the first time you reference them. And then it will generate the associations and validations, and identify the keys and constraints the first time you create an instance of your class.&lt;br /&gt;&lt;br /&gt;What this means is that you can ditch all the code you write today to map, describe, and constrain DB data in your application.&lt;br /&gt;&lt;br /&gt;I will dig into the gory details of how DrySQL works in subsequent posts, but in the meantime please check out the &lt;a href="http://drysql.rubyforge.org/"&gt;DrySQL project homepage&lt;/a&gt; on RubyForge for more details about the features of DrySQL, how to use it, and how to download it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31748626-2990640179589996432?l=allyourdatabase.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://allyourdatabase.blogspot.com/feeds/2990640179589996432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31748626&amp;postID=2990640179589996432' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/2990640179589996432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/2990640179589996432'/><link rel='alternate' type='text/html' href='http://allyourdatabase.blogspot.com/2006/11/introducing-drysql.html' title='Introducing DrySQL'/><author><name>Bryan Evans</name><uri>http://www.blogger.com/profile/17994955569354693357</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://photos1.blogger.com/blogger/7063/3458/1600/bry_mic2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31748626.post-116170143715977739</id><published>2006-10-24T10:11:00.000-04:00</published><updated>2006-11-06T15:10:29.739-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>Some Interesting MySQL facts</title><content type='html'>&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-family:verdana;"&gt;I've been doing a lot of research into the internals of MySQL in order to develop &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://drysql.rubyforge.org/"&gt;DrySQL&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;, and here are some useful bits of information that I came  across:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;1) &lt;/span&gt;&lt;span style="font-family:verdana;"&gt;Check constraints are not supported in the latest version of MySQL (5.1.x). The syntax for check constraints is supported,  but any check constraints in your alter/create table syntax are just ignored.&lt;/span&gt;&lt;br /&gt;&lt;a style="font-family: verdana;" href="http://dev.mysql.com/doc/refman/5.1/en/table-constraints-table.html"&gt;Official MySQL documentation&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;2) &lt;/span&gt;&lt;span style="font-family:verdana;"&gt; The REFERENTIAL_CONSTRAINTS table was added to the INFORMATION_SCHEMA database as of MySQL 5.1.10.&lt;/span&gt;&lt;br /&gt;&lt;a style="font-family: verdana;" href="http://bugs.mysql.com/bug.php?id=10857"&gt;Bug Report/Feature Request&lt;/a&gt;&lt;br /&gt;&lt;a style="font-family: verdana;" href="http://dev.mysql.com/doc/refman/5.1/en/referential-constraints-table.html"&gt;Official MySQL documentation&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;This is in compliance with the ISO SQL:2003 standard. This table is useful to those who want information about the "ON UPDATE" and "ON DELETE" rules associated with a table constraint. Currently, the only solution for retrieving this info is to parse the SHOW CREATE TABLE output, which is a  pretty ugly hack and a performance hit compared to retrieving the constraint info directly from the INFORMATION_SCHEMA DB.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;span style="font-weight: bold;"&gt;3)&lt;/span&gt; MySQL creates implicit default values for columns if no default is specified. If the column is nullable, then MySQL sets the default value to NULL. If the column is not nullable, the default is value is set the MySQL's implicit default value for that column type (check &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/data-type-defaults.html"&gt;this link&lt;/a&gt; for details about implicit defaults).&lt;br /&gt;&lt;br /&gt;Suppose I create the following table:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="code"&gt;CREATE TABLE TEST (ID  CHAR(11)   NOT NULL)&lt;/blockquote&gt;&lt;br /&gt;If I query the information schema's COLUMNS table to find out whether a default value has been specified for the ID column in the TEST table, MySQL will return to me the empty string as the default value. Does this mean that the empty string was defined as the default value for this column, or that no default was specified at all? Unfortunately, there is no way to make this determination in the latest version of MySQL, which is a pain for those of us developing DB tools against MySQL.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;Errata:&lt;/span&gt; As of version 5.0.2, MySQL no longer creates implicit default values when no default is specified&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;4) &lt;/span&gt;&lt;span style="font-family:verdana;"&gt;Roland Bouman created an excellent clickable diagram of the MySQL Information Schema, which can be found &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://www.xcdsql.org/MySQL/information_schema/5.1/MySQL_5_1_INFORMATION_SCHEMA.html"&gt;here&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31748626-116170143715977739?l=allyourdatabase.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://allyourdatabase.blogspot.com/feeds/116170143715977739/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31748626&amp;postID=116170143715977739' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/116170143715977739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/116170143715977739'/><link rel='alternate' type='text/html' href='http://allyourdatabase.blogspot.com/2006/10/some-interesting-mysql-resources-ive.html' title='Some Interesting MySQL facts'/><author><name>Bryan Evans</name><uri>http://www.blogger.com/profile/17994955569354693357</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://photos1.blogger.com/blogger/7063/3458/1600/bry_mic2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31748626.post-116154225462268556</id><published>2006-10-22T13:04:00.000-04:00</published><updated>2006-10-31T10:45:55.005-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby-smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><category scheme='http://www.blogger.com/atom/ns#' term='ORM'/><title type='text'>ORM Frameworks...the horror! (And a solution)</title><content type='html'>&lt;span style="font-family: verdana;"&gt;I've used a lot of Object-Relational Mapping frameworks over the years in the enterprise space. They're supposed to make it easier to objectify relational data, and they do. However, they all seem to force me to contravene one of the most important principles (IMO) of software development: Don't Repeat Yourself.&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;&lt;br /&gt;In my experience in the enterprise space, a database schema is carefully crafted to ensure data integrity. The database can then be used by a number of applications, none of whom need to worry about data integrity, right? Then why, after I define referential constraints, unique constraints, check constraints, not-null conditions, and default values in my DB schema, do I need to define many of these again in a config file used by my ORM framework? What happens if I change the structure of my DB?&lt;/span&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Hibernate&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;Hibernate is the ORM framework I have used most often in the workplace, and it is great in a number of areas. Handling DB table changes in a dynamic way is not one of them. If I change my underlying DB structure, I need to change associated config files, re-generate data classes, re-build and re-deploy my app(s). I may be jaded from my experience using Smalltalk, but I find this lack of dynamicism unacceptable. I'll admit that the Smalltalk ORM frameworks I've used are no better (worse, in fact), but I can see that the language itself allows for a much more dynamic framework to be built. I'm not sure that's the case with Java, but would love to hear (politely, of course) that I'm wrong (yes, I've heard of Trails, but I'm not sold on it at present).&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;&lt;br /&gt;There are a number of tools available that support some degree of round-trip engineering with Hibernate. XDoclet, MiddleGen, and even the Hibernate tools package can be very useful for autogenerating code and config files. However, I personally don't want to have to use 4 different frameworks to support round-trip engineering. And I don't want to have to re-build my app after a DB table change.&lt;/span&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Ruby on Rails&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;So after complaining about these sorts of problems for awhile (read: years), I decided to work on a solution. I've been experimenting with Ruby and ActiveRecord (the part of the Rails framework that interfaces with databases) for a few months now. Ruby has the dynamic, reflective nature of Smalltalk, which won me over immediately. And ActiveRecord sure makes ORM a lot more simple and pleasant than most other frameworks. It is not without weaknesses, though.&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;&lt;br /&gt;On any given table, I can change the names of the columns, remove/add columns, and my Rails app will handle these changes without requiring changes to the code. I just need to re-start my app. However, ActiveRecord uses naming conventions to infer properties of tables, and even table names themselves. For example, unless I specifically call &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;set_primary_key &lt;/span&gt;&lt;span style="font-family: verdana;"&gt;in my class definition, ActiveRecord will assume that the primary key column for my &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;Invoices&lt;/span&gt;&lt;span style="font-family: verdana;"&gt; table is &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;invoice_id&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;. Thankfully, I can override such assumptions in my class definitions, but I shouldn't have to. My primary key is defined in my database schema in the form of a table constraint, and can be retrieved from the information_schema tables (or system catalogs, or whatever terminology applies to the metadata schema in your DB of choice).&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;&lt;br /&gt;To summarize my long-winded rant:&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;&lt;br /&gt;1) I personally can gain a lot of productivity from having a very dynamic, reflective ORM framework that doesn't require me to define my DB schema anywhere but in my DB itself.&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;&lt;br /&gt;2) I have found that Ruby/Rails/ActiveRecord comes closest to giving me what I need, but could really use some enhancements to better support legacy DB tables, and really use the DB schema to its full potential&lt;/span&gt;&lt;span style="font-family: verdana;font-size:100%;" &gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A Solution&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;I have nearly completed a solution to this "problem" in the form of a Ruby Gem called DrySQL that is an extension to ActiveRecord. I will explain DrySQL fully in a subsequent post, but put simply your data class can look like this:&lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;class Invoice&lt;br /&gt;end&lt;/blockquote&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;--&gt; or if your DB table isn't named &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;Invoices,&lt;/span&gt;&lt;span style="font-family: verdana;"&gt; your class would look like this:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;&lt;blockquote&gt;class Invoice&lt;br /&gt; set_table_name "XYZ123"&lt;br /&gt;end&lt;/blockquote&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;You do not need to specify primary/foreign keys, associations, or validations. DrySQL will retrieve all your table's constraints and metadata from the DB, and generate the necessary logic in your Ruby app.&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;&lt;br /&gt;This is extremely useful to me, and I hope that others will find it useful as well.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31748626-116154225462268556?l=allyourdatabase.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://allyourdatabase.blogspot.com/feeds/116154225462268556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31748626&amp;postID=116154225462268556' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/116154225462268556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31748626/posts/default/116154225462268556'/><link rel='alternate' type='text/html' href='http://allyourdatabase.blogspot.com/2006/10/or-mapping-frameworks.html' title='ORM Frameworks...the horror! (And a solution)'/><author><name>Bryan Evans</name><uri>http://www.blogger.com/profile/17994955569354693357</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://photos1.blogger.com/blogger/7063/3458/1600/bry_mic2.jpg'/></author><thr:total>0</thr:total></entry></feed>
