desc: Tests that manipulation data in tables table_variable_name: tbl tbl2 tbl3 tests: # Set up tables - py: tbl.insert([{'id':i, 'a':i%4} for i in xrange(100)]) js: | tbl.insert(function(){ var res = [] for (var i = 0; i < 100; i++) { res.push({id:i, 'a':i%4}); } return res; }()) rb: tbl.insert((0..99).map{ |i| { :id => i, :a => i % 4 } }) ot: ({'deleted':0.0,'replaced':0.0,'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':100}) - py: tbl2.insert([{'id':i, 'b':i%4} for i in xrange(100)]) js: | tbl2.insert(function(){ var res = [] for (var i = 0; i < 100; i++) { res.push({id:i, 'b':i%4}); } return res; }()) rb: tbl2.insert((0..99).map{ |i| { :id => i, :b => i % 4 } }) ot: ({'deleted':0.0,'replaced':0.0,'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':100}) # Table type - cd: tbl.type_of() ot: 'TABLE' # Missing db case - cd: r.db('missing').table('bar') ot: err("ReqlOpFailedError", 'Database `missing` does not exist.', [0]) # Missing table case - cd: r.db('test').table('missing') ot: err("ReqlOpFailedError", 'Table `test.missing` does not exist.', [0]) # Nulls should not be allowed in primary keys - cd: tbl.insert({"id":"\x00"}).pluck("errors","inserted") ot: ({"errors":1,"inserted":0}) - cd: tbl.insert({"id":["embedded",["null\x00"]]}).pluck("errors","inserted") ot: ({"errors":1,"inserted":0}) # make sure we can insert and query json docs with arbitrary unicode attrs - js: tbl3.insert({'id':'Здравствуй','value':'Земля!'}) py: tbl3.insert({'id':u'Здравствуй','value':u'Земля!'}) py3.0: tbl3.insert({'id':'Здравствуй','value':'Земля!'}) py3.1: tbl3.insert({'id':'Здравствуй','value':'Земля!'}) py3.2: tbl3.insert({'id':'Здравствуй','value':'Земля!'}) rb: tbl3.insert({:id => "\u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439", :value => "\u0417\u0435\u043C\u043B\u044F!"}) ot: ({'deleted':0.0,'replaced':0.0,'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':1}) # make sure we can query json docs by arbitrary unicode attrs - cd: cd: tbl3.get('Здравствуй') py: tbl3.get(u'Здравствуй') py3.0: tbl3.get('Здравствуй') py3.1: tbl3.get('Здравствуй') py3.2: tbl3.get('Здравствуй') ot: cd: {'id':'Здравствуй','value':'Земля!'} py: {u'id':u'Здравствуй',u'value':u'Земля!'} py3.0: {'id':'Здравствуй','value':'Земля!'} py3.1: {'id':'Здравствуй','value':'Земля!'} py3.2: {'id':'Здравствуй','value':'Земля!'} - cd: cd: tbl3.filter({'value':'Земля!'}) py: tbl3.filter({'value':u'Земля!'}) py3.0: tbl3.filter({'value':'Земля!'}) py3.1: tbl3.filter({'value':'Земля!'}) py3.2: tbl3.filter({'value':'Земля!'}) ot: cd: [{'id':'Здравствуй','value':'Земля!'}] py: [{u'id':u'Здравствуй',u'value':u'Земля!'}] py3.0: [{'id':'Здравствуй','value':'Земля!'}] py3.1: [{'id':'Здравствуй','value':'Земля!'}] py3.2: [{'id':'Здравствуй','value':'Земля!'}] # db and table name validation - cd: r.db('%') ot: err("ReqlQueryLogicError", 'Database name `%` invalid (Use A-Za-z0-9_ only).', [0]) - cd: r.db('test').table('%') ot: err("ReqlQueryLogicError", 'Table name `%` invalid (Use A-Za-z0-9_ only).', [0]) # Access a table from default db - cd: tbl.count() ot: 100 # Access a table using different read modes - def: tbl2Name = tbl2.info().get_field('name') - def: tbl2DbName = tbl2.info().get_field('db').get_field('name') - py: - r.db(tbl2DbName).table(tbl2Name, read_mode='outdated').count() - r.db(tbl2DbName).table(tbl2Name, read_mode='single').count() - r.db(tbl2DbName).table(tbl2Name, read_mode='majority').count() js: - r.db(tbl2DbName).table(tbl2Name, {readMode:'outdated'}).count() - r.db(tbl2DbName).table(tbl2Name, {readMode:'single'}).count() - r.db(tbl2DbName).table(tbl2Name, {readMode:'majority'}).count() rb: - r.db(tbl2DbName).table(tbl2Name, {:read_mode => 'outdated'}).count() - r.db(tbl2DbName).table(tbl2Name, {:read_mode => 'single'}).count() - r.db(tbl2DbName).table(tbl2Name, {:read_mode => 'majority'}).count() ot: 100 # Access a table with an invalid read mode - py: r.db(tbl2DbName).table(tbl2Name, read_mode=null).count() js: r.db(tbl2DbName).table(tbl2Name, {readMode:null}).count() rb: r.db(tbl2DbName).table(tbl2Name, {:read_mode => null}).count() ot: err("ReqlNonExistenceError", 'Expected type STRING but found NULL.') - py: r.db(tbl2DbName).table(tbl2Name, read_mode=true).count() js: r.db(tbl2DbName).table(tbl2Name, {readMode:false}).count() rb: r.db(tbl2DbName).table(tbl2Name, {:read_mode => true}).count() ot: err("ReqlQueryLogicError", 'Expected type STRING but found BOOL.') - py: r.db(tbl2DbName).table(tbl2Name, read_mode='fake').count() js: r.db(tbl2DbName).table(tbl2Name, {readMode:'fake'}).count() rb: r.db(tbl2DbName).table(tbl2Name, {:read_mode => 'fake'}).count() ot: err("ReqlQueryLogicError", 'Read mode `fake` unrecognized (options are "majority", "single", and "outdated").') - cd: tbl.get(20).count() ot: 2 # Get a document that exists - cd: tbl.get(20) ot: {'id':20,'a':0} # Get a document that doesn't exist - cd: tbl.get(2000) ot: null # Make sure get only takes one arg (since we used to be able to pass id) - cd: tbl.get() ot: err("ReqlCompileError", 'Expected 2 arguments but found 1.', [1]) - cd: tbl.get(10, 20) ot: err("ReqlCompileError", 'Expected 2 arguments but found 3.', [1]) # Create a table with a non-id primary key - py: r.db('test').table_create('testpkey', primary_key='foo') js: r.db('test').tableCreate('testpkey', {primaryKey:'foo'}) rb: r.db('test').table_create('testpkey', { :primary_key => 'foo' }) ot: partial({'tables_created':1}) def: tblpkey = r.db('test').table('testpkey') - cd: tblpkey.insert({'foo':10,'a':10}) ot: {'deleted':0.0,'replaced':0.0,'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':1} # get for table where id isn't a primary key - cd: tblpkey.get(10) ot: {'foo':10,'a':10} # Get all - cd: tbl.get_all() ot: [] - cd: tbl.get_all(20) ot: [{"id":20,"a":0}] - cd: tbl.get_all().type_of() ot: "SELECTION" - cd: tbl.get_all(20).type_of() ot: "SELECTION" # Between - cd: tbl.between(2, 1).type_of() ot: 'TABLE_SLICE' - cd: tbl.between(1, 2).type_of() ot: 'TABLE_SLICE' - py: tbl.between(1, 2, index='id').type_of() js: tbl.between(1, 2, {'index':'id'}).typeOf() rb: tbl.between(1, 2, :index => 'id').type_of() ot: 'TABLE_SLICE' - py: tbl.between(1, 1, right_bound='closed').type_of() js: tbl.between(1, 1, {'right_bound':'closed'}).typeOf() rb: tbl.between(1, 1, :right_bound => 'closed').type_of() ot: 'TABLE_SLICE' - cd: tbl.between(2, 1).type_of() ot: 'TABLE_SLICE' - py: tbl.between(2, 1, index='id').type_of() js: tbl.between(2, 1, {'index':'id'}).typeOf() rb: tbl.between(2, 1, :index => 'id').type_of() ot: 'TABLE_SLICE' - cd: tbl.between(21, 20).count() ot: 0 - cd: tbl.between(20, 29).count() ot: 9 - cd: tbl.between(-10, 9).count() ot: 9 - cd: tbl.between(80, 2000).count() ot: 20 - cd: tbl.between(-2000, 2000).count() ot: 100 # Between - cd: tbl.between(20, 29, :right_bound => 'closed').count() py: tbl.between(20, 29, right_bound='closed').count() js: tbl.between(20, 29, {'right_bound':'closed'}).count() ot: 10 - cd: tbl.between(-10, 9, :right_bound => 'closed').count() py: tbl.between(-10, 9, right_bound='closed').count() js: tbl.between(-10, 9, {'right_bound':'closed'}).count() ot: 10 - cd: tbl.between(80, 2000, :right_bound => 'closed').count() py: tbl.between(80, 2000, right_bound='closed').count() js: tbl.between(80, 2000, {'right_bound':'closed'}).count() ot: 20 - cd: tbl.between(-2000, 2000, :right_bound => 'closed').count() py: tbl.between(-2000, 2000, right_bound='closed').count() js: tbl.between(-2000, 2000, {'right_bound':'closed'}).count() ot: 100 # Between - cd: tbl.between(20, 29, :left_bound => 'open').count() py: tbl.between(20, 29, left_bound='open').count() js: tbl.between(20, 29, {'left_bound':'open'}).count() ot: 8 - cd: tbl.between(-10, 9, :left_bound => 'open').count() py: tbl.between(-10, 9, left_bound='open').count() js: tbl.between(-10, 9, {'left_bound':'open'}).count() ot: 9 - cd: tbl.between(80, 2000, :left_bound => 'open').count() py: tbl.between(80, 2000, left_bound='open').count() js: tbl.between(80, 2000, {'left_bound':'open'}).count() ot: 19 - cd: tbl.between(-2000, 2000, :left_bound => 'open').count() py: tbl.between(-2000, 2000, left_bound='open').count() js: tbl.between(-2000, 2000, {'left_bound':'open'}).count() ot: 100 # Between shouldn't work on arrays - cd: r.expr([1, 2, 3]).between(-1, 2) ot: err('ReqlQueryLogicError', 'Expected type TABLE_SLICE but found DATUM:', [0]) # test between on open intervals - cd: tbl.between(r.minval, 2).count() ot: 2 - cd: tbl.between(r.minval, 2, :right_bound => 'closed').count() py: tbl.between(r.minval, 2, right_bound='closed').count() js: tbl.between(r.minval, 2, {'right_bound':'closed'}).count() ot: 3 - cd: tbl.between(r.minval, 2, :left_bound => 'open').count() py: tbl.between(r.minval, 2, left_bound='open').count() js: tbl.between(r.minval, 2, {'left_bound':'open'}).count() ot: 2 - cd: tbl.between(2, r.maxval).count() ot: 98 - cd: tbl.between(2).count() ot: cd: err('ReqlCompileError', 'Expected 3 arguments but found 2.', '[]') js: err('ReqlCompileError', 'Expected 2 arguments (not including options) but found 1.', '[]') # test between with null bounds (allowed in old versions, now an error) - cd: - tbl.between(null, 2).count() - tbl.between(2, null).count() - tbl.between(null, null).count() ot: err('ReqlQueryLogicError', 'Cannot use `nu' + 'll` in BETWEEN, use `r.minval` or `r.maxval` to denote unboundedness.') # test between table where id isn't a primary key - cd: tblpkey.between(9, 11).count() ot: 1 - cd: tblpkey.between(11, 12).count() ot: 0 # Filter - py: tbl.filter(lambda row:row['a'] > 2).count() js: tbl.filter(function(row) { return row('a').gt(2); }).count() rb: tbl.filter{ |row| row[:a] > 2 }.count ot: 25 # test not returning a boolean - py: tbl.filter(lambda row: 1).count() js: tbl.filter(function(row) { return 1; }).count() rb: tbl.filter{ |row| 1 }.count ot: 100 # test seq.filter.filter (chaining and r.row(s)) - py: r.expr([1, 2, 3, 4, 5]).filter(r.row > 2).filter(r.row > 3) js: r.expr([1, 2, 3, 4, 5]).filter(r.row.gt(2)).filter(r.row.gt(3)) rb: r.expr([1, 2, 3, 4, 5]).filter{|x| x > 2}.filter{|x| x > 3} ot: [4, 5] # test nesting (and r.rows(s)) - def: nested = r.expr([[1, 2], [3, 4], [5, 6]]) - py: nested.filter(lambda x: x.filter(lambda y: y >= 4).count() > 0) js: nested.filter(function (x) { return x.filter(function (y) { return y.ge(4); }).count().gt(0) }) rb: nested.filter{ |x| x.filter{ |y| y >= 4}.count > 0 } ot: [[3, 4], [5, 6]] - py: nested.filter(r.row.filter(lambda y: y >= 4).count() > 0) js: nested.filter(r.row.filter(function(y) { return y.ge(4) }).count().gt(0)) ot: ([[3, 4], [5, 6]]) - py: nested.filter(lambda x: x.filter(r.row >= 4).count() > 0) js: nested.filter(function (x) { return x.filter(r.row.ge(4)).count().gt(0) }) ot: err("ReqlCompileError", 'Cannot use r.row in nested queries. Use functions instead.', [0]) - py: r.expr([[1, 2], [3, 4], [5, 6]]).filter(r.row.filter(r.row >= 4).count() > 0) js: nested.filter(r.row.filter(r.row.ge(4)).count().gt(0)) ot: err("ReqlCompileError", 'Cannot use r.row in nested queries. Use functions instead.', [0]) # test static value syntax for filter (make sure r.row in it works) - cd: r.expr([{'a':1,'b':1,'c':3},{'a':1,'b':2,'c':3}]).filter({'a':1,'b':2}) ot: [{'a':1,'b':2,'c':3}] - cd: r.expr([{'a':1,'b':1,'c':3},{'a':1,'b':2,'c':3}]).filter({'a':1}) ot: [{'a':1,'b':1,'c':3},{'a':1,'b':2,'c':3}] # test static value syntax for filter with r.row - cd: r.expr([{'a':1,'b':1,'c':3},{'a':1,'b':2,'c':3}]).filter({'a':r.row['b']}) js: r.expr([{'a':1,'b':1,'c':3},{'a':1,'b':2,'c':3}]).filter({'a':r.row('b')}) rb: # r.row not supported ot: [{'a':1,'b':1,'c':3}] # test filtering for things by a missing attribute - cd: r.expr([{'a':1}]).filter({'b':1}) ot: [] # Count with parameter - js: tbl.count(function(){ return {'a':1}; }) rb: tbl.count{ |row| {:a => 1} } py: tbl.count(lambda row: {'a':1}) ot: 25 - js: tbl.count({'a':1}) ot: 0 - cd: r.expr([1,2,3,1]).count(1) ot: 2 - cd: r.expr([null, 4, null, 'foo']).count(null) ot: 2 # what the heck, let's see what happens - py: r.expr(5) + tbl js: r.expr(5).add(tbl) rb: r 5 + tbl ot: err('ReqlQueryLogicError', 'Expected type DATUM but found TABLE:', [0]) - cd: tbl.has_fields('field').type_of() ot: "SELECTION"