alf-sql 0.15.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 (121) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/Gemfile +13 -0
  3. data/Gemfile.lock +38 -0
  4. data/LICENCE.md +22 -0
  5. data/Manifest.txt +12 -0
  6. data/README.md +52 -0
  7. data/Rakefile +11 -0
  8. data/lib/alf-sql.rb +1 -0
  9. data/lib/alf/algebra/operand.rb +18 -0
  10. data/lib/alf/predicate/nodes.rb +20 -0
  11. data/lib/alf/predicate/nodes/and.rb +11 -0
  12. data/lib/alf/predicate/nodes/contradiction.rb +12 -0
  13. data/lib/alf/predicate/nodes/dyadic_comp.rb +14 -0
  14. data/lib/alf/predicate/nodes/eq.rb +11 -0
  15. data/lib/alf/predicate/nodes/exists.rb +14 -0
  16. data/lib/alf/predicate/nodes/expr.rb +20 -0
  17. data/lib/alf/predicate/nodes/gt.rb +11 -0
  18. data/lib/alf/predicate/nodes/gte.rb +11 -0
  19. data/lib/alf/predicate/nodes/identifier.rb +12 -0
  20. data/lib/alf/predicate/nodes/in.rb +31 -0
  21. data/lib/alf/predicate/nodes/literal.rb +12 -0
  22. data/lib/alf/predicate/nodes/lt.rb +11 -0
  23. data/lib/alf/predicate/nodes/lte.rb +11 -0
  24. data/lib/alf/predicate/nodes/nadic_bool.rb +18 -0
  25. data/lib/alf/predicate/nodes/native.rb +11 -0
  26. data/lib/alf/predicate/nodes/neq.rb +11 -0
  27. data/lib/alf/predicate/nodes/not.rb +14 -0
  28. data/lib/alf/predicate/nodes/or.rb +11 -0
  29. data/lib/alf/predicate/nodes/qualified_identifier.rb +12 -0
  30. data/lib/alf/predicate/nodes/tautology.rb +12 -0
  31. data/lib/alf/sql.rb +15 -0
  32. data/lib/alf/sql/builder.rb +152 -0
  33. data/lib/alf/sql/cog.rb +32 -0
  34. data/lib/alf/sql/compiler.rb +137 -0
  35. data/lib/alf/sql/grammar.rb +44 -0
  36. data/lib/alf/sql/grammar.sexp.yml +92 -0
  37. data/lib/alf/sql/loader.rb +2 -0
  38. data/lib/alf/sql/nodes/column_name.rb +25 -0
  39. data/lib/alf/sql/nodes/cross_join.rb +28 -0
  40. data/lib/alf/sql/nodes/except.rb +14 -0
  41. data/lib/alf/sql/nodes/expr.rb +90 -0
  42. data/lib/alf/sql/nodes/from_clause.rb +24 -0
  43. data/lib/alf/sql/nodes/inner_join.rb +37 -0
  44. data/lib/alf/sql/nodes/intersect.rb +14 -0
  45. data/lib/alf/sql/nodes/limit_clause.rb +19 -0
  46. data/lib/alf/sql/nodes/literal.rb +18 -0
  47. data/lib/alf/sql/nodes/name_intro.rb +23 -0
  48. data/lib/alf/sql/nodes/offset_clause.rb +19 -0
  49. data/lib/alf/sql/nodes/order_by_clause.rb +25 -0
  50. data/lib/alf/sql/nodes/order_by_term.rb +30 -0
  51. data/lib/alf/sql/nodes/qualified_name.rb +32 -0
  52. data/lib/alf/sql/nodes/range_var_name.rb +17 -0
  53. data/lib/alf/sql/nodes/select_exp.rb +101 -0
  54. data/lib/alf/sql/nodes/select_item.rb +37 -0
  55. data/lib/alf/sql/nodes/select_list.rb +31 -0
  56. data/lib/alf/sql/nodes/select_star.rb +15 -0
  57. data/lib/alf/sql/nodes/set_operator.rb +64 -0
  58. data/lib/alf/sql/nodes/set_quantifier.rb +20 -0
  59. data/lib/alf/sql/nodes/subquery_as.rb +28 -0
  60. data/lib/alf/sql/nodes/table_as.rb +31 -0
  61. data/lib/alf/sql/nodes/table_name.rb +17 -0
  62. data/lib/alf/sql/nodes/union.rb +14 -0
  63. data/lib/alf/sql/nodes/where_clause.rb +20 -0
  64. data/lib/alf/sql/nodes/with_exp.rb +50 -0
  65. data/lib/alf/sql/nodes/with_spec.rb +24 -0
  66. data/lib/alf/sql/processor.rb +85 -0
  67. data/lib/alf/sql/processor/all.rb +17 -0
  68. data/lib/alf/sql/processor/clip.rb +39 -0
  69. data/lib/alf/sql/processor/distinct.rb +17 -0
  70. data/lib/alf/sql/processor/flatten.rb +24 -0
  71. data/lib/alf/sql/processor/from_self.rb +29 -0
  72. data/lib/alf/sql/processor/join.rb +80 -0
  73. data/lib/alf/sql/processor/join_support.rb +27 -0
  74. data/lib/alf/sql/processor/limit_offset.rb +30 -0
  75. data/lib/alf/sql/processor/merge.rb +42 -0
  76. data/lib/alf/sql/processor/order_by.rb +32 -0
  77. data/lib/alf/sql/processor/rename.rb +25 -0
  78. data/lib/alf/sql/processor/reorder.rb +21 -0
  79. data/lib/alf/sql/processor/requalify.rb +24 -0
  80. data/lib/alf/sql/processor/semi_join.rb +57 -0
  81. data/lib/alf/sql/processor/star.rb +17 -0
  82. data/lib/alf/sql/processor/where.rb +25 -0
  83. data/lib/alf/sql/version.rb +16 -0
  84. data/spec/algebra/operand/test_to_sql.rb +32 -0
  85. data/spec/builder/test_order_by_clause.rb +44 -0
  86. data/spec/helpers/ast.rb +242 -0
  87. data/spec/helpers/compiler.rb +23 -0
  88. data/spec/nodes/column_name/test_as_name.rb +14 -0
  89. data/spec/nodes/column_name/test_qualifier.rb +14 -0
  90. data/spec/nodes/order_by_clause/test_to_ordering.rb +30 -0
  91. data/spec/nodes/order_by_term/test_as_name.rb +22 -0
  92. data/spec/nodes/order_by_term/test_direction.rb +22 -0
  93. data/spec/nodes/order_by_term/test_qualifier.rb +22 -0
  94. data/spec/nodes/select_exp/test_order_by_clause.rb +22 -0
  95. data/spec/nodes/select_item/test_as_name.rb +22 -0
  96. data/spec/predicate/nodes/exists/test_not.rb +20 -0
  97. data/spec/processor/clip/test_on_select_exp.rb +32 -0
  98. data/spec/processor/clip/test_on_select_list.rb +24 -0
  99. data/spec/processor/distinct/test_on_set_quantified.rb +31 -0
  100. data/spec/processor/from_self/test_on_nonjoin_exp.rb +60 -0
  101. data/spec/processor/from_self/test_on_with_exp.rb +22 -0
  102. data/spec/processor/merge/test_on_select_exp.rb +73 -0
  103. data/spec/processor/merge/test_on_with_exp.rb +56 -0
  104. data/spec/processor/order_by/test_on_select_exp.rb +24 -0
  105. data/spec/processor/rename/test_on_select_item.rb +30 -0
  106. data/spec/processor/rename/test_on_select_list.rb +22 -0
  107. data/spec/processor/reorder/test_on_select_list.rb +22 -0
  108. data/spec/processor/requalify/test_on_select_exp.rb +24 -0
  109. data/spec/processor/star/test_on_select_exp.rb +24 -0
  110. data/spec/processor/test_clip.rb +24 -0
  111. data/spec/processor/test_distinct.rb +24 -0
  112. data/spec/processor/test_on_select_exp.rb +28 -0
  113. data/spec/processor/test_on_set_operator.rb +28 -0
  114. data/spec/processor/test_rename.rb +24 -0
  115. data/spec/shared/compiled_examples.rb +13 -0
  116. data/spec/spec_helper.rb +14 -0
  117. data/spec/test_sql.rb +10 -0
  118. data/tasks/bench.rake +40 -0
  119. data/tasks/gem.rake +8 -0
  120. data/tasks/test.rake +6 -0
  121. metadata +235 -0
