rubyrep 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +18 -0
  5. data/Gemfile.lock +84 -0
  6. data/History.txt +6 -0
  7. data/README.txt +1 -1
  8. data/Rakefile +6 -27
  9. data/bin/rubyrep +1 -1
  10. data/config/mysql_config.rb +2 -2
  11. data/config/postgres_config.rb +5 -3
  12. data/lib/rubyrep/command_runner.rb +1 -1
  13. data/lib/rubyrep/connection_extenders/connection_extenders.rb +30 -44
  14. data/lib/rubyrep/connection_extenders/mysql_extender.rb +23 -1
  15. data/lib/rubyrep/connection_extenders/postgresql_extender.rb +31 -168
  16. data/lib/rubyrep/generate_runner.rb +1 -1
  17. data/lib/rubyrep/logged_change.rb +1 -1
  18. data/lib/rubyrep/proxy_connection.rb +22 -12
  19. data/lib/rubyrep/replication_difference.rb +1 -1
  20. data/lib/rubyrep/replication_extenders/mysql_replication.rb +1 -1
  21. data/lib/rubyrep/replication_helper.rb +1 -1
  22. data/lib/rubyrep/replication_runner.rb +10 -0
  23. data/lib/rubyrep/scan_report_printers/scan_detail_reporter.rb +1 -1
  24. data/lib/rubyrep/table_spec_resolver.rb +1 -1
  25. data/lib/rubyrep/type_casting_cursor.rb +8 -4
  26. data/lib/rubyrep/version.rb +1 -7
  27. data/lib/rubyrep.rb +4 -3
  28. data/rubyrep +4 -0
  29. data/rubyrep.bat +5 -0
  30. data/rubyrep.gemspec +29 -0
  31. data/sims/performance/big_rep_spec.rb +34 -17
  32. data/sims/performance/performance.rake +11 -31
  33. data/tasks/database.rake +14 -14
  34. data/tasks/java.rake +18 -5
  35. data/tasks/rspec.rake +14 -34
  36. data/tasks/stats.rake +1 -16
  37. metadata +99 -162
  38. data/.gemtest +0 -0
  39. data/config/requirements.rb +0 -32
  40. data/lib/rubyrep/connection_extenders/jdbc_extender.rb +0 -65
  41. data/spec/base_runner_spec.rb +0 -218
  42. data/spec/buffered_committer_spec.rb +0 -274
  43. data/spec/command_runner_spec.rb +0 -145
  44. data/spec/committers_spec.rb +0 -178
  45. data/spec/configuration_spec.rb +0 -203
  46. data/spec/connection_extender_interface_spec.rb +0 -141
  47. data/spec/connection_extenders_registration_spec.rb +0 -164
  48. data/spec/database_proxy_spec.rb +0 -48
  49. data/spec/database_rake_spec.rb +0 -40
  50. data/spec/db_specific_connection_extenders_spec.rb +0 -34
  51. data/spec/db_specific_replication_extenders_spec.rb +0 -38
  52. data/spec/direct_table_scan_spec.rb +0 -61
  53. data/spec/dolphins.jpg +0 -0
  54. data/spec/generate_runner_spec.rb +0 -84
  55. data/spec/initializer_spec.rb +0 -46
  56. data/spec/log_helper_spec.rb +0 -39
  57. data/spec/logged_change_loader_spec.rb +0 -68
  58. data/spec/logged_change_spec.rb +0 -470
  59. data/spec/noisy_connection_spec.rb +0 -78
  60. data/spec/postgresql_replication_spec.rb +0 -48
  61. data/spec/postgresql_schema_support_spec.rb +0 -212
  62. data/spec/postgresql_support_spec.rb +0 -63
  63. data/spec/progress_bar_spec.rb +0 -77
  64. data/spec/proxied_table_scan_spec.rb +0 -151
  65. data/spec/proxy_block_cursor_spec.rb +0 -197
  66. data/spec/proxy_connection_spec.rb +0 -423
  67. data/spec/proxy_cursor_spec.rb +0 -56
  68. data/spec/proxy_row_cursor_spec.rb +0 -66
  69. data/spec/proxy_runner_spec.rb +0 -70
  70. data/spec/replication_difference_spec.rb +0 -161
  71. data/spec/replication_extender_interface_spec.rb +0 -367
  72. data/spec/replication_extenders_spec.rb +0 -32
  73. data/spec/replication_helper_spec.rb +0 -178
  74. data/spec/replication_initializer_spec.rb +0 -509
  75. data/spec/replication_run_spec.rb +0 -443
  76. data/spec/replication_runner_spec.rb +0 -254
  77. data/spec/replicators_spec.rb +0 -36
  78. data/spec/rubyrep_spec.rb +0 -8
  79. data/spec/scan_detail_reporter_spec.rb +0 -119
  80. data/spec/scan_progress_printers_spec.rb +0 -68
  81. data/spec/scan_report_printers_spec.rb +0 -67
  82. data/spec/scan_runner_spec.rb +0 -50
  83. data/spec/scan_summary_reporter_spec.rb +0 -61
  84. data/spec/session_spec.rb +0 -253
  85. data/spec/spec.opts +0 -1
  86. data/spec/spec_helper.rb +0 -305
  87. data/spec/strange_name_support_spec.rb +0 -135
  88. data/spec/sync_helper_spec.rb +0 -169
  89. data/spec/sync_runner_spec.rb +0 -78
  90. data/spec/syncers_spec.rb +0 -171
  91. data/spec/table_scan_helper_spec.rb +0 -36
  92. data/spec/table_scan_spec.rb +0 -49
  93. data/spec/table_sorter_spec.rb +0 -30
  94. data/spec/table_spec_resolver_spec.rb +0 -111
  95. data/spec/table_sync_spec.rb +0 -140
  96. data/spec/task_sweeper_spec.rb +0 -47
  97. data/spec/trigger_mode_switcher_spec.rb +0 -83
  98. data/spec/two_way_replicator_spec.rb +0 -721
  99. data/spec/two_way_syncer_spec.rb +0 -256
  100. data/spec/type_casting_cursor_spec.rb +0 -50
  101. data/spec/uninstall_runner_spec.rb +0 -93
  102. data/tasks/rubyrep.tailor +0 -18
  103. 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
