alf-shell 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 (276) hide show
  1. data/Gemfile +5 -2
  2. data/Gemfile.lock +29 -10
  3. data/bin/alf +2 -0
  4. data/doc/man/alf-explain.man +22 -0
  5. data/doc/man/alf-metadata.man +13 -0
  6. data/doc/man/alf-show.man +16 -0
  7. data/doc/man/alf.man +77 -0
  8. data/doc/man/allbut.man +39 -0
  9. data/doc/man/among.man +25 -0
  10. data/doc/man/avg.man +37 -0
  11. data/doc/man/between.man +24 -0
  12. data/doc/man/concat.man +55 -0
  13. data/doc/man/contradiction.man +26 -0
  14. data/doc/man/count.man +20 -0
  15. data/doc/man/eq.man +29 -0
  16. data/doc/man/extend.man +33 -0
  17. data/doc/man/frame.man +60 -0
  18. data/doc/man/group.man +51 -0
  19. data/doc/man/gt.man +30 -0
  20. data/doc/man/gte.man +30 -0
  21. data/doc/man/intersect.man +54 -0
  22. data/doc/man/join.man +84 -0
  23. data/doc/man/lt.man +30 -0
  24. data/doc/man/lte.man +30 -0
  25. data/doc/man/matching.man +73 -0
  26. data/doc/man/max.man +36 -0
  27. data/doc/man/min.man +36 -0
  28. data/doc/man/minus.man +54 -0
  29. data/doc/man/native.man +32 -0
  30. data/doc/man/neq.man +29 -0
  31. data/doc/man/not_matching.man +51 -0
  32. data/doc/man/page.man +60 -0
  33. data/doc/man/project.man +36 -0
  34. data/doc/man/rank.man +42 -0
  35. data/doc/man/rename.man +29 -0
  36. data/doc/man/restrict.man +38 -0
  37. data/doc/man/stddev.man +37 -0
  38. data/doc/man/sum.man +37 -0
  39. data/doc/man/summarize.man +45 -0
  40. data/doc/man/tautology.man +26 -0
  41. data/doc/man/ungroup.man +30 -0
  42. data/doc/man/union.man +55 -0
  43. data/doc/man/unwrap.man +37 -0
  44. data/doc/man/variance.man +37 -0
  45. data/doc/man/wrap.man +37 -0
  46. data/doc/txt/alf-explain.man +22 -0
  47. data/doc/txt/alf-metadata.man +16 -0
  48. data/doc/txt/alf-show.man +19 -0
  49. data/doc/txt/alf.man +80 -0
  50. data/doc/txt/allbut.txt +31 -0
  51. data/doc/txt/among.txt +20 -0
  52. data/doc/txt/avg.txt +22 -0
  53. data/doc/txt/between.txt +19 -0
  54. data/doc/txt/concat.txt +31 -0
  55. data/doc/txt/contradiction.txt +15 -0
  56. data/doc/txt/count.txt +14 -0
  57. data/doc/txt/eq.txt +19 -0
  58. data/doc/txt/extend.txt +29 -0
  59. data/doc/txt/frame.txt +48 -0
  60. data/doc/txt/group.txt +37 -0
  61. data/doc/txt/gt.txt +20 -0
  62. data/doc/txt/gte.txt +20 -0
  63. data/doc/txt/intersect.txt +42 -0
  64. data/doc/txt/join.txt +65 -0
  65. data/doc/txt/lt.txt +20 -0
  66. data/doc/txt/lte.txt +20 -0
  67. data/doc/txt/matching.txt +54 -0
  68. data/doc/txt/max.txt +21 -0
  69. data/doc/txt/min.txt +21 -0
  70. data/doc/txt/minus.txt +42 -0
  71. data/doc/txt/native.txt +27 -0
  72. data/doc/txt/neq.txt +19 -0
  73. data/doc/txt/not_matching.txt +39 -0
  74. data/doc/txt/page.txt +48 -0
  75. data/doc/txt/project.txt +28 -0
  76. data/doc/txt/rank.txt +34 -0
  77. data/doc/txt/rename.txt +25 -0
  78. data/doc/txt/restrict.txt +26 -0
  79. data/doc/txt/stddev.txt +22 -0
  80. data/doc/txt/sum.txt +22 -0
  81. data/doc/txt/summarize.txt +33 -0
  82. data/doc/txt/tautology.txt +15 -0
  83. data/doc/txt/ungroup.txt +26 -0
  84. data/doc/txt/union.txt +43 -0
  85. data/doc/txt/unwrap.txt +29 -0
  86. data/doc/txt/variance.txt +22 -0
  87. data/doc/txt/wrap.txt +29 -0
  88. data/lib/alf/shell.rb +2 -32
  89. data/lib/alf/shell/alfrc.rb +3 -0
  90. data/lib/alf/shell/command.rb +2 -18
  91. data/lib/alf/shell/command/explain.rb +37 -0
  92. data/lib/alf/shell/command/help.rb +3 -21
  93. data/lib/alf/shell/command/main.rb +20 -78
  94. data/lib/alf/shell/command/metadata.rb +32 -0
  95. data/lib/alf/shell/command/show.rb +17 -5
  96. data/lib/alf/shell/support.rb +21 -13
  97. data/lib/alf/shell/version.rb +1 -1
  98. data/spec/integration/explain/explain.cmd +1 -0
  99. data/spec/integration/explain/explain.stdout +11 -0
  100. data/spec/integration/show/group.alf +2 -0
  101. data/spec/integration/show/show_alf.cmd +1 -0
  102. data/spec/integration/{group/group_0.stdout → show/show_alf.stdout} +0 -0
  103. data/tasks/doc.rake +4 -0
  104. metadata +116 -178
  105. data/doc/commands/exec.md +0 -16
  106. data/doc/commands/help.md +0 -11
  107. data/doc/commands/main.md +0 -33
  108. data/doc/commands/show.md +0 -12
  109. data/doc/operators/non_relational/autonum.md +0 -23
  110. data/doc/operators/non_relational/clip.md +0 -31
  111. data/doc/operators/non_relational/coerce.md +0 -15
  112. data/doc/operators/non_relational/compact.md +0 -20
  113. data/doc/operators/non_relational/defaults.md +0 -32
  114. data/doc/operators/non_relational/generator.md +0 -20
  115. data/doc/operators/non_relational/sort.md +0 -24
  116. data/doc/operators/non_relational/type-safe.md +0 -20
  117. data/doc/operators/relational/extend.md +0 -18
  118. data/doc/operators/relational/frame.md +0 -26
  119. data/doc/operators/relational/group.md +0 -27
  120. data/doc/operators/relational/hierarchize.md +0 -14
  121. data/doc/operators/relational/infer-heading.md +0 -20
  122. data/doc/operators/relational/intersect.md +0 -13
  123. data/doc/operators/relational/join.md +0 -28
  124. data/doc/operators/relational/matching.md +0 -24
  125. data/doc/operators/relational/minus.md +0 -12
  126. data/doc/operators/relational/not-matching.md +0 -20
  127. data/doc/operators/relational/page.md +0 -31
  128. data/doc/operators/relational/project.md +0 -28
  129. data/doc/operators/relational/quota.md +0 -21
  130. data/doc/operators/relational/rank.md +0 -27
  131. data/doc/operators/relational/rename.md +0 -17
  132. data/doc/operators/relational/restrict.md +0 -25
  133. data/doc/operators/relational/summarize.md +0 -25
  134. data/doc/operators/relational/ungroup.md +0 -20
  135. data/doc/operators/relational/union.md +0 -14
  136. data/doc/operators/relational/unwrap.md +0 -20
  137. data/doc/operators/relational/wrap.md +0 -24
  138. data/lib/alf/shell/command/exec.rb +0 -16
  139. data/lib/alf/shell/doc_manager.rb +0 -84
  140. data/lib/alf/shell/ext/signature.rb +0 -45
  141. data/lib/alf/shell/from_argv.rb +0 -84
  142. data/lib/alf/shell/operator.rb +0 -63
  143. data/spec/integration/__database__/group.alf +0 -3
  144. data/spec/integration/alf/alf_e.cmd +0 -1
  145. data/spec/integration/alf/alf_e.stdout +0 -4
  146. data/spec/integration/alf/alf_help.cmd +0 -1
  147. data/spec/integration/alf/alf_help.stdout +0 -76
  148. data/spec/integration/alf/alf_r.cmd +0 -1
  149. data/spec/integration/alf/alf_r.stdout +0 -5
  150. data/spec/integration/autonum/autonum_0.cmd +0 -1
  151. data/spec/integration/autonum/autonum_0.stdout +0 -9
  152. data/spec/integration/autonum/autonum_1.cmd +0 -1
  153. data/spec/integration/autonum/autonum_1.stdout +0 -9
  154. data/spec/integration/clip/clip_0.cmd +0 -1
  155. data/spec/integration/clip/clip_0.stdout +0 -9
  156. data/spec/integration/clip/clip_1.cmd +0 -1
  157. data/spec/integration/clip/clip_1.stdout +0 -9
  158. data/spec/integration/coerce/coerce_1.cmd +0 -1
  159. data/spec/integration/coerce/coerce_1.stdout +0 -5
  160. data/spec/integration/compact/compact_0.cmd +0 -1
  161. data/spec/integration/compact/compact_0.stdout +0 -9
  162. data/spec/integration/defaults/defaults_0.cmd +0 -1
  163. data/spec/integration/defaults/defaults_0.stdout +0 -9
  164. data/spec/integration/defaults/defaults_1.cmd +0 -1
  165. data/spec/integration/defaults/defaults_1.stdout +0 -9
  166. data/spec/integration/defaults/defaults_2.cmd +0 -1
  167. data/spec/integration/defaults/defaults_2.stdout +0 -9
  168. data/spec/integration/extend/extend_0.cmd +0 -1
  169. data/spec/integration/extend/extend_0.stdout +0 -16
  170. data/spec/integration/frame/frame_0.cmd +0 -1
  171. data/spec/integration/frame/frame_0.stdout +0 -6
  172. data/spec/integration/generator/generator_1.cmd +0 -1
  173. data/spec/integration/generator/generator_1.stdout +0 -10
  174. data/spec/integration/generator/generator_2.cmd +0 -1
  175. data/spec/integration/generator/generator_2.stdout +0 -5
  176. data/spec/integration/generator/generator_3.cmd +0 -1
  177. data/spec/integration/generator/generator_3.stdout +0 -5
  178. data/spec/integration/group/group_0.cmd +0 -1
  179. data/spec/integration/group/group_1.cmd +0 -1
  180. data/spec/integration/group/group_1.stdout +0 -32
  181. data/spec/integration/help/help_1.cmd +0 -1
  182. data/spec/integration/help/help_1.stdout +0 -12
  183. data/spec/integration/intersect/intersect_0.cmd +0 -1
  184. data/spec/integration/intersect/intersect_0.stdout +0 -9
  185. data/spec/integration/join/join_0.cmd +0 -1
  186. data/spec/integration/join/join_0.stdout +0 -16
  187. data/spec/integration/matching/matching_0.cmd +0 -1
  188. data/spec/integration/matching/matching_0.stdout +0 -8
  189. data/spec/integration/minus/minus_0.cmd +0 -1
  190. data/spec/integration/minus/minus_0.stdout +0 -4
  191. data/spec/integration/not-matching/not-matching_0.cmd +0 -1
  192. data/spec/integration/not-matching/not-matching_0.stdout +0 -5
  193. data/spec/integration/page/page_0.cmd +0 -1
  194. data/spec/integration/page/page_0.stdout +0 -6
  195. data/spec/integration/project/project_0.cmd +0 -1
  196. data/spec/integration/project/project_0.stdout +0 -9
  197. data/spec/integration/project/project_1.cmd +0 -1
  198. data/spec/integration/project/project_1.stdout +0 -9
  199. data/spec/integration/quota/quota_0.cmd +0 -1
  200. data/spec/integration/quota/quota_0.stdout +0 -16
  201. data/spec/integration/rank/rank_1.cmd +0 -1
  202. data/spec/integration/rank/rank_1.stdout +0 -10
  203. data/spec/integration/rank/rank_2.cmd +0 -1
  204. data/spec/integration/rank/rank_2.stdout +0 -10
  205. data/spec/integration/rank/rank_3.cmd +0 -1
  206. data/spec/integration/rank/rank_3.stdout +0 -10
  207. data/spec/integration/rank/rank_4.cmd +0 -1
  208. data/spec/integration/rank/rank_4.stdout +0 -6
  209. data/spec/integration/rank/rank_5.cmd +0 -1
  210. data/spec/integration/rank/rank_5.stdout +0 -6
  211. data/spec/integration/rename/rename_0.cmd +0 -1
  212. data/spec/integration/rename/rename_0.stdout +0 -9
  213. data/spec/integration/restrict/restrict_0.cmd +0 -1
  214. data/spec/integration/restrict/restrict_0.stdout +0 -6
  215. data/spec/integration/restrict/restrict_1.cmd +0 -1
  216. data/spec/integration/restrict/restrict_1.stdout +0 -6
  217. data/spec/integration/sort/sort_0.cmd +0 -1
  218. data/spec/integration/sort/sort_0.stdout +0 -9
  219. data/spec/integration/sort/sort_1.cmd +0 -1
  220. data/spec/integration/sort/sort_1.stdout +0 -9
  221. data/spec/integration/sort/sort_2.cmd +0 -1
  222. data/spec/integration/sort/sort_2.stdout +0 -9
  223. data/spec/integration/sort/sort_3.cmd +0 -1
  224. data/spec/integration/sort/sort_3.stdout +0 -9
  225. data/spec/integration/summarize/summarize_0.cmd +0 -1
  226. data/spec/integration/summarize/summarize_0.stdout +0 -8
  227. data/spec/integration/union/union_0.cmd +0 -1
  228. data/spec/integration/union/union_0.stdout +0 -9
  229. data/spec/integration/unwrap/unwrap_0.cmd +0 -1
  230. data/spec/integration/unwrap/unwrap_0.stdout +0 -9
  231. data/spec/integration/wrap/wrap_0.cmd +0 -1
  232. data/spec/integration/wrap/wrap_0.stdout +0 -9
  233. data/spec/unit/doc_manager/dynamic.md +0 -1
  234. data/spec/unit/doc_manager/example.md +0 -1
  235. data/spec/unit/doc_manager/example_1.txt +0 -11
  236. data/spec/unit/doc_manager/static.md +0 -1
  237. data/spec/unit/doc_manager/test_call.rb +0 -41
  238. data/spec/unit/ext/signature/test_argv2args.rb +0 -82
  239. data/spec/unit/ext/signature/test_to_shell.rb +0 -103
  240. data/spec/unit/from_argv/test_to_attr_list.rb +0 -30
  241. data/spec/unit/from_argv/test_to_attr_name.rb +0 -27
  242. data/spec/unit/from_argv/test_to_boolean.rb +0 -32
  243. data/spec/unit/from_argv/test_to_heading.rb +0 -37
  244. data/spec/unit/from_argv/test_to_ordering.rb +0 -28
  245. data/spec/unit/from_argv/test_to_predicate.rb +0 -26
  246. data/spec/unit/from_argv/test_to_renaming.rb +0 -23
  247. data/spec/unit/from_argv/test_to_size.rb +0 -32
  248. data/spec/unit/from_argv/test_to_summarization.rb +0 -19
  249. data/spec/unit/from_argv/test_to_tuple_computation.rb +0 -18
  250. data/spec/unit/from_argv/test_to_tuple_expression.rb +0 -38
  251. data/spec/unit/main/test_class_methods.rb +0 -44
  252. data/spec/unit/operator/test_autonum.rb +0 -28
  253. data/spec/unit/operator/test_clip.rb +0 -29
  254. data/spec/unit/operator/test_coerce.rb +0 -22
  255. data/spec/unit/operator/test_compact.rb +0 -16
  256. data/spec/unit/operator/test_defaults.rb +0 -29
  257. data/spec/unit/operator/test_extend.rb +0 -21
  258. data/spec/unit/operator/test_generator.rb +0 -37
  259. data/spec/unit/operator/test_group.rb +0 -32
  260. data/spec/unit/operator/test_infer_heading.rb +0 -16
  261. data/spec/unit/operator/test_intersect.rb +0 -18
  262. data/spec/unit/operator/test_join.rb +0 -18
  263. data/spec/unit/operator/test_matching.rb +0 -18
  264. data/spec/unit/operator/test_minus.rb +0 -18
  265. data/spec/unit/operator/test_not_matching.rb +0 -18
  266. data/spec/unit/operator/test_project.rb +0 -38
  267. data/spec/unit/operator/test_quota.rb +0 -23
  268. data/spec/unit/operator/test_rank.rb +0 -30
  269. data/spec/unit/operator/test_rename.rb +0 -21
  270. data/spec/unit/operator/test_restrict.rb +0 -36
  271. data/spec/unit/operator/test_sort.rb +0 -49
  272. data/spec/unit/operator/test_summarize.rb +0 -30
  273. data/spec/unit/operator/test_ungroup.rb +0 -28
  274. data/spec/unit/operator/test_union.rb +0 -18
  275. data/spec/unit/operator/test_unwrap.rb +0 -28
  276. data/spec/unit/operator/test_wrap.rb +0 -30
