activerecord-turntable 2.2.2 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0183e069709e21d8fd4f93be3b443e9dab8ae88c
|
4
|
+
data.tar.gz: c2f793eebeaa9d49278d09892eef7060fddcd757
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e2305795803f74373a78c8bae47f24054b8abc358d54e49b106f09993b262e96ea8081d37268db7e7c38b5c56a4701720b1c2a3d09669bc5655d38cf20e6b22
|
7
|
+
data.tar.gz: c17da81b6c308cb370183d96edfff8b39a9f4431f9af6e76b3e2778c80f414c6cdab1172db34ff0e7e62899bb64619961f658915a24f7988bb2d4cb4151639af
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -9,14 +9,22 @@ module SQLTree
|
|
9
9
|
end
|
10
10
|
|
11
11
|
class SQLTree::Token
|
12
|
-
|
13
|
-
KEYWORDS
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
extended_keywords = ['BINARY', 'LIMIT', 'OFFSET', 'INDEX', 'KEY', 'USE', 'FORCE', 'IGNORE']
|
13
|
+
KEYWORDS.concat(extended_keywords)
|
14
|
+
|
15
|
+
extended_keywords.each do |kwd|
|
16
|
+
const_set(kwd, Class.new(SQLTree::Token::Keyword))
|
17
|
+
end
|
18
18
|
|
19
19
|
BINARY_ESCAPE = Class.new(SQLTree::Token).new('x')
|
20
|
+
|
21
|
+
def possible_index_hint?
|
22
|
+
[SQLTree::Token::USE, SQLTree::Token::FORCE, SQLTree::Token::IGNORE].include?(self.class)
|
23
|
+
end
|
24
|
+
|
25
|
+
def index_keyword?
|
26
|
+
[SQLTree::Token::INDEX, SQLTree::Token::KEY].include?(self.class)
|
27
|
+
end
|
20
28
|
end
|
21
29
|
|
22
30
|
class SQLTree::Tokenizer
|
@@ -141,9 +149,16 @@ module SQLTree::Node
|
|
141
149
|
end
|
142
150
|
|
143
151
|
class TableReference < Base
|
152
|
+
leaf :index_hint
|
153
|
+
|
154
|
+
def initialize(table, table_alias = nil, index_hint = nil)
|
155
|
+
@table, @table_alias, @index_hint = table, table_alias, index_hint
|
156
|
+
end
|
157
|
+
|
144
158
|
def to_sql(options={})
|
145
159
|
sql = (SQLTree::Node::SubQuery === table) ? table.to_sql : quote_field_name(table)
|
146
160
|
sql << " AS " << quote_field_name(table_alias) if table_alias
|
161
|
+
sql << " " << index_hint.to_sql if index_hint
|
147
162
|
return sql
|
148
163
|
end
|
149
164
|
|
@@ -151,10 +166,14 @@ module SQLTree::Node
|
|
151
166
|
if SQLTree::Token::Identifier === tokens.peek
|
152
167
|
tokens.next
|
153
168
|
table_reference = self.new(tokens.current.literal)
|
154
|
-
if
|
169
|
+
if tokens.peek && !tokens.peek.possible_index_hint? &&
|
170
|
+
(SQLTree::Token::AS === tokens.peek || SQLTree::Token::Identifier === tokens.peek)
|
155
171
|
tokens.consume(SQLTree::Token::AS) if SQLTree::Token::AS === tokens.peek
|
156
172
|
table_reference.table_alias = tokens.next.literal
|
157
173
|
end
|
174
|
+
if tokens.peek && tokens.peek.possible_index_hint? && tokens.peek(2).index_keyword?
|
175
|
+
table_reference.index_hint = SQLTree::Node::IndexHint.parse(tokens)
|
176
|
+
end
|
158
177
|
return table_reference
|
159
178
|
elsif SQLTree::Token::SELECT === tokens.peek(2)
|
160
179
|
table_reference = self.new(SQLTree::Node::SubQuery.parse(tokens))
|
@@ -169,6 +188,35 @@ module SQLTree::Node
|
|
169
188
|
end
|
170
189
|
end
|
171
190
|
|
191
|
+
class IndexHint < Base
|
192
|
+
leaf :hint_method
|
193
|
+
leaf :hint_key
|
194
|
+
leaf :index_list
|
195
|
+
|
196
|
+
def initialize(hint_method, hint_key, index_list)
|
197
|
+
@hint_method, @hint_key, @index_list = hint_method, hint_key, index_list
|
198
|
+
end
|
199
|
+
|
200
|
+
def to_sql(options={})
|
201
|
+
sql = "#{hint_method} #{hint_key} "
|
202
|
+
sql << "(#{index_list.map {|idx| idx.to_sql }.join(' ')})"
|
203
|
+
sql
|
204
|
+
end
|
205
|
+
|
206
|
+
def self.parse(tokens)
|
207
|
+
hint_method = tokens.next.literal
|
208
|
+
if tokens.peek.index_keyword?
|
209
|
+
hint_key = tokens.next.literal
|
210
|
+
tokens.consume(SQLTree::Token::LPAREN)
|
211
|
+
index_list = parse_list(tokens, SQLTree::Node::Expression::Field)
|
212
|
+
tokens.consume(SQLTree::Token::RPAREN)
|
213
|
+
self.new(hint_method, hint_key, index_list)
|
214
|
+
else
|
215
|
+
raise SQLTree::Parser::UnexpectedToken.new(tokens.current)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
172
220
|
class Expression < Base
|
173
221
|
class BinaryOperator < SQLTree::Node::Expression
|
174
222
|
TOKEN_PRECEDENCE[2] << SQLTree::Token::BETWEEN
|
@@ -11,4 +11,24 @@ describe SQLTree do
|
|
11
11
|
it { expect { subject }.to_not raise_error }
|
12
12
|
its(:to_sql) { is_expected.to include("x'deadbeef") }
|
13
13
|
end
|
14
|
+
|
15
|
+
context "Select query with index hint" do
|
16
|
+
["FORCE INDEX", "IGNORE INDEX", "USE INDEX"].each do |hint|
|
17
|
+
context hint do
|
18
|
+
subject { SQLTree["SELECT * FROM table #{hint} (`foo`) WHERE field = 'value'"] }
|
19
|
+
it { expect { subject }.to_not raise_error }
|
20
|
+
its(:to_sql) { is_expected.to include("#{hint} (`foo`)") }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "Select query without index hint" do
|
26
|
+
subject { SQLTree["SELECT * FROM table WHERE field = 'value'"] }
|
27
|
+
it { expect { subject }.to_not raise_error }
|
28
|
+
end
|
29
|
+
|
30
|
+
context "Delete query" do
|
31
|
+
subject { SQLTree["DELETE FROM table"] }
|
32
|
+
it { expect { subject }.to_not raise_error }
|
33
|
+
end
|
14
34
|
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.
|
4
|
+
version: 2.3.0
|
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: 2015-
|
12
|
+
date: 2015-07-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -522,4 +522,3 @@ test_files:
|
|
522
522
|
- spec/spec_helper.rb
|
523
523
|
- spec/support/matchers/be_saved_to.rb
|
524
524
|
- spec/support/turntable_helper.rb
|
525
|
-
has_rdoc:
|