def setUp(self):
     TestBase.set_up(self)
     self.shardkeys = [0, 1]
     ids = [0, 1, 2, 3, 4, 5]
     write_multiple_request = WriteMultipleRequest()
     for sk in self.shardkeys:
         for i in ids:
             row = {'fld_sid': sk, 'fld_id': i, 'fld_long': 2147483648,
                    'fld_float': 3.1414999961853027, 'fld_double': 3.1415,
                    'fld_bool': True,
                    'fld_str': '{"name": u1, "phone": null}',
                    'fld_bin': bytearray(pack('>i', 4)),
                    'fld_time': datetime.now(), 'fld_num': Decimal(5),
                    'fld_json': {'a': '1', 'b': None, 'c': '3'},
                    'fld_arr': ['a', 'b', 'c'],
                    'fld_map': {'a': '1', 'b': '2', 'c': '3'},
                    'fld_rec': {'fld_id': 1, 'fld_bool': False,
                                'fld_str': None}}
             write_multiple_request.add(
                 PutRequest().set_value(row).set_table_name(table_name),
                 True)
         self.handle.write_multiple(write_multiple_request)
         write_multiple_request.clear()
     self.key = {'fld_sid': 1}
     self.multi_delete_request = MultiDeleteRequest().set_timeout(timeout)
     prep_request = PrepareRequest().set_statement(
         'SELECT fld_sid, fld_id FROM ' + table_name)
     prep_result = self.handle.prepare(prep_request)
     self.query_request = QueryRequest().set_prepared_statement(prep_result)
Example #2
0
 def setUp(self):
     TestBase.set_up(self)
     self.handle_config = get_handle_config(tenant_id)
     shardkeys = [0, 1]
     ids = [0, 1, 2, 3, 4, 5]
     write_multiple_request = WriteMultipleRequest()
     for sk in shardkeys:
         for i in ids:
             row = {
                 'fld_sid': sk,
                 'fld_id': i,
                 'fld_long': 2147483648,
                 'fld_float': 3.1414999961853027,
                 'fld_double': 3.1415,
                 'fld_bool': True,
                 'fld_str': '{"name": u1, "phone": null}',
                 'fld_bin': bytearray(pack('>i', 4)),
                 'fld_time': datetime.now(),
                 'fld_num': Decimal(5),
                 'fld_json': {
                     'a': '1',
                     'b': None,
                     'c': '3'
                 },
                 'fld_arr': ['a', 'b', 'c'],
                 'fld_map': {
                     'a': '1',
                     'b': '2',
                     'c': '3'
                 },
                 'fld_rec': {
                     'fld_id': 1,
                     'fld_bool': False,
                     'fld_str': None
                 }
             }
             write_multiple_request.add(
                 PutRequest().set_value(row).set_table_name(table_name),
                 True)
         self.handle.write_multiple(write_multiple_request)
         write_multiple_request.clear()
     prepare_statement_update = (
         'DECLARE $fld_sid INTEGER; $fld_id INTEGER; UPDATE ' + table_name +
         ' u SET u.fld_long = u.fld_long + 1 WHERE fld_sid = $fld_sid ' +
         'AND fld_id = $fld_id')
     prepare_request_update = PrepareRequest().set_statement(
         prepare_statement_update)
     self.prepare_result_update = self.handle.prepare(
         prepare_request_update)
     prepare_statement_select = (
         'DECLARE $fld_long LONG; SELECT fld_sid, fld_id, fld_long FROM ' +
         table_name + ' WHERE fld_long = $fld_long')
     prepare_request_select = PrepareRequest().set_statement(
         prepare_statement_select)
     self.prepare_result_select = self.handle.prepare(
         prepare_request_select)
     self.query_request = QueryRequest().set_timeout(timeout)
     self.get_request = GetRequest().set_table_name(table_name)
Example #3
0
 def setUp(self):
     self.set_up()
     self.handle_config = get_handle_config(tenant_id)
     self.min_time = list()
     self.max_time = list()
     shardkeys = 2
     ids = 6
     write_multiple_request = WriteMultipleRequest()
     for sk in range(shardkeys):
         for i in range(ids):
             row = get_row()
             if i == 0:
                 self.min_time.append(row['fld_time'])
             elif i == ids - 1:
                 self.max_time.append(row['fld_time'])
             row['fld_sid'] = sk
             row['fld_id'] = i
             row['fld_bool'] = False if sk == 0 else True
             row['fld_str'] = (
                 '{"name": u' +
                 str(shardkeys * ids - sk * ids - i - 1).zfill(2) + '}')
             row['fld_json']['location']['coordinates'] = ([
                 23.549 - sk * 0.5 - i, 35.2908 + sk * 0.5 + i
             ])
             write_multiple_request.add(
                 PutRequest().set_value(row).set_table_name(table_name),
                 True)
         self.handle.write_multiple(write_multiple_request)
         write_multiple_request.clear()
     prepare_statement_update = (
         'DECLARE $fld_sid INTEGER; $fld_id INTEGER; UPDATE ' + table_name +
         ' u SET u.fld_long = u.fld_long + 1 WHERE fld_sid = $fld_sid ' +
         'AND fld_id = $fld_id')
     prepare_request_update = PrepareRequest().set_statement(
         prepare_statement_update)
     self.prepare_result_update = self.handle.prepare(
         prepare_request_update)
     prepare_statement_select = (
         'DECLARE $fld_long LONG; SELECT fld_sid, fld_id, fld_long FROM ' +
         table_name + ' WHERE fld_long = $fld_long')
     prepare_request_select = PrepareRequest().set_statement(
         prepare_statement_select)
     self.prepare_result_select = self.handle.prepare(
         prepare_request_select)
     self.query_request = QueryRequest().set_timeout(timeout)
     self.get_request = GetRequest().set_table_name(table_name)
