github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/client/client_remote_test.go (about) 1 // Copyright 2020 DataStax 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package client_test 16 17 import ( 18 "context" 19 "encoding/binary" 20 "fmt" 21 "github.com/datastax/go-cassandra-native-protocol/client" 22 "github.com/datastax/go-cassandra-native-protocol/datatype" 23 "github.com/datastax/go-cassandra-native-protocol/frame" 24 "github.com/datastax/go-cassandra-native-protocol/message" 25 "github.com/datastax/go-cassandra-native-protocol/primitive" 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 "math" 29 "sync" 30 "testing" 31 "time" 32 ) 33 34 // This test requires a remote server listening on localhost:9042 without authentication. 35 func TestRemoteServerNoAuth(t *testing.T) { 36 if !remoteAvailable { 37 t.Skip("No remote cluster available") 38 } 39 for _, version := range primitive.SupportedProtocolVersions() { 40 t.Run(version.String(), func(t *testing.T) { 41 42 for genName, generator := range streamIdGenerators { 43 t.Run(fmt.Sprintf("generator %v", genName), func(t *testing.T) { 44 45 for _, compression := range compressions { 46 if version.SupportsCompression(compression) { 47 t.Run(fmt.Sprintf("%v", compression), func(t *testing.T) { 48 49 clt := client.NewCqlClient("127.0.0.1:9042", nil) 50 clt.Compression = compression 51 if version <= primitive.ProtocolVersion2 { 52 clt.MaxInFlight = math.MaxInt8 53 } 54 clientTest(t, clt, version, generator, compression != primitive.CompressionNone, version.IsDse()) 55 56 }) 57 } 58 } 59 }) 60 } 61 }) 62 } 63 } 64 65 // This test requires a remote server listening on localhost:9042 with authentication. 66 func TestRemoteServerAuth(t *testing.T) { 67 if !remoteAvailable { 68 t.Skip("No remote cluster available") 69 } 70 for _, version := range primitive.SupportedProtocolVersions() { 71 t.Run(version.String(), func(t *testing.T) { 72 73 for genName, generator := range streamIdGenerators { 74 t.Run(fmt.Sprintf("generator %v", genName), func(t *testing.T) { 75 76 for _, compression := range compressions { 77 if version.SupportsCompression(compression) { 78 t.Run(fmt.Sprintf("%v", compression), func(t *testing.T) { 79 80 clt := client.NewCqlClient( 81 "127.0.0.1:9042", 82 &client.AuthCredentials{Username: "cassandra", Password: "cassandra"}, 83 ) 84 clt.Compression = compression 85 86 clientTest(t, clt, version, generator, compression != primitive.CompressionNone, version.IsDse()) 87 }) 88 } 89 } 90 }) 91 } 92 }) 93 } 94 } 95 96 func clientTest( 97 t *testing.T, 98 clt *client.CqlClient, 99 version primitive.ProtocolVersion, 100 generator func(int, primitive.ProtocolVersion) int16, 101 compress bool, 102 continuousPaging bool, 103 ) { 104 ks := fmt.Sprintf("ks_%d", time.Now().UnixNano()) 105 table := fmt.Sprintf("t_%d", time.Now().UnixNano()) 106 107 eventsCount := 0 108 clt.EventHandlers = []client.EventHandler{checkEventsReceived(t, &eventsCount, ks, table)} 109 110 ctx, cancel := context.WithCancel(context.Background()) 111 defer cancel() 112 113 clientConn, err := clt.ConnectAndInit(ctx, version, generator(1, version)) 114 require.NoError(t, err) 115 require.False(t, clientConn.IsClosed()) 116 117 registerForSchemaChanges(t, clientConn, version, generator, compress) 118 createSchema(t, clientConn, ks, table, version, generator, compress) 119 120 require.GreaterOrEqual(t, eventsCount, 2) 121 122 insertData(t, clientConn, ks, table, version, generator, compress) 123 insertDataBatch(t, clientConn, ks, table, version, generator, compress) 124 insertDataPrepared(t, clientConn, ks, table, version, generator, compress) 125 insertDataBatchPrepared(t, clientConn, ks, table, version, generator, compress) 126 127 retrieveData(t, clientConn, ks, table, version, generator, compress) 128 retrieveDataPrepared(t, clientConn, ks, table, version, generator, compress) 129 if continuousPaging { 130 retrieveDataContinuousPaging(t, clientConn, ks, table, version, generator, compress) 131 } 132 133 truncate(t, clientConn, ks, table, version, generator, compress) 134 insertAndRetrieveLargeData(t, clientConn, ks, table, version, generator, compress) 135 136 dropSchema(t, clientConn, ks, version, generator, compress) 137 checkEventsByChannel(t, clientConn) 138 require.GreaterOrEqual(t, eventsCount, 4) 139 140 cancel() 141 assert.Eventually(t, clientConn.IsClosed, time.Second*10, time.Millisecond*10) 142 143 } 144 145 func checkEventsReceived(t *testing.T, eventsCount *int, ks string, table string) client.EventHandler { 146 return func(event *frame.Frame, conn *client.CqlClientConnection) { 147 assert.Equal(t, primitive.OpCodeEvent, event.Header.OpCode) 148 assert.EqualValues(t, -1, event.Header.StreamId) 149 assert.IsType(t, &message.SchemaChangeEvent{}, event.Body.Message) 150 sce := event.Body.Message.(*message.SchemaChangeEvent) 151 if *eventsCount == 0 { 152 assert.Equal(t, primitive.SchemaChangeTargetKeyspace, sce.Target) 153 assert.Equal(t, primitive.SchemaChangeTypeCreated, sce.ChangeType) 154 assert.Equal(t, ks, sce.Keyspace) 155 assert.Equal(t, "", sce.Object) 156 } else if *eventsCount == 1 { 157 assert.Equal(t, primitive.SchemaChangeTargetTable, sce.Target) 158 assert.Equal(t, primitive.SchemaChangeTypeCreated, sce.ChangeType) 159 assert.Equal(t, ks, sce.Keyspace) 160 assert.Equal(t, table, sce.Object) 161 } else { 162 assert.Equal(t, primitive.SchemaChangeTypeDropped, sce.ChangeType) 163 } 164 *eventsCount++ 165 } 166 } 167 168 func checkEventsByChannel(t *testing.T, clientConn *client.CqlClientConnection) { 169 // expect 4 events, 2 CREATED, 2 DROPPED // 2 KEYSPACE, 2 TABLE 170 created := 0 171 dropped := 0 172 ks := 0 173 table := 0 174 for i := 0; i < 4; i++ { 175 event, err := clientConn.ReceiveEvent() 176 require.NoError(t, err) 177 assert.EqualValues(t, -1, event.Header.StreamId) 178 assert.IsType(t, &message.SchemaChangeEvent{}, event.Body.Message) 179 sce := event.Body.Message.(*message.SchemaChangeEvent) 180 switch sce.ChangeType { 181 case primitive.SchemaChangeTypeCreated: 182 created++ 183 case primitive.SchemaChangeTypeDropped: 184 dropped++ 185 } 186 switch sce.Target { 187 case primitive.SchemaChangeTargetKeyspace: 188 ks++ 189 case primitive.SchemaChangeTargetTable: 190 table++ 191 } 192 } 193 assert.Equal(t, 2, created) 194 assert.Equal(t, 2, dropped) 195 assert.Equal(t, 2, ks) 196 assert.Equal(t, 2, table) 197 } 198 199 func registerForSchemaChanges( 200 t *testing.T, 201 clientConn *client.CqlClientConnection, 202 version primitive.ProtocolVersion, 203 generator func(int, primitive.ProtocolVersion) int16, 204 compress bool, 205 ) { 206 request := frame.NewFrame( 207 version, 208 generator(1, version), 209 &message.Register{EventTypes: []primitive.EventType{primitive.EventTypeSchemaChange}}, 210 ) 211 request.SetCompress(compress) 212 response, err := clientConn.SendAndReceive(request) 213 require.NoError(t, err) 214 require.IsType(t, &message.Ready{}, response.Body.Message) 215 } 216 217 func createSchema( 218 t *testing.T, 219 clientConn *client.CqlClientConnection, 220 ks string, 221 table string, 222 version primitive.ProtocolVersion, 223 generator func(int, primitive.ProtocolVersion) int16, 224 compress bool, 225 ) { 226 request := frame.NewFrame( 227 version, 228 generator(1, version), 229 &message.Query{ 230 Query: fmt.Sprintf("CREATE KEYSPACE %s "+ 231 "WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'} "+ 232 "AND durable_writes = true", ks), 233 }, 234 ) 235 request.SetCompress(compress) 236 response, err := clientConn.SendAndReceive(request) 237 require.NoError(t, err) 238 require.IsType(t, &message.SchemaChangeResult{}, response.Body.Message) 239 result := response.Body.Message.(*message.SchemaChangeResult) 240 require.Equal(t, result.ChangeType, primitive.SchemaChangeTypeCreated) 241 require.Equal(t, result.Target, primitive.SchemaChangeTargetKeyspace) 242 require.Equal(t, result.Keyspace, ks) 243 require.Equal(t, result.Object, "") 244 request = frame.NewFrame( 245 version, 246 generator(1, version), 247 &message.Query{ 248 Query: fmt.Sprintf("CREATE TABLE %s.%s "+ 249 "(pk int, cc int, v int, PRIMARY KEY (pk, cc))", ks, table), 250 }, 251 ) 252 request.SetCompress(compress) 253 response, err = clientConn.SendAndReceive(request) 254 require.NoError(t, err) 255 require.IsType(t, &message.SchemaChangeResult{}, response.Body.Message) 256 result = response.Body.Message.(*message.SchemaChangeResult) 257 require.Equal(t, result.ChangeType, primitive.SchemaChangeTypeCreated) 258 require.Equal(t, result.Target, primitive.SchemaChangeTargetTable) 259 require.Equal(t, result.Keyspace, ks) 260 require.Equal(t, result.Object, table) 261 } 262 263 func truncate( 264 t *testing.T, 265 clientConn *client.CqlClientConnection, 266 ks string, 267 table string, 268 version primitive.ProtocolVersion, 269 generator func(int, primitive.ProtocolVersion) int16, 270 compress bool, 271 ) { 272 request := frame.NewFrame( 273 version, 274 generator(1, version), 275 &message.Query{ 276 Query: fmt.Sprintf("TRUNCATE %s.%s", ks, table), 277 }, 278 ) 279 request.SetCompress(compress) 280 response, err := clientConn.SendAndReceive(request) 281 require.NoError(t, err) 282 require.IsType(t, &message.VoidResult{}, response.Body.Message) 283 } 284 285 func dropSchema( 286 t *testing.T, 287 clientConn *client.CqlClientConnection, 288 ks string, 289 version primitive.ProtocolVersion, 290 generator func(int, primitive.ProtocolVersion) int16, 291 compress bool, 292 ) { 293 request := frame.NewFrame( 294 version, 295 generator(1, version), 296 &message.Query{ 297 Query: fmt.Sprintf("DROP KEYSPACE %s", ks), 298 }, 299 ) 300 request.SetCompress(compress) 301 response, err := clientConn.SendAndReceive(request) 302 require.NoError(t, err) 303 require.IsType(t, &message.SchemaChangeResult{}, response.Body.Message) 304 result := response.Body.Message.(*message.SchemaChangeResult) 305 require.Equal(t, result.ChangeType, primitive.SchemaChangeTypeDropped) 306 require.Equal(t, result.Target, primitive.SchemaChangeTargetKeyspace) 307 require.Equal(t, result.Keyspace, ks) 308 require.Equal(t, result.Object, "") 309 } 310 311 func insertData( 312 t *testing.T, 313 clientConn *client.CqlClientConnection, 314 ks string, 315 table string, 316 version primitive.ProtocolVersion, 317 generator func(int, primitive.ProtocolVersion) int16, 318 compress bool, 319 ) { 320 wg := &sync.WaitGroup{} 321 for i := 1; i <= 10; i++ { 322 wg.Add(1) 323 go func(i int) { 324 defer wg.Done() 325 for j := 1; j <= 10; j++ { 326 pk := make([]byte, 4) 327 cc := make([]byte, 4) 328 v := make([]byte, 4) 329 binary.BigEndian.PutUint32(pk, uint32(i)) 330 binary.BigEndian.PutUint32(cc, uint32(j)) 331 binary.BigEndian.PutUint32(v, uint32(i)*uint32(j)) 332 request := frame.NewFrame( 333 version, 334 generator(i, version), 335 &message.Query{ 336 Query: fmt.Sprintf("INSERT INTO %s.%s (pk, cc, v) VALUES (?,?,?)", ks, table), 337 Options: &message.QueryOptions{ 338 Consistency: primitive.ConsistencyLevelOne, 339 PositionalValues: []*primitive.Value{ 340 primitive.NewValue(pk), 341 primitive.NewValue(cc), 342 primitive.NewValue(v), 343 }, 344 }, 345 }, 346 ) 347 request.SetCompress(compress) 348 response, err := clientConn.SendAndReceive(request) 349 require.NoError(t, err) 350 require.IsType(t, &message.VoidResult{}, response.Body.Message) 351 } 352 }(i) 353 } 354 wg.Wait() 355 } 356 357 func insertDataPrepared( 358 t *testing.T, 359 clientConn *client.CqlClientConnection, 360 ks string, 361 table string, 362 version primitive.ProtocolVersion, 363 generator func(int, primitive.ProtocolVersion) int16, 364 compress bool, 365 ) { 366 prepared := prepareInsert(t, clientConn, ks, table, version, generator, compress) 367 wg := &sync.WaitGroup{} 368 for i := 1; i <= 10; i++ { 369 wg.Add(1) 370 go func(i int) { 371 defer wg.Done() 372 for j := 1; j <= 10; j++ { 373 pk := make([]byte, 4) 374 cc := make([]byte, 4) 375 v := make([]byte, 4) 376 binary.BigEndian.PutUint32(pk, uint32(i)) 377 binary.BigEndian.PutUint32(cc, uint32(j)) 378 binary.BigEndian.PutUint32(v, uint32(i)*uint32(j)) 379 request := frame.NewFrame( 380 version, 381 generator(i, version), 382 &message.Execute{ 383 QueryId: prepared.PreparedQueryId, 384 ResultMetadataId: prepared.ResultMetadataId, 385 Options: &message.QueryOptions{ 386 Consistency: primitive.ConsistencyLevelOne, 387 PositionalValues: []*primitive.Value{ 388 primitive.NewValue(pk), 389 primitive.NewValue(cc), 390 primitive.NewValue(v), 391 }, 392 }, 393 }, 394 ) 395 request.SetCompress(compress) 396 response, err := clientConn.SendAndReceive(request) 397 require.NoError(t, err) 398 require.IsType(t, &message.VoidResult{}, response.Body.Message) 399 } 400 }(i) 401 } 402 wg.Wait() 403 } 404 405 func insertDataBatch( 406 t *testing.T, 407 clientConn *client.CqlClientConnection, 408 ks string, 409 table string, 410 version primitive.ProtocolVersion, 411 generator func(int, primitive.ProtocolVersion) int16, 412 compress bool, 413 ) { 414 wg := &sync.WaitGroup{} 415 for i := 1; i <= 10; i++ { 416 wg.Add(1) 417 go func(i int) { 418 defer wg.Done() 419 children := make([]*message.BatchChild, 10) 420 for j := 1; j <= 10; j++ { 421 pk := make([]byte, 4) 422 cc := make([]byte, 4) 423 v := make([]byte, 4) 424 binary.BigEndian.PutUint32(pk, uint32(i)) 425 binary.BigEndian.PutUint32(cc, uint32(j)) 426 binary.BigEndian.PutUint32(v, uint32(i)*uint32(j)) 427 children[j-1] = &message.BatchChild{ 428 Query: fmt.Sprintf("INSERT INTO %s.%s (pk, cc, v) VALUES (?,?,?)", ks, table), 429 Values: []*primitive.Value{ 430 primitive.NewValue(pk), 431 primitive.NewValue(cc), 432 primitive.NewValue(v), 433 }, 434 } 435 } 436 request := frame.NewFrame( 437 version, 438 generator(i, version), 439 &message.Batch{ 440 Consistency: primitive.ConsistencyLevelLocalOne, 441 Children: children, 442 }, 443 ) 444 request.SetCompress(compress) 445 response, err := clientConn.SendAndReceive(request) 446 require.NoError(t, err) 447 require.IsType(t, &message.VoidResult{}, response.Body.Message) 448 }(i) 449 } 450 wg.Wait() 451 } 452 453 func insertDataBatchPrepared( 454 t *testing.T, 455 clientConn *client.CqlClientConnection, 456 ks string, 457 table string, 458 version primitive.ProtocolVersion, 459 generator func(int, primitive.ProtocolVersion) int16, 460 compress bool, 461 ) { 462 prepared := prepareInsert(t, clientConn, ks, table, version, generator, compress) 463 wg := &sync.WaitGroup{} 464 for i := 1; i <= 10; i++ { 465 wg.Add(1) 466 go func(i int) { 467 defer wg.Done() 468 children := make([]*message.BatchChild, 10) 469 for j := 1; j <= 10; j++ { 470 pk := make([]byte, 4) 471 cc := make([]byte, 4) 472 v := make([]byte, 4) 473 binary.BigEndian.PutUint32(pk, uint32(i)) 474 binary.BigEndian.PutUint32(cc, uint32(j)) 475 binary.BigEndian.PutUint32(v, uint32(i)*uint32(j)) 476 children[j-1] = &message.BatchChild{ 477 Id: prepared.PreparedQueryId, 478 Values: []*primitive.Value{ 479 primitive.NewValue(pk), 480 primitive.NewValue(cc), 481 primitive.NewValue(v), 482 }, 483 } 484 } 485 request := frame.NewFrame( 486 version, 487 generator(i, version), 488 &message.Batch{ 489 Consistency: primitive.ConsistencyLevelLocalOne, 490 Children: children, 491 }, 492 ) 493 request.SetCompress(compress) 494 response, err := clientConn.SendAndReceive(request) 495 require.NoError(t, err) 496 require.IsType(t, &message.VoidResult{}, response.Body.Message) 497 498 }(i) 499 } 500 wg.Wait() 501 } 502 503 func retrieveData( 504 t *testing.T, 505 clientConn *client.CqlClientConnection, 506 ks string, 507 table string, 508 version primitive.ProtocolVersion, 509 generator func(int, primitive.ProtocolVersion) int16, 510 compress bool, 511 ) { 512 wg := &sync.WaitGroup{} 513 for i := 1; i <= 10; i++ { 514 wg.Add(1) 515 go func(i int) { 516 defer wg.Done() 517 for j := 1; j <= 10; j++ { 518 pk := make([]byte, 4) 519 cc := make([]byte, 4) 520 binary.BigEndian.PutUint32(pk, uint32(i)) 521 binary.BigEndian.PutUint32(cc, uint32(j)) 522 request := frame.NewFrame( 523 version, 524 generator(i, version), 525 &message.Query{ 526 Query: fmt.Sprintf("SELECT v FROM %s.%s WHERE pk = ? AND cc = ?", ks, table), 527 Options: &message.QueryOptions{ 528 Consistency: primitive.ConsistencyLevelOne, 529 PositionalValues: []*primitive.Value{ 530 primitive.NewValue(pk), 531 primitive.NewValue(cc), 532 }, 533 }, 534 }, 535 ) 536 request.SetCompress(compress) 537 response, err := clientConn.SendAndReceive(request) 538 require.NoError(t, err) 539 require.IsType(t, &message.RowsResult{}, response.Body.Message) 540 result := response.Body.Message.(*message.RowsResult) 541 require.Len(t, result.Data, 1) 542 row := result.Data[0] 543 require.Len(t, row, 1) 544 column := row[0] 545 require.Len(t, column, 4) 546 v := binary.BigEndian.Uint32(column) 547 require.Equal(t, uint32(i*j), v) 548 } 549 }(i) 550 } 551 wg.Wait() 552 } 553 554 func retrieveDataPrepared( 555 t *testing.T, 556 clientConn *client.CqlClientConnection, 557 ks string, 558 table string, 559 version primitive.ProtocolVersion, 560 generator func(int, primitive.ProtocolVersion) int16, 561 compress bool, 562 ) { 563 prepared := prepareSelect(t, clientConn, ks, table, version, generator, compress) 564 wg := &sync.WaitGroup{} 565 for i := 1; i <= 10; i++ { 566 wg.Add(1) 567 go func(i int) { 568 defer wg.Done() 569 for j := 1; j <= 10; j++ { 570 pk := make([]byte, 4) 571 cc := make([]byte, 4) 572 binary.BigEndian.PutUint32(pk, uint32(i)) 573 binary.BigEndian.PutUint32(cc, uint32(j)) 574 request := frame.NewFrame( 575 version, 576 generator(i, version), 577 &message.Execute{ 578 QueryId: prepared.PreparedQueryId, 579 ResultMetadataId: prepared.ResultMetadataId, 580 Options: &message.QueryOptions{ 581 Consistency: primitive.ConsistencyLevelOne, 582 PositionalValues: []*primitive.Value{ 583 primitive.NewValue(pk), 584 primitive.NewValue(cc), 585 }, 586 }, 587 }, 588 ) 589 request.SetCompress(compress) 590 response, err := clientConn.SendAndReceive(request) 591 require.NoError(t, err) 592 require.IsType(t, &message.RowsResult{}, response.Body.Message) 593 result := response.Body.Message.(*message.RowsResult) 594 require.Len(t, result.Data, 1) 595 row := result.Data[0] 596 require.Len(t, row, 1) 597 column := row[0] 598 require.Len(t, column, 4) 599 v := binary.BigEndian.Uint32(column) 600 require.Equal(t, uint32(i*j), v) 601 } 602 }(i) 603 } 604 wg.Wait() 605 } 606 607 func retrieveDataContinuousPaging( 608 t *testing.T, 609 clientConn *client.CqlClientConnection, 610 ks string, 611 table string, 612 version primitive.ProtocolVersion, 613 generator func(int, primitive.ProtocolVersion) int16, 614 compress bool, 615 ) { 616 request := frame.NewFrame( 617 version, 618 generator(1, version), 619 &message.Query{ 620 Query: fmt.Sprintf("SELECT v FROM %s.%s", ks, table), 621 Options: &message.QueryOptions{ 622 Consistency: primitive.ConsistencyLevelLocalOne, 623 PageSize: 10, 624 ContinuousPagingOptions: &message.ContinuousPagingOptions{MaxPages: 5}, 625 }, 626 }, 627 ) 628 request.SetCompress(compress) 629 630 ch, err := clientConn.Send(request) 631 require.NoError(t, err) 632 633 for i := 1; i <= 5; i++ { 634 f, err := clientConn.Receive(ch) 635 require.NoError(t, err) 636 require.NotNil(t, f) 637 require.IsType(t, &message.RowsResult{}, f.Body.Message) 638 result := f.Body.Message.(*message.RowsResult) 639 assert.Equal(t, result.Metadata.ContinuousPageNumber, int32(i)) 640 assert.Equal(t, result.Metadata.LastContinuousPage, i == 5) 641 assert.Len(t, result.Data, 10) 642 } 643 644 request = frame.NewFrame( 645 version, 646 generator(1, version), 647 &message.Revise{ 648 RevisionType: primitive.DseRevisionTypeCancelContinuousPaging, 649 TargetStreamId: int32(request.Header.StreamId), 650 }, 651 ) 652 request.SetCompress(compress) 653 654 response, err := clientConn.SendAndReceive(request) 655 require.NoError(t, err) 656 require.IsType(t, &message.RowsResult{}, response.Body.Message) 657 result := response.Body.Message.(*message.RowsResult) 658 require.Len(t, result.Data, 1) 659 row := result.Data[0] 660 require.Len(t, row, 1) 661 column := row[0] 662 require.Len(t, column, 1) // boolean 663 } 664 665 func prepareInsert( 666 t *testing.T, 667 clientConn *client.CqlClientConnection, 668 ks string, 669 table string, 670 version primitive.ProtocolVersion, 671 generator func(int, primitive.ProtocolVersion) int16, 672 compress bool, 673 ) *message.PreparedResult { 674 request := frame.NewFrame( 675 version, 676 generator(1, version), 677 &message.Prepare{ 678 Query: fmt.Sprintf("INSERT INTO %s.%s (pk, cc, v) VALUES (?,?,?)", ks, table), 679 }, 680 ) 681 request.SetCompress(compress) 682 response, err := clientConn.SendAndReceive(request) 683 require.NoError(t, err) 684 require.IsType(t, &message.PreparedResult{}, response.Body.Message) 685 prepared := response.Body.Message.(*message.PreparedResult) 686 assert.Len(t, prepared.VariablesMetadata.Columns, 3) 687 assert.Equal(t, ks, prepared.VariablesMetadata.Columns[0].Keyspace) 688 assert.Equal(t, table, prepared.VariablesMetadata.Columns[0].Table) 689 assert.Equal(t, "pk", prepared.VariablesMetadata.Columns[0].Name) 690 assert.Equal(t, datatype.Int, prepared.VariablesMetadata.Columns[0].Type) 691 assert.Equal(t, ks, prepared.VariablesMetadata.Columns[1].Keyspace) 692 assert.Equal(t, table, prepared.VariablesMetadata.Columns[1].Table) 693 assert.Equal(t, "cc", prepared.VariablesMetadata.Columns[1].Name) 694 assert.Equal(t, datatype.Int, prepared.VariablesMetadata.Columns[1].Type) 695 assert.Equal(t, ks, prepared.VariablesMetadata.Columns[2].Keyspace) 696 assert.Equal(t, table, prepared.VariablesMetadata.Columns[2].Table) 697 assert.Equal(t, "v", prepared.VariablesMetadata.Columns[2].Name) 698 assert.Equal(t, datatype.Int, prepared.VariablesMetadata.Columns[2].Type) 699 if version >= primitive.ProtocolVersion4 { 700 assert.Equal(t, prepared.VariablesMetadata.PkIndices, []uint16{0}) 701 } 702 assert.Zero(t, prepared.ResultMetadata.ColumnCount) 703 assert.Nil(t, prepared.ResultMetadata.Columns) 704 return prepared 705 } 706 707 func prepareSelect( 708 t *testing.T, 709 clientConn *client.CqlClientConnection, 710 ks string, 711 table string, 712 version primitive.ProtocolVersion, 713 generator func(int, primitive.ProtocolVersion) int16, 714 compress bool, 715 ) *message.PreparedResult { 716 request := frame.NewFrame( 717 version, 718 generator(1, version), 719 &message.Prepare{ 720 Query: fmt.Sprintf("SELECT v FROM %s.%s WHERE pk = ? AND cc = ?", ks, table), 721 }, 722 ) 723 request.SetCompress(compress) 724 response, err := clientConn.SendAndReceive(request) 725 require.NoError(t, err) 726 require.IsType(t, &message.PreparedResult{}, response.Body.Message) 727 prepared := response.Body.Message.(*message.PreparedResult) 728 assert.Len(t, prepared.VariablesMetadata.Columns, 2) 729 assert.Equal(t, ks, prepared.VariablesMetadata.Columns[0].Keyspace) 730 assert.Equal(t, table, prepared.VariablesMetadata.Columns[0].Table) 731 assert.Equal(t, "pk", prepared.VariablesMetadata.Columns[0].Name) 732 assert.Equal(t, datatype.Int, prepared.VariablesMetadata.Columns[0].Type) 733 assert.Equal(t, ks, prepared.VariablesMetadata.Columns[1].Keyspace) 734 assert.Equal(t, table, prepared.VariablesMetadata.Columns[1].Table) 735 assert.Equal(t, "cc", prepared.VariablesMetadata.Columns[1].Name) 736 assert.Equal(t, datatype.Int, prepared.VariablesMetadata.Columns[1].Type) 737 if version >= primitive.ProtocolVersion4 { 738 assert.Equal(t, prepared.VariablesMetadata.PkIndices, []uint16{0}) 739 } 740 assert.EqualValues(t, 1, prepared.ResultMetadata.ColumnCount) 741 assert.Len(t, prepared.ResultMetadata.Columns, 1) 742 assert.Equal(t, ks, prepared.ResultMetadata.Columns[0].Keyspace) 743 assert.Equal(t, table, prepared.ResultMetadata.Columns[0].Table) 744 assert.Equal(t, "v", prepared.ResultMetadata.Columns[0].Name) 745 assert.Equal(t, datatype.Int, prepared.ResultMetadata.Columns[0].Type) 746 return prepared 747 } 748 749 func insertAndRetrieveLargeData( 750 t *testing.T, 751 clientConn *client.CqlClientConnection, 752 ks string, 753 table string, 754 version primitive.ProtocolVersion, 755 generator func(int, primitive.ProtocolVersion) int16, 756 compress bool, 757 ) { 758 // generate enough data to trigger a multi-segment response in protocol v5 759 for i := 1; i <= 10000; i++ { 760 pk := make([]byte, 4) 761 cc := make([]byte, 4) 762 v := make([]byte, 4) 763 binary.BigEndian.PutUint32(pk, uint32(i)) 764 binary.BigEndian.PutUint32(cc, uint32(i)) 765 binary.BigEndian.PutUint32(v, uint32(i)) 766 request := frame.NewFrame( 767 version, 768 generator(i, version), 769 &message.Query{ 770 Query: fmt.Sprintf("INSERT INTO %s.%s (pk, cc, v) VALUES (?,?,?)", ks, table), 771 Options: &message.QueryOptions{ 772 Consistency: primitive.ConsistencyLevelOne, 773 PositionalValues: []*primitive.Value{ 774 primitive.NewValue(pk), 775 primitive.NewValue(cc), 776 primitive.NewValue(v), 777 }, 778 }, 779 }, 780 ) 781 request.SetCompress(compress) 782 response, err := clientConn.SendAndReceive(request) 783 require.NoError(t, err) 784 require.IsType(t, &message.VoidResult{}, response.Body.Message) 785 } 786 request := frame.NewFrame( 787 version, 788 generator(1, version), 789 &message.Query{ 790 Query: fmt.Sprintf("SELECT * FROM %s.%s", ks, table), 791 Options: &message.QueryOptions{ 792 Consistency: primitive.ConsistencyLevelOne, 793 }, 794 }, 795 ) 796 request.SetCompress(compress) 797 response, err := clientConn.SendAndReceive(request) 798 require.NoError(t, err) 799 require.IsType(t, &message.RowsResult{}, response.Body.Message) 800 result := response.Body.Message.(*message.RowsResult) 801 require.Len(t, result.Data, 10000) 802 }