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
@@ -42,44 +42,44 @@ module Rasti
|
|
42
42
|
comparison_equal
|
43
43
|
end
|
44
44
|
|
45
|
-
rule
|
46
|
-
_tables:(table:
|
45
|
+
rule attribute
|
46
|
+
_tables:(table:attribute_name '.')* _column:attribute_name <Nodes::Attribute>
|
47
47
|
end
|
48
48
|
|
49
49
|
rule comparison_include
|
50
|
-
|
50
|
+
attribute:attribute space* comparator:':' space* argument:basic <Nodes::Comparisons::Include>
|
51
51
|
end
|
52
52
|
|
53
53
|
rule comparison_not_include
|
54
|
-
|
54
|
+
attribute:attribute space* comparator:'!:' space* argument:basic <Nodes::Comparisons::NotInclude>
|
55
55
|
end
|
56
56
|
|
57
57
|
rule comparison_like
|
58
|
-
|
58
|
+
attribute:attribute space* comparator:'~' space* argument:basic <Nodes::Comparisons::Like>
|
59
59
|
end
|
60
60
|
|
61
61
|
rule comparison_greater_than
|
62
|
-
|
62
|
+
attribute:attribute space* comparator:'>' space* argument:basic <Nodes::Comparisons::GreaterThan>
|
63
63
|
end
|
64
64
|
|
65
65
|
rule comparison_greater_than_or_equal
|
66
|
-
|
66
|
+
attribute:attribute space* comparator:'>=' space* argument:basic <Nodes::Comparisons::GreaterThanOrEqual>
|
67
67
|
end
|
68
68
|
|
69
69
|
rule comparison_less_than
|
70
|
-
|
70
|
+
attribute:attribute space* comparator:'<' space* argument:basic <Nodes::Comparisons::LessThan>
|
71
71
|
end
|
72
72
|
|
73
73
|
rule comparison_less_than_or_equal
|
74
|
-
|
74
|
+
attribute:attribute space* comparator:'<=' space* argument:basic <Nodes::Comparisons::LessThanOrEqual>
|
75
75
|
end
|
76
76
|
|
77
77
|
rule comparison_not_equal
|
78
|
-
|
78
|
+
attribute:attribute space* comparator:'!=' space* argument:basic <Nodes::Comparisons::NotEqual>
|
79
79
|
end
|
80
80
|
|
81
81
|
rule comparison_equal
|
82
|
-
|
82
|
+
attribute:attribute space* comparator:'=' space* argument:basic <Nodes::Comparisons::Equal>
|
83
83
|
end
|
84
84
|
|
85
85
|
rule basic
|
@@ -95,7 +95,7 @@ module Rasti
|
|
95
95
|
[\s\t\n]
|
96
96
|
end
|
97
97
|
|
98
|
-
rule
|
98
|
+
rule attribute_name
|
99
99
|
[a-z_]+
|
100
100
|
end
|
101
101
|
|
data/lib/rasti/db/query.rb
CHANGED
@@ -57,6 +57,12 @@ module Rasti
|
|
57
57
|
build_query relations_graph: relations_graph.with_all_attributes_for(relations)
|
58
58
|
end
|
59
59
|
|
60
|
+
def append_computed_attribute(name)
|
61
|
+
computed_attribute = collection_class.computed_attributes[name]
|
62
|
+
ds = computed_attribute.apply_join(dataset).select_append(computed_attribute.identifier.as(name))
|
63
|
+
build_query dataset: ds
|
64
|
+
end
|
65
|
+
|
60
66
|
def all
|
61
67
|
with_graph(dataset.all).map do |row|
|
62
68
|
collection_class.model.new row
|
@@ -64,8 +70,19 @@ module Rasti
|
|
64
70
|
end
|
65
71
|
alias_method :to_a, :all
|
66
72
|
|
67
|
-
def each(&block)
|
68
|
-
|
73
|
+
def each(batch_size:nil, &block)
|
74
|
+
if batch_size.nil?
|
75
|
+
all.each(&block)
|
76
|
+
else
|
77
|
+
each_model_in_batches(size: batch_size, &block)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def each_batch(size:, &block)
|
82
|
+
dataset.each_page(size) do |page|
|
83
|
+
query = build_query dataset: page
|
84
|
+
block.call query.all
|
85
|
+
end
|
69
86
|
end
|
70
87
|
|
71
88
|
def graph(*relations)
|
@@ -94,12 +111,12 @@ module Rasti
|
|
94
111
|
|
95
112
|
def first
|
96
113
|
row = dataset.first
|
97
|
-
row ?
|
114
|
+
row ? build_model(row) : nil
|
98
115
|
end
|
99
116
|
|
100
117
|
def last
|
101
118
|
row = dataset.last
|
102
|
-
row ?
|
119
|
+
row ? build_model(row) : nil
|
103
120
|
end
|
104
121
|
|
105
122
|
def detect(*args, &block)
|
@@ -116,10 +133,15 @@ module Rasti
|
|
116
133
|
|
117
134
|
raise NQL::InvalidExpressionError.new(filter_expression) if sentence.nil?
|
118
135
|
|
136
|
+
ds = sentence.computed_attributes(collection_class).inject(dataset) do |ds, name|
|
137
|
+
collection_class.computed_attributes[name].apply_join ds
|
138
|
+
end
|
139
|
+
query = build_query dataset: ds
|
140
|
+
|
119
141
|
dependency_tables = sentence.dependency_tables
|
120
|
-
query =
|
121
|
-
|
122
|
-
query.where sentence.filter_condition
|
142
|
+
query = query.join(*dependency_tables) unless dependency_tables.empty?
|
143
|
+
|
144
|
+
query.where sentence.filter_condition(collection_class)
|
123
145
|
end
|
124
146
|
|
125
147
|
private
|
@@ -137,10 +159,22 @@ module Rasti
|
|
137
159
|
Query.new(**current_args.merge(args))
|
138
160
|
end
|
139
161
|
|
162
|
+
def build_model(row)
|
163
|
+
collection_class.model.new with_graph(row)
|
164
|
+
end
|
165
|
+
|
140
166
|
def chainable(&block)
|
141
167
|
build_query dataset: instance_eval(&block)
|
142
168
|
end
|
143
169
|
|
170
|
+
def each_model_in_batches(size:, &block)
|
171
|
+
dataset.each_page(size) do |page|
|
172
|
+
page.each do |row|
|
173
|
+
block.call build_model(row)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
144
178
|
def with_related(relation_name, primary_keys)
|
145
179
|
ds = collection_class.relations[relation_name].apply_filter environment, dataset, primary_keys
|
146
180
|
build_query dataset: ds
|
data/lib/rasti/db/version.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe 'ComputedAttribute' do
|
4
|
+
|
5
|
+
it 'Apply Join wiht join attribute must generate correct query' do
|
6
|
+
dataset = db[:users]
|
7
|
+
computed_attribute = Rasti::DB::ComputedAttribute.new(Sequel[:comments_count][:value]) do |dataset|
|
8
|
+
subquery = dataset.db.from(:comments)
|
9
|
+
.select(Sequel[:user_id], Sequel.function('count', :id).as(:value))
|
10
|
+
.group(:user_id)
|
11
|
+
.as(:comments_count)
|
12
|
+
|
13
|
+
dataset.join_table(:inner, subquery, :user_id => :id)
|
14
|
+
end
|
15
|
+
expected_query = "SELECT *, `comments_count`.`value` AS 'value' FROM `users` INNER JOIN (SELECT `user_id`, count(`id`) AS 'value' FROM `comments` GROUP BY `user_id`) AS 'comments_count' ON (`comments_count`.`user_id` = `users`.`id`)"
|
16
|
+
computed_attribute.apply_join(dataset)
|
17
|
+
.select_append(computed_attribute.identifier)
|
18
|
+
.sql
|
19
|
+
.must_equal expected_query
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'Apply join without join attribute must generate correct query' do
|
23
|
+
dataset = db[:people]
|
24
|
+
computed_attribute = Rasti::DB::ComputedAttribute.new Sequel.join([:first_name, ' ', :last_name])
|
25
|
+
expected_query = "SELECT * FROM `people` WHERE ((`first_name` || ' ' || `last_name`) = 'FULL NAME')"
|
26
|
+
computed_attribute.apply_join(dataset)
|
27
|
+
.where(computed_attribute.identifier => 'FULL NAME')
|
28
|
+
.sql
|
29
|
+
.must_equal expected_query
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/spec/minitest_helper.rb
CHANGED
@@ -13,11 +13,11 @@ Rasti::DB.configure do |config|
|
|
13
13
|
config.type_converters = [Rasti::DB::TypeConverters::TimeInZone]
|
14
14
|
end
|
15
15
|
|
16
|
-
User = Rasti::DB::Model[:id, :name, :posts, :comments, :person]
|
17
|
-
Post = Rasti::DB::Model[:id, :title, :body, :user_id, :user, :comments, :categories, :language_id, :language]
|
16
|
+
User = Rasti::DB::Model[:id, :name, :posts, :comments, :person, :comments_count]
|
17
|
+
Post = Rasti::DB::Model[:id, :title, :body, :user_id, :user, :comments, :categories, :language_id, :language, :notice, :author]
|
18
18
|
Comment = Rasti::DB::Model[:id, :text, :user_id, :user, :post_id, :post]
|
19
19
|
Category = Rasti::DB::Model[:id, :name, :posts]
|
20
|
-
Person = Rasti::DB::Model[:document_number, :first_name, :last_name, :birth_date, :user_id, :user, :languages]
|
20
|
+
Person = Rasti::DB::Model[:document_number, :first_name, :last_name, :birth_date, :user_id, :user, :languages, :full_name]
|
21
21
|
Language = Rasti::DB::Model[:id, :name, :people]
|
22
22
|
|
23
23
|
|
@@ -25,6 +25,18 @@ class Users < Rasti::DB::Collection
|
|
25
25
|
one_to_many :posts
|
26
26
|
one_to_many :comments
|
27
27
|
one_to_one :person
|
28
|
+
|
29
|
+
computed_attribute :comments_count do
|
30
|
+
Rasti::DB::ComputedAttribute.new(Sequel[:comments_count][:value]) do |dataset|
|
31
|
+
subquery = dataset.db.from(:comments)
|
32
|
+
.select(Sequel[:user_id], Sequel.function('count', :id).as(:value))
|
33
|
+
.group(:user_id)
|
34
|
+
.as(:comments_count)
|
35
|
+
|
36
|
+
dataset.join_table(:inner, subquery, :user_id => :id)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
28
40
|
end
|
29
41
|
|
30
42
|
class Posts < Rasti::DB::Collection
|
@@ -47,6 +59,15 @@ class Posts < Rasti::DB::Collection
|
|
47
59
|
.distinct
|
48
60
|
end
|
49
61
|
end
|
62
|
+
|
63
|
+
computed_attribute :notice do
|
64
|
+
Rasti::DB::ComputedAttribute.new Sequel.join([:title, ': ', :body])
|
65
|
+
end
|
66
|
+
|
67
|
+
computed_attribute :author do
|
68
|
+
Rasti::DB::ComputedAttribute.new Sequel[:user]
|
69
|
+
end
|
70
|
+
|
50
71
|
end
|
51
72
|
|
52
73
|
class Comments < Rasti::DB::Collection
|
@@ -73,6 +94,10 @@ class People < Rasti::DB::Collection
|
|
73
94
|
|
74
95
|
many_to_one :user
|
75
96
|
many_to_many :languages
|
97
|
+
|
98
|
+
computed_attribute :full_name do |db|
|
99
|
+
Rasti::DB::ComputedAttribute.new Sequel.join([:first_name, ' ', :last_name])
|
100
|
+
end
|
76
101
|
end
|
77
102
|
|
78
103
|
class Languages < Rasti::DB::Collection
|
@@ -107,6 +132,8 @@ class Minitest::Spec
|
|
107
132
|
let :db do
|
108
133
|
Sequel.connect(driver).tap do |db|
|
109
134
|
|
135
|
+
db.extension :pagination
|
136
|
+
|
110
137
|
db.create_table :users do
|
111
138
|
primary_key :id
|
112
139
|
String :name, null: false, unique: true
|
data/spec/model_spec.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe 'NQL::ComputedAttributes' do
|
4
|
+
|
5
|
+
let(:parser) { Rasti::DB::NQL::SyntaxParser.new }
|
6
|
+
|
7
|
+
def parse(expression)
|
8
|
+
parser.parse expression
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'must have one computed attributes' do
|
12
|
+
tree = parse 'notice = any notice'
|
13
|
+
|
14
|
+
tree.computed_attributes(Posts).must_equal [:notice]
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'must have multiple computed attributes' do
|
18
|
+
tree = parse 'notice = any notice & (author: anonym | title = good morning)'
|
19
|
+
|
20
|
+
tree.computed_attributes(Posts).must_equal [:notice, :author]
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'must have not repeated computed attributes when expression have it' do
|
24
|
+
tree = parse 'notice = Hi | notice = Bye'
|
25
|
+
|
26
|
+
tree.computed_attributes(Posts).must_equal [:notice]
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -4,9 +4,11 @@ describe 'NQL::FilterCondition' do
|
|
4
4
|
|
5
5
|
let(:parser) { Rasti::DB::NQL::SyntaxParser.new }
|
6
6
|
|
7
|
+
let(:collection_class) { Rasti::DB::Collection }
|
8
|
+
|
7
9
|
def filter_condition(expression)
|
8
10
|
tree = parser.parse expression
|
9
|
-
tree.filter_condition
|
11
|
+
tree.filter_condition(collection_class)
|
10
12
|
end
|
11
13
|
|
12
14
|
def assert_identifier(identifier, expected_value)
|
@@ -95,7 +97,7 @@ describe 'NQL::FilterCondition' do
|
|
95
97
|
|
96
98
|
end
|
97
99
|
|
98
|
-
it 'must create filter from expression with
|
100
|
+
it 'must create filter from expression with attribute with multiple tables' do
|
99
101
|
filter = filter_condition 'table_one.table_two.column = test'
|
100
102
|
identifier, value = filter.first
|
101
103
|
|
@@ -31,7 +31,7 @@ describe 'NQL::SyntaxParser' do
|
|
31
31
|
proposition = tree.proposition
|
32
32
|
proposition.must_be_instance_of node_class
|
33
33
|
proposition.comparator.text_value.must_equal comparator
|
34
|
-
proposition.
|
34
|
+
proposition.attribute.text_value.must_equal 'column'
|
35
35
|
proposition.argument.text_value.must_equal 'value'
|
36
36
|
end
|
37
37
|
end
|
@@ -44,7 +44,7 @@ describe 'NQL::SyntaxParser' do
|
|
44
44
|
proposition = tree.proposition
|
45
45
|
proposition.must_be_instance_of Rasti::DB::NQL::Nodes::Comparisons::Equal
|
46
46
|
proposition.comparator.text_value.must_equal '='
|
47
|
-
proposition.
|
47
|
+
proposition.attribute.text_value.must_equal 'column'
|
48
48
|
proposition.argument.text_value.must_equal 'value'
|
49
49
|
end
|
50
50
|
|
@@ -128,12 +128,19 @@ describe 'NQL::SyntaxParser' do
|
|
128
128
|
|
129
129
|
end
|
130
130
|
|
131
|
-
it 'must parse expression with
|
131
|
+
it 'must parse expression with attribute with tables' do
|
132
132
|
tree = parse 'relation_table_one.relation_table_two.column = 1'
|
133
133
|
|
134
|
-
left_hand_operand = tree.proposition.
|
134
|
+
left_hand_operand = tree.proposition.attribute
|
135
135
|
left_hand_operand.tables.must_equal ['relation_table_one', 'relation_table_two']
|
136
|
-
left_hand_operand.column.must_equal
|
136
|
+
left_hand_operand.column.must_equal :column
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'must parse expression with computed attribute' do
|
140
|
+
tree = parse 'comments_count = 1'
|
141
|
+
computed = tree.proposition.attribute
|
142
|
+
computed.tables.must_equal []
|
143
|
+
computed.computed_attributes(Users).must_equal [:comments_count]
|
137
144
|
end
|
138
145
|
|
139
146
|
end
|
data/spec/query_spec.rb
CHANGED
@@ -5,13 +5,13 @@ describe 'Query' do
|
|
5
5
|
before do
|
6
6
|
custom_db[:languages].insert name: 'Spanish'
|
7
7
|
|
8
|
-
1.upto(10) do |i|
|
8
|
+
1.upto(10) do |i|
|
9
9
|
db[:users].insert name: "User #{i}"
|
10
10
|
|
11
|
-
db[:people].insert user_id: i,
|
12
|
-
document_number: "document_#{i}",
|
13
|
-
first_name: "Name #{i}",
|
14
|
-
last_name: "Last Name #{i}",
|
11
|
+
db[:people].insert user_id: i,
|
12
|
+
document_number: "document_#{i}",
|
13
|
+
first_name: "Name #{i}",
|
14
|
+
last_name: "Last Name #{i}",
|
15
15
|
birth_date: Date.parse('2020-04-24')
|
16
16
|
|
17
17
|
db[:languages_people].insert language_id: 1, document_number: "document_#{i}"
|
@@ -22,7 +22,7 @@ describe 'Query' do
|
|
22
22
|
db[:posts].insert user_id: 4, title: 'Best post', body: '...', language_id: 1
|
23
23
|
|
24
24
|
1.upto(3) { |i| db[:categories].insert name: "Category #{i}" }
|
25
|
-
|
25
|
+
|
26
26
|
db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 1'
|
27
27
|
db[:comments].insert post_id: 1, user_id: 7, text: 'Comment 2'
|
28
28
|
db[:comments].insert post_id: 2, user_id: 2, text: 'Comment 3'
|
@@ -35,11 +35,13 @@ describe 'Query' do
|
|
35
35
|
end
|
36
36
|
|
37
37
|
let(:users_query) { Rasti::DB::Query.new collection_class: Users, dataset: db[:users], environment: environment }
|
38
|
-
|
38
|
+
|
39
39
|
let(:posts_query) { Rasti::DB::Query.new collection_class: Posts, dataset: db[:posts], environment: environment }
|
40
|
-
|
40
|
+
|
41
41
|
let(:comments_query) { Rasti::DB::Query.new collection_class: Comments, dataset: db[:comments], environment: environment }
|
42
42
|
|
43
|
+
let(:people_query) { Rasti::DB::Query.new collection_class: People, dataset: db[:people], environment: environment }
|
44
|
+
|
43
45
|
let(:languages_query) { Rasti::DB::Query.new collection_class: Languages, dataset: custom_db[:languages], environment: environment }
|
44
46
|
|
45
47
|
it 'Count' do
|
@@ -87,8 +89,8 @@ describe 'Query' do
|
|
87
89
|
post = Post.new db[:posts].where(id: 1).first.merge(user: user, categories: categories)
|
88
90
|
|
89
91
|
selected_attributes = {
|
90
|
-
user: [:id],
|
91
|
-
'user.person' => [:document_number, :user_id],
|
92
|
+
user: [:id],
|
93
|
+
'user.person' => [:document_number, :user_id],
|
92
94
|
'user.person.languages' => [:id],
|
93
95
|
categories: [:id]
|
94
96
|
}
|
@@ -99,7 +101,7 @@ describe 'Query' do
|
|
99
101
|
.all
|
100
102
|
.must_equal [post]
|
101
103
|
end
|
102
|
-
|
104
|
+
|
103
105
|
it 'Exclude graph attributes' do
|
104
106
|
language = Language.new custom_db[:languages].where(id: 1).select(:id).first
|
105
107
|
|
@@ -112,8 +114,8 @@ describe 'Query' do
|
|
112
114
|
post = Post.new db[:posts].where(id: 1).first.merge(user: user, categories: categories)
|
113
115
|
|
114
116
|
excluded_attributes = {
|
115
|
-
user: [:name],
|
116
|
-
'user.person' => [:first_name, :last_name, :birth_date],
|
117
|
+
user: [:name],
|
118
|
+
'user.person' => [:first_name, :last_name, :birth_date],
|
117
119
|
'user.person.languages' => [:name],
|
118
120
|
categories: [:name]
|
119
121
|
}
|
@@ -124,7 +126,7 @@ describe 'Query' do
|
|
124
126
|
.all
|
125
127
|
.must_equal [post]
|
126
128
|
end
|
127
|
-
|
129
|
+
|
128
130
|
it 'All graph attributes' do
|
129
131
|
person = Person.new db[:people].where(document_number: 'document_2').first
|
130
132
|
|
@@ -140,6 +142,30 @@ describe 'Query' do
|
|
140
142
|
.must_equal [post]
|
141
143
|
end
|
142
144
|
|
145
|
+
describe 'Append computed attribute' do
|
146
|
+
it 'With join' do
|
147
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 4'
|
148
|
+
users_query.append_computed_attribute(:comments_count)
|
149
|
+
.where(id: 5)
|
150
|
+
.all
|
151
|
+
.must_equal [User.new(id: 5, name: 'User 5', comments_count: 2)]
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'Without join' do
|
155
|
+
person_expected = Person.new user_id: 1,
|
156
|
+
document_number: 'document_1',
|
157
|
+
first_name: 'Name 1',
|
158
|
+
last_name: 'Last Name 1',
|
159
|
+
birth_date: Date.parse('2020-04-24'),
|
160
|
+
full_name: 'Name 1 Last Name 1'
|
161
|
+
|
162
|
+
people_query.append_computed_attribute(:full_name)
|
163
|
+
.where(document_number: 'document_1')
|
164
|
+
.all
|
165
|
+
.must_equal [person_expected]
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
143
169
|
it 'Map' do
|
144
170
|
users_query.map(&:name).must_equal db[:users].map(:name)
|
145
171
|
end
|
@@ -148,45 +174,88 @@ describe 'Query' do
|
|
148
174
|
users_query.detect(id: 3).must_equal User.new(id: 3, name: 'User 3')
|
149
175
|
end
|
150
176
|
|
177
|
+
describe 'Each' do
|
178
|
+
|
179
|
+
it 'without size' do
|
180
|
+
users = []
|
181
|
+
|
182
|
+
users_query.each do |user|
|
183
|
+
users << user
|
184
|
+
end
|
185
|
+
|
186
|
+
users.size.must_equal 10
|
187
|
+
users.each_with_index do |user, i|
|
188
|
+
user.must_equal User.new(id: i+1, name: "User #{i+1}")
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'with size' do
|
193
|
+
users = []
|
194
|
+
users_query.each(batch_size: 2) do |user|
|
195
|
+
users << user
|
196
|
+
end
|
197
|
+
|
198
|
+
users.size.must_equal 10
|
199
|
+
users.each_with_index do |user, i|
|
200
|
+
user.must_equal User.new(id: i+1, name: "User #{i+1}")
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'Each batch' do
|
207
|
+
users_batch = []
|
208
|
+
users_query.each_batch(size: 2) do |page|
|
209
|
+
users_batch << page
|
210
|
+
end
|
211
|
+
|
212
|
+
users_batch.size.must_equal 5
|
213
|
+
i = 1
|
214
|
+
users_batch.each do |user_page|
|
215
|
+
user_page.must_equal [User.new(id: i, name: "User #{i}"), User.new(id: i+1, name: "User #{i+1}")]
|
216
|
+
i += 2
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
151
220
|
it 'Where' do
|
152
221
|
users_query.where(id: 3).all.must_equal [User.new(id: 3, name: 'User 3')]
|
153
222
|
end
|
154
|
-
|
223
|
+
|
155
224
|
it 'Exclude' do
|
156
225
|
users_query.exclude(id: [1,2,3,4,5,6,7,8,9]).all.must_equal [User.new(id: 10, name: 'User 10')]
|
157
226
|
end
|
158
|
-
|
227
|
+
|
159
228
|
it 'And' do
|
160
229
|
users_query.where(id: [1,2]).where(name: 'User 2').all.must_equal [User.new(id: 2, name: 'User 2')]
|
161
230
|
end
|
162
|
-
|
231
|
+
|
163
232
|
it 'Or' do
|
164
233
|
users_query.where(id: 1).or(name: 'User 2').all.must_equal [
|
165
|
-
User.new(id: 1, name: 'User 1'),
|
234
|
+
User.new(id: 1, name: 'User 1'),
|
166
235
|
User.new(id: 2, name: 'User 2')
|
167
236
|
]
|
168
237
|
end
|
169
|
-
|
238
|
+
|
170
239
|
it 'Order' do
|
171
240
|
posts_query.order(:title).all.must_equal [
|
172
|
-
Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1),
|
173
|
-
Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
|
241
|
+
Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1),
|
242
|
+
Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
|
174
243
|
Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...', language_id: 1)
|
175
244
|
]
|
176
245
|
end
|
177
|
-
|
246
|
+
|
178
247
|
it 'Reverse order' do
|
179
248
|
posts_query.reverse_order(:title).all.must_equal [
|
180
249
|
Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...', language_id: 1),
|
181
|
-
Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
|
250
|
+
Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
|
182
251
|
Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1)
|
183
252
|
]
|
184
253
|
end
|
185
|
-
|
254
|
+
|
186
255
|
it 'Limit and offset' do
|
187
256
|
users_query.limit(1).offset(1).all.must_equal [User.new(id: 2, name: 'User 2')]
|
188
257
|
end
|
189
|
-
|
258
|
+
|
190
259
|
it 'First' do
|
191
260
|
users_query.first.must_equal User.new(id: 1, name: 'User 1')
|
192
261
|
end
|
@@ -203,21 +272,21 @@ describe 'Query' do
|
|
203
272
|
language = Language.new id: 1, name: 'Spanish'
|
204
273
|
|
205
274
|
person = Person.new user_id: 2,
|
206
|
-
document_number: 'document_2',
|
207
|
-
first_name: 'Name 2',
|
208
|
-
last_name: 'Last Name 2',
|
275
|
+
document_number: 'document_2',
|
276
|
+
first_name: 'Name 2',
|
277
|
+
last_name: 'Last Name 2',
|
209
278
|
birth_date: Date.parse('2020-04-24'),
|
210
279
|
languages: [language]
|
211
280
|
|
212
|
-
user = User.new id: 2,
|
281
|
+
user = User.new id: 2,
|
213
282
|
name: 'User 2',
|
214
283
|
person: person
|
215
284
|
|
216
|
-
post = Post.new id: 1,
|
217
|
-
user_id: 2,
|
285
|
+
post = Post.new id: 1,
|
286
|
+
user_id: 2,
|
218
287
|
user: user,
|
219
|
-
title: 'Sample post',
|
220
|
-
body: '...',
|
288
|
+
title: 'Sample post',
|
289
|
+
body: '...',
|
221
290
|
language_id: 1,
|
222
291
|
language: language
|
223
292
|
|
@@ -323,7 +392,7 @@ describe 'Query' do
|
|
323
392
|
error = proc { posts_query.nql('a + b') }.must_raise Rasti::DB::NQL::InvalidExpressionError
|
324
393
|
error.message.must_equal 'Invalid filter expression: a + b'
|
325
394
|
end
|
326
|
-
|
395
|
+
|
327
396
|
it 'Filter to self table' do
|
328
397
|
posts_query.nql('user_id > 1')
|
329
398
|
.pluck(:user_id)
|
@@ -350,6 +419,49 @@ describe 'Query' do
|
|
350
419
|
.must_equal [2]
|
351
420
|
end
|
352
421
|
|
422
|
+
describe 'Computed Attributes' do
|
423
|
+
|
424
|
+
it 'Filter relation computed attribute' do
|
425
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 4'
|
426
|
+
users_query.nql('comments_count = 2').all.must_equal [User.new(id: 5, name: 'User 5')]
|
427
|
+
end
|
428
|
+
|
429
|
+
it 'Filter with relation computed attribute with "and" combined' do
|
430
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 4'
|
431
|
+
db[:comments].insert post_id: 1, user_id: 4, text: 'Comment 3'
|
432
|
+
users_query.nql('(comments_count > 1) & (id = 5)').all.must_equal [User.new(id: 5, name: 'User 5')]
|
433
|
+
end
|
434
|
+
|
435
|
+
it 'Filter relation computed attribute with "or" combined' do
|
436
|
+
db[:comments].insert post_id: 1, user_id: 2, text: 'Comment 3'
|
437
|
+
users_query.nql('(comments_count = 2) | (id = 5)')
|
438
|
+
.order(:id)
|
439
|
+
.all
|
440
|
+
.must_equal [ User.new(id: 2, name: 'User 2'), User.new(id: 5, name: 'User 5') ]
|
441
|
+
end
|
442
|
+
|
443
|
+
it 'Filter relation computed attribute with "and" and "or" combined' do
|
444
|
+
db[:comments].insert post_id: 1, user_id: 2, text: 'Comment 3'
|
445
|
+
users_query.nql('((comments_count = 2) | (id = 5)) & (name: User 5)')
|
446
|
+
.order(:id)
|
447
|
+
.all
|
448
|
+
.must_equal [ User.new(id: 5, name: 'User 5') ]
|
449
|
+
end
|
450
|
+
|
451
|
+
it 'Filter simple computed attribute' do
|
452
|
+
person_expected = Person.new user_id: 1,
|
453
|
+
document_number: 'document_1',
|
454
|
+
first_name: 'Name 1',
|
455
|
+
last_name: 'Last Name 1',
|
456
|
+
birth_date: Date.parse('2020-04-24')
|
457
|
+
|
458
|
+
people_query.nql('full_name = Name 1 Last Name 1')
|
459
|
+
.all
|
460
|
+
.must_equal [person_expected]
|
461
|
+
end
|
462
|
+
|
463
|
+
end
|
464
|
+
|
353
465
|
end
|
354
466
|
|
355
467
|
end
|