Example #4
0
 def setUp(self):
     self.set_up()
     self.shardkeys = [0, 1]
     ids = [0, 1, 2, 3, 4, 5]
     write_multiple_request = WriteMultipleRequest()
     for sk in self.shardkeys:
         for i in ids:
             row = get_row()
             row['fld_sid'] = sk
             row['fld_id'] = i
             write_multiple_request.add(
                 PutRequest().set_value(row).set_table_name(table_name),
                 True)
         self.handle.write_multiple(write_multiple_request)
         write_multiple_request.clear()
     self.key = {'fld_sid': 1}
     self.multi_delete_request = MultiDeleteRequest().set_timeout(timeout)
     prep_request = PrepareRequest().set_statement(
         'SELECT fld_sid, fld_id FROM ' + table_name)
     prep_result = self.handle.prepare(prep_request)
     self.query_request = QueryRequest().set_prepared_statement(prep_result)
Example #5
0
def main():

    handle = None
    try:
        #
        # Create a handle
        #
        handle = get_handle(tenant_id)

        #
        # Create a table
        #
        statement = 'Create table if not exists ' + table_name + '(id integer, \
sid integer, name string, primary key(shard(sid), id))'

        print('Creating table: ' + statement)
        request = TableRequest().set_statement(statement).set_table_limits(
            TableLimits(30, 10, 1))
        handle.do_table_request(request, 50000, 3000)
        print('After create table')

        #
        # Put a few rows
        #
        request = PutRequest().set_table_name(table_name)
        for i in range(10):
            value = {'id': i, 'sid': 0, 'name': 'myname' + str(i)}
            request.set_value(value)
            handle.put(request)
        print('After put of 10 rows')

        #
        # Multiple write a few rows
        #
        request = WriteMultipleRequest()
        for i in range(10):
            value = {'id': i, 'sid': 0, 'name': 'newname' + str(i)}
            request.add(
                PutRequest().set_value(value).set_table_name(table_name), True)
        result = handle.write_multiple(request)
        print('After multiple write: ' + str(result))

        #
        # Prepare a statement
        #
        statement = 'select * from ' + table_name + ' where id > 2 and id < 8'
        request = PrepareRequest().set_statement(statement)
        prepared_result = handle.prepare(request)
        print('After prepare the statement: ' + statement)

        #
        # Query, using the prepared statement
        #
        request = QueryRequest().set_prepared_statement(prepared_result)
        print('Query results for the prepared statement: ')
        while True:
            result = handle.query(request)
            for r in result.get_results():
                print('\t' + str(r))
            if request.is_done():
                break

        #
        # Multiple delete the rows
        #
        request = MultiDeleteRequest().set_table_name(table_name).set_key(
            {'sid': 0})
        result = handle.multi_delete(request)
        print('After multiple delete: ' + str(result))

        #
        # Query again to show deletions, using the prepared statement
        #
        request = QueryRequest().set_prepared_statement(prepared_result)
        print('Query results for the prepared statement (should be no rows): ')
        while True:
            result = handle.query(request)
            for r in result.get_results():
                print('\t' + str(r))
            if request.is_done():
                break

        #
        # Drop the table
        #
        if drop_table:
            request = TableRequest().set_statement('drop table if exists ' +
                                                   table_name)
            handle.do_table_request(request, 40000, 2000)
            print('After drop table')
        else:
            print('Not dropping table')

        print('Example is complete')
    except Exception as e:
        print(e)
        traceback.print_exc()
    finally:
        # If the handle isn't closed Python will not exit properly
        if handle is not None:
            handle.close()
 def setUp(self):
     self.set_up()
     self.shardkeys = [0, 1]
     self.ids = [0, 1, 2, 3, 4, 5]
     self.rows = list()
     self.new_rows = list()
     self.versions = list()
     self.requests = list()
     self.illegal_requests = list()
     ttl = TimeToLive.of_days(16)
     for sk in self.shardkeys:
         self.rows.append(list())
         self.new_rows.append(list())
         self.versions.append(list())
         for i in self.ids:
             row = get_row()
             row['fld_sid'] = sk
             row['fld_id'] = i
             new_row = deepcopy(row)
             new_row['fld_long'] = 2147483649
             self.rows[sk].append(row)
             self.new_rows[sk].append(new_row)
             put_request = PutRequest().set_value(row).set_table_name(
                 table_name).set_ttl(ttl)
             self.versions[sk].append(
                 self.handle.put(put_request).get_version())
     self.old_expect_expiration = ttl.to_expiration_time(
         int(round(time() * 1000)))
     self.ttl = TimeToLive.of_hours(1)
     self.ops_sk = 0
     illegal_sk = 1
     self.requests.append(PutRequest().set_value(
         self.new_rows[self.ops_sk][0]).set_table_name(table_name).set_ttl(
             self.ttl).set_return_row(True))
     self.requests.append(PutRequest().set_value(self.new_rows[
         self.ops_sk][1]).set_table_name(table_name).set_option(
             PutOption.IF_ABSENT).set_ttl(self.ttl).set_return_row(True))
     self.requests.append(PutRequest().set_value(
         self.new_rows[self.ops_sk][2]).set_use_table_default_ttl(
             True).set_table_name(table_name).set_option(
                 PutOption.IF_PRESENT).set_return_row(True))
     self.requests.append(PutRequest().set_value(
         self.new_rows[self.ops_sk][3]).set_table_name(table_name).set_ttl(
             self.ttl).set_option(PutOption.IF_VERSION).set_match_version(
                 self.versions[self.ops_sk][3]).set_return_row(True))
     self.requests.append(DeleteRequest().set_key({
         'fld_sid': self.ops_sk,
         'fld_id': 4
     }).set_table_name(table_name).set_return_row(True))
     self.requests.append(DeleteRequest().set_key({
         'fld_sid': self.ops_sk,
         'fld_id': 5
     }).set_table_name(table_name).set_return_row(True).set_match_version(
         self.versions[self.ops_sk][0]))
     self.illegal_requests.append(DeleteRequest().set_key({
         'fld_sid': self.ops_sk,
         'fld_id': 0
     }).set_table_name('IllegalUsers'))
     self.illegal_requests.append(DeleteRequest().set_key({
         'fld_sid': illegal_sk,
         'fld_id': 0
     }).set_table_name(table_name))
     self.write_multiple_request = WriteMultipleRequest().set_timeout(
         timeout)
     self.get_request = GetRequest().set_table_name(table_name)
     self.hour_in_milliseconds = 60 * 60 * 1000
     self.day_in_milliseconds = 24 * 60 * 60 * 1000
