activerecord-jdbc-adapter 1.3.0.beta2 → 1.3.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +14 -8
- data/.travis.yml +40 -31
- data/.yardopts +4 -0
- data/Appraisals +2 -5
- data/CONTRIBUTING.md +46 -0
- data/Gemfile +21 -4
- data/Gemfile.lock +42 -17
- data/{History.txt → History.md} +142 -75
- data/README.md +102 -104
- data/RUNNING_TESTS.md +76 -0
- data/Rakefile.jdbc +20 -0
- data/activerecord-jdbc-adapter.gemspec +35 -18
- data/gemfiles/rails23.gemfile +4 -3
- data/gemfiles/rails23.gemfile.lock +9 -6
- data/gemfiles/rails30.gemfile +4 -3
- data/gemfiles/rails30.gemfile.lock +9 -6
- data/gemfiles/rails31.gemfile +4 -3
- data/gemfiles/rails31.gemfile.lock +9 -6
- data/gemfiles/rails32.gemfile +4 -3
- data/gemfiles/rails32.gemfile.lock +17 -14
- data/gemfiles/rails40.gemfile +5 -5
- data/gemfiles/rails40.gemfile.lock +17 -69
- data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
- data/lib/arel/visitors/compat.rb +22 -3
- data/lib/arel/visitors/db2.rb +8 -4
- data/lib/arel/visitors/derby.rb +14 -13
- data/lib/arel/visitors/firebird.rb +5 -4
- data/lib/arel/visitors/hsqldb.rb +11 -9
- data/lib/arel/visitors/sql_server.rb +89 -61
- data/lib/arjdbc.rb +1 -1
- data/lib/arjdbc/db2/adapter.rb +181 -212
- data/lib/arjdbc/db2/as400.rb +31 -18
- data/lib/arjdbc/db2/column.rb +167 -0
- data/lib/arjdbc/db2/connection_methods.rb +2 -0
- data/lib/arjdbc/derby/adapter.rb +206 -107
- data/lib/arjdbc/derby/connection_methods.rb +4 -9
- data/lib/arjdbc/firebird.rb +1 -0
- data/lib/arjdbc/firebird/adapter.rb +202 -64
- data/lib/arjdbc/firebird/connection_methods.rb +20 -0
- data/lib/arjdbc/h2/adapter.rb +56 -36
- data/lib/arjdbc/hsqldb/adapter.rb +99 -68
- data/lib/arjdbc/jdbc/adapter.rb +474 -265
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/adapter_require.rb +8 -7
- data/lib/arjdbc/jdbc/arel_support.rb +132 -0
- data/lib/arjdbc/jdbc/base_ext.rb +8 -7
- data/lib/arjdbc/jdbc/callbacks.rb +16 -10
- data/lib/arjdbc/jdbc/column.rb +25 -3
- data/lib/arjdbc/jdbc/connection.rb +28 -55
- data/lib/arjdbc/jdbc/extension.rb +14 -14
- data/lib/arjdbc/jdbc/java.rb +6 -3
- data/lib/arjdbc/jdbc/jdbc.rake +1 -1
- data/lib/arjdbc/jdbc/quoted_primary_key.rb +2 -2
- data/lib/arjdbc/jdbc/rake_tasks.rb +1 -1
- data/lib/arjdbc/jdbc/type_converter.rb +5 -2
- data/lib/arjdbc/mssql/adapter.rb +160 -280
- data/lib/arjdbc/mssql/column.rb +182 -0
- data/lib/arjdbc/mssql/connection_methods.rb +37 -4
- data/lib/arjdbc/mssql/explain_support.rb +13 -21
- data/lib/arjdbc/mssql/limit_helpers.rb +79 -42
- data/lib/arjdbc/mssql/lock_methods.rb +77 -0
- data/lib/arjdbc/mssql/utils.rb +11 -11
- data/lib/arjdbc/mysql/adapter.rb +165 -247
- data/lib/arjdbc/mysql/column.rb +123 -0
- data/lib/arjdbc/mysql/connection_methods.rb +3 -6
- data/lib/arjdbc/oracle/adapter.rb +282 -288
- data/lib/arjdbc/oracle/column.rb +122 -0
- data/lib/arjdbc/oracle/connection_methods.rb +3 -0
- data/lib/arjdbc/postgresql/adapter.rb +336 -574
- data/lib/arjdbc/postgresql/column.rb +458 -0
- data/lib/arjdbc/postgresql/connection_methods.rb +1 -2
- data/lib/arjdbc/postgresql/schema_creation.rb +38 -0
- data/lib/arjdbc/sqlite3/adapter.rb +189 -145
- data/lib/arjdbc/sqlite3/explain_support.rb +1 -1
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +8 -8
- data/lib/arjdbc/util/quoted_cache.rb +60 -0
- data/lib/arjdbc/util/table_copier.rb +110 -0
- data/lib/arjdbc/version.rb +6 -7
- data/pom.xml +56 -2
- data/rakelib/02-test.rake +72 -83
- data/rakelib/db.rake +29 -17
- data/src/java/arjdbc/ArJdbcModule.java +21 -18
- data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +84 -12
- data/src/java/arjdbc/derby/DerbyModule.java +140 -143
- data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +58 -7
- data/src/java/arjdbc/h2/H2Module.java +43 -0
- data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +7 -6
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1223 -648
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +24 -23
- data/src/java/arjdbc/mysql/MySQLModule.java +33 -32
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +147 -30
- data/src/java/arjdbc/oracle/OracleModule.java +13 -13
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +114 -6
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +166 -36
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +101 -19
- data/src/java/arjdbc/util/QuotingUtils.java +19 -19
- metadata +240 -394
- data/bench/bench_attributes.rb +0 -13
- data/bench/bench_attributes_new.rb +0 -14
- data/bench/bench_create.rb +0 -12
- data/bench/bench_find_all.rb +0 -12
- data/bench/bench_find_all_mt.rb +0 -25
- data/bench/bench_model.rb +0 -85
- data/bench/bench_new.rb +0 -12
- data/bench/bench_new_valid.rb +0 -12
- data/bench/bench_valid.rb +0 -13
- data/lib/arel/engines/sql/compilers/db2_compiler.rb +0 -9
- data/lib/arel/engines/sql/compilers/derby_compiler.rb +0 -6
- data/lib/arel/engines/sql/compilers/h2_compiler.rb +0 -6
- data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +0 -15
- data/lib/arel/engines/sql/compilers/jdbc_compiler.rb +0 -6
- data/lib/arel/engines/sql/compilers/mssql_compiler.rb +0 -46
- data/lib/arjdbc/jdbc/missing_functionality_helper.rb +0 -98
- data/lib/arjdbc/mssql/lock_helpers.rb +0 -76
- data/lib/arjdbc/mssql/tsql_methods.rb +0 -58
- data/lib/arjdbc/postgresql/column_cast.rb +0 -134
- data/test/activerecord/connections/native_jdbc_mysql/connection.rb +0 -25
- data/test/activerecord/jall.sh +0 -7
- data/test/activerecord/jtest.sh +0 -3
- data/test/assets/flowers.jpg +0 -0
- data/test/binary.rb +0 -67
- data/test/db/db2.rb +0 -43
- data/test/db/db2/binary_test.rb +0 -6
- data/test/db/db2/has_many_through_test.rb +0 -6
- data/test/db/db2/rake_test.rb +0 -82
- data/test/db/db2/rake_test_data.sql +0 -35
- data/test/db/db2/reset_column_information_test.rb +0 -5
- data/test/db/db2/serialize_test.rb +0 -6
- data/test/db/db2/simple_test.rb +0 -81
- data/test/db/db2/test_helper.rb +0 -6
- data/test/db/db2/unit_test.rb +0 -73
- data/test/db/derby.rb +0 -12
- data/test/db/derby/binary_test.rb +0 -6
- data/test/db/derby/migration_test.rb +0 -74
- data/test/db/derby/rake_test.rb +0 -96
- data/test/db/derby/reset_column_information_test.rb +0 -6
- data/test/db/derby/row_locking_test.rb +0 -20
- data/test/db/derby/schema_dump_test.rb +0 -5
- data/test/db/derby/serialize_test.rb +0 -6
- data/test/db/derby/simple_test.rb +0 -173
- data/test/db/derby/test_helper.rb +0 -6
- data/test/db/derby/unit_test.rb +0 -32
- data/test/db/derby/xml_column_test.rb +0 -17
- data/test/db/h2.rb +0 -11
- data/test/db/h2/binary_test.rb +0 -6
- data/test/db/h2/change_column_test.rb +0 -68
- data/test/db/h2/identity_column_test.rb +0 -35
- data/test/db/h2/offset_test.rb +0 -49
- data/test/db/h2/rake_test.rb +0 -98
- data/test/db/h2/schema_dump_test.rb +0 -29
- data/test/db/h2/serialize_test.rb +0 -6
- data/test/db/h2/simple_test.rb +0 -56
- data/test/db/hsqldb.rb +0 -11
- data/test/db/hsqldb/binary_test.rb +0 -6
- data/test/db/hsqldb/rake_test.rb +0 -101
- data/test/db/hsqldb/schema_dump_test.rb +0 -19
- data/test/db/hsqldb/serialize_test.rb +0 -6
- data/test/db/hsqldb/simple_test.rb +0 -17
- data/test/db/informix.rb +0 -13
- data/test/db/jdbc.rb +0 -16
- data/test/db/jdbc_derby.rb +0 -14
- data/test/db/jdbc_h2.rb +0 -17
- data/test/db/jdbc_mysql.rb +0 -13
- data/test/db/jdbc_postgres.rb +0 -23
- data/test/db/jndi_config.rb +0 -32
- data/test/db/jndi_pooled_config.rb +0 -32
- data/test/db/mssql.rb +0 -11
- data/test/db/mssql/binary_test.rb +0 -6
- data/test/db/mssql/exec_proc_test.rb +0 -46
- data/test/db/mssql/identity_insert_test.rb +0 -18
- data/test/db/mssql/ignore_system_views_test.rb +0 -40
- data/test/db/mssql/limit_offset_test.rb +0 -190
- data/test/db/mssql/multibyte_test.rb +0 -16
- data/test/db/mssql/multiple_connections_test.rb +0 -71
- data/test/db/mssql/rake_test.rb +0 -143
- data/test/db/mssql/reset_column_information_test.rb +0 -6
- data/test/db/mssql/row_locking_test.rb +0 -7
- data/test/db/mssql/serialize_test.rb +0 -6
- data/test/db/mssql/simple_test.rb +0 -140
- data/test/db/mssql/transaction_test.rb +0 -6
- data/test/db/mssql/types_test.rb +0 -205
- data/test/db/mssql/unit_test.rb +0 -249
- data/test/db/mysql.rb +0 -4
- data/test/db/mysql/_rails_test_mysql.32.out +0 -6585
- data/test/db/mysql/binary_test.rb +0 -6
- data/test/db/mysql/connection_test.rb +0 -51
- data/test/db/mysql/index_length_test.rb +0 -58
- data/test/db/mysql/multibyte_test.rb +0 -10
- data/test/db/mysql/nonstandard_primary_key_test.rb +0 -39
- data/test/db/mysql/rake_test.rb +0 -97
- data/test/db/mysql/reset_column_information_test.rb +0 -6
- data/test/db/mysql/schema_dump_test.rb +0 -228
- data/test/db/mysql/serialize_test.rb +0 -6
- data/test/db/mysql/simple_test.rb +0 -187
- data/test/db/mysql/statement_escaping_test.rb +0 -46
- data/test/db/mysql/transaction_test.rb +0 -6
- data/test/db/mysql/types_test.rb +0 -30
- data/test/db/mysql/unit_test.rb +0 -93
- data/test/db/mysql_config.rb +0 -7
- data/test/db/oracle.rb +0 -27
- data/test/db/oracle/binary_test.rb +0 -6
- data/test/db/oracle/limit_test.rb +0 -24
- data/test/db/oracle/multibyte_test.rb +0 -22
- data/test/db/oracle/rake_test.rb +0 -100
- data/test/db/oracle/reset_column_information_test.rb +0 -6
- data/test/db/oracle/serialize_test.rb +0 -6
- data/test/db/oracle/simple_test.rb +0 -140
- data/test/db/oracle/specific_test.rb +0 -180
- data/test/db/oracle/transaction_test.rb +0 -31
- data/test/db/oracle/unit_test.rb +0 -31
- data/test/db/postgres.rb +0 -11
- data/test/db/postgres/_rails_test_postgres.32.out +0 -6405
- data/test/db/postgres/a_custom_primary_key_test.rb +0 -50
- data/test/db/postgres/active_schema_unit_test.rb +0 -68
- data/test/db/postgres/array_type_test.rb +0 -101
- data/test/db/postgres/binary_test.rb +0 -6
- data/test/db/postgres/connection_test.rb +0 -63
- data/test/db/postgres/data_types_test.rb +0 -703
- data/test/db/postgres/hstore_test.rb +0 -200
- data/test/db/postgres/information_schema_leak_test.rb +0 -30
- data/test/db/postgres/json_test.rb +0 -86
- data/test/db/postgres/ltree_test.rb +0 -51
- data/test/db/postgres/mixed_case_test.rb +0 -29
- data/test/db/postgres/native_types_test.rb +0 -124
- data/test/db/postgres/rake_test.rb +0 -117
- data/test/db/postgres/reserved_test.rb +0 -22
- data/test/db/postgres/reset_column_information_test.rb +0 -6
- data/test/db/postgres/row_locking_test.rb +0 -21
- data/test/db/postgres/schema_dump_test.rb +0 -95
- data/test/db/postgres/schema_test.rb +0 -115
- data/test/db/postgres/simple_test.rb +0 -260
- data/test/db/postgres/table_alias_length_test.rb +0 -16
- data/test/db/postgres/transaction_test.rb +0 -6
- data/test/db/postgres/unit_test.rb +0 -31
- data/test/db/postgres_config.rb +0 -10
- data/test/db/sqlite3.rb +0 -6
- data/test/db/sqlite3/_rails_test_sqlite3.32.out +0 -6274
- data/test/db/sqlite3/has_many_though_test.rb +0 -6
- data/test/db/sqlite3/rake_test.rb +0 -71
- data/test/db/sqlite3/reset_column_information_test.rb +0 -6
- data/test/db/sqlite3/schema_dump_test.rb +0 -6
- data/test/db/sqlite3/serialize_test.rb +0 -6
- data/test/db/sqlite3/simple_test.rb +0 -268
- data/test/db/sqlite3/transaction_test.rb +0 -32
- data/test/db/sqlite3/type_conversion_test.rb +0 -104
- data/test/has_many_through.rb +0 -61
- data/test/informix_simple_test.rb +0 -48
- data/test/jdbc/db2.rb +0 -36
- data/test/jdbc/oracle.rb +0 -34
- data/test/jdbc_column_test.rb +0 -23
- data/test/jdbc_common.rb +0 -16
- data/test/jdbc_connection_test.rb +0 -196
- data/test/jndi_callbacks_test.rb +0 -33
- data/test/jndi_test.rb +0 -55
- data/test/manualTestDatabase.rb +0 -191
- data/test/models/add_not_null_column_to_table.rb +0 -9
- data/test/models/auto_id.rb +0 -15
- data/test/models/binary.rb +0 -18
- data/test/models/custom_pk_name.rb +0 -15
- data/test/models/data_types.rb +0 -40
- data/test/models/entry.rb +0 -41
- data/test/models/mixed_case.rb +0 -22
- data/test/models/reserved_word.rb +0 -15
- data/test/models/rights_and_roles.rb +0 -57
- data/test/models/string_id.rb +0 -17
- data/test/models/thing.rb +0 -17
- data/test/models/topic.rb +0 -32
- data/test/models/validates_uniqueness_of_string.rb +0 -19
- data/test/rails/mysql.rb +0 -13
- data/test/rails/sqlite3/version.rb +0 -6
- data/test/rails_stub.rb +0 -31
- data/test/rake_test_support.rb +0 -298
- data/test/row_locking.rb +0 -102
- data/test/schema_dump.rb +0 -182
- data/test/serialize.rb +0 -275
- data/test/shared_helper.rb +0 -35
- data/test/simple.rb +0 -1317
- data/test/sybase_jtds_simple_test.rb +0 -28
- data/test/sybase_reset_column_information_test.rb +0 -6
- data/test/test_helper.rb +0 -304
- data/test/transaction.rb +0 -109
@@ -4,13 +4,15 @@ require 'arjdbc/hsqldb/explain_support'
|
|
4
4
|
module ArJdbc
|
5
5
|
module HSQLDB
|
6
6
|
include ExplainSupport
|
7
|
-
|
7
|
+
|
8
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcColumn#column_types
|
8
9
|
def self.column_selector
|
9
|
-
[ /hsqldb/i, lambda { |
|
10
|
+
[ /hsqldb/i, lambda { |config, column| column.extend(Column) } ]
|
10
11
|
end
|
11
12
|
|
13
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcColumn
|
12
14
|
module Column
|
13
|
-
|
15
|
+
|
14
16
|
private
|
15
17
|
|
16
18
|
def extract_limit(sql_type)
|
@@ -21,7 +23,7 @@ module ArJdbc
|
|
21
23
|
when /^bigint/i then @sql_type = 'bigint'; limit = 8
|
22
24
|
when /^double/i then @sql_type = 'double'; limit = 8
|
23
25
|
when /^real/i then @sql_type = 'real'; limit = 8
|
24
|
-
# NOTE: once again we get incorrect "limits" from HypesSQL's JDBC
|
26
|
+
# NOTE: once again we get incorrect "limits" from HypesSQL's JDBC
|
25
27
|
# thus yet again we need to fix incorrectly detected limits :
|
26
28
|
when /^integer/i then @sql_type = 'integer'; limit = 4
|
27
29
|
when /^float/i then @sql_type = 'float'; limit = 8
|
@@ -31,79 +33,82 @@ module ArJdbc
|
|
31
33
|
when /^time/i then @sql_type = 'time'; limit = nil
|
32
34
|
when /^date/i then @sql_type = 'date'; limit = nil
|
33
35
|
else
|
34
|
-
# HSQLDB appears to return "LONGVARCHAR(0)" for :text columns,
|
36
|
+
# HSQLDB appears to return "LONGVARCHAR(0)" for :text columns,
|
35
37
|
# which for AR purposes should be interpreted as "no limit" :
|
36
38
|
limit = nil if sql_type =~ /\(0\)$/
|
37
39
|
end
|
38
40
|
limit
|
39
41
|
end
|
40
|
-
|
42
|
+
|
41
43
|
def simplified_type(field_type)
|
42
44
|
case field_type
|
43
|
-
when /
|
44
|
-
when /
|
45
|
-
when /
|
46
|
-
when /
|
47
|
-
when /
|
45
|
+
when /^nvarchar/i then :string
|
46
|
+
when /^character/i then :string
|
47
|
+
when /^longvarchar/i then :text
|
48
|
+
when /int/i then :integer # TINYINT, SMALLINT, BIGINT, INT
|
49
|
+
when /real|double/i then :float
|
50
|
+
when /^bit/i then :boolean
|
51
|
+
when /binary/i then :binary # VARBINARY, LONGVARBINARY
|
48
52
|
else
|
49
53
|
super
|
50
54
|
end
|
51
55
|
end
|
52
|
-
|
56
|
+
|
53
57
|
# Post process default value from JDBC into a Rails-friendly format (columns{-internal})
|
54
58
|
def default_value(value)
|
55
59
|
# JDBC returns column default strings with actual single quotes around the value.
|
56
60
|
return $1 if value =~ /^'(.*)'$/
|
57
61
|
value
|
58
62
|
end
|
59
|
-
|
63
|
+
|
60
64
|
end
|
61
65
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
ADAPTER_NAME
|
66
|
+
# @see ActiveRecord::ConnectionAdapters::Jdbc::ArelSupport
|
67
|
+
def self.arel_visitor_type(config = nil)
|
68
|
+
require 'arel/visitors/hsqldb'; ::Arel::Visitors::HSQLDB
|
66
69
|
end
|
67
70
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
'jdbchsqldb' => ::Arel::Visitors::HSQLDB,
|
73
|
-
}
|
71
|
+
ADAPTER_NAME = 'HSQLDB'.freeze
|
72
|
+
|
73
|
+
def adapter_name
|
74
|
+
ADAPTER_NAME
|
74
75
|
end
|
75
|
-
|
76
|
+
|
76
77
|
NATIVE_DATABASE_TYPES = {
|
77
78
|
:primary_key => "integer GENERATED BY DEFAULT AS IDENTITY(START WITH 0) PRIMARY KEY",
|
78
|
-
:string => { :name => "varchar", :limit => 255 },
|
79
|
+
:string => { :name => "varchar", :limit => 255 }, # :limit => 2147483647
|
79
80
|
:text => { :name => "clob" },
|
80
81
|
:binary => { :name => "blob" },
|
81
|
-
:boolean => { :name => "boolean" },
|
82
|
+
:boolean => { :name => "boolean" }, # :name => "tinyint", :limit => 1
|
83
|
+
:bit => { :name=>"bit" }, # stored as 0/1 on HSQLDB 2.2 (translates true/false)
|
82
84
|
:integer => { :name => "integer", :limit => 4 },
|
83
|
-
:
|
85
|
+
:decimal => { :name => "decimal" }, # :limit => 2147483647
|
86
|
+
:numeric => { :name => "numeric" }, # :limit => 2147483647
|
84
87
|
# NOTE: fix incorrectly detected limits :
|
85
88
|
:tinyint => { :name => "tinyint", :limit => 1 },
|
86
89
|
:smallint => { :name => "smallint", :limit => 2 },
|
87
90
|
:bigint => { :name => "bigint", :limit => 8 },
|
91
|
+
:float => { :name => "float" },
|
88
92
|
:double => { :name => "double", :limit => 8 },
|
89
93
|
:real => { :name => "real", :limit => 8 },
|
94
|
+
:date => { :name=>"date" },
|
95
|
+
:time => { :name=>"time" },
|
96
|
+
:timestamp => { :name=>"timestamp" },
|
97
|
+
:datetime => { :name=>"timestamp" },
|
98
|
+
:other => { :name=>"other" },
|
99
|
+
# NOTE: would be great if AR allowed as to refactor as :
|
100
|
+
# t.column :string, :ignorecase => true
|
101
|
+
:character => { :name => "character" },
|
102
|
+
:varchar_ignorecase => { :name => "varchar_ignorecase" },
|
90
103
|
}
|
91
|
-
|
104
|
+
|
105
|
+
# @override
|
92
106
|
def native_database_types
|
93
|
-
|
94
|
-
end
|
95
|
-
|
96
|
-
def modify_types(types)
|
97
|
-
super(types)
|
98
|
-
types[:primary_key] = NATIVE_DATABASE_TYPES[:primary_key]
|
99
|
-
types[:string] = NATIVE_DATABASE_TYPES[:string].dup
|
100
|
-
#types[:integer][:limit] = nil
|
101
|
-
#types[:boolean][:limit] = nil
|
102
|
-
types[:text][:limit] = nil
|
103
|
-
types
|
107
|
+
NATIVE_DATABASE_TYPES
|
104
108
|
end
|
105
109
|
|
106
|
-
|
110
|
+
# @override
|
111
|
+
def quote(value, column = nil)
|
107
112
|
return value.quoted_id if value.respond_to?(:quoted_id)
|
108
113
|
|
109
114
|
case value
|
@@ -118,8 +123,12 @@ module ArJdbc
|
|
118
123
|
"'#{quote_string(value)}'"
|
119
124
|
end
|
120
125
|
when Time
|
121
|
-
|
126
|
+
column_type = column && column.type
|
127
|
+
if column_type == :time
|
122
128
|
"'#{value.strftime("%H:%M:%S")}'"
|
129
|
+
#elsif column_type == :timestamp # || column_type == :datetime
|
130
|
+
#value = ::ActiveRecord::Base.default_timezone == :utc ? value.getutc : value.getlocal
|
131
|
+
#"'#{value.strftime("%Y-%m-%d %H:%M:%S")}.#{sprintf("%06d", value.usec)}'"
|
123
132
|
else
|
124
133
|
super
|
125
134
|
end
|
@@ -128,7 +137,21 @@ module ArJdbc
|
|
128
137
|
end
|
129
138
|
end
|
130
139
|
|
131
|
-
|
140
|
+
# Quote date/time values for use in SQL input.
|
141
|
+
# Includes microseconds if the value is a Time responding to usec.
|
142
|
+
# @override
|
143
|
+
def quoted_date(value)
|
144
|
+
if value.acts_like?(:time) && value.respond_to?(:usec)
|
145
|
+
usec = sprintf("%06d", value.usec)
|
146
|
+
value = ::ActiveRecord::Base.default_timezone == :utc ? value.getutc : value.getlocal
|
147
|
+
"#{value.strftime("%Y-%m-%d %H:%M:%S")}.#{usec}"
|
148
|
+
else
|
149
|
+
super
|
150
|
+
end
|
151
|
+
end if ::ActiveRecord::VERSION::MAJOR >= 3
|
152
|
+
|
153
|
+
# @override
|
154
|
+
def quote_column_name(name)
|
132
155
|
name = name.to_s
|
133
156
|
if name =~ /[-]/
|
134
157
|
%Q{"#{name.upcase}"}
|
@@ -137,13 +160,15 @@ module ArJdbc
|
|
137
160
|
end
|
138
161
|
end
|
139
162
|
|
163
|
+
# @override
|
140
164
|
def add_column(table_name, column_name, type, options = {})
|
141
165
|
add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
|
142
166
|
add_column_options!(add_column_sql, options)
|
143
167
|
execute(add_column_sql)
|
144
168
|
end
|
145
169
|
|
146
|
-
|
170
|
+
# @override
|
171
|
+
def change_column(table_name, column_name, type, options = {})
|
147
172
|
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} #{type_to_sql(type, options[:limit])}"
|
148
173
|
end
|
149
174
|
|
@@ -151,17 +176,18 @@ module ArJdbc
|
|
151
176
|
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DEFAULT #{quote(default)}"
|
152
177
|
end
|
153
178
|
|
179
|
+
# @override
|
154
180
|
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
155
181
|
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} RENAME TO #{new_column_name}"
|
156
182
|
end
|
157
183
|
|
158
|
-
#
|
184
|
+
# @override
|
159
185
|
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
160
186
|
return super if defined?(::Jdbc::H2) || type.to_s != 'integer' || limit == nil
|
161
|
-
|
162
187
|
type
|
163
188
|
end
|
164
189
|
|
190
|
+
# @override
|
165
191
|
def rename_table(name, new_name)
|
166
192
|
execute "ALTER TABLE #{name} RENAME TO #{new_name}"
|
167
193
|
end
|
@@ -171,46 +197,47 @@ module ArJdbc
|
|
171
197
|
Integer(identity.nil? ? 0 : identity)
|
172
198
|
end
|
173
199
|
|
200
|
+
# @private
|
174
201
|
def _execute(sql, name = nil)
|
175
202
|
result = super
|
176
203
|
self.class.insert?(sql) ? last_insert_id : result
|
177
204
|
end
|
178
205
|
private :_execute
|
179
206
|
|
180
|
-
|
207
|
+
# @note Only used with (non-AREL) ActiveRecord **2.3**.
|
208
|
+
# @see Arel::Visitors::HSQLDB#limit_offset
|
209
|
+
def add_limit_offset!(sql, options)
|
181
210
|
if sql =~ /^select/i
|
182
211
|
offset = options[:offset] || 0
|
183
|
-
bef = sql[7..-1]
|
184
212
|
if limit = options[:limit]
|
185
|
-
sql.replace "SELECT LIMIT #{offset} #{limit} #{
|
213
|
+
sql.replace "SELECT LIMIT #{offset} #{limit} #{sql[7..-1]}"
|
186
214
|
elsif offset > 0
|
187
|
-
sql.replace "SELECT LIMIT #{offset} 0 #{
|
215
|
+
sql.replace "SELECT LIMIT #{offset} 0 #{sql[7..-1]}"
|
188
216
|
end
|
189
217
|
end
|
190
|
-
end
|
218
|
+
end if ::ActiveRecord::VERSION::MAJOR < 3
|
191
219
|
|
220
|
+
# @override
|
192
221
|
def empty_insert_statement_value
|
193
|
-
# on HSQLDB only work with tables that have a default value for each
|
222
|
+
# on HSQLDB only work with tables that have a default value for each
|
194
223
|
# and every column ... you'll need to avoid `Model.create!` on 4.0
|
195
224
|
'DEFAULT VALUES'
|
196
225
|
end
|
197
|
-
|
198
|
-
# filter out system tables (
|
199
|
-
#
|
200
|
-
# now takes an optional block filter so we can screen out
|
201
|
-
# rows corresponding to system tables. HSQLDB names its
|
202
|
-
# system tables SYSTEM.*, but H2 seems to name them without
|
203
|
-
# any kind of convention
|
226
|
+
|
227
|
+
# We filter out HSQLDB's system tables (named "SYSTEM.*").
|
228
|
+
# @override
|
204
229
|
def tables
|
205
230
|
@connection.tables.select { |row| row.to_s !~ /^system_/i }
|
206
231
|
end
|
207
232
|
|
233
|
+
# @override
|
208
234
|
def remove_index(table_name, options = {})
|
209
235
|
execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
|
210
236
|
end
|
211
|
-
|
237
|
+
|
238
|
+
# @override
|
212
239
|
def structure_dump
|
213
|
-
execute('SCRIPT').map do |result|
|
240
|
+
execute('SCRIPT').map do |result|
|
214
241
|
# [ { 'command' => SQL }, { 'command' ... }, ... ]
|
215
242
|
case sql = result.first[1] # ['command']
|
216
243
|
when /CREATE USER SA PASSWORD DIGEST .*?/i then nil
|
@@ -221,24 +248,28 @@ module ArJdbc
|
|
221
248
|
end.compact.join("\n\n")
|
222
249
|
end
|
223
250
|
|
251
|
+
# @see #structure_dump
|
224
252
|
def structure_load(dump)
|
225
253
|
dump.each_line("\n\n") { |ddl| execute(ddl) }
|
226
254
|
end
|
227
|
-
|
255
|
+
|
228
256
|
def shutdown
|
229
257
|
execute 'SHUTDOWN'
|
230
258
|
end
|
231
|
-
|
232
|
-
|
259
|
+
|
260
|
+
# @private
|
261
|
+
def recreate_database(name = nil, options = {})
|
233
262
|
drop_database(name)
|
234
263
|
create_database(name, options)
|
235
264
|
end
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
265
|
+
|
266
|
+
# @private
|
267
|
+
def create_database(name = nil, options = {}); end
|
268
|
+
|
269
|
+
# @private
|
270
|
+
def drop_database(name = nil)
|
240
271
|
execute('DROP SCHEMA PUBLIC CASCADE')
|
241
272
|
end
|
242
|
-
|
273
|
+
|
243
274
|
end
|
244
275
|
end
|
data/lib/arjdbc/jdbc/adapter.rb
CHANGED
@@ -8,59 +8,99 @@ require 'arjdbc/jdbc/connection_methods'
|
|
8
8
|
require 'arjdbc/jdbc/driver'
|
9
9
|
require 'arjdbc/jdbc/column'
|
10
10
|
require 'arjdbc/jdbc/connection'
|
11
|
+
require 'arjdbc/jdbc/arel_support'
|
11
12
|
require 'arjdbc/jdbc/callbacks'
|
12
13
|
require 'arjdbc/jdbc/extension'
|
13
14
|
require 'arjdbc/jdbc/type_converter'
|
14
15
|
|
15
16
|
module ActiveRecord
|
16
17
|
module ConnectionAdapters
|
18
|
+
# Built on top of `ActiveRecord::ConnectionAdapters::AbstractAdapter` which
|
19
|
+
# provides the abstract interface for database-specific functionality, this
|
20
|
+
# class serves 2 purposes in AR-JDBC :
|
21
|
+
# - as a base class for sub-classes
|
22
|
+
# - usable standalone (or with a mixed in adapter spec module)
|
23
|
+
#
|
24
|
+
# Historically this class is mostly been used standalone and that's still a
|
25
|
+
# valid use-case esp. since (with it's `arjdbc.jdbc.RubyJdbcConnectionClass`)
|
26
|
+
# JDBC provides a unified interface for all databases in Java it tries to do
|
27
|
+
# it's best implementing all `ActiveRecord` functionality on top of that.
|
28
|
+
# This might no be perfect that's why it checks for a `config[:adapter_spec]`
|
29
|
+
# module (or tries to resolve one from the JDBC driver's meta-data) and if
|
30
|
+
# the database has "extended" AR-JDBC support mixes in the given module for
|
31
|
+
# each adapter instance.
|
32
|
+
# This is sufficient for most database specific specs we support, but for
|
33
|
+
# compatibility with native (MRI) adapters it's perfectly fine to sub-class
|
34
|
+
# the adapter and override some of its API methods.
|
17
35
|
class JdbcAdapter < AbstractAdapter
|
18
36
|
extend ShadowCoreMethods
|
19
|
-
|
20
|
-
include
|
21
|
-
|
37
|
+
|
38
|
+
include Jdbc::ArelSupport
|
39
|
+
include Jdbc::ConnectionPoolCallbacks
|
40
|
+
|
22
41
|
attr_reader :config
|
23
|
-
|
24
|
-
|
25
|
-
|
42
|
+
|
43
|
+
# Initializes the (JDBC connection) adapter instance.
|
44
|
+
# The passed configuration Hash's keys are symbolized, thus changes to
|
45
|
+
# the original `config` keys won't be reflected in the adapter.
|
46
|
+
# If the adapter's sub-class or the spec module that this instance will
|
47
|
+
# extend in responds to `configure_connection` than it will be called.
|
48
|
+
# @param connection an (optional) connection instance
|
49
|
+
# @param logger the `ActiveRecord::Base.logger` to use (or nil)
|
50
|
+
# @param config the database configuration
|
51
|
+
# @note `initialize(logger, config)` with 2 arguments is supported as well
|
52
|
+
def initialize(connection, logger, config = nil)
|
53
|
+
if config.nil? && logger.respond_to?(:key?) # (logger, config)
|
26
54
|
config, logger, connection = logger, connection, nil
|
27
55
|
end
|
28
|
-
|
29
|
-
@config = config
|
30
|
-
|
56
|
+
|
57
|
+
@config = config.respond_to?(:symbolize_keys) ? config.symbolize_keys : config
|
58
|
+
# NOTE: JDBC 4.0 drivers support checking if connection isValid
|
59
|
+
# thus no need to @config[:connection_alive_sql] ||= 'SELECT 1'
|
60
|
+
#
|
61
|
+
# NOTE: setup to retry 5-times previously - maybe do not set at all ?
|
62
|
+
@config[:retry_count] ||= 1
|
63
|
+
|
31
64
|
@config[:adapter_spec] = adapter_spec(@config) unless @config.key?(:adapter_spec)
|
32
65
|
spec = @config[:adapter_spec]
|
33
|
-
|
34
|
-
connection ||= jdbc_connection_class(spec).new(@config)
|
35
|
-
|
36
|
-
super(connection, logger)
|
37
|
-
|
66
|
+
|
38
67
|
# kind of like `extend ArJdbc::MyDB if self.class == JdbcAdapter` :
|
39
68
|
klass = @config[:adapter_class]
|
40
69
|
extend spec if spec && ( ! klass || klass == JdbcAdapter)
|
41
|
-
|
42
|
-
connection.
|
43
|
-
|
70
|
+
# NOTE: adapter spec's init_connection only called if instantiated here :
|
71
|
+
connection ||= jdbc_connection_class(spec).new(@config, self)
|
72
|
+
|
73
|
+
super(connection, logger)
|
74
|
+
|
44
75
|
# NOTE: should not be necessary for JNDI due reconnect! on checkout :
|
45
76
|
configure_connection if respond_to?(:configure_connection)
|
46
|
-
|
47
|
-
JndiConnectionPoolCallbacks.prepare(self, connection)
|
48
|
-
|
49
|
-
@visitor = new_visitor
|
77
|
+
|
78
|
+
Jdbc::JndiConnectionPoolCallbacks.prepare(self, connection)
|
79
|
+
|
80
|
+
@visitor = new_visitor # nil if no AREL (AR-2.3)
|
50
81
|
end
|
51
|
-
|
82
|
+
|
83
|
+
# Returns the (JDBC) connection class to be used for this adapter.
|
84
|
+
# This is used by (database specific) spec modules to override the class
|
85
|
+
# used assuming some of the available methods have been re-defined.
|
86
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcConnection
|
52
87
|
def jdbc_connection_class(spec)
|
53
88
|
connection_class = spec.jdbc_connection_class if spec && spec.respond_to?(:jdbc_connection_class)
|
54
89
|
connection_class ? connection_class : ::ActiveRecord::ConnectionAdapters::JdbcConnection
|
55
90
|
end
|
56
91
|
|
92
|
+
# Returns the (JDBC) `ActiveRecord` column class for this adapter.
|
93
|
+
# This is used by (database specific) spec modules to override the class.
|
94
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcColumn
|
57
95
|
def jdbc_column_class
|
58
|
-
ActiveRecord::ConnectionAdapters::JdbcColumn
|
96
|
+
::ActiveRecord::ConnectionAdapters::JdbcColumn
|
59
97
|
end
|
60
98
|
|
61
|
-
# Retrieve the raw java.sql.Connection object.
|
62
|
-
# The unwrap parameter is useful if an attempt to unwrap a pooled (JNDI)
|
63
|
-
# connection should be made - to really return the native
|
99
|
+
# Retrieve the raw `java.sql.Connection` object.
|
100
|
+
# The unwrap parameter is useful if an attempt to unwrap a pooled (JNDI)
|
101
|
+
# connection should be made - to really return the 'native' JDBC object.
|
102
|
+
# @param unwrap [true, false] whether to unwrap the connection object
|
103
|
+
# @return [Java::JavaSql::Connection] the JDBC connection
|
64
104
|
def jdbc_connection(unwrap = nil)
|
65
105
|
java_connection = raw_connection.connection
|
66
106
|
return java_connection unless unwrap
|
@@ -75,7 +115,14 @@ module ActiveRecord
|
|
75
115
|
end
|
76
116
|
end
|
77
117
|
|
78
|
-
# Locate specialized adapter specification
|
118
|
+
# Locate the specialized (database specific) adapter specification module
|
119
|
+
# if one exists based on provided configuration data. This module will than
|
120
|
+
# extend an instance of the adapter (unless an `:adapter_class` provided).
|
121
|
+
#
|
122
|
+
# This method is called during {#initialize} unless an explicit
|
123
|
+
# `config[:adapter_spec]` is set.
|
124
|
+
# @param config the configuration to check for `:adapter_spec`
|
125
|
+
# @return [Module] the database specific module
|
79
126
|
def adapter_spec(config)
|
80
127
|
dialect = (config[:dialect] || config[:driver]).to_s
|
81
128
|
::ArJdbc.modules.each do |constant| # e.g. ArJdbc::MySQL
|
@@ -87,7 +134,7 @@ module ActiveRecord
|
|
87
134
|
|
88
135
|
if (config[:jndi] || config[:data_source]) && ! config[:dialect]
|
89
136
|
begin
|
90
|
-
data_source = config[:data_source] ||
|
137
|
+
data_source = config[:data_source] ||
|
91
138
|
Java::JavaxNaming::InitialContext.new.lookup(config[:jndi])
|
92
139
|
connection = data_source.getConnection
|
93
140
|
config[:dialect] = connection.getMetaData.getDatabaseProductName
|
@@ -103,33 +150,40 @@ module ActiveRecord
|
|
103
150
|
nil
|
104
151
|
end
|
105
152
|
|
106
|
-
|
107
|
-
|
153
|
+
ADAPTER_NAME = 'JDBC'.freeze
|
154
|
+
|
155
|
+
# @return [String] the 'JDBC' adapter name.
|
156
|
+
def adapter_name
|
157
|
+
ADAPTER_NAME
|
108
158
|
end
|
109
159
|
|
110
|
-
|
111
|
-
|
160
|
+
# @override
|
161
|
+
# Will return true even when native adapter classes passed in
|
162
|
+
# e.g. `jdbc_adapter.is_a? ConnectionAdapter::PostgresqlAdapter`
|
163
|
+
#
|
164
|
+
# This is only necessary (for built-in adapters) when
|
165
|
+
# `config[:adapter_class]` is forced to `nil` and the `:adapter_spec`
|
166
|
+
# module is used to extend the `JdbcAdapter`, otherwise we replace the
|
167
|
+
# class constants for built-in adapters (MySQL, PostgreSQL and SQLite3).
|
168
|
+
def is_a?(klass)
|
169
|
+
# This is to fake out current_adapter? conditional logic in AR tests
|
170
|
+
if klass.is_a?(Class) && klass.name =~ /#{adapter_name}Adapter$/i
|
171
|
+
true
|
172
|
+
else
|
173
|
+
super
|
174
|
+
end
|
112
175
|
end
|
113
176
|
|
177
|
+
# @deprecated re-implemented - no longer used
|
178
|
+
# @return [Hash] the AREL visitor to use
|
179
|
+
# If there's a `self.arel2_visitors(config)` method on the adapter
|
180
|
+
# spec than it is preferred and will be used instead of this one.
|
114
181
|
def self.arel2_visitors(config)
|
115
182
|
{ 'jdbc' => ::Arel::Visitors::ToSql }
|
116
183
|
end
|
117
184
|
|
118
|
-
#
|
119
|
-
|
120
|
-
config = pool.spec.config
|
121
|
-
adapter = config[:adapter] # e.g. "sqlite3" (based on {#adapter_name})
|
122
|
-
unless visitor = ::Arel::Visitors::VISITORS[ adapter ]
|
123
|
-
adapter_spec = config[:adapter_spec] || self # e.g. ArJdbc::SQLite3
|
124
|
-
if adapter =~ /^(jdbc|jndi)$/
|
125
|
-
visitor = adapter_spec.arel2_visitors(config).values.first
|
126
|
-
else
|
127
|
-
visitor = adapter_spec.arel2_visitors(config)[adapter]
|
128
|
-
end
|
129
|
-
end
|
130
|
-
( prepared_statements?(config) ? visitor : bind_substitution(visitor) ).new(pool)
|
131
|
-
end
|
132
|
-
|
185
|
+
# @deprecated re-implemented - no longer used
|
186
|
+
# @see #arel2_visitors
|
133
187
|
def self.configure_arel2_visitors(config)
|
134
188
|
visitors = ::Arel::Visitors::VISITORS
|
135
189
|
klass = config[:adapter_spec]
|
@@ -144,83 +198,45 @@ module ActiveRecord
|
|
144
198
|
visitor
|
145
199
|
end
|
146
200
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
end
|
157
|
-
protected :new_visitor
|
158
|
-
|
159
|
-
unless defined? ::Arel::Visitors::VISITORS # NO-OP when no AREL (AR-2.3)
|
160
|
-
def self.configure_arel2_visitors(config); end
|
161
|
-
def new_visitor(config = self.config); end
|
162
|
-
end
|
163
|
-
|
164
|
-
@@bind_substitutions = nil
|
165
|
-
|
166
|
-
# @return a {#Arel::Visitors::BindVisitor} class for given visitor type
|
167
|
-
def self.bind_substitution(visitor)
|
168
|
-
# NOTE: similar convention as in AR (but no base substitution type) :
|
169
|
-
# class BindSubstitution < ::Arel::Visitors::ToSql
|
170
|
-
# include ::Arel::Visitors::BindVisitor
|
171
|
-
# end
|
172
|
-
return const_get(:BindSubstitution) if const_defined?(:BindSubstitution)
|
173
|
-
|
174
|
-
@@bind_substitutions ||= Java::JavaUtil::HashMap.new
|
175
|
-
unless bind_visitor = @@bind_substitutions.get(visitor)
|
176
|
-
@@bind_substitutions.synchronized do
|
177
|
-
unless @@bind_substitutions.get(visitor)
|
178
|
-
bind_visitor = Class.new(visitor) do
|
179
|
-
include ::Arel::Visitors::BindVisitor
|
180
|
-
end
|
181
|
-
@@bind_substitutions.put(visitor, bind_visitor)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
bind_visitor = @@bind_substitutions.get(visitor)
|
201
|
+
# DB specific types are detected but adapter specs (or extenders) are
|
202
|
+
# expected to hand tune these types for concrete databases.
|
203
|
+
# @return [Hash] the native database types
|
204
|
+
# @override
|
205
|
+
def native_database_types
|
206
|
+
@native_database_types ||= begin
|
207
|
+
types = @connection.native_database_types
|
208
|
+
modify_types(types)
|
209
|
+
types
|
185
210
|
end
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
end
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
# @override default implementation (does nothing silently)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Allows for modification of the detected native types.
|
214
|
+
# @param types the resolved native database types
|
215
|
+
# @see #native_database_types
|
216
|
+
def modify_types(types)
|
217
|
+
types
|
218
|
+
end
|
219
|
+
|
220
|
+
# Abstract adapter default implementation does nothing silently.
|
221
|
+
# @override
|
199
222
|
def structure_dump
|
200
223
|
raise NotImplementedError, "structure_dump not supported"
|
201
224
|
end
|
202
|
-
|
203
|
-
def is_a?(klass) # :nodoc:
|
204
|
-
# This is to fake out current_adapter? conditional logic in AR tests
|
205
|
-
if Class === klass && klass.name =~ /#{adapter_name}Adapter$/i
|
206
|
-
true
|
207
|
-
else
|
208
|
-
super
|
209
|
-
end
|
210
|
-
end
|
211
225
|
|
226
|
+
# JDBC adapters support migration.
|
227
|
+
# @return [true]
|
228
|
+
# @override
|
212
229
|
def supports_migrations?
|
213
230
|
true
|
214
231
|
end
|
215
232
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
def database_name # :nodoc:
|
233
|
+
# Returns the underlying database name.
|
234
|
+
# @override
|
235
|
+
def database_name
|
221
236
|
@connection.database_name
|
222
237
|
end
|
223
238
|
|
239
|
+
# @private
|
224
240
|
def native_sql_to_type(type)
|
225
241
|
if /^(.*?)\(([0-9]+)\)/ =~ type
|
226
242
|
tname, limit = $1, $2.to_i
|
@@ -232,7 +248,7 @@ module ActiveRecord
|
|
232
248
|
if name == :primary_key
|
233
249
|
next
|
234
250
|
end
|
235
|
-
if val[:name].downcase == tname.downcase &&
|
251
|
+
if val[:name].downcase == tname.downcase &&
|
236
252
|
( val[:limit].nil? || val[:limit].to_i == limit )
|
237
253
|
return name, limit
|
238
254
|
end
|
@@ -256,47 +272,147 @@ module ActiveRecord
|
|
256
272
|
return nil, nil
|
257
273
|
end
|
258
274
|
|
275
|
+
# @override
|
259
276
|
def active?
|
260
277
|
@connection.active?
|
261
278
|
end
|
262
279
|
|
280
|
+
# @override
|
263
281
|
def reconnect!
|
264
282
|
@connection.reconnect! # handles adapter.configure_connection
|
265
283
|
@connection
|
266
284
|
end
|
267
285
|
|
286
|
+
# @override
|
268
287
|
def disconnect!
|
269
288
|
@connection.disconnect!
|
270
289
|
end
|
271
290
|
|
272
291
|
if ActiveRecord::VERSION::MAJOR < 3
|
273
|
-
|
274
|
-
|
275
|
-
|
292
|
+
|
293
|
+
# @private
|
294
|
+
def jdbc_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
295
|
+
insert_sql(sql, name, pk, id_value, sequence_name)
|
276
296
|
end
|
277
297
|
alias_chained_method :insert, :query_dirty, :jdbc_insert
|
278
|
-
|
279
|
-
|
298
|
+
|
299
|
+
# @private
|
300
|
+
def jdbc_update(sql, name = nil, binds = [])
|
280
301
|
execute(sql, name, binds)
|
281
302
|
end
|
282
303
|
alias_chained_method :update, :query_dirty, :jdbc_update
|
283
|
-
|
284
|
-
|
304
|
+
|
305
|
+
# @private
|
306
|
+
def jdbc_select_all(sql, name = nil, binds = [])
|
285
307
|
select(sql, name, binds)
|
286
308
|
end
|
287
309
|
alias_chained_method :select_all, :query_cache, :jdbc_select_all
|
288
|
-
|
310
|
+
|
311
|
+
end
|
312
|
+
|
313
|
+
# @note Used on AR 2.3 and 3.0
|
314
|
+
# @override
|
315
|
+
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
316
|
+
id = execute(sql, name)
|
317
|
+
id_value || id
|
289
318
|
end
|
290
|
-
|
319
|
+
|
291
320
|
def columns(table_name, name = nil)
|
292
321
|
@connection.columns(table_name.to_s)
|
293
322
|
end
|
294
|
-
|
295
|
-
#
|
296
|
-
#
|
297
|
-
|
298
|
-
|
299
|
-
|
323
|
+
|
324
|
+
# Starts a database transaction.
|
325
|
+
# @override
|
326
|
+
def begin_db_transaction
|
327
|
+
@connection.begin
|
328
|
+
end
|
329
|
+
|
330
|
+
# Commits the current database transaction.
|
331
|
+
# @override
|
332
|
+
def commit_db_transaction
|
333
|
+
@connection.commit
|
334
|
+
end
|
335
|
+
|
336
|
+
# Rolls back the current database transaction.
|
337
|
+
# @override
|
338
|
+
def rollback_db_transaction
|
339
|
+
@connection.rollback
|
340
|
+
end
|
341
|
+
|
342
|
+
# Starts a database transaction.
|
343
|
+
# @param isolation the transaction isolation to use
|
344
|
+
# @since 1.3.0
|
345
|
+
# @override on **AR-4.0**
|
346
|
+
def begin_isolated_db_transaction(isolation)
|
347
|
+
@connection.begin(isolation)
|
348
|
+
end
|
349
|
+
|
350
|
+
# Does this adapter support setting the isolation level for a transaction?
|
351
|
+
# Unlike 'plain' `ActiveRecord` we allow checking for concrete transaction
|
352
|
+
# isolation level support by the database.
|
353
|
+
# @param level optional to check if we support a specific isolation level
|
354
|
+
# @since 1.3.0
|
355
|
+
# @extension added optional level parameter
|
356
|
+
def supports_transaction_isolation?(level = nil)
|
357
|
+
@connection.supports_transaction_isolation?(level)
|
358
|
+
end
|
359
|
+
|
360
|
+
# Does our database (+ its JDBC driver) support save-points?
|
361
|
+
# @since 1.3.0
|
362
|
+
# @override
|
363
|
+
def supports_savepoints?
|
364
|
+
@connection.supports_savepoints?
|
365
|
+
end
|
366
|
+
|
367
|
+
# Creates a (transactional) save-point one can rollback to.
|
368
|
+
# Unlike 'plain' `ActiveRecord` it is allowed to pass a save-point name.
|
369
|
+
# @param name the save-point name
|
370
|
+
# @return save-point name (even if nil passed will be generated)
|
371
|
+
# @since 1.3.0
|
372
|
+
# @extension added optional name parameter
|
373
|
+
def create_savepoint(name = current_savepoint_name(true))
|
374
|
+
@connection.create_savepoint(name)
|
375
|
+
end
|
376
|
+
|
377
|
+
# Transaction rollback to a given (previously created) save-point.
|
378
|
+
# If no save-point name given rollback to the last created one.
|
379
|
+
# @param name the save-point name
|
380
|
+
# @since 1.3.0
|
381
|
+
# @extension added optional name parameter
|
382
|
+
def rollback_to_savepoint(name = current_savepoint_name)
|
383
|
+
@connection.rollback_savepoint(name)
|
384
|
+
end
|
385
|
+
|
386
|
+
# Release a previously created save-point.
|
387
|
+
# @note Save-points are auto-released with the transaction they're created
|
388
|
+
# in (on transaction commit or roll-back).
|
389
|
+
# @param name the save-point name
|
390
|
+
# @since 1.3.0
|
391
|
+
# @extension added optional name parameter
|
392
|
+
def release_savepoint(name = current_savepoint_name)
|
393
|
+
@connection.release_savepoint(name)
|
394
|
+
end
|
395
|
+
|
396
|
+
# Due tracking of save-points created in a LIFO manner, always returns
|
397
|
+
# the correct name if any (last) save-point has been marked and not released.
|
398
|
+
# Otherwise when creating a save-point same naming convention as
|
399
|
+
# `ActiveRecord` uses ("active_record_" prefix) will be returned.
|
400
|
+
# @return [String] the current save-point name
|
401
|
+
# @since 1.3.0
|
402
|
+
# @override
|
403
|
+
def current_savepoint_name(create = nil)
|
404
|
+
return "active_record_#{open_transactions}" if create
|
405
|
+
@connection.marked_savepoint_names.last || "active_record_#{open_transactions}"
|
406
|
+
end
|
407
|
+
|
408
|
+
# Executes a SQL query in the context of this connection using the bind
|
409
|
+
# substitutes.
|
410
|
+
# @param sql the query string (or AREL object)
|
411
|
+
# @param name logging marker for the executed SQL statement log entry
|
412
|
+
# @param binds the bind parameters
|
413
|
+
# @return [ActiveRecord::Result] or [Array] on **AR-2.3**
|
414
|
+
# @override available since **AR-3.1**
|
415
|
+
def exec_query(sql, name = 'SQL', binds = [])
|
300
416
|
if prepared_statements?
|
301
417
|
log(sql, name, binds) { @connection.execute_query(sql, binds) }
|
302
418
|
else
|
@@ -305,35 +421,59 @@ module ActiveRecord
|
|
305
421
|
end
|
306
422
|
end
|
307
423
|
|
308
|
-
# Executes insert
|
309
|
-
#
|
310
|
-
# the executed
|
311
|
-
|
312
|
-
|
313
|
-
|
424
|
+
# Executes an insert statement in the context of this connection.
|
425
|
+
# @param sql the query string (or AREL object)
|
426
|
+
# @param name logging marker for the executed SQL statement log entry
|
427
|
+
# @param binds the bind parameters
|
428
|
+
# @override available since **AR-3.1**
|
429
|
+
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
|
430
|
+
if prepared_statements?
|
431
|
+
log(sql, name || 'SQL', binds) { @connection.execute_insert(sql, binds) }
|
432
|
+
else
|
433
|
+
sql = suble_binds sql, binds
|
434
|
+
log(sql, name || 'SQL') { @connection.execute_insert(sql) }
|
435
|
+
end
|
314
436
|
end
|
315
437
|
|
316
|
-
# Executes delete
|
317
|
-
#
|
318
|
-
# the executed
|
319
|
-
|
320
|
-
|
321
|
-
|
438
|
+
# Executes a delete statement in the context of this connection.
|
439
|
+
# @param sql the query string (or AREL object)
|
440
|
+
# @param name logging marker for the executed SQL statement log entry
|
441
|
+
# @param binds the bind parameters
|
442
|
+
# @override available since **AR-3.1**
|
443
|
+
def exec_delete(sql, name, binds)
|
444
|
+
if prepared_statements?
|
445
|
+
log(sql, name || 'SQL', binds) { @connection.execute_delete(sql, binds) }
|
446
|
+
else
|
447
|
+
sql = suble_binds sql, binds
|
448
|
+
log(sql, name || 'SQL') { @connection.execute_delete(sql) }
|
449
|
+
end
|
322
450
|
end
|
323
451
|
|
324
|
-
# Executes update
|
325
|
-
#
|
326
|
-
# the executed
|
327
|
-
|
328
|
-
|
329
|
-
|
452
|
+
# # Executes an update statement in the context of this connection.
|
453
|
+
# @param sql the query string (or AREL object)
|
454
|
+
# @param name logging marker for the executed SQL statement log entry
|
455
|
+
# @param binds the bind parameters
|
456
|
+
# @override available since **AR-3.1**
|
457
|
+
def exec_update(sql, name, binds)
|
458
|
+
if prepared_statements?
|
459
|
+
log(sql, name || 'SQL', binds) { @connection.execute_update(sql, binds) }
|
460
|
+
else
|
461
|
+
sql = suble_binds sql, binds
|
462
|
+
log(sql, name || 'SQL') { @connection.execute_update(sql) }
|
463
|
+
end
|
330
464
|
end
|
331
|
-
|
465
|
+
|
332
466
|
# Similar to {#exec_query} except it returns "raw" results in an array
|
333
|
-
# where each rows is a hash with keys as columns (just like Rails used to
|
467
|
+
# where each rows is a hash with keys as columns (just like Rails used to
|
334
468
|
# do up until 3.0) instead of wrapping them in a {#ActiveRecord::Result}.
|
335
|
-
|
336
|
-
|
469
|
+
# @param sql the query string (or AREL object)
|
470
|
+
# @param name logging marker for the executed SQL statement log entry
|
471
|
+
# @param binds the bind parameters
|
472
|
+
# @yield [v1, v2] depending on the row values returned from the query
|
473
|
+
# In case a block is given it will yield each row from the result set
|
474
|
+
# instead of returning mapped query results in an array.
|
475
|
+
# @return [Array] unless a block is given
|
476
|
+
def exec_query_raw(sql, name = 'SQL', binds = [], &block)
|
337
477
|
if prepared_statements?
|
338
478
|
log(sql, name, binds) { @connection.execute_query_raw(sql, binds, &block) }
|
339
479
|
else
|
@@ -341,252 +481,321 @@ module ActiveRecord
|
|
341
481
|
log(sql, name) { @connection.execute_query_raw(sql, &block) }
|
342
482
|
end
|
343
483
|
end
|
344
|
-
|
484
|
+
|
485
|
+
# @private
|
486
|
+
# @override
|
345
487
|
def select_rows(sql, name = nil)
|
346
488
|
exec_query_raw(sql, name).map!(&:values)
|
347
489
|
end
|
348
|
-
|
490
|
+
|
349
491
|
if ActiveRecord::VERSION::MAJOR > 3 # expects AR::Result e.g. from select_all
|
350
|
-
|
492
|
+
|
493
|
+
# @private
|
351
494
|
def select(sql, name = nil, binds = [])
|
352
|
-
exec_query(sql, name, binds)
|
495
|
+
exec_query(to_sql(sql, binds), name, binds)
|
353
496
|
end
|
354
|
-
|
497
|
+
|
355
498
|
else
|
356
|
-
|
499
|
+
|
500
|
+
# @private
|
357
501
|
def select(sql, name = nil, binds = []) # NOTE: only (sql, name) on AR < 3.1
|
358
|
-
exec_query_raw(sql, name, binds)
|
502
|
+
exec_query_raw(to_sql(sql, binds), name, binds)
|
359
503
|
end
|
360
|
-
|
504
|
+
|
361
505
|
end
|
362
|
-
|
363
|
-
if ActiveRecord::VERSION::MAJOR < 3 # 2.3.x
|
364
|
-
|
365
|
-
# NOTE: 2.3 log(sql, name) while does not like `name == nil`
|
366
|
-
|
506
|
+
|
367
507
|
# Executes the SQL statement in the context of this connection.
|
368
|
-
|
369
|
-
|
508
|
+
# The return value from this method depends on the SQL type (whether
|
509
|
+
# it's a SELECT, INSERT etc.). For INSERTs a generated id might get
|
510
|
+
# returned while for UPDATE statements the affected row count.
|
511
|
+
# Please note that this method returns "raw" results (in an array) for
|
512
|
+
# statements that return a result set, while {#exec_query} is expected to
|
513
|
+
# return a `ActiveRecord::Result` (since AR 3.1).
|
514
|
+
# @note This method does not use prepared statements.
|
515
|
+
# @see #exec_query
|
516
|
+
# @see #exec_insert
|
517
|
+
# @see #exec_update
|
518
|
+
def execute(sql, name = nil, binds = nil)
|
519
|
+
sql = suble_binds to_sql(sql, binds), binds if binds
|
370
520
|
if name == :skip_logging
|
371
521
|
_execute(sql, name)
|
372
522
|
else
|
373
|
-
log(sql, name
|
523
|
+
log(sql, name) { _execute(sql, name) }
|
374
524
|
end
|
375
525
|
end
|
376
526
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
sql = suble_binds to_sql(sql, binds), binds
|
385
|
-
if name == :skip_logging
|
527
|
+
# @private documented above
|
528
|
+
def execute(sql, name = nil, skip_logging = false)
|
529
|
+
if skip_logging.is_a?(Array)
|
530
|
+
binds, skip_logging = skip_logging, false
|
531
|
+
sql = suble_binds to_sql(sql, binds), binds
|
532
|
+
end
|
533
|
+
if skip_logging || name == :skip_logging
|
386
534
|
_execute(sql, name)
|
387
535
|
else
|
388
536
|
log(sql, name) { _execute(sql, name) }
|
389
537
|
end
|
390
|
-
end
|
391
|
-
|
392
|
-
|
393
|
-
#
|
394
|
-
|
395
|
-
#
|
396
|
-
|
397
|
-
|
398
|
-
# we need to do it this way, to allow Rails stupid tests to always work
|
399
|
-
# even if we define a new execute method. Instead of mixing in a new
|
400
|
-
# execute, an _execute should be mixed in.
|
538
|
+
end if ActiveRecord::VERSION::MAJOR < 3 ||
|
539
|
+
( ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0 )
|
540
|
+
|
541
|
+
# We need to do it this way, to allow Rails stupid tests to always work
|
542
|
+
# even if we define a new `execute` method. Instead of mixing in a new
|
543
|
+
# `execute`, an `_execute` should be mixed in.
|
544
|
+
# @deprecated it was only introduced due tests
|
545
|
+
# @private
|
401
546
|
def _execute(sql, name = nil)
|
402
547
|
@connection.execute(sql)
|
403
548
|
end
|
404
549
|
private :_execute
|
405
550
|
|
406
|
-
#
|
407
|
-
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) # :nodoc:
|
408
|
-
id = execute(sql, name = nil, binds)
|
409
|
-
id_value || id
|
410
|
-
end
|
411
|
-
|
551
|
+
# @override
|
412
552
|
def tables(name = nil)
|
413
553
|
@connection.tables
|
414
554
|
end
|
415
555
|
|
556
|
+
# @override
|
416
557
|
def table_exists?(name)
|
417
558
|
@connection.table_exists?(name) # schema_name = nil
|
418
559
|
end
|
419
560
|
|
561
|
+
# @override
|
420
562
|
def indexes(table_name, name = nil, schema_name = nil)
|
421
563
|
@connection.indexes(table_name, name, schema_name)
|
422
564
|
end
|
423
565
|
|
424
|
-
|
425
|
-
|
566
|
+
# @override
|
567
|
+
def pk_and_sequence_for(table)
|
568
|
+
( key = primary_key(table) ) ? [ key, nil ] : nil
|
426
569
|
end
|
427
570
|
|
428
|
-
|
429
|
-
|
571
|
+
# @override
|
572
|
+
def primary_key(table)
|
573
|
+
primary_keys(table).first
|
430
574
|
end
|
431
575
|
|
432
|
-
|
433
|
-
|
576
|
+
# @override
|
577
|
+
def primary_keys(table)
|
578
|
+
@connection.primary_keys(table)
|
434
579
|
end
|
435
580
|
|
436
|
-
|
437
|
-
@connection.begin(isolation)
|
438
|
-
end
|
439
|
-
|
440
|
-
# Does this adapter support setting the isolation level for a transaction?
|
441
|
-
# @note We allow to ask for a specified transaction isolation level ...
|
442
|
-
def supports_transaction_isolation?(level = nil)
|
443
|
-
@connection.supports_transaction_isolation?(level)
|
444
|
-
end
|
445
|
-
|
581
|
+
# @deprecated use {#update_lob_value} instead
|
446
582
|
def write_large_object(*args)
|
447
583
|
@connection.write_large_object(*args)
|
448
584
|
end
|
449
585
|
|
450
|
-
def
|
451
|
-
|
452
|
-
[ key, nil ] if key
|
453
|
-
end
|
454
|
-
|
455
|
-
def primary_key(table)
|
456
|
-
primary_keys(table).first
|
457
|
-
end
|
458
|
-
|
459
|
-
def primary_keys(table)
|
460
|
-
@connection.primary_keys(table)
|
586
|
+
def update_lob_value(record, column, value)
|
587
|
+
@connection.update_lob_value(record, column, value)
|
461
588
|
end
|
462
589
|
|
463
590
|
if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0
|
464
|
-
|
591
|
+
|
465
592
|
#attr_reader :visitor unless method_defined?(:visitor) # not in 3.0
|
466
|
-
|
467
|
-
#
|
468
|
-
def to_sql(arel, binds =
|
593
|
+
|
594
|
+
# @private
|
595
|
+
def to_sql(arel, binds = nil)
|
469
596
|
# NOTE: can not handle `visitor.accept(arel.ast)` right
|
470
597
|
arel.respond_to?(:to_sql) ? arel.send(:to_sql) : arel
|
471
598
|
end
|
472
|
-
|
473
|
-
elsif ActiveRecord::VERSION::MAJOR
|
474
|
-
|
475
|
-
#
|
599
|
+
|
600
|
+
elsif ActiveRecord::VERSION::MAJOR < 3 # AR-2.3 'fake' #to_sql method
|
601
|
+
|
602
|
+
# @private
|
603
|
+
def to_sql(sql, binds = nil)
|
604
|
+
sql
|
605
|
+
end
|
606
|
+
|
607
|
+
else # AR >= 3.1 or 4.0
|
608
|
+
|
609
|
+
# @private
|
476
610
|
def to_sql(arel, binds = [])
|
611
|
+
# NOTE: same on 3.1/3.2 but on 4.0 binds are dup-ed
|
612
|
+
# for us it is intentional to 'consume' (empty) the binds array
|
613
|
+
# due our {#suble_binds} hack (that will be getting deprecated)
|
477
614
|
if arel.respond_to?(:ast)
|
478
|
-
visitor.accept(arel.ast)
|
615
|
+
visitor.accept(arel.ast) do
|
616
|
+
quote(*binds.shift.reverse)
|
617
|
+
end
|
479
618
|
else
|
480
619
|
arel
|
481
620
|
end
|
482
621
|
end
|
483
|
-
|
484
|
-
else # AR-2.3 no #to_sql method
|
485
|
-
|
486
|
-
def to_sql(sql, binds = nil)
|
487
|
-
sql
|
488
|
-
end
|
489
|
-
|
622
|
+
|
490
623
|
end
|
491
|
-
|
624
|
+
|
492
625
|
protected
|
493
|
-
|
626
|
+
|
627
|
+
# @override so that we do not have to care having 2 arguments on 3.0
|
628
|
+
def log(sql, name = nil, binds = [])
|
629
|
+
unless binds.blank?
|
630
|
+
binds = binds.map do |column, value|
|
631
|
+
column ? [column.name, value] : [nil, value]
|
632
|
+
end
|
633
|
+
sql = "#{sql} #{binds.inspect}"
|
634
|
+
end
|
635
|
+
super(sql, name || 'SQL') # `log(sql, name)` on AR <= 3.0
|
636
|
+
end if ActiveRecord::VERSION::MAJOR < 3 ||
|
637
|
+
( ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR < 1 )
|
638
|
+
|
494
639
|
def translate_exception(e, message)
|
495
640
|
# we shall not translate native "Java" exceptions as they might
|
496
641
|
# swallow an ArJdbc / driver bug into a AR::StatementInvalid ...
|
497
642
|
return e if e.is_a?(NativeException) # JRuby 1.6
|
498
643
|
return e if e.is_a?(Java::JavaLang::Throwable)
|
499
|
-
|
644
|
+
|
645
|
+
case e
|
646
|
+
when SystemExit, SignalException, NoMemoryError then e
|
647
|
+
# NOTE: wraps AR::JDBCError into AR::StatementInvalid, desired ?!
|
648
|
+
else super
|
649
|
+
end
|
500
650
|
end
|
501
651
|
|
652
|
+
# Take an id from the result of an INSERT query.
|
653
|
+
# @return [Integer, NilClass]
|
502
654
|
def last_inserted_id(result)
|
503
|
-
result
|
655
|
+
if result.is_a?(Hash) || result.is_a?(ActiveRecord::Result)
|
656
|
+
result.first.first[1] # .first = { "id"=>1 } .first = [ "id", 1 ]
|
657
|
+
else
|
658
|
+
result
|
659
|
+
end
|
504
660
|
end
|
505
|
-
|
506
|
-
#
|
507
|
-
|
661
|
+
|
662
|
+
# @private
|
663
|
+
def last_inserted_id(result)
|
664
|
+
if result.is_a?(Hash)
|
665
|
+
result.first.first[1] # .first = { "id"=>1 } .first = [ "id", 1 ]
|
666
|
+
else
|
667
|
+
result
|
668
|
+
end
|
669
|
+
end unless defined? ActiveRecord::Result
|
670
|
+
|
671
|
+
# Helper to easily override #table_definition (on AR 3.x/4.0) as :
|
672
|
+
# ```
|
508
673
|
# def table_definition(*args)
|
509
674
|
# new_table_definition(TableDefinition, *args)
|
510
675
|
# end
|
511
|
-
#
|
676
|
+
# ```
|
512
677
|
def new_table_definition(table_definition, *args)
|
513
678
|
table_definition.new(self) # args ignored only used for 4.0
|
514
679
|
end
|
515
680
|
private :new_table_definition
|
516
|
-
|
517
|
-
# if adapter overrides #table_definition it
|
681
|
+
|
682
|
+
# NOTE: make sure if adapter overrides #table_definition that it will
|
683
|
+
# work on AR 3.x as well as 4.0
|
518
684
|
if ActiveRecord::VERSION::MAJOR > 3
|
519
|
-
|
685
|
+
|
520
686
|
# aliasing #create_table_definition as #table_definition :
|
521
687
|
alias table_definition create_table_definition
|
522
688
|
|
523
|
-
# TableDefinition.new native_database_types, name, temporary, options
|
689
|
+
# `TableDefinition.new native_database_types, name, temporary, options`
|
690
|
+
# @private
|
524
691
|
def create_table_definition(name, temporary, options)
|
525
692
|
table_definition(name, temporary, options)
|
526
693
|
end
|
527
|
-
|
528
|
-
# arguments expected: (name, temporary, options)
|
694
|
+
|
695
|
+
# @note AR-4x arguments expected: `(name, temporary, options)`
|
696
|
+
# @private documented above
|
529
697
|
def new_table_definition(table_definition, *args)
|
530
698
|
table_definition.new native_database_types, *args
|
531
699
|
end
|
532
700
|
private :new_table_definition
|
533
|
-
|
701
|
+
|
534
702
|
end
|
535
|
-
|
536
|
-
|
537
|
-
|
703
|
+
|
704
|
+
# @return whether `:prepared_statements` are to be used
|
538
705
|
def prepared_statements?
|
539
|
-
|
706
|
+
return @prepared_statements unless (@prepared_statements ||= nil).nil?
|
707
|
+
@prepared_statements = self.class.prepared_statements?(config)
|
540
708
|
end
|
541
|
-
|
709
|
+
|
710
|
+
# Allows changing the prepared statements setting for this connection.
|
711
|
+
# @see #prepared_statements?
|
712
|
+
#def prepared_statements=(statements)
|
713
|
+
# @prepared_statements = statements
|
714
|
+
#end
|
715
|
+
|
716
|
+
private
|
717
|
+
|
542
718
|
def self.prepared_statements?(config)
|
543
719
|
config.key?(:prepared_statements) ?
|
544
720
|
type_cast_config_to_boolean(config.fetch(:prepared_statements)) :
|
545
|
-
false #
|
721
|
+
false # off by default
|
546
722
|
end
|
547
723
|
|
548
724
|
def suble_binds(sql, binds)
|
549
725
|
return sql if binds.nil? || binds.empty?
|
550
726
|
copy = binds.dup
|
727
|
+
# TODO deprecate/warn about this behavior !
|
551
728
|
sql.gsub('?') { quote(*copy.shift.reverse) }
|
552
729
|
end
|
553
|
-
|
554
|
-
# @deprecated
|
730
|
+
|
731
|
+
# @deprecated Replaced with {#suble_binds}.
|
555
732
|
def substitute_binds(sql, binds)
|
556
733
|
suble_binds(extract_sql(sql), binds)
|
557
734
|
end
|
558
735
|
|
559
|
-
# @deprecated
|
736
|
+
# @deprecated No longer used, only kept for 1.2 API compatibility.
|
560
737
|
def extract_sql(obj)
|
561
738
|
obj.respond_to?(:to_sql) ? obj.send(:to_sql) : obj
|
562
739
|
end
|
563
|
-
|
740
|
+
|
741
|
+
# Helper to get local/UTC time (based on `ActiveRecord::Base.default_timezone`).
|
742
|
+
def get_time(value)
|
743
|
+
get = ::ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
|
744
|
+
value.respond_to?(get) ? value.send(get) : value
|
745
|
+
end
|
746
|
+
|
564
747
|
protected
|
565
|
-
|
748
|
+
|
749
|
+
# @return whether the given SQL string is a 'SELECT' like
|
750
|
+
# query (returning a result set)
|
566
751
|
def self.select?(sql)
|
567
752
|
JdbcConnection::select?(sql)
|
568
753
|
end
|
569
754
|
|
755
|
+
# @return whether the given SQL string is an 'INSERT' query
|
570
756
|
def self.insert?(sql)
|
571
757
|
JdbcConnection::insert?(sql)
|
572
758
|
end
|
573
759
|
|
760
|
+
# @return whether the given SQL string is an 'UPDATE' (or 'DELETE') query
|
574
761
|
def self.update?(sql)
|
575
762
|
! select?(sql) && ! insert?(sql)
|
576
763
|
end
|
577
|
-
|
764
|
+
|
578
765
|
unless defined? AbstractAdapter.type_cast_config_to_integer
|
579
|
-
|
766
|
+
|
767
|
+
# @private
|
580
768
|
def self.type_cast_config_to_integer(config)
|
581
769
|
config =~ /\A\d+\z/ ? config.to_i : config
|
582
770
|
end
|
583
771
|
|
772
|
+
# @private
|
584
773
|
def self.type_cast_config_to_boolean(config)
|
585
774
|
config == "false" ? false : config
|
586
775
|
end
|
587
|
-
|
776
|
+
|
777
|
+
end
|
778
|
+
|
779
|
+
public
|
780
|
+
|
781
|
+
# @note Used by Java API to convert dates from (custom) SELECTs (might get refactored).
|
782
|
+
# @private
|
783
|
+
def _string_to_date(value)
|
784
|
+
jdbc_column_class.string_to_date(value)
|
588
785
|
end
|
589
|
-
|
786
|
+
|
787
|
+
# @note Used by Java API to convert times from (custom) SELECTs (might get refactored).
|
788
|
+
# @private
|
789
|
+
def _string_to_time(value)
|
790
|
+
jdbc_column_class.string_to_dummy_time(value)
|
791
|
+
end
|
792
|
+
|
793
|
+
# @note Used by Java API to convert times from (custom) SELECTs (might get refactored).
|
794
|
+
# @private
|
795
|
+
def _string_to_timestamp(value)
|
796
|
+
jdbc_column_class.string_to_time(value)
|
797
|
+
end
|
798
|
+
|
590
799
|
end
|
591
800
|
end
|
592
801
|
end
|