bmg 0.15.0 → 0.16.0.pre.rc1
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/sequel/translator.rb +17 -17
- data/lib/bmg/sql.rb +1 -0
- data/lib/bmg/sql/processor/join.rb +1 -1
- data/lib/bmg/sql/support/from_clause_orderer.rb +120 -0
- data/lib/bmg/version.rb +2 -2
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d34f68bbc40a7dd25495cc9964074e20567c8d66
|
4
|
+
data.tar.gz: 9f6beb3a44b9da0a89e1bf523e9b02543e0ea136
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd37f8ad39cd7c05e7a725dfb305b8f8a3d74364d5abab1771f4a598c70d1b643b0b7046907f15fba7788645bfab5e302a4f48285b8ae1f6a7f3b7994a6f727b
|
7
|
+
data.tar.gz: ecd95510bde8bc27ed111a917a3e38add365db53faaf62df6f21d2ea2703f8e6d60ffb8428819af31862971cda7fa99112efbe04a610b61d590db1d8dca5c3ef
|
@@ -38,7 +38,7 @@ module Bmg
|
|
38
38
|
|
39
39
|
def on_select_exp(sexpr)
|
40
40
|
dataset = sequel_db.select(1)
|
41
|
-
dataset =
|
41
|
+
dataset = apply(sexpr.from_clause) if sexpr.from_clause
|
42
42
|
#
|
43
43
|
selection = apply(sexpr.select_list)
|
44
44
|
predicate = apply(sexpr.predicate) if sexpr.predicate
|
@@ -84,24 +84,28 @@ module Bmg
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def on_from_clause(sexpr)
|
87
|
-
|
87
|
+
orderer = Sql::Support::FromClauseOrderer.new
|
88
|
+
ordering = orderer.call(sexpr)
|
89
|
+
ordering.inject(nil) do |ds,(kind,table,on)|
|
90
|
+
if ds.nil?
|
91
|
+
dataset(apply(table))
|
92
|
+
elsif kind == :cross_join
|
93
|
+
ds.cross_join(apply(table))
|
94
|
+
elsif kind == :inner_join
|
95
|
+
options = { qualify: false, table_alias: false }
|
96
|
+
ds.join_table(:inner, apply(table), nil, options){|*args|
|
97
|
+
apply(on)
|
98
|
+
}
|
99
|
+
end
|
100
|
+
end
|
88
101
|
end
|
89
102
|
|
90
103
|
def on_table_name(sexpr)
|
91
104
|
::Sequel.expr(sexpr.last.to_sym)
|
92
105
|
end
|
93
106
|
|
94
|
-
def
|
95
|
-
|
96
|
-
dataset(left).cross_join(right)
|
97
|
-
end
|
98
|
-
|
99
|
-
def on_inner_join(sexpr)
|
100
|
-
left, right = apply(sexpr.left), apply(sexpr.right)
|
101
|
-
options = {qualify: false, table_alias: false}
|
102
|
-
dataset(left).join_table(:inner, right, nil, options){|*args|
|
103
|
-
apply(sexpr.predicate)
|
104
|
-
}
|
107
|
+
def on_native_table_as(sexpr)
|
108
|
+
sexpr[1].from_self(:alias => sexpr.as_name)
|
105
109
|
end
|
106
110
|
|
107
111
|
def on_table_as(sexpr)
|
@@ -112,10 +116,6 @@ module Bmg
|
|
112
116
|
::Sequel.as(apply(sexpr.subquery), ::Sequel.identifier(sexpr.as_name))
|
113
117
|
end
|
114
118
|
|
115
|
-
def on_native_table_as(sexpr)
|
116
|
-
sexpr[1].from_self(:alias => sexpr.as_name)
|
117
|
-
end
|
118
|
-
|
119
119
|
def on_order_by_clause(sexpr)
|
120
120
|
sexpr.sexpr_body.map{|c| apply(c)}
|
121
121
|
end
|
data/lib/bmg/sql.rb
CHANGED
@@ -0,0 +1,120 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
module Support
|
4
|
+
class FromClauseOrderer
|
5
|
+
|
6
|
+
# Takes a from_clause AST as input and generates an relationally
|
7
|
+
# equivalent list of (type,table,predicate) triplets, where:
|
8
|
+
#
|
9
|
+
# - type is :base, :cross_join or :inner_join
|
10
|
+
# - table is table_as, native_table_as or subquery_as
|
11
|
+
# - predicate is a join predicate
|
12
|
+
#
|
13
|
+
# The types are observed in strict increasing order
|
14
|
+
# (one :base, zero or more :cross_join, zero or more
|
15
|
+
# :inner_join). The list is such that it can be safely
|
16
|
+
# written as an expression of the following SQL form:
|
17
|
+
#
|
18
|
+
# t1 # [ :base, t1, nil ]
|
19
|
+
# cross_join t2 # [ :cross_join, t2, nil ]
|
20
|
+
# cross_join t3 # [ :cross_join, t3, nil ]
|
21
|
+
# inner_join t4 ON p4 # [ :inner_join, t4, p4 ]
|
22
|
+
# inner_join t5 ON p5 # [ :inner_join, t5, p5 ]
|
23
|
+
#
|
24
|
+
# A NotImplementedError may be raised if no linearization can
|
25
|
+
# be found.
|
26
|
+
#
|
27
|
+
def call(sexpr)
|
28
|
+
tables, joins = collect(sexpr)
|
29
|
+
order_all(tables, joins)
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def order_all(tables, joins, result = [])
|
35
|
+
if tables.empty? and joins.empty?
|
36
|
+
result
|
37
|
+
elsif tables.empty?
|
38
|
+
raise NotImplementedError, "Orphan joins: `#{joins.inspect}`"
|
39
|
+
else
|
40
|
+
table, tables_tail = tables.first, tables[1..-1]
|
41
|
+
on, joins_tail = split_joins(joins, table, tables_tail)
|
42
|
+
join_kind = result.empty? ? :base : (on.empty? ? :cross_join : :inner_join)
|
43
|
+
predicate = on.inject(nil){|p,clause|
|
44
|
+
p.nil? ? clause : Predicate::Factory.and(p, clause)
|
45
|
+
}
|
46
|
+
clause = [ join_kind, table, predicate ]
|
47
|
+
order_all(tables_tail, joins_tail, result + [clause])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def split_joins(joins, table, tables_tail)
|
52
|
+
joins.partition{|j|
|
53
|
+
uses?(j, table) && !tables_tail.find{|t|
|
54
|
+
uses?(j, t)
|
55
|
+
}
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
protected
|
60
|
+
|
61
|
+
def collect(sexpr)
|
62
|
+
tables = []
|
63
|
+
joins = []
|
64
|
+
_collect(sexpr, tables, joins)
|
65
|
+
tables.sort!{|t1,t2|
|
66
|
+
t1js = joins.select{|j| uses?(j, t1) }.size
|
67
|
+
t2js = joins.select{|j| uses?(j, t2) }.size
|
68
|
+
t1js == 0 ? (t2js == 0 ? 0 : -1) : (t2js == 0 ? 1 : 0)
|
69
|
+
}
|
70
|
+
[ tables, joins ]
|
71
|
+
end
|
72
|
+
|
73
|
+
def _collect(sexpr, tables, joins)
|
74
|
+
case sexpr.first
|
75
|
+
when :from_clause
|
76
|
+
_collect(sexpr.table_spec, tables, joins)
|
77
|
+
when :table_as, :native_table_as, :subquery_as
|
78
|
+
tables << sexpr
|
79
|
+
when :inner_join
|
80
|
+
_collect_joins(sexpr.predicate, joins)
|
81
|
+
_collect(sexpr.left, tables, joins)
|
82
|
+
_collect(sexpr.right, tables, joins)
|
83
|
+
when :cross_join
|
84
|
+
_collect(sexpr.left, tables, joins)
|
85
|
+
_collect(sexpr.right, tables, joins)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def _collect_joins(sexpr, joins)
|
90
|
+
case sexpr.first
|
91
|
+
when :and
|
92
|
+
_collect_joins(sexpr[1], joins)
|
93
|
+
_collect_joins(sexpr[2], joins)
|
94
|
+
when :eq
|
95
|
+
joins << sexpr
|
96
|
+
else
|
97
|
+
raise NotImplementedError, "Unexpected predicate `#{sexpr.inspect}`"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def uses?(join, table)
|
102
|
+
name = table.as_name.to_s
|
103
|
+
left_name = var_name(join[1])
|
104
|
+
right_name = var_name(join[2])
|
105
|
+
(left_name == name) or (right_name == name)
|
106
|
+
end
|
107
|
+
|
108
|
+
def var_name(qualified)
|
109
|
+
case qualified.first
|
110
|
+
when :qualified_identifier then qualified[1].to_s
|
111
|
+
when :qualified_name then qualified[1][1].to_s
|
112
|
+
else
|
113
|
+
raise NotImplementedError, "Unexpected qualified name `#{qualified.inspect}`"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end # class FromClauseOrderer
|
118
|
+
end # module Support
|
119
|
+
end # module Sql
|
120
|
+
end # module Bmg
|
data/lib/bmg/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bmg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0.pre.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernard Lambeau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01
|
11
|
+
date: 2019-02-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: predicate
|
@@ -213,6 +213,7 @@ files:
|
|
213
213
|
- lib/bmg/sql/processor/star.rb
|
214
214
|
- lib/bmg/sql/processor/where.rb
|
215
215
|
- lib/bmg/sql/relation.rb
|
216
|
+
- lib/bmg/sql/support/from_clause_orderer.rb
|
216
217
|
- lib/bmg/sql/version.rb
|
217
218
|
- lib/bmg/support.rb
|
218
219
|
- lib/bmg/support/keys.rb
|
@@ -236,9 +237,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
236
237
|
version: '0'
|
237
238
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
238
239
|
requirements:
|
239
|
-
- - "
|
240
|
+
- - ">"
|
240
241
|
- !ruby/object:Gem::Version
|
241
|
-
version:
|
242
|
+
version: 1.3.1
|
242
243
|
requirements: []
|
243
244
|
rubyforge_project:
|
244
245
|
rubygems_version: 2.5.2
|