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