diff --git a/CHANGES.txt b/CHANGES.txt index eb73da2b59..15898df292 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -24,6 +24,7 @@ Merged from 2.2: * Improve streaming synchronization and fault tolerance (CASSANDRA-11414) * MemoryUtil.getShort() should return an unsigned short also for architectures not supporting unaligned memory accesses (CASSANDRA-11973) Merged from 2.1: + * cannot use cql since upgrading python to 2.7.11+ (CASSANDRA-11850) * Fix filtering on clustering columns when 2i is used (CASSANDRA-11907) diff --git a/bin/cqlsh.py b/bin/cqlsh.py index f770ff1f97..70eecfd2b4 100644 --- a/bin/cqlsh.py +++ b/bin/cqlsh.py @@ -758,10 +758,6 @@ class Shell(cmd.Cmd): self.display_timezone = display_timezone - # If there is no schema metadata present (due to a schema mismatch), force schema refresh - if not self.conn.metadata.keyspaces: - self.refresh_schema_metadata_best_effort() - self.session.default_timeout = request_timeout self.session.row_factory = ordered_dict_factory self.session.default_consistency_level = cassandra.ConsistencyLevel.ONE @@ -818,15 +814,6 @@ class Shell(cmd.Cmd): "If you experience encoding problems, change your console" " codepage with 'chcp 65001' before starting cqlsh.\n".format(self.encoding)) - def refresh_schema_metadata_best_effort(self): - try: - self.conn.refresh_schema_metadata(5) # will throw exception if there is a schema mismatch - except Exception: - self.printerr("Warning: schema version mismatch detected, which might be caused by DOWN nodes; if " - "this is not the case, check the schema versions of your nodes in system.local and " - "system.peers.") - self.conn.refresh_schema_metadata(0) - def set_expanded_cql_version(self, ver): ver, vertuple = full_cql_version(ver) self.cql_version = ver @@ -1153,7 +1140,7 @@ class Shell(cmd.Cmd): except EOFError: self.handle_eof() except CQL_ERRORS, cqlerr: - self.printerr(unicode(cqlerr)) + self.printerr(cqlerr.message.decode(encoding='utf-8')) except KeyboardInterrupt: self.reset_statement() print @@ -1308,22 +1295,27 @@ class Shell(cmd.Cmd): if not statement: return False, None - while True: + future = self.session.execute_async(statement, trace=self.tracing_enabled) + result = None + try: + result = future.result() + except CQL_ERRORS, err: + self.printerr(unicode(err.__class__.__name__) + u": " + err.message.decode(encoding='utf-8')) + except Exception: + import traceback + self.printerr(traceback.format_exc()) + + # Even if statement failed we try to refresh schema if not agreed (see CASSANDRA-9689) + if not future.is_schema_agreed: try: - future = self.session.execute_async(statement, trace=self.tracing_enabled) - result = future.result() - break - except cassandra.OperationTimedOut, err: - self.refresh_schema_metadata_best_effort() - self.printerr(unicode(err.__class__.__name__) + u": " + unicode(err)) - return False, None - except CQL_ERRORS, err: - self.printerr(unicode(err.__class__.__name__) + u": " + unicode(err)) - return False, None - except Exception, err: - import traceback - self.printerr(traceback.format_exc()) - return False, None + self.conn.refresh_schema_metadata(5) # will throw exception if there is a schema mismatch + except Exception: + self.printerr("Warning: schema version mismatch detected; check the schema versions of your " + "nodes in system.local and system.peers.") + self.conn.refresh_schema_metadata(-1) + + if result is None: + return False, None if statement.query_string[:6].lower() == 'select': self.print_result(result, self.parse_for_select_meta(statement.query_string)) diff --git a/lib/cassandra-driver-internal-only-3.0.0-6af642d.zip b/lib/cassandra-driver-internal-only-3.0.0-6af642d.zip deleted file mode 100644 index 507370b979..0000000000 Binary files a/lib/cassandra-driver-internal-only-3.0.0-6af642d.zip and /dev/null differ diff --git a/lib/cassandra-driver-internal-only-3.5.0.post0-d8d0456.zip b/lib/cassandra-driver-internal-only-3.5.0.post0-d8d0456.zip new file mode 100644 index 0000000000..7d23b48224 Binary files /dev/null and b/lib/cassandra-driver-internal-only-3.5.0.post0-d8d0456.zip differ diff --git a/pylib/cqlshlib/copyutil.py b/pylib/cqlshlib/copyutil.py index ef009e2b99..85d9cffc22 100644 --- a/pylib/cqlshlib/copyutil.py +++ b/pylib/cqlshlib/copyutil.py @@ -671,11 +671,11 @@ class ExportTask(CopyTask): hosts = [] if replicas: for r in replicas: - if r.is_up and r.datacenter == local_dc: + if r.is_up is not False and r.datacenter == local_dc: hosts.append(r.address) if not hosts: hosts.append(hostname) # fallback to default host if no replicas in current dc - return {'hosts': tuple(hosts), 'attempts': 0, 'rows': 0} + return {'hosts': tuple(hosts), 'attempts': 0, 'rows': 0, 'workerno': -1} if begin_token and begin_token < min_token: shell.printerr('Begin token %d must be bigger or equal to min token %d' % (begin_token, min_token)) @@ -742,8 +742,11 @@ class ExportTask(CopyTask): return None def send_work(self, ranges, tokens_to_send): - i = 0 + prev_worker_no = ranges[tokens_to_send[0]]['workerno'] + i = prev_worker_no + 1 if -1 <= prev_worker_no < (self.num_processes - 1) else 0 + for token_range in tokens_to_send: + ranges[token_range]['workerno'] = i self.outmsg.channels[i].send((token_range, ranges[token_range])) ranges[token_range]['attempts'] += 1 @@ -1346,6 +1349,7 @@ class ChildProcess(mp.Process): self.thousands_sep = options.copy['thousandssep'] self.boolean_styles = options.copy['boolstyle'] self.max_attempts = options.copy['maxattempts'] + self.encoding = options.copy['encoding'] # Here we inject some failures for testing purposes, only if this environment variable is set if os.environ.get('CQLSH_COPY_TEST_FAILURES', ''): self.test_failures = json.loads(os.environ.get('CQLSH_COPY_TEST_FAILURES', '')) @@ -1460,7 +1464,6 @@ class ExportProcess(ChildProcess): def __init__(self, params): ChildProcess.__init__(self, params=params, target=self.run) options = params['options'] - self.encoding = options.copy['encoding'] self.float_precision = options.copy['float_precision'] self.nullval = options.copy['nullval'] self.max_requests = options.copy['maxrequests'] @@ -1712,6 +1715,7 @@ class ImportConversion(object): self.boolean_styles = parent.boolean_styles self.date_time_format = parent.date_time_format.timestamp_format self.debug = parent.debug + self.encoding = parent.encoding self.table_meta = table_meta self.primary_key_indexes = [self.columns.index(col.name) for col in self.table_meta.primary_key] @@ -1733,8 +1737,13 @@ class ImportConversion(object): # only when using prepared statements self.coltypes = [table_meta.columns[name].cql_type for name in parent.valid_columns] # these functions are used for non-prepared statements to protect values with quotes if required - self.protectors = [protect_value if t in ('ascii', 'text', 'timestamp', 'date', 'time', 'inet') else lambda v: v - for t in self.coltypes] + self.protectors = [self._get_protector(t) for t in self.coltypes] + + def _get_protector(self, t): + if t in ('ascii', 'text', 'timestamp', 'date', 'time', 'inet'): + return lambda v: unicode(protect_value(v), self.encoding) + else: + return lambda v: v @staticmethod def _get_primary_key_statement(parent, table_meta): @@ -2067,7 +2076,7 @@ class TokenMap(object): def filter_replicas(self, hosts): shuffled = tuple(sorted(hosts, key=lambda k: random.random())) - return filter(lambda r: r.is_up and r.datacenter == self.local_dc, shuffled) if hosts else () + return filter(lambda r: r.is_up is not False and r.datacenter == self.local_dc, shuffled) if hosts else () class FastTokenAwarePolicy(DCAwareRoundRobinPolicy): diff --git a/pylib/cqlshlib/test/test_cqlsh_output.py b/pylib/cqlshlib/test/test_cqlsh_output.py index 85ce626c8e..d9050951e2 100644 --- a/pylib/cqlshlib/test/test_cqlsh_output.py +++ b/pylib/cqlshlib/test/test_cqlsh_output.py @@ -554,7 +554,7 @@ class TestCqlshOutput(BaseTestCase): self.assertTrue(outputlines[start_index+1].endswith('cqlsh:system> ')) midline = ColoredText(outputlines[start_index]) self.assertEqual(midline.plain(), - 'InvalidRequest: code=2200 [Invalid query] message="Keyspace \'nonexistentkeyspace\' does not exist"') + 'InvalidRequest: Error from server: code=2200 [Invalid query] message="Keyspace \'nonexistentkeyspace\' does not exist"') self.assertColorFromTags(midline, "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR") diff --git a/pylib/cqlshlib/tracing.py b/pylib/cqlshlib/tracing.py index c30965c0da..cea3568c6b 100644 --- a/pylib/cqlshlib/tracing.py +++ b/pylib/cqlshlib/tracing.py @@ -81,7 +81,7 @@ def total_micro_seconds(td): """ Convert a timedelta into total microseconds """ - return int((td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6)) if td else "--" + return int((td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6)) if td else "--" def datetime_from_utc_to_local(utc_datetime):