go-hep.org/x/hep@v0.38.1/groot/rsql/rsqldrv/driver_test.go (about) 1 // Copyright ©2019 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package rsqldrv_test 6 7 import ( 8 "database/sql" 9 "fmt" 10 "math" 11 "reflect" 12 "testing" 13 14 "github.com/xwb1989/sqlparser" 15 "go-hep.org/x/hep/groot" 16 "go-hep.org/x/hep/groot/root" 17 "go-hep.org/x/hep/groot/rsql/rsqldrv" 18 "go-hep.org/x/hep/groot/rtree" 19 ) 20 21 func TestOpenDB(t *testing.T) { 22 f, err := groot.Open("../../testdata/simple.root") 23 if err != nil { 24 t.Fatal(err) 25 } 26 defer f.Close() 27 28 o, err := f.Get("tree") 29 if err != nil { 30 t.Fatal(err) 31 } 32 33 tree := o.(rtree.Tree) 34 35 db := rsqldrv.OpenDB(rtree.FileOf(tree)) 36 defer db.Close() 37 38 type data struct { 39 i32 int32 40 f32 float32 41 str string 42 } 43 44 rows, err := db.Query("SELECT * FROM tree") 45 if err != nil { 46 t.Fatal(err) 47 } 48 defer rows.Close() 49 50 var ( 51 got []data 52 want = []data{ 53 {1, 1.1, "uno"}, 54 {2, 2.2, "dos"}, 55 {3, 3.3, "tres"}, 56 {4, 4.4, "quatro"}, 57 } 58 ) 59 60 for rows.Next() { 61 var v data 62 err = rows.Scan(&v.i32, &v.f32, &v.str) 63 if err != nil { 64 t.Fatal(err) 65 } 66 got = append(got, v) 67 } 68 69 if !reflect.DeepEqual(got, want) { 70 t.Fatalf("invalid select\ngot = %#v\nwant= %#v", got, want) 71 } 72 } 73 74 func TestOpenWithConnector(t *testing.T) { 75 f, err := groot.Open("../../testdata/simple.root") 76 if err != nil { 77 t.Fatal(err) 78 } 79 defer f.Close() 80 81 o, err := f.Get("tree") 82 if err != nil { 83 t.Fatal(err) 84 } 85 86 tree := o.(rtree.Tree) 87 88 db := sql.OpenDB(rsqldrv.Connector(rtree.FileOf(tree))) 89 defer db.Close() 90 91 type data struct { 92 i32 int32 93 f32 float32 94 str string 95 } 96 97 rows, err := db.Query("SELECT * FROM tree") 98 if err != nil { 99 t.Fatal(err) 100 } 101 defer rows.Close() 102 103 var ( 104 got []data 105 want = []data{ 106 {1, 1.1, "uno"}, 107 {2, 2.2, "dos"}, 108 {3, 3.3, "tres"}, 109 {4, 4.4, "quatro"}, 110 } 111 ) 112 113 for rows.Next() { 114 var v data 115 err = rows.Scan(&v.i32, &v.f32, &v.str) 116 if err != nil { 117 t.Fatal(err) 118 } 119 got = append(got, v) 120 } 121 122 if !reflect.DeepEqual(got, want) { 123 t.Fatalf("invalid select\ngot = %#v\nwant= %#v", got, want) 124 } 125 } 126 127 func TestQuery(t *testing.T) { 128 db, err := sql.Open("root", "../../testdata/simple.root") 129 if err != nil { 130 t.Fatal(err) 131 } 132 defer db.Close() 133 134 type data struct { 135 i32 int32 136 f32 float32 137 str string 138 } 139 for _, tc := range []struct { 140 query string 141 args []any 142 cols []string 143 want []data 144 }{ 145 { 146 query: `SELECT * FROM tree`, 147 cols: []string{"one", "two", "three"}, 148 want: []data{ 149 {1, 1.1, "uno"}, 150 {2, 2.2, "dos"}, 151 {3, 3.3, "tres"}, 152 {4, 4.4, "quatro"}, 153 }, 154 }, 155 { 156 query: `SELECT (one, two, three) FROM tree`, 157 cols: []string{"one", "two", "three"}, 158 want: []data{ 159 {1, 1.1, "uno"}, 160 {2, 2.2, "dos"}, 161 {3, 3.3, "tres"}, 162 {4, 4.4, "quatro"}, 163 }, 164 }, 165 { 166 query: `SELECT (one+10, two+20, "--"+three+"--") FROM tree`, 167 cols: []string{"", "", ""}, 168 want: []data{ 169 {11, 21.1, "--uno--"}, 170 {12, 22.2, "--dos--"}, 171 {13, 23.3, "--tres--"}, 172 {14, 24.4, "--quatro--"}, 173 }, 174 }, 175 { 176 query: `SELECT (one+?, two+?, ?+three+"--") FROM tree`, 177 cols: []string{"", "", ""}, 178 args: []any{int32(10), 20.0, "++"}, 179 want: []data{ 180 {11, 21.1, "++uno--"}, 181 {12, 22.2, "++dos--"}, 182 {13, 23.3, "++tres--"}, 183 {14, 24.4, "++quatro--"}, 184 }, 185 }, 186 { 187 query: `SELECT (one, two, three) FROM tree WHERE (one <= 2)`, 188 cols: []string{"one", "two", "three"}, 189 want: []data{ 190 {1, 1.1, "uno"}, 191 {2, 2.2, "dos"}, 192 }, 193 }, 194 { 195 query: `SELECT (one, two, three) FROM tree WHERE (2 >= one)`, 196 cols: []string{"one", "two", "three"}, 197 want: []data{ 198 {1, 1.1, "uno"}, 199 {2, 2.2, "dos"}, 200 }, 201 }, 202 { 203 query: `SELECT (one, two, three) FROM tree WHERE (one <= ?)`, 204 cols: []string{"one", "two", "three"}, 205 args: []any{int32(2)}, 206 want: []data{ 207 {1, 1.1, "uno"}, 208 {2, 2.2, "dos"}, 209 }, 210 }, 211 { 212 query: `SELECT (one, two, three) FROM tree WHERE (one <= ?)`, 213 cols: []string{"one", "two", "three"}, 214 args: []any{2}, 215 want: []data{ 216 {1, 1.1, "uno"}, 217 {2, 2.2, "dos"}, 218 }, 219 }, 220 { 221 query: `SELECT (one, two, three) FROM tree WHERE (two <= ?)`, 222 cols: []string{"one", "two", "three"}, 223 args: []any{2.2}, 224 want: []data{ 225 {1, 1.1, "uno"}, 226 {2, 2.2, "dos"}, 227 }, 228 }, 229 { 230 query: `SELECT (one, two, three) FROM tree WHERE (two <= ?)`, 231 cols: []string{"one", "two", "three"}, 232 args: []any{3}, 233 want: []data{ 234 {1, 1.1, "uno"}, 235 {2, 2.2, "dos"}, 236 }, 237 }, 238 { 239 query: `SELECT (one, two, three) FROM tree WHERE (three != ? && three != ?)`, 240 cols: []string{"one", "two", "three"}, 241 args: []any{"tres", "quatro"}, 242 want: []data{ 243 {1, 1.1, "uno"}, 244 {2, 2.2, "dos"}, 245 }, 246 }, 247 { 248 query: `SELECT (one, two, three) FROM tree WHERE (one > -1 && two > -1 && three != "N/A")`, 249 cols: []string{"one", "two", "three"}, 250 want: []data{ 251 {1, 1.1, "uno"}, 252 {2, 2.2, "dos"}, 253 {3, 3.3, "tres"}, 254 {4, 4.4, "quatro"}, 255 }, 256 }, 257 { 258 query: `SELECT (one, two, three) FROM tree WHERE (one >= 3)`, 259 cols: []string{"one", "two", "three"}, 260 want: []data{ 261 {3, 3.3, "tres"}, 262 {4, 4.4, "quatro"}, 263 }, 264 }, 265 { 266 query: `SELECT (one, two, three) FROM tree WHERE (one > 2)`, 267 cols: []string{"one", "two", "three"}, 268 want: []data{ 269 {3, 3.3, "tres"}, 270 {4, 4.4, "quatro"}, 271 }, 272 }, 273 { 274 query: `SELECT (one, two, three) FROM tree WHERE (two >= 2.2 || two < 10)`, 275 cols: []string{"one", "two", "three"}, 276 want: []data{ 277 {1, 1.1, "uno"}, 278 {2, 2.2, "dos"}, 279 {3, 3.3, "tres"}, 280 {4, 4.4, "quatro"}, 281 }, 282 }, 283 { 284 query: `SELECT (one, two, three) FROM tree WHERE (two >= 2.2 && two < 4)`, 285 cols: []string{"one", "two", "three"}, 286 want: []data{ 287 {2, 2.2, "dos"}, 288 {3, 3.3, "tres"}, 289 }, 290 }, 291 { 292 query: `SELECT (one, two, three) FROM tree WHERE ((two+2) >= 4.2)`, 293 cols: []string{"one", "two", "three"}, 294 want: []data{ 295 {2, 2.2, "dos"}, 296 {3, 3.3, "tres"}, 297 {4, 4.4, "quatro"}, 298 }, 299 }, 300 { 301 query: `SELECT (one, two, three) FROM tree WHERE ((2+two) >= 4.2)`, 302 cols: []string{"one", "two", "three"}, 303 want: []data{ 304 {2, 2.2, "dos"}, 305 {3, 3.3, "tres"}, 306 {4, 4.4, "quatro"}, 307 }, 308 }, 309 { 310 query: `SELECT (one, two, three) FROM tree WHERE (2+two >= 4.2)`, 311 cols: []string{"one", "two", "three"}, 312 want: []data{ 313 {2, 2.2, "dos"}, 314 {3, 3.3, "tres"}, 315 {4, 4.4, "quatro"}, 316 }, 317 }, 318 { 319 query: `SELECT (one, two, three) FROM tree WHERE ((2*two) >= 4.2)`, 320 cols: []string{"one", "two", "three"}, 321 want: []data{ 322 {2, 2.2, "dos"}, 323 {3, 3.3, "tres"}, 324 {4, 4.4, "quatro"}, 325 }, 326 }, 327 { 328 query: `SELECT (one, two, three) FROM tree WHERE (three = ?)`, 329 cols: []string{"one", "two", "three"}, 330 args: []any{"quatro"}, 331 want: []data{ 332 {4, 4.4, "quatro"}, 333 }, 334 }, 335 } { 336 t.Run(tc.query, func(t *testing.T) { 337 _, err := sqlparser.Parse(tc.query) 338 if err != nil { 339 t.Fatalf("could not parse query %q: %v", tc.query, err) 340 } 341 342 rows, err := db.Query(tc.query, tc.args...) 343 if err != nil { 344 t.Fatal(err) 345 } 346 defer rows.Close() 347 348 cols, err := rows.Columns() 349 if err != nil { 350 t.Fatal(err) 351 } 352 353 if got, want := cols, tc.cols; !reflect.DeepEqual(got, want) { 354 t.Fatalf("invalid columns\ngot= %q\nwant=%q", got, want) 355 } 356 357 var got []data 358 for rows.Next() { 359 var v data 360 err = rows.Scan(&v.i32, &v.f32, &v.str) 361 if err != nil { 362 t.Fatal(err) 363 } 364 got = append(got, v) 365 } 366 367 if !reflect.DeepEqual(got, tc.want) { 368 t.Fatalf("invalid select\ngot = %#v\nwant= %#v", got, tc.want) 369 } 370 }) 371 } 372 } 373 374 type eventData struct { 375 B bool `groot:"B"` 376 Str string `groot:"Str"` 377 I8 int8 `groot:"I8"` 378 I16 int16 `groot:"I16"` 379 I32 int32 `groot:"I32"` 380 I64 int64 `groot:"I64"` 381 U8 uint8 `groot:"U8"` 382 U16 uint16 `groot:"U16"` 383 U32 uint32 `groot:"U32"` 384 U64 uint64 `groot:"U64"` 385 F32 float32 `groot:"F32"` 386 F64 float64 `groot:"F64"` 387 D16 root.Float16 `groot:"D16"` 388 D32 root.Double32 `groot:"D32"` 389 ArrBs [10]bool `groot:"ArrBs[10]"` 390 ArrI8 [10]int8 `groot:"ArrI8[10]"` 391 ArrI16 [10]int16 `groot:"ArrI16[10]"` 392 ArrI32 [10]int32 `groot:"ArrI32[10]"` 393 ArrI64 [10]int64 `groot:"ArrI64[10]"` 394 ArrU8 [10]uint8 `groot:"ArrU8[10]"` 395 ArrU16 [10]uint16 `groot:"ArrU16[10]"` 396 ArrU32 [10]uint32 `groot:"ArrU32[10]"` 397 ArrU64 [10]uint64 `groot:"ArrU64[10]"` 398 ArrF32 [10]float32 `groot:"ArrF32[10]"` 399 ArrF64 [10]float64 `groot:"ArrF64[10]"` 400 ArrD16 [10]root.Float16 `groot:"ArrD16[10]"` 401 ArrD32 [10]root.Double32 `groot:"ArrD32[10]"` 402 N int32 `groot:"N"` 403 SliBs []bool `groot:"SliBs[N]"` 404 SliI8 []int8 `groot:"SliI8[N]"` 405 SliI16 []int16 `groot:"SliI16[N]"` 406 SliI32 []int32 `groot:"SliI32[N]"` 407 SliI64 []int64 `groot:"SliI64[N]"` 408 SliU8 []uint8 `groot:"SliU8[N]"` 409 SliU16 []uint16 `groot:"SliU16[N]"` 410 SliU32 []uint32 `groot:"SliU32[N]"` 411 SliU64 []uint64 `groot:"SliU64[N]"` 412 SliF32 []float32 `groot:"SliF32[N]"` 413 SliF64 []float64 `groot:"SliF64[N]"` 414 SliD16 []root.Float16 `groot:"SliD16[N]"` 415 SliD32 []root.Double32 `groot:"SliD32[N]"` 416 } 417 418 func (eventData) want(i int64) (data eventData) { 419 data.B = i%2 == 0 420 data.Str = fmt.Sprintf("str-%d", i) 421 data.I8 = int8(-i) 422 data.I16 = int16(-i) 423 data.I32 = int32(-i) 424 data.I64 = int64(-i) 425 data.U8 = uint8(i) 426 data.U16 = uint16(i) 427 data.U32 = uint32(i) 428 data.U64 = uint64(i) 429 data.F32 = float32(i) 430 data.F64 = float64(i) 431 data.D16 = root.Float16(i) 432 data.D32 = root.Double32(i) 433 for ii := range data.ArrI32 { 434 data.ArrBs[ii] = ii == int(i) 435 data.ArrI8[ii] = int8(-i) 436 data.ArrI16[ii] = int16(-i) 437 data.ArrI32[ii] = int32(-i) 438 data.ArrI64[ii] = int64(-i) 439 data.ArrU8[ii] = uint8(i) 440 data.ArrU16[ii] = uint16(i) 441 data.ArrU32[ii] = uint32(i) 442 data.ArrU64[ii] = uint64(i) 443 data.ArrF32[ii] = float32(i) 444 data.ArrF64[ii] = float64(i) 445 data.ArrD16[ii] = root.Float16(i) 446 data.ArrD32[ii] = root.Double32(i) 447 } 448 data.N = int32(i) % 10 449 data.SliBs = make([]bool, int(data.N)) 450 data.SliI8 = make([]int8, int(data.N)) 451 data.SliI16 = make([]int16, int(data.N)) 452 data.SliI32 = make([]int32, int(data.N)) 453 data.SliI64 = make([]int64, int(data.N)) 454 data.SliU8 = make([]uint8, int(data.N)) 455 data.SliU16 = make([]uint16, int(data.N)) 456 data.SliU32 = make([]uint32, int(data.N)) 457 data.SliU64 = make([]uint64, int(data.N)) 458 data.SliF32 = make([]float32, int(data.N)) 459 data.SliF64 = make([]float64, int(data.N)) 460 data.SliD16 = make([]root.Float16, int(data.N)) 461 data.SliD32 = make([]root.Double32, int(data.N)) 462 for ii := range int(data.N) { 463 data.SliBs[ii] = (ii + 1) == int(i) 464 data.SliI8[ii] = int8(-i) 465 data.SliI16[ii] = int16(-i) 466 data.SliI32[ii] = int32(-i) 467 data.SliI64[ii] = int64(-i) 468 data.SliU8[ii] = uint8(i) 469 data.SliU16[ii] = uint16(i) 470 data.SliU32[ii] = uint32(i) 471 data.SliU64[ii] = uint64(i) 472 data.SliF32[ii] = float32(i) 473 data.SliF64[ii] = float64(i) 474 data.SliD16[ii] = root.Float16(i) 475 data.SliD32[ii] = root.Double32(i) 476 } 477 return data 478 } 479 480 func TestFlatTree(t *testing.T) { 481 db, err := sql.Open("root", "../../testdata/x-flat-tree.root") 482 if err != nil { 483 t.Fatal(err) 484 } 485 defer db.Close() 486 487 rows, err := db.Query("SELECT * FROM tree") 488 if err != nil { 489 t.Fatal(err) 490 } 491 defer rows.Close() 492 493 cols, err := rows.ColumnTypes() 494 if err != nil { 495 t.Fatal(err) 496 } 497 498 for i, want := range []struct { 499 name string 500 hasNullable bool 501 hasLength bool 502 503 nullable bool 504 length int64 505 scanType reflect.Type 506 }{ 507 {"B", true, false, false, 0, reflect.ValueOf(false).Type()}, 508 {"Str", true, false, false, 0, reflect.ValueOf("").Type()}, 509 {"I8", true, false, false, 0, reflect.ValueOf(int8(0)).Type()}, 510 {"I16", true, false, false, 0, reflect.ValueOf(int16(0)).Type()}, 511 {"I32", true, false, false, 0, reflect.ValueOf(int32(0)).Type()}, 512 {"I64", true, false, false, 0, reflect.ValueOf(int64(0)).Type()}, 513 {"U8", true, false, false, 0, reflect.ValueOf(uint8(0)).Type()}, 514 {"U16", true, false, false, 0, reflect.ValueOf(uint16(0)).Type()}, 515 {"U32", true, false, false, 0, reflect.ValueOf(uint32(0)).Type()}, 516 {"U64", true, false, false, 0, reflect.ValueOf(uint64(0)).Type()}, 517 {"F32", true, false, false, 0, reflect.ValueOf(float32(0)).Type()}, 518 {"F64", true, false, false, 0, reflect.ValueOf(float64(0)).Type()}, 519 {"D16", true, false, false, 0, reflect.ValueOf(root.Float16(0)).Type()}, 520 {"D32", true, false, false, 0, reflect.ValueOf(root.Double32(0)).Type()}, 521 {"ArrBs", true, true, false, 10, reflect.ValueOf(false).Type()}, 522 {"ArrI8", true, true, false, 10, reflect.ValueOf(int8(0)).Type()}, 523 {"ArrI16", true, true, false, 10, reflect.ValueOf(int16(0)).Type()}, 524 {"ArrI32", true, true, false, 10, reflect.ValueOf(int32(0)).Type()}, 525 {"ArrI64", true, true, false, 10, reflect.ValueOf(int64(0)).Type()}, 526 {"ArrU8", true, true, false, 10, reflect.ValueOf(uint8(0)).Type()}, 527 {"ArrU16", true, true, false, 10, reflect.ValueOf(uint16(0)).Type()}, 528 {"ArrU32", true, true, false, 10, reflect.ValueOf(uint32(0)).Type()}, 529 {"ArrU64", true, true, false, 10, reflect.ValueOf(uint64(0)).Type()}, 530 {"ArrF32", true, true, false, 10, reflect.ValueOf(float32(0)).Type()}, 531 {"ArrF64", true, true, false, 10, reflect.ValueOf(float64(0)).Type()}, 532 {"ArrD16", true, true, false, 10, reflect.ValueOf(root.Float16(0)).Type()}, 533 {"ArrD32", true, true, false, 10, reflect.ValueOf(root.Double32(0)).Type()}, 534 {"N", true, false, false, 0, reflect.ValueOf(int32(0)).Type()}, 535 {"SliBs", true, true, true, math.MaxInt64, reflect.ValueOf(false).Type()}, 536 {"SliI8", true, true, true, math.MaxInt64, reflect.ValueOf(int8(0)).Type()}, 537 {"SliI16", true, true, true, math.MaxInt64, reflect.ValueOf(int16(0)).Type()}, 538 {"SliI32", true, true, true, math.MaxInt64, reflect.ValueOf(int32(0)).Type()}, 539 {"SliI64", true, true, true, math.MaxInt64, reflect.ValueOf(int64(0)).Type()}, 540 {"SliU8", true, true, true, math.MaxInt64, reflect.ValueOf(uint8(0)).Type()}, 541 {"SliU16", true, true, true, math.MaxInt64, reflect.ValueOf(uint16(0)).Type()}, 542 {"SliU32", true, true, true, math.MaxInt64, reflect.ValueOf(uint32(0)).Type()}, 543 {"SliU64", true, true, true, math.MaxInt64, reflect.ValueOf(uint64(0)).Type()}, 544 {"SliF32", true, true, true, math.MaxInt64, reflect.ValueOf(float32(0)).Type()}, 545 {"SliF64", true, true, true, math.MaxInt64, reflect.ValueOf(float64(0)).Type()}, 546 {"SliD16", true, true, true, math.MaxInt64, reflect.ValueOf(root.Float16(0)).Type()}, 547 {"SliD32", true, true, true, math.MaxInt64, reflect.ValueOf(root.Double32(0)).Type()}, 548 } { 549 got := cols[i] 550 if got.Name() != want.name { 551 t.Fatalf("col[%d]: invalid name. got=%q, want=%q", i, got.Name(), want.name) 552 } 553 554 nullable, hasNullable := got.Nullable() 555 if hasNullable != want.hasNullable { 556 t.Fatalf("col[%d]: invalid nullable state. got=%v, want=%v", i, hasNullable, want.hasNullable) 557 } 558 if nullable != want.nullable { 559 t.Fatalf("col[%d]: invalid nullable. got=%v, want=%v", i, nullable, want.nullable) 560 } 561 562 length, hasLength := got.Length() 563 if hasLength != want.hasLength { 564 t.Fatalf("col[%d]: invalid length state. got=%v, want=%v", i, hasLength, want.hasLength) 565 } 566 if length != want.length { 567 t.Fatalf("col[%d]: invalid length. got=%v, want=%v", i, length, want.length) 568 } 569 570 if got, want := got.ScanType(), want.scanType; !reflect.DeepEqual(got, want) { 571 t.Fatalf("col[%d]: invalid type. got=%v, want=%v", i, got, want) 572 } 573 } 574 575 var ( 576 want = eventData{}.want 577 i int64 578 ) 579 for rows.Next() { 580 var v eventData 581 err = rows.Scan( 582 &v.B, 583 &v.Str, 584 &v.I8, &v.I16, &v.I32, &v.I64, 585 &v.U8, &v.U16, &v.U32, &v.U64, 586 &v.F32, &v.F64, 587 &v.D16, &v.D32, 588 &v.ArrBs, 589 &v.ArrI8, &v.ArrI16, &v.ArrI32, &v.ArrI64, 590 &v.ArrU8, &v.ArrU16, &v.ArrU32, &v.ArrU64, 591 &v.ArrF32, &v.ArrF64, 592 &v.ArrD16, &v.ArrD32, 593 &v.N, 594 &v.SliBs, 595 &v.SliI8, &v.SliI16, &v.SliI32, &v.SliI64, 596 &v.SliU8, &v.SliU16, &v.SliU32, &v.SliU64, 597 &v.SliF32, &v.SliF64, 598 &v.SliD16, &v.SliD32, 599 ) 600 if err != nil { 601 t.Fatal(err) 602 } 603 604 if got, want := v, want(i); !reflect.DeepEqual(got, want) { 605 t.Fatalf("invalid row[%d]:\ngot= %#v\nwant=%#v\n", i, got, want) 606 } 607 i++ 608 } 609 }