@@ -0,0 +1,22 @@
1
+ # Sum
2
+
3
+ Arithmetic sum
4
+
5
+ ## Signature
6
+
7
+ sum(expr: AttrName|(Tuple->Numeric)) -> Aggregator
8
+
9
+ ## Examples
10
+ sum(:qty)
11
+ sum{|t| t.qty * t.price }
12
+ sum(->(t){ t.qty * t.price })
13
+
14
+ ## Description
15
+
16
+ Computes `v1 + v2 + ... + vn`.
17
+
18
+ ## Implementation notes
19
+
20
+ This aggregate function should only be used with numeric types. As of
21
+ current Alf version, it does not aggregate empty sets correctly on
22
+ non-numeric data types.
@@ -0,0 +1,33 @@
1
+ # Summarize
2
+
3
+ Aggregate and compute
4
+
5
+ ## Signature
6
+
7
+ summarize(operand: Relation, by: AttrList, aggs: Summarization) -> Relation
8
+
9
+ ## Examples
10
+
11
+ summarize(supplies, [:sid], total: sum(:qty))
12
+
13
+ summarize(supplies, [:sid], total: sum{|t| t.qty * 2 })
14
+
15
+ summarize(supplies, [:pid, :qty], {total: sum{|t| t.qty * 2 }}, allbut: true)
16
+
17
+ ## Description
18
+
19
+ Computes the relation obtained by taking the projection of `operand`
20
+ on `by` attributes then extending each tuple `t` with the result of
21
+ aggregations defined by `aggs` on the tuples from `operand` matching `t`.
22
+
23
+ In SQL terms, `SELECT [by], [agg] FROM operand GROUP BY [by]`.
24
+
25
+ ## Implementation notes
26
+
27
+ As of current Alf version, this operator cannot be translated to SQL code.
28
+ That means that all computations are done in ruby, which may seriously
29
+ hurt performance.
30
+
31
+ Similarly, as `summarize` tends to be a showstopper during compilation, it
32
+ is strongly recommanded to use it as high as possible in query expressions
33
+ trees so as to delegate the largest possible query parts to data engines.
@@ -0,0 +1,15 @@
1
+ # Tautology
2
+
3
+ TRUE
4
+
5
+ ## Signature
6
+
7
+ tautology() -> Predicate
8
+
9
+ ## Examples
10
+ true
11
+ tautology
12
+
13
+ ## Description
14
+
15
+ This predicate always return true. It is equivalent to `->(t){ true }`.
@@ -0,0 +1,26 @@
1
+ # Ungroup
2
+
3
+ Inverse of group
4
+
5
+ ## Signature
6
+
7
+ ungroup(operand: Relation, rva: AttrName) -> Relation
8
+
9
+ ## Examples
10
+
11
+ ungroup(group(suppliers, [:city], :suppliers, allbut: true), :suppliers)
12
+
13
+ ## Description
14
+
15
+ Computes the relation obtained by ungrouping a relation-valued attribute
16
+ `rva`. Ungrouping `rva` leads as many tuples as in `rva`, each extended
17
+ with the other attributes of `operand`.
18
+
19
+ `rva` must be a relation-valued attribute. It should not itself contain
20
+ any attribute whose name clashes with an attribute of `operand`.
21
+
22
+ ## Implementation notes
23
+
24
+ This operator does not compile to SQL so far. Contributions are welcome
25
+ to provide it with a SQL compilation for SQL DBMSs that support this kind
26
+ of feature (e.g. PostgreSQL with JSON data type)
@@ -0,0 +1,43 @@
1
+ # Union
2
+
3
+ Logical OR
4
+
5
+ ## Signature
6
+
7
+ union(left: Relation, right: Relation) -> Relation
8
+
9
+ ## Examples
10
+
11
+ union(project(suppliers, [:city]), project(parts, [:city]))
12
+
13
+ ## Description
14
+
15
+ Computes the relation as the set union of `left` and `right`.
16
+
17
+ The `left` and `right` relations must be union-compatible, meaning that they
18
+ must have same heading (type inheritance is partly supported through ruby's
19
+ own type system, so that the actual behavior is slighlty more permissive).
20
+
21
+ ## Implementation notes
22
+
23
+ Unlike SQL, this operator ALWAYS remove duplicates. There is no way, in
24
+ Alf, to compute _bags_ of tuples and therefore no way to express something
25
+ such as SQL's UNION ALL.
26
+
27
+ The optimizer is not smart enough so far to discover when operands are
28
+ actually disjoint and duplicate removal not needed (e.g. the SQL compiler
29
+ never generates UNION ALL). Any patch improving this is welcome!
30
+
31
+ Similarly, it is sometimes idiomatic in Alf to use `union` as a logical OR,
32
+ as illustrated below. So far, the optimizer/compiler is not smart enough to
33
+ translate the former in the latter (which is likely to have a better query
34
+ plan, especially when using faithful SQL compilation and usual SQL DBMSs).
35
+ Any patch is welcome here too!
36
+
37
+ union(
38
+ restrict(suppliers, city: 'Paris'),
39
+ restrict(suppliers, city: 'London'))
40
+
41
+ is equivalent to
42
+
43
+ restrict(suppliers, eq(:city, 'Paris') | eq(:city, 'London'))
@@ -0,0 +1,29 @@
1
+ # Unwrap
2
+
3
+ Inverse of wrap
4
+
5
+ ## Signature
6
+
7
+ unwrap(operand: Relation, tva: AttrName) -> Relation
8
+
9
+ ## Examples
10
+
11
+ unwrap(wrap(suppliers, [:city, :status], :extra), :extra)
12
+
13
+ ## Description
14
+
15
+ Computes the relation obtained by unwrapping a tuple-valued attribute `tva`.
16
+ Unwrapping of `tva` on an input tuple `t` consists in removing `tva` from
17
+ `t` and extending the result with `tva`'s own attributes:
18
+
19
+ Tuple(x: 1, tva: Tuple(y: 2, z: 3)) -> Tuple(x: 1, y: 2, z: 3)
20
+
21
+ `tva` must be a tuple-valued attribute. It should not itself contain any
22
+ attribute whose name clashes with an attribute of `operand`. In the examples
23
+ above, `tva` may not contain an attribute called `x`.
24
+
25
+ ## Implementation notes
26
+
27
+ This operator does not compile to SQL so far. Contributions are welcome to
28
+ provide it with a SQL compilation for SQL DBMSs that support this kind of
29
+ feature (e.g. PostgreSQL with JSON data type)
@@ -0,0 +1,22 @@
1
+ # Variance
2
+
3
+ Variance
4
+
5
+ ## Signature
6
+
7
+ variance(expr: AttrName|(Tuple->Numeric)) -> Aggregator
8
+
9
+ ## Examples
10
+ variance(:qty)
11
+ variance{|t| t.qty * t.price }
12
+ variance(->(t){ t.qty * t.price })
13
+
14
+ ## Description
15
+
16
+ Computes how far the set of input values is spread out.
17
+
18
+ ## Implementation notes
19
+
20
+ This aggregate function should only be used with numeric types. As of
21
+ current Alf version, it does not aggregate empty sets correctly on
22
+ non-numeric data types.
@@ -0,0 +1,29 @@
1
+ # Wrap
2
+
3
+ Tuple-valued attribute
4
+
5
+ ## Signature
6
+
7
+ wrap(operand: Relation, attributes: AttrList, as: AttrName) -> Relation
8
+
9
+ ## Examples
10
+
11
+ wrap(suppliers, [:city, :status], :extra)
12
+
13
+ wrap(suppliers, [:city, :status], :extra, allbut: true)
14
+
15
+ ## Description
16
+
17
+ Computes the relation obtained by removing `attributes` and replacing them
18
+ by a single attribute (`as`). The latter is a tuple-valued attribute
19
+ obtained by projecting the input tuple on `attributes`.
20
+
21
+ This operators supports an ALL BUT variant, through the `allbut` option.
22
+ When set to true, the operator keeps specified attributes and wraps all the
23
+ remaining ones as a tuple-valued attribute.
24
+
25
+ ## Implementation notes
26
+
27
+ This operator does not compile to SQL so far. Contributions are welcome to
28
+ provide it with a SQL compilation for SQL DBMSs that support this kind of
29
+ feature (e.g. PostgreSQL with JSON data type)
@@ -1,52 +1,22 @@
1
1
  require_relative 'shell/version'
