Title: [973] trunk/activerecord-jdbc: JRUBY-2438: Adding first cut of Joseph Athman's sqlite3 adapter

Diff

Modified: trunk/activerecord-jdbc/History.txt (972 => 973)


--- trunk/activerecord-jdbc/History.txt	2008-04-23 16:08:30 UTC (rev 972)
+++ trunk/activerecord-jdbc/History.txt	2008-04-24 15:43:01 UTC (rev 973)
@@ -1,3 +1,9 @@
+== 0.8.1
+
+- Now sporting a JDBC sqlite3 adapter! Thanks Joseph Athman.
+- Added support for InterSystems Cache database (Ryan Bell)
+- Fix for JRUBY-2256
+
 == 0.8
 
 - NOTE: This release is only compatible with JRuby 1.1RC3 or later.

Modified: trunk/activerecord-jdbc/README.txt (972 => 973)


--- trunk/activerecord-jdbc/README.txt	2008-04-23 16:08:30 UTC (rev 972)
+++ trunk/activerecord-jdbc/README.txt	2008-04-24 15:43:01 UTC (rev 973)
@@ -26,6 +26,8 @@
   * rename_column
 * HSQLDB - Complete
 * H2 - Complete
+* SQLite3 - work in progress, definitely not working:
+  * remove_column
 
 Other databases will require testing and likely a custom configuration module. Please join the jruby-extras mailing-list[http://rubyforge.org/mail/?group_id=2014] to help us discover support for more databases.
 

Modified: trunk/activerecord-jdbc/Rakefile (972 => 973)


--- trunk/activerecord-jdbc/Rakefile	2008-04-23 16:08:30 UTC (rev 972)
+++ trunk/activerecord-jdbc/Rakefile	2008-04-24 15:43:01 UTC (rev 973)
@@ -29,6 +29,7 @@
   rm_rf FileList['derby*']
   rm_rf FileList['test.db.*']
   rm_rf "test/reports"
+  rm_f "test.sqlite3"
   rm_f FileList['lib/**/*.jar']
   rm_f "manifest.mf"
 end
@@ -41,7 +42,7 @@
 
 if RUBY_PLATFORM =~ /java/
   # TODO: add more databases into the standard tests here.
-  task :test => [:test_mysql, :test_jdbc, :test_derby, :test_hsqldb, :test_h2]
+  task :test => [:test_mysql, :test_jdbc, :test_derby, :test_hsqldb, :test_h2, :test_sqlite3]
 else
   task :test => [:test_mysql]
 end

Added: trunk/activerecord-jdbc/adapters/sqlite3/LICENSE.txt (0 => 973)


--- trunk/activerecord-jdbc/adapters/sqlite3/LICENSE.txt	                        (rev 0)
+++ trunk/activerecord-jdbc/adapters/sqlite3/LICENSE.txt	2008-04-24 15:43:01 UTC (rev 973)
@@ -0,0 +1,21 @@
+Copyright (c) 2006-2007 Nick Sieger <[EMAIL PROTECTED]>
+Copyright (c) 2006-2007 Ola Bini <[EMAIL PROTECTED]>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Added: trunk/activerecord-jdbc/adapters/sqlite3/README.txt (0 => 973)


--- trunk/activerecord-jdbc/adapters/sqlite3/README.txt	                        (rev 0)
+++ trunk/activerecord-jdbc/adapters/sqlite3/README.txt	2008-04-24 15:43:01 UTC (rev 973)
@@ -0,0 +1,5 @@
+This is an ActiveRecord driver for SQLite3 using JDBC running under JRuby. Please see
+
+http://jruby-extras.rubyforge.org/activerecord-jdbc-adapter/
+
+for more information.
\ No newline at end of file

Copied: trunk/activerecord-jdbc/adapters/sqlite3/Rakefile (from rev 972, trunk/activerecord-jdbc/drivers/sqlite3/Rakefile) (0 => 973)


--- trunk/activerecord-jdbc/adapters/sqlite3/Rakefile	                        (rev 0)
+++ trunk/activerecord-jdbc/adapters/sqlite3/Rakefile	2008-04-24 15:43:01 UTC (rev 973)
@@ -0,0 +1,31 @@
+MANIFEST = FileList["Manifest.txt", "Rakefile", "README.txt", "LICENSE.txt", "lib/**/*"]
+
+file "Manifest.txt" => :manifest
+task :manifest do
+  File.open("Manifest.txt", "w") {|f| MANIFEST.each {|n| f << "#{n}\n"} }
+end
+Rake::Task['manifest'].invoke
+
+require File.dirname(__FILE__) + "/../../lib/jdbc_adapter/version"
+$LOAD_PATH << File.dirname(__FILE__) + "/../../drivers/sqlite3/lib"
+require "jdbc/sqlite3"
+
+begin
+  require 'hoe'
+  Hoe.new("activerecord-jdbcsqlite3-adapter", JdbcAdapter::Version::VERSION) do |p|
+    p.rubyforge_name = "jruby-extras"
+    p.url = ""
+    p.author = "Nick Sieger, Ola Bini and JRuby contributors"
+    p.email = "[EMAIL PROTECTED], [EMAIL PROTECTED]"
+    p.summary = "SQLite3 JDBC adapter for JRuby on Rails."
+    p.changes = "Updated to SQLite3 version #{Jdbc::SQLite3::VERSION}."
+    p.description = "Install this gem to use SQLite3 with JRuby on Rails."
+    p.extra_deps += [
+      ['activerecord-jdbc-adapter', ">= #{JdbcAdapter::Version::VERSION}"],
+      ['jdbc-sqlite3', ">= #{Jdbc::SQLite3::VERSION}"]]
+  end.spec.dependencies.delete_if { |dep| dep.name == "hoe" }
+rescue LoadError
+  puts "You really need Hoe installed to be able to package this gem"
+rescue => e
+  puts "ignoring error while loading hoe: #{e.to_s}"
+end

Added: trunk/activerecord-jdbc/adapters/sqlite3/lib/active_record/connection_adapters/jdbcsqlite3_adapter.rb (0 => 973)


--- trunk/activerecord-jdbc/adapters/sqlite3/lib/active_record/connection_adapters/jdbcsqlite3_adapter.rb	                        (rev 0)
+++ trunk/activerecord-jdbc/adapters/sqlite3/lib/active_record/connection_adapters/jdbcsqlite3_adapter.rb	2008-04-24 15:43:01 UTC (rev 973)
@@ -0,0 +1,30 @@
+tried_gem = false
+begin
+  require "jdbc_adapter"
+rescue LoadError
+  raise if tried_gem
+  require 'rubygems'
+  gem "activerecord-jdbc-adapter"
+  tried_gem = true
+  retry
+end
+tried_gem = false
+begin
+  require "jdbc/sqlite3"
+rescue LoadError
+  raise if tried_gem
+  require 'rubygems'
+  gem "jdbc-sqlite3"
+  tried_gem = true
+  retry
+end
+
+require 'active_record/connection_adapters/jdbc_adapter'
+
+module ActiveRecord
+  class Base
+    class << self
+      alias_method :jdbcsqlite3_connection, :sqlite3_connection
+    end
+  end
+end
\ No newline at end of file

Modified: trunk/activerecord-jdbc/drivers/sqlite3/Rakefile (972 => 973)


--- trunk/activerecord-jdbc/drivers/sqlite3/Rakefile	2008-04-23 16:08:30 UTC (rev 972)
+++ trunk/activerecord-jdbc/drivers/sqlite3/Rakefile	2008-04-24 15:43:01 UTC (rev 973)
@@ -10,14 +10,14 @@
 require "jdbc/sqlite3"
 begin
   require 'hoe'
-  Hoe.new("jdbc-sqlite3", Jdbc::SQLite::VERSION) do |p|
+  Hoe.new("jdbc-sqlite3", Jdbc::SQLite3::VERSION) do |p|
     p.rubyforge_name = "jruby-extras"
     p.url = ""
     p.author = "Nick Sieger, Ola Bini and JRuby contributors"
     p.email = "[EMAIL PROTECTED], [EMAIL PROTECTED]"
-    p.summary = "SQLite JDBC driver for Java and SQLite/ActiveRecord-JDBC."
-    p.changes = "Updated to SQLite version #{Jdbc::SQLite::VERSION}."
-    p.description = "Install this gem and require 'sqlite' within JRuby to load the driver."
+    p.summary = "SQLite3 JDBC driver for Java and SQLite3/ActiveRecord-JDBC."
+    p.changes = "Updated to SQLite3 version #{Jdbc::SQLite3::VERSION}."
+    p.description = "Install this gem and require 'sqlite3' within JRuby to load the driver."
   end.spec.dependencies.delete_if { |dep| dep.name == "hoe" }
 rescue LoadError
   puts "You really need Hoe installed to be able to package this gem"

Modified: trunk/activerecord-jdbc/drivers/sqlite3/lib/jdbc/sqlite3.rb (972 => 973)


--- trunk/activerecord-jdbc/drivers/sqlite3/lib/jdbc/sqlite3.rb	2008-04-23 16:08:30 UTC (rev 972)
+++ trunk/activerecord-jdbc/drivers/sqlite3/lib/jdbc/sqlite3.rb	2008-04-24 15:43:01 UTC (rev 973)
@@ -1,10 +1,10 @@
 module Jdbc
-  module SQLite
+  module SQLite3
     VERSION = "3.5.8"
   end
 end
 if RUBY_PLATFORM =~ /java/
-  require "sqlite-#{Jdbc::SQLite::VERSION}.jar"
+  require "sqlite-#{Jdbc::SQLite3::VERSION}.jar"
 else
-  warn "jdbc-SQLite is only for use with JRuby"
+  warn "jdbc-SQLite3 is only for use with JRuby"
 end
\ No newline at end of file

Modified: trunk/activerecord-jdbc/lib/active_record/connection_adapters/jdbc_adapter.rb (972 => 973)


--- trunk/activerecord-jdbc/lib/active_record/connection_adapters/jdbc_adapter.rb	2008-04-23 16:08:30 UTC (rev 972)
+++ trunk/activerecord-jdbc/lib/active_record/connection_adapters/jdbc_adapter.rb	2008-04-24 15:43:01 UTC (rev 973)
@@ -135,6 +135,7 @@
                           lambda {|r| r['type_name'] =~ /^decimal$/i},
                           lambda {|r| r['type_name'] =~ /^numeric$/i},
                           lambda {|r| r['type_name'] =~ /^number$/i},
+                          lambda {|r| r['type_name'] =~ /^real$/i},
                           lambda {|r| r['precision'] == '38'},
                           lambda {|r| r['data_type'] == '2'}],
         :float       => [ lambda {|r| [Jdbc::Types::FLOAT,Jdbc::Types::DOUBLE, Jdbc::Types::REAL].include?(r['data_type'].to_i)},
@@ -146,17 +147,21 @@
         :datetime    => [ lambda {|r| Jdbc::Types::TIMESTAMP == r['data_type'].to_i},
                           lambda {|r| r['type_name'] =~ /^datetime$/i},
                           lambda {|r| r['type_name'] =~ /^timestamp$/i},
-                          lambda {|r| r['type_name'] =~ /^date/i}],
+                          lambda {|r| r['type_name'] =~ /^date/i},
+                          lambda {|r| r['type_name'] =~ /^integer/i}],  #Num of milliseconds for SQLite3 JDBC Driver
         :timestamp   => [ lambda {|r| Jdbc::Types::TIMESTAMP == r['data_type'].to_i},
                           lambda {|r| r['type_name'] =~ /^timestamp$/i},
                           lambda {|r| r['type_name'] =~ /^datetime/i},
-                          lambda {|r| r['type_name'] =~ /^date/i}],
+                          lambda {|r| r['type_name'] =~ /^date/i},
+                          lambda {|r| r['type_name'] =~ /^integer/i}],  #Num of milliseconds for SQLite3 JDBC Driver
         :time        => [ lambda {|r| Jdbc::Types::TIME == r['data_type'].to_i},
                           lambda {|r| r['type_name'] =~ /^time$/i},
-                          lambda {|r| r['type_name'] =~ /^date/i}],
+                          lambda {|r| r['type_name'] =~ /^date/i},
+                          lambda {|r| r['type_name'] =~ /^integer/i}],  #Num of milliseconds for SQLite3 JDBC Driver
         :date        => [ lambda {|r| Jdbc::Types::DATE == r['data_type'].to_i},
                           lambda {|r| r['type_name'] =~ /^date$/i},
-                          lambda {|r| r['type_name'] =~ /^date/i}],
+                          lambda {|r| r['type_name'] =~ /^date/i},
+                          lambda {|r| r['type_name'] =~ /^integer/i}],  #Num of milliseconds for SQLite3 JDBC Driver3
         :binary      => [ lambda {|r| [Jdbc::Types::LONGVARBINARY,Jdbc::Types::BINARY,Jdbc::Types::BLOB].include?(r['data_type'].to_i)},
                           lambda {|r| r['type_name'] =~ /^blob/i},
                           lambda {|r| r['type_name'] =~ /sub_type 0$/i}, # For FireBird
@@ -166,7 +171,8 @@
                           lambda {|r| r['type_name'] =~ /^bool/i},
                           lambda {|r| r['data_type'] == '-7'},
                           lambda {|r| r['type_name'] =~ /^tinyint$/i},
-                          lambda {|r| r['type_name'] =~ /^decimal$/i}]
+                          lambda {|r| r['type_name'] =~ /^decimal$/i},
+                          lambda {|r| r['type_name'] =~ /^integer$/i}]
       }
 
       def initialize(types)

