|
7 | 7 | "errors" |
8 | 8 | "math" |
9 | 9 | "net/url" |
| 10 | + "reflect" |
10 | 11 | "testing" |
11 | 12 | "time" |
12 | 13 |
|
@@ -365,3 +366,104 @@ func Test_time(t *testing.T) { |
365 | 366 | }) |
366 | 367 | } |
367 | 368 | } |
| 369 | + |
| 370 | +func Test_ColumnType_ScanType(t *testing.T) { |
| 371 | + var ( |
| 372 | + INT = reflect.TypeOf(int64(0)) |
| 373 | + REAL = reflect.TypeOf(float64(0)) |
| 374 | + TEXT = reflect.TypeOf("") |
| 375 | + BLOB = reflect.TypeOf([]byte{}) |
| 376 | + BOOL = reflect.TypeOf(false) |
| 377 | + TIME = reflect.TypeOf(time.Time{}) |
| 378 | + ANY = reflect.TypeOf((*any)(nil)).Elem() |
| 379 | + ) |
| 380 | + |
| 381 | + t.Parallel() |
| 382 | + tmp := memdb.TestDB(t) |
| 383 | + |
| 384 | + db, err := sql.Open("sqlite3", tmp) |
| 385 | + if err != nil { |
| 386 | + t.Fatal(err) |
| 387 | + } |
| 388 | + defer db.Close() |
| 389 | + |
| 390 | + _, err = db.Exec(` |
| 391 | + CREATE TABLE test ( |
| 392 | + col_int INTEGER, |
| 393 | + col_real REAL, |
| 394 | + col_text TEXT, |
| 395 | + col_blob BLOB, |
| 396 | + col_bool BOOLEAN, |
| 397 | + col_time DATETIME, |
| 398 | + col_decimal DECIMAL |
| 399 | + ); |
| 400 | + INSERT INTO test VALUES |
| 401 | + (1, 1, 1, 1, 1, 1, 1), |
| 402 | + (2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0), |
| 403 | + ('1', '1', '1', '1', '1', '1', '1'), |
| 404 | + ('x', 'x', 'x', 'x', 'x', 'x', 'x'), |
| 405 | + (x'', x'', x'', x'', x'', x'', x''), |
| 406 | + ('2006-01-02T15:04:05Z', '2006-01-02T15:04:05Z', '2006-01-02T15:04:05Z', '2006-01-02T15:04:05Z', |
| 407 | + '2006-01-02T15:04:05Z', '2006-01-02T15:04:05Z', '2006-01-02T15:04:05Z'), |
| 408 | + (TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE), |
| 409 | + (NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
| 410 | + `) |
| 411 | + if err != nil { |
| 412 | + t.Fatal(err) |
| 413 | + } |
| 414 | + |
| 415 | + rows, err := db.Query(`SELECT * FROM test`) |
| 416 | + if err != nil { |
| 417 | + t.Fatal(err) |
| 418 | + } |
| 419 | + defer rows.Close() |
| 420 | + |
| 421 | + cols, err := rows.ColumnTypes() |
| 422 | + if err != nil { |
| 423 | + t.Fatal(err) |
| 424 | + } |
| 425 | + |
| 426 | + want := [][]reflect.Type{ |
| 427 | + {INT, REAL, TEXT, BLOB, BOOL, TIME, ANY}, |
| 428 | + {INT, REAL, TEXT, INT, BOOL, TIME, INT}, |
| 429 | + {INT, REAL, TEXT, REAL, INT, TIME, INT}, |
| 430 | + {INT, REAL, TEXT, TEXT, BOOL, TIME, INT}, |
| 431 | + {TEXT, TEXT, TEXT, TEXT, TEXT, TEXT, TEXT}, |
| 432 | + {BLOB, BLOB, BLOB, BLOB, BLOB, BLOB, BLOB}, |
| 433 | + {TEXT, TEXT, TEXT, TEXT, TEXT, TIME, TEXT}, |
| 434 | + {INT, REAL, TEXT, INT, BOOL, TIME, INT}, |
| 435 | + {ANY, ANY, ANY, BLOB, ANY, ANY, ANY}, |
| 436 | + } |
| 437 | + for j, c := range cols { |
| 438 | + got := c.ScanType() |
| 439 | + if got != want[0][j] { |
| 440 | + t.Errorf("want %v, got %v, at column %d", want[0][j], got, j) |
| 441 | + } |
| 442 | + } |
| 443 | + |
| 444 | + dest := make([]any, len(cols)) |
| 445 | + for i := 1; rows.Next(); i++ { |
| 446 | + cols, err := rows.ColumnTypes() |
| 447 | + if err != nil { |
| 448 | + t.Fatal(err) |
| 449 | + } |
| 450 | + |
| 451 | + for j, c := range cols { |
| 452 | + got := c.ScanType() |
| 453 | + if got != want[i][j] { |
| 454 | + t.Errorf("want %v, got %v, at row %d column %d", want[i][j], got, i, j) |
| 455 | + } |
| 456 | + dest[j] = reflect.New(got).Interface() |
| 457 | + } |
| 458 | + |
| 459 | + err = rows.Scan(dest...) |
| 460 | + if err != nil { |
| 461 | + t.Error(err) |
| 462 | + } |
| 463 | + } |
| 464 | + |
| 465 | + err = rows.Err() |
| 466 | + if err != nil { |
| 467 | + t.Fatal(err) |
| 468 | + } |
| 469 | +} |
0 commit comments