github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/message/result_prepared_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 message 16 17 import ( 18 "bytes" 19 "testing" 20 21 "github.com/stretchr/testify/assert" 22 23 "github.com/datastax/go-cassandra-native-protocol/datatype" 24 "github.com/datastax/go-cassandra-native-protocol/primitive" 25 ) 26 27 func TestPreparedResult_DeepCopy(t *testing.T) { 28 msg := &PreparedResult{ 29 PreparedQueryId: []byte{0x12}, 30 ResultMetadataId: []byte{0x23}, 31 VariablesMetadata: &VariablesMetadata{ 32 PkIndices: []uint16{0}, 33 Columns: []*ColumnMetadata{ 34 { 35 Keyspace: "ks1", 36 Table: "tb1", 37 Name: "c1", 38 Index: 0, 39 Type: datatype.Ascii, 40 }, 41 }, 42 }, 43 ResultMetadata: &RowsMetadata{ 44 ColumnCount: 1, 45 PagingState: nil, 46 NewResultMetadataId: nil, 47 ContinuousPageNumber: 1, 48 LastContinuousPage: false, 49 Columns: []*ColumnMetadata{ 50 { 51 Keyspace: "ks1", 52 Table: "tb1", 53 Name: "c1", 54 Index: 0, 55 Type: datatype.Ascii, 56 }, 57 }, 58 }, 59 } 60 61 cloned := msg.DeepCopy() 62 assert.Equal(t, msg, cloned) 63 64 cloned.PreparedQueryId = []byte{0x42} 65 cloned.ResultMetadataId = []byte{0x51} 66 cloned.VariablesMetadata = &VariablesMetadata{ 67 PkIndices: []uint16{1}, 68 Columns: []*ColumnMetadata{ 69 { 70 Keyspace: "ks2", 71 Table: "tb2", 72 Name: "c2", 73 Index: 0, 74 Type: datatype.Float, 75 }, 76 { 77 Keyspace: "ks2", 78 Table: "tb2", 79 Name: "c3", 80 Index: 1, 81 Type: datatype.Uuid, 82 }, 83 }, 84 } 85 cloned.ResultMetadata = &RowsMetadata{ 86 ColumnCount: 1, 87 PagingState: []byte{0x22}, 88 NewResultMetadataId: []byte{0x33}, 89 ContinuousPageNumber: 3, 90 LastContinuousPage: true, 91 Columns: []*ColumnMetadata{ 92 { 93 Keyspace: "ks2", 94 Table: "tb2", 95 Name: "c2", 96 Index: 0, 97 Type: datatype.Float, 98 }, 99 { 100 Keyspace: "ks2", 101 Table: "tb2", 102 Name: "c3", 103 Index: 1, 104 Type: datatype.Uuid, 105 }, 106 }, 107 } 108 109 assert.NotEqual(t, msg, cloned) 110 assert.Equal(t, []byte{0x12}, msg.PreparedQueryId) 111 assert.Equal(t, []byte{0x23}, msg.ResultMetadataId) 112 assert.EqualValues(t, 0, msg.VariablesMetadata.PkIndices[0]) 113 assert.Equal(t, "ks1", msg.VariablesMetadata.Columns[0].Keyspace) 114 assert.Equal(t, "tb1", msg.VariablesMetadata.Columns[0].Table) 115 assert.Equal(t, "c1", msg.VariablesMetadata.Columns[0].Name) 116 assert.EqualValues(t, 0, msg.VariablesMetadata.Columns[0].Index) 117 assert.Equal(t, datatype.Ascii, msg.VariablesMetadata.Columns[0].Type) 118 119 assert.EqualValues(t, 1, msg.ResultMetadata.ColumnCount) 120 assert.Nil(t, msg.ResultMetadata.PagingState) 121 assert.Nil(t, msg.ResultMetadata.NewResultMetadataId) 122 assert.EqualValues(t, 1, msg.ResultMetadata.ContinuousPageNumber) 123 assert.False(t, msg.ResultMetadata.LastContinuousPage) 124 assert.Equal(t, "ks1", msg.ResultMetadata.Columns[0].Keyspace) 125 assert.Equal(t, "tb1", msg.ResultMetadata.Columns[0].Table) 126 assert.Equal(t, "c1", msg.ResultMetadata.Columns[0].Name) 127 assert.EqualValues(t, 0, msg.ResultMetadata.Columns[0].Index) 128 assert.Equal(t, datatype.Ascii, msg.ResultMetadata.Columns[0].Type) 129 130 assert.Equal(t, []byte{0x42}, cloned.PreparedQueryId) 131 assert.Equal(t, []byte{0x51}, cloned.ResultMetadataId) 132 assert.EqualValues(t, 1, cloned.VariablesMetadata.PkIndices[0]) 133 assert.Equal(t, "ks2", cloned.VariablesMetadata.Columns[0].Keyspace) 134 assert.Equal(t, "tb2", cloned.VariablesMetadata.Columns[0].Table) 135 assert.Equal(t, "c2", cloned.VariablesMetadata.Columns[0].Name) 136 assert.EqualValues(t, 0, cloned.VariablesMetadata.Columns[0].Index) 137 assert.Equal(t, datatype.Float, cloned.VariablesMetadata.Columns[0].Type) 138 assert.Equal(t, "ks2", cloned.VariablesMetadata.Columns[1].Keyspace) 139 assert.Equal(t, "tb2", cloned.VariablesMetadata.Columns[1].Table) 140 assert.Equal(t, "c3", cloned.VariablesMetadata.Columns[1].Name) 141 assert.EqualValues(t, 1, cloned.VariablesMetadata.Columns[1].Index) 142 assert.Equal(t, datatype.Uuid, cloned.VariablesMetadata.Columns[1].Type) 143 144 assert.EqualValues(t, 1, cloned.ResultMetadata.ColumnCount) 145 assert.Equal(t, []byte{0x22}, cloned.ResultMetadata.PagingState) 146 assert.Equal(t, []byte{0x33}, cloned.ResultMetadata.NewResultMetadataId) 147 assert.EqualValues(t, 3, cloned.ResultMetadata.ContinuousPageNumber) 148 assert.True(t, cloned.ResultMetadata.LastContinuousPage) 149 assert.Equal(t, "ks2", cloned.ResultMetadata.Columns[0].Keyspace) 150 assert.Equal(t, "tb2", cloned.ResultMetadata.Columns[0].Table) 151 assert.Equal(t, "c2", cloned.ResultMetadata.Columns[0].Name) 152 assert.EqualValues(t, 0, cloned.ResultMetadata.Columns[0].Index) 153 assert.Equal(t, datatype.Float, cloned.ResultMetadata.Columns[0].Type) 154 assert.Equal(t, "ks2", cloned.ResultMetadata.Columns[1].Keyspace) 155 assert.Equal(t, "tb2", cloned.ResultMetadata.Columns[1].Table) 156 assert.Equal(t, "c3", cloned.ResultMetadata.Columns[1].Name) 157 assert.EqualValues(t, 1, cloned.ResultMetadata.Columns[1].Index) 158 assert.Equal(t, datatype.Uuid, cloned.ResultMetadata.Columns[1].Type) 159 } 160 161 func TestResultCodec_Encode_Prepared(test *testing.T) { 162 codec := &resultCodec{} 163 // versions < 4 164 for _, version := range primitive.SupportedProtocolVersionsLesserThan(primitive.ProtocolVersion4) { 165 test.Run(version.String(), func(test *testing.T) { 166 tests := []encodeTestCase{ 167 { 168 "prepared result without bound variables", 169 &PreparedResult{PreparedQueryId: []byte{1, 2, 3, 4}}, 170 []byte{ 171 0, 0, 0, 4, // result type 172 0, 4, 1, 2, 3, 4, // prepared id 173 // variables metadata 174 0, 0, 0, 0, // flags 175 0, 0, 0, 0, // column count 176 // result metadata 177 0, 0, 0, 4, // flags (NO_METADATA) 178 0, 0, 0, 0, // column count 179 }, 180 nil, 181 }, 182 { 183 "prepared result with bound variables and no result metadata", 184 &PreparedResult{ 185 PreparedQueryId: []byte{1, 2, 3, 4}, 186 VariablesMetadata: &VariablesMetadata{ 187 Columns: []*ColumnMetadata{ 188 { 189 Keyspace: "ks1", 190 Table: "table1", 191 Name: "col1", 192 Index: 0, 193 Type: datatype.Int, 194 }, 195 }, 196 }, 197 }, 198 []byte{ 199 0, 0, 0, 4, // result type 200 0, 4, 1, 2, 3, 4, // prepared id 201 // variables metadata 202 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 203 0, 0, 0, 1, // column count 204 0, 3, k, s, _1, // global ks 205 0, 6, t, a, b, l, e, _1, // global table 206 0, 4, c, o, l, _1, // col1 name 207 0, 9, // col1 type 208 // result metadata 209 0, 0, 0, 4, // flags (NO_METADATA) 210 0, 0, 0, 0, // column count 211 }, 212 nil, 213 }, 214 { 215 "prepared result with bound variables and result metadata", 216 &PreparedResult{ 217 PreparedQueryId: []byte{1, 2, 3, 4}, 218 VariablesMetadata: &VariablesMetadata{ 219 Columns: []*ColumnMetadata{ 220 { 221 Keyspace: "ks1", 222 Table: "table1", 223 Name: "col1", 224 Index: 0, 225 Type: datatype.Int, 226 }, 227 }, 228 }, 229 ResultMetadata: &RowsMetadata{ 230 ColumnCount: 1, 231 Columns: []*ColumnMetadata{ 232 { 233 Keyspace: "ks1", 234 Table: "table1", 235 Name: "col2", 236 Index: 0, 237 Type: datatype.Varchar, 238 }, 239 }, 240 }, 241 }, 242 []byte{ 243 0, 0, 0, 4, // result type 244 0, 4, 1, 2, 3, 4, // prepared id 245 // variables metadata 246 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 247 0, 0, 0, 1, // column count 248 0, 3, k, s, _1, // global ks 249 0, 6, t, a, b, l, e, _1, // global table 250 0, 4, c, o, l, _1, // col1 name 251 0, 9, // col1 type 252 // result metadata 253 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 254 0, 0, 0, 1, // column count 255 0, 3, k, s, _1, // global ks 256 0, 6, t, a, b, l, e, _1, // global table 257 0, 4, c, o, l, _2, // col1 name 258 0, 13, // col1 type 259 }, 260 nil, 261 }, 262 } 263 for _, tt := range tests { 264 test.Run(tt.name, func(t *testing.T) { 265 dest := &bytes.Buffer{} 266 err := codec.Encode(tt.input, dest, version) 267 assert.Equal(t, tt.expected, dest.Bytes()) 268 assert.Equal(t, tt.err, err) 269 }) 270 } 271 }) 272 } 273 // versions 4, DSE v1 274 for _, version := range []primitive.ProtocolVersion{primitive.ProtocolVersion4, primitive.ProtocolVersionDse1} { 275 test.Run(version.String(), func(test *testing.T) { 276 tests := []encodeTestCase{ 277 { 278 "prepared result without bound variables", 279 &PreparedResult{PreparedQueryId: []byte{1, 2, 3, 4}}, 280 []byte{ 281 0, 0, 0, 4, // result type 282 0, 4, 1, 2, 3, 4, // prepared id 283 // variables metadata 284 0, 0, 0, 0, // flags 285 0, 0, 0, 0, // column count 286 0, 0, 0, 0, // pk count 287 // result metadata 288 0, 0, 0, 4, // flags (NO_METADATA) 289 0, 0, 0, 0, // column count 290 }, 291 nil, 292 }, 293 { 294 "prepared result with bound variables + partition key indices and no result metadata", 295 &PreparedResult{ 296 PreparedQueryId: []byte{1, 2, 3, 4}, 297 VariablesMetadata: &VariablesMetadata{ 298 PkIndices: []uint16{0}, 299 Columns: []*ColumnMetadata{ 300 { 301 Keyspace: "ks1", 302 Table: "table1", 303 Name: "col1", 304 Index: 0, 305 Type: datatype.Int, 306 }, 307 }, 308 }, 309 }, 310 []byte{ 311 0, 0, 0, 4, // result type 312 0, 4, 1, 2, 3, 4, // prepared id 313 // variables metadata 314 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 315 0, 0, 0, 1, // column count 316 0, 0, 0, 1, // pk count 317 0, 0, // pk1 318 0, 3, k, s, _1, // global ks 319 0, 6, t, a, b, l, e, _1, // global table 320 0, 4, c, o, l, _1, // col1 name 321 0, 9, // col1 type 322 // result metadata 323 0, 0, 0, 4, // flags (NO_METADATA) 324 0, 0, 0, 0, // column count 325 }, 326 nil, 327 }, 328 { 329 "prepared result with bound variables + partition key indices and result metadata", 330 &PreparedResult{ 331 PreparedQueryId: []byte{1, 2, 3, 4}, 332 VariablesMetadata: &VariablesMetadata{ 333 PkIndices: []uint16{0}, 334 Columns: []*ColumnMetadata{ 335 { 336 Keyspace: "ks1", 337 Table: "table1", 338 Name: "col1", 339 Index: 0, 340 Type: datatype.Int, 341 }, 342 }, 343 }, 344 ResultMetadata: &RowsMetadata{ 345 ColumnCount: 1, 346 Columns: []*ColumnMetadata{ 347 { 348 Keyspace: "ks1", 349 Table: "table1", 350 Name: "col2", 351 Index: 0, 352 Type: datatype.Varchar, 353 }, 354 }, 355 }, 356 }, 357 []byte{ 358 0, 0, 0, 4, // result type 359 0, 4, 1, 2, 3, 4, // prepared id 360 // variables metadata 361 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 362 0, 0, 0, 1, // column count 363 0, 0, 0, 1, // pk count 364 0, 0, // pk1 365 0, 3, k, s, _1, // global ks 366 0, 6, t, a, b, l, e, _1, // global table 367 0, 4, c, o, l, _1, // col1 name 368 0, 9, // col1 type 369 // result metadata 370 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 371 0, 0, 0, 1, // column count 372 0, 3, k, s, _1, // global ks 373 0, 6, t, a, b, l, e, _1, // global table 374 0, 4, c, o, l, _2, // col1 name 375 0, 13, // col1 type 376 }, 377 nil, 378 }, 379 } 380 for _, tt := range tests { 381 test.Run(tt.name, func(t *testing.T) { 382 dest := &bytes.Buffer{} 383 err := codec.Encode(tt.input, dest, version) 384 assert.Equal(t, tt.expected, dest.Bytes()) 385 assert.Equal(t, tt.err, err) 386 }) 387 } 388 }) 389 } 390 // versions 5, DSE v2 391 for _, version := range []primitive.ProtocolVersion{primitive.ProtocolVersion5, primitive.ProtocolVersionDse2} { 392 test.Run(version.String(), func(test *testing.T) { 393 tests := []encodeTestCase{ 394 { 395 "prepared result without bound variables", 396 &PreparedResult{ 397 PreparedQueryId: []byte{1, 2, 3, 4}, 398 ResultMetadataId: []byte{5, 6, 7, 8}, 399 }, 400 []byte{ 401 0, 0, 0, 4, // result type 402 0, 4, 1, 2, 3, 4, // prepared id 403 0, 4, 5, 6, 7, 8, // result metadata id 404 // variables metadata 405 0, 0, 0, 0, // flags 406 0, 0, 0, 0, // column count 407 0, 0, 0, 0, // pk count 408 // result metadata 409 0, 0, 0, 4, // flags (NO_METADATA) 410 0, 0, 0, 0, // column count 411 }, 412 nil, 413 }, 414 { 415 "prepared result with bound variables + partition key indices and no result metadata", 416 &PreparedResult{ 417 PreparedQueryId: []byte{1, 2, 3, 4}, 418 ResultMetadataId: []byte{5, 6, 7, 8}, 419 VariablesMetadata: &VariablesMetadata{ 420 PkIndices: []uint16{0}, 421 Columns: []*ColumnMetadata{ 422 { 423 Keyspace: "ks1", 424 Table: "table1", 425 Name: "col1", 426 Index: 0, 427 Type: datatype.Int, 428 }, 429 }, 430 }, 431 }, 432 []byte{ 433 0, 0, 0, 4, // result type 434 0, 4, 1, 2, 3, 4, // prepared id 435 0, 4, 5, 6, 7, 8, // result metadata id 436 // variables metadata 437 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 438 0, 0, 0, 1, // column count 439 0, 0, 0, 1, // pk count 440 0, 0, // pk1 441 0, 3, k, s, _1, // global ks 442 0, 6, t, a, b, l, e, _1, // global table 443 0, 4, c, o, l, _1, // col1 name 444 0, 9, // col1 type 445 // result metadata 446 0, 0, 0, 4, // flags (NO_METADATA) 447 0, 0, 0, 0, // column count 448 }, 449 nil, 450 }, 451 { 452 "prepared result with bound variables + partition key indices and result metadata", 453 &PreparedResult{ 454 PreparedQueryId: []byte{1, 2, 3, 4}, 455 ResultMetadataId: []byte{5, 6, 7, 8}, 456 VariablesMetadata: &VariablesMetadata{ 457 PkIndices: []uint16{0}, 458 Columns: []*ColumnMetadata{ 459 { 460 Keyspace: "ks1", 461 Table: "table1", 462 Name: "col1", 463 Index: 0, 464 Type: datatype.Int, 465 }, 466 }, 467 }, 468 ResultMetadata: &RowsMetadata{ 469 ColumnCount: 1, 470 Columns: []*ColumnMetadata{ 471 { 472 Keyspace: "ks1", 473 Table: "table1", 474 Name: "col2", 475 Index: 0, 476 Type: datatype.Varchar, 477 }, 478 }, 479 }, 480 }, 481 []byte{ 482 0, 0, 0, 4, // result type 483 0, 4, 1, 2, 3, 4, // prepared id 484 0, 4, 5, 6, 7, 8, // result metadata id 485 // variables metadata 486 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 487 0, 0, 0, 1, // column count 488 0, 0, 0, 1, // pk count 489 0, 0, // pk1 490 0, 3, k, s, _1, // global ks 491 0, 6, t, a, b, l, e, _1, // global table 492 0, 4, c, o, l, _1, // col1 name 493 0, 9, // col1 type 494 // result metadata 495 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 496 0, 0, 0, 1, // column count 497 0, 3, k, s, _1, // global ks 498 0, 6, t, a, b, l, e, _1, // global table 499 0, 4, c, o, l, _2, // col1 name 500 0, 13, // col1 type 501 }, 502 nil, 503 }, 504 } 505 for _, tt := range tests { 506 test.Run(tt.name, func(t *testing.T) { 507 dest := &bytes.Buffer{} 508 err := codec.Encode(tt.input, dest, version) 509 assert.Equal(t, tt.expected, dest.Bytes()) 510 assert.Equal(t, tt.err, err) 511 }) 512 } 513 }) 514 } 515 } 516 517 func TestResultCodec_EncodedLength_Prepared(test *testing.T) { 518 codec := &resultCodec{} 519 // versions < 4 520 for _, version := range primitive.SupportedProtocolVersionsLesserThan(primitive.ProtocolVersion4) { 521 test.Run(version.String(), func(test *testing.T) { 522 tests := []encodedLengthTestCase{ 523 { 524 "prepared result without bound variables", 525 &PreparedResult{PreparedQueryId: []byte{1, 2, 3, 4}}, 526 primitive.LengthOfInt + // result type 527 primitive.LengthOfShortBytes([]byte{1, 2, 3, 4}) + 528 primitive.LengthOfInt + // flags 529 primitive.LengthOfInt + // column count 530 primitive.LengthOfInt + // flags 531 primitive.LengthOfInt, // column count 532 nil, 533 }, 534 { 535 "prepared result with bound variables and no result metadata", 536 &PreparedResult{ 537 PreparedQueryId: []byte{1, 2, 3, 4}, 538 VariablesMetadata: &VariablesMetadata{ 539 Columns: []*ColumnMetadata{ 540 { 541 Keyspace: "ks1", 542 Table: "table1", 543 Name: "col1", 544 Index: 0, 545 Type: datatype.Int, 546 }, 547 }, 548 }, 549 }, 550 primitive.LengthOfInt + // result type 551 primitive.LengthOfShortBytes([]byte{1, 2, 3, 4}) + 552 primitive.LengthOfInt + // flags 553 primitive.LengthOfInt + // column count 554 primitive.LengthOfString("ks1") + 555 primitive.LengthOfString("table1") + 556 primitive.LengthOfString("col1") + 557 primitive.LengthOfShort + // col type 558 primitive.LengthOfInt + // flags 559 primitive.LengthOfInt, // column count 560 nil, 561 }, 562 { 563 "prepared result with bound variables and result metadata", 564 &PreparedResult{ 565 PreparedQueryId: []byte{1, 2, 3, 4}, 566 VariablesMetadata: &VariablesMetadata{ 567 Columns: []*ColumnMetadata{ 568 { 569 Keyspace: "ks1", 570 Table: "table1", 571 Name: "col1", 572 Index: 0, 573 Type: datatype.Int, 574 }, 575 }, 576 }, 577 ResultMetadata: &RowsMetadata{ 578 ColumnCount: 1, 579 Columns: []*ColumnMetadata{ 580 { 581 Keyspace: "ks1", 582 Table: "table1", 583 Name: "col2", 584 Index: 0, 585 Type: datatype.Varchar, 586 }, 587 }, 588 }, 589 }, 590 primitive.LengthOfInt + // result type 591 primitive.LengthOfShortBytes([]byte{1, 2, 3, 4}) + 592 primitive.LengthOfInt + // flags 593 primitive.LengthOfInt + // column count 594 primitive.LengthOfString("ks1") + 595 primitive.LengthOfString("table1") + 596 primitive.LengthOfString("col1") + 597 primitive.LengthOfShort + // col type 598 primitive.LengthOfInt + // flags 599 primitive.LengthOfInt + // column count 600 primitive.LengthOfString("ks1") + 601 primitive.LengthOfString("table1") + 602 primitive.LengthOfString("col2") + 603 primitive.LengthOfShort, // col type 604 nil, 605 }, 606 } 607 for _, tt := range tests { 608 test.Run(tt.name, func(t *testing.T) { 609 actual, err := codec.EncodedLength(tt.input, version) 610 assert.Equal(t, tt.expected, actual) 611 assert.Equal(t, tt.err, err) 612 }) 613 } 614 }) 615 } 616 // versions 4, DSE v1 617 for _, version := range []primitive.ProtocolVersion{primitive.ProtocolVersion4, primitive.ProtocolVersionDse1} { 618 test.Run(version.String(), func(test *testing.T) { 619 tests := []encodedLengthTestCase{ 620 { 621 "prepared result without bound variables", 622 &PreparedResult{PreparedQueryId: []byte{1, 2, 3, 4}}, 623 primitive.LengthOfInt + // result type 624 primitive.LengthOfShortBytes([]byte{1, 2, 3, 4}) + 625 primitive.LengthOfInt + // flags 626 primitive.LengthOfInt + // column count 627 primitive.LengthOfInt + // pk count 628 primitive.LengthOfInt + // flags 629 primitive.LengthOfInt, // column count 630 nil, 631 }, 632 { 633 "prepared result with bound variables + partition key indices and no result metadata", 634 &PreparedResult{ 635 PreparedQueryId: []byte{1, 2, 3, 4}, 636 VariablesMetadata: &VariablesMetadata{ 637 PkIndices: []uint16{0}, 638 Columns: []*ColumnMetadata{ 639 { 640 Keyspace: "ks1", 641 Table: "table1", 642 Name: "col1", 643 Index: 0, 644 Type: datatype.Int, 645 }, 646 }, 647 }, 648 }, 649 primitive.LengthOfInt + // result type 650 primitive.LengthOfShortBytes([]byte{1, 2, 3, 4}) + 651 primitive.LengthOfInt + // flags 652 primitive.LengthOfInt + // column count 653 primitive.LengthOfInt + // pk count 654 primitive.LengthOfShort + // pk1 655 primitive.LengthOfString("ks1") + 656 primitive.LengthOfString("table1") + 657 primitive.LengthOfString("col1") + 658 primitive.LengthOfShort + // col type 659 primitive.LengthOfInt + // flags 660 primitive.LengthOfInt, // column count 661 nil, 662 }, 663 { 664 "prepared result with bound variables + partition key indices and result metadata", 665 &PreparedResult{ 666 PreparedQueryId: []byte{1, 2, 3, 4}, 667 VariablesMetadata: &VariablesMetadata{ 668 PkIndices: []uint16{0}, 669 Columns: []*ColumnMetadata{ 670 { 671 Keyspace: "ks1", 672 Table: "table1", 673 Name: "col1", 674 Index: 0, 675 Type: datatype.Int, 676 }, 677 }, 678 }, 679 ResultMetadata: &RowsMetadata{ 680 ColumnCount: 1, 681 Columns: []*ColumnMetadata{ 682 { 683 Keyspace: "ks1", 684 Table: "table1", 685 Name: "col2", 686 Index: 0, 687 Type: datatype.Varchar, 688 }, 689 }, 690 }, 691 }, 692 primitive.LengthOfInt + // result type 693 primitive.LengthOfShortBytes([]byte{1, 2, 3, 4}) + 694 primitive.LengthOfInt + // flags 695 primitive.LengthOfInt + // column count 696 primitive.LengthOfInt + // pk count 697 primitive.LengthOfShort + // pk1 698 primitive.LengthOfString("ks1") + 699 primitive.LengthOfString("table1") + 700 primitive.LengthOfString("col1") + 701 primitive.LengthOfShort + // col type 702 primitive.LengthOfInt + // flags 703 primitive.LengthOfInt + // column count 704 primitive.LengthOfString("ks1") + 705 primitive.LengthOfString("table1") + 706 primitive.LengthOfString("col2") + 707 primitive.LengthOfShort, // col type 708 nil, 709 }, 710 } 711 for _, tt := range tests { 712 test.Run(tt.name, func(t *testing.T) { 713 actual, err := codec.EncodedLength(tt.input, version) 714 assert.Equal(t, tt.expected, actual) 715 assert.Equal(t, tt.err, err) 716 }) 717 } 718 }) 719 } 720 // versions 5, DSE v2 721 for _, version := range []primitive.ProtocolVersion{primitive.ProtocolVersion5, primitive.ProtocolVersionDse2} { 722 test.Run(version.String(), func(test *testing.T) { 723 tests := []encodedLengthTestCase{ 724 { 725 "prepared result without bound variables", 726 &PreparedResult{ 727 PreparedQueryId: []byte{1, 2, 3, 4}, 728 ResultMetadataId: []byte{5, 6, 7, 8}, 729 }, 730 primitive.LengthOfInt + // result type 731 primitive.LengthOfShortBytes([]byte{1, 2, 3, 4}) + 732 primitive.LengthOfShortBytes([]byte{5, 6, 7, 8}) + 733 primitive.LengthOfInt + // flags 734 primitive.LengthOfInt + // column count 735 primitive.LengthOfInt + // pk count 736 primitive.LengthOfInt + // flags 737 primitive.LengthOfInt, // column count 738 nil, 739 }, 740 { 741 "prepared result with bound variables + partition key indices and no result metadata", 742 &PreparedResult{ 743 PreparedQueryId: []byte{1, 2, 3, 4}, 744 ResultMetadataId: []byte{5, 6, 7, 8}, 745 VariablesMetadata: &VariablesMetadata{ 746 PkIndices: []uint16{0}, 747 Columns: []*ColumnMetadata{ 748 { 749 Keyspace: "ks1", 750 Table: "table1", 751 Name: "col1", 752 Index: 0, 753 Type: datatype.Int, 754 }, 755 }, 756 }, 757 }, 758 primitive.LengthOfInt + // result type 759 primitive.LengthOfShortBytes([]byte{1, 2, 3, 4}) + 760 primitive.LengthOfShortBytes([]byte{5, 6, 7, 8}) + 761 primitive.LengthOfInt + // flags 762 primitive.LengthOfInt + // column count 763 primitive.LengthOfInt + // pk count 764 primitive.LengthOfShort + // pk1 765 primitive.LengthOfString("ks1") + 766 primitive.LengthOfString("table1") + 767 primitive.LengthOfString("col1") + 768 primitive.LengthOfShort + // col type 769 primitive.LengthOfInt + // flags 770 primitive.LengthOfInt, // column count 771 nil, 772 }, 773 { 774 "prepared result with bound variables + partition key indices and result metadata", 775 &PreparedResult{ 776 PreparedQueryId: []byte{1, 2, 3, 4}, 777 ResultMetadataId: []byte{5, 6, 7, 8}, 778 VariablesMetadata: &VariablesMetadata{ 779 PkIndices: []uint16{0}, 780 Columns: []*ColumnMetadata{ 781 { 782 Keyspace: "ks1", 783 Table: "table1", 784 Name: "col1", 785 Index: 0, 786 Type: datatype.Int, 787 }, 788 }, 789 }, 790 ResultMetadata: &RowsMetadata{ 791 ColumnCount: 1, 792 Columns: []*ColumnMetadata{ 793 { 794 Keyspace: "ks1", 795 Table: "table1", 796 Name: "col2", 797 Index: 0, 798 Type: datatype.Varchar, 799 }, 800 }, 801 }, 802 }, 803 primitive.LengthOfInt + // result type 804 primitive.LengthOfShortBytes([]byte{1, 2, 3, 4}) + 805 primitive.LengthOfShortBytes([]byte{5, 6, 7, 8}) + 806 primitive.LengthOfInt + // flags 807 primitive.LengthOfInt + // column count 808 primitive.LengthOfInt + // pk count 809 primitive.LengthOfShort + // pk1 810 primitive.LengthOfString("ks1") + 811 primitive.LengthOfString("table1") + 812 primitive.LengthOfString("col1") + 813 primitive.LengthOfShort + // col type 814 primitive.LengthOfInt + // flags 815 primitive.LengthOfInt + // column count 816 primitive.LengthOfString("ks1") + 817 primitive.LengthOfString("table1") + 818 primitive.LengthOfString("col2") + 819 primitive.LengthOfShort, // col type 820 nil, 821 }, 822 } 823 for _, tt := range tests { 824 test.Run(tt.name, func(t *testing.T) { 825 actual, err := codec.EncodedLength(tt.input, version) 826 assert.Equal(t, tt.expected, actual) 827 assert.Equal(t, tt.err, err) 828 }) 829 } 830 }) 831 } 832 } 833 834 func TestResultCodec_Decode_Prepared(test *testing.T) { 835 codec := &resultCodec{} 836 // versions < 4 837 for _, version := range primitive.SupportedProtocolVersionsLesserThan(primitive.ProtocolVersion4) { 838 test.Run(version.String(), func(test *testing.T) { 839 tests := []decodeTestCase{ 840 { 841 "prepared result without bound variables", 842 []byte{ 843 0, 0, 0, 4, // result type 844 0, 4, 1, 2, 3, 4, // prepared id 845 // variables metadata 846 0, 0, 0, 0, // flags 847 0, 0, 0, 0, // column count 848 0, 0, 0, 4, // flags (NO_METADATA) 849 0, 0, 0, 0, // column count 850 }, 851 &PreparedResult{ 852 PreparedQueryId: []byte{1, 2, 3, 4}, 853 VariablesMetadata: &VariablesMetadata{}, 854 ResultMetadata: &RowsMetadata{}, 855 }, 856 nil, 857 }, 858 { 859 "prepared result with bound variables and no result metadata", 860 []byte{ 861 0, 0, 0, 4, // result type 862 0, 4, 1, 2, 3, 4, // prepared id 863 // variables metadata 864 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 865 0, 0, 0, 1, // column count 866 0, 3, k, s, _1, // global ks 867 0, 6, t, a, b, l, e, _1, // global table 868 0, 4, c, o, l, _1, // col1 name 869 0, 9, // col1 type 870 // result metadata 871 0, 0, 0, 4, // flags (NO_METADATA) 872 0, 0, 0, 0, // column count 873 }, 874 &PreparedResult{ 875 PreparedQueryId: []byte{1, 2, 3, 4}, 876 VariablesMetadata: &VariablesMetadata{ 877 Columns: []*ColumnMetadata{ 878 { 879 Keyspace: "ks1", 880 Table: "table1", 881 Name: "col1", 882 Index: 0, 883 Type: datatype.Int, 884 }, 885 }, 886 }, 887 ResultMetadata: &RowsMetadata{}, 888 }, 889 nil, 890 }, 891 { 892 "prepared result with bound variables and result metadata", 893 []byte{ 894 0, 0, 0, 4, // result type 895 0, 4, 1, 2, 3, 4, // prepared id 896 // variables metadata 897 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 898 0, 0, 0, 1, // column count 899 0, 3, k, s, _1, // global ks 900 0, 6, t, a, b, l, e, _1, // global table 901 0, 4, c, o, l, _1, // col1 name 902 0, 9, // col1 type 903 // result metadata 904 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 905 0, 0, 0, 1, // column count 906 0, 3, k, s, _1, // global ks 907 0, 6, t, a, b, l, e, _1, // global table 908 0, 4, c, o, l, _2, // col1 name 909 0, 13, // col1 type 910 }, 911 &PreparedResult{ 912 PreparedQueryId: []byte{1, 2, 3, 4}, 913 VariablesMetadata: &VariablesMetadata{ 914 Columns: []*ColumnMetadata{ 915 { 916 Keyspace: "ks1", 917 Table: "table1", 918 Name: "col1", 919 Index: 0, 920 Type: datatype.Int, 921 }, 922 }, 923 }, 924 ResultMetadata: &RowsMetadata{ 925 ColumnCount: 1, 926 Columns: []*ColumnMetadata{ 927 { 928 Keyspace: "ks1", 929 Table: "table1", 930 Name: "col2", 931 Index: 0, 932 Type: datatype.Varchar, 933 }, 934 }, 935 }, 936 }, 937 nil, 938 }, 939 } 940 for _, tt := range tests { 941 test.Run(tt.name, func(t *testing.T) { 942 source := bytes.NewBuffer(tt.input) 943 actual, err := codec.Decode(source, version) 944 assert.Equal(t, tt.expected, actual) 945 assert.Equal(t, tt.err, err) 946 }) 947 } 948 }) 949 } 950 // versions 4, DSE v1 951 for _, version := range []primitive.ProtocolVersion{primitive.ProtocolVersion4, primitive.ProtocolVersionDse1} { 952 test.Run(version.String(), func(test *testing.T) { 953 tests := []decodeTestCase{ 954 { 955 "prepared result without bound variables", 956 []byte{ 957 0, 0, 0, 4, // result type 958 0, 4, 1, 2, 3, 4, // prepared id 959 // variables metadata 960 0, 0, 0, 0, // flags 961 0, 0, 0, 0, // column count 962 0, 0, 0, 0, // pk count 963 // result metadata 964 0, 0, 0, 4, // flags (NO_METADATA) 965 0, 0, 0, 0, // column count 966 }, 967 &PreparedResult{ 968 PreparedQueryId: []byte{1, 2, 3, 4}, 969 VariablesMetadata: &VariablesMetadata{}, 970 ResultMetadata: &RowsMetadata{}, 971 }, 972 nil, 973 }, 974 { 975 "prepared result with bound variables + partition key indices and no result metadata", 976 []byte{ 977 0, 0, 0, 4, // result type 978 0, 4, 1, 2, 3, 4, // prepared id 979 // variables metadata 980 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 981 0, 0, 0, 1, // column count 982 0, 0, 0, 1, // pk count 983 0, 0, // pk1 984 0, 3, k, s, _1, // global ks 985 0, 6, t, a, b, l, e, _1, // global table 986 0, 4, c, o, l, _1, // col1 name 987 0, 9, // col1 type 988 // result metadata 989 0, 0, 0, 4, // flags (NO_METADATA) 990 0, 0, 0, 0, // column count 991 }, 992 &PreparedResult{ 993 PreparedQueryId: []byte{1, 2, 3, 4}, 994 VariablesMetadata: &VariablesMetadata{ 995 PkIndices: []uint16{0}, 996 Columns: []*ColumnMetadata{ 997 { 998 Keyspace: "ks1", 999 Table: "table1", 1000 Name: "col1", 1001 Index: 0, 1002 Type: datatype.Int, 1003 }, 1004 }, 1005 }, 1006 ResultMetadata: &RowsMetadata{}, 1007 }, 1008 nil, 1009 }, 1010 { 1011 "prepared result with bound variables + partition key indices and result metadata", 1012 []byte{ 1013 0, 0, 0, 4, // result type 1014 0, 4, 1, 2, 3, 4, // prepared id 1015 // variables metadata 1016 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 1017 0, 0, 0, 1, // column count 1018 0, 0, 0, 1, // pk count 1019 0, 0, // pk1 1020 0, 3, k, s, _1, // global ks 1021 0, 6, t, a, b, l, e, _1, // global table 1022 0, 4, c, o, l, _1, // col1 name 1023 0, 9, // col1 type 1024 // result metadata 1025 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 1026 0, 0, 0, 1, // column count 1027 0, 3, k, s, _1, // global ks 1028 0, 6, t, a, b, l, e, _1, // global table 1029 0, 4, c, o, l, _2, // col1 name 1030 0, 13, // col1 type 1031 }, 1032 &PreparedResult{ 1033 PreparedQueryId: []byte{1, 2, 3, 4}, 1034 VariablesMetadata: &VariablesMetadata{ 1035 PkIndices: []uint16{0}, 1036 Columns: []*ColumnMetadata{ 1037 { 1038 Keyspace: "ks1", 1039 Table: "table1", 1040 Name: "col1", 1041 Index: 0, 1042 Type: datatype.Int, 1043 }, 1044 }, 1045 }, 1046 ResultMetadata: &RowsMetadata{ 1047 ColumnCount: 1, 1048 Columns: []*ColumnMetadata{ 1049 { 1050 Keyspace: "ks1", 1051 Table: "table1", 1052 Name: "col2", 1053 Index: 0, 1054 Type: datatype.Varchar, 1055 }, 1056 }, 1057 }, 1058 }, 1059 nil, 1060 }, 1061 } 1062 for _, tt := range tests { 1063 test.Run(tt.name, func(t *testing.T) { 1064 source := bytes.NewBuffer(tt.input) 1065 actual, err := codec.Decode(source, version) 1066 assert.Equal(t, tt.expected, actual) 1067 assert.Equal(t, tt.err, err) 1068 }) 1069 } 1070 }) 1071 } 1072 // versions 5, DSE v2 1073 for _, version := range []primitive.ProtocolVersion{primitive.ProtocolVersion5, primitive.ProtocolVersionDse2} { 1074 test.Run(version.String(), func(test *testing.T) { 1075 tests := []decodeTestCase{ 1076 { 1077 "prepared result without bound variables", 1078 []byte{ 1079 0, 0, 0, 4, // result type 1080 0, 4, 1, 2, 3, 4, // prepared id 1081 0, 4, 5, 6, 7, 8, // result metadata id 1082 // variables metadata 1083 0, 0, 0, 0, // flags 1084 0, 0, 0, 0, // column count 1085 0, 0, 0, 0, // pk count 1086 // result metadata 1087 0, 0, 0, 4, // flags (NO_METADATA) 1088 0, 0, 0, 0, // column count 1089 }, 1090 &PreparedResult{ 1091 PreparedQueryId: []byte{1, 2, 3, 4}, 1092 ResultMetadataId: []byte{5, 6, 7, 8}, 1093 VariablesMetadata: &VariablesMetadata{}, 1094 ResultMetadata: &RowsMetadata{}, 1095 }, 1096 nil, 1097 }, 1098 { 1099 "prepared result with bound variables partition key indices and no result metadata", 1100 []byte{ 1101 0, 0, 0, 4, // result type 1102 0, 4, 1, 2, 3, 4, // prepared id 1103 0, 4, 5, 6, 7, 8, // result metadata id 1104 // variables metadata 1105 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 1106 0, 0, 0, 1, // column count 1107 0, 0, 0, 1, // pk count 1108 0, 0, // pk1 1109 0, 3, k, s, _1, // global ks 1110 0, 6, t, a, b, l, e, _1, // global table 1111 0, 4, c, o, l, _1, // col1 name 1112 0, 9, // col1 type 1113 // result metadata 1114 0, 0, 0, 4, // flags (NO_METADATA) 1115 0, 0, 0, 0, // column count 1116 }, 1117 &PreparedResult{ 1118 PreparedQueryId: []byte{1, 2, 3, 4}, 1119 ResultMetadataId: []byte{5, 6, 7, 8}, 1120 VariablesMetadata: &VariablesMetadata{ 1121 PkIndices: []uint16{0}, 1122 Columns: []*ColumnMetadata{ 1123 { 1124 Keyspace: "ks1", 1125 Table: "table1", 1126 Name: "col1", 1127 Index: 0, 1128 Type: datatype.Int, 1129 }, 1130 }, 1131 }, 1132 ResultMetadata: &RowsMetadata{}, 1133 }, 1134 nil, 1135 }, 1136 { 1137 "prepared result with bound variables + partition key indices and result metadata", 1138 []byte{ 1139 0, 0, 0, 4, // result type 1140 0, 4, 1, 2, 3, 4, // prepared id 1141 0, 4, 5, 6, 7, 8, // result metadata id 1142 // variables metadata 1143 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 1144 0, 0, 0, 1, // column count 1145 0, 0, 0, 1, // pk count 1146 0, 0, // pk1 1147 0, 3, k, s, _1, // global ks 1148 0, 6, t, a, b, l, e, _1, // global table 1149 0, 4, c, o, l, _1, // col1 name 1150 0, 9, // col1 type 1151 // result metadata 1152 0, 0, 0, 1, // flags (GLOBAL_TABLE_SPEC) 1153 0, 0, 0, 1, // column count 1154 0, 3, k, s, _1, // global ks 1155 0, 6, t, a, b, l, e, _1, // global table 1156 0, 4, c, o, l, _2, // col1 name 1157 0, 13, // col1 type 1158 }, 1159 &PreparedResult{ 1160 PreparedQueryId: []byte{1, 2, 3, 4}, 1161 ResultMetadataId: []byte{5, 6, 7, 8}, 1162 VariablesMetadata: &VariablesMetadata{ 1163 PkIndices: []uint16{0}, 1164 Columns: []*ColumnMetadata{ 1165 { 1166 Keyspace: "ks1", 1167 Table: "table1", 1168 Name: "col1", 1169 Index: 0, 1170 Type: datatype.Int, 1171 }, 1172 }, 1173 }, 1174 ResultMetadata: &RowsMetadata{ 1175 ColumnCount: 1, 1176 Columns: []*ColumnMetadata{ 1177 { 1178 Keyspace: "ks1", 1179 Table: "table1", 1180 Name: "col2", 1181 Index: 0, 1182 Type: datatype.Varchar, 1183 }, 1184 }, 1185 }, 1186 }, 1187 nil, 1188 }, 1189 } 1190 for _, tt := range tests { 1191 test.Run(tt.name, func(t *testing.T) { 1192 source := bytes.NewBuffer(tt.input) 1193 actual, err := codec.Decode(source, version) 1194 assert.Equal(t, tt.expected, actual) 1195 assert.Equal(t, tt.err, err) 1196 }) 1197 } 1198 }) 1199 } 1200 }