activerecord-jdbc-adapter 1.3.0.beta1 → 1.3.0.beta2
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.
- data/.gitignore +12 -11
- data/.travis.yml +36 -7
- data/Appraisals +3 -3
- data/Gemfile +1 -1
- data/Gemfile.lock +13 -6
- data/History.txt +64 -0
- data/README.md +8 -1
- data/Rakefile +3 -1
- data/gemfiles/rails23.gemfile +1 -1
- data/gemfiles/rails23.gemfile.lock +6 -5
- data/gemfiles/rails30.gemfile +1 -1
- data/gemfiles/rails30.gemfile.lock +7 -6
- data/gemfiles/rails31.gemfile +1 -1
- data/gemfiles/rails31.gemfile.lock +6 -5
- data/gemfiles/rails32.gemfile +1 -1
- data/gemfiles/rails32.gemfile.lock +6 -5
- data/gemfiles/rails40.gemfile +2 -4
- data/gemfiles/rails40.gemfile.lock +37 -51
- data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
- data/lib/active_record/connection_adapters/db2_adapter.rb +1 -1
- data/lib/arel/visitors/db2.rb +5 -1
- data/lib/arel/visitors/hsqldb.rb +1 -0
- data/lib/arel/visitors/sql_server.rb +55 -13
- data/lib/arjdbc/db2/adapter.rb +197 -227
- data/lib/arjdbc/db2/as400.rb +124 -0
- data/lib/arjdbc/db2/connection_methods.rb +20 -1
- data/lib/arjdbc/derby/adapter.rb +17 -85
- data/lib/arjdbc/derby/connection_methods.rb +2 -1
- data/lib/arjdbc/discover.rb +55 -47
- data/lib/arjdbc/h2/adapter.rb +52 -18
- data/lib/arjdbc/h2/connection_methods.rb +10 -2
- data/lib/arjdbc/hsqldb/adapter.rb +33 -9
- data/lib/arjdbc/hsqldb/connection_methods.rb +10 -2
- data/lib/arjdbc/informix.rb +2 -1
- data/lib/arjdbc/jdbc.rb +5 -1
- data/lib/arjdbc/jdbc/adapter.rb +167 -89
- 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 +25 -3
- data/lib/arjdbc/jdbc/callbacks.rb +9 -8
- data/lib/arjdbc/jdbc/column.rb +8 -20
- data/lib/arjdbc/jdbc/connection.rb +69 -80
- data/lib/arjdbc/jdbc/extension.rb +6 -8
- data/lib/arjdbc/jdbc/jdbc.rake +3 -141
- data/lib/arjdbc/jdbc/rake_tasks.rb +3 -10
- data/lib/arjdbc/mssql/adapter.rb +108 -34
- data/lib/arjdbc/mssql/connection_methods.rb +3 -1
- data/lib/arjdbc/mssql/limit_helpers.rb +3 -2
- data/lib/arjdbc/mssql/lock_helpers.rb +5 -1
- data/lib/arjdbc/mysql/adapter.rb +127 -70
- data/lib/arjdbc/mysql/connection_methods.rb +5 -2
- data/lib/arjdbc/oracle/adapter.rb +124 -94
- data/lib/arjdbc/oracle/connection_methods.rb +2 -1
- data/lib/arjdbc/postgresql/adapter.rb +99 -67
- data/lib/arjdbc/postgresql/column_cast.rb +3 -5
- data/lib/arjdbc/postgresql/connection_methods.rb +6 -6
- data/lib/arjdbc/railtie.rb +3 -1
- data/lib/arjdbc/sqlite3/adapter.rb +60 -43
- data/lib/arjdbc/sqlite3/connection_methods.rb +9 -9
- data/lib/arjdbc/sybase.rb +1 -1
- data/lib/arjdbc/tasks.rb +13 -0
- data/lib/arjdbc/tasks/database_tasks.rb +50 -0
- data/lib/arjdbc/tasks/databases.rake +89 -0
- data/lib/arjdbc/tasks/databases3.rake +203 -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 +29 -0
- data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
- data/lib/arjdbc/tasks/jdbc_database_tasks.rb +122 -0
- data/lib/arjdbc/tasks/mssql_database_tasks.rb +36 -0
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +297 -0
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +62 -0
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +11 -12
- 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/02-test.rake +42 -15
- data/rakelib/compile.rake +29 -2
- data/rakelib/db.rake +2 -1
- data/rakelib/rails.rake +23 -6
- data/src/java/arjdbc/ArJdbcModule.java +175 -0
- data/src/java/arjdbc/db2/DB2Module.java +2 -1
- data/src/java/arjdbc/derby/DerbyModule.java +5 -24
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +3 -2
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +3 -46
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1001 -259
- data/src/java/arjdbc/mssql/MSSQLModule.java +2 -1
- data/src/java/arjdbc/mysql/MySQLModule.java +4 -3
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +12 -7
- data/src/java/arjdbc/oracle/OracleModule.java +2 -1
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +2 -1
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +12 -0
- data/test/db/db2.rb +14 -7
- data/test/db/db2/rake_test.rb +82 -0
- data/test/db/db2/rake_test_data.sql +35 -0
- data/test/db/db2/simple_test.rb +20 -0
- data/test/db/db2/unit_test.rb +3 -1
- data/test/db/derby.rb +7 -5
- data/test/db/derby/rake_test.rb +96 -0
- data/test/db/derby/simple_test.rb +10 -2
- data/test/db/h2.rb +6 -8
- data/test/db/h2/identity_column_test.rb +35 -0
- data/test/db/h2/offset_test.rb +49 -0
- data/test/db/h2/rake_test.rb +98 -0
- data/test/db/h2/schema_dump_test.rb +5 -1
- data/test/db/hsqldb.rb +6 -10
- data/test/db/hsqldb/rake_test.rb +101 -0
- data/test/db/hsqldb/schema_dump_test.rb +5 -1
- data/test/db/hsqldb/simple_test.rb +8 -0
- data/test/db/jndi_config.rb +1 -3
- data/test/db/jndi_pooled_config.rb +1 -3
- data/test/db/mssql/limit_offset_test.rb +23 -14
- data/test/db/mssql/rake_test.rb +143 -0
- data/test/db/mysql/_rails_test_mysql.32.out +1069 -1252
- data/test/db/mysql/nonstandard_primary_key_test.rb +21 -24
- data/test/db/mysql/rake_test.rb +97 -0
- data/test/db/mysql/schema_dump_test.rb +11 -11
- data/test/db/mysql/simple_test.rb +52 -3
- data/test/db/mysql/statement_escaping_test.rb +46 -0
- data/test/db/oracle/rake_test.rb +100 -0
- data/test/db/oracle/simple_test.rb +48 -0
- data/test/db/postgres/_rails_test_postgres.32.out +998 -1370
- data/test/db/postgres/active_schema_unit_test.rb +68 -0
- data/test/db/postgres/connection_test.rb +10 -2
- data/test/db/postgres/data_types_test.rb +2 -2
- data/test/db/postgres/ltree_test.rb +6 -5
- data/test/db/postgres/native_types_test.rb +1 -5
- data/test/db/postgres/rake_test.rb +117 -0
- data/test/db/postgres/schema_dump_test.rb +9 -2
- data/test/db/postgres/schema_test.rb +4 -2
- data/test/db/postgres/simple_test.rb +57 -16
- data/test/db/sqlite3.rb +3 -10
- data/test/db/sqlite3/_rails_test_sqlite3.32.out +1070 -1298
- data/test/db/sqlite3/rake_test.rb +71 -0
- data/test/db/sqlite3/simple_test.rb +9 -9
- data/test/has_many_through.rb +4 -1
- data/test/jdbc/db2.rb +14 -1
- data/test/jdbc_column_test.rb +23 -0
- data/test/{generic_jdbc_connection_test.rb → jdbc_connection_test.rb} +22 -17
- data/test/jndi_callbacks_test.rb +26 -28
- data/test/jndi_test.rb +7 -16
- data/test/models/data_types.rb +2 -1
- data/test/models/thing.rb +1 -0
- data/test/rails/mysql.rb +13 -0
- data/test/rails/sqlite3/version.rb +6 -0
- data/test/rails_stub.rb +31 -0
- data/test/rake_test_support.rb +298 -0
- data/test/serialize.rb +2 -4
- data/test/{helper.rb → shared_helper.rb} +0 -0
- data/test/simple.rb +167 -93
- data/test/test_helper.rb +52 -16
- metadata +388 -354
- data/lib/pg.rb +0 -26
- data/test/abstract_db_create.rb +0 -139
- data/test/activerecord/connection_adapters/type_conversion_test.rb +0 -36
- data/test/db/mssql/db_create_test.rb +0 -29
- data/test/db/mysql/db_create_test.rb +0 -33
- data/test/db/postgres/db_create_test.rb +0 -44
- data/test/db/postgres/db_drop_test.rb +0 -17
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
# rails tasks already defined; load the override tasks now
|
|
5
|
-
load jdbc_rakefile
|
|
6
|
-
else
|
|
7
|
-
# rails tasks not loaded yet; load as an import
|
|
8
|
-
Rake.application.add_import(jdbc_rakefile)
|
|
9
|
-
end
|
|
10
|
-
end
|
|
1
|
+
# @deprecated
|
|
2
|
+
warn "[DEPRECATED] load 'arjdbc/tasks.rb' instead of 'arjdbc/jdbc/rake_tasks.rb'"
|
|
3
|
+
load 'arjdbc/tasks.rb'
|
data/lib/arjdbc/mssql/adapter.rb
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
ArJdbc.load_java_part :MSSQL
|
|
2
|
+
|
|
1
3
|
require 'strscan'
|
|
2
4
|
require 'arjdbc/mssql/utils'
|
|
3
5
|
require 'arjdbc/mssql/tsql_methods'
|
|
4
6
|
require 'arjdbc/mssql/limit_helpers'
|
|
5
7
|
require 'arjdbc/mssql/lock_helpers'
|
|
6
8
|
require 'arjdbc/mssql/explain_support'
|
|
7
|
-
require 'arjdbc/jdbc/serialized_attributes_helper'
|
|
8
9
|
|
|
9
10
|
module ArJdbc
|
|
10
11
|
module MSSQL
|
|
@@ -12,39 +13,41 @@ module ArJdbc
|
|
|
12
13
|
include TSqlMethods
|
|
13
14
|
|
|
14
15
|
include ExplainSupport
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def self.extended(base)
|
|
19
|
-
unless @@_lob_callback_added
|
|
20
|
-
ActiveRecord::Base.class_eval do
|
|
21
|
-
def after_save_with_mssql_lob
|
|
22
|
-
self.class.columns.select { |c| c.sql_type =~ /image/i }.each do |column|
|
|
23
|
-
value = ::ArJdbc::SerializedAttributesHelper.dump_column_value(self, column)
|
|
24
|
-
next if value.nil? || (value == '')
|
|
25
|
-
|
|
26
|
-
connection.write_large_object(
|
|
27
|
-
column.type == :binary, column.name,
|
|
28
|
-
self.class.table_name, self.class.primary_key,
|
|
29
|
-
quote_value(id), value
|
|
30
|
-
)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
ActiveRecord::Base.after_save :after_save_with_mssql_lob
|
|
36
|
-
@@_lob_callback_added = true
|
|
37
|
-
end
|
|
16
|
+
|
|
17
|
+
def self.extended(adapter) # :nodoc:
|
|
18
|
+
initialize!
|
|
38
19
|
|
|
39
|
-
if ( version =
|
|
20
|
+
if ( version = adapter.sqlserver_version ) == '2000'
|
|
40
21
|
extend LimitHelpers::SqlServer2000AddLimitOffset
|
|
41
22
|
else
|
|
42
23
|
extend LimitHelpers::SqlServerAddLimitOffset
|
|
43
24
|
end
|
|
44
|
-
|
|
45
|
-
base.configure_connection
|
|
25
|
+
adapter.config[:sqlserver_version] ||= version
|
|
46
26
|
end
|
|
47
27
|
|
|
28
|
+
@@_initialized = nil
|
|
29
|
+
|
|
30
|
+
def self.initialize!
|
|
31
|
+
return if @@_initialized; @@_initialized = true
|
|
32
|
+
|
|
33
|
+
require 'arjdbc/jdbc/serialized_attributes_helper'
|
|
34
|
+
ActiveRecord::Base.class_eval do
|
|
35
|
+
def after_save_with_mssql_lob
|
|
36
|
+
self.class.columns.select { |c| c.sql_type =~ /image/i }.each do |column|
|
|
37
|
+
value = ::ArJdbc::SerializedAttributesHelper.dump_column_value(self, column)
|
|
38
|
+
next if value.nil? || (value == '')
|
|
39
|
+
|
|
40
|
+
self.class.connection.write_large_object(
|
|
41
|
+
column.type == :binary, column.name,
|
|
42
|
+
self.class.table_name, self.class.primary_key,
|
|
43
|
+
self.class.connection.quote(id), value
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
ActiveRecord::Base.after_save :after_save_with_mssql_lob
|
|
49
|
+
end
|
|
50
|
+
|
|
48
51
|
def configure_connection
|
|
49
52
|
use_database # config[:database]
|
|
50
53
|
end
|
|
@@ -72,7 +75,7 @@ module ArJdbc
|
|
|
72
75
|
@sqlserver_version ||= begin
|
|
73
76
|
config_version = config[:sqlserver_version]
|
|
74
77
|
config_version ? config_version.to_s :
|
|
75
|
-
select_value("SELECT @@version")[/Microsoft SQL Server\s
|
|
78
|
+
select_value("SELECT @@version")[/(Microsoft SQL Server\s+|Microsoft SQL Azure.+\n.+)(\d{4})/, 2]
|
|
76
79
|
end
|
|
77
80
|
end
|
|
78
81
|
|
|
@@ -310,13 +313,17 @@ module ArJdbc
|
|
|
310
313
|
quote_column_name(name)
|
|
311
314
|
end
|
|
312
315
|
|
|
316
|
+
# def quote_table_name_for_assignment(table, attr)
|
|
317
|
+
# quote_column_name(attr)
|
|
318
|
+
# end if ::ActiveRecord::VERSION::MAJOR > 3
|
|
319
|
+
|
|
313
320
|
def quote_column_name(name)
|
|
314
321
|
name.to_s.split('.').map do |n| # "[#{name}]"
|
|
315
322
|
n =~ /^\[.*\]$/ ? n : "[#{n.gsub(']', ']]')}]"
|
|
316
323
|
end.join('.')
|
|
317
324
|
end
|
|
318
325
|
|
|
319
|
-
ADAPTER_NAME = 'MSSQL'
|
|
326
|
+
ADAPTER_NAME = 'MSSQL'.freeze
|
|
320
327
|
|
|
321
328
|
def adapter_name # :nodoc:
|
|
322
329
|
ADAPTER_NAME
|
|
@@ -351,12 +358,13 @@ module ArJdbc
|
|
|
351
358
|
#
|
|
352
359
|
# http://blogs.msdn.com/b/mssqlisv/archive/2007/03/23/upgrading-to-sql-server-2005-and-default-schema-setting.aspx
|
|
353
360
|
|
|
354
|
-
# Returns the default schema (to be used for table resolution) used for
|
|
355
|
-
# the {#current_user}.
|
|
361
|
+
# Returns the default schema (to be used for table resolution) used for the {#current_user}.
|
|
356
362
|
def default_schema
|
|
357
363
|
return current_user if sqlserver_2000?
|
|
358
364
|
@default_schema ||=
|
|
359
|
-
|
|
365
|
+
@connection.execute_query_raw(
|
|
366
|
+
"SELECT default_schema_name FROM sys.database_principals WHERE name = CURRENT_USER"
|
|
367
|
+
).first['default_schema_name']
|
|
360
368
|
end
|
|
361
369
|
alias_method :current_schema, :default_schema
|
|
362
370
|
|
|
@@ -372,12 +380,16 @@ module ArJdbc
|
|
|
372
380
|
|
|
373
381
|
# `SELECT CURRENT_USER`
|
|
374
382
|
def current_user
|
|
375
|
-
@current_user ||=
|
|
383
|
+
@current_user ||= @connection.execute_query_raw("SELECT CURRENT_USER").first['']
|
|
376
384
|
end
|
|
377
385
|
|
|
378
386
|
def charset
|
|
379
387
|
select_value "SELECT SERVERPROPERTY('SqlCharSetName')"
|
|
380
388
|
end
|
|
389
|
+
|
|
390
|
+
def collation
|
|
391
|
+
select_value "SELECT SERVERPROPERTY('Collation')"
|
|
392
|
+
end
|
|
381
393
|
|
|
382
394
|
def current_database
|
|
383
395
|
select_value 'SELECT DB_NAME()'
|
|
@@ -410,6 +422,10 @@ module ArJdbc
|
|
|
410
422
|
def create_database(name, options = {})
|
|
411
423
|
execute "CREATE DATABASE #{quote_table_name(name)}"
|
|
412
424
|
end
|
|
425
|
+
|
|
426
|
+
def database_exists?(name)
|
|
427
|
+
select_value "SELECT name FROM sys.databases WHERE name = '#{name}'"
|
|
428
|
+
end
|
|
413
429
|
|
|
414
430
|
def rename_table(table_name, new_table_name)
|
|
415
431
|
clear_cached_table(table_name)
|
|
@@ -601,7 +617,23 @@ module ArJdbc
|
|
|
601
617
|
# NOTE: we allow to execute SQL as requested returning a results.
|
|
602
618
|
# e.g. this allows to use SQLServer's EXEC with a result set ...
|
|
603
619
|
sql = repair_special_columns to_sql(sql, binds)
|
|
604
|
-
|
|
620
|
+
if prepared_statements?
|
|
621
|
+
log(sql, name, binds) { @connection.execute_query(sql, binds) }
|
|
622
|
+
else
|
|
623
|
+
sql = suble_binds(sql, binds)
|
|
624
|
+
log(sql, name) { @connection.execute_query(sql) }
|
|
625
|
+
end
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
# @override
|
|
629
|
+
def exec_query_raw(sql, name = 'SQL', binds = [], &block) # :nodoc:
|
|
630
|
+
sql = repair_special_columns to_sql(sql, binds)
|
|
631
|
+
if prepared_statements?
|
|
632
|
+
log(sql, name, binds) { @connection.execute_query_raw(sql, binds, &block) }
|
|
633
|
+
else
|
|
634
|
+
sql = suble_binds(sql, binds)
|
|
635
|
+
log(sql, name) { @connection.execute_query_raw(sql, &block) }
|
|
636
|
+
end
|
|
605
637
|
end
|
|
606
638
|
|
|
607
639
|
private
|
|
@@ -671,7 +703,49 @@ module ArJdbc
|
|
|
671
703
|
end
|
|
672
704
|
|
|
673
705
|
module ActiveRecord::ConnectionAdapters
|
|
706
|
+
|
|
707
|
+
class MSSQLAdapter < JdbcAdapter
|
|
708
|
+
include ::ArJdbc::MSSQL
|
|
709
|
+
|
|
710
|
+
def initialize(*args)
|
|
711
|
+
::ArJdbc::MSSQL.initialize!
|
|
712
|
+
|
|
713
|
+
super # configure_connection happens in super
|
|
714
|
+
|
|
715
|
+
if ( version = self.sqlserver_version ) == '2000'
|
|
716
|
+
extend LimitHelpers::SqlServer2000AddLimitOffset
|
|
717
|
+
else
|
|
718
|
+
extend LimitHelpers::SqlServerAddLimitOffset
|
|
719
|
+
end
|
|
720
|
+
config[:sqlserver_version] ||= version
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
# some QUOTING caching :
|
|
724
|
+
|
|
725
|
+
@@quoted_table_names = {}
|
|
726
|
+
|
|
727
|
+
def quote_table_name(name)
|
|
728
|
+
unless quoted = @@quoted_table_names[name]
|
|
729
|
+
quoted = super
|
|
730
|
+
@@quoted_table_names[name] = quoted.freeze
|
|
731
|
+
end
|
|
732
|
+
quoted
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
@@quoted_column_names = {}
|
|
736
|
+
|
|
737
|
+
def quote_column_name(name)
|
|
738
|
+
unless quoted = @@quoted_column_names[name]
|
|
739
|
+
quoted = super
|
|
740
|
+
@@quoted_column_names[name] = quoted.freeze
|
|
741
|
+
end
|
|
742
|
+
quoted
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
end
|
|
746
|
+
|
|
674
747
|
class MSSQLColumn < JdbcColumn
|
|
675
748
|
include ArJdbc::MSSQL::Column
|
|
676
749
|
end
|
|
750
|
+
|
|
677
751
|
end
|
|
@@ -12,7 +12,9 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
|
12
12
|
config[:host] ||= "localhost"
|
|
13
13
|
config[:port] ||= 1433
|
|
14
14
|
config[:driver] ||= defined?(::Jdbc::JTDS.driver_name) ? ::Jdbc::JTDS.driver_name : 'net.sourceforge.jtds.jdbc.Driver'
|
|
15
|
-
config[:adapter_spec]
|
|
15
|
+
config[:adapter_spec] ||= ::ArJdbc::MSSQL
|
|
16
|
+
config[:adapter_class] = ActiveRecord::ConnectionAdapters::MSSQLAdapter unless config.key?(:adapter_class)
|
|
17
|
+
config[:connection_alive_sql] ||= 'SELECT 1'
|
|
16
18
|
|
|
17
19
|
config[:url] ||= begin
|
|
18
20
|
url = "jdbc:jtds:sqlserver://#{config[:host]}:#{config[:port]}/#{config[:database]}"
|
|
@@ -23,11 +23,12 @@ module ArJdbc
|
|
|
23
23
|
rest_of_query = from_table + '.' + rest_of_query
|
|
24
24
|
end
|
|
25
25
|
new_sql = "#{select} t.* FROM (SELECT ROW_NUMBER() OVER(#{order}) AS _row_num, #{rest_of_query}"
|
|
26
|
-
new_sql << ") AS t WHERE t._row_num BETWEEN #{start_row
|
|
26
|
+
new_sql << ") AS t WHERE t._row_num BETWEEN #{start_row} AND #{end_row}"
|
|
27
27
|
sql.replace(new_sql)
|
|
28
28
|
end
|
|
29
29
|
sql
|
|
30
30
|
end
|
|
31
|
+
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
module SqlServerAddLimitOffset
|
|
@@ -116,7 +117,7 @@ module ArJdbc
|
|
|
116
117
|
if order =~ /(\w*id\w*)/i
|
|
117
118
|
$1
|
|
118
119
|
else
|
|
119
|
-
unquoted_name = unquote_table_name(table_name)
|
|
120
|
+
unquoted_name = Utils.unquote_table_name(table_name)
|
|
120
121
|
model = descendants.find { |m| m.table_name == table_name || m.table_name == unquoted_name }
|
|
121
122
|
model ? model.primary_key : 'id'
|
|
122
123
|
end
|
|
@@ -2,6 +2,9 @@ module ArJdbc
|
|
|
2
2
|
module MSSQL
|
|
3
3
|
module LockHelpers
|
|
4
4
|
module SqlServerAddLock
|
|
5
|
+
|
|
6
|
+
SELECT_FROM_WHERE_RE = /\A(\s*SELECT\s.*?)(\sFROM\s)(.*?)(\sWHERE\s.*|)\Z/mi # :nodoc:
|
|
7
|
+
|
|
5
8
|
# Microsoft SQL Server uses its own syntax for SELECT .. FOR UPDATE:
|
|
6
9
|
# SELECT .. FROM table1 WITH(ROWLOCK,UPDLOCK), table2 WITH(ROWLOCK,UPDLOCK) WHERE ..
|
|
7
10
|
#
|
|
@@ -14,7 +17,7 @@ module ArJdbc
|
|
|
14
17
|
add_lock!(subselect, options)
|
|
15
18
|
return sql.replace(prefix + subselect + suffix)
|
|
16
19
|
end
|
|
17
|
-
unless sql =~
|
|
20
|
+
unless sql =~ SELECT_FROM_WHERE_RE
|
|
18
21
|
# If you get this error, this driver probably needs to be fixed.
|
|
19
22
|
raise NotImplementedError, "Don't know how to add_lock! to SQL statement: #{sql.inspect}"
|
|
20
23
|
end
|
|
@@ -66,6 +69,7 @@ module ArJdbc
|
|
|
66
69
|
end
|
|
67
70
|
sql
|
|
68
71
|
end
|
|
72
|
+
|
|
69
73
|
end
|
|
70
74
|
end
|
|
71
75
|
end
|
data/lib/arjdbc/mysql/adapter.rb
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
+
ArJdbc.load_java_part :MySQL
|
|
2
|
+
|
|
1
3
|
require 'bigdecimal'
|
|
2
4
|
require 'active_record/connection_adapters/abstract/schema_definitions'
|
|
3
5
|
require 'arjdbc/mysql/explain_support'
|
|
4
6
|
|
|
5
7
|
module ArJdbc
|
|
6
8
|
module MySQL
|
|
7
|
-
|
|
8
|
-
def self.extended(adapter)
|
|
9
|
-
adapter.configure_connection
|
|
10
|
-
end
|
|
11
|
-
|
|
9
|
+
|
|
12
10
|
def configure_connection
|
|
13
11
|
variables = config[:variables] || {}
|
|
14
12
|
# By default, MySQL 'where id is null' selects the last inserted id. Turn this off.
|
|
@@ -57,6 +55,16 @@ module ArJdbc
|
|
|
57
55
|
config.key?(:strict) ? config[:strict] : ::ActiveRecord::VERSION::MAJOR > 3
|
|
58
56
|
end
|
|
59
57
|
|
|
58
|
+
@@emulate_booleans = true
|
|
59
|
+
|
|
60
|
+
# Boolean emulation can be disabled using (or using the adapter method) :
|
|
61
|
+
#
|
|
62
|
+
# ArJdbc::MySQL.emulate_booleans = false
|
|
63
|
+
#
|
|
64
|
+
# @see ActiveRecord::ConnectionAdapters::MysqlAdapter#emulate_booleans
|
|
65
|
+
def self.emulate_booleans; @@emulate_booleans; end
|
|
66
|
+
def self.emulate_booleans=(emulate); @@emulate_booleans = emulate; end
|
|
67
|
+
|
|
60
68
|
module Column
|
|
61
69
|
|
|
62
70
|
def extract_default(default)
|
|
@@ -79,15 +87,19 @@ module ArJdbc
|
|
|
79
87
|
end
|
|
80
88
|
|
|
81
89
|
def simplified_type(field_type)
|
|
90
|
+
if adapter.respond_to?(:emulate_booleans) && adapter.emulate_booleans
|
|
91
|
+
return :boolean if field_type.downcase.index('tinyint(1)')
|
|
92
|
+
end
|
|
93
|
+
|
|
82
94
|
case field_type
|
|
83
|
-
when /
|
|
84
|
-
when /
|
|
85
|
-
when /
|
|
95
|
+
when /enum/i, /set/i then :string
|
|
96
|
+
when /year/i then :integer
|
|
97
|
+
when /bit/i then :binary
|
|
86
98
|
else
|
|
87
99
|
super
|
|
88
100
|
end
|
|
89
101
|
end
|
|
90
|
-
|
|
102
|
+
|
|
91
103
|
def extract_limit(sql_type)
|
|
92
104
|
case sql_type
|
|
93
105
|
when /blob|text/i
|
|
@@ -126,6 +138,9 @@ module ArJdbc
|
|
|
126
138
|
type != :string && !null && default == ''
|
|
127
139
|
end
|
|
128
140
|
|
|
141
|
+
def adapter; end
|
|
142
|
+
private :adapter
|
|
143
|
+
|
|
129
144
|
end
|
|
130
145
|
|
|
131
146
|
ColumnExtensions = Column # :nodoc: backwards-compatibility
|
|
@@ -172,6 +187,16 @@ module ArJdbc
|
|
|
172
187
|
}
|
|
173
188
|
end
|
|
174
189
|
|
|
190
|
+
def new_visitor(config = nil)
|
|
191
|
+
visitor = ::Arel::Visitors::MySQL
|
|
192
|
+
( prepared_statements? ? visitor : bind_substitution(visitor) ).new(self)
|
|
193
|
+
end if defined? ::Arel::Visitors::MySQL
|
|
194
|
+
|
|
195
|
+
# @see #bind_substitution
|
|
196
|
+
class BindSubstitution < Arel::Visitors::MySQL # :nodoc:
|
|
197
|
+
include Arel::Visitors::BindVisitor
|
|
198
|
+
end if defined? Arel::Visitors::BindVisitor
|
|
199
|
+
|
|
175
200
|
def case_sensitive_equality_operator
|
|
176
201
|
"= BINARY"
|
|
177
202
|
end
|
|
@@ -289,7 +314,7 @@ module ArJdbc
|
|
|
289
314
|
|
|
290
315
|
# SCHEMA STATEMENTS ========================================
|
|
291
316
|
|
|
292
|
-
def structure_dump
|
|
317
|
+
def structure_dump # :nodoc:
|
|
293
318
|
if supports_views?
|
|
294
319
|
sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"
|
|
295
320
|
else
|
|
@@ -309,33 +334,53 @@ module ArJdbc
|
|
|
309
334
|
end
|
|
310
335
|
end
|
|
311
336
|
|
|
312
|
-
#
|
|
313
|
-
|
|
314
|
-
|
|
337
|
+
# Returns just a table's primary key
|
|
338
|
+
def primary_key(table)
|
|
339
|
+
#pk_and_sequence = pk_and_sequence_for(table)
|
|
340
|
+
#pk_and_sequence && pk_and_sequence.first
|
|
341
|
+
@connection.primary_keys(table).first
|
|
342
|
+
end
|
|
343
|
+
|
|
315
344
|
# Returns a table's primary key and belonging sequence.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
result = execute("SHOW
|
|
319
|
-
result.
|
|
320
|
-
keys
|
|
345
|
+
# @note not used only here for potential compatibility with AR's adapter.
|
|
346
|
+
def pk_and_sequence_for(table)
|
|
347
|
+
result = execute("SHOW CREATE TABLE #{quote_table_name(table)}", 'SCHEMA').first
|
|
348
|
+
if result['Create Table'].to_s =~ /PRIMARY KEY\s+(?:USING\s+\w+\s+)?\((.+)\)/
|
|
349
|
+
keys = $1.split(","); keys.map! { |key| key.gsub(/[`"]/, "") }
|
|
350
|
+
return keys.length == 1 ? [ keys.first, nil ] : nil
|
|
351
|
+
else
|
|
352
|
+
return nil
|
|
321
353
|
end
|
|
322
|
-
keys.length == 1 ? [keys.first, nil] : nil
|
|
323
354
|
end
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
355
|
+
|
|
356
|
+
IndexDefinition = ::ActiveRecord::ConnectionAdapters::IndexDefinition
|
|
357
|
+
|
|
358
|
+
if ::ActiveRecord::VERSION::MAJOR > 3
|
|
359
|
+
|
|
360
|
+
INDEX_TYPES = [ :fulltext, :spatial ]
|
|
361
|
+
INDEX_USINGS = [ :btree, :hash ]
|
|
362
|
+
|
|
363
|
+
end
|
|
364
|
+
|
|
327
365
|
# Returns an array of indexes for the given table.
|
|
328
|
-
def indexes(table_name, name = nil)
|
|
366
|
+
def indexes(table_name, name = nil) # :nodoc:
|
|
329
367
|
indexes = []
|
|
330
368
|
current_index = nil
|
|
331
|
-
result = execute("SHOW KEYS FROM #{quote_table_name(table_name)}", name)
|
|
369
|
+
result = execute("SHOW KEYS FROM #{quote_table_name(table_name)}", name || 'SCHEMA')
|
|
332
370
|
result.each do |row|
|
|
333
|
-
key_name = row[
|
|
371
|
+
key_name = row['Key_name']
|
|
334
372
|
if current_index != key_name
|
|
335
|
-
next if key_name ==
|
|
373
|
+
next if key_name == 'PRIMARY' # skip the primary key
|
|
336
374
|
current_index = key_name
|
|
337
|
-
indexes <<
|
|
338
|
-
|
|
375
|
+
indexes <<
|
|
376
|
+
if self.class.const_defined?(:INDEX_TYPES) # AR 4.0
|
|
377
|
+
mysql_index_type = row['Index_type'].downcase.to_sym
|
|
378
|
+
index_type = INDEX_TYPES.include?(mysql_index_type) ? mysql_index_type : nil
|
|
379
|
+
index_using = INDEX_USINGS.include?(mysql_index_type) ? mysql_index_type : nil
|
|
380
|
+
IndexDefinition.new(row['Table'], key_name, row['Non_unique'].to_i == 0, [], [], nil, nil, index_type, index_using)
|
|
381
|
+
else
|
|
382
|
+
IndexDefinition.new(row['Table'], key_name, row['Non_unique'].to_i == 0, [], [])
|
|
383
|
+
end
|
|
339
384
|
end
|
|
340
385
|
|
|
341
386
|
indexes.last.columns << row["Column_name"]
|
|
@@ -343,26 +388,23 @@ module ArJdbc
|
|
|
343
388
|
end
|
|
344
389
|
indexes
|
|
345
390
|
end
|
|
346
|
-
|
|
347
|
-
def
|
|
391
|
+
|
|
392
|
+
def columns(table_name, name = nil) # :nodoc:
|
|
348
393
|
sql = "SHOW FIELDS FROM #{quote_table_name(table_name)}"
|
|
349
|
-
|
|
350
|
-
|
|
394
|
+
column = ::ActiveRecord::ConnectionAdapters::MysqlAdapter::Column
|
|
395
|
+
result = execute(sql, name || 'SCHEMA')
|
|
396
|
+
result.map! do |field|
|
|
397
|
+
column.new(field["Field"], field["Default"], field["Type"], field["Null"] == "YES")
|
|
351
398
|
end
|
|
399
|
+
result
|
|
352
400
|
end
|
|
353
401
|
|
|
354
|
-
|
|
355
|
-
def primary_key(table)
|
|
356
|
-
pk_and_sequence = pk_and_sequence_for(table)
|
|
357
|
-
pk_and_sequence && pk_and_sequence.first
|
|
358
|
-
end
|
|
359
|
-
|
|
360
|
-
def recreate_database(name, options = {}) #:nodoc:
|
|
402
|
+
def recreate_database(name, options = {}) # :nodoc:
|
|
361
403
|
drop_database(name)
|
|
362
404
|
create_database(name, options)
|
|
363
405
|
end
|
|
364
406
|
|
|
365
|
-
def create_database(name, options = {})
|
|
407
|
+
def create_database(name, options = {}) # :nodoc:
|
|
366
408
|
if options[:collation]
|
|
367
409
|
execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}` COLLATE `#{options[:collation]}`"
|
|
368
410
|
else
|
|
@@ -572,7 +614,7 @@ module ArJdbc
|
|
|
572
614
|
end
|
|
573
615
|
column
|
|
574
616
|
end
|
|
575
|
-
|
|
617
|
+
|
|
576
618
|
def show_create_table(table)
|
|
577
619
|
select_one("SHOW CREATE TABLE #{quote_table_name(table)}")
|
|
578
620
|
end
|
|
@@ -598,29 +640,41 @@ end
|
|
|
598
640
|
module ActiveRecord
|
|
599
641
|
module ConnectionAdapters
|
|
600
642
|
# Remove any vestiges of core/Ruby MySQL adapter
|
|
601
|
-
remove_const(:MysqlColumn) if const_defined?(:MysqlColumn)
|
|
602
643
|
remove_const(:MysqlAdapter) if const_defined?(:MysqlAdapter)
|
|
644
|
+
|
|
645
|
+
class MysqlAdapter < JdbcAdapter
|
|
646
|
+
include ::ArJdbc::MySQL
|
|
647
|
+
include ::ArJdbc::MySQL::ExplainSupport
|
|
648
|
+
|
|
649
|
+
# By default, the MysqlAdapter will consider all columns of type
|
|
650
|
+
# <tt>tinyint(1)</tt> as boolean. If you wish to disable this :
|
|
651
|
+
#
|
|
652
|
+
# ActiveRecord::ConnectionAdapters::Mysql[2]Adapter.emulate_booleans = false
|
|
653
|
+
#
|
|
654
|
+
def self.emulate_booleans; ::ArJdbc::MySQL.emulate_booleans; end
|
|
655
|
+
def self.emulate_booleans=(emulate); ::ArJdbc::MySQL.emulate_booleans = emulate; end
|
|
656
|
+
|
|
657
|
+
class Column < JdbcColumn
|
|
658
|
+
include ::ArJdbc::MySQL::Column
|
|
603
659
|
|
|
604
|
-
|
|
605
|
-
|
|
660
|
+
def initialize(name, *args)
|
|
661
|
+
if Hash === name
|
|
662
|
+
super
|
|
663
|
+
else
|
|
664
|
+
super(nil, name, *args)
|
|
665
|
+
end
|
|
666
|
+
end
|
|
606
667
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
else
|
|
611
|
-
super(nil, name, *args)
|
|
668
|
+
# @note {#ArJdbc::MySQL::Column} uses this to check for boolean emulation
|
|
669
|
+
def adapter
|
|
670
|
+
MysqlAdapter
|
|
612
671
|
end
|
|
672
|
+
|
|
613
673
|
end
|
|
614
674
|
|
|
615
|
-
end
|
|
616
|
-
|
|
617
|
-
class MysqlAdapter < JdbcAdapter
|
|
618
|
-
include ::ArJdbc::MySQL
|
|
619
|
-
include ::ArJdbc::MySQL::ExplainSupport
|
|
620
|
-
|
|
621
675
|
def initialize(*args)
|
|
622
676
|
super
|
|
623
|
-
configure_connection
|
|
677
|
+
# configure_connection happens in super
|
|
624
678
|
end
|
|
625
679
|
|
|
626
680
|
def jdbc_connection_class(spec)
|
|
@@ -628,9 +682,8 @@ module ActiveRecord
|
|
|
628
682
|
end
|
|
629
683
|
|
|
630
684
|
def jdbc_column_class
|
|
631
|
-
|
|
685
|
+
Column
|
|
632
686
|
end
|
|
633
|
-
alias_chained_method :columns, :query_cache, :jdbc_columns
|
|
634
687
|
|
|
635
688
|
# some QUOTING caching :
|
|
636
689
|
|
|
@@ -655,18 +708,22 @@ module ActiveRecord
|
|
|
655
708
|
end
|
|
656
709
|
|
|
657
710
|
end
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
module Mysql # :nodoc:
|
|
666
|
-
remove_const(:Error) if const_defined?(:Error)
|
|
667
|
-
class Error < ::ActiveRecord::JDBCError; end
|
|
711
|
+
|
|
712
|
+
if ActiveRecord::VERSION::MAJOR < 3 ||
|
|
713
|
+
( ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR <= 1 )
|
|
714
|
+
remove_const(:MysqlColumn) if const_defined?(:MysqlColumn)
|
|
715
|
+
MysqlColumn = MysqlAdapter::Column
|
|
716
|
+
end
|
|
668
717
|
|
|
669
|
-
|
|
670
|
-
|
|
718
|
+
if ActiveRecord::VERSION::MAJOR > 3 ||
|
|
719
|
+
( ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR >= 1 )
|
|
720
|
+
remove_const(:Mysql2Adapter) if const_defined?(:Mysql2Adapter)
|
|
721
|
+
Mysql2Adapter = MysqlAdapter
|
|
722
|
+
if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 1
|
|
723
|
+
remove_const(:Mysql2Column) if const_defined?(:Mysql2Column)
|
|
724
|
+
Mysql2Column = MysqlAdapter::Column
|
|
725
|
+
end
|
|
726
|
+
end
|
|
727
|
+
|
|
671
728
|
end
|
|
672
729
|
end
|