3636from glob import glob
3737from io import StringIO
3838from uuid import UUID
39+ from ssl import SSLContext , PROTOCOL_TLSv1_2 , CERT_REQUIRED
3940
4041if sys .version_info < (3 , 6 ):
4142 sys .exit ("\n cqlsh requires Python 3.6+\n " )
@@ -131,7 +132,7 @@ def find_zip(libprefix):
131132 'Error: %s\n ' % (sys .executable , sys .path , e ))
132133
133134from cassandra .auth import PlainTextAuthProvider
134- from cassandra .cluster import Cluster
135+ from cassandra .cluster import Cluster , ExecutionProfile , EXEC_PROFILE_DEFAULT
135136from cassandra .cqltypes import cql_typename
136137from cassandra .marshal import int64_unpack
137138from cassandra .metadata import (ColumnMetadata , KeyspaceMetadata , TableMetadata )
@@ -145,7 +146,7 @@ def find_zip(libprefix):
145146if os .path .isdir (cqlshlibdir ):
146147 sys .path .insert (0 , cqlshlibdir )
147148
148- from cqlshlib import cql3handling , pylexotron , sslhandling , cqlshhandling , authproviderhandling
149+ from cqlshlib import cql3handling , pylexotron , sslhandling , cqlshhandling , authproviderhandling , legacydesc3x
149150from cqlshlib .copyutil import ExportTask , ImportTask
150151from cqlshlib .displaying import (ANSI_RESET , BLUE , COLUMN_NAME_COLORS , CYAN ,
151152 RED , WHITE , FormattedValue , colorme )
@@ -155,7 +156,7 @@ def find_zip(libprefix):
155156from cqlshlib .tracing import print_trace , print_trace_session
156157from cqlshlib .util import get_file_encoding_bomsize , trim_if_present
157158from cqlshlib .util import is_file_secure
158-
159+ from cqlshlib . legacydesc3x import *
159160
160161DEFAULT_HOST = '127.0.0.1'
161162DEFAULT_PORT = 9042
@@ -233,18 +234,17 @@ def find_zip(libprefix):
233234opt_values = optparse .Values ()
234235(options , arguments ) = parser .parse_args (sys .argv [1 :], values = opt_values )
235236
236- # WARN message for deprecated options
237+ # Raise Exception for deprecated options
237238if hasattr (options , 'sigv4' ):
238- print ('\n Warning: Specified sigv4 flag was deprecated, refer to cqlshrc file for sigv4 authentication'
239+ raise Exception ('\n Warning: Specified sigv4 flag was deprecated, refer to cqlshrc file for sigv4 authentication'
239240 'https://cassandra.apache.org/_/blog/Apache-Cassandra-4.1-Features-Authentication-Plugin-Support-for-CQLSH.html' )
240241
241242if hasattr (options , 'auth_provider_name' ):
242- print ('\n Warning: auth-provider flag was deprecated, refer to cqlshrc file for authentication'
243+ raise Exception ('\n Warning: auth-provider flag was deprecated, refer to cqlshrc file for authentication'
243244 'https://cassandra.apache.org/_/blog/Apache-Cassandra-4.1-Features-Authentication-Plugin-Support-for-CQLSH.html' )
244245
245246# BEGIN history/config definition
246247
247-
248248def mkdirp (path ):
249249 """Creates all parent directories up to path parameter or fails when path exists, but it is not a directory."""
250250
@@ -262,7 +262,6 @@ def resolve_cql_history_file():
262262 else :
263263 return default_cql_history
264264
265-
266265HISTORY = resolve_cql_history_file ()
267266HISTORY_DIR = os .path .dirname (HISTORY )
268267
@@ -477,6 +476,12 @@ def __init__(self, hostname, port, color=False,
477476 self .tracing_enabled = tracing_enabled
478477 self .page_size = self .default_page_size
479478 self .expand_enabled = expand_enabled
479+ Keypsaces_profile = ExecutionProfile (
480+ consistency_level = cassandra .ConsistencyLevel .LOCAL_QUORUM ,
481+ request_timeout = request_timeout ,
482+ row_factory = ordered_dict_factory ,
483+ load_balancing_policy = WhiteListRoundRobinPolicy ([self .hostname ]))
484+
480485 if use_conn :
481486 self .conn = use_conn
482487 else :
@@ -486,12 +491,13 @@ def __init__(self, hostname, port, color=False,
486491 self .conn = Cluster (contact_points = (self .hostname ,), port = self .port , cql_version = cqlver ,
487492 auth_provider = self .auth_provider ,
488493 ssl_options = sslhandling .ssl_settings (hostname , CONFIG_FILE ) if ssl else None ,
489- load_balancing_policy = WhiteListRoundRobinPolicy ([self .hostname ]),
490494 control_connection_timeout = connect_timeout ,
491- connect_timeout = connect_timeout ,
495+ connect_timeout = connect_timeout ,
496+ execution_profiles = {EXEC_PROFILE_DEFAULT : Keypsaces_profile },
492497 ** kwargs )
493498 self .owns_connection = not use_conn
494499
500+
495501 if keyspace :
496502 self .session = self .conn .connect (keyspace )
497503 else :
@@ -511,9 +517,11 @@ def __init__(self, hostname, port, color=False,
511517
512518 self .display_timezone = display_timezone
513519
514- self .session .default_timeout = request_timeout
515- self .session .row_factory = ordered_dict_factory
516- self .session .default_consistency_level = cassandra .ConsistencyLevel .ONE
520+ ##### These configurations are moved to EXEC_PROFILE_DEFAULT
521+ # self.session.default_timeout = request_timeout
522+ # self.session.row_factory = ordered_dict_factory
523+ # self.session.default_consistency_level = cassandra.ConsistencyLevel.ONE
524+
517525 self .get_connection_versions ()
518526 self .set_expanded_cql_version (self .connection_versions ['cql' ])
519527
@@ -629,15 +637,6 @@ def get_connection_versions(self):
629637 }
630638 self .connection_versions = vers
631639
632- def get_keyspace_names (self ):
633- return list (self .conn .metadata .keyspaces .keys ())
634-
635- def get_columnfamily_names (self , ksname = None ):
636- if ksname is None :
637- ksname = self .current_keyspace
638-
639- return list (self .get_keyspace_meta (ksname ).tables .keys ())
640-
641640 def get_materialized_view_names (self , ksname = None ):
642641 if ksname is None :
643642 ksname = self .current_keyspace
@@ -1370,117 +1369,86 @@ def do_describe(self, parsed):
13701369 will not work in cqlsh connected to Cassandra < 4.0.In cqlsh-expansion we have modified code to support describe statements for
13711370 Cassandra 3.11
13721371 """
1373- try :
1372+ stmt = SimpleStatement (parsed .extract_orig (), consistency_level = cassandra .ConsistencyLevel .LOCAL_ONE , fetch_size = self .page_size if self .use_paging else None )
1373+ future = self .session .execute_async (stmt )
13741374
1375+ if self .connection_versions ['build' ][0 ] < '4' :
1376+ try :
13751377 what = parsed .matched [1 ][1 ].lower ()
13761378 if what == 'keyspaces' :
1377- self . describe_keyspaces ( )
1379+ describe_keyspaces_3x ( self )
13781380 elif what == 'keyspace' :
13791381 ksname = self .cql_unprotect_name (parsed .get_binding ('ksname' , '' ))
13801382 if not ksname :
13811383 ksname = self .current_keyspace
13821384 if ksname is None :
13831385 self .printerr ('Not in any keyspace.' )
13841386 return
1385- self . describe_keyspace ( ksname )
1387+ describe_keyspace_3x ( self , ksname )
13861388 elif what in ('columnfamily' , 'table' ):
13871389 ks = self .cql_unprotect_name (parsed .get_binding ('ksname' , None ))
13881390 cf = self .cql_unprotect_name (parsed .get_binding ('cfname' ))
1389- self . describe_columnfamily ( ks , cf )
1391+ describe_columnfamily_3x ( self , ks , cf )
13901392 elif what in ('columnfamilies' , 'tables' ):
1391- self . describe_columnfamilies ( self .current_keyspace )
1393+ describe_columnfamilies_3x ( self , self .current_keyspace )
13921394 elif what == 'desc ' :
1393- self . describe_schema ( False )
1395+ describe_schema_3x ( self , False )
13941396 elif what == 'full' and parsed .matched [2 ][1 ].lower () == 'schema' :
1395- self . describe_schema ( True )
1397+ describe_schema_3x ( self , True )
13961398 elif what == 'cluster' :
1397- self . describe_cluster ( )
1399+ describe_cluster_3x ( self )
13981400 elif what :
13991401 ks = self .cql_unprotect_name (parsed .get_binding ('ksname' , None ))
14001402 name = self .cql_unprotect_name (parsed .get_binding ('cfname' ))
14011403 if not name :
14021404 name = self .cql_unprotect_name (parsed .get_binding ('idxname' , None ))
14031405 if not name :
14041406 name = self .cql_unprotect_name (parsed .get_binding ('mvname' , None ))
1405- self .describe_object (ks , name )
1406-
1407- except CQL_ERRORS as err :
1407+ describe_object_3x (self , ks , name )
1408+ except CQL_ERRORS as err :
14081409 err_msg = err .message if hasattr (err , 'message' ) else str (err )
14091410 self .printerr (err_msg .partition ("message=" )[2 ].strip ('"' ))
1410- except Exception :
1411+ except Exception :
14111412 import traceback
14121413 self .printerr (traceback .format_exc ())
14131414
1414- do_desc = do_describe
1415+ else :
1416+ try :
1417+ result = future .result ()
1418+ what = parsed .matched [1 ][1 ].lower ()
1419+
1420+ if what in ('columnfamilies' , 'tables' , 'types' , 'functions' , 'aggregates' ):
1421+ self .describe_list (result )
1422+ elif what == 'keyspaces' :
1423+ self .describe_keyspaces (result )
1424+ elif what == 'cluster' :
1425+ self .describe_cluster (result )
1426+ elif what :
1427+ self .describe_element (result )
1428+
1429+ except CQL_ERRORS as err :
1430+ err_msg = err .message if hasattr (err , 'message' ) else str (err )
1431+ self .printerr (err_msg .partition ("message=" )[2 ].strip ('"' ))
1432+ except Exception :
1433+ import traceback
1434+ self .printerr (traceback .format_exc ())
14151435
1416- def print_recreate_keyspace (self , ksdef , out ):
1417- out .write (ksdef .export_as_string ())
1418- out .write ("\n " )
1419-
1420- def print_recreate_columnfamily (self , ksname , cfname , out ):
1421- """
1422- Output CQL commands which should be pasteable back into a CQL session
1423- to recreate the given table.
1424- Writes output to the given out stream.
1425- """
1426- out .write (self .get_table_meta (ksname , cfname ).export_as_string ())
1427- out .write ("\n " )
1428-
1429- def print_recreate_object (self , ks , name , out ):
1430- """
1431- Output CQL commands which should be pasteable back into a CQL session
1432- to recreate the given object (ks, table or index).
1433- Writes output to the given out stream.
1434- """
1435- out .write (self .get_object_meta (ks , name ).export_as_string ())
1436- out .write ("\n " )
1436+ if future :
1437+ if future .warnings :
1438+ self .print_warnings (future .warnings )
1439+
1440+
1441+ do_desc = do_describe
14371442
1438- def describe_keyspaces (self ):
1443+ def describe_keyspaces (self , rows ):
14391444 """
14401445 Print the output for a DESCRIBE KEYSPACES query
14411446 """
1442- print ('' )
1443- cmd .Cmd .columnize (self , self .get_keyspace_names ())
1444- print ('' )
1447+ names = [r ['name' ] for r in rows ]
14451448
1446- def describe_keyspace (self , ksname ):
1447- print
1448- self .print_recreate_keyspace (self .get_keyspace_meta (ksname ), sys .stdout )
1449- print
1450-
1451- def describe_columnfamily (self , ksname , cfname ):
1452- if ksname is None :
1453- ksname = self .current_keyspace
1454- if ksname is None :
1455- raise NoKeyspaceError ("No keyspace specified and no current keyspace" )
1456- print
1457- self .print_recreate_columnfamily (ksname , cfname , sys .stdout )
1458- print
1459-
1460- def describe_columnfamilies (self , ksname ):
1461- print
1462- if ksname is None :
1463- for k in self .get_keyspaces ():
1464- name = k .name
1465- print ('Keyspace %s' % name )
1466- print ('---------%s' % ('-' * len (name )))
1467- cmd .Cmd .columnize (self , self .get_columnfamily_names (k .name ))
1468- print
1469- else :
1470- cmd .Cmd .columnize (self , self .get_columnfamily_names (ksname ))
1471- print
1472-
1473- def describe_schema (self , include_system = False ):
1474- print
1475- for k in self .get_keyspaces ():
1476- if include_system or k .name not in cql3handling .SYSTEM_KEYSPACES :
1477- self .print_recreate_keyspace (k , sys .stdout )
1478- print
1479-
1480- def describe_object (self , ks , name ):
1481- print
1482- self .print_recreate_object (ks , name , sys .stdout )
1483- print
1449+ print ('' )
1450+ cmd .Cmd .columnize (self , names )
1451+ print ('' )
14841452
14851453 def describe_list (self , rows ):
14861454 """
@@ -1518,19 +1486,22 @@ def describe_element(self, rows):
15181486 self .query_out .write (row ['create_statement' ])
15191487 print ('' )
15201488
1521- def describe_cluster (self ):
1522- print ('\n Cluster: %s' % self .get_cluster_name ())
1523- p = trim_if_present (self .get_partitioner (), 'org.apache.cassandra.dht.' )
1524- print ('Partitioner: %s\n ' % p )
1525- # TODO: snitch?
1526- # snitch = trim_if_present(self.get_snitch(), 'org.apache.cassandra.locator.')
1527- # print 'Snitch: %s\n' % snitch
1528- if self .current_keyspace is not None and self .current_keyspace != 'system' :
1529- print ("Range ownership:" )
1530- ring = self .get_ring (self .current_keyspace )
1531- for entry in ring .items ():
1532- print (' %39s [%s]' % (str (entry [0 ].value ), ', ' .join ([host .address for host in entry [1 ]])))
1533- print
1489+ def describe_cluster (self , rows ):
1490+ """
1491+ Print the output for a DESCRIBE CLUSTER query.
1492+
1493+ If a specified keyspace was in use the returned ResultSet will contains a 'range_ownership' column,
1494+ otherwise not.
1495+ """
1496+ for row in rows :
1497+ print ('\n Cluster: %s' % row ['cluster' ])
1498+ print ('Partitioner: %s' % row ['partitioner' ])
1499+ print ('Snitch: %s\n ' % row ['snitch' ])
1500+ if 'range_ownership' in row :
1501+ print ("Range ownership:" )
1502+ for entry in list (row ['range_ownership' ].items ()):
1503+ print (' %39s [%s]' % (entry [0 ], ', ' .join ([host for host in entry [1 ]])))
1504+ print ('' )
15341505
15351506 def do_copy (self , parsed ):
15361507 r"""
@@ -1613,7 +1584,6 @@ def do_copy(self, parsed):
16131584 When entering CSV data on STDIN, you can use the sequence "\."
16141585 on a line by itself to end the data input.
16151586 """
1616-
16171587 ks = self .cql_unprotect_name (parsed .get_binding ('ksname' , None ))
16181588 if ks is None :
16191589 ks = self .current_keyspace
0 commit comments