rethinkdb 1.2.6.1 → 1.4.0.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/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