activerecord-turntable 2.5.0 → 3.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -0
  3. data/.travis.yml +3 -7
  4. data/CHANGELOG.md +4 -14
  5. data/Gemfile +3 -0
  6. data/Guardfile +12 -7
  7. data/README.md +11 -19
  8. data/Rakefile +14 -15
  9. data/activerecord-turntable.gemspec +24 -27
  10. data/gemfiles/rails5_0.gemfile +6 -0
  11. data/lib/active_record/turntable/active_record_ext/abstract_adapter.rb +24 -20
  12. data/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +6 -16
  13. data/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb +25 -16
  14. data/lib/active_record/turntable/active_record_ext/association.rb +33 -14
  15. data/lib/active_record/turntable/active_record_ext/association_preloader.rb +4 -24
  16. data/lib/active_record/turntable/active_record_ext/clever_load.rb +2 -2
  17. data/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb +11 -15
  18. data/lib/active_record/turntable/active_record_ext/database_tasks.rb +9 -9
  19. data/lib/active_record/turntable/active_record_ext/fixtures.rb +11 -41
  20. data/lib/active_record/turntable/active_record_ext/locking_optimistic.rb +40 -147
  21. data/lib/active_record/turntable/active_record_ext/log_subscriber.rb +6 -37
  22. data/lib/active_record/turntable/active_record_ext/migration_proxy.rb +1 -1
  23. data/lib/active_record/turntable/active_record_ext/persistence.rb +54 -148
  24. data/lib/active_record/turntable/active_record_ext/relation.rb +17 -45
  25. data/lib/active_record/turntable/active_record_ext/schema_dumper.rb +80 -78
  26. data/lib/active_record/turntable/active_record_ext/sequencer.rb +6 -15
  27. data/lib/active_record/turntable/active_record_ext/transactions.rb +14 -9
  28. data/lib/active_record/turntable/active_record_ext.rb +15 -16
  29. data/lib/active_record/turntable/algorithm/modulo_algorithm.rb +1 -1
  30. data/lib/active_record/turntable/algorithm/range_algorithm.rb +9 -9
  31. data/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +12 -12
  32. data/lib/active_record/turntable/base.rb +27 -14
  33. data/lib/active_record/turntable/cluster.rb +10 -13
  34. data/lib/active_record/turntable/cluster_helper_methods.rb +6 -6
  35. data/lib/active_record/turntable/config.rb +3 -3
  36. data/lib/active_record/turntable/connection_proxy/mixable.rb +1 -1
  37. data/lib/active_record/turntable/connection_proxy.rb +23 -22
  38. data/lib/active_record/turntable/helpers/test_helper.rb +4 -4
  39. data/lib/active_record/turntable/master_shard.rb +12 -7
  40. data/lib/active_record/turntable/migration.rb +41 -47
  41. data/lib/active_record/turntable/mixer/fader/calculate_shards_sum_result.rb +7 -7
  42. data/lib/active_record/turntable/mixer/fader/select_shards_merge_result.rb +12 -12
  43. data/lib/active_record/turntable/mixer.rb +121 -121
  44. data/lib/active_record/turntable/plugin.rb +1 -1
  45. data/lib/active_record/turntable/pool_proxy.rb +7 -19
  46. data/lib/active_record/turntable/query_cache.rb +41 -0
  47. data/lib/active_record/turntable/railtie.rb +7 -5
  48. data/lib/active_record/turntable/railties/databases.rake +19 -20
  49. data/lib/active_record/turntable/seq_shard.rb +15 -15
  50. data/lib/active_record/turntable/sequencer/api.rb +7 -7
  51. data/lib/active_record/turntable/sequencer/barrage.rb +6 -7
  52. data/lib/active_record/turntable/sequencer/mysql.rb +2 -2
  53. data/lib/active_record/turntable/sequencer.rb +15 -15
  54. data/lib/active_record/turntable/shard.rb +23 -20
  55. data/lib/active_record/turntable/sql_tree_patch.rb +59 -57
  56. data/lib/active_record/turntable/util.rb +1 -21
  57. data/lib/active_record/turntable/version.rb +1 -1
  58. data/lib/active_record/turntable.rb +14 -19
  59. data/lib/activerecord-turntable.rb +2 -2
  60. data/script/performance/algorithm +8 -9
  61. data/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb +4 -4
  62. data/spec/active_record/turntable/active_record_ext/association_spec.rb +5 -14
  63. data/spec/active_record/turntable/active_record_ext/clever_load_spec.rb +6 -6
  64. data/spec/active_record/turntable/active_record_ext/fixture_set_spec.rb +4 -4
  65. data/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb +2 -15
  66. data/spec/active_record/turntable/active_record_ext/migration_spec.rb +4 -4
  67. data/spec/active_record/turntable/active_record_ext/persistence_spec.rb +17 -15
  68. data/spec/active_record/turntable/active_record_ext/sequencer_spec.rb +1 -1
  69. data/spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb +3 -3
  70. data/spec/active_record/turntable/algorithm/modulo_algorithm_spec.rb +2 -3
  71. data/spec/active_record/turntable/algorithm/range_algorithm_spec.rb +2 -3
  72. data/spec/active_record/turntable/algorithm/range_bsearch_algorithm_spec.rb +2 -3
  73. data/spec/active_record/turntable/algorithm_spec.rb +5 -5
  74. data/spec/active_record/turntable/base_spec.rb +1 -1
  75. data/spec/active_record/turntable/cluster_spec.rb +1 -1
  76. data/spec/active_record/turntable/config_spec.rb +1 -1
  77. data/spec/active_record/turntable/connection_proxy_spec.rb +16 -17
  78. data/spec/active_record/turntable/finder_spec.rb +1 -1
  79. data/spec/active_record/turntable/mixer/fader_spec.rb +1 -1
  80. data/spec/active_record/turntable/mixer_spec.rb +2 -4
  81. data/spec/active_record/turntable/query_cache_spec.rb +28 -0
  82. data/spec/active_record/turntable/sequencer/api_spec.rb +4 -4
  83. data/spec/active_record/turntable/sequencer/barrage_spec.rb +2 -2
  84. data/spec/active_record/turntable/sequencer/mysql_spec.rb +1 -1
  85. data/spec/active_record/turntable/shard_spec.rb +1 -1
  86. data/spec/active_record/turntable/sql_tree_patch_spec.rb +2 -2
  87. data/spec/active_record/turntable/transaction_spec.rb +2 -2
  88. data/spec/active_record/turntable_spec.rb +3 -3
  89. data/spec/migrations/002_create_user_statuses.rb +4 -4
  90. data/spec/migrations/003_create_cards.rb +3 -3
  91. data/spec/migrations/004_create_cards_users.rb +2 -2
  92. data/spec/models/user_status.rb +0 -1
  93. data/spec/spec_helper.rb +15 -14
  94. data/spec/support/turntable_helper.rb +4 -4
  95. metadata +98 -59
  96. data/gemfiles/rails4_0.gemfile +0 -7
  97. data/gemfiles/rails4_1.gemfile +0 -7
  98. data/gemfiles/rails4_2.gemfile +0 -7
  99. data/lib/active_record/turntable/rack/connection_management.rb +0 -18
  100. data/lib/active_record/turntable/rack/query_cache.rb +0 -40
  101. data/lib/active_record/turntable/rack.rb +0 -8
  102. data/spec/active_record/turntable/rack/query_cache_spec.rb +0 -19
