wvanbergen-scoped_search 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +48 -32
- data/Rakefile +1 -3
- data/lib/scoped_search.rb +45 -95
- data/lib/scoped_search/adapters.rb +41 -0
- data/lib/scoped_search/definition.rb +122 -0
- data/lib/scoped_search/query_builder.rb +213 -0
- data/lib/scoped_search/query_language.rb +30 -0
- data/lib/scoped_search/query_language/ast.rb +141 -0
- data/lib/scoped_search/query_language/parser.rb +115 -0
- data/lib/scoped_search/query_language/tokenizer.rb +62 -0
- data/{test → spec}/database.yml +0 -0
- data/spec/integration/api_spec.rb +82 -0
- data/spec/integration/ordinal_querying_spec.rb +153 -0
- data/spec/integration/relation_querying_spec.rb +258 -0
- data/spec/integration/string_querying_spec.rb +187 -0
- data/spec/lib/database.rb +44 -0
- data/spec/lib/matchers.rb +40 -0
- data/spec/lib/mocks.rb +19 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/unit/ast_spec.rb +197 -0
- data/spec/unit/definition_spec.rb +24 -0
- data/spec/unit/parser_spec.rb +105 -0
- data/spec/unit/query_builder_spec.rb +5 -0
- data/spec/unit/tokenizer_spec.rb +97 -0
- data/tasks/database_tests.rake +5 -5
- data/tasks/github-gem.rake +8 -3
- metadata +39 -23
- data/lib/scoped_search/query_conditions_builder.rb +0 -209
- data/lib/scoped_search/query_language_parser.rb +0 -117
- data/lib/scoped_search/reg_tokens.rb +0 -51
- data/tasks/documentation.rake +0 -33
- data/test/integration/api_test.rb +0 -53
- data/test/lib/test_models.rb +0 -148
- data/test/lib/test_schema.rb +0 -68
- data/test/test_helper.rb +0 -44
- data/test/unit/query_conditions_builder_test.rb +0 -410
- data/test/unit/query_language_test.rb +0 -155
- data/test/unit/search_for_test.rb +0 -124
data/tasks/database_tests.rake
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'yaml' unless Object::const_defined?('YAML')
|
2
2
|
|
3
|
-
namespace :
|
3
|
+
namespace :spec do
|
4
4
|
|
5
|
-
databases = YAML.load(File.read(File.dirname(__FILE__) + '/../
|
5
|
+
databases = YAML.load(File.read(File.dirname(__FILE__) + '/../spec/database.yml'))
|
6
6
|
|
7
|
-
desc "Run testsuite on all configured databases in
|
7
|
+
desc "Run testsuite on all configured databases in spec/database.yml"
|
8
8
|
task(:all => databases.keys.map { |db| db.to_sym }) do
|
9
9
|
puts "\nFinished testing on all configured databases!"
|
10
10
|
puts "(Configure databases by adjusting test/database.yml)"
|
@@ -13,8 +13,8 @@ namespace :test do
|
|
13
13
|
databases.each do |database, config|
|
14
14
|
desc "Run testsuite on #{database} database."
|
15
15
|
task database.to_sym do
|
16
|
-
puts "Running
|
17
|
-
sh "rake
|
16
|
+
puts "Running specs for #{database} database...\n\n"
|
17
|
+
sh "rake spec DATABASE=#{database}"
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
data/tasks/github-gem.rake
CHANGED
@@ -97,7 +97,7 @@ module Rake
|
|
97
97
|
protected
|
98
98
|
|
99
99
|
def has_rdoc?
|
100
|
-
|
100
|
+
branch_exist?('gh-pages')
|
101
101
|
end
|
102
102
|
|
103
103
|
def has_specs?
|
@@ -168,6 +168,11 @@ module Rake
|
|
168
168
|
run_command('git branch').detect { |line| /^\* (.+)/ =~ line }
|
169
169
|
raise "You are currently not working in the master branch!" unless branch == $1
|
170
170
|
end
|
171
|
+
|
172
|
+
def branch_exist?(branch)
|
173
|
+
run_command('git branch').any? { |line| line.split(' ').last == branch }
|
174
|
+
end
|
175
|
+
|
171
176
|
|
172
177
|
def verify_clean_status(on_branch = nil)
|
173
178
|
sh "git fetch"
|
@@ -232,10 +237,10 @@ module Rake
|
|
232
237
|
|
233
238
|
def create_version_tag!
|
234
239
|
# commit the gemspec file
|
235
|
-
git_commit_file(gemspec_file, "
|
240
|
+
git_commit_file(gemspec_file, "Updated #{gemspec_file} for release of version #{@specification.version}") if git_modified?(gemspec_file)
|
236
241
|
|
237
242
|
# create tag and push changes
|
238
|
-
git_create_tag("#{@name}-#{@specification.version}", "Tagged
|
243
|
+
git_create_tag("#{@name}-#{@specification.version}", "Tagged version #{@specification.version}")
|
239
244
|
git_push('origin', 'master', [:tags])
|
240
245
|
end
|
241
246
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wvanbergen-scoped_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Willem van Bergen
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-
|
13
|
+
date: 2009-08-26 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -32,27 +32,38 @@ files:
|
|
32
32
|
- lib
|
33
33
|
- lib/scoped_search
|
34
34
|
- lib/scoped_search.rb
|
35
|
-
- lib/scoped_search/
|
36
|
-
- lib/scoped_search/
|
37
|
-
- lib/scoped_search/
|
35
|
+
- lib/scoped_search/adapters.rb
|
36
|
+
- lib/scoped_search/definition.rb
|
37
|
+
- lib/scoped_search/query_builder.rb
|
38
|
+
- lib/scoped_search/query_language
|
39
|
+
- lib/scoped_search/query_language.rb
|
40
|
+
- lib/scoped_search/query_language/ast.rb
|
41
|
+
- lib/scoped_search/query_language/parser.rb
|
42
|
+
- lib/scoped_search/query_language/tokenizer.rb
|
43
|
+
- spec
|
44
|
+
- spec/database.yml
|
45
|
+
- spec/integration
|
46
|
+
- spec/integration/api_spec.rb
|
47
|
+
- spec/integration/ordinal_querying_spec.rb
|
48
|
+
- spec/integration/relation_querying_spec.rb
|
49
|
+
- spec/integration/string_querying_spec.rb
|
50
|
+
- spec/lib
|
51
|
+
- spec/lib/database.rb
|
52
|
+
- spec/lib/matchers.rb
|
53
|
+
- spec/lib/mocks.rb
|
54
|
+
- spec/spec_helper.rb
|
55
|
+
- spec/unit
|
56
|
+
- spec/unit/ast_spec.rb
|
57
|
+
- spec/unit/definition_spec.rb
|
58
|
+
- spec/unit/parser_spec.rb
|
59
|
+
- spec/unit/query_builder_spec.rb
|
60
|
+
- spec/unit/tokenizer_spec.rb
|
38
61
|
- tasks
|
39
62
|
- tasks/database_tests.rake
|
40
|
-
- tasks/documentation.rake
|
41
63
|
- tasks/github-gem.rake
|
42
|
-
- test
|
43
|
-
- test/database.yml
|
44
|
-
- test/integration
|
45
|
-
- test/integration/api_test.rb
|
46
|
-
- test/lib
|
47
|
-
- test/lib/test_models.rb
|
48
|
-
- test/lib/test_schema.rb
|
49
|
-
- test/test_helper.rb
|
50
|
-
- test/unit
|
51
|
-
- test/unit/query_conditions_builder_test.rb
|
52
|
-
- test/unit/query_language_test.rb
|
53
|
-
- test/unit/search_for_test.rb
|
54
64
|
has_rdoc: true
|
55
65
|
homepage: http://wiki.github.com/wvanbergen/scoped_search
|
66
|
+
licenses:
|
56
67
|
post_install_message:
|
57
68
|
rdoc_options:
|
58
69
|
- --title
|
@@ -78,12 +89,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
89
|
requirements: []
|
79
90
|
|
80
91
|
rubyforge_project:
|
81
|
-
rubygems_version: 1.
|
92
|
+
rubygems_version: 1.3.5
|
82
93
|
signing_key:
|
83
94
|
specification_version: 2
|
84
95
|
summary: A Rails plugin to search your models using a named_scope
|
85
96
|
test_files:
|
86
|
-
-
|
87
|
-
-
|
88
|
-
-
|
89
|
-
-
|
97
|
+
- spec/integration/api_spec.rb
|
98
|
+
- spec/integration/ordinal_querying_spec.rb
|
99
|
+
- spec/integration/relation_querying_spec.rb
|
100
|
+
- spec/integration/string_querying_spec.rb
|
101
|
+
- spec/unit/ast_spec.rb
|
102
|
+
- spec/unit/definition_spec.rb
|
103
|
+
- spec/unit/parser_spec.rb
|
104
|
+
- spec/unit/query_builder_spec.rb
|
105
|
+
- spec/unit/tokenizer_spec.rb
|
@@ -1,209 +0,0 @@
|
|
1
|
-
module ScopedSearch
|
2
|
-
|
3
|
-
class QueryConditionsBuilder
|
4
|
-
|
5
|
-
# Builds the query string by calling the build method on a new instances of QueryConditionsBuilder.
|
6
|
-
def self.build_query(search_conditions, query_fields)
|
7
|
-
self.new.build(search_conditions, query_fields)
|
8
|
-
end
|
9
|
-
|
10
|
-
# Initializes the default class variables.
|
11
|
-
def initialize
|
12
|
-
@query_fields = nil
|
13
|
-
@query_params = {}
|
14
|
-
|
15
|
-
@sql_like = 'LIKE'
|
16
|
-
|
17
|
-
if ActiveRecord::Base.connected? and ActiveRecord::Base.connection.adapter_name.downcase == 'postgresql'
|
18
|
-
@sql_like = 'ILIKE'
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
|
23
|
-
# Build the query based on the search conditions and the fields to query.
|
24
|
-
#
|
25
|
-
# Hash query_options : A hash of fields and field types.
|
26
|
-
#
|
27
|
-
# Example:
|
28
|
-
#
|
29
|
-
# search_conditions = [["Wes", :like], ["Hays", :not], ["Hello World", :like], ["Goodnight Moon", :not],
|
30
|
-
# ["Bob OR Wes", :or], ["Happy cow OR Sad Frog", :or], ["Man made OR Dogs", :or],
|
31
|
-
# ["Cows OR Frog Toys", :or], ['9/28/1980, :datetime]]
|
32
|
-
# query_fields = {:first_name => :string, :created_at => :datetime}
|
33
|
-
#
|
34
|
-
# Exceptons :
|
35
|
-
# 1) If search_conditions is not an array
|
36
|
-
# 2) If query_fields is not a Hash
|
37
|
-
def build(search_conditions, query_fields)
|
38
|
-
raise 'search_conditions must be a hash' unless search_conditions.class.to_s == 'Array'
|
39
|
-
raise 'query_fields must be a hash' unless query_fields.class.to_s == 'Hash'
|
40
|
-
@query_fields = query_fields
|
41
|
-
|
42
|
-
conditions = []
|
43
|
-
|
44
|
-
search_conditions.each_with_index do |search_condition, index|
|
45
|
-
keyword_name = "keyword_#{index}".to_sym
|
46
|
-
conditions << case search_condition.last
|
47
|
-
# :like also handles integers
|
48
|
-
when :like then like_condition(keyword_name, search_condition.first)
|
49
|
-
when :not then not_like_condition(keyword_name, search_condition.first)
|
50
|
-
|
51
|
-
when :or then or_condition(keyword_name, search_condition.first)
|
52
|
-
|
53
|
-
when :less_than_date then less_than_date(keyword_name, search_condition.first)
|
54
|
-
when :less_than_or_equal_to_date then less_than_or_equal_to_date(keyword_name, search_condition.first)
|
55
|
-
when :as_of_date then as_of_date(keyword_name, search_condition.first)
|
56
|
-
when :greater_than_date then greater_than_date(keyword_name, search_condition.first)
|
57
|
-
when :greater_than_or_equal_to_date then greater_than_or_equal_to_date(keyword_name, search_condition.first)
|
58
|
-
|
59
|
-
when :between_dates then between_dates(keyword_name, search_condition.first)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
[conditions.compact.join(' AND '), @query_params]
|
64
|
-
end
|
65
|
-
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
def like_condition(keyword_name, value)
|
70
|
-
retVal = []
|
71
|
-
@query_fields.each do |field, field_type| #|key,value|
|
72
|
-
if field_type == :string or field_type == :text
|
73
|
-
@query_params[keyword_name] = "%#{value}%"
|
74
|
-
retVal << "#{field} #{@sql_like} :#{keyword_name.to_s}"
|
75
|
-
end
|
76
|
-
if value.strip =~ /^[0-9]+$/ and (field_type == :int or field_type == :integer)
|
77
|
-
qkey = "#{keyword_name}_#{value.strip}"
|
78
|
-
@query_params[qkey.to_sym] = value.strip.to_i
|
79
|
-
retVal << "#{field} = :#{qkey}"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
"(#{retVal.join(' OR ')})"
|
83
|
-
end
|
84
|
-
|
85
|
-
def not_like_condition(keyword_name, value)
|
86
|
-
@query_params[keyword_name] = "%#{value}%"
|
87
|
-
retVal = []
|
88
|
-
@query_fields.each do |field, field_type| #|key,value|
|
89
|
-
if field_type == :string or field_type == :text
|
90
|
-
retVal << "(#{field} NOT #{@sql_like} :#{keyword_name.to_s} OR #{field} IS NULL)"
|
91
|
-
end
|
92
|
-
end
|
93
|
-
"(#{retVal.join(' AND ')})"
|
94
|
-
end
|
95
|
-
|
96
|
-
def or_condition(keyword_name, value)
|
97
|
-
retVal = []
|
98
|
-
word1, word2 = value.split(' OR ')
|
99
|
-
keyword_name_a = "#{keyword_name.to_s}a".to_sym
|
100
|
-
keyword_name_b = "#{keyword_name.to_s}b".to_sym
|
101
|
-
@query_params[keyword_name_a] = "%#{word1}%"
|
102
|
-
@query_params[keyword_name_b] = "%#{word2}%"
|
103
|
-
@query_fields.each do |field, field_type| #|key,value|
|
104
|
-
if field_type == :string or field_type == :text
|
105
|
-
retVal << "(#{field} #{@sql_like} :#{keyword_name_a.to_s} OR #{field} #{@sql_like} :#{keyword_name_b.to_s})"
|
106
|
-
end
|
107
|
-
if (word1.strip =~ /^[0-9]+$/ and word2.strip =~ /^[0-9]+$/) and (field_type == :int or field_type == :integer)
|
108
|
-
qkeya = "#{keyword_name}_a_#{word1.strip}"
|
109
|
-
qkeyb = "#{keyword_name}_b_#{word2.strip}"
|
110
|
-
@query_params[qkeya] = word1.strip.to_i
|
111
|
-
@query_params[qkeyb] = word2.strip.to_i
|
112
|
-
retVal << "(#{field} = :#{qkeya} OR #{field} = :#{qkeyb})"
|
113
|
-
elsif (word1.strip =~ /^[0-9]+$/ or word2.strip =~ /^[0-9]+$/) and (field_type == :int or field_type == :integer)
|
114
|
-
num_word = word1.strip =~ /^[0-9]+$/ ? word1.strip.to_i : word2.strip.to_i
|
115
|
-
qkey = "#{keyword_name}_#{num_word}"
|
116
|
-
@query_params[qkey.to_sym] = num_word
|
117
|
-
retVal << "(#{field} = :#{qkey})"
|
118
|
-
end
|
119
|
-
end
|
120
|
-
"(#{retVal.join(' OR ')})"
|
121
|
-
end
|
122
|
-
|
123
|
-
def less_than_date(keyword_name, value)
|
124
|
-
helper_date_operation('<', keyword_name, value)
|
125
|
-
end
|
126
|
-
|
127
|
-
def less_than_or_equal_to_date(keyword_name, value)
|
128
|
-
helper_date_operation('<=', keyword_name, value)
|
129
|
-
end
|
130
|
-
|
131
|
-
def as_of_date(keyword_name, value)
|
132
|
-
retVal = []
|
133
|
-
begin
|
134
|
-
dt = Date.parse(value) # This will throw an exception if it is not valid
|
135
|
-
@query_params[keyword_name] = dt.to_s
|
136
|
-
@query_fields.each do |field, field_type| #|key,value|
|
137
|
-
if field_type == :date or field_type == :datetime or field_type == :timestamp
|
138
|
-
retVal << "#{field} = :#{keyword_name.to_s}"
|
139
|
-
end
|
140
|
-
end
|
141
|
-
rescue
|
142
|
-
# do not search on any date columns since the date is invalid
|
143
|
-
retVal = [] # Reset just in case
|
144
|
-
end
|
145
|
-
|
146
|
-
# Search the text fields for the date as well as it could be in text.
|
147
|
-
# Also still search on the text columns for an invalid date as it could
|
148
|
-
# have a different meaning.
|
149
|
-
found_text_fields_to_search = false
|
150
|
-
keyword_name_b = "#{keyword_name}b".to_sym
|
151
|
-
@query_fields.each do |field, field_type| #|key,value|
|
152
|
-
if field_type == :string or field_type == :text
|
153
|
-
found_text_fields_to_search = true
|
154
|
-
retVal << "#{field} #{@sql_like} :#{keyword_name_b.to_s}"
|
155
|
-
end
|
156
|
-
end
|
157
|
-
if found_text_fields_to_search
|
158
|
-
@query_params[keyword_name_b] = "%#{value}%"
|
159
|
-
end
|
160
|
-
|
161
|
-
retVal.empty? ? '' : "(#{retVal.join(' OR ')})"
|
162
|
-
end
|
163
|
-
|
164
|
-
def greater_than_date(keyword_name, value)
|
165
|
-
helper_date_operation('>', keyword_name, value)
|
166
|
-
end
|
167
|
-
|
168
|
-
def greater_than_or_equal_to_date(keyword_name, value)
|
169
|
-
helper_date_operation('>=', keyword_name, value)
|
170
|
-
end
|
171
|
-
|
172
|
-
def between_dates(keyword_name, value)
|
173
|
-
date1, date2 = value.split(' TO ')
|
174
|
-
dt1 = Date.parse(date1) # This will throw an exception if it is not valid
|
175
|
-
dt2 = Date.parse(date2) # This will throw an exception if it is not valid
|
176
|
-
keyword_name_a = "#{keyword_name.to_s}a".to_sym
|
177
|
-
keyword_name_b = "#{keyword_name.to_s}b".to_sym
|
178
|
-
@query_params[keyword_name_a] = dt1.to_s
|
179
|
-
@query_params[keyword_name_b] = dt2.to_s
|
180
|
-
|
181
|
-
retVal = []
|
182
|
-
@query_fields.each do |field, field_type| #|key,value|
|
183
|
-
if field_type == :date or field_type == :datetime or field_type == :timestamp
|
184
|
-
retVal << "(#{field} BETWEEN :#{keyword_name_a.to_s} AND :#{keyword_name_b.to_s})"
|
185
|
-
end
|
186
|
-
end
|
187
|
-
"(#{retVal.join(' OR ')})"
|
188
|
-
rescue
|
189
|
-
# The date is not valid so just ignore it
|
190
|
-
return nil
|
191
|
-
end
|
192
|
-
|
193
|
-
|
194
|
-
def helper_date_operation(operator, keyword_name, value)
|
195
|
-
dt = Date.parse(value) # This will throw an exception if it is not valid
|
196
|
-
@query_params[keyword_name] = dt.to_s
|
197
|
-
retVal = []
|
198
|
-
@query_fields.each do |field, field_type| #|key,value|
|
199
|
-
if field_type == :date or field_type == :datetime or field_type == :timestamp
|
200
|
-
retVal << "#{field} #{operator} :#{keyword_name.to_s}"
|
201
|
-
end
|
202
|
-
end
|
203
|
-
"(#{retVal.join(' OR ')})"
|
204
|
-
rescue
|
205
|
-
# The date is not valid so just ignore it
|
206
|
-
return nil
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
@@ -1,117 +0,0 @@
|
|
1
|
-
module ScopedSearch
|
2
|
-
|
3
|
-
# Used to parse and build the conditions tree for the search.
|
4
|
-
class QueryLanguageParser
|
5
|
-
|
6
|
-
# Parses the query string by calling the parse_query method on a new instances of QueryLanguageParser.
|
7
|
-
#
|
8
|
-
# query:: The query string to parse. If nil the all values will be returned (default is nil)
|
9
|
-
# If the query string is longer then 300 characters then it will be truncated to a
|
10
|
-
# length of 300.
|
11
|
-
def self.parse(query)
|
12
|
-
self.new.parse_query(query)
|
13
|
-
end
|
14
|
-
|
15
|
-
# Parse the query string.
|
16
|
-
#
|
17
|
-
# query:: The query string to parse. If nil the all values will be returned (default is nil)
|
18
|
-
# If the query string is longer then 300 characters then it will be truncated to a
|
19
|
-
# length of 300.
|
20
|
-
def parse_query(query = nil)
|
21
|
-
# truncate query string at 300 characters
|
22
|
-
query = query[0...300] if query.length > 300
|
23
|
-
return build_conditions_tree(tokenize(query))
|
24
|
-
end
|
25
|
-
|
26
|
-
protected
|
27
|
-
|
28
|
-
# Build the conditions tree based on the tokens found.
|
29
|
-
#
|
30
|
-
# tokens:: An array of tokens.
|
31
|
-
def build_conditions_tree(tokens)
|
32
|
-
conditions_tree = []
|
33
|
-
|
34
|
-
negate = false
|
35
|
-
tokens.each do |item|
|
36
|
-
case item
|
37
|
-
when :not
|
38
|
-
negate = true
|
39
|
-
else
|
40
|
-
if /^.+[ ]OR[ ].+$/ =~ item
|
41
|
-
conditions_tree << [item, :or]
|
42
|
-
elsif /^#{RegTokens::BetweenDateFormatMMDDYYYY}$/ =~ item or
|
43
|
-
/^#{RegTokens::BetweenDateFormatYYYYMMDD}$/ =~ item or
|
44
|
-
/^#{RegTokens::BetweenDatabaseFormat}$/ =~ item
|
45
|
-
conditions_tree << [item, :between_dates]
|
46
|
-
elsif /^#{RegTokens::GreaterThanOrEqualToDateFormatMMDDYYYY}$/ =~ item or
|
47
|
-
/^#{RegTokens::GreaterThanOrEqualToDateFormatYYYYMMDD}$/ =~ item or
|
48
|
-
/^#{RegTokens::GreaterThanOrEqualToDatabaseFormat}$/ =~ item
|
49
|
-
conditions_tree << [item, :greater_than_or_equal_to_date]
|
50
|
-
elsif /^#{RegTokens::LessThanOrEqualToDateFormatMMDDYYYY}$/ =~ item or
|
51
|
-
/^#{RegTokens::LessThanOrEqualToDateFormatYYYYMMDD}$/ =~ item or
|
52
|
-
/^#{RegTokens::LessThanOrEqualToDatabaseFormat}$/ =~ item
|
53
|
-
conditions_tree << [item, :less_than_or_equal_to_date]
|
54
|
-
elsif /^#{RegTokens::GreaterThanDateFormatMMDDYYYY}$/ =~ item or
|
55
|
-
/^#{RegTokens::GreaterThanDateFormatYYYYMMDD}$/ =~ item or
|
56
|
-
/^#{RegTokens::GreaterThanDatabaseFormat}$/ =~ item
|
57
|
-
conditions_tree << [item, :greater_than_date]
|
58
|
-
elsif /^#{RegTokens::LessThanDateFormatMMDDYYYY}$/ =~ item or
|
59
|
-
/^#{RegTokens::LessThanDateFormatYYYYMMDD}$/ =~ item or
|
60
|
-
/^#{RegTokens::LessThanDatabaseFormat}$/ =~ item
|
61
|
-
conditions_tree << [item, :less_than_date]
|
62
|
-
elsif /^#{RegTokens::DateFormatMMDDYYYY}$/ =~ item or
|
63
|
-
/^#{RegTokens::DateFormatYYYYMMDD}$/ =~ item or
|
64
|
-
/^#{RegTokens::DatabaseFormat}$/ =~ item
|
65
|
-
conditions_tree << [item, :as_of_date]
|
66
|
-
else
|
67
|
-
conditions_tree << (negate ? [item, :not] : [item, :like])
|
68
|
-
negate = false
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
return conditions_tree
|
74
|
-
end
|
75
|
-
|
76
|
-
# Tokenize the query based on the different RegTokens.
|
77
|
-
def tokenize(query)
|
78
|
-
pattern = [RegTokens::BetweenDateFormatMMDDYYYY,
|
79
|
-
RegTokens::BetweenDateFormatYYYYMMDD,
|
80
|
-
RegTokens::BetweenDatabaseFormat,
|
81
|
-
RegTokens::GreaterThanOrEqualToDateFormatMMDDYYYY,
|
82
|
-
RegTokens::GreaterThanOrEqualToDateFormatYYYYMMDD,
|
83
|
-
RegTokens::GreaterThanOrEqualToDatabaseFormat,
|
84
|
-
RegTokens::LessThanOrEqualToDateFormatMMDDYYYY,
|
85
|
-
RegTokens::LessThanOrEqualToDateFormatYYYYMMDD,
|
86
|
-
RegTokens::LessThanOrEqualToDatabaseFormat,
|
87
|
-
RegTokens::GreaterThanDateFormatMMDDYYYY,
|
88
|
-
RegTokens::GreaterThanDateFormatYYYYMMDD,
|
89
|
-
RegTokens::GreaterThanDatabaseFormat,
|
90
|
-
RegTokens::LessThanDateFormatMMDDYYYY,
|
91
|
-
RegTokens::LessThanDateFormatYYYYMMDD,
|
92
|
-
RegTokens::LessThanDatabaseFormat,
|
93
|
-
RegTokens::DateFormatMMDDYYYY,
|
94
|
-
RegTokens::DateFormatYYYYMMDD,
|
95
|
-
RegTokens::DatabaseFormat,
|
96
|
-
RegTokens::WordOrWord,
|
97
|
-
RegTokens::WordOrString,
|
98
|
-
RegTokens::StringOrWord,
|
99
|
-
RegTokens::StringOrString,
|
100
|
-
RegTokens::PossiblyNegatedWord,
|
101
|
-
RegTokens::PossiblyNegatedString]
|
102
|
-
pattern = Regexp.new(pattern.join('|'))
|
103
|
-
|
104
|
-
tokens = []
|
105
|
-
matches = query.scan(pattern).flatten.compact
|
106
|
-
matches.each { |match|
|
107
|
-
tokens << :not if match.index('-') == 0
|
108
|
-
# Remove any escaped quotes
|
109
|
-
# Remove any dashes preceded by a space or at the beginning of a token
|
110
|
-
# Remove any additional spaces - more that one.
|
111
|
-
cleaned_token = match.gsub(/"/,'').gsub(/^-| -/,'').gsub(/[ ]{2,}/, ' ')
|
112
|
-
tokens << cleaned_token if cleaned_token.length > 0
|
113
|
-
}
|
114
|
-
return tokens
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|