class TestWriteMultiple(unittest.TestCase, TestBase):
    @classmethod
    def setUpClass(cls):
        cls.set_up_class()
        create_statement = ('CREATE TABLE ' + table_name +
                            '(fld_sid INTEGER, fld_id INTEGER, \
fld_long LONG, fld_float FLOAT, fld_double DOUBLE, fld_bool BOOLEAN, \
fld_str STRING, fld_bin BINARY, fld_time TIMESTAMP(8), fld_num NUMBER, \
fld_json JSON, fld_arr ARRAY(STRING), fld_map MAP(STRING), \
fld_rec RECORD(fld_id LONG, fld_bool BOOLEAN, fld_str STRING), \
PRIMARY KEY(SHARD(fld_sid), fld_id))')
        limits = TableLimits(50, 50, 1)
        create_request = TableRequest().set_statement(
            create_statement).set_table_limits(limits)
        cls.table_request(create_request)

    @classmethod
    def tearDownClass(cls):
        cls.tear_down_class()

    def setUp(self):
        self.set_up()
        self.shardkeys = [0, 1]
        self.ids = [0, 1, 2, 3, 4, 5]
        self.rows = list()
        self.new_rows = list()
        self.versions = list()
        self.requests = list()
        self.illegal_requests = list()
        ttl = TimeToLive.of_days(16)
        for sk in self.shardkeys:
            self.rows.append(list())
            self.new_rows.append(list())
            self.versions.append(list())
            for i in self.ids:
                row = get_row()
                row['fld_sid'] = sk
                row['fld_id'] = i
                new_row = deepcopy(row)
                new_row['fld_long'] = 2147483649
                self.rows[sk].append(row)
                self.new_rows[sk].append(new_row)
                put_request = PutRequest().set_value(row).set_table_name(
                    table_name).set_ttl(ttl)
                self.versions[sk].append(
                    self.handle.put(put_request).get_version())
        self.old_expect_expiration = ttl.to_expiration_time(
            int(round(time() * 1000)))
        self.ttl = TimeToLive.of_hours(1)
        self.ops_sk = 0
        illegal_sk = 1
        self.requests.append(PutRequest().set_value(
            self.new_rows[self.ops_sk][0]).set_table_name(table_name).set_ttl(
                self.ttl).set_return_row(True))
        self.requests.append(PutRequest().set_value(self.new_rows[
            self.ops_sk][1]).set_table_name(table_name).set_option(
                PutOption.IF_ABSENT).set_ttl(self.ttl).set_return_row(True))
        self.requests.append(PutRequest().set_value(
            self.new_rows[self.ops_sk][2]).set_use_table_default_ttl(
                True).set_table_name(table_name).set_option(
                    PutOption.IF_PRESENT).set_return_row(True))
        self.requests.append(PutRequest().set_value(
            self.new_rows[self.ops_sk][3]).set_table_name(table_name).set_ttl(
                self.ttl).set_option(PutOption.IF_VERSION).set_match_version(
                    self.versions[self.ops_sk][3]).set_return_row(True))
        self.requests.append(DeleteRequest().set_key({
            'fld_sid': self.ops_sk,
            'fld_id': 4
        }).set_table_name(table_name).set_return_row(True))
        self.requests.append(DeleteRequest().set_key({
            'fld_sid': self.ops_sk,
            'fld_id': 5
        }).set_table_name(table_name).set_return_row(True).set_match_version(
            self.versions[self.ops_sk][0]))
        self.illegal_requests.append(DeleteRequest().set_key({
            'fld_sid': self.ops_sk,
            'fld_id': 0
        }).set_table_name('IllegalUsers'))
        self.illegal_requests.append(DeleteRequest().set_key({
            'fld_sid': illegal_sk,
            'fld_id': 0
        }).set_table_name(table_name))
        self.write_multiple_request = WriteMultipleRequest().set_timeout(
            timeout)
        self.get_request = GetRequest().set_table_name(table_name)
        self.hour_in_milliseconds = 60 * 60 * 1000
        self.day_in_milliseconds = 24 * 60 * 60 * 1000

    def tearDown(self):
        for sk in self.shardkeys:
            key = {'fld_sid': sk}
            request = MultiDeleteRequest().set_table_name(table_name).set_key(
                key)
            self.handle.multi_delete(request)
        self.tear_down()

    def testWriteMultipleSetIllegalCompartment(self):
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.set_compartment, {})
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.set_compartment, '')

    def testWriteMultipleAddIllegalRequestAndAbortIfUnsuccessful(self):
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.add, 'IllegalRequest',
                          True)
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.add, PutRequest(),
                          'IllegalAbortIfUnsuccessful')
        # add two operations with different table name
        self.write_multiple_request.add(self.requests[0], True)
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.add,
                          self.illegal_requests[0], False)
        self.write_multiple_request.clear()
        # add two operations with different major paths
        self.write_multiple_request.add(self.requests[0],
                                        True).add(self.illegal_requests[1],
                                                  False)
        self.assertRaises(IllegalArgumentException, self.handle.write_multiple,
                          self.write_multiple_request)
        if not is_onprem():
            # add operations when the request size exceeded the limit
            self.write_multiple_request.clear()
            for op in range(64):
                row = get_row()
                row['fld_str'] = self.get_random_str(0.4)
                self.write_multiple_request.add(
                    PutRequest().set_value(row).set_table_name(table_name),
                    True)
            self.assertRaises(RequestSizeLimitException,
                              self.handle.write_multiple,
                              self.write_multiple_request)
            # add operations when sub requests reached the max number
            self.write_multiple_request.clear()
            for op in range(51):
                row = get_row()
                row['fld_id'] = op
                self.write_multiple_request.add(
                    PutRequest().set_value(row).set_table_name(table_name),
                    True)
            self.assertRaises(BatchOperationNumberLimitException,
                              self.handle.write_multiple,
                              self.write_multiple_request)

    def testWriteMultipleGetRequestWithIllegalIndex(self):
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.get_request,
                          'IllegalIndex')
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.get_request, -1)
        self.assertRaises(IndexError, self.write_multiple_request.get_request,
                          0)

    def testWriteMultipleSetIllegalTimeout(self):
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.set_timeout,
                          'IllegalTimeout')
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.set_timeout, 0)
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.set_timeout, -1)

    def testWriteMultipleNoOperations(self):
        self.assertRaises(IllegalArgumentException, self.handle.write_multiple,
                          self.write_multiple_request)

    def testWriteMultipleGets(self):
        num_operations = 6
        for request in self.requests:
            self.write_multiple_request.add(request, True)
        self.assertIsNone(self.write_multiple_request.get_compartment())
        self.assertEqual(self.write_multiple_request.get_table_name(),
                         table_name)
        self.assertEqual(self.write_multiple_request.get_request(2),
                         self.requests[2])
        requests = self.write_multiple_request.get_operations()
        for idx in range(len(requests)):
            self.assertEqual(requests[idx].get_request(), self.requests[idx])
            self.assertTrue(requests[idx].is_abort_if_unsuccessful())
        self.assertEqual(self.write_multiple_request.get_num_operations(),
                         num_operations)
        self.assertEqual(self.write_multiple_request.get_timeout(), timeout)
        self.write_multiple_request.clear()
        self.assertIsNone(self.write_multiple_request.get_table_name())
        self.assertEqual(self.write_multiple_request.get_operations(), [])
        self.assertEqual(self.write_multiple_request.get_num_operations(), 0)
        self.assertEqual(self.write_multiple_request.get_timeout(), timeout)

    def testWriteMultipleNormal(self):
        num_operations = 6
        for request in self.requests:
            self.write_multiple_request.add(request, False)
        result = self.handle.write_multiple(self.write_multiple_request)
        expect_expiration = self.ttl.to_expiration_time(
            int(round(time() * 1000)))
        op_results = self._check_write_multiple_result(result, num_operations)
        for idx in range(result.size()):
            if idx == 1 or idx == 5:
                # putIfAbsent and deleteIfVersion failed
                self._check_operation_result(
                    op_results[idx],
                    existing_version=self.versions[self.ops_sk][idx],
                    existing_value=self.rows[self.ops_sk][idx])
            elif idx == 4:
                # delete succeed
                self._check_operation_result(op_results[idx], success=True)
            else:
                # put, putIfPresent and putIfVersion succeed
                self._check_operation_result(op_results[idx], True, True)
        self.check_cost(result, 5, 10, 7, 7)
        # check the records after write_multiple request succeed
        for sk in self.shardkeys:
            for i in self.ids:
                self.get_request.set_key({'fld_sid': sk, 'fld_id': i})
                result = self.handle.get(self.get_request)
                if sk == 1 or i == 1 or i == 5:
                    self.check_get_result(result, self.rows[sk][i],
                                          self.versions[sk][i],
                                          self.old_expect_expiration,
                                          TimeUnit.DAYS)
                elif i == 4:
                    self.check_get_result(result)
                elif i == 2:
                    self.check_get_result(result,
                                          self.new_rows[sk][i],
                                          self.versions[sk][i],
                                          ver_eq=False)
                else:
                    self.check_get_result(result, self.new_rows[sk][i],
                                          self.versions[sk][i],
                                          expect_expiration, TimeUnit.HOURS,
                                          False)
                self.check_cost(result, 1, 2, 0, 0)

    def testWriteMultipleAbortIfUnsuccessful(self):
        failed_idx = 1
        for request in self.requests:
            self.write_multiple_request.add(request, True)
        result = self.handle.write_multiple(self.write_multiple_request)
        op_results = self._check_write_multiple_result(result, 1, True,
                                                       failed_idx, False)
        self._check_operation_result(
            op_results[0],
            existing_version=self.versions[self.ops_sk][failed_idx],
            existing_value=self.rows[self.ops_sk][failed_idx])
        failed_result = result.get_failed_operation_result()
        self._check_operation_result(
            failed_result,
            existing_version=self.versions[self.ops_sk][failed_idx],
            existing_value=self.rows[self.ops_sk][failed_idx])
        self.check_cost(result, 1, 2, 2, 2)
        # check the records after multi_delete request failed
        for sk in self.shardkeys:
            for i in self.ids:
                self.get_request.set_key({'fld_sid': sk, 'fld_id': i})
                result = self.handle.get(self.get_request)
                self.check_get_result(result, self.rows[sk][i],
                                      self.versions[sk][i],
                                      self.old_expect_expiration,
                                      TimeUnit.DAYS)
                self.check_cost(result, 1, 2, 0, 0)

    def testWriteMultipleWithIdentityColumn(self):
        num_operations = 10
        id_table = table_prefix + 'Identity'
        create_request = TableRequest().set_statement(
            'CREATE TABLE ' + id_table + '(sid INTEGER, id LONG GENERATED \
ALWAYS AS IDENTITY, name STRING, PRIMARY KEY(SHARD(sid), id))')
        create_request.set_table_limits(TableLimits(50, 50, 1))
        self.table_request(create_request)

        # add ten operations
        row = {'name': 'myname', 'sid': 1}
        for idx in range(num_operations):
            put_request = PutRequest().set_table_name(id_table).set_value(row)
            put_request.set_identity_cache_size(idx)
            self.write_multiple_request.add(put_request, False)
        # execute the write multiple request
        versions = list()
        result = self.handle.write_multiple(self.write_multiple_request)
        op_results = self._check_write_multiple_result(result, num_operations)
        generated = 0
        for idx in range(result.size()):
            version, generated = self._check_operation_result(
                op_results[idx], True, True, generated)
            versions.append(version)
        self.check_cost(result, 0, 0, num_operations, num_operations)
        # check the records after write_multiple request succeed
        self.get_request.set_table_name(id_table)
        for idx in range(num_operations):
            curr_id = generated - num_operations + idx + 1
            self.get_request.set_key({'sid': 1, 'id': curr_id})
            result = self.handle.get(self.get_request)
            expected = OrderedDict()
            expected['sid'] = 1
            expected['id'] = curr_id
            expected['name'] = 'myname'
            self.check_get_result(result, expected, versions[idx])
            self.check_cost(result, 1, 2, 0, 0)

    def _check_operation_result(self,
                                op_result,
                                version=False,
                                success=False,
                                last_generated=None,
                                existing_version=None,
                                existing_value=None):
        # check version of operation result
        ver = op_result.get_version()
        self.assertIsNotNone(ver) if version else self.assertIsNone(ver)
        # check if the operation success
        self.assertEqual(op_result.get_success(), success)
        # check generated value of operation result
        generated = op_result.get_generated_value()
        if last_generated is None:
            self.assertIsNone(generated)
        else:
            self.assertGreater(generated, last_generated)
        # check existing version
        existing_ver = op_result.get_existing_version()
        (self.assertIsNone(existing_ver)
         if existing_version is None else self.assertEqual(
             existing_ver.get_bytes(), existing_version.get_bytes()))
        # check existing value
        self.assertEqual(op_result.get_existing_value(), existing_value)
        return ver, generated

    def _check_write_multiple_result(self,
                                     result,
                                     num_operations,
                                     has_failed_operation=False,
                                     failed_index=-1,
                                     success=True):
        # check number of operations
        self.assertEqual(result.size(), num_operations)
        # check failed operation
        failed_result = result.get_failed_operation_result()
        (self.assertIsNotNone(failed_result)
         if has_failed_operation else self.assertIsNone(failed_result))
        # check failed operation index
        self.assertEqual(result.get_failed_operation_index(), failed_index)
        # check operation status
        self.assertEqual(result.get_success(), success)
        return result.get_results()
 def setUp(self):
     TestBase.set_up(self)
     self.shardkeys = [0, 1]
     self.ids = [0, 1, 2, 3, 4, 5]
     self.rows = list()
     self.new_rows = list()
     self.versions = list()
     self.requests = list()
     self.illegal_requests = list()
     ttl = TimeToLive.of_days(16)
     for sk in self.shardkeys:
         self.rows.append(list())
         self.new_rows.append(list())
         self.versions.append(list())
         for i in self.ids:
             row = {'fld_sid': sk, 'fld_id': i, 'fld_long': 2147483648,
                    'fld_float': 3.1414999961853027, 'fld_double': 3.1415,
                    'fld_bool': True,
                    'fld_str': '{"name": u1, "phone": null}',
                    'fld_bin': bytearray(pack('>i', 4)),
                    'fld_time': datetime.now(), 'fld_num': Decimal(5),
                    'fld_json': {'a': '1', 'b': None, 'c': '3'},
                    'fld_arr': ['a', 'b', 'c'],
                    'fld_map': {'a': '1', 'b': '2', 'c': '3'},
                    'fld_rec': {'fld_id': 1, 'fld_bool': False,
                                'fld_str': None}}
             new_row = deepcopy(row)
             new_row.update({'fld_long': 2147483649})
             self.rows[sk].append(row)
             self.new_rows[sk].append(new_row)
             put_request = PutRequest().set_value(row).set_table_name(
                 table_name).set_ttl(ttl)
             self.versions[sk].append(
                 self.handle.put(put_request).get_version())
     self.old_expect_expiration = ttl.to_expiration_time(
         int(round(time() * 1000)))
     self.ttl = TimeToLive.of_hours(1)
     self.ops_sk = 0
     illegal_sk = 1
     self.requests.append(PutRequest().set_value(
         self.new_rows[self.ops_sk][0]).set_table_name(table_name).set_ttl(
         self.ttl).set_return_row(True))
     self.requests.append(PutRequest().set_value(
         self.new_rows[self.ops_sk][1]).set_table_name(
         table_name).set_option(PutOption.IF_ABSENT).set_ttl(
         self.ttl).set_return_row(True))
     self.requests.append(PutRequest().set_value(
         self.new_rows[self.ops_sk][2]).set_use_table_default_ttl(
         True).set_table_name(table_name).set_option(
         PutOption.IF_PRESENT).set_return_row(True))
     self.requests.append(PutRequest().set_value(
         self.new_rows[self.ops_sk][3]).set_table_name(
         table_name).set_option(PutOption.IF_VERSION).set_ttl(
         self.ttl).set_match_version(
         self.versions[self.ops_sk][3]).set_return_row(True))
     self.requests.append(DeleteRequest().set_key(
         {'fld_sid': self.ops_sk, 'fld_id': 4}).set_table_name(
         table_name).set_return_row(True))
     self.requests.append(DeleteRequest().set_key(
         {'fld_sid': self.ops_sk, 'fld_id': 5}).set_table_name(
             table_name).set_match_version(
             self.versions[self.ops_sk][0]).set_return_row(True))
     self.illegal_requests.append(DeleteRequest().set_key(
         {'fld_sid': self.ops_sk, 'fld_id': 0}).set_table_name(
         'IllegalUsers'))
     self.illegal_requests.append(DeleteRequest().set_key(
         {'fld_sid': illegal_sk, 'fld_id': 0}).set_table_name(table_name))
     self.write_multiple_request = WriteMultipleRequest().set_timeout(
         timeout)
     self.get_request = GetRequest().set_table_name(table_name)
     self.hour_in_milliseconds = 60 * 60 * 1000
     self.day_in_milliseconds = 24 * 60 * 60 * 1000
