activerecord-jdbc-adapter 1.0.3-java → 50.1-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +33 -0
- data/.travis.yml +79 -0
- data/.yardopts +4 -0
- data/CONTRIBUTING.md +50 -0
- data/Gemfile +91 -0
- data/History.md +1191 -0
- data/LICENSE.txt +22 -17
- data/README.md +169 -0
- data/RUNNING_TESTS.md +127 -0
- data/Rakefile +294 -5
- data/Rakefile.jdbc +20 -0
- data/activerecord-jdbc-adapter.gemspec +55 -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/firebird_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
- data/lib/activerecord-jdbc-adapter.rb +0 -5
- data/lib/arel/visitors/compat.rb +60 -0
- data/lib/arel/visitors/db2.rb +128 -6
- data/lib/arel/visitors/derby.rb +103 -10
- data/lib/arel/visitors/firebird.rb +79 -0
- data/lib/arel/visitors/h2.rb +25 -0
- data/lib/arel/visitors/hsqldb.rb +18 -10
- 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 +293 -0
- data/lib/arjdbc.rb +11 -21
- data/lib/arjdbc/abstract/connection_management.rb +35 -0
- data/lib/arjdbc/abstract/core.rb +64 -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 +3 -1
- data/lib/arjdbc/db2/adapter.rb +630 -250
- 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 +1 -5
- data/lib/arjdbc/derby/active_record_patch.rb +13 -0
- data/lib/arjdbc/derby/adapter.rb +409 -217
- data/lib/arjdbc/derby/connection_methods.rb +16 -14
- data/lib/arjdbc/derby/schema_creation.rb +15 -0
- data/lib/arjdbc/discover.rb +62 -50
- data/lib/arjdbc/firebird.rb +3 -1
- data/lib/arjdbc/firebird/adapter.rb +365 -62
- data/lib/arjdbc/firebird/connection_methods.rb +23 -0
- data/lib/arjdbc/h2.rb +2 -3
- data/lib/arjdbc/h2/adapter.rb +273 -6
- data/lib/arjdbc/h2/connection_methods.rb +23 -8
- data/lib/arjdbc/hsqldb.rb +2 -3
- data/lib/arjdbc/hsqldb/adapter.rb +204 -77
- data/lib/arjdbc/hsqldb/connection_methods.rb +24 -10
- data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
- data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
- data/lib/arjdbc/informix.rb +4 -2
- data/lib/arjdbc/informix/adapter.rb +78 -54
- data/lib/arjdbc/informix/connection_methods.rb +8 -9
- data/lib/arjdbc/jdbc.rb +59 -2
- data/lib/arjdbc/jdbc/adapter.rb +356 -166
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -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 +27 -18
- data/lib/arjdbc/jdbc/column.rb +79 -20
- data/lib/arjdbc/jdbc/connection.rb +5 -119
- data/lib/arjdbc/jdbc/connection_methods.rb +32 -4
- data/lib/arjdbc/jdbc/error.rb +65 -0
- data/lib/arjdbc/jdbc/extension.rb +41 -29
- data/lib/arjdbc/jdbc/java.rb +5 -6
- data/lib/arjdbc/jdbc/jdbc.rake +3 -126
- data/lib/arjdbc/jdbc/railtie.rb +2 -9
- data/lib/arjdbc/jdbc/rake_tasks.rb +3 -10
- 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 +35 -19
- data/lib/arjdbc/mssql.rb +6 -3
- data/lib/arjdbc/mssql/adapter.rb +630 -298
- data/lib/arjdbc/mssql/column.rb +200 -0
- data/lib/arjdbc/mssql/connection_methods.rb +66 -17
- data/lib/arjdbc/mssql/explain_support.rb +99 -0
- data/lib/arjdbc/mssql/limit_helpers.rb +189 -50
- data/lib/arjdbc/mssql/lock_methods.rb +77 -0
- data/lib/arjdbc/mssql/types.rb +343 -0
- data/lib/arjdbc/mssql/utils.rb +82 -0
- data/lib/arjdbc/mysql.rb +2 -3
- data/lib/arjdbc/mysql/adapter.rb +86 -356
- data/lib/arjdbc/mysql/connection_methods.rb +159 -23
- data/lib/arjdbc/oracle/adapter.rb +714 -263
- data/lib/arjdbc/postgresql.rb +2 -3
- data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +24 -0
- data/lib/arjdbc/postgresql/adapter.rb +570 -400
- 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 +57 -18
- data/lib/arjdbc/postgresql/name.rb +24 -0
- data/lib/arjdbc/postgresql/oid_types.rb +192 -0
- data/lib/arjdbc/railtie.rb +11 -0
- data/lib/arjdbc/sqlite3.rb +2 -3
- data/lib/arjdbc/sqlite3/adapter.rb +518 -198
- data/lib/arjdbc/sqlite3/connection_methods.rb +49 -24
- data/lib/arjdbc/sybase.rb +2 -2
- data/lib/arjdbc/sybase/adapter.rb +7 -6
- data/lib/arjdbc/tasks.rb +13 -0
- data/lib/arjdbc/tasks/database_tasks.rb +52 -0
- data/lib/arjdbc/tasks/databases.rake +91 -0
- data/lib/arjdbc/tasks/databases3.rake +215 -0
- data/lib/arjdbc/tasks/databases4.rake +39 -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 +1 -6
- data/lib/generators/jdbc/USAGE +9 -0
- data/lib/generators/jdbc/jdbc_generator.rb +8 -0
- data/lib/jdbc_adapter.rb +1 -1
- data/lib/jdbc_adapter/rake_tasks.rb +3 -2
- data/lib/jdbc_adapter/version.rb +2 -1
- data/pom.xml +114 -0
- data/rails_generators/jdbc_generator.rb +1 -1
- data/rails_generators/templates/config/initializers/jdbc.rb +8 -5
- data/rails_generators/templates/lib/tasks/jdbc.rake +7 -4
- data/rakelib/01-tomcat.rake +51 -0
- data/rakelib/02-test.rake +132 -0
- data/rakelib/bundler_ext.rb +11 -0
- data/rakelib/compile.rake +67 -22
- data/rakelib/db.rake +61 -0
- data/rakelib/rails.rake +204 -29
- data/src/java/arjdbc/ArJdbcModule.java +286 -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 +99 -243
- data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +152 -0
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +174 -0
- data/src/java/arjdbc/{jdbc/JdbcConnectionFactory.java → h2/H2Module.java} +20 -6
- data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +27 -12
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +73 -0
- data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +7 -6
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +7 -29
- data/src/java/arjdbc/jdbc/Callable.java +44 -0
- data/src/java/arjdbc/jdbc/ConnectionFactory.java +132 -0
- data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +157 -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/RubyJdbcConnection.java +3622 -948
- data/src/java/arjdbc/mssql/MSSQLModule.java +90 -0
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +181 -0
- data/src/java/arjdbc/mysql/MySQLModule.java +99 -81
- 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 +387 -17
- data/src/java/arjdbc/postgresql/ByteaUtils.java +157 -0
- data/src/java/arjdbc/postgresql/PgResultSetMetaDataWrapper.java +23 -0
- data/src/java/arjdbc/postgresql/PostgreSQLModule.java +77 -0
- data/src/java/arjdbc/postgresql/PostgreSQLResult.java +184 -0
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +952 -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 +580 -0
- data/src/java/arjdbc/util/ObjectSupport.java +65 -0
- data/src/java/arjdbc/util/QuotingUtils.java +138 -0
- data/src/java/arjdbc/util/StringCache.java +63 -0
- data/src/java/arjdbc/util/StringHelper.java +159 -0
- metadata +245 -268
- data/History.txt +0 -369
- data/Manifest.txt +0 -180
- data/README.txt +0 -181
- data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
- 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/arel/visitors/mssql.rb +0 -44
- data/lib/arjdbc/jdbc/compatibility.rb +0 -51
- data/lib/arjdbc/jdbc/core_ext.rb +0 -24
- data/lib/arjdbc/jdbc/discover.rb +0 -18
- data/lib/arjdbc/jdbc/driver.rb +0 -44
- data/lib/arjdbc/jdbc/missing_functionality_helper.rb +0 -87
- data/lib/arjdbc/jdbc/quoted_primary_key.rb +0 -28
- data/lib/arjdbc/jdbc/require_driver.rb +0 -16
- data/lib/arjdbc/mimer.rb +0 -2
- data/lib/arjdbc/mimer/adapter.rb +0 -142
- data/lib/arjdbc/mssql/tsql_helper.rb +0 -61
- data/lib/arjdbc/oracle.rb +0 -3
- data/lib/arjdbc/oracle/connection_methods.rb +0 -11
- data/lib/pg.rb +0 -4
- data/rakelib/package.rake +0 -92
- data/rakelib/test.rake +0 -81
- data/src/java/arjdbc/jdbc/SQLBlock.java +0 -48
- data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +0 -127
- data/src/java/arjdbc/postgresql/PostgresqlRubyJdbcConnection.java +0 -57
- data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +0 -64
- data/test/abstract_db_create.rb +0 -117
- data/test/activerecord/connection_adapters/type_conversion_test.rb +0 -31
- data/test/activerecord/connections/native_jdbc_mysql/connection.rb +0 -25
- data/test/db/db2.rb +0 -11
- data/test/db/derby.rb +0 -12
- data/test/db/h2.rb +0 -11
- data/test/db/hsqldb.rb +0 -13
- data/test/db/informix.rb +0 -11
- data/test/db/jdbc.rb +0 -11
- data/test/db/jndi_config.rb +0 -40
- data/test/db/logger.rb +0 -3
- data/test/db/mssql.rb +0 -9
- data/test/db/mysql.rb +0 -10
- data/test/db/oracle.rb +0 -34
- data/test/db/postgres.rb +0 -9
- data/test/db/sqlite3.rb +0 -11
- data/test/db2_simple_test.rb +0 -66
- data/test/derby_migration_test.rb +0 -68
- data/test/derby_multibyte_test.rb +0 -12
- data/test/derby_simple_test.rb +0 -99
- data/test/generic_jdbc_connection_test.rb +0 -29
- data/test/h2_simple_test.rb +0 -41
- data/test/has_many_through.rb +0 -79
- data/test/helper.rb +0 -5
- data/test/hsqldb_simple_test.rb +0 -6
- data/test/informix_simple_test.rb +0 -48
- data/test/jdbc_common.rb +0 -25
- data/test/jndi_callbacks_test.rb +0 -40
- data/test/jndi_test.rb +0 -25
- data/test/manualTestDatabase.rb +0 -191
- data/test/models/add_not_null_column_to_table.rb +0 -12
- data/test/models/auto_id.rb +0 -18
- data/test/models/data_types.rb +0 -28
- data/test/models/entry.rb +0 -43
- data/test/models/mixed_case.rb +0 -25
- data/test/models/reserved_word.rb +0 -18
- data/test/models/string_id.rb +0 -18
- data/test/models/validates_uniqueness_of_string.rb +0 -19
- data/test/mssql_db_create_test.rb +0 -26
- data/test/mssql_identity_insert_test.rb +0 -19
- data/test/mssql_legacy_types_test.rb +0 -58
- data/test/mssql_limit_offset_test.rb +0 -136
- data/test/mssql_multibyte_test.rb +0 -18
- data/test/mssql_simple_test.rb +0 -55
- data/test/mysql_db_create_test.rb +0 -27
- data/test/mysql_info_test.rb +0 -113
- data/test/mysql_multibyte_test.rb +0 -10
- data/test/mysql_nonstandard_primary_key_test.rb +0 -42
- data/test/mysql_simple_test.rb +0 -49
- data/test/oracle_simple_test.rb +0 -18
- data/test/oracle_specific_test.rb +0 -83
- data/test/pick_rails_version.rb +0 -3
- data/test/postgres_db_create_test.rb +0 -32
- data/test/postgres_drop_db_test.rb +0 -16
- data/test/postgres_mixed_case_test.rb +0 -29
- data/test/postgres_nonseq_pkey_test.rb +0 -38
- data/test/postgres_reserved_test.rb +0 -22
- data/test/postgres_schema_search_path_test.rb +0 -44
- data/test/postgres_simple_test.rb +0 -51
- data/test/postgres_table_alias_length_test.rb +0 -15
- data/test/simple.rb +0 -546
- data/test/sqlite3_simple_test.rb +0 -233
- data/test/sybase_jtds_simple_test.rb +0 -28
@@ -1,14 +1,28 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
10
13
|
|
11
|
-
|
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
|
12
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)
|
13
26
|
end
|
27
|
+
alias_method :jdbchsqldb_connection, :hsqldb_connection
|
14
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
|
data/lib/arjdbc/informix.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
-
require 'arjdbc
|
2
|
-
|
1
|
+
require 'arjdbc'
|
2
|
+
ArJdbc.load_java_part :Informix
|
3
3
|
require 'arjdbc/informix/adapter'
|
4
|
+
require 'arjdbc/informix/connection_methods'
|
5
|
+
ArJdbc.warn_unsupported_adapter 'informix', [4, 2] # warns on AR >= 4.2
|
@@ -1,47 +1,53 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
+
)
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
@@db_major_version = base.select_one("SELECT dbinfo('version', 'major') version FROM systables WHERE tabid = 1")['version'].to_i
|
26
|
+
ActiveRecord::Base.after_save :after_save_with_informix_lob
|
27
|
+
@@_lob_callback_added = true
|
28
|
+
end
|
32
29
|
end
|
33
30
|
|
31
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcColumn#column_types
|
34
32
|
def self.column_selector
|
35
|
-
[ /informix/i,
|
36
|
-
lambda { |cfg, column| column.extend(::ArJdbc::Informix::Column) } ]
|
33
|
+
[ /informix/i, lambda { |cfg, column| column.extend(ColumnMethods) } ]
|
37
34
|
end
|
38
35
|
|
36
|
+
JdbcConnection = ::ActiveRecord::ConnectionAdapters::InformixJdbcConnection
|
37
|
+
|
38
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
|
39
39
|
def self.jdbc_connection_class
|
40
40
|
::ActiveRecord::ConnectionAdapters::InformixJdbcConnection
|
41
41
|
end
|
42
42
|
|
43
|
-
|
44
|
-
|
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
|
45
51
|
# TODO: Test all Informix column types.
|
46
52
|
def simplified_type(field_type)
|
47
53
|
if field_type =~ /serial/i
|
@@ -50,21 +56,23 @@ module ::ArJdbc
|
|
50
56
|
super
|
51
57
|
end
|
52
58
|
end
|
59
|
+
|
53
60
|
end
|
54
61
|
|
55
|
-
def modify_types(
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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
|
68
76
|
end
|
69
77
|
|
70
78
|
def prefetch_primary_key?(table_name = nil)
|
@@ -81,11 +89,9 @@ module ::ArJdbc
|
|
81
89
|
|
82
90
|
def add_limit_offset!(sql, options)
|
83
91
|
if options[:limit]
|
84
|
-
limit = "FIRST #{options[:limit]}"
|
85
|
-
|
86
|
-
|
87
|
-
"SKIP #{options[:offset]}" : "")
|
88
|
-
sql.sub!(/^select /i, "SELECT #{offset} #{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} ")
|
89
95
|
end
|
90
96
|
sql
|
91
97
|
end
|
@@ -100,10 +106,11 @@ module ::ArJdbc
|
|
100
106
|
end
|
101
107
|
|
102
108
|
def quote(value, column = nil)
|
103
|
-
|
109
|
+
column_type = column && column.type
|
110
|
+
if column_type == :binary || column_type == :text
|
104
111
|
# LOBs are updated separately by an after_save trigger.
|
105
112
|
"NULL"
|
106
|
-
elsif
|
113
|
+
elsif column_type == :date
|
107
114
|
"'#{value.mon}/#{value.day}/#{value.year}'"
|
108
115
|
else
|
109
116
|
super
|
@@ -129,10 +136,27 @@ module ::ArJdbc
|
|
129
136
|
@connection.execute_update("DROP INDEX #{index_name(table_name, options)}")
|
130
137
|
end
|
131
138
|
|
132
|
-
|
133
|
-
def select(sql, name = nil)
|
139
|
+
def select(sql, *rest)
|
134
140
|
# Informix does not like "= NULL", "!= NULL", or "<> NULL".
|
135
|
-
|
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
|
136
149
|
end
|
150
|
+
|
137
151
|
end # module Informix
|
138
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
|
@@ -1,10 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
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)
|
9
8
|
end
|
10
|
-
end
|
9
|
+
end
|
data/lib/arjdbc/jdbc.rb
CHANGED
@@ -1,2 +1,59 @@
|
|
1
|
-
require '
|
2
|
-
|
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
|
data/lib/arjdbc/jdbc/adapter.rb
CHANGED
@@ -1,285 +1,475 @@
|
|
1
1
|
require 'active_record/version'
|
2
2
|
require 'active_record/connection_adapters/abstract_adapter'
|
3
|
+
|
3
4
|
require 'arjdbc/version'
|
4
|
-
require 'arjdbc/jdbc/require_driver'
|
5
|
-
require 'arjdbc/jdbc/connection_methods'
|
6
|
-
require 'arjdbc/jdbc/compatibility'
|
7
|
-
require 'arjdbc/jdbc/core_ext'
|
8
5
|
require 'arjdbc/jdbc/java'
|
9
|
-
require 'arjdbc/jdbc/
|
10
|
-
require 'arjdbc/jdbc/
|
6
|
+
require 'arjdbc/jdbc/base_ext'
|
7
|
+
require 'arjdbc/jdbc/error'
|
8
|
+
require 'arjdbc/jdbc/connection_methods'
|
11
9
|
require 'arjdbc/jdbc/column'
|
12
10
|
require 'arjdbc/jdbc/connection'
|
13
11
|
require 'arjdbc/jdbc/callbacks'
|
14
12
|
require 'arjdbc/jdbc/extension'
|
15
|
-
require '
|
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'
|
16
18
|
|
17
19
|
module ActiveRecord
|
18
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.
|
19
38
|
class JdbcAdapter < AbstractAdapter
|
20
|
-
|
21
|
-
|
22
|
-
include
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
spec = adapter_spec config
|
29
|
-
unless connection
|
30
|
-
connection_class = jdbc_connection_class spec
|
31
|
-
connection = connection_class.new config
|
32
|
-
end
|
33
|
-
super(connection, logger)
|
34
|
-
extend spec if spec
|
35
|
-
configure_arel2_visitors(config)
|
36
|
-
connection.adapter = self
|
37
|
-
JndiConnectionPoolCallbacks.prepare(self, connection)
|
38
|
-
end
|
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
|
39
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
|
40
52
|
def jdbc_connection_class(spec)
|
41
53
|
connection_class = spec.jdbc_connection_class if spec && spec.respond_to?(:jdbc_connection_class)
|
42
|
-
connection_class
|
43
|
-
connection_class
|
54
|
+
connection_class ? connection_class : ::ActiveRecord::ConnectionAdapters::JdbcConnection
|
44
55
|
end
|
45
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
|
46
60
|
def jdbc_column_class
|
47
|
-
ActiveRecord::ConnectionAdapters::JdbcColumn
|
61
|
+
::ActiveRecord::ConnectionAdapters::JdbcColumn
|
48
62
|
end
|
49
63
|
|
50
|
-
#
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
#
|
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
|
56
72
|
def adapter_spec(config)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
return spec if spec
|
63
|
-
end
|
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
|
64
78
|
end
|
79
|
+
end
|
65
80
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
config[:dialect] = conn.getMetaData.getClass.getName.downcase
|
71
|
-
|
72
|
-
# Derby-specific hack
|
73
|
-
if ::ArJdbc::Derby.adapter_matcher(config[:dialect], config)
|
74
|
-
# Needed to set the correct database schema name
|
75
|
-
config[:username] ||= conn.getMetaData.getUserName
|
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
|
76
85
|
end
|
77
|
-
|
78
|
-
|
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]
|
79
91
|
end
|
80
92
|
end
|
93
|
+
|
81
94
|
nil
|
82
95
|
end
|
83
96
|
|
84
|
-
|
85
|
-
|
97
|
+
ADAPTER_NAME = 'JDBC'.freeze
|
98
|
+
|
99
|
+
# @return [String] the 'JDBC' adapter name.
|
100
|
+
def adapter_name
|
101
|
+
ADAPTER_NAME
|
86
102
|
end
|
87
103
|
|
88
|
-
|
89
|
-
|
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
|
90
119
|
end
|
91
120
|
|
92
|
-
|
93
|
-
|
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 }
|
94
127
|
end
|
95
128
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
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
|
107
154
|
end
|
108
155
|
end
|
109
156
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
true
|
114
|
-
else
|
115
|
-
super
|
116
|
-
end
|
157
|
+
# @override introduced in AR 4.2
|
158
|
+
def valid_type?(type)
|
159
|
+
! native_database_types[type].nil?
|
117
160
|
end
|
118
161
|
|
119
|
-
|
120
|
-
|
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
|
121
167
|
end
|
122
168
|
|
123
|
-
|
124
|
-
|
169
|
+
# Abstract adapter default implementation does nothing silently.
|
170
|
+
# @override
|
171
|
+
def structure_dump
|
172
|
+
raise NotImplementedError, "structure_dump not supported"
|
125
173
|
end
|
126
174
|
|
127
|
-
|
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
|
128
185
|
@connection.database_name
|
129
186
|
end
|
130
187
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
limit = $2.to_i
|
135
|
-
|
136
|
-
if
|
137
|
-
return :primary_key,nil
|
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
|
138
195
|
else
|
139
|
-
|
196
|
+
ntypes.each do |name, val|
|
140
197
|
if name == :primary_key
|
141
198
|
next
|
142
199
|
end
|
143
|
-
if val[:name].downcase == tname.downcase &&
|
144
|
-
|
200
|
+
if val[:name].downcase == tname.downcase &&
|
201
|
+
( val[:limit].nil? || val[:limit].to_i == limit )
|
202
|
+
return name, limit
|
145
203
|
end
|
146
204
|
end
|
147
205
|
end
|
148
|
-
elsif /^(.*?)/ =~
|
206
|
+
elsif /^(.*?)/ =~ type
|
149
207
|
tname = $1
|
150
|
-
|
151
|
-
if
|
152
|
-
return :primary_key,nil
|
208
|
+
ntypes = native_database_types
|
209
|
+
if ntypes[:primary_key] == type
|
210
|
+
return :primary_key, nil
|
153
211
|
else
|
154
|
-
|
212
|
+
ntypes.each do |name, val|
|
155
213
|
if val[:name].downcase == tname.downcase && val[:limit].nil?
|
156
|
-
return name,nil
|
214
|
+
return name, nil
|
157
215
|
end
|
158
216
|
end
|
159
217
|
end
|
160
218
|
else
|
161
|
-
return :string,255
|
219
|
+
return :string, 255
|
162
220
|
end
|
163
|
-
return nil,nil
|
221
|
+
return nil, nil
|
164
222
|
end
|
165
223
|
|
166
|
-
def
|
167
|
-
@connection.
|
224
|
+
def columns(table_name, name = nil)
|
225
|
+
@connection.columns(table_name.to_s)
|
168
226
|
end
|
169
227
|
|
170
|
-
|
171
|
-
|
172
|
-
@connection
|
228
|
+
# @override
|
229
|
+
def supports_views?
|
230
|
+
@connection.supports_views?
|
173
231
|
end
|
174
232
|
|
175
|
-
|
176
|
-
|
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
|
177
251
|
end
|
178
252
|
|
179
|
-
|
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
|
180
273
|
if name == :skip_logging
|
181
|
-
_execute(sql)
|
274
|
+
_execute(sql, name)
|
182
275
|
else
|
183
|
-
log(sql, name) { _execute(sql) }
|
276
|
+
log(sql, name) { _execute(sql, name) }
|
184
277
|
end
|
185
278
|
end
|
186
279
|
|
187
|
-
#
|
188
|
-
# even if we define a new execute method. Instead of mixing in a new
|
189
|
-
# execute
|
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
|
190
285
|
def _execute(sql, name = nil)
|
191
286
|
@connection.execute(sql)
|
192
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
|
193
300
|
|
194
|
-
|
195
|
-
|
301
|
+
# @override
|
302
|
+
def tables(name = nil)
|
303
|
+
@connection.tables
|
196
304
|
end
|
197
305
|
|
198
|
-
|
199
|
-
|
306
|
+
# @override
|
307
|
+
def table_exists?(name)
|
308
|
+
return false unless name
|
309
|
+
@connection.table_exists?(name) # schema_name = nil
|
200
310
|
end
|
201
|
-
|
202
|
-
|
311
|
+
|
312
|
+
# @override
|
313
|
+
def data_sources
|
314
|
+
tables
|
203
315
|
end
|
204
316
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
alias_chained_method :insert, :query_dirty, :jdbc_insert
|
317
|
+
# @override
|
318
|
+
def data_source_exists?(name)
|
319
|
+
table_exists?(name)
|
320
|
+
end
|
210
321
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
end
|
322
|
+
# @override
|
323
|
+
def indexes(table_name, name = nil, schema_name = nil)
|
324
|
+
@connection.indexes(table_name, name, schema_name)
|
215
325
|
end
|
216
326
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
rows
|
327
|
+
# @override
|
328
|
+
def pk_and_sequence_for(table)
|
329
|
+
( key = primary_key(table) ) ? [ key, nil ] : nil
|
221
330
|
end
|
222
331
|
|
223
|
-
|
224
|
-
|
225
|
-
|
332
|
+
# @override
|
333
|
+
def primary_keys(table)
|
334
|
+
@connection.primary_keys(table)
|
226
335
|
end
|
227
336
|
|
228
|
-
|
229
|
-
|
337
|
+
# @override
|
338
|
+
def foreign_keys(table_name)
|
339
|
+
@connection.foreign_keys(table_name)
|
230
340
|
end
|
231
|
-
alias_chained_method :columns, :query_cache, :jdbc_columns
|
232
341
|
|
233
|
-
|
234
|
-
|
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?
|
235
347
|
end
|
236
348
|
|
237
|
-
|
238
|
-
|
349
|
+
# @deprecated Rather use {#update_lob_value} instead.
|
350
|
+
def write_large_object(*args)
|
351
|
+
@connection.write_large_object(*args)
|
239
352
|
end
|
240
353
|
|
241
|
-
|
242
|
-
|
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
|
243
371
|
end
|
244
372
|
|
245
|
-
|
246
|
-
|
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)
|
247
383
|
end
|
248
384
|
|
249
|
-
|
250
|
-
|
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)
|
251
389
|
end
|
390
|
+
private :new_table_definition
|
252
391
|
|
253
|
-
|
254
|
-
|
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)
|
255
396
|
end
|
397
|
+
private :new_index_definition
|
256
398
|
|
257
|
-
|
258
|
-
|
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
|
259
410
|
end
|
411
|
+
public :add_column_options!
|
260
412
|
|
261
|
-
|
262
|
-
|
263
|
-
|
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)
|
264
417
|
end
|
265
418
|
|
266
|
-
|
267
|
-
|
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 !?
|
268
429
|
end
|
269
430
|
|
270
|
-
|
271
|
-
|
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)
|
272
447
|
end
|
273
448
|
|
274
|
-
|
275
|
-
|
449
|
+
# @return whether the given SQL string is an 'INSERT' query
|
450
|
+
def self.insert?(sql)
|
451
|
+
JdbcConnection::insert?(sql)
|
276
452
|
end
|
277
453
|
|
278
|
-
|
279
|
-
|
280
|
-
|
454
|
+
# @return whether the given SQL string is an 'UPDATE' (or 'DELETE') query
|
455
|
+
def self.update?(sql)
|
456
|
+
! select?(sql) && ! insert?(sql)
|
281
457
|
end
|
282
|
-
|
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
|
+
|
283
473
|
end
|
284
474
|
end
|
285
475
|
end
|