activerecord-jdbc-alt-adapter 50.3.0-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 (198) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/.travis.yml +100 -0
  4. data/.yardopts +4 -0
  5. data/CONTRIBUTING.md +50 -0
  6. data/Gemfile +92 -0
  7. data/History.md +1191 -0
  8. data/LICENSE.txt +26 -0
  9. data/README.md +240 -0
  10. data/RUNNING_TESTS.md +127 -0
  11. data/Rakefile +336 -0
  12. data/Rakefile.jdbc +20 -0
  13. data/activerecord-jdbc-adapter.gemspec +55 -0
  14. data/activerecord-jdbc-alt-adapter.gemspec +56 -0
  15. data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
  16. data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
  17. data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
  18. data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
  19. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
  20. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
  21. data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
  22. data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
  23. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
  24. data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
  25. data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
  26. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
  27. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
  28. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
  29. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
  30. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
  31. data/lib/activerecord-jdbc-adapter.rb +1 -0
  32. data/lib/arel/visitors/compat.rb +60 -0
  33. data/lib/arel/visitors/db2.rb +137 -0
  34. data/lib/arel/visitors/derby.rb +112 -0
  35. data/lib/arel/visitors/firebird.rb +79 -0
  36. data/lib/arel/visitors/h2.rb +25 -0
  37. data/lib/arel/visitors/hsqldb.rb +32 -0
  38. data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
  39. data/lib/arel/visitors/sql_server.rb +225 -0
  40. data/lib/arel/visitors/sql_server/ng42.rb +294 -0
  41. data/lib/arel/visitors/sqlserver.rb +214 -0
  42. data/lib/arjdbc.rb +19 -0
  43. data/lib/arjdbc/abstract/connection_management.rb +35 -0
  44. data/lib/arjdbc/abstract/core.rb +74 -0
  45. data/lib/arjdbc/abstract/database_statements.rb +64 -0
  46. data/lib/arjdbc/abstract/statement_cache.rb +58 -0
  47. data/lib/arjdbc/abstract/transaction_support.rb +86 -0
  48. data/lib/arjdbc/db2.rb +4 -0
  49. data/lib/arjdbc/db2/adapter.rb +789 -0
  50. data/lib/arjdbc/db2/as400.rb +130 -0
  51. data/lib/arjdbc/db2/column.rb +167 -0
  52. data/lib/arjdbc/db2/connection_methods.rb +44 -0
  53. data/lib/arjdbc/derby.rb +3 -0
  54. data/lib/arjdbc/derby/active_record_patch.rb +13 -0
  55. data/lib/arjdbc/derby/adapter.rb +540 -0
  56. data/lib/arjdbc/derby/connection_methods.rb +20 -0
  57. data/lib/arjdbc/derby/schema_creation.rb +15 -0
  58. data/lib/arjdbc/discover.rb +104 -0
  59. data/lib/arjdbc/firebird.rb +4 -0
  60. data/lib/arjdbc/firebird/adapter.rb +434 -0
  61. data/lib/arjdbc/firebird/connection_methods.rb +23 -0
  62. data/lib/arjdbc/h2.rb +3 -0
  63. data/lib/arjdbc/h2/adapter.rb +303 -0
  64. data/lib/arjdbc/h2/connection_methods.rb +27 -0
  65. data/lib/arjdbc/hsqldb.rb +3 -0
  66. data/lib/arjdbc/hsqldb/adapter.rb +297 -0
  67. data/lib/arjdbc/hsqldb/connection_methods.rb +28 -0
  68. data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
  69. data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
  70. data/lib/arjdbc/informix.rb +5 -0
  71. data/lib/arjdbc/informix/adapter.rb +162 -0
  72. data/lib/arjdbc/informix/connection_methods.rb +9 -0
  73. data/lib/arjdbc/jdbc.rb +59 -0
  74. data/lib/arjdbc/jdbc/adapter.rb +475 -0
  75. data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
  76. data/lib/arjdbc/jdbc/base_ext.rb +15 -0
  77. data/lib/arjdbc/jdbc/callbacks.rb +53 -0
  78. data/lib/arjdbc/jdbc/column.rb +97 -0
  79. data/lib/arjdbc/jdbc/connection.rb +14 -0
  80. data/lib/arjdbc/jdbc/connection_methods.rb +37 -0
  81. data/lib/arjdbc/jdbc/error.rb +65 -0
  82. data/lib/arjdbc/jdbc/extension.rb +59 -0
  83. data/lib/arjdbc/jdbc/java.rb +13 -0
  84. data/lib/arjdbc/jdbc/railtie.rb +2 -0
  85. data/lib/arjdbc/jdbc/rake_tasks.rb +3 -0
  86. data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -0
  87. data/lib/arjdbc/jdbc/type_cast.rb +166 -0
  88. data/lib/arjdbc/jdbc/type_converter.rb +142 -0
  89. data/lib/arjdbc/mssql.rb +7 -0
  90. data/lib/arjdbc/mssql/adapter.rb +384 -0
  91. data/lib/arjdbc/mssql/column.rb +29 -0
  92. data/lib/arjdbc/mssql/connection_methods.rb +79 -0
  93. data/lib/arjdbc/mssql/database_statements.rb +134 -0
  94. data/lib/arjdbc/mssql/errors.rb +6 -0
  95. data/lib/arjdbc/mssql/explain_support.rb +129 -0
  96. data/lib/arjdbc/mssql/extensions.rb +36 -0
  97. data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
  98. data/lib/arjdbc/mssql/lock_methods.rb +77 -0
  99. data/lib/arjdbc/mssql/old_adapter.rb +804 -0
  100. data/lib/arjdbc/mssql/old_column.rb +200 -0
  101. data/lib/arjdbc/mssql/quoting.rb +101 -0
  102. data/lib/arjdbc/mssql/schema_creation.rb +31 -0
  103. data/lib/arjdbc/mssql/schema_definitions.rb +74 -0
  104. data/lib/arjdbc/mssql/schema_statements.rb +329 -0
  105. data/lib/arjdbc/mssql/transaction.rb +69 -0
  106. data/lib/arjdbc/mssql/types.rb +52 -0
  107. data/lib/arjdbc/mssql/types/binary_types.rb +33 -0
  108. data/lib/arjdbc/mssql/types/date_and_time_types.rb +134 -0
  109. data/lib/arjdbc/mssql/types/deprecated_types.rb +40 -0
  110. data/lib/arjdbc/mssql/types/numeric_types.rb +71 -0
  111. data/lib/arjdbc/mssql/types/string_types.rb +56 -0
  112. data/lib/arjdbc/mssql/utils.rb +66 -0
  113. data/lib/arjdbc/mysql.rb +3 -0
  114. data/lib/arjdbc/mysql/adapter.rb +140 -0
  115. data/lib/arjdbc/mysql/connection_methods.rb +166 -0
  116. data/lib/arjdbc/oracle/adapter.rb +863 -0
  117. data/lib/arjdbc/postgresql.rb +3 -0
  118. data/lib/arjdbc/postgresql/adapter.rb +687 -0
  119. data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
  120. data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
  121. data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
  122. data/lib/arjdbc/postgresql/base/pgconn.rb +11 -0
  123. data/lib/arjdbc/postgresql/column.rb +51 -0
  124. data/lib/arjdbc/postgresql/connection_methods.rb +67 -0
  125. data/lib/arjdbc/postgresql/name.rb +24 -0
  126. data/lib/arjdbc/postgresql/oid_types.rb +266 -0
  127. data/lib/arjdbc/railtie.rb +11 -0
  128. data/lib/arjdbc/sqlite3.rb +3 -0
  129. data/lib/arjdbc/sqlite3/adapter.rb +678 -0
  130. data/lib/arjdbc/sqlite3/connection_methods.rb +59 -0
  131. data/lib/arjdbc/sybase.rb +2 -0
  132. data/lib/arjdbc/sybase/adapter.rb +47 -0
  133. data/lib/arjdbc/tasks.rb +13 -0
  134. data/lib/arjdbc/tasks/database_tasks.rb +31 -0
  135. data/lib/arjdbc/tasks/databases.rake +48 -0
  136. data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
  137. data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
  138. data/lib/arjdbc/tasks/h2_database_tasks.rb +31 -0
  139. data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
  140. data/lib/arjdbc/tasks/jdbc_database_tasks.rb +169 -0
  141. data/lib/arjdbc/tasks/mssql_database_tasks.rb +46 -0
  142. data/lib/arjdbc/util/quoted_cache.rb +60 -0
  143. data/lib/arjdbc/util/serialized_attributes.rb +98 -0
  144. data/lib/arjdbc/util/table_copier.rb +110 -0
  145. data/lib/arjdbc/version.rb +3 -0
  146. data/lib/generators/jdbc/USAGE +9 -0
  147. data/lib/generators/jdbc/jdbc_generator.rb +17 -0
  148. data/lib/jdbc_adapter.rb +2 -0
  149. data/lib/jdbc_adapter/rake_tasks.rb +4 -0
  150. data/lib/jdbc_adapter/version.rb +4 -0
  151. data/pom.xml +114 -0
  152. data/rails_generators/jdbc_generator.rb +15 -0
  153. data/rails_generators/templates/config/initializers/jdbc.rb +10 -0
  154. data/rails_generators/templates/lib/tasks/jdbc.rake +11 -0
  155. data/rakelib/01-tomcat.rake +51 -0
  156. data/rakelib/02-test.rake +132 -0
  157. data/rakelib/bundler_ext.rb +11 -0
  158. data/rakelib/db.rake +75 -0
  159. data/rakelib/rails.rake +223 -0
  160. data/src/java/arjdbc/ArJdbcModule.java +276 -0
  161. data/src/java/arjdbc/db2/DB2Module.java +76 -0
  162. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +126 -0
  163. data/src/java/arjdbc/derby/DerbyModule.java +178 -0
  164. data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +152 -0
  165. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +174 -0
  166. data/src/java/arjdbc/h2/H2Module.java +50 -0
  167. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +85 -0
  168. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +73 -0
  169. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +75 -0
  170. data/src/java/arjdbc/jdbc/AdapterJavaService.java +43 -0
  171. data/src/java/arjdbc/jdbc/Callable.java +44 -0
  172. data/src/java/arjdbc/jdbc/ConnectionFactory.java +45 -0
  173. data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +156 -0
  174. data/src/java/arjdbc/jdbc/DriverConnectionFactory.java +63 -0
  175. data/src/java/arjdbc/jdbc/DriverWrapper.java +119 -0
  176. data/src/java/arjdbc/jdbc/JdbcResult.java +130 -0
  177. data/src/java/arjdbc/jdbc/RubyConnectionFactory.java +61 -0
  178. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +3979 -0
  179. data/src/java/arjdbc/mssql/MSSQLModule.java +90 -0
  180. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +508 -0
  181. data/src/java/arjdbc/mysql/MySQLModule.java +152 -0
  182. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +294 -0
  183. data/src/java/arjdbc/oracle/OracleModule.java +80 -0
  184. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +455 -0
  185. data/src/java/arjdbc/postgresql/ByteaUtils.java +157 -0
  186. data/src/java/arjdbc/postgresql/PgDateTimeUtils.java +52 -0
  187. data/src/java/arjdbc/postgresql/PostgreSQLModule.java +77 -0
  188. data/src/java/arjdbc/postgresql/PostgreSQLResult.java +192 -0
  189. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +948 -0
  190. data/src/java/arjdbc/sqlite3/SQLite3Module.java +73 -0
  191. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +525 -0
  192. data/src/java/arjdbc/util/CallResultSet.java +826 -0
  193. data/src/java/arjdbc/util/DateTimeUtils.java +699 -0
  194. data/src/java/arjdbc/util/ObjectSupport.java +65 -0
  195. data/src/java/arjdbc/util/QuotingUtils.java +137 -0
  196. data/src/java/arjdbc/util/StringCache.java +63 -0
  197. data/src/java/arjdbc/util/StringHelper.java +145 -0
  198. metadata +269 -0
