activerecord-jdbc-adapter 1.0.3-java → 50.1-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 (268) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +33 -0
  3. data/.travis.yml +79 -0
  4. data/.yardopts +4 -0
  5. data/CONTRIBUTING.md +50 -0
  6. data/Gemfile +91 -0
  7. data/History.md +1191 -0
  8. data/LICENSE.txt +22 -17
  9. data/README.md +169 -0
  10. data/RUNNING_TESTS.md +127 -0
  11. data/Rakefile +294 -5
  12. data/Rakefile.jdbc +20 -0
  13. data/activerecord-jdbc-adapter.gemspec +55 -0
  14. data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
  15. data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
  16. data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
  17. data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
  18. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
  19. data/lib/activerecord-jdbc-adapter.rb +0 -5
  20. data/lib/arel/visitors/compat.rb +60 -0
  21. data/lib/arel/visitors/db2.rb +128 -6
  22. data/lib/arel/visitors/derby.rb +103 -10
  23. data/lib/arel/visitors/firebird.rb +79 -0
  24. data/lib/arel/visitors/h2.rb +25 -0
  25. data/lib/arel/visitors/hsqldb.rb +18 -10
  26. data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
  27. data/lib/arel/visitors/sql_server.rb +225 -0
  28. data/lib/arel/visitors/sql_server/ng42.rb +293 -0
  29. data/lib/arjdbc.rb +11 -21
  30. data/lib/arjdbc/abstract/connection_management.rb +35 -0
  31. data/lib/arjdbc/abstract/core.rb +64 -0
  32. data/lib/arjdbc/abstract/database_statements.rb +64 -0
  33. data/lib/arjdbc/abstract/statement_cache.rb +58 -0
  34. data/lib/arjdbc/abstract/transaction_support.rb +86 -0
  35. data/lib/arjdbc/db2.rb +3 -1
  36. data/lib/arjdbc/db2/adapter.rb +630 -250
  37. data/lib/arjdbc/db2/as400.rb +130 -0
  38. data/lib/arjdbc/db2/column.rb +167 -0
  39. data/lib/arjdbc/db2/connection_methods.rb +44 -0
  40. data/lib/arjdbc/derby.rb +1 -5
  41. data/lib/arjdbc/derby/active_record_patch.rb +13 -0
  42. data/lib/arjdbc/derby/adapter.rb +409 -217
  43. data/lib/arjdbc/derby/connection_methods.rb +16 -14
  44. data/lib/arjdbc/derby/schema_creation.rb +15 -0
  45. data/lib/arjdbc/discover.rb +62 -50
  46. data/lib/arjdbc/firebird.rb +3 -1
  47. data/lib/arjdbc/firebird/adapter.rb +365 -62
  48. data/lib/arjdbc/firebird/connection_methods.rb +23 -0
  49. data/lib/arjdbc/h2.rb +2 -3
  50. data/lib/arjdbc/h2/adapter.rb +273 -6
  51. data/lib/arjdbc/h2/connection_methods.rb +23 -8
  52. data/lib/arjdbc/hsqldb.rb +2 -3
  53. data/lib/arjdbc/hsqldb/adapter.rb +204 -77
  54. data/lib/arjdbc/hsqldb/connection_methods.rb +24 -10
  55. data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
  56. data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
  57. data/lib/arjdbc/informix.rb +4 -2
  58. data/lib/arjdbc/informix/adapter.rb +78 -54
  59. data/lib/arjdbc/informix/connection_methods.rb +8 -9
  60. data/lib/arjdbc/jdbc.rb +59 -2
  61. data/lib/arjdbc/jdbc/adapter.rb +356 -166
  62. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  63. data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
  64. data/lib/arjdbc/jdbc/base_ext.rb +15 -0
  65. data/lib/arjdbc/jdbc/callbacks.rb +27 -18
  66. data/lib/arjdbc/jdbc/column.rb +79 -20
  67. data/lib/arjdbc/jdbc/connection.rb +5 -119
  68. data/lib/arjdbc/jdbc/connection_methods.rb +32 -4
  69. data/lib/arjdbc/jdbc/error.rb +65 -0
  70. data/lib/arjdbc/jdbc/extension.rb +41 -29
  71. data/lib/arjdbc/jdbc/java.rb +5 -6
  72. data/lib/arjdbc/jdbc/jdbc.rake +3 -126
  73. data/lib/arjdbc/jdbc/railtie.rb +2 -9
  74. data/lib/arjdbc/jdbc/rake_tasks.rb +3 -10
  75. data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -0
  76. data/lib/arjdbc/jdbc/type_cast.rb +166 -0
  77. data/lib/arjdbc/jdbc/type_converter.rb +35 -19
  78. data/lib/arjdbc/mssql.rb +6 -3
  79. data/lib/arjdbc/mssql/adapter.rb +630 -298
  80. data/lib/arjdbc/mssql/column.rb +200 -0
  81. data/lib/arjdbc/mssql/connection_methods.rb +66 -17
  82. data/lib/arjdbc/mssql/explain_support.rb +99 -0
  83. data/lib/arjdbc/mssql/limit_helpers.rb +189 -50
  84. data/lib/arjdbc/mssql/lock_methods.rb +77 -0
  85. data/lib/arjdbc/mssql/types.rb +343 -0
  86. data/lib/arjdbc/mssql/utils.rb +82 -0
  87. data/lib/arjdbc/mysql.rb +2 -3
  88. data/lib/arjdbc/mysql/adapter.rb +86 -356
  89. data/lib/arjdbc/mysql/connection_methods.rb +159 -23
  90. data/lib/arjdbc/oracle/adapter.rb +714 -263
  91. data/lib/arjdbc/postgresql.rb +2 -3
  92. data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +24 -0
  93. data/lib/arjdbc/postgresql/adapter.rb +570 -400
  94. data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
  95. data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
  96. data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
  97. data/lib/arjdbc/postgresql/base/pgconn.rb +11 -0
  98. data/lib/arjdbc/postgresql/column.rb +51 -0
  99. data/lib/arjdbc/postgresql/connection_methods.rb +57 -18
  100. data/lib/arjdbc/postgresql/name.rb +24 -0
  101. data/lib/arjdbc/postgresql/oid_types.rb +192 -0
  102. data/lib/arjdbc/railtie.rb +11 -0
  103. data/lib/arjdbc/sqlite3.rb +2 -3
  104. data/lib/arjdbc/sqlite3/adapter.rb +518 -198
  105. data/lib/arjdbc/sqlite3/connection_methods.rb +49 -24
  106. data/lib/arjdbc/sybase.rb +2 -2
  107. data/lib/arjdbc/sybase/adapter.rb +7 -6
  108. data/lib/arjdbc/tasks.rb +13 -0
  109. data/lib/arjdbc/tasks/database_tasks.rb +52 -0
  110. data/lib/arjdbc/tasks/databases.rake +91 -0
  111. data/lib/arjdbc/tasks/databases3.rake +215 -0
  112. data/lib/arjdbc/tasks/databases4.rake +39 -0
  113. data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
  114. data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
  115. data/lib/arjdbc/tasks/h2_database_tasks.rb +31 -0
  116. data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
  117. data/lib/arjdbc/tasks/jdbc_database_tasks.rb +169 -0
  118. data/lib/arjdbc/tasks/mssql_database_tasks.rb +46 -0
  119. data/lib/arjdbc/util/quoted_cache.rb +60 -0
  120. data/lib/arjdbc/util/serialized_attributes.rb +98 -0
  121. data/lib/arjdbc/util/table_copier.rb +110 -0
  122. data/lib/arjdbc/version.rb +1 -6
  123. data/lib/generators/jdbc/USAGE +9 -0
  124. data/lib/generators/jdbc/jdbc_generator.rb +8 -0
  125. data/lib/jdbc_adapter.rb +1 -1
  126. data/lib/jdbc_adapter/rake_tasks.rb +3 -2
  127. data/lib/jdbc_adapter/version.rb +2 -1
  128. data/pom.xml +114 -0
  129. data/rails_generators/jdbc_generator.rb +1 -1
  130. data/rails_generators/templates/config/initializers/jdbc.rb +8 -5
  131. data/rails_generators/templates/lib/tasks/jdbc.rake +7 -4
  132. data/rakelib/01-tomcat.rake +51 -0
  133. data/rakelib/02-test.rake +132 -0
  134. data/rakelib/bundler_ext.rb +11 -0
  135. data/rakelib/compile.rake +67 -22
  136. data/rakelib/db.rake +61 -0
  137. data/rakelib/rails.rake +204 -29
  138. data/src/java/arjdbc/ArJdbcModule.java +286 -0
  139. data/src/java/arjdbc/db2/DB2Module.java +76 -0
  140. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +126 -0
  141. data/src/java/arjdbc/derby/DerbyModule.java +99 -243
  142. data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +152 -0
  143. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +174 -0
  144. data/src/java/arjdbc/{jdbc/JdbcConnectionFactory.java → h2/H2Module.java} +20 -6
  145. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +27 -12
  146. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +73 -0
  147. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +7 -6
  148. data/src/java/arjdbc/jdbc/AdapterJavaService.java +7 -29
  149. data/src/java/arjdbc/jdbc/Callable.java +44 -0
  150. data/src/java/arjdbc/jdbc/ConnectionFactory.java +132 -0
  151. data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +157 -0
  152. data/src/java/arjdbc/jdbc/DriverConnectionFactory.java +63 -0
  153. data/src/java/arjdbc/jdbc/DriverWrapper.java +119 -0
  154. data/src/java/arjdbc/jdbc/JdbcResult.java +130 -0
  155. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +3622 -948
  156. data/src/java/arjdbc/mssql/MSSQLModule.java +90 -0
  157. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +181 -0
  158. data/src/java/arjdbc/mysql/MySQLModule.java +99 -81
  159. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +294 -0
  160. data/src/java/arjdbc/oracle/OracleModule.java +80 -0
  161. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +387 -17
  162. data/src/java/arjdbc/postgresql/ByteaUtils.java +157 -0
  163. data/src/java/arjdbc/postgresql/PgResultSetMetaDataWrapper.java +23 -0
  164. data/src/java/arjdbc/postgresql/PostgreSQLModule.java +77 -0
  165. data/src/java/arjdbc/postgresql/PostgreSQLResult.java +184 -0
  166. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +952 -0
  167. data/src/java/arjdbc/sqlite3/SQLite3Module.java +73 -0
  168. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +525 -0
  169. data/src/java/arjdbc/util/CallResultSet.java +826 -0
  170. data/src/java/arjdbc/util/DateTimeUtils.java +580 -0
  171. data/src/java/arjdbc/util/ObjectSupport.java +65 -0
  172. data/src/java/arjdbc/util/QuotingUtils.java +138 -0
  173. data/src/java/arjdbc/util/StringCache.java +63 -0
  174. data/src/java/arjdbc/util/StringHelper.java +159 -0
  175. metadata +245 -268
  176. data/History.txt +0 -369
  177. data/Manifest.txt +0 -180
  178. data/README.txt +0 -181
  179. data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
  180. data/lib/arel/engines/sql/compilers/db2_compiler.rb +0 -9
  181. data/lib/arel/engines/sql/compilers/derby_compiler.rb +0 -6
  182. data/lib/arel/engines/sql/compilers/h2_compiler.rb +0 -6
  183. data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +0 -15
  184. data/lib/arel/engines/sql/compilers/jdbc_compiler.rb +0 -6
  185. data/lib/arel/engines/sql/compilers/mssql_compiler.rb +0 -46
  186. data/lib/arel/visitors/mssql.rb +0 -44
  187. data/lib/arjdbc/jdbc/compatibility.rb +0 -51
  188. data/lib/arjdbc/jdbc/core_ext.rb +0 -24
  189. data/lib/arjdbc/jdbc/discover.rb +0 -18
  190. data/lib/arjdbc/jdbc/driver.rb +0 -44
  191. data/lib/arjdbc/jdbc/missing_functionality_helper.rb +0 -87
  192. data/lib/arjdbc/jdbc/quoted_primary_key.rb +0 -28
  193. data/lib/arjdbc/jdbc/require_driver.rb +0 -16
  194. data/lib/arjdbc/mimer.rb +0 -2
  195. data/lib/arjdbc/mimer/adapter.rb +0 -142
  196. data/lib/arjdbc/mssql/tsql_helper.rb +0 -61
  197. data/lib/arjdbc/oracle.rb +0 -3
  198. data/lib/arjdbc/oracle/connection_methods.rb +0 -11
  199. data/lib/pg.rb +0 -4
  200. data/rakelib/package.rake +0 -92
  201. data/rakelib/test.rake +0 -81
  202. data/src/java/arjdbc/jdbc/SQLBlock.java +0 -48
  203. data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +0 -127
  204. data/src/java/arjdbc/postgresql/PostgresqlRubyJdbcConnection.java +0 -57
  205. data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +0 -64
  206. data/test/abstract_db_create.rb +0 -117
  207. data/test/activerecord/connection_adapters/type_conversion_test.rb +0 -31
  208. data/test/activerecord/connections/native_jdbc_mysql/connection.rb +0 -25
  209. data/test/db/db2.rb +0 -11
  210. data/test/db/derby.rb +0 -12
  211. data/test/db/h2.rb +0 -11
  212. data/test/db/hsqldb.rb +0 -13
  213. data/test/db/informix.rb +0 -11
  214. data/test/db/jdbc.rb +0 -11
  215. data/test/db/jndi_config.rb +0 -40
  216. data/test/db/logger.rb +0 -3
  217. data/test/db/mssql.rb +0 -9
  218. data/test/db/mysql.rb +0 -10
  219. data/test/db/oracle.rb +0 -34
  220. data/test/db/postgres.rb +0 -9
  221. data/test/db/sqlite3.rb +0 -11
  222. data/test/db2_simple_test.rb +0 -66
  223. data/test/derby_migration_test.rb +0 -68
  224. data/test/derby_multibyte_test.rb +0 -12
  225. data/test/derby_simple_test.rb +0 -99
  226. data/test/generic_jdbc_connection_test.rb +0 -29
  227. data/test/h2_simple_test.rb +0 -41
  228. data/test/has_many_through.rb +0 -79
  229. data/test/helper.rb +0 -5
  230. data/test/hsqldb_simple_test.rb +0 -6
  231. data/test/informix_simple_test.rb +0 -48
  232. data/test/jdbc_common.rb +0 -25
  233. data/test/jndi_callbacks_test.rb +0 -40
  234. data/test/jndi_test.rb +0 -25
  235. data/test/manualTestDatabase.rb +0 -191
  236. data/test/models/add_not_null_column_to_table.rb +0 -12
  237. data/test/models/auto_id.rb +0 -18
  238. data/test/models/data_types.rb +0 -28
  239. data/test/models/entry.rb +0 -43
  240. data/test/models/mixed_case.rb +0 -25
  241. data/test/models/reserved_word.rb +0 -18
  242. data/test/models/string_id.rb +0 -18
  243. data/test/models/validates_uniqueness_of_string.rb +0 -19
  244. data/test/mssql_db_create_test.rb +0 -26
  245. data/test/mssql_identity_insert_test.rb +0 -19
  246. data/test/mssql_legacy_types_test.rb +0 -58
  247. data/test/mssql_limit_offset_test.rb +0 -136
  248. data/test/mssql_multibyte_test.rb +0 -18
  249. data/test/mssql_simple_test.rb +0 -55
  250. data/test/mysql_db_create_test.rb +0 -27
  251. data/test/mysql_info_test.rb +0 -113
  252. data/test/mysql_multibyte_test.rb +0 -10
  253. data/test/mysql_nonstandard_primary_key_test.rb +0 -42
  254. data/test/mysql_simple_test.rb +0 -49
  255. data/test/oracle_simple_test.rb +0 -18
  256. data/test/oracle_specific_test.rb +0 -83
  257. data/test/pick_rails_version.rb +0 -3
  258. data/test/postgres_db_create_test.rb +0 -32
  259. data/test/postgres_drop_db_test.rb +0 -16
  260. data/test/postgres_mixed_case_test.rb +0 -29
  261. data/test/postgres_nonseq_pkey_test.rb +0 -38
  262. data/test/postgres_reserved_test.rb +0 -22
  263. data/test/postgres_schema_search_path_test.rb +0 -44
  264. data/test/postgres_simple_test.rb +0 -51
  265. data/test/postgres_table_alias_length_test.rb +0 -15
  266. data/test/simple.rb +0 -546
  267. data/test/sqlite3_simple_test.rb +0 -233
  268. data/test/sybase_jtds_simple_test.rb +0 -28