@@ -2,19 +2,19 @@
2
2
  #
3
3
  # Sequencer via HTTP API
4
4
  #
5
- require 'httpclient'
5
+ require "httpclient"
6
6
 
7
7
  module ActiveRecord::Turntable
8
8
  class Sequencer
9
9
  class Api < Sequencer
10
- API_ENDPOINT = '/sequences/'
11
- NEXT_VALUE_ENDPOINT = '/new'
10
+ API_ENDPOINT = "/sequences/".freeze
11
+ NEXT_VALUE_ENDPOINT = "/new".freeze
12
12
 
13
13
  def initialize(klass, options = {})
14
14
  @klass = klass
15
15
  @options = options
16
- @host = @options["api_host"]
17
- @port = @options["api_port"]
16
+ @host = @options[:api_host]
17
+ @port = @options[:api_port]
18
18
  @client = HTTPClient.new
19
19
  end
20
20
 
@@ -22,14 +22,14 @@ module ActiveRecord::Turntable
22
22
  res = @client.get_content("http://#{@host}:#{@port}#{API_ENDPOINT}#{sequence_name}#{NEXT_VALUE_ENDPOINT}")
23
23
  new_id = res.to_i
24
24
  raise SequenceNotFoundError if new_id.zero?
25
- return new_id
25
+ new_id
26
26
  end
27
27
 
28
28
  def current_sequence_value(sequence_name)
29
29
  res = @client.get_content("http://#{@host}:#{@port}#{API_ENDPOINT}#{sequence_name}")
30
30
  current_id = res.to_i
31
31
  raise SequenceNotFoundError if current_id.zero?
