activerecord-turntable 2.0.2 → 2.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4906bb6f73e98fee1490a6470ec0e6fb5d46e799
4
- data.tar.gz: 6304957da987dd1e9315a3a3ce8be4b1bb720bd9
3
+ metadata.gz: c7d26c10b2a5821aa33e7136734bcf2e5ef25080
4
+ data.tar.gz: 5a4709f8c44aaf2f2d9ac437c8b1bc3ff679fa1d
5
5
  SHA512:
6
- metadata.gz: 40b81ab32f081801cffa81d68921fc94b3dd6f62284d9c3cf54081c8f949203c2417c51b7e9d6a93e8bcac557d9124632d706a12eb45023f33a0a6ebaa48e95d
7
- data.tar.gz: e99818a708e9b58f6d5924e6af43eb0a0f7446b50c8cfaa3c98a0bdfcb6ca1b281b62e79a39d44c1043629fd1ea08b46c1e1218d8d0200590dd356f782394df7
6
+ metadata.gz: c990394e1144fc5f7b20fa6c5a9a2a818e8937683676bb0c5752f26582109a17ef43c8548e8645d811884facf0e4a9a4f196a62b4025947dde23fcfcb65bfbfd
7
+ data.tar.gz: 7afc6bc759ecbe127e720664888576b91c3628990a02c38bdd1cf5f4af8c71dff0e426f211fee76b640d5d5c6de4f7fbcc13509690c5db6b057007340c2d4323
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## activerecord-turntable 2.0.3 ##
2
+
3
+ ### Bugfixes
4
+
5
+ * Fix parse error on sql with binary string literal: ```x'...'```
6
+
1
7
  ## activerecord-turntable 2.0.2 ##
2
8
 
3
9
  ### Bugfixes
@@ -15,6 +15,8 @@ class SQLTree::Token
15
15
  const_set('BINARY', Class.new(SQLTree::Token::Keyword))
16
16
  const_set('LIMIT', Class.new(SQLTree::Token::Keyword))
17
17
  const_set('OFFSET', Class.new(SQLTree::Token::Keyword))
18
+
19
+ BINARY_ESCAPE = Class.new(SQLTree::Token).new('x')
18
20
  end
19
21
 
20
22
  class SQLTree::Tokenizer
@@ -25,6 +27,44 @@ class SQLTree::Tokenizer
25
27
  end
26
28
  handle_token(SQLTree::Token::String.new(string), &block)
27
29
  end
30
+
31
+ # @note Override to handle x'..' binary string
32
+ def each_token(&block) # :yields: SQLTree::Token
33
+
34
+ while next_char
35
+ case current_char
36
+ when /^\s?$/; # whitespace, go to next character
37
+ when '('; handle_token(SQLTree::Token::LPAREN, &block)
38
+ when ')'; handle_token(SQLTree::Token::RPAREN, &block)
39
+ when '.'; handle_token(SQLTree::Token::DOT, &block)
40
+ when ','; handle_token(SQLTree::Token::COMMA, &block)
41
+ when /\d/; tokenize_number(&block)
42
+ when "'"; tokenize_quoted_string(&block)
43
+ when 'E', 'x', 'X'; tokenize_possible_escaped_string(&block)
44
+ when /\w/; tokenize_keyword(&block)
45
+ when OPERATOR_CHARS; tokenize_operator(&block)
46
+ when SQLTree.identifier_quote_char; tokenize_quoted_identifier(&block)
47
+ end
48
+ end
49
+
50
+ # Make sure to yield any tokens that are still stashed on the queue.
51
+ empty_keyword_queue!(&block)
52
+ end
53
+ alias :each :each_token
54
+
55
+ def tokenize_possible_escaped_string(&block)
56
+ if peek_char == "'"
57
+ token = case current_char
58
+ when 'E'
59
+ SQLTree::Token::STRING_ESCAPE
60
+ when 'x', 'X'
61
+ SQLTree::Token::BINARY_ESCAPE
62
+ end
63
+ handle_token(token, &block)
64
+ else
65
+ tokenize_keyword(&block)
66
+ end
67
+ end
28
68
  end
29
69
 
30
70
  module SQLTree::Node
@@ -167,6 +207,65 @@ module SQLTree::Node
167
207
  @table.nil? ? quote_field_name(@name) : quote_field_name(@table) + '.' + quote_field_name(@name)
