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,169 @@
|
|
|
1
|
+
module ArJdbc
|
|
2
|
+
module Tasks
|
|
3
|
+
# Sharing task related code between AR 3.x and 4.x
|
|
4
|
+
#
|
|
5
|
+
# @note this class needs to conform to the API available since AR 4.0
|
|
6
|
+
# mostly to be usable with ActiveRecord::Tasks::DatabaseTasks module
|
|
7
|
+
class JdbcDatabaseTasks
|
|
8
|
+
|
|
9
|
+
attr_reader :configuration
|
|
10
|
+
alias_method :config, :configuration
|
|
11
|
+
|
|
12
|
+
def initialize(configuration)
|
|
13
|
+
@configuration = configuration
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
delegate :connection, :establish_connection, :to => ActiveRecord::Base
|
|
17
|
+
|
|
18
|
+
def create
|
|
19
|
+
begin
|
|
20
|
+
establish_connection(config)
|
|
21
|
+
ActiveRecord::Base.connection
|
|
22
|
+
if defined? ActiveRecord::Tasks::DatabaseAlreadyExists
|
|
23
|
+
raise ActiveRecord::Tasks::DatabaseAlreadyExists # AR-4.x
|
|
24
|
+
end # silence on AR < 4.0
|
|
25
|
+
rescue #=> error # database does not exists :
|
|
26
|
+
url = config['url']
|
|
27
|
+
url = $1 if url && url =~ /^(.*(?<!\/)\/)(?=\w)/
|
|
28
|
+
|
|
29
|
+
establish_connection(config.merge('database' => nil, 'url' => url))
|
|
30
|
+
|
|
31
|
+
unless connection.respond_to?(:create_database)
|
|
32
|
+
raise "AR-JDBC adapter '#{adapter_with_spec}' does not support create_database"
|
|
33
|
+
end
|
|
34
|
+
connection.create_database(resolve_database(config), config)
|
|
35
|
+
|
|
36
|
+
establish_connection(config)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def drop
|
|
41
|
+
establish_connection(config)
|
|
42
|
+
unless ActiveRecord::Base.connection.respond_to?(:drop_database)
|
|
43
|
+
raise "AR-JDBC adapter '#{adapter_with_spec}' does not support drop_database"
|
|
44
|
+
end
|
|
45
|
+
connection.drop_database resolve_database(config)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def purge
|
|
49
|
+
establish_connection(config) # :test
|
|
50
|
+
unless ActiveRecord::Base.connection.respond_to?(:recreate_database)
|
|
51
|
+
raise "AR-JDBC adapter '#{adapter_with_spec}' does not support recreate_database (purge)"
|
|
52
|
+
end
|
|
53
|
+
db_name = ActiveRecord::Base.connection.database_name
|
|
54
|
+
ActiveRecord::Base.connection.recreate_database(db_name, config)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def charset
|
|
58
|
+
establish_connection(config)
|
|
59
|
+
if connection.respond_to?(:charset)
|
|
60
|
+
puts connection.charset
|
|
61
|
+
elsif connection.respond_to?(:encoding)
|
|
62
|
+
puts connection.encoding
|
|
63
|
+
else
|
|
64
|
+
raise "AR-JDBC adapter '#{adapter_with_spec}' does not support charset/encoding"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def collation
|
|
69
|
+
establish_connection(config)
|
|
70
|
+
if connection.respond_to?(:collation)
|
|
71
|
+
puts connection.collation
|
|
72
|
+
else
|
|
73
|
+
raise "AR-JDBC adapter '#{adapter_with_spec}' does not support collation"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def structure_dump(filename)
|
|
78
|
+
establish_connection(config)
|
|
79
|
+
if connection.respond_to?(:structure_dump)
|
|
80
|
+
File.open(filename, "w:utf-8") { |f| f << connection.structure_dump }
|
|
81
|
+
else
|
|
82
|
+
raise "AR-JDBC adapter '#{adapter_with_spec}' does not support structure_dump"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def structure_load(filename)
|
|
87
|
+
establish_connection(config)
|
|
88
|
+
if connection.respond_to?(:structure_load)
|
|
89
|
+
connection.structure_load IO.read(filename)
|
|
90
|
+
else
|
|
91
|
+
#IO.read(filename).split(/;\n*/m).each do |ddl|
|
|
92
|
+
# connection.execute(ddl)
|
|
93
|
+
#end
|
|
94
|
+
raise "AR-JDBC adapter '#{adapter_with_spec}' does not support structure_load"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
protected
|
|
99
|
+
|
|
100
|
+
def expand_path(path)
|
|
101
|
+
require 'pathname'
|
|
102
|
+
path = Pathname.new path
|
|
103
|
+
return path.to_s if path.absolute?
|
|
104
|
+
rails_root ? File.join(rails_root, path) : File.expand_path(path)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def resolve_database(config, file_paths = false)
|
|
108
|
+
config['database'] || resolve_database_from_url(config['url'] || '', file_paths)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def resolve_database_from_url(url, file_paths = false)
|
|
112
|
+
( config = config_from_url(url, file_paths) ) ? config['database'] : nil
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
def config_from_url(url, file_paths = false)
|
|
118
|
+
match = url.match %r{
|
|
119
|
+
^ jdbc:
|
|
120
|
+
( [\w]+ ): # $1 protocol
|
|
121
|
+
(?: ([\w]+) : )? # $2 (sub-protocol)
|
|
122
|
+
(?://)?
|
|
123
|
+
(?: ([\w\-]*) (?: [/:] ([\w\-]*) )? @ (?://)? )? # user[:password]@ or user[/password]@ ($3 $4)
|
|
124
|
+
( [\w\.\-]+ )? # $5 host (or database if there's nothing left)
|
|
125
|
+
(?: : (\d+) )? # $6 port if any
|
|
126
|
+
(?: :? (/?[\w\-\./~]+) [\?;]? )? ([^/]*?) $
|
|
127
|
+
# $7 database part (ends with '?' or ';') and $8 query string - properties
|
|
128
|
+
}x
|
|
129
|
+
|
|
130
|
+
return nil unless match
|
|
131
|
+
|
|
132
|
+
config = {}
|
|
133
|
+
config['_protocol'] = match[1]
|
|
134
|
+
config['_sub_protocol'] = match[2] if match[2]
|
|
135
|
+
config['username'] = match[3] if match[3]
|
|
136
|
+
config['password'] = match[4] if match[4]
|
|
137
|
+
host = match[5]; port = match[6]
|
|
138
|
+
database = match[7]
|
|
139
|
+
if database.nil? && port.nil?
|
|
140
|
+
config['database'] = database = host
|
|
141
|
+
else
|
|
142
|
+
config['host'] = host if host
|
|
143
|
+
config['port'] = port if port
|
|
144
|
+
config['database'] = database
|
|
145
|
+
end
|
|
146
|
+
if database && ! file_paths && database[0...1] == '/'
|
|
147
|
+
config['database'] = database[1..-1]
|
|
148
|
+
end
|
|
149
|
+
if query_string = match[8]
|
|
150
|
+
properties = query_string.split('&').inject({}) do |memo, pair|
|
|
151
|
+
pair = pair.split("="); memo[ pair[0] ] = pair[1]; memo
|
|
152
|
+
end
|
|
153
|
+
config['properties'] = properties
|
|
154
|
+
end
|
|
155
|
+
config
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def adapter_with_spec
|
|
159
|
+
adapter, spec = config['adapter'], config['adapter_spec']
|
|
160
|
+
spec ? "#{adapter} (#{spec})" : adapter
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def rails_root
|
|
164
|
+
defined?(Rails.root) ? Rails.root : ( RAILS_ROOT )
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'arjdbc/tasks/jdbc_database_tasks'
|
|
2
|
+
|
|
3
|
+
module ArJdbc
|
|
4
|
+
module Tasks
|
|
5
|
+
class MSSQLDatabaseTasks < JdbcDatabaseTasks
|
|
6
|
+
|
|
7
|
+
def purge
|
|
8
|
+
test = deep_dup(configuration)
|
|
9
|
+
test_database = resolve_database(test)
|
|
10
|
+
test['database'] = 'master'
|
|
11
|
+
establish_connection(test)
|
|
12
|
+
connection.recreate_database(test_database)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def structure_dump(filename)
|
|
16
|
+
config = config_from_url_if_needed
|
|
17
|
+
`smoscript -s #{config['host']} -d #{config['database']} -u #{config['username']} -p #{config['password']} -f #{filename} -A -U`
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def structure_load(filename)
|
|
21
|
+
config = config_from_url_if_needed
|
|
22
|
+
`sqlcmd -S #{config['host']} -d #{config['database']} -U #{config['username']} -P #{config['password']} -i #{filename}`
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def config_from_url_if_needed
|
|
28
|
+
config = self.config
|
|
29
|
+
if config['url'] && ! config.key?('database')
|
|
30
|
+
config = config_from_url(config['url'])
|
|
31
|
+
end
|
|
32
|
+
config
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def deep_dup(hash)
|
|
36
|
+
dup = hash.dup
|
|
37
|
+
dup.each_pair do |k,v|
|
|
38
|
+
tv = dup[k]
|
|
39
|
+
dup[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? deep_dup(tv) : v
|
|
40
|
+
end
|
|
41
|
+
dup
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module ArJdbc
|
|
2
|
+
module Util
|
|
3
|
+
# Caches table and column name (quoted) outcomes.
|
|
4
|
+
# Uses {ThreadSafe::Cache} as a concurrent lock free (on JRuby) cache backend.
|
|
5
|
+
# The thread_safe gem is a dependency since ActiveSupport 4.0, when using
|
|
6
|
+
# ActiveRecord <= 3.2 one should add `gem 'thread_safe'` into the *Gemfile*
|
|
7
|
+
# as it is not forced (currently) as an explicit gem dependency.
|
|
8
|
+
#
|
|
9
|
+
# Caching can also be disabled by setting the *arjdbc.quoted_cache.disabled*
|
|
10
|
+
# system property = 'true'.
|
|
11
|
+
module QuotedCache
|
|
12
|
+
|
|
13
|
+
# @private
|
|
14
|
+
DISABLED = Java::JavaLang::Boolean.getBoolean('arjdbc.quoted_cache.disabled')
|
|
15
|
+
|
|
16
|
+
def self.included(base)
|
|
17
|
+
# the thread_safe gem is an ActiveSupport dependency (since 4.0) :
|
|
18
|
+
begin; require 'thread_safe'; rescue LoadError; end unless DISABLED
|
|
19
|
+
if ! DISABLED && defined? ThreadSafe::Cache
|
|
20
|
+
base.const_set :QUOTED_TABLE_NAMES, ThreadSafe::Cache.new
|
|
21
|
+
base.const_set :QUOTED_COLUMN_NAMES, ThreadSafe::Cache.new
|
|
22
|
+
else
|
|
23
|
+
base.const_set :QUOTED_TABLE_NAMES, nil
|
|
24
|
+
base.const_set :QUOTED_COLUMN_NAMES, nil
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Caches quoted table names, the cache is stored in the class'
|
|
29
|
+
# `QUOTED_TABLE_NAMES` constant.
|
|
30
|
+
# @return [String]
|
|
31
|
+
def quote_table_name(name, *args)
|
|
32
|
+
if cache = self.class::QUOTED_TABLE_NAMES
|
|
33
|
+
unless quoted = cache[name]
|
|
34
|
+
quoted = super
|
|
35
|
+
cache.put_if_absent name, quoted.freeze
|
|
36
|
+
end
|
|
37
|
+
quoted
|
|
38
|
+
else
|
|
39
|
+
super
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Caches quoted table names, the cache is stored in the class'
|
|
44
|
+
# `QUOTED_COLUMN_NAMES` constant.
|
|
45
|
+
# @return [String]
|
|
46
|
+
def quote_column_name(name, *args)
|
|
47
|
+
if cache = self.class::QUOTED_COLUMN_NAMES
|
|
48
|
+
unless quoted = cache[name]
|
|
49
|
+
quoted = super
|
|
50
|
+
cache.put_if_absent name, quoted.freeze
|
|
51
|
+
end
|
|
52
|
+
quoted
|
|
53
|
+
else
|
|
54
|
+
super
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
module ArJdbc
|
|
2
|
+
module Util
|
|
3
|
+
# Gets included into `ActiveRecord::Base` to support sending LOB values
|
|
4
|
+
# in a separate update SQL statement for DB adapters that need this.
|
|
5
|
+
module SerializedAttributes
|
|
6
|
+
|
|
7
|
+
# protected
|
|
8
|
+
|
|
9
|
+
def update_lob_columns
|
|
10
|
+
klass = self.class
|
|
11
|
+
return unless type = klass.lob_type # e.g. /blob/i
|
|
12
|
+
connection = klass.connection
|
|
13
|
+
if connection.respond_to?(:update_lob_values?)
|
|
14
|
+
return false unless connection.update_lob_values?
|
|
15
|
+
end
|
|
16
|
+
klass.columns.each do |column|
|
|
17
|
+
next if column.sql_type !~ type
|
|
18
|
+
next if ( value = dump_column_value(column) ).nil?
|
|
19
|
+
if connection.respond_to?(:update_lob_value?)
|
|
20
|
+
next unless connection.update_lob_value?(value, column)
|
|
21
|
+
end
|
|
22
|
+
connection.update_lob_value(self, column, value)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def dump_column_value(column)
|
|
29
|
+
SerializedAttributes.dump_column_value(self, column)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if defined? ActiveRecord::Type::Serialized # ArJdbc::AR42
|
|
33
|
+
|
|
34
|
+
def self.dump_column_value(record, column)
|
|
35
|
+
value = record[ column.name.to_s ]
|
|
36
|
+
column.cast_type.type_cast_for_database(value)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
else
|
|
40
|
+
|
|
41
|
+
def self.dump_column_value(record, column)
|
|
42
|
+
value = record[ name = column.name.to_s ]
|
|
43
|
+
if record.class.respond_to?(:serialized_attributes)
|
|
44
|
+
if coder = record.class.serialized_attributes[name]
|
|
45
|
+
value = coder.respond_to?(:dump) ? coder.dump(value) : value.to_yaml
|
|
46
|
+
end
|
|
47
|
+
else
|
|
48
|
+
if record.respond_to?(:unserializable_attribute?)
|
|
49
|
+
value = value.to_yaml if record.unserializable_attribute?(name, column)
|
|
50
|
+
else
|
|
51
|
+
value = value.to_yaml if value.is_a?(Hash)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
value
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.setup(lob_type = nil, after_save_alias = nil)
|
|
60
|
+
ActiveRecord::Base.send :include, self # include SerializedAttributes
|
|
61
|
+
ActiveRecord::Base.lob_type = lob_type unless lob_type.nil?
|
|
62
|
+
if after_save_alias
|
|
63
|
+
ActiveRecord::Base.class_eval do
|
|
64
|
+
alias_method after_save_alias, 'update_lob_columns'
|
|
65
|
+
end
|
|
66
|
+
ActiveRecord::Base.after_save after_save_alias
|
|
67
|
+
else
|
|
68
|
+
ActiveRecord::Base.after_save 'update_lob_columns'
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.included(base)
|
|
73
|
+
base.extend ClassMethods
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
module ClassMethods
|
|
77
|
+
|
|
78
|
+
def lob_type
|
|
79
|
+
@lob_type ||= begin
|
|
80
|
+
if superclass.respond_to?(:lob_type)
|
|
81
|
+
superclass.lob_type
|
|
82
|
+
else
|
|
83
|
+
/blob|clob/i
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def lob_type=(type)
|
|
89
|
+
@lob_type = type
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
# @private only due backwards compatibility
|
|
97
|
+
SerializedAttributesHelper = Util::SerializedAttributes
|
|
98
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
module ArJdbc
|
|
2
|
+
module Util
|
|
3
|
+
module TableCopier
|
|
4
|
+
|
|
5
|
+
# taken from SQLite adapter, code loosely based on http://git.io/P7tFQA
|
|
6
|
+
|
|
7
|
+
# Performs changes for table by first copying (and preserving contents)
|
|
8
|
+
# into another (temporary) table, than alters and copies all data back.
|
|
9
|
+
def alter_table(table_name, options = {})
|
|
10
|
+
table_name = table_name.to_s.downcase
|
|
11
|
+
altered_table_name = "a#{table_name}"
|
|
12
|
+
caller = lambda { |definition| yield definition if block_given? }
|
|
13
|
+
|
|
14
|
+
transaction do
|
|
15
|
+
# A temporary table might improve performance here, but
|
|
16
|
+
# it doesn't seem to maintain indices across the whole move.
|
|
17
|
+
move_table(table_name, altered_table_name, options)
|
|
18
|
+
move_table(altered_table_name, table_name, &caller)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Move a table into another while preserving all content.
|
|
23
|
+
# @see #copy_table
|
|
24
|
+
def move_table(from, to, options = {}, &block)
|
|
25
|
+
copy_table(from, to, options, &block)
|
|
26
|
+
drop_table(from)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @see #copy_table_contents
|
|
30
|
+
# @see #copy_table_indexes
|
|
31
|
+
def copy_table(from, to, options = {})
|
|
32
|
+
from_primary_key = primary_key(from)
|
|
33
|
+
create_table(to, options.merge(:id => false)) do |definition|
|
|
34
|
+
@definition = definition
|
|
35
|
+
@definition.primary_key(from_primary_key) if from_primary_key.present?
|
|
36
|
+
columns(from).each do |column|
|
|
37
|
+
column_name = options[:rename] ?
|
|
38
|
+
(options[:rename][column.name] ||
|
|
39
|
+
options[:rename][column.name.to_sym] ||
|
|
40
|
+
column.name) : column.name
|
|
41
|
+
|
|
42
|
+
next if column_name == from_primary_key
|
|
43
|
+
|
|
44
|
+
@definition.column(column_name, column.type,
|
|
45
|
+
:limit => column.limit, :default => column.default,
|
|
46
|
+
:precision => column.precision, :scale => column.scale,
|
|
47
|
+
:null => column.null)
|
|
48
|
+
end
|
|
49
|
+
yield @definition if block_given?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
copy_table_indexes(from, to, options[:rename] || {})
|
|
53
|
+
copy_table_contents(from, to,
|
|
54
|
+
@definition.columns.map {|column| column.name},
|
|
55
|
+
options[:rename] || {})
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Copies indexes for a given table.
|
|
59
|
+
def copy_table_indexes(from, to, rename = {})
|
|
60
|
+
indexes(from).each do |index|
|
|
61
|
+
name = index.name.downcase
|
|
62
|
+
if to == "a#{from}"
|
|
63
|
+
name = "t#{name}"
|
|
64
|
+
elsif from == "a#{to}"
|
|
65
|
+
name = name[1..-1]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
to_column_names = columns(to).map(&:name)
|
|
69
|
+
columns = index.columns.map { |column| rename[column] || column }
|
|
70
|
+
columns = columns.select { |column| to_column_names.include?(column) }
|
|
71
|
+
|
|
72
|
+
unless columns.empty?
|
|
73
|
+
# index name can't be the same
|
|
74
|
+
opts = { :name => name.gsub(/(^|_)(#{from})_/, "\\1#{to}_"), :internal => true }
|
|
75
|
+
opts[:unique] = true if index.unique
|
|
76
|
+
add_index(to, columns, opts)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Copies the content of a table into another.
|
|
82
|
+
def copy_table_contents(from, to, columns, rename = {})
|
|
83
|
+
column_mappings = Hash[ columns.map { |name| [name, name] } ]
|
|
84
|
+
rename.each { |a| column_mappings[a.last] = a.first }
|
|
85
|
+
from_columns = columns(from).collect {|col| col.name}
|
|
86
|
+
columns = columns.find_all{ |col| from_columns.include?(column_mappings[col]) }
|
|
87
|
+
quoted_columns = columns.map { |col| quote_column_name(col) } * ','
|
|
88
|
+
|
|
89
|
+
quoted_to = quote_table_name(to)
|
|
90
|
+
|
|
91
|
+
raw_column_mappings = Hash[ columns(from).map { |c| [c.name, c] } ]
|
|
92
|
+
|
|
93
|
+
execute("SELECT * FROM #{quote_table_name(from)}", 'Copy Table').each do |row|
|
|
94
|
+
sql = "INSERT INTO #{quoted_to} (#{quoted_columns}) VALUES ("
|
|
95
|
+
|
|
96
|
+
column_values = columns.map do |col|
|
|
97
|
+
quote(row[column_mappings[col]], raw_column_mappings[col])
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
sql << column_values * ', '
|
|
101
|
+
sql << ')'
|
|
102
|
+
exec_insert sql, 'Copy Table', []
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
# @private @deprecated backwards compatibility
|
|
109
|
+
MissingFunctionalityHelper = Util::TableCopier
|
|
110
|
+
end
|