github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/internal/table/scanner/scanner_data_test.go (about) 1 package scanner 2 3 import ( 4 "fmt" 5 "strconv" 6 "time" 7 8 "github.com/ydb-platform/ydb-go-genproto/protos/Ydb" 9 10 "github.com/ydb-platform/ydb-go-sdk/v3/table/result/indexed" 11 "github.com/ydb-platform/ydb-go-sdk/v3/table/types" 12 ) 13 14 type column struct { 15 name string 16 typeID Ydb.Type_PrimitiveTypeId 17 optional bool 18 scanner bool 19 ydbvalue bool 20 testDefault bool 21 nilValue bool 22 } 23 24 type intIncScanner int64 25 26 func (s *intIncScanner) Scan(src interface{}) error { 27 v, ok := src.(int64) 28 if !ok { 29 return fmt.Errorf("wrong type: %T, exp: int64", src) 30 } 31 *s = intIncScanner(v + 10) 32 33 return nil 34 } 35 36 type dateScanner time.Time 37 38 func (s *dateScanner) Scan(src interface{}) error { 39 v, ok := src.(time.Time) 40 if !ok { 41 return fmt.Errorf("wrong type: %T, exp: time.Time", src) 42 } 43 *s = dateScanner(v) 44 45 return nil 46 } 47 48 var scannerData = []struct { 49 name string 50 count int 51 columns []*column 52 values []indexed.RequiredOrOptional 53 setColumns []string 54 setColumnIndexes []int 55 }{ 56 { 57 name: "Scan UUID, DATE", 58 count: 10, 59 columns: []*column{{ 60 name: "uuid", 61 typeID: Ydb.Type_UUID, 62 }, { 63 name: "date", 64 typeID: Ydb.Type_DATE, 65 }}, 66 values: []indexed.RequiredOrOptional{new([16]byte), new(time.Time)}, 67 }, 68 { 69 name: "Scan JSON, DOUBLE", 70 count: 20, 71 columns: []*column{{ 72 name: "json", 73 typeID: Ydb.Type_JSON, 74 }, { 75 name: "double", 76 typeID: Ydb.Type_DOUBLE, 77 }}, 78 values: []indexed.RequiredOrOptional{new([]byte), new(float64)}, 79 }, 80 { 81 name: "Scan INT8, INT16, INT32", 82 count: 210, 83 columns: []*column{{ 84 name: "int8", 85 typeID: Ydb.Type_INT8, 86 }, { 87 name: "int16", 88 typeID: Ydb.Type_INT16, 89 }, { 90 name: "int32", 91 typeID: Ydb.Type_INT32, 92 }}, 93 values: []indexed.RequiredOrOptional{new(int8), new(int16), new(int32)}, 94 setColumns: []string{"int8", "int16", "int32"}, 95 }, 96 { 97 name: "Scan YSON, DOUBLE. Zero rows in the result", 98 count: 0, 99 columns: []*column{{ 100 name: "yson", 101 typeID: Ydb.Type_YSON, 102 }, { 103 name: "double", 104 typeID: Ydb.Type_DOUBLE, 105 }}, 106 values: []indexed.RequiredOrOptional{new([]byte), new(float64)}, 107 }, 108 { 109 name: "Scan JSON, FLOAT", 110 count: 1000, 111 columns: []*column{{ 112 name: "jsondocument", 113 typeID: Ydb.Type_JSON_DOCUMENT, 114 }, { 115 name: "float", 116 typeID: Ydb.Type_FLOAT, 117 }}, 118 values: []indexed.RequiredOrOptional{new([]byte), new(float32)}, 119 }, 120 { 121 name: "Scan UINT8, UINT16, UINT32", 122 count: 200, 123 columns: []*column{{ 124 name: "uint8", 125 typeID: Ydb.Type_UINT8, 126 }, { 127 name: "uint16", 128 typeID: Ydb.Type_UINT16, 129 }, { 130 name: "uint32", 131 typeID: Ydb.Type_UINT32, 132 }}, 133 values: []indexed.RequiredOrOptional{new(uint8), new(uint16), new(uint32)}, 134 }, 135 { 136 name: "Scan DYNUMBER, Type_UTF8, Type_STRING", 137 count: 5, 138 columns: []*column{{ 139 name: "dynumber", 140 typeID: Ydb.Type_DYNUMBER, 141 }, { 142 name: "utf8", 143 typeID: Ydb.Type_UTF8, 144 }, { 145 name: "string", 146 typeID: Ydb.Type_STRING, 147 }}, 148 values: []indexed.RequiredOrOptional{new(string), new(string), new([]byte)}, 149 }, 150 { 151 name: "Scan float32, int64, uint64 and skip other columns", 152 count: 15, 153 columns: []*column{{ 154 name: "float32", 155 typeID: Ydb.Type_FLOAT, 156 }, { 157 name: "utf8", 158 typeID: Ydb.Type_UTF8, 159 }, { 160 name: "int64", 161 typeID: Ydb.Type_INT64, 162 }, { 163 name: "string", 164 typeID: Ydb.Type_STRING, 165 }, { 166 name: "uint64", 167 typeID: Ydb.Type_UINT64, 168 }}, 169 values: []indexed.RequiredOrOptional{new(float32), new(int64), new(uint64)}, 170 setColumns: []string{"float32", "int64", "uint64"}, 171 setColumnIndexes: []int{0, 2, 4}, 172 }, 173 { 174 name: "Scan TIMESTAMP, BOOL, INTERVAL in a different order", 175 count: 20, 176 columns: []*column{{ 177 name: "timestamp", 178 typeID: Ydb.Type_TIMESTAMP, 179 }, { 180 name: "bool", 181 typeID: Ydb.Type_BOOL, 182 }, { 183 name: "interval", 184 typeID: Ydb.Type_INTERVAL, 185 }}, 186 values: []indexed.RequiredOrOptional{new(bool), new(time.Duration), new(time.Time)}, 187 setColumns: []string{"bool", "interval", "timestamp"}, 188 setColumnIndexes: []int{1, 2, 0}, 189 }, 190 { 191 name: "ScanWithDefaults for required columns TZ_TIMESTAMP, TZ_DATE, TZ_DATETIME in a different order", 192 count: 300, 193 columns: []*column{{ 194 name: "tztimestamp", 195 typeID: Ydb.Type_TZ_TIMESTAMP, 196 testDefault: true, 197 }, { 198 name: "tzdate", 199 typeID: Ydb.Type_TZ_DATE, 200 testDefault: true, 201 }, { 202 name: "tzdatetime", 203 typeID: Ydb.Type_TZ_DATETIME, 204 testDefault: true, 205 }}, 206 values: []indexed.RequiredOrOptional{new(time.Time), new(time.Time), new(time.Time)}, 207 setColumns: []string{"tztimestamp", "tzdatetime", "tzdate"}, 208 setColumnIndexes: []int{0, 2, 1}, 209 }, 210 { 211 name: "Scan int64, float, json as ydb.valueType", 212 count: 100, 213 columns: []*column{{ 214 name: "valueint64", 215 typeID: Ydb.Type_INT64, 216 ydbvalue: true, 217 }, { 218 name: "valuefloat", 219 typeID: Ydb.Type_FLOAT, 220 ydbvalue: true, 221 }, { 222 name: "valuejson", 223 typeID: Ydb.Type_JSON, 224 ydbvalue: true, 225 }}, 226 values: []indexed.RequiredOrOptional{ 227 new(types.Value), 228 new(types.Value), 229 new(types.Value), 230 }, 231 }, 232 { 233 name: "Scan table with single column", 234 count: 10, 235 columns: []*column{{ 236 name: "datetime", 237 typeID: Ydb.Type_DATETIME, 238 }}, 239 values: []indexed.RequiredOrOptional{new(time.Time)}, 240 }, 241 { 242 name: "Scan optional values", 243 count: 500, 244 columns: []*column{{ 245 name: "otzdatetime", 246 typeID: Ydb.Type_TZ_DATETIME, 247 optional: true, 248 }, { 249 name: "ouint16", 250 typeID: Ydb.Type_UINT16, 251 optional: true, 252 }, { 253 name: "ostring", 254 typeID: Ydb.Type_STRING, 255 optional: true, 256 }}, 257 values: []indexed.RequiredOrOptional{new(*time.Time), new(*uint16), new(*[]byte)}, 258 }, 259 { 260 name: "Scan optional values", 261 count: 30, 262 columns: []*column{{ 263 name: "ointerval", 264 typeID: Ydb.Type_INTERVAL, 265 optional: true, 266 }, { 267 name: "ouuid", 268 typeID: Ydb.Type_UUID, 269 optional: true, 270 }, { 271 name: "odouble", 272 typeID: Ydb.Type_DOUBLE, 273 optional: true, 274 }}, 275 values: []indexed.RequiredOrOptional{new(*time.Duration), new(*[16]byte), new(*float64)}, 276 }, 277 { 278 name: "Scan int64, date, string as ydb.Scanner", 279 count: 4, 280 columns: []*column{{ 281 name: "sint64", 282 typeID: Ydb.Type_INT64, 283 scanner: true, 284 }, { 285 name: "sdate", 286 typeID: Ydb.Type_DATE, 287 scanner: true, 288 }, { 289 name: "sstring", 290 typeID: Ydb.Type_STRING, 291 scanner: true, 292 }}, 293 values: []indexed.RequiredOrOptional{new(intIncScanner), new(dateScanner), new([]byte)}, 294 }, 295 { 296 name: "Scan optional int64, date, string as ydb.Scanner", 297 count: 30, 298 columns: []*column{{ 299 name: "sint64", 300 typeID: Ydb.Type_INT64, 301 optional: true, 302 scanner: true, 303 }, { 304 name: "sdate", 305 typeID: Ydb.Type_DATE, 306 optional: true, 307 scanner: true, 308 }, { 309 name: "sstring", 310 typeID: Ydb.Type_STRING, 311 optional: true, 312 }}, 313 values: []indexed.RequiredOrOptional{new(intIncScanner), new(dateScanner), new(*[]byte)}, 314 }, 315 { 316 name: "ScanWithDefaults optional int64, date, string with null values as ydb.Scanner", 317 count: 30, 318 columns: []*column{{ 319 name: "sint64", 320 typeID: Ydb.Type_INT64, 321 optional: true, 322 scanner: true, 323 }, { 324 name: "sdate", 325 typeID: Ydb.Type_DATE, 326 optional: true, 327 scanner: true, 328 }, { 329 name: "sstring", 330 typeID: Ydb.Type_STRING, 331 optional: true, 332 scanner: true, 333 nilValue: true, 334 }}, 335 values: []indexed.RequiredOrOptional{new(intIncScanner), new(dateScanner), new(*[]byte)}, 336 }, 337 { 338 name: "ScanWithDefaults optional int32, time interval, string", 339 count: 30, 340 columns: []*column{{ 341 name: "oint32", 342 typeID: Ydb.Type_INT32, 343 optional: true, 344 testDefault: true, 345 }, { 346 name: "otimeinterval", 347 typeID: Ydb.Type_INTERVAL, 348 optional: true, 349 testDefault: true, 350 }, { 351 name: "ostring", 352 typeID: Ydb.Type_STRING, 353 optional: true, 354 testDefault: true, 355 }}, 356 values: []indexed.RequiredOrOptional{new(int32), new(time.Duration), new([]byte)}, 357 }, 358 { 359 name: "ScanWithDefaults optional int32, time interval, string, nil values applied as default value types", 360 count: 14, 361 columns: []*column{{ 362 name: "oint32", 363 typeID: Ydb.Type_INT32, 364 optional: true, 365 testDefault: true, 366 nilValue: true, 367 }, { 368 name: "otimeinterval", 369 typeID: Ydb.Type_INTERVAL, 370 optional: true, 371 testDefault: true, 372 nilValue: true, 373 }, { 374 name: "ostring", 375 typeID: Ydb.Type_STRING, 376 optional: true, 377 testDefault: true, 378 nilValue: true, 379 }}, 380 values: []indexed.RequiredOrOptional{new(int32), new(time.Duration), new([]byte)}, 381 }, 382 { 383 name: "Scan optional int32, time interval, string. All values are null", 384 count: 15, 385 columns: []*column{{ 386 name: "oint32", 387 typeID: Ydb.Type_INT32, 388 optional: true, 389 nilValue: true, 390 }, { 391 name: "otimeinterval", 392 typeID: Ydb.Type_INTERVAL, 393 optional: true, 394 nilValue: true, 395 }, { 396 name: "ostring", 397 typeID: Ydb.Type_STRING, 398 optional: true, 399 nilValue: true, 400 }}, 401 values: []indexed.RequiredOrOptional{new(*int32), new(*time.Duration), new(*[]byte)}, 402 }, 403 { 404 name: "Scan optional uint8, yson, tzdatetime, uuid. All values are null", 405 count: 15, 406 columns: []*column{{ 407 name: "ouint8", 408 typeID: Ydb.Type_UINT8, 409 optional: true, 410 nilValue: true, 411 }, { 412 name: "oyson", 413 typeID: Ydb.Type_YSON, 414 optional: true, 415 nilValue: true, 416 }, { 417 name: "otzdatetime", 418 typeID: Ydb.Type_TZ_DATETIME, 419 optional: true, 420 nilValue: true, 421 }, { 422 name: "ouuid", 423 typeID: Ydb.Type_UUID, 424 optional: true, 425 nilValue: true, 426 }}, 427 values: []indexed.RequiredOrOptional{new(*uint8), new(*[]byte), new(*time.Time), new(*[16]byte)}, 428 }, 429 { 430 name: "Scan string as byte array.", 431 count: 19, 432 columns: []*column{{ 433 name: "string", 434 typeID: Ydb.Type_STRING, 435 }}, 436 values: []indexed.RequiredOrOptional{new([]byte)}, 437 }, 438 { 439 name: "Scan optional string as byte array.", 440 count: 18, 441 columns: []*column{{ 442 name: "string", 443 typeID: Ydb.Type_STRING, 444 optional: true, 445 }}, 446 values: []indexed.RequiredOrOptional{new(*[]byte)}, 447 }, 448 { 449 name: "Scan optional null string as byte array.", 450 count: 17, 451 columns: []*column{{ 452 name: "string", 453 typeID: Ydb.Type_STRING, 454 optional: true, 455 nilValue: true, 456 }}, 457 values: []indexed.RequiredOrOptional{new(*[]byte)}, 458 }, 459 { 460 name: "Scan optional default string as byte array.", 461 count: 16, 462 columns: []*column{{ 463 name: "string", 464 typeID: Ydb.Type_STRING, 465 optional: true, 466 nilValue: true, 467 testDefault: true, 468 }}, 469 values: []indexed.RequiredOrOptional{new([]byte)}, 470 }, 471 } 472 473 func initScanner() *valueScanner { 474 res := valueScanner{ 475 set: &Ydb.ResultSet{ 476 Columns: nil, 477 Rows: nil, 478 Truncated: false, 479 }, 480 row: nil, 481 stack: scanStack{ 482 v: nil, 483 p: 0, 484 }, 485 nextRow: 0, 486 nextItem: 0, 487 columnIndexes: nil, 488 err: nil, 489 } 490 491 return &res 492 } 493 494 func PrepareScannerPerformanceTest(count int) *valueScanner { 495 res := initScanner() 496 res.set.Columns = []*Ydb.Column{{ 497 Name: "series_id", 498 Type: &Ydb.Type{ 499 Type: &Ydb.Type_TypeId{ 500 TypeId: Ydb.Type_UINT64, 501 }, 502 }, 503 }, { 504 Name: "title", 505 Type: &Ydb.Type{ 506 Type: &Ydb.Type_OptionalType{ 507 OptionalType: &Ydb.OptionalType{ 508 Item: &Ydb.Type{ 509 Type: &Ydb.Type_TypeId{ 510 TypeId: Ydb.Type_UTF8, 511 }, 512 }, 513 }, 514 }, 515 }, 516 }, { 517 Name: "release_date", 518 Type: &Ydb.Type{ 519 Type: &Ydb.Type_OptionalType{ 520 OptionalType: &Ydb.OptionalType{ 521 Item: &Ydb.Type{ 522 Type: &Ydb.Type_TypeId{ 523 TypeId: Ydb.Type_DATETIME, 524 }, 525 }, 526 }, 527 }, 528 }, 529 }} 530 res.set.Rows = []*Ydb.Value{} 531 for i := 0; i < count; i++ { 532 res.set.Rows = append(res.set.GetRows(), &Ydb.Value{ 533 Items: []*Ydb.Value{{ 534 Value: &Ydb.Value_Uint64Value{ 535 Uint64Value: uint64(i), 536 }, 537 }, { 538 Value: &Ydb.Value_TextValue{ 539 TextValue: strconv.Itoa(i) + "a", 540 }, 541 }, { 542 Value: &Ydb.Value_Uint32Value{ 543 Uint32Value: uint32(i), 544 }, 545 }}, 546 }) 547 } 548 res.converter = &rawConverter{res} 549 550 return res 551 }