bmg 0.9.1 → 0.10.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.
- checksums.yaml +4 -4
- data/lib/bmg/algebra.rb +2 -26
- data/lib/bmg/algebra/shortcuts.rb +14 -0
- data/lib/bmg/operator/autowrap.rb +32 -2
- data/lib/bmg/operator/constants.rb +12 -0
- data/lib/bmg/operator/image.rb +10 -0
- data/lib/bmg/operator/rename.rb +8 -0
- data/lib/bmg/relation/spied.rb +4 -9
- data/lib/bmg/sequel.rb +53 -2
- data/lib/bmg/sequel/relation.rb +24 -19
- data/lib/bmg/sequel/translator.rb +153 -0
- data/lib/bmg/sequel/type_inference.rb +42 -0
- data/lib/bmg/sql.rb +20 -0
- data/lib/bmg/sql/builder.rb +177 -0
- data/lib/bmg/sql/dialect.rb +15 -0
- data/lib/bmg/sql/ext/predicate.rb +23 -0
- data/lib/bmg/sql/ext/predicate/and.rb +9 -0
- data/lib/bmg/sql/ext/predicate/contradiction.rb +10 -0
- data/lib/bmg/sql/ext/predicate/dyadic_comp.rb +12 -0
- data/lib/bmg/sql/ext/predicate/eq.rb +9 -0
- data/lib/bmg/sql/ext/predicate/exists.rb +12 -0
- data/lib/bmg/sql/ext/predicate/expr.rb +18 -0
- data/lib/bmg/sql/ext/predicate/gt.rb +9 -0
- data/lib/bmg/sql/ext/predicate/gte.rb +9 -0
- data/lib/bmg/sql/ext/predicate/identifier.rb +10 -0
- data/lib/bmg/sql/ext/predicate/in.rb +29 -0
- data/lib/bmg/sql/ext/predicate/literal.rb +10 -0
- data/lib/bmg/sql/ext/predicate/lt.rb +9 -0
- data/lib/bmg/sql/ext/predicate/lte.rb +9 -0
- data/lib/bmg/sql/ext/predicate/nadic_bool.rb +16 -0
- data/lib/bmg/sql/ext/predicate/native.rb +9 -0
- data/lib/bmg/sql/ext/predicate/neq.rb +9 -0
- data/lib/bmg/sql/ext/predicate/not.rb +12 -0
- data/lib/bmg/sql/ext/predicate/or.rb +9 -0
- data/lib/bmg/sql/ext/predicate/qualified_identifier.rb +12 -0
- data/lib/bmg/sql/ext/predicate/tautology.rb +10 -0
- data/lib/bmg/sql/grammar.rb +45 -0
- data/lib/bmg/sql/grammar.sexp.yml +96 -0
- data/lib/bmg/sql/nodes/column_name.rb +25 -0
- data/lib/bmg/sql/nodes/cross_join.rb +28 -0
- data/lib/bmg/sql/nodes/except.rb +14 -0
- data/lib/bmg/sql/nodes/expr.rb +94 -0
- data/lib/bmg/sql/nodes/from_clause.rb +24 -0
- data/lib/bmg/sql/nodes/inner_join.rb +37 -0
- data/lib/bmg/sql/nodes/intersect.rb +14 -0
- data/lib/bmg/sql/nodes/limit_clause.rb +19 -0
- data/lib/bmg/sql/nodes/literal.rb +18 -0
- data/lib/bmg/sql/nodes/name_intro.rb +23 -0
- data/lib/bmg/sql/nodes/native_table_as.rb +31 -0
- data/lib/bmg/sql/nodes/offset_clause.rb +19 -0
- data/lib/bmg/sql/nodes/order_by_clause.rb +25 -0
- data/lib/bmg/sql/nodes/order_by_term.rb +30 -0
- data/lib/bmg/sql/nodes/qualified_name.rb +32 -0
- data/lib/bmg/sql/nodes/range_var_name.rb +17 -0
- data/lib/bmg/sql/nodes/select_exp.rb +109 -0
- data/lib/bmg/sql/nodes/select_item.rb +37 -0
- data/lib/bmg/sql/nodes/select_list.rb +35 -0
- data/lib/bmg/sql/nodes/select_star.rb +22 -0
- data/lib/bmg/sql/nodes/set_operator.rb +68 -0
- data/lib/bmg/sql/nodes/set_quantifier.rb +20 -0
- data/lib/bmg/sql/nodes/subquery_as.rb +28 -0
- data/lib/bmg/sql/nodes/table_as.rb +31 -0
- data/lib/bmg/sql/nodes/table_name.rb +17 -0
- data/lib/bmg/sql/nodes/union.rb +14 -0
- data/lib/bmg/sql/nodes/where_clause.rb +20 -0
- data/lib/bmg/sql/nodes/with_exp.rb +51 -0
- data/lib/bmg/sql/nodes/with_spec.rb +24 -0
- data/lib/bmg/sql/processor.rb +85 -0
- data/lib/bmg/sql/processor/all.rb +17 -0
- data/lib/bmg/sql/processor/clip.rb +57 -0
- data/lib/bmg/sql/processor/distinct.rb +17 -0
- data/lib/bmg/sql/processor/flatten.rb +24 -0
- data/lib/bmg/sql/processor/from_self.rb +29 -0
- data/lib/bmg/sql/processor/join.rb +80 -0
- data/lib/bmg/sql/processor/join_support.rb +28 -0
- data/lib/bmg/sql/processor/limit_offset.rb +30 -0
- data/lib/bmg/sql/processor/merge.rb +49 -0
- data/lib/bmg/sql/processor/order_by.rb +32 -0
- data/lib/bmg/sql/processor/rename.rb +25 -0
- data/lib/bmg/sql/processor/reorder.rb +21 -0
- data/lib/bmg/sql/processor/requalify.rb +24 -0
- data/lib/bmg/sql/processor/semi_join.rb +68 -0
- data/lib/bmg/sql/processor/star.rb +17 -0
- data/lib/bmg/sql/processor/where.rb +25 -0
- data/lib/bmg/sql/relation.rb +141 -0
- data/lib/bmg/sql/version.rb +16 -0
- data/lib/bmg/support.rb +1 -0
- data/lib/bmg/support/keys.rb +59 -0
- data/lib/bmg/type.rb +95 -14
- data/lib/bmg/version.rb +2 -2
- data/tasks/test.rake +9 -2
- metadata +97 -5
@@ -0,0 +1,16 @@
|
|
1
|
+
class Predicate
|
2
|
+
module NadicBool
|
3
|
+
|
4
|
+
def to_sql(buffer, dialect)
|
5
|
+
each_with_index do |child, index|
|
6
|
+
next if index == 0
|
7
|
+
unless index == 1
|
8
|
+
buffer << Sql::Expr::SPACE << to_sql_operator << Sql::Expr::SPACE
|
9
|
+
end
|
10
|
+
child.to_sql(buffer, dialect)
|
11
|
+
end
|
12
|
+
buffer
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
Grammar = Sexpr.load(Path.dir/'grammar.sexp.yml')
|
4
|
+
module Grammar
|
5
|
+
|
6
|
+
def tagging_reference
|
7
|
+
Sql
|
8
|
+
end
|
9
|
+
|
10
|
+
def default_tagging_module
|
11
|
+
Expr
|
12
|
+
end
|
13
|
+
|
14
|
+
end # module Grammar
|
15
|
+
end # module Sql
|
16
|
+
end # module Bmg
|
17
|
+
require_relative "nodes/expr"
|
18
|
+
require_relative "nodes/set_operator"
|
19
|
+
require_relative "nodes/literal"
|
20
|
+
require_relative "nodes/column_name"
|
21
|
+
require_relative "nodes/qualified_name"
|
22
|
+
require_relative "nodes/range_var_name"
|
23
|
+
require_relative "nodes/select_exp"
|
24
|
+
require_relative "nodes/set_quantifier"
|
25
|
+
require_relative "nodes/select_list"
|
26
|
+
require_relative "nodes/select_star"
|
27
|
+
require_relative "nodes/select_item"
|
28
|
+
require_relative "nodes/from_clause"
|
29
|
+
require_relative "nodes/table_as"
|
30
|
+
require_relative "nodes/native_table_as"
|
31
|
+
require_relative "nodes/subquery_as"
|
32
|
+
require_relative "nodes/table_name"
|
33
|
+
require_relative "nodes/order_by_clause"
|
34
|
+
require_relative "nodes/order_by_term"
|
35
|
+
require_relative "nodes/limit_clause"
|
36
|
+
require_relative "nodes/offset_clause"
|
37
|
+
require_relative "nodes/union"
|
38
|
+
require_relative "nodes/intersect"
|
39
|
+
require_relative "nodes/except"
|
40
|
+
require_relative "nodes/with_exp"
|
41
|
+
require_relative "nodes/with_spec"
|
42
|
+
require_relative "nodes/name_intro"
|
43
|
+
require_relative "nodes/where_clause"
|
44
|
+
require_relative "nodes/cross_join"
|
45
|
+
require_relative "nodes/inner_join"
|
@@ -0,0 +1,96 @@
|
|
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
|
+
- native_table_as
|
63
|
+
- table_as
|
64
|
+
- subquery_as
|
65
|
+
- join_exp
|
66
|
+
table_as:
|
67
|
+
- [ table_name, range_var_name ]
|
68
|
+
native_table_as:
|
69
|
+
- "::Object"
|
70
|
+
subquery_as:
|
71
|
+
- [ nonjoin_exp, range_var_name ]
|
72
|
+
scalar_exp:
|
73
|
+
- qualified_name
|
74
|
+
- column_name
|
75
|
+
- literal
|
76
|
+
qualified_name:
|
77
|
+
- [ range_var_name, column_name ]
|
78
|
+
column_name:
|
79
|
+
- [ name_rgx ]
|
80
|
+
table_name:
|
81
|
+
- [ name_rgx ]
|
82
|
+
range_var_name:
|
83
|
+
- [ name_rgx ]
|
84
|
+
limit_clause:
|
85
|
+
- [ integer ]
|
86
|
+
offset_clause:
|
87
|
+
- [ integer ]
|
88
|
+
integer:
|
89
|
+
- "::Integer"
|
90
|
+
literal:
|
91
|
+
- "::Object"
|
92
|
+
name_rgx:
|
93
|
+
!ruby/regexp /^[a-zA-Z0-9_]+$/
|
94
|
+
truth_value:
|
95
|
+
- "::TrueClass"
|
96
|
+
- "::FalseClass"
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Bmg
|
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, dialect)
|
19
|
+
buffer << dialect.quote_identifier(last)
|
20
|
+
buffer
|
21
|
+
end
|
22
|
+
|
23
|
+
end # module ColumnName
|
24
|
+
end # module Sql
|
25
|
+
end # module Bmg
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Bmg
|
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, dialect)
|
19
|
+
each_child do |child, index|
|
20
|
+
buffer << COMMA << SPACE unless index == 0
|
21
|
+
child.to_sql(buffer, dialect)
|
22
|
+
end
|
23
|
+
buffer
|
24
|
+
end
|
25
|
+
|
26
|
+
end # module CrossJoin
|
27
|
+
end # module Sql
|
28
|
+
end # module Bmg
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Bmg
|
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
|
+
def flatten
|
64
|
+
Processor::Flatten.new(nil).call(self)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def find_child(kind = nil, &search)
|
70
|
+
if search.nil? and kind
|
71
|
+
search = ->(x){ x.is_a?(Array) && x.first == kind }
|
72
|
+
end
|
73
|
+
each_child do |child|
|
74
|
+
return child if search.call(child)
|
75
|
+
end
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def find_child_index(kind)
|
80
|
+
each_with_index do |child,index|
|
81
|
+
return index if child.is_a?(Array) && child.first == kind
|
82
|
+
end
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
def sql_parenthesized(buffer)
|
87
|
+
buffer << LEFT_PARENTHESE
|
88
|
+
yield(buffer)
|
89
|
+
buffer << RIGHT_PARENTHESE
|
90
|
+
end
|
91
|
+
|
92
|
+
end # module Expr
|
93
|
+
end # module Sql
|
94
|
+
end # module Bmg
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Bmg
|
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, dialect)
|
17
|
+
buffer << FROM << SPACE
|
18
|
+
last.to_sql(buffer, dialect)
|
19
|
+
buffer
|
20
|
+
end
|
21
|
+
|
22
|
+
end # module FromClause
|
23
|
+
end # module Sql
|
24
|
+
end # module Bmg
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Bmg
|
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, dialect)
|
27
|
+
left.to_sql(buffer, dialect)
|
28
|
+
buffer << SPACE << JOIN << SPACE
|
29
|
+
right.to_sql(buffer, dialect)
|
30
|
+
buffer << SPACE << ON << SPACE
|
31
|
+
predicate.to_sql(buffer, dialect)
|
32
|
+
buffer
|
33
|
+
end
|
34
|
+
|
35
|
+
end # module InnerJoin
|
36
|
+
end # module Sql
|
37
|
+
end # module Bmg
|