@@ -0,0 +1,214 @@
1
+ # NOTE: this code was take from the **sqlserver** adapter and adapted to work
2
+ # with this adapter.
3
+ #
4
+ module Arel
5
+ module Visitors
6
+ class SQLServer < Arel::Visitors::ToSql
7
+
8
+ OFFSET = " OFFSET "
9
+ ROWS = " ROWS"
10
+ FETCH = " FETCH NEXT "
11
+ FETCH0 = " FETCH FIRST (SELECT 0) "
12
+ ROWS_ONLY = " ROWS ONLY"
13
+
14
+
15
+ private
16
+
17
+ # SQLServer ToSql/Visitor (Overides)
18
+
19
+ def visit_Arel_Nodes_BindParam o, collector
20
+ # collector.add_bind(o) { |i| "@#{i-1}" }
21
+ collector.add_bind(o) { |i| '?' }
22
+ end
23
+
24
+ def visit_Arel_Nodes_Bin o, collector
25
+ visit o.expr, collector
26
+ collector << " #{ActiveRecord::ConnectionAdapters::MSSQLAdapter.cs_equality_operator} "
27
+ end
28
+
29
+ def visit_Arel_Nodes_UpdateStatement(o, a)
30
+ if o.orders.any? && o.limit.nil?
31
+ o.limit = Nodes::Limit.new(9_223_372_036_854_775_807)
32
+ end
33
+ super
34
+ end
35
+
36
+ def visit_Arel_Nodes_Lock o, collector
37
+ o.expr = Arel.sql('WITH(UPDLOCK)') if o.expr.to_s =~ /FOR UPDATE/
38
+ collector << SPACE
39
+ visit o.expr, collector
40
+ end
41
+
42
+ def visit_Arel_Nodes_Offset o, collector
43
+ collector << OFFSET
44
+ visit o.expr, collector
45
+ collector << ROWS
46
+ end
47
+
48
+ def visit_Arel_Nodes_Limit o, collector
49
+ if node_value(o) == 0
50
+ collector << FETCH0
51
+ collector << ROWS_ONLY
52
+ else
53
+ collector << FETCH
54
+ visit o.expr, collector
55
+ collector << ROWS_ONLY
56
+ end
57
+ end
58
+
59
+ def visit_Arel_Nodes_SelectStatement o, collector
60
+ @select_statement = o
61
+ distinct_One_As_One_Is_So_Not_Fetch o
62
+ if o.with
63
+ collector = visit o.with, collector
64
+ collector << SPACE
65
+ end
66
+ collector = o.cores.inject(collector) { |c,x|
67
+ visit_Arel_Nodes_SelectCore(x, c)
68
+ }
69
+ collector = visit_Orders_And_Let_Fetch_Happen o, collector
70
+ collector = visit_Make_Fetch_Happen o, collector
71
+ collector
72
+ ensure
73
+ @select_statement = nil
74
+ end
75
+
76
+ def visit_Arel_Table o, collector
77
+ # Apparently, o.engine.connection can actually be a different adapter
78
+ # than sqlserver. Can be removed if fixed in ActiveRecord. See:
79
+ # github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/450
80
+ table_name = begin
81
+ if o.class.engine.connection.respond_to?(:sqlserver?) && o.class.engine.connection.database_prefix_remote_server?
82
+ remote_server_table_name(o)
83
+ else
84
+ quote_table_name(o.name)
85
+ end
86
+ rescue Exception => e
87
+ quote_table_name(o.name)
88
+ end
89
+ if o.table_alias
90
+ collector << "#{table_name} #{quote_table_name o.table_alias}"
91
+ else
92
+ collector << table_name
93
+ end
94
+ end
95
+
96
+ def visit_Arel_Nodes_JoinSource o, collector
97
+ if o.left
98
+ collector = visit o.left, collector
99
+ collector = visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector
100
+ end
101
+ if o.right.any?
102
+ collector << " " if o.left
103
+ collector = inject_join o.right, collector, ' '
104
+ end
105
+ collector
106
+ end
107
+
108
+ def visit_Arel_Nodes_OuterJoin o, collector
109
+ collector << "LEFT OUTER JOIN "
110
+ collector = visit o.left, collector
111
+ collector = visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, space: true
112
+ collector << " "
113
+ visit o.right, collector
114
+ end
115
+
116
+ # SQLServer ToSql/Visitor (Additions)
117
+
118
+ def visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, options = {}
119
+ if select_statement_lock?
120
+ collector = visit @select_statement.lock, collector
121
+ collector << SPACE if options[:space]
122
+ end
123
+ collector
124
+ end
125
+
126
+ def visit_Orders_And_Let_Fetch_Happen o, collector
127
+ make_Fetch_Possible_And_Deterministic o
128
+ unless o.orders.empty?
129
+ collector << SPACE
130
+ collector << ORDER_BY
131
+ len = o.orders.length - 1
132
+ o.orders.each_with_index { |x, i|
133
+ collector = visit(x, collector)
134
+ collector << COMMA unless len == i
135
+ }
136
+ end
137
+ collector
138
+ end
139
+
140
+ def visit_Make_Fetch_Happen o, collector
141
+ o.offset = Nodes::Offset.new(0) if o.limit && !o.offset
142
+ collector = visit o.offset, collector if o.offset
143
+ collector = visit o.limit, collector if o.limit
144
+ collector
145
+ end
146
+
147
+ # SQLServer Helpers
148
+
149
+ def node_value(node)
150
+ return nil unless node
151
+ case node.expr
152
+ when NilClass then nil
153
+ when Numeric then node.expr
154
+ when Arel::Nodes::Unary then node.expr.expr
155
+ end
156
+ end
157
+
158
+ def select_statement_lock?
159
+ @select_statement && @select_statement.lock
160
+ end
161
+
162
+ def make_Fetch_Possible_And_Deterministic o
163
+ return if o.limit.nil? && o.offset.nil?
164
+ t = table_From_Statement o
165
+ pk = primary_Key_From_Table t
166
+ return unless pk
167
+ if o.orders.empty?
168
+ # Prefer deterministic vs a simple `(SELECT NULL)` expr.
169
+ o.orders = [pk.asc]
170
+ end
171
+ end
172
+
173
+ def distinct_One_As_One_Is_So_Not_Fetch o
174
+ core = o.cores.first
175
+ distinct = Nodes::Distinct === core.set_quantifier
176
+ oneasone = core.projections.all? { |x| x == ActiveRecord::FinderMethods::ONE_AS_ONE }
177
+ limitone = [nil, 0, 1].include? node_value(o.limit)
178
+ if distinct && oneasone && limitone && !o.offset
179
+ # NOTE: part clears the limit part of the query but the bind parameter
180
+ # is still hanging around in active record, this issue makes
181
+ # the prepared statement to fails with "index i is out of range"
182
+ # As a quick fix is just add the bind marker as parameter of TOP
183
+ # which always be one.
184
+ core.projections = [Arel.sql("TOP(?) 1 AS [one]")]
185
+ o.limit = nil
186
+ end
187
+ end
188
+
189
+ def table_From_Statement o
190
+ core = o.cores.first
191
+ if Arel::Table === core.from
192
+ core.from
193
+ elsif Arel::Nodes::SqlLiteral === core.from
194
+ Arel::Table.new(core.from)
195
+ elsif Arel::Nodes::JoinSource === core.source
196
+ Arel::Nodes::SqlLiteral === core.source.left ? Arel::Table.new(core.source.left, @engine) : core.source.left
197
+ end
198
+ end
199
+
200
+ def primary_Key_From_Table t
201
+ return unless t
202
+ column_name = schema_cache.primary_keys(t.name) || column_cache(t.name).first.try(:second).try(:name)
203
+ column_name ? t[column_name] : nil
204
+ end
205
+
206
+ def remote_server_table_name o
207
+ ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
208
+ "#{o.class.engine.connection.database_prefix}#{o.name}"
209
+ ).quoted
210
+ end
211
+
212
+ end
213
+ end
214
+ end
data/lib/arjdbc.rb ADDED
@@ -0,0 +1,19 @@
1
+ if defined?(JRUBY_VERSION)
2
+ begin
3
+ require 'active_record/version'
4
+ require 'active_record'
5
+ rescue LoadError => e
6
+ warn "activerecord-jdbc-adapter requires the activerecord gem at runtime"
7
+ raise e
8
+ end
9
+ require 'arjdbc/jdbc'
10
+ begin
11
+ require 'arjdbc/railtie'
12
+ rescue LoadError => e
13
+ warn "activerecord-jdbc-adapter failed to load railtie: #{e.inspect}"
14
+ end if defined?(Rails) && ActiveRecord::VERSION::MAJOR >= 3
15
+ else
16
+ warn "activerecord-jdbc-adapter is for use with JRuby only"
17
+ end
18
+
19
+ require 'arjdbc/version'
@@ -0,0 +1,35 @@
1
+ module ArJdbc
2
+ module Abstract
3
+ module ConnectionManagement
4
+
5
+ # @override
6
+ def active?
7
+ return unless @connection
8
+ @connection.active?
9
+ end
10
+
11
+ # @override
12
+ def reconnect!
13
+ super # clear_cache! && reset_transaction
14
+ @connection.reconnect! # handles adapter.configure_connection
15
+ end
16
+
17
+ # @override
18
+ def disconnect!
19
+ super # clear_cache! && reset_transaction
20
+ return unless @connection
21
+ @connection.disconnect!
22
+ end
23
+
24
+ # @override
25
+ # def verify!(*ignored)
26
+ # if @connection && @connection.jndi?
27
+ # # checkout call-back does #reconnect!
28
+ # else
29
+ # reconnect! unless active? # super
30
+ # end
31
+ # end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,74 @@
1
+ module ArJdbc
2
+ module Abstract
3
+
4
+ # This is minimum amount of code needed from base JDBC Adapter class to make common adapters
5
+ # work. This replaces using jdbc/adapter as a base class for all adapters.
6
+ module Core
7
+
8
+ attr_reader :config
9
+
10
+ def initialize(connection, logger = nil, config = {})
11
+ @config = config
12
+
13
+ if self.class.equal? ActiveRecord::ConnectionAdapters::JdbcAdapter
14
+ spec = @config.key?(:adapter_spec) ? @config[:adapter_spec] :
15
+ ( @config[:adapter_spec] = adapter_spec(@config) ) # due resolving visitor
16
+ extend spec if spec
17
+ end
18
+
19
+ connection ||= jdbc_connection_class(config[:adapter_spec]).new(config, self)
20
+
21
+ super(connection, logger, config) # AbstractAdapter
22
+
23
+ connection.configure_connection # will call us (maybe)
24
+ end
25
+
26
+ # Retrieve the raw `java.sql.Connection` object.
27
+ # The unwrap parameter is useful if an attempt to unwrap a pooled (JNDI)
28
+ # connection should be made - to really return the 'native' JDBC object.
29
+ # @param unwrap [true, false] whether to unwrap the connection object
30
+ # @return [Java::JavaSql::Connection] the JDBC connection
31
+ def jdbc_connection(unwrap = nil)
32
+ raw_connection.jdbc_connection(unwrap)
33
+ end
34
+
35
+ protected
36
+
37
+ def translate_exception_class(e, sql)
38
+ begin
39
+ message = "#{e.class.name}: #{e.message}: #{sql}"
40
+ rescue Encoding::CompatibilityError
41
+ message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql}"
42
+ end
43
+
44
+ exception = translate_exception(e, message)
45
+ exception.set_backtrace e.backtrace unless e.equal?(exception)
46
+ exception
47
+ end
48
+
49
+ def translate_exception(e, message)
50
+ # we shall not translate native "Java" exceptions as they might
51
+ # swallow an ArJdbc / driver bug into an AR::StatementInvalid !
52
+ return e if e.is_a?(Java::JavaLang::Throwable)
53
+
54
+ case e
55
+ when SystemExit, SignalException, NoMemoryError then e
56
+ when ActiveModel::RangeError, TypeError, RuntimeError then e
57
+ else ActiveRecord::StatementInvalid.new(message)
58
+ end
59
+ end
60
+
61
+ def extract_raw_bind_values(binds)
62
+ binds.map(&:value_for_database)
63
+ end
64
+
65
+ # this version of log() automatically fills type_casted_binds from binds if necessary
66
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil)
67
+ if binds.any? && (type_casted_binds.nil? || type_casted_binds.empty?)
68
+ type_casted_binds = ->{ extract_raw_bind_values(binds) }
69
+ end
70
+ super
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ArJdbc
4
+ module Abstract
5
+
6
+ # This provides the basic interface for interacting with the
7
+ # database for JDBC based adapters
8
+ module DatabaseStatements
9
+
10
+ NO_BINDS = [].freeze
11
+
12
+ def exec_insert(sql, name = nil, binds = NO_BINDS, pk = nil, sequence_name = nil)
13
+ if without_prepared_statement?(binds)
14
+ log(sql, name) { @connection.execute_insert(sql) }
15
+ else
16
+ log(sql, name, binds) do
17
+ @connection.execute_insert(sql, binds)
18
+ end
19
+ end
20
+ end
21
+
22
+ # It appears that at this point (AR 5.0) "prepare" should only ever be true
23
+ # if prepared statements are enabled
24
+ def exec_query(sql, name = nil, binds = NO_BINDS, prepare: false)
25
+ if without_prepared_statement?(binds)
26
+ log(sql, name) { @connection.execute_query(sql) }
27
+ else
28
+ log(sql, name, binds) do
29
+ # this is different from normal AR that always caches
30
+ cached_statement = fetch_cached_statement(sql) if prepare && @jdbc_statement_cache_enabled
31
+ @connection.execute_prepared_query(sql, binds, cached_statement)
32
+ end
33
+ end
34
+ end
35
+
36
+ def exec_update(sql, name = nil, binds = NO_BINDS)
37
+ if without_prepared_statement?(binds)
38
+ log(sql, name) { @connection.execute_update(sql) }
39
+ else
40
+ log(sql, name, binds) { @connection.execute_prepared_update(sql, binds) }
41
+ end
42
+ end
43
+ alias :exec_delete :exec_update
44
+
45
+ def execute(sql, name = nil)
46
+ log(sql, name) { @connection.execute(sql) }
47
+ end
48
+
49
+ def select_all(arel, name = nil, binds = NO_BINDS, preparable: nil)
50
+ binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
51
+ super
52
+ end
53
+
54
+ private
55
+
56
+ def convert_legacy_binds_to_attributes(binds)
57
+ binds.map do |column, value|
58
+ ActiveRecord::Relation::QueryAttribute.new(nil, type_cast(value, column), ActiveModel::Type::Value.new)
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,58 @@
1
+ require 'active_record/connection_adapters/statement_pool'
2
+
3
+ module ArJdbc
4
+ module Abstract
5
+ module StatementCache
6
+
7
+ # This works a little differently than the AR implementation in that
8
+ # we are storing an actual PreparedStatement object instead of just
9
+ # the name of the prepared statement
10
+ class StatementPool < ActiveRecord::ConnectionAdapters::StatementPool
11
+
12
+ private
13
+
14
+ def dealloc(statement)
15
+ statement.close
16
+ end
17
+
18
+ end
19
+
20
+ def initialize(*args) # (connection, logger, config)
21
+ super
22
+
23
+ # Only say we support the statement cache if we are using prepared statements
24
+ # and have a max number of statements defined
25
+ statement_limit = self.class.type_cast_config_to_integer(config[:statement_limit])
26
+ @jdbc_statement_cache_enabled = prepared_statements && (statement_limit.nil? || statement_limit > 0)
27
+
28
+ @statements = StatementPool.new(statement_limit) # AR (5.0) expects this to be stored as @statements
29
+ end
30
+
31
+ # Clears the prepared statements cache.
32
+ def clear_cache!
33
+ @statements.clear
34
+ end
35
+
36
+ def delete_cached_statement(sql)
37
+ @statements.delete(sql_key(sql))
38
+ end
39
+
40
+ def fetch_cached_statement(sql)
41
+ @statements[sql_key(sql)] ||= @connection.prepare_statement(sql)
42
+ end
43
+
44
+ def supports_statement_cache?
45
+ @jdbc_statement_cache_enabled
46
+ end
47
+
48
+ private
49
+
50
+ # This should be overridden by the adapter if the sql itself
51
+ # is not enough to make the key unique
52
+ def sql_key(sql)
53
+ sql
54
+ end
55
+
56
+ end
57
+ end
58
+ end