alf 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/Gemfile +6 -3
  2. data/Gemfile.lock +65 -19
  3. data/README.md +77 -183
  4. data/Rakefile +25 -0
  5. data/alf.gemspec +5 -3
  6. data/alf.noespec +8 -6
  7. data/lib/alf/loader.rb +1 -0
  8. data/lib/alf/version.rb +1 -1
  9. data/spec/facade/test_query.rb +12 -0
  10. data/spec/key-inference/queries.yml +10 -0
  11. data/spec/key-inference/test_all.rb +21 -0
  12. data/{test → spec}/migrations/test_folder_migration.rb +0 -0
  13. data/{test → spec}/migrations/test_sequel_migration.rb +1 -1
  14. data/spec/operators/ungroup/grouped.json +3 -0
  15. data/spec/operators/ungroup/test_on_json_content.rb +11 -0
  16. data/spec/operators/unwrap/test_on_json_content.rb +11 -0
  17. data/spec/operators/unwrap/wrapped.json +3 -0
  18. data/spec/optimizer/project/extend.yml +20 -0
  19. data/spec/optimizer/project/intersect.yml +10 -0
  20. data/spec/optimizer/project/join.yml +20 -0
  21. data/spec/optimizer/project/matching.yml +21 -0
  22. data/spec/optimizer/project/minus.yml +9 -0
  23. data/spec/optimizer/project/not_matching.yml +21 -0
  24. data/spec/optimizer/project/project.yml +88 -0
  25. data/spec/optimizer/project/rename.yml +30 -0
  26. data/spec/optimizer/project/sort.yml +45 -0
  27. data/spec/optimizer/project/union.yml +8 -0
  28. data/spec/optimizer/restrict/clip.yml +4 -0
  29. data/spec/optimizer/restrict/compact.yml +4 -0
  30. data/spec/optimizer/restrict/generator.yml +4 -0
  31. data/spec/optimizer/restrict/intersect.yml +4 -0
  32. data/spec/optimizer/restrict/leaf_operand.yml +4 -0
  33. data/spec/optimizer/restrict/minus.yml +4 -0
  34. data/spec/optimizer/restrict/page.yml +12 -0
  35. data/spec/optimizer/restrict/project.yml +4 -0
  36. data/spec/optimizer/restrict/sort.yml +4 -0
  37. data/spec/optimizer/restrict/union.yml +4 -0
  38. data/spec/optimizer/test_all.rb +34 -0
  39. data/spec/sql/helpers.rb +25 -0
  40. data/spec/sql/queries/01-leaf-operand.yml +5 -0
  41. data/spec/sql/queries/02-clip.yml +12 -0
  42. data/spec/sql/queries/03-sort.yml +58 -0
  43. data/spec/sql/queries/04-frame.yml +57 -0
  44. data/spec/sql/queries/05-intersect.yml +23 -0
  45. data/spec/sql/queries/06-join.yml +207 -0
  46. data/spec/sql/queries/07-matching.yml +76 -0
  47. data/spec/sql/queries/08-minus.yml +23 -0
  48. data/spec/sql/queries/09-not-matching.yml +57 -0
  49. data/spec/sql/queries/10-page.yml +31 -0
  50. data/spec/sql/queries/11-project.yml +48 -0
  51. data/spec/sql/queries/12-rename.yml +24 -0
  52. data/spec/sql/queries/13-restrict.yml +114 -0
  53. data/spec/sql/queries/15-union.yml +90 -0
  54. data/spec/sql/queries/16-wrap.yml +3 -0
  55. data/spec/sql/queries/91-reuse.yml +28 -0
  56. data/spec/sql/test_sequel_compiler.rb +41 -0
  57. data/spec/sql/test_sql_compiler.rb +52 -0
  58. data/{test → spec}/test_alf.rb +0 -0
  59. data/spec/test_helpers.rb +54 -0
  60. data/tasks/doc.rake +10 -0
  61. data/tasks/fixtures.rake +52 -0
  62. data/tasks/mod.rake +50 -0
  63. data/tasks/release.rake +34 -0
  64. data/tasks/test.rake +2 -2
  65. metadata +150 -19
  66. data/test/seeding/test_seeding.rb +0 -49
  67. data/test/test_helpers.rb +0 -24
