rasti-db 2.2.0 → 3.0.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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/lib/rasti/db.rb +16 -5
  4. data/lib/rasti/db/collection.rb +10 -10
  5. data/lib/rasti/db/data_source.rb +1 -1
  6. data/lib/rasti/db/model.rb +3 -104
  7. data/lib/rasti/db/nql/filter_condition_strategies/base.rb +17 -0
  8. data/lib/rasti/db/nql/filter_condition_strategies/postgres.rb +21 -0
  9. data/lib/rasti/db/nql/filter_condition_strategies/sqlite.rb +21 -0
  10. data/lib/rasti/db/nql/filter_condition_strategies/types/generic.rb +49 -0
  11. data/lib/rasti/db/nql/filter_condition_strategies/types/pg_array.rb +32 -0
  12. data/lib/rasti/db/nql/filter_condition_strategies/types/sqlite_array.rb +34 -0
  13. data/lib/rasti/db/nql/filter_condition_strategies/unsupported_type_comparison.rb +22 -0
  14. data/lib/rasti/db/nql/nodes/array_content.rb +21 -0
  15. data/lib/rasti/db/nql/nodes/binary_node.rb +1 -1
  16. data/lib/rasti/db/nql/nodes/comparisons/base.rb +10 -0
  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/constants/array.rb +17 -0
  27. data/lib/rasti/db/nql/nodes/constants/base.rb +17 -0
  28. data/lib/rasti/db/nql/nodes/constants/false.rb +1 -1
  29. data/lib/rasti/db/nql/nodes/constants/float.rb +1 -1
  30. data/lib/rasti/db/nql/nodes/constants/integer.rb +1 -1
  31. data/lib/rasti/db/nql/nodes/constants/literal_string.rb +1 -1
  32. data/lib/rasti/db/nql/nodes/constants/string.rb +1 -1
  33. data/lib/rasti/db/nql/nodes/constants/time.rb +1 -1
  34. data/lib/rasti/db/nql/nodes/constants/true.rb +1 -1
  35. data/lib/rasti/db/nql/nodes/parenthesis_sentence.rb +1 -1
  36. data/lib/rasti/db/nql/syntax.rb +229 -11
  37. data/lib/rasti/db/nql/syntax.treetop +24 -11
  38. data/lib/rasti/db/relations/base.rb +3 -3
  39. data/lib/rasti/db/relations/graph.rb +15 -15
  40. data/lib/rasti/db/relations/many_to_many.rb +4 -4
  41. data/lib/rasti/db/relations/many_to_one.rb +4 -4
  42. data/lib/rasti/db/relations/one_to_many.rb +2 -2
  43. data/lib/rasti/db/type_converters/postgres.rb +32 -36
  44. data/lib/rasti/db/type_converters/postgres_types/array.rb +11 -9
  45. data/lib/rasti/db/type_converters/postgres_types/hstore.rb +10 -9
  46. data/lib/rasti/db/type_converters/postgres_types/json.rb +17 -14
  47. data/lib/rasti/db/type_converters/postgres_types/jsonb.rb +17 -14
  48. data/lib/rasti/db/type_converters/sqlite.rb +62 -0
  49. data/lib/rasti/db/type_converters/sqlite_types/array.rb +34 -0
  50. data/lib/rasti/db/type_converters/time_in_zone.rb +1 -1
  51. data/lib/rasti/db/version.rb +1 -1
  52. data/rasti-db.gemspec +2 -0
  53. data/spec/collection_spec.rb +36 -28
  54. data/spec/minitest_helper.rb +4 -2
  55. data/spec/nql/filter_condition_spec.rb +19 -2
  56. data/spec/nql/filter_condition_strategies_spec.rb +112 -0
  57. data/spec/nql/syntax_parser_spec.rb +24 -0
  58. data/spec/query_spec.rb +89 -0
  59. data/spec/relations_spec.rb +17 -17
  60. data/spec/type_converters/sqlite_spec.rb +66 -0
  61. data/spec/type_converters/time_in_zone_spec.rb +1 -1
  62. metadata +46 -4
  63. data/spec/model_spec.rb +0 -90
