rethinkdb 1.2.0.1

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/rethinkdb.rb ADDED
@@ -0,0 +1,16 @@
1
+ # Copyright 2010-2012 RethinkDB, all rights reserved.
2
+ require 'rubygems'
3
+ require 'query_language.pb.rb'
4
+ require 'socket'
5
+ require 'pp'
6
+
7
+ load 'bt.rb'
8
+ load 'utils.rb'
9
+ load 'protob_compiler.rb'
10
+
11
+ load 'net.rb'
12
+
13
+ load 'data_collectors.rb'
14
+ load 'base_classes.rb'
15
+ load 'query.rb'
16
+ load 'rql.rb'
data/lib/rql.rb ADDED
@@ -0,0 +1,458 @@
1
+ # Copyright 2010-2012 RethinkDB, all rights reserved.
2
+ module RethinkDB
3
+ module Mixin_H4x # :nodoc:
4
+ def &(l,r) # :nodoc:
5
+ RQL.all_h4x(l,r)
6
+ end
7
+ end
8
+
9
+ # This module contains the RQL query construction functions. By far
10
+ # the most common way of gaining access to those functions, however,
11
+ # is to include/extend RethinkDB::Shortcuts to gain access to the
12
+ # shortcut <b>+r+</b>. That shortcut is used in all the examples
13
+ # below.
14
+ #
15
+ # Also, many of the functions here can be called as if they were
16
+ # instance methods of a RQL query. So the following are all equivalent:
17
+ # r.add(1,2)
18
+ # r(1).add(2)
19
+ # r(1) + 2
20
+ # r.+(1, 2)
21
+ module RQL
22
+ # Construct a javascript expression, which may refer to variables in scope
23
+ # (use <b>+to_s+</b> to get the name of a variable query, or simply splice
24
+ # it in). Defaults to a javascript expression, but if the optional second
25
+ # argument is <b>+:func+</b>, then you may instead provide the body of a
26
+ # javascript function. If you have a table <b>+table+</b>, the following
27
+ # are equivalent:
28
+ # table.map{|row| row[:id]}
29
+ # table.map{|row| r.js("#{row}.id")}
30
+ # table.map{r.js("this.id")} #implicit variable
31
+ # table.map{r.js("return this.id;", :func)} #implicit variable
32
+ # As are:
33
+ # r.let(:a => 1, :b => 2) { r.add(r.letvar('a'), r.letvar('b'), 1) }
34
+ # r.let(:a => 1, :b => 2) { r.js('a+b+1') }
35
+ def self.js(str, type=:expr);
36
+ if type == :expr then JSON_Expression.new [:js, "return #{str}"]
37
+ elsif type == :func then JSON_Expression.new [:js, str]
38
+ else raise TypeError, 'Type of javascript must be either :expr or :func.'
39
+ end
40
+ end
41
+
42
+ # Refer to the database named <b>+db_name+</b>. Usually used as a
43
+ # stepping stone to a table reference. For instance, to refer to
44
+ # the table 'tbl' in the database 'db':
45
+ # db('db').table('tbl')
46
+ def self.db(db_name); Database.new db_name; end
47
+
48
+ # Convert from a Ruby datatype to an RQL query. Numbers, strings, booleans,
49
+ # arrays, objects, and nil are all converted to their respective JSON types.
50
+ # <b>Note:</b> this function is idempotent, so the following are equivalent:
51
+ # r.expr(5)
52
+ # r.expr(r.expr(5))
53
+ # The shortcut `r` also acts like this when used as a function, so
54
+ # the following are equivalent:
55
+ # r.expr(1)
56
+ # r(1)
57
+ def self.expr x
58
+ return x if x.kind_of? RQL_Query
59
+ BT.alt_inspect(case x.class().hash
60
+ when Table.hash then x.to_mrs
61
+ when String.hash then JSON_Expression.new [:string, x]
62
+ when Fixnum.hash then JSON_Expression.new [:number, x]
63
+ when Float.hash then JSON_Expression.new [:number, x]
64
+ when TrueClass.hash then JSON_Expression.new [:bool, x]
65
+ when FalseClass.hash then JSON_Expression.new [:bool, x]
66
+ when NilClass.hash then JSON_Expression.new [:json_null]
67
+ when Array.hash then JSON_Expression.new [:array, *x.map{|y| expr(y)}]
68
+ when Hash.hash then
69
+ JSON_Expression.new [:object, *x.map{|var,term| [S.checkdict(var), expr(term)]}]
70
+
71
+ else raise TypeError, "RQL::expr can't handle object `#{x.inspect}` of class `#{x.class()}`.
72
+ Make sure you're providing a RQL expression or an object that can be coerced
73
+ to a JSON type (a String, Fixnum, Float, TrueClass, FalseClass, NilClass, Array,
74
+ or Hash)."
75
+ end) { x.inspect } end
76
+
77
+ # Explicitly construct an RQL variable from a string. See RQL::let.
78
+ # r.letvar('varname')
79
+ def self.letvar(varname)
80
+ BT.alt_inspect(Var_Expression.new [:var, varname]) { "letvar(#{varname.inspect})" }
81
+ end
82
+
83
+ # Provide a literal JSON string that will be parsed by the server. For
84
+ # example, the following are equivalent:
85
+ # r.expr({"a" => 5})
86
+ # r.json('{"a": 5}')
87
+ def self.json(str); JSON_Expression.new [:json, str]; end
88
+
89
+ # Construct an error. This is usually used in the branch of an <b>+if+</b>
90
+ # expression. For example:
91
+ # r.if(r(1) > 2, false, r.error('unreachable'))
92
+ # will only run the error query if 1 is greater than 2. If an error query
93
+ # does get run, it will be received as a RuntimeError in Ruby, so be
94
+ # prepared to handle it.
95
+ def self.error(err); JSON_Expression.new [:error, err]; end
96
+
97
+ # Test a predicate and execute one of two branches (just like
98
+ # Ruby's <b>+if+</b>). For example, if we have a table
99
+ # <b>+table+</b>:
100
+ # table.update{|row| r.if(row[:score] < 10, {:score => 10}, {})}
101
+ # will change every row with score below 10 in <b>+table+</b> to have score 10.
102
+ def self.branch(test, t_branch, f_branch)
103
+ tb = S.r(t_branch)
104
+ fb = S.r(f_branch)
105
+ if tb.kind_of? fb.class
106
+ resclass = fb.class
107
+ elsif fb.kind_of? tb.class
108
+ resclass = tb.class
109
+ else
110
+ raise TypeError, "Both branches of IF must be of compatible types."
111
+ end
112
+ resclass.new [:branch, S.r(test), S.r(t_branch), S.r(f_branch)]
113
+ end
114
+
115
+ # Construct a query that binds some values to variable (as
116
+ # specified by <b>+varbinds+</b>) and then executes <b>+body+</b>
117
+ # with those variables accessible through RQL::letvar. For
118
+ # example, the following are equivalent:
119
+ # r.let(:a => 2, :b => 3) { r.letvar('a') + r.letvar('b') }
120
+ # r.expr(5)
121
+ def self.let(varbinds, &body)
122
+ varbinds = varbinds.to_a
123
+ varbinds.map! {|name, value| [name.to_s, expr(value)]}
124
+ res = S.r(body.call)
125
+ res.class.new [:let, varbinds, res]
126
+ end
127
+
128
+ # Negate a boolean. May also be called as if it were an instance method of
129
+ # JSON_Expression for convenience. The following are equivalent:
130
+ # r.not(true)
131
+ # r(true).not
132
+ def self.not(pred); JSON_Expression.new [:call, [:not], [S.r(pred)]]; end
133
+
134
+ # Add two or more numbers together. May also be called as if it
135
+ # were a instance method of JSON_Expression for convenience, and
136
+ # overloads <b><tt>+</tt></b> if the lefthand side is a query.
137
+ # The following are all equivalent:
138
+ # r.add(1,2)
139
+ # r(1).add(2)
140
+ # (r(1) + 2) # Note that (1 + r(2)) is *incorrect* because Ruby only
141
+ # # overloads based on the lefthand side.
142
+ # The following is also legal:
143
+ # r.add(1,2,3)
144
+ # Add may also be used to concatenate arrays. The following are equivalent:
145
+ # r([1,2,3])
146
+ # r.add([1, 2], [3])
147
+ # r([1,2]) + [3]
148
+ def self.add(a, b, *rest)
149
+ JSON_Expression.new [:call, [:add], [S.r(a), S.r(b), *(rest.map{|x| S.r x})]];
150
+ end
151
+
152
+ # Subtract one number from another.
153
+ # May also be called as if it were a instance method of JSON_Expression for
154
+ # convenience, and overloads <b><tt>-</tt></b> if the lefthand side is a
155
+ # query. Also has the shorter synonym <b>+sub+</b>. The following are all
156
+ # equivalent:
157
+ # r.subtract(1,2)
158
+ # r(1).subtract(2)
159
+ # r.sub(1,2)
160
+ # r(1).sub(2)
161
+ # (r(1) - 2) # Note that (1 - r(2)) is *incorrect* because Ruby only
162
+ # # overloads based on the lefthand side.
163
+ def self.subtract(a, b); JSON_Expression.new [:call, [:subtract], [S.r(a), S.r(b)]]; end
164
+
165
+ # Multiply two numbers together. May also be called as if it were
166
+ # a instance method of JSON_Expression for convenience, and
167
+ # overloads <b><tt>+</tt></b> if the lefthand side is a query.
168
+ # Also has the shorter synonym <b>+mul+</b>. The following are
169
+ # all equivalent:
170
+ # r.multiply(1,2)
171
+ # r(1).multiply(2)
172
+ # r.mul(1,2)
173
+ # r(1).mul(2)
174
+ # (r(1) * 2) # Note that (1 * r(2)) is *incorrect* because Ruby only
175
+ # # overloads based on the lefthand side.
176
+ # The following is also legal:
177
+ # r.multiply(1,2,3)
178
+ def self.multiply(a, b, *rest)
179
+ JSON_Expression.new [:call, [:multiply], [S.r(a), S.r(b), *(rest.map{|x| S.r x})]];
180
+ end
181
+
182
+ # Divide one number by another. May also be called as if it were
183
+ # a instance method of JSON_Expression for convenience, and
184
+ # overloads <b><tt>/</tt></b> if the lefthand side is a query.
185
+ # Also has the shorter synonym <b>+div+</b>. The following are
186
+ # all equivalent:
187
+ # r.divide(1,2)
188
+ # r(1).divide(2)
189
+ # r.div(1,2)
190
+ # r(1).div(2)
191
+ # (r(1) / 2) # Note that (1 / r(2)) is *incorrect* because Ruby only
192
+ # # overloads based on the lefthand side.
193
+ def self.divide(a, b); JSON_Expression.new [:call, [:divide], [S.r(a), S.r(b)]]; end
194
+
195
+ # Take one number modulo another. May also be called as if it
196
+ # were a instance method of JSON_Expression for convenience, and
197
+ # overloads <b><tt>%</tt></b> if the lefthand side is a query.
198
+ # Also has the shorter synonym <b>+mod+</b>. The following are all
199
+ # equivalent:
200
+ # r.modulo(1,2)
201
+ # r(1).modulo(2)
202
+ # r.mod(1,2)
203
+ # r(1).mod(2)
204
+ # (r(1) % 2) # Note that (1 % r(2)) is *incorrect* because Ruby only
205
+ # # overloads based on the lefthand side.
206
+ def self.modulo(a, b); JSON_Expression.new [:call, [:modulo], [S.r(a), S.r(b)]]; end
207
+
208
+ # Returns true if any of its arguments are true, like <b>+or+</b>
209
+ # in ruby (but with arbitrarily many arguments). May also be
210
+ # called as if it were a instance method of JSON_Expression for
211
+ # convenience, and overloads <b><tt>|</tt></b> if the lefthand
212
+ # side is a query. Also has the synonym <b>+or+</b>. The
213
+ # following are all equivalent:
214
+ # r(true)
215
+ # r.any(false, true)
216
+ # r.or(false, true)
217
+ # r(false).any(true)
218
+ # r(false).or(true)
219
+ # (r(false) | true) # Note that (false | r(true)) is *incorrect* because
220
+ # # Ruby only overloads based on the lefthand side
221
+ def self.any(pred, *rest)
222
+ JSON_Expression.new [:call, [:any], [S.r(pred), *(rest.map{|x| S.r x})]];
223
+ end
224
+
225
+ # Returns true if all of its arguments are true, like <b>+and+</b>
226
+ # in ruby (but with arbitrarily many arguments). May also be
227
+ # called as if it were a instance method of JSON_Expression for
228
+ # convenience, and overloads <b><tt>&</tt></b> if the lefthand
229
+ # side is a query. Also has the synonym <b>+and+</b>. The
230
+ # following are all equivalent:
231
+ # r(false)
232
+ # r.all(false, true)
233
+ # r.and(false, true)
234
+ # r(false).all(true)
235
+ # r(false).and(true)
236
+ # (r(false) & true) # Note that (false & r(true)) is *incorrect* because
237
+ # # Ruby only overloads based on the lefthand side
238
+ def self.all(pred, *rest)
239
+ JSON_Expression.new [:call, [:all], [S.r(pred), *(rest.map{|x| S.r x})]];
240
+ end
241
+
242
+ # Take the union of 2 or more sequences <b>+seqs+</b>. Note that
243
+ # unlike normal set union, duplicate values are preserved. May
244
+ # also be called as if it were a instance method of RQL_Query,
245
+ # for convenience. For example, if we have a table
246
+ # <b>+table+</b>, the following are equivalent:
247
+ # r.union(table.map{|row| r[:id]}, table.map{|row| row[:num]})
248
+ # table.map{|row| row[:id]}.union(table.map{|row| row[:num]})
249
+ def self.union(*seqs)
250
+ #TODO: this looks wrong...
251
+ if seqs.all? {|x| x.kind_of? Stream_Expression}
252
+ resclass = Stream_Expression
253
+ elsif seqs.all? {|x| x.kind_of? JSON_Expression}
254
+ resclass = JSON_Expression
255
+ else
256
+ seqs = seqs.map {|x| self.expr x}
257
+ resclass = JSON_Expression
258
+ end
259
+ resclass.new [:call, [:union], seqs.map{|x| S.r x}];
260
+ end
261
+
262
+ # Merge two objects together with a preference for the object on the right.
263
+ # The resulting object has all the attributes in both objects, and if the
264
+ # two objects share an attribute, the value from the object on the right
265
+ # "wins" and is included in the final object. May also be called as if it
266
+ # were an instance method of JSON_Expression, for convenience. The following are
267
+ # equivalent:
268
+ # r({:a => 10, :b => 2, :c => 30})
269
+ # r.merge({:a => 1, :b => 2}, {:a => 10, :c => 30})
270
+ # r({:a => 1, :b => 2}).merge({:a => 10, :c => 30})
271
+ def self.merge(obj1, obj2)
272
+ JSON_Expression.new [:call, [:merge], [S.r(obj1), S.r(obj2)]]
273
+ end
274
+
275
+ # Check whether two JSON expressions are equal. May also be called as
276
+ # if it were a member function of JSON_Expression for convenience. Has the
277
+ # synonym <b>+equals+</b>. The following are all equivalent:
278
+ # r(true)
279
+ # r.eq 1,1
280
+ # r(1).eq(1)
281
+ # r.equals 1,1
282
+ # r(1).equals(1)
283
+ # May also be used with more than two arguments. The following are
284
+ # equivalent:
285
+ # r(false)
286
+ # r.eq(1, 1, 2)
287
+ def self.eq(*args)
288
+ JSON_Expression.new [:call, [:compare, :eq], args.map{|x| S.r x}]
289
+ end
290
+
291
+ # Check whether two JSON expressions are *not* equal. May also be
292
+ # called as if it were a member function of JSON_Expression for convenience. The
293
+ # following are all equivalent:
294
+ # r(true)
295
+ # r.ne 1,2
296
+ # r(1).ne(2)
297
+ # r.not r.eq(1,2)
298
+ # r(1).eq(2).not
299
+ # May also be used with more than two arguments. The following are
300
+ # equivalent:
301
+ # r(true)
302
+ # r.ne(1, 1, 2)
303
+ def self.ne(*args)
304
+ JSON_Expression.new [:call, [:compare, :ne], args.map{|x| S.r x}]
305
+ end
306
+
307
+ # Check whether one JSON expression is less than another. May also be
308
+ # called as if it were a member function of JSON_Expression for convenience. May
309
+ # also be called as the infix operator <b><tt> < </tt></b> if the lefthand
310
+ # side is a query. The following are all equivalent:
311
+ # r(true)
312
+ # r.lt 1,2
313
+ # r(1).lt(2)
314
+ # r(1) < 2
315
+ # Note that the following is illegal, because Ruby only overloads infix
316
+ # operators based on the lefthand side:
317
+ # 1 < r(2)
318
+ # May also be used with more than two arguments. The following are
319
+ # equivalent:
320
+ # r(true)
321
+ # r.lt(1, 2, 3)
322
+ def self.lt(*args)
323
+ JSON_Expression.new [:call, [:compare, :lt], args.map{|x| S.r x}]
324
+ end
325
+
326
+ # Check whether one JSON expression is less than or equal to another.
327
+ # May also be called as if it were a member function of JSON_Expression for
328
+ # convenience. May also be called as the infix operator <b><tt> <= </tt></b>
329
+ # if the lefthand side is a query. The following are all equivalent:
330
+ # r(true)
331
+ # r.le 1,1
332
+ # r(1).le(1)
333
+ # r(1) <= 1
334
+ # Note that the following is illegal, because Ruby only overloads infix
335
+ # operators based on the lefthand side:
336
+ # 1 <= r(1)
337
+ # May also be used with more than two arguments. The following are
338
+ # equivalent:
339
+ # r(true)
340
+ # r.le(1, 2, 2)
341
+ def self.le(*args)
342
+ JSON_Expression.new [:call, [:compare, :le], args.map{|x| S.r x}]
343
+ end
344
+
345
+ # Check whether one JSON expression is greater than another.
346
+ # May also be called as if it were a member function of JSON_Expression for
347
+ # convenience. May also be called as the infix operator <b><tt> > </tt></b>
348
+ # if the lefthand side is an RQL query. The following are all equivalent:
349
+ # r(true)
350
+ # r.gt 2,1
351
+ # r(2).gt(1)
352
+ # r(2) > 1
353
+ # Note that the following is illegal, because Ruby only overloads infix
354
+ # operators based on the lefthand side:
355
+ # 2 > r(1)
356
+ # May also be used with more than two arguments. The following are
357
+ # equivalent:
358
+ # r(true)
359
+ # r.gt(3, 2, 1)
360
+ def self.gt(*args)
361
+ JSON_Expression.new [:call, [:compare, :gt], args.map{|x| S.r x}]
362
+ end
363
+
364
+ # Check whether one JSON expression is greater than or equal to another.
365
+ # May also be called as if it were a member function of JSON_Expression for
366
+ # convenience. May also be called as the infix operator <b><tt> >= </tt></b>
367
+ # if the lefthand side is a query. The following are all equivalent:
368
+ # r(true)
369
+ # r.ge 1,1
370
+ # r(1).ge(1)
371
+ # r(1) >= 1
372
+ # Note that the following is illegal, because Ruby only overloads infix
373
+ # operators based on the lefthand side:
374
+ # 1 >= r(1)
375
+ # May also be used with more than two arguments. The following are
376
+ # equivalent:
377
+ # r(true)
378
+ # r.ge(2, 2, 1)
379
+ def self.ge(*args)
380
+ JSON_Expression.new [:call, [:compare, :ge], args.map{|x| S.r x}]
381
+ end
382
+
383
+ # Create a new database with name <b>+db_name+</b>. Either
384
+ # returns <b>+nil+</b> or raises an error.
385
+ def self.db_create(db_name); Meta_Query.new [:create_db, db_name]; end
386
+
387
+ # List all databases. Either returns an array of strings or raises an error.
388
+ def self.db_list(); Meta_Query.new [:list_dbs]; end
389
+
390
+ # Drop the database with name <b>+db_name+</b>. Either returns
391
+ # <b>+nil+</b> or raises an error.
392
+ def self.db_drop(db_name); Meta_Query.new [:drop_db, db_name]; end
393
+
394
+ # Dereference aliases (see utils.rb)
395
+ def self.method_missing(m, *args, &block) # :nodoc:
396
+ (m2 = C.method_aliases[m]) ? self.send(m2, *args, &block) : super(m, *args, &block)
397
+ end
398
+
399
+ # Refer to a table by name. When run over a connection, this query uses the
400
+ # default database of that connection. If we have a connection <b>+c+</b>
401
+ # like so:
402
+ # c = r.connect('localhost', 28015, 'db_name')
403
+ # then the following are equivalent:
404
+ # c.run(r.table('tbl_name'))
405
+ # c.run(r.db('db_name').table('tbl_name')
406
+ def self.table(name, opts={})
407
+ Table.new(:default_db, name, opts)
408
+ end
409
+
410
+ # A shortcut for Data_Collectors::count
411
+ def self.count(*args); Data_Collectors.count(*args); end
412
+ # A shortcut for Data_Collectors::sum
413
+ def self.sum(*args); Data_Collectors.sum(*args); end
414
+ # A shortcut for Data_Collectors::avg
415
+ def self.avg(*args); Data_Collectors.avg(*args); end
416
+
417
+ def self.boolprop(op, l, r) # :nodoc:
418
+ badop = l.boolop? ? l : r
419
+ if l.boolop? || r.boolop?
420
+ raise RuntimeError,"Error: Cannot use infix #{op} operator on infix boolean expression:
421
+ #{badop.inspect}
422
+ This is almost always a precedence error; try adding parentheses. If you
423
+ actually need to compare booleans, use non-infix operators like `r.all(a,b)`
424
+ instead of `a & b`."
425
+ end
426
+ return RQL.send(op, l, r)
427
+ end
428
+ # def self.boolprop(op, l, r) # :nodoc:
429
+ # if l.boolop?
430
+ # larg,rarg = l.body[2]
431
+ # sexp = [l.body[0], l.body[1], [larg, boolprop(op, rarg, r)]]
432
+ # elsif r.boolop?
433
+ # larg,rarg = r.body[2]
434
+ # sexp = [r.body[0], r.body[1], [boolprop(op, l, larg), rarg]]
435
+ # else
436
+ # return RQL.send(op, l, r);
437
+ # end
438
+ # return S.mark_boolop(JSON_Expression.new sexp)
439
+ # end
440
+
441
+ # See RQL::lt
442
+ def self.< (l,r); boolprop(:lt, S.r(l), S.r(r)); end
443
+ # See RQL::le
444
+ def self.<=(l,r); boolprop(:le, S.r(l), S.r(r)); end
445
+ # See RQL::gt
446
+ def self.> (l,r); boolprop(:gt, S.r(l), S.r(r)); end
447
+ # See RQL::ge
448
+ def self.>=(l,r); boolprop(:ge, S.r(l), S.r(r)); end
449
+
450
+ def self.|(l,r) # :nodoc:
451
+ S.mark_boolop(any(l,r))
452
+ end
453
+ extend Mixin_H4x
454
+ def self.all_h4x(l,r) # :nodoc:
455
+ S.mark_boolop(all(l,r))
456
+ end
457
+ end
458
+ end