search_lingo 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +2 -2
- data/README.md +4 -5
- data/examples/complex.rb +15 -33
- data/examples/sequel_example.rb +15 -3
- data/lib/search_lingo/abstract_search.rb +25 -17
- data/lib/search_lingo/parsers/date_parser.rb +55 -17
- data/lib/search_lingo/parsers/mdy.rb +6 -5
- data/lib/search_lingo/parsers.rb +0 -5
- data/lib/search_lingo/version.rb +1 -1
- data/search_lingo.gemspec +1 -1
- metadata +7 -11
- data/lib/search_lingo/parsers/date_range_parser.rb +0 -15
- data/lib/search_lingo/parsers/gte_date_parser.rb +0 -13
- data/lib/search_lingo/parsers/lte_date_parser.rb +0 -13
- data/lib/search_lingo/parsers/open_date_range_parser.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 473413fa017d4fe273ea20952b89c778fd07d98735efaeef1c28954bc70c96ea
|
4
|
+
data.tar.gz: 11df6b8d3f02b8147afc5a7248a548861b038c8e7e9dffd854dca506e185fa7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6783a0cb4a8d8db96ddaf4a9cff6704484a6421f93351de009202a7f680c46a50d44c62672e7201a7cdaeb3999ac9df7646b1905471cfef43ef2c9c2e6ef87d
|
7
|
+
data.tar.gz: bed0ac621a52ffc67fc50ee32f5dd560f58a3f11444741bc3bae63a9be8f1d0e7e59e0656b5d1cab07cc2a05c1c200889d408c1c7142ceab31416a156edc9d38
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -276,11 +276,10 @@ Additionally, there are parsers for handling closed date ranges (e.g.,
|
|
276
276
|
`12/31/15`). Look at the files in `lib/search_lingo/parsers` for more details.
|
277
277
|
|
278
278
|
The date parser are specifically designed to work with US-formatted dates. Time
|
279
|
-
permitting, I will work on making them more flexible.
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
route, a Sequel-specific implementation should also be provided.)
|
279
|
+
permitting, I will work on making them more flexible.
|
280
|
+
|
281
|
+
As implemented they generate queries using AREL. In the future, we should try
|
282
|
+
generalizing this behavior to also support Sequel for generating queries.
|
284
283
|
|
285
284
|
## Development
|
286
285
|
|
data/examples/complex.rb
CHANGED
@@ -21,36 +21,18 @@ module Parsers # :nodoc:
|
|
21
21
|
end
|
22
22
|
|
23
23
|
class JobSearch < SearchLingo::AbstractSearch # :nodoc:
|
24
|
+
parser SearchLingo::Parsers::DateParser.new Job.arel_table[:date]
|
24
25
|
parser Parsers::IdParser.new Job.table_name
|
25
26
|
|
26
|
-
parser SearchLingo::Parsers::DateParser.new Job.table_name,
|
27
|
-
:date
|
28
|
-
parser SearchLingo::Parsers::DateRangeParser.new Job.table_name,
|
29
|
-
:date
|
30
|
-
parser SearchLingo::Parsers::OpenDateRangeParser.new Job.table_name,
|
31
|
-
:date, connection: Job.connection
|
32
|
-
|
33
27
|
def default_parse(token)
|
34
|
-
[:where,
|
28
|
+
[:where, Job.arel_table[:name].lower.like("%#{token}%")]
|
35
29
|
end
|
36
30
|
end
|
37
31
|
|
38
32
|
class ReceiptSearch < SearchLingo::AbstractSearch # :nodoc:
|
39
|
-
parser Parsers::
|
40
|
-
|
41
|
-
|
42
|
-
:check_date
|
43
|
-
parser SearchLingo::Parsers::DateRangeParser.new Receipt.table_name,
|
44
|
-
:check_date
|
45
|
-
parser SearchLingo::Parsers::OpenDateRangeParser.new Receipt.table_name,
|
46
|
-
:check_date, connection: Receipt.connection
|
47
|
-
|
48
|
-
parser SearchLingo::Parsers::DateParser.new Receipt.table_name,
|
49
|
-
:post_date, 'posted'
|
50
|
-
parser SearchLingo::Parsers::DateRangeParser.new Receipt.table_name,
|
51
|
-
:post_date, 'posted'
|
52
|
-
parser SearchLingo::Parsers::OpenDateRangeParser.new Receipt.table_name,
|
53
|
-
:post_date, 'posted', connection: Receipt.connection
|
33
|
+
parser SearchLingo::Parsers::DateParser.new Receipt.arel_table[:check_date]
|
34
|
+
parser SearchLingo::Parsers::DateParser.new Receipt.arel_table[:post_date],
|
35
|
+
modifier: 'posted'
|
54
36
|
|
55
37
|
parser do |token|
|
56
38
|
token.match /\Aamount: (\d+(?:\.\d+)?)\z/ do |m|
|
@@ -59,19 +41,19 @@ class ReceiptSearch < SearchLingo::AbstractSearch # :nodoc:
|
|
59
41
|
end
|
60
42
|
|
61
43
|
def default_parse(token)
|
62
|
-
[:where,
|
44
|
+
[:where, Receipt.arel_table[:check_no].like(token)]
|
63
45
|
end
|
64
46
|
end
|
65
47
|
|
66
48
|
search = JobSearch.new('6/4/15-6/5/15 id: 42 "foo bar"')
|
67
|
-
search.results
|
68
|
-
|
69
|
-
|
70
|
-
|
49
|
+
search.results
|
50
|
+
# => Job.where(Job.arel_table[:date].in(Date.new(2015,6,4)..Date.new(2015,6,5)))
|
51
|
+
# .where('jobs' => { id: '42' })
|
52
|
+
# .where(Job.arel_table[:name].lower.like('%foo bar%'))
|
71
53
|
|
72
54
|
search = ReceiptSearch.new('-6/4/15 posted: 6/5/15- amount: 1000 123')
|
73
|
-
search.results
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
55
|
+
search.results
|
56
|
+
# => Receipt.where(Receipt.arel_table[:check_date].lteq(Date.new(2015,6,4)))
|
57
|
+
# .where(Receipt.arel_table[:post_date].gteq(Date.new(2015,6,5)))
|
58
|
+
# .where(receipts: { amount: '1000' })
|
59
|
+
# .where(Receipt.arel_table[:check_no].matches('123'))
|
data/examples/sequel_example.rb
CHANGED
@@ -31,7 +31,7 @@ end
|
|
31
31
|
class CategoryParser # :nodoc:
|
32
32
|
def call(token)
|
33
33
|
if token.modifier == 'cat'
|
34
|
-
[:where, {
|
34
|
+
[:where, { Sequel.qualify('category', 'name') => token.term }]
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -39,12 +39,20 @@ end
|
|
39
39
|
class TaskSearch < SearchLingo::AbstractSearch # :nodoc:
|
40
40
|
parser CategoryParser.new
|
41
41
|
|
42
|
+
# Match categories with priority less than or greater than a given value.
|
43
|
+
#
|
44
|
+
# <2 => Categories with priority < 2
|
45
|
+
# >5 => Categories with priority > 5
|
42
46
|
parser do |token|
|
43
47
|
token.match /\A([<>])([[:digit:]]+)\z/ do |m|
|
44
|
-
[:where,
|
48
|
+
[:where, Sequel.expr { priority.send m[1], m[2] }]
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
52
|
+
# Match tasks with a given due_date.
|
53
|
+
#
|
54
|
+
# 7/4/1776 => Tasks with due_date == Date.new(1776, 7, 4)
|
55
|
+
# 7/4/17 => Tasks with due_date == Date.new(2017, 7, 4)
|
48
56
|
parser do |token|
|
49
57
|
token.match %r{\A(?<m>\d{1,2})/(?<d>\d{1,2})/(?<y>\d{2}\d{2}?)\z} do |m|
|
50
58
|
begin
|
@@ -54,8 +62,12 @@ class TaskSearch < SearchLingo::AbstractSearch # :nodoc:
|
|
54
62
|
end
|
55
63
|
end
|
56
64
|
|
65
|
+
# Match tasks with names that contain a given term.
|
66
|
+
#
|
67
|
+
# pay bills => Match tasks with names like "pay bills", "pay bills by today"
|
68
|
+
# brush teeth => Match tasks with names like "brush teeth", "brush teeth and floss"
|
57
69
|
def default_parse(token)
|
58
|
-
[:where, 'tasks.name LIKE ?', "%#{token.term}%"]
|
70
|
+
[:where, Sequel.lit('tasks.name LIKE ?', "%#{token.term}%")]
|
59
71
|
end
|
60
72
|
|
61
73
|
def scope
|
@@ -23,34 +23,30 @@ module SearchLingo
|
|
23
23
|
##
|
24
24
|
# Adds a new parser to the list of parsers used by this class.
|
25
25
|
#
|
26
|
-
# The parser
|
27
|
-
# +#call
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
26
|
+
# The parser may be given as an anonymous block or as any argument which
|
27
|
+
# responds to +#call+. The parser will be send +#call+ with a single
|
28
|
+
# argument which will be a token from the query string.
|
29
|
+
#
|
30
|
+
# If both a callable object and a block are given, or if neither a callable
|
31
|
+
# object nor a block are given, an +ArgumentError+ will be raised.
|
31
32
|
#
|
32
33
|
# class MyParser
|
33
|
-
# def call
|
34
|
+
# def call(token)
|
34
35
|
# # return something
|
35
36
|
# end
|
36
37
|
# end
|
37
38
|
#
|
38
39
|
# class MySearch < SearchLingo::AbstractSearch
|
39
40
|
# parser MyParser.new
|
40
|
-
# parser do
|
41
|
+
# parser do |token|
|
41
42
|
# # return something
|
42
43
|
# end
|
43
44
|
# end
|
44
|
-
def self.parser(
|
45
|
-
unless
|
46
|
-
raise ArgumentError, 'parse must be called with callable
|
47
|
-
end
|
48
|
-
if callable && block_given?
|
49
|
-
# TODO: should this raise an error instead?
|
50
|
-
warn "WARNING: parse called with callable and block (#{caller.first}"
|
45
|
+
def self.parser(parser = nil, &block)
|
46
|
+
unless block_given? ^ parser.respond_to?(:call)
|
47
|
+
raise ArgumentError, 'parse must be called with callable OR block'
|
51
48
|
end
|
52
|
-
|
53
|
-
parsers << (callable || block)
|
49
|
+
parsers << (parser || block)
|
54
50
|
end
|
55
51
|
|
56
52
|
##
|
@@ -62,7 +58,13 @@ module SearchLingo
|
|
62
58
|
##
|
63
59
|
# Returns the results of executing the search.
|
64
60
|
def results
|
65
|
-
@results ||=
|
61
|
+
@results ||= load_results
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Constructs and performs the query.
|
66
|
+
def load_results
|
67
|
+
conditions.inject(scope) do |query, condition|
|
66
68
|
query.public_send(*condition)
|
67
69
|
end
|
68
70
|
end
|
@@ -85,11 +87,16 @@ module SearchLingo
|
|
85
87
|
def conditions
|
86
88
|
tokenizer.inject([]) do |conditions, token|
|
87
89
|
conditions << catch(:match) do
|
90
|
+
# 1. Try each parser with the token until :match is thrown.
|
88
91
|
parse token
|
92
|
+
|
93
|
+
# 2. If :match not thrown and token is compound, simplify and try again.
|
89
94
|
if token.compound?
|
90
95
|
token = tokenizer.simplify
|
91
96
|
parse token
|
92
97
|
end
|
98
|
+
|
99
|
+
# 3. If :match still not thrown, fallback on default parser.
|
93
100
|
default_parse token
|
94
101
|
end
|
95
102
|
end
|
@@ -113,6 +120,7 @@ module SearchLingo
|
|
113
120
|
result = parser.call token
|
114
121
|
throw :match, result if result
|
115
122
|
end
|
123
|
+
nil
|
116
124
|
end
|
117
125
|
|
118
126
|
##
|
@@ -5,33 +5,71 @@ module SearchLingo
|
|
5
5
|
class DateParser
|
6
6
|
include MDY
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
##
|
9
|
+
# Instantiates a new DateParser object.
|
10
|
+
#
|
11
|
+
# The required argument +column+ should be an Arel attribute.
|
12
|
+
#
|
13
|
+
# If present, the optional argument +modifier+ will be used as the
|
14
|
+
# operator which precedes the date term.
|
15
|
+
#
|
16
|
+
# DateParser.new Booking.arel_table[:date]
|
17
|
+
# DateParser.new Contract.arel_table[:date], modifier: 'contract'
|
18
|
+
def initialize(column, modifier: nil)
|
19
|
+
@column = column
|
20
|
+
@prefix = %r{#{modifier}:[[:space:]]*} if modifier
|
14
21
|
end
|
15
22
|
|
16
|
-
attr_reader :
|
23
|
+
attr_reader :column, :prefix
|
17
24
|
|
18
|
-
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
25
|
+
##
|
26
|
+
# Attempts to parse the token as a date, closed date range, or open date
|
27
|
+
# range.
|
28
|
+
#
|
29
|
+
# Examples of single dates are 7/14, 7/14/17, and 7/14/2017.
|
30
|
+
# Examples of closed date ranges are 1/1-6/30 and 7/1/16-6/30/18.
|
31
|
+
# Examples of open date ranges are -6/30 and 7/1/17-.
|
22
32
|
def call(token)
|
33
|
+
parse_single_date(token) ||
|
34
|
+
parse_date_range(token) ||
|
35
|
+
parse_lte_date(token) ||
|
36
|
+
parse_gte_date(token)
|
37
|
+
end
|
38
|
+
|
39
|
+
def inspect # :nodoc:
|
40
|
+
'#<%s:0x%x @prefix=%s @column=%s>' %
|
41
|
+
[self.class, object_id << 1, prefix.inspect, column.inspect]
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def parse_single_date(token)
|
23
47
|
token.match /\A#{prefix}(?<date>#{US_DATE})\z/ do |m|
|
24
|
-
date = parse
|
25
|
-
[:where,
|
48
|
+
date = parse(m[:date]) or return nil
|
49
|
+
[:where, column.eq(date)]
|
26
50
|
end
|
27
51
|
end
|
28
52
|
|
29
|
-
def
|
53
|
+
def parse_date_range(token)
|
54
|
+
token.match /\A#{prefix}(?<min>#{US_DATE})-(?<max>#{US_DATE})\z/ do |m|
|
55
|
+
min = parse(m[:min]) or return nil
|
56
|
+
max = parse(m[:max], relative_to: min.next_year) or return nil
|
57
|
+
[:where, column.in(min..max)]
|
58
|
+
end
|
30
59
|
end
|
31
60
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
61
|
+
def parse_lte_date(token)
|
62
|
+
token.match /\A#{prefix}-(?<date>#{US_DATE})\z/ do |m|
|
63
|
+
date = parse(m[:date]) or return nil
|
64
|
+
[:where, column.lteq(date)]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def parse_gte_date(token)
|
69
|
+
token.match /\A#{prefix}(?<date>#{US_DATE})-\z/ do |m|
|
70
|
+
date = parse(m[:date]) or return nil
|
71
|
+
[:where, column.gteq(date)]
|
72
|
+
end
|
35
73
|
end
|
36
74
|
end
|
37
75
|
end
|
@@ -13,8 +13,8 @@ module SearchLingo
|
|
13
13
|
# Returns a +Date+ object for the date represented by +term+. Returns
|
14
14
|
# +nil+ if +term+ can not be parsed.
|
15
15
|
#
|
16
|
-
# If the year has two digits, it will be expanded into a
|
17
|
-
# +Date.parse+.
|
16
|
+
# If the year has two digits, it will be implicitly expanded into a
|
17
|
+
# four-digit year by +Date.parse+. Otherwise it will be used as is.
|
18
18
|
#
|
19
19
|
# If the year is omitted, it will be inferred using +relative_to+ as a
|
20
20
|
# reference date. In this scenario, the resulting date will always be
|
@@ -26,12 +26,13 @@ module SearchLingo
|
|
26
26
|
term.match /\A#{US_DATE}\z/ do |m|
|
27
27
|
return Date.parse "#{m[:y]}/#{m[:m]}/#{m[:d]}" if m[:y]
|
28
28
|
|
29
|
+
ref = relative_to
|
29
30
|
day = Integer(m[:d])
|
30
31
|
month = Integer(m[:m])
|
31
|
-
year = if month <
|
32
|
-
|
32
|
+
year = if month < ref.month || month == ref.month && day <= ref.day
|
33
|
+
ref.year
|
33
34
|
else
|
34
|
-
|
35
|
+
ref.year - 1
|
35
36
|
end
|
36
37
|
|
37
38
|
Date.new year, month, day
|
data/lib/search_lingo/parsers.rb
CHANGED
data/lib/search_lingo/version.rb
CHANGED
data/search_lingo.gemspec
CHANGED
@@ -27,6 +27,6 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_development_dependency "rake", "~> 10.0"
|
28
28
|
spec.add_development_dependency 'minitest'
|
29
29
|
spec.add_development_dependency 'pry'
|
30
|
-
spec.add_development_dependency 'sequel'
|
30
|
+
spec.add_development_dependency 'sequel', '~> 4.48'
|
31
31
|
spec.add_development_dependency 'sqlite3'
|
32
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: search_lingo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Parker
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -70,16 +70,16 @@ dependencies:
|
|
70
70
|
name: sequel
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '4.48'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '4.48'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: sqlite3
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -117,11 +117,7 @@ files:
|
|
117
117
|
- lib/search_lingo/constants.rb
|
118
118
|
- lib/search_lingo/parsers.rb
|
119
119
|
- lib/search_lingo/parsers/date_parser.rb
|
120
|
-
- lib/search_lingo/parsers/date_range_parser.rb
|
121
|
-
- lib/search_lingo/parsers/gte_date_parser.rb
|
122
|
-
- lib/search_lingo/parsers/lte_date_parser.rb
|
123
120
|
- lib/search_lingo/parsers/mdy.rb
|
124
|
-
- lib/search_lingo/parsers/open_date_range_parser.rb
|
125
121
|
- lib/search_lingo/token.rb
|
126
122
|
- lib/search_lingo/tokenizer.rb
|
127
123
|
- lib/search_lingo/version.rb
|
@@ -150,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
146
|
version: '0'
|
151
147
|
requirements: []
|
152
148
|
rubyforge_project:
|
153
|
-
rubygems_version: 2.
|
149
|
+
rubygems_version: 2.7.7
|
154
150
|
signing_key:
|
155
151
|
specification_version: 4
|
156
152
|
summary: Framework for building simple query languages
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'search_lingo/parsers/date_parser'
|
2
|
-
|
3
|
-
module SearchLingo
|
4
|
-
module Parsers # :nodoc:
|
5
|
-
class DateRangeParser < DateParser
|
6
|
-
def call(token)
|
7
|
-
token.match /\A#{prefix}(?<min>#{US_DATE})-(?<max>#{US_DATE})\z/ do |m|
|
8
|
-
min = parse m[:min]
|
9
|
-
max = parse m[:max], relative_to: min.next_year if min
|
10
|
-
[:where, { table => { column => min..max } }] if min && max
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'search_lingo/parsers/open_date_range_parser'
|
2
|
-
|
3
|
-
module SearchLingo
|
4
|
-
module Parsers # :nodoc:
|
5
|
-
class GTEDateParser < OpenDateRangeParser # :nodoc:
|
6
|
-
def initialize(*)
|
7
|
-
warn "DEPRECATION WARNING: use SearchLingo::Parsers::OpenDateRangeParser " \
|
8
|
-
"instead of #{self.class} (from #{caller.first})"
|
9
|
-
super
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'search_lingo/parsers/open_date_range_parser'
|
2
|
-
|
3
|
-
module SearchLingo
|
4
|
-
module Parsers # :nodoc:
|
5
|
-
class LTEDateParser < OpenDateRangeParser # :nodoc:
|
6
|
-
def initialize(*)
|
7
|
-
warn "DEPRECATION WARNING: use SearchLingo::Parsers::OpenDateRangeParser " \
|
8
|
-
"instead of #{self.class} (from #{caller.first})"
|
9
|
-
super
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'search_lingo/parsers/date_parser'
|
2
|
-
require 'forwardable'
|
3
|
-
|
4
|
-
module SearchLingo
|
5
|
-
module Parsers # :nodoc:
|
6
|
-
class OpenDateRangeParser < DateParser
|
7
|
-
extend Forwardable
|
8
|
-
|
9
|
-
def call(token)
|
10
|
-
parse_lte(token) || parse_gte(token)
|
11
|
-
end
|
12
|
-
|
13
|
-
def post_initialize(connection:, **)
|
14
|
-
@connection = connection
|
15
|
-
end
|
16
|
-
|
17
|
-
def_delegators :@connection, :quote_column_name, :quote_table_name
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def parse_lte(token) # :nodoc:
|
22
|
-
token.match /\A#{prefix}-(?<date>#{US_DATE})\z/ do |m|
|
23
|
-
if date = parse(m[:date])
|
24
|
-
[
|
25
|
-
:where,
|
26
|
-
"#{quote_table_name table}.#{quote_column_name column} <= ?",
|
27
|
-
date
|
28
|
-
]
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def parse_gte(token) # :nodoc:
|
34
|
-
token.match /\A#{prefix}(?<date>#{US_DATE})-\z/ do |m|
|
35
|
-
if date = parse(m[:date])
|
36
|
-
[
|
37
|
-
:where,
|
38
|
-
"#{quote_table_name table}.#{quote_column_name column} >= ?",
|
39
|
-
date
|
40
|
-
]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|