@@ -0,0 +1,22 @@
1
+ module Rasti
2
+ module DB
3
+ module NQL
4
+ module FilterConditionStrategies
5
+ class UnsupportedTypeComparison < StandardError
6
+
7
+ attr_reader :argument_type, :comparison_name
8
+
9
+ def initialize(argument_type, comparison_name)
10
+ @argument_type = argument_type
11
+ @comparison_name = comparison_name
12
+ end
13
+
14
+ def message
15
+ "Unsupported comparison #{comparison_name} for #{argument_type}"
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ module Rasti
2
+ module DB
3
+ module NQL
4
+ module Nodes
5
+ class ArrayContent < Treetop::Runtime::SyntaxNode
6
+
7
+ def values
8
+ [left.value] + right_value
9
+ end
10
+
11
+ private
12
+
13
+ def right_value
14
+ right.is_a?(self.class) ? right.values : [right.value]
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -3,7 +3,7 @@ module Rasti
3
3
  module NQL
4
4
  module Nodes
5
5
  class BinaryNode < Treetop::Runtime::SyntaxNode
6
-
6
+
7
7
  def dependency_tables
8
8
  values.flat_map(&:dependency_tables)
9
9
  end
@@ -13,6 +13,16 @@ module Rasti
13
13
  attribute.computed_attributes(collection_class)
14
14
  end
15
15
 
16
+ def filter_condition(collection_class)
17
+ DB.nql_filter_condition_for comparison_name, attribute.identifier(collection_class), argument
18
+ end
19
+
20
+ private
21
+
22
+ def comparison_name
23
+ Inflecto.underscore(Inflecto.demodulize(self.class)).to_sym
24
+ end
25
+
16
26
  end
17
27
  end
18
28
  end
@@ -5,10 +5,6 @@ module Rasti
5
5
  module Comparisons
6
6
  class Equal < Base
7
7
 
8
- def filter_condition(collection_class)
9
- { attribute.identifier(collection_class) => argument.value }
10
- end
11
-
12
8
  end
13
9
  end
14
10
  end
@@ -5,10 +5,6 @@ module Rasti
5
5
  module Comparisons
6
6
  class GreaterThan < Base
7
7
 
8
- def filter_condition(collection_class)
9
- attribute.identifier(collection_class) > argument.value
10
- end
11
-
12
8
  end
13
9
  end
14
10
  end
@@ -5,10 +5,6 @@ module Rasti
5
5
  module Comparisons
6
6
  class GreaterThanOrEqual < Base
7
7
 
8
- def filter_condition(collection_class)
9
- attribute.identifier(collection_class) >= argument.value
10
- end
11
-
12
8
  end
13
9
  end
14
10
  end
@@ -5,10 +5,6 @@ module Rasti
5
5
  module Comparisons
6
6
  class Include < Base
7
7
 
8
- def filter_condition(collection_class)
9
- Sequel.ilike(attribute.identifier(collection_class), "%#{argument.value}%")
10
- end
11
-
12
8
  end
13
9
  end
14
10
  end
@@ -5,10 +5,6 @@ module Rasti
5
5
  module Comparisons
6
6
  class LessThan < Base
7
7
 
8
- def filter_condition(collection_class)
9
- attribute.identifier(collection_class) < argument.value
10
- end
11
-
12
8
  end
13
9
  end
14
10
  end
@@ -5,10 +5,6 @@ module Rasti
5
5
  module Comparisons
6
6
  class LessThanOrEqual < Base
7
7
 
8
- def filter_condition(collection_class)
9
- attribute.identifier(collection_class) <= argument.value
10
- end
11
-
12
8
  end
13
9
  end
14
10
  end
@@ -5,10 +5,6 @@ module Rasti
5
5
  module Comparisons
6
6
  class Like < Base
7
7
 
8
- def filter_condition(collection_class)
9
- Sequel.ilike(attribute.identifier(collection_class), argument.value)
10
- end
11
-
12
8
  end
13
9
  end
14
10
  end
@@ -5,10 +5,6 @@ module Rasti
5
5
  module Comparisons
6
6
  class NotEqual < Base
7
7
 
8
- def filter_condition(collection_class)
9
- Sequel.negate(attribute.identifier(collection_class) => argument.value)
10
- end
11
-
12
8
  end
13
9
  end
14
10
  end
@@ -5,10 +5,6 @@ module Rasti
5
5
  module Comparisons
6
6
  class NotInclude < Base
7
7
 
8
- def filter_condition(collection_class)
9
- ~ Sequel.ilike(attribute.identifier(collection_class), "%#{argument.value}%")
10
- end
11
-
12
8
  end
13
9
  end
14
10
  end
