alf 0.14.0 → 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 (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]}