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,42 @@
1
+ module Alf
2
+ module Sql
3
+ class Processor
4
+ class Merge < Processor
5
+
6
+ def initialize(kind, right, builder)
7
+ super(builder)
8
+ @kind = kind
9
+ @right = right
10
+ end
11
+
12
+ def on_with_exp(sexpr)
13
+ if @right.with_exp?
14
+ reordered = Reorder.new(sexpr.to_attr_list, builder).call(@right)
15
+ main = [ @kind, builder.distinct, sexpr.select_exp, reordered.select_exp ]
16
+ merge_with_exps(sexpr, reordered, main)
17
+ else
18
+ [ :with_exp,
19
+ sexpr.with_spec,
20
+ apply(sexpr.last) ]
21
+ end
22
+ end
23
+
24
+ def on_nonjoin_exp(sexpr)
25
+ reordered = Reorder.new(sexpr.to_attr_list, builder).call(@right)
26
+ if @right.with_exp?
27
+ [ :with_exp,
28
+ reordered.with_spec,
29
+ [ @kind, builder.distinct, sexpr, reordered.select_exp ] ]
30
+ else
31
+ [ @kind, builder.distinct, sexpr, reordered ]
32
+ end
33
+ end
34
+ alias :on_union :on_nonjoin_exp
35
+ alias :on_except :on_nonjoin_exp
36
+ alias :on_intersect :on_nonjoin_exp
37
+ alias :on_select_exp :on_nonjoin_exp
38
+
39
+ end # class Merge
40
+ end # class Processor
41
+ end # module Sql
42
+ end # module Alf
@@ -0,0 +1,32 @@
1
+ module Alf
2
+ module Sql
3
+ class Processor
4
+ class OrderBy < Processor
5
+
6
+ def initialize(ordering, builder)
7
+ super(builder)
8
+ @ordering = ordering
9
+ end
10
+ attr_reader :ordering
11
+
12
+ def on_set_operator(sexpr)
13
+ call(builder.from_self(sexpr))
14
+ end
15
+ alias :on_union :on_set_operator
16
+ alias :on_except :on_set_operator
17
+ alias :on_intersect :on_set_operator
18
+
19
+ def on_select_exp(sexpr)
20
+ if obc = sexpr.order_by_clause
21
+ sexpr = builder.from_self(sexpr)
22
+ call(sexpr)
23
+ else
24
+ needed = builder.order_by_clause(ordering, &sexpr.desaliaser)
25
+ sexpr.dup.push(needed)
26
+ end
27
+ end
28
+
29
+ end # class OrderBy
30
+ end # class Processor
31
+ end # module Sql
32
+ end # module Alf
@@ -0,0 +1,25 @@
1
+ module Alf
2
+ module Sql
3
+ class Processor
4
+ class Rename < Processor
5
+
6
+ def initialize(renaming, builder)
7
+ super(builder)
8
+ @renaming = renaming
9
+ end
10
+
11
+ def on_select_list(sexpr)
12
+ sexpr.each_with_index.map{|child,index|
13
+ index == 0 ? child : apply(child)
14
+ }
15
+ end
16
+
17
+ def on_select_item(sexpr)
18
+ return sexpr unless newname = @renaming[sexpr.as_name.to_sym]
19
+ builder.select_item(sexpr.qualifier, sexpr.would_be_name, newname.to_s)
20
+ end
21
+
22
+ end # class Rename
23
+ end # class Processor
24
+ end # module Sql
25
+ end # module Alf
@@ -0,0 +1,21 @@
1
+ module Alf
2
+ module Sql
3
+ class Processor
4
+ class Reorder < Processor
5
+
6
+ def initialize(attr_list, builder)
7
+ super(builder)
8
+ @indexes = Hash[attr_list.to_a.map(&:to_s).each_with_index.to_a]
9
+ end
10
+
11
+ def on_select_list(sexpr)
12
+ reordered = sexpr.sexpr_body.sort{|i1,i2|
13
+ @indexes[i1.as_name] <=> @indexes[i2.as_name]
14
+ }
15
+ reordered.unshift(:select_list)
16
+ end
17
+
18
+ end # class Reorder
19
+ end # class Processor
20
+ end # module Sql
21
+ end # module Alf
@@ -0,0 +1,24 @@
1
+ module Alf
2
+ module Sql
3
+ class Processor
4
+ class Requalify < Processor
5
+
6
+ def initialize(builder)
7
+ super
8
+ @requalify = Hash.new{|h,k|
9
+ h[k] = Grammar.sexpr [:range_var_name, builder.next_qualifier!]
10
+ }
11
+ end
12
+ attr_reader :requalify
13
+
14
+ alias :on_select_exp :copy_and_apply
15
+ alias :on_missing :copy_and_apply
16
+
17
+ def on_range_var_name(sexpr)
18
+ requalify[sexpr]
19
+ end
20
+
21
+ end # class Requalify
22
+ end # class Processor
23
+ end # module Sql
24
+ end # module Alf
@@ -0,0 +1,57 @@
1
+ module Alf
2
+ module Sql
3
+ class Processor
4
+ class SemiJoin < Processor
5
+ include JoinSupport
6
+
7
+ def initialize(right, negate = false, builder)
8
+ super(builder)
9
+ @right = right
10
+ @negate = negate
11
+ end
12
+ attr_reader :right, :negate
13
+
14
+ def call(sexpr)
15
+ if sexpr.set_operator?
16
+ call(builder.from_self(sexpr))
17
+ elsif right.set_operator?
18
+ SemiJoin.new(builder.from_self(right), negate, builder).call(sexpr)
19
+ else
20
+ super(sexpr)
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def apply_join_strategy(left, right)
27
+ commons = left.to_attr_list & right.to_attr_list
28
+ subquery = Clip.new(commons, :star, builder).call(right)
29
+ if commons.size == 0
30
+ predicate = builder.exists(subquery)
31
+ elsif commons.size == 1
32
+ identifier = left.desaliaser[commons.to_a.first]
33
+ predicate = Predicate::Factory.in(identifier, subquery)
34
+ else
35
+ join_pre = join_predicate(left, subquery, commons)
36
+ subquery = expand_where_clause(subquery, join_pre)
37
+ predicate = builder.exists(subquery)
38
+ end
39
+ expand_where_clause(left, negate ? !predicate : predicate)
40
+ end
41
+
42
+ def expand_where_clause(sexpr, predicate)
43
+ Grammar.sexpr \
44
+ [ :select_exp,
45
+ sexpr.set_quantifier,
46
+ sexpr.select_list,
47
+ sexpr.from_clause,
48
+ [ :where_clause, (sexpr.predicate || tautology) & predicate ],
49
+ sexpr.order_by_clause,
50
+ sexpr.limit_clause,
51
+ sexpr.offset_clause ].compact
52
+ end
53
+
54
+ end # class SemiJoin
55
+ end # class Processor
56
+ end # module Sql
57
+ end # module Alf
@@ -0,0 +1,17 @@
1
+ module Alf
2
+ module Sql
3
+ class Processor
4
+ class Star < Processor
5
+
6
+ def on_select_exp(sexpr)
7
+ if sexpr.from_clause
8
+ sexpr.with_update(:select_list, builder.select_star)
9
+ else
10
+ sexpr
11
+ end
12
+ end
13
+
14
+ end # class Star
15
+ end # class Processor
16
+ end # module Sql
17
+ end # module Alf
@@ -0,0 +1,25 @@
1
+ module Alf
2
+ module Sql
3
+ class Processor
4
+ class Where < Processor
5
+
6
+ def initialize(predicate, builder)
7
+ super(builder)
8
+ @predicate = predicate
9
+ end
10
+
11
+ def on_select_exp(sexpr)
12
+ pred = @predicate.rename(sexpr.desaliaser).sexpr
13
+ if sexpr.where_clause
14
+ anded = [:and, sexpr.where_clause.predicate, pred ]
15
+ anded = Alf::Predicate::Grammar.sexpr(anded)
16
+ sexpr.with_update(:where_clause, [ :where_clause, anded ])
17
+ else
18
+ sexpr.with_insert(4, [ :where_clause, pred ])
19
+ end
20
+ end
21
+
22
+ end # class Where
23
+ end # class Processor
24
+ end # module Sql
25
+ end # module Alf
@@ -0,0 +1,16 @@
1
+ module Alf
2
+ module Sql
3
+ module Version
4
+
5
+ MAJOR = 0
6
+ MINOR = 15
7
+ TINY = 0
8
+
9
+ def self.to_s
10
+ [ MAJOR, MINOR, TINY ].join('.')
11
+ end
12
+
13
+ end
14
+ VERSION = Version.to_s
15
+ end
16
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Algebra
4
+ describe Operand, "to_sql" do
5
+
6
+ subject{ op.to_sql }
7
+
8
+ context 'when to_cog does not support to_sql' do
9
+ let(:op) { restrict(suppliers, city: 'London') }
10
+
11
+ before do
12
+ op.to_cog.should_not respond_to(:to_sql)
13
+ end
14
+
15
+ it{ should eq("SELECT t1.sid, t1.name, t1.status, t1.city FROM suppliers AS t1 WHERE t1.city = 'London'") }
16
+ end
17
+
18
+ context 'when to_cog does support to_sql' do
19
+ let(:op) { restrict(suppliers, city: 'London') }
20
+
21
+ before do
22
+ def op.to_sql
23
+ :foo
24
+ end
25
+ end
26
+
27
+ it{ should eq(:foo) }
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Sql
4
+ describe Builder, "order_by_clause" do
5
+
6
+ let(:ordering){ Ordering.new([[:name, :asc], [:city, :desc]]) }
7
+
8
+ context 'without desaliaser' do
9
+ subject{ builder.order_by_clause(ordering) }
10
+
11
+ let(:expected){
12
+ [:order_by_clause,
13
+ [:order_by_term, [:column_name, 'name'], 'asc'],
14
+ [:order_by_term, [:column_name, 'city'], 'desc'] ]
15
+ }
16
+
17
+ it{ should eq(expected) }
18
+ end
19
+
20
+ context 'with a desaliaser' do
21
+ let(:desaliaser){
22
+ ->(a){
23
+ if a == "name"
24
+ [:qualified_name, [:range_var_name, "t1"], [:column_name, a]]
25
+ else
26
+ nil
27
+ end
28
+ }
29
+ }
30
+
31
+ subject{ builder.order_by_clause(ordering, &desaliaser) }
32
+
33
+ let(:expected){
34
+ [:order_by_clause,
35
+ [:order_by_term, [:qualified_name, [:range_var_name, "t1"], [:column_name, 'name']], 'asc'],
36
+ [:order_by_term, [:column_name, 'city'], 'desc'] ]
37
+ }
38
+
39
+ it{ should eq(expected) }
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,242 @@
1
+ module Helpers
2
+ module Ast
3
+
4
+ def sexpr(arg)
5
+ Alf::Sql::Grammar.sexpr(arg)
6
+ end
7
+
8
+ def with_exp(spec, selection = select_ab)
9
+ sexpr [:with_exp, with_spec(spec), selection]
10
+ end
11
+
12
+ def with_spec(spec = nil)
13
+ spec = {} if spec.nil?
14
+ sexpr spec.map{|k,v|
15
+ [:name_intro, [:table_name, k.to_s], v]
16
+ }.unshift(:with_spec)
17
+ end
18
+
19
+ def union(left = select_all, right = select_all_t2)
20
+ sexpr [:union, distinct, left, right]
21
+ end
22
+
23
+ def except(left = select_all, right = select_all_t2)
24
+ sexpr [:except, distinct, left, right]
25
+ end
26
+
27
+ def intersect(left = select_all, right = select_all_t2)
28
+ sexpr [:intersect, distinct, left, right]
29
+ end
30
+
31
+ def select_is_table_dee(where)
32
+ exists = Alf::Predicate::Grammar.sexpr([:exists, where])
33
+ sexpr [:select_exp, all,
34
+ [:select_list,
35
+ [:select_item,
36
+ [:literal, true],
37
+ [:column_name, "is_table_dee"]] ],
38
+ [:where_clause, exists] ]
39
+ end
40
+
41
+ def select_ab
42
+ sexpr [:select_exp, all, select_list, from_clause]
43
+ end
44
+
45
+ def select_a
46
+ sexpr [:select_exp, all, select_list_a, from_clause]
47
+ end
48
+
49
+ def select_distinct
50
+ sexpr [:select_exp, distinct, select_list, from_clause]
51
+ end
52
+
53
+ def select_distinct_star
54
+ sexpr [:select_exp, distinct, select_star, from_clause]
55
+ end
56
+
57
+ def select_distinct_ab
58
+ sexpr [:select_exp, distinct, select_list_ab, from_clause]
59
+ end
60
+
61
+ def select_distinct_a
62
+ sexpr [:select_exp, distinct, select_list_a, from_clause]
63
+ end
64
+
65
+ def select_all
66
+ sexpr [:select_exp, all, select_list, from_clause]
67
+ end
68
+
69
+ def select_all_star
70
+ sexpr [:select_exp, all, select_star, from_clause]
71
+ end
72
+
73
+ def select_all_from_t1_as_t2
74
+ sexpr [:select_exp, all, select_list_t2, from_clause_t1_as_t2]
75
+ end
76
+
77
+ def select_all_t2
78
+ sexpr [:select_exp, all, select_list_t2, from_clause_t2]
79
+ end
80
+
81
+ def select_all_t3
82
+ sexpr [:select_exp, all, select_list_t3, from_clause_t3]
83
+ end
84
+
85
+ def select_all_ab
86
+ sexpr [:select_exp, all, select_list_ab, from_clause]
87
+ end
88
+
89
+ def select_all_a
90
+ sexpr [:select_exp, all, select_list_a, from_clause]
91
+ end
92
+
93
+ def select_all_a_as_b
94
+ sexpr [:select_exp, all, select_list_a_as_b, from_clause]
95
+ end
96
+
97
+ def select_all_b
98
+ sexpr [:select_exp, all, select_list_b, from_clause]
99
+ end
100
+
101
+ def select_star
102
+ sexpr [:select_star]
103
+ end
104
+
105
+ def select_list(hash = {"a" => "a", "b" => "b"})
106
+ sexpr [:select_list] + hash.map{|(k,v)| select_item(k, v) }
107
+ end
108
+ alias :select_list_ab :select_list
109
+
110
+ def select_list_t2
111
+ sexpr [:select_list, select_item_a_t2, select_item_b_t2 ]
112
+ end
113
+
114
+ def select_list_t3
115
+ sexpr [:select_list, select_item_a_t3, select_item_b_t3 ]
116
+ end
117
+
118
+ def select_list_ab
119
+ sexpr [:select_list, select_item_a, select_item_b]
120
+ end
121
+
122
+ def select_list_ba
123
+ sexpr [:select_list, select_item_b, select_item_a]
124
+ end
125
+
126
+ def select_list_a
127
+ sexpr [:select_list, select_item_a]
128
+ end
129
+
130
+ def select_list_a_as_b
131
+ sexpr [:select_list, select_item("a","b")]
132
+ end
133
+
134
+ def select_list_b
135
+ sexpr [:select_list, select_item_b]
136
+ end
137
+
138
+ def select_item_a
139
+ select_item("a")
140
+ end
141
+
142
+ def select_item_a_t2
143
+ select_item(qualified_name("t2", "a"), "a")
144
+ end
145
+
146
+ def select_item_a_t3
147
+ select_item(qualified_name("t3", "a"), "a")
148
+ end
149
+
150
+ def select_item_b_t2
151
+ select_item(qualified_name("t2", "b"), "b")
152
+ end
153
+
154
+ def select_item_b_t3
155
+ select_item(qualified_name("t3", "b"), "b")
156
+ end
157
+
158
+ def select_item_b
159
+ select_item("b")
160
+ end
161
+
162
+ def select_item(name, as = name)
163
+ name = qualified_name("t1", name) unless name.is_a?(Array)
164
+ sexpr [:select_item, name, column_name(as)]
165
+ end
166
+
167
+ def column_name_a
168
+ column_name("a")
169
+ end
170
+
171
+ def column_name_b
172
+ column_name("b")
173
+ end
174
+
175
+ def column_name(x)
176
+ sexpr [:column_name, x]
177
+ end
178
+
179
+ def qualified_name_a
180
+ qualified_name("t1", "a")
181
+ end
182
+
183
+ def qualified_name_b
184
+ qualified_name("t2", "b")
185
+ end
186
+
187
+ def qualified_name(qualifier, name)
188
+ sexpr [:qualified_name, [:range_var_name, qualifier], [:column_name, name]]
189
+ end
190
+
191
+ def from_clause
192
+ sexpr [:from_clause, [:table_as, [:table_name, "t1"], [:range_var_name, "t1"]]]
193
+ end
194
+
195
+ def from_clause_t2
196
+ sexpr [:from_clause, [:table_as, [:table_name, "t2"], [:range_var_name, "t2"]]]
197
+ end
198
+
199
+ def from_clause_t1_as_t2
200
+ sexpr [:from_clause, [:table_as, [:table_name, "t1"], [:range_var_name, "t2"]]]
201
+ end
202
+
203
+ def from_clause_t3
204
+ sexpr [:from_clause, [:table_as, [:table_name, "t3"], [:range_var_name, "t3"]]]
205
+ end
206
+
207
+ def ordering
208
+ Alf::Ordering.new([[:a, :asc], [:b, :desc]])
209
+ end
210
+
211
+ def subordering
212
+ Alf::Ordering.new([[:a, :desc], [:b, :asc]])
213
+ end
214
+
215
+ def order_by_clause
216
+ [:order_by_clause,
217
+ order_by_term("a", "asc"),
218
+ order_by_term("b", "desc")]
219
+ end
220
+
221
+ def order_by_clause_2
222
+ [:order_by_clause,
223
+ order_by_term("a", "desc"),
224
+ order_by_term("b", "asc")]
225
+ end
226
+
227
+ def order_by_term(name, direction)
228
+ name = qualified_name("t1", name) unless name.is_a?(Array)
229
+ sexpr [:order_by_term, name, direction]
230
+ end
231
+
232
+ def distinct
233
+ [:set_quantifier, "distinct"]
234
+ end
235
+
236
+ def all
237
+ [:set_quantifier, "all"]
238
+ end
239
+
240
+ end
241
+ include Ast
242
+ end