30
30
UnsupportedOperation , UserFunctionDescriptor ,
31
31
UserAggregateDescriptor , SchemaTargetType )
32
32
from cassandra .marshal import (int32_pack , int32_unpack , uint16_pack , uint16_unpack ,
33
- int8_pack , int8_unpack , uint64_pack , header_pack ,
33
+ uint8_pack , int8_unpack , uint64_pack , header_pack ,
34
34
v3_header_pack , uint32_pack )
35
35
from cassandra .cqltypes import (AsciiType , BytesType , BooleanType ,
36
36
CounterColumnType , DateType , DecimalType ,
@@ -387,6 +387,11 @@ def to_exception(self):
387
387
return AlreadyExists (** self .info )
388
388
389
389
390
+ class ClientWriteError (RequestExecutionException ):
391
+ summary = 'Client write failure.'
392
+ error_code = 0x8000
393
+
394
+
390
395
class StartupMessage (_MessageType ):
391
396
opcode = 0x01
392
397
name = 'STARTUP'
@@ -512,31 +517,34 @@ def recv_body(cls, f, *args):
512
517
_PAGE_SIZE_FLAG = 0x04
513
518
_WITH_PAGING_STATE_FLAG = 0x08
514
519
_WITH_SERIAL_CONSISTENCY_FLAG = 0x10
515
- _PROTOCOL_TIMESTAMP = 0x20
520
+ _PROTOCOL_TIMESTAMP_FLAG = 0x20
521
+ _NAMES_FOR_VALUES_FLAG = 0x40 # not used here
516
522
_WITH_KEYSPACE_FLAG = 0x80
517
523
_PREPARED_WITH_KEYSPACE_FLAG = 0x01
524
+ _PAGE_SIZE_BYTES_FLAG = 0x40000000
525
+ _PAGING_OPTIONS_FLAG = 0x80000000
518
526
519
527
520
- class QueryMessage (_MessageType ):
521
- opcode = 0x07
522
- name = 'QUERY'
528
+ class _QueryMessage (_MessageType ):
523
529
524
- def __init__ (self , query , consistency_level , serial_consistency_level = None ,
525
- fetch_size = None , paging_state = None , timestamp = None , keyspace = None ):
526
- self .query = query
530
+ def __init__ (self , query_params , consistency_level ,
531
+ serial_consistency_level = None , fetch_size = None ,
532
+ paging_state = None , timestamp = None , skip_meta = False ,
533
+ continuous_paging_options = None , keyspace = None ):
534
+ self .query_params = query_params
527
535
self .consistency_level = consistency_level
528
536
self .serial_consistency_level = serial_consistency_level
529
537
self .fetch_size = fetch_size
530
538
self .paging_state = paging_state
531
539
self .timestamp = timestamp
540
+ self .skip_meta = skip_meta
541
+ self .continuous_paging_options = continuous_paging_options
532
542
self .keyspace = keyspace
533
- self ._query_params = None # only used internally. May be set to a list of native-encoded values to have them sent with the request.
534
543
535
- def send_body (self , f , protocol_version ):
536
- write_longstring (f , self .query )
544
+ def _write_query_params (self , f , protocol_version ):
537
545
write_consistency_level (f , self .consistency_level )
538
546
flags = 0x00
539
- if self ._query_params is not None :
547
+ if self .query_params is not None :
540
548
flags |= _VALUES_FLAG # also v2+, but we're only setting params internally right now
541
549
542
550
if self .serial_consistency_level :
@@ -565,26 +573,33 @@ def send_body(self, f, protocol_version):
565
573
"2 or higher. Consider setting Cluster.protocol_version to 2." )
566
574
567
575
if self .timestamp is not None :
568
- flags |= _PROTOCOL_TIMESTAMP
576
+ flags |= _PROTOCOL_TIMESTAMP_FLAG
577
+
578
+ if self .continuous_paging_options :
579
+ if ProtocolVersion .has_continuous_paging_support (protocol_version ):
580
+ flags |= _PAGING_OPTIONS_FLAG
581
+ else :
582
+ raise UnsupportedOperation (
583
+ "Continuous paging may only be used with protocol version "
584
+ "ProtocolVersion.DSE_V1 or higher. Consider setting Cluster.protocol_version to ProtocolVersion.DSE_V1." )
569
585
570
586
if self .keyspace is not None :
571
587
if ProtocolVersion .uses_keyspace_flag (protocol_version ):
572
588
flags |= _WITH_KEYSPACE_FLAG
573
589
else :
574
590
raise UnsupportedOperation (
575
591
"Keyspaces may only be set on queries with protocol version "
576
- "5 or higher. Consider setting Cluster.protocol_version to 5 ." )
592
+ "DSE_V2 or higher. Consider setting Cluster.protocol_version to ProtocolVersion.DSE_V2 ." )
577
593
578
594
if ProtocolVersion .uses_int_query_flags (protocol_version ):
579
595
write_uint (f , flags )
580
596
else :
581
597
write_byte (f , flags )
582
598
583
- if self ._query_params is not None :
584
- write_short (f , len (self ._query_params ))
585
- for param in self ._query_params :
599
+ if self .query_params is not None :
600
+ write_short (f , len (self .query_params ))
601
+ for param in self .query_params :
586
602
write_value (f , param )
587
-
588
603
if self .fetch_size :
589
604
write_int (f , self .fetch_size )
590
605
if self .paging_state :
@@ -595,6 +610,49 @@ def send_body(self, f, protocol_version):
595
610
write_long (f , self .timestamp )
596
611
if self .keyspace is not None :
597
612
write_string (f , self .keyspace )
613
+ if self .continuous_paging_options :
614
+ self ._write_paging_options (f , self .continuous_paging_options , protocol_version )
615
+
616
+ def _write_paging_options (self , f , paging_options , protocol_version ):
617
+ write_int (f , paging_options .max_pages )
618
+ write_int (f , paging_options .max_pages_per_second )
619
+ if ProtocolVersion .has_continuous_paging_next_pages (protocol_version ):
620
+ write_int (f , paging_options .max_queue_size )
621
+
622
+
623
+ class QueryMessage (_QueryMessage ):
624
+ opcode = 0x07
625
+ name = 'QUERY'
626
+
627
+ def __init__ (self , query , consistency_level , serial_consistency_level = None ,
628
+ fetch_size = None , paging_state = None , timestamp = None , continuous_paging_options = None , keyspace = None ):
629
+ self .query = query
630
+ super (QueryMessage , self ).__init__ (None , consistency_level , serial_consistency_level , fetch_size ,
631
+ paging_state , timestamp , False , continuous_paging_options , keyspace )
632
+
633
+ def send_body (self , f , protocol_version ):
634
+ write_longstring (f , self .query )
635
+ self ._write_query_params (f , protocol_version )
636
+
637
+
638
+ class ExecuteMessage (_QueryMessage ):
639
+ opcode = 0x0A
640
+ name = 'EXECUTE'
641
+
642
+ def __init__ (self , query_id , query_params , consistency_level ,
643
+ serial_consistency_level = None , fetch_size = None ,
644
+ paging_state = None , timestamp = None , skip_meta = False ,
645
+ continuous_paging_options = None , result_metadata_id = None ):
646
+ self .query_id = query_id
647
+ self .result_metadata_id = result_metadata_id
648
+ super (ExecuteMessage , self ).__init__ (query_params , consistency_level , serial_consistency_level , fetch_size ,
649
+ paging_state , timestamp , skip_meta , continuous_paging_options )
650
+
651
+ def send_body (self , f , protocol_version ):
652
+ write_string (f , self .query_id )
653
+ if ProtocolVersion .uses_prepared_metadata (protocol_version ):
654
+ write_string (f , self .result_metadata_id )
655
+ self ._write_query_params (f , protocol_version )
598
656
599
657
600
658
CUSTOM_TYPE = object ()
@@ -611,6 +669,8 @@ class ResultMessage(_MessageType):
611
669
name = 'RESULT'
612
670
613
671
kind = None
672
+ results = None
673
+ paging_state = None
614
674
615
675
# Names match type name in module scope. Most are imported from cassandra.cqltypes (except CUSTOM_TYPE)
616
676
type_codes = _cqltypes_by_code = dict ((v , globals ()[k ]) for k , v in type_codes .__dict__ .items () if not k .startswith ('_' ))
@@ -622,6 +682,8 @@ class ResultMessage(_MessageType):
622
682
_CONTINUOUS_PAGING_LAST_FLAG = 0x80000000
623
683
_METADATA_ID_FLAG = 0x0008
624
684
685
+ kind = None
686
+
625
687
# These are all the things a result message might contain. They are populated according to 'kind'
626
688
column_names = None
627
689
column_types = None
@@ -635,7 +697,6 @@ class ResultMessage(_MessageType):
635
697
bind_metadata = None
636
698
pk_indexes = None
637
699
schema_change_event = None
638
- result_metadata_id = None
639
700
640
701
def __init__ (self , kind ):
641
702
self .kind = kind
@@ -818,7 +879,7 @@ def send_body(self, f, protocol_version):
818
879
else :
819
880
raise UnsupportedOperation (
820
881
"Keyspaces may only be set on queries with protocol version "
821
- "5 or higher. Consider setting Cluster.protocol_version to 5 ." )
882
+ "5 or DSE_V2 or higher. Consider setting Cluster.protocol_version." )
822
883
823
884
if ProtocolVersion .uses_prepare_flags (protocol_version ):
824
885
write_uint (f , flags )
@@ -829,87 +890,14 @@ def send_body(self, f, protocol_version):
829
890
"Attempted to set flags with value {flags:0=#8x} on"
830
891
"protocol version {pv}, which doesn't support flags"
831
892
"in prepared statements."
832
- "Consider setting Cluster.protocol_version to 5."
893
+ "Consider setting Cluster.protocol_version to 5 or DSE_V2 ."
833
894
"" .format (flags = flags , pv = protocol_version ))
834
895
835
896
if ProtocolVersion .uses_keyspace_flag (protocol_version ):
836
897
if self .keyspace :
837
898
write_string (f , self .keyspace )
838
899
839
900
840
- class ExecuteMessage (_MessageType ):
841
- opcode = 0x0A
842
- name = 'EXECUTE'
843
-
844
- def __init__ (self , query_id , query_params , consistency_level ,
845
- serial_consistency_level = None , fetch_size = None ,
846
- paging_state = None , timestamp = None , skip_meta = False ,
847
- result_metadata_id = None ):
848
- self .query_id = query_id
849
- self .query_params = query_params
850
- self .consistency_level = consistency_level
851
- self .serial_consistency_level = serial_consistency_level
852
- self .fetch_size = fetch_size
853
- self .paging_state = paging_state
854
- self .timestamp = timestamp
855
- self .skip_meta = skip_meta
856
- self .result_metadata_id = result_metadata_id
857
-
858
- def send_body (self , f , protocol_version ):
859
- write_string (f , self .query_id )
860
- if ProtocolVersion .uses_prepared_metadata (protocol_version ):
861
- write_string (f , self .result_metadata_id )
862
- if protocol_version == 1 :
863
- if self .serial_consistency_level :
864
- raise UnsupportedOperation (
865
- "Serial consistency levels require the use of protocol version "
866
- "2 or higher. Consider setting Cluster.protocol_version to 2 "
867
- "to support serial consistency levels." )
868
- if self .fetch_size or self .paging_state :
869
- raise UnsupportedOperation (
870
- "Automatic query paging may only be used with protocol version "
871
- "2 or higher. Consider setting Cluster.protocol_version to 2." )
872
- write_short (f , len (self .query_params ))
873
- for param in self .query_params :
874
- write_value (f , param )
875
- write_consistency_level (f , self .consistency_level )
876
- else :
877
- write_consistency_level (f , self .consistency_level )
878
- flags = _VALUES_FLAG
879
- if self .serial_consistency_level :
880
- flags |= _WITH_SERIAL_CONSISTENCY_FLAG
881
- if self .fetch_size :
882
- flags |= _PAGE_SIZE_FLAG
883
- if self .paging_state :
884
- flags |= _WITH_PAGING_STATE_FLAG
885
- if self .timestamp is not None :
886
- if protocol_version >= 3 :
887
- flags |= _PROTOCOL_TIMESTAMP
888
- else :
889
- raise UnsupportedOperation (
890
- "Protocol-level timestamps may only be used with protocol version "
891
- "3 or higher. Consider setting Cluster.protocol_version to 3." )
892
- if self .skip_meta :
893
- flags |= _SKIP_METADATA_FLAG
894
-
895
- if ProtocolVersion .uses_int_query_flags (protocol_version ):
896
- write_uint (f , flags )
897
- else :
898
- write_byte (f , flags )
899
-
900
- write_short (f , len (self .query_params ))
901
- for param in self .query_params :
902
- write_value (f , param )
903
- if self .fetch_size :
904
- write_int (f , self .fetch_size )
905
- if self .paging_state :
906
- write_longstring (f , self .paging_state )
907
- if self .serial_consistency_level :
908
- write_consistency_level (f , self .serial_consistency_level )
909
- if self .timestamp is not None :
910
- write_long (f , self .timestamp )
911
-
912
-
913
901
class BatchMessage (_MessageType ):
914
902
opcode = 0x0D
915
903
name = 'BATCH'
@@ -945,7 +933,7 @@ def send_body(self, f, protocol_version):
945
933
if self .serial_consistency_level :
946
934
flags |= _WITH_SERIAL_CONSISTENCY_FLAG
947
935
if self .timestamp is not None :
948
- flags |= _PROTOCOL_TIMESTAMP
936
+ flags |= _PROTOCOL_TIMESTAMP_FLAG
949
937
if self .keyspace :
950
938
if ProtocolVersion .uses_keyspace_flag (protocol_version ):
951
939
flags |= _WITH_KEYSPACE_FLAG
@@ -1146,7 +1134,7 @@ def decode_message(cls, protocol_version, user_type_map, stream_id, flags, opcod
1146
1134
else :
1147
1135
custom_payload = None
1148
1136
1149
- flags &= USE_BETA_MASK # will only be set if we asserted it in connection estabishment
1137
+ flags &= USE_BETA_MASK # will only be set if we asserted it in connection estabishment
1150
1138
1151
1139
if flags :
1152
1140
log .warning ("Unknown protocol flags set: %02x. May cause problems." , flags )
@@ -1164,6 +1152,7 @@ def decode_message(cls, protocol_version, user_type_map, stream_id, flags, opcod
1164
1152
1165
1153
return msg
1166
1154
1155
+
1167
1156
def cython_protocol_handler (colparser ):
1168
1157
"""
1169
1158
Given a column parser to deserialize ResultMessages, return a suitable
@@ -1229,7 +1218,7 @@ def read_byte(f):
1229
1218
1230
1219
1231
1220
def write_byte (f , b ):
1232
- f .write (int8_pack (b ))
1221
+ f .write (uint8_pack (b ))
1233
1222
1234
1223
1235
1224
def read_int (f ):
0 commit comments