alf-sql 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
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,56 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Merge, "on_with_exp" do
6
+
7
+ subject{ Merge.new(:intersect, right, builder(1)).on_with_exp(expr) }
8
+
9
+ context 'when right is a simple exp' do
10
+ let(:expr){
11
+ # with t1 AS ...
12
+ # SELECT * FROM t1
13
+ with_exp({t1: select_all}, select_all)
14
+ }
15
+
16
+ let(:right){
17
+ # SELECT * FROM t2
18
+ select_all_t2
19
+ }
20
+
21
+ let(:expected){
22
+ # WITH t1 AS ...
23
+ # SELECT * FROM t1 INTERSECT SELECT * FROM t2
24
+ with_exp({t1: select_all}, intersect)
25
+ }
26
+
27
+ it{ should eq(expected) }
28
+ end
29
+
30
+ context 'when right is a with_exp' do
31
+ let(:expr){
32
+ # WITH t1 AS ...
33
+ # SELECT * FROM t1
34
+ with_exp({t1: select_all}, select_all)
35
+ }
36
+
37
+ let(:right){
38
+ # WITH t2 AS ...
39
+ # SELECT * FROM t2
40
+ with_exp({t2: select_all_t2}, select_all_t2)
41
+ }
42
+
43
+ let(:expected){
44
+ # WITH t1 AS ...
45
+ # t2 AS ...
46
+ # SELECT * FROM t1 INTERSECT SELECT * FROM t2
47
+ with_exp({t1: select_all, t2: select_all_t2}, intersect)
48
+ }
49
+
50
+ it{ should eq(expected) }
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe OrderBy, "on_select_exp" do
6
+
7
+ subject{ OrderBy.new(ordering, builder).on_select_exp(expr) }
8
+
9
+ context 'when not already ordered' do
10
+ let(:expr){
11
+ select_all
12
+ }
13
+
14
+ let(:expected){
15
+ select_all.push(order_by_clause)
16
+ }
17
+
18
+ it{ should eq(expected) }
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Rename, "on_select_item" do
6
+
7
+ subject{ Rename.new(Renaming[a: :x], Builder.new).on_select_item(expr) }
8
+
9
+ context 'when included' do
10
+ let(:expr){ select_item('a', 'a') }
11
+
12
+ it{ should eq(select_item('a', 'x')) }
13
+ end
14
+
15
+ context 'when already a renaming' do
16
+ let(:expr){ select_item('b', 'a') }
17
+
18
+ it{ should eq(select_item('b', 'x')) }
19
+ end
20
+
21
+ context 'when not matching' do
22
+ let(:expr){ select_item('a', 'y') }
23
+
24
+ it{ should be(expr) }
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Rename, "on_select_list" do
6
+
7
+ subject{ Rename.new(Renaming[a: :b, c: :d], Builder.new).on_select_list(expr) }
8
+
9
+ let(:expr){
10
+ select_list("a" => "a", "x" => "c", "y" => "z")
11
+ }
12
+
13
+ let(:expected){
14
+ select_list("a" => "b", "x" => "d", "y" => "z")
15
+ }
16
+
17
+ it{ should eq(expected) }
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Reorder, "on_select_list" do
6
+
7
+ subject{ Reorder.new([:b, :a], Builder.new).on_select_list(expr) }
8
+
9
+ let(:expr){
10
+ select_list_ab
11
+ }
12
+
13
+ let(:expected){
14
+ select_list_ba
15
+ }
16
+
17
+ it{ should eq(expected) }
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Requalify, "on_select_exp" do
6
+
7
+ subject{ Requalify.new(Builder.new(1)).on_select_exp(expr) }
8
+
9
+ context 'when not already ordered' do
10
+ let(:expr){
11
+ select_all
12
+ }
13
+
14
+ let(:expected){
15
+ select_all_from_t1_as_t2
16
+ }
17
+
18
+ it{ should eq(expected) }
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Star, "on_select_list" do
6
+
7
+ subject{ Star.new(Builder.new).on_select_exp(expr) }
8
+
9
+ context 'on select_all' do
10
+ let(:expr){ select_all }
11
+
12
+ it{ should eq(select_all_star) }
13
+ end
14
+
15
+ context 'on select_distinct' do
16
+ let(:expr){ select_distinct }
17
+
18
+ it{ should eq(select_distinct_star) }
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Clip do
6
+
7
+ subject{ Clip.new([:a], Builder.new).call(expr) }
8
+
9
+ context 'on a select_exp' do
10
+ let(:expr){ select_ab }
11
+
12
+ it{ should eq(select_a) }
13
+ end
14
+
15
+ context 'on a with_exp' do
16
+ let(:expr){ with_exp(nil, select_ab) }
17
+
18
+ it{ should eq(with_exp(nil, select_a)) }
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Distinct do
6
+
7
+ subject{ Distinct.new(Builder.new).call(expr) }
8
+
9
+ context 'on a select_exp' do
10
+ let(:expr){ select_all }
11
+
12
+ it{ should eq(select_distinct) }
13
+ end
14
+
15
+ context 'on a with_exp' do
16
+ let(:expr){ with_exp(nil, select_all) }
17
+
18
+ it{ should eq(with_exp(nil, select_distinct)) }
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ describe Processor, "on_select_exp" do
5
+
6
+ let(:clazz){
7
+ Class.new(Processor){
8
+ def on_select_list(sexpr)
9
+ [:foo, :bar, sexpr]
10
+ end
11
+ }
12
+ }
13
+
14
+ subject{ clazz.new(Builder.new).on_select_exp(expr) }
15
+
16
+ let(:expr){
17
+ Grammar.sexpr [:select_exp, distinct, select_list_ab, [:baz]]
18
+ }
19
+
20
+ let(:expected){
21
+ [:select_exp, distinct, [:foo, :bar, select_list_ab], [:baz]]
22
+ }
23
+
24
+ it{ should eq(expected) }
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ describe Processor, "on_set_operator" do
5
+
6
+ let(:clazz){
7
+ Class.new(Processor){
8
+ def on_select_exp(sexpr)
9
+ [:foo, :bar, sexpr]
10
+ end
11
+ }
12
+ }
13
+
14
+ subject{ clazz.new(Builder.new).on_set_operator(expr) }
15
+
16
+ let(:expr){
17
+ [:union, all, select_all_a, select_all_b]
18
+ }
19
+
20
+ let(:expected){
21
+ [:union, all, [:foo, :bar, select_all_a], [:foo, :bar, select_all_b]]
22
+ }
23
+
24
+ it{ should eq(expected) }
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ class Processor
5
+ describe Rename do
6
+
7
+ subject{ Rename.new(Renaming[a: :b], Builder.new).call(expr) }
8
+
9
+ context 'on a select_exp' do
10
+ let(:expr){ select_all_a }
11
+
12
+ it{ should eq(select_all_a_as_b) }
13
+ end
14
+
15
+ context 'on a with_exp' do
16
+ let(:expr){ with_exp(nil, select_all_a) }
17
+
18
+ it{ should eq(with_exp(nil, select_all_a_as_b)) }
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ shared_examples_for "a compiled" do
2
+
3
+ it{ should be_a(Alf::Sql::Cog) }
4
+
5
+ it 'has correct traceability' do
6
+ subject.expr.should be(expr)
7
+ end
8
+
9
+ it 'has correct compiler' do
10
+ subject.compiler.should be(compiler)
11
+ end
12
+
13
+ end
@@ -0,0 +1,14 @@
1
+ require 'alf-core'
2
+ require 'alf-sql'
3
+ require "rspec"
4
+
5
+ require_relative 'helpers/ast'
6
+ require_relative 'helpers/compiler'
7
+
8
+ require_relative 'shared/compiled_examples'
9
+
10
+ RSpec.configure do |c|
11
+ c.include Alf::Lang::Functional
12
+ c.include Helpers
13
+ c.extend Helpers
14
+ end
data/spec/test_sql.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe Sql do
4
+
5
+ it "should have a version number" do
6
+ Sql.const_defined?(:VERSION).should be_true
7
+ end
8
+
9
+ end
10
+ end
data/tasks/bench.rake ADDED
@@ -0,0 +1,40 @@
1
+ namespace :bench do
2
+
3
+ def bench_cmd
4
+ "bundle exec ruby -Ilib -I spec/integration/ spec/integration/bench_all.rb"
5
+ end
6
+
7
+ def alf_cmd(tail)
8
+ "bundle exec alf --ff=%.6f --input-reader=rash #{tail}"
9
+ end
10
+
11
+ task :run do
12
+ cmd = bench_cmd
13
+ $stderr.puts cmd
14
+ exec(cmd)
15
+ end
16
+
17
+ task :summary do
18
+ cmd = bench_cmd
19
+ cmd << " | "
20
+ cmd << alf_cmd("summarize -- category -- min 'min{ total }' max 'max{ total }' avg 'avg{ total }' stddev 'stddev{ total }'")
21
+ $stderr.puts cmd
22
+ exec(cmd)
23
+ end
24
+
25
+ task :rank do
26
+ cmd = bench_cmd
27
+ cmd << " | "
28
+ cmd << alf_cmd("summarize -- category alf -- parsing 'avg{ parsing }' compiling 'avg{ compiling }' translating 'avg{ translating }' printing 'avg{ printing }' total 'avg{ total }'")
29
+ cmd << " | "
30
+ cmd << alf_cmd("rank -- total desc -- position")
31
+ cmd << " | "
32
+ cmd << alf_cmd("project -- position category alf parsing compiling printing total")
33
+ cmd << " | "
34
+ cmd << alf_cmd("restrict -- 'position < 10'")
35
+ $stderr.puts cmd
36
+ exec(cmd)
37
+ end
38
+
39
+ end
40
+ task :bench => :"bench:run"
data/tasks/gem.rake ADDED
@@ -0,0 +1,8 @@
1
+ require 'rubygems/package_task'
2
+ gemspec_file = File.expand_path('../../alf-sql.gemspec', __FILE__)
3
+ gemspec = Kernel.eval(File.read(gemspec_file))
4
+ Gem::PackageTask.new(gemspec) do |t|
5
+ t.name = gemspec.name
6
+ t.version = gemspec.version
7
+ t.package_files = gemspec.files
8
+ end