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,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