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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -3
  3. data/lib/rasti/db.rb +11 -1
  4. data/lib/rasti/db/collection.rb +10 -1
  5. data/lib/rasti/db/computed_attribute.rb +22 -0
  6. data/lib/rasti/db/nql/filter_condition_strategies/base.rb +17 -0
  7. data/lib/rasti/db/nql/filter_condition_strategies/postgres.rb +21 -0
  8. data/lib/rasti/db/nql/filter_condition_strategies/sqlite.rb +21 -0
  9. data/lib/rasti/db/nql/filter_condition_strategies/types/generic.rb +49 -0
  10. data/lib/rasti/db/nql/filter_condition_strategies/types/pg_array.rb +32 -0
  11. data/lib/rasti/db/nql/filter_condition_strategies/types/sqlite_array.rb +34 -0
  12. data/lib/rasti/db/nql/filter_condition_strategies/unsupported_type_comparison.rb +22 -0
  13. data/lib/rasti/db/nql/nodes/array_content.rb +21 -0
  14. data/lib/rasti/db/nql/nodes/attribute.rb +37 -0
  15. data/lib/rasti/db/nql/nodes/binary_node.rb +4 -0
  16. data/lib/rasti/db/nql/nodes/comparisons/base.rb +15 -1
  17. data/lib/rasti/db/nql/nodes/comparisons/equal.rb +0 -4
  18. data/lib/rasti/db/nql/nodes/comparisons/greater_than.rb +0 -4
  19. data/lib/rasti/db/nql/nodes/comparisons/greater_than_or_equal.rb +0 -4
  20. data/lib/rasti/db/nql/nodes/comparisons/include.rb +0 -4
  21. data/lib/rasti/db/nql/nodes/comparisons/less_than.rb +0 -4
  22. data/lib/rasti/db/nql/nodes/comparisons/less_than_or_equal.rb +0 -4
  23. data/lib/rasti/db/nql/nodes/comparisons/like.rb +0 -4
  24. data/lib/rasti/db/nql/nodes/comparisons/not_equal.rb +0 -4
  25. data/lib/rasti/db/nql/nodes/comparisons/not_include.rb +0 -4
  26. data/lib/rasti/db/nql/nodes/conjunction.rb +2 -2
  27. data/lib/rasti/db/nql/nodes/constants/array.rb +17 -0
  28. data/lib/rasti/db/nql/nodes/constants/base.rb +17 -0
  29. data/lib/rasti/db/nql/nodes/constants/false.rb +1 -1
  30. data/lib/rasti/db/nql/nodes/constants/float.rb +1 -1
  31. data/lib/rasti/db/nql/nodes/constants/integer.rb +1 -1
  32. data/lib/rasti/db/nql/nodes/constants/literal_string.rb +1 -1
  33. data/lib/rasti/db/nql/nodes/constants/string.rb +1 -1
  34. data/lib/rasti/db/nql/nodes/constants/time.rb +1 -1
  35. data/lib/rasti/db/nql/nodes/constants/true.rb +1 -1
  36. data/lib/rasti/db/nql/nodes/disjunction.rb +2 -2
  37. data/lib/rasti/db/nql/nodes/parenthesis_sentence.rb +6 -2
  38. data/lib/rasti/db/nql/nodes/sentence.rb +6 -2
  39. data/lib/rasti/db/nql/syntax.rb +262 -44
  40. data/lib/rasti/db/nql/syntax.treetop +27 -14
  41. data/lib/rasti/db/query.rb +42 -14
  42. data/lib/rasti/db/type_converters/postgres.rb +32 -36
  43. data/lib/rasti/db/type_converters/postgres_types/array.rb +11 -9
  44. data/lib/rasti/db/type_converters/postgres_types/hstore.rb +10 -9
  45. data/lib/rasti/db/type_converters/postgres_types/json.rb +17 -14
  46. data/lib/rasti/db/type_converters/postgres_types/jsonb.rb +17 -14
  47. data/lib/rasti/db/type_converters/sqlite.rb +62 -0
  48. data/lib/rasti/db/type_converters/sqlite_types/array.rb +34 -0
  49. data/lib/rasti/db/version.rb +1 -1
  50. data/rasti-db.gemspec +1 -0
  51. data/spec/collection_spec.rb +19 -11
  52. data/spec/computed_attribute_spec.rb +32 -0
  53. data/spec/minitest_helper.rb +32 -5
  54. data/spec/model_spec.rb +1 -1
  55. data/spec/nql/computed_attributes_spec.rb +29 -0
  56. data/spec/nql/filter_condition_spec.rb +23 -4
  57. data/spec/nql/filter_condition_strategies_spec.rb +112 -0
  58. data/spec/nql/syntax_parser_spec.rb +36 -5
  59. data/spec/query_spec.rb +254 -39
  60. data/spec/type_converters/sqlite_spec.rb +66 -0
  61. metadata +38 -3
  62. 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
@@ -1,5 +1,5 @@
1
1
  module Rasti
2
2
  module DB
3
- VERSION = '2.0.0'
3
+ VERSION = '2.3.1'
4
4
  end
5
5
  end
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'
@@ -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
@@ -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
@@ -42,7 +42,7 @@ describe 'Model' do
42
42
  describe 'To String' do
43
43
 
44
44
  it 'Class' do
45
- User.to_s.must_equal 'User[id, name, posts, comments, person]'
45
+ User.to_s.must_equal 'User[id, name, posts, comments, person, comments_count]'
46
46
  end
47
47
 
48
48
  it 'Instance' do
@@ -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 field with multiple tables' do
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