@@ -0,0 +1,7 @@
1
+ statsvn/*
2
+ coverage/*
3
+ profile/*
4
+ doc/*
5
+ website/.*\.html$
6
+ pkg/*
7
+ tmp/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
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) 2009 Arndt Lehmann
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
- require 'config/requirements'
2
- require 'config/hoe' if Object.const_defined? 'Hoe' # setup Hoe + all gem configuration
1
+ namespace :bundler do
2
+ require "bundler/gem_tasks"
3
+ end
3
4
 
4
- require 'lib/rubyrep'
5
- require 'tasks/task_helper'
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
@@ -1,4 +1,4 @@
1
- #!/usr/bin/ruby
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
4
4
 
@@ -3,7 +3,7 @@
3
3
 
4
4
  RR::Initializer::run do |config|
5
5
  config.left = {
6
- :adapter => 'mysql',
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 => 'mysql',
16
+ :adapter => 'mysql2',
17
17
  :database => 'rr_right',
18
18
  :username => 'root',
19
19
  :password => '',
@@ -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
@@ -32,7 +32,7 @@ module RR
32
32
 
33
33
  # Prints the version to stderr
34
34
  def self.show_version
35
- $stdout.puts "rubyrep version #{RR::VERSION::STRING}"
35
+ $stdout.puts "rubyrep version #{RR::VERSION}"
36
36
  end
37
37
 
38
38
 
@@ -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
- # Dummy ActiveRecord descendant only used to create database connections.
43
- class DummyActiveRecord < ActiveRecord::Base
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
- if RUBY_PLATFORM =~ /java/
56
- adapter = config[:adapter]
57
-
58
- # As recommended in the activerecord-jdbc-adapter use the jdbc versions
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
- DummyActiveRecord.establish_connection(config.merge(:adapter => adapter))
63
- else
64
- DummyActiveRecord.establish_connection(config)
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
- connection = DummyActiveRecord.connection
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::BufferedLogger.new(config[:logger])
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
- logger.debug payload[:sql].squeeze(" ")
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 :mysql => self
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
- column_ids = column_parray.sub(/^\{(.*)\}$/,'\1').split(',').map {|a| a.to_i}
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
- # Sets the schema search path as per configuration parameters
190
- def initialize_search_path
191
- execute "SET search_path TO #{config[:schema_search_path] || 'public'}"
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
- # *** Moneky patch***
195
- # Returns the column objects for the named table.
196
- # Fixes JRuby schema support
197
- def columns(table_name, name = nil)
198
- jdbc_connection = @connection.connection # the actual JDBC DatabaseConnection
199
- @unquoted_schema ||= select_one("show search_path")['search_path']
200
-
201
- # check if table exists
202
- table_results = jdbc_connection.meta_data.get_tables(
203
- jdbc_connection.catalog,
204
- @unquoted_schema,
205
- table_name,
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
@@ -9,7 +9,7 @@ module RR
9
9
  CONFIG_TEMPLATE = <<EOF
10
10
  RR::Initializer::run do |config|
11
11
  config.left = {
12
- :adapter => 'postgresql', # or 'mysql'
12
+ :adapter => 'postgresql', # or 'mysql2'
13
13
  :database => 'SCOTT',
14
14
  :username => 'scott',
15
15
  :password => 'tiger',
@@ -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