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,92 @@
1
+ rules:
2
+ query:
3
+ - with_exp
4
+ - nonjoin_exp
5
+ with_exp:
6
+ - [ with_spec, nonjoin_exp ]
7
+ with_spec:
8
+ - [ name_intro+ ]
9
+ name_intro:
10
+ - [ table_name, nonjoin_exp ]
11
+ nonjoin_exp:
12
+ - union
13
+ - except
14
+ - intersect
15
+ - select_exp
16
+ union:
17
+ - [ all, nonjoin_exp, nonjoin_exp ]
18
+ all:
19
+ - truth_value
20
+ except:
21
+ - [ set_quantifier, nonjoin_exp, nonjoin_exp ]
22
+ intersect:
23
+ - [ set_quantifier, nonjoin_exp, nonjoin_exp ]
24
+ join_exp:
25
+ - cross_join
26
+ - inner_join
27
+ cross_join:
28
+ - [ table_spec, table_spec ]
29
+ inner_join:
30
+ - [ table_spec, table_spec, predicate ]
31
+ using:
32
+ - [ column_name+ ]
33
+ select_exp:
34
+ - [ set_quantifier,
35
+ [ select_list, select_star ],
36
+ from_clause,
37
+ where_clause,
38
+ order_by_clause,
39
+ limit_clause,
40
+ offset_clause ]
41
+ set_quantifier:
42
+ - [ set_quantifier_name ]
43
+ select_star:
44
+ - []
45
+ set_quantifier_name:
46
+ !ruby/regexp /^all|distinct$/
47
+ select_list:
48
+ - [ select_item+ ]
49
+ from_clause:
50
+ - [ table_spec ]
51
+ where_clause:
52
+ - [ predicate ]
53
+ order_by_clause:
54
+ - [ order_by_term+ ]
55
+ order_by_term:
56
+ - [ qualified_name, direction ]
57
+ direction:
58
+ !ruby/regexp /^asc|desc$/
59
+ select_item:
60
+ - [ scalar_exp, column_name ]
61
+ table_spec:
62
+ - table_as
63
+ - subquery_as
64
+ - join_exp
65
+ table_as:
66
+ - [ table_name, range_var_name ]
67
+ subquery_as:
68
+ - [ nonjoin_exp, range_var_name ]
69
+ scalar_exp:
70
+ - qualified_name
71
+ - column_name
72
+ - literal
73
+ qualified_name:
74
+ - [ range_var_name, column_name ]
75
+ column_name:
76
+ - [ name_rgx ]
77
+ table_name:
78
+ - [ name_rgx ]
79
+ range_var_name:
80
+ - [ name_rgx ]
81
+ limit_clause:
82
+ - [ integer ]
83
+ offset_clause:
84
+ - [ integer ]
85
+ integer:
86
+ - "::Integer"
87
+ literal:
88
+ - "::Object"
89
+ name_rgx:
90
+ !ruby/regexp /^[a-zA-Z0-9_]+$/
91
+ truth_value:
92
+ "::Alf::Boolean"
@@ -0,0 +1,2 @@
1
+ require "alf-core"
2
+ require "sexpr"
@@ -0,0 +1,25 @@
1
+ module Alf
2
+ module Sql
3
+ module ColumnName
4
+ include Expr
5
+
6
+ def qualifier
7
+ nil
8
+ end
9
+
10
+ def as_name
11
+ last
12
+ end
13
+
14
+ def would_be_name
15
+ last
16
+ end
17
+
18
+ def to_sql(buffer = "")
19
+ buffer << last
20
+ buffer
21
+ end
22
+
23
+ end # module ColumnName
24
+ end # module Sql
25
+ end # module Alf
@@ -0,0 +1,28 @@
1
+ module Alf
2
+ module Sql
3
+ module CrossJoin
4
+ include Expr
5
+
6
+ def join?
7
+ true
8
+ end
9
+
10
+ def left
11
+ self[1]
12
+ end
13
+
14
+ def right
15
+ self[2]
16
+ end
17
+
18
+ def to_sql(buffer = "")
19
+ each_child do |child, index|
20
+ buffer << COMMA << SPACE unless index == 0
21
+ child.to_sql(buffer)
22
+ end
23
+ buffer
24
+ end
25
+
26
+ end # module CrossJoin
27
+ end # module Sql
28
+ end # module Alf
@@ -0,0 +1,14 @@
1
+ module Alf
2
+ module Sql
3
+ module Except
4
+ include SetOperator
5
+
6
+ EXCEPT = "EXCEPT".freeze
7
+
8
+ def keyword
9
+ EXCEPT
10
+ end
11
+
12
+ end # module Except
13
+ end # module Sql
14
+ end # module Alf
@@ -0,0 +1,90 @@
1
+ module Alf
2
+ module Sql
3
+ module Expr
4
+
5
+ LEFT_PARENTHESE = "(".freeze
6
+ RIGHT_PARENTHESE = ")".freeze
7
+ SPACE = " ".freeze
8
+ COMMA = ",".freeze
9
+ DOT = ".".freeze
10
+ QUOTE = "'".freeze
11
+ AS = "AS".freeze
12
+ AND = "AND".freeze
13
+ OR = "OR".freeze
14
+ NOT = "NOT".freeze
15
+ TRUE = "TRUE".freeze
16
+ FALSE = "FALSE".freeze
17
+ EQUAL = "=".freeze
18
+ NOT_EQUAL = "<>".freeze
19
+ GREATER = ">".freeze
20
+ LESS = "<".freeze
21
+ GREATER_OR_EQUAL = ">=".freeze
22
+ LESS_OR_EQUAL = "<=".freeze
23
+ IN = "IN".freeze
24
+ EXISTS = "EXISTS".freeze
25
+
26
+ def set_operator?
27
+ false
28
+ end
29
+
30
+ def limit_or_offset?
31
+ not(limit_clause.nil? and offset_clause.nil?)
32
+ end
33
+
34
+ def join?
35
+ false
36
+ end
37
+
38
+ def ordering
39
+ obc = order_by_clause
40
+ obc && order_by_clause.to_ordering
41
+ end
42
+
43
+ def with_update(index, what)
44
+ index = find_child_index(index) if index.is_a?(Symbol)
45
+ dup.tap{|x| x[index] = Grammar.sexpr(what) }
46
+ end
47
+
48
+ def with_insert(index, what)
49
+ dup.tap{|x| x.insert(index, Grammar.sexpr(what)) }
50
+ end
51
+
52
+ def with_push(*sexprs)
53
+ dup.push(*sexprs)
54
+ end
55
+
56
+ def each_child(skip = 0)
57
+ each_with_index do |c,i|
58
+ next if i <= skip
59
+ yield(c, i - 1)
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def find_child(kind = nil, &search)
66
+ if search.nil? and kind
67
+ search = ->(x){ x.is_a?(Array) && x.first == kind }
68
+ end
69
+ each_child do |child|
70
+ return child if search.call(child)
71
+ end
72
+ nil
73
+ end
74
+
75
+ def find_child_index(kind)
76
+ each_with_index do |child,index|
77
+ return index if child.is_a?(Array) && child.first == kind
78
+ end
79
+ nil
80
+ end
81
+
82
+ def sql_parenthesized(buffer)
83
+ buffer << LEFT_PARENTHESE
84
+ yield(buffer)
85
+ buffer << RIGHT_PARENTHESE
86
+ end
87
+
88
+ end # module Expr
89
+ end # module Sql
90
+ end # module Alf
@@ -0,0 +1,24 @@
1
+ module Alf
2
+ module Sql
3
+ module FromClause
4
+ include Expr
5
+
6
+ FROM = "FROM".freeze
7
+
8
+ def table_spec
9
+ last
10
+ end
11
+
12
+ def join?
13
+ table_spec.join?
14
+ end
15
+
16
+ def to_sql(buffer = "")
17
+ buffer << FROM << SPACE
18
+ last.to_sql(buffer)
19
+ buffer
20
+ end
21
+
22
+ end # module FromClause
23
+ end # module Sql
24
+ end # module Alf
@@ -0,0 +1,37 @@
1
+ module Alf
2
+ module Sql
3
+ module InnerJoin
4
+ include Expr
5
+
6
+ INNER = "INNER".freeze
7
+ JOIN = "JOIN".freeze
8
+ ON = "ON".freeze
9
+
10
+ def join?
11
+ true
12
+ end
13
+
14
+ def left
15
+ self[1]
16
+ end
17
+
18
+ def right
19
+ self[2]
20
+ end
21
+
22
+ def predicate
23
+ last
24
+ end
25
+
26
+ def to_sql(buffer = "")
27
+ left.to_sql(buffer)
28
+ buffer << SPACE << JOIN << SPACE
29
+ right.to_sql(buffer)
30
+ buffer << SPACE << ON << SPACE
31
+ predicate.to_sql(buffer)
32
+ buffer
33
+ end
34
+
35
+ end # module InnerJoin
36
+ end # module Sql
37
+ end # module Alf
@@ -0,0 +1,14 @@
1
+ module Alf
2
+ module Sql
3
+ module Intersect
4
+ include SetOperator
5
+
6
+ INTERSECT = "INTERSECT".freeze
7
+
8
+ def keyword
9
+ INTERSECT
10
+ end
11
+
12
+ end # module Intersect
13
+ end # module Sql
14
+ end # module Alf
@@ -0,0 +1,19 @@
1
+ module Alf
2
+ module Sql
3
+ module LimitClause
4
+ include Expr
5
+
6
+ LIMIT = "LIMIT"
7
+
8
+ def limit
9
+ last.to_i
10
+ end
11
+
12
+ def to_sql(buffer = "")
13
+ buffer << LIMIT << SPACE << limit.to_s
14
+ buffer
15
+ end
16
+
17
+ end # module LimitClause
18
+ end # module Sql
19
+ end # module Alf
@@ -0,0 +1,18 @@
1
+ module Alf
2
+ module Sql
3
+ module Literal
4
+ include Expr
5
+ include Alf::Predicate::Expr
6
+
7
+ def would_be_name
8
+ nil
9
+ end
10
+
11
+ def to_sql(buffer = "")
12
+ to_sql_literal(buffer, last)
13
+ buffer
14
+ end
15
+
16
+ end # module Literal
17
+ end # module Sql
18
+ end # module Alf
@@ -0,0 +1,23 @@
1
+ module Alf
2
+ module Sql
3
+ module NameIntro
4
+ include Expr
5
+
6
+ def table_name
7
+ self[1]
8
+ end
9
+
10
+ def subquery
11
+ self[2]
12
+ end
13
+
14
+ def to_sql(buffer = "")
15
+ table_name.to_sql(buffer)
16
+ buffer << SPACE << AS << SPACE
17
+ subquery.to_sql(buffer, true)
18
+ buffer
19
+ end
20
+
21
+ end # module WithSpec
22
+ end # module Sql
23
+ end # module Alf
@@ -0,0 +1,19 @@
1
+ module Alf
2
+ module Sql
3
+ module OffsetClause
4
+ include Expr
5
+
6
+ OFFSET = "OFFSET"
7
+
8
+ def offset
9
+ last.to_i
10
+ end
11
+
12
+ def to_sql(buffer = "")
13
+ buffer << OFFSET << SPACE << offset.to_s
14
+ buffer
15
+ end
16
+
17
+ end # module OffsetClause
18
+ end # module Sql
19
+ end # module Alf
@@ -0,0 +1,25 @@
1
+ module Alf
2
+ module Sql
3
+ module OrderByClause
4
+ include Expr
5
+
6
+ ORDER_BY = "ORDER BY".freeze
7
+
8
+ def to_ordering
9
+ @ordering ||= Ordering.new(sexpr_body.map{|x|
10
+ [x.as_name, x.direction]
11
+ })
12
+ end
13
+
14
+ def to_sql(buffer = "")
15
+ buffer << ORDER_BY << SPACE
16
+ each_child do |item,index|
17
+ buffer << COMMA << SPACE unless index == 0
18
+ item.to_sql(buffer)
19
+ end
20
+ buffer
21
+ end
22
+
23
+ end # module OrderByClause
24
+ end # module Sql
25
+ end # module Alf