Beispiel #1
0
  def test_indexed_table(self):
    # Assume that a table with indexes exists before we begin. 
    # The driver should see the indexes and use them
    self.ds = DynamoDatastore(self.conn)
    pkey = Key('/' + self.INDEXED_TABLE)

    johnny_key = pkey.child('sales.Johnny')
    johnny = {
      'key': str(johnny_key),
      'department': 'sales',
      'name': 'Johnny',
      'group': 'managers',
      'age': 20,
      'score': 1500
    }
    tom_key = pkey.child('sales.Tom')
    tom = {
      'key': str(tom_key),
      'department': 'sales',
      'name': 'Tom',
      'group': 'employees',
      'age': 30,
      'score': 1000
    }
    barbara_key = pkey.child('online_marketing.Barbara')
    barbara = {
      'key': str(barbara_key),
      'department': 'online_marketing',
      'name': 'Barbara',
      'group': 'managers',
      'age': 40,
      'score': 500
    }
    self.ds.put(johnny_key, johnny)
    self.ds.put(tom_key, tom)
    self.ds.put(barbara_key, barbara)

    query = Query(pkey).filter('age','>',20)
    # since the query does not contain any of the hash keys (department, username), 
    # we'll have to do a scan instead of a query
    with mock.patch.object(Table, 'query', return_value=None) as mock_method:
      res = list(self.ds.query(query))
      assert not mock_method.called
      assert res == [tom, barbara] or res == [barbara, tom]

    # From here on out we don't want to use scan anymore
    with mock.patch.object(Table, 'scan', return_value=None) as mock_method:
      assert self.ds.get(johnny_key) == johnny
      assert self.ds.get(tom_key) == tom
      assert self.ds.get(barbara_key) == barbara

      # Filter on hash key exclusively
      q = Query(pkey).filter('department', '=', 'sales')
      table = self.ds._table(q.key.child('_'))
      idx = DynamoQuery.index_for_query(table, q)
      assert idx.name is None, idx.name 
      assert idx.hash_key == 'department', idx.hash_key
      assert idx.range_key == 'name', idx.range_key
      res = list(self.ds.query(q))
      assert res == [tom, johnny] or res == [johnny, tom]
      
      # Filter on hash and range key
      q = Query(pkey).filter('department', '=', 'sales').filter('name','=','Johnny')
      res = list(self.ds.query(q))
      assert res == [johnny]

      # Filter on hash and range key with comparison
      q = Query(pkey).filter('department', '=', 'sales').filter('name','>','Jason')
      res = list(self.ds.query(q))
      assert res == [johnny, tom] or res == [tom, johnny]

      # Filter on a hash key and an arbitrary other non-indexed key
      q = Query(pkey).filter('department', '=', 'sales').filter('age','>',25)
      res = list(self.ds.query(q))
      assert res == [tom]

      # Filter on a hash key, secondary index, and non-indexed
      q = Query(pkey).filter('department', '=', 'sales').filter('score','>=',25).filter('age','>=',25)
      idx = DynamoQuery.index_for_query(table, q)
      assert idx.name == 'ScoreIndex', idx.name 
      assert idx.hash_key == 'department', idx.hash_key
      assert idx.range_key == 'score', idx.range_key
      args = DynamoQuery.query_arguments(table, q, index=idx)
      assert args == {'score__gte': 25, 'department__eq': 'sales'} # age is not indexed, not in query filters
      res = list(self.ds.query(q))
      assert res == [tom]
      
      # Filter on hash and secondary index key
      q = Query(pkey).filter('department', '=', 'sales').filter('score','>',500)
      res = list(self.ds.query(q))
      assert res == [tom, johnny] or res == [johnny, tom]

      # Filter on global hash key exclusively
      q = Query(pkey).filter('group', '=', 'managers')
      idx = DynamoQuery.index_for_query(table, q)
      assert idx.name == 'GroupIndex', idx.name 
      assert idx.hash_key == 'group', idx.hash_key
      assert idx.range_key == 'age', idx.range_key
      res = list(self.ds.query(q))
      assert res == [johnny, barbara] or res == [barbara, johnny], res
      
      # Filter on global hash and range key
      q = Query(pkey).filter('group', '=', 'managers').filter('age','=',40)
      res = list(self.ds.query(q))
      assert res == [barbara]

      # Filter on global hash and range key with comparison
      q = Query(pkey).filter('group', '=', 'managers').filter('age','<',30)
      res = list(self.ds.query(q))
      assert res == [johnny]

      # Filter on global hash key and an arbitrary other non-indexed key
      q = Query(pkey).filter('group', '=', 'managers').filter('score','>',500)
      res = list(self.ds.query(q))
      assert res == [johnny]

      # Update a secondary index range key
      tom['score'] = 400
      self.ds.put(tom_key, tom)

      # Query using secondary index again, verify updated values
      q = Query(pkey).filter('department', '=', 'sales').filter('score','>',500)
      res = list(self.ds.query(q))
      assert res == [johnny] or res == [johnny]

      # Update a global index rang key
      johnny['age'] = 35
      self.ds.put(johnny_key, johnny)
      
      # Query using global index again, verify updated values
      q = Query(pkey).filter('group', '=', 'managers').filter('age','>',30)
      res = list(self.ds.query(q))
      assert res == [johnny, barbara] or res == [barbara, johnny]

      assert not mock_method.called

      # Try to create an item with the key separator in the hash
      bad_key = pkey.child('datastore.dynamo.Bad')
      bad_item = {
        'key': str(bad_key),
        'department': 'datastore.dynamo',
        'name': 'Bad',
        'group': 'employees',
        'age': 30,
        'score': 1000
      }
      try:
        self.ds.put(bad_key, bad_item)
        assert False, "should have not allowed, bad key"
      except ValueError:
        pass