32
- return current_id
32
+ current_id
33
33
  end
34
34
  end
35
35
  end
@@ -4,25 +4,24 @@ module ActiveRecord::Turntable
4
4
  @@unique_barrage_instance = {}
5
5
 
6
6
  def initialize(klass, options = {})
7
- require 'barrage'
7
+ require "barrage"
8
8
  @klass = klass
9
9
  @options = options["options"]
10
- @barrage = get_barrage_instance
11
10
  end
12
11
 
13
12
  def next_sequence_value(sequence_name)
14
- @barrage.next
13
+ barrage.next
15
14
  end
16
15
 
17
16
  def current_sequence_value(sequence_name)
18
- @barrage.current
17
+ barrage.current
19
18
  end
20
19
 
21
20
  private
22
21
 
23
- def get_barrage_instance
24
- @@unique_barrage_instance[@options] ||= ::Barrage.new(@options)
25
- end
22
+ def barrage
23
+ @@unique_barrage_instance[@options] ||= ::Barrage.new(@options)
24
+ end
26
25
  end
27
26
  end
28
27
  end
@@ -17,7 +17,7 @@ module ActiveRecord::Turntable
17
17
  res = conn.execute("SELECT LAST_INSERT_ID()")
18
18
  new_id = res.first.first.to_i
19
19
  raise SequenceNotFoundError if new_id.zero?
20
- return new_id
20
+ new_id
21
21
  end
22
22
 
23
23
  def current_sequence_value(sequence_name)
@@ -25,7 +25,7 @@ module ActiveRecord::Turntable
25
25
  conn.execute "UPDATE #{@klass.connection.quote_table_name(sequence_name)} SET id=LAST_INSERT_ID(id)"
26
26
  res = conn.execute("SELECT LAST_INSERT_ID()")
27
27
  current_id = res.first.first.to_i
28
- return current_id
28
+ current_id
29
29
  end
30
30
  end
31
31
  end
@@ -14,9 +14,9 @@ module ActiveRecord::Turntable
14
14
  end
15
15
 
16
16
  @@sequence_types = {
17
- :api => Api,
18
- :mysql => Mysql,
19
- :barrage => Barrage
17
+ api: Api,
18
+ mysql: Mysql,
19
+ barrage: Barrage,
20
20
  }
21
21
 
22
22
  @@sequences = {}
@@ -24,9 +24,9 @@ module ActiveRecord::Turntable
24
24
  cattr_reader :sequences, :tables
25
25
 
26
26
  def self.build(klass, sequence_name = nil, cluster_name = nil)
27
- sequence_name ||= current_cluster_config_for(cluster_name || klass)["seq"].keys.first
28
- seq_config = current_cluster_config_for(cluster_name || klass)["seq"][sequence_name]
29
- seq_type = (seq_config["seq_type"] ? seq_config["seq_type"].to_sym : :mysql)
27
+ sequence_name ||= current_cluster_config_for(cluster_name || klass)[:seq].keys.first
28
+ seq_config = current_cluster_config_for(cluster_name || klass)[:seq][sequence_name]
29
+ seq_type = (seq_config[:seq_type] ? seq_config[:seq_type].to_sym : :mysql)
30
30
  @@tables[klass.table_name] ||= (@@sequences[sequence_name(klass.table_name, klass.primary_key)] ||= @@sequence_types[seq_type].new(klass, seq_config))
31
31
  end
32
32
 
@@ -39,7 +39,7 @@ module ActiveRecord::Turntable
39
39
  end
40
40
 
41
41
  def self.table_name(seq_name)
42
- seq_name.split('_').first
42
+ seq_name.split("_").first
43
43
  end
44
44
 
45
45
  def next_sequence_value
@@ -52,13 +52,13 @@ module ActiveRecord::Turntable
52
52
 
53
53
  private
54
54
 
55
- def self.current_cluster_config_for(klass_or_name)
56
- cluster_name = if klass_or_name.is_a?(Symbol)
57
- klass_or_name
58
- else
59
- klass_or_name.turntable_cluster_name.to_s
60
- end
61
- ActiveRecord::Base.turntable_config["clusters"][cluster_name]
62
- end
55
+ def self.current_cluster_config_for(klass_or_name)
56
+ cluster_name = if klass_or_name.is_a?(Symbol)
57
+ klass_or_name
58
+ else
59
+ klass_or_name.turntable_cluster_name.to_s
60
+ end
61
+ ActiveRecord::Base.turntable_config[:clusters][cluster_name]
62
+ end
63
63
  end
64
64
  end
