github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/tests/stmt_test.go (about) 1 package tests 2 3 import ( 4 "encoding/json" 5 "math" 6 "testing" 7 "time" 8 9 "github.com/ncruces/go-sqlite3" 10 _ "github.com/ncruces/go-sqlite3/embed" 11 _ "github.com/ncruces/go-sqlite3/tests/testcfg" 12 ) 13 14 func TestStmt(t *testing.T) { 15 t.Parallel() 16 17 db, err := sqlite3.Open(":memory:") 18 if err != nil { 19 t.Fatal(err) 20 } 21 defer db.Close() 22 23 err = db.Exec(`CREATE TABLE test (col)`) 24 if err != nil { 25 t.Fatal(err) 26 } 27 28 stmt, _, err := db.Prepare(`INSERT INTO test VALUES (?)`) 29 if err != nil { 30 t.Fatal(err) 31 } 32 defer stmt.Close() 33 34 if got := stmt.ReadOnly(); got != false { 35 t.Error("got true, want false") 36 } 37 38 if got := stmt.BindCount(); got != 1 { 39 t.Errorf("got %d, want 1", got) 40 } 41 42 if err := stmt.BindBool(1, false); err != nil { 43 t.Fatal(err) 44 } 45 if err := stmt.Exec(); err != nil { 46 t.Fatal(err) 47 } 48 49 if err := stmt.BindBool(1, true); err != nil { 50 t.Fatal(err) 51 } 52 if err := stmt.Exec(); err != nil { 53 t.Fatal(err) 54 } 55 56 if err := stmt.BindInt(1, 2); err != nil { 57 t.Fatal(err) 58 } 59 if err = stmt.Exec(); err != nil { 60 t.Fatal(err) 61 } 62 63 if err := stmt.BindFloat(1, math.Pi); err != nil { 64 t.Fatal(err) 65 } 66 if err := stmt.Exec(); err != nil { 67 t.Fatal(err) 68 } 69 70 if err := stmt.BindNull(1); err != nil { 71 t.Fatal(err) 72 } 73 if err := stmt.Exec(); err != nil { 74 t.Fatal(err) 75 } 76 77 if err := stmt.BindText(1, ""); err != nil { 78 t.Fatal(err) 79 } 80 if err := stmt.Exec(); err != nil { 81 t.Fatal(err) 82 } 83 84 if err := stmt.BindText(1, "text"); err != nil { 85 t.Fatal(err) 86 } 87 if err := stmt.Exec(); err != nil { 88 t.Fatal(err) 89 } 90 91 if err := stmt.BindBlob(1, []byte("")); err != nil { 92 t.Fatal(err) 93 } 94 if err := stmt.Exec(); err != nil { 95 t.Fatal(err) 96 } 97 98 if err := stmt.BindBlob(1, []byte("blob")); err != nil { 99 t.Fatal(err) 100 } 101 if err := stmt.Exec(); err != nil { 102 t.Fatal(err) 103 } 104 105 if err := stmt.BindBlob(1, nil); err != nil { 106 t.Fatal(err) 107 } 108 if err := stmt.Exec(); err != nil { 109 t.Fatal(err) 110 } 111 112 if err := stmt.BindZeroBlob(1, 4); err != nil { 113 t.Fatal(err) 114 } 115 if err := stmt.Exec(); err != nil { 116 t.Fatal(err) 117 } 118 119 if err := stmt.BindJSON(1, true); err != nil { 120 t.Fatal(err) 121 } 122 if err := stmt.Exec(); err != nil { 123 t.Fatal(err) 124 } 125 126 if err := stmt.ClearBindings(); err != nil { 127 t.Fatal(err) 128 } 129 if err := stmt.Exec(); err != nil { 130 t.Fatal(err) 131 } 132 133 err = stmt.Close() 134 if err != nil { 135 t.Fatal(err) 136 } 137 138 // The table should have: 0, 1, 2, π, NULL, "", "text", "", "blob", NULL, "\0\0\0\0", "true", NULL 139 stmt, _, err = db.Prepare(`SELECT col FROM test`) 140 if err != nil { 141 t.Fatal(err) 142 } 143 defer stmt.Close() 144 145 if got := stmt.ReadOnly(); got != true { 146 t.Error("got false, want true") 147 } 148 149 if stmt.Step() { 150 if got := stmt.ColumnType(0); got != sqlite3.INTEGER { 151 t.Errorf("got %v, want INTEGER", got) 152 } 153 if got := stmt.ColumnBool(0); got != false { 154 t.Errorf("got %v, want false", got) 155 } 156 if got := stmt.ColumnInt(0); got != 0 { 157 t.Errorf("got %v, want zero", got) 158 } 159 if got := stmt.ColumnFloat(0); got != 0 { 160 t.Errorf("got %v, want zero", got) 161 } 162 if got := stmt.ColumnText(0); got != "0" { 163 t.Errorf("got %q, want zero", got) 164 } 165 if got := stmt.ColumnBlob(0, nil); string(got) != "0" { 166 t.Errorf("got %q, want zero", got) 167 } 168 var got int 169 if err := stmt.ColumnJSON(0, &got); err != nil { 170 t.Error(err) 171 } else if got != 0 { 172 t.Errorf("got %v, want zero", got) 173 } 174 } 175 176 if stmt.Step() { 177 if got := stmt.ColumnType(0); got != sqlite3.INTEGER { 178 t.Errorf("got %v, want INTEGER", got) 179 } 180 if got := stmt.ColumnBool(0); got != true { 181 t.Errorf("got %v, want true", got) 182 } 183 if got := stmt.ColumnInt(0); got != 1 { 184 t.Errorf("got %v, want one", got) 185 } 186 if got := stmt.ColumnFloat(0); got != 1 { 187 t.Errorf("got %v, want one", got) 188 } 189 if got := stmt.ColumnText(0); got != "1" { 190 t.Errorf("got %q, want one", got) 191 } 192 if got := stmt.ColumnBlob(0, nil); string(got) != "1" { 193 t.Errorf("got %q, want one", got) 194 } 195 var got float32 196 if err := stmt.ColumnJSON(0, &got); err != nil { 197 t.Error(err) 198 } else if got != 1 { 199 t.Errorf("got %v, want one", got) 200 } 201 } 202 203 if stmt.Step() { 204 if got := stmt.ColumnType(0); got != sqlite3.INTEGER { 205 t.Errorf("got %v, want INTEGER", got) 206 } 207 if got := stmt.ColumnBool(0); got != true { 208 t.Errorf("got %v, want true", got) 209 } 210 if got := stmt.ColumnInt(0); got != 2 { 211 t.Errorf("got %v, want two", got) 212 } 213 if got := stmt.ColumnFloat(0); got != 2 { 214 t.Errorf("got %v, want two", got) 215 } 216 if got := stmt.ColumnText(0); got != "2" { 217 t.Errorf("got %q, want two", got) 218 } 219 if got := stmt.ColumnBlob(0, nil); string(got) != "2" { 220 t.Errorf("got %q, want two", got) 221 } 222 var got json.Number 223 if err := stmt.ColumnJSON(0, &got); err != nil { 224 t.Error(err) 225 } else if got != "2" { 226 t.Errorf("got %v, want two", got) 227 } 228 } 229 230 if stmt.Step() { 231 if got := stmt.ColumnType(0); got != sqlite3.FLOAT { 232 t.Errorf("got %v, want FLOAT", got) 233 } 234 if got := stmt.ColumnBool(0); got != true { 235 t.Errorf("got %v, want true", got) 236 } 237 if got := stmt.ColumnInt(0); got != 3 { 238 t.Errorf("got %v, want three", got) 239 } 240 if got := stmt.ColumnFloat(0); got != math.Pi { 241 t.Errorf("got %v, want π", got) 242 } 243 if got := stmt.ColumnText(0); got != "3.14159265358979" { 244 t.Errorf("got %q, want π", got) 245 } 246 if got := stmt.ColumnBlob(0, nil); string(got) != "3.14159265358979" { 247 t.Errorf("got %q, want π", got) 248 } 249 var got float64 250 if err := stmt.ColumnJSON(0, &got); err != nil { 251 t.Error(err) 252 } else if got != math.Pi { 253 t.Errorf("got %v, want π", got) 254 } 255 } 256 257 if stmt.Step() { 258 if got := stmt.ColumnType(0); got != sqlite3.NULL { 259 t.Errorf("got %v, want NULL", got) 260 } 261 if got := stmt.ColumnBool(0); got != false { 262 t.Errorf("got %v, want false", got) 263 } 264 if got := stmt.ColumnInt(0); got != 0 { 265 t.Errorf("got %v, want zero", got) 266 } 267 if got := stmt.ColumnFloat(0); got != 0 { 268 t.Errorf("got %v, want zero", got) 269 } 270 if got := stmt.ColumnText(0); got != "" { 271 t.Errorf("got %q, want empty", got) 272 } 273 if got := stmt.ColumnBlob(0, nil); got != nil { 274 t.Errorf("got %q, want nil", got) 275 } 276 var got any = 1 277 if err := stmt.ColumnJSON(0, &got); err != nil { 278 t.Error(err) 279 } else if got != nil { 280 t.Errorf("got %v, want NULL", got) 281 } 282 } 283 284 if stmt.Step() { 285 if got := stmt.ColumnType(0); got != sqlite3.TEXT { 286 t.Errorf("got %v, want TEXT", got) 287 } 288 if got := stmt.ColumnBool(0); got != false { 289 t.Errorf("got %v, want false", got) 290 } 291 if got := stmt.ColumnInt(0); got != 0 { 292 t.Errorf("got %v, want zero", got) 293 } 294 if got := stmt.ColumnFloat(0); got != 0 { 295 t.Errorf("got %v, want zero", got) 296 } 297 if got := stmt.ColumnText(0); got != "" { 298 t.Errorf("got %q, want empty", got) 299 } 300 if got := stmt.ColumnBlob(0, nil); got != nil { 301 t.Errorf("got %q, want nil", got) 302 } 303 var got any 304 if err := stmt.ColumnJSON(0, &got); err == nil { 305 t.Errorf("got %v, want error", got) 306 } 307 } 308 309 if stmt.Step() { 310 if got := stmt.ColumnType(0); got != sqlite3.TEXT { 311 t.Errorf("got %v, want TEXT", got) 312 } 313 if got := stmt.ColumnBool(0); got != false { 314 t.Errorf("got %v, want false", got) 315 } 316 if got := stmt.ColumnInt(0); got != 0 { 317 t.Errorf("got %v, want zero", got) 318 } 319 if got := stmt.ColumnFloat(0); got != 0 { 320 t.Errorf("got %v, want zero", got) 321 } 322 if got := stmt.ColumnText(0); got != "text" { 323 t.Errorf(`got %q, want "text"`, got) 324 } 325 if got := stmt.ColumnBlob(0, nil); string(got) != "text" { 326 t.Errorf(`got %q, want "text"`, got) 327 } 328 var got any 329 if err := stmt.ColumnJSON(0, &got); err == nil { 330 t.Errorf("got %v, want error", got) 331 } 332 } 333 334 if stmt.Step() { 335 if got := stmt.ColumnType(0); got != sqlite3.BLOB { 336 t.Errorf("got %v, want BLOB", got) 337 } 338 if got := stmt.ColumnBool(0); got != false { 339 t.Errorf("got %v, want false", got) 340 } 341 if got := stmt.ColumnInt(0); got != 0 { 342 t.Errorf("got %v, want zero", got) 343 } 344 if got := stmt.ColumnFloat(0); got != 0 { 345 t.Errorf("got %v, want zero", got) 346 } 347 if got := stmt.ColumnText(0); got != "" { 348 t.Errorf("got %q, want empty", got) 349 } 350 if got := stmt.ColumnBlob(0, nil); got != nil { 351 t.Errorf("got %q, want nil", got) 352 } 353 var got any 354 if err := stmt.ColumnJSON(0, &got); err == nil { 355 t.Errorf("got %v, want error", got) 356 } 357 } 358 359 if stmt.Step() { 360 if got := stmt.ColumnType(0); got != sqlite3.BLOB { 361 t.Errorf("got %v, want BLOB", got) 362 } 363 if got := stmt.ColumnBool(0); got != false { 364 t.Errorf("got %v, want false", got) 365 } 366 if got := stmt.ColumnInt(0); got != 0 { 367 t.Errorf("got %v, want zero", got) 368 } 369 if got := stmt.ColumnFloat(0); got != 0 { 370 t.Errorf("got %v, want zero", got) 371 } 372 if got := stmt.ColumnText(0); got != "blob" { 373 t.Errorf(`got %q, want "blob"`, got) 374 } 375 if got := stmt.ColumnBlob(0, nil); string(got) != "blob" { 376 t.Errorf(`got %q, want "blob"`, got) 377 } 378 var got any 379 if err := stmt.ColumnJSON(0, &got); err == nil { 380 t.Errorf("got %v, want error", got) 381 } 382 } 383 384 if stmt.Step() { 385 if got := stmt.ColumnType(0); got != sqlite3.NULL { 386 t.Errorf("got %v, want NULL", got) 387 } 388 if got := stmt.ColumnBool(0); got != false { 389 t.Errorf("got %v, want false", got) 390 } 391 if got := stmt.ColumnInt(0); got != 0 { 392 t.Errorf("got %v, want zero", got) 393 } 394 if got := stmt.ColumnFloat(0); got != 0 { 395 t.Errorf("got %v, want zero", got) 396 } 397 if got := stmt.ColumnText(0); got != "" { 398 t.Errorf("got %q, want empty", got) 399 } 400 if got := stmt.ColumnBlob(0, nil); got != nil { 401 t.Errorf("got %q, want nil", got) 402 } 403 var got any = 1 404 if err := stmt.ColumnJSON(0, &got); err != nil { 405 t.Error(err) 406 } else if got != nil { 407 t.Errorf("got %v, want NULL", got) 408 } 409 } 410 411 if stmt.Step() { 412 if got := stmt.ColumnType(0); got != sqlite3.BLOB { 413 t.Errorf("got %v, want BLOB", got) 414 } 415 if got := stmt.ColumnBool(0); got != false { 416 t.Errorf("got %v, want false", got) 417 } 418 if got := stmt.ColumnInt(0); got != 0 { 419 t.Errorf("got %v, want zero", got) 420 } 421 if got := stmt.ColumnFloat(0); got != 0 { 422 t.Errorf("got %v, want zero", got) 423 } 424 if got := stmt.ColumnText(0); got != "\x00\x00\x00\x00" { 425 t.Errorf(`got %q, want "\x00\x00\x00\x00"`, got) 426 } 427 if got := stmt.ColumnBlob(0, nil); string(got) != "\x00\x00\x00\x00" { 428 t.Errorf(`got %q, want "\x00\x00\x00\x00"`, got) 429 } 430 var got any 431 if err := stmt.ColumnJSON(0, &got); err == nil { 432 t.Errorf("got %v, want error", got) 433 } 434 } 435 436 if stmt.Step() { 437 if got := stmt.ColumnType(0); got != sqlite3.TEXT { 438 t.Errorf("got %v, want TEXT", got) 439 } 440 if got := stmt.ColumnBool(0); got != false { 441 t.Errorf("got %v, want false", got) 442 } 443 if got := stmt.ColumnInt(0); got != 0 { 444 t.Errorf("got %v, want zero", got) 445 } 446 if got := stmt.ColumnFloat(0); got != 0 { 447 t.Errorf("got %v, want zero", got) 448 } 449 if got := stmt.ColumnText(0); got != "true" { 450 t.Errorf("got %q, want true", got) 451 } 452 if got := stmt.ColumnBlob(0, nil); string(got) != "true" { 453 t.Errorf("got %q, want true", got) 454 } 455 var got any = 1 456 if err := stmt.ColumnJSON(0, &got); err != nil { 457 t.Error(err) 458 } else if got != true { 459 t.Errorf("got %v, want true", got) 460 } 461 } 462 463 if stmt.Step() { 464 if got := stmt.ColumnType(0); got != sqlite3.NULL { 465 t.Errorf("got %v, want NULL", got) 466 } 467 if got := stmt.ColumnBool(0); got != false { 468 t.Errorf("got %v, want false", got) 469 } 470 if got := stmt.ColumnInt(0); got != 0 { 471 t.Errorf("got %v, want zero", got) 472 } 473 if got := stmt.ColumnFloat(0); got != 0 { 474 t.Errorf("got %v, want zero", got) 475 } 476 if got := stmt.ColumnText(0); got != "" { 477 t.Errorf("got %q, want empty", got) 478 } 479 if got := stmt.ColumnBlob(0, nil); got != nil { 480 t.Errorf("got %q, want nil", got) 481 } 482 var got any = 1 483 if err := stmt.ColumnJSON(0, &got); err != nil { 484 t.Error(err) 485 } else if got != nil { 486 t.Errorf("got %v, want NULL", got) 487 } 488 } 489 490 if err := stmt.Close(); err != nil { 491 t.Fatal(err) 492 } 493 494 if err := db.Close(); err != nil { 495 t.Fatal(err) 496 } 497 } 498 499 func TestStmt_Close(t *testing.T) { 500 var stmt *sqlite3.Stmt 501 stmt.Close() 502 } 503 504 func TestStmt_BindName(t *testing.T) { 505 t.Parallel() 506 507 db, err := sqlite3.Open(":memory:") 508 if err != nil { 509 t.Fatal(err) 510 } 511 defer db.Close() 512 513 want := []string{"", "", "", "", "?5", ":AAA", "@AAA", "$AAA"} 514 stmt, _, err := db.Prepare(`SELECT ?, ?5, :AAA, @AAA, $AAA`) 515 if err != nil { 516 t.Fatal(err) 517 } 518 defer stmt.Close() 519 520 if got := stmt.BindCount(); got != len(want) { 521 t.Errorf("got %d, want %d", got, len(want)) 522 } 523 524 for i, name := range want { 525 id := i + 1 526 if got := stmt.BindName(id); got != name { 527 t.Errorf("got %q, want %q", got, name) 528 } 529 if name == "" { 530 id = 0 531 } 532 if got := stmt.BindIndex(name); got != id { 533 t.Errorf("got %d, want %d", got, id) 534 } 535 } 536 } 537 538 func TestStmt_ColumnTime(t *testing.T) { 539 t.Parallel() 540 541 db, err := sqlite3.Open(":memory:") 542 if err != nil { 543 t.Fatal(err) 544 } 545 defer db.Close() 546 547 stmt, _, err := db.Prepare(`SELECT ?, ?, ?, datetime(), unixepoch(), julianday(), NULL, 'abc'`) 548 if err != nil { 549 t.Fatal(err) 550 } 551 defer stmt.Close() 552 553 reference := time.Date(2013, 10, 7, 4, 23, 19, 120_000_000, time.FixedZone("", -4*3600)) 554 err = stmt.BindTime(1, reference, sqlite3.TimeFormat4) 555 if err != nil { 556 t.Fatal(err) 557 } 558 err = stmt.BindTime(2, reference, sqlite3.TimeFormatUnixMilli) 559 if err != nil { 560 t.Fatal(err) 561 } 562 err = stmt.BindTime(3, reference, sqlite3.TimeFormatJulianDay) 563 if err != nil { 564 t.Fatal(err) 565 } 566 567 if now := time.Now(); stmt.Step() { 568 if got := stmt.ColumnTime(0, sqlite3.TimeFormatAuto); !got.Equal(reference) { 569 t.Errorf("got %v, want %v", got, reference) 570 } 571 if got := stmt.ColumnTime(1, sqlite3.TimeFormatAuto); !got.Equal(reference) { 572 t.Errorf("got %v, want %v", got, reference) 573 } 574 if got := stmt.ColumnTime(2, sqlite3.TimeFormatAuto); got.Sub(reference).Abs() > time.Millisecond { 575 t.Errorf("got %v, want %v", got, reference) 576 } 577 578 if got := stmt.ColumnTime(3, sqlite3.TimeFormatAuto); got.Sub(now).Abs() > time.Second { 579 t.Errorf("got %v, want %v", got, now) 580 } 581 if got := stmt.ColumnTime(4, sqlite3.TimeFormatAuto); got.Sub(now).Abs() > time.Second { 582 t.Errorf("got %v, want %v", got, now) 583 } 584 if got := stmt.ColumnTime(5, sqlite3.TimeFormatAuto); got.Sub(now).Abs() > time.Second/10 { 585 t.Errorf("got %v, want %v", got, now) 586 } 587 588 if got := stmt.ColumnTime(6, sqlite3.TimeFormatAuto); got != (time.Time{}) { 589 t.Errorf("got %v, want zero", got) 590 } 591 if got := stmt.ColumnTime(7, sqlite3.TimeFormatAuto); got != (time.Time{}) { 592 t.Errorf("got %v, want zero", got) 593 } 594 if stmt.Err() == nil { 595 t.Errorf("want error") 596 } 597 } 598 599 if got := stmt.Status(sqlite3.STMTSTATUS_RUN, true); got != 1 { 600 t.Errorf("got %d, want 1", got) 601 } 602 } 603 604 func TestStmt_Error(t *testing.T) { 605 t.Parallel() 606 607 db, err := sqlite3.Open(":memory:") 608 if err != nil { 609 t.Fatal(err) 610 } 611 defer db.Close() 612 613 var blob [1e9 + 1]byte 614 615 _, _, err = db.Prepare(string(blob[:])) 616 if err == nil { 617 t.Errorf("want error") 618 } else { 619 t.Log(err) 620 } 621 622 stmt, _, err := db.Prepare(`SELECT ?`) 623 if err != nil { 624 t.Fatal(err) 625 } 626 defer stmt.Close() 627 628 err = stmt.BindText(1, string(blob[:])) 629 if err == nil { 630 t.Errorf("want error") 631 } else { 632 t.Log(err) 633 } 634 635 err = stmt.BindBlob(1, blob[:]) 636 if err == nil { 637 t.Errorf("want error") 638 } else { 639 t.Log(err) 640 } 641 642 err = stmt.BindRawText(1, blob[:]) 643 if err == nil { 644 t.Errorf("want error") 645 } else { 646 t.Log(err) 647 } 648 649 err = stmt.BindZeroBlob(1, 1e9+1) 650 if err == nil { 651 t.Errorf("want error") 652 } else { 653 t.Log(err) 654 } 655 }