safrano 0.3.4 → 0.4.4
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 +4 -4
- data/lib/core_ext/Dir/iter.rb +18 -0
- data/lib/core_ext/Hash/transform.rb +21 -0
- data/lib/core_ext/Integer/edm.rb +13 -0
- data/lib/core_ext/REXML/Document/output.rb +16 -0
- data/lib/core_ext/String/convert.rb +25 -0
- data/lib/core_ext/String/edm.rb +13 -0
- data/lib/core_ext/dir.rb +3 -0
- data/lib/core_ext/hash.rb +3 -0
- data/lib/core_ext/integer.rb +3 -0
- data/lib/core_ext/rexml.rb +3 -0
- data/lib/core_ext/string.rb +5 -0
- data/lib/odata/attribute.rb +15 -10
- data/lib/odata/batch.rb +17 -15
- data/lib/odata/collection.rb +141 -500
- data/lib/odata/collection_filter.rb +44 -37
- data/lib/odata/collection_media.rb +193 -43
- data/lib/odata/collection_order.rb +50 -37
- data/lib/odata/common_logger.rb +39 -12
- data/lib/odata/complex_type.rb +152 -0
- data/lib/odata/edm/primitive_types.rb +184 -0
- data/lib/odata/entity.rb +201 -176
- data/lib/odata/error.rb +186 -33
- data/lib/odata/expand.rb +126 -0
- data/lib/odata/filter/base.rb +69 -0
- data/lib/odata/filter/error.rb +55 -6
- data/lib/odata/filter/parse.rb +38 -36
- data/lib/odata/filter/sequel.rb +121 -67
- data/lib/odata/filter/sequel_function_adapter.rb +148 -0
- data/lib/odata/filter/token.rb +15 -11
- data/lib/odata/filter/tree.rb +110 -60
- data/lib/odata/function_import.rb +166 -0
- data/lib/odata/model_ext.rb +618 -0
- data/lib/odata/navigation_attribute.rb +50 -32
- data/lib/odata/relations.rb +7 -7
- data/lib/odata/select.rb +54 -0
- data/lib/{safrano_core.rb → odata/transition.rb} +14 -60
- data/lib/odata/url_parameters.rb +128 -37
- data/lib/odata/walker.rb +19 -11
- data/lib/safrano.rb +18 -28
- data/lib/safrano/contract.rb +143 -0
- data/lib/safrano/core.rb +43 -0
- data/lib/safrano/core_ext.rb +13 -0
- data/lib/safrano/deprecation.rb +73 -0
- data/lib/{multipart.rb → safrano/multipart.rb} +37 -41
- data/lib/safrano/rack_app.rb +175 -0
- data/lib/{odata_rack_builder.rb → safrano/rack_builder.rb} +18 -2
- data/lib/{request.rb → safrano/request.rb} +102 -50
- data/lib/{response.rb → safrano/response.rb} +5 -4
- data/lib/safrano/sequel_join_by_paths.rb +5 -0
- data/lib/{service.rb → safrano/service.rb} +257 -188
- data/lib/safrano/version.rb +5 -0
- data/lib/sequel/plugins/join_by_paths.rb +17 -29
- metadata +53 -17
- data/lib/rack_app.rb +0 -174
- data/lib/sequel_join_by_paths.rb +0 -5
- data/lib/version.rb +0 -4
data/lib/odata/filter/error.rb
CHANGED
@@ -1,12 +1,31 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../error'
|
4
|
+
|
5
|
+
module Safrano
|
6
|
+
class SequelAdapterError < StandardError
|
7
|
+
attr_reader :inner
|
8
|
+
|
9
|
+
def initialize(err)
|
10
|
+
@inner = err
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
2
14
|
module Filter
|
3
15
|
class Parser
|
4
16
|
# Parser errors
|
5
|
-
|
17
|
+
|
18
|
+
class Error
|
19
|
+
def Error.http_code
|
20
|
+
const_get(:HTTP_CODE)
|
21
|
+
end
|
22
|
+
HTTP_CODE = 400
|
23
|
+
|
6
24
|
attr_reader :tok
|
7
25
|
attr_reader :typ
|
8
26
|
attr_reader :cur_val
|
9
27
|
attr_reader :cur_typ
|
28
|
+
|
10
29
|
def initialize(tok, typ, cur)
|
11
30
|
@tok = tok
|
12
31
|
@typ = typ
|
@@ -18,31 +37,61 @@ module OData
|
|
18
37
|
end
|
19
38
|
# Invalid Tokens
|
20
39
|
class ErrorInvalidToken < Error
|
40
|
+
include ::Safrano::ErrorInstance
|
41
|
+
def initialize(tok, typ, cur)
|
42
|
+
super
|
43
|
+
@msg = "Bad Request: invalid token #{tok} in $filter"
|
44
|
+
end
|
21
45
|
end
|
22
46
|
# Unmached closed
|
23
47
|
class ErrorUnmatchedClose < Error
|
48
|
+
include ::Safrano::ErrorInstance
|
49
|
+
def initialize(tok, typ, cur)
|
50
|
+
super
|
51
|
+
@msg = "Bad Request: unmatched #{tok} in $filter"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class ErrorFunctionArgumentType
|
56
|
+
include ::Safrano::ErrorInstance
|
24
57
|
end
|
25
58
|
|
26
|
-
class
|
59
|
+
class ErrorWrongColumnName
|
60
|
+
include ::Safrano::ErrorInstance
|
27
61
|
end
|
28
62
|
|
29
|
-
|
63
|
+
# attempt to add a child to a Leave
|
64
|
+
class ErrorLeaveChild
|
65
|
+
include ::Safrano::ErrorInstance
|
30
66
|
end
|
31
67
|
|
32
68
|
# Invalid function arity
|
33
69
|
class ErrorInvalidArity < Error
|
70
|
+
include ::Safrano::ErrorInstance
|
71
|
+
def initialize(tok, typ, cur)
|
72
|
+
super
|
73
|
+
@msg = "Bad Request: wrong number of parameters for function #{cur.parent.value.to_s} in $filter"
|
74
|
+
end
|
34
75
|
end
|
35
76
|
# Invalid separator in this context (missing parenthesis?)
|
36
77
|
class ErrorInvalidSeparator < Error
|
78
|
+
include ::Safrano::ErrorInstance
|
37
79
|
end
|
38
80
|
|
39
81
|
# unmatched quot3
|
40
82
|
class UnmatchedQuoteError < Error
|
83
|
+
include ::Safrano::ErrorInstance
|
84
|
+
def initialize(tok, typ, cur)
|
85
|
+
super
|
86
|
+
@msg = "Bad Request: unbalanced quotes #{tok} in $filter"
|
87
|
+
end
|
41
88
|
end
|
42
89
|
|
43
90
|
# wrong type of function argument
|
44
|
-
class ErrorInvalidArgumentType <
|
45
|
-
|
91
|
+
class ErrorInvalidArgumentType < Error
|
92
|
+
include ::Safrano::ErrorInstance
|
93
|
+
|
94
|
+
def initialize(tree, expected:, actual:)
|
46
95
|
@tree = tree
|
47
96
|
@expected = expected
|
48
97
|
@actual = actual
|
data/lib/odata/filter/parse.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
-
|
2
|
-
require_relative './tree.rb'
|
3
|
-
require_relative './error.rb'
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
|
6
|
-
|
3
|
+
require_relative './token'
|
4
|
+
require_relative './tree'
|
5
|
+
require_relative './error'
|
6
|
+
|
7
|
+
# top level Safrano namespace
|
8
|
+
module Safrano
|
7
9
|
# for handling $filter
|
8
10
|
module Filter
|
9
11
|
# Parser for $filter input
|
10
12
|
class Parser
|
11
13
|
include Token
|
12
14
|
attr_reader :cursor
|
15
|
+
attr_reader :error
|
16
|
+
|
13
17
|
def initialize(input)
|
14
18
|
@tree = RootTree.new
|
15
19
|
@cursor = @tree
|
@@ -18,10 +22,14 @@ module OData
|
|
18
22
|
@binop_stack = []
|
19
23
|
end
|
20
24
|
|
25
|
+
def server_error
|
26
|
+
(@error = ::Safrano::ServerError)
|
27
|
+
end
|
28
|
+
|
21
29
|
def grow_at_cursor(child)
|
22
|
-
|
30
|
+
return server_error if @cursor.nil?
|
23
31
|
|
24
|
-
@cursor.attach(child)
|
32
|
+
@cursor.attach(child).tap_error { |err| return (@error = err) }
|
25
33
|
@cursor = child
|
26
34
|
end
|
27
35
|
|
@@ -40,7 +48,7 @@ module OData
|
|
40
48
|
def insert_before_cursor(node)
|
41
49
|
left = detach_cursor
|
42
50
|
grow_at_cursor(node)
|
43
|
-
@cursor.attach(left)
|
51
|
+
@cursor.attach(left).tap_error { |err| return (@error = err) }
|
44
52
|
end
|
45
53
|
|
46
54
|
def invalid_separator_error(tok, typ)
|
@@ -56,36 +64,29 @@ module OData
|
|
56
64
|
end
|
57
65
|
|
58
66
|
def with_accepted(tok, typ)
|
59
|
-
|
60
|
-
if acc
|
61
|
-
yield
|
62
|
-
else
|
63
|
-
@error = err
|
64
|
-
end
|
67
|
+
(err = @cursor.accept?(tok, typ)) ? (@error = err) : yield
|
65
68
|
end
|
66
69
|
|
67
70
|
def build
|
68
71
|
each_typed_token(@input) do |tok, typ|
|
69
72
|
case typ
|
70
73
|
when :FuncTree
|
71
|
-
with_accepted(tok, typ)
|
72
|
-
|
73
|
-
end
|
74
|
+
with_accepted(tok, typ) { grow_at_cursor(FuncTree.new(tok)) }
|
75
|
+
|
74
76
|
when :Delimiter
|
75
77
|
case tok
|
76
78
|
when '('
|
77
79
|
with_accepted(tok, typ) do
|
78
|
-
unless @cursor.is_a? FuncTree
|
79
|
-
|
80
|
+
grow_at_cursor(IdentityFuncTree.new) unless @cursor.is_a? FuncTree
|
81
|
+
unless @error
|
82
|
+
openarg = ArgTree.new('(')
|
83
|
+
@stack << openarg
|
84
|
+
grow_at_cursor(openarg)
|
80
85
|
end
|
81
|
-
openarg = ArgTree.new('(')
|
82
|
-
@stack << openarg
|
83
|
-
grow_at_cursor(openarg)
|
84
86
|
end
|
87
|
+
|
85
88
|
when ')'
|
86
|
-
unless (@cursor = @stack.pop)
|
87
|
-
break invalid_closing_delimiter_error(tok, typ)
|
88
|
-
end
|
89
|
+
break invalid_closing_delimiter_error(tok, typ) unless (@cursor = @stack.pop)
|
89
90
|
|
90
91
|
with_accepted(tok, typ) do
|
91
92
|
@cursor.update_state(tok, typ)
|
@@ -94,9 +95,7 @@ module OData
|
|
94
95
|
end
|
95
96
|
|
96
97
|
when :Separator
|
97
|
-
unless (@cursor = @stack.last)
|
98
|
-
break invalid_separator_error(tok, typ)
|
99
|
-
end
|
98
|
+
break invalid_separator_error(tok, typ) unless (@cursor = @stack.last)
|
100
99
|
|
101
100
|
with_accepted(tok, typ) { @cursor.update_state(tok, typ) }
|
102
101
|
|
@@ -129,6 +128,7 @@ module OData
|
|
129
128
|
end
|
130
129
|
insert_before_cursor(binoptr)
|
131
130
|
end
|
131
|
+
|
132
132
|
when :BinopArithm
|
133
133
|
with_accepted(tok, typ) do
|
134
134
|
binoptr = BinopArithm.new(tok)
|
@@ -168,19 +168,21 @@ module OData
|
|
168
168
|
@cursor.update_state(tok, typ)
|
169
169
|
grow_at_cursor(FPNumber.new(tok))
|
170
170
|
end
|
171
|
+
|
171
172
|
when :unmatchedQuote
|
172
173
|
break unmatched_quote_error(tok, typ)
|
174
|
+
|
175
|
+
when :space
|
176
|
+
with_accepted(tok, typ) do
|
177
|
+
@cursor.update_state(tok, typ)
|
178
|
+
end
|
173
179
|
else
|
174
|
-
|
180
|
+
server_error
|
175
181
|
end
|
176
|
-
break if @error
|
177
|
-
end
|
178
|
-
begin
|
179
|
-
@tree.check_types unless @error
|
180
|
-
rescue ErrorInvalidArgumentType => e
|
181
|
-
@error = e
|
182
|
+
break(@error) if @error
|
182
183
|
end
|
183
|
-
@error
|
184
|
+
(@error = @tree.check_types) unless @error
|
185
|
+
@error ? @error : Contract.valid(@tree)
|
184
186
|
end
|
185
187
|
end
|
186
188
|
end
|
data/lib/odata/filter/sequel.rb
CHANGED
@@ -1,19 +1,24 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './base'
|
4
|
+
require_relative './sequel_function_adapter'
|
5
|
+
|
6
|
+
module Safrano
|
3
7
|
module Filter
|
4
8
|
# Base class for Leaves, Trees, RootTrees etc
|
5
|
-
class Node
|
6
|
-
end
|
9
|
+
# class Node
|
10
|
+
# end
|
7
11
|
|
8
12
|
# Leaves are Nodes with a parent but no children
|
9
|
-
class Leave < Node
|
10
|
-
end
|
13
|
+
# class Leave < Node
|
14
|
+
# end
|
11
15
|
|
12
16
|
# RootTrees have childrens but no parent
|
13
17
|
class RootTree
|
14
18
|
def apply_to_dataset(dtcx, jh)
|
15
|
-
|
16
|
-
|
19
|
+
@children.first.leuqes(jh).if_valid do |filtexpr|
|
20
|
+
jh.dataset(dtcx).where(filtexpr).select_all(jh.start_model.table_name)
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
19
24
|
def sequel_expr(jh)
|
@@ -26,57 +31,108 @@ module OData
|
|
26
31
|
end
|
27
32
|
|
28
33
|
# For functions... should have a single child---> the argument list
|
34
|
+
# note: Adapter specific function helpers like year() or substringof_sig2()
|
35
|
+
# need to be mixed in on startup (eg. on publish finalize)
|
29
36
|
class FuncTree < Tree
|
30
37
|
def leuqes(jh)
|
31
38
|
case @value
|
32
39
|
when :startswith
|
33
|
-
|
34
|
-
|
40
|
+
Contract.collect_result!(args[0].leuqes(jh),
|
41
|
+
args[1].leuqes_starts_like(jh)) do |l0, l1|
|
42
|
+
Sequel.like(l0, l1)
|
43
|
+
end
|
44
|
+
|
35
45
|
when :endswith
|
36
|
-
|
37
|
-
|
46
|
+
Contract.collect_result!(args[0].leuqes(jh),
|
47
|
+
args[1].leuqes_ends_like(jh)) do |l0, l1|
|
48
|
+
Sequel.like(l0, l1)
|
49
|
+
end
|
50
|
+
|
38
51
|
when :substringof
|
39
52
|
|
40
53
|
# there are multiple possible argument types (but all should return edm.string)
|
41
|
-
if
|
54
|
+
if args[0].is_a?(QString)
|
42
55
|
# substringof('Rhum', name) -->
|
43
56
|
# name contains substr 'Rhum'
|
44
|
-
|
45
|
-
|
57
|
+
Contract.collect_result!(args[1].leuqes(jh),
|
58
|
+
args[0].leuqes_substringof_sig1(jh)) do |l1, l0|
|
59
|
+
Sequel.like(l1, l0)
|
60
|
+
end
|
61
|
+
|
46
62
|
# special non standard (ui5 client) case ?
|
47
|
-
elsif
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
# '__Route du Rhum__' contains name as a substring
|
53
|
-
# TODO... check if the database supports instr (how?)
|
54
|
-
# othewise use substr(postgresql) or whatevr?
|
55
|
-
instr_substr_func = if (Sequel::Model.db.adapter_scheme == :postgres)
|
56
|
-
Sequel.function(:strpos, args[1].leuqes(jh), args[0].leuqes(jh))
|
57
|
-
else
|
58
|
-
Sequel.function(:instr, args[1].leuqes(jh), args[0].leuqes(jh))
|
59
|
-
end
|
60
|
-
|
61
|
-
Sequel::SQL::BooleanExpression.new(:>, instr_substr_func, 0)
|
63
|
+
elsif args[0].is_a?(Literal) && args[1].is_a?(Literal)
|
64
|
+
Contract.collect_result!(args[1].leuqes(jh),
|
65
|
+
args[0].leuqes_substringof_sig1(jh)) do |l1, l0|
|
66
|
+
Sequel.like(l1, l0)
|
67
|
+
end
|
62
68
|
|
69
|
+
elsif args[1].is_a?(QString)
|
70
|
+
substringof_sig2(jh) # adapter specific
|
63
71
|
else
|
64
72
|
# TODO... actually not supported?
|
65
|
-
raise
|
73
|
+
raise Safrano::Filter::Parser::ErrorFunctionArgumentType
|
66
74
|
end
|
67
75
|
when :concat
|
68
|
-
|
69
|
-
|
76
|
+
Contract.collect_result!(args[0].leuqes(jh),
|
77
|
+
args[1].leuqes(jh)) do |l0, l1|
|
78
|
+
Sequel.join([l0, l1])
|
79
|
+
end
|
80
|
+
|
70
81
|
when :length
|
71
|
-
|
82
|
+
args.first.leuqes(jh)
|
83
|
+
.map_result! { |l| Sequel.char_length(l) }
|
84
|
+
|
72
85
|
when :trim
|
73
|
-
|
86
|
+
args.first.leuqes(jh)
|
87
|
+
.map_result! { |l| Sequel.trim(l) }
|
88
|
+
|
74
89
|
when :toupper
|
75
|
-
|
90
|
+
args.first.leuqes(jh)
|
91
|
+
.map_result! { |l| Sequel.function(:upper, l) }
|
92
|
+
|
76
93
|
when :tolower
|
77
|
-
|
94
|
+
args.first.leuqes(jh)
|
95
|
+
.map_result! { |l| Sequel.function(:lower, l) }
|
96
|
+
|
97
|
+
# all datetime funcs are adapter specific (because sqlite does not have extract)
|
98
|
+
when :year
|
99
|
+
args.first.leuqes(jh)
|
100
|
+
.map_result! { |l| year(l) }
|
101
|
+
|
102
|
+
when :month
|
103
|
+
args.first.leuqes(jh)
|
104
|
+
.map_result! { |l| month(l) }
|
105
|
+
|
106
|
+
when :second
|
107
|
+
args.first.leuqes(jh)
|
108
|
+
.map_result! { |l| second(l) }
|
109
|
+
|
110
|
+
when :minute
|
111
|
+
args.first.leuqes(jh)
|
112
|
+
.map_result! { |l| minute(l) }
|
113
|
+
|
114
|
+
when :hour
|
115
|
+
args.first.leuqes(jh)
|
116
|
+
.map_result! { |l| hour(l) }
|
117
|
+
|
118
|
+
when :day
|
119
|
+
args.first.leuqes(jh)
|
120
|
+
.map_result! { |l| day(l) }
|
121
|
+
|
122
|
+
# math functions
|
123
|
+
when :round
|
124
|
+
args.first.leuqes(jh)
|
125
|
+
.map_result! { |l| Sequel.function(:round, l) }
|
126
|
+
|
127
|
+
when :floor
|
128
|
+
args.first.leuqes(jh)
|
129
|
+
.if_valid { |l| floor(l) }
|
130
|
+
|
131
|
+
when :ceiling
|
132
|
+
args.first.leuqes(jh)
|
133
|
+
.if_valid { |l| ceiling(l) }
|
78
134
|
else
|
79
|
-
|
135
|
+
Safrano::FilterParseError
|
80
136
|
end
|
81
137
|
end
|
82
138
|
end
|
@@ -95,9 +151,9 @@ module OData
|
|
95
151
|
def leuqes(jh)
|
96
152
|
case @value
|
97
153
|
when :not
|
98
|
-
|
154
|
+
@children.first.leuqes(jh).map_result! { |l| Sequel.~(l) }
|
99
155
|
else
|
100
|
-
|
156
|
+
Safrano::FilterParseError
|
101
157
|
end
|
102
158
|
end
|
103
159
|
end
|
@@ -123,12 +179,12 @@ module OData
|
|
123
179
|
when :and
|
124
180
|
:AND
|
125
181
|
else
|
126
|
-
|
182
|
+
return Safrano::FilterParseError
|
127
183
|
end
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
184
|
+
Contract.collect_result!(@children[0].leuqes(jh),
|
185
|
+
@children[1].leuqes(jh)) do |c0, c1|
|
186
|
+
Sequel::SQL::BooleanExpression.new(leuqes_op, c0, c1)
|
187
|
+
end
|
132
188
|
end
|
133
189
|
end
|
134
190
|
|
@@ -147,12 +203,12 @@ module OData
|
|
147
203
|
when :mod
|
148
204
|
:%
|
149
205
|
else
|
150
|
-
|
206
|
+
return Safrano::FilterParseError
|
151
207
|
end
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
208
|
+
Contract.collect_result!(@children[0].leuqes(jh),
|
209
|
+
@children[1].leuqes(jh)) do |c0, c1|
|
210
|
+
Sequel::SQL::NumericExpression.new(leuqes_op, c0, c1)
|
211
|
+
end
|
156
212
|
end
|
157
213
|
end
|
158
214
|
|
@@ -163,44 +219,42 @@ module OData
|
|
163
219
|
# Numbers (floating point, ints, dec)
|
164
220
|
class FPNumber
|
165
221
|
def leuqes(_jh)
|
166
|
-
Sequel.lit(@value)
|
222
|
+
success Sequel.lit(@value)
|
167
223
|
end
|
168
224
|
|
169
225
|
def leuqes_starts_like(_jh)
|
170
|
-
"#{@value
|
226
|
+
success "#{@value}%"
|
171
227
|
end
|
172
228
|
|
173
229
|
def leuqes_ends_like(_jh)
|
174
|
-
"%#{@value
|
230
|
+
success "%#{@value}"
|
175
231
|
end
|
176
232
|
|
177
233
|
def leuqes_substringof_sig1(_jh)
|
178
|
-
"%#{@value
|
234
|
+
success "%#{@value}%"
|
179
235
|
end
|
180
236
|
end
|
181
237
|
|
182
238
|
# Literals are unquoted words
|
183
239
|
class Literal
|
184
240
|
def leuqes(jh)
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
raise OData::Filter::Parser::ErrorWrongColumnName
|
189
|
-
end
|
241
|
+
return Safrano::FilterParseErrorWrongColumnName unless jh.start_model.db_schema.key?(@value.to_sym)
|
242
|
+
|
243
|
+
success Sequel[jh.start_model.table_name][@value.to_sym]
|
190
244
|
end
|
191
245
|
|
192
246
|
# non stantard extensions to support things like
|
193
247
|
# substringof(Rhum, name) ????
|
194
248
|
def leuqes_starts_like(_jh)
|
195
|
-
"#{@value}%"
|
249
|
+
success "#{@value}%"
|
196
250
|
end
|
197
251
|
|
198
252
|
def leuqes_ends_like(_jh)
|
199
|
-
"%#{@value}"
|
253
|
+
success "%#{@value}"
|
200
254
|
end
|
201
255
|
|
202
256
|
def leuqes_substringof_sig1(_jh)
|
203
|
-
"%#{@value}%"
|
257
|
+
success "%#{@value}%"
|
204
258
|
end
|
205
259
|
|
206
260
|
def as_string
|
@@ -213,26 +267,26 @@ module OData
|
|
213
267
|
def leuqes(jh)
|
214
268
|
jh.add(@path)
|
215
269
|
talias = jh.start_model.get_alias_sym(@path)
|
216
|
-
Sequel[talias][@attrib.to_sym]
|
270
|
+
success Sequel[talias][@attrib.to_sym]
|
217
271
|
end
|
218
272
|
end
|
219
273
|
|
220
274
|
# Quoted Strings
|
221
275
|
class QString
|
222
276
|
def leuqes(_jh)
|
223
|
-
@value
|
277
|
+
success @value
|
224
278
|
end
|
225
279
|
|
226
280
|
def leuqes_starts_like(_jh)
|
227
|
-
"#{@value}%"
|
281
|
+
success "#{@value}%"
|
228
282
|
end
|
229
283
|
|
230
284
|
def leuqes_ends_like(_jh)
|
231
|
-
"%#{@value}"
|
285
|
+
success "%#{@value}"
|
232
286
|
end
|
233
287
|
|
234
288
|
def leuqes_substringof_sig1(_jh)
|
235
|
-
"%#{@value}%"
|
289
|
+
success "%#{@value}%"
|
236
290
|
end
|
237
291
|
end
|
238
292
|
end
|