desc: Tests that manipulation data in tables
tests:

    # Set up some data
    - cd: r.db('test').table_create('test1')
      ot: ({'created':1})
      def: tbl = r.db('test').table('test1')

    - cd: r.db('test').table_create('test2')
      ot: ({'created':1})
      def: tbl2 = r.db('test').table('test2')

    - py: r.db('test').table_create('test3', primary_key='foo')
      rb: r.db('test').table_create('test3', {:primary_key=>'foo'})
      js: r.db('test').tableCreate('test3', {'primaryKey':'foo'})
      ot: ({'created':1})
      def: tbl3 = r.db('test').table('test3')

    - 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})

    - py: tbl3.insert([{'foo':i, 'b':i%4} for i in xrange(100)])
      js: |
        tbl3.insert(function(){
            var res = []
            for (var i = 0; i < 100; i++) {
                res.push({foo:i, 'b':i%4});
            }
            return res;
        }())
      rb: tbl3.insert((0..99).map{ |i| { :foo => i, :b => i % 4 } })
      ot: ({'deleted':0.0,'replaced':0.0,'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':100})

    # Inner-Join
    - def:
        py: ij = tbl.inner_join(tbl2, lambda x,y:x['a'] == y['b']).zip()
        js: ij = tbl.innerJoin(tbl2, function(x, y) { return x('a').eq(y('b')); }).zip()
        rb: ij = tbl.inner_join(tbl2){ |x, y| x[:a].eq y[:b] }.zip
    - cd: ij.count()
      ot: 2500
    - py: ij.filter(lambda row:row['a'] != row['b']).count()
      js: ij.filter(function(row) { return row('a').ne(row('b')); }).count()
      rb: ij.filter{ |row| row[:a].ne row[:b] }.count
      ot: 0

    # Outer-Join
    - def:
        py: oj = tbl.outer_join(tbl2, lambda x,y:x['a'] == y['b']).zip()
        js: oj = tbl.outerJoin(tbl2, function(x, y) { return x('a').eq(y('b')); }).zip()
        rb: oj = tbl.outer_join(tbl2){ |x, y| x[:a].eq y[:b] }.zip
    - cd: oj.count()
      ot: 2500
    - py: oj.filter(lambda row:row['a'] != row['b']).count()
      js: oj.filter(function(row) { return row('a').ne(row('b')); }).count()
      rb: oj.filter{ |row| row[:a].ne row[:b] }.count
      ot: 0

    # Eq-Join
    - def: ej = tbl.eq_join('a', tbl2).zip()
      cd: ej.count()
      ot: 100

    - py: "tbl.eq_join(lambda x: x['a'], tbl2).count()"
      rb: tbl.eq_join(lambda {|x| x[:a]}, tbl2).count()
      js: tbl.eq_join(function(x) { return x('a'); }, tbl2).count()
      ot: 100

    # eqjoin where id isn't a primary key
    - def: ej = tbl.eq_join('a', tbl3).zip()
      cd: ej.count()
      ot: 100

    - py: "tbl.eq_join(lambda x: x['a'], tbl3).count()"
      rb: tbl.eq_join(lambda {|x| x[:a]}, tbl3).count()
      js: tbl.eq_join(function(x) { return x('a'); }, tbl3).count()
      ot: 100

    # test an inner-join condition where inner-join differs from outer-join
    - def: left = r.expr([{'a':1},{'a':2},{'a':3}])
    - def: right = r.expr([{'b':2},{'b':3}])

    - py: left.inner_join(right, lambda l, r:l['a'] == r['b']).zip()
      js: left.innerJoin(right, function(l, r) { return l('a').eq(r('b')); }).zip()
      rb: left.inner_join(right){ |lt, rt| lt[:a].eq(rt[:b]) }.zip
      ot: [{'a':2,'b':2},{'a':3,'b':3}]
    
    # test an outer-join condition where outer-join differs from inner-join
    - py: left.outer_join(right, lambda l, r:l['a'] == r['b']).zip()
      js: left.outerJoin(right, function(l, r) { return l('a').eq(r('b')); }).zip()
      rb: left.outer_join(right){ |lt, rt| lt[:a].eq(rt[:b]) }.zip
      ot: [{'a':1},{'a':2,'b':2},{'a':3,'b':3}]
    
    
    # Clean up
    - cd: r.db('test').table_drop('test1')
      ot: ({'dropped':1})
    - cd: r.db('test').table_drop('test2')
      ot: ({'dropped':1})
    - cd: r.db('test').table_drop('test3')
      ot: ({'dropped':1})