@@ -0,0 +1,11 @@
1
+ require 'rails/railtie'
2
+
3
+ module ArJdbc
4
+ class Railtie < ::Rails::Railtie
5
+ rake_tasks do
6
+ if defined? ActiveRecord::Railtie # only if AR being used
7
+ load File.expand_path('tasks.rb', File.dirname(__FILE__))
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,4 +1,3 @@
1
- require 'arjdbc/jdbc'
2
- jdbc_require_driver 'jdbc/sqlite3'
3
- require 'arjdbc/sqlite3/connection_methods'
1
+ require 'arjdbc'
4
2
  require 'arjdbc/sqlite3/adapter'
3
+ require 'arjdbc/sqlite3/connection_methods'
@@ -1,226 +1,353 @@
1
- require 'arjdbc/jdbc/missing_functionality_helper'
1
+ ArJdbc.load_java_part :SQLite3
2
+
3
+ require "arjdbc/abstract/core"
4
+ require "arjdbc/abstract/database_statements"
5
+ require 'arjdbc/abstract/statement_cache'
6
+ require "arjdbc/abstract/transaction_support"
7
+ require "active_record/connection_adapters/statement_pool"
8
+ require "active_record/connection_adapters/abstract/database_statements"
9
+ require "active_record/connection_adapters/sqlite3/explain_pretty_printer"
10
+ require "active_record/connection_adapters/sqlite3/quoting"
11
+ require "active_record/connection_adapters/sqlite3/schema_creation"
12
+
13
+ module ArJdbc
14
+ # All the code in this module is a copy of ConnectionAdapters::SQLite3Adapter from active_record 5.
15
+ # The constants at the front of this file are to allow the rest of the file to remain with no modifications
16
+ # from its original source. If you hack on this file try not to modify this module and instead try and
17
+ # put those overrides in SQL3Adapter below. We try and keep a copy of the Rails this adapter supports
18
+ # with the current goal of being able to diff changes easily over time and to also eventually remove
19
+ # this module from ARJDBC altogether.
20
+ module SQLite3
21
+ # DIFFERENCE: Some common constant names to reduce differences in rest of this module from AR5 version
22
+ ConnectionAdapters = ::ActiveRecord::ConnectionAdapters
23
+ IndexDefinition = ::ActiveRecord::ConnectionAdapters::IndexDefinition
24
+ Quoting = ::ActiveRecord::ConnectionAdapters::SQLite3::Quoting
25
+ RecordNotUnique = ::ActiveRecord::RecordNotUnique
26
+ SchemaCreation = ConnectionAdapters::SQLite3::SchemaCreation
27
+ SQLite3Adapter = ConnectionAdapters::AbstractAdapter
28
+
29
+ ADAPTER_NAME = 'SQLite'.freeze
30
+
31
+ include Quoting
32
+
33
+ NATIVE_DATABASE_TYPES = {
34
+ primary_key: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL",
35
+ string: { name: "varchar" },
36
+ text: { name: "text" },
37
+ integer: { name: "integer" },
38
+ float: { name: "float" },
39
+ decimal: { name: "decimal" },
40
+ datetime: { name: "datetime" },
41
+ time: { name: "time" },
42
+ date: { name: "date" },
43
+ binary: { name: "blob" },
44
+ boolean: { name: "boolean" }
45
+ }
46
+
47
+ class StatementPool < ConnectionAdapters::StatementPool
48
+ private
2
49
 