class TestWriteMultiple(unittest.TestCase, TestBase):
    @classmethod
    def setUpClass(cls):
        TestBase.set_up_class()
        create_statement = (
            'CREATE TABLE ' + table_name + '(fld_sid INTEGER, fld_id INTEGER, \
fld_long LONG, fld_float FLOAT, fld_double DOUBLE, fld_bool BOOLEAN, \
fld_str STRING, fld_bin BINARY, fld_time TIMESTAMP(8), fld_num NUMBER, \
fld_json JSON, fld_arr ARRAY(STRING), fld_map MAP(STRING), \
fld_rec RECORD(fld_id LONG, fld_bool BOOLEAN, fld_str STRING), \
PRIMARY KEY(SHARD(fld_sid), fld_id))')
        limits = TableLimits(5000, 5000, 50)
        create_request = TableRequest().set_statement(
            create_statement).set_table_limits(limits)
        cls._result = TestBase.table_request(create_request, State.ACTIVE)

    @classmethod
    def tearDownClass(cls):
        TestBase.tear_down_class()

    def setUp(self):
        TestBase.set_up(self)
        self.shardkeys = [0, 1]
        self.ids = [0, 1, 2, 3, 4, 5]
        self.rows = list()
        self.new_rows = list()
        self.versions = list()
        self.requests = list()
        self.illegal_requests = list()
        ttl = TimeToLive.of_days(16)
        for sk in self.shardkeys:
            self.rows.append(list())
            self.new_rows.append(list())
            self.versions.append(list())
            for i in self.ids:
                row = {'fld_sid': sk, 'fld_id': i, 'fld_long': 2147483648,
                       'fld_float': 3.1414999961853027, 'fld_double': 3.1415,
                       'fld_bool': True,
                       'fld_str': '{"name": u1, "phone": null}',
                       'fld_bin': bytearray(pack('>i', 4)),
                       'fld_time': datetime.now(), 'fld_num': Decimal(5),
                       'fld_json': {'a': '1', 'b': None, 'c': '3'},
                       'fld_arr': ['a', 'b', 'c'],
                       'fld_map': {'a': '1', 'b': '2', 'c': '3'},
                       'fld_rec': {'fld_id': 1, 'fld_bool': False,
                                   'fld_str': None}}
                new_row = deepcopy(row)
                new_row.update({'fld_long': 2147483649})
                self.rows[sk].append(row)
                self.new_rows[sk].append(new_row)
                put_request = PutRequest().set_value(row).set_table_name(
                    table_name).set_ttl(ttl)
                self.versions[sk].append(
                    self.handle.put(put_request).get_version())
        self.old_expect_expiration = ttl.to_expiration_time(
            int(round(time() * 1000)))
        self.ttl = TimeToLive.of_hours(1)
        self.ops_sk = 0
        illegal_sk = 1
        self.requests.append(PutRequest().set_value(
            self.new_rows[self.ops_sk][0]).set_table_name(table_name).set_ttl(
            self.ttl).set_return_row(True))
        self.requests.append(PutRequest().set_value(
            self.new_rows[self.ops_sk][1]).set_table_name(
            table_name).set_option(PutOption.IF_ABSENT).set_ttl(
            self.ttl).set_return_row(True))
        self.requests.append(PutRequest().set_value(
            self.new_rows[self.ops_sk][2]).set_use_table_default_ttl(
            True).set_table_name(table_name).set_option(
            PutOption.IF_PRESENT).set_return_row(True))
        self.requests.append(PutRequest().set_value(
            self.new_rows[self.ops_sk][3]).set_table_name(
            table_name).set_option(PutOption.IF_VERSION).set_ttl(
            self.ttl).set_match_version(
            self.versions[self.ops_sk][3]).set_return_row(True))
        self.requests.append(DeleteRequest().set_key(
            {'fld_sid': self.ops_sk, 'fld_id': 4}).set_table_name(
            table_name).set_return_row(True))
        self.requests.append(DeleteRequest().set_key(
            {'fld_sid': self.ops_sk, 'fld_id': 5}).set_table_name(
                table_name).set_match_version(
                self.versions[self.ops_sk][0]).set_return_row(True))
        self.illegal_requests.append(DeleteRequest().set_key(
            {'fld_sid': self.ops_sk, 'fld_id': 0}).set_table_name(
            'IllegalUsers'))
        self.illegal_requests.append(DeleteRequest().set_key(
            {'fld_sid': illegal_sk, 'fld_id': 0}).set_table_name(table_name))
        self.write_multiple_request = WriteMultipleRequest().set_timeout(
            timeout)
        self.get_request = GetRequest().set_table_name(table_name)
        self.hour_in_milliseconds = 60 * 60 * 1000
        self.day_in_milliseconds = 24 * 60 * 60 * 1000

    def tearDown(self):
        for sk in self.shardkeys:
            key = {'fld_sid': sk}
            request = MultiDeleteRequest().set_table_name(
                table_name).set_key(key)
            self.handle.multi_delete(request)
        TestBase.tear_down(self)

    def testWriteMultipleAddIllegalRequestAndAbortIfUnsuccessful(self):
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.add,
                          'IllegalRequest', True)
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.add,
                          PutRequest(), 'IllegalAbortIfUnsuccessful')
        # add two operations with different table name
        self.write_multiple_request.add(self.requests[0], True)
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.add,
                          self.illegal_requests[0], False)
        self.write_multiple_request.clear()
        # add two operations with different major paths
        self.write_multiple_request.add(
            self.requests[0], True).add(self.illegal_requests[1], False)
        self.assertRaises(IllegalArgumentException, self.handle.write_multiple,
                          self.write_multiple_request)
        self.write_multiple_request.clear()
        # add operations when sub requests reached the max number
        count = 0
        while count < 50:
            self.write_multiple_request.add(self.requests[0], True)
            count += 1
        self.assertRaises(BatchOperationNumberLimitException,
                          self.write_multiple_request.add,
                          self.requests[0], True)

    def testWriteMultipleGetRequestWithIllegalIndex(self):
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.get_request,
                          'IllegalIndex')
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.get_request, -1)
        self.assertRaises(IndexError, self.write_multiple_request.get_request,
                          0)

    def testWriteMultipleSetIllegalTimeout(self):
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.set_timeout,
                          'IllegalTimeout')
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.set_timeout, 0)
        self.assertRaises(IllegalArgumentException,
                          self.write_multiple_request.set_timeout, -1)

    def testWriteMultipleNoOperations(self):
        self.assertRaises(IllegalArgumentException, self.handle.write_multiple,
                          self.write_multiple_request)

    def testWriteMultipleGets(self):
        num_operations = 6
        for request in self.requests:
            self.write_multiple_request.add(request, True)
        self.assertEqual(self.write_multiple_request.get_table_name(),
                         table_name)
        self.assertEqual(self.write_multiple_request.get_request(2),
                         self.requests[2])
        requests = self.write_multiple_request.get_operations()
        for idx in range(len(requests)):
            self.assertEqual(requests[idx].get_request(),
                             self.requests[idx])
            self.assertTrue(requests[idx].is_abort_if_unsuccessful())
        self.assertEqual(self.write_multiple_request.get_num_operations(),
                         num_operations)
        self.assertEqual(self.write_multiple_request.get_timeout(), timeout)
        self.write_multiple_request.clear()
        self.assertIsNone(self.write_multiple_request.get_table_name())
        self.assertEqual(self.write_multiple_request.get_operations(), [])
        self.assertEqual(self.write_multiple_request.get_num_operations(), 0)
        self.assertEqual(self.write_multiple_request.get_timeout(), timeout)

    def testWriteMultipleNormal(self):
        num_operations = 6
        for request in self.requests:
            self.write_multiple_request.add(request, False)
        result = self.handle.write_multiple(self.write_multiple_request)
        expect_expiration = self.ttl.to_expiration_time(
            int(round(time() * 1000)))
        self.assertEqual(result.size(), num_operations)
        op_results = result.get_results()
        for idx in range(result.size()):
            if idx == 1 or idx == 5:
                # putIfAbsent and deleteIfVersion failed
                self.assertIsNone(op_results[idx].get_version())
                self.assertFalse(op_results[idx].get_success())
                self.assertEqual(
                    op_results[idx].get_existing_version().get_bytes(),
                    self.versions[self.ops_sk][idx].get_bytes())
                self.assertEqual(op_results[idx].get_existing_value(),
                                 self.rows[self.ops_sk][idx])
            elif idx == 4:
                # delete succeed
                self.assertIsNone(op_results[idx].get_version())
                self.assertTrue(op_results[idx].get_success())
                self.assertIsNone(op_results[idx].get_existing_version())
                self.assertIsNone(op_results[idx].get_existing_value())
            else:
                # put, putIfPresent and putIfVersion succeed
                self.assertIsNotNone(op_results[idx].get_version())
                self.assertNotEqual(op_results[idx].get_version(),
                                    self.versions[self.ops_sk][idx])
                self.assertTrue(op_results[idx].get_success())
                self.assertIsNone(op_results[idx].get_existing_version())
                self.assertIsNone(op_results[idx].get_existing_value())
        self.assertIsNone(result.get_failed_operation_result())
        self.assertEqual(result.get_failed_operation_index(), -1)
        self.assertTrue(result.get_success())
        self.assertEqual(result.get_read_kb(), 0 + 1 + 1 + 1 + 1 + 1)
        self.assertEqual(result.get_read_units(), 0 + 2 + 2 + 2 + 2 + 2)
        self.assertEqual(result.get_write_kb(), 2 + 0 + 2 + 2 + 1 + 0)
        self.assertEqual(result.get_write_units(), 2 + 0 + 2 + 2 + 1 + 0)
        # check the records after write_multiple request succeed
        for sk in self.shardkeys:
            for i in self.ids:
                self.get_request.set_key({'fld_sid': sk, 'fld_id': i})
                result = self.handle.get(self.get_request)
                if sk == 1 or i == 1 or i == 5:
                    self.assertEqual(result.get_value(), self.rows[sk][i])
                    self.assertEqual(result.get_version().get_bytes(),
                                     self.versions[sk][i].get_bytes())
                    actual_expiration = result.get_expiration_time()
                    actual_expect_diff = (actual_expiration -
                                          self.old_expect_expiration)
                    self.assertGreater(actual_expiration, 0)
                    self.assertLess(actual_expect_diff,
                                    self.day_in_milliseconds)
                elif i == 4:
                    self.assertIsNone(result.get_value())
                    self.assertIsNone(result.get_version())
                    self.assertEqual(result.get_expiration_time(), 0)
                else:
                    self.assertEqual(result.get_value(), self.new_rows[sk][i])
                    self.assertNotEqual(result.get_version().get_bytes(), 0)
                    self.assertNotEqual(result.get_version().get_bytes(),
                                        self.versions[sk][i].get_bytes())
                    if i == 2:
                        self.assertEqual(result.get_expiration_time(), 0)
                    else:
                        actual_expiration = result.get_expiration_time()
                        actual_expect_diff = (actual_expiration -
                                              expect_expiration)
                        self.assertGreater(actual_expiration, 0)
                        self.assertLess(actual_expect_diff,
                                        self.hour_in_milliseconds)
                self.assertEqual(result.get_read_kb(), 1)
                self.assertEqual(result.get_read_units(), 2)
                self.assertEqual(result.get_write_kb(), 0)
                self.assertEqual(result.get_write_units(), 0)

    def testWriteMultipleAbortIfUnsuccessful(self):
        failed_idx = 1
        for request in self.requests:
            self.write_multiple_request.add(request, True)
        result = self.handle.write_multiple(self.write_multiple_request)
        self.assertEqual(result.size(), 1)
        op_results = result.get_results()
        self.assertIsNone(op_results[0].get_version())
        self.assertFalse(op_results[0].get_success())
        self.assertEqual(op_results[0].get_existing_version().get_bytes(),
                         self.versions[self.ops_sk][failed_idx].get_bytes())
        self.assertEqual(op_results[0].get_existing_value(),
                         self.rows[self.ops_sk][failed_idx])
        failed_result = result.get_failed_operation_result()
        self.assertIsNone(failed_result.get_version())
        self.assertFalse(failed_result.get_success())
        self.assertEqual(failed_result.get_existing_version().get_bytes(),
                         self.versions[self.ops_sk][failed_idx].get_bytes())
        self.assertEqual(failed_result.get_existing_value(),
                         self.rows[self.ops_sk][failed_idx])
        self.assertEqual(result.get_failed_operation_index(), failed_idx)
        self.assertFalse(result.get_success())
        self.assertEqual(result.get_read_kb(), 0 + 1)
        self.assertEqual(result.get_read_units(), 0 + 2)
        self.assertEqual(result.get_write_kb(), 2 + 0)
        self.assertEqual(result.get_write_units(), 2 + 0)
        # check the records after multi_delete request failed
        for sk in self.shardkeys:
            for i in self.ids:
                self.get_request.set_key({'fld_sid': sk, 'fld_id': i})
                result = self.handle.get(self.get_request)
                self.assertEqual(result.get_value(), self.rows[sk][i])
                self.assertEqual(result.get_version().get_bytes(),
                                 self.versions[sk][i].get_bytes())
                actual_expiration = result.get_expiration_time()
                actual_expect_diff = (actual_expiration -
                                      self.old_expect_expiration)
                self.assertGreater(actual_expiration, 0)
                self.assertLess(actual_expect_diff, self.day_in_milliseconds)
                self.assertEqual(result.get_read_kb(), 1)
                self.assertEqual(result.get_read_units(), 2)
                self.assertEqual(result.get_write_kb(), 0)
                self.assertEqual(result.get_write_units(), 0)