@@ -0,0 +1,23 @@
1
+ module Helpers
2
+ module Compiler
3
+
4
+ def an_operand(cog = nil)
5
+ Alf::Algebra::Operand::Fake.new(nil, cog)
6
+ end
7
+
8
+ def compiler
9
+ @compiler ||= Alf::Sql::Compiler.new
10
+ end
11
+
12
+ def builder(start = 0)
13
+ @builder ||= Alf::Sql::Builder.new(start)
14
+ end
15
+
16
+ def suppliers
17
+ @suppliers ||= an_operand.with_name(:suppliers)
18
+ .with_heading(sid: String, name: String, status: Integer, city: String)
19
+ end
20
+
21
+ end
22
+ include Compiler
23
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ describe ColumnName, "as_name" do
5
+
6
+ subject{ expr.as_name }
7
+
8
+ let(:expr){ column_name_a }
9
+
10
+ it{ should eq("a") }
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ describe ColumnName, "qualifier" do
5
+
6
+ subject{ expr.qualifier }
7
+
8
+ let(:expr){ column_name_a }
9
+
10
+ it{ should be_nil }
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ describe OrderByClause, "to_ordering" do
5
+
6
+ subject{ expr.to_ordering }
7
+
8
+ let(:ordering){
9
+ Ordering.new([[:a, :asc], [:b, :desc]])
10
+ }
11
+
12
+ context 'when not qualified' do
13
+ let(:expr){ builder.order_by_clause(ordering) }
14
+
15
+ it{ should eq(ordering) }
16
+ end
17
+
18
+ context 'when qualified' do
19
+ let(:expr){
20
+ builder.order_by_clause(ordering){|a|
21
+ [:qualified_name, [:range_var_name, "t1"], [:column_name, a]]
22
+ }
23
+ }
24
+
25
+ it{ should eq(ordering) }
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ describe OrderByTerm, "as_name" do
5
+
6
+ subject{ expr.as_name }
7
+
8
+ context 'when qualified' do
9
+ let(:expr){ order_by_term(qualified_name('t1', 'a'), "asc") }
10
+
11
+ it{ should eq('a') }
12
+ end
13
+
14
+ context 'when not qualified' do
15
+ let(:expr){ order_by_term(column_name_a, "asc") }
16
+
17
+ it{ should eq('a') }
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ describe OrderByTerm, "direction" do
5
+
6
+ subject{ expr.direction }
7
+
8
+ context 'when qualified' do
9
+ let(:expr){ order_by_term(qualified_name('t1', 'a'), "asc") }
10
+
11
+ it{ should eq('asc') }
12
+ end
13
+
14
+ context 'when not qualified' do
15
+ let(:expr){ order_by_term(column_name_a, "asc") }
16
+
17
+ it{ should eq('asc') }
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ describe OrderByTerm, "qualifier" do
5
+
6
+ subject{ expr.qualifier }
7
+
8
+ context 'when qualified' do
9
+ let(:expr){ order_by_term(qualified_name('t1', 'a'), "asc") }
10
+
11
+ it{ should eq('t1') }
12
+ end
13
+
14
+ context 'when not qualified' do
15
+ let(:expr){ order_by_term(column_name_a, "asc") }
16
+
17
+ it{ should be_nil }
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ describe SelectExp, "order_by_clause" do
5
+
6
+ subject{ expr.order_by_clause }
7
+
8
+ context 'when an order by clause' do
9
+ let(:expr){ select_all.push(order_by_clause) }
10
+
11
+ it{ should eq(order_by_clause) }
12
+ end
13
+
14
+ context 'without such clause' do
15
+ let(:expr){ select_all }
16
+
17
+ it{ should be_nil }
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ describe SelectItem, "as_name" do
5
+
6
+ subject{ expr.as_name }
7
+
8
+ context 'on a select item with no real renaming' do
9
+ let(:expr){ select_item("a", "a") }
10
+
11
+ it{ should eq("a") }
12
+ end
13
+
14
+ context 'on a select item with with real renaming' do
15
+ let(:expr){ select_item("a", "x") }
16
+
17
+ it{ should eq("x") }
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ class Predicate
4
+ describe Exists, "!" do
5
+
6
+ let(:expr){
7
+ Grammar.sexpr [:exists, :foo]
8
+ }
9
+
10
+ let(:expected){
11
+ Grammar.sexpr [:not, [:exists, :foo]]
12
+ }
13
+
14
+ subject{ !expr }
15
+
16
+ it{ should eq(expected) }
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Clip, "on_select_exp" do
6
+
7
+ subject{ Clip.new(AttrList[:a], Builder.new).on_select_exp(expr) }
8
+
9
+ context 'normal_case' do
10
+ let(:expr){ select_all }
11
+
12
+ it{ should eq(select_all_a) }
13
+ end
14
+
15
+ context 'distinct_case' do
16
+ let(:expr){ select_distinct }
17
+
18
+ it{ should eq(select_distinct_a) }
19
+ end
20
+
21
+ context 'when leading to an empty select_list' do
22
+ let(:expr){ select_all_b }
23
+
24
+ context 'the default behavior' do
25
+ it{ should eq(select_is_table_dee(select_all_star)) }
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Clip, "on_select_list" do
6
+
7
+ subject{ Clip.new(AttrList[:a], Builder.new).on_select_list(expr) }
8
+
9
+ context 'when included' do
10
+ let(:expr){ select_list_ab }
11
+
12
+ it{ should eq(select_list_a) }
13
+ end
14
+
15
+ context 'when unique' do
16
+ let(:expr){ select_list_a }
17
+
18
+ it{ should eq(select_list_a) }
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Distinct, "on_set_quantified" do
6
+
7
+ subject{ Distinct.new(Builder.new).on_set_quantified(expr) }
8
+
9
+ let(:expected){
10
+ [:x, distinct]
11
+ }
12
+
13
+ context 'when already distinct' do
14
+ let(:expr){
15
+ Grammar.sexpr [:x, distinct]
16
+ }
17
+
18
+ it{ should eq(expected) }
19
+ end
20
+
21
+ context 'when not distinct' do
22
+ let(:expr){
23
+ Grammar.sexpr [:x, all]
24
+ }
25
+
26
+ it{ should eq(expected) }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe FromSelf, "on_nonjoin_exp" do
6
+
7
+ subject{ FromSelf.new(builder).on_nonjoin_exp(expr) }
8
+
9
+ context 'on select_exp' do
10
+ let(:expr){
11
+ select_all
12
+ }
13
+
14
+ let(:expected){
15
+ with_exp(t1: select_all)
16
+ }
17
+
18
+ it{ should eq(expected) }
19
+ end
20
+
21
+ context 'on union' do
22
+ let(:expr){
23
+ union
24
+ }
25
+
26
+ let(:expected){
27
+ with_exp(t1: union)
28
+ }
29
+
30
+ it{ should eq(expected) }
31
+ end
32
+
33
+ context 'on intersect' do
34
+ let(:expr){
35
+ intersect
36
+ }
37
+
38
+ let(:expected){
39
+ with_exp(t1: intersect)
40
+ }
41
+
42
+ it{ should eq(expected) }
43
+ end
44
+
45
+ context 'on except' do
46
+ let(:expr){
47
+ except
48
+ }
49
+
50
+ let(:expected){
51
+ with_exp(t1: except)
52
+ }
53
+
54
+ it{ should eq(expected) }
55
+ end
56
+
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe FromSelf, "on_with_exp" do
6
+
7
+ subject{ FromSelf.new(builder(1)).on_with_exp(expr) }
8
+
9
+ let(:expr){
10
+ with_exp({t1: select_all}, select_all_t2)
11
+ }
12
+
13
+ let(:expected){
14
+ with_exp({t1: select_all, t2: select_all_t2}, select_all_t2)
15
+ }
16
+
17
+ it{ should eq(expected) }
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Merge, "on_select_exp" do
6
+
7
+ subject{ Merge.new(:intersect, right, builder(1)).on_select_exp(expr) }
8
+
9
+ context 'when right a simple select_exp' do
10
+ let(:expr){
11
+ # SELECT * FROM t1
12
+ select_all
13
+ }
14
+
15
+ let(:right){
16
+ # SELECT * FROM t2
17
+ select_all_t2
18
+ }
19
+
20
+ let(:expected){
21
+ # SELECT * FROM t1 INTERSECT SELECT * FROM t2
22
+ intersect
23
+ }
24
+
25
+ it{ should eq(expected) }
26
+ end
27
+
28
+ context 'when right an intersect' do
29
+ let(:expr){
30
+ # SELECT * FROM t1
31
+ select_all
32
+ }
33
+
34
+ let(:right){
35
+ # SELECT * FROM t1 INTERSECT SELECT * FROM t2
36
+ intersect
37
+ }
38
+
39
+ let(:expected){
40
+ # SELECT * FROM t1 INTERSECT SELECT * FROM t1 INTERSECT SELECT * FROM t2
41
+ intersect(expr, right)
42
+ }
43
+
44
+ it{ should eq(expected) }
45
+ end
46
+
47
+ context 'when right is a with_exp' do
48
+ let(:expr){
49
+ # SELECT * FROM t1
50
+ select_all
51
+ }
52
+
53
+ let(:right){
54
+ # WITH t2 AS ...
55
+ # SELECT * FROM t2
56
+ with_exp({t2: select_all_t2}, select_all_t2)
57
+ }
58
+
59
+ let(:expected){
60
+ # WITH t2 AS ...
61
+ # SELECT * FROM t1 INTERSECT SELECT * FROM t2
62
+ with_exp(
63
+ {t2: select_all_t2},
64
+ intersect(select_all, select_all_t2))
65
+ }
66
+
67
+ it{ should eq(expected) }
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end