rasti-db 2.0.1 → 2.1.0
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/README.md +11 -3
- data/lib/rasti/db/collection.rb +10 -1
- data/lib/rasti/db/computed_attribute.rb +22 -0
- data/lib/rasti/db/nql/nodes/attribute.rb +37 -0
- data/lib/rasti/db/nql/nodes/binary_node.rb +4 -0
- data/lib/rasti/db/nql/nodes/comparisons/base.rb +5 -1
- data/lib/rasti/db/nql/nodes/comparisons/equal.rb +2 -2
- data/lib/rasti/db/nql/nodes/comparisons/greater_than.rb +2 -2
- data/lib/rasti/db/nql/nodes/comparisons/greater_than_or_equal.rb +2 -2
- data/lib/rasti/db/nql/nodes/comparisons/include.rb +2 -2
- data/lib/rasti/db/nql/nodes/comparisons/less_than.rb +2 -2
- data/lib/rasti/db/nql/nodes/comparisons/less_than_or_equal.rb +2 -2
- data/lib/rasti/db/nql/nodes/comparisons/like.rb +2 -2
- data/lib/rasti/db/nql/nodes/comparisons/not_equal.rb +2 -2
- data/lib/rasti/db/nql/nodes/comparisons/not_include.rb +2 -2
- data/lib/rasti/db/nql/nodes/conjunction.rb +2 -2
- data/lib/rasti/db/nql/nodes/disjunction.rb +2 -2
- data/lib/rasti/db/nql/nodes/parenthesis_sentence.rb +6 -2
- data/lib/rasti/db/nql/nodes/sentence.rb +6 -2
- data/lib/rasti/db/nql/syntax.rb +33 -33
- data/lib/rasti/db/nql/syntax.treetop +12 -12
- data/lib/rasti/db/query.rb +41 -7
- data/lib/rasti/db/version.rb +1 -1
- data/spec/computed_attribute_spec.rb +32 -0
- data/spec/minitest_helper.rb +30 -3
- data/spec/model_spec.rb +1 -1
- data/spec/nql/computed_attributes_spec.rb +29 -0
- data/spec/nql/filter_condition_spec.rb +4 -2
- data/spec/nql/syntax_parser_spec.rb +12 -5
- data/spec/query_spec.rb +146 -34
- metadata +8 -3
- data/lib/rasti/db/nql/nodes/field.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3166fff22e51aca6cd07d0994d1bf6170438e0bc9aed41e90370a83920a0d9ff
|
4
|
+
data.tar.gz: 73e64013ec42740653058f0d9ff6c37ee45de41be0312f2296e4926fb7bff5b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55c6fc7f5b3ef1d904f252e6d54c595b5d4cb72f1fbdf67f3e577c9cc095bd838f0963f34f611f6b7069971f7ead1d96d7dd20864dbcfea8ed542c5a3008dfdc
|
7
|
+
data.tar.gz: 3b6c0136ba9823832cf329b3efe78406e69ea92d6d90f89950652628de740ea675a8b7d7152e530838f269b9b32140fa7f80750bcc2b41af70c9efc2b275cd78
|
data/README.md
CHANGED
@@ -93,7 +93,7 @@ User = Rasti::DB::Model[:id, :name, :posts, :comments, :person]
|
|
93
93
|
Post = Rasti::DB::Model[:id, :title, :body, :user_id, :user, :comments, :categories]
|
94
94
|
Comment = Rasti::DB::Model[:id, :text, :user_id, :user, :post_id, :post]
|
95
95
|
Category = Rasti::DB::Model[:id, :name, :posts]
|
96
|
-
Person = Rasti::DB::Model[:document_number, :first_name, :last_name, :birth_date, :user_id, :user]
|
96
|
+
Person = Rasti::DB::Model[:document_number, :first_name, :last_name, :full_name, :birth_date, :user_id, :user]
|
97
97
|
Language = Rasti::DB::Model[:id, :name, :people]
|
98
98
|
```
|
99
99
|
|
@@ -111,10 +111,10 @@ class Posts < Rasti::DB::Collection
|
|
111
111
|
many_to_many :categories
|
112
112
|
one_to_many :comments
|
113
113
|
|
114
|
-
query :created_by do |user_id|
|
114
|
+
query :created_by do |user_id|
|
115
115
|
where user_id: user_id
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
query :entitled, -> (title) { where title: title }
|
119
119
|
|
120
120
|
query :commented_by do |user_id|
|
@@ -144,6 +144,10 @@ class People < Rasti::DB::Collection
|
|
144
144
|
|
145
145
|
many_to_one :user
|
146
146
|
many_to_many :languages
|
147
|
+
|
148
|
+
computed_attribute :full_name do
|
149
|
+
Rasti::DB::ComputedAttribute.new Sequel.join([:first_name, ' ', :last_name])
|
150
|
+
end
|
147
151
|
end
|
148
152
|
|
149
153
|
class Languages < Rasti::DB::Collection
|
@@ -210,6 +214,10 @@ posts.all_attributes # => [Post, ...]
|
|
210
214
|
posts.graph('user.person').select_graph_attributes(user: [:id], 'user.person': [:last_name, :user_id]) # => [Post, ...]
|
211
215
|
posts.graph('user.person').exclude_graph_attributes(user: [:name], 'user.person': [:first_name, :last_name]) # => [Post, ...]
|
212
216
|
posts.graph('user.person').all_graph_attributes('user.person') # => [Post, ...]
|
217
|
+
|
218
|
+
posts.each { |post| do_something post } # Iterate posts loading all at first
|
219
|
+
posts.each(batch_size: 1000) { |post| do_something post } # Iterate posts loading in batches
|
220
|
+
posts.each_batch(size: 1000) { |posts| do_something posts } # Iterate batches of posts
|
213
221
|
```
|
214
222
|
### Natural Query Language
|
215
223
|
|
data/lib/rasti/db/collection.rb
CHANGED
@@ -14,7 +14,7 @@ module Rasti
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def collection_attributes
|
17
|
-
@collection_attributes ||= model.attributes - relations.keys
|
17
|
+
@collection_attributes ||= model.attributes - relations.keys - computed_attributes.keys
|
18
18
|
end
|
19
19
|
|
20
20
|
def primary_key
|
@@ -47,6 +47,10 @@ module Rasti
|
|
47
47
|
@queries ||= Hash::Indifferent.new
|
48
48
|
end
|
49
49
|
|
50
|
+
def computed_attributes
|
51
|
+
@computed_attributes ||= Hash::Indifferent.new
|
52
|
+
end
|
53
|
+
|
50
54
|
private
|
51
55
|
|
52
56
|
def set_collection_name(collection_name)
|
@@ -91,6 +95,11 @@ module Rasti
|
|
91
95
|
end
|
92
96
|
end
|
93
97
|
|
98
|
+
def computed_attribute(name, &block)
|
99
|
+
raise "Computed Attribute #{name} already exists" if computed_attributes.key? name
|
100
|
+
computed_attributes[name] = block.call
|
101
|
+
end
|
102
|
+
|
94
103
|
end
|
95
104
|
|
96
105
|
def initialize(environment)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Rasti
|
2
|
+
module DB
|
3
|
+
class ComputedAttribute
|
4
|
+
|
5
|
+
attr_reader :identifier
|
6
|
+
|
7
|
+
def initialize(identifier, &join)
|
8
|
+
@identifier = identifier
|
9
|
+
@join = join
|
10
|
+
end
|
11
|
+
|
12
|
+
def apply_join(dataset)
|
13
|
+
join ? join.call(dataset) : dataset
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :join
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Rasti
|
2
|
+
module DB
|
3
|
+
module NQL
|
4
|
+
module Nodes
|
5
|
+
class Attribute < Treetop::Runtime::SyntaxNode
|
6
|
+
|
7
|
+
def identifier(collection_class)
|
8
|
+
if computed? collection_class
|
9
|
+
collection_class.computed_attributes[column].identifier
|
10
|
+
else
|
11
|
+
tables.empty? ? Sequel[column] : Sequel[tables.join('__').to_sym][column]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def tables
|
16
|
+
_tables.elements.map{ |e| e.table.text_value }
|
17
|
+
end
|
18
|
+
|
19
|
+
def column
|
20
|
+
_column.text_value.to_sym
|
21
|
+
end
|
22
|
+
|
23
|
+
def computed_attributes(collection_class)
|
24
|
+
computed?(collection_class) ? [column] : []
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def computed?(collection_class)
|
30
|
+
collection_class.computed_attributes.key? column
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -8,6 +8,10 @@ module Rasti
|
|
8
8
|
values.flat_map(&:dependency_tables)
|
9
9
|
end
|
10
10
|
|
11
|
+
def computed_attributes(collection_class)
|
12
|
+
left.computed_attributes(collection_class) | right.computed_attributes(collection_class)
|
13
|
+
end
|
14
|
+
|
11
15
|
def values
|
12
16
|
@values ||= values_for(left) + values_for(right)
|
13
17
|
end
|
@@ -6,7 +6,11 @@ module Rasti
|
|
6
6
|
class Base < Treetop::Runtime::SyntaxNode
|
7
7
|
|
8
8
|
def dependency_tables
|
9
|
-
|
9
|
+
attribute.tables.empty? ? [] : [attribute.tables.join('.')]
|
10
|
+
end
|
11
|
+
|
12
|
+
def computed_attributes(collection_class)
|
13
|
+
attribute.computed_attributes(collection_class)
|
10
14
|
end
|
11
15
|
|
12
16
|
end
|
@@ -5,8 +5,8 @@ module Rasti
|
|
5
5
|
module Comparisons
|
6
6
|
class Include < Base
|
7
7
|
|
8
|
-
def filter_condition
|
9
|
-
Sequel.ilike(
|
8
|
+
def filter_condition(collection_class)
|
9
|
+
Sequel.ilike(attribute.identifier(collection_class), "%#{argument.value}%")
|
10
10
|
end
|
11
11
|
|
12
12
|
end
|
@@ -5,8 +5,8 @@ module Rasti
|
|
5
5
|
module Comparisons
|
6
6
|
class NotEqual < Base
|
7
7
|
|
8
|
-
def filter_condition
|
9
|
-
Sequel.negate(
|
8
|
+
def filter_condition(collection_class)
|
9
|
+
Sequel.negate(attribute.identifier(collection_class) => argument.value)
|
10
10
|
end
|
11
11
|
|
12
12
|
end
|
@@ -5,8 +5,8 @@ module Rasti
|
|
5
5
|
module Comparisons
|
6
6
|
class NotInclude < Base
|
7
7
|
|
8
|
-
def filter_condition
|
9
|
-
~ Sequel.ilike(
|
8
|
+
def filter_condition(collection_class)
|
9
|
+
~ Sequel.ilike(attribute.identifier(collection_class), "%#{argument.value}%")
|
10
10
|
end
|
11
11
|
|
12
12
|
end
|
@@ -4,8 +4,8 @@ module Rasti
|
|
4
4
|
module Nodes
|
5
5
|
class Conjunction < BinaryNode
|
6
6
|
|
7
|
-
def filter_condition
|
8
|
-
Sequel.&(*values.map(
|
7
|
+
def filter_condition(collection_class)
|
8
|
+
Sequel.&(*values.map { |value| value.filter_condition(collection_class) } )
|
9
9
|
end
|
10
10
|
|
11
11
|
end
|
@@ -4,8 +4,8 @@ module Rasti
|
|
4
4
|
module Nodes
|
5
5
|
class Disjunction < BinaryNode
|
6
6
|
|
7
|
-
def filter_condition
|
8
|
-
Sequel.|(*values.map(
|
7
|
+
def filter_condition(collection_class)
|
8
|
+
Sequel.|(*values.map { |value| value.filter_condition(collection_class) } )
|
9
9
|
end
|
10
10
|
|
11
11
|
end
|
@@ -8,8 +8,12 @@ module Rasti
|
|
8
8
|
sentence.dependency_tables
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
sentence.
|
11
|
+
def computed_attributes(collection_class)
|
12
|
+
sentence.computed_attributes(collection_class)
|
13
|
+
end
|
14
|
+
|
15
|
+
def filter_condition(collection_class)
|
16
|
+
sentence.filter_condition collection_class
|
13
17
|
end
|
14
18
|
|
15
19
|
end
|
@@ -8,8 +8,12 @@ module Rasti
|
|
8
8
|
proposition.dependency_tables
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
proposition.
|
11
|
+
def computed_attributes(collection_class)
|
12
|
+
proposition.computed_attributes collection_class
|
13
|
+
end
|
14
|
+
|
15
|
+
def filter_condition(collection_class)
|
16
|
+
proposition.filter_condition collection_class
|
13
17
|
end
|
14
18
|
|
15
19
|
end
|
data/lib/rasti/db/nql/syntax.rb
CHANGED
@@ -433,14 +433,14 @@ module Rasti
|
|
433
433
|
r0
|
434
434
|
end
|
435
435
|
|
436
|
-
module
|
436
|
+
module Attribute0
|
437
437
|
def table
|
438
438
|
elements[0]
|
439
439
|
end
|
440
440
|
|
441
441
|
end
|
442
442
|
|
443
|
-
module
|
443
|
+
module Attribute1
|
444
444
|
def _tables
|
445
445
|
elements[0]
|
446
446
|
end
|
@@ -450,10 +450,10 @@ module Rasti
|
|
450
450
|
end
|
451
451
|
end
|
452
452
|
|
453
|
-
def
|
453
|
+
def _nt_attribute
|
454
454
|
start_index = index
|
455
|
-
if node_cache[:
|
456
|
-
cached = node_cache[:
|
455
|
+
if node_cache[:attribute].has_key?(index)
|
456
|
+
cached = node_cache[:attribute][index]
|
457
457
|
if cached
|
458
458
|
cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
459
459
|
@index = cached.interval.end
|
@@ -465,7 +465,7 @@ module Rasti
|
|
465
465
|
s1, i1 = [], index
|
466
466
|
loop do
|
467
467
|
i2, s2 = index, []
|
468
|
-
r3 =
|
468
|
+
r3 = _nt_attribute_name
|
469
469
|
s2 << r3
|
470
470
|
if r3
|
471
471
|
if has_terminal?('.', false, index)
|
@@ -479,7 +479,7 @@ module Rasti
|
|
479
479
|
end
|
480
480
|
if s2.last
|
481
481
|
r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
|
482
|
-
r2.extend(
|
482
|
+
r2.extend(Attribute0)
|
483
483
|
else
|
484
484
|
@index = i2
|
485
485
|
r2 = nil
|
@@ -493,24 +493,24 @@ module Rasti
|
|
493
493
|
r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
|
494
494
|
s0 << r1
|
495
495
|
if r1
|
496
|
-
r5 =
|
496
|
+
r5 = _nt_attribute_name
|
497
497
|
s0 << r5
|
498
498
|
end
|
499
499
|
if s0.last
|
500
|
-
r0 = instantiate_node(Nodes::
|
501
|
-
r0.extend(
|
500
|
+
r0 = instantiate_node(Nodes::Attribute,input, i0...index, s0)
|
501
|
+
r0.extend(Attribute1)
|
502
502
|
else
|
503
503
|
@index = i0
|
504
504
|
r0 = nil
|
505
505
|
end
|
506
506
|
|
507
|
-
node_cache[:
|
507
|
+
node_cache[:attribute][start_index] = r0
|
508
508
|
|
509
509
|
r0
|
510
510
|
end
|
511
511
|
|
512
512
|
module ComparisonInclude0
|
513
|
-
def
|
513
|
+
def attribute
|
514
514
|
elements[0]
|
515
515
|
end
|
516
516
|
|
@@ -535,7 +535,7 @@ module Rasti
|
|
535
535
|
end
|
536
536
|
|
537
537
|
i0, s0 = index, []
|
538
|
-
r1 =
|
538
|
+
r1 = _nt_attribute
|
539
539
|
s0 << r1
|
540
540
|
if r1
|
541
541
|
s2, i2 = [], index
|
@@ -591,7 +591,7 @@ module Rasti
|
|
591
591
|
end
|
592
592
|
|
593
593
|
module ComparisonNotInclude0
|
594
|
-
def
|
594
|
+
def attribute
|
595
595
|
elements[0]
|
596
596
|
end
|
597
597
|
|
@@ -616,7 +616,7 @@ module Rasti
|
|
616
616
|
end
|
617
617
|
|
618
618
|
i0, s0 = index, []
|
619
|
-
r1 =
|
619
|
+
r1 = _nt_attribute
|
620
620
|
s0 << r1
|
621
621
|
if r1
|
622
622
|
s2, i2 = [], index
|
@@ -672,7 +672,7 @@ module Rasti
|
|
672
672
|
end
|
673
673
|
|
674
674
|
module ComparisonLike0
|
675
|
-
def
|
675
|
+
def attribute
|
676
676
|
elements[0]
|
677
677
|
end
|
678
678
|
|
@@ -697,7 +697,7 @@ module Rasti
|
|
697
697
|
end
|
698
698
|
|
699
699
|
i0, s0 = index, []
|
700
|
-
r1 =
|
700
|
+
r1 = _nt_attribute
|
701
701
|
s0 << r1
|
702
702
|
if r1
|
703
703
|
s2, i2 = [], index
|
@@ -753,7 +753,7 @@ module Rasti
|
|
753
753
|
end
|
754
754
|
|
755
755
|
module ComparisonGreaterThan0
|
756
|
-
def
|
756
|
+
def attribute
|
757
757
|
elements[0]
|
758
758
|
end
|
759
759
|
|
@@ -778,7 +778,7 @@ module Rasti
|
|
778
778
|
end
|
779
779
|
|
780
780
|
i0, s0 = index, []
|
781
|
-
r1 =
|
781
|
+
r1 = _nt_attribute
|
782
782
|
s0 << r1
|
783
783
|
if r1
|
784
784
|
s2, i2 = [], index
|
@@ -834,7 +834,7 @@ module Rasti
|
|
834
834
|
end
|
835
835
|
|
836
836
|
module ComparisonGreaterThanOrEqual0
|
837
|
-
def
|
837
|
+
def attribute
|
838
838
|
elements[0]
|
839
839
|
end
|
840
840
|
|
@@ -859,7 +859,7 @@ module Rasti
|
|
859
859
|
end
|
860
860
|
|
861
861
|
i0, s0 = index, []
|
862
|
-
r1 =
|
862
|
+
r1 = _nt_attribute
|
863
863
|
s0 << r1
|
864
864
|
if r1
|
865
865
|
s2, i2 = [], index
|
@@ -915,7 +915,7 @@ module Rasti
|
|
915
915
|
end
|
916
916
|
|
917
917
|
module ComparisonLessThan0
|
918
|
-
def
|
918
|
+
def attribute
|
919
919
|
elements[0]
|
920
920
|
end
|
921
921
|
|
@@ -940,7 +940,7 @@ module Rasti
|
|
940
940
|
end
|
941
941
|
|
942
942
|
i0, s0 = index, []
|
943
|
-
r1 =
|
943
|
+
r1 = _nt_attribute
|
944
944
|
s0 << r1
|
945
945
|
if r1
|
946
946
|
s2, i2 = [], index
|
@@ -996,7 +996,7 @@ module Rasti
|
|
996
996
|
end
|
997
997
|
|
998
998
|
module ComparisonLessThanOrEqual0
|
999
|
-
def
|
999
|
+
def attribute
|
1000
1000
|
elements[0]
|
1001
1001
|
end
|
1002
1002
|
|
@@ -1021,7 +1021,7 @@ module Rasti
|
|
1021
1021
|
end
|
1022
1022
|
|
1023
1023
|
i0, s0 = index, []
|
1024
|
-
r1 =
|
1024
|
+
r1 = _nt_attribute
|
1025
1025
|
s0 << r1
|
1026
1026
|
if r1
|
1027
1027
|
s2, i2 = [], index
|
@@ -1077,7 +1077,7 @@ module Rasti
|
|
1077
1077
|
end
|
1078
1078
|
|
1079
1079
|
module ComparisonNotEqual0
|
1080
|
-
def
|
1080
|
+
def attribute
|
1081
1081
|
elements[0]
|
1082
1082
|
end
|
1083
1083
|
|
@@ -1102,7 +1102,7 @@ module Rasti
|
|
1102
1102
|
end
|
1103
1103
|
|
1104
1104
|
i0, s0 = index, []
|
1105
|
-
r1 =
|
1105
|
+
r1 = _nt_attribute
|
1106
1106
|
s0 << r1
|
1107
1107
|
if r1
|
1108
1108
|
s2, i2 = [], index
|
@@ -1158,7 +1158,7 @@ module Rasti
|
|
1158
1158
|
end
|
1159
1159
|
|
1160
1160
|
module ComparisonEqual0
|
1161
|
-
def
|
1161
|
+
def attribute
|
1162
1162
|
elements[0]
|
1163
1163
|
end
|
1164
1164
|
|
@@ -1183,7 +1183,7 @@ module Rasti
|
|
1183
1183
|
end
|
1184
1184
|
|
1185
1185
|
i0, s0 = index, []
|
1186
|
-
r1 =
|
1186
|
+
r1 = _nt_attribute
|
1187
1187
|
s0 << r1
|
1188
1188
|
if r1
|
1189
1189
|
s2, i2 = [], index
|
@@ -1311,10 +1311,10 @@ module Rasti
|
|
1311
1311
|
r0
|
1312
1312
|
end
|
1313
1313
|
|
1314
|
-
def
|
1314
|
+
def _nt_attribute_name
|
1315
1315
|
start_index = index
|
1316
|
-
if node_cache[:
|
1317
|
-
cached = node_cache[:
|
1316
|
+
if node_cache[:attribute_name].has_key?(index)
|
1317
|
+
cached = node_cache[:attribute_name][index]
|
1318
1318
|
if cached
|
1319
1319
|
cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
1320
1320
|
@index = cached.interval.end
|
@@ -1343,7 +1343,7 @@ module Rasti
|
|
1343
1343
|
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
1344
1344
|
end
|
1345
1345
|
|
1346
|
-
node_cache[:
|
1346
|
+
node_cache[:attribute_name][start_index] = r0
|
1347
1347
|
|
1348
1348
|
r0
|
1349
1349
|
end
|