activerecord-jdbc-adapter 1.0.3-java → 50.1-java

Sign up to get free protection for your applications and to get access to all the features.
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