<?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>Chasing &#187; Ruby-ADT</title>
	<atom:link href="http://chase.ratchetsoftware.com/category/work/ruby-adt/feed/" rel="self" type="application/rss+xml" />
	<link>http://chase.ratchetsoftware.com</link>
	<description>Chase Gray&#039;s blog with solutions to various problems by a curious american Ph.D. student.</description>
	<lastBuildDate>Wed, 09 Jun 2010 05:13:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<item>
		<title>Reading Advantage Database Server Files (.ADT) in Ruby</title>
		<link>http://chase.ratchetsoftware.com/2010/02/reading-advantage-database-server-files-adt-in-ruby/</link>
		<comments>http://chase.ratchetsoftware.com/2010/02/reading-advantage-database-server-files-adt-in-ruby/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 01:45:50 +0000</pubDate>
		<dc:creator>chasemgray</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Ruby-ADT]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://chase.ratchetsoftware.com/?p=172</guid>
		<description><![CDATA[I recently received some data in the Advantage Database Server file format (.adt). In the past I have worked with DBF, Access, and .xls. I was able to find some way to retrieve data from these formats using open source software. The open source solutions were much easier to work with, usually not requiring any [...]]]></description>
			<content:encoded><![CDATA[<p>I recently received some data in the <a href="http://www.sybase.com/products/databasemanagement/advantagedatabaseserver">Advantage Database Server</a> file format (.adt).  In the past I have worked with DBF, Access, and .xls.  I was able to find some way to retrieve data from these formats using open source software.  The open source solutions were much easier to work with, usually not requiring any sort of driver installation, etc.</p>
<p>I searched thoroughly for an easy way to retrieve information from this set of .ADT files I was dealing with.  Sybase provides tools to work with the data, but all of them require using their software or drivers developed by them.  I would have settled for this if it wasn&#8217;t such a hassle to figure out how to use them.  I asked the question on <a href="http://stackoverflow.com/questions/2289519/automate-conversion-of-sybase-adt-files-to-sql">Stackoverflow.com</a> and got an answer from one of the employee&#8217;s of Sybase.  While helpful, the suggested Perl driver was one of the things I was avoiding.  I did attempt it and after a little hassle, moved on to creating a simpler solution.</p>
<p><span id="more-172"></span>One solution was to simply use Sybase&#8217;s provided &#8220;<a href="http://devzone.advantagedatabase.com/dz/content.aspx?key=20&amp;Release=13">Advantage Data Architect</a>&#8221; software to open the .ADT files and export them all to SQL.  This is possible with their software, but it would not work for my situation.  The developers of the program outputting these .adt files used a separate embedded database for each new report that was being worked on.  This meant there was hundreds of folders, each containing 30-40 .ADT files making up their own embedded database.  I needed something that could automate the extraction of this data.</p>
<h2>Data Format</h2>
<p>To cut this short, I decided to open up the .ADT files with a hex editor and see if I could get the information I needed out.  I only needed the column names, their types, and the actual rows of data.  To aid anybody else doing something similar to this, I&#8217;ll include some of my notes about the format here:</p>
<ul>
<li>The data is stored at the very end of the file. </li>
<li>The byte offset when the data starts is located at byte 32 and is 32-bits</li>
<li>Byte 24 contains a 32-bit integer specifying the number of rows</li>
<li>Byte 36 contains the a 32-bit number representing the number of bytes each record consumes</li>
<li>The header is 400 bytes</li>
<li>Column information is after the header, before the data.  Each column entry is 200 bytes.</li>
<li>The number of columns can be calculated (data_offset-400)/200</li>
<li>Column names consume the first 128 of each column entry.</li>
<li>Byte 130 contains a 16-bit integer representing the type of data.</li>
<li>Byte 136 contains a 16-bit integer, the length of the field in bytes</li>
<li>Character = 04, Double = 0A, Integer = 0B, Shortint = 0C, CICharacter = 14, Date = 03, Time = 0D, Timestamp = 0E, Autoinc = 0F</li>
</ul>
<p>This was enough information to get what I wanted.</p>
<h2>Ruby-ADT Gem</h2>
<p>I took the existing <a href="http://github.com/infused/dbf">DBF gem</a> by Keith Morrison.  Most of the credit for this gem goes to him as I borrowed the structure heavily from his gem.</p>
<p>I&#8217;ll provide an example of what is now possible with my new ADT gem.  No drivers are required and it&#8217;s as simple as installing the gem.  I&#8217;ll include a snippet of the readme from my <a href="http://github.com/chasemgray/Ruby-ADT">Ruby-ADT gem</a> on github, borrowed heavily again from the DBF gem.</p>
<h3>Installation</h3>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">gem install ruby<span style="color:#006600; font-weight:bold;">-</span>adt</pre></div></div>

<h3>Basic Usage</h3>
<p>Load an ADT file:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'adt'</span>
&nbsp;
table = <span style="color:#6666ff; font-weight:bold;">ADT::Table</span>.<span style="color:#5A0A0A; font-weight:bold;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;test.adt&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Enumerate all records</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">table.<span style="color:#5A0A0A; font-weight:bold;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>record<span style="color:#006600; font-weight:bold;">|</span>          
	<span style="color:#CC0066; font-weight:bold;">puts</span> record.<span style="color:#9900CC;">name</span>          
	<span style="color:#CC0066; font-weight:bold;">puts</span> record.<span style="color:#9900CC;">email</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Load a single record using <tt>record</tt> or <tt>find</tt></p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">table.<span style="color:#9900CC;">record</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">6</span><span style="color:#006600; font-weight:bold;">&#41;</span>
table.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">6</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Attributes can also be accessed through the attributes hash in  original or underscored form or as an accessor method using the underscored name.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">table.<span style="color:#9900CC;">record</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">4</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">attributes</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;PhoneBook&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
table.<span style="color:#9900CC;">record</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">4</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">attributes</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;phone_book&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
table.<span style="color:#9900CC;">record</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">4</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">phone_book</span></pre></div></div>

<p>Search for records using a simple hash format.  Multiple search  criteria are ANDed. Use the block form of find if the resulting recordset could be  large otherwise all records will be loaded into memory.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># find all records with first_name equal to Keith</span>
&nbsp;
table.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:first_name</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">'Keith'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>record<span style="color:#006600; font-weight:bold;">|</span>  
	<span style="color:#CC0066; font-weight:bold;">puts</span> record.<span style="color:#9900CC;">last_name</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># find all records with first_name equal to Keith and last_name equal to Morrison</span>
table.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:first_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Keith'</span>, <span style="color:#ff3333; font-weight:bold;">:last_name</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">'Morrison'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>record<span style="color:#006600; font-weight:bold;">|</span>   
	<span style="color:#CC0066; font-weight:bold;">puts</span> record.<span style="color:#9900CC;">last_name</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># find the first record with first_name equal to Keith</span>
&nbsp;
table.<span style="color:#9900CC;">find</span> <span style="color:#ff3333; font-weight:bold;">:first</span>, <span style="color:#ff3333; font-weight:bold;">:first_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Keith'</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># find record number 10 </span>
&nbsp;
table.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">10</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<h3>Migrating to ActiveRecord</h3>
<p>An example of migrating a DBF book table to ActiveRecord using a  migration:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'adt'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> CreateBooks <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span>      
	<span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">up</span>            
		table = <span style="color:#6666ff; font-weight:bold;">ADT::Table</span>.<span style="color:#5A0A0A; font-weight:bold;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'db/adt/books.adt'</span><span style="color:#006600; font-weight:bold;">&#41;</span>            
		<span style="color:#CC0066; font-weight:bold;">eval</span><span style="color:#006600; font-weight:bold;">&#40;</span>table.<span style="color:#9900CC;">schema</span><span style="color:#006600; font-weight:bold;">&#41;</span>        
		table.<span style="color:#5A0A0A; font-weight:bold;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>record<span style="color:#006600; font-weight:bold;">|</span>                  
			Book.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span>record.<span style="color:#9900CC;">attributes</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>  
	<span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">down</span>        
		drop_table <span style="color:#ff3333; font-weight:bold;">:books</span>    
	<span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3>Limitations and known bugs</h3>
<ul>
<li>ADT is read-only</li>
<li>External index files are not used</li>
<li>Dates are not currently handled correctly.</li>
</ul>
<h2>Future Directions</h2>
<p>I am going to continue working on this library.  I have already heard from a few others that found this useful immediately after I posted it online.  I was surprised people could find it so quickly.  I&#8217;m sure there are bugs.  I would appreciate any problems to be reported to the <a href="http://github.com/chasemgray/Ruby-ADT">Ruby-ADT Github page</a>.  Emails are also welcome, but any issues should be directed to the github page and I&#8217;ll get to them when I can.</p>
</p>
<p>Hope this helps somebody out there dealing with this format.</p>
</p>
<p>- Chase Gray</p>
]]></content:encoded>
			<wfw:commentRss>http://chase.ratchetsoftware.com/2010/02/reading-advantage-database-server-files-adt-in-ruby/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