@@ -1,16 +1,19 @@
1
1
  module ActiveRecord::Turntable
2
2
  class Shard
3
3
  module Connections; end
4
+ def self.connection_classes
5
+ Connections.constants.map { |name| Connections.const_get(name) }
6
+ end
4
7
 
5
8
  DEFAULT_CONFIG = {
6
- "connection" => (defined?(Rails) ? Rails.env : "development")
9
+ "connection" => (defined?(Rails) ? Rails.env : "development"),
7
10
  }.with_indifferent_access
8
11
 
9
12
  attr_reader :name
10
13
 
11
14
  def initialize(shard_spec)
12
15
  @config = DEFAULT_CONFIG.merge(shard_spec)
13
- @name = @config["connection"]
16
+ @name = @config[:connection]
14
17
  ActiveRecord::Base.turntable_connections[name] = connection_pool
15
18
  end
16
19
 
@@ -26,26 +29,26 @@ module ActiveRecord::Turntable
26
29
 
27
30
  private
28
31
 
29
- def connection_klass
30
- @connection_klass ||= create_connection_class
31
- end
32
+ def connection_klass
33
+ @connection_klass ||= create_connection_class
34
+ end
32
35
 
33
- def get_or_set_connection_class
34
- if Connections.const_defined?(name.classify)
35
- klass = Connections.const_get(name.classify)
36
- else
37
- klass = Class.new(ActiveRecord::Base)
38
- Connections.const_set(name.classify, klass)
39
- klass.abstract_class = true
36
+ def get_or_set_connection_class
37
+ if Connections.const_defined?(name.classify)
38
+ klass = Connections.const_get(name.classify)
39
+ else
40
+ klass = Class.new(ActiveRecord::Base)
41
+ Connections.const_set(name.classify, klass)
42
+ klass.abstract_class = true
43
+ end
44
+ klass
40
45
  end
41
- klass
42
- end
43
46
 
44
- def create_connection_class
45
- klass = get_or_set_connection_class
46
- klass.remove_connection
47
- klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:shards][name].with_indifferent_access
48
- klass
49
- end
47
+ def create_connection_class
48
+ klass = get_or_set_connection_class
49
+ klass.remove_connection
50
+ klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:shards][name].with_indifferent_access
51
+ klass
52
+ end
50
53
  end
51
54
  end
@@ -1,22 +1,22 @@
1
- require 'sql_tree'
2
- require 'active_support/core_ext/kernel/reporting'
1
+ require "sql_tree"
2
+ require "active_support/core_ext/kernel/reporting"
3
3
 
4
4
  module SQLTree
5
5
  class << self
6
6
  attr_accessor :identifier_quote_field_char
7
7
  end
8
- self.identifier_quote_field_char = '`'
8
+ self.identifier_quote_field_char = "`"
9
9
  end
10
10
 
11
11
  class SQLTree::Token
12
- extended_keywords = ['BINARY', 'LIMIT', 'OFFSET', 'INDEX', 'KEY', 'USE', 'FORCE', 'IGNORE']
12
+ extended_keywords = %w(BINARY LIMIT OFFSET INDEX KEY USE FORCE IGNORE)
13
13
  KEYWORDS.concat(extended_keywords)
14
14
 
15
15
  extended_keywords.each do |kwd|
16
16
  const_set(kwd, Class.new(SQLTree::Token::Keyword))
17
17
  end
18
18
 
19
- BINARY_ESCAPE = Class.new(SQLTree::Token).new('x')
19
+ BINARY_ESCAPE = Class.new(SQLTree::Token).new("x")
20
20
 
21
21
  def possible_index_hint?
22
22
  [SQLTree::Token::USE, SQLTree::Token::FORCE, SQLTree::Token::IGNORE].include?(self.class)
@@ -29,7 +29,7 @@ end
29
29
 
30
30
  class SQLTree::Tokenizer
31
31
  def tokenize_quoted_string(&block) # :yields: SQLTree::Token::String
32
- string = ''
32
+ string = ""
33
33
  until next_char.nil? || current_char == "'"
34
34
  string << (current_char == "\\" ? instance_eval("%@\\#{next_char.gsub('@', '\@')}@") : current_char)
35
35
  end
@@ -38,34 +38,33 @@ class SQLTree::Tokenizer
38
38
 
39
39
  # @note Override to handle x'..' binary string
40
40
  def each_token(&block) # :yields: SQLTree::Token
41
-
42
41
  while next_char
43
42
  case current_char