3
- module ActiveRecord::ConnectionAdapters
4
- Sqlite3Adapter = Class.new(AbstractAdapter) unless const_defined?(:Sqlite3Adapter)
5
- end
50
+ def dealloc(stmt)
51
+ stmt[:stmt].close unless stmt[:stmt].closed?
52
+ end
53
+ end
6
54
 
7
- module ::ArJdbc
8
- module SQLite3
9
- def self.column_selector
10
- [/sqlite/i, lambda {|cfg,col| col.extend(::ArJdbc::SQLite3::Column)}]
55
+ def schema_creation # :nodoc:
56
+ SQLite3::SchemaCreation.new self
11
57
  end
12
58
 
13
- def self.jdbc_connection_class
14
- ::ActiveRecord::ConnectionAdapters::Sqlite3JdbcConnection
59
+ def arel_visitor # :nodoc:
60
+ Arel::Visitors::SQLite.new(self)
15
61
  end
16
62
 
17
- module Column
18
- def init_column(name, default, *args)
19
- @default = '' if default =~ /NULL/
20
- end
63
+ # Difference we remove connection_options because we are not using it.
64
+ def initialize(connection, logger, config)
65
+ super(connection, logger, config)
21
66
 
22
- def type_cast(value)
23
- return nil if value.nil?
24
- case type
25
- when :string then value
26
- when :primary_key then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
27
- when :float then value.to_f
28
- when :decimal then self.class.value_to_decimal(value)
29
- when :boolean then self.class.value_to_boolean(value)
30
- else super
31
- end
32
- end
67
+ @active = nil
68
+ @statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
69
+ end
33
70
 