Modified: trunk/activerecord-jdbc/lib/active_record/connection_adapters/jdbc_adapter_spec.rb (972 => 973)


--- trunk/activerecord-jdbc/lib/active_record/connection_adapters/jdbc_adapter_spec.rb	2008-04-23 16:08:30 UTC (rev 972)
+++ trunk/activerecord-jdbc/lib/active_record/connection_adapters/jdbc_adapter_spec.rb	2008-04-24 15:43:01 UTC (rev 973)
@@ -9,3 +9,4 @@
 require 'jdbc_adapter/jdbc_db2'
 require 'jdbc_adapter/jdbc_mssql'
 require 'jdbc_adapter/jdbc_cachedb'
+require 'jdbc_adapter/jdbc_sqlite3'

Added: trunk/activerecord-jdbc/lib/active_record/connection_adapters/sqlite3_adapter.rb (0 => 973)


--- trunk/activerecord-jdbc/lib/active_record/connection_adapters/sqlite3_adapter.rb	                        (rev 0)
+++ trunk/activerecord-jdbc/lib/active_record/connection_adapters/sqlite3_adapter.rb	2008-04-24 15:43:01 UTC (rev 973)
@@ -0,0 +1,13 @@
+tried_gem = false
+begin
+  require "jdbc/sqlite3"
+rescue LoadError
+  unless tried_gem
+    require 'rubygems'
+    gem "jdbc-sqlite3"
+    tried_gem = true
+    retry
+  end
+  # trust that the sqlite jar is already present
+end
+require 'active_record/connection_adapters/jdbc_adapter'

