@@ -723,8 +723,9 @@ func (f *framer) readTypeInfo() TypeInfo {
723723 typ : Type (id ),
724724 }
725725
726- // Fast path: simple native types (0x0001-0x0015) need no further processing
727- if id > 0 && id <= 0x0015 {
726+ // Fast path: simple native types (0x0001 through TypeDuration) need no further processing.
727+ // These are all scalar types that require no additional wire reads beyond the type ID.
728+ if id > 0 && id <= uint16 (TypeDuration ) {
728729 return simple
729730 }
730731
@@ -851,23 +852,16 @@ func (f *framer) parsePreparedMetadata() preparedMetadata {
851852 }
852853
853854 var cols []ColumnInfo
854- sameKeyspaceTable := true
855- firstKeyspace := ""
856- firstTable := ""
857855 readPerColumnSpec := ! globalSpec
856+ var tracker keyspaceTableTracker
858857 if meta .colCount < 1000 {
859858 // preallocate columninfo to avoid excess copying
860859 cols = make ([]ColumnInfo , meta .colCount )
861860 for i := 0 ; i < meta .colCount ; i ++ {
862861 col := & cols [i ]
863862 keyspace , table := f .readColWithSpec (col , & meta .resultMetadata , globalSpec , meta .keyspace , meta .table , i , readPerColumnSpec )
864863 if readPerColumnSpec {
865- if i == 0 {
866- firstKeyspace = keyspace
867- firstTable = table
868- } else if keyspace != firstKeyspace || table != firstTable {
869- sameKeyspaceTable = false
870- }
864+ tracker .track (i , keyspace , table )
871865 }
872866 }
873867 } else {
@@ -877,20 +871,15 @@ func (f *framer) parsePreparedMetadata() preparedMetadata {
877871 var col ColumnInfo
878872 keyspace , table := f .readColWithSpec (& col , & meta .resultMetadata , globalSpec , meta .keyspace , meta .table , i , readPerColumnSpec )
879873 if readPerColumnSpec {
880- if i == 0 {
881- firstKeyspace = keyspace
882- firstTable = table
883- } else if keyspace != firstKeyspace || table != firstTable {
884- sameKeyspaceTable = false
885- }
874+ tracker .track (i , keyspace , table )
886875 }
887876 cols = append (cols , col )
888877 }
889878 }
890879
891- if ! globalSpec && meta .colCount > 0 && sameKeyspaceTable {
892- meta .keyspace = firstKeyspace
893- meta .table = firstTable
880+ if ! globalSpec && meta .colCount > 0 && tracker . allSame {
881+ meta .keyspace = tracker . keyspace
882+ meta .table = tracker . table
894883 }
895884
896885 meta .columns = cols
@@ -919,6 +908,24 @@ func (r resultMetadata) String() string {
919908 return fmt .Sprintf ("[metadata flags=0x%x paging_state=% X columns=%v]" , r .flags , r .pagingState , r .columns )
920909}
921910
911+ // keyspaceTableTracker tracks whether all columns in a prepared statement
912+ // share the same keyspace and table, recording the first column's values.
913+ type keyspaceTableTracker struct {
914+ keyspace string
915+ table string
916+ allSame bool
917+ }
918+
919+ func (t * keyspaceTableTracker ) track (colIndex int , keyspace , table string ) {
920+ if colIndex == 0 {
921+ t .keyspace = keyspace
922+ t .table = table
923+ t .allSame = true
924+ } else if keyspace != t .keyspace || table != t .table {
925+ t .allSame = false
926+ }
927+ }
928+
922929func (f * framer ) readColWithSpec (col * ColumnInfo , meta * resultMetadata , globalSpec bool , keyspace , table string , colIndex int , readPerColumnSpec bool ) (string , string ) {
923930 if readPerColumnSpec {
924931 // In case of prepared statements with per-column spec, we need to read the keyspace and table for each column.
@@ -964,7 +971,12 @@ func (f *framer) parseResultMetadata() resultMetadata {
964971
965972 globalSpec := meta .flags & frm .FlagGlobalTableSpec == frm .FlagGlobalTableSpec
966973 if globalSpec || meta .colCount > 0 {
967- // globalSpec: read from metadata position; !globalSpec: read from first column position
974+ // When globalSpec is set, keyspace/table are encoded once at the metadata level.
975+ // When !globalSpec, the protocol encodes keyspace/table per-column, but in practice
976+ // CQL result sets always come from a single table, so we read from the first column's
977+ // position and reuse for all columns. This avoids per-column string allocation.
978+ // See readColWithSpec: column 0 skips reading (already consumed here), columns 1+
979+ // skip the redundant per-column keyspace/table bytes on the wire.
968980 meta .keyspace = f .readString ()
969981 meta .table = f .readString ()
970982 }
0 commit comments