34
- private
35
- def simplified_type(field_type)
36
- case field_type
37
- when /boolean/i then :boolean
38
- when /text/i then :text
39
- when /varchar/i then :string
40
- when /int/i then :integer
41
- when /float/i then :float
42
- when /real/i then @scale == 0 ? :integer : :decimal
43
- when /datetime/i then :datetime
44
- when /date/i then :date
45
- when /time/i then :time
46
- when /blob/i then :binary
47
- end
48
- end
71
+ def supports_ddl_transactions?
72
+ true
73
+ end
49
74
 
50
- def extract_precision(sql_type)
51
- case sql_type
52
- when /^(real)\((\d+)(,\d+)?\)/i then $2.to_i
53
- else super
54
- end
55
- end
75
+ def supports_savepoints?
76
+ true
77
+ end
56
78
 
57
- def extract_scale(sql_type)
58
- case sql_type
59
- when /^(real)\((\d+)\)/i then 0
60
- when /^(real)\((\d+)(,(\d+))\)/i then $4.to_i
61
- else super
62
- end
63
- end
79
+ def supports_partial_index?
80
+ sqlite_version >= "3.8.0"
81
+ end
64
82
 
65
- # Post process default value from JDBC into a Rails-friendly format (columns{-internal})
66
- def default_value(value)
67
- # jdbc returns column default strings with actual single quotes around the value.
68
- return $1 if value =~ /^'(.*)'$/
83
+ # Returns true, since this connection adapter supports prepared statement
84
+ # caching.
85
+ def supports_statement_cache?
86
+ true
87
+ end
69
88
 
70
- value
71
- end
89
+ # Returns true, since this connection adapter supports migrations.
90
+ def supports_migrations? #:nodoc:
91
+ true
72
92
  end
73
93
 
74
- def adapter_name #:nodoc:
75
- 'SQLite'
94
+ def supports_primary_key? #:nodoc:
95
+ true
76
96
  end
77
97
 
78
- def supports_add_column?
79
- sqlite_version >= '3.1.6'
98
+ def requires_reloading?
99
+ true
80
100
  end
81
101
 
82
- def supports_count_distinct? #:nodoc:
83
- sqlite_version >= '3.2.6'
102
+ def supports_views?
103
+ true
84
104
  end
85
105
 
86
- def supports_autoincrement? #:nodoc:
87
- sqlite_version >= '3.1.0'
106
+ def supports_datetime_with_precision?
107
+ true
88
108
  end
89
109
 
90
- def sqlite_version
91
- @sqlite_version ||= select_value('select sqlite_version(*)')
110
+ def supports_multi_insert?
111
+ sqlite_version >= "3.7.11"
92
112
  end
93
113
 
94
- def modify_types(tp)
95
- tp[:primary_key] = "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"
96
- tp[:string] = { :name => "VARCHAR", :limit => 255 }
97
- tp[:float] = { :name => "REAL" }
98
- tp[:decimal] = { :name => "REAL" }
99
- tp[:datetime] = { :name => "DATETIME" }
100
- tp[:timestamp] = { :name => "DATETIME" }
101
- tp[:time] = { :name => "TIME" }
102
- tp[:date] = { :name => "DATE" }
103
- tp[:boolean] = { :name => "BOOLEAN" }
104
- tp[:binary] = { :name => "BLOB" }
105
- tp
114
+ def active?
115
+ @active != false
106
116
  end
107
117
 
108
- def quote_column_name(name) #:nodoc:
109
- %Q("#{name}")
118
+ # Disconnects from the database if already connected. Otherwise, this
119
+ # method does nothing.
120
+ def disconnect!
121
+ super
122
+ @active = false
123
+ @connection.close rescue nil
110
124
  end
111
125
 