data/Gemfile CHANGED
@@ -1,9 +1,12 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
3
  group :runtime do
4
- gem "alf-core", "~> 0.14.0"
5
- gem "alf-sequel", "~> 0.14.0"
6
- gem "alf-shell", "~> 0.14.0"
4
+ gem "alf", path: "."
5
+ gem "alf-core", path: "./alf-core"
6
+ gem "alf-sql", path: "./alf-sql"
7
+ gem "alf-shell", path: "./alf-shell"
8
+ gem "alf-sequel", path: "./alf-sequel"
9
+ gem "alf-rack", path: "./alf-rack"
7
10
  end
8
11
 
9
12
  group :test do
data/Gemfile.lock CHANGED
@@ -1,44 +1,90 @@
1
- GEM
2
- remote: http://rubygems.org/
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ alf (0.15.0)
5
+ alf-core (~> 0.15.0)
6
+ alf-rack (~> 0.15.0)
7
+ alf-sequel (~> 0.15.0)
8
+ alf-shell (~> 0.15.0)
9
+ alf-sql (~> 0.15.0)
10
+
11
+ PATH
12
+ remote: ./alf-core
3
13
  specs:
4
- alf-core (0.14.0)
14
+ alf-core (0.15.0)
5
15
  domain (~> 1.0)
6
16
  myrrha (~> 3.0)
7
17
  path (~> 1.3)
8
- sexpr (~> 0.5.1)
9
- alf-sequel (0.14.0)
10
- alf-core (~> 0.14.0)
11
- sequel (~> 3.48)
12
- alf-shell (0.14.0)
13
- alf-core (~> 0.14.0)
18
+ sexpr (~> 0.6.0)
19
+
20
+ PATH
21
+ remote: ./alf-rack
22
+ specs:
23
+ alf-rack (0.15.0)
24
+ alf-core (~> 0.15.0)
25
+ rack (~> 1.5)
26
+ rack-accept (~> 0.4.5)
27
+ ruby_cop (~> 1.0)
28
+
29
+ PATH
30
+ remote: ./alf-sequel
31
+ specs:
32
+ alf-sequel (0.15.0)
33
+ alf-core (~> 0.15.0)
34
+ alf-sql (~> 0.15.0)
35
+ sequel (~> 4.2)
36
+
37
+ PATH
38
+ remote: ./alf-shell
39
+ specs:
40
+ alf-shell (0.15.0)
41
+ alf-core (~> 0.15.0)
14
42
  quickl (~> 0.4.3)
43
+
44
+ PATH
45
+ remote: ./alf-sql
46
+ specs:
47
+ alf-sql (0.15.0)
48
+ alf-core (~> 0.15.0)
49
+ sexpr (~> 0.6.0)
50
+
51
+ GEM
52
+ remote: http://rubygems.org/
53
+ specs:
15
54
  diff-lcs (1.2.4)
16
55
  domain (1.0.0)
17
56
  myrrha (3.0.0)
18
57
  domain (~> 1.0)
19
58
  path (1.3.3)
20
- pg (0.14.1)
59
+ pg (0.17.0)
21
60
  quickl (0.4.3)
61
+ rack (1.5.2)
62
+ rack-accept (0.4.5)
63
+ rack (>= 0.4)
22
64
  rake (10.1.0)
23
65
  rspec (2.14.1)
24
66
  rspec-core (~> 2.14.0)
25
67
  rspec-expectations (~> 2.14.0)
26
68
  rspec-mocks (~> 2.14.0)
27
- rspec-core (2.14.4)
28
- rspec-expectations (2.14.0)
69
+ rspec-core (2.14.7)
70
+ rspec-expectations (2.14.3)
29
71
  diff-lcs (>= 1.1.3, < 2.0)
30
- rspec-mocks (2.14.1)
31
- sequel (3.48.0)
32
- sexpr (0.5.1)
33
- sqlite3 (1.3.7)
72
+ rspec-mocks (2.14.4)
73
+ ruby_cop (1.0.5)
74
+ sequel (4.3.0)
75
+ sexpr (0.6.0)
76
+ sqlite3 (1.3.8)
34
77
 