168
208
  end
169
209
  end
210
+
211
+ class EscapedValue < Value
212
+ def initialize(value, escape = nil)
213
+ @value = value
214
+ @escape = escape
215
+ end
216
+
217
+ def to_sql(options = {})
218
+ case value
219
+ when nil; 'NULL'
220
+ when String; "#{escape_string}#{quote_str(@value)}"
221
+ when Numeric; @value.to_s
222
+ when Date; @value.strftime("'%Y-%m-%d'")
223
+ when DateTime, Time; @value.strftime("'%Y-%m-%d %H:%M:%S'")
224
+ else raise "Don't know how te represent this value in SQL!"
225
+ end
226
+ end
227
+
228
+ def escape_string
229
+ @escape.to_s
230
+ end
231
+
232
+ def self.parse(tokens)
233
+ escape = tokens.next
234
+ case tokens.next
235
+ when SQLTree::Token::String
236
+ SQLTree::Node::Expression::EscapedValue.new(tokens.current.literal, escape.literal)
237
+ else
238
+ raise SQLTree::Parser::UnexpectedToken.new(tokens.current, :literal)
239
+ end
240
+ end
241
+ end
242
+
243
+ def self.parse_atomic(tokens)
244
+ if SQLTree::Token::LPAREN === tokens.peek
245
+ tokens.consume(SQLTree::Token::LPAREN)
246
+ expr = self.parse(tokens)
247
+ tokens.consume(SQLTree::Token::RPAREN)
248
+ expr
249
+ elsif tokens.peek.prefix_operator?
250
+ PrefixOperator.parse(tokens)
251
+ elsif tokens.peek.variable?
252
+ if SQLTree::Token::LPAREN === tokens.peek(2)
253
+ FunctionCall.parse(tokens)
254
+ elsif SQLTree::Token::DOT === tokens.peek(2)
255
+ Field.parse(tokens)
256
+ else
257
+ Variable.parse(tokens)
258
+ end
259
+ elsif SQLTree::Token::STRING_ESCAPE == tokens.peek
260
+ EscapedValue.parse(tokens)
261
+ elsif SQLTree::Token::BINARY_ESCAPE == tokens.peek
262
+ EscapedValue.parse(tokens)
263
+ elsif SQLTree::Token::INTERVAL === tokens.peek
264
+ IntervalValue.parse(tokens)
265
+ else
266
+ Value.parse(tokens)
267
+ end
268
+ end
170
269
  end
171
270
 
172
271
  class InsertQuery < Base
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Turntable
3
- VERSION = "2.0.2"
3
+ VERSION = "2.0.3"
4
4
  end
5
5
  end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ require 'active_record/turntable/sql_tree_patch'
3
+
4
+ describe SQLTree do
5
+ before(:all) do
6
+ reload_turntable!(File.join(File.dirname(__FILE__), "../../config/turntable.yml"))
7
+ end
8
+
9
+ context "Insert query with binary string" do
10
+ subject { SQLTree["INSERT INTO `hogehoge` (`name`) VALUES (x'deadbeef')"] }
11
+ it { expect { subject }.to_not raise_error }
12
+ its(:to_sql) { is_expected.to include("x'deadbeef") }
13
+ end
14
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-turntable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - gussan
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-11-17 00:00:00.000000000 Z
12
+ date: 2014-11-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -396,6 +396,7 @@ files:
396
396
  - spec/active_record/turntable/sequencer/barrage_spec.rb
397
397
  - spec/active_record/turntable/sequencer/mysql_spec.rb
398
398
  - spec/active_record/turntable/shard_spec.rb
399
+ - spec/active_record/turntable/sql_tree_patch_spec.rb
399
400
  - spec/active_record/turntable/transaction_spec.rb
400
401
  - spec/active_record/turntable_spec.rb
401
402
  - spec/config/database.yml
@@ -461,6 +462,7 @@ test_files:
461
462
  - spec/active_record/turntable/sequencer/barrage_spec.rb
462
463
  - spec/active_record/turntable/sequencer/mysql_spec.rb
463
464
  - spec/active_record/turntable/shard_spec.rb
465
+ - spec/active_record/turntable/sql_tree_patch_spec.rb
464
466
  - spec/active_record/turntable/transaction_spec.rb
465
467
  - spec/active_record/turntable_spec.rb
466
468
  - spec/config/database.yml