@@ -0,0 +1,17 @@
1
+ module Rasti
2
+ module DB
3
+ module NQL
4
+ module Nodes
5
+ module Constants
6
+ class Array < Base
7
+
8
+ def value
9
+ contents.is_a?(ArrayContent) ? contents.values : [contents.value]
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Rasti
2
+ module DB
3
+ module NQL
4
+ module Nodes
5
+ module Constants
6
+ class Base < Treetop::Runtime::SyntaxNode
7
+
8
+ def type
9
+ Inflecto.underscore(Inflecto.demodulize(self.class)).to_sym
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -3,7 +3,7 @@ module Rasti
3
3
  module NQL
4
4
  module Nodes
5
5
  module Constants
6
- class False < Treetop::Runtime::SyntaxNode
6
+ class False < Base
7
7
 
8
8
  def value
9
9
  false
@@ -3,7 +3,7 @@ module Rasti
3
3
  module NQL
4
4
  module Nodes
5
5
  module Constants
6
- class Float < Treetop::Runtime::SyntaxNode
6
+ class Float < Base
7
7
 
8
8
  def value
9
9
  text_value.to_f
@@ -3,7 +3,7 @@ module Rasti
3
3
  module NQL
4
4
  module Nodes
5
5
  module Constants
6
- class Integer < Treetop::Runtime::SyntaxNode
6
+ class Integer < Base
7
7
 
8
8
  def value
9
9
  text_value.to_i
@@ -3,7 +3,7 @@ module Rasti
3
3
  module NQL
4
4
  module Nodes
5
5
  module Constants
6
- class LiteralString < Treetop::Runtime::SyntaxNode
6
+ class LiteralString < Base
7
7
 
8
8
  def value
9
9
  string.text_value
@@ -3,7 +3,7 @@ module Rasti
3
3
  module NQL
4
4
  module Nodes
5
5
  module Constants
6
- class String < Treetop::Runtime::SyntaxNode
6
+ class String < Base
7
7
 
8
8
  def value
9
9
  text_value.strip
@@ -3,7 +3,7 @@ module Rasti
3
3
  module NQL
4
4
  module Nodes
5
5
  module Constants
6
- class Time < Treetop::Runtime::SyntaxNode
6
+ class Time < Base
7
7
 
8
8
  def value
9
9
  time.to_s
@@ -3,7 +3,7 @@ module Rasti
3
3
  module NQL
4
4
  module Nodes
5
5
  module Constants
6
- class True < Treetop::Runtime::SyntaxNode
6
+ class True < Base
7
7
 
8
8
  def value
9
9
  true
@@ -3,7 +3,7 @@ module Rasti
3
3
  module NQL
4
4
  module Nodes
5
5
  class ParenthesisSentence < Treetop::Runtime::SyntaxNode
6
-
6
+
7
7
  def dependency_tables
8
8
  sentence.dependency_tables
9
9
  end
@@ -571,7 +571,7 @@ module Rasti
571
571
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
572
572
  s0 << r5
573
573
  if r5
574
- r7 = _nt_basic
574
+ r7 = _nt_argument
575
575
  s0 << r7
576
576
  end
577
577
  end
@@ -652,7 +652,7 @@ module Rasti
652
652
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
653
653
  s0 << r5
654
654
  if r5
655
- r7 = _nt_basic
655
+ r7 = _nt_argument
656
656
  s0 << r7
657
657
  end
658
658
  end
@@ -733,7 +733,7 @@ module Rasti
733
733
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
734
734
  s0 << r5
735
735
  if r5
736
- r7 = _nt_basic
736
+ r7 = _nt_argument
737
737
  s0 << r7
738
738
  end
739
739
  end
@@ -814,7 +814,7 @@ module Rasti
814
814
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
815
815
  s0 << r5
816
816
  if r5
817
- r7 = _nt_basic
817
+ r7 = _nt_argument
818
818
  s0 << r7
819
819
  end
820
820
  end
@@ -895,7 +895,7 @@ module Rasti
895
895
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
896
896
  s0 << r5
897
897
  if r5
898
- r7 = _nt_basic
898
+ r7 = _nt_argument
899
899
  s0 << r7
900
900
  end
901
901
  end
@@ -976,7 +976,7 @@ module Rasti
976
976
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
977
977
  s0 << r5
978
978
  if r5
979
- r7 = _nt_basic
979
+ r7 = _nt_argument
980
980
  s0 << r7
981
981
  end
982
982
  end
@@ -1057,7 +1057,7 @@ module Rasti
1057
1057
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
1058
1058
  s0 << r5
