rasti-db 2.0.0 → 2.3.1
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.rb +11 -1
- data/lib/rasti/db/collection.rb +10 -1
- data/lib/rasti/db/computed_attribute.rb +22 -0
- data/lib/rasti/db/nql/filter_condition_strategies/base.rb +17 -0
- data/lib/rasti/db/nql/filter_condition_strategies/postgres.rb +21 -0
- data/lib/rasti/db/nql/filter_condition_strategies/sqlite.rb +21 -0
- data/lib/rasti/db/nql/filter_condition_strategies/types/generic.rb +49 -0
- data/lib/rasti/db/nql/filter_condition_strategies/types/pg_array.rb +32 -0
- data/lib/rasti/db/nql/filter_condition_strategies/types/sqlite_array.rb +34 -0
- data/lib/rasti/db/nql/filter_condition_strategies/unsupported_type_comparison.rb +22 -0
- data/lib/rasti/db/nql/nodes/array_content.rb +21 -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 +15 -1
- data/lib/rasti/db/nql/nodes/comparisons/equal.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/greater_than.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/greater_than_or_equal.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/include.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/less_than.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/less_than_or_equal.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/like.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/not_equal.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/not_include.rb +0 -4
- data/lib/rasti/db/nql/nodes/conjunction.rb +2 -2
- data/lib/rasti/db/nql/nodes/constants/array.rb +17 -0
- data/lib/rasti/db/nql/nodes/constants/base.rb +17 -0
- data/lib/rasti/db/nql/nodes/constants/false.rb +1 -1
- data/lib/rasti/db/nql/nodes/constants/float.rb +1 -1
- data/lib/rasti/db/nql/nodes/constants/integer.rb +1 -1
- data/lib/rasti/db/nql/nodes/constants/literal_string.rb +1 -1
- data/lib/rasti/db/nql/nodes/constants/string.rb +1 -1
- data/lib/rasti/db/nql/nodes/constants/time.rb +1 -1
- data/lib/rasti/db/nql/nodes/constants/true.rb +1 -1
- 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 +262 -44
- data/lib/rasti/db/nql/syntax.treetop +27 -14
- data/lib/rasti/db/query.rb +42 -14
- data/lib/rasti/db/type_converters/postgres.rb +32 -36
- data/lib/rasti/db/type_converters/postgres_types/array.rb +11 -9
- data/lib/rasti/db/type_converters/postgres_types/hstore.rb +10 -9
- data/lib/rasti/db/type_converters/postgres_types/json.rb +17 -14
- data/lib/rasti/db/type_converters/postgres_types/jsonb.rb +17 -14
- data/lib/rasti/db/type_converters/sqlite.rb +62 -0
- data/lib/rasti/db/type_converters/sqlite_types/array.rb +34 -0
- data/lib/rasti/db/version.rb +1 -1
- data/rasti-db.gemspec +1 -0
- data/spec/collection_spec.rb +19 -11
- data/spec/computed_attribute_spec.rb +32 -0
- data/spec/minitest_helper.rb +32 -5
- data/spec/model_spec.rb +1 -1
- data/spec/nql/computed_attributes_spec.rb +29 -0
- data/spec/nql/filter_condition_spec.rb +23 -4
- data/spec/nql/filter_condition_strategies_spec.rb +112 -0
- data/spec/nql/syntax_parser_spec.rb +36 -5
- data/spec/query_spec.rb +254 -39
- data/spec/type_converters/sqlite_spec.rb +66 -0
- metadata +38 -3
- data/lib/rasti/db/nql/nodes/field.rb +0 -23
@@ -0,0 +1,62 @@
|
|
1
|
+
module Rasti
|
2
|
+
module DB
|
3
|
+
module TypeConverters
|
4
|
+
class SQLite
|
5
|
+
|
6
|
+
CONVERTERS = [SQLiteTypes::Array]
|
7
|
+
|
8
|
+
@to_db_mapping = {}
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def to_db(db, collection_name, attribute_name, value)
|
13
|
+
to_db_mapping = to_db_mapping_for db, collection_name
|
14
|
+
|
15
|
+
if to_db_mapping.key? attribute_name
|
16
|
+
to_db_mapping[attribute_name][:converter].to_db value
|
17
|
+
else
|
18
|
+
value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def from_db(object)
|
23
|
+
converter = find_converter_from_db object
|
24
|
+
if !converter.nil?
|
25
|
+
converter.from_db object
|
26
|
+
else
|
27
|
+
object
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def to_db_mapping_for(db, collection_name)
|
34
|
+
key = [db.opts[:database], collection_name]
|
35
|
+
|
36
|
+
@to_db_mapping[key] ||= begin
|
37
|
+
columns = Hash[db.schema(collection_name)]
|
38
|
+
|
39
|
+
columns.each_with_object({}) do |(name, schema), hash|
|
40
|
+
CONVERTERS.each do |converter|
|
41
|
+
unless hash.key? name
|
42
|
+
match = converter.column_type_regex.match schema[:db_type]
|
43
|
+
|
44
|
+
hash[name] = { converter: converter } if match
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def find_converter_from_db(object)
|
52
|
+
CONVERTERS.find do |converter|
|
53
|
+
converter.respond_for? object
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Rasti
|
2
|
+
module DB
|
3
|
+
module TypeConverters
|
4
|
+
module SQLiteTypes
|
5
|
+
class Array
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def column_type_regex
|
10
|
+
/^([a-z]+)\[\]$/
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_db(values)
|
14
|
+
JSON.dump(values)
|
15
|
+
end
|
16
|
+
|
17
|
+
def respond_for?(object)
|
18
|
+
parsed = JSON.parse object
|
19
|
+
object == to_db(parsed)
|
20
|
+
rescue
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
24
|
+
def from_db(object)
|
25
|
+
JSON.parse object
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/rasti/db/version.rb
CHANGED
data/rasti-db.gemspec
CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_runtime_dependency 'multi_require', '~> 1.0'
|
27
27
|
spec.add_runtime_dependency 'hierarchical_graph', '~> 1.0'
|
28
28
|
spec.add_runtime_dependency 'hash_ext', '~> 0.5'
|
29
|
+
spec.add_runtime_dependency 'inflecto', '~> 0.0'
|
29
30
|
|
30
31
|
spec.add_development_dependency 'rake', '~> 12.3'
|
31
32
|
spec.add_development_dependency 'minitest', '~> 5.0', '< 5.11'
|
data/spec/collection_spec.rb
CHANGED
@@ -2,6 +2,14 @@ require 'minitest_helper'
|
|
2
2
|
|
3
3
|
describe 'Collection' do
|
4
4
|
|
5
|
+
before do
|
6
|
+
Rasti::DB.type_converters = [Rasti::DB::TypeConverters::TimeInZone]
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
Rasti::DB.type_converters = [Rasti::DB::TypeConverters::TimeInZone, Rasti::DB::TypeConverters::SQLite]
|
11
|
+
end
|
12
|
+
|
5
13
|
describe 'Specification' do
|
6
14
|
|
7
15
|
it 'Implicit' do
|
@@ -537,20 +545,20 @@ describe 'Collection' do
|
|
537
545
|
case sql
|
538
546
|
|
539
547
|
when 'SELECT users.* FROM schema_1.users',
|
540
|
-
'SELECT users.* FROM schema_1.users WHERE (id IN (2, 1))'
|
548
|
+
'SELECT users.* FROM schema_1.users WHERE (users.id IN (2, 1))'
|
541
549
|
[
|
542
550
|
{id: 1},
|
543
551
|
{id: 2}
|
544
552
|
]
|
545
553
|
|
546
554
|
when 'SELECT posts.* FROM schema_1.posts',
|
547
|
-
'SELECT posts.* FROM schema_1.posts WHERE (user_id IN (1, 2))'
|
555
|
+
'SELECT posts.* FROM schema_1.posts WHERE (posts.user_id IN (1, 2))'
|
548
556
|
[
|
549
557
|
{id: 3, user_id: 1, language_id: 1},
|
550
558
|
{id: 4, user_id: 2, language_id: 2}
|
551
559
|
]
|
552
560
|
|
553
|
-
when 'SELECT comments.* FROM schema_1.comments WHERE (post_id IN (3, 4))'
|
561
|
+
when 'SELECT comments.* FROM schema_1.comments WHERE (comments.post_id IN (3, 4))'
|
554
562
|
[
|
555
563
|
{id: 5, user_id: 2, post_id: 3},
|
556
564
|
{id: 6, user_id: 1, post_id: 3},
|
@@ -558,7 +566,7 @@ describe 'Collection' do
|
|
558
566
|
{id: 8, user_id: 2, post_id: 4}
|
559
567
|
]
|
560
568
|
|
561
|
-
when 'SELECT languages.* FROM schema_2.languages WHERE (id IN (1, 2))'
|
569
|
+
when 'SELECT languages.* FROM schema_2.languages WHERE (languages.id IN (1, 2))'
|
562
570
|
[
|
563
571
|
{id: 1},
|
564
572
|
{id: 2}
|
@@ -663,7 +671,7 @@ describe 'Collection' do
|
|
663
671
|
stub_users.where(id: [1,2]).limit(1).order(:name).all
|
664
672
|
|
665
673
|
stub_db.sqls.must_equal [
|
666
|
-
'SELECT users.* FROM schema_1.users WHERE (id IN (1, 2)) ORDER BY name LIMIT 1'
|
674
|
+
'SELECT users.* FROM schema_1.users WHERE (users.id IN (1, 2)) ORDER BY users.name LIMIT 1'
|
667
675
|
]
|
668
676
|
end
|
669
677
|
|
@@ -673,13 +681,13 @@ describe 'Collection' do
|
|
673
681
|
stub_db.sqls.must_equal [
|
674
682
|
'SELECT posts.* FROM schema_1.posts',
|
675
683
|
'SELECT categories.*, categories_posts.post_id AS source_foreign_key FROM schema_1.categories INNER JOIN schema_1.categories_posts ON (schema_1.categories_posts.category_id = schema_1.categories.id) WHERE (categories_posts.post_id IN (3, 4))',
|
676
|
-
'SELECT comments.* FROM schema_1.comments WHERE (post_id IN (3, 4))',
|
677
|
-
'SELECT users.* FROM schema_1.users WHERE (id IN (2, 1))',
|
678
|
-
'SELECT posts.* FROM schema_1.posts WHERE (user_id IN (1, 2))',
|
684
|
+
'SELECT comments.* FROM schema_1.comments WHERE (comments.post_id IN (3, 4))',
|
685
|
+
'SELECT users.* FROM schema_1.users WHERE (users.id IN (2, 1))',
|
686
|
+
'SELECT posts.* FROM schema_1.posts WHERE (posts.user_id IN (1, 2))',
|
679
687
|
'SELECT categories.*, categories_posts.post_id AS source_foreign_key FROM schema_1.categories INNER JOIN schema_1.categories_posts ON (schema_1.categories_posts.category_id = schema_1.categories.id) WHERE (categories_posts.post_id IN (3, 4))',
|
680
|
-
'SELECT languages.* FROM schema_2.languages WHERE (id IN (1, 2))',
|
688
|
+
'SELECT languages.* FROM schema_2.languages WHERE (languages.id IN (1, 2))',
|
681
689
|
'SELECT people.*, languages_people.language_id AS source_foreign_key FROM schema_1.people INNER JOIN schema_1.languages_people ON (schema_1.languages_people.document_number = schema_1.people.document_number) WHERE (languages_people.language_id IN (1, 2))',
|
682
|
-
'SELECT users.* FROM schema_1.users WHERE (id IN (1, 2))'
|
690
|
+
'SELECT users.* FROM schema_1.users WHERE (users.id IN (1, 2))'
|
683
691
|
]
|
684
692
|
end
|
685
693
|
|
@@ -687,7 +695,7 @@ describe 'Collection' do
|
|
687
695
|
stub_posts.join('user.person').where(document_number: 'document_1').all
|
688
696
|
|
689
697
|
stub_db.sqls.must_equal [
|
690
|
-
"SELECT DISTINCT posts.* FROM schema_1.posts INNER JOIN schema_1.users AS user ON (user.id = posts.user_id) INNER JOIN schema_1.people AS user__person ON (user__person.user_id = user.id) WHERE (document_number = 'document_1')"
|
698
|
+
"SELECT DISTINCT posts.* FROM schema_1.posts INNER JOIN schema_1.users AS user ON (user.id = posts.user_id) INNER JOIN schema_1.people AS user__person ON (user__person.user_id = user.id) WHERE (posts.document_number = 'document_1')"
|
691
699
|
]
|
692
700
|
end
|
693
701
|
|
@@ -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
@@ -10,14 +10,15 @@ require 'sequel/extensions/pg_array'
|
|
10
10
|
require 'sequel/extensions/pg_json'
|
11
11
|
|
12
12
|
Rasti::DB.configure do |config|
|
13
|
-
config.type_converters = [Rasti::DB::TypeConverters::TimeInZone]
|
13
|
+
config.type_converters = [Rasti::DB::TypeConverters::TimeInZone, Rasti::DB::TypeConverters::SQLite]
|
14
|
+
config.nql_filter_condition_strategy = Rasti::DB::NQL::FilterConditionStrategies::SQLite.new
|
14
15
|
end
|
15
16
|
|
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]
|
18
|
-
Comment = Rasti::DB::Model[:id, :text, :user_id, :user, :post_id, :post]
|
17
|
+
User = Rasti::DB::Model[:id, :name, :posts, :comments, :person, :comments_count]
|
18
|
+
Post = Rasti::DB::Model[:id, :title, :body, :user_id, :user, :comments, :categories, :language_id, :language, :notice, :author]
|
19
|
+
Comment = Rasti::DB::Model[:id, :text, :user_id, :user, :post_id, :post, :tags]
|
19
20
|
Category = Rasti::DB::Model[:id, :name, :posts]
|
20
|
-
Person = Rasti::DB::Model[:document_number, :first_name, :last_name, :birth_date, :user_id, :user, :languages]
|
21
|
+
Person = Rasti::DB::Model[:document_number, :first_name, :last_name, :birth_date, :user_id, :user, :languages, :full_name]
|
21
22
|
Language = Rasti::DB::Model[:id, :name, :people]
|
22
23
|
|
23
24
|
|
@@ -25,6 +26,18 @@ class Users < Rasti::DB::Collection
|
|
25
26
|
one_to_many :posts
|
26
27
|
one_to_many :comments
|
27
28
|
one_to_one :person
|
29
|
+
|
30
|
+
computed_attribute :comments_count do
|
31
|
+
Rasti::DB::ComputedAttribute.new(Sequel[:comments_count][:value]) do |dataset|
|
32
|
+
subquery = dataset.db.from(:comments)
|
33
|
+
.select(Sequel[:user_id], Sequel.function('count', :id).as(:value))
|
34
|
+
.group(:user_id)
|
35
|
+
.as(:comments_count)
|
36
|
+
|
37
|
+
dataset.join_table(:inner, subquery, :user_id => :id)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
28
41
|
end
|
29
42
|
|
30
43
|
class Posts < Rasti::DB::Collection
|
@@ -47,6 +60,15 @@ class Posts < Rasti::DB::Collection
|
|
47
60
|
.distinct
|
48
61
|
end
|
49
62
|
end
|
63
|
+
|
64
|
+
computed_attribute :notice do
|
65
|
+
Rasti::DB::ComputedAttribute.new Sequel.join([:title, ': ', :body])
|
66
|
+
end
|
67
|
+
|
68
|
+
computed_attribute :author do
|
69
|
+
Rasti::DB::ComputedAttribute.new Sequel[:user]
|
70
|
+
end
|
71
|
+
|
50
72
|
end
|
51
73
|
|
52
74
|
class Comments < Rasti::DB::Collection
|
@@ -73,6 +95,10 @@ class People < Rasti::DB::Collection
|
|
73
95
|
|
74
96
|
many_to_one :user
|
75
97
|
many_to_many :languages
|
98
|
+
|
99
|
+
computed_attribute :full_name do |db|
|
100
|
+
Rasti::DB::ComputedAttribute.new Sequel.join([:first_name, ' ', :last_name])
|
101
|
+
end
|
76
102
|
end
|
77
103
|
|
78
104
|
class Languages < Rasti::DB::Collection
|
@@ -123,6 +149,7 @@ class Minitest::Spec
|
|
123
149
|
db.create_table :comments do
|
124
150
|
primary_key :id
|
125
151
|
String :text, null: false
|
152
|
+
String :tags, default: Sequel.lit("'[]'")
|
126
153
|
foreign_key :user_id, :users, null: false, index: true
|
127
154
|
foreign_key :post_id, :posts, null: false, index: true
|
128
155
|
end
|
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)
|
@@ -17,13 +19,30 @@ describe 'NQL::FilterCondition' do
|
|
17
19
|
def assert_comparison(filter, expected_left, expected_comparator, expected_right)
|
18
20
|
filter.must_be_instance_of Sequel::SQL::BooleanExpression
|
19
21
|
filter.op.must_equal expected_comparator.to_sym
|
20
|
-
|
22
|
+
|
21
23
|
left, right = filter.args
|
22
24
|
assert_identifier left, expected_left
|
23
25
|
|
24
26
|
right.must_equal expected_right
|
25
27
|
end
|
26
28
|
|
29
|
+
describe 'None Filter Condition Strategy Validation' do
|
30
|
+
|
31
|
+
before do
|
32
|
+
Rasti::DB.nql_filter_condition_strategy = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
after do
|
36
|
+
Rasti::DB.nql_filter_condition_strategy = Rasti::DB::NQL::FilterConditionStrategies::SQLite.new
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'must raise error' do
|
40
|
+
error = proc { filter_condition 'column = value' }.must_raise RuntimeError
|
41
|
+
error.message.must_equal 'Undefined Rasti::DB.nql_filter_condition_strategy'
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
27
46
|
describe 'Comparison' do
|
28
47
|
|
29
48
|
it 'must create filter from expression with <' do
|
@@ -95,7 +114,7 @@ describe 'NQL::FilterCondition' do
|
|
95
114
|
|
96
115
|
end
|
97
116
|
|
98
|
-
it 'must create filter from expression with
|
117
|
+
it 'must create filter from expression with attribute with multiple tables' do
|
99
118
|
filter = filter_condition 'table_one.table_two.column = test'
|
100
119
|
identifier, value = filter.first
|
101
120
|
|
@@ -132,7 +151,7 @@ describe 'NQL::FilterCondition' do
|
|
132
151
|
|
133
152
|
filter.must_be_instance_of Sequel::SQL::BooleanExpression
|
134
153
|
filter.op.must_equal :AND
|
135
|
-
|
154
|
+
|
136
155
|
major_expression, and_expression = filter.args
|
137
156
|
assert_comparison major_expression, 'column_one', '>', 1
|
138
157
|
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe 'NQL::FilterConditionStrategies' do
|
4
|
+
|
5
|
+
let(:comments_query) { Rasti::DB::Query.new collection_class: Comments, dataset: db[:comments], environment: environment }
|
6
|
+
|
7
|
+
def sqls_where(query)
|
8
|
+
"#<Rasti::DB::Query: \"SELECT `comments`.* FROM `comments` WHERE (#{query})\">"
|
9
|
+
end
|
10
|
+
|
11
|
+
def sqls_where_not(query)
|
12
|
+
"#<Rasti::DB::Query: \"SELECT `comments`.* FROM `comments` WHERE NOT (#{query})\">"
|
13
|
+
end
|
14
|
+
|
15
|
+
def nql_s(nql_query)
|
16
|
+
comments_query.nql(nql_query).to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'Generic' do
|
20
|
+
|
21
|
+
it 'Equal' do
|
22
|
+
nql_s('text = hola').must_equal sqls_where("`comments`.`text` = 'hola'")
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'Not Equal' do
|
26
|
+
nql_s('text != hola').must_equal sqls_where("`comments`.`text` != 'hola'")
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'Greather Than' do
|
30
|
+
nql_s('id > 1').must_equal sqls_where("`comments`.`id` > 1")
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'Greather Than or Equal' do
|
34
|
+
nql_s('id >= 1').must_equal sqls_where("`comments`.`id` >= 1")
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'Less Than' do
|
38
|
+
nql_s('id < 1').must_equal sqls_where("`comments`.`id` < 1")
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'Less Than or Equal' do
|
42
|
+
nql_s('id <= 1').must_equal sqls_where("`comments`.`id` <= 1")
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'Like' do
|
46
|
+
nql_s('text ~ hola').must_equal sqls_where("UPPER(`comments`.`text`) LIKE UPPER('hola') ESCAPE '\\'")
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'Include' do
|
50
|
+
nql_s('text: hola').must_equal sqls_where("UPPER(`comments`.`text`) LIKE UPPER('%hola%') ESCAPE '\\'")
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'Not Include' do
|
54
|
+
nql_s('text!: hola').must_equal sqls_where_not("UPPER(`comments`.`text`) LIKE UPPER('%hola%') ESCAPE '\\'")
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'SQLite Array' do
|
60
|
+
|
61
|
+
it 'Equal' do
|
62
|
+
nql_s('tags = [notice]').must_equal sqls_where("`comments`.`tags` = '[\"notice\"]'")
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'Not Equal' do
|
66
|
+
nql_s('tags != [notice]').must_equal sqls_where_not("`comments`.`tags` LIKE '%\"notice\"%' ESCAPE '\\'")
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'Like' do
|
70
|
+
nql_s('tags ~ [notice]').must_equal sqls_where("`comments`.`tags` LIKE '%notice%' ESCAPE '\\'")
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'Include' do
|
74
|
+
nql_s('tags: [notice]').must_equal sqls_where("`comments`.`tags` LIKE '%\"notice\"%' ESCAPE '\\'")
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'Not Include' do
|
78
|
+
nql_s('tags!: [notice]').must_equal sqls_where_not("`comments`.`tags` LIKE '%\"notice\"%' ESCAPE '\\'")
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'Postgres Array' do
|
84
|
+
|
85
|
+
before do
|
86
|
+
Rasti::DB.nql_filter_condition_strategy = Rasti::DB::NQL::FilterConditionStrategies::Postgres.new
|
87
|
+
Sequel.extension :pg_array_ops
|
88
|
+
end
|
89
|
+
|
90
|
+
after do
|
91
|
+
Rasti::DB.nql_filter_condition_strategy = Rasti::DB::NQL::FilterConditionStrategies::SQLite.new
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'Equal' do
|
95
|
+
nql_s('tags = [notice]').must_equal sqls_where("(`comments`.`tags` @> ARRAY['notice']) AND (`comments`.`tags` <@ ARRAY['notice'])")
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'Not Equal' do
|
99
|
+
nql_s('tags != [notice]').must_equal sqls_where("NOT (`comments`.`tags` @> ARRAY['notice']) OR NOT (`comments`.`tags` <@ ARRAY['notice'])")
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'Include' do
|
103
|
+
nql_s('tags: [notice]').must_equal sqls_where("`comments`.`tags` && ARRAY['notice']")
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'Not Include' do
|
107
|
+
nql_s('tags!: [notice]').must_equal sqls_where_not("`comments`.`tags` && ARRAY['notice']")
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|