rubyrep 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +84 -0
- data/History.txt +6 -0
- data/README.txt +1 -1
- data/Rakefile +6 -27
- data/bin/rubyrep +1 -1
- data/config/mysql_config.rb +2 -2
- data/config/postgres_config.rb +5 -3
- data/lib/rubyrep/command_runner.rb +1 -1
- data/lib/rubyrep/connection_extenders/connection_extenders.rb +30 -44
- data/lib/rubyrep/connection_extenders/mysql_extender.rb +23 -1
- data/lib/rubyrep/connection_extenders/postgresql_extender.rb +31 -168
- data/lib/rubyrep/generate_runner.rb +1 -1
- data/lib/rubyrep/logged_change.rb +1 -1
- data/lib/rubyrep/proxy_connection.rb +22 -12
- data/lib/rubyrep/replication_difference.rb +1 -1
- data/lib/rubyrep/replication_extenders/mysql_replication.rb +1 -1
- data/lib/rubyrep/replication_helper.rb +1 -1
- data/lib/rubyrep/replication_runner.rb +10 -0
- data/lib/rubyrep/scan_report_printers/scan_detail_reporter.rb +1 -1
- data/lib/rubyrep/table_spec_resolver.rb +1 -1
- data/lib/rubyrep/type_casting_cursor.rb +8 -4
- data/lib/rubyrep/version.rb +1 -7
- data/lib/rubyrep.rb +4 -3
- data/rubyrep +4 -0
- data/rubyrep.bat +5 -0
- data/rubyrep.gemspec +29 -0
- data/sims/performance/big_rep_spec.rb +34 -17
- data/sims/performance/performance.rake +11 -31
- data/tasks/database.rake +14 -14
- data/tasks/java.rake +18 -5
- data/tasks/rspec.rake +14 -34
- data/tasks/stats.rake +1 -16
- metadata +99 -162
- data/.gemtest +0 -0
- data/config/requirements.rb +0 -32
- data/lib/rubyrep/connection_extenders/jdbc_extender.rb +0 -65
- data/spec/base_runner_spec.rb +0 -218
- data/spec/buffered_committer_spec.rb +0 -274
- data/spec/command_runner_spec.rb +0 -145
- data/spec/committers_spec.rb +0 -178
- data/spec/configuration_spec.rb +0 -203
- data/spec/connection_extender_interface_spec.rb +0 -141
- data/spec/connection_extenders_registration_spec.rb +0 -164
- data/spec/database_proxy_spec.rb +0 -48
- data/spec/database_rake_spec.rb +0 -40
- data/spec/db_specific_connection_extenders_spec.rb +0 -34
- data/spec/db_specific_replication_extenders_spec.rb +0 -38
- data/spec/direct_table_scan_spec.rb +0 -61
- data/spec/dolphins.jpg +0 -0
- data/spec/generate_runner_spec.rb +0 -84
- data/spec/initializer_spec.rb +0 -46
- data/spec/log_helper_spec.rb +0 -39
- data/spec/logged_change_loader_spec.rb +0 -68
- data/spec/logged_change_spec.rb +0 -470
- data/spec/noisy_connection_spec.rb +0 -78
- data/spec/postgresql_replication_spec.rb +0 -48
- data/spec/postgresql_schema_support_spec.rb +0 -212
- data/spec/postgresql_support_spec.rb +0 -63
- data/spec/progress_bar_spec.rb +0 -77
- data/spec/proxied_table_scan_spec.rb +0 -151
- data/spec/proxy_block_cursor_spec.rb +0 -197
- data/spec/proxy_connection_spec.rb +0 -423
- data/spec/proxy_cursor_spec.rb +0 -56
- data/spec/proxy_row_cursor_spec.rb +0 -66
- data/spec/proxy_runner_spec.rb +0 -70
- data/spec/replication_difference_spec.rb +0 -161
- data/spec/replication_extender_interface_spec.rb +0 -367
- data/spec/replication_extenders_spec.rb +0 -32
- data/spec/replication_helper_spec.rb +0 -178
- data/spec/replication_initializer_spec.rb +0 -509
- data/spec/replication_run_spec.rb +0 -443
- data/spec/replication_runner_spec.rb +0 -254
- data/spec/replicators_spec.rb +0 -36
- data/spec/rubyrep_spec.rb +0 -8
- data/spec/scan_detail_reporter_spec.rb +0 -119
- data/spec/scan_progress_printers_spec.rb +0 -68
- data/spec/scan_report_printers_spec.rb +0 -67
- data/spec/scan_runner_spec.rb +0 -50
- data/spec/scan_summary_reporter_spec.rb +0 -61
- data/spec/session_spec.rb +0 -253
- data/spec/spec.opts +0 -1
- data/spec/spec_helper.rb +0 -305
- data/spec/strange_name_support_spec.rb +0 -135
- data/spec/sync_helper_spec.rb +0 -169
- data/spec/sync_runner_spec.rb +0 -78
- data/spec/syncers_spec.rb +0 -171
- data/spec/table_scan_helper_spec.rb +0 -36
- data/spec/table_scan_spec.rb +0 -49
- data/spec/table_sorter_spec.rb +0 -30
- data/spec/table_spec_resolver_spec.rb +0 -111
- data/spec/table_sync_spec.rb +0 -140
- data/spec/task_sweeper_spec.rb +0 -47
- data/spec/trigger_mode_switcher_spec.rb +0 -83
- data/spec/two_way_replicator_spec.rb +0 -721
- data/spec/two_way_syncer_spec.rb +0 -256
- data/spec/type_casting_cursor_spec.rb +0 -50
- data/spec/uninstall_runner_spec.rb +0 -93
- data/tasks/rubyrep.tailor +0 -18
- data/tasks/website.rake +0 -19
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dce60ecb06296f28c795f0e6f622f44cfb254f36
|
4
|
+
data.tar.gz: d93b227992e944a55bd0dc465c58e63189fca282
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0c1617bceecfff4c4337f054db6e34d93a6fc403f10fa4164cd4e66bd6ebf2a1fbf057514dad0c7437dd14b589d0afe9cea745568e8b8e150ed2a86bee642786
|
7
|
+
data.tar.gz: 359351384c8600b69c16dddb46434bf43f2b3f2a82f1c6c6d554b38fd4fea3fce9a0d36cd50961b245d24d5ca2a6ed19f70615819e7ad244b96d88437fb50692
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
|
3
|
+
gem 'activerecord', '~> 4.2'
|
4
|
+
|
5
|
+
gem 'pg', platform: :ruby
|
6
|
+
gem 'mysql2', platform: :ruby
|
7
|
+
|
8
|
+
gem 'jdbc-postgres', platform: :jruby
|
9
|
+
gem 'jdbc-mysql', platform: :jruby
|
10
|
+
gem 'activerecord-jdbc-adapter', platform: :jruby
|
11
|
+
gem 'activerecord-jdbcpostgresql-adapter', platform: :jruby
|
12
|
+
gem 'activerecord-jdbcmysql-adapter', platform: :jruby
|
13
|
+
|
14
|
+
gem 'rspec'
|
15
|
+
gem 'crack'
|
16
|
+
gem 'awesome_print', require: 'ap'
|
17
|
+
gem 'rake'
|
18
|
+
gem 'simplecov', :require => false, :group => :test
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (4.2.8)
|
5
|
+
activesupport (= 4.2.8)
|
6
|
+
builder (~> 3.1)
|
7
|
+
activerecord (4.2.8)
|
8
|
+
activemodel (= 4.2.8)
|
9
|
+
activesupport (= 4.2.8)
|
10
|
+
arel (~> 6.0)
|
11
|
+
activerecord-jdbc-adapter (1.3.23)
|
12
|
+
activerecord (>= 2.2, < 5.0)
|
13
|
+
activerecord-jdbcmysql-adapter (1.3.23)
|
14
|
+
activerecord-jdbc-adapter (~> 1.3.23)
|
15
|
+
jdbc-mysql (>= 5.1.22)
|
16
|
+
activerecord-jdbcpostgresql-adapter (1.3.23)
|
17
|
+
activerecord-jdbc-adapter (~> 1.3.23)
|
18
|
+
jdbc-postgres (>= 9.1)
|
19
|
+
activesupport (4.2.8)
|
20
|
+
i18n (~> 0.7)
|
21
|
+
minitest (~> 5.1)
|
22
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
23
|
+
tzinfo (~> 1.1)
|
24
|
+
arel (6.0.4)
|
25
|
+
awesome_print (1.7.0)
|
26
|
+
builder (3.2.3)
|
27
|
+
crack (0.4.3)
|
28
|
+
safe_yaml (~> 1.0.0)
|
29
|
+
diff-lcs (1.3)
|
30
|
+
docile (1.1.5)
|
31
|
+
i18n (0.8.1)
|
32
|
+
jdbc-mysql (5.1.42)
|
33
|
+
jdbc-postgres (9.4.1206)
|
34
|
+
json (2.0.2)
|
35
|
+
json (2.0.2-java)
|
36
|
+
minitest (5.10.2)
|
37
|
+
mysql2 (0.4.6)
|
38
|
+
pg (0.20.0)
|
39
|
+
rake (12.0.0)
|
40
|
+
rspec (3.5.0)
|
41
|
+
rspec-core (~> 3.5.0)
|
42
|
+
rspec-expectations (~> 3.5.0)
|
43
|
+
rspec-mocks (~> 3.5.0)
|
44
|
+
rspec-core (3.5.4)
|
45
|
+
rspec-support (~> 3.5.0)
|
46
|
+
rspec-expectations (3.5.0)
|
47
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
48
|
+
rspec-support (~> 3.5.0)
|
49
|
+
rspec-mocks (3.5.0)
|
50
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
51
|
+
rspec-support (~> 3.5.0)
|
52
|
+
rspec-support (3.5.0)
|
53
|
+
safe_yaml (1.0.4)
|
54
|
+
simplecov (0.14.1)
|
55
|
+
docile (~> 1.1.0)
|
56
|
+
json (>= 1.8, < 3)
|
57
|
+
simplecov-html (~> 0.10.0)
|
58
|
+
simplecov-html (0.10.1)
|
59
|
+
thread_safe (0.3.6)
|
60
|
+
thread_safe (0.3.6-java)
|
61
|
+
tzinfo (1.2.3)
|
62
|
+
thread_safe (~> 0.1)
|
63
|
+
|
64
|
+
PLATFORMS
|
65
|
+
java
|
66
|
+
ruby
|
67
|
+
|
68
|
+
DEPENDENCIES
|
69
|
+
activerecord (~> 4.2)
|
70
|
+
activerecord-jdbc-adapter
|
71
|
+
activerecord-jdbcmysql-adapter
|
72
|
+
activerecord-jdbcpostgresql-adapter
|
73
|
+
awesome_print
|
74
|
+
crack
|
75
|
+
jdbc-mysql
|
76
|
+
jdbc-postgres
|
77
|
+
mysql2
|
78
|
+
pg
|
79
|
+
rake
|
80
|
+
rspec
|
81
|
+
simplecov
|
82
|
+
|
83
|
+
BUNDLED WITH
|
84
|
+
1.14.6
|
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 2.0.0 2017-06-01
|
2
|
+
|
3
|
+
* Feature: compatibility with Rails 4, Ruby 2.4 and JRuby 9.1
|
4
|
+
* Breaking: specify MySQL support in database config with adapter 'mysql2' instead of 'mysql'
|
5
|
+
* Breaking: postgres table names must not contains dots (".") anymore
|
6
|
+
|
1
7
|
== 1.2.0 2011-03-07
|
2
8
|
|
3
9
|
* Feature: compatibility with Rails 3
|
data/README.txt
CHANGED
@@ -15,7 +15,7 @@ Refer to the project website at http://www.rubyrep.org
|
|
15
15
|
|
16
16
|
(The MIT License)
|
17
17
|
|
18
|
-
Copyright (c)
|
18
|
+
Copyright (c) 2017 Arndt Lehmann
|
19
19
|
|
20
20
|
Permission is hereby granted, free of charge, to any person obtaining
|
21
21
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -1,30 +1,9 @@
|
|
1
|
-
|
2
|
-
require
|
1
|
+
namespace :bundler do
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
end
|
3
4
|
|
4
|
-
|
5
|
-
|
5
|
+
require_relative 'lib/rubyrep'
|
6
|
+
require_relative 'tasks/task_helper'
|
6
7
|
|
7
8
|
Dir['tasks/**/*.rake'].each { |rake| load rake }
|
8
|
-
load 'sims/performance/performance.rake'
|
9
|
-
|
10
|
-
desc "Creates the repository commit statistics"
|
11
|
-
task :repostats do
|
12
|
-
# phase 0: create the repository tmp directory
|
13
|
-
system 'mkdir -p tmp'
|
14
|
-
# phase 1: migrate the hg repository to svn
|
15
|
-
tailor_path = '~/usr/tailor/tailor'
|
16
|
-
cmd = "#{tailor_path} --use-propset --configfile '#{File.dirname(__FILE__) + '/tasks/rubyrep.tailor'}'"
|
17
|
-
system cmd
|
18
|
-
|
19
|
-
# phase 2: create the repository statistics through the statsvn library
|
20
|
-
jar_path = '~/usr/statsvn/statsvn.jar'
|
21
|
-
log_path = File.dirname(__FILE__) + '/tmp/statsvn.log'
|
22
|
-
checkout_path = '/tmp/rubyrep_tailor/svn'
|
23
|
-
svnstats_dir = File.dirname(__FILE__) + '/statsvn'
|
24
|
-
|
25
|
-
system "cd #{checkout_path}; svn update"
|
26
|
-
cmd = "cd #{checkout_path}; svn log -v --xml >#{log_path}"
|
27
|
-
system cmd
|
28
|
-
cmd = "java -jar #{jar_path} -output-dir #{svnstats_dir} -exclude 'setup.rb:website/**' #{log_path} #{checkout_path}"
|
29
|
-
system cmd
|
30
|
-
end
|
9
|
+
load 'sims/performance/performance.rake'
|
data/bin/rubyrep
CHANGED
data/config/mysql_config.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
RR::Initializer::run do |config|
|
5
5
|
config.left = {
|
6
|
-
:adapter => '
|
6
|
+
:adapter => 'mysql2',
|
7
7
|
:database => 'rr_left',
|
8
8
|
:username => 'root',
|
9
9
|
:password => '',
|
@@ -13,7 +13,7 @@ RR::Initializer::run do |config|
|
|
13
13
|
}
|
14
14
|
|
15
15
|
config.right = {
|
16
|
-
:adapter => '
|
16
|
+
:adapter => 'mysql2',
|
17
17
|
:database => 'rr_right',
|
18
18
|
:username => 'root',
|
19
19
|
:password => '',
|
data/config/postgres_config.rb
CHANGED
@@ -4,10 +4,11 @@
|
|
4
4
|
RR::Initializer::run do |config|
|
5
5
|
config.left = {
|
6
6
|
:adapter => 'postgresql',
|
7
|
-
:database => 'rr_left',
|
7
|
+
:database => 'rr_left',
|
8
8
|
:username => 'postgres',
|
9
9
|
:password => 'password',
|
10
|
-
:host => 'localhost'
|
10
|
+
:host => 'localhost',
|
11
|
+
:min_messages => 'warning'
|
11
12
|
}
|
12
13
|
|
13
14
|
config.right = {
|
@@ -15,7 +16,8 @@ RR::Initializer::run do |config|
|
|
15
16
|
:database => 'rr_right',
|
16
17
|
:username => 'postgres',
|
17
18
|
:password => 'password',
|
18
|
-
:host => 'localhost'
|
19
|
+
:host => 'localhost',
|
20
|
+
:min_messages => 'warning'
|
19
21
|
}
|
20
22
|
|
21
23
|
end
|
@@ -3,19 +3,6 @@ class ActiveRecord::ConnectionAdapters::AbstractAdapter
|
|
3
3
|
attr_accessor :log_subscriber
|
4
4
|
end
|
5
5
|
|
6
|
-
class ActiveRecord::ConnectionAdapters::Column
|
7
|
-
# Bug in ActiveRecord parsing of PostgreSQL timestamps with microseconds:
|
8
|
-
# Certain values are incorrectly rounded, thus ending up with timestamps
|
9
|
-
# that are off by one microsecond.
|
10
|
-
# This monkey patch fixes the problem.
|
11
|
-
def self.fast_string_to_time(string)
|
12
|
-
if string =~ Format::ISO_DATETIME
|
13
|
-
microsec = ($7.to_f * 1_000_000).round # used to be #to_i instead
|
14
|
-
new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
6
|
module RR
|
20
7
|
|
21
8
|
# Connection extenders provide additional database specific functionality
|
@@ -39,10 +26,18 @@ module RR
|
|
39
26
|
@extenders.merge! extender
|
40
27
|
end
|
41
28
|
|
42
|
-
#
|
43
|
-
|
29
|
+
# Creates a new ActiveRecord::Base descending class that can be used to create and manage
|
30
|
+
# database connections.
|
31
|
+
#
|
32
|
+
# @return [Class] the new ActiveRecord::Base descending class
|
33
|
+
def self.active_record_class_for_database_connection
|
34
|
+
active_record_class = Class.new(ActiveRecord::Base)
|
35
|
+
@active_record_class_counter ||= 0
|
36
|
+
@active_record_class_counter += 1
|
37
|
+
RR.const_set("DummyActiveRecord#{@active_record_class_counter}", active_record_class)
|
38
|
+
active_record_class
|
44
39
|
end
|
45
|
-
|
40
|
+
|
46
41
|
# Creates an ActiveRecord database connection according to the provided +config+ connection hash.
|
47
42
|
# Possible values of this parameter are described in ActiveRecord::Base#establish_connection.
|
48
43
|
# The database connection is extended with the correct ConnectionExtenders module.
|
@@ -52,38 +47,29 @@ module RR
|
|
52
47
|
# To go around this, we delete ActiveRecord's memory of the existing database connection
|
53
48
|
# as soon as it is created.
|
54
49
|
def self.db_connect_without_cache(config)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
# of the Adapters. E. g. instead of "postgresql", "jdbcpostgresql".
|
60
|
-
adapter = 'jdbc' + adapter unless adapter =~ /^jdbc/
|
50
|
+
# active_record_class = active_record_class_for_connection(config)
|
51
|
+
# active_record_class = DummyActiveRecord.dup
|
52
|
+
active_record_class = active_record_class_for_database_connection
|
53
|
+
active_record_class.establish_connection(config)
|
61
54
|
|
62
|
-
|
63
|
-
|
64
|
-
|
55
|
+
|
56
|
+
# To suppress Postgres debug messages (which cannot be suppress in another way),
|
57
|
+
# temporarily replace stdout.
|
58
|
+
org_stdout = $stdout
|
59
|
+
$stdout = StringIO.new
|
60
|
+
begin
|
61
|
+
connection = active_record_class.connection
|
62
|
+
ensure
|
63
|
+
puts $stdout.string
|
64
|
+
$stdout = org_stdout
|
65
65
|
end
|
66
|
-
|
67
|
-
|
68
|
-
# Delete the database connection from ActiveRecords's 'memory'
|
69
|
-
ActiveRecord::Base.connection_handler.connection_pools.delete DummyActiveRecord.name
|
70
|
-
|
71
|
-
extender = ""
|
72
|
-
if RUBY_PLATFORM =~ /java/
|
73
|
-
extender = :jdbc
|
74
|
-
elsif ConnectionExtenders.extenders.include? config[:adapter].to_sym
|
66
|
+
|
67
|
+
if ConnectionExtenders.extenders.include? config[:adapter].to_sym
|
75
68
|
extender = config[:adapter].to_sym
|
76
69
|
else
|
77
70
|
raise "No ConnectionExtender available for :#{config[:adapter]}"
|
78
71
|
end
|
79
72
|
connection.extend ConnectionExtenders.extenders[extender]
|
80
|
-
|
81
|
-
# Hack to get Postgres schema support under JRuby to par with the standard
|
82
|
-
# ruby version
|
83
|
-
if RUBY_PLATFORM =~ /java/ and config[:adapter].to_sym == :postgresql
|
84
|
-
connection.extend RR::ConnectionExtenders::PostgreSQLExtender
|
85
|
-
connection.initialize_search_path
|
86
|
-
end
|
87
73
|
|
88
74
|
replication_module = ReplicationExtenders.extenders[config[:adapter].to_sym]
|
89
75
|
connection.extend replication_module if replication_module
|
@@ -112,14 +98,15 @@ module RR
|
|
112
98
|
if config[:logger].respond_to?(:debug)
|
113
99
|
logger = config[:logger]
|
114
100
|
else
|
115
|
-
logger = ActiveSupport::
|
101
|
+
logger = ActiveSupport::Logger.new(config[:logger])
|
116
102
|
end
|
117
103
|
db_connection.instance_variable_set :@logger, logger
|
118
104
|
if ActiveSupport.const_defined?(:Notifications)
|
119
105
|
connection_object_id = db_connection.object_id
|
120
106
|
db_connection.log_subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |name, start, finish, id, payload|
|
121
107
|
if payload[:connection_id] == connection_object_id and logger.debug?
|
122
|
-
|
108
|
+
sql = payload[:sql].squeeze(" ") rescue payload[:sql]
|
109
|
+
logger.debug sql
|
123
110
|
end
|
124
111
|
end
|
125
112
|
end
|
@@ -146,7 +133,6 @@ module RR
|
|
146
133
|
end
|
147
134
|
|
148
135
|
install_logger db_connection, config
|
149
|
-
|
150
136
|
db_connection
|
151
137
|
end
|
152
138
|
|
@@ -4,7 +4,7 @@ module RR
|
|
4
4
|
|
5
5
|
# Provides various MySQL specific functionality required by Rubyrep.
|
6
6
|
module MysqlExtender
|
7
|
-
RR::ConnectionExtenders.register :
|
7
|
+
RR::ConnectionExtenders.register :mysql2 => self
|
8
8
|
|
9
9
|
# Returns an ordered list of primary key column names of the given table
|
10
10
|
def primary_key_names(table)
|
@@ -54,6 +54,28 @@ module RR
|
|
54
54
|
end
|
55
55
|
result
|
56
56
|
end
|
57
|
+
|
58
|
+
# Quotes the value so it can be used in SQL insert / update statements.
|
59
|
+
#
|
60
|
+
# @param [Object] value the target value
|
61
|
+
# @param [ActiveRecord::ConnectionAdapters::MySQL::Column] column the target column
|
62
|
+
# @return [String] the quoted string
|
63
|
+
def column_aware_quote(value, column)
|
64
|
+
if column.sql_type == 'blob' and RUBY_PLATFORM == 'java'
|
65
|
+
quote(column.type_cast_for_database(value))
|
66
|
+
else
|
67
|
+
quote(value)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Casts a value returned from the database back into the according ruby type.
|
72
|
+
#
|
73
|
+
# @param [Object] value the received value
|
74
|
+
# @param [ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::Column] column the originating column
|
75
|
+
# @return [Object] the casted value
|
76
|
+
def fixed_type_cast(value, column)
|
77
|
+
column.type_cast_from_database value
|
78
|
+
end
|
57
79
|
end
|
58
80
|
end
|
59
81
|
end
|
@@ -1,83 +1,5 @@
|
|
1
1
|
require 'time'
|
2
2
|
|
3
|
-
# Hack:
|
4
|
-
# For some reasons these methods were removed in Rails 2.2.2, thus breaking
|
5
|
-
# the binary and multi-lingual data loading.
|
6
|
-
# So here they are again.
|
7
|
-
module ActiveRecord
|
8
|
-
module ConnectionAdapters
|
9
|
-
# PostgreSQL-specific extensions to column definitions in a table.
|
10
|
-
class PostgreSQLColumn < Column #:nodoc:
|
11
|
-
|
12
|
-
# Escapes binary strings for bytea input to the database.
|
13
|
-
def self.string_to_binary(value)
|
14
|
-
if PGconn.respond_to?(:escape_bytea)
|
15
|
-
self.class.module_eval do
|
16
|
-
define_method(:string_to_binary) do |value|
|
17
|
-
PGconn.escape_bytea(value) if value
|
18
|
-
end
|
19
|
-
end
|
20
|
-
else
|
21
|
-
self.class.module_eval do
|
22
|
-
define_method(:string_to_binary) do |value|
|
23
|
-
if value
|
24
|
-
result = ''
|
25
|
-
value.each_byte { |c| result << sprintf('\\\\%03o', c) }
|
26
|
-
result
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
self.class.string_to_binary(value)
|
32
|
-
end
|
33
|
-
|
34
|
-
# Unescapes bytea output from a database to the binary string it represents.
|
35
|
-
def self.binary_to_string(value)
|
36
|
-
# In each case, check if the value actually is escaped PostgreSQL bytea output
|
37
|
-
# or an unescaped Active Record attribute that was just written.
|
38
|
-
if PGconn.respond_to?(:unescape_bytea)
|
39
|
-
self.class.module_eval do
|
40
|
-
define_method(:binary_to_string) do |value|
|
41
|
-
if value =~ /\\\d{3}/
|
42
|
-
PGconn.unescape_bytea(value)
|
43
|
-
else
|
44
|
-
value
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
else
|
49
|
-
self.class.module_eval do
|
50
|
-
define_method(:binary_to_string) do |value|
|
51
|
-
if value =~ /\\\d{3}/
|
52
|
-
result = ''
|
53
|
-
i, max = 0, value.size
|
54
|
-
while i < max
|
55
|
-
char = value[i]
|
56
|
-
if char == ?\\
|
57
|
-
if value[i+1] == ?\\
|
58
|
-
char = ?\\
|
59
|
-
i += 1
|
60
|
-
else
|
61
|
-
char = value[i+1..i+3].oct
|
62
|
-
i += 3
|
63
|
-
end
|
64
|
-
end
|
65
|
-
result << char
|
66
|
-
i += 1
|
67
|
-
end
|
68
|
-
result
|
69
|
-
else
|
70
|
-
value
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
self.class.binary_to_string(value)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
3
|
module RR
|
82
4
|
module ConnectionExtenders
|
83
5
|
|
@@ -107,15 +29,6 @@ module RR
|
|
107
29
|
SQL
|
108
30
|
end
|
109
31
|
|
110
|
-
# Disables schema extraction from table names by overwriting the according
|
111
|
-
# ActiveRecord method.
|
112
|
-
# Necessary to support table names containing dots (".").
|
113
|
-
# (This is possible as rubyrep exclusively uses the search_path setting to
|
114
|
-
# support PostgreSQL schemas.)
|
115
|
-
def extract_pg_identifier_from_name(name)
|
116
|
-
return name, nil
|
117
|
-
end
|
118
|
-
|
119
32
|
# Returns an ordered list of primary key column names of the given table
|
120
33
|
def primary_key_names(table)
|
121
34
|
row = self.select_one(<<-end_sql)
|
@@ -138,7 +51,11 @@ module RR
|
|
138
51
|
|
139
52
|
# Change a Postgres Array of attribute numbers
|
140
53
|
# (returned in String form, e. g.: "{1,2}") into an array of Integers
|
141
|
-
|
54
|
+
if column_parray.kind_of?(Array)
|
55
|
+
column_ids = column_parray # in JRuby the attribute numbers are already returned as array
|
56
|
+
else
|
57
|
+
column_ids = column_parray.sub(/^\{(.*)\}$/,'\1').split(',').map {|a| a.to_i}
|
58
|
+
end
|
142
59
|
|
143
60
|
columns = {}
|
144
61
|
rows = self.select_all(<<-end_sql)
|
@@ -186,89 +103,35 @@ module RR
|
|
186
103
|
result
|
187
104
|
end
|
188
105
|
|
189
|
-
#
|
190
|
-
|
191
|
-
|
106
|
+
# Quotes the value so it can be used in SQL insert / update statements.
|
107
|
+
#
|
108
|
+
# @param [Object] value the target value
|
109
|
+
# @param [ActiveRecord::ConnectionAdapters::PostgreSQLColumn] column the target column
|
110
|
+
# @return [String] the quoted string
|
111
|
+
def column_aware_quote(value, column)
|
112
|
+
if column.try(:sql_type) == 'bytea'
|
113
|
+
quoted_value = "'#{escape_bytea value}'"
|
114
|
+
# tests showed that there is a wrong leading double backslash under JRuby
|
115
|
+
quoted_value.sub!(/\\\\/, '\\')
|
116
|
+
quoted_value
|
117
|
+
else
|
118
|
+
quote value
|
119
|
+
end
|
192
120
|
end
|
193
121
|
|
194
|
-
#
|
195
|
-
#
|
196
|
-
#
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
["TABLE","VIEW","SYNONYM"].to_java(:string)
|
207
|
-
)
|
208
|
-
table_exists = table_results.next
|
209
|
-
table_results.close
|
210
|
-
raise "table '#{table_name}' not found" unless table_exists
|
211
|
-
|
212
|
-
# get ResultSet for columns of table
|
213
|
-
column_results = jdbc_connection.meta_data.get_columns(
|
214
|
-
jdbc_connection.catalog,
|
215
|
-
@unquoted_schema,
|
216
|
-
table_name,
|
217
|
-
nil
|
218
|
-
)
|
219
|
-
|
220
|
-
# create the Column objects
|
221
|
-
columns = []
|
222
|
-
while column_results.next
|
223
|
-
|
224
|
-
# generate type clause
|
225
|
-
type_clause = column_results.get_string('TYPE_NAME')
|
226
|
-
precision = column_results.get_int('COLUMN_SIZE')
|
227
|
-
scale = column_results.get_int('DECIMAL_DIGITS')
|
228
|
-
if precision > 0
|
229
|
-
type_clause += "(#{precision}#{scale > 0 ? ",#{scale}" : ""})"
|
230
|
-
end
|
231
|
-
|
232
|
-
# create column
|
233
|
-
columns << ::ActiveRecord::ConnectionAdapters::JdbcColumn.new(
|
234
|
-
@config,
|
235
|
-
column_results.get_string('COLUMN_NAME'),
|
236
|
-
column_results.get_string('COLUMN_DEF'),
|
237
|
-
type_clause,
|
238
|
-
column_results.get_string('IS_NULLABLE').strip == "NO"
|
239
|
-
)
|
122
|
+
# Casts a value returned from the database back into the according ruby type.
|
123
|
+
#
|
124
|
+
# @param [Object] value the received value
|
125
|
+
# @param [ActiveRecord::ConnectionAdapters::PostgreSQLColumn] column the originating column
|
126
|
+
# @return [Object] the casted value
|
127
|
+
def fixed_type_cast(value, column)
|
128
|
+
if column.sql_type == 'bytea' and RUBY_PLATFORM == 'java'
|
129
|
+
# Apparently in Java / JRuby binary data are automatically unescaped.
|
130
|
+
# So #type_cast_from_database must be prevented from double-unescaping the binary data.
|
131
|
+
value
|
132
|
+
else
|
133
|
+
column.type_cast_from_database value
|
240
134
|
end
|
241
|
-
column_results.close
|
242
|
-
|
243
|
-
columns
|
244
|
-
end if RUBY_PLATFORM =~ /java/
|
245
|
-
|
246
|
-
# *** Monkey patch***
|
247
|
-
# Returns the list of a table's column names, data types, and default values.
|
248
|
-
# This overwrites the according ActiveRecord::PostgreSQLAdapter method
|
249
|
-
# to
|
250
|
-
# * work with tables containing a dot (".") and
|
251
|
-
# * only look for tables in the current schema search path.
|
252
|
-
def column_definitions(table_name) #:nodoc:
|
253
|
-
rows = self.select_all <<-end_sql
|
254
|
-
SELECT
|
255
|
-
a.attname as name,
|
256
|
-
format_type(a.atttypid, a.atttypmod) as type,
|
257
|
-
d.adsrc as source,
|
258
|
-
a.attnotnull as notnull
|
259
|
-
FROM pg_attribute a LEFT JOIN pg_attrdef d
|
260
|
-
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
|
261
|
-
WHERE a.attrelid = (
|
262
|
-
SELECT oid FROM pg_class
|
263
|
-
WHERE relname = '#{table_name}' AND relnamespace IN
|
264
|
-
(SELECT oid FROM pg_namespace WHERE nspname in (#{schemas}))
|
265
|
-
LIMIT 1
|
266
|
-
)
|
267
|
-
AND a.attnum > 0 AND NOT a.attisdropped
|
268
|
-
ORDER BY a.attnum
|
269
|
-
end_sql
|
270
|
-
|
271
|
-
rows.map {|row| [row['name'], row['type'], row['source'], row['notnull']]}
|
272
135
|
end
|
273
136
|
|
274
137
|
end
|
@@ -153,7 +153,7 @@ module RR
|
|
153
153
|
|
154
154
|
# Prevents session from going into YAML output
|
155
155
|
def to_yaml_properties
|
156
|
-
instance_variables.sort.reject {|var_name| ['@session', '@loader'].include? var_name}
|
156
|
+
instance_variables.sort.reject {|var_name| [:'@session', :'@loader'].include? var_name}
|
157
157
|
end
|
158
158
|
|
159
159
|
end
|