1059
1059
  if r5
1060
- r7 = _nt_basic
1060
+ r7 = _nt_argument
1061
1061
  s0 << r7
1062
1062
  end
1063
1063
  end
@@ -1138,7 +1138,7 @@ module Rasti
1138
1138
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
1139
1139
  s0 << r5
1140
1140
  if r5
1141
- r7 = _nt_basic
1141
+ r7 = _nt_argument
1142
1142
  s0 << r7
1143
1143
  end
1144
1144
  end
@@ -1219,7 +1219,7 @@ module Rasti
1219
1219
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
1220
1220
  s0 << r5
1221
1221
  if r5
1222
- r7 = _nt_basic
1222
+ r7 = _nt_argument
1223
1223
  s0 << r7
1224
1224
  end
1225
1225
  end
@@ -1238,6 +1238,36 @@ module Rasti
1238
1238
  r0
1239
1239
  end
1240
1240
 
1241
+ def _nt_argument
1242
+ start_index = index
1243
+ if node_cache[:argument].has_key?(index)
1244
+ cached = node_cache[:argument][index]
1245
+ if cached
1246
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
1247
+ @index = cached.interval.end
1248
+ end
1249
+ return cached
1250
+ end
1251
+
1252
+ i0 = index
1253
+ r1 = _nt_array
1254
+ if r1
1255
+ r0 = r1
1256
+ else
1257
+ r2 = _nt_basic
1258
+ if r2
1259
+ r0 = r2
1260
+ else
1261
+ @index = i0
1262
+ r0 = nil
1263
+ end
1264
+ end
1265
+
1266
+ node_cache[:argument][start_index] = r0
1267
+
1268
+ r0
1269
+ end
1270
+
1241
1271
  def _nt_basic
1242
1272
  start_index = index
1243
1273
  if node_cache[:basic].has_key?(index)
@@ -1288,6 +1318,194 @@ module Rasti
1288
1318
  r0
1289
1319
  end
1290
1320
 