44
- when /^\s?$/; # whitespace, go to next character
45
- when '('; handle_token(SQLTree::Token::LPAREN, &block)
46
- when ')'; handle_token(SQLTree::Token::RPAREN, &block)
47
- when '.'; handle_token(SQLTree::Token::DOT, &block)
48
- when ','; handle_token(SQLTree::Token::COMMA, &block)
49
- when /\d/; tokenize_number(&block)
50
- when "'"; tokenize_quoted_string(&block)
51
- when 'E', 'x', 'X'; tokenize_possible_escaped_string(&block)
52
- when /\w/; tokenize_keyword(&block)
53
- when OPERATOR_CHARS; tokenize_operator(&block)
54
- when SQLTree.identifier_quote_char; tokenize_quoted_identifier(&block)
43
+ when /^\s?$/ then # whitespace, go to next character
44
+ when "(" then handle_token(SQLTree::Token::LPAREN, &block)
45
+ when ")" then handle_token(SQLTree::Token::RPAREN, &block)
46
+ when "." then handle_token(SQLTree::Token::DOT, &block)
47
+ when "," then handle_token(SQLTree::Token::COMMA, &block)
48
+ when /\d/ then tokenize_number(&block)
49
+ when "'" then tokenize_quoted_string(&block)
50
+ when "E", "x", 'X' then tokenize_possible_escaped_string(&block)
51
+ when /\w/ then tokenize_keyword(&block)
52
+ when OPERATOR_CHARS then tokenize_operator(&block)
53
+ when SQLTree.identifier_quote_char then tokenize_quoted_identifier(&block)
55
54
  end
56
55
  end
57
56
 
58
57
  # Make sure to yield any tokens that are still stashed on the queue.
59
58
  empty_keyword_queue!(&block)
60
59
  end
61
- alias :each :each_token
60
+ alias_method :each, :each_token
62
61
 
63
62
  def tokenize_possible_escaped_string(&block)
64
63
  if peek_char == "'"
65
64
  token = case current_char
66
- when 'E'
65
+ when "E"
67
66
  SQLTree::Token::STRING_ESCAPE
68
- when 'x', 'X'
67
+ when "x", "X"
69
68
  SQLTree::Token::BINARY_ESCAPE
70
69
  end
71
70
  handle_token(token, &block)
@@ -87,16 +86,16 @@ module SQLTree::Node
87
86
 
88
87
  def to_sql(options = {})
89
88
  raise "At least one SELECT expression is required" if self.select.empty?
90
- sql = (self.distinct) ? "SELECT DISTINCT " : "SELECT "
91
- sql << select.map { |s| s.to_sql(options) }.join(', ')
92
- sql << " FROM " << from.map { |f| f.to_sql(options) }.join(', ') if from
89
+ sql = self.distinct ? "SELECT DISTINCT " : "SELECT "
90
+ sql << select.map { |s| s.to_sql(options) }.join(", ")
91
+ sql << " FROM " << from.map { |f| f.to_sql(options) }.join(", ") if from
93
92
  sql << " WHERE " << where.to_sql(options) if where
94
- sql << " GROUP BY " << group_by.map { |g| g.to_sql(options) }.join(', ') if group_by
95
- sql << " ORDER BY " << order_by.map { |o| o.to_sql(options) }.join(', ') if order_by
93
+ sql << " GROUP BY " << group_by.map { |g| g.to_sql(options) }.join(", ") if group_by
94
+ sql << " ORDER BY " << order_by.map { |o| o.to_sql(options) }.join(", ") if order_by
96
95
  sql << " HAVING " << having.to_sql(options) if having
97
- sql << " LIMIT " << Array(limit).map {|f| f.to_sql(options) }.join(', ') if limit
96
+ sql << " LIMIT " << Array(limit).map { |f| f.to_sql(options) }.join(", ") if limit
98
97
  sql << " OFFSET " << offset.to_sql(options) if offset
99
- return sql
98
+ sql
100
99
  end
101
100
 
102
101
  def self.parse(tokens)
@@ -116,12 +115,12 @@ module SQLTree::Node
116
115
  select_node.having = self.parse_having_clause(tokens) if SQLTree::Token::HAVING === tokens.peek
117
116
  end
118
117
  select_node.order_by = self.parse_order_clause(tokens) if SQLTree::Token::ORDER === tokens.peek
119
- if SQLTree::Token::LIMIT === tokens.peek and list = self.parse_limit_clause(tokens)
118
+ if SQLTree::Token::LIMIT === tokens.peek && (list = self.parse_limit_clause(tokens))
120
119
  select_node.offset = list.shift if list.size > 1
121
120
  select_node.limit = list.shift
122
121
  end
