activerecord-jdbc-adapter 0.9.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. data/History.txt +163 -0
  2. data/Manifest.txt +130 -65
  3. data/README.txt +64 -72
  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 -633
  9. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -1
  10. data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
  11. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
  12. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -13
  13. data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -1
  14. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -13
  15. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -13
  16. data/lib/activerecord-jdbc-adapter.rb +6 -0
  17. data/lib/arel/engines/sql/compilers/db2_compiler.rb +9 -0
  18. data/lib/arel/engines/sql/compilers/derby_compiler.rb +6 -0
  19. data/lib/arel/engines/sql/compilers/h2_compiler.rb +6 -0
  20. data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +15 -0
  21. data/lib/arel/engines/sql/compilers/jdbc_compiler.rb +6 -0
  22. data/lib/arel/engines/sql/compilers/mssql_compiler.rb +46 -0
  23. data/lib/arel/visitors/db2.rb +15 -0
  24. data/lib/arel/visitors/derby.rb +19 -0
  25. data/lib/arel/visitors/hsqldb.rb +24 -0
  26. data/lib/arel/visitors/mssql.rb +44 -0
  27. data/lib/arjdbc.rb +29 -0
  28. data/lib/arjdbc/db2.rb +2 -0
  29. data/lib/arjdbc/db2/adapter.rb +413 -0
  30. data/lib/arjdbc/derby.rb +7 -0
  31. data/lib/{jdbc_adapter/jdbc_derby.rb → arjdbc/derby/adapter.rb} +58 -132
  32. data/lib/arjdbc/derby/connection_methods.rb +18 -0
  33. data/lib/arjdbc/discover.rb +92 -0
  34. data/lib/arjdbc/firebird.rb +2 -0
  35. data/lib/{jdbc_adapter/jdbc_firebird.rb → arjdbc/firebird/adapter.rb} +36 -14
  36. data/lib/arjdbc/h2.rb +4 -0
  37. data/lib/arjdbc/h2/adapter.rb +36 -0
  38. data/lib/arjdbc/h2/connection_methods.rb +12 -0
  39. data/lib/arjdbc/hsqldb.rb +4 -0
  40. data/lib/{jdbc_adapter/jdbc_hsqldb.rb → arjdbc/hsqldb/adapter.rb} +34 -62
  41. data/lib/arjdbc/hsqldb/connection_methods.rb +14 -0
  42. data/lib/arjdbc/informix.rb +3 -0
  43. data/lib/{jdbc_adapter/jdbc_informix.rb → arjdbc/informix/adapter.rb} +10 -19
  44. data/lib/arjdbc/informix/connection_methods.rb +10 -0
  45. data/lib/arjdbc/jdbc.rb +2 -0
  46. data/lib/arjdbc/jdbc/adapter.rb +285 -0
  47. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  48. data/lib/arjdbc/jdbc/callbacks.rb +44 -0
  49. data/lib/arjdbc/jdbc/column.rb +38 -0
  50. data/lib/arjdbc/jdbc/compatibility.rb +51 -0
  51. data/lib/arjdbc/jdbc/connection.rb +128 -0
  52. data/lib/arjdbc/jdbc/connection_methods.rb +16 -0
  53. data/lib/arjdbc/jdbc/core_ext.rb +24 -0
  54. data/lib/arjdbc/jdbc/discover.rb +18 -0
  55. data/lib/arjdbc/jdbc/driver.rb +44 -0
  56. data/lib/arjdbc/jdbc/extension.rb +47 -0
  57. data/lib/arjdbc/jdbc/java.rb +14 -0
  58. data/lib/{jdbc_adapter → arjdbc/jdbc}/jdbc.rake +36 -26
  59. data/lib/{jdbc_adapter → arjdbc/jdbc}/missing_functionality_helper.rb +5 -5
  60. data/lib/arjdbc/jdbc/quoted_primary_key.rb +28 -0
  61. data/lib/arjdbc/jdbc/railtie.rb +9 -0
  62. data/lib/arjdbc/jdbc/rake_tasks.rb +10 -0
  63. data/lib/arjdbc/jdbc/require_driver.rb +16 -0
  64. data/lib/arjdbc/jdbc/type_converter.rb +126 -0
  65. data/lib/arjdbc/mimer.rb +2 -0
  66. data/lib/{jdbc_adapter/jdbc_mimer.rb → arjdbc/mimer/adapter.rb} +17 -16
  67. data/lib/arjdbc/mssql.rb +4 -0
  68. data/lib/arjdbc/mssql/adapter.rb +472 -0
  69. data/lib/arjdbc/mssql/connection_methods.rb +30 -0
  70. data/lib/arjdbc/mssql/limit_helpers.rb +92 -0
  71. data/lib/{jdbc_adapter → arjdbc/mssql}/tsql_helper.rb +2 -1
  72. data/lib/arjdbc/mysql.rb +4 -0
  73. data/lib/arjdbc/mysql/adapter.rb +416 -0
  74. data/lib/arjdbc/mysql/connection_methods.rb +27 -0
  75. data/lib/arjdbc/oracle.rb +3 -0
  76. data/lib/{jdbc_adapter/jdbc_oracle.rb → arjdbc/oracle/adapter.rb} +68 -33
  77. data/lib/arjdbc/oracle/connection_methods.rb +11 -0
  78. data/lib/arjdbc/postgresql.rb +4 -0
  79. data/lib/{jdbc_adapter/jdbc_postgre.rb → arjdbc/postgresql/adapter.rb} +147 -72
  80. data/lib/arjdbc/postgresql/connection_methods.rb +21 -0
  81. data/lib/arjdbc/sqlite3.rb +4 -0
  82. data/lib/arjdbc/sqlite3/adapter.rb +381 -0
  83. data/lib/arjdbc/sqlite3/connection_methods.rb +34 -0
  84. data/lib/arjdbc/sybase.rb +2 -0
  85. data/lib/arjdbc/sybase/adapter.rb +46 -0
  86. data/lib/arjdbc/version.rb +8 -0
  87. data/lib/generators/jdbc/jdbc_generator.rb +9 -0
  88. data/lib/jdbc_adapter.rb +2 -27
  89. data/lib/jdbc_adapter/rake_tasks.rb +3 -10
  90. data/lib/jdbc_adapter/version.rb +3 -5
  91. data/lib/pg.rb +23 -1
  92. data/rails_generators/jdbc_generator.rb +2 -2
  93. data/rails_generators/templates/{jdbc.rb → config/initializers/jdbc.rb} +1 -1
  94. data/rails_generators/templates/{jdbc.rake → lib/tasks/jdbc.rake} +2 -2
  95. data/rakelib/compile.rake +5 -3
  96. data/rakelib/db.rake +19 -0
  97. data/rakelib/package.rake +12 -6
  98. data/rakelib/test.rake +24 -14
  99. data/src/java/{jdbc_adapter/JdbcDerbySpec.java → arjdbc/derby/DerbyModule.java} +63 -34
  100. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +70 -0
  101. data/src/java/{jdbc_adapter/MssqlRubyJdbcConnection.java → arjdbc/informix/InformixRubyJdbcConnection.java} +15 -12
  102. data/src/java/{jdbc_adapter/JdbcAdapterInternalService.java → arjdbc/jdbc/AdapterJavaService.java} +21 -8
  103. data/src/java/{jdbc_adapter → arjdbc/jdbc}/JdbcConnectionFactory.java +6 -6
  104. data/src/java/{jdbc_adapter → arjdbc/jdbc}/RubyJdbcConnection.java +210 -67
  105. data/src/java/arjdbc/jdbc/SQLBlock.java +48 -0
  106. data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +127 -0
  107. data/src/java/{jdbc_adapter/JdbcMySQLSpec.java → arjdbc/mysql/MySQLModule.java} +12 -12
  108. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +87 -0
  109. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +85 -0
  110. data/src/java/{jdbc_adapter/PostgresRubyJdbcConnection.java → arjdbc/postgresql/PostgresqlRubyJdbcConnection.java} +11 -9
  111. data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +64 -0
  112. data/test/abstract_db_create.rb +98 -19
  113. data/test/activerecord/connection_adapters/type_conversion_test.rb +1 -1
  114. data/test/db/db2.rb +4 -2
  115. data/test/db/derby.rb +12 -14
  116. data/test/db/hsqldb.rb +3 -2
  117. data/test/db/jndi_config.rb +22 -12
  118. data/test/db/mssql.rb +5 -5
  119. data/test/db/sqlite3.rb +2 -6
  120. data/test/db2_simple_test.rb +56 -0
  121. data/test/derby_migration_test.rb +50 -3
  122. data/test/derby_simple_test.rb +87 -0
  123. data/test/generic_jdbc_connection_test.rb +21 -1
  124. data/test/h2_simple_test.rb +35 -0
  125. data/test/jdbc_common.rb +4 -5
  126. data/test/jndi_callbacks_test.rb +3 -1
  127. data/test/jndi_test.rb +1 -11
  128. data/test/models/entry.rb +20 -0
  129. data/test/models/mixed_case.rb +7 -2
  130. data/test/models/string_id.rb +18 -0
  131. data/test/mssql_db_create_test.rb +26 -0
  132. data/test/mssql_identity_insert_test.rb +19 -0
  133. data/test/mssql_legacy_types_test.rb +58 -0
  134. data/test/mssql_limit_offset_test.rb +136 -0
  135. data/test/mssql_multibyte_test.rb +18 -0
  136. data/test/mssql_simple_test.rb +49 -0
  137. data/test/mysql_db_create_test.rb +8 -6
  138. data/test/mysql_info_test.rb +123 -0
  139. data/test/mysql_simple_test.rb +19 -1
  140. data/test/oracle_simple_test.rb +9 -20
  141. data/test/oracle_specific_test.rb +83 -0
  142. data/test/pick_rails_version.rb +3 -0
  143. data/test/postgres_db_create_test.rb +11 -0
  144. data/test/postgres_drop_db_test.rb +16 -0
  145. data/test/postgres_mixed_case_test.rb +11 -1
  146. data/test/postgres_nonseq_pkey_test.rb +0 -2
  147. data/test/postgres_schema_search_path_test.rb +44 -0
  148. data/test/postgres_simple_test.rb +53 -0
  149. data/test/postgres_table_alias_length_test.rb +15 -0
  150. data/test/simple.rb +103 -9
  151. data/test/sqlite3_simple_test.rb +1 -0
  152. data/test/sybase_jtds_simple_test.rb +22 -0
  153. metadata +239 -137
  154. data/lib/active_record/connection_adapters/cachedb_adapter.rb +0 -1
  155. data/lib/active_record/connection_adapters/jdbc_adapter_spec.rb +0 -26
  156. data/lib/jdbc_adapter/jdbc_adapter_internal.jar +0 -0
  157. data/lib/jdbc_adapter/jdbc_cachedb.rb +0 -33
  158. data/lib/jdbc_adapter/jdbc_db2.rb +0 -191
  159. data/lib/jdbc_adapter/jdbc_mssql.rb +0 -333
  160. data/lib/jdbc_adapter/jdbc_mysql.rb +0 -236
  161. data/lib/jdbc_adapter/jdbc_sqlite3.rb +0 -379
  162. data/lib/jdbc_adapter/jdbc_sybase.rb +0 -50
  163. data/src/java/jdbc_adapter/SQLBlock.java +0 -27
  164. data/src/java/jdbc_adapter/Sqlite3RubyJdbcConnection.java +0 -41
  165. data/test/cachedb_simple_test.rb +0 -6
  166. data/test/db/cachedb.rb +0 -9
  167. data/test/jdbc_adapter/jdbc_db2_test.rb +0 -26
  168. data/test/jdbc_adapter/jdbc_sybase_test.rb +0 -33
  169. data/test/minirunit.rb +0 -109
  170. data/test/minirunit/testConnect.rb +0 -14
  171. data/test/minirunit/testH2.rb +0 -73
  172. data/test/minirunit/testHsqldb.rb +0 -73
  173. data/test/minirunit/testLoadActiveRecord.rb +0 -3
  174. data/test/minirunit/testMysql.rb +0 -83
  175. data/test/minirunit/testRawSelect.rb +0 -24
