safrano 0.4.1 → 0.4.6
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 +15 -13
- data/lib/odata/collection.rb +144 -535
- data/lib/odata/collection_filter.rb +47 -40
- data/lib/odata/collection_media.rb +155 -99
- data/lib/odata/collection_order.rb +50 -37
- data/lib/odata/common_logger.rb +36 -34
- data/lib/odata/complex_type.rb +152 -0
- data/lib/odata/edm/primitive_types.rb +184 -0
- data/lib/odata/entity.rb +183 -216
- data/lib/odata/error.rb +195 -31
- data/lib/odata/expand.rb +126 -0
- data/lib/odata/filter/base.rb +74 -0
- data/lib/odata/filter/error.rb +49 -6
- data/lib/odata/filter/parse.rb +44 -36
- data/lib/odata/filter/sequel.rb +136 -67
- data/lib/odata/filter/sequel_function_adapter.rb +148 -0
- data/lib/odata/filter/token.rb +26 -19
- data/lib/odata/filter/tree.rb +113 -63
- data/lib/odata/function_import.rb +168 -0
- data/lib/odata/model_ext.rb +639 -0
- data/lib/odata/navigation_attribute.rb +44 -61
- data/lib/odata/relations.rb +5 -5
- data/lib/odata/select.rb +54 -0
- data/lib/odata/transition.rb +71 -0
- data/lib/odata/url_parameters.rb +128 -37
- data/lib/odata/walker.rb +20 -10
- data/lib/safrano.rb +17 -37
- data/lib/safrano/contract.rb +143 -0
- data/lib/safrano/core.rb +29 -104
- data/lib/safrano/core_ext.rb +13 -0
- data/lib/safrano/deprecation.rb +73 -0
- data/lib/safrano/multipart.rb +39 -43
- data/lib/safrano/rack_app.rb +68 -67
- data/lib/safrano/{odata_rack_builder.rb → rack_builder.rb} +18 -2
- data/lib/safrano/request.rb +102 -51
- data/lib/safrano/response.rb +5 -3
- data/lib/safrano/sequel_join_by_paths.rb +2 -2
- data/lib/safrano/service.rb +274 -219
- data/lib/safrano/version.rb +3 -1
- data/lib/sequel/plugins/join_by_paths.rb +17 -29
- metadata +34 -11
data/lib/odata/filter/error.rb
CHANGED
@@ -1,18 +1,31 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../error'
|
4
|
+
|
5
|
+
module Safrano
|
2
6
|
class SequelAdapterError < StandardError
|
3
7
|
attr_reader :inner
|
8
|
+
|
4
9
|
def initialize(err)
|
5
10
|
@inner = err
|
6
11
|
end
|
7
12
|
end
|
13
|
+
|
8
14
|
module Filter
|
9
15
|
class Parser
|
10
16
|
# Parser errors
|
11
|
-
|
17
|
+
|
18
|
+
class Error
|
19
|
+
def Error.http_code
|
20
|
+
const_get(:HTTP_CODE)
|
21
|
+
end
|
22
|
+
HTTP_CODE = 400
|
23
|
+
|
12
24
|
attr_reader :tok
|
13
25
|
attr_reader :typ
|
14
26
|
attr_reader :cur_val
|
15
27
|
attr_reader :cur_typ
|
28
|
+
|
16
29
|
def initialize(tok, typ, cur)
|
17
30
|
@tok = tok
|
18
31
|
@typ = typ
|
@@ -24,31 +37,61 @@ module OData
|
|
24
37
|
end
|
25
38
|
# Invalid Tokens
|
26
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
|
27
45
|
end
|
28
46
|
# Unmached closed
|
29
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
|
30
53
|
end
|
31
54
|
|
32
|
-
class ErrorFunctionArgumentType
|
55
|
+
class ErrorFunctionArgumentType
|
56
|
+
include ::Safrano::ErrorInstance
|
33
57
|
end
|
34
58
|
|
35
|
-
class ErrorWrongColumnName
|
59
|
+
class ErrorWrongColumnName
|
60
|
+
include ::Safrano::ErrorInstance
|
61
|
+
end
|
62
|
+
|
63
|
+
# attempt to add a child to a Leave
|
64
|
+
class ErrorLeaveChild
|
65
|
+
include ::Safrano::ErrorInstance
|
36
66
|
end
|
37
67
|
|
38
68
|
# Invalid function arity
|
39
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
|
40
75
|
end
|
41
76
|
# Invalid separator in this context (missing parenthesis?)
|
42
77
|
class ErrorInvalidSeparator < Error
|
78
|
+
include ::Safrano::ErrorInstance
|
43
79
|
end
|
44
80
|
|
45
81
|
# unmatched quot3
|
46
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
|
47
88
|
end
|
48
89
|
|
49
90
|
# wrong type of function argument
|
50
|
-
class ErrorInvalidArgumentType <
|
51
|
-
|
91
|
+
class ErrorInvalidArgumentType < Error
|
92
|
+
include ::Safrano::ErrorInstance
|
93
|
+
|
94
|
+
def initialize(tree, expected:, actual:)
|
52
95
|
@tree = tree
|
53
96
|
@expected = expected
|
54
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)
|
@@ -151,6 +151,12 @@ module OData
|
|
151
151
|
grow_at_cursor(Literal.new(tok))
|
152
152
|
end
|
153
153
|
|
154
|
+
when :NullLiteral
|
155
|
+
with_accepted(tok, typ) do
|
156
|
+
@cursor.update_state(tok, typ)
|
157
|
+
grow_at_cursor(NullLiteral.new(tok))
|
158
|
+
end
|
159
|
+
|
154
160
|
when :Qualit
|
155
161
|
with_accepted(tok, typ) do
|
156
162
|
@cursor.update_state(tok, typ)
|
@@ -168,19 +174,21 @@ module OData
|
|
168
174
|
@cursor.update_state(tok, typ)
|
169
175
|
grow_at_cursor(FPNumber.new(tok))
|
170
176
|
end
|
177
|
+
|
171
178
|
when :unmatchedQuote
|
172
179
|
break unmatched_quote_error(tok, typ)
|
180
|
+
|
181
|
+
when :space
|
182
|
+
with_accepted(tok, typ) do
|
183
|
+
@cursor.update_state(tok, typ)
|
184
|
+
end
|
173
185
|
else
|
174
|
-
|
186
|
+
server_error
|
175
187
|
end
|
176
|
-
break if @error
|
177
|
-
end
|
178
|
-
begin
|
179
|
-
@tree.check_types unless @error
|
180
|
-
rescue ErrorInvalidArgumentType => e
|
181
|
-
@error = e
|
188
|
+
break(@error) if @error
|
182
189
|
end
|
183
|
-
@error
|
190
|
+
(@error = @tree.check_types) unless @error
|
191
|
+
@error ? @error : Contract.valid(@tree)
|
184
192
|
end
|
185
193
|
end
|
186
194
|
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,19 @@ 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
|
+
if c1 == NullLiteral::LEUQES
|
187
|
+
if @value == :eq
|
188
|
+
leuqes_op = :IS
|
189
|
+
elsif @value == :ne
|
190
|
+
leuqes_op = :'IS NOT'
|
191
|
+
end
|
192
|
+
end
|
193
|
+
Sequel::SQL::BooleanExpression.new(leuqes_op, c0, c1)
|
194
|
+
end
|
132
195
|
end
|
133
196
|
end
|
134
197
|
|
@@ -147,12 +210,12 @@ module OData
|
|
147
210
|
when :mod
|
148
211
|
:%
|
149
212
|
else
|
150
|
-
|
213
|
+
return Safrano::FilterParseError
|
151
214
|
end
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
215
|
+
Contract.collect_result!(@children[0].leuqes(jh),
|
216
|
+
@children[1].leuqes(jh)) do |c0, c1|
|
217
|
+
Sequel::SQL::NumericExpression.new(leuqes_op, c0, c1)
|
218
|
+
end
|
156
219
|
end
|
157
220
|
end
|
158
221
|
|
@@ -163,44 +226,42 @@ module OData
|
|
163
226
|
# Numbers (floating point, ints, dec)
|
164
227
|
class FPNumber
|
165
228
|
def leuqes(_jh)
|
166
|
-
Sequel.lit(@value)
|
229
|
+
success Sequel.lit(@value)
|
167
230
|
end
|
168
231
|
|
169
232
|
def leuqes_starts_like(_jh)
|
170
|
-
"#{@value
|
233
|
+
success "#{@value}%"
|
171
234
|
end
|
172
235
|
|
173
236
|
def leuqes_ends_like(_jh)
|
174
|
-
"%#{@value
|
237
|
+
success "%#{@value}"
|
175
238
|
end
|
176
239
|
|
177
240
|
def leuqes_substringof_sig1(_jh)
|
178
|
-
"%#{@value
|
241
|
+
success "%#{@value}%"
|
179
242
|
end
|
180
243
|
end
|
181
244
|
|
182
245
|
# Literals are unquoted words
|
183
246
|
class Literal
|
184
247
|
def leuqes(jh)
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
raise OData::Filter::Parser::ErrorWrongColumnName
|
189
|
-
end
|
248
|
+
return Safrano::FilterParseErrorWrongColumnName unless jh.start_model.db_schema.key?(@value.to_sym)
|
249
|
+
|
250
|
+
success Sequel[jh.start_model.table_name][@value.to_sym]
|
190
251
|
end
|
191
252
|
|
192
253
|
# non stantard extensions to support things like
|
193
254
|
# substringof(Rhum, name) ????
|
194
255
|
def leuqes_starts_like(_jh)
|
195
|
-
"#{@value}%"
|
256
|
+
success "#{@value}%"
|
196
257
|
end
|
197
258
|
|
198
259
|
def leuqes_ends_like(_jh)
|
199
|
-
"%#{@value}"
|
260
|
+
success "%#{@value}"
|
200
261
|
end
|
201
262
|
|
202
263
|
def leuqes_substringof_sig1(_jh)
|
203
|
-
"%#{@value}%"
|
264
|
+
success "%#{@value}%"
|
204
265
|
end
|
205
266
|
|
206
267
|
def as_string
|
@@ -208,31 +269,39 @@ module OData
|
|
208
269
|
end
|
209
270
|
end
|
210
271
|
|
272
|
+
# Null
|
273
|
+
class NullLiteral
|
274
|
+
def leuqes(jh)
|
275
|
+
# Sequel's representation of NULL
|
276
|
+
success LEUQES
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
211
280
|
# Qualit (qualified lits) are words separated by /
|
212
281
|
class Qualit
|
213
282
|
def leuqes(jh)
|
214
283
|
jh.add(@path)
|
215
284
|
talias = jh.start_model.get_alias_sym(@path)
|
216
|
-
Sequel[talias][@attrib.to_sym]
|
285
|
+
success Sequel[talias][@attrib.to_sym]
|
217
286
|
end
|
218
287
|
end
|
219
288
|
|
220
289
|
# Quoted Strings
|
221
290
|
class QString
|
222
291
|
def leuqes(_jh)
|
223
|
-
@value
|
292
|
+
success @value
|
224
293
|
end
|
225
294
|
|
226
295
|
def leuqes_starts_like(_jh)
|
227
|
-
"#{@value}%"
|
296
|
+
success "#{@value}%"
|
228
297
|
end
|
229
298
|
|
230
299
|
def leuqes_ends_like(_jh)
|
231
|
-
"%#{@value}"
|
300
|
+
success "%#{@value}"
|
232
301
|
end
|
233
302
|
|
234
303
|
def leuqes_substringof_sig1(_jh)
|
235
|
-
"%#{@value}%"
|
304
|
+
success "%#{@value}%"
|
236
305
|
end
|
237
306
|
end
|
238
307
|
end
|