alf-shell 0.13.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.
- data/CHANGELOG.md +4 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +35 -0
- data/LICENCE.md +22 -0
- data/Manifest.txt +13 -0
- data/README.md +11 -0
- data/Rakefile +11 -0
- data/bin/alf +17 -0
- data/lib/alf-shell.rb +1 -0
- data/lib/alf/shell.rb +48 -0
- data/lib/alf/shell/command.rb +21 -0
- data/lib/alf/shell/command/exec.rb +16 -0
- data/lib/alf/shell/command/help.rb +30 -0
- data/lib/alf/shell/command/main.rb +175 -0
- data/lib/alf/shell/command/show.rb +49 -0
- data/lib/alf/shell/doc_manager.rb +83 -0
- data/lib/alf/shell/ext/signature.rb +45 -0
- data/lib/alf/shell/from_argv.rb +78 -0
- data/lib/alf/shell/loader.rb +2 -0
- data/lib/alf/shell/operator.rb +63 -0
- data/lib/alf/shell/support.rb +28 -0
- data/lib/alf/shell/version.rb +16 -0
- data/spec/integration/__database__/group.alf +3 -0
- data/spec/integration/__database__/parts.rash +6 -0
- data/spec/integration/__database__/suppliers.rash +5 -0
- data/spec/integration/__database__/suppliers_csv.csv +6 -0
- data/spec/integration/__database__/supplies.rash +12 -0
- data/spec/integration/alf/alf.db +0 -0
- data/spec/integration/alf/alf_db.cmd +1 -0
- data/spec/integration/alf/alf_db.stdout +5 -0
- data/spec/integration/alf/alf_e.cmd +1 -0
- data/spec/integration/alf/alf_e.stdout +4 -0
- data/spec/integration/alf/alf_help.cmd +1 -0
- data/spec/integration/alf/alf_help.stdout +72 -0
- data/spec/integration/alf/alf_json.cmd +1 -0
- data/spec/integration/alf/alf_json.stdout +1 -0
- data/spec/integration/alf/alf_r.cmd +1 -0
- data/spec/integration/alf/alf_r.stdout +5 -0
- data/spec/integration/alf/alf_version.cmd +1 -0
- data/spec/integration/alf/alf_version.stdout +2 -0
- data/spec/integration/alf/alf_yaml.cmd +1 -0
- data/spec/integration/alf/alf_yaml.stdout +22 -0
- data/spec/integration/alf/rel.rash +1 -0
- data/spec/integration/autonum/autonum_0.cmd +1 -0
- data/spec/integration/autonum/autonum_0.stdout +9 -0
- data/spec/integration/autonum/autonum_1.cmd +1 -0
- data/spec/integration/autonum/autonum_1.stdout +9 -0
- data/spec/integration/clip/clip_0.cmd +1 -0
- data/spec/integration/clip/clip_0.stdout +9 -0
- data/spec/integration/clip/clip_1.cmd +1 -0
- data/spec/integration/clip/clip_1.stdout +9 -0
- data/spec/integration/coerce/coerce_1.cmd +1 -0
- data/spec/integration/coerce/coerce_1.stdout +5 -0
- data/spec/integration/compact/compact_0.cmd +1 -0
- data/spec/integration/compact/compact_0.stdout +9 -0
- data/spec/integration/defaults/defaults_0.cmd +1 -0
- data/spec/integration/defaults/defaults_0.stdout +9 -0
- data/spec/integration/defaults/defaults_1.cmd +1 -0
- data/spec/integration/defaults/defaults_1.stdout +9 -0
- data/spec/integration/defaults/defaults_2.cmd +1 -0
- data/spec/integration/defaults/defaults_2.stdout +9 -0
- data/spec/integration/extend/extend_0.cmd +1 -0
- data/spec/integration/extend/extend_0.stdout +16 -0
- data/spec/integration/generator/generator_1.cmd +1 -0
- data/spec/integration/generator/generator_1.stdout +10 -0
- data/spec/integration/generator/generator_2.cmd +1 -0
- data/spec/integration/generator/generator_2.stdout +5 -0
- data/spec/integration/generator/generator_3.cmd +1 -0
- data/spec/integration/generator/generator_3.stdout +5 -0
- data/spec/integration/group/group_0.cmd +1 -0
- data/spec/integration/group/group_0.stdout +32 -0
- data/spec/integration/group/group_1.cmd +1 -0
- data/spec/integration/group/group_1.stdout +32 -0
- data/spec/integration/help/help_1.cmd +1 -0
- data/spec/integration/help/help_1.stdout +25 -0
- data/spec/integration/intersect/intersect_0.cmd +1 -0
- data/spec/integration/intersect/intersect_0.stdout +9 -0
- data/spec/integration/join/join_0.cmd +1 -0
- data/spec/integration/join/join_0.stdout +16 -0
- data/spec/integration/matching/matching_0.cmd +1 -0
- data/spec/integration/matching/matching_0.stdout +8 -0
- data/spec/integration/minus/minus_0.cmd +1 -0
- data/spec/integration/minus/minus_0.stdout +4 -0
- data/spec/integration/not-matching/not-matching_0.cmd +1 -0
- data/spec/integration/not-matching/not-matching_0.stdout +5 -0
- data/spec/integration/project/project_0.cmd +1 -0
- data/spec/integration/project/project_0.stdout +9 -0
- data/spec/integration/project/project_1.cmd +1 -0
- data/spec/integration/project/project_1.stdout +9 -0
- data/spec/integration/quota/quota_0.cmd +1 -0
- data/spec/integration/quota/quota_0.stdout +16 -0
- data/spec/integration/rank/rank_1.cmd +1 -0
- data/spec/integration/rank/rank_1.stdout +10 -0
- data/spec/integration/rank/rank_2.cmd +1 -0
- data/spec/integration/rank/rank_2.stdout +10 -0
- data/spec/integration/rank/rank_3.cmd +1 -0
- data/spec/integration/rank/rank_3.stdout +10 -0
- data/spec/integration/rank/rank_4.cmd +1 -0
- data/spec/integration/rank/rank_4.stdout +6 -0
- data/spec/integration/rank/rank_5.cmd +1 -0
- data/spec/integration/rank/rank_5.stdout +6 -0
- data/spec/integration/rename/rename_0.cmd +1 -0
- data/spec/integration/rename/rename_0.stdout +9 -0
- data/spec/integration/restrict/restrict_0.cmd +1 -0
- data/spec/integration/restrict/restrict_0.stdout +6 -0
- data/spec/integration/restrict/restrict_1.cmd +1 -0
- data/spec/integration/restrict/restrict_1.stdout +6 -0
- data/spec/integration/show/show_base.cmd +1 -0
- data/spec/integration/show/show_base.stdout +5 -0
- data/spec/integration/show/show_base_sort_1.cmd +1 -0
- data/spec/integration/show/show_base_sort_1.stdout +9 -0
- data/spec/integration/show/show_base_sort_2.cmd +1 -0
- data/spec/integration/show/show_base_sort_2.stdout +9 -0
- data/spec/integration/show/show_conflictual.cmd +1 -0
- data/spec/integration/show/show_conflictual.stdout +5 -0
- data/spec/integration/show/show_ff.cmd +1 -0
- data/spec/integration/show/show_ff.stdout +10 -0
- data/spec/integration/show/show_rash.cmd +1 -0
- data/spec/integration/show/show_rash.stdout +5 -0
- data/spec/integration/show/show_rash_pretty.cmd +1 -0
- data/spec/integration/show/show_rash_pretty.stdout +30 -0
- data/spec/integration/show/show_yaml.cmd +1 -0
- data/spec/integration/show/show_yaml.stdout +22 -0
- data/spec/integration/sort/sort_0.cmd +1 -0
- data/spec/integration/sort/sort_0.stdout +9 -0
- data/spec/integration/sort/sort_1.cmd +1 -0
- data/spec/integration/sort/sort_1.stdout +9 -0
- data/spec/integration/sort/sort_2.cmd +1 -0
- data/spec/integration/sort/sort_2.stdout +9 -0
- data/spec/integration/sort/sort_3.cmd +1 -0
- data/spec/integration/sort/sort_3.stdout +9 -0
- data/spec/integration/summarize/summarize_0.cmd +1 -0
- data/spec/integration/summarize/summarize_0.stdout +8 -0
- data/spec/integration/test_shell.rb +56 -0
- data/spec/integration/union/union_0.cmd +1 -0
- data/spec/integration/union/union_0.stdout +9 -0
- data/spec/integration/unwrap/unwrap_0.cmd +1 -0
- data/spec/integration/unwrap/unwrap_0.stdout +9 -0
- data/spec/integration/wrap/wrap_0.cmd +1 -0
- data/spec/integration/wrap/wrap_0.stdout +9 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/test_shell.rb +10 -0
- data/spec/unit/doc_manager/dynamic.md +1 -0
- data/spec/unit/doc_manager/example.md +1 -0
- data/spec/unit/doc_manager/example_1.txt +11 -0
- data/spec/unit/doc_manager/static.md +1 -0
- data/spec/unit/doc_manager/test_call.rb +43 -0
- data/spec/unit/ext/signature/test_argv2args.rb +82 -0
- data/spec/unit/ext/signature/test_to_shell.rb +103 -0
- data/spec/unit/from_argv/test_to_attr_list.rb +30 -0
- data/spec/unit/from_argv/test_to_attr_name.rb +27 -0
- data/spec/unit/from_argv/test_to_boolean.rb +32 -0
- data/spec/unit/from_argv/test_to_heading.rb +37 -0
- data/spec/unit/from_argv/test_to_ordering.rb +28 -0
- data/spec/unit/from_argv/test_to_predicate.rb +26 -0
- data/spec/unit/from_argv/test_to_renaming.rb +23 -0
- data/spec/unit/from_argv/test_to_size.rb +32 -0
- data/spec/unit/from_argv/test_to_summarization.rb +19 -0
- data/spec/unit/from_argv/test_to_tuple_computation.rb +18 -0
- data/spec/unit/from_argv/test_to_tuple_expression.rb +38 -0
- data/spec/unit/main/test_class_methods.rb +44 -0
- data/spec/unit/operator/test_autonum.rb +28 -0
- data/spec/unit/operator/test_clip.rb +29 -0
- data/spec/unit/operator/test_coerce.rb +22 -0
- data/spec/unit/operator/test_compact.rb +16 -0
- data/spec/unit/operator/test_defaults.rb +29 -0
- data/spec/unit/operator/test_extend.rb +21 -0
- data/spec/unit/operator/test_generator.rb +37 -0
- data/spec/unit/operator/test_group.rb +32 -0
- data/spec/unit/operator/test_infer_heading.rb +16 -0
- data/spec/unit/operator/test_intersect.rb +18 -0
- data/spec/unit/operator/test_join.rb +18 -0
- data/spec/unit/operator/test_matching.rb +18 -0
- data/spec/unit/operator/test_minus.rb +18 -0
- data/spec/unit/operator/test_not_matching.rb +18 -0
- data/spec/unit/operator/test_project.rb +38 -0
- data/spec/unit/operator/test_quota.rb +23 -0
- data/spec/unit/operator/test_rank.rb +30 -0
- data/spec/unit/operator/test_rename.rb +21 -0
- data/spec/unit/operator/test_restrict.rb +36 -0
- data/spec/unit/operator/test_sort.rb +49 -0
- data/spec/unit/operator/test_summarize.rb +30 -0
- data/spec/unit/operator/test_ungroup.rb +28 -0
- data/spec/unit/operator/test_union.rb +18 -0
- data/spec/unit/operator/test_unwrap.rb +28 -0
- data/spec/unit/operator/test_wrap.rb +30 -0
- data/tasks/gem.rake +8 -0
- data/tasks/test.rake +6 -0
- metadata +317 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module Alf
|
|
2
|
+
module Shell
|
|
3
|
+
class DocManager
|
|
4
|
+
|
|
5
|
+
# Main documentation folder
|
|
6
|
+
DOC_FOLDER = Path.backfind("doc")
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# Called by Quickl when it's time to generate documentation of `cmd`.
|
|
10
|
+
#
|
|
11
|
+
def call(cmd, options = {})
|
|
12
|
+
if File.exists?(file = find_file(cmd))
|
|
13
|
+
text = File.read(file)
|
|
14
|
+
|
|
15
|
+
# Replace occurences of #{signature} to #{signature.to_xxx}
|
|
16
|
+
# according to options
|
|
17
|
+
method = (options[:method] || "shell").to_s
|
|
18
|
+
text = text.gsub('#(signature)', '#(signature.to_' + method + ')')
|
|
19
|
+
|
|
20
|
+
# Replace occurences of #{...} on single lines
|
|
21
|
+
text = text.gsub(/^([ \t]*)#\(([^\)]+)\)/){|match|
|
|
22
|
+
spacing, invocation = $1, $2
|
|
23
|
+
res = cmd.instance_eval(invocation).to_s
|
|
24
|
+
realign(res, spacing, true)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# Replace occurences of #{...} in other places
|
|
28
|
+
text = text.gsub(/#\(([^\)]+)\)/){|match|
|
|
29
|
+
cmd.instance_eval($1).to_s
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# Replace occurences of !{...} by the execution of the example
|
|
33
|
+
text = text.gsub(/^([ \t]*)!\(([^\)]+)\)/){|match|
|
|
34
|
+
spacing, invocation = $1, $2
|
|
35
|
+
args = Quickl.parse_commandline_args(invocation)[1..-1]
|
|
36
|
+
op = run_alf_command(args)
|
|
37
|
+
res = op.to_relation.to_s
|
|
38
|
+
res = realign(res, spacing, false)[0...-1]
|
|
39
|
+
if options[:method] == :lispy
|
|
40
|
+
invocation = Alf::Support.to_lispy(op)
|
|
41
|
+
end
|
|
42
|
+
realign("$ #{invocation}\n\n#{res}", spacing, false)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
else
|
|
46
|
+
"Sorry, no documentation available for #{cmd.command_name}"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def run_alf_command(argv, requester = nil)
|
|
53
|
+
argv = Quickl.parse_commandline_args(argv) if argv.is_a?(String)
|
|
54
|
+
argv = Quickl.split_commandline_args(argv, '|')
|
|
55
|
+
argv.inject(nil) do |cmd,arr|
|
|
56
|
+
arr.shift if arr.first == "alf"
|
|
57
|
+
main = Alf::Shell::Main.new(Alf.examples)
|
|
58
|
+
main.stdin_operand = cmd unless cmd.nil?
|
|
59
|
+
main.run(arr, requester)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def realign(txt, spacing, strip)
|
|
64
|
+
rx = strip ? /^[ \t]*/ : /^/
|
|
65
|
+
txt.gsub(rx, spacing)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def find_file(cmd)
|
|
69
|
+
where = if cmd.command?
|
|
70
|
+
"commands"
|
|
71
|
+
elsif cmd.operator? && cmd.relational?
|
|
72
|
+
File.join("operators", "relational")
|
|
73
|
+
elsif cmd.operator? && cmd.non_relational?
|
|
74
|
+
File.join("operators", "non_relational")
|
|
75
|
+
else
|
|
76
|
+
raise "Unexpected command #{cmd}"
|
|
77
|
+
end
|
|
78
|
+
File.join(DOC_FOLDER, where, "#{cmd.command_name}.md")
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end # class DocManager
|
|
82
|
+
end # module Shell
|
|
83
|
+
end # module Alf
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Alf
|
|
2
|
+
module Algebra
|
|
3
|
+
class Signature
|
|
4
|
+
|
|
5
|
+
# Converts commandline arguments to operator constructor arguments
|
|
6
|
+
def argv2args(argv)
|
|
7
|
+
# First split over --
|
|
8
|
+
argv = Quickl.split_commandline_args(argv)
|
|
9
|
+
|
|
10
|
+
# Parse the options and replace argv[0] by remaining arguments
|
|
11
|
+
opts = {}
|
|
12
|
+
argv[0] = option_parser(opts).parse!(argv[0])
|
|
13
|
+
opts = default_options.merge(opts)
|
|
14
|
+
|
|
15
|
+
# Operands are argv[0], and can be removed
|
|
16
|
+
oper = argv.shift
|
|
17
|
+
|
|
18
|
+
# Coerce each remaining argument according to the signature
|
|
19
|
+
args = []
|
|
20
|
+
with_each_arg(argv) do |name,dom,value|
|
|
21
|
+
invalid_args!(args) if value.nil?
|
|
22
|
+
args << Shell.from_argv(Array(value), dom)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
[oper, args, opts]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Returns a shell synopsis for this signature.
|
|
29
|
+
#
|
|
30
|
+
# Example:
|
|
31
|
+
#
|
|
32
|
+
# Alf::Algebra::Project.signature.to_shell
|
|
33
|
+
# # => "alf project [--allbut] [OPERAND] -- ATTRIBUTES"
|
|
34
|
+
def to_shell
|
|
35
|
+
oper = operator.nullary? ? "" :
|
|
36
|
+
(operator.unary? ? "[OPERAND]" : "[LEFT] RIGHT")
|
|
37
|
+
opts = options.map{|opt| "[#{option_name(opt)}]" }.join(" ")
|
|
38
|
+
args = arguments.map{|arg,_| "#{arg.to_s.upcase}" }.join(" -- ")
|
|
39
|
+
optargs = "#{opts} #{oper} " + (args.empty? ? "" : "-- #{args}")
|
|
40
|
+
"alf #{operator.rubycase_name} #{optargs.strip}".strip
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end # class Signature
|
|
44
|
+
end # module Algebra
|
|
45
|
+
end # module Alf
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module Alf
|
|
2
|
+
module Shell
|
|
3
|
+
|
|
4
|
+
FROM_ARGV = Myrrha.coercions do |c|
|
|
5
|
+
|
|
6
|
+
# ARGV -> Boolean
|
|
7
|
+
c.coercion(Array, Boolean){|argv,_|
|
|
8
|
+
throw :next_rule if argv.size > 1
|
|
9
|
+
Alf::Support.coerce(argv.first || false, Boolean)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
# ARGV -> Size
|
|
13
|
+
c.coercion(Array, Size){|argv,_|
|
|
14
|
+
throw :next_rule if argv.size > 1
|
|
15
|
+
Size.new(Integer(argv.first || 0))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
# ARGV -> AttrName
|
|
19
|
+
c.coercion(Array, AttrName){|argv,_|
|
|
20
|
+
throw :next_rule if argv.size > 1
|
|
21
|
+
AttrName.coerce(argv.first)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# ARGV -> AttrList
|
|
25
|
+
c.coercion(Array, AttrList){|argv,_|
|
|
26
|
+
AttrList.coerce(argv)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# ARGV -> Heading
|
|
30
|
+
c.coercion(Array, Heading){|argv,_|
|
|
31
|
+
Heading.coerce(argv)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# ARGV -> Ordering
|
|
35
|
+
c.coercion(Array, Ordering){|argv,_|
|
|
36
|
+
Ordering.coerce(argv)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# ARGV -> Renaming
|
|
40
|
+
c.coercion(Array, Renaming){|argv,_|
|
|
41
|
+
Renaming.coerce(argv)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# ARGV -> Summarization
|
|
45
|
+
c.coercion(Array, Summarization){|argv,_|
|
|
46
|
+
Summarization.coerce(argv)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# ARGV -> TupleComputation
|
|
50
|
+
c.coercion(Array, TupleComputation){|argv,_|
|
|
51
|
+
TupleComputation.coerce(argv)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# ARGV -> TupleExpression
|
|
55
|
+
c.coercion(Array, TupleExpression){|argv,_|
|
|
56
|
+
throw :next_rule if argv.size != 1
|
|
57
|
+
TupleExpression.coerce(argv.first)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# ARGV -> Predicate
|
|
61
|
+
c.coercion(Array, Predicate){|argv,_|
|
|
62
|
+
if argv.size == 1
|
|
63
|
+
Predicate.coerce(argv.first)
|
|
64
|
+
elsif (argv.size % 2) == 0
|
|
65
|
+
Predicate.coerce(Hash[argv.each_slice(2).map{|k,v| [k.to_sym, eval(v)] }])
|
|
66
|
+
else
|
|
67
|
+
throw :next_rule
|
|
68
|
+
end
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def self.from_argv(argv, target_domain)
|
|
74
|
+
FROM_ARGV.coerce(argv, target_domain)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end # module Shell
|
|
78
|
+
end # module Alf
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
module Alf
|
|
3
|
+
module Shell
|
|
4
|
+
module Operator
|
|
5
|
+
|
|
6
|
+
module ClassMethods
|
|
7
|
+
extend Forwardable
|
|
8
|
+
|
|
9
|
+
attr_accessor :operator_class
|
|
10
|
+
def_delegators :operator_class, :signature,
|
|
11
|
+
:relational?,
|
|
12
|
+
:non_relational?,
|
|
13
|
+
:experimental?,
|
|
14
|
+
:nullary?,
|
|
15
|
+
:unary?,
|
|
16
|
+
:binary?
|
|
17
|
+
|
|
18
|
+
def command?
|
|
19
|
+
false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def operator?
|
|
23
|
+
true
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module InstanceMethods
|
|
28
|
+
extend Forwardable
|
|
29
|
+
|
|
30
|
+
def_delegators :"self.class", :signature, :operator_class
|
|
31
|
+
|
|
32
|
+
def run(argv, req = nil)
|
|
33
|
+
@requester = req
|
|
34
|
+
compile(argv)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def compile(argv)
|
|
38
|
+
operands, args, options = signature.argv2args(argv)
|
|
39
|
+
operands = operands(operands, operator_class.arity)
|
|
40
|
+
init_args = [operands] + args + [options]
|
|
41
|
+
operator_class.new(*init_args)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end # module InstanceMethods
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# Defines a command for `clazz`
|
|
48
|
+
def self.define_operator(op_name, op_class)
|
|
49
|
+
superclass = Shell::Operator() do |b|
|
|
50
|
+
b.callback do |cmd|
|
|
51
|
+
cmd.operator_class = op_class
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
Operator.const_set(::Alf::Support.class_name(op_class), Class.new(superclass))
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
Algebra::Operator.listen do |op_name, op_class|
|
|
58
|
+
define_operator(op_name, op_class)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end # module Operator
|
|
62
|
+
end # module Shell
|
|
63
|
+
end # module Alf
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Alf
|
|
2
|
+
module Shell
|
|
3
|
+
module Support
|
|
4
|
+
|
|
5
|
+
def database
|
|
6
|
+
requester && requester.database
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def compiler
|
|
10
|
+
@compiler ||= (database && database.connection.compiler) || Engine::Compiler.new(nil)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def operands(argv, size = nil)
|
|
14
|
+
operands = [ stdin_operand ] + Array(argv)
|
|
15
|
+
operands = operands[(operands.size - size)..-1] if size
|
|
16
|
+
operands = operands.map{|arg|
|
|
17
|
+
arg = Algebra.named_operand(arg.to_sym, database) if arg.is_a?(String)
|
|
18
|
+
Algebra::Operand.coerce(arg)
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def stdin_operand
|
|
23
|
+
requester.stdin_operand rescue $stdin
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end # module Support
|
|
27
|
+
end # module Shell
|
|
28
|
+
end # module Alf
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{:pid => 'P1', :name => 'Nut', :color => 'Red', :weight => 12.0, :city => 'London'}
|
|
2
|
+
{:pid => 'P2', :name => 'Bolt', :color => 'Green', :weight => 17.0, :city => 'Paris'}
|
|
3
|
+
{:pid => 'P3', :name => 'Screw', :color => 'Blue', :weight => 17.0, :city => 'Oslo'}
|
|
4
|
+
{:pid => 'P4', :name => 'Screw', :color => 'Red', :weight => 14.0, :city => 'London'}
|
|
5
|
+
{:pid => 'P5', :name => 'Cam', :color => 'Blue', :weight => 12.0, :city => 'Paris'}
|
|
6
|
+
{:pid => 'P6', :name => 'Cog', :color => 'Red', :weight => 19.0, :city => 'London'}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
{:sid => 'S1', :name => 'Smith', :status => 20, :city => 'London'}
|
|
2
|
+
{:sid => 'S2', :name => 'Jones', :status => 10, :city => 'Paris'}
|
|
3
|
+
{:sid => 'S3', :name => 'Blake', :status => 30, :city => 'Paris'}
|
|
4
|
+
{:sid => 'S4', :name => 'Clark', :status => 20, :city => 'London'}
|
|
5
|
+
{:sid => 'S5', :name => 'Adams', :status => 30, :city => 'Athens'}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{:sid => 'S1', :pid => 'P1', :qty => 300}
|
|
2
|
+
{:sid => 'S1', :pid => 'P2', :qty => 200}
|
|
3
|
+
{:sid => 'S1', :pid => 'P3', :qty => 400}
|
|
4
|
+
{:sid => 'S1', :pid => 'P4', :qty => 200}
|
|
5
|
+
{:sid => 'S1', :pid => 'P5', :qty => 100}
|
|
6
|
+
{:sid => 'S1', :pid => 'P6', :qty => 100}
|
|
7
|
+
{:sid => 'S2', :pid => 'P1', :qty => 300}
|
|
8
|
+
{:sid => 'S2', :pid => 'P2', :qty => 400}
|
|
9
|
+
{:sid => 'S3', :pid => 'P2', :qty => 200}
|
|
10
|
+
{:sid => 'S4', :pid => 'P2', :qty => 200}
|
|
11
|
+
{:sid => 'S4', :pid => 'P4', :qty => 300}
|
|
12
|
+
{:sid => 'S4', :pid => 'P5', :qty => 400}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
alf --db=$(_("alf",__FILE__)) show --text rel
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
alf -e "(restrict suppliers, lambda{ status > 10})"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
alf --help
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
|
|
2
|
+
alf - Relational algebra at your fingertips
|
|
3
|
+
|
|
4
|
+
SYNOPSIS
|
|
5
|
+
|
|
6
|
+
alf [--version] [--help]
|
|
7
|
+
alf -e '(lispy command)'
|
|
8
|
+
alf [FILE.alf]
|
|
9
|
+
alf [alf opts] OPERATOR [operator opts] ARGS ...
|
|
10
|
+
alf help OPERATOR
|
|
11
|
+
|
|
12
|
+
OPTIONS
|
|
13
|
+
|
|
14
|
+
-e, --execute Execute one line of script (Lispy API)
|
|
15
|
+
--rash Render output as ruby hashes
|
|
16
|
+
--text Render output as a text table
|
|
17
|
+
--yaml Render output in YAML
|
|
18
|
+
--json Render output in JSON
|
|
19
|
+
--csv Render output in CSV
|
|
20
|
+
--examples Use the example database for database
|
|
21
|
+
--db=DB Set the database to use
|
|
22
|
+
--input-reader=READER Specify the kind of reader when reading on $stdin (rash,csv,json)
|
|
23
|
+
-Idirectory Specify $LOAD_PATH directory (may be used more than once)
|
|
24
|
+
-rlibrary Require the library, before executing alf
|
|
25
|
+
--[no-]pretty Enable/disable pretty print best effort
|
|
26
|
+
-h, --help Show help
|
|
27
|
+
-v, --version Show version
|
|
28
|
+
|
|
29
|
+
RELATIONAL OPERATORS
|
|
30
|
+
|
|
31
|
+
extend Relational extension (additional, computed attributes)
|
|
32
|
+
group Relational grouping (relation-valued attributes)
|
|
33
|
+
intersect Relational intersection (aka a logical and)
|
|
34
|
+
join Relational join (and cartesian product)
|
|
35
|
+
matching Relational matching (join + project back on left)
|
|
36
|
+
minus Relational minus (aka difference)
|
|
37
|
+
not-matching Relational not matching (inverse of matching)
|
|
38
|
+
project Relational projection (clip + compact)
|
|
39
|
+
rank Relational ranking (explicit tuple positions)
|
|
40
|
+
rename Relational renaming (rename some attributes)
|
|
41
|
+
restrict Relational restriction (aka where, predicate filtering)
|
|
42
|
+
summarize Relational summarization (group-by + aggregate ops)
|
|
43
|
+
ungroup Relational un-grouping (inverse of group)
|
|
44
|
+
union Relational union
|
|
45
|
+
unwrap Relational un-wrapping (inverse of wrap)
|
|
46
|
+
wrap Relational wrapping (tuple-valued attributes)
|
|
47
|
+
|
|
48
|
+
EXPERIMENTAL RELATIONAL OPERATORS
|
|
49
|
+
|
|
50
|
+
infer-heading Relational heading inference (print the relation type)
|
|
51
|
+
quota Generalized quota-queries (position, sum progression, etc.)
|
|
52
|
+
|
|
53
|
+
NON-RELATIONAL OPERATORS
|
|
54
|
+
|
|
55
|
+
autonum Extend its operand with an unique autonumber attribute
|
|
56
|
+
clip Clip input tuples to a subset of attributes
|
|
57
|
+
coerce Force attribute coercion according to a heading
|
|
58
|
+
compact Remove tuple duplicates
|
|
59
|
+
defaults Force default values on missing/nil attributes
|
|
60
|
+
generator Generate a relation with an auto-numbered attribute
|
|
61
|
+
sort Sort input tuples according to an order relation
|
|
62
|
+
type-safe Check that input tuples are of a specified heading
|
|
63
|
+
|
|
64
|
+
OTHER NON-RELATIONAL COMMANDS
|
|
65
|
+
|
|
66
|
+
exec Executes an .alf file on current database
|
|
67
|
+
help Show help about a specific command
|
|
68
|
+
show Output input tuples through a specific renderer (text, yaml, ...)
|
|
69
|
+
|
|
70
|
+
See 'alf help COMMAND' for details about a specific command.
|
|
71
|
+
|
|
72
|
+
SystemExit
|