@@ -1,13 +1 @@
1
- tried_gem = false
2
- begin
3
- require "jdbc/derby"
4
- rescue LoadError
5
- unless tried_gem
6
- require 'rubygems'
7
- gem "jdbc-derby"
8
- tried_gem = true
9
- retry
10
- end
11
- # trust that the derby jar is already present
12
- end
13
- require 'active_record/connection_adapters/jdbc_adapter'
1
+ require 'arjdbc/derby'
@@ -1,13 +1 @@
1
- tried_gem = false
2
- begin
3
- require "jdbc/h2"
4
- rescue LoadError
5
- unless tried_gem
6
- require 'rubygems'
7
- gem "jdbc-h2"
8
- tried_gem = true
9
- retry
10
- end
11
- # trust that the hsqldb jar is already present
12
- end
13
- require 'active_record/connection_adapters/jdbc_adapter'
1
+ require 'arjdbc/h2'
@@ -1,13 +1 @@
1
- tried_gem = false
2
- begin
3
- require "jdbc/hsqldb"
4
- rescue LoadError
5
- unless tried_gem
6
- require 'rubygems'
7
- gem "jdbc-hsqldb"
8
- tried_gem = true
9
- retry
10
- end
11
- # trust that the hsqldb jar is already present
12
- end
13
- require 'active_record/connection_adapters/jdbc_adapter'
1
+ require 'arjdbc/hsqldb'
@@ -1 +1 @@
1
- require 'active_record/connection_adapters/jdbc_adapter'
1
+ require 'arjdbc/informix'
@@ -1,633 +1 @@
1
- require 'active_record/version'
2
- require 'active_record/connection_adapters/abstract_adapter'
3
- require 'java'
4
- require 'active_record/connection_adapters/jdbc_adapter_spec'
5
- require 'jdbc_adapter/jdbc_adapter_internal'
6
- require 'bigdecimal'
7
-
8
- # AR's 2.2 version of this method is sufficient, but we need it for
9
- # older versions
10
- if ActiveRecord::VERSION::MAJOR <= 2 && ActiveRecord::VERSION::MINOR < 2
11
- module ActiveRecord
12
- module ConnectionAdapters # :nodoc:
13
- module SchemaStatements
14
- # Convert the speficied column type to a SQL string.
15
- def type_to_sql(type, limit = nil, precision = nil, scale = nil)
16
- if native = native_database_types[type]
17
- column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
18
-
19
- if type == :decimal # ignore limit, use precision and scale
20
- scale ||= native[:scale]
21
-
22
- if precision ||= native[:precision]
23
- if scale
24
- column_type_sql << "(#{precision},#{scale})"
25
- else
26
- column_type_sql << "(#{precision})"
27
- end
28
- elsif scale
29
- raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale if specified"
30
- end
31
-
32
- elsif limit ||= native.is_a?(Hash) && native[:limit]
33
- column_type_sql << "(#{limit})"
34
- end
35
-
36
- column_type_sql
37
- else
38
- type
39
- end
40
- end
41
- end
42
- end
43
- end
44
- end
45
-
46
- module JdbcSpec
47
- module ActiveRecordExtensions
48
- def jdbc_connection(config)
49
- ::ActiveRecord::ConnectionAdapters::JdbcAdapter.new(nil, logger, config)
50
- end
51
- alias jndi_connection jdbc_connection
52
-
53
- def embedded_driver(config)
54
- config[:username] ||= "sa"
55
- config[:password] ||= ""
56
- jdbc_connection(config)
57
- end
58
- end
59
- end
60
-
61
- module ActiveRecord
62
- class Base
63
- extend JdbcSpec::ActiveRecordExtensions
64
-
65
- alias :attributes_with_quotes_pre_oracle :attributes_with_quotes
66
- def attributes_with_quotes(include_primary_key = true, *args) #:nodoc:
67
- aq = attributes_with_quotes_pre_oracle(include_primary_key, *args)
68
- if connection.class == ConnectionAdapters::JdbcAdapter && (connection.is_a?(JdbcSpec::Oracle) || connection.is_a?(JdbcSpec::Mimer))
69
- aq[self.class.primary_key] = "?" if include_primary_key && aq[self.class.primary_key].nil?
70
- end
71
- aq
72
- end
73
- end
74
-
75
- module ConnectionAdapters
76
- module Java
77
- Class = java.lang.Class
78
- URL = java.net.URL
79
- URLClassLoader = java.net.URLClassLoader
80
- end
81
-
82
- module Jdbc
83
- Mutex = java.lang.Object.new
84
- DriverManager = java.sql.DriverManager
85
- Statement = java.sql.Statement
86
- Types = java.sql.Types
87
-
88
- # some symbolic constants for the benefit of the JDBC-based
89
- # JdbcConnection#indexes method
90
- module IndexMetaData
91
- INDEX_NAME = 6
92
- NON_UNIQUE = 4
93
- TABLE_NAME = 3
94
- COLUMN_NAME = 9
95
- end
96
-
97
- module TableMetaData
98
- TABLE_CAT = 1
99
- TABLE_SCHEM = 2
100
- TABLE_NAME = 3
101
- TABLE_TYPE = 4
102
- end
103
-
104
- module PrimaryKeyMetaData
105
- COLUMN_NAME = 4
106
- end
107
-
108
- end
109
-
110
- # I want to use JDBC's DatabaseMetaData#getTypeInfo to choose the best native types to
111
- # use for ActiveRecord's Adapter#native_database_types in a database-independent way,
112
- # but apparently a database driver can return multiple types for a given
113
- # java.sql.Types constant. So this type converter uses some heuristics to try to pick
114
- # the best (most common) type to use. It's not great, it would be better to just
115
- # delegate to each database's existin AR adapter's native_database_types method, but I
116
- # wanted to try to do this in a way that didn't pull in all the other adapters as
117
- # dependencies. Suggestions appreciated.
118
- class JdbcTypeConverter
119
- # The basic ActiveRecord types, mapped to an array of procs that are used to #select
120
- # the best type. The procs are used as selectors in order until there is only one
121
- # type left. If all the selectors are applied and there is still more than one
122
- # type, an exception will be raised.
123
- AR_TO_JDBC_TYPES = {
124
- :string => [ lambda {|r| Jdbc::Types::VARCHAR == r['data_type'].to_i},
125
- lambda {|r| r['type_name'] =~ /^varchar/i},
126
- lambda {|r| r['type_name'] =~ /^varchar$/i},
127
- lambda {|r| r['type_name'] =~ /varying/i}],
128
- :text => [ lambda {|r| [Jdbc::Types::LONGVARCHAR, Jdbc::Types::CLOB].include?(r['data_type'].to_i)},
129
- lambda {|r| r['type_name'] =~ /^text$/i}, # For Informix
130
- lambda {|r| r['type_name'] =~ /^(text|clob)$/i},
131
- lambda {|r| r['type_name'] =~ /^character large object$/i},
132
- lambda {|r| r['sql_data_type'] == 2005}],
133
- :integer => [ lambda {|r| Jdbc::Types::INTEGER == r['data_type'].to_i},
134
- lambda {|r| r['type_name'] =~ /^integer$/i},
135
- lambda {|r| r['type_name'] =~ /^int4$/i},
136
- lambda {|r| r['type_name'] =~ /^int$/i}],
137
- :decimal => [ lambda {|r| Jdbc::Types::DECIMAL == r['data_type'].to_i},
138
- lambda {|r| r['type_name'] =~ /^decimal$/i},
139
- lambda {|r| r['type_name'] =~ /^numeric$/i},
140
- lambda {|r| r['type_name'] =~ /^number$/i},
141
- lambda {|r| r['type_name'] =~ /^real$/i},
142
- lambda {|r| r['precision'] == '38'},
143
- lambda {|r| r['data_type'] == '2'}],
144
- :float => [ lambda {|r| [Jdbc::Types::FLOAT,Jdbc::Types::DOUBLE, Jdbc::Types::REAL].include?(r['data_type'].to_i)},
145
- lambda {|r| r['data_type'].to_i == Jdbc::Types::REAL}, #Prefer REAL to DOUBLE for Postgresql
146
- lambda {|r| r['type_name'] =~ /^float/i},
147
- lambda {|r| r['type_name'] =~ /^double$/i},
148
- lambda {|r| r['type_name'] =~ /^real$/i},
149
- lambda {|r| r['precision'] == '15'}],
150
- :datetime => [ lambda {|r| Jdbc::Types::TIMESTAMP == r['data_type'].to_i},
151
- lambda {|r| r['type_name'] =~ /^datetime$/i},
152
- lambda {|r| r['type_name'] =~ /^timestamp$/i},
153
- lambda {|r| r['type_name'] =~ /^date/i},
154
- lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver
155
- :timestamp => [ lambda {|r| Jdbc::Types::TIMESTAMP == r['data_type'].to_i},
156
- lambda {|r| r['type_name'] =~ /^timestamp$/i},
157
- lambda {|r| r['type_name'] =~ /^datetime/i},
158
- lambda {|r| r['type_name'] =~ /^date/i},
159
- lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver
160
- :time => [ lambda {|r| Jdbc::Types::TIME == r['data_type'].to_i},
161
- lambda {|r| r['type_name'] =~ /^time$/i},
162
- lambda {|r| r['type_name'] =~ /^datetime/i}, # For Informix
163
- lambda {|r| r['type_name'] =~ /^date/i},
164
- lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver
165
- :date => [ lambda {|r| Jdbc::Types::DATE == r['data_type'].to_i},
166
- lambda {|r| r['type_name'] =~ /^date$/i},
167
- lambda {|r| r['type_name'] =~ /^date/i},
168
- lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver3
169
- :binary => [ lambda {|r| [Jdbc::Types::LONGVARBINARY,Jdbc::Types::BINARY,Jdbc::Types::BLOB].include?(r['data_type'].to_i)},
170
- lambda {|r| r['type_name'] =~ /^blob/i},
171
- lambda {|r| r['type_name'] =~ /sub_type 0$/i}, # For FireBird
172
- lambda {|r| r['type_name'] =~ /^varbinary$/i}, # We want this sucker for Mimer
173
- lambda {|r| r['type_name'] =~ /^binary$/i}, ],
174
- :boolean => [ lambda {|r| [Jdbc::Types::TINYINT].include?(r['data_type'].to_i)},
175
- lambda {|r| r['type_name'] =~ /^bool/i},
176
- lambda {|r| r['data_type'] == '-7'},
177
- lambda {|r| r['type_name'] =~ /^tinyint$/i},
178
- lambda {|r| r['type_name'] =~ /^decimal$/i},
179
- lambda {|r| r['type_name'] =~ /^integer$/i}]
180
- }
181
-
182
- def initialize(types)
183
- @types = types
184
- @types.each {|t| t['type_name'] ||= t['local_type_name']} # Sybase driver seems to want 'local_type_name'
185
- end
186
-
187
- def choose_best_types
188
- type_map = {}
189
- @types.each do |row|
190
- name = row['type_name'].downcase
191
- k = name.to_sym
192
- type_map[k] = { :name => name }
193
- type_map[k][:limit] = row['precision'].to_i if row['precision']
194
- end
195
-
196
- AR_TO_JDBC_TYPES.keys.each do |k|
197
- typerow = choose_type(k)
198
- type_map[k] = { :name => typerow['type_name'].downcase }
199
- case k
200
- when :integer, :string, :decimal
201
- type_map[k][:limit] = typerow['precision'] && typerow['precision'].to_i
202
- when :boolean
203
- type_map[k][:limit] = 1
204
- end
205
- end
206
- type_map
207
- end
208
-
209
- def choose_type(ar_type)
210
- procs = AR_TO_JDBC_TYPES[ar_type]
211
- types = @types
212
- procs.each do |p|
213
- new_types = types.reject {|r| r["data_type"].to_i == Jdbc::Types::OTHER}
214
- new_types = new_types.select(&p)
215
- new_types = new_types.inject([]) do |typs,t|
216
- typs << t unless typs.detect {|el| el['type_name'] == t['type_name']}
217
- typs
218
- end
219
- return new_types.first if new_types.length == 1
220
- types = new_types if new_types.length > 0
221
- end
222
- raise "unable to choose type for #{ar_type} from:\n#{types.collect{|t| t['type_name']}.inspect}"
223
- end
224
- end
225
-
226
- class JdbcDriver
227
- def initialize(name)
228
- @name = name
229
- end
230
-
231
- def driver_class
232
- @driver_class ||= begin
233
- driver_class_const = (@name[0...1].capitalize + @name[1..@name.length]).gsub(/\./, '_')
234
- Jdbc::Mutex.synchronized do
235
- unless Jdbc.const_defined?(driver_class_const)
236
- driver_class_name = @name
237
- Jdbc.module_eval do
238
- include_class(driver_class_name) { driver_class_const }
239
- end
240
- end
241
- end
242
- driver_class = Jdbc.const_get(driver_class_const)
243
- raise "You specify a driver for your JDBC connection" unless driver_class
244
- driver_class
245
- end
246
- end
247
-
248
- def load
249
- Jdbc::DriverManager.registerDriver(create)
250
- end
251
-
252
- def connection(url, user, pass)
253
- Jdbc::DriverManager.getConnection(url, user, pass)
254
- rescue
255
- # bypass DriverManager to get around problem with dynamically loaded jdbc drivers
256
- props = java.util.Properties.new
257
- props.setProperty("user", user)
258
- props.setProperty("password", pass)
259
- create.connect(url, props)
260
- end
261
-
262
- def create
263
- driver_class.new
264
- end
265
- end
266
-
267
- class JdbcColumn < Column
268
- attr_writer :limit, :precision
269
-
270
- COLUMN_TYPES = ::JdbcSpec.constants.map{|c|
271
- ::JdbcSpec.const_get c }.select{ |c|
272
- c.respond_to? :column_selector }.map{|c|
273
- c.column_selector }.inject({}) { |h,val|
274
- h[val[0]] = val[1]; h }
275
-
276
- def initialize(config, name, default, *args)
277
- dialect = config[:dialect] || config[:driver]
278
- for reg, func in COLUMN_TYPES
279
- if reg === dialect.to_s
280
- func.call(config,self)
281
- end
282
- end
283
- super(name,default_value(default),*args)
284
- init_column(name, default, *args)
285
- end
286
-
287
- def init_column(*args)
288
- end
289
-
290
- def default_value(val)
291
- val
292
- end
293
- end
294
-
295
- include_class "jdbc_adapter.JdbcConnectionFactory"
296
-
297
- class JdbcConnection
298
- attr_reader :adapter, :connection_factory
299
-
300
- # @native_database_types - setup properly by adapter= versus set_native_database_types.
301
- # This contains type information for the adapter. Individual adapters can make tweaks
302
- # by defined modify_types
303
- #
304
- # @native_types - This is the default type settings sans any modifications by the
305
- # individual adapter. My guess is that if we loaded two adapters of different types
306
- # then this is used as a base to be tweaked by each adapter to create @native_database_types
307
-
308
- def initialize(config)
309
- @config = config.symbolize_keys!
310
- @config[:retry_count] ||= 5
311
- @config[:connection_alive_sql] ||= "select 1"
312
- if @config[:jndi]
313
- begin
314
- configure_jndi
315
- rescue => e
316
- warn "JNDI data source unavailable: #{e.message}; trying straight JDBC"
317
- configure_jdbc
318
- end
319
- else
320
- configure_jdbc
321
- end
322
- connection # force the connection to load
323
- set_native_database_types
324
- @stmts = {}
325
- rescue Exception => e
326
- raise "The driver encountered an error: #{e}"
327
- end
328
-
329
- def adapter=(adapter)
330
- @adapter = adapter
331
- @native_database_types = dup_native_types
332
- @adapter.modify_types(@native_database_types)
333
- end
334
-
335
- # Duplicate all native types into new hash structure so it can be modified
336
- # without destroying original structure.
337
- def dup_native_types
338
- types = {}
339
- @native_types.each_pair do |k, v|
340
- types[k] = v.inject({}) do |memo, kv|
341
- memo[kv.first] = begin kv.last.dup rescue kv.last end
342
- memo
343
- end
344
- end
345
- types
346
- end
347
- private :dup_native_types
348
-
349
- def jndi_connection?
350
- @jndi_connection
351
- end
352
-
353
- private
354
- def configure_jndi
355
- jndi = @config[:jndi].to_s
356
- ctx = javax.naming.InitialContext.new
357
- ds = ctx.lookup(jndi)
358
- @connection_factory = JdbcConnectionFactory.impl do
359
- ds.connection
360
- end
361
- unless @config[:driver]
362
- @config[:driver] = connection.meta_data.connection.java_class.name
363
- end
364
- @jndi_connection = true
365
- end
366
-
367
- def configure_jdbc
368
- driver = @config[:driver].to_s
369
- user = @config[:username].to_s
370
- pass = @config[:password].to_s
371
- url = @config[:url].to_s
372
-
373
- unless driver && url
374
- raise ::ActiveRecord::ConnectionFailed, "jdbc adapter requires driver class and url"
375
- end
376
-
377
- jdbc_driver = JdbcDriver.new(driver)
378
- jdbc_driver.load
379
- @connection_factory = JdbcConnectionFactory.impl do
380
- jdbc_driver.connection(url, user, pass)
381
- end
382
- end
383
- end
384
-
385
- class JdbcAdapter < AbstractAdapter
386
- module ShadowCoreMethods
387
- def alias_chained_method(meth, feature, target)
388
- if instance_methods.include?("#{meth}_without_#{feature}")
389
- alias_method "#{meth}_without_#{feature}".to_sym, target
390
- else
391
- alias_method meth, target
392
- end
393
- end
394
- end
395
-
396
- module CompatibilityMethods
397
- def self.needed?(base)
398
- !base.instance_methods.include?("quote_table_name")
399
- end
400
-
401
- def quote_table_name(name)
402
- quote_column_name(name)
403
- end
404
- end
405
-
406
- module ConnectionPoolCallbacks
407
- def self.included(base)
408
- base.checkin :on_checkin
409
- base.checkout :on_checkout
410
- end
411
-
412
- def self.needed?
413
- ActiveRecord::Base.respond_to?(:connection_pool)
414
- end
415
-
416
- def on_checkin
417
- # default implementation does nothing
418
- end
419
-
420
- def on_checkout
421
- # default implementation does nothing
422
- end
423
- end
424
-
425
- module JndiConnectionPoolCallbacks
426
- def self.prepare(adapter, conn)
427
- if ActiveRecord::Base.respond_to?(:connection_pool) && conn.jndi_connection?
428
- adapter.extend self
429
- conn.disconnect! # disconnect initial connection in JdbcConnection#initialize
430
- end
431
- end
432
-
433
- def on_checkin
434
- disconnect!
435
- end
436
-
437
- def on_checkout
438
- reconnect!
439
- end
440
- end
441
-
442
- extend ShadowCoreMethods
443
- include CompatibilityMethods if CompatibilityMethods.needed?(self)
444
- include ConnectionPoolCallbacks if ConnectionPoolCallbacks.needed?
445
-
446
- attr_reader :config
447
-
448
- def initialize(connection, logger, config)
449
- @config = config
450
- spec = adapter_spec config
451
- unless connection
452
- connection_class = jdbc_connection_class spec
453
- connection = connection_class.new config
454
- end
455
- super(connection, logger)
456
- extend spec if spec
457
- connection.adapter = self
458
- JndiConnectionPoolCallbacks.prepare(self, connection)
459
- end
460
-
461
- def jdbc_connection_class(spec)
462
- connection_class = spec.jdbc_connection_class if spec && spec.respond_to?(:jdbc_connection_class)
463
- connection_class = ::ActiveRecord::ConnectionAdapters::JdbcConnection unless connection_class
464
- connection_class
465
- end
466
-
467
- # Locate specialized adapter specification if one exists based on config data
468
- def adapter_spec(config)
469
- dialect = (config[:dialect] || config[:driver]).to_s
470
- ::JdbcSpec.constants.map { |name| ::JdbcSpec.const_get name }.each do |constant|
471
- if constant.respond_to? :adapter_matcher
472
- spec = constant.adapter_matcher(dialect, config)
473
- return spec if spec
474
- end
475
- end
476
- nil
477
- end
478
-
479
- def modify_types(tp)
480
- tp
481
- end
482
-
483
- def adapter_name #:nodoc:
484
- 'JDBC'
485
- end
486
-
487
- def supports_migrations?
488
- true
489
- end
490
-
491
- def native_database_types #:nodoc:
492
- @connection.native_database_types
493
- end
494
-
495
- def database_name #:nodoc:
496
- @connection.database_name
497
- end
498
-
499
- def native_sql_to_type(tp)
500
- if /^(.*?)\(([0-9]+)\)/ =~ tp
501
- tname = $1
502
- limit = $2.to_i
503
- ntype = native_database_types
504
- if ntype[:primary_key] == tp
505
- return :primary_key,nil
506
- else
507
- ntype.each do |name,val|
508
- if name == :primary_key
509
- next
510
- end
511
- if val[:name].downcase == tname.downcase && (val[:limit].nil? || val[:limit].to_i == limit)
512
- return name,limit
513
- end
514
- end
515
- end
516
- elsif /^(.*?)/ =~ tp
517
- tname = $1
518
- ntype = native_database_types
519
- if ntype[:primary_key] == tp
520
- return :primary_key,nil
521
- else
522
- ntype.each do |name,val|
523
- if val[:name].downcase == tname.downcase && val[:limit].nil?
524
- return name,nil
525
- end
526
- end
527
- end
528
- else
529
- return :string,255
530
- end
531
- return nil,nil
532
- end
533
-
534
- def reconnect!
535
- @connection.reconnect!
536
- @connection
537
- end
538
-
539
- def disconnect!
540
- @connection.disconnect!
541
- end
542
-
543
- def jdbc_select_all(sql, name = nil)
544
- select(sql, name)
545
- end
546
- alias_chained_method :select_all, :query_cache, :jdbc_select_all
547
-
548
- def select_rows(sql, name = nil)
549
- rows = []
550
- select(sql, name).each {|row| rows << row.values }
551
- rows
552
- end
553
-
554
- def select_one(sql, name = nil)
555
- select(sql, name).first
556
- end
557
-
558
- def execute(sql, name = nil)
559
- log(sql, name) do
560
- _execute(sql,name)
561
- end
562
- end
563
-
564
- # we need to do it this way, to allow Rails stupid tests to always work
565
- # even if we define a new execute method. Instead of mixing in a new
566
- # execute, an _execute should be mixed in.
567
- def _execute(sql, name = nil)
568
- if JdbcConnection::select?(sql)
569
- @connection.execute_query(sql)
570
- elsif JdbcConnection::insert?(sql)
571
- @connection.execute_insert(sql)
572
- else
573
- @connection.execute_update(sql)
574
- end
575
- end
576
-
577
- def jdbc_update(sql, name = nil) #:nodoc:
578
- execute(sql, name)
579
- end
580
- alias_chained_method :update, :query_dirty, :jdbc_update
581
-
582
- def jdbc_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
583
- id = execute(sql, name = nil)
584
- id_value || id
585
- end
586
- alias_chained_method :insert, :query_dirty, :jdbc_insert
587
-
588
- def jdbc_columns(table_name, name = nil)
589
- @connection.columns(table_name.to_s)
590
- end
591
- alias_chained_method :columns, :query_cache, :jdbc_columns
592
-
593
- def tables
594
- @connection.tables
595
- end
596
-
597
- def indexes(table_name, name = nil, schema_name = nil)
598
- @connection.indexes(table_name, name, schema_name)
599
- end
600
-
601
- def begin_db_transaction
602
- @connection.begin
603
- end
604
-
605
- def commit_db_transaction
606
- @connection.commit
607
- end
608
-
609
- def rollback_db_transaction
610
- @connection.rollback
611
- end
612
-
613
- def write_large_object(*args)
614
- @connection.write_large_object(*args)
615
- end
616
-
617
- def pk_and_sequence_for(table)
618
- result_set = @connection.connection.get_meta_data.get_primary_keys(nil, nil, table)
619
- if result_set.next
620
- keys = [result_set.getString("COLUMN_NAME"), nil]
621
- end
622
- keys.blank? ? nil : keys
623
- ensure
624
- result_set.close
625
- end
626
-
627
- private
628
- def select(sql, name=nil)
629
- execute(sql,name)
630
- end
631
- end
632
- end
633
- end
1
+ require 'arjdbc/jdbc'