kb-activerecord-jdbc-adapter 0.9.7.1-java → 1.0.0.beta1-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. data/History.txt +11 -0
  2. data/Manifest.txt +71 -38
  3. data/lib/active_record/connection_adapters/cachedb_adapter.rb +1 -1
  4. data/lib/active_record/connection_adapters/derby_adapter.rb +1 -13
  5. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -13
  6. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -13
  7. data/lib/active_record/connection_adapters/informix_adapter.rb +1 -1
  8. data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -661
  9. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -1
  10. data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -13
  11. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -13
  12. data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -1
  13. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -13
  14. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -13
  15. data/lib/activerecord-jdbc-adapter.rb +2 -2
  16. data/lib/arjdbc/cachedb/adapter.rb +20 -0
  17. data/lib/arjdbc/cachedb/connection_methods.rb +10 -0
  18. data/lib/arjdbc/cachedb.rb +3 -0
  19. data/lib/{jdbc_adapter/jdbc_db2.rb → arjdbc/db2/adapter.rb} +2 -17
  20. data/lib/arjdbc/db2.rb +2 -0
  21. data/lib/{jdbc_adapter/jdbc_derby.rb → arjdbc/derby/adapter.rb} +8 -26
  22. data/lib/arjdbc/derby/connection_methods.rb +18 -0
  23. data/lib/arjdbc/derby.rb +7 -0
  24. data/lib/arjdbc/discover.rb +99 -0
  25. data/lib/{jdbc_adapter/jdbc_firebird.rb → arjdbc/firebird/adapter.rb} +12 -16
  26. data/lib/arjdbc/firebird.rb +2 -0
  27. data/lib/arjdbc/h2/adapter.rb +15 -0
  28. data/lib/arjdbc/h2/connection_methods.rb +12 -0
  29. data/lib/arjdbc/h2.rb +4 -0
  30. data/lib/{jdbc_adapter/jdbc_hsqldb.rb → arjdbc/hsqldb/adapter.rb} +6 -58
  31. data/lib/arjdbc/hsqldb/connection_methods.rb +14 -0
  32. data/lib/arjdbc/hsqldb.rb +4 -0
  33. data/lib/{jdbc_adapter/jdbc_informix.rb → arjdbc/informix/adapter.rb} +6 -19
  34. data/lib/arjdbc/informix/connection_methods.rb +10 -0
  35. data/lib/arjdbc/informix.rb +3 -0
  36. data/lib/arjdbc/jdbc/adapter.rb +235 -0
  37. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  38. data/lib/arjdbc/jdbc/callbacks.rb +44 -0
  39. data/lib/arjdbc/jdbc/column.rb +38 -0
  40. data/lib/arjdbc/jdbc/compatibility.rb +51 -0
  41. data/lib/arjdbc/jdbc/connection.rb +97 -0
  42. data/lib/arjdbc/jdbc/connection_methods.rb +16 -0
  43. data/lib/arjdbc/jdbc/core_ext.rb +24 -0
  44. data/lib/arjdbc/jdbc/discover.rb +18 -0
  45. data/lib/arjdbc/jdbc/driver.rb +44 -0
  46. data/lib/arjdbc/jdbc/extension.rb +47 -0
  47. data/lib/arjdbc/jdbc/java.rb +14 -0
  48. data/lib/{jdbc_adapter → arjdbc/jdbc}/missing_functionality_helper.rb +5 -5
  49. data/lib/arjdbc/jdbc/quoted_primary_key.rb +28 -0
  50. data/lib/{jdbc_adapter → arjdbc/jdbc}/railtie.rb +1 -1
  51. data/lib/arjdbc/jdbc/require_driver.rb +16 -0
  52. data/lib/arjdbc/jdbc/type_converter.rb +119 -0
  53. data/lib/arjdbc/jdbc.rb +2 -0
  54. data/lib/{jdbc_adapter/jdbc_mimer.rb → arjdbc/mimer/adapter.rb} +16 -19
  55. data/lib/arjdbc/mimer.rb +2 -0
  56. data/lib/{jdbc_adapter/jdbc_mssql.rb → arjdbc/mssql/adapter.rb} +19 -31
  57. data/lib/arjdbc/mssql/connection_methods.rb +13 -0
  58. data/lib/arjdbc/mssql.rb +4 -0
  59. data/lib/arjdbc/mysql/adapter.rb +388 -0
  60. data/lib/arjdbc/mysql/connection_methods.rb +26 -0
  61. data/lib/arjdbc/mysql.rb +4 -0
  62. data/lib/{jdbc_adapter/jdbc_oracle.rb → arjdbc/oracle/adapter.rb} +9 -17
  63. data/lib/arjdbc/oracle/connection_methods.rb +11 -0
  64. data/lib/arjdbc/oracle.rb +3 -0
  65. data/lib/{jdbc_adapter/jdbc_postgre.rb → arjdbc/postgresql/adapter.rb} +7 -36
  66. data/lib/arjdbc/postgresql/connection_methods.rb +21 -0
  67. data/lib/arjdbc/postgresql.rb +4 -0
  68. data/lib/{jdbc_adapter/jdbc_sqlite3.rb → arjdbc/sqlite3/adapter.rb} +106 -104
  69. data/lib/arjdbc/sqlite3/connection_methods.rb +33 -0
  70. data/lib/arjdbc/sqlite3.rb +4 -0
  71. data/lib/arjdbc/sybase/adapter.rb +46 -0
  72. data/lib/arjdbc/sybase.rb +2 -0
  73. data/lib/arjdbc/version.rb +8 -0
  74. data/lib/arjdbc.rb +29 -0
  75. data/lib/jdbc_adapter/version.rb +3 -5
  76. data/lib/jdbc_adapter.rb +2 -27
  77. data/rails_generators/templates/config/initializers/jdbc.rb +1 -1
  78. data/rakelib/compile.rake +3 -2
  79. data/rakelib/package.rake +3 -3
  80. data/src/java/{jdbc_adapter/JdbcDerbySpec.java → arjdbc/derby/DerbyModule.java} +32 -32
  81. data/src/java/{jdbc_adapter/JdbcAdapterInternalService.java → arjdbc/jdbc/AdapterJavaService.java} +13 -7
  82. data/src/java/{jdbc_adapter → arjdbc/jdbc}/JdbcConnectionFactory.java +6 -6
  83. data/src/java/{jdbc_adapter → arjdbc/jdbc}/RubyJdbcConnection.java +91 -16
  84. data/src/java/arjdbc/jdbc/SQLBlock.java +48 -0
  85. data/src/java/{jdbc_adapter → arjdbc/mssql}/MssqlRubyJdbcConnection.java +5 -2
  86. data/src/java/{jdbc_adapter/JdbcMySQLSpec.java → arjdbc/mysql/MySQLModule.java} +12 -12
  87. data/src/java/{jdbc_adapter/PostgresRubyJdbcConnection.java → arjdbc/postgresql/PostgresqlRubyJdbcConnection.java} +11 -9
  88. data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +64 -0
  89. data/test/abstract_db_create.rb +4 -1
  90. data/test/activerecord/connection_adapters/type_conversion_test.rb +1 -1
  91. data/test/db/cachedb.rb +0 -0
  92. data/test/db/derby.rb +12 -14
  93. data/test/db/hsqldb.rb +3 -2
  94. data/test/db/jndi_config.rb +4 -4
  95. data/test/db/sqlite3.rb +2 -6
  96. data/test/db2_simple_test.rb +23 -0
  97. data/test/derby_migration_test.rb +50 -3
  98. data/test/jdbc_common.rb +1 -1
  99. data/test/jndi_callbacks_test.rb +1 -0
  100. data/test/postgres_nonseq_pkey_test.rb +0 -2
  101. data/test/postgres_schema_search_path_test.rb +0 -2
  102. data/test/simple.rb +3 -3
  103. data/test/sybase_jtds_simple_test.rb +22 -0
  104. metadata +81 -46
  105. data/lib/active_record/connection_adapters/jdbc_adapter_spec.rb +0 -26
  106. data/lib/jdbc_adapter/jdbc_adapter_internal.jar +0 -0
  107. data/lib/jdbc_adapter/jdbc_cachedb.rb +0 -33
  108. data/lib/jdbc_adapter/jdbc_mysql.rb +0 -260
  109. data/lib/jdbc_adapter/jdbc_sybase.rb +0 -50
  110. data/src/java/jdbc_adapter/SQLBlock.java +0 -27
  111. data/src/java/jdbc_adapter/Sqlite3RubyJdbcConnection.java +0 -41
  112. data/test/jdbc_adapter/jdbc_db2_test.rb +0 -26
  113. data/test/jdbc_adapter/jdbc_sybase_test.rb +0 -33
  114. data/test/minirunit/testConnect.rb +0 -14
  115. data/test/minirunit/testH2.rb +0 -73
  116. data/test/minirunit/testHsqldb.rb +0 -73
  117. data/test/minirunit/testLoadActiveRecord.rb +0 -3
  118. data/test/minirunit/testMysql.rb +0 -83
  119. data/test/minirunit/testRawSelect.rb +0 -24
  120. data/test/minirunit.rb +0 -109
  121. /data/lib/{jdbc_adapter → arjdbc/jdbc}/jdbc.rake +0 -0
  122. /data/lib/{jdbc_adapter → arjdbc/jdbc}/rake_tasks.rb +0 -0
  123. /data/lib/{jdbc_adapter → arjdbc/mssql}/tsql_helper.rb +0 -0