1321
+ module Array0
1322
+ def open
1323
+ elements[0]
1324
+ end
1325
+
1326
+ def contents
1327
+ elements[2]
1328
+ end
1329
+
1330
+ def close
1331
+ elements[4]
1332
+ end
1333
+ end
1334
+
1335
+ def _nt_array
1336
+ start_index = index
1337
+ if node_cache[:array].has_key?(index)
1338
+ cached = node_cache[:array][index]
1339
+ if cached
1340
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
1341
+ @index = cached.interval.end
1342
+ end
1343
+ return cached
1344
+ end
1345
+
1346
+ i0, s0 = index, []
1347
+ if has_terminal?('[', false, index)
1348
+ r1 = instantiate_node(SyntaxNode,input, index...(index + 1))
1349
+ @index += 1
1350
+ else
1351
+ terminal_parse_failure('[')
1352
+ r1 = nil
1353
+ end
1354
+ s0 << r1
1355
+ if r1
1356
+ s2, i2 = [], index
1357
+ loop do
1358
+ r3 = _nt_space
1359
+ if r3
1360
+ s2 << r3
1361
+ else
1362
+ break
1363
+ end
1364
+ end
1365
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
1366
+ s0 << r2
1367
+ if r2
1368
+ i4 = index
1369
+ r5 = _nt_array_content
1370
+ if r5
1371
+ r4 = r5
1372
+ else
1373
+ r6 = _nt_basic
1374
+ if r6
1375
+ r4 = r6
1376
+ else
1377
+ @index = i4
1378
+ r4 = nil
1379
+ end
1380
+ end
1381
+ s0 << r4
1382
+ if r4
1383
+ s7, i7 = [], index
1384
+ loop do
1385
+ r8 = _nt_space
1386
+ if r8
1387
+ s7 << r8
1388
+ else
1389
+ break
1390
+ end
1391
+ end
1392
+ r7 = instantiate_node(SyntaxNode,input, i7...index, s7)
1393
+ s0 << r7
1394
+ if r7
1395
+ if has_terminal?(']', false, index)
1396
+ r9 = instantiate_node(SyntaxNode,input, index...(index + 1))
1397
+ @index += 1
1398
+ else
1399
+ terminal_parse_failure(']')
1400
+ r9 = nil
1401
+ end
1402
+ s0 << r9
1403
+ end
1404
+ end
1405
+ end
1406
+ end
1407
+ if s0.last
1408
+ r0 = instantiate_node(Nodes::Constants::Array,input, i0...index, s0)
1409
+ r0.extend(Array0)
1410
+ else
1411
+ @index = i0
1412
+ r0 = nil
1413
+ end
1414
+
1415
+ node_cache[:array][start_index] = r0
1416
+
1417
+ r0
1418
+ end
1419
+
1420
+ module ArrayContent0
1421
+ def left
1422
+ elements[0]
1423
+ end
1424
+
1425
+ def right
1426
+ elements[4]
1427
+ end
1428
+ end
1429
+
1430
+ def _nt_array_content
1431
+ start_index = index
1432
+ if node_cache[:array_content].has_key?(index)
1433
+ cached = node_cache[:array_content][index]
1434
+ if cached
1435
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
1436
+ @index = cached.interval.end
1437
+ end
1438
+ return cached
1439
+ end
1440
+
1441
+ i0, s0 = index, []
1442
+ r1 = _nt_basic
1443
+ s0 << r1
1444
+ if r1
1445
+ s2, i2 = [], index
1446
+ loop do
1447
+ r3 = _nt_space
1448
+ if r3
1449
+ s2 << r3
1450
+ else
1451
+ break
1452
+ end
1453
+ end
1454
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
1455
+ s0 << r2
1456
+ if r2
1457
+ if has_terminal?(',', false, index)
1458
+ r4 = instantiate_node(SyntaxNode,input, index...(index + 1))
1459
+ @index += 1
1460
+ else
1461
+ terminal_parse_failure(',')
1462
+ r4 = nil
1463
+ end
1464
+ s0 << r4
1465
+ if r4
1466
+ s5, i5 = [], index
1467
+ loop do
1468
+ r6 = _nt_space
1469
+ if r6
1470
+ s5 << r6
1471
+ else
1472
+ break
1473
+ end
1474
+ end
1475
+ r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
1476
+ s0 << r5
1477
+ if r5
1478
+ i7 = index
1479
+ r8 = _nt_array_content
1480
+ if r8
1481
+ r7 = r8
1482
+ else
1483
+ r9 = _nt_basic
1484
+ if r9
1485
+ r7 = r9
1486
+ else
1487
+ @index = i7
1488
+ r7 = nil
1489
+ end
1490
+ end
1491
+ s0 << r7
1492
+ end
1493
+ end
1494
+ end
1495
+ end
1496
+ if s0.last
1497
+ r0 = instantiate_node(Nodes::ArrayContent,input, i0...index, s0)
1498
+ r0.extend(ArrayContent0)
1499
+ else
1500
+ @index = i0
1501
+ r0 = nil
1502
+ end
1503
+
1504
+ node_cache[:array_content][start_index] = r0
1505
+
1506
+ r0
1507
+ end
1508
+
1291
1509
  def _nt_space
1292
1510
  start_index = index
1293
1511
  if node_cache[:space].has_key?(index)
@@ -2015,7 +2233,7 @@ module Rasti
2015
2233
  return cached
2016
2234
  end
2017
2235
 
2018
- if has_terminal?('\G[0-9a-zA-ZÁÀÄÂÃÅĀĂǍáàäâãåāăǎÉÈËÊĒĔĖĚéèëêēĕėěÍÌÏÎĨĬǏíìïîĩĭǐÓÒÖÔÕŌŎŐǑóòöôõōŏőǒÚÙÜÛŨŪŬŮŰǓúùüûũūŭůűǔÑñçÇ%@#+-_\'?!$*/\\s]', true, index)
2236
+ if has_terminal?('\G[0-9a-zA-ZÁÀÄÂÃÅĀĂǍáàäâãåāăǎÉÈËÊĒĔĖĚéèëêēĕėěÍÌÏÎĨĬǏíìïîĩĭǐÓÒÖÔÕŌŎŐǑóòöôõōŏőǒÚÙÜÛŨŪŬŮŰǓúùüûũūŭůűǔÑñçÇ%@#+\\--Z\\\\^_\'?!$*/\\s]', true, index)
2019
2237
  r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
2020
2238
  @index += 1
2021
2239
  else
@@ -2243,7 +2461,7 @@ module Rasti
2243
2461
  return cached
2244
2462
  end
2245
2463
 
2246
- if has_terminal?('\G[&|.():!=<>~]', true, index)
2464
+ if has_terminal?('\G[&|.():!=<>~,\\]\\[]', true, index)
2247
2465
  r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
2248
2466
  @index += 1
2249
2467
  else