rethinkdb 1.2.6.1 → 1.4.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/bt.rb DELETED
@@ -1,148 +0,0 @@
1
- # Copyright 2010-2012 RethinkDB, all rights reserved.
2
- module RethinkDB
3
- module BT_Mixin
4
- attr_accessor :highlight, :line
5
-
6
- def sanitize_context(context)
7
- if __FILE__ =~ /^(.*\/)[^\/]+.rb$/
8
- prefix = $1;
9
- context.reject{|x| x =~ /^#{prefix}/}
10
- else
11
- context
12
- end
13
- end
14
-
15
- def format_highlights(str)
16
- str.chars.map{|x| x == "\000" ? "^" : " "}.join.rstrip
17
- end
18
-
19
- def force_raise(query, debug=false)
20
- obj = query.run
21
- #maybe_reformat_err(query, obj);
22
- PP.pp obj if debug
23
- if obj.class == Query_Results
24
- obj = obj.to_a
25
- elsif obj.class == Hash
26
- raise RuntimeError,obj['first_error'] if obj['first_error']
27
- end
28
- obj
29
- end
30
-
31
- def maybe_reformat_err(query, obj)
32
- if obj.class == Hash && (err = obj['first_error'])
33
- obj['first_error'] = format_err(query, err)
34
- end
35
- end
36
-
37
- def format_err(query, err)
38
- parts = err.split("\nBacktrace:\n")
39
- errline = parts[0] || ""
40
- bt = (parts[1] && parts[1].split("\n")) || []
41
- errline+"\n"+query.print_backtrace(bt)
42
- end
43
-
44
- def set(sym,val)
45
- @map = {} if not @map
46
- res, @map[sym] = @map[sym], val
47
- return res
48
- end
49
- def consume sym
50
- @map = {} if not @map
51
- res, @map[sym] = @map[sym], nil
52
- return res.nil? ? 0 : res
53
- end
54
- def expand arg
55
- case arg
56
- when 'attr' then []
57
- when 'attrname' then []
58
- when 'base' then [1+consume(:reduce)]
59
- when 'body' then [4+consume(:reduce)]
60
- when 'datacenter' then []
61
- when 'db_name' then []
62
- when 'expr' then [2]
63
- when 'false' then [3]
64
- when 'group_mapping' then [1, 1, 1]
65
- when 'key' then [3]
66
- when 'keyname' then []
67
- when 'lowerbound' then [1, 2]
68
- when 'mapping' then [1, 2]
69
- when 'modify_map' then [2, 1]
70
- when 'order_by' then []
71
- when 'point_map' then [4, 1]
72
- when 'predicate' then [1, 2]
73
- when 'reduce' then [1]
74
- when 'reduction' then set(:reduce, -1); [1, 3]
75
- when 'stream' then [1]
76
- when 'table_name' then []
77
- when 'table_ref' then []
78
- when 'test' then [1]
79
- when 'true' then [2]
80
- when 'upperbound' then [1, 3]
81
- when 'value_mapping' then [1, 2, 1]
82
- when 'view' then [1]
83
- when /arg:([0-9]+)/ then [2, $1.to_i]
84
- when /attrs:([0-9]+)/ then []
85
- when /elem:([0-9]+)/ then [$1.to_i+1]
86
- when /bind:(.+)$/ then [1, $1]
87
- when /key:(.+)$/ then [1..-1, $1]
88
- when /query:([0-9]+)/ then [3, $1.to_i]
89
- when /term:([0-9]+)/ then [2, $1.to_i]
90
- else [:error]
91
- end
92
- end
93
-
94
- def recur(arr, lst, val)
95
- if lst[0].class == String
96
- entry = arr[0..-1].find{|x| x[0].to_s == lst[0]}
97
- raise RuntimeError if not entry
98
- mark(entry[1], lst[1..-1], val)
99
- elsif lst[0].class == Fixnum || lst[0].class == Range
100
- mark(arr[lst[0]], lst[1..-1], val) if lst != []
101
- else
102
- raise RuntimeError
103
- end
104
- end
105
- def mark(query, lst, val)
106
- #PP.pp [lst, query.class, query]
107
- if query.class == Array
108
- recur(query, lst, val) if lst != []
109
- elsif query.kind_of? RQL_Query
110
- if lst == []
111
- @line = sanitize_context(query.context)[0]
112
- val,query.marked = query.marked, val
113
- val
114
- else
115
- recur(query.body, lst, val)
116
- end
117
- else raise RuntimeError
118
- end
119
- end
120
-
121
- def with_marked_error(query, bt)
122
- @map = {}
123
- bt = bt.map{|x| expand x}.flatten
124
- raise RuntimeError if bt.any?{|x| x == :error}
125
- old = mark(query, bt, :error)
126
- res = yield
127
- mark(query, bt, old)
128
- return res
129
- end
130
-
131
- def with_highlight
132
- @highlight = true
133
- str = yield
134
- @highlight = false
135
- str.chars.map{|x| x == "\000" ? "^" : " "}.join.rstrip
136
- end
137
-
138
- def alt_inspect(query, &block)
139
- class << query
140
- attr_accessor :str_block
141
- def inspect; real_inspect({:str => @str_block.call(self)}); end
142
- end
143
- query.str_block = block
144
- query
145
- end
146
- end
147
- module BT; extend BT_Mixin; end
148
- end
@@ -1,35 +0,0 @@
1
- # Copyright 2010-2012 RethinkDB, all rights reserved.
2
- module RethinkDB
3
- # Data collectors are ways of aggregating data (for use with
4
- # Sequence#groupby). You can define your own; all they are is a hash
5
- # containing a <b>+mapping+</b> to be applied to row, a
6
- # <b>+base+</b>/<b>+reduction+</b> to reduce over the mappings, and an
7
- # optional <b>+finalizer+</b> to call on the output of the reduction. You can
8
- # expand the builtin data collectors below for examples.
9
- #
10
- # All of the builtin collectors can also be accessed using the <b>+r+</b>
11
- # shortcut (like <b>+r.sum+</b>).
12
- module Data_Collectors
13
- # Count the number of rows in each group.
14
- def self.count
15
- { :mapping => lambda{|row| 1},
16
- :base => 0,
17
- :reduction => lambda{|acc, val| acc + val} }
18
- end
19
-
20
- # Sum a particular attribute of the rows in each group.
21
- def self.sum(attr)
22
- { :mapping => lambda{|row| row[attr]},
23
- :base => 0,
24
- :reduction => lambda{|acc, val| acc + val} }
25
- end
26
-
27
- # Average a particular attribute of the rows in each group.
28
- def self.avg(attr)
29
- { :mapping => lambda{|row| [row[attr], 1]},
30
- :base => [0, 0],
31
- :reduction => lambda{|acc, val| [acc[0] + val[0], acc[1] + val[1]]},
32
- :finalizer => lambda{|res| res[0] / res[1]} }
33
- end
34
- end
35
- end
data/lib/jsons.rb DELETED
@@ -1,140 +0,0 @@
1
- # Copyright 2010-2012 RethinkDB, all rights reserved.
2
- module RethinkDB
3
- # A query returning a JSON expression. Most of the functions that you
4
- # can run on a JSON object are found in RethinkDB::RQL and accessed
5
- # with the <b>+r+</b> shortcut. For convenience, may of the
6
- # functions in Rethinkdb::RQL can be run as if they were instance
7
- # methods of JSON_Expression. For example, the following are
8
- # equivalent:
9
- # r.add(1, 2)
10
- # r(1).add(2)
11
- # r(3)
12
- #
13
- # Running a JSON_Expression query will return a literal Ruby
14
- # representation of the resulting JSON, rather than a stream or a
15
- # string. For example, the following are equivalent:
16
- # r.add(1,2).run
17
- # 3
18
- # As are:
19
- # r({:a => 1, :b => 2}).pick(:a).run
20
- # {'a' => 1}
21
- # (Note that the symbol keys were coerced into string keys in the
22
- # object. JSON doesn't distinguish between symbols and strings.)
23
- class JSON_Expression
24
- # If <b>+ind+</b> is a symbol or a string, gets the corresponding
25
- # attribute of an object. For example, the following are equivalent:
26
- # r({:id => 1})[:id]
27
- # r({:id => 1})['id']
28
- # r(1)
29
- # Otherwise, if <b>+ind+</b> is a number or a range, invokes RethinkDB::Sequence#[]
30
- def [](ind)
31
- if ind.class == Symbol || ind.class == String
32
- BT.alt_inspect(JSON_Expression.new [:call, [:getattr, ind], [self]]) {
33
- "#{self.inspect}[#{ind.inspect}]"
34
- }
35
- else
36
- super
37
- end
38
- end
39
-
40
- # Append a single element to an array. The following are equivalent:
41
- # r([1,2,3,4])
42
- # r([1,2,3]).append(4)
43
- def append(el)
44
- JSON_Expression.new [:call, [:arrayappend], [self, S.r(el)]]
45
- end
46
-
47
- # Get an attribute of a JSON object (the same as
48
- # JSON_Expression#[]). The following are equivalent.
49
- # r({:id => 1}).getattr(:id)
50
- # r({:id => 1})[:id]
51
- # r(1)
52
- def getattr(attrname)
53
- JSON_Expression.new [:call, [:getattr, attrname], [self]]
54
- end
55
-
56
- # Check whether a JSON object has all of the particular attributes. The
57
- # following are equivalent:
58
- # r({:id => 1, :val => 2}).contains(:id, :val)
59
- # r(true)
60
- def contains(*attrnames)
61
- if attrnames.length == 1
62
- JSON_Expression.new [:call, [:contains, attrnames[0]], [self]]
63
- else
64
- self.contains(attrnames[0]) & self.contains(*attrnames[1..-1])
65
- end
66
- end
67
-
68
- # Construct a JSON object that has a subset of the attributes of
69
- # another JSON object by specifying which to keep. The following are equivalent:
70
- # r({:a => 1, :b => 2, :c => 3}).pick(:a, :c)
71
- # r({:a => 1, :c => 3})
72
- def pick(*attrnames)
73
- JSON_Expression.new [:call, [:pick, *attrnames], [self]]
74
- end
75
-
76
- # Construct a JSON object that has a subset of the attributes of
77
- # another JSON object by specifying which to drop. The following are equivalent:
78
- # r({:a => 1, :b => 2, :c => 3}).without(:a, :c)
79
- # r({:b => 2})
80
- def unpick(*attrnames)
81
- JSON_Expression.new [:call, [:unpick, *attrnames], [self]]
82
- end
83
-
84
- # Convert from an array to a stream. While most sequence functions are polymorphic
85
- # and handle both arrays and streams, when arrays or streams need to be
86
- # combined (e.g. via <b>+union+</b>) you need to explicitly convert between
87
- # the types. This is mostly for safety, but also because which type you're
88
- # working with affects error handling. The following are equivalent:
89
- # r([1,2,3]).arraytostream
90
- # r([1,2,3]).to_stream
91
- def array_to_stream(); Stream_Expression.new [:call, [:array_to_stream], [self]]; end
92
-
93
- # Prefix numeric -. The following are equivalent:
94
- # -r(1)
95
- # r(-1)
96
- def -@; JSON_Expression.new [:call, [:subtract], [self]]; end
97
- # Prefix numeric +. The following are equivalent:
98
- # +r(-1)
99
- # r(-1)
100
- def +@; JSON_Expression.new [:call, [:add], [self]]; end
101
- end
102
-
103
- # A query representing a variable. Produced by e.g. RQL::letvar. This
104
- # is its own class because it needs to behave correctly when spliced
105
- # into a string (see RQL::js).
106
- class Var_Expression < JSON_Expression
107
- # Convert from an RQL query representing a variable to the name of that
108
- # variable. Used e.g. in constructing javascript functions.
109
- def to_s
110
- if @body.class == Array and @body[0] == :var
111
- then @body[1]
112
- else raise TypeError, 'Can only call to_s on RQL_Queries representing variables.'
113
- end
114
- end
115
- end
116
-
117
- # Like Multi_Row_Selection, but for a single row. E.g.:
118
- # table.get(0)
119
- # yields a Single_Row_Selection
120
- class Single_Row_Selection < JSON_Expression
121
- # Analagous to Multi_Row_Selection#update
122
- def update(variant=nil)
123
- S.with_var {|vname,v|
124
- Write_Query.new [:pointupdate, *(@body[1..-1] + [[vname, S.r(yield(v))]])]
125
- }.apply_variant(variant)
126
- end
127
-
128
- # Analagous to Multi_Row_Selection#mutate
129
- def replace(variant=nil)
130
- S.with_var {|vname,v|
131
- Write_Query.new [:pointreplace, *(@body[1..-1] + [[vname, S.r(yield(v))]])]
132
- }.apply_variant(variant)
133
- end
134
-
135
- # Analagous to Multi_Row_Selection#delete
136
- def delete
137
- Write_Query.new [:pointdelete, *(@body[1..-1])]
138
- end
139
- end
140
- end
@@ -1,137 +0,0 @@
1
- # Copyright 2010-2012 RethinkDB, all rights reserved.
2
- module RethinkDB
3
- module RQL_Protob_Mixin
4
- include P_Mixin
5
- @@token = 0 # We need a new token every time we compile a query
6
- @@backtrace = []
7
-
8
- # Right now the only special case is :compare, but in general we might have
9
- # terms that don't follow the conventions and we need a place to store that.
10
- def handle_special_cases(message, query_type, query_args)
11
- #PP.pp ["special_case", message, query_type, query_args]
12
- case query_type
13
- when :compare then
14
- message.comparison = enum_type(Builtin::Comparison, *query_args)
15
- throw :unknown_comparator_error if not message.comparison
16
- return true
17
- else return false
18
- end
19
- end
20
-
21
- ################################################################################
22
- # I apologize for the code after this. I was originally doing something
23
- # clever to generate the S-expressions, so they don't always match the
24
- # protobufs perfectly, and the complexity necessary to handle that got
25
- # pushed down into protobuf compilation. Later the cleverness went away,
26
- # but I left the code below intact rather than refactoring for two reasons:
27
- # 1) It's fragile and took about a day to get right, so refactoring it
28
- # probably isn't free.
29
- # 2) We are probably going to have to change protobuf implementations for
30
- # speed reasons anyway, at which point this will have to be rewritten,
31
- # and rewriting it twice doesn't make sense
32
- ################################################################################
33
-
34
- # Compile an RQL query into a protobuf.
35
- def comp(message_class, args, repeating=false)
36
- # H4x to make the backtraces print right until we fix the protobuf.
37
- message_class = S.rewrite(message_class);
38
- #PP.pp(["A", message_class, args, repeating]) #DEBUG
39
-
40
- # Handle special cases of arguments:
41
- # * When we're compiling a repeating term, in which case we want to
42
- # compile the elements of [args] rather than [args] itself.
43
- # * Objects, which correspond to optional argument specifications.
44
- # * Empty arguments
45
- return args.map {|arg| comp(message_class, arg)} if repeating
46
- args = args[0] if args.class == Array and args[0].class == Hash
47
- raise TypeError,"Can't build #{message_class} from #{args.inspect}." if args == []
48
-
49
- # Handle terminal parts of the protobuf, where we have to actually pack values.
50
- if message_class.kind_of? Symbol
51
- # It's easier for the user if we allow both atoms and 1-element lists
52
- args = [args] if args.class != Array
53
- if args.length != 1
54
- then raise TypeError,"Can't build #{message_class} from #{args.inspect}." end
55
- # Coercing symbols into strings makes our attribute notation more consistent
56
- args[0] = args[0].to_s if args[0].class == Symbol
57
- return args[0]
58
- end
59
-
60
- # Handle nonterminal parts of the protobuf, where we have to descend
61
- message = message_class.new
62
- if (message_type_class = C.class_types[message_class])
63
- query_type = S.rewrite(args[0]) # Our first argument is the type of our variant.
64
- message.type = enum_type(message_type_class, query_type)
65
- raise TypeError,"No type '#{query_type}' for '#{message_class}'."if !message.type
66
-
67
- if args.length == 1 # Our variant takes no arguments of its own.
68
- return message
69
- else # Compile our variant's arguments.
70
- query_args = args[1..-1]
71
- query_args = [query_args] if C.trampolines.include? query_type
72
- return message if handle_special_cases(message, query_type, query_args)
73
-
74
- # The general, non-special case.
75
- query_type = C.query_rewrites[query_type] || query_type
76
- field_metadata = message_class.fields.select{|x,y| y.name==query_type}.to_a[0]
77
- if not field_metadata
78
- then raise ArgumentError,"No field '#{query_type}' in '#{message_class}'." end
79
- field = field_metadata[1]
80
- message_set(message, query_type,
81
- comp(field.type, query_args,field.rule==:repeated))
82
- end
83
- # Handle cases where we aren't constructing a toplevel variant type.
84
- elsif args.class == Array
85
- # Handle the case where we're constructinga the fields in order.
86
- args = args.map{|x| x == nil ? RQL.expr(x) : x}
87
- fields = message.fields.sort_by {|kv| kv[0]}
88
- fields.zip(args).each {|_params|;field = _params[0][1];arg = _params[1]
89
- if arg == S.skip
90
- if field.rule != :optional
91
- raise RuntimeError, "Cannot skip non-optional rule."
92
- end
93
- else
94
- message_set(message, field.name,
95
- comp(field.type, arg, field.rule==:repeated)) if arg != nil
96
- end
97
- }
98
- else
99
- # Handle the case where the user provided neither an Array nor a Hash,
100
- # in which case they probably provided an Atom that we should treat as a
101
- # single argument (allowing this makes the interface cleaner).
102
- message = comp(message_class, [args], repeating)
103
- end
104
- return message
105
- rescue => e # Add our own, semantic backtrace to exceptions
106
- new_msg = repeating ? e.message :
107
- e.message + "\n...when compiling #{message_class} with:\n#{args.pretty_inspect}"
108
- raise e.class, new_msg
109
- end
110
-
111
- def handle_special_query_cases(sexp)
112
- if C.nonatomic_variants.include?(sexp[0])
113
- sexp[0] = sexp[0].to_s.split('_')[0].to_sym
114
- res = query(sexp)
115
- res.write_query.atomic = false
116
- return res
117
- end
118
- return nil
119
- end
120
-
121
- # Construct a protobuf query from an RQL query by inferring the query type.
122
- def query(sexp)
123
- raise TypeError, "Cannot build query from #{sexp.inspect}" if sexp.class != Array
124
- if (m = handle_special_query_cases(sexp))
125
- then q = m
126
- elsif enum_type(WriteQuery::WriteQueryType, S.rewrite(sexp[0]))
127
- then q = comp(Query, [:write, *sexp])
128
- elsif enum_type(MetaQuery::MetaQueryType, sexp[0])
129
- then q = comp(Query, [:meta, *sexp])
130
- else q = comp(Query, [:read, sexp])
131
- end
132
- q.token = (@@token += 1)
133
- return q
134
- end
135
- end
136
- module RQL_Protob; extend RQL_Protob_Mixin; end
137
- end