112
- def quote_string(str)
113
- str.gsub(/'/, "''")
126
+ # Clears the prepared statements cache.
127
+ def clear_cache!
128
+ @statements.clear
114
129
  end
115
130
 
116
- def quoted_true
117
- %Q{'t'}
131
+ def supports_index_sort_order?
132
+ true
118
133
  end
119
134
 
120
- def quoted_false
121
- %Q{'f'}
135
+ def valid_type?(type)
136
+ true
122
137
  end
123
138
 
124
- def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
125
- @connection.execute_update(sql)
126
- id_value || last_insert_id
139
+ # Returns 62. SQLite supports index names up to 64
140
+ # characters. The rest is used by Rails internally to perform
141
+ # temporary rename operations
142
+ def allowed_index_name_length
143
+ index_name_length - 2
127
144
  end
128
145
 
129
- def last_insert_id
130
- Integer(select_value("SELECT last_insert_rowid()"))
146
+ def native_database_types #:nodoc:
147
+ NATIVE_DATABASE_TYPES
131
148
  end
132
149
 
133
- def tables(name = nil) #:nodoc:
134
- sql = <<-SQL
135
- SELECT name
136
- FROM sqlite_master
137
- WHERE type = 'table' AND NOT name = 'sqlite_sequence'
138
- SQL
150
+ # Returns the current database encoding format as a string, eg: 'UTF-8'
151
+ def encoding
152
+ @connection.encoding.to_s
153
+ end
139
154
 
140
- select_rows(sql, name).map do |row|
141
- row[0]
142
- end
155
+ def supports_explain?
156
+ true
143
157
  end
144
158
 
145
- def remove_index(table_name, options = {})
146
- execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
159
+ #--
160
+ # DATABASE STATEMENTS ======================================
161
+ #++
162
+
163
+ def explain(arel, binds = [])
164
+ sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
165
+ ::ActiveRecord::ConnectionAdapters::SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", []))
147
166
  end
148
167
 
149
- def indexes(table_name, name = nil)
150
- result = select_rows("SELECT name, sql FROM sqlite_master WHERE tbl_name = '#{table_name}' AND type = 'index'", name)
168
+ def exec_query(sql, name = nil, binds = [], prepare: false)
169
+ type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
151
170
 
152
- result.collect do |row|
153
- name = row[0]
154
- index_sql = row[1]
155
- unique = (index_sql =~ /unique/i)
156
- cols = index_sql.match(/\((.*)\)/)[1].gsub(/,/,' ').split.map do |c|
157
- match = /^"(.+)"$/.match(c); match ? match[1] : c
171
+ log(sql, name, binds) do
172
+ # Don't cache statements if they are not prepared
173
+ unless prepare
174
+ stmt = @connection.prepare(sql)
175
+ begin
176
+ cols = stmt.columns
177
+ unless without_prepared_statement?(binds)
178
+ stmt.bind_params(type_casted_binds)
179
+ end
180
+ records = stmt.to_a
181
+ ensure
182
+ stmt.close
183
+ end
184
+ stmt = records
185
+ else
186
+ cache = @statements[sql] ||= {
187
+ :stmt => @connection.prepare(sql)
188
+ }
189
+ stmt = cache[:stmt]
190
+ cols = cache[:cols] ||= stmt.columns
191
+ stmt.reset!
192
+ stmt.bind_params(type_casted_binds)
158
193
  end
159
- ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, name, unique, cols)
194
+
195
+ ActiveRecord::Result.new(cols, stmt.to_a)
160
196
  end
161
197
  end
162
198
 
163
- def primary_key(table_name) #:nodoc:
164
- column = table_structure(table_name).find {|field| field['pk'].to_i == 1}
165
- column ? column['name'] : nil
199
+ def exec_delete(sql, name = 'SQL', binds = [])
200
+ exec_query(sql, name, binds)
201
+ @connection.changes
166
202
  end
203
+ alias :exec_update :exec_delete
167
204
 
168
- def recreate_database(name)
169
- tables.each{ |table| drop_table(table) }
205
+ def last_inserted_id(result)
206
+ @connection.last_insert_row_id
170
207
  end
171
208
 
172
- def _execute(sql, name = nil)
173
- result = super
174
- ActiveRecord::ConnectionAdapters::JdbcConnection::insert?(sql) ? last_insert_id : result
209
+ def execute(sql, name = nil) #:nodoc:
210
+ log(sql, name) { @connection.execute(sql) }
175
211
  end
176
212
 
177
- def select(sql, name=nil)
178
- execute(sql, name).map do |row|
179
- record = {}
180
- row.each_key do |key|
181
- if key.is_a?(String)
182
- record[key.sub(/^"?\w+"?\./, '')] = row[key]
183
- end
184
- end
185
- record
213
+ def begin_db_transaction #:nodoc:
214
+ log("begin transaction",nil) { @connection.transaction }
215
+ end
216
+
217
+ def commit_db_transaction #:nodoc:
218
+ log("commit transaction",nil) { @connection.commit }
219
+ end
220
+
221
+ def exec_rollback_db_transaction #:nodoc:
222
+ log("rollback transaction",nil) { @connection.rollback }
223
+ end
224
+
225
+ # SCHEMA STATEMENTS ========================================
226
+
227
+ def tables(name = nil) # :nodoc:
228
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
229
+ #tables currently returns both tables and views.
230
+ This behavior is deprecated and will be changed with Rails 5.1 to only return tables.
231
+ Use #data_sources instead.
232
+ MSG
233
+
234
+ if name
235
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
236
+ Passing arguments to #tables is deprecated without replacement.
237
+ MSG
186
238
  end
239
+
240
+ data_sources
187
241
  end
188
242
 
189
- def table_structure(table_name)
190
- structure = @connection.execute_query("PRAGMA table_info(#{quote_table_name(table_name)})")
191
- raise ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'" if structure.empty?
192
- structure
243
+ def data_sources
244
+ select_values("SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'", "SCHEMA")
193
245
  end
194
246
 