123
122
  select_node.offset = self.parse_offset_clause(tokens) if SQLTree::Token::OFFSET === tokens.peek
124
- return select_node
123
+ select_node
125
124
  end
126
125
 
127
126
  def self.parse_limit_clause(tokens)
@@ -137,14 +136,14 @@ module SQLTree::Node
137
136
 
138
137
  class SubQuery < SelectQuery
139
138
  def to_sql(options = {})
140
- "("+super(options)+")"
139
+ "(" + super(options) + ")"
141
140
  end
142
141
 
143
142
  def self.parse(tokens)
144
143
  tokens.consume(SQLTree::Token::LPAREN)
145
144
  select_node = super(tokens)
146
145
  tokens.consume(SQLTree::Token::RPAREN)
147
- return select_node
146
+ select_node
148
147
  end
149
148
  end
150
149
 
@@ -152,14 +151,16 @@ module SQLTree::Node
152
151
  leaf :index_hint
153
152
 
154
153
  def initialize(table, table_alias = nil, index_hint = nil)
155
- @table, @table_alias, @index_hint = table, table_alias, index_hint
154
+ @table = table
155
+ @table_alias = table_alias
156
+ @index_hint = index_hint
156
157
  end
157
158
 
158
- def to_sql(options={})
159
+ def to_sql(options = {})
159
160
  sql = (SQLTree::Node::SubQuery === table) ? table.to_sql : quote_field_name(table)
160
161
  sql << " AS " << quote_field_name(table_alias) if table_alias
161
162
  sql << " " << index_hint.to_sql if index_hint
162
- return sql
163
+ sql
163
164
  end
164
165
 
165
166
  def self.parse(tokens)
@@ -167,7 +168,7 @@ module SQLTree::Node
167
168
  tokens.next
168
169
  table_reference = self.new(tokens.current.literal)
169
170
  if tokens.peek && !tokens.peek.possible_index_hint? &&
170
- (SQLTree::Token::AS === tokens.peek || SQLTree::Token::Identifier === tokens.peek)
171
+ (SQLTree::Token::AS === tokens.peek || SQLTree::Token::Identifier === tokens.peek)
171
172
  tokens.consume(SQLTree::Token::AS) if SQLTree::Token::AS === tokens.peek
172
173
  table_reference.table_alias = tokens.next.literal
173
174
  end
@@ -194,12 +195,14 @@ module SQLTree::Node
194
195
  leaf :index_list
195
196
 
196
197
  def initialize(hint_method, hint_key, index_list)
197
- @hint_method, @hint_key, @index_list = hint_method, hint_key, index_list
198
+ @hint_method = hint_method
199
+ @hint_key = hint_key
200
+ @index_list = index_list
198
201
  end
199
202
 
200
- def to_sql(options={})
203
+ def to_sql(options = {})
201
204
  sql = "#{hint_method} #{hint_key} "
202
- sql << "(#{index_list.map {|idx| idx.to_sql }.join(' ')})"
205
+ sql << "(#{index_list.map(&:to_sql).join(' ')})"
203
206
  sql
204
207
  end
205
208
 
@@ -225,20 +228,20 @@ module SQLTree::Node
225
228
  end
226
229
 
227
230
  def self.parse_rhs(tokens, precedence, operator = nil)
228
- if ['IN', 'NOT IN'].include?(operator)
231
+ if ["IN", "NOT IN"].include?(operator)
229
232
  if SQLTree::Token::SELECT === tokens.peek(2)
230
233
  return SQLTree::Node::SubQuery.parse(tokens)
231
234
  else
232
235
  return List.parse(tokens)
233
236
  end
234
- elsif ['IS', 'IS NOT'].include?(operator)
237
+ elsif ["IS", "IS NOT"].include?(operator)
235
238
  tokens.consume(SQLTree::Token::NULL)
236
239
  return SQLTree::Node::Expression::Value.new(nil)
237
- elsif ['BETWEEN'].include?(operator)
240
+ elsif ["BETWEEN"].include?(operator)
238
241
  expr = parse_atomic(tokens)
239
242
  operator = parse_operator(tokens)
240
243
  rhs = parse_rhs(tokens, precedence, operator)
241
- expr = self.new(:operator => operator, :lhs => expr, :rhs => rhs)
244
+ expr = self.new(operator: operator, lhs: expr, rhs: rhs)
242
245
  return expr
243
246
  else
244
247
  return parse(tokens, precedence + 1)
@@ -252,7 +255,7 @@ module SQLTree::Node
252
255
 
253
256
  class Field < Variable