Beispiel #2
0
    def __subtest_basic(self, string):
        fixed_string = Key.remove_duplicate_slashes(string)
        last_namespace = fixed_string.rsplit('/')[-1].split(':')
        k_type = last_namespace[0] if len(last_namespace) > 1 else ''
        name = last_namespace[-1]
        path = fixed_string.rsplit('/', 1)[0] + '/' + k_type
        instance = fixed_string + ':' + 'c'

        self.assertEqual(Key(string)._string, fixed_string)
        self.assertEqual(Key(string), Key(string))
        self.assertEqual(str(Key(string)), fixed_string)
        self.assertEqual(repr(Key(string)), "Key('%s')" % fixed_string)
        self.assertEqual(Key(string).name, name)
        self.assertEqual(Key(string).type, k_type)
        self.assertEqual(Key(string).instance('c'), Key(instance))
        self.assertEqual(Key(string).path, Key(path))
        self.assertEqual(Key(string), eval(repr(Key(string))))

        self.assertTrue(Key(string).child('a') > Key(string))
        self.assertTrue(Key(string).child('a') < Key(string).child('b'))
        self.assertTrue(Key(string) == Key(string))

        split_string = fixed_string.split('/')
        if len(split_string) > 1:
            self.assertEqual(Key('/'.join(split_string[:-1])), Key(string).parent)
        else:
            self.assertRaises(ValueError, lambda: Key(string).parent)

        namespace = split_string[-1].split(':')
        if len(namespace) > 1:
            self.assertEqual(namespace[0], Key(string).type)
        else:
            self.assertEqual('', Key(string).type)
Beispiel #3
0
    def test_ancestry(self):
        k1 = Key('/A/B/C')
        k2 = Key('/A/B/C/D')

        self.assertEqual(k1._string, '/A/B/C')
        self.assertEqual(k2._string, '/A/B/C/D')
        self.assertTrue(k1.is_ancestor_of(k2))
        self.assertTrue(k2.is_descendant_of(k1))
        self.assertTrue(Key('/A').is_ancestor_of(k2))
        self.assertTrue(Key('/A').is_ancestor_of(k1))
        self.assertFalse(Key('/A').is_descendant_of(k2))
        self.assertFalse(Key('/A').is_descendant_of(k1))
        self.assertTrue(k2.is_descendant_of(Key('/A')))
        self.assertTrue(k1.is_descendant_of(Key('/A')))
        self.assertFalse(k2.is_ancestor_of(Key('/A')))
        self.assertFalse(k1.is_ancestor_of(Key('/A')))
        self.assertFalse(k2.is_ancestor_of(k2))
        self.assertFalse(k1.is_ancestor_of(k1))
        self.assertEqual(k1.child('D'), k2)
        self.assertEqual(k1, k2.parent)
        self.assertEqual(k1.path, k2.parent.path)
Beispiel #4
0
def random_key():
    return Key('/herp/' + random_string() + '/derp')