195
- def columns(table_name, name = nil) #:nodoc:
247
+ def table_exists?(table_name)
248
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
249
+ #table_exists? currently checks both tables and views.
250
+ This behavior is deprecated and will be changed with Rails 5.1 to only check tables.
251
+ Use #data_source_exists? instead.
252
+ MSG
253
+
254
+ data_source_exists?(table_name)
255
+ end
256
+
257
+ def data_source_exists?(table_name)
258
+ return false unless table_name.present?
259
+
260
+ sql = "SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'"
261
+ sql << " AND name = #{quote(table_name)}"
262
+
263
+ select_values(sql, "SCHEMA").any?
264
+ end
265
+
266
+ def views # :nodoc:
267
+ select_values("SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'", "SCHEMA")
268
+ end
269
+
270
+ def view_exists?(view_name) # :nodoc:
271
+ return false unless view_name.present?
272
+
273
+ sql = "SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'"
274
+ sql << " AND name = #{quote(view_name)}"
275
+
276
+ select_values(sql, "SCHEMA").any?
277
+ end
278
+
279
+ # Returns an array of +Column+ objects for the table specified by +table_name+.
280
+ def columns(table_name) # :nodoc:
281
+ table_name = table_name.to_s
196
282
  table_structure(table_name).map do |field|
197
- ::ActiveRecord::ConnectionAdapters::SQLite3Column.new(@config, field['name'], field['dflt_value'], field['type'], field['notnull'] == 0)
283
+ case field["dflt_value"]
284
+ when /^null$/i
285
+ field["dflt_value"] = nil
286
+ when /^'(.*)'$/m
287
+ field["dflt_value"] = $1.gsub("''", "'")
288
+ when /^"(.*)"$/m
289
+ field["dflt_value"] = $1.gsub('""', '"')
290
+ end
291
+
292
+ collation = field["collation"]
293
+ sql_type = field["type"]
294
+ type_metadata = fetch_type_metadata(sql_type)
295
+ new_column(field["name"], field["dflt_value"], type_metadata, field["notnull"].to_i == 0, table_name, nil, collation)
198
296
  end
199
297
  end
200
298
 
201
- def primary_key(table_name) #:nodoc:
202
- column = table_structure(table_name).find { |field|
203
- field['pk'].to_i == 1
204
- }
205
- column && column['name']
299
+ # Returns an array of indexes for the given table.
300
+ def indexes(table_name, name = nil) #:nodoc:
301
+ exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", "SCHEMA").map do |row|
302
+ sql = <<-SQL
303
+ SELECT sql
304
+ FROM sqlite_master
305
+ WHERE name=#{quote(row['name'])} AND type='index'
306
+ UNION ALL
307
+ SELECT sql
308
+ FROM sqlite_temp_master
309
+ WHERE name=#{quote(row['name'])} AND type='index'
310
+ SQL
311
+ index_sql = exec_query(sql).first["sql"]
312
+ match = /\sWHERE\s+(.+)$/i.match(index_sql)
313
+ where = match[1] if match
314
+ IndexDefinition.new(
315
+ table_name,
316
+ row["name"],
317
+ row["unique"] != 0,
318
+ exec_query("PRAGMA index_info('#{row['name']}')", "SCHEMA").map { |col|
319
+ col["name"]
320
+ }, nil, nil, where)
321
+ end
206
322
  end
207
323
 
208
- def remove_index!(table_name, index_name) #:nodoc:
209
- execute "DROP INDEX #{quote_column_name(index_name)}"
324
+ def primary_keys(table_name) # :nodoc:
325
+ pks = table_structure(table_name).select { |f| f["pk"] > 0 }
326
+ pks.sort_by { |f| f["pk"] }.map { |f| f["name"] }
210
327
  end
211
328
 
212
- def rename_table(name, new_name)
213
- execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
329
+ def remove_index(table_name, options = {}) #:nodoc:
330
+ index_name = index_name_for_remove(table_name, options)
331
+ exec_query "DROP INDEX #{quote_column_name(index_name)}"
332
+ end
333
+
334
+ # Renames a table.
335
+ #
336
+ # Example:
337
+ # rename_table('octopuses', 'octopi')
338
+ def rename_table(table_name, new_name)
339
+ exec_query "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
340
+ rename_table_indexes(table_name, new_name)
214
341
  end
215
342
 
216
343
  # See: http://www.sqlite.org/lang_altertable.html
217
344
  # SQLite has an additional restriction on the ALTER TABLE statement
218
- def valid_alter_table_options( type, options)
345
+ def valid_alter_table_type?(type)
219
346
  type.to_sym != :primary_key
220
347
  end
221
348
 
222
349
  def add_column(table_name, column_name, type, options = {}) #:nodoc:
223
- if supports_add_column? && valid_alter_table_options( type, options )
350
+ if valid_alter_table_type?(type)
224
351
  super(table_name, column_name, type, options)
225
352
  else
226
353
  alter_table(table_name) do |definition|
@@ -229,25 +356,23 @@ module ::ArJdbc
229
356
  end
230
357
  end
231
358
 
232
- def remove_column(table_name, *column_names) #:nodoc:
233
- raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
234
- column_names.flatten.each do |column_name|
235
- alter_table(table_name) do |definition|
236
- definition.columns.delete(definition[column_name])
237
- end
359
+ def remove_column(table_name, column_name, type = nil, options = {}) #:nodoc:
360
+ alter_table(table_name) do |definition|
361
+ definition.remove_column column_name
238
362
  end
239
363
  end
240
- alias :remove_columns :remove_column
241
364
 
242
- def change_column_default(table_name, column_name, default) #:nodoc:
365
+ def change_column_default(table_name, column_name, default_or_changes) #:nodoc:
366
+ default = extract_new_default_value(default_or_changes)
367
+
243
368
  alter_table(table_name) do |definition|
244
369
  definition[column_name].default = default
245
370
  end
246
371
  end
247
372
 
248
- def change_column_null(table_name, column_name, null, default = nil)
373
+ def change_column_null(table_name, column_name, null, default = nil) #:nodoc:
249
374
  unless null || default.nil?
250
- execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
375
+ exec_query("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
251
376
  end
252
377
  alter_table(table_name) do |definition|
253
378
  definition[column_name].null = null
@@ -262,47 +387,166 @@ module ::ArJdbc
262
387
  self.limit = options[:limit] if options.include?(:limit)
263
388
  self.default = options[:default] if include_default
264
389
  self.null = options[:null] if options.include?(:null)
390
+ self.precision = options[:precision] if options.include?(:precision)
391
+ self.scale = options[:scale] if options.include?(:scale)
392
+ self.collation = options[:collation] if options.include?(:collation)
265
393
  end
266
394
  end
267
395
  end
268
396
 
269
397
  def rename_column(table_name, column_name, new_column_name) #:nodoc:
270
- unless columns(table_name).detect{|c| c.name == column_name.to_s }
271
- raise ActiveRecord::ActiveRecordError, "Missing column #{table_name}.#{column_name}"
398
+ column = column_for(table_name, column_name)
399
+ alter_table(table_name, rename: { column.name => new_column_name.to_s })
400
+ rename_column_indexes(table_name, column.name, new_column_name)
401
+ end
402
+
403
+ protected
404
+
405
+ def table_structure(table_name)
406
+ structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", "SCHEMA")
407
+ raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
408
+ table_structure_with_collation(table_name, structure)
409
+ end
410
+
411
+ def alter_table(table_name, options = {}) #:nodoc:
412
+ altered_table_name = "a#{table_name}"
413
+ caller = lambda { |definition| yield definition if block_given? }
414
+
415
+ transaction do
416
+ move_table(table_name, altered_table_name,
417
+ options.merge(temporary: true))
418
+ move_table(altered_table_name, table_name, &caller)
272
419
  end
273
- alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s})
274
420
  end