254
257
  def to_sql(options = {})
255
- @table.nil? ? quote_field_name(@name) : quote_field_name(@table) + '.' + quote_field_name(@name)
258
+ @table.nil? ? quote_field_name(@name) : quote_field_name(@table) + "." + quote_field_name(@name)
256
259
  end
257
260
  end
258
261
 
@@ -268,11 +271,11 @@ module SQLTree::Node
268
271
 
269
272
  def to_sql(options = {})
270
273
  case value
271
- when nil; 'NULL'
272
- when String; "#{escape_string}#{quote_str(@value)}"
273
- when Numeric; @value.to_s
274
- when Date; @value.strftime("'%Y-%m-%d'")
275
- when DateTime, Time; @value.strftime("'%Y-%m-%d %H:%M:%S'")
274
+ when nil then "NULL"
275
+ when String then "#{escape_string}#{quote_str(@value)}"
276
+ when Numeric then @value.to_s
277
+ when Date then @value.strftime("'%Y-%m-%d'")
278
+ when DateTime, Time then @value.strftime("'%Y-%m-%d %H:%M:%S'")
276
279
  else raise "Don't know how te represent this value in SQL!"
277
280
  end
278
281
  end
@@ -321,14 +324,13 @@ module SQLTree::Node
321
324
  end
322
325
 
323
326
  class InsertQuery < Base
324
-
325
- def to_sql(options = { })
326
- sql = "INSERT INTO #{ table.to_sql(options)} "
327
- sql << '(' + fields.map { |f| f.to_sql(options) }.join(', ') + ') ' if fields
328
- sql << 'VALUES'
327
+ def to_sql(options = {})
328
+ sql = "INSERT INTO #{table.to_sql(options)} "
329
+ sql << "(" + fields.map { |f| f.to_sql(options) }.join(", ") + ") " if fields
330
+ sql << "VALUES"
329
331
  sql << values.map do |value|
330
- ' (' + value.map { |v| v.to_sql(options) }.join(', ') + ')'
331
- end.join(',')
332
+ " (" + value.map { |v| v.to_sql(options) }.join(", ") + ")"
333
+ end.join(",")
332
334
  sql
333
335
  end
334
336
 
@@ -344,7 +346,7 @@ module SQLTree::Node
344
346
  values << parse_list(tokens)
345
347
  tokens.consume(SQLTree::Token::RPAREN)
346
348
  end
347
- return values
349
+ values
348
350
  end
349
351
  end
350
352
  end
@@ -10,28 +10,8 @@ module ActiveRecord::Turntable
10
10
  ar_version < Gem::Version.new(version)
11
11
  end
12
12
 
13
- def ar4?
14
- ActiveRecord::VERSION::MAJOR == 4
15
- end
16
-
17
- def ar41_or_later?
18
- ar_version_equals_or_later?("4.1")
19
- end
20
-
21
- def earlier_than_ar41?
22
- ar_version_earlier_than?("4.1")
23
- end
24
-
25
- def ar42_or_later?
26
- ar_version_equals_or_later?("4.2")
27
- end
28
-
29
- def earlier_than_ar42?
30
- ar_version_earlier_than?("4.2")
31
- end
32
-
33
13
  def ar_version
34
- ActiveRecord::gem_version
14
+ ActiveRecord.gem_version
35
15
  end
36
16
  end
37
17
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Turntable
3
- VERSION = "2.5.0"
3
+ VERSION = "3.0.0.alpha1".freeze
4
4
  end
5
5
  end
@@ -3,23 +3,14 @@
3
3
  #
4
4
  # ActiveRecord Sharding Plugin
5
5
  #
6
- require 'active_record/turntable/version'
7
- require 'active_record'
8
- require 'active_record/fixtures'
9
- require 'active_support/concern'
10
- require 'active_record/turntable/error'
11
- require 'active_record/turntable/util'
12
- require 'logger'
13
- require 'singleton'
14
-
15
- # for 4.0.x series
16
- module ActiveRecord
17
- unless respond_to?(:gem_version)
18
- class << self
19
- alias_method :gem_version, :version
20
- end
21
- end
22
- end
6
+ require "active_record/turntable/version"
7
+ require "active_record"
8
+ require "active_record/fixtures"
9
+ require "active_support/concern"
10
+ require "active_record/turntable/error"
11
+ require "active_record/turntable/util"
12
+ require "logger"
13
+ require "singleton"
23
14
 
24
15
  module ActiveRecord::Turntable
25
16
  extend ActiveSupport::Concern
@@ -37,12 +28,12 @@ module ActiveRecord::Turntable
37
28
  autoload :Migration
