alf-sql 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +38 -0
- data/LICENCE.md +22 -0
- data/Manifest.txt +12 -0
- data/README.md +52 -0
- data/Rakefile +11 -0
- data/lib/alf-sql.rb +1 -0
- data/lib/alf/algebra/operand.rb +18 -0
- data/lib/alf/predicate/nodes.rb +20 -0
- data/lib/alf/predicate/nodes/and.rb +11 -0
- data/lib/alf/predicate/nodes/contradiction.rb +12 -0
- data/lib/alf/predicate/nodes/dyadic_comp.rb +14 -0
- data/lib/alf/predicate/nodes/eq.rb +11 -0
- data/lib/alf/predicate/nodes/exists.rb +14 -0
- data/lib/alf/predicate/nodes/expr.rb +20 -0
- data/lib/alf/predicate/nodes/gt.rb +11 -0
- data/lib/alf/predicate/nodes/gte.rb +11 -0
- data/lib/alf/predicate/nodes/identifier.rb +12 -0
- data/lib/alf/predicate/nodes/in.rb +31 -0
- data/lib/alf/predicate/nodes/literal.rb +12 -0
- data/lib/alf/predicate/nodes/lt.rb +11 -0
- data/lib/alf/predicate/nodes/lte.rb +11 -0
- data/lib/alf/predicate/nodes/nadic_bool.rb +18 -0
- data/lib/alf/predicate/nodes/native.rb +11 -0
- data/lib/alf/predicate/nodes/neq.rb +11 -0
- data/lib/alf/predicate/nodes/not.rb +14 -0
- data/lib/alf/predicate/nodes/or.rb +11 -0
- data/lib/alf/predicate/nodes/qualified_identifier.rb +12 -0
- data/lib/alf/predicate/nodes/tautology.rb +12 -0
- data/lib/alf/sql.rb +15 -0
- data/lib/alf/sql/builder.rb +152 -0
- data/lib/alf/sql/cog.rb +32 -0
- data/lib/alf/sql/compiler.rb +137 -0
- data/lib/alf/sql/grammar.rb +44 -0
- data/lib/alf/sql/grammar.sexp.yml +92 -0
- data/lib/alf/sql/loader.rb +2 -0
- data/lib/alf/sql/nodes/column_name.rb +25 -0
- data/lib/alf/sql/nodes/cross_join.rb +28 -0
- data/lib/alf/sql/nodes/except.rb +14 -0
- data/lib/alf/sql/nodes/expr.rb +90 -0
- data/lib/alf/sql/nodes/from_clause.rb +24 -0
- data/lib/alf/sql/nodes/inner_join.rb +37 -0
- data/lib/alf/sql/nodes/intersect.rb +14 -0
- data/lib/alf/sql/nodes/limit_clause.rb +19 -0
- data/lib/alf/sql/nodes/literal.rb +18 -0
- data/lib/alf/sql/nodes/name_intro.rb +23 -0
- data/lib/alf/sql/nodes/offset_clause.rb +19 -0
- data/lib/alf/sql/nodes/order_by_clause.rb +25 -0
- data/lib/alf/sql/nodes/order_by_term.rb +30 -0
- data/lib/alf/sql/nodes/qualified_name.rb +32 -0
- data/lib/alf/sql/nodes/range_var_name.rb +17 -0
- data/lib/alf/sql/nodes/select_exp.rb +101 -0
- data/lib/alf/sql/nodes/select_item.rb +37 -0
- data/lib/alf/sql/nodes/select_list.rb +31 -0
- data/lib/alf/sql/nodes/select_star.rb +15 -0
- data/lib/alf/sql/nodes/set_operator.rb +64 -0
- data/lib/alf/sql/nodes/set_quantifier.rb +20 -0
- data/lib/alf/sql/nodes/subquery_as.rb +28 -0
- data/lib/alf/sql/nodes/table_as.rb +31 -0
- data/lib/alf/sql/nodes/table_name.rb +17 -0
- data/lib/alf/sql/nodes/union.rb +14 -0
- data/lib/alf/sql/nodes/where_clause.rb +20 -0
- data/lib/alf/sql/nodes/with_exp.rb +50 -0
- data/lib/alf/sql/nodes/with_spec.rb +24 -0
- data/lib/alf/sql/processor.rb +85 -0
- data/lib/alf/sql/processor/all.rb +17 -0
- data/lib/alf/sql/processor/clip.rb +39 -0
- data/lib/alf/sql/processor/distinct.rb +17 -0
- data/lib/alf/sql/processor/flatten.rb +24 -0
- data/lib/alf/sql/processor/from_self.rb +29 -0
- data/lib/alf/sql/processor/join.rb +80 -0
- data/lib/alf/sql/processor/join_support.rb +27 -0
- data/lib/alf/sql/processor/limit_offset.rb +30 -0
- data/lib/alf/sql/processor/merge.rb +42 -0
- data/lib/alf/sql/processor/order_by.rb +32 -0
- data/lib/alf/sql/processor/rename.rb +25 -0
- data/lib/alf/sql/processor/reorder.rb +21 -0
- data/lib/alf/sql/processor/requalify.rb +24 -0
- data/lib/alf/sql/processor/semi_join.rb +57 -0
- data/lib/alf/sql/processor/star.rb +17 -0
- data/lib/alf/sql/processor/where.rb +25 -0
- data/lib/alf/sql/version.rb +16 -0
- data/spec/algebra/operand/test_to_sql.rb +32 -0
- data/spec/builder/test_order_by_clause.rb +44 -0
- data/spec/helpers/ast.rb +242 -0
- data/spec/helpers/compiler.rb +23 -0
- data/spec/nodes/column_name/test_as_name.rb +14 -0
- data/spec/nodes/column_name/test_qualifier.rb +14 -0
- data/spec/nodes/order_by_clause/test_to_ordering.rb +30 -0
- data/spec/nodes/order_by_term/test_as_name.rb +22 -0
- data/spec/nodes/order_by_term/test_direction.rb +22 -0
- data/spec/nodes/order_by_term/test_qualifier.rb +22 -0
- data/spec/nodes/select_exp/test_order_by_clause.rb +22 -0
- data/spec/nodes/select_item/test_as_name.rb +22 -0
- data/spec/predicate/nodes/exists/test_not.rb +20 -0
- data/spec/processor/clip/test_on_select_exp.rb +32 -0
- data/spec/processor/clip/test_on_select_list.rb +24 -0
- data/spec/processor/distinct/test_on_set_quantified.rb +31 -0
- data/spec/processor/from_self/test_on_nonjoin_exp.rb +60 -0
- data/spec/processor/from_self/test_on_with_exp.rb +22 -0
- data/spec/processor/merge/test_on_select_exp.rb +73 -0
- data/spec/processor/merge/test_on_with_exp.rb +56 -0
- data/spec/processor/order_by/test_on_select_exp.rb +24 -0
- data/spec/processor/rename/test_on_select_item.rb +30 -0
- data/spec/processor/rename/test_on_select_list.rb +22 -0
- data/spec/processor/reorder/test_on_select_list.rb +22 -0
- data/spec/processor/requalify/test_on_select_exp.rb +24 -0
- data/spec/processor/star/test_on_select_exp.rb +24 -0
- data/spec/processor/test_clip.rb +24 -0
- data/spec/processor/test_distinct.rb +24 -0
- data/spec/processor/test_on_select_exp.rb +28 -0
- data/spec/processor/test_on_set_operator.rb +28 -0
- data/spec/processor/test_rename.rb +24 -0
- data/spec/shared/compiled_examples.rb +13 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/test_sql.rb +10 -0
- data/tasks/bench.rake +40 -0
- data/tasks/gem.rake +8 -0
- data/tasks/test.rake +6 -0
- metadata +235 -0
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ../alf-core
|
3
|
+
specs:
|
4
|
+
alf-core (0.15.0)
|
5
|
+
domain (~> 1.0)
|
6
|
+
myrrha (~> 3.0)
|
7
|
+
path (~> 1.3)
|
8
|
+
sexpr (~> 0.6.0)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: http://rubygems.org/
|
12
|
+
specs:
|
13
|
+
awesome_print (1.2.0)
|
14
|
+
diff-lcs (1.2.4)
|
15
|
+
domain (1.0.0)
|
16
|
+
myrrha (3.0.0)
|
17
|
+
domain (~> 1.0)
|
18
|
+
path (1.3.3)
|
19
|
+
rake (10.1.0)
|
20
|
+
rspec (2.14.1)
|
21
|
+
rspec-core (~> 2.14.0)
|
22
|
+
rspec-expectations (~> 2.14.0)
|
23
|
+
rspec-mocks (~> 2.14.0)
|
24
|
+
rspec-core (2.14.7)
|
25
|
+
rspec-expectations (2.14.3)
|
26
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
27
|
+
rspec-mocks (2.14.4)
|
28
|
+
sexpr (0.6.0)
|
29
|
+
|
30
|
+
PLATFORMS
|
31
|
+
ruby
|
32
|
+
|
33
|
+
DEPENDENCIES
|
34
|
+
alf-core!
|
35
|
+
awesome_print
|
36
|
+
rake (~> 10.1)
|
37
|
+
rspec (~> 2.14)
|
38
|
+
sexpr (~> 0.6.0)
|
data/LICENCE.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# The MIT Licence
|
2
|
+
|
3
|
+
Copyright (c) 2013 - Bernard Lambeau
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
ADDED
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Alf::Sql
|
2
|
+
|
3
|
+
[![Build Status](https://secure.travis-ci.org/alf-tool/alf-sql.png)](http://travis-ci.org/alf-tool/alf-sql)
|
4
|
+
[![Dependency Status](https://gemnasium.com/alf-tool/alf-sql.png)](https://gemnasium.com/alf-tool/alf-sql)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/alf-tool/alf-sql.png)](https://codeclimate.com/github/alf-tool/alf-sql)
|
6
|
+
|
7
|
+
An abstract SQL compiler for Alf expressions
|
8
|
+
|
9
|
+
## Links
|
10
|
+
|
11
|
+
* [http://github.com/alf-tool/alf](http://github.com/alf-tool/alf#synopsis)
|
12
|
+
* [http://github.com/alf-tool/alf-sql](http://github.com/alf-tool/alf-sql#synopsis)
|
13
|
+
* [http://github.com/alf-tool/alf-sequel](http://github.com/alf-tool/alf-sequel#synopsis)
|
14
|
+
|
15
|
+
## Synopsis
|
16
|
+
|
17
|
+
This sub-module provides an abstract SQL compiler for Alf expressions. It is
|
18
|
+
NOT aimed at being used by end-users (the API illustrated below is considered
|
19
|
+
private and may change at any time). Instead, it provides a basis for concrete
|
20
|
+
translators converting the resulting SQL abstract syntax tree to a concrete SQL
|
21
|
+
dialect through third-party libraries.
|
22
|
+
|
23
|
+
See [alf-sequel](https://github.com/alf-tool/alf-sequel) for a translator built
|
24
|
+
on top of [Sequel](http://sequel.rubyforge.org/).
|
25
|
+
|
26
|
+
## Example
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
require 'alf-sql'
|
30
|
+
|
31
|
+
Alf.connect("sap.db") do |conn|
|
32
|
+
# Let parse some relational expression
|
33
|
+
expr = conn.parse{
|
34
|
+
restrict(suppliers, city: 'London')
|
35
|
+
}
|
36
|
+
|
37
|
+
# Translate to SQL
|
38
|
+
# (non-portable SQL output unless you require alf-sequel as well)
|
39
|
+
puts expr.to_sql
|
40
|
+
# => SELECT t1.sid, t1.name, t1.status, t1.city
|
41
|
+
# FROM suppliers AS t1
|
42
|
+
# WHERE t1.city = 'London'
|
43
|
+
|
44
|
+
# Alternatively (for translator implementers),
|
45
|
+
# compile to an abstract cog (cannot be iterated)
|
46
|
+
cog = Alf::Sql::Compiler.new.call(expr)
|
47
|
+
|
48
|
+
# Let see the SQL AST
|
49
|
+
puts cog.to_sexpr.inspect
|
50
|
+
# => [ :select_exp, [:select_list, ...] ]
|
51
|
+
end
|
52
|
+
```
|
data/Rakefile
ADDED
data/lib/alf-sql.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "alf/sql"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Alf
|
2
|
+
module Algebra
|
3
|
+
module Operand
|
4
|
+
|
5
|
+
def to_sql
|
6
|
+
cog = to_cog
|
7
|
+
if cog.respond_to?(:to_sql)
|
8
|
+
cog.to_sql
|
9
|
+
else
|
10
|
+
Alf::Sql::Compiler.new.call(self).to_sql
|
11
|
+
end
|
12
|
+
rescue NotSupportedError => ex
|
13
|
+
raise NotSupportedError, "Unable to compile `#{self}` to SQL"
|
14
|
+
end
|
15
|
+
|
16
|
+
end # module Operand
|
17
|
+
end # module Algebra
|
18
|
+
end # module Alf
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'nodes/expr'
|
2
|
+
require_relative 'nodes/dyadic_comp'
|
3
|
+
require_relative 'nodes/nadic_bool'
|
4
|
+
require_relative 'nodes/tautology'
|
5
|
+
require_relative 'nodes/contradiction'
|
6
|
+
require_relative 'nodes/identifier'
|
7
|
+
require_relative 'nodes/qualified_identifier'
|
8
|
+
require_relative 'nodes/and'
|
9
|
+
require_relative 'nodes/or'
|
10
|
+
require_relative 'nodes/not'
|
11
|
+
require_relative 'nodes/eq'
|
12
|
+
require_relative 'nodes/neq'
|
13
|
+
require_relative 'nodes/gt'
|
14
|
+
require_relative 'nodes/gte'
|
15
|
+
require_relative 'nodes/lt'
|
16
|
+
require_relative 'nodes/lte'
|
17
|
+
require_relative 'nodes/in'
|
18
|
+
require_relative 'nodes/exists'
|
19
|
+
require_relative 'nodes/literal'
|
20
|
+
require_relative 'nodes/native'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Alf
|
2
|
+
class Predicate
|
3
|
+
module Expr
|
4
|
+
|
5
|
+
def to_sql_literal(buffer, value)
|
6
|
+
case value
|
7
|
+
when TrueClass
|
8
|
+
buffer << Sql::Expr::TRUE
|
9
|
+
when FalseClass
|
10
|
+
buffer << Sql::Expr::FALSE
|
11
|
+
when Integer, Float
|
12
|
+
buffer << value.to_s
|
13
|
+
else
|
14
|
+
buffer << Sql::Expr::QUOTE << value.to_s << Sql::Expr::QUOTE
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Alf
|
2
|
+
class Predicate
|
3
|
+
module In
|
4
|
+
|
5
|
+
def subquery?
|
6
|
+
Sql::Expr === last
|
7
|
+
end
|
8
|
+
|
9
|
+
def subquery
|
10
|
+
subquery? ? last : nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_sql(buffer = "")
|
14
|
+
identifier.to_sql(buffer)
|
15
|
+
buffer << Sql::Expr::SPACE << Sql::Expr::IN << Sql::Expr::SPACE
|
16
|
+
if subquery?
|
17
|
+
values.to_sql(buffer)
|
18
|
+
else
|
19
|
+
buffer << Sql::Expr::LEFT_PARENTHESE
|
20
|
+
values.each_with_index do |val,index|
|
21
|
+
buffer << Sql::Expr::COMMA << Sql::Expr::SPACE unless index==0
|
22
|
+
to_sql_literal(buffer, val)
|
23
|
+
end
|
24
|
+
buffer << Sql::Expr::RIGHT_PARENTHESE
|
25
|
+
end
|
26
|
+
buffer
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Alf
|
2
|
+
class Predicate
|
3
|
+
module NadicBool
|
4
|
+
|
5
|
+
def to_sql(buffer = "")
|
6
|
+
each_with_index do |child, index|
|
7
|
+
next if index == 0
|
8
|
+
unless index == 1
|
9
|
+
buffer << Sql::Expr::SPACE << to_sql_operator << Sql::Expr::SPACE
|
10
|
+
end
|
11
|
+
child.to_sql(buffer)
|
12
|
+
end
|
13
|
+
buffer
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|