275
421
 
276
- # SELECT ... FOR UPDATE is redundant since the table is locked.
277
- def add_lock!(sql, options) #:nodoc:
278
- sql
422
+ def move_table(from, to, options = {}, &block) #:nodoc:
423
+ copy_table(from, to, options, &block)
424
+ drop_table(from)
425
+ end
426
+
427
+ def copy_table(from, to, options = {}) #:nodoc:
428
+ from_primary_key = primary_key(from)
429
+ options[:id] = false
430
+ create_table(to, options) do |definition|
431
+ @definition = definition
432
+ @definition.primary_key(from_primary_key) if from_primary_key.present?
433
+ columns(from).each do |column|
434
+ column_name = options[:rename] ?
435
+ (options[:rename][column.name] ||
436
+ options[:rename][column.name.to_sym] ||
437
+ column.name) : column.name
438
+ next if column_name == from_primary_key
439
+
440
+ @definition.column(column_name, column.type,
441
+ limit: column.limit, default: column.default,
442
+ precision: column.precision, scale: column.scale,
443
+ null: column.null, collation: column.collation)
444
+ end
445
+ yield @definition if block_given?
446
+ end
447
+ copy_table_indexes(from, to, options[:rename] || {})
448
+ copy_table_contents(from, to,
449
+ @definition.columns.map(&:name),
450
+ options[:rename] || {})
451
+ end
452
+
453
+ def copy_table_indexes(from, to, rename = {}) #:nodoc:
454
+ indexes(from).each do |index|
455
+ name = index.name
456
+ if to == "a#{from}"
457
+ name = "t#{name}"
458
+ elsif from == "a#{to}"
459
+ name = name[1..-1]
460
+ end
461
+
462
+ to_column_names = columns(to).map(&:name)
463
+ columns = index.columns.map { |c| rename[c] || c }.select do |column|
464
+ to_column_names.include?(column)
465
+ end
466
+
467
+ unless columns.empty?
468
+ # index name can't be the same
469
+ opts = { name: name.gsub(/(^|_)(#{from})_/, "\\1#{to}_"), internal: true }
470
+ opts[:unique] = true if index.unique
471
+ add_index(to, columns, opts)
472
+ end
473
+ end
279
474
  end
280
475
 
281
- def empty_insert_statement_value
282
- "VALUES(NULL)"
476
+ def copy_table_contents(from, to, columns, rename = {}) #:nodoc:
477
+ column_mappings = Hash[columns.map { |name| [name, name] }]
478
+ rename.each { |a| column_mappings[a.last] = a.first }
479
+ from_columns = columns(from).collect(&:name)
480
+ columns = columns.find_all { |col| from_columns.include?(column_mappings[col]) }
481
+ from_columns_to_copy = columns.map { |col| column_mappings[col] }
482
+ quoted_columns = columns.map { |col| quote_column_name(col) } * ","
483
+ quoted_from_columns = from_columns_to_copy.map { |col| quote_column_name(col) } * ","
484
+
485
+ exec_query("INSERT INTO #{quote_table_name(to)} (#{quoted_columns})
486
+ SELECT #{quoted_from_columns} FROM #{quote_table_name(from)}")
283
487
  end
284
488
 
285
- protected
286
- include ArJdbc::MissingFunctionalityHelper
489
+ def sqlite_version
490
+ @sqlite_version ||= SQLite3Adapter::Version.new(select_value("select sqlite_version(*)"))
491
+ end
287
492
 
288
493
  def translate_exception(exception, message)
289
494
  case exception.message
290
- when /column(s)? .* (is|are) not unique/
291
- ActiveRecord::RecordNotUnique.new(message, exception)
495
+ # SQLite 3.8.2 returns a newly formatted error message:
496
+ # UNIQUE constraint failed: *table_name*.*column_name*
497
+ # Older versions of SQLite return:
498
+ # column *column_name* is not unique
499
+ when /column(s)? .* (is|are) not unique/, /UNIQUE constraint failed: .*/
500
+ RecordNotUnique.new(message)
501
+ else
502
+ super
503
+ end
504
+ end
505
+
506
+ private
507
+ COLLATE_REGEX = /.*\"(\w+)\".*collate\s+\"(\w+)\".*/i.freeze
508
+
509
+ def table_structure_with_collation(table_name, basic_structure)
510
+ collation_hash = {}
511
+ sql = "SELECT sql FROM
512
+ (SELECT * FROM sqlite_master UNION ALL
513
+ SELECT * FROM sqlite_temp_master)
514
+ WHERE type='table' and name='#{ table_name }' \;"
515
+
516
+ # Result will have following sample string
517
+ # CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
518
+ # "password_digest" varchar COLLATE "NOCASE");
519
+ result = exec_query(sql, 'SCHEMA').first
520
+
521
+ if result
522
+ # Splitting with left parentheses and picking up last will return all
523
+ # columns separated with comma(,).
524
+ columns_string = result["sql"].split('(').last
525
+
526
+ columns_string.split(',').each do |column_string|
527
+ # This regex will match the column name and collation type and will save
528
+ # the value in $1 and $2 respectively.
529
+ collation_hash[$1] = $2 if (COLLATE_REGEX =~ column_string)
530
+ end
531
+
532
+ basic_structure.map! do |column|
533
+ column_name = column['name']
534
+
535
+ if collation_hash.has_key? column_name
536
+ column['collation'] = collation_hash[column_name]
537
+ end
538
+
539
+ column
540
+ end
292
541
  else
293
- super
542
+ basic_structure.to_hash
294
543
  end
295
544
  end
296
545
  end
297
546
  end
298
547
 
299
548
  module ActiveRecord::ConnectionAdapters
300
- remove_const(:SQLite3Adapter) if const_defined?(:SQLite3Adapter)
301
- remove_const(:SQLiteAdapter) if const_defined?(:SQLiteAdapter)
302
-
303
549
  class SQLite3Column < JdbcColumn
304
- include ArJdbc::SQLite3::Column
305
-
306
550
  def initialize(name, *args)
307
551
  if Hash === name
308
552
  super
@@ -311,49 +555,125 @@ module ActiveRecord::ConnectionAdapters
311
555
  end
312
556
  end
313
557
 
314
- def call_discovered_column_callbacks(*)
315
- end
316
-
317
558
  def self.string_to_binary(value)
318
- "\000b64" + [value].pack('m*').split("\n").join('')
559
+ value
319
560
  end
320
561
 
321
562
  def self.binary_to_string(value)
322
- if value.respond_to?(:force_encoding) && value.encoding != Encoding::ASCII_8BIT
563
+ if value.respond_to?(:encoding) && value.encoding != Encoding::ASCII_8BIT
323
564
  value = value.force_encoding(Encoding::ASCII_8BIT)
324
565
  end
566
+ value
567
+ end
325
568
 
326
- if value[0..3] == "\000b64"
327
- value[4..-1].unpack('m*').first
569
+ # @override {ActiveRecord::ConnectionAdapters::JdbcColumn#init_column}
570
+ def init_column(name, default, *args)
571
+ if default =~ /NULL/
572
+ @default = nil
328
573
  else
329
- value
574
+ super
575
+ end
576
+ end
577
+
578
+ # @override {ActiveRecord::ConnectionAdapters::JdbcColumn#default_value}
579
+ def default_value(value)
580
+ # JDBC returns column default strings with actual single quotes :
581
+ return $1 if value =~ /^'(.*)'$/
582
+
583
+ value
584
+ end
585
+
586
+ # @override {ActiveRecord::ConnectionAdapters::Column#type_cast}
587
+ def type_cast(value)
588
+ return nil if value.nil?
589
+ case type
590
+ when :string then value
591
+ when :primary_key
592
+ value.respond_to?(:to_i) ? value.to_i : ( value ? 1 : 0 )
593
+ when :float then value.to_f
594
+ when :decimal then self.class.value_to_decimal(value)
595
+ when :boolean then self.class.value_to_boolean(value)
596
+ else super
597
+ end
598
+ end
599
+
600
+ private
601
+
602
+ # @override {ActiveRecord::ConnectionAdapters::Column#simplified_type}
603
+ def simplified_type(field_type)
604
+ case field_type
605
+ when /boolean/i then :boolean
606
+ when /text/i then :text
607
+ when /varchar/i then :string
608
+ when /int/i then :integer
609
+ when /float/i then :float
610
+ when /real|decimal/i then
611
+ extract_scale(field_type) == 0 ? :integer : :decimal
612
+ when /datetime/i then :datetime
613
+ when /date/i then :date
614
+ when /time/i then :time
615
+ when /blob/i then :binary
616
+ else super
617
+ end
618
+ end
619
+
620
+ # @override {ActiveRecord::ConnectionAdapters::Column#extract_limit}
621
+ def extract_limit(sql_type)
622
+ return nil if sql_type =~ /^(real)\(\d+/i
623
+ super
624
+ end
625
+
626
+ def extract_precision(sql_type)
627
+ case sql_type
628
+ when /^(real)\((\d+)(,\d+)?\)/i then $2.to_i
629
+ else super
630
+ end
631
+ end
632
+
633
+ def extract_scale(sql_type)
634
+ case sql_type
635
+ when /^(real)\((\d+)\)/i then 0
636
+ when /^(real)\((\d+)(,(\d+))\)/i then $4.to_i
637
+ else super
330
638
  end
331
639
  end
332
640
  end
333
641
 
334
- class SQLite3Adapter < JdbcAdapter
642
+ remove_const(:SQLite3Adapter) if const_defined?(:SQLite3Adapter)
643
+
644
+ # Currently our adapter is named the same as what AR5 names its adapter. We will need to get
645
+ # this changed at some point so this can be a unique name and we can extend activerecord
646
+ # ActiveRecord::ConnectionAdapters::SQLite3Adapter. Once we can do that we can remove the
647
+ # module SQLite3 above and remove a majority of this file.
648
+ class SQLite3Adapter < AbstractAdapter
649
+ include ArJdbc::Abstract::Core
335
650
  include ArJdbc::SQLite3
651
+ include ArJdbc::Abstract::DatabaseStatements
652
+ include ArJdbc::Abstract::StatementCache
653
+ include ArJdbc::Abstract::TransactionSupport
336
654
 
337
- def adapter_spec(config)
338
- # return nil to avoid extending ArJdbc::SQLite3, which we've already done
655
+ def begin_isolated_db_transaction(isolation)
656
+ raise ActiveRecord::TransactionIsolationError, 'adapter does not support setting transaction isolation'
339
657
  end
340
658
 
341
- def jdbc_connection_class(spec)
342
- ::ArJdbc::SQLite3.jdbc_connection_class
659
+ # SQLite driver doesn't support all types of insert statements with executeUpdate so
660
+ # make it act like a regular query and the ids will be returned from #last_inserted_id
661
+ # example: INSERT INTO "aircraft" DEFAULT VALUES
662
+ def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
663
+ exec_query(sql, name, binds)
343
664
  end
344
665
 
345
666
  def jdbc_column_class
346
- ActiveRecord::ConnectionAdapters::SQLite3Column
667
+ ::ActiveRecord::ConnectionAdapters::SQLite3Column
347
668
  end
348
- end
349
669
 
350
- SQLiteAdapter = SQLite3Adapter
351
- end
670
+ def jdbc_connection_class(spec)
671
+ self.class.jdbc_connection_class
672
+ end
352
673
 
353
- # Fake out sqlite3/version driver for AR tests
354
- $LOADED_FEATURES << 'sqlite3/version.rb'
355
- module SQLite3
356
- module Version
357
- VERSION = '1.2.6' # query_cache_test.rb requires SQLite3::Version::VERSION > '1.2.5'
674
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
675
+ def self.jdbc_connection_class
676
+ ::ActiveRecord::ConnectionAdapters::SQLite3JdbcConnection
677
+ end
358
678
  end
359
679
  end