38
29
  autoload :Mixer
39
30
  autoload :PoolProxy
31
+ autoload :QueryCache
40
32
  autoload :Shard
41
33
  autoload :ShardingCondition
42
34
  autoload :SeqShard
43
35
  autoload :Sequencer
44
36
  end
45
- autoload :Rack
46
37
  autoload :Helpers
47
38
 
48
39
  included do
@@ -56,7 +47,7 @@ module ActiveRecord::Turntable
56
47
  def turntable_config_file
57
48
  @@turntable_config_file ||=
58
49
  File.join(defined?(::Rails) ?
59
- ::Rails.root.to_s : DEFAULT_PATH, 'config/turntable.yml')
50
+ ::Rails.root.to_s : DEFAULT_PATH, "config/turntable.yml")
60
51
  end
61
52
 
62
53
  def turntable_config_file=(filename)
@@ -66,6 +57,10 @@ module ActiveRecord::Turntable
66
57
  def turntable_config
67
58
  ActiveRecord::Turntable::Config.instance
68
59
  end
60
+
61
+ def turntable_connection_classes
62
+ ActiveRecord::Turntable::Shard.connection_classes
63
+ end
69
64
  end
70
65
 
71
66
  require "active_record/turntable/railtie" if defined?(Rails)
@@ -1,2 +1,2 @@
1
- require 'active_record'
2
- require 'active_record/turntable'
1
+ require "active_record"
2
+ require "active_record/turntable"
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
- require 'rspec'
3
- require File.join(File.dirname(__FILE__), '../../../spec/spec_helper')
4
- require 'benchmark'
2
+ require "rspec"
3
+ require File.join(File.dirname(__FILE__), "../../spec/spec_helper")
4
+ require "benchmark"
5
5
 
6
6
  def setup_algorithm(n, alg = "Range")
7
7
  config = {
8
8
  "shards" => n.times.map do |i|
9
- {"connection" => "connection_#{i}", "less_than" => (i+1) * 100}
10
- end
11
- }
9
+ { connection: "connection_#{i}", less_than: (i + 1) * 100 }
10
+ end,
11
+ }.with_indifferent_access
12
12
  "ActiveRecord::Turntable::Algorithm::#{alg}Algorithm".constantize.new(config)
13
13
  end
14
14
 
@@ -18,15 +18,14 @@ Benchmark.bm(40) do |x|
18
18
  algorithm = setup_algorithm(n, alg)
19
19
  x.report("#{alg}: selrand(#{n}) * 1000") {
20
20
  1000.times do
21
- algorithm.calculate(rand(n*100))
21
+ algorithm.calculate(rand(n * 100))
22
22
  end
23
23
  }
24
24
  x.report("#{alg}: sellast(#{n}) * 1000") {
25
25
  1000.times do
26
- algorithm.calculate(n*100-1)
26
+ algorithm.calculate(n * 100 - 1)
27
27
  end
28
28
  }
29
29
  end
30
30
  end
31
31
  end
32
-
@@ -1,4 +1,4 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe ActiveRecord::Turntable::ActiveRecordExt::Association do
4
4
  before(:all) do
@@ -11,7 +11,7 @@ describe ActiveRecord::Turntable::ActiveRecordExt::Association do
11
11
  end
12
12
 
13
13
  let!(:user) do
14
- user = User.new({:nickname => 'user1'})
14
+ user = User.new({ nickname: "user1" })
15
15
  user.id = 1
16
16
  user.save
17
17
  user
@@ -49,7 +49,7 @@ describe ActiveRecord::Turntable::ActiveRecordExt::Association do
49
49
  end
50
50
 
51
51
  it "its has_many targets should be assigned all related object" do
52
- expect(subject.cards_users_histories).to include(*cards_users_histories.select { |history| history.cards_user_id == subject.id} )
52
+ expect(subject.cards_users_histories).to include(*cards_users_histories.select { |history| history.cards_user_id == subject.id })
53
53
  end
54
54
  end
55
55
 
@@ -64,7 +64,7 @@ describe ActiveRecord::Turntable::ActiveRecordExt::Association do
64
64
  end
65
65
 
66
66
  it "its has_many targets should be assigned all related object" do
67
- expect(subject.events_users_histories_with_foreign_shard_key).to include(*events_users_histories.select { |history| history.cards_user_id == subject.id} )
67
+ expect(subject.events_users_histories_with_foreign_shard_key).to include(*events_users_histories.select { |history| history.cards_user_id == subject.id })
68
68
  end
69
69
  end
70
70