35
78
  PLATFORMS
36
79
  ruby
37
80
 
38
81
  DEPENDENCIES
39
- alf-core (~> 0.14.0)
40
- alf-sequel (~> 0.14.0)
41
- alf-shell (~> 0.14.0)
82
+ alf!
83
+ alf-core!
84
+ alf-rack!
85
+ alf-sequel!
86
+ alf-shell!
87
+ alf-sql!
42
88
  jdbc-sqlite3 (~> 3.7)
43
89
  pg (~> 0.14)
44
90
  rake (~> 10.1)
data/README.md CHANGED
@@ -7,190 +7,84 @@ Relational Algebra at your fingertips
7
7
 
8
8
  ## Links
9
9
 
10
- * [Official documentation](http://blambeau.github.com/alf)
10
+ * [Try it online](http://www.try-alf.org/)
11
+ * [Official documentation](http://www.try-alf.org/doc/)
12
+ * [Blog](http://www.try-alf.org/blog/)
11
13
  * [Source and Issues](http://github.com/alf-tool/alf)
12
- * [Relational basics as needed](http://www.revision-zero.org/relational-basics-2)
13
-
14
- ## What & Why
15
-
16
- Alf brings the relational algebra both in Shell and in Ruby. In Shell, because
17
- manipulating any relation-like data source should be as straightforward as a one-liner.
18
- In Ruby, because I've never understood why programming languages provide data structures
19
- like arrays, hashes, sets, trees and graphs but not _relations_...
20
-
21
- ## Shell Example
22
-
23
- % alf --examples show suppliers
24
-
25
- +------+-------+---------+--------+
26
- | :sid | :name | :status | :city |
27
- +------+-------+---------+--------+
28
- | S1 | Smith | 20 | London |
29
- | S2 | Jones | 10 | Paris |
30
- | S3 | Blake | 30 | Paris |
31
- | S4 | Clark | 20 | London |
32
- | S5 | Adams | 30 | Athens |
33
- +------+-------+---------+--------+
34
-
35
- % alf --examples group suppliers -- size name status -- in_that_city
36
-
37
- +--------+----------------------------+
38
- | :city | :in_that_city |
39
- +--------+----------------------------+
40
- | London | +------+-------+---------+ |
41
- | | | :sid | :name | :status | |
42
- | | +------+-------+---------+ |
43
- | | | S1 | Smith | 20 | |
44
- | | | S4 | Clark | 20 | |
45
- | | +------+-------+---------+ |
46
- | Paris | +------+-------+---------+ |
47
- | | | :sid | :name | :status | |
48
- | | +------+-------+---------+ |
49
- | | | S2 | Jones | 10 | |
50
- | | | S3 | Blake | 30 | |
51
- | | +------+-------+---------+ |
52
- | Athens | +------+-------+---------+ |
53
- | | | :sid | :name | :status | |
54
- | | +------+-------+---------+ |
55
- | | | S5 | Adams | 30 | |
56
- | | +------+-------+---------+ |
57
- +--------+----------------------------+
58
-
59
- ## Ruby Example
60
-
61
- # Let get the same database in ruby
62
- db = Alf.examples
63
-
64
- # Group suppliers by city
65
- grouped = db.query{
66
- group(:suppliers, [:sid, :name, :status], :in_that_city)
67
- }
68
- # => same result as in shell
69
-
70
- # Let make some computations on the sub-relations
71
- db.query{
72
- extend(grouped, how_many: ->{ in_that_city.count },
73
- avg_status: ->{ in_that_city.avg{ status } })
74
- }
75
- # +--------+----------------------------+-----------+-------------+
76
- # | :city | :in_that_city | :how_many | :avg_status |
77
- # +--------+----------------------------+-----------+-------------+
78
- # | London | +------+-------+---------+ | 2 | 20.000 |
79
- # | | | :sid | :name | :status | | | |
80
- # | | +------+-------+---------+ | | |
81
- # | | | S1 | Smith | 20 | | | |
82
- # | | | S4 | Clark | 20 | | | |
83
- # | | +------+-------+---------+ | | |
84
- # | Paris | +------+-------+---------+ | 2 | 20.000 |
85
- # | | | :sid | :name | :status | | | |
86
- # | | +------+-------+---------+ | | |
87
- # | | | S2 | Jones | 10 | | | |
88
- # | | | S3 | Blake | 30 | | | |
89
- # | | +------+-------+---------+ | | |
90
- # | Athens | +------+-------+---------+ | 1 | 30.000 |
91
- # | | | :sid | :name | :status | | | |
92
- # | | +------+-------+---------+ | | |
93
- # | | | S5 | Adams | 30 | | | |
94
- # | | +------+-------+---------+ | | |
95
- # +--------+----------------------------+-----------+-------------+
96
-
97
- # Now observe that the same result can also be expressed as follows (and can be
98
- # optimized more easily)
99
- summarized = db.query{
100
- summary = summarize(:suppliers, [ :city ], how_many: count, avg_status: avg{ status })
101
- join(grouped, summary)
102
- }
103
-
104
- # Oh, and of course...
105
- require 'json'
106
- puts summarized.to_json
107
- # [{"city":"London","in_that_city":[{"sid":"S1","name":"Smith","status":20},{"sid":"S4"...
108
-
109
- ## Install, bundler, require
110
-
111
- % [sudo] gem install alf [fastercsv, ...]
112
- % alf --help
113
-
114
- # API is not considered stable enough for now, please use
115
- gem "alf", "= 0.13.0"
116
-
117
- # The following should not break your code, but is a bit less safe,
118
- # until 1.0.0 has been reached
119
- gem "alf", "~> 0.13.0"
120
-
121
- ## Related Work & Tools
122
-
123
- - You should certainly have a look at the
124
- [Third Manifesto website](http://www.thethirdmanifesto.com/):
125
- - Why not reading the
126
- [third manifesto](http://www.dcs.warwick.ac.uk/~hugh/TTM/DBE-Chapter01.pdf) ?
127
- - Also have a look at
128
- [other implementation projects](http://www.dcs.warwick.ac.uk/~hugh/TTM/Projects.html)
129
- especially [Rel](http://dbappbuilder.sourceforge.net/Rel.php) which provides an
130
- implementation of the **Tutorial D** language.
131
- - [Dan Kubb's Veritas](https://github.com/dkubb/veritas) project is worth considering
132
- also in the Ruby community. While very similar to Alf in providing a pure ruby
133
- algebra implementation, Veritas mostly provides a framework for manipulating
134
- and statically analyzing algebra expressions so as to be able to
135
- [optimize them](https://github.com/dkubb/veritas-optimizer) and
136
- [compile them to SQL](https://github.com/dkubb/veritas-sql-generator).
14
+
15
+ ## Overview
16
+
17
+ Alf is a modern query language, rooted in relational algebra, and implemented
18
+ as a Ruby Domain Specific Language. It is distributed as a consolidated ruby
19
+ gem:
20
+
21
+ ```
22
+ gem install alf
23
+ ```
24
+
25
+ You'll also need the usual adapter gems for connecting to SQL engines, such as
26
+ `pg` for PostgreSQL or `sqlite3` for SQlite. I've not tested Alf against MySQL
27
+ and won't.
28
+
29
+ See the official documentation for getting started using Alf
30
+ [in Ruby](http://www.try-alf.org/doc/pages/alf-in-ruby) and
31
+ [in Shell](http://www.try-alf.org/doc/pages/alf-in-shell).
32
+
33
+ ## Detailed overview
34
+
35
+ The consolidated gem is assembled from the following components:
36
+
37
+ * [alf-core](http://github.com/alf-tool/alf-core) core classes of Alf,
38
+ algebra, memory engine, Relation, compiler, and so on. This is actually Alf
39
+ itself, I would say.
40
+ * [alf-sql](http://github.com/alf-tool/alf-sql) extension of core's compiler
41
+ to handle SQL compilation specifically, in an abstract way.
42
+ * [alf-sequel](http://github.com/alf-tool/alf-sequel) an adapter for
43
+ connecting to SQL DBMSs using [Sequel](http://sequel.rubyforge.org/).
44
+ * [alf-shell](http://github.com/alf-tool/alf-shell) implements the commandline
45
+ tool that you can use without even knowing ruby.
46
+ * [alf-rack](http://github.com/alf-tool/alf-rack) a few Rack middlewares for
47
+ using Alf in ruby web applications.
48
+ * [alf-doc](http://github.com/alf-tool/alf-doc) is the source of all the
49
+ documentation found in man pages (shell) and on [try-alf.org](http://www.try-alf.org/).
50
+ * [try-alf](http://github.com/alf-tool/try-alf) is the source code of try-alf.org
51
+ itself.
52
+
53
+ Those components are distributed as separated ruby gems as well. A typical
54
+ ruby configuration (Gemfile) for using Alf and connecting to SQL databases is
55
+ either:
56
+
57
+ ```
58
+ # consolidated gem, possibly with a lot of uneeded dependencies.
59
+ gem "alf", "~> 0.15.0"
60
+ ```
61
+
62
+ or
63
+
64
+ ```
65
+ # take only those gems that you need, here for a web app connecting to SQL
66
+ # databases.
67
+ gem "alf-core", "~> 0.15.0" # you can even omit this one
68
+ gem "alf-sequel", "~> 0.15.0"
69
+ gem "alf-rack", "~> 0.15.0"
70
+ ```
137
71
 
138
72
  ## Contributing
139
73
 
140
- You know the rules:
141
-
142
- * The code is on github https://github.com/blambeau/alf
143
- * Please report any problem or bug in the issue tracker on github
144
- * Don't hesitate to fork and send me a pull request for any contribution/idea!
145
-
146
- Alf is distributed under a MIT licence. Please let me know if it does not fit
147
- your needs and I'll see what I can do!
148
-
149
- ## Roadmap
150
-
151
- Below is what I've imagined about Alf's future. However, this is to be interpreted
152
- as my own wish list, while I would love hearing yours instead.
153
-
154
- - Towards 1.0.0, I would like to stabilize and document Alf public APIs as well
155
- as internals (a few concepts are still unstable there). Alf also has a certain
156
- number of limitations that are worth overcoming for version 1.0.0. The latter
157
- include the semantically wrong way of applying joins on sub-relations, the
158
- impossibility to use Lispy expressions on sub-relations in extend, and the error
159
- management which is unspecific and unfriendly so far.
160
- - I also would like starting collecting Reader, Renderer and Connection
161
- contributions for common data sources (SQL, NoSQL, CSV, LOGS) and output
162
- formats (HTML, XML, JSON). Contributions could be either developped as different
163
- gem projects or distributed with Alf's gem and source code, I still need to
164
- decide the exact policy (suggestions are more than welcome here)
165
- - Alf will remain a practical tool before everything else. In the middle term,
166
- I would like to complete the set of available operators (relational and non-
167
- relational ones). Some of them will be operators described in D & D books
168
- while others will be new suggestions of mine.
169
- - In the long term Alf should be able to avoid loading tuples in memory (under
170
- a certain number of conditions on datasources) for almost all queries.
171
- - Without targetting a fast tool at all, I also would like Alf to provide a basic
172
- optimizer that would be able to push equality restrictions down and materialize
173
- sub-expressions used more than once in with expressions.
174
-
175
- ## Versioning policy
176
-
177
- Alf respects [semantic versioning](http://semver.org/), which means that it has
178
- a X.Y.Z version number and follows a few rules.
179
-
180
- - The public API is made of the commandline tool, the Lispy dialect and the
181
- Relation datastructure. This API will become stable with version 1.0.0 in a
182
- near future.
183
- - Currently, version 1.0.0 **has not been reached**. It means that **anything
184
- may change at any time**. Best effort will be done to upgrade Y when backward
185
- incompatible changes occur.
186
- - Once 1.0.0 will be reached, the following rules will be followed:
187
- - Backward compatible bug fixes will increase Z.
188
- - New features and enhancements that do not break backward compatibility of
189
- the public API will increase the Y number.
190
- - Non backward compatible changes of the public API will increase the X
191
- number.
192
-
193
- All classes and modules but Alf module, the Lispy DSL and Alf::Relation are part
194
- of the private API and may change at any time. A best-effort strategy is followed
195
- to avoid breaking internals on tiny (Z) version increases, especially extension
196
- points like Reader and Renderer.
74
+ As usual, on github, issues and pull requests, either on sub-projects (if you
75
+ know where your issue/contribution fits) or on this one (if you don't).
76
+
77
+ Integration work on Alf requires having all components available. The scenario
78
+ below might be a good way for getting started:
79
+
80
+ ```
81
+ git clone git://github.com/alf-tool/alf.git
82
+ git submodule init
83
+ git submodule update
84
+ rake mod:test
85
+ rake test
86
+ ```
87
+
88
+ Let me know if some tests fail in your environment. I'm not sure to know the
89
+ idiomatic way to use github with submodules when clones are involved. If you
90
+ do know, feel free to contribute your first pull request on this README ;-)
data/Rakefile CHANGED
@@ -1,6 +1,31 @@
1
1
  # We run tests by default
2
2
  task :default => :test
3
3
 
4
+ SUB_MODULES = %w[
5
+ core
6
+ sql
7
+ sequel
8
+ shell
9
+ rack
10
+ doc
11
+ rest
12
+ ]
13
+
14
+ def clean_env(&bl)
15
+ Bundler.with_clean_env(&bl)
16
+ end
17
+
18
+ def in_each_sub_module(msg)
19
+ clean_env do
20
+ SUB_MODULES.each do |sub|
21
+ chdir("alf-#{sub}") do
22
+ puts "#{msg} #{sub}"
23
+ yield(sub)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
4
29
  #
5
30
  # Install all tasks found in tasks folder
6
31
  #
data/alf.gemspec CHANGED
@@ -125,9 +125,11 @@ Gem::Specification.new do |s|
125
125
  #
126
126
  s.add_development_dependency("rake", "~> 10.1")
127
127
  s.add_development_dependency("rspec", "~> 2.14")
128
- s.add_dependency("alf-core", "~> 0.14.0")
129
- s.add_dependency("alf-sequel", "~> 0.14.0")
130
- s.add_dependency("alf-shell", "~> 0.14.0")
128
+ s.add_dependency("alf-core", "~> 0.15.0")
129
+ s.add_dependency("alf-sql", "~> 0.15.0")
130
+ s.add_dependency("alf-sequel", "~> 0.15.0")
131
+ s.add_dependency("alf-shell", "~> 0.15.0")
132
+ s.add_dependency("alf-rack", "~> 0.15.0")
131
133
 
132
134
  # The version of ruby required by this gem
133
135
  #
data/alf.noespec CHANGED
@@ -6,9 +6,9 @@ template-info:
6
6
  safe-override: false
7
7
  tasks/spec_test.rake:
8
8
  ignore: true
9
- spec/spec_helper:
9
+ spec/spec_helper.rb:
10
10
  ignore: true
11
- spec/test_alf:
11
+ spec/test___lower__.rb:
12
12
  ignore: true
13
13
  variables:
14
14
  lower:
@@ -16,7 +16,7 @@ variables:
16
16
  upper:
17
17
  Alf
18
18
  version:
19
- 0.13.0
19
+ 0.15.0
20
20
  summary: |-
21
21
  Relational Algebra at your fingertips
22
22
  description: |-
@@ -29,8 +29,10 @@ variables:
29
29
  - http://rubygems.org/gems/alf
30
30
  - http://rubydoc.info/gems/alf
31
31
  dependencies:
32
- - {name: alf-core, version: "~> 0.14.0", groups: [runtime]}
33
- - {name: alf-sequel, version: "~> 0.14.0", groups: [runtime]}
34
- - {name: alf-shell, version: "~> 0.14.0", groups: [runtime]}
32
+ - {name: alf-core, version: "~> 0.15.0", groups: [runtime]}
33
+ - {name: alf-sql, version: "~> 0.15.0", groups: [runtime]}
34
+ - {name: alf-sequel, version: "~> 0.15.0", groups: [runtime]}
35
+ - {name: alf-shell, version: "~> 0.15.0", groups: [runtime]}
36
+ - {name: alf-rack, version: "~> 0.15.0", groups: [runtime]}
35
37
  - {name: rake, version: "~> 10.1", groups: [test, release]}
36
38
  - {name: rspec, version: "~> 2.14", groups: [test, release]}