Added: trunk/activerecord-jdbc/lib/jdbc_adapter/jdbc_sqlite3.rb (0 => 973)


--- trunk/activerecord-jdbc/lib/jdbc_adapter/jdbc_sqlite3.rb	                        (rev 0)
+++ trunk/activerecord-jdbc/lib/jdbc_adapter/jdbc_sqlite3.rb	2008-04-24 15:43:01 UTC (rev 973)
@@ -0,0 +1,194 @@
+module ::JdbcSpec
+  module ActiveRecordExtensions
+    def sqlite3_connection(config)
+      config[:url] ||= "jdbc:sqlite:#{config[:database]}"
+      config[:driver] ||= "org.sqlite.JDBC"
+      jdbc_connection(config)
+    end
+  end
+
+  module SQLite3
+    def self.column_selector
+      [/sqlite/i, lambda {|cfg,col| col.extend(::JdbcSpec::SQLite3::Column)}]
+    end
+
+    def self.adapter_selector
+      [/sqlite/i, lambda {|cfg,adapt| adapt.extend(::JdbcSpec::SQLite3)}]
+    end
+
+    module Column
+
+      private
+      def simplified_type(field_type)
+        case field_type
+        when /^integer\(1\)$/i                  then :boolean
+        when /text/i                           then :string
+        when /int/i                            then :integer
+        when /real/i                   then @scale == 0 ? :integer : :decimal
+        when /date|time/i                      then :datetime
+        when /blob/i                           then :binary
+        end
+      end
+
+      def self.cast_to_date_or_time(value)
+        return value if value.is_a? Date
+        return nil if value.blank?
+        guess_date_or_time((value.is_a? Time) ? value : cast_to_time(value))
+      end
+
+      def self.cast_to_time(value)
+        return value if value.is_a? Time
+        Time.at(value) rescue nil
+      end
+
+      def self.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
+
+    def type_cast(value)
+      return nil if value.nil?
+      case type
+      when :string   then value
+      when :integer  then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
+      when :primary_key then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
+      when :float    then value.to_f
+      when :datetime then JdbcSpec::SQLite3::Column.cast_to_date_or_time(value)
+      when :time     then JdbcSpec::SQLite3::Column.cast_to_time(value)
+      when :decimal   then self.class.value_to_decimal(value)
+      when :boolean   then self.class.value_to_boolean(value)
+      else value
+      end
+    end
+
+    def modify_types(tp)
+      tp[:primary_key] = "INTEGER PRIMARY KEY AUTOINCREMENT"
+      tp[:float] = { :name => "REAL" }
+      tp[:decimal] = { :name => "REAL" }
+      tp[:datetime] = { :name => "INTEGER" }
+      tp[:timestamp] = { :name => "INTEGER" }
+      tp[:time] = { :name => "INTEGER" }
+      tp[:date] = { :name => "INTEGER" }
+      tp[:boolean] = { :name => "INTEGER", :limit => 1}
+      tp
+    end
+
+    def quote(value, column = nil) # :nodoc:
+      return value.quoted_id if value.respond_to?(:quoted_id)
+
+      case value
+      when String
+        if column && column.type == :binary
+          "'#{quote_string(value).unpack("C*").collect {|v| v.to_s(16)}.join}'"
+        else
+          "'#{quote_string(value)}'"
+        end
+      else super
+      end
+    end
+
+    def quote_string(str)
+      str.gsub(/'/, "''")
+    end
+
+    def quoted_true
+      '1'
+    end
+
+    def quoted_false
+      '0'
+    end
+
+    def add_column(table_name, column_name, type, options = {})
+      if option_not_null = options[:null] == false
+        option_not_null = options.delete(:null)
+      end
+      add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
+      add_column_options!(add_column_sql, options)
+      execute(add_column_sql)
+      if option_not_null
+        alter_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ALTER #{quote_column_name(column_name)} NOT NULL"
+      end
+    end
+
+    def remove_column(table_name, column_name) #:nodoc:
+      puts "not implemented in SQLite3"
+    end
+
+    def change_column(table_name, column_name, type, options = {}) #:nodoc:
+      execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} #{type_to_sql(type, options[:limit])}"
+    end
+
+    def change_column_default(table_name, column_name, default) #:nodoc:
+      execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DEFAULT #{quote(default)}"
+    end
+
+    def rename_column(table_name, column_name, new_column_name) #:nodoc:
+      execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} RENAME TO #{new_column_name}"
+    end
+
+    def rename_table(name, new_name)
+      execute "ALTER TABLE #{name} RENAME TO #{new_name}"
+    end
+
+    def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
+      log(sql,name) do
+        @connection.execute_update(sql)
+      end
+      table = sql.split(" ", 4)[2]
+      id_value || last_insert_id(table, nil)
+    end
+
+    def last_insert_id(table, sequence_name)
+      Integer(select_value("SELECT SEQ FROM SQLITE_SEQUENCE WHERE NAME = '#{table}'"))
+    end
+
+    # Override normal #_execute: See Rubyforge #11567
+    def _execute(sql, name = nil)
+      if ::ActiveRecord::ConnectionAdapters::JdbcConnection::select?(sql)
+        @connection.execute_query(sql)
+      elsif ::ActiveRecord::ConnectionAdapters::JdbcConnection::insert?(sql)
+        insert(sql, name)
+      else
+        @connection.execute_update(sql)
+      end
+    end
+
+    def add_limit_offset!(sql, options) #:nodoc:
+      if options[:limit]
+        sql << " LIMIT #{options[:limit]}"
+        sql << " OFFSET #{options[:offset]}" if options[:offset]
+      end
+    end
+
+    def tables
+      @connection.tables.select {|row| row.to_s !~ /^sqlite_/i }
+    end
+
+    def remove_index(table_name, options = {})
+      execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
+    end
+
+    def indexes(table_name, name = nil)
+      result = select_rows(<<-SQL, name)
+        SELECT name, sql
+          FROM sqlite_master
+         WHERE tbl_name = '#{table_name}'
+           AND type = 'index'
+      SQL
+
+      indexes = []
+
+      result.each do |row|
+        name = row[0]
+        index_sql = row[1]
+        unique = (index_sql =~ /unique/i)
+        cols = index_sql.match(/\((.*)\)/)[1].gsub(/,/,' ').split
+        indexes << ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, name, unique, cols)
+      end
+
+      indexes
+    end
+  end
+end

