<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	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:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
		>
<channel>
	<title>Comments on: Some issues with Oracle views as ActiveRecord source</title>
	<atom:link href="http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/</link>
	<description>About Ruby, Oracle, Mac and others</description>
	<lastBuildDate>Wed, 28 Jul 2010 16:18:03 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
	<item>
		<title>By: labria</title>
		<link>http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-393</link>
		<dc:creator>labria</dc:creator>
		<pubDate>Tue, 16 Dec 2008 03:17:11 +0000</pubDate>
		<guid isPermaLink="false">http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-393</guid>
		<description>Thank you SO much for the NLS_LANG tip. It just saved my day!</description>
		<content:encoded><![CDATA[<p>Thank you SO much for the NLS_LANG tip. It just saved my day!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: ActiveRecord Oracle enhanced adapter &#171; ray_apps_blog</title>
		<link>http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-222</link>
		<dc:creator>ActiveRecord Oracle enhanced adapter &#171; ray_apps_blog</dc:creator>
		<pubDate>Mon, 12 May 2008 22:06:06 +0000</pubDate>
		<guid isPermaLink="false">http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-222</guid>
		<description>[...] ActiveRecord Oracle enhanced&#160;adapter Filed under: oracle, rails, ruby &#8212; Raimonds Simanovskis @ 12:05 am   In all Ruby on Rails on Oracle projects where I am using original ActiveRecord Oracle adapter I always create some &#8220;monkey patches&#8221; of Oracle adapter to support my needs. I have written about several of these patches in this blog (see 1, 2, 3). [...]</description>
		<content:encoded><![CDATA[<p>[...] ActiveRecord Oracle enhanced&nbsp;adapter Filed under: oracle, rails, ruby &#8212; Raimonds Simanovskis @ 12:05 am   In all Ruby on Rails on Oracle projects where I am using original ActiveRecord Oracle adapter I always create some &#8220;monkey patches&#8221; of Oracle adapter to support my needs. I have written about several of these patches in this blog (see 1, 2, 3). [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Duke</title>
		<link>http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-211</link>
		<dc:creator>Duke</dc:creator>
		<pubDate>Thu, 01 May 2008 17:51:57 +0000</pubDate>
		<guid isPermaLink="false">http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-211</guid>
		<description>Thanks for putting that description of how ruby sees the different Numbers!  Luckily I can have the schema changed, or I&#039;d be digging deeper into the patch.  Saved me a lot of headache!</description>
		<content:encoded><![CDATA[<p>Thanks for putting that description of how ruby sees the different Numbers!  Luckily I can have the schema changed, or I&#8217;d be digging deeper into the patch.  Saved me a lot of headache!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Simon</title>
		<link>http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-191</link>
		<dc:creator>Simon</dc:creator>
		<pubDate>Wed, 02 Apr 2008 15:32:28 +0000</pubDate>
		<guid isPermaLink="false">http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-191</guid>
		<description>Ok found a solution i have no idea why it work but it works.
all i had to do was add 

        def simplified_type(field_type)
          return :boolean if OracleAdapter.emulate_booleans &amp;&amp; field_type == &#039;NUMBER(1)&#039;
          case field_type
             when /date&#124;time/i then :datetime
            # RSI: treat columns which end with &#039;date&#039; as ruby date columns
	     when /date$/i then :date
	    # RSI: removed &#039;date&#039; from regex
	     when /time/i then :datetime
	    # RSI: treat id columns (primary key) and (foreign keys) as integer
	     when /^id$/i then :integer
	     when /_pk$/i then :integer
	     when /_fk$/i then :integer
            else super
          end
         x=5 #WTF! Why is this here? Oh wait some how I have to have a statement here any statement or it wont work? 
        end

 I discovered this by chance because i removed :float all together and it still didn&#039;t work but with that x=5 or puts &quot;test&quot; it some how works</description>
		<content:encoded><![CDATA[<p>Ok found a solution i have no idea why it work but it works.<br />
all i had to do was add </p>
<p>        def simplified_type(field_type)<br />
          return :boolean if OracleAdapter.emulate_booleans &amp;&amp; field_type == &#8216;NUMBER(1)&#8217;<br />
          case field_type<br />
             when /date|time/i then :datetime<br />
            # RSI: treat columns which end with &#8216;date&#8217; as ruby date columns<br />
	     when /date$/i then :date<br />
	    # RSI: removed &#8216;date&#8217; from regex<br />
	     when /time/i then :datetime<br />
	    # RSI: treat id columns (primary key) and (foreign keys) as integer<br />
	     when /^id$/i then :integer<br />
	     when /_pk$/i then :integer<br />
	     when /_fk$/i then :integer<br />
            else super<br />
          end<br />
         x=5 #WTF! Why is this here? Oh wait some how I have to have a statement here any statement or it wont work?<br />
        end</p>
<p> I discovered this by chance because i removed :float all together and it still didn&#8217;t work but with that x=5 or puts &#8220;test&#8221; it some how works</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Simon</title>
		<link>http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-190</link>
		<dc:creator>Simon</dc:creator>
		<pubDate>Wed, 02 Apr 2008 14:05:11 +0000</pubDate>
		<guid isPermaLink="false">http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-190</guid>
		<description>Also my view is create from a select statement that maps the output of pl/sql function

PS Sorry for the HUGE cope paste</description>
		<content:encoded><![CDATA[<p>Also my view is create from a select statement that maps the output of pl/sql function</p>
<p>PS Sorry for the HUGE cope paste</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Simon</title>
		<link>http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-189</link>
		<dc:creator>Simon</dc:creator>
		<pubDate>Wed, 02 Apr 2008 13:50:23 +0000</pubDate>
		<guid isPermaLink="false">http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-189</guid>
		<description>Well apparently when you do the command &quot;y Tablename.find(:all)&quot; in the process of the &#039;y&#039; command converting the data into yml format removes any .0 . And when i run the command without y it looks like this

#&lt;Job cus_uid_pk: #, cus_name: &quot;HENRY JR TORRES&quot;, svo_uid_pk: #, slo_uid_pk: #,

ive also added this code into hopes of force integer handling
im using rails 2.0.2 and oracle-adapter from http://svn.rubyonrails.org/rails/adapters/oracle/lib/active_record/connection_adapters/
since the gem install is broken. 
I have  also tried adding more code to force an integer relation

          select_all(table_cols, name).map do &#124;row&#124;
            limit, scale = row[&#039;limit&#039;], row[&#039;scale&#039;]
#patch map NUMBER , where column names ends with _pk or _fk to NUMBER(38)
            if (row[&#039;name&#039;] =~ /_pk$/i &#124;&#124; row[&#039;name&#039;] =~ /_fk$/i )
	    	    	row[&#039;limit&#039;] = 38
	    end
            if limit &#124;&#124; scale
              row[&#039;sql_type&#039;] &lt; 0 ? &quot;,#{scale})&quot; : &quot;)&quot;)
            end

here is my whole oracle_adapter.rb

require &#039;active_record/connection_adapters/abstract_adapter&#039;
require &#039;delegate&#039;

begin
  require_library_or_gem &#039;oci8&#039; unless self.class.const_defined? :OCI8

  module ActiveRecord
    class Base
      def self.oracle_connection(config) #:nodoc:
        # Use OCI8AutoRecover instead of normal OCI8 driver.
        ConnectionAdapters::OracleAdapter.new OCI8AutoRecover.new(config), logger
      end

      # for backwards-compatibility
      def self.oci_connection(config) #:nodoc:
        config[:database] = config[:host]
        self.oracle_connection(config)
      end

      # After setting large objects to empty, select the OCI8::LOB
      # and write back the data.
      after_save :write_lobs
      def write_lobs #:nodoc:
        if connection.is_a?(ConnectionAdapters::OracleAdapter)
          connection.write_lobs(self.class.table_name, self.class, attributes)
        end
      end

      private :write_lobs
    end


    module ConnectionAdapters #:nodoc:
      class OracleColumn &lt; Column #:nodoc:

        def type_cast(value)
          return guess_date_or_time(value) if type == :datetime &amp;&amp; OracleAdapter.emulate_dates
          super
        end

        private
        def simplified_type(field_type)
          return :boolean if OracleAdapter.emulate_booleans &amp;&amp; field_type == &#039;NUMBER(1)&#039;
          case field_type
             when /date&#124;time/i then :datetime
            # RSI: treat columns which end with &#039;date&#039; as ruby date columns
	     when /date$/i then :date
	    # RSI: removed &#039;date&#039; from regex
	     when /time/i then :datetime
	    # RSI: treat id columns (primary key) and (foreign keys) as integer
	     when /^id$/i then :integer
	     when /_pk$/i then :integer
	     when /_fk$/i then :integer
            else super
          end
        end

        def guess_date_or_time(value)
          (value.hour == 0 and value.min == 0 and value.sec == 0) ?
            Date.new(value.year, value.month, value.day) : value
        end
      end


      # This is an Oracle/OCI adapter for the ActiveRecord persistence
      # framework. It relies upon the OCI8 driver, which works with Oracle 8i
      # and above. Most recent development has been on Debian Linux against
      # a 10g database, ActiveRecord 1.12.1 and OCI8 0.1.13.
      # See: http://rubyforge.org/projects/ruby-oci8/
      #
      # Usage notes:
      # * Key generation assumes a &quot;${table_name}_seq&quot; sequence is available
      #   for all tables; the sequence name can be changed using
      #   ActiveRecord::Base.set_sequence_name. When using Migrations, these
      #   sequences are created automatically.
      # * Oracle uses DATE or TIMESTAMP datatypes for both dates and times.
      #   Consequently some hacks are employed to map data back to Date or Time
      #   in Ruby. If the column_name ends in _time it&#039;s created as a Ruby Time.
      #   Else if the hours/minutes/seconds are 0, I make it a Ruby Date. Else
      #   it&#039;s a Ruby Time. This is a bit nasty - but if you use Duck Typing
      #   you&#039;ll probably not care very much. In 9i and up it&#039;s tempting to
      #   map DATE to Date and TIMESTAMP to Time, but too many databases use
      #   DATE for both. Timezones and sub-second precision on timestamps are
      #   not supported.
      # * Default values that are functions (such as &quot;SYSDATE&quot;) are not
      #   supported. This is a restriction of the way ActiveRecord supports
      #   default values.
      # * Support for Oracle8 is limited by Rails&#039; use of ANSI join syntax, which
      #   is supported in Oracle9i and later. You will need to use #finder_sql for
      #   has_and_belongs_to_many associations to run against Oracle8.
      #
      # Required parameters:
      #
      # * :username
      # * :password
      # * :database
      class OracleAdapter  &quot;NUMBER(38) NOT NULL PRIMARY KEY&quot;,
            :string      =&gt; { :name =&gt; &quot;VARCHAR2&quot;, :limit =&gt; 255 },
            :text        =&gt; { :name =&gt; &quot;CLOB&quot; },
            :integer     =&gt; { :name =&gt; &quot;NUMBER&quot;, :limit =&gt; 38 },
            :float       =&gt; { :name =&gt; &quot;NUMBER&quot; },
            :decimal     =&gt; { :name =&gt; &quot;DECIMAL&quot; },
            :datetime    =&gt; { :name =&gt; &quot;DATE&quot; },
            :timestamp   =&gt; { :name =&gt; &quot;DATE&quot; },
            :time        =&gt; { :name =&gt; &quot;DATE&quot; },
            :date        =&gt; { :name =&gt; &quot;DATE&quot; },
            :binary      =&gt; { :name =&gt; &quot;BLOB&quot; },
            :boolean     =&gt; { :name =&gt; &quot;NUMBER&quot;, :limit =&gt; 1 }
          }
        end

        def table_alias_length
          30
        end

        # QUOTING ==================================================
        #
        # see: abstract/quoting.rb

        # camelCase column names need to be quoted; not that anyone using Oracle
        # would really do this, but handling this case means we pass the test...
        def quote_column_name(name) #:nodoc:
          name.to_s =~ /[A-Z]/ ? &quot;\&quot;#{name}\&quot;&quot; : name
        end

        def quote_string(s) #:nodoc:
          s.gsub(/&#039;/, &quot;&#039;&#039;&quot;)
        end

        def quote(value, column = nil) #:nodoc:
          if value &amp;&amp; column &amp;&amp; [:text, :binary].include?(column.type)
            %Q{empty_#{ column.sql_type.downcase rescue &#039;blob&#039; }()}
          else
            super
          end
        end

        def quoted_true
          &quot;1&quot;
        end

        def quoted_false
          &quot;0&quot;
        end


        # CONNECTION MANAGEMENT ====================================
        #

        # Returns true if the connection is active.
        def active?
          # Pings the connection to check if it&#039;s still good. Note that an
          # #active? method is also available, but that simply returns the
          # last known state, which isn&#039;t good enough if the connection has
          # gone stale since the last use.
          @connection.ping
        rescue OCIException
          false
        end

        # Reconnects to the database.
        def reconnect!
          @connection.reset!
        rescue OCIException =&gt; e
          @logger.warn &quot;#{adapter_name} automatic reconnection failed: #{e.message}&quot;
        end

        # Disconnects from the database.
        def disconnect!
          @connection.logoff rescue nil
          @connection.active = false
        end


        # DATABASE STATEMENTS ======================================
        #
        # see: abstract/database_statements.rb

        def execute(sql, name = nil) #:nodoc:
          log(sql, name) { @connection.exec sql }
        end

        # Returns the next sequence value from a sequence generator. Not generally
        # called directly; used by ActiveRecord to get the next primary key value
        # when inserting a new database record (see #prefetch_primary_key?).
        def next_sequence_value(sequence_name)
          id = 0
          @connection.exec(&quot;select #{sequence_name}.nextval id from dual&quot;) { &#124;r&#124; id = r[0].to_i }
          id
        end

        def begin_db_transaction #:nodoc:
          @connection.autocommit = false
        end

        def commit_db_transaction #:nodoc:
          @connection.commit
        ensure
          @connection.autocommit = true
        end

        def rollback_db_transaction #:nodoc:
          @connection.rollback
        ensure
          @connection.autocommit = true
        end

        def add_limit_offset!(sql, options) #:nodoc:
          offset = options[:offset] &#124;&#124; 0

          if limit = options[:limit]
            sql.replace &quot;select * from (select raw_sql_.*, rownum raw_rnum_ from (#{sql}) raw_sql_ where rownum  #{offset}&quot;
          elsif offset &gt; 0
            sql.replace &quot;select * from (select raw_sql_.*, rownum raw_rnum_ from (#{sql}) raw_sql_) where raw_rnum_ &gt; #{offset}&quot;
          end
        end

        # Returns true for Oracle adapter (since Oracle requires primary key
        # values to be pre-fetched before insert). See also #next_sequence_value.
        def prefetch_primary_key?(table_name = nil)
          true
        end

        def default_sequence_name(table, column) #:nodoc:
          &quot;#{table}_seq&quot;
        end


        # Inserts the given fixture into the table. Overridden to properly handle lobs.
        def insert_fixture(fixture, table_name)
          super

          klass = fixture.class_name.constantize rescue nil
          if klass.respond_to?(:ancestors) &amp;&amp; klass.ancestors.include?(ActiveRecord::Base)
            write_lobs(table_name, klass, fixture)
          end
        end

        # Writes LOB values from attributes, as indicated by the LOB columns of klass.
        def write_lobs(table_name, klass, attributes)
          id = quote(attributes[klass.primary_key])
          klass.columns.select { &#124;col&#124; col.sql_type =~ /LOB$/i }.each do &#124;col&#124;
            value = attributes[col.name]
            value = value.to_yaml if col.text? &amp;&amp; klass.serialized_attributes[col.name]
            next if value.nil?  &#124;&#124; (value == &#039;&#039;)
            lob = select_one(&quot;SELECT #{col.name} FROM #{table_name} WHERE #{klass.primary_key} = #{id}&quot;,
                             &#039;Writable Large Object&#039;)[col.name]
            lob.write value
          end
        end


        # SCHEMA STATEMENTS ========================================
        #
        # see: abstract/schema_statements.rb

        def current_database #:nodoc:
          select_one(&quot;select sys_context(&#039;userenv&#039;,&#039;db_name&#039;) db from dual&quot;)[&quot;db&quot;]
        end

        def tables(name = nil) #:nodoc:
          select_all(&quot;select lower(table_name) from user_tables&quot;).inject([]) do &#124; tabs, t &#124;
            tabs &lt;&lt; t.to_a.first.last
          end
        end

        def indexes(table_name, name = nil) #:nodoc:
          result = select_all(&lt;&lt;-SQL, name)
            SELECT lower(i.index_name) as index_name, i.uniqueness, lower(c.column_name) as column_name
              FROM user_indexes i, user_ind_columns c
             WHERE i.table_name = &#039;#{table_name.to_s.upcase}&#039;
               AND c.index_name = i.index_name
               AND i.index_name NOT IN (SELECT uc.index_name FROM user_constraints uc WHERE uc.constraint_type = &#039;P&#039;)
              ORDER BY i.index_name, c.column_position
          SQL

          current_index = nil
          indexes = []

          result.each do &#124;row&#124;
            if current_index != row[&#039;index_name&#039;]
              indexes &lt;&lt; IndexDefinition.new(table_name, row[&#039;index_name&#039;], row[&#039;uniqueness&#039;] == &quot;UNIQUE&quot;, [])
              current_index = row[&#039;index_name&#039;]
            end

            indexes.last.columns &lt;&lt; row[&#039;column_name&#039;]
          end

          indexes
        end

        def columns(table_name, name = nil) #:nodoc:

          (owner, table_name) = @connection.describe(table_name)

          table_cols = &lt;&lt;-SQL
            select column_name as name, data_type as sql_type, data_default, nullable,
                   decode(data_type, &#039;NUMBER&#039;, data_precision,
                                     &#039;FLOAT&#039;, data_precision,
                                     &#039;VARCHAR2&#039;, data_length,
                                     &#039;CHAR&#039;, data_length,
                                      null) as limit,
                   decode(data_type, &#039;NUMBER&#039;, data_scale, null) as scale
              from all_tab_columns
             where owner      = &#039;#{owner}&#039;
               and table_name = &#039;#{table_name}&#039;
             order by column_id
          SQL

          select_all(table_cols, name).map do &#124;row&#124;
            limit, scale = row[&#039;limit&#039;], row[&#039;scale&#039;]
            if (row[&#039;name&#039;] =~ /_pk$/i &#124;&#124; row[&#039;name&#039;] =~ /_fk$/i )
	    	    	row[&#039;limit&#039;] = 38
	    end
            if limit &#124;&#124; scale
              row[&#039;sql_type&#039;] &lt; 0 ? &quot;,#{scale})&quot; : &quot;)&quot;)
            end
            # clean up odd default spacing from Oracle
            if row[&#039;data_default&#039;]
              row[&#039;data_default&#039;].sub!(/^(.*?)\s*$/, &#039;\1&#039;)
              row[&#039;data_default&#039;].sub!(/^&#039;(.*)&#039;$/, &#039;\1&#039;)
              row[&#039;data_default&#039;] = nil if row[&#039;data_default&#039;] =~ /^(null&#124;empty_[bc]lob\(\))$/i
            end
		
            OracleColumn.new(oracle_downcase(row[&#039;name&#039;]),
                             row[&#039;data_default&#039;],
                             row[&#039;sql_type&#039;],
                             row[&#039;nullable&#039;] == &#039;Y&#039;)
            
          end
        end

        def create_table(name, options = {}) #:nodoc:
          super(name, options)
          seq_name = options[:sequence_name] &#124;&#124; &quot;#{name}_seq&quot;
          execute &quot;CREATE SEQUENCE #{seq_name} START WITH 10000&quot; unless options[:id] == false
        end

        def rename_table(name, new_name) #:nodoc:
          execute &quot;RENAME #{name} TO #{new_name}&quot;
          execute &quot;RENAME #{name}_seq TO #{new_name}_seq&quot; rescue nil
        end

        def drop_table(name, options = {}) #:nodoc:
          super(name)
          seq_name = options[:sequence_name] &#124;&#124; &quot;#{name}_seq&quot;
          execute &quot;DROP SEQUENCE #{seq_name}&quot; rescue nil
        end

        def remove_index(table_name, options = {}) #:nodoc:
          execute &quot;DROP INDEX #{index_name(table_name, options)}&quot;
        end

        def change_column_default(table_name, column_name, default) #:nodoc:
          execute &quot;ALTER TABLE #{table_name} MODIFY #{quote_column_name(column_name)} DEFAULT #{quote(default)}&quot;
        end

        def change_column(table_name, column_name, type, options = {}) #:nodoc:
          change_column_sql = &quot;ALTER TABLE #{table_name} MODIFY #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}&quot;
          add_column_options!(change_column_sql, options)
          execute(change_column_sql)
        end

        def rename_column(table_name, column_name, new_column_name) #:nodoc:
          execute &quot;ALTER TABLE #{table_name} RENAME COLUMN #{quote_column_name(column_name)} to #{quote_column_name(new_column_name)}&quot;
        end

        def remove_column(table_name, column_name) #:nodoc:
          execute &quot;ALTER TABLE #{table_name} DROP COLUMN #{quote_column_name(column_name)}&quot;
        end

        # Find a table&#039;s primary key and sequence. 
        # *Note*: Only primary key is implemented - sequence will be nil.
        def pk_and_sequence_for(table_name)
          (owner, table_name) = @connection.describe(table_name)

          pks = select_values(&lt;&lt;-SQL, &#039;Primary Key&#039;)
            select cc.column_name
              from all_constraints c, all_cons_columns cc
             where c.owner = &#039;#{owner}&#039;
               and c.table_name = &#039;#{table_name}&#039;
               and c.constraint_type = &#039;P&#039;
               and cc.owner = c.owner
               and cc.constraint_name = c.constraint_name
          SQL

          # only support single column keys
          pks.size == 1 ? [oracle_downcase(pks.first), nil] : nil
        end

        def structure_dump #:nodoc:
          s = select_all(&quot;select sequence_name from user_sequences&quot;).inject(&quot;&quot;) do &#124;structure, seq&#124;
            structure &lt;&lt; &quot;create sequence #{seq.to_a.first.last};\n\n&quot;
          end

          select_all(&quot;select table_name from user_tables&quot;).inject(s) do &#124;structure, table&#124;
            ddl = &quot;create table #{table.to_a.first.last} (\n &quot;
            cols = select_all(%Q{
              select column_name, data_type, data_length, data_precision, data_scale, data_default, nullable
              from user_tab_columns
              where table_name = &#039;#{table.to_a.first.last}&#039;
              order by column_id
            }).map do &#124;row&#124;
              col = &quot;#{row[&#039;column_name&#039;].downcase} #{row[&#039;data_type&#039;].downcase}&quot;
              if row[&#039;data_type&#039;] ==&#039;NUMBER&#039; and !row[&#039;data_precision&#039;].nil?
                col &lt;&lt; &quot;(#{row[&#039;data_precision&#039;].to_i}&quot;
                col &lt;&lt; &quot;,#{row[&#039;data_scale&#039;].to_i}&quot; if !row[&#039;data_scale&#039;].nil?
                col &lt;&lt; &#039;)&#039;
              elsif row[&#039;data_type&#039;].include?(&#039;CHAR&#039;)
                col &lt;&lt; &quot;(#{row[&#039;data_length&#039;].to_i})&quot;
              end
              col &lt;&lt; &quot; default #{row[&#039;data_default&#039;]}&quot; if !row[&#039;data_default&#039;].nil?
              col &lt;&lt; &#039; not null&#039; if row[&#039;nullable&#039;] == &#039;N&#039;
              col
            end
            ddl &lt;&lt; cols.join(&quot;,\n &quot;)
            ddl &lt;&lt; &quot;);\n\n&quot;
            structure &lt;&lt; ddl
          end
        end

        def structure_drop #:nodoc:
          s = select_all(&quot;select sequence_name from user_sequences&quot;).inject(&quot;&quot;) do &#124;drop, seq&#124;
            drop &lt;&lt; &quot;drop sequence #{seq.to_a.first.last};\n\n&quot;
          end

          select_all(&quot;select table_name from user_tables&quot;).inject(s) do &#124;drop, table&#124;
            drop &lt;&lt; &quot;drop table #{table.to_a.first.last} cascade constraints;\n\n&quot;
          end
        end

        def add_column_options!(sql, options) #:nodoc:
          # handle case of defaults for CLOB columns, which would otherwise get &quot;quoted&quot; incorrectly
          if options_include_default?(options) &amp;&amp; (column = options[:column]) &amp;&amp; column.type == :text
            sql &lt;&lt; &quot; DEFAULT #{quote(options.delete(:default))}&quot; 
          end
          super
        end

        # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
        #
        # Oracle requires the ORDER BY columns to be in the SELECT list for DISTINCT
        # queries. However, with those columns included in the SELECT DISTINCT list, you
        # won&#039;t actually get a distinct list of the column you want (presuming the column
        # has duplicates with multiple values for the ordered-by columns. So we use the 
        # FIRST_VALUE function to get a single (first) value for each column, effectively
        # making every row the same.
        #
        #   distinct(&quot;posts.id&quot;, &quot;posts.created_at desc&quot;)
        def distinct(columns, order_by)
          return &quot;DISTINCT #{columns}&quot; if order_by.blank?

          # construct a valid DISTINCT clause, ie. one that includes the ORDER BY columns, using
          # FIRST_VALUE such that the inclusion of these columns doesn&#039;t invalidate the DISTINCT
          order_columns = order_by.split(&#039;,&#039;).map { &#124;s&#124; s.strip }.reject(&amp;:blank?)
          order_columns = order_columns.zip((0...order_columns.size).to_a).map do &#124;c, i&#124;
            &quot;FIRST_VALUE(#{c.split.first}) OVER (PARTITION BY #{columns} ORDER BY #{c}) AS alias_#{i}__&quot;
          end
          sql = &quot;DISTINCT #{columns}, &quot;
          sql &lt;&lt; order_columns * &quot;, &quot;
        end

        # ORDER BY clause for the passed order option.
        # 
        # Uses column aliases as defined by #distinct.
        def add_order_by_for_association_limiting!(sql, options)
          return sql if options[:order].blank?

          order = options[:order].split(&#039;,&#039;).collect { &#124;s&#124; s.strip }.reject(&amp;:blank?)
          order.map! {&#124;s&#124; $1 if s =~ / (.*)/}
          order = order.zip((0...order.size).to_a).map { &#124;s,i&#124; &quot;alias_#{i}__ #{s}&quot; }.join(&#039;, &#039;)

          sql &lt;&lt; &quot; ORDER BY #{order}&quot;
        end

        private

        def select(sql, name = nil)
          cursor = execute(sql, name)
          cols = cursor.get_col_names.map { &#124;x&#124; oracle_downcase(x) }
          rows = []

          while row = cursor.fetch
            hash = Hash.new

            cols.each_with_index do &#124;col, i&#124;
              hash[col] =
                case row[i]
                when OCI8::LOB
                  name == &#039;Writable Large Object&#039; ? row[i]: row[i].read
                when OraDate
                  d = row[i]
                  if emulate_dates &amp;&amp; (d.hour == 0 &amp;&amp; d.minute == 0 &amp;&amp; d.second == 0)
                    d.to_date
                  else
                    # see string_to_time; Time overflowing to DateTime, respecting the default timezone
                    time_array = [d.year, d.month, d.day, d.hour, d.minute, d.second]
                    begin
                      Time.send(Base.default_timezone, *time_array)
                    rescue
                      zone_offset = if Base.default_timezone == :local then DateTime.now.offset else 0 end
                      # Append zero calendar reform start to account for dates skipped by calendar reform
                      DateTime.new(*time_array[0..5] &lt;&lt; zone_offset &lt;&lt; 0) rescue nil
                    end
                  end
                else row[i]
                end unless col == &#039;raw_rnum_&#039;
              	# RSI: patch - convert to integer if column is ID or ends with _pk or _fk
              	if (col !~ /^session_id$/i) &amp;&amp; (col =~ /^id$/i &#124;&#124; col =~ /_pk$/i &#124;&#124; col =~ /_fk$/i) &amp;&amp; hash[col]
			hash[col] = hash[col].to_i
              	end
            end
            
            rows &lt;&lt; hash
          end

          rows
        ensure
          cursor.close if cursor
        end

        # Oracle column names by default are case-insensitive, but treated as upcase;
        # for neatness, we&#039;ll downcase within Rails. EXCEPT that folks CAN quote
        # their column names when creating Oracle tables, which makes then case-sensitive.
        # I don&#039;t know anybody who does this, but we&#039;ll handle the theoretical case of a
        # camelCase column name. I imagine other dbs handle this different, since there&#039;s a
        # unit test that&#039;s currently failing test_oci.
        def oracle_downcase(column_name)
          column_name =~ /[a-z]/ ? column_name : column_name.downcase
        end

      end
    end
  end


  class OCI8 #:nodoc:

    # This OCI8 patch may not longer be required with the upcoming
    # release of version 0.2.
    class Cursor #:nodoc:
      alias :define_a_column_pre_ar :define_a_column
      def define_a_column(i)
        case do_ocicall(@ctx) { @parms[i - 1].attrGet(OCI_ATTR_DATA_TYPE) }
        when 8;   @stmt.defineByPos(i, String, 65535) # Read LONG values
        when 187; @stmt.defineByPos(i, OraDate) # Read TIMESTAMP values
        when 108
          if @parms[i - 1].attrGet(OCI_ATTR_TYPE_NAME) == &#039;XMLTYPE&#039;
            @stmt.defineByPos(i, String, 65535)
          else
            raise &#039;unsupported datatype&#039;
          end
        else define_a_column_pre_ar i
        end
      end
    end

    # missing constant from oci8 = &#039;0.1.14&#039;
      @desc.describeAny(@svc, name.to_s, OCI_PTYPE_UNK) rescue raise %Q{&quot;DESC #{name}&quot; failed; does it exist?}
      info = @desc.attrGet(OCI_ATTR_PARAM)

      case info.attrGet(OCI_ATTR_PTYPE)
      when OCI_PTYPE_TABLE, OCI_PTYPE_VIEW
        owner      = info.attrGet(OCI_ATTR_OBJ_SCHEMA)
        table_name = info.attrGet(OCI_ATTR_OBJ_NAME)
        [owner, table_name]
      when OCI_PTYPE_SYN
        schema = info.attrGet(OCI_ATTR_SCHEMA_NAME)
        name   = info.attrGet(OCI_ATTR_NAME)
        describe(schema + &#039;.&#039; + name)
      else raise %Q{&quot;DESC #{name}&quot; failed; not a table or view.}
      end
    end

  end


  # The OracleConnectionFactory factors out the code necessary to connect and
  # configure an Oracle/OCI connection.
  class OracleConnectionFactory #:nodoc:
    def new_connection(username, password, database, async, prefetch_rows, cursor_sharing)
      conn = OCI8.new username, password, database
      conn.exec %q{alter session set nls_date_format = &#039;YYYY-MM-DD HH24:MI:SS&#039;}
      conn.exec %q{alter session set nls_timestamp_format = &#039;YYYY-MM-DD HH24:MI:SS&#039;} rescue nil
      conn.autocommit = true
      conn.non_blocking = true if async
      conn.prefetch_rows = prefetch_rows
      conn.exec &quot;alter session set cursor_sharing = #{cursor_sharing}&quot; rescue nil
      conn
    end
  end


  # The OCI8AutoRecover class enhances the OCI8 driver with auto-recover and
  # reset functionality. If a call to #exec fails, and autocommit is turned on
  # (ie., we&#039;re not in the middle of a longer transaction), it will
  # automatically reconnect and try again. If autocommit is turned off,
  # this would be dangerous (as the earlier part of the implied transaction
  # may have failed silently if the connection died) -- so instead the
  # connection is marked as dead, to be reconnected on it&#039;s next use.
  class OCI8AutoRecover &lt; DelegateClass(OCI8) #:nodoc:
    attr_accessor :active
    alias :active? :active

    cattr_accessor :auto_retry
    class &lt; e
        raise unless LOST_CONNECTION_ERROR_CODES.include?(e.code)
        @active = false
        raise unless should_retry
        should_retry = false
        reset! rescue nil
        retry
      end
    end

  end

rescue LoadError
  # OCI8 driver is unavailable.
  module ActiveRecord # :nodoc:
    class Base
      @@oracle_error_message = &quot;Oracle/OCI libraries could not be loaded: #{$!.to_s}&quot;
      def self.oracle_connection(config) # :nodoc:
        # Set up a reasonable error message
        raise LoadError, @@oracle_error_message
      end
      def self.oci_connection(config) # :nodoc:
        # Set up a reasonable error message
        raise LoadError, @@oracle_error_message
      end
    end
  end
end
</description>
		<content:encoded><![CDATA[<p>Well apparently when you do the command &#8220;y Tablename.find(:all)&#8221; in the process of the &#8216;y&#8217; command converting the data into yml format removes any .0 . And when i run the command without y it looks like this</p>
<p>#&lt;Job cus_uid_pk: #, cus_name: &#8220;HENRY JR TORRES&#8221;, svo_uid_pk: #, slo_uid_pk: #,</p>
<p>ive also added this code into hopes of force integer handling<br />
im using rails 2.0.2 and oracle-adapter from <a href="http://svn.rubyonrails.org/rails/adapters/oracle/lib/active_record/connection_adapters/" rel="nofollow">http://svn.rubyonrails.org/rails/adapters/oracle/lib/active_record/connection_adapters/</a><br />
since the gem install is broken.<br />
I have  also tried adding more code to force an integer relation</p>
<p>          select_all(table_cols, name).map do |row|<br />
            limit, scale = row['limit'], row['scale']<br />
#patch map NUMBER , where column names ends with _pk or _fk to NUMBER(38)<br />
            if (row['name'] =~ /_pk$/i || row['name'] =~ /_fk$/i )<br />
	    	    	row['limit'] = 38<br />
	    end<br />
            if limit || scale<br />
              row['sql_type'] &lt; 0 ? &#8220;,#{scale})&#8221; : &#8220;)&#8221;)<br />
            end</p>
<p>here is my whole oracle_adapter.rb</p>
<p>require &#8216;active_record/connection_adapters/abstract_adapter&#8217;<br />
require &#8216;delegate&#8217;</p>
<p>begin<br />
  require_library_or_gem &#8216;oci8&#8242; unless self.class.const_defined? :OCI8</p>
<p>  module ActiveRecord<br />
    class Base<br />
      def self.oracle_connection(config) #:nodoc:<br />
        # Use OCI8AutoRecover instead of normal OCI8 driver.<br />
        ConnectionAdapters::OracleAdapter.new OCI8AutoRecover.new(config), logger<br />
      end</p>
<p>      # for backwards-compatibility<br />
      def self.oci_connection(config) #:nodoc:<br />
        config[:database] = config[:host]<br />
        self.oracle_connection(config)<br />
      end</p>
<p>      # After setting large objects to empty, select the OCI8::LOB<br />
      # and write back the data.<br />
      after_save :write_lobs<br />
      def write_lobs #:nodoc:<br />
        if connection.is_a?(ConnectionAdapters::OracleAdapter)<br />
          connection.write_lobs(self.class.table_name, self.class, attributes)<br />
        end<br />
      end</p>
<p>      private :write_lobs<br />
    end</p>
<p>    module ConnectionAdapters #:nodoc:<br />
      class OracleColumn &lt; Column #:nodoc:</p>
<p>        def type_cast(value)<br />
          return guess_date_or_time(value) if type == :datetime &amp;&amp; OracleAdapter.emulate_dates<br />
          super<br />
        end</p>
<p>        private<br />
        def simplified_type(field_type)<br />
          return :boolean if OracleAdapter.emulate_booleans &amp;&amp; field_type == &#8216;NUMBER(1)&#8217;<br />
          case field_type<br />
             when /date|time/i then :datetime<br />
            # RSI: treat columns which end with &#8216;date&#8217; as ruby date columns<br />
	     when /date$/i then :date<br />
	    # RSI: removed &#8216;date&#8217; from regex<br />
	     when /time/i then :datetime<br />
	    # RSI: treat id columns (primary key) and (foreign keys) as integer<br />
	     when /^id$/i then :integer<br />
	     when /_pk$/i then :integer<br />
	     when /_fk$/i then :integer<br />
            else super<br />
          end<br />
        end</p>
<p>        def guess_date_or_time(value)<br />
          (value.hour == 0 and value.min == 0 and value.sec == 0) ?<br />
            Date.new(value.year, value.month, value.day) : value<br />
        end<br />
      end</p>
<p>      # This is an Oracle/OCI adapter for the ActiveRecord persistence<br />
      # framework. It relies upon the OCI8 driver, which works with Oracle 8i<br />
      # and above. Most recent development has been on Debian Linux against<br />
      # a 10g database, ActiveRecord 1.12.1 and OCI8 0.1.13.<br />
      # See: <a href="http://rubyforge.org/projects/ruby-oci8/" rel="nofollow">http://rubyforge.org/projects/ruby-oci8/</a><br />
      #<br />
      # Usage notes:<br />
      # * Key generation assumes a &#8220;${table_name}_seq&#8221; sequence is available<br />
      #   for all tables; the sequence name can be changed using<br />
      #   ActiveRecord::Base.set_sequence_name. When using Migrations, these<br />
      #   sequences are created automatically.<br />
      # * Oracle uses DATE or TIMESTAMP datatypes for both dates and times.<br />
      #   Consequently some hacks are employed to map data back to Date or Time<br />
      #   in Ruby. If the column_name ends in _time it&#8217;s created as a Ruby Time.<br />
      #   Else if the hours/minutes/seconds are 0, I make it a Ruby Date. Else<br />
      #   it&#8217;s a Ruby Time. This is a bit nasty &#8211; but if you use Duck Typing<br />
      #   you&#8217;ll probably not care very much. In 9i and up it&#8217;s tempting to<br />
      #   map DATE to Date and TIMESTAMP to Time, but too many databases use<br />
      #   DATE for both. Timezones and sub-second precision on timestamps are<br />
      #   not supported.<br />
      # * Default values that are functions (such as &#8220;SYSDATE&#8221;) are not<br />
      #   supported. This is a restriction of the way ActiveRecord supports<br />
      #   default values.<br />
      # * Support for Oracle8 is limited by Rails&#8217; use of ANSI join syntax, which<br />
      #   is supported in Oracle9i and later. You will need to use #finder_sql for<br />
      #   has_and_belongs_to_many associations to run against Oracle8.<br />
      #<br />
      # Required parameters:<br />
      #<br />
      # * :username<br />
      # * :password<br />
      # * :database<br />
      class OracleAdapter  &#8220;NUMBER(38) NOT NULL PRIMARY KEY&#8221;,<br />
            :string      =&gt; { :name =&gt; &#8220;VARCHAR2&#8243;, :limit =&gt; 255 },<br />
            :text        =&gt; { :name =&gt; &#8220;CLOB&#8221; },<br />
            :integer     =&gt; { :name =&gt; &#8220;NUMBER&#8221;, :limit =&gt; 38 },<br />
            :float       =&gt; { :name =&gt; &#8220;NUMBER&#8221; },<br />
            :decimal     =&gt; { :name =&gt; &#8220;DECIMAL&#8221; },<br />
            :datetime    =&gt; { :name =&gt; &#8220;DATE&#8221; },<br />
            :timestamp   =&gt; { :name =&gt; &#8220;DATE&#8221; },<br />
            :time        =&gt; { :name =&gt; &#8220;DATE&#8221; },<br />
            :date        =&gt; { :name =&gt; &#8220;DATE&#8221; },<br />
            :binary      =&gt; { :name =&gt; &#8220;BLOB&#8221; },<br />
            :boolean     =&gt; { :name =&gt; &#8220;NUMBER&#8221;, :limit =&gt; 1 }<br />
          }<br />
        end</p>
<p>        def table_alias_length<br />
          30<br />
        end</p>
<p>        # QUOTING ==================================================<br />
        #<br />
        # see: abstract/quoting.rb</p>
<p>        # camelCase column names need to be quoted; not that anyone using Oracle<br />
        # would really do this, but handling this case means we pass the test&#8230;<br />
        def quote_column_name(name) #:nodoc:<br />
          name.to_s =~ /[A-Z]/ ? &#8220;\&#8221;#{name}\&#8221;" : name<br />
        end</p>
<p>        def quote_string(s) #:nodoc:<br />
          s.gsub(/&#8217;/, &#8220;&#8221;&#8221;)<br />
        end</p>
<p>        def quote(value, column = nil) #:nodoc:<br />
          if value &amp;&amp; column &amp;&amp; [:text, :binary].include?(column.type)<br />
            %Q{empty_#{ column.sql_type.downcase rescue &#8216;blob&#8217; }()}<br />
          else<br />
            super<br />
          end<br />
        end</p>
<p>        def quoted_true<br />
          &#8220;1&#8243;<br />
        end</p>
<p>        def quoted_false<br />
          &#8220;0&#8243;<br />
        end</p>
<p>        # CONNECTION MANAGEMENT ====================================<br />
        #</p>
<p>        # Returns true if the connection is active.<br />
        def active?<br />
          # Pings the connection to check if it&#8217;s still good. Note that an<br />
          # #active? method is also available, but that simply returns the<br />
          # last known state, which isn&#8217;t good enough if the connection has<br />
          # gone stale since the last use.<br />
          @connection.ping<br />
        rescue OCIException<br />
          false<br />
        end</p>
<p>        # Reconnects to the database.<br />
        def reconnect!<br />
          @connection.reset!<br />
        rescue OCIException =&gt; e<br />
          @logger.warn &#8220;#{adapter_name} automatic reconnection failed: #{e.message}&#8221;<br />
        end</p>
<p>        # Disconnects from the database.<br />
        def disconnect!<br />
          @connection.logoff rescue nil<br />
          @connection.active = false<br />
        end</p>
<p>        # DATABASE STATEMENTS ======================================<br />
        #<br />
        # see: abstract/database_statements.rb</p>
<p>        def execute(sql, name = nil) #:nodoc:<br />
          log(sql, name) { @connection.exec sql }<br />
        end</p>
<p>        # Returns the next sequence value from a sequence generator. Not generally<br />
        # called directly; used by ActiveRecord to get the next primary key value<br />
        # when inserting a new database record (see #prefetch_primary_key?).<br />
        def next_sequence_value(sequence_name)<br />
          id = 0<br />
          @connection.exec(&#8220;select #{sequence_name}.nextval id from dual&#8221;) { |r| id = r[0].to_i }<br />
          id<br />
        end</p>
<p>        def begin_db_transaction #:nodoc:<br />
          @connection.autocommit = false<br />
        end</p>
<p>        def commit_db_transaction #:nodoc:<br />
          @connection.commit<br />
        ensure<br />
          @connection.autocommit = true<br />
        end</p>
<p>        def rollback_db_transaction #:nodoc:<br />
          @connection.rollback<br />
        ensure<br />
          @connection.autocommit = true<br />
        end</p>
<p>        def add_limit_offset!(sql, options) #:nodoc:<br />
          offset = options[:offset] || 0</p>
<p>          if limit = options[:limit]<br />
            sql.replace &#8220;select * from (select raw_sql_.*, rownum raw_rnum_ from (#{sql}) raw_sql_ where rownum  #{offset}&#8221;<br />
          elsif offset &gt; 0<br />
            sql.replace &#8220;select * from (select raw_sql_.*, rownum raw_rnum_ from (#{sql}) raw_sql_) where raw_rnum_ &gt; #{offset}&#8221;<br />
          end<br />
        end</p>
<p>        # Returns true for Oracle adapter (since Oracle requires primary key<br />
        # values to be pre-fetched before insert). See also #next_sequence_value.<br />
        def prefetch_primary_key?(table_name = nil)<br />
          true<br />
        end</p>
<p>        def default_sequence_name(table, column) #:nodoc:<br />
          &#8220;#{table}_seq&#8221;<br />
        end</p>
<p>        # Inserts the given fixture into the table. Overridden to properly handle lobs.<br />
        def insert_fixture(fixture, table_name)<br />
          super</p>
<p>          klass = fixture.class_name.constantize rescue nil<br />
          if klass.respond_to?(:ancestors) &amp;&amp; klass.ancestors.include?(ActiveRecord::Base)<br />
            write_lobs(table_name, klass, fixture)<br />
          end<br />
        end</p>
<p>        # Writes LOB values from attributes, as indicated by the LOB columns of klass.<br />
        def write_lobs(table_name, klass, attributes)<br />
          id = quote(attributes[klass.primary_key])<br />
          klass.columns.select { |col| col.sql_type =~ /LOB$/i }.each do |col|<br />
            value = attributes[col.name]<br />
            value = value.to_yaml if col.text? &amp;&amp; klass.serialized_attributes[col.name]<br />
            next if value.nil?  || (value == &#8221;)<br />
            lob = select_one(&#8220;SELECT #{col.name} FROM #{table_name} WHERE #{klass.primary_key} = #{id}&#8221;,<br />
                             &#8216;Writable Large Object&#8217;)[col.name]<br />
            lob.write value<br />
          end<br />
        end</p>
<p>        # SCHEMA STATEMENTS ========================================<br />
        #<br />
        # see: abstract/schema_statements.rb</p>
<p>        def current_database #:nodoc:<br />
          select_one(&#8220;select sys_context(&#8216;userenv&#8217;,'db_name&#8217;) db from dual&#8221;)["db"]<br />
        end</p>
<p>        def tables(name = nil) #:nodoc:<br />
          select_all(&#8220;select lower(table_name) from user_tables&#8221;).inject([]) do | tabs, t |<br />
            tabs &lt;&lt; t.to_a.first.last<br />
          end<br />
        end</p>
<p>        def indexes(table_name, name = nil) #:nodoc:<br />
          result = select_all(&lt;&lt;-SQL, name)<br />
            SELECT lower(i.index_name) as index_name, i.uniqueness, lower(c.column_name) as column_name<br />
              FROM user_indexes i, user_ind_columns c<br />
             WHERE i.table_name = &#8216;#{table_name.to_s.upcase}&#8217;<br />
               AND c.index_name = i.index_name<br />
               AND i.index_name NOT IN (SELECT uc.index_name FROM user_constraints uc WHERE uc.constraint_type = &#8216;P&#8217;)<br />
              ORDER BY i.index_name, c.column_position<br />
          SQL</p>
<p>          current_index = nil<br />
          indexes = []</p>
<p>          result.each do |row|<br />
            if current_index != row['index_name']<br />
              indexes &lt;&lt; IndexDefinition.new(table_name, row['index_name'], row['uniqueness'] == &#8220;UNIQUE&#8221;, [])<br />
              current_index = row['index_name']<br />
            end</p>
<p>            indexes.last.columns &lt;&lt; row['column_name']<br />
          end</p>
<p>          indexes<br />
        end</p>
<p>        def columns(table_name, name = nil) #:nodoc:</p>
<p>          (owner, table_name) = @connection.describe(table_name)</p>
<p>          table_cols = &lt;&lt;-SQL<br />
            select column_name as name, data_type as sql_type, data_default, nullable,<br />
                   decode(data_type, &#8216;NUMBER&#8217;, data_precision,<br />
                                     &#8216;FLOAT&#8217;, data_precision,<br />
                                     &#8216;VARCHAR2&#8242;, data_length,<br />
                                     &#8216;CHAR&#8217;, data_length,<br />
                                      null) as limit,<br />
                   decode(data_type, &#8216;NUMBER&#8217;, data_scale, null) as scale<br />
              from all_tab_columns<br />
             where owner      = &#8216;#{owner}&#8217;<br />
               and table_name = &#8216;#{table_name}&#8217;<br />
             order by column_id<br />
          SQL</p>
<p>          select_all(table_cols, name).map do |row|<br />
            limit, scale = row['limit'], row['scale']<br />
            if (row['name'] =~ /_pk$/i || row['name'] =~ /_fk$/i )<br />
	    	    	row['limit'] = 38<br />
	    end<br />
            if limit || scale<br />
              row['sql_type'] &lt; 0 ? &#8220;,#{scale})&#8221; : &#8220;)&#8221;)<br />
            end<br />
            # clean up odd default spacing from Oracle<br />
            if row['data_default']<br />
              row['data_default'].sub!(/^(.*?)\s*$/, &#8216;\1&#8242;)<br />
              row['data_default'].sub!(/^&#8217;(.*)&#8217;$/, &#8216;\1&#8242;)<br />
              row['data_default'] = nil if row['data_default'] =~ /^(null|empty_[bc]lob\(\))$/i<br />
            end</p>
<p>            OracleColumn.new(oracle_downcase(row['name']),<br />
                             row['data_default'],<br />
                             row['sql_type'],<br />
                             row['nullable'] == &#8216;Y&#8217;)</p>
<p>          end<br />
        end</p>
<p>        def create_table(name, options = {}) #:nodoc:<br />
          super(name, options)<br />
          seq_name = options[:sequence_name] || &#8220;#{name}_seq&#8221;<br />
          execute &#8220;CREATE SEQUENCE #{seq_name} START WITH 10000&#8243; unless options[:id] == false<br />
        end</p>
<p>        def rename_table(name, new_name) #:nodoc:<br />
          execute &#8220;RENAME #{name} TO #{new_name}&#8221;<br />
          execute &#8220;RENAME #{name}_seq TO #{new_name}_seq&#8221; rescue nil<br />
        end</p>
<p>        def drop_table(name, options = {}) #:nodoc:<br />
          super(name)<br />
          seq_name = options[:sequence_name] || &#8220;#{name}_seq&#8221;<br />
          execute &#8220;DROP SEQUENCE #{seq_name}&#8221; rescue nil<br />
        end</p>
<p>        def remove_index(table_name, options = {}) #:nodoc:<br />
          execute &#8220;DROP INDEX #{index_name(table_name, options)}&#8221;<br />
        end</p>
<p>        def change_column_default(table_name, column_name, default) #:nodoc:<br />
          execute &#8220;ALTER TABLE #{table_name} MODIFY #{quote_column_name(column_name)} DEFAULT #{quote(default)}&#8221;<br />
        end</p>
<p>        def change_column(table_name, column_name, type, options = {}) #:nodoc:<br />
          change_column_sql = &#8220;ALTER TABLE #{table_name} MODIFY #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}&#8221;<br />
          add_column_options!(change_column_sql, options)<br />
          execute(change_column_sql)<br />
        end</p>
<p>        def rename_column(table_name, column_name, new_column_name) #:nodoc:<br />
          execute &#8220;ALTER TABLE #{table_name} RENAME COLUMN #{quote_column_name(column_name)} to #{quote_column_name(new_column_name)}&#8221;<br />
        end</p>
<p>        def remove_column(table_name, column_name) #:nodoc:<br />
          execute &#8220;ALTER TABLE #{table_name} DROP COLUMN #{quote_column_name(column_name)}&#8221;<br />
        end</p>
<p>        # Find a table&#8217;s primary key and sequence.<br />
        # *Note*: Only primary key is implemented &#8211; sequence will be nil.<br />
        def pk_and_sequence_for(table_name)<br />
          (owner, table_name) = @connection.describe(table_name)</p>
<p>          pks = select_values(&lt;&lt;-SQL, &#8216;Primary Key&#8217;)<br />
            select cc.column_name<br />
              from all_constraints c, all_cons_columns cc<br />
             where c.owner = &#8216;#{owner}&#8217;<br />
               and c.table_name = &#8216;#{table_name}&#8217;<br />
               and c.constraint_type = &#8216;P&#8217;<br />
               and cc.owner = c.owner<br />
               and cc.constraint_name = c.constraint_name<br />
          SQL</p>
<p>          # only support single column keys<br />
          pks.size == 1 ? [oracle_downcase(pks.first), nil] : nil<br />
        end</p>
<p>        def structure_dump #:nodoc:<br />
          s = select_all(&#8220;select sequence_name from user_sequences&#8221;).inject(&#8220;&#8221;) do |structure, seq|<br />
            structure &lt;&lt; &#8220;create sequence #{seq.to_a.first.last};\n\n&#8221;<br />
          end</p>
<p>          select_all(&#8220;select table_name from user_tables&#8221;).inject(s) do |structure, table|<br />
            ddl = &#8220;create table #{table.to_a.first.last} (\n &#8221;<br />
            cols = select_all(%Q{<br />
              select column_name, data_type, data_length, data_precision, data_scale, data_default, nullable<br />
              from user_tab_columns<br />
              where table_name = &#8216;#{table.to_a.first.last}&#8217;<br />
              order by column_id<br />
            }).map do |row|<br />
              col = &#8220;#{row['column_name'].downcase} #{row['data_type'].downcase}&#8221;<br />
              if row['data_type'] ==&#8217;NUMBER&#8217; and !row['data_precision'].nil?<br />
                col &lt;&lt; &#8220;(#{row['data_precision'].to_i}&#8221;<br />
                col &lt;&lt; &#8220;,#{row['data_scale'].to_i}&#8221; if !row['data_scale'].nil?<br />
                col &lt;&lt; &#8216;)&#8217;<br />
              elsif row['data_type'].include?(&#8216;CHAR&#8217;)<br />
                col &lt;&lt; &#8220;(#{row['data_length'].to_i})&#8221;<br />
              end<br />
              col &lt;&lt; &#8221; default #{row['data_default']}&#8221; if !row['data_default'].nil?<br />
              col &lt;&lt; &#8216; not null&#8217; if row['nullable'] == &#8216;N&#8217;<br />
              col<br />
            end<br />
            ddl &lt;&lt; cols.join(&#8220;,\n &#8220;)<br />
            ddl &lt;&lt; &#8220;);\n\n&#8221;<br />
            structure &lt;&lt; ddl<br />
          end<br />
        end</p>
<p>        def structure_drop #:nodoc:<br />
          s = select_all(&#8220;select sequence_name from user_sequences&#8221;).inject(&#8220;&#8221;) do |drop, seq|<br />
            drop &lt;&lt; &#8220;drop sequence #{seq.to_a.first.last};\n\n&#8221;<br />
          end</p>
<p>          select_all(&#8220;select table_name from user_tables&#8221;).inject(s) do |drop, table|<br />
            drop &lt;&lt; &#8220;drop table #{table.to_a.first.last} cascade constraints;\n\n&#8221;<br />
          end<br />
        end</p>
<p>        def add_column_options!(sql, options) #:nodoc:<br />
          # handle case of defaults for CLOB columns, which would otherwise get &#8220;quoted&#8221; incorrectly<br />
          if options_include_default?(options) &amp;&amp; (column = options[:column]) &amp;&amp; column.type == :text<br />
            sql &lt;&lt; &#8221; DEFAULT #{quote(options.delete(:default))}&#8221;<br />
          end<br />
          super<br />
        end</p>
<p>        # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.<br />
        #<br />
        # Oracle requires the ORDER BY columns to be in the SELECT list for DISTINCT<br />
        # queries. However, with those columns included in the SELECT DISTINCT list, you<br />
        # won&#8217;t actually get a distinct list of the column you want (presuming the column<br />
        # has duplicates with multiple values for the ordered-by columns. So we use the<br />
        # FIRST_VALUE function to get a single (first) value for each column, effectively<br />
        # making every row the same.<br />
        #<br />
        #   distinct(&#8220;posts.id&#8221;, &#8220;posts.created_at desc&#8221;)<br />
        def distinct(columns, order_by)<br />
          return &#8220;DISTINCT #{columns}&#8221; if order_by.blank?</p>
<p>          # construct a valid DISTINCT clause, ie. one that includes the ORDER BY columns, using<br />
          # FIRST_VALUE such that the inclusion of these columns doesn&#8217;t invalidate the DISTINCT<br />
          order_columns = order_by.split(&#8216;,&#8217;).map { |s| s.strip }.reject(&amp;:blank?)<br />
          order_columns = order_columns.zip((0&#8230;order_columns.size).to_a).map do |c, i|<br />
            &#8220;FIRST_VALUE(#{c.split.first}) OVER (PARTITION BY #{columns} ORDER BY #{c}) AS alias_#{i}__&#8221;<br />
          end<br />
          sql = &#8220;DISTINCT #{columns}, &#8221;<br />
          sql &lt;&lt; order_columns * &#8220;, &#8221;<br />
        end</p>
<p>        # ORDER BY clause for the passed order option.<br />
        #<br />
        # Uses column aliases as defined by #distinct.<br />
        def add_order_by_for_association_limiting!(sql, options)<br />
          return sql if options[:order].blank?</p>
<p>          order = options[:order].split(&#8216;,&#8217;).collect { |s| s.strip }.reject(&amp;:blank?)<br />
          order.map! {|s| $1 if s =~ / (.*)/}<br />
          order = order.zip((0&#8230;order.size).to_a).map { |s,i| &#8220;alias_#{i}__ #{s}&#8221; }.join(&#8216;, &#8216;)</p>
<p>          sql &lt;&lt; &#8221; ORDER BY #{order}&#8221;<br />
        end</p>
<p>        private</p>
<p>        def select(sql, name = nil)<br />
          cursor = execute(sql, name)<br />
          cols = cursor.get_col_names.map { |x| oracle_downcase(x) }<br />
          rows = []</p>
<p>          while row = cursor.fetch<br />
            hash = Hash.new</p>
<p>            cols.each_with_index do |col, i|<br />
              hash[col] =<br />
                case row[i]<br />
                when OCI8::LOB<br />
                  name == &#8216;Writable Large Object&#8217; ? row[i]: row[i].read<br />
                when OraDate<br />
                  d = row[i]<br />
                  if emulate_dates &amp;&amp; (d.hour == 0 &amp;&amp; d.minute == 0 &amp;&amp; d.second == 0)<br />
                    d.to_date<br />
                  else<br />
                    # see string_to_time; Time overflowing to DateTime, respecting the default timezone<br />
                    time_array = [d.year, d.month, d.day, d.hour, d.minute, d.second]<br />
                    begin<br />
                      Time.send(Base.default_timezone, *time_array)<br />
                    rescue<br />
                      zone_offset = if Base.default_timezone == :local then DateTime.now.offset else 0 end<br />
                      # Append zero calendar reform start to account for dates skipped by calendar reform<br />
                      DateTime.new(*time_array[0..5] &lt;&lt; zone_offset &lt;&lt; 0) rescue nil<br />
                    end<br />
                  end<br />
                else row[i]<br />
                end unless col == &#8216;raw_rnum_&#8217;<br />
              	# RSI: patch &#8211; convert to integer if column is ID or ends with _pk or _fk<br />
              	if (col !~ /^session_id$/i) &amp;&amp; (col =~ /^id$/i || col =~ /_pk$/i || col =~ /_fk$/i) &amp;&amp; hash[col]<br />
			hash[col] = hash[col].to_i<br />
              	end<br />
            end</p>
<p>            rows &lt;&lt; hash<br />
          end</p>
<p>          rows<br />
        ensure<br />
          cursor.close if cursor<br />
        end</p>
<p>        # Oracle column names by default are case-insensitive, but treated as upcase;<br />
        # for neatness, we&#8217;ll downcase within Rails. EXCEPT that folks CAN quote<br />
        # their column names when creating Oracle tables, which makes then case-sensitive.<br />
        # I don&#8217;t know anybody who does this, but we&#8217;ll handle the theoretical case of a<br />
        # camelCase column name. I imagine other dbs handle this different, since there&#8217;s a<br />
        # unit test that&#8217;s currently failing test_oci.<br />
        def oracle_downcase(column_name)<br />
          column_name =~ /[a-z]/ ? column_name : column_name.downcase<br />
        end</p>
<p>      end<br />
    end<br />
  end</p>
<p>  class OCI8 #:nodoc:</p>
<p>    # This OCI8 patch may not longer be required with the upcoming<br />
    # release of version 0.2.<br />
    class Cursor #:nodoc:<br />
      alias :define_a_column_pre_ar :define_a_column<br />
      def define_a_column(i)<br />
        case do_ocicall(@ctx) { @parms[i - 1].attrGet(OCI_ATTR_DATA_TYPE) }<br />
        when 8;   @stmt.defineByPos(i, String, 65535) # Read LONG values<br />
        when 187; @stmt.defineByPos(i, OraDate) # Read TIMESTAMP values<br />
        when 108<br />
          if @parms[i - 1].attrGet(OCI_ATTR_TYPE_NAME) == &#8216;XMLTYPE&#8217;<br />
            @stmt.defineByPos(i, String, 65535)<br />
          else<br />
            raise &#8216;unsupported datatype&#8217;<br />
          end<br />
        else define_a_column_pre_ar i<br />
        end<br />
      end<br />
    end</p>
<p>    # missing constant from oci8 = &#8217;0.1.14&#8242;<br />
      @desc.describeAny(@svc, name.to_s, OCI_PTYPE_UNK) rescue raise %Q{&#8220;DESC #{name}&#8221; failed; does it exist?}<br />
      info = @desc.attrGet(OCI_ATTR_PARAM)</p>
<p>      case info.attrGet(OCI_ATTR_PTYPE)<br />
      when OCI_PTYPE_TABLE, OCI_PTYPE_VIEW<br />
        owner      = info.attrGet(OCI_ATTR_OBJ_SCHEMA)<br />
        table_name = info.attrGet(OCI_ATTR_OBJ_NAME)<br />
        [owner, table_name]<br />
      when OCI_PTYPE_SYN<br />
        schema = info.attrGet(OCI_ATTR_SCHEMA_NAME)<br />
        name   = info.attrGet(OCI_ATTR_NAME)<br />
        describe(schema + &#8216;.&#8217; + name)<br />
      else raise %Q{&#8220;DESC #{name}&#8221; failed; not a table or view.}<br />
      end<br />
    end</p>
<p>  end</p>
<p>  # The OracleConnectionFactory factors out the code necessary to connect and<br />
  # configure an Oracle/OCI connection.<br />
  class OracleConnectionFactory #:nodoc:<br />
    def new_connection(username, password, database, async, prefetch_rows, cursor_sharing)<br />
      conn = OCI8.new username, password, database<br />
      conn.exec %q{alter session set nls_date_format = &#8216;YYYY-MM-DD HH24:MI:SS&#8217;}<br />
      conn.exec %q{alter session set nls_timestamp_format = &#8216;YYYY-MM-DD HH24:MI:SS&#8217;} rescue nil<br />
      conn.autocommit = true<br />
      conn.non_blocking = true if async<br />
      conn.prefetch_rows = prefetch_rows<br />
      conn.exec &#8220;alter session set cursor_sharing = #{cursor_sharing}&#8221; rescue nil<br />
      conn<br />
    end<br />
  end</p>
<p>  # The OCI8AutoRecover class enhances the OCI8 driver with auto-recover and<br />
  # reset functionality. If a call to #exec fails, and autocommit is turned on<br />
  # (ie., we&#8217;re not in the middle of a longer transaction), it will<br />
  # automatically reconnect and try again. If autocommit is turned off,<br />
  # this would be dangerous (as the earlier part of the implied transaction<br />
  # may have failed silently if the connection died) &#8212; so instead the<br />
  # connection is marked as dead, to be reconnected on it&#8217;s next use.<br />
  class OCI8AutoRecover &lt; DelegateClass(OCI8) #:nodoc:<br />
    attr_accessor :active<br />
    alias :active? :active</p>
<p>    cattr_accessor :auto_retry<br />
    class &lt; e<br />
        raise unless LOST_CONNECTION_ERROR_CODES.include?(e.code)<br />
        @active = false<br />
        raise unless should_retry<br />
        should_retry = false<br />
        reset! rescue nil<br />
        retry<br />
      end<br />
    end</p>
<p>  end</p>
<p>rescue LoadError<br />
  # OCI8 driver is unavailable.<br />
  module ActiveRecord # :nodoc:<br />
    class Base<br />
      @@oracle_error_message = &#8220;Oracle/OCI libraries could not be loaded: #{$!.to_s}&#8221;<br />
      def self.oracle_connection(config) # :nodoc:<br />
        # Set up a reasonable error message<br />
        raise LoadError, @@oracle_error_message<br />
      end<br />
      def self.oci_connection(config) # :nodoc:<br />
        # Set up a reasonable error message<br />
        raise LoadError, @@oracle_error_message<br />
      end<br />
    end<br />
  end<br />
end</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Raimonds Simanovskis</title>
		<link>http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-188</link>
		<dc:creator>Raimonds Simanovskis</dc:creator>
		<pubDate>Wed, 02 Apr 2008 12:32:30 +0000</pubDate>
		<guid isPermaLink="false">http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-188</guid>
		<description>It&#039;s quite strange. Scaffold controller is doing the same Table.find(:all) and then for each record in view to_param method is called from named route helper method to get the parameter string.

Try Table.find(:all).first.to_param - will it return integer or will it return .0 at the end?</description>
		<content:encoded><![CDATA[<p>It&#8217;s quite strange. Scaffold controller is doing the same Table.find(:all) and then for each record in view to_param method is called from named route helper method to get the parameter string.</p>
<p>Try Table.find(:all).first.to_param &#8211; will it return integer or will it return .0 at the end?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Simon</title>
		<link>http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-187</link>
		<dc:creator>Simon</dc:creator>
		<pubDate>Wed, 02 Apr 2008 11:43:29 +0000</pubDate>
		<guid isPermaLink="false">http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-187</guid>
		<description>oops. well this works find if you do a script/console session and trye &quot; y Table.find(:all)&quot;
keys don&#039;t have the .0 on them. BUT if you look at it in scaffold like localhost:3000/tablename
the .0&#039;s are back

just wondering in if you had any suggestions</description>
		<content:encoded><![CDATA[<p>oops. well this works find if you do a script/console session and trye &#8221; y Table.find(:all)&#8221;<br />
keys don&#8217;t have the .0 on them. BUT if you look at it in scaffold like localhost:3000/tablename<br />
the .0&#8242;s are back</p>
<p>just wondering in if you had any suggestions</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Simon</title>
		<link>http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-186</link>
		<dc:creator>Simon</dc:creator>
		<pubDate>Wed, 02 Apr 2008 11:40:03 +0000</pubDate>
		<guid isPermaLink="false">http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-186</guid>
		<description>I tried your code by modifying the oracle-adapter.rb file 
and add my companies own legacy conventions. Here all keys end with _pk or _fk.

def simplified_type(field_type)
          return :boolean if OracleAdapter.emulate_booleans &amp;&amp; field_type == &#039;NUMBER(1)&#039;
          case field_type
            when /date&#124;time/i then :datetime
 	    # RSI: treat columns which end with &#039;date&#039; as ruby date columns
	     when /date$/i then :date
	    # RSI: removed &#039;date&#039; from regex
	     when /time/i then :datetime
	    # RSI: treat id columns (primary key) and (foreign keys) as integer
	     when /^id$/i then :integer
	     when /_pk$/i then :integer
	     when /_fk$/i then :integer
            else super
          end
        end
def select(sql, name = nil)
          cursor = execute(sql, name)
          cols = cursor.get_col_names.map { &#124;x&#124; oracle_downcase(x) }
          rows = []

          while row = cursor.fetch
            hash = Hash.new

            cols.each_with_index do &#124;col, i&#124;
              hash[col] =
                case row[i]
                when OCI8::LOB
                  name == &#039;Writable Large Object&#039; ? row[i]: row[i].read
                when OraDate
                  d = row[i]
                  if emulate_dates &amp;&amp; (d.hour == 0 &amp;&amp; d.minute == 0 &amp;&amp; d.second == 0)
                    d.to_date
                  else
                    # see string_to_time; Time overflowing to DateTime, respecting the default timezone
                    time_array = [d.year, d.month, d.day, d.hour, d.minute, d.second]
                    begin
                      Time.send(Base.default_timezone, *time_array)
                    rescue
                      zone_offset = if Base.default_timezone == :local then DateTime.now.offset else 0 end
                      # Append zero calendar reform start to account for dates skipped by calendar reform
                      DateTime.new(*time_array[0..5] &lt;&lt; zone_offset &lt;&lt; 0) rescue nil
                    end
                  end
                else row[i]
                end unless col == &#039;raw_rnum_&#039;
                # RSI: patch - convert to integer if column is ID or ends with _pk or _fk
                hash[col] = hash[col].to_i if (col =~ /^id$/i &#124;&#124; col =~ /_pk$/i &#124;&#124; col =~ /_fk/i) &amp;&amp; hash[col]
              	
            end

            rows &lt;&lt; hash
          end

          rows
        ensure
          cursor.close if cursor
        end
</description>
		<content:encoded><![CDATA[<p>I tried your code by modifying the oracle-adapter.rb file<br />
and add my companies own legacy conventions. Here all keys end with _pk or _fk.</p>
<p>def simplified_type(field_type)<br />
          return :boolean if OracleAdapter.emulate_booleans &amp;&amp; field_type == &#8216;NUMBER(1)&#8217;<br />
          case field_type<br />
            when /date|time/i then :datetime<br />
 	    # RSI: treat columns which end with &#8216;date&#8217; as ruby date columns<br />
	     when /date$/i then :date<br />
	    # RSI: removed &#8216;date&#8217; from regex<br />
	     when /time/i then :datetime<br />
	    # RSI: treat id columns (primary key) and (foreign keys) as integer<br />
	     when /^id$/i then :integer<br />
	     when /_pk$/i then :integer<br />
	     when /_fk$/i then :integer<br />
            else super<br />
          end<br />
        end<br />
def select(sql, name = nil)<br />
          cursor = execute(sql, name)<br />
          cols = cursor.get_col_names.map { |x| oracle_downcase(x) }<br />
          rows = []</p>
<p>          while row = cursor.fetch<br />
            hash = Hash.new</p>
<p>            cols.each_with_index do |col, i|<br />
              hash[col] =<br />
                case row[i]<br />
                when OCI8::LOB<br />
                  name == &#8216;Writable Large Object&#8217; ? row[i]: row[i].read<br />
                when OraDate<br />
                  d = row[i]<br />
                  if emulate_dates &amp;&amp; (d.hour == 0 &amp;&amp; d.minute == 0 &amp;&amp; d.second == 0)<br />
                    d.to_date<br />
                  else<br />
                    # see string_to_time; Time overflowing to DateTime, respecting the default timezone<br />
                    time_array = [d.year, d.month, d.day, d.hour, d.minute, d.second]<br />
                    begin<br />
                      Time.send(Base.default_timezone, *time_array)<br />
                    rescue<br />
                      zone_offset = if Base.default_timezone == :local then DateTime.now.offset else 0 end<br />
                      # Append zero calendar reform start to account for dates skipped by calendar reform<br />
                      DateTime.new(*time_array[0..5] &lt;&lt; zone_offset &lt;&lt; 0) rescue nil<br />
                    end<br />
                  end<br />
                else row[i]<br />
                end unless col == &#8216;raw_rnum_&#8217;<br />
                # RSI: patch &#8211; convert to integer if column is ID or ends with _pk or _fk<br />
                hash[col] = hash[col].to_i if (col =~ /^id$/i || col =~ /_pk$/i || col =~ /_fk/i) &amp;&amp; hash[col]</p>
<p>            end</p>
<p>            rows &lt;&lt; hash<br />
          end</p>
<p>          rows<br />
        ensure<br />
          cursor.close if cursor<br />
        end</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jesse Hu</title>
		<link>http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-181</link>
		<dc:creator>Jesse Hu</dc:creator>
		<pubDate>Tue, 01 Apr 2008 11:19:43 +0000</pubDate>
		<guid isPermaLink="false">http://blog.rayapps.com/2007/11/16/some-issues-with-oracle-views-as-activerecord-source/#comment-181</guid>
		<description>that&#039;s nice!</description>
		<content:encoded><![CDATA[<p>that&#8217;s nice!</p>
]]></content:encoded>
	</item>
</channel>
</rss>