2
2
  require_relative 'shell/loader'
3
- require_relative 'shell/ext/signature'
4
3
  require_relative 'shell/alfrc'
5
- require_relative 'shell/doc_manager'
6
4
  module Alf
7
5
  module Shell
8
6
 
9
- # This is the main documentation extractor
10
- DOC_EXTRACTOR = DocManager.new
11
-
12
7
  # This is the default configuration to be forked from
13
8
  DEFAULT_CONFIG = Alfrc.new
14
9
 
15
- # Delegator command factory
16
- def self.Delegator()
17
- Quickl::Delegator(){|builder|
18
- builder.doc_extractor = DOC_EXTRACTOR
19
- builder.class_module Command::ClassMethods
20
- yield(builder) if block_given?
21
- }
22
- end
23
-
24
10
  # Command factory
25
- def self.Command()
26
- Quickl::Command(){|builder|
27
- builder.command_parent = Alf::Shell::Main
28
- builder.doc_extractor = DOC_EXTRACTOR
29
- builder.class_module Command::ClassMethods
30
- builder.instance_module Shell::Support
31
- yield(builder) if block_given?
32
- }
33
- end
34
-
35
- # Operator factory
36
- def self.Operator()
37
- Quickl::Command(){|builder|
11
+ def self.Command(*args)
12
+ Quickl::Command(*args){|builder|
38
13
  builder.command_parent = Alf::Shell::Main
39
- builder.doc_extractor = DOC_EXTRACTOR
40
- builder.class_module Operator::ClassMethods
41
14
  builder.instance_module Shell::Support
42
- builder.instance_module Operator::InstanceMethods
43
15
  yield(builder) if block_given?
44
16
  }
45
17
  end
46
18
 
47
19
  end # module Shell
48
20
  end # module Alf
49
- require_relative 'shell/from_argv'
50
21
  require_relative 'shell/support'
51
22
  require_relative 'shell/command'
52
- require_relative 'shell/operator'
@@ -11,6 +11,9 @@ module Alf
11
11
  # Default renderer to use for outputting relations
12
12
  option :default_renderer, Class, ->{ $stdout.tty? ? Renderer::Text : Renderer::Rash }
13
13
 
14
+ # Default reader name to use for reading on stdin
15
+ option :stdin_reader, Symbol, :rash
16
+
14
17
  # Float format to use
15
18
  option :float_format, String, "%.3f"
16
19
 
@@ -1,21 +1,5 @@
1
- module Alf
2
- module Command
3
- module ClassMethods
4
-
5
- # @return true
6
- def command?
7
- true
8
- end
9
-
10
- # @return false
11
- def operator?
12
- false
13
- end
14
-
15
- end # module ClassMethods
16
- end # module Command
17
- end # module Alf
18
1
  require_relative 'command/main'
19
- require_relative 'command/exec'
20
2
  require_relative 'command/help'
21
3
  require_relative 'command/show'
4
+ require_relative 'command/metadata'
5
+ require_relative 'command/explain'
@@ -0,0 +1,37 @@
1
+ module Alf
2
+ module Shell
3
+ class Explain < Shell::Command(__FILE__,__LINE__)
4
+
5
+ options do |opt|
6
+
7
+ opt.on_tail('-h', "--help", "Show help") do
8
+ show_help("alf-explain")
9
+ end
10
+
11
+ end
12
+
13
+ def run(argv, requester)
14
+ # set requester and parse options
15
+ @requester = requester
16
+ argv = parse_options(argv, :split)
17
+
18
+ operand = compile(argv)
19
+
20
+ puts "Logical plan:"
21
+ puts
22
+ puts operand.to_ascii_tree.gsub(/^/, " ")
23
+
24
+ puts
25
+
26
+ puts "Physical plan:"
27
+ puts
28
+ puts operand.to_cog.to_ascii_tree.gsub(/^/, " ")
29
+ end
30
+
31
+ def compile(argv)
32
+ operand(argv.shift)
33
+ end
34
+
35
+ end # class Explain
36
+ end # module Shell
37
+ end # module Alf
@@ -1,30 +1,12 @@
1
1
  module Alf
2
2
  module Shell
3
- class Help < Shell::Command()
4
-
5
- # Let NoSuchCommandError be passed to higher stage
6
- no_react_to Quickl::NoSuchCommand
7
-
8
- options do |opt|
9
- @dialect = :shell
10
- opt.on('--lispy',
11
- 'Display operator signatures in lispy DSL') do
12
- @dialect = :lispy
13
- end
14
- opt.on('--shell',
15
- 'Display operator signatures in shell DSL') do
16
- @dialect = :shell
17
- end
18
- end
3
+ class Help < Shell::Command(__FILE__, __LINE__)
19
4
 
20
5
  # Command execution
21
6
  def execute(args)
22
- sup = Quickl.super_command(self)
23
- sub = (args.size != 1) ? sup : Quickl.sub_command!(sup, args.first)
24
- doc = sub.documentation(:method => @dialect)
25
- puts doc
7
+ show_help(args.first.strip)
26
8
  end
27
-
9
+
28
10
  end # class Help
29
11
  end # module Shell
30
12
  end # module Alf
@@ -1,49 +1,7 @@
1
1
  module Alf
2
2
  module Shell
3
- class Main < Shell::Delegator()
4
-
5
- class << self
6
-
7
- def relational_operators(sort_by_name = true)
8
- ops = subcommands.select{|cmd|
9
- cmd.operator? and cmd.relational? and !cmd.experimental?
10
- }
11
- sort_operators(ops, sort_by_name)
12
- end
13
-
14
- def experimental_operators(sort_by_name = true)
15
- ops = subcommands.select{|cmd|
16
- cmd.operator? and cmd.relational? and cmd.experimental?
17
- }
18
- sort_operators(ops, sort_by_name)
19
- end
20
-
21
- def non_relational_operators(sort_by_name = true)
22
- ops = subcommands.select{|cmd|
23
- cmd.operator? and !cmd.relational?
24
- }
25
- sort_operators(ops, sort_by_name)
26
- end
27
-
28
- def other_non_relational_commands(sort_by_name = true)
29
- ops = subcommands.select{|cmd|
30
- cmd.command?
31
- }
32
- sort_operators(ops, sort_by_name)
33
- end
34
-
35
- private
36
-
37
- def sort_operators(ops, sort_by_name)
38
- sort_by_name ? ops.sort{|op1,op2|
39
- op1.command_name.to_s <=> op2.command_name.to_s
40
- } : ops
41
- end
42
-
43
- end # class << self
44
-
45
- # The reader to use when stdin is used as operand
46
- attr_accessor :stdin_operand
3
+ class Main < Quickl::Delegator(__FILE__, __LINE__)
4
+ include Support
47
5
 
48
6
  # Creates a command instance
49
7
  def initialize(config = load_config)
@@ -55,11 +13,6 @@ module Alf
55
13
  options do |opt|
56
14
  @rendering_options = {}
57
15
 
58
- @execute = false
59
- opt.on("-e", "--execute", "Execute one line of script (Lispy API)") do
60
- @execute = true
61
- end
62
-
63
16
  Renderer.each do |name,descr,clazz|
64
17
  opt.on("--#{name}", "Render output #{descr}"){
65
18
  config.default_renderer = clazz
@@ -75,12 +28,11 @@ module Alf
75
28
  config.adapter = value
76
29
  end
77
30
 
78
- @input_reader = :rash
79
- readers = Reader.all.map{|r| r.first}
80
- opt.on('--input-reader=READER', readers,
81
- "Specify the kind of reader when reading on $stdin "\
31
+ readers = Reader.all.map{|r| r.first }
32
+ opt.on('--stdin=READER', readers,
33
+ "Specify the kind of reader when reading on standard input "\
82
34
  "(#{readers.join(',')})") do |value|
83
- @input_reader = value.to_sym
35
+ config.stdin_reader = value.to_sym
84
36
  end
85
37
 
86
38
  opt.on("-Idirectory",
@@ -104,9 +56,7 @@ module Alf
104
56
  end
105
57
 
106
58
  opt.on_tail('-h', "--help", "Show help") do
107
- install_load_path
108
- install_requires
109
- raise Quickl::Help
59
+ show_help("alf")
110
60
  end
111
61
 
112
62
  opt.on_tail('-v', "--version", "Show version") do
@@ -115,26 +65,17 @@ module Alf
115
65
  end
116
66
  end # Alf's options
117
67
 
118
- def stdin_operand
119
- @stdin_operand || Reader.send(@input_reader, $stdin)
120
- end
121
-
122
68
  def connection
123
- @connection ||= config.database.connection(viewpoint: config.viewpoint)
69
+ @connection ||= config.database.connection(viewpoint: build_viewpoint)
124
70
  end
125
71
 
126
72
  def execute(argv)
127
73
  install_load_path
128
74
  install_requires
129
75
 
130
- # special case where a .alf file is provided
131
- if argv.empty? or (argv.size == 1 && Path(argv.first).file?)
132
- argv.unshift("exec")
133
- end
134
-
135
76
  # compile the operator, render and returns it
136
- compile(argv){ super }.tap do |op|
137
- render(connection.compile(op)) if op && requester
77
+ super.tap do |op|
78
+ render(connection.relvar(op)) if op && requester
138
79
  end
139
80
  end
140
81
 
@@ -160,19 +101,20 @@ module Alf
160
101
  config
161
102
  end
162
103
 
163
- def compile(argv)
164
- if @execute
165
- connection.query(argv.first)
166
- else
167
- op = yield
168
- op = op.bind(connection) if op
169
- op
170
- end
104
+ def build_viewpoint
105
+ config = self.config
106
+ Module.new{
107
+ include Alf::Viewpoint
108
+ include config.viewpoint
109
+ def stdin
110
+ Algebra::Operand.coerce Reader.send(contextual_params[:reader], $stdin)
111
+ end
112
+ }[reader: config.stdin_reader]
171
113
  end
172
114
 
173
115
  def rendering_options
174
116
  options = { float_format: config.float_format }
175
- if config.pretty? and (hl = highline)
117
+ if config.pretty? and (hl = highline) and (hl.output_cols)
176
118
  options[:pretty] = config.pretty?
177
119
  options[:trim_at] = hl.output_cols - 1
178
120
  end