@@ -0,0 +1,28 @@
1
+ module ArJdbc
2
+ module QuotedPrimaryKeyExtension
3
+ def self.extended(base)
4
+ # Rails 3 method Rails 2 method
5
+ meth = [:arel_attributes_values, :attributes_with_quotes].detect do |m|
6
+ base.private_instance_methods.include?(m.to_s)
7
+ end
8
+ pk_hash_key = "self.class.primary_key"
9
+ pk_hash_value = '"?"'
10
+ if meth == :arel_attributes_values
11
+ pk_hash_key = "self.class.arel_table[#{pk_hash_key}]"
12
+ pk_hash_value = "Arel::SqlLiteral.new(#{pk_hash_value})"
13
+ end
14
+ if meth
15
+ base.module_eval <<-PK, __FILE__, __LINE__
16
+ alias :#{meth}_pre_pk :#{meth}
17
+ def #{meth}(include_primary_key = true, *args) #:nodoc:
18
+ aq = #{meth}_pre_pk(include_primary_key, *args)
19
+ if connection.is_a?(ArJdbc::Oracle) || connection.is_a?(ArJdbc::Mimer)
20
+ aq[#{pk_hash_key}] = #{pk_hash_value} if include_primary_key && aq[#{pk_hash_key}].nil?
21
+ end
22
+ aq
23
+ end
24
+ PK
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,6 +1,6 @@
1
1
  require 'rails/railtie'
2
2
 
3
- module ::JdbcSpec
3
+ module ::ArJdbc
4
4
  class Railtie < ::Rails::Railtie
5
5
  rake_tasks do
6
6
  load File.expand_path('../rake_tasks.rb', __FILE__)
@@ -0,0 +1,16 @@
1
+ module Kernel
2
+ # load a JDBC driver library/gem, failing silently. If failed, trust
3
+ # that the driver jar is already present through some other means
4
+ def jdbc_require_driver(path, gem_name = nil)
5
+ gem_name ||= path.sub('/', '-')
6
+ 2.times do
7
+ begin
8
+ require path
9
+ break
10
+ rescue LoadError
11
+ require 'rubygems'
12
+ begin; gem gem_name; rescue LoadError; end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,119 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ # I want to use JDBC's DatabaseMetaData#getTypeInfo to choose the best native types to
4
+ # use for ActiveRecord's Adapter#native_database_types in a database-independent way,
5
+ # but apparently a database driver can return multiple types for a given
6
+ # java.sql.Types constant. So this type converter uses some heuristics to try to pick
7
+ # the best (most common) type to use. It's not great, it would be better to just
8
+ # delegate to each database's existin AR adapter's native_database_types method, but I
9
+ # wanted to try to do this in a way that didn't pull in all the other adapters as
10
+ # dependencies. Suggestions appreciated.
11
+ class JdbcTypeConverter
12
+ # The basic ActiveRecord types, mapped to an array of procs that are used to #select
13
+ # the best type. The procs are used as selectors in order until there is only one
14
+ # type left. If all the selectors are applied and there is still more than one
15
+ # type, an exception will be raised.
16
+ AR_TO_JDBC_TYPES = {
17
+ :string => [ lambda {|r| Jdbc::Types::VARCHAR == r['data_type'].to_i},
18
+ lambda {|r| r['type_name'] =~ /^varchar/i},
19
+ lambda {|r| r['type_name'] =~ /^varchar$/i},
20
+ lambda {|r| r['type_name'] =~ /varying/i}],
21
+ :text => [ lambda {|r| [Jdbc::Types::LONGVARCHAR, Jdbc::Types::CLOB].include?(r['data_type'].to_i)},
22
+ lambda {|r| r['type_name'] =~ /^text$/i}, # For Informix
23
+ lambda {|r| r['type_name'] =~ /^(text|clob)$/i},
24
+ lambda {|r| r['type_name'] =~ /^character large object$/i},
25
+ lambda {|r| r['sql_data_type'] == 2005}],
26
+ :integer => [ lambda {|r| Jdbc::Types::INTEGER == r['data_type'].to_i},
27
+ lambda {|r| r['type_name'] =~ /^integer$/i},
28
+ lambda {|r| r['type_name'] =~ /^int4$/i},
29
+ lambda {|r| r['type_name'] =~ /^int$/i}],
30
+ :decimal => [ lambda {|r| Jdbc::Types::DECIMAL == r['data_type'].to_i},
31
+ lambda {|r| r['type_name'] =~ /^decimal$/i},
32
+ lambda {|r| r['type_name'] =~ /^numeric$/i},
33
+ lambda {|r| r['type_name'] =~ /^number$/i},
34
+ lambda {|r| r['type_name'] =~ /^real$/i},
35
+ lambda {|r| r['precision'] == '38'},
36
+ lambda {|r| r['data_type'] == '2'}],
37
+ :float => [ lambda {|r| [Jdbc::Types::FLOAT,Jdbc::Types::DOUBLE, Jdbc::Types::REAL].include?(r['data_type'].to_i)},
38
+ lambda {|r| r['data_type'].to_i == Jdbc::Types::REAL}, #Prefer REAL to DOUBLE for Postgresql
39
+ lambda {|r| r['type_name'] =~ /^float/i},
40
+ lambda {|r| r['type_name'] =~ /^double$/i},
41
+ lambda {|r| r['type_name'] =~ /^real$/i},
42
+ lambda {|r| r['precision'] == '15'}],
43
+ :datetime => [ lambda {|r| Jdbc::Types::TIMESTAMP == r['data_type'].to_i},
44
+ lambda {|r| r['type_name'] =~ /^datetime$/i},
45
+ lambda {|r| r['type_name'] =~ /^timestamp$/i},
46
+ lambda {|r| r['type_name'] =~ /^date/i},
47
+ lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver
48
+ :timestamp => [ lambda {|r| Jdbc::Types::TIMESTAMP == r['data_type'].to_i},
49
+ lambda {|r| r['type_name'] =~ /^timestamp$/i},
50
+ lambda {|r| r['type_name'] =~ /^datetime/i},
51
+ lambda {|r| r['type_name'] =~ /^date/i},
52
+ lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver
53
+ :time => [ lambda {|r| Jdbc::Types::TIME == r['data_type'].to_i},
54
+ lambda {|r| r['type_name'] =~ /^time$/i},
55
+ lambda {|r| r['type_name'] =~ /^datetime/i}, # For Informix
56
+ lambda {|r| r['type_name'] =~ /^date/i},
57
+ lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver
58
+ :date => [ lambda {|r| Jdbc::Types::DATE == r['data_type'].to_i},
59
+ lambda {|r| r['type_name'] =~ /^date$/i},
60
+ lambda {|r| r['type_name'] =~ /^date/i},
61
+ lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver3
62
+ :binary => [ lambda {|r| [Jdbc::Types::LONGVARBINARY,Jdbc::Types::BINARY,Jdbc::Types::BLOB].include?(r['data_type'].to_i)},
63
+ lambda {|r| r['type_name'] =~ /^blob/i},
64
+ lambda {|r| r['type_name'] =~ /sub_type 0$/i}, # For FireBird
65
+ lambda {|r| r['type_name'] =~ /^varbinary$/i}, # We want this sucker for Mimer
66
+ lambda {|r| r['type_name'] =~ /^binary$/i}, ],
67
+ :boolean => [ lambda {|r| [Jdbc::Types::TINYINT].include?(r['data_type'].to_i)},
68
+ lambda {|r| r['type_name'] =~ /^bool/i},
69
+ lambda {|r| r['data_type'] == '-7'},
70
+ lambda {|r| r['type_name'] =~ /^tinyint$/i},
71
+ lambda {|r| r['type_name'] =~ /^decimal$/i},
72
+ lambda {|r| r['type_name'] =~ /^integer$/i}]
73
+ }
74
+
75
+ def initialize(types)
76
+ @types = types
77
+ @types.each {|t| t['type_name'] ||= t['local_type_name']} # Sybase driver seems to want 'local_type_name'
78
+ end
79
+
80
+ def choose_best_types
81
+ type_map = {}
82
+ @types.each do |row|
83
+ name = row['type_name'].downcase
84
+ k = name.to_sym
85
+ type_map[k] = { :name => name }
86
+ type_map[k][:limit] = row['precision'].to_i if row['precision']
87
+ end
88
+
89
+ AR_TO_JDBC_TYPES.keys.each do |k|
90
+ typerow = choose_type(k)
91
+ type_map[k] = { :name => typerow['type_name'].downcase }
92
+ case k
93
+ when :integer, :string, :decimal
94
+ type_map[k][:limit] = typerow['precision'] && typerow['precision'].to_i
95
+ when :boolean
96
+ type_map[k][:limit] = 1
97
+ end
98
+ end
99
+ type_map
100
+ end
101
+
102
+ def choose_type(ar_type)
103
+ procs = AR_TO_JDBC_TYPES[ar_type]
104
+ types = @types
105
+ procs.each do |p|
106
+ new_types = types.reject {|r| r["data_type"].to_i == Jdbc::Types::OTHER}
107
+ new_types = new_types.select(&p)
108
+ new_types = new_types.inject([]) do |typs,t|
109
+ typs << t unless typs.detect {|el| el['type_name'] == t['type_name']}
110
+ typs
111
+ end
112
+ return new_types.first if new_types.length == 1
113
+ types = new_types if new_types.length > 0
114
+ end
115
+ raise "unable to choose type for #{ar_type} from:\n#{types.collect{|t| t['type_name']}.inspect}"
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,2 @@
1
+ require 'arjdbc/jdbc/adapter'
2
+ require 'arjdbc/jdbc/discover'
@@ -1,11 +1,8 @@
1
- module JdbcSpec
1
+ module ArJdbc
2
2
  module Mimer
3
3
  def self.extended(mod)
4
- ActiveRecord::Base.extend JdbcSpec::QuotedPrimaryKeyExtension
5
- end
6
-
7
- def self.adapter_matcher(name, *)
8
- name =~ /mimer/i ? self : false
4
+ require 'arjdbc/jdbc/quoted_primary_key'
5
+ ActiveRecord::Base.extend ArJdbc::QuotedPrimaryKeyExtension
9
6
  end
10
7
 
11
8
  def modify_types(tp)
@@ -20,7 +17,7 @@ module JdbcSpec
20
17
  tp[:date] = { :name => "TIMESTAMP" }
21
18
  tp
22
19
  end
23
-
20
+
24
21
  def default_sequence_name(table, column) #:nodoc:
25
22
  "#{table}_seq"
26
23
  end
@@ -54,13 +51,13 @@ module JdbcSpec
54
51
  log(sql, name) { @connection.execute_insert sql,pk }
55
52
  else # Assume the sql contains a bind-variable for the id
56
53
  id_value = select_one("SELECT NEXT_VALUE OF #{sequence_name} AS val FROM MIMER.ONEROW")['val']
57
- log(sql, name) {
54
+ log(sql, name) {
58
55
  execute_prepared_insert(sql,id_value)
59
56
  }
60
57
  end
61
58
  id_value
62
59
  end
63
-
60
+
64
61
  def execute_prepared_insert(sql, id)
65
62
  @stmts ||= {}
66
63
  @stmts[sql] ||= @connection.ps(sql)
@@ -72,24 +69,24 @@ module JdbcSpec
72
69
 
73
70
  def quote(value, column = nil) #:nodoc:
74
71
  return value.quoted_id if value.respond_to?(:quoted_id)
75
-
72
+
76
73
  if String === value && column && column.type == :binary
77
74
  return "X'#{quote_string(value.unpack("C*").collect {|v| v.to_s(16)}.join)}'"
78
75
  end
79
76
  case value
80
- when String
77
+ when String
81
78
  %Q{'#{quote_string(value)}'}
82
- when NilClass
79
+ when NilClass
83
80
  'NULL'
84
- when TrueClass
81
+ when TrueClass
85
82
  '1'
86
- when FalseClass
83
+ when FalseClass
87
84
  '0'
88
- when Numeric
85
+ when Numeric
89
86
  value.to_s
90
- when Date, Time
87
+ when Date, Time
91
88
  %Q{TIMESTAMP '#{value.strftime("%Y-%m-%d %H:%M:%S")}'}
92
- else
89
+ else
93
90
  %Q{'#{quote_string(value.to_yaml)}'}
94
91
  end
95
92
  end
@@ -106,7 +103,7 @@ module JdbcSpec
106
103
  @limit = options[:limit]
107
104
  @offset = options[:offset]
108
105
  end
109
-
106
+
110
107
  def select_all(sql, name = nil)
111
108
  @offset ||= 0
112
109
  if !@limit || @limit == -1
@@ -118,7 +115,7 @@ module JdbcSpec
118
115
  ensure
119
116
  @limit = @offset = nil
120
117
  end
121
-
118
+
122
119
  def select_one(sql, name = nil)
123
120
  @offset ||= 0
124
121
  select(sql, name)[@offset]
@@ -0,0 +1,2 @@
1
+ require 'arjdbc/jdbc'
2
+ require 'arjdbc/mimer/adapter'
@@ -1,22 +1,7 @@
1
- require 'jdbc_adapter/tsql_helper'
2
-
3
- module ::JdbcSpec
4
-
5
- module ActiveRecordExtensions
6
-
7
- def mssql_connection(config)
8
- require "active_record/connection_adapters/mssql_adapter"
9
- config[:host] ||= "localhost"
10
- config[:port] ||= 1433
11
- config[:url] ||= "jdbc:jtds:sqlserver://#{config[:host]}:#{config[:port]}/#{config[:database]}"
12
- config[:driver] ||= "net.sourceforge.jtds.jdbc.Driver"
13
- embedded_driver(config)
14
- end
15
-
16
- end
1
+ require 'arjdbc/mssql/tsql_helper'
17
2
 
3
+ module ::ArJdbc
18
4
  module MsSQL
19
-
20
5
  include TSqlMethods
21
6
 
22
7
  def self.extended(mod)
@@ -39,12 +24,8 @@ module ::JdbcSpec
39
24
  mod.add_version_specific_add_limit_offset
40
25
  end
41
26
 
42
- def self.adapter_matcher(name, *)
43
- name =~ /sqlserver|tds/i ? self : false
44
- end
45
-
46
27
  def self.column_selector
47
- [/sqlserver|tds/i, lambda {|cfg,col| col.extend(::JdbcSpec::MsSQL::Column)}]
28
+ [/sqlserver|tds/i, lambda {|cfg,col| col.extend(::ArJdbc::MsSQL::Column)}]
48
29
  end
49
30
 
50
31
  def self.jdbc_connection_class
@@ -102,7 +83,7 @@ module ::JdbcSpec
102
83
  def type_cast(value)
103
84
  return nil if value.nil? || value == "(null)" || value == "(NULL)"
104
85
  case type
105
- when :integer then unquote(value).to_i rescue value ? 1 : 0
86
+ when :integer then value.to_i rescue unquote(value).to_i rescue value ? 1 : 0
106
87
  when :primary_key then value == true || value == false ? value == true ? 1 : 0 : value.to_i
107
88
  when :decimal then self.class.value_to_decimal(unquote(value))
108
89
  when :datetime then cast_to_datetime(value)
@@ -165,7 +146,7 @@ module ::JdbcSpec
165
146
  when String, ActiveSupport::Multibyte::Chars
166
147
  value = value.to_s
167
148
  if column && column.type == :binary
168
- "'#{quote_string(JdbcSpec::MsSQL::Column.string_to_binary(value))}'" # ' (for ruby-mode)
149
+ "'#{quote_string(ArJdbc::MsSQL::Column.string_to_binary(value))}'" # ' (for ruby-mode)
169
150
  elsif column && [:integer, :float].include?(column.type)
170
151
  value = column.type == :integer ? value.to_i : value.to_f
171
152
  value.to_s
@@ -209,7 +190,7 @@ module ::JdbcSpec
209
190
  end_row = offset + limit.to_i
210
191
  order = (options[:order] || determine_order_clause(sql))
211
192
  sql.sub!(/ ORDER BY.*$/i, '')
212
- find_select = /\b(SELECT(?:\s+DISTINCT)?)\b(.*)/i
193
+ find_select = /\b(SELECT(?:\s+DISTINCT)?)\b(.*)/im
213
194
  whole, select, rest_of_query = find_select.match(sql).to_a
214
195
  if (start_row == 1) && (end_row ==1)
215
196
  new_sql = "#{select} TOP 1 #{rest_of_query}"
@@ -240,7 +221,7 @@ module ::JdbcSpec
240
221
  end_row = offset + limit.to_i
241
222
  order = (options[:order] || determine_order_clause(sql))
242
223
  sql.sub!(/ ORDER BY.*$/i, '')
243
- find_select = /\b(SELECT(?:\s+DISTINCT)?)\b(.*)/i
224
+ find_select = /\b(SELECT(?:\s+DISTINCT)?)\b(.*)/im
244
225
  whole, select, rest_of_query = find_select.match(sql).to_a
245
226
  new_sql = "#{select} t.* FROM (SELECT ROW_NUMBER() OVER(ORDER BY #{order}) AS row_num, #{rest_of_query}"
246
227
  new_sql << ") AS t WHERE t.row_num BETWEEN #{start_row.to_s} AND #{end_row.to_s}"
@@ -371,6 +352,12 @@ module ::JdbcSpec
371
352
  end
372
353
  end
373
354
 
355
+ def select(sql, name = nil)
356
+ log(sql, name) do
357
+ @connection.execute_query(sql)
358
+ end
359
+ end
360
+
374
361
  #SELECT .. FOR UPDATE is not supported on Microsoft SQL Server
375
362
  def add_lock!(sql, options)
376
363
  sql
@@ -452,17 +439,18 @@ module ::JdbcSpec
452
439
 
453
440
  def determine_order_clause(sql)
454
441
  return $1 if sql =~ /ORDER BY (.*)$/
455
- sql =~ /FROM +(\w+?)\b/ || raise("can't determine table name")
456
- table_name = $1
442
+ table_name = get_table_name(sql)
457
443
  "#{table_name}.#{determine_primary_key(table_name)}"
458
444
  end
459
445
 
460
446
  def determine_primary_key(table_name)
461
447
  primary_key = columns(table_name).detect { |column| column.primary || column.identity }
462
- primary_key ? primary_key.name : "id"
448
+ return primary_key.name if primary_key
449
+ # Look for an id column. Return it, without changing case, to cover dbs with a case-sensitive collation.
450
+ columns(table_name).each { |column| return column.name if column.name =~ /^id$/i }
451
+ # Give up and provide something which is going to crash almost certainly
452
+ "id"
463
453
  end
464
-
465
454
  end
466
-
467
455
  end
468
456
 
@@ -0,0 +1,13 @@
1
+ class ActiveRecord::Base
2
+ class << self
3
+ def mssql_connection(config)
4
+ require "arjdbc/mssql"
5
+ config[:host] ||= "localhost"
6
+ config[:port] ||= 1433
7
+ config[:url] ||= "jdbc:jtds:sqlserver://#{config[:host]}:#{config[:port]}/#{config[:database]}"
8
+ config[:driver] ||= "net.sourceforge.jtds.jdbc.Driver"
9
+ embedded_driver(config)
10
+ end
11
+ alias_method :jdbcmssql_connection, :mssql_connection
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ require 'arjdbc/jdbc'
2
+ jdbc_require_driver 'jdbc/jtds', 'jdbc-mssql'
3
+ require 'arjdbc/mssql/connection_methods'
4
+ require 'arjdbc/mssql/adapter'