Added: trunk/activerecord-jdbc/test/db/sqlite3.rb (0 => 973)


--- trunk/activerecord-jdbc/test/db/sqlite3.rb	                        (rev 0)
+++ trunk/activerecord-jdbc/test/db/sqlite3.rb	2008-04-24 15:43:01 UTC (rev 973)
@@ -0,0 +1,11 @@
+config = {
+  :adapter => 'sqlite3',
+  :database => 'test.sqlite3'
+}
+
+ActiveRecord::Base.establish_connection(config)
+
+at_exit {
+  # Clean up hsqldb when done
+  Dir['test.sqlite3*'].each {|f| File.delete(f)}
+}

Added: trunk/activerecord-jdbc/test/sqlite3_simple_test.rb (0 => 973)


--- trunk/activerecord-jdbc/test/sqlite3_simple_test.rb	                        (rev 0)
+++ trunk/activerecord-jdbc/test/sqlite3_simple_test.rb	2008-04-24 15:43:01 UTC (rev 973)
@@ -0,0 +1,6 @@
+require 'jdbc_common'
+require 'db/sqlite3'
+
+class SQLite3SimpleTest < Test::Unit::TestCase
+  include SimpleTestMethods
+end
_______________________________________________
Jruby-extras-devel mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/jruby-extras-devel

Reply via email to