activerecord-jdbc-alt-adapter 50.3.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +35 -0
- data/.travis.yml +100 -0
- data/.yardopts +4 -0
- data/CONTRIBUTING.md +50 -0
- data/Gemfile +92 -0
- data/History.md +1191 -0
- data/LICENSE.txt +26 -0
- data/README.md +240 -0
- data/RUNNING_TESTS.md +127 -0
- data/Rakefile +336 -0
- data/Rakefile.jdbc +20 -0
- data/activerecord-jdbc-adapter.gemspec +55 -0
- data/activerecord-jdbc-alt-adapter.gemspec +56 -0
- data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
- data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
- data/lib/activerecord-jdbc-adapter.rb +1 -0
- data/lib/arel/visitors/compat.rb +60 -0
- data/lib/arel/visitors/db2.rb +137 -0
- data/lib/arel/visitors/derby.rb +112 -0
- data/lib/arel/visitors/firebird.rb +79 -0
- data/lib/arel/visitors/h2.rb +25 -0
- data/lib/arel/visitors/hsqldb.rb +32 -0
- data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
- data/lib/arel/visitors/sql_server.rb +225 -0
- data/lib/arel/visitors/sql_server/ng42.rb +294 -0
- data/lib/arel/visitors/sqlserver.rb +214 -0
- data/lib/arjdbc.rb +19 -0
- data/lib/arjdbc/abstract/connection_management.rb +35 -0
- data/lib/arjdbc/abstract/core.rb +74 -0
- data/lib/arjdbc/abstract/database_statements.rb +64 -0
- data/lib/arjdbc/abstract/statement_cache.rb +58 -0
- data/lib/arjdbc/abstract/transaction_support.rb +86 -0
- data/lib/arjdbc/db2.rb +4 -0
- data/lib/arjdbc/db2/adapter.rb +789 -0
- data/lib/arjdbc/db2/as400.rb +130 -0
- data/lib/arjdbc/db2/column.rb +167 -0
- data/lib/arjdbc/db2/connection_methods.rb +44 -0
- data/lib/arjdbc/derby.rb +3 -0
- data/lib/arjdbc/derby/active_record_patch.rb +13 -0
- data/lib/arjdbc/derby/adapter.rb +540 -0
- data/lib/arjdbc/derby/connection_methods.rb +20 -0
- data/lib/arjdbc/derby/schema_creation.rb +15 -0
- data/lib/arjdbc/discover.rb +104 -0
- data/lib/arjdbc/firebird.rb +4 -0
- data/lib/arjdbc/firebird/adapter.rb +434 -0
- data/lib/arjdbc/firebird/connection_methods.rb +23 -0
- data/lib/arjdbc/h2.rb +3 -0
- data/lib/arjdbc/h2/adapter.rb +303 -0
- data/lib/arjdbc/h2/connection_methods.rb +27 -0
- data/lib/arjdbc/hsqldb.rb +3 -0
- data/lib/arjdbc/hsqldb/adapter.rb +297 -0
- data/lib/arjdbc/hsqldb/connection_methods.rb +28 -0
- data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
- data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
- data/lib/arjdbc/informix.rb +5 -0
- data/lib/arjdbc/informix/adapter.rb +162 -0
- data/lib/arjdbc/informix/connection_methods.rb +9 -0
- data/lib/arjdbc/jdbc.rb +59 -0
- data/lib/arjdbc/jdbc/adapter.rb +475 -0
- data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
- data/lib/arjdbc/jdbc/base_ext.rb +15 -0
- data/lib/arjdbc/jdbc/callbacks.rb +53 -0
- data/lib/arjdbc/jdbc/column.rb +97 -0
- data/lib/arjdbc/jdbc/connection.rb +14 -0
- data/lib/arjdbc/jdbc/connection_methods.rb +37 -0
- data/lib/arjdbc/jdbc/error.rb +65 -0
- data/lib/arjdbc/jdbc/extension.rb +59 -0
- data/lib/arjdbc/jdbc/java.rb +13 -0
- data/lib/arjdbc/jdbc/railtie.rb +2 -0
- data/lib/arjdbc/jdbc/rake_tasks.rb +3 -0
- data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -0
- data/lib/arjdbc/jdbc/type_cast.rb +166 -0
- data/lib/arjdbc/jdbc/type_converter.rb +142 -0
- data/lib/arjdbc/mssql.rb +7 -0
- data/lib/arjdbc/mssql/adapter.rb +384 -0
- data/lib/arjdbc/mssql/column.rb +29 -0
- data/lib/arjdbc/mssql/connection_methods.rb +79 -0
- data/lib/arjdbc/mssql/database_statements.rb +134 -0
- data/lib/arjdbc/mssql/errors.rb +6 -0
- data/lib/arjdbc/mssql/explain_support.rb +129 -0
- data/lib/arjdbc/mssql/extensions.rb +36 -0
- data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
- data/lib/arjdbc/mssql/lock_methods.rb +77 -0
- data/lib/arjdbc/mssql/old_adapter.rb +804 -0
- data/lib/arjdbc/mssql/old_column.rb +200 -0
- data/lib/arjdbc/mssql/quoting.rb +101 -0
- data/lib/arjdbc/mssql/schema_creation.rb +31 -0
- data/lib/arjdbc/mssql/schema_definitions.rb +74 -0
- data/lib/arjdbc/mssql/schema_statements.rb +329 -0
- data/lib/arjdbc/mssql/transaction.rb +69 -0
- data/lib/arjdbc/mssql/types.rb +52 -0
- data/lib/arjdbc/mssql/types/binary_types.rb +33 -0
- data/lib/arjdbc/mssql/types/date_and_time_types.rb +134 -0
- data/lib/arjdbc/mssql/types/deprecated_types.rb +40 -0
- data/lib/arjdbc/mssql/types/numeric_types.rb +71 -0
- data/lib/arjdbc/mssql/types/string_types.rb +56 -0
- data/lib/arjdbc/mssql/utils.rb +66 -0
- data/lib/arjdbc/mysql.rb +3 -0
- data/lib/arjdbc/mysql/adapter.rb +140 -0
- data/lib/arjdbc/mysql/connection_methods.rb +166 -0
- data/lib/arjdbc/oracle/adapter.rb +863 -0
- data/lib/arjdbc/postgresql.rb +3 -0
- data/lib/arjdbc/postgresql/adapter.rb +687 -0
- data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
- data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
- data/lib/arjdbc/postgresql/base/pgconn.rb +11 -0
- data/lib/arjdbc/postgresql/column.rb +51 -0
- data/lib/arjdbc/postgresql/connection_methods.rb +67 -0
- data/lib/arjdbc/postgresql/name.rb +24 -0
- data/lib/arjdbc/postgresql/oid_types.rb +266 -0
- data/lib/arjdbc/railtie.rb +11 -0
- data/lib/arjdbc/sqlite3.rb +3 -0
- data/lib/arjdbc/sqlite3/adapter.rb +678 -0
- data/lib/arjdbc/sqlite3/connection_methods.rb +59 -0
- data/lib/arjdbc/sybase.rb +2 -0
- data/lib/arjdbc/sybase/adapter.rb +47 -0
- data/lib/arjdbc/tasks.rb +13 -0
- data/lib/arjdbc/tasks/database_tasks.rb +31 -0
- data/lib/arjdbc/tasks/databases.rake +48 -0
- data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
- data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
- data/lib/arjdbc/tasks/h2_database_tasks.rb +31 -0
- data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
- data/lib/arjdbc/tasks/jdbc_database_tasks.rb +169 -0
- data/lib/arjdbc/tasks/mssql_database_tasks.rb +46 -0
- data/lib/arjdbc/util/quoted_cache.rb +60 -0
- data/lib/arjdbc/util/serialized_attributes.rb +98 -0
- data/lib/arjdbc/util/table_copier.rb +110 -0
- data/lib/arjdbc/version.rb +3 -0
- data/lib/generators/jdbc/USAGE +9 -0
- data/lib/generators/jdbc/jdbc_generator.rb +17 -0
- data/lib/jdbc_adapter.rb +2 -0
- data/lib/jdbc_adapter/rake_tasks.rb +4 -0
- data/lib/jdbc_adapter/version.rb +4 -0
- data/pom.xml +114 -0
- data/rails_generators/jdbc_generator.rb +15 -0
- data/rails_generators/templates/config/initializers/jdbc.rb +10 -0
- data/rails_generators/templates/lib/tasks/jdbc.rake +11 -0
- data/rakelib/01-tomcat.rake +51 -0
- data/rakelib/02-test.rake +132 -0
- data/rakelib/bundler_ext.rb +11 -0
- data/rakelib/db.rake +75 -0
- data/rakelib/rails.rake +223 -0
- data/src/java/arjdbc/ArJdbcModule.java +276 -0
- data/src/java/arjdbc/db2/DB2Module.java +76 -0
- data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +126 -0
- data/src/java/arjdbc/derby/DerbyModule.java +178 -0
- data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +152 -0
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +174 -0
- data/src/java/arjdbc/h2/H2Module.java +50 -0
- data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +85 -0
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +73 -0
- data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +75 -0
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +43 -0
- data/src/java/arjdbc/jdbc/Callable.java +44 -0
- data/src/java/arjdbc/jdbc/ConnectionFactory.java +45 -0
- data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +156 -0
- data/src/java/arjdbc/jdbc/DriverConnectionFactory.java +63 -0
- data/src/java/arjdbc/jdbc/DriverWrapper.java +119 -0
- data/src/java/arjdbc/jdbc/JdbcResult.java +130 -0
- data/src/java/arjdbc/jdbc/RubyConnectionFactory.java +61 -0
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +3979 -0
- data/src/java/arjdbc/mssql/MSSQLModule.java +90 -0
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +508 -0
- data/src/java/arjdbc/mysql/MySQLModule.java +152 -0
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +294 -0
- data/src/java/arjdbc/oracle/OracleModule.java +80 -0
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +455 -0
- data/src/java/arjdbc/postgresql/ByteaUtils.java +157 -0
- data/src/java/arjdbc/postgresql/PgDateTimeUtils.java +52 -0
- data/src/java/arjdbc/postgresql/PostgreSQLModule.java +77 -0
- data/src/java/arjdbc/postgresql/PostgreSQLResult.java +192 -0
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +948 -0
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +73 -0
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +525 -0
- data/src/java/arjdbc/util/CallResultSet.java +826 -0
- data/src/java/arjdbc/util/DateTimeUtils.java +699 -0
- data/src/java/arjdbc/util/ObjectSupport.java +65 -0
- data/src/java/arjdbc/util/QuotingUtils.java +137 -0
- data/src/java/arjdbc/util/StringCache.java +63 -0
- data/src/java/arjdbc/util/StringHelper.java +145 -0
- metadata +269 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
ArJdbc::ConnectionMethods.module_eval do
|
|
2
|
+
def hsqldb_connection(config)
|
|
3
|
+
config[:adapter_spec] ||= ::ArJdbc::HSQLDB
|
|
4
|
+
config[:adapter_class] = ActiveRecord::ConnectionAdapters::HsqldbAdapter unless config.key?(:adapter_class)
|
|
5
|
+
|
|
6
|
+
return jndi_connection(config) if jndi_config?(config)
|
|
7
|
+
|
|
8
|
+
begin
|
|
9
|
+
require 'jdbc/hsqldb'
|
|
10
|
+
::Jdbc::HSQLDB.load_driver(:require) if defined?(::Jdbc::HSQLDB.load_driver)
|
|
11
|
+
rescue LoadError # assuming driver.jar is on the class-path
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
config[:url] ||= begin
|
|
15
|
+
db = config[:database]
|
|
16
|
+
if db[0, 4] == 'mem:' || db[0, 5] == 'file:' || db[0, 5] == 'hsql:'
|
|
17
|
+
"jdbc:hsqldb:#{db}"
|
|
18
|
+
else
|
|
19
|
+
"jdbc:hsqldb:file:#{db}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
config[:driver] ||= defined?(::Jdbc::HSQLDB.driver_name) ? ::Jdbc::HSQLDB.driver_name : 'org.hsqldb.jdbcDriver'
|
|
23
|
+
config[:connection_alive_sql] ||= 'CALL PI()' # does not like 'SELECT 1'
|
|
24
|
+
|
|
25
|
+
embedded_driver(config)
|
|
26
|
+
end
|
|
27
|
+
alias_method :jdbchsqldb_connection, :hsqldb_connection
|
|
28
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module ArJdbc
|
|
2
|
+
module HSQLDB
|
|
3
|
+
module ExplainSupport
|
|
4
|
+
def supports_explain?; true; end
|
|
5
|
+
|
|
6
|
+
def explain(arel, binds = [])
|
|
7
|
+
sql = "EXPLAIN PLAN FOR #{to_sql(arel, binds)}"
|
|
8
|
+
raw_result = exec_query_raw(sql, "EXPLAIN", binds)
|
|
9
|
+
# HSQLDB's SqlTool just prints it as it comes :
|
|
10
|
+
#
|
|
11
|
+
# sql> EXPLAIN PLAN FOR SELECT * FROM entries JOIN users on ... ;
|
|
12
|
+
#
|
|
13
|
+
# isDistinctSelect=[false]
|
|
14
|
+
# isGrouped=[false]
|
|
15
|
+
# isAggregated=[false]
|
|
16
|
+
# columns=[ COLUMN: PUBLIC.ENTRIES.ID
|
|
17
|
+
# not nullable COLUMN: PUBLIC.ENTRIES.TITLE
|
|
18
|
+
# nullable COLUMN: PUBLIC.ENTRIES.UPDATED_ON
|
|
19
|
+
# nullable COLUMN: PUBLIC.ENTRIES.CONTENT
|
|
20
|
+
# nullable COLUMN: PUBLIC.ENTRIES.RATING
|
|
21
|
+
# nullable COLUMN: PUBLIC.ENTRIES.USER_ID
|
|
22
|
+
# nullable COLUMN: PUBLIC.USERS.ID
|
|
23
|
+
# not nullable COLUMN: PUBLIC.USERS.LOGIN
|
|
24
|
+
# nullable
|
|
25
|
+
# ]
|
|
26
|
+
# ...
|
|
27
|
+
# PARAMETERS=[]
|
|
28
|
+
# SUBQUERIES[]
|
|
29
|
+
#
|
|
30
|
+
raw_result.map!(&:values)
|
|
31
|
+
raw_result.join("\n")
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module ArJdbc
|
|
2
|
+
module HSQLDB
|
|
3
|
+
# @private
|
|
4
|
+
SchemaCreation = ::ActiveRecord::ConnectionAdapters::AbstractAdapter::SchemaCreation
|
|
5
|
+
|
|
6
|
+
def schema_creation
|
|
7
|
+
SchemaCreation.new self
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
end
|
|
11
|
+
end if ::ActiveRecord::ConnectionAdapters::AbstractAdapter.const_defined? :SchemaCreation
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
require 'arjdbc/util/serialized_attributes'
|
|
2
|
+
|
|
3
|
+
module ArJdbc
|
|
4
|
+
module Informix
|
|
5
|
+
|
|
6
|
+
@@_lob_callback_added = nil
|
|
7
|
+
|
|
8
|
+
def self.extended(base)
|
|
9
|
+
unless @@_lob_callback_added
|
|
10
|
+
ActiveRecord::Base.class_eval do
|
|
11
|
+
def after_save_with_informix_lob
|
|
12
|
+
lob_columns = self.class.columns.select { |c| [:text, :binary].include?(c.type) }
|
|
13
|
+
lob_columns.each do |column|
|
|
14
|
+
value = ::ArJdbc::SerializedAttributesHelper.dump_column_value(self, column)
|
|
15
|
+
next if value.nil? || (value == '')
|
|
16
|
+
|
|
17
|
+
connection.write_large_object(
|
|
18
|
+
column.type == :binary, column.name,
|
|
19
|
+
self.class.table_name, self.class.primary_key,
|
|
20
|
+
quote_value(id), value
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
ActiveRecord::Base.after_save :after_save_with_informix_lob
|
|
27
|
+
@@_lob_callback_added = true
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcColumn#column_types
|
|
32
|
+
def self.column_selector
|
|
33
|
+
[ /informix/i, lambda { |cfg, column| column.extend(ColumnMethods) } ]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
JdbcConnection = ::ActiveRecord::ConnectionAdapters::InformixJdbcConnection
|
|
37
|
+
|
|
38
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
|
|
39
|
+
def self.jdbc_connection_class
|
|
40
|
+
::ActiveRecord::ConnectionAdapters::InformixJdbcConnection
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_column_class
|
|
44
|
+
def jdbc_column_class
|
|
45
|
+
::ActiveRecord::ConnectionAdapters::InformixColumn
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module ColumnMethods
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
# TODO: Test all Informix column types.
|
|
52
|
+
def simplified_type(field_type)
|
|
53
|
+
if field_type =~ /serial/i
|
|
54
|
+
:primary_key
|
|
55
|
+
else
|
|
56
|
+
super
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def modify_types(types)
|
|
63
|
+
super(types)
|
|
64
|
+
types[:primary_key] = "SERIAL PRIMARY KEY"
|
|
65
|
+
types[:string] = { :name => "VARCHAR", :limit => 255 }
|
|
66
|
+
types[:integer] = { :name => "INTEGER" }
|
|
67
|
+
types[:float] = { :name => "FLOAT" }
|
|
68
|
+
types[:decimal] = { :name => "DECIMAL" }
|
|
69
|
+
types[:datetime] = { :name => "DATETIME YEAR TO FRACTION(5)" }
|
|
70
|
+
types[:timestamp] = { :name => "DATETIME YEAR TO FRACTION(5)" }
|
|
71
|
+
types[:time] = { :name => "DATETIME HOUR TO FRACTION(5)" }
|
|
72
|
+
types[:date] = { :name => "DATE" }
|
|
73
|
+
types[:binary] = { :name => "BYTE" }
|
|
74
|
+
types[:boolean] = { :name => "BOOLEAN" }
|
|
75
|
+
types
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def prefetch_primary_key?(table_name = nil)
|
|
79
|
+
true
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def supports_migrations?
|
|
83
|
+
true
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def default_sequence_name(table, column)
|
|
87
|
+
"#{table}_seq"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def add_limit_offset!(sql, options)
|
|
91
|
+
if options[:limit]
|
|
92
|
+
limit = "FIRST #{options[:limit]}" # SKIP available only in IDS >= 10 :
|
|
93
|
+
offset = (db_major_version >= 10 && options[:offset] ? "SKIP #{options[:offset]}" : "")
|
|
94
|
+
sql.sub!(/^\s*?select /i, "SELECT #{offset} #{limit} ")
|
|
95
|
+
end
|
|
96
|
+
sql
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def next_sequence_value(sequence_name)
|
|
100
|
+
select_one("SELECT #{sequence_name}.nextval id FROM systables WHERE tabid=1")['id']
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# TODO: Add some smart quoting for newlines in string and text fields.
|
|
104
|
+
def quote_string(string)
|
|
105
|
+
string.gsub(/\'/, "''")
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def quote(value, column = nil)
|
|
109
|
+
column_type = column && column.type
|
|
110
|
+
if column_type == :binary || column_type == :text
|
|
111
|
+
# LOBs are updated separately by an after_save trigger.
|
|
112
|
+
"NULL"
|
|
113
|
+
elsif column_type == :date
|
|
114
|
+
"'#{value.mon}/#{value.day}/#{value.year}'"
|
|
115
|
+
else
|
|
116
|
+
super
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def create_table(name, options = {})
|
|
121
|
+
super(name, options)
|
|
122
|
+
execute("CREATE SEQUENCE #{name}_seq")
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def rename_table(name, new_name)
|
|
126
|
+
execute("RENAME TABLE #{name} TO #{new_name}")
|
|
127
|
+
execute("RENAME SEQUENCE #{name}_seq TO #{new_name}_seq")
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def drop_table(name)
|
|
131
|
+
super(name)
|
|
132
|
+
execute("DROP SEQUENCE #{name}_seq")
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def remove_index(table_name, options = {})
|
|
136
|
+
@connection.execute_update("DROP INDEX #{index_name(table_name, options)}")
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def select(sql, *rest)
|
|
140
|
+
# Informix does not like "= NULL", "!= NULL", or "<> NULL".
|
|
141
|
+
super(sql.gsub(/(!=|<>)\s*null/i, "IS NOT NULL").gsub(/=\s*null/i, "IS NULL"), *rest)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
private
|
|
145
|
+
|
|
146
|
+
def db_major_version
|
|
147
|
+
@@db_major_version ||=
|
|
148
|
+
select_one("SELECT dbinfo('version', 'major') version FROM systables WHERE tabid = 1")['version'].to_i
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
end # module Informix
|
|
152
|
+
end # module ::ArJdbc
|
|
153
|
+
|
|
154
|
+
module ActiveRecord::ConnectionAdapters
|
|
155
|
+
class InformixColumn < JdbcColumn
|
|
156
|
+
include ::ArJdbc::Informix::ColumnMethods
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
class InformixAdapter < JdbcAdapter
|
|
160
|
+
include ::ArJdbc::Informix
|
|
161
|
+
end
|
|
162
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
ArJdbc::ConnectionMethods.module_eval do
|
|
2
|
+
def informix_connection(config)
|
|
3
|
+
config[:port] ||= 9088
|
|
4
|
+
config[:url] ||= "jdbc:informix-sqli://#{config[:host]}:#{config[:port]}/#{config[:database]}:INFORMIXSERVER=#{config[:servername]}"
|
|
5
|
+
config[:driver] = 'com.informix.jdbc.IfxDriver'
|
|
6
|
+
config[:adapter_spec] = ::ArJdbc::Informix
|
|
7
|
+
jdbc_connection(config)
|
|
8
|
+
end
|
|
9
|
+
end
|
data/lib/arjdbc/jdbc.rb
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'active_support/deprecation'
|
|
2
|
+
|
|
3
|
+
module ArJdbc
|
|
4
|
+
|
|
5
|
+
# @private
|
|
6
|
+
AR40 = ::ActiveRecord::VERSION::MAJOR > 3
|
|
7
|
+
# @private
|
|
8
|
+
AR42 = ::ActiveRecord::VERSION::STRING >= '4.2'
|
|
9
|
+
# @private
|
|
10
|
+
AR50 = ::ActiveRecord::VERSION::MAJOR > 4
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
|
|
14
|
+
# @private Internal API
|
|
15
|
+
def warn_unsupported_adapter(adapter, version = nil)
|
|
16
|
+
warn_prefix = 'NOTE:'
|
|
17
|
+
if version # e.g. [4, 2]
|
|
18
|
+
ar_version = [ ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR, ActiveRecord::VERSION::TINY ]
|
|
19
|
+
if ( ar_version <=> version ) >= 0 # e.g. 4.2.0 > 4.2
|
|
20
|
+
warn_prefix = "NOTE: ActiveRecord #{version.join('.')} with"
|
|
21
|
+
else
|
|
22
|
+
warn_prefix = nil
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
warn "#{warn_prefix} adapter: #{adapter} is not (yet) fully supported by AR-JDBC," <<
|
|
26
|
+
" please consider helping us out." if warn_prefix
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def warn(message, once = nil)
|
|
30
|
+
super(message) || true if warn?(message, once)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def deprecate(message, once = nil) # adds a "DEPRECATION WARNING: " prefix
|
|
34
|
+
::ActiveSupport::Deprecation.warn(message, caller_locations) || true if warn?(message, once)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
@@warns = nil
|
|
40
|
+
@@warns = false if ENV_JAVA['arjdbc.warn'].eql? 'false'
|
|
41
|
+
|
|
42
|
+
def warn?(message, once)
|
|
43
|
+
return nil if @@warns.equal?(false) || ! message
|
|
44
|
+
warns = @@warns ||= ( require 'set'; Set.new )
|
|
45
|
+
return false if warns.include?(message)
|
|
46
|
+
warns << message.dup if once
|
|
47
|
+
true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
require 'arjdbc/jdbc/adapter'
|
|
53
|
+
|
|
54
|
+
if ENV_JAVA['arjdbc.extensions.discover'].eql? 'true'
|
|
55
|
+
self.discover_extensions
|
|
56
|
+
else
|
|
57
|
+
require 'arjdbc/discover'
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
require 'active_record/version'
|
|
2
|
+
require 'active_record/connection_adapters/abstract_adapter'
|
|
3
|
+
|
|
4
|
+
require 'arjdbc/version'
|
|
5
|
+
require 'arjdbc/jdbc/java'
|
|
6
|
+
require 'arjdbc/jdbc/base_ext'
|
|
7
|
+
require 'arjdbc/jdbc/error'
|
|
8
|
+
require 'arjdbc/jdbc/connection_methods'
|
|
9
|
+
require 'arjdbc/jdbc/column'
|
|
10
|
+
require 'arjdbc/jdbc/connection'
|
|
11
|
+
require 'arjdbc/jdbc/callbacks'
|
|
12
|
+
require 'arjdbc/jdbc/extension'
|
|
13
|
+
require 'arjdbc/jdbc/type_converter'
|
|
14
|
+
require 'arjdbc/abstract/core'
|
|
15
|
+
require 'arjdbc/abstract/connection_management'
|
|
16
|
+
require 'arjdbc/abstract/database_statements'
|
|
17
|
+
require 'arjdbc/abstract/transaction_support'
|
|
18
|
+
|
|
19
|
+
module ActiveRecord
|
|
20
|
+
module ConnectionAdapters
|
|
21
|
+
# Built on top of `ActiveRecord::ConnectionAdapters::AbstractAdapter` which
|
|
22
|
+
# provides the abstract interface for database-specific functionality, this
|
|
23
|
+
# class serves 2 purposes in AR-JDBC :
|
|
24
|
+
# - as a base class for sub-classes
|
|
25
|
+
# - usable standalone (or with a mixed in adapter spec module)
|
|
26
|
+
#
|
|
27
|
+
# Historically this class is mostly been used standalone and that's still a
|
|
28
|
+
# valid use-case esp. since (with it's `arjdbc.jdbc.RubyJdbcConnectionClass`)
|
|
29
|
+
# JDBC provides a unified interface for all databases in Java it tries to do
|
|
30
|
+
# it's best implementing all `ActiveRecord` functionality on top of that.
|
|
31
|
+
# This might no be perfect that's why it checks for a `config[:adapter_spec]`
|
|
32
|
+
# module (or tries to resolve one from the JDBC driver's meta-data) and if
|
|
33
|
+
# the database has "extended" AR-JDBC support mixes in the given module for
|
|
34
|
+
# each adapter instance.
|
|
35
|
+
# This is sufficient for most database specific specs we support, but for
|
|
36
|
+
# compatibility with native (MRI) adapters it's perfectly fine to sub-class
|
|
37
|
+
# the adapter and override some of its API methods.
|
|
38
|
+
class JdbcAdapter < AbstractAdapter
|
|
39
|
+
include Jdbc::ConnectionPoolCallbacks
|
|
40
|
+
|
|
41
|
+
include ArJdbc::Abstract::Core
|
|
42
|
+
include ArJdbc::Abstract::ConnectionManagement
|
|
43
|
+
include ArJdbc::Abstract::DatabaseStatements
|
|
44
|
+
include ArJdbc::Abstract::TransactionSupport
|
|
45
|
+
|
|
46
|
+
attr_reader :prepared_statements
|
|
47
|
+
|
|
48
|
+
# Returns the (JDBC) connection class to be used for this adapter.
|
|
49
|
+
# This is used by (database specific) spec modules to override the class
|
|
50
|
+
# used assuming some of the available methods have been re-defined.
|
|
51
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcConnection
|
|
52
|
+
def jdbc_connection_class(spec)
|
|
53
|
+
connection_class = spec.jdbc_connection_class if spec && spec.respond_to?(:jdbc_connection_class)
|
|
54
|
+
connection_class ? connection_class : ::ActiveRecord::ConnectionAdapters::JdbcConnection
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Returns the (JDBC) `ActiveRecord` column class for this adapter.
|
|
58
|
+
# This is used by (database specific) spec modules to override the class.
|
|
59
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcColumn
|
|
60
|
+
def jdbc_column_class
|
|
61
|
+
::ActiveRecord::ConnectionAdapters::JdbcColumn
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Locate the specialized (database specific) adapter specification module
|
|
65
|
+
# if one exists based on provided configuration data. This module will than
|
|
66
|
+
# extend an instance of the adapter (unless an `:adapter_class` provided).
|
|
67
|
+
#
|
|
68
|
+
# This method is called during {#initialize} unless an explicit
|
|
69
|
+
# `config[:adapter_spec]` is set.
|
|
70
|
+
# @param config the configuration to check for `:adapter_spec`
|
|
71
|
+
# @return [Module] the database specific module
|
|
72
|
+
def adapter_spec(config)
|
|
73
|
+
dialect = (config[:dialect] || config[:driver]).to_s
|
|
74
|
+
::ArJdbc.modules.each do |constant| # e.g. ArJdbc::MySQL
|
|
75
|
+
if constant.respond_to?(:adapter_matcher)
|
|
76
|
+
spec = constant.adapter_matcher(dialect, config)
|
|
77
|
+
return spec if spec
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
unless config.key?(:dialect)
|
|
82
|
+
begin # does nothing unless config[:jndi] || config[:data_source]
|
|
83
|
+
dialect = ::ArJdbc.with_meta_data_from_data_source_if_any(config) do
|
|
84
|
+
|meta_data| config[:dialect] = meta_data.getDatabaseProductName
|
|
85
|
+
end
|
|
86
|
+
return adapter_spec(config) if dialect # re-try matching with :dialect
|
|
87
|
+
rescue => e
|
|
88
|
+
::ArJdbc.warn("failed to set :dialect from database meda-data: #{e.inspect}")
|
|
89
|
+
else
|
|
90
|
+
return adapter_spec(config) # re-try matching a spec with set config[:dialect]
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
nil
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
ADAPTER_NAME = 'JDBC'.freeze
|
|
98
|
+
|
|
99
|
+
# @return [String] the 'JDBC' adapter name.
|
|
100
|
+
def adapter_name
|
|
101
|
+
ADAPTER_NAME
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# @override
|
|
105
|
+
# Will return true even when native adapter classes passed in
|
|
106
|
+
# e.g. `jdbc_adapter.is_a? ConnectionAdapter::PostgresqlAdapter`
|
|
107
|
+
#
|
|
108
|
+
# This is only necessary (for built-in adapters) when
|
|
109
|
+
# `config[:adapter_class]` is forced to `nil` and the `:adapter_spec`
|
|
110
|
+
# module is used to extend the `JdbcAdapter`, otherwise we replace the
|
|
111
|
+
# class constants for built-in adapters (MySQL, PostgreSQL and SQLite3).
|
|
112
|
+
def is_a?(klass)
|
|
113
|
+
# This is to fake out current_adapter? conditional logic in AR tests
|
|
114
|
+
if klass.is_a?(Class) && klass.name =~ /#{adapter_name}Adapter$/i
|
|
115
|
+
true
|
|
116
|
+
else
|
|
117
|
+
super
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# @deprecated re-implemented - no longer used
|
|
122
|
+
# @return [Hash] the AREL visitor to use
|
|
123
|
+
# If there's a `self.arel2_visitors(config)` method on the adapter
|
|
124
|
+
# spec than it is preferred and will be used instead of this one.
|
|
125
|
+
def self.arel2_visitors(config)
|
|
126
|
+
{ 'jdbc' => ::Arel::Visitors::ToSql }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# @deprecated re-implemented - no longer used
|
|
130
|
+
# @see #arel2_visitors
|
|
131
|
+
def self.configure_arel2_visitors(config)
|
|
132
|
+
visitors = ::Arel::Visitors::VISITORS
|
|
133
|
+
klass = config[:adapter_spec]
|
|
134
|
+
klass = self unless klass.respond_to?(:arel2_visitors)
|
|
135
|
+
visitor = nil
|
|
136
|
+
klass.arel2_visitors(config).each do |name, arel|
|
|
137
|
+
visitors[name] = ( visitor = arel )
|
|
138
|
+
end
|
|
139
|
+
if visitor && config[:adapter] =~ /^(jdbc|jndi)$/
|
|
140
|
+
visitors[ config[:adapter] ] = visitor
|
|
141
|
+
end
|
|
142
|
+
visitor
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# DB specific types are detected but adapter specs (or extenders) are
|
|
146
|
+
# expected to hand tune these types for concrete databases.
|
|
147
|
+
# @return [Hash] the native database types
|
|
148
|
+
# @override
|
|
149
|
+
def native_database_types
|
|
150
|
+
@native_database_types ||= begin
|
|
151
|
+
types = @connection.native_database_types
|
|
152
|
+
modify_types(types)
|
|
153
|
+
types
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# @override introduced in AR 4.2
|
|
158
|
+
def valid_type?(type)
|
|
159
|
+
! native_database_types[type].nil?
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Allows for modification of the detected native types.
|
|
163
|
+
# @param types the resolved native database types
|
|
164
|
+
# @see #native_database_types
|
|
165
|
+
def modify_types(types)
|
|
166
|
+
types
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Abstract adapter default implementation does nothing silently.
|
|
170
|
+
# @override
|
|
171
|
+
def structure_dump
|
|
172
|
+
raise NotImplementedError, "structure_dump not supported"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# JDBC adapters support migration.
|
|
176
|
+
# @return [true]
|
|
177
|
+
# @override
|
|
178
|
+
def supports_migrations?
|
|
179
|
+
true
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Returns the underlying database name.
|
|
183
|
+
# @override
|
|
184
|
+
def database_name
|
|
185
|
+
@connection.database_name
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# @private
|
|
189
|
+
def native_sql_to_type(type)
|
|
190
|
+
if /^(.*?)\(([0-9]+)\)/ =~ type
|
|
191
|
+
tname, limit = $1, $2.to_i
|
|
192
|
+
ntypes = native_database_types
|
|
193
|
+
if ntypes[:primary_key] == type
|
|
194
|
+
return :primary_key, nil
|
|
195
|
+
else
|
|
196
|
+
ntypes.each do |name, val|
|
|
197
|
+
if name == :primary_key
|
|
198
|
+
next
|
|
199
|
+
end
|
|
200
|
+
if val[:name].downcase == tname.downcase &&
|
|
201
|
+
( val[:limit].nil? || val[:limit].to_i == limit )
|
|
202
|
+
return name, limit
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
elsif /^(.*?)/ =~ type
|
|
207
|
+
tname = $1
|
|
208
|
+
ntypes = native_database_types
|
|
209
|
+
if ntypes[:primary_key] == type
|
|
210
|
+
return :primary_key, nil
|
|
211
|
+
else
|
|
212
|
+
ntypes.each do |name, val|
|
|
213
|
+
if val[:name].downcase == tname.downcase && val[:limit].nil?
|
|
214
|
+
return name, nil
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
else
|
|
219
|
+
return :string, 255
|
|
220
|
+
end
|
|
221
|
+
return nil, nil
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def columns(table_name, name = nil)
|
|
225
|
+
@connection.columns(table_name.to_s)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# @override
|
|
229
|
+
def supports_views?
|
|
230
|
+
@connection.supports_views?
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Similar to {#exec_query} except it returns "raw" results in an array
|
|
234
|
+
# where each rows is a hash with keys as columns (just like Rails used to
|
|
235
|
+
# do up until 3.0) instead of wrapping them in a {#ActiveRecord::Result}.
|
|
236
|
+
# @param sql the query string (or AREL object)
|
|
237
|
+
# @param name logging marker for the executed SQL statement log entry
|
|
238
|
+
# @param binds the bind parameters
|
|
239
|
+
# @yield [v1, v2] depending on the row values returned from the query
|
|
240
|
+
# In case a block is given it will yield each row from the result set
|
|
241
|
+
# instead of returning mapped query results in an array.
|
|
242
|
+
# @return [Array] unless a block is given
|
|
243
|
+
def exec_query_raw(sql, name = 'SQL', binds = [], &block)
|
|
244
|
+
sql = to_sql(sql, binds) if sql.respond_to?(:to_sql)
|
|
245
|
+
|
|
246
|
+
if prepared_statements?
|
|
247
|
+
log(sql, name, binds) { @connection.execute_query_raw(sql, binds, &block) }
|
|
248
|
+
else
|
|
249
|
+
log(sql, name) { @connection.execute_query_raw(sql, &block) }
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# @private
|
|
254
|
+
# @override
|
|
255
|
+
def select_rows(sql, name = nil, binds = [])
|
|
256
|
+
exec_query_raw(sql, name, binds).map!(&:values)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Executes the SQL statement in the context of this connection.
|
|
260
|
+
# The return value from this method depends on the SQL type (whether
|
|
261
|
+
# it's a SELECT, INSERT etc.). For INSERTs a generated id might get
|
|
262
|
+
# returned while for UPDATE statements the affected row count.
|
|
263
|
+
# Please note that this method returns "raw" results (in an array) for
|
|
264
|
+
# statements that return a result set, while {#exec_query} is expected to
|
|
265
|
+
# return a `ActiveRecord::Result` (since AR 3.1).
|
|
266
|
+
# @note This method does not use prepared statements.
|
|
267
|
+
# @note The method does not emulate various "native" `execute` results on MRI.
|
|
268
|
+
# @see #exec_query
|
|
269
|
+
# @see #exec_insert
|
|
270
|
+
# @see #exec_update
|
|
271
|
+
def execute(sql, name = nil, binds = nil)
|
|
272
|
+
sql = to_sql(sql, binds) if binds
|
|
273
|
+
if name == :skip_logging
|
|
274
|
+
_execute(sql, name)
|
|
275
|
+
else
|
|
276
|
+
log(sql, name) { _execute(sql, name) }
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# We need to do it this way, to allow Rails stupid tests to always work
|
|
281
|
+
# even if we define a new `execute` method. Instead of mixing in a new
|
|
282
|
+
# `execute`, an `_execute` should be mixed in.
|
|
283
|
+
# @deprecated it was only introduced due tests
|
|
284
|
+
# @private
|
|
285
|
+
def _execute(sql, name = nil)
|
|
286
|
+
@connection.execute(sql)
|
|
287
|
+
end
|
|
288
|
+
private :_execute
|
|
289
|
+
|
|
290
|
+
# Kind of `execute(sql) rescue nil` but logging failures at debug level only.
|
|
291
|
+
def execute_quietly(sql, name = 'SQL')
|
|
292
|
+
log(sql, name) do
|
|
293
|
+
begin
|
|
294
|
+
_execute(sql)
|
|
295
|
+
rescue => e
|
|
296
|
+
logger.debug("#{e.class}: #{e.message}: #{sql}")
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# @override
|
|
302
|
+
def tables(name = nil)
|
|
303
|
+
@connection.tables
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# @override
|
|
307
|
+
def table_exists?(name)
|
|
308
|
+
return false unless name
|
|
309
|
+
@connection.table_exists?(name) # schema_name = nil
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
# @override
|
|
313
|
+
def data_sources
|
|
314
|
+
tables
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
# @override
|
|
318
|
+
def data_source_exists?(name)
|
|
319
|
+
table_exists?(name)
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
# @override
|
|
323
|
+
def indexes(table_name, name = nil, schema_name = nil)
|
|
324
|
+
@connection.indexes(table_name, name, schema_name)
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
# @override
|
|
328
|
+
def pk_and_sequence_for(table)
|
|
329
|
+
( key = primary_key(table) ) ? [ key, nil ] : nil
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
# @override
|
|
333
|
+
def primary_keys(table)
|
|
334
|
+
@connection.primary_keys(table)
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# @override
|
|
338
|
+
def foreign_keys(table_name)
|
|
339
|
+
@connection.foreign_keys(table_name)
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# Does our database (+ its JDBC driver) support foreign-keys?
|
|
343
|
+
# @since 1.3.18
|
|
344
|
+
# @override
|
|
345
|
+
def supports_foreign_keys?
|
|
346
|
+
@connection.supports_foreign_keys?
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
# @deprecated Rather use {#update_lob_value} instead.
|
|
350
|
+
def write_large_object(*args)
|
|
351
|
+
@connection.write_large_object(*args)
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# @param record the record e.g. `User.find(1)`
|
|
355
|
+
# @param column the model's column e.g. `User.columns_hash['photo']`
|
|
356
|
+
# @param value the lob value - string or (IO or Java) stream
|
|
357
|
+
def update_lob_value(record, column, value)
|
|
358
|
+
@connection.update_lob_value(record, column, value)
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
protected
|
|
362
|
+
|
|
363
|
+
# Take an id from the result of an INSERT query.
|
|
364
|
+
# @return [Integer, NilClass]
|
|
365
|
+
def last_inserted_id(result)
|
|
366
|
+
if result.is_a?(Hash) || result.is_a?(ActiveRecord::Result)
|
|
367
|
+
result.first.first[1] # .first = { "id"=>1 } .first = [ "id", 1 ]
|
|
368
|
+
else
|
|
369
|
+
result
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# aliasing #create_table_definition as #table_definition :
|
|
374
|
+
alias table_definition create_table_definition
|
|
375
|
+
|
|
376
|
+
# `TableDefinition.new native_database_types, name, temporary, options`
|
|
377
|
+
# and ActiveRecord 4.1 supports optional `as` argument (which defaults
|
|
378
|
+
# to nil) to provide the SQL to use to generate the table:
|
|
379
|
+
# `TableDefinition.new native_database_types, name, temporary, options, as`
|
|
380
|
+
# @private
|
|
381
|
+
def create_table_definition(*args)
|
|
382
|
+
table_definition(*args)
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# @note AR-4x arguments expected: `(name, temporary, options)`
|
|
386
|
+
# @private documented bellow
|
|
387
|
+
def new_table_definition(table_definition, *args)
|
|
388
|
+
table_definition.new(*args)
|
|
389
|
+
end
|
|
390
|
+
private :new_table_definition
|
|
391
|
+
|
|
392
|
+
# @private
|
|
393
|
+
def new_index_definition(table, name, unique, columns, lengths,
|
|
394
|
+
orders = nil, where = nil, type = nil, using = nil)
|
|
395
|
+
IndexDefinition.new(table, name, unique, columns, lengths, orders, where, type, using)
|
|
396
|
+
end
|
|
397
|
+
private :new_index_definition
|
|
398
|
+
|
|
399
|
+
#
|
|
400
|
+
|
|
401
|
+
# Provides backwards-compatibility on ActiveRecord 4.1 for DB adapters
|
|
402
|
+
# that override this and than call super expecting to work.
|
|
403
|
+
# @note This method is available in 4.0 but won't be in 4.1
|
|
404
|
+
# @private
|
|
405
|
+
def add_column_options!(sql, options)
|
|
406
|
+
sql << " DEFAULT #{quote(options[:default], options[:column])}" if options_include_default?(options)
|
|
407
|
+
# must explicitly check for :null to allow change_column to work on migrations
|
|
408
|
+
sql << " NOT NULL" if options[:null] == false
|
|
409
|
+
sql << " AUTO_INCREMENT" if options[:auto_increment] == true
|
|
410
|
+
end
|
|
411
|
+
public :add_column_options!
|
|
412
|
+
|
|
413
|
+
# @return whether `:prepared_statements` are to be used
|
|
414
|
+
def prepared_statements?
|
|
415
|
+
return @prepared_statements unless (@prepared_statements ||= nil).nil?
|
|
416
|
+
@prepared_statements = self.class.prepared_statements?(config)
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
# Allows changing the prepared statements setting for this connection.
|
|
420
|
+
# @see #prepared_statements?
|
|
421
|
+
#def prepared_statements=(statements)
|
|
422
|
+
# @prepared_statements = statements
|
|
423
|
+
#end
|
|
424
|
+
|
|
425
|
+
def self.prepared_statements?(config)
|
|
426
|
+
config.key?(:prepared_statements) ?
|
|
427
|
+
type_cast_config_to_boolean(config.fetch(:prepared_statements)) :
|
|
428
|
+
false # off by default - NOTE: on AR 4.x it's on by default !?
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
private
|
|
432
|
+
|
|
433
|
+
# Helper useful during {#quote} since AREL might pass in it's literals
|
|
434
|
+
# to be quoted, fixed since AREL 4.0.0.beta1 : http://git.io/7gyTig
|
|
435
|
+
def sql_literal?(value); ::Arel::Nodes::SqlLiteral === value; end
|
|
436
|
+
|
|
437
|
+
# Helper to get local/UTC time (based on `ActiveRecord::Base.default_timezone`).
|
|
438
|
+
def get_time(value)
|
|
439
|
+
get = ::ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
|
|
440
|
+
value.respond_to?(get) ? value.send(get) : value
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
# @return whether the given SQL string is a 'SELECT' like
|
|
444
|
+
# query (returning a result set)
|
|
445
|
+
def self.select?(sql)
|
|
446
|
+
JdbcConnection::select?(sql)
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
# @return whether the given SQL string is an 'INSERT' query
|
|
450
|
+
def self.insert?(sql)
|
|
451
|
+
JdbcConnection::insert?(sql)
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
# @return whether the given SQL string is an 'UPDATE' (or 'DELETE') query
|
|
455
|
+
def self.update?(sql)
|
|
456
|
+
! select?(sql) && ! insert?(sql)
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
unless defined? AbstractAdapter.type_cast_config_to_integer
|
|
460
|
+
|
|
461
|
+
# @private
|
|
462
|
+
def self.type_cast_config_to_integer(config)
|
|
463
|
+
config =~ /\A\d+\z/ ? config.to_i : config
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
# @private
|
|
469
|
+
def self.type_cast_config_to_boolean(config)
|
|
470
|
+
config == 'false' ? false : (config == 'true' ? true : config)
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
end
|