modernc.org/cc@v1.0.1/v2/testdata/_sqlite/test/shell1.test (about) 1 # 2009 Nov 11 2 # 3 # The author disclaims copyright to this source code. In place of 4 # a legal notice, here is a blessing: 5 # 6 # May you do good and not evil. 7 # May you find forgiveness for yourself and forgive others. 8 # May you share freely, never taking more than you give. 9 # 10 #*********************************************************************** 11 # 12 # The focus of this file is testing the CLI shell tool. 13 # 14 # 15 16 # Test plan: 17 # 18 # shell1-1.*: Basic command line option handling. 19 # shell1-2.*: Basic "dot" command token parsing. 20 # shell1-3.*: Basic test that "dot" command can be called. 21 # 22 set testdir [file dirname $argv0] 23 source $testdir/tester.tcl 24 set CLI [test_find_cli] 25 db close 26 forcedelete test.db test.db-journal test.db-wal 27 sqlite3 db test.db 28 29 #---------------------------------------------------------------------------- 30 # Test cases shell1-1.*: Basic command line option handling. 31 # 32 33 # invalid option 34 do_test shell1-1.1.1 { 35 set res [catchcmd "-bad test.db" ""] 36 set rc [lindex $res 0] 37 list $rc \ 38 [regexp {Error: unknown option: -bad} $res] 39 } {1 1} 40 do_test shell1-1.1.1b { 41 set res [catchcmd "test.db -bad" ""] 42 set rc [lindex $res 0] 43 list $rc \ 44 [regexp {Error: unknown option: -bad} $res] 45 } {1 1} 46 # error on extra options 47 do_test shell1-1.1.2 { 48 catchcmd "test.db \"select+3\" \"select+4\"" "" 49 } {0 {3 50 4}} 51 # error on extra options 52 do_test shell1-1.1.3 { 53 catchcmd "test.db FOO test.db BAD" ".quit" 54 } {1 {Error: near "FOO": syntax error}} 55 56 # -help 57 do_test shell1-1.2.1 { 58 set res [catchcmd "-help test.db" ""] 59 set rc [lindex $res 0] 60 list $rc \ 61 [regexp {Usage} $res] \ 62 [regexp {\-init} $res] \ 63 [regexp {\-version} $res] 64 } {1 1 1 1} 65 66 # -init filename read/process named file 67 do_test shell1-1.3.1 { 68 catchcmd "-init FOO test.db" "" 69 } {0 {}} 70 do_test shell1-1.3.2 { 71 catchcmd "-init FOO test.db .quit BAD" "" 72 } {0 {}} 73 do_test shell1-1.3.3 { 74 catchcmd "-init FOO test.db BAD .quit" "" 75 } {1 {Error: near "BAD": syntax error}} 76 77 # -echo print commands before execution 78 do_test shell1-1.4.1 { 79 catchcmd "-echo test.db" "" 80 } {0 {}} 81 82 # -[no]header turn headers on or off 83 do_test shell1-1.5.1 { 84 catchcmd "-header test.db" "" 85 } {0 {}} 86 do_test shell1-1.5.2 { 87 catchcmd "-noheader test.db" "" 88 } {0 {}} 89 90 # -bail stop after hitting an error 91 do_test shell1-1.6.1 { 92 catchcmd "-bail test.db" "" 93 } {0 {}} 94 95 # -interactive force interactive I/O 96 do_test shell1-1.7.1 { 97 set res [catchcmd "-interactive test.db" ".quit"] 98 set rc [lindex $res 0] 99 list $rc \ 100 [regexp {SQLite version} $res] \ 101 [regexp {Enter ".help" for usage hints} $res] 102 } {0 1 1} 103 104 # -batch force batch I/O 105 do_test shell1-1.8.1 { 106 catchcmd "-batch test.db" "" 107 } {0 {}} 108 109 # -column set output mode to 'column' 110 do_test shell1-1.9.1 { 111 catchcmd "-column test.db" "" 112 } {0 {}} 113 114 # -csv set output mode to 'csv' 115 do_test shell1-1.10.1 { 116 catchcmd "-csv test.db" "" 117 } {0 {}} 118 119 # -html set output mode to HTML 120 do_test shell1-1.11.1 { 121 catchcmd "-html test.db" "" 122 } {0 {}} 123 124 # -line set output mode to 'line' 125 do_test shell1-1.12.1 { 126 catchcmd "-line test.db" "" 127 } {0 {}} 128 129 # -list set output mode to 'list' 130 do_test shell1-1.13.1 { 131 catchcmd "-list test.db" "" 132 } {0 {}} 133 134 # -separator 'x' set output field separator (|) 135 do_test shell1-1.14.1 { 136 catchcmd "-separator 'x' test.db" "" 137 } {0 {}} 138 do_test shell1-1.14.2 { 139 catchcmd "-separator x test.db" "" 140 } {0 {}} 141 do_test shell1-1.14.3 { 142 set res [catchcmd "-separator" ""] 143 set rc [lindex $res 0] 144 list $rc \ 145 [regexp {Error: missing argument to -separator} $res] 146 } {1 1} 147 148 # -stats print memory stats before each finalize 149 do_test shell1-1.14b.1 { 150 catchcmd "-stats test.db" "" 151 } {0 {}} 152 153 # -nullvalue 'text' set text string for NULL values 154 do_test shell1-1.15.1 { 155 catchcmd "-nullvalue 'x' test.db" "" 156 } {0 {}} 157 do_test shell1-1.15.2 { 158 catchcmd "-nullvalue x test.db" "" 159 } {0 {}} 160 do_test shell1-1.15.3 { 161 set res [catchcmd "-nullvalue" ""] 162 set rc [lindex $res 0] 163 list $rc \ 164 [regexp {Error: missing argument to -nullvalue} $res] 165 } {1 1} 166 167 # -version show SQLite version 168 do_test shell1-1.16.1 { 169 set x [catchcmd "-version test.db" ""] 170 } {/3.[0-9.]+ 20\d\d-[01]\d-\d\d \d\d:\d\d:\d\d [0-9a-f]+/} 171 172 #---------------------------------------------------------------------------- 173 # Test cases shell1-2.*: Basic "dot" command token parsing. 174 # 175 176 # check first token handling 177 do_test shell1-2.1.1 { 178 catchcmd "test.db" ".foo" 179 } {1 {Error: unknown command or invalid arguments: "foo". Enter ".help" for help}} 180 do_test shell1-2.1.2 { 181 catchcmd "test.db" ".\"foo OFF\"" 182 } {1 {Error: unknown command or invalid arguments: "foo OFF". Enter ".help" for help}} 183 do_test shell1-2.1.3 { 184 catchcmd "test.db" ".\'foo OFF\'" 185 } {1 {Error: unknown command or invalid arguments: "foo OFF". Enter ".help" for help}} 186 187 # unbalanced quotes 188 do_test shell1-2.2.1 { 189 catchcmd "test.db" ".\"foo OFF" 190 } {1 {Error: unknown command or invalid arguments: "foo OFF". Enter ".help" for help}} 191 do_test shell1-2.2.2 { 192 catchcmd "test.db" ".\'foo OFF" 193 } {1 {Error: unknown command or invalid arguments: "foo OFF". Enter ".help" for help}} 194 do_test shell1-2.2.3 { 195 catchcmd "test.db" ".explain \"OFF" 196 } {0 {}} 197 do_test shell1-2.2.4 { 198 catchcmd "test.db" ".explain \'OFF" 199 } {0 {}} 200 do_test shell1-2.2.5 { 201 catchcmd "test.db" ".mode \"insert FOO" 202 } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} 203 do_test shell1-2.2.6 { 204 catchcmd "test.db" ".mode \'insert FOO" 205 } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} 206 207 # check multiple tokens, and quoted tokens 208 do_test shell1-2.3.1 { 209 catchcmd "test.db" ".explain 1" 210 } {0 {}} 211 do_test shell1-2.3.2 { 212 catchcmd "test.db" ".explain on" 213 } {0 {}} 214 do_test shell1-2.3.3 { 215 catchcmd "test.db" ".explain \"1 2 3\"" 216 } {1 {ERROR: Not a boolean value: "1 2 3". Assuming "no".}} 217 do_test shell1-2.3.4 { 218 catchcmd "test.db" ".explain \"OFF\"" 219 } {0 {}} 220 do_test shell1-2.3.5 { 221 catchcmd "test.db" ".\'explain\' \'OFF\'" 222 } {0 {}} 223 do_test shell1-2.3.6 { 224 catchcmd "test.db" ".explain \'OFF\'" 225 } {0 {}} 226 do_test shell1-2.3.7 { 227 catchcmd "test.db" ".\'explain\' \'OFF\'" 228 } {0 {}} 229 230 # check quoted args are unquoted 231 do_test shell1-2.4.1 { 232 catchcmd "test.db" ".mode FOO" 233 } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} 234 do_test shell1-2.4.2 { 235 catchcmd "test.db" ".mode csv" 236 } {0 {}} 237 do_test shell1-2.4.2 { 238 catchcmd "test.db" ".mode \"csv\"" 239 } {0 {}} 240 241 242 #---------------------------------------------------------------------------- 243 # Test cases shell1-3.*: Basic test that "dot" command can be called. 244 # 245 246 # .backup ?DB? FILE Backup DB (default "main") to FILE 247 do_test shell1-3.1.1 { 248 catchcmd "test.db" ".backup" 249 } {1 {missing FILENAME argument on .backup}} 250 do_test shell1-3.1.2 { 251 catchcmd "test.db" ".backup FOO" 252 } {0 {}} 253 do_test shell1-3.1.3 { 254 catchcmd "test.db" ".backup FOO BAR" 255 } {1 {Error: unknown database FOO}} 256 do_test shell1-3.1.4 { 257 # too many arguments 258 catchcmd "test.db" ".backup FOO BAR BAD" 259 } {1 {too many arguments to .backup}} 260 261 # .bail ON|OFF Stop after hitting an error. Default OFF 262 do_test shell1-3.2.1 { 263 catchcmd "test.db" ".bail" 264 } {1 {Usage: .bail on|off}} 265 do_test shell1-3.2.2 { 266 catchcmd "test.db" ".bail ON" 267 } {0 {}} 268 do_test shell1-3.2.3 { 269 catchcmd "test.db" ".bail OFF" 270 } {0 {}} 271 do_test shell1-3.2.4 { 272 # too many arguments 273 catchcmd "test.db" ".bail OFF BAD" 274 } {1 {Usage: .bail on|off}} 275 276 ifcapable vtab { 277 # .databases List names and files of attached databases 278 do_test shell1-3.3.1 { 279 catchcmd "-csv test.db" ".databases" 280 } "/0.+main.+[string map {/ ".{1,2}"} [string range [get_pwd] 0 10]].*/" 281 do_test shell1-3.3.2 { 282 # extra arguments ignored 283 catchcmd "test.db" ".databases BAD" 284 } "/0.+main.+[string map {/ ".{1,2}"} [string range [get_pwd] 0 10]].*/" 285 } 286 287 # .dump ?TABLE? ... Dump the database in an SQL text format 288 # If TABLE specified, only dump tables matching 289 # LIKE pattern TABLE. 290 do_test shell1-3.4.1 { 291 set res [catchcmd "test.db" ".dump"] 292 list [regexp {BEGIN TRANSACTION;} $res] \ 293 [regexp {COMMIT;} $res] 294 } {1 1} 295 do_test shell1-3.4.2 { 296 set res [catchcmd "test.db" ".dump FOO"] 297 list [regexp {BEGIN TRANSACTION;} $res] \ 298 [regexp {COMMIT;} $res] 299 } {1 1} 300 do_test shell1-3.4.3 { 301 # too many arguments 302 catchcmd "test.db" ".dump FOO BAD" 303 } {1 {Usage: .dump ?--preserve-rowids? ?--newlines? ?LIKE-PATTERN?}} 304 305 # .echo ON|OFF Turn command echo on or off 306 do_test shell1-3.5.1 { 307 catchcmd "test.db" ".echo" 308 } {1 {Usage: .echo on|off}} 309 do_test shell1-3.5.2 { 310 catchcmd "test.db" ".echo ON" 311 } {0 {}} 312 do_test shell1-3.5.3 { 313 catchcmd "test.db" ".echo OFF" 314 } {0 {}} 315 do_test shell1-3.5.4 { 316 # too many arguments 317 catchcmd "test.db" ".echo OFF BAD" 318 } {1 {Usage: .echo on|off}} 319 320 # .exit Exit this program 321 do_test shell1-3.6.1 { 322 catchcmd "test.db" ".exit" 323 } {0 {}} 324 325 # .explain ON|OFF Turn output mode suitable for EXPLAIN on or off. 326 do_test shell1-3.7.1 { 327 catchcmd "test.db" ".explain" 328 # explain is the exception to the booleans. without an option, it turns it on. 329 } {0 {}} 330 do_test shell1-3.7.2 { 331 catchcmd "test.db" ".explain ON" 332 } {0 {}} 333 do_test shell1-3.7.3 { 334 catchcmd "test.db" ".explain OFF" 335 } {0 {}} 336 do_test shell1-3.7.4 { 337 # extra arguments ignored 338 catchcmd "test.db" ".explain OFF BAD" 339 } {0 {}} 340 341 342 # .header(s) ON|OFF Turn display of headers on or off 343 do_test shell1-3.9.1 { 344 catchcmd "test.db" ".header" 345 } {1 {Usage: .headers on|off}} 346 do_test shell1-3.9.2 { 347 catchcmd "test.db" ".header ON" 348 } {0 {}} 349 do_test shell1-3.9.3 { 350 catchcmd "test.db" ".header OFF" 351 } {0 {}} 352 do_test shell1-3.9.4 { 353 # too many arguments 354 catchcmd "test.db" ".header OFF BAD" 355 } {1 {Usage: .headers on|off}} 356 357 do_test shell1-3.9.5 { 358 catchcmd "test.db" ".headers" 359 } {1 {Usage: .headers on|off}} 360 do_test shell1-3.9.6 { 361 catchcmd "test.db" ".headers ON" 362 } {0 {}} 363 do_test shell1-3.9.7 { 364 catchcmd "test.db" ".headers OFF" 365 } {0 {}} 366 do_test shell1-3.9.8 { 367 # too many arguments 368 catchcmd "test.db" ".headers OFF BAD" 369 } {1 {Usage: .headers on|off}} 370 371 # .help Show this message 372 do_test shell1-3.10.1 { 373 set res [catchcmd "test.db" ".help"] 374 # look for a few of the possible help commands 375 list [regexp {.help} $res] \ 376 [regexp {.quit} $res] \ 377 [regexp {.show} $res] 378 } {1 1 1} 379 do_test shell1-3.10.2 { 380 # we allow .help to take extra args (it is help after all) 381 set res [catchcmd "test.db" ".help BAD"] 382 # look for a few of the possible help commands 383 list [regexp {.help} $res] \ 384 [regexp {.quit} $res] \ 385 [regexp {.show} $res] 386 } {1 1 1} 387 388 # .import FILE TABLE Import data from FILE into TABLE 389 do_test shell1-3.11.1 { 390 catchcmd "test.db" ".import" 391 } {1 {Usage: .import FILE TABLE}} 392 do_test shell1-3.11.2 { 393 catchcmd "test.db" ".import FOO" 394 } {1 {Usage: .import FILE TABLE}} 395 #do_test shell1-3.11.2 { 396 # catchcmd "test.db" ".import FOO BAR" 397 #} {1 {Error: no such table: BAR}} 398 do_test shell1-3.11.3 { 399 # too many arguments 400 catchcmd "test.db" ".import FOO BAR BAD" 401 } {1 {Usage: .import FILE TABLE}} 402 403 # .indexes ?TABLE? Show names of all indexes 404 # If TABLE specified, only show indexes for tables 405 # matching LIKE pattern TABLE. 406 do_test shell1-3.12.1 { 407 catchcmd "test.db" ".indexes" 408 } {0 {}} 409 do_test shell1-3.12.2 { 410 catchcmd "test.db" ".indexes FOO" 411 } {0 {}} 412 do_test shell1-3.12.2-legacy { 413 catchcmd "test.db" ".indices FOO" 414 } {0 {}} 415 do_test shell1-3.12.3 { 416 # too many arguments 417 catchcmd "test.db" ".indexes FOO BAD" 418 } {1 {Usage: .indexes ?LIKE-PATTERN?}} 419 420 # .mode MODE ?TABLE? Set output mode where MODE is one of: 421 # ascii Columns/rows delimited by 0x1F and 0x1E 422 # csv Comma-separated values 423 # column Left-aligned columns. (See .width) 424 # html HTML <table> code 425 # insert SQL insert statements for TABLE 426 # line One value per line 427 # list Values delimited by .separator strings 428 # tabs Tab-separated values 429 # tcl TCL list elements 430 do_test shell1-3.13.1 { 431 catchcmd "test.db" ".mode" 432 } {0 {current output mode: list}} 433 do_test shell1-3.13.2 { 434 catchcmd "test.db" ".mode FOO" 435 } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} 436 do_test shell1-3.13.3 { 437 catchcmd "test.db" ".mode csv" 438 } {0 {}} 439 do_test shell1-3.13.4 { 440 catchcmd "test.db" ".mode column" 441 } {0 {}} 442 do_test shell1-3.13.5 { 443 catchcmd "test.db" ".mode html" 444 } {0 {}} 445 do_test shell1-3.13.6 { 446 catchcmd "test.db" ".mode insert" 447 } {0 {}} 448 do_test shell1-3.13.7 { 449 catchcmd "test.db" ".mode line" 450 } {0 {}} 451 do_test shell1-3.13.8 { 452 catchcmd "test.db" ".mode list" 453 } {0 {}} 454 do_test shell1-3.13.9 { 455 catchcmd "test.db" ".mode tabs" 456 } {0 {}} 457 do_test shell1-3.13.10 { 458 catchcmd "test.db" ".mode tcl" 459 } {0 {}} 460 do_test shell1-3.13.11 { 461 # extra arguments ignored 462 catchcmd "test.db" ".mode tcl BAD" 463 } {0 {}} 464 465 # don't allow partial mode type matches 466 do_test shell1-3.13.12 { 467 catchcmd "test.db" ".mode l" 468 } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} 469 do_test shell1-3.13.13 { 470 catchcmd "test.db" ".mode li" 471 } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} 472 do_test shell1-3.13.14 { 473 catchcmd "test.db" ".mode lin" 474 } {0 {}} 475 476 # .nullvalue STRING Print STRING in place of NULL values 477 do_test shell1-3.14.1 { 478 catchcmd "test.db" ".nullvalue" 479 } {1 {Usage: .nullvalue STRING}} 480 do_test shell1-3.14.2 { 481 catchcmd "test.db" ".nullvalue FOO" 482 } {0 {}} 483 do_test shell1-3.14.3 { 484 # too many arguments 485 catchcmd "test.db" ".nullvalue FOO BAD" 486 } {1 {Usage: .nullvalue STRING}} 487 488 # .output FILENAME Send output to FILENAME 489 do_test shell1-3.15.1 { 490 catchcmd "test.db" ".output" 491 } {0 {}} 492 do_test shell1-3.15.2 { 493 catchcmd "test.db" ".output FOO" 494 } {0 {}} 495 do_test shell1-3.15.3 { 496 # too many arguments 497 catchcmd "test.db" ".output FOO BAD" 498 } {1 {Usage: .output FILE}} 499 500 # .output stdout Send output to the screen 501 do_test shell1-3.16.1 { 502 catchcmd "test.db" ".output stdout" 503 } {0 {}} 504 do_test shell1-3.16.2 { 505 # too many arguments 506 catchcmd "test.db" ".output stdout BAD" 507 } {1 {Usage: .output FILE}} 508 509 # .prompt MAIN CONTINUE Replace the standard prompts 510 do_test shell1-3.17.1 { 511 catchcmd "test.db" ".prompt" 512 } {0 {}} 513 do_test shell1-3.17.2 { 514 catchcmd "test.db" ".prompt FOO" 515 } {0 {}} 516 do_test shell1-3.17.3 { 517 catchcmd "test.db" ".prompt FOO BAR" 518 } {0 {}} 519 do_test shell1-3.17.4 { 520 # too many arguments 521 catchcmd "test.db" ".prompt FOO BAR BAD" 522 } {0 {}} 523 524 # .quit Exit this program 525 do_test shell1-3.18.1 { 526 catchcmd "test.db" ".quit" 527 } {0 {}} 528 do_test shell1-3.18.2 { 529 # too many arguments 530 catchcmd "test.db" ".quit BAD" 531 } {0 {}} 532 533 # .read FILENAME Execute SQL in FILENAME 534 do_test shell1-3.19.1 { 535 catchcmd "test.db" ".read" 536 } {1 {Usage: .read FILE}} 537 do_test shell1-3.19.2 { 538 forcedelete FOO 539 catchcmd "test.db" ".read FOO" 540 } {1 {Error: cannot open "FOO"}} 541 do_test shell1-3.19.3 { 542 # too many arguments 543 catchcmd "test.db" ".read FOO BAD" 544 } {1 {Usage: .read FILE}} 545 546 # .restore ?DB? FILE Restore content of DB (default "main") from FILE 547 do_test shell1-3.20.1 { 548 catchcmd "test.db" ".restore" 549 } {1 {Usage: .restore ?DB? FILE}} 550 do_test shell1-3.20.2 { 551 catchcmd "test.db" ".restore FOO" 552 } {0 {}} 553 do_test shell1-3.20.3 { 554 catchcmd "test.db" ".restore FOO BAR" 555 } {1 {Error: unknown database FOO}} 556 do_test shell1-3.20.4 { 557 # too many arguments 558 catchcmd "test.db" ".restore FOO BAR BAD" 559 } {1 {Usage: .restore ?DB? FILE}} 560 561 ifcapable vtab { 562 # .schema ?TABLE? Show the CREATE statements 563 # If TABLE specified, only show tables matching 564 # LIKE pattern TABLE. 565 do_test shell1-3.21.1 { 566 catchcmd "test.db" ".schema" 567 } {0 {}} 568 do_test shell1-3.21.2 { 569 catchcmd "test.db" ".schema FOO" 570 } {0 {}} 571 do_test shell1-3.21.3 { 572 # too many arguments 573 catchcmd "test.db" ".schema FOO BAD" 574 } {1 {Usage: .schema ?--indent? ?LIKE-PATTERN?}} 575 576 do_test shell1-3.21.4 { 577 catchcmd "test.db" { 578 CREATE TABLE t1(x); 579 CREATE VIEW v2 AS SELECT x+1 AS y FROM t1; 580 CREATE VIEW v1 AS SELECT y+1 FROM v2; 581 } 582 catchcmd "test.db" ".schema" 583 } {0 {CREATE TABLE t1(x); 584 CREATE VIEW v2 AS SELECT x+1 AS y FROM t1; 585 CREATE VIEW v1 AS SELECT y+1 FROM v2;}} 586 db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;} 587 } 588 589 # .separator STRING Change column separator used by output and .import 590 do_test shell1-3.22.1 { 591 catchcmd "test.db" ".separator" 592 } {1 {Usage: .separator COL ?ROW?}} 593 do_test shell1-3.22.2 { 594 catchcmd "test.db" ".separator FOO" 595 } {0 {}} 596 do_test shell1-3.22.3 { 597 catchcmd "test.db" ".separator ABC XYZ" 598 } {0 {}} 599 do_test shell1-3.22.4 { 600 # too many arguments 601 catchcmd "test.db" ".separator FOO BAD BAD2" 602 } {1 {Usage: .separator COL ?ROW?}} 603 604 # .show Show the current values for various settings 605 do_test shell1-3.23.1 { 606 set res [catchcmd "test.db" ".show"] 607 list [regexp {echo:} $res] \ 608 [regexp {explain:} $res] \ 609 [regexp {headers:} $res] \ 610 [regexp {mode:} $res] \ 611 [regexp {nullvalue:} $res] \ 612 [regexp {output:} $res] \ 613 [regexp {colseparator:} $res] \ 614 [regexp {rowseparator:} $res] \ 615 [regexp {stats:} $res] \ 616 [regexp {width:} $res] 617 } {1 1 1 1 1 1 1 1 1 1} 618 do_test shell1-3.23.2 { 619 # too many arguments 620 catchcmd "test.db" ".show BAD" 621 } {1 {Usage: .show}} 622 623 # .stats ON|OFF Turn stats on or off 624 #do_test shell1-3.23b.1 { 625 # catchcmd "test.db" ".stats" 626 #} {1 {Usage: .stats on|off}} 627 do_test shell1-3.23b.2 { 628 catchcmd "test.db" ".stats ON" 629 } {0 {}} 630 do_test shell1-3.23b.3 { 631 catchcmd "test.db" ".stats OFF" 632 } {0 {}} 633 do_test shell1-3.23b.4 { 634 # too many arguments 635 catchcmd "test.db" ".stats OFF BAD" 636 } {1 {Usage: .stats ?on|off?}} 637 638 # .tables ?TABLE? List names of tables 639 # If TABLE specified, only list tables matching 640 # LIKE pattern TABLE. 641 do_test shell1-3.24.1 { 642 catchcmd "test.db" ".tables" 643 } {0 {}} 644 do_test shell1-3.24.2 { 645 catchcmd "test.db" ".tables FOO" 646 } {0 {}} 647 do_test shell1-3.24.3 { 648 # too many arguments 649 catchcmd "test.db" ".tables FOO BAD" 650 } {0 {}} 651 652 # .timeout MS Try opening locked tables for MS milliseconds 653 do_test shell1-3.25.1 { 654 catchcmd "test.db" ".timeout" 655 } {0 {}} 656 do_test shell1-3.25.2 { 657 catchcmd "test.db" ".timeout zzz" 658 # this should be treated the same as a '0' timeout 659 } {0 {}} 660 do_test shell1-3.25.3 { 661 catchcmd "test.db" ".timeout 1" 662 } {0 {}} 663 do_test shell1-3.25.4 { 664 # too many arguments 665 catchcmd "test.db" ".timeout 1 BAD" 666 } {0 {}} 667 668 # .width NUM NUM ... Set column widths for "column" mode 669 do_test shell1-3.26.1 { 670 catchcmd "test.db" ".width" 671 } {0 {}} 672 do_test shell1-3.26.2 { 673 catchcmd "test.db" ".width xxx" 674 # this should be treated the same as a '0' width for col 1 675 } {0 {}} 676 do_test shell1-3.26.3 { 677 catchcmd "test.db" ".width xxx yyy" 678 # this should be treated the same as a '0' width for col 1 and 2 679 } {0 {}} 680 do_test shell1-3.26.4 { 681 catchcmd "test.db" ".width 1 1" 682 # this should be treated the same as a '1' width for col 1 and 2 683 } {0 {}} 684 do_test shell1-3.26.5 { 685 catchcmd "test.db" ".mode column\n.width 10 -10\nSELECT 'abcdefg', 123456;" 686 # this should be treated the same as a '1' width for col 1 and 2 687 } {0 {abcdefg 123456}} 688 do_test shell1-3.26.6 { 689 catchcmd "test.db" ".mode column\n.width -10 10\nSELECT 'abcdefg', 123456;" 690 # this should be treated the same as a '1' width for col 1 and 2 691 } {0 { abcdefg 123456 }} 692 693 694 # .timer ON|OFF Turn the CPU timer measurement on or off 695 do_test shell1-3.27.1 { 696 catchcmd "test.db" ".timer" 697 } {1 {Usage: .timer on|off}} 698 do_test shell1-3.27.2 { 699 catchcmd "test.db" ".timer ON" 700 } {0 {}} 701 do_test shell1-3.27.3 { 702 catchcmd "test.db" ".timer OFF" 703 } {0 {}} 704 do_test shell1-3.27.4 { 705 # too many arguments 706 catchcmd "test.db" ".timer OFF BAD" 707 } {1 {Usage: .timer on|off}} 708 709 do_test shell1-3-28.1 { 710 catchcmd test.db \ 711 ".log stdout\nSELECT coalesce(sqlite_log(123,'hello'),'456');" 712 } "0 {(123) hello\n456}" 713 714 do_test shell1-3-29.1 { 715 catchcmd "test.db" ".print this is a test" 716 } {0 {this is a test}} 717 718 # dot-command argument quoting 719 do_test shell1-3-30.1 { 720 catchcmd {test.db} {.print "this\"is'a\055test" 'this\"is\\a\055test'} 721 } {0 {this"is'a-test this\"is\\a\055test}} 722 do_test shell1-3-31.1 { 723 catchcmd {test.db} {.print "this\nis\ta\\test" 'this\nis\ta\\test'} 724 } [list 0 "this\nis\ta\\test this\\nis\\ta\\\\test"] 725 726 727 # Test the output of the ".dump" command 728 # 729 do_test shell1-4.1 { 730 db close 731 forcedelete test.db 732 sqlite3 db test.db 733 db eval { 734 PRAGMA encoding=UTF16; 735 CREATE TABLE t1(x); 736 INSERT INTO t1 VALUES(null), (''), (1), (2.25), ('hello'), (x'807f'); 737 CREATE TABLE t3(x,y); 738 INSERT INTO t3 VALUES(1,null), (2,''), (3,1), 739 (4,2.25), (5,'hello'), (6,x'807f'); 740 } 741 catchcmd test.db {.dump} 742 } {0 {PRAGMA foreign_keys=OFF; 743 BEGIN TRANSACTION; 744 CREATE TABLE t1(x); 745 INSERT INTO t1 VALUES(NULL); 746 INSERT INTO t1 VALUES(''); 747 INSERT INTO t1 VALUES(1); 748 INSERT INTO t1 VALUES(2.25); 749 INSERT INTO t1 VALUES('hello'); 750 INSERT INTO t1 VALUES(X'807f'); 751 CREATE TABLE t3(x,y); 752 INSERT INTO t3 VALUES(1,NULL); 753 INSERT INTO t3 VALUES(2,''); 754 INSERT INTO t3 VALUES(3,1); 755 INSERT INTO t3 VALUES(4,2.25); 756 INSERT INTO t3 VALUES(5,'hello'); 757 INSERT INTO t3 VALUES(6,X'807f'); 758 COMMIT;}} 759 760 761 ifcapable vtab { 762 763 # The --preserve-rowids option to .dump 764 # 765 do_test shell1-4.1.1 { 766 catchcmd test.db {.dump --preserve-rowids} 767 } {0 {PRAGMA foreign_keys=OFF; 768 BEGIN TRANSACTION; 769 CREATE TABLE t1(x); 770 INSERT INTO t1(rowid,x) VALUES(1,NULL); 771 INSERT INTO t1(rowid,x) VALUES(2,''); 772 INSERT INTO t1(rowid,x) VALUES(3,1); 773 INSERT INTO t1(rowid,x) VALUES(4,2.25); 774 INSERT INTO t1(rowid,x) VALUES(5,'hello'); 775 INSERT INTO t1(rowid,x) VALUES(6,X'807f'); 776 CREATE TABLE t3(x,y); 777 INSERT INTO t3(rowid,x,y) VALUES(1,1,NULL); 778 INSERT INTO t3(rowid,x,y) VALUES(2,2,''); 779 INSERT INTO t3(rowid,x,y) VALUES(3,3,1); 780 INSERT INTO t3(rowid,x,y) VALUES(4,4,2.25); 781 INSERT INTO t3(rowid,x,y) VALUES(5,5,'hello'); 782 INSERT INTO t3(rowid,x,y) VALUES(6,6,X'807f'); 783 COMMIT;}} 784 785 # If the table contains an INTEGER PRIMARY KEY, do not record a separate 786 # rowid column in the output. 787 # 788 do_test shell1-4.1.2 { 789 db close 790 forcedelete test2.db 791 sqlite3 db test2.db 792 db eval { 793 CREATE TABLE t1(x INTEGER PRIMARY KEY, y); 794 INSERT INTO t1 VALUES(1,null), (2,''), (3,1), 795 (4,2.25), (5,'hello'), (6,x'807f'); 796 } 797 catchcmd test2.db {.dump --preserve-rowids} 798 } {0 {PRAGMA foreign_keys=OFF; 799 BEGIN TRANSACTION; 800 CREATE TABLE t1(x INTEGER PRIMARY KEY, y); 801 INSERT INTO t1 VALUES(1,NULL); 802 INSERT INTO t1 VALUES(2,''); 803 INSERT INTO t1 VALUES(3,1); 804 INSERT INTO t1 VALUES(4,2.25); 805 INSERT INTO t1 VALUES(5,'hello'); 806 INSERT INTO t1 VALUES(6,X'807f'); 807 COMMIT;}} 808 809 # Verify that the table named [table] is correctly quoted and that 810 # an INTEGER PRIMARY KEY DESC is not an alias for the rowid. 811 # 812 do_test shell1-4.1.3 { 813 db close 814 forcedelete test2.db 815 sqlite3 db test2.db 816 db eval { 817 CREATE TABLE [table](x INTEGER PRIMARY KEY DESC, y); 818 INSERT INTO [table] VALUES(1,null), (12,''), (23,1), 819 (34,2.25), (45,'hello'), (56,x'807f'); 820 } 821 catchcmd test2.db {.dump --preserve-rowids} 822 } {0 {PRAGMA foreign_keys=OFF; 823 BEGIN TRANSACTION; 824 CREATE TABLE [table](x INTEGER PRIMARY KEY DESC, y); 825 INSERT INTO "table"(rowid,x,y) VALUES(1,1,NULL); 826 INSERT INTO "table"(rowid,x,y) VALUES(2,12,''); 827 INSERT INTO "table"(rowid,x,y) VALUES(3,23,1); 828 INSERT INTO "table"(rowid,x,y) VALUES(4,34,2.25); 829 INSERT INTO "table"(rowid,x,y) VALUES(5,45,'hello'); 830 INSERT INTO "table"(rowid,x,y) VALUES(6,56,X'807f'); 831 COMMIT;}} 832 833 # Do not record rowids for a WITHOUT ROWID table. Also check correct quoting 834 # of table names that contain odd characters. 835 # 836 do_test shell1-4.1.4 { 837 db close 838 forcedelete test2.db 839 sqlite3 db test2.db 840 db eval { 841 CREATE TABLE [ta<>ble](x INTEGER PRIMARY KEY, y) WITHOUT ROWID; 842 INSERT INTO [ta<>ble] VALUES(1,null), (12,''), (23,1), 843 (34,2.25), (45,'hello'), (56,x'807f'); 844 } 845 catchcmd test2.db {.dump --preserve-rowids} 846 } {0 {PRAGMA foreign_keys=OFF; 847 BEGIN TRANSACTION; 848 CREATE TABLE [ta<>ble](x INTEGER PRIMARY KEY, y) WITHOUT ROWID; 849 INSERT INTO "ta<>ble" VALUES(1,NULL); 850 INSERT INTO "ta<>ble" VALUES(12,''); 851 INSERT INTO "ta<>ble" VALUES(23,1); 852 INSERT INTO "ta<>ble" VALUES(34,2.25); 853 INSERT INTO "ta<>ble" VALUES(45,'hello'); 854 INSERT INTO "ta<>ble" VALUES(56,X'807f'); 855 COMMIT;}} 856 857 # Do not record rowids if the rowid is inaccessible 858 # 859 do_test shell1-4.1.5 { 860 db close 861 forcedelete test2.db 862 sqlite3 db test2.db 863 db eval { 864 CREATE TABLE t1(_ROWID_,rowid,oid); 865 INSERT INTO t1 VALUES(1,null,'alpha'), (12,'',99), (23,1,x'b0b1b2'); 866 } 867 catchcmd test2.db {.dump --preserve-rowids} 868 } {0 {PRAGMA foreign_keys=OFF; 869 BEGIN TRANSACTION; 870 CREATE TABLE t1(_ROWID_,rowid,oid); 871 INSERT INTO t1 VALUES(1,NULL,'alpha'); 872 INSERT INTO t1 VALUES(12,'',99); 873 INSERT INTO t1 VALUES(23,1,X'b0b1b2'); 874 COMMIT;}} 875 876 } else { 877 878 do_test shell1-4.1.6 { 879 db close 880 forcedelete test2.db 881 sqlite3 db test2.db 882 db eval { 883 CREATE TABLE t1(x INTEGER PRIMARY KEY, y); 884 INSERT INTO t1 VALUES(1,null), (2,''), (3,1), 885 (4,2.25), (5,'hello'), (6,x'807f'); 886 } 887 catchcmd test2.db {.dump --preserve-rowids} 888 } {1 {The --preserve-rowids option is not compatible with SQLITE_OMIT_VIRTUALTABLE}} 889 890 } 891 892 893 # Test the output of ".mode insert" 894 # 895 do_test shell1-4.2.1 { 896 catchcmd test.db ".mode insert t1\nselect * from t1;" 897 } {0 {INSERT INTO t1 VALUES(NULL); 898 INSERT INTO t1 VALUES(''); 899 INSERT INTO t1 VALUES(1); 900 INSERT INTO t1 VALUES(2.25); 901 INSERT INTO t1 VALUES('hello'); 902 INSERT INTO t1 VALUES(X'807f');}} 903 904 # Test the output of ".mode insert" with headers 905 # 906 do_test shell1-4.2.2 { 907 catchcmd test.db ".mode insert t1\n.headers on\nselect * from t1;" 908 } {0 {INSERT INTO t1(x) VALUES(NULL); 909 INSERT INTO t1(x) VALUES(''); 910 INSERT INTO t1(x) VALUES(1); 911 INSERT INTO t1(x) VALUES(2.25); 912 INSERT INTO t1(x) VALUES('hello'); 913 INSERT INTO t1(x) VALUES(X'807f');}} 914 915 # Test the output of ".mode insert" 916 # 917 do_test shell1-4.2.3 { 918 catchcmd test.db ".mode insert t3\nselect * from t3;" 919 } {0 {INSERT INTO t3 VALUES(1,NULL); 920 INSERT INTO t3 VALUES(2,''); 921 INSERT INTO t3 VALUES(3,1); 922 INSERT INTO t3 VALUES(4,2.25); 923 INSERT INTO t3 VALUES(5,'hello'); 924 INSERT INTO t3 VALUES(6,X'807f');}} 925 926 # Test the output of ".mode insert" with headers 927 # 928 do_test shell1-4.2.4 { 929 catchcmd test.db ".mode insert t3\n.headers on\nselect * from t3;" 930 } {0 {INSERT INTO t3(x,y) VALUES(1,NULL); 931 INSERT INTO t3(x,y) VALUES(2,''); 932 INSERT INTO t3(x,y) VALUES(3,1); 933 INSERT INTO t3(x,y) VALUES(4,2.25); 934 INSERT INTO t3(x,y) VALUES(5,'hello'); 935 INSERT INTO t3(x,y) VALUES(6,X'807f');}} 936 937 # Test the output of ".mode tcl" 938 # 939 do_test shell1-4.3 { 940 db close 941 forcedelete test.db 942 sqlite3 db test.db 943 db eval { 944 PRAGMA encoding=UTF8; 945 CREATE TABLE t1(x); 946 INSERT INTO t1 VALUES(null), (''), (1), (2.25), ('hello'), (x'807f'); 947 } 948 catchcmd test.db ".mode tcl\nselect * from t1;" 949 } {0 {"" 950 "" 951 "1" 952 "2.25" 953 "hello" 954 "\200\177"}} 955 956 # Test the output of ".mode tcl" with multiple columns 957 # 958 do_test shell1-4.4 { 959 db eval { 960 CREATE TABLE t2(x,y); 961 INSERT INTO t2 VALUES(null, ''), (1, 2.25), ('hello', x'807f'); 962 } 963 catchcmd test.db ".mode tcl\nselect * from t2;" 964 } {0 {"" "" 965 "1" "2.25" 966 "hello" "\200\177"}} 967 968 # Test the output of ".mode tcl" with ".nullvalue" 969 # 970 do_test shell1-4.5 { 971 catchcmd test.db ".mode tcl\n.nullvalue NULL\nselect * from t2;" 972 } {0 {"NULL" "" 973 "1" "2.25" 974 "hello" "\200\177"}} 975 976 # Test the output of ".mode tcl" with Tcl reserved characters 977 # 978 do_test shell1-4.6 { 979 db eval { 980 CREATE TABLE tcl1(x); 981 INSERT INTO tcl1 VALUES('"'), ('['), (']'), ('\{'), ('\}'), (';'), ('$'); 982 } 983 foreach {x y} [catchcmd test.db ".mode tcl\nselect * from tcl1;"] break 984 list $x $y [llength $y] 985 } {0 {"\"" 986 "[" 987 "]" 988 "\\{" 989 "\\}" 990 ";" 991 "$"} 7} 992 993 # Test using arbitrary byte data with the shell via standard input/output. 994 # 995 do_test shell1-5.0 { 996 # 997 # NOTE: Skip NUL byte because it appears to be incompatible with command 998 # shell argument parsing. 999 # 1000 for {set i 1} {$i < 256} {incr i} { 1001 # 1002 # NOTE: Due to how the Tcl [exec] command works (i.e. where it treats 1003 # command channels opened for it as textual ones), the carriage 1004 # return character (and on Windows, the end-of-file character) 1005 # cannot be used here. 1006 # 1007 if {$i==0x0D || ($tcl_platform(platform)=="windows" && $i==0x1A)} { 1008 continue 1009 } 1010 if {$i>=0xE0 && $tcl_platform(os)=="OpenBSD"} continue 1011 if {$i>=0xE0 && $i<=0xEF && $tcl_platform(os)=="Linux"} continue 1012 set hex [format %02X $i] 1013 set char [subst \\x$hex]; set oldChar $char 1014 set escapes [list] 1015 if {$tcl_platform(platform)=="windows"} { 1016 # 1017 # NOTE: On Windows, we need to escape all the whitespace characters, 1018 # the alarm (\a) character, and those with special meaning to 1019 # the SQLite shell itself. 1020 # 1021 set escapes [list \ 1022 \a \\a \b \\b \t \\t \n \\n \v \\v \f \\f \r \\r \ 1023 " " "\" \"" \" \\\" ' \"'\" \\ \\\\] 1024 } else { 1025 # 1026 # NOTE: On Unix, we need to escape most of the whitespace characters 1027 # and those with special meaning to the SQLite shell itself. 1028 # The alarm (\a), backspace (\b), and carriage-return (\r) 1029 # characters do not appear to require escaping on Unix. For 1030 # the alarm and backspace characters, this is probably due to 1031 # differences in the command shell. For the carriage-return, 1032 # it is probably due to differences in how Tcl handles command 1033 # channel end-of-line translations. 1034 # 1035 set escapes [list \ 1036 \t \\t \n \\n \v \\v \f \\f \ 1037 " " "\" \"" \" \\\" ' \"'\" \\ \\\\] 1038 } 1039 set char [string map $escapes $char] 1040 set x [catchcmdex test.db ".print $char\n"] 1041 set code [lindex $x 0] 1042 set res [lindex $x 1] 1043 if {$code ne "0"} { 1044 error "failed with error: $res" 1045 } 1046 if {$res ne "$oldChar\n"} { 1047 if {[llength $res] > 0} { 1048 set got [format %02X [scan $res %c]] 1049 } else { 1050 set got <empty> 1051 } 1052 error "failed with byte $hex mismatch, got $got" 1053 } 1054 } 1055 } {} 1056 1057 # These test cases do not work on MinGW 1058 if 0 { 1059 1060 # The string used here is the word "test" in Chinese. 1061 # In UTF-8, it is encoded as: \xE6\xB5\x8B\xE8\xAF\x95 1062 set test \u6D4B\u8BD5 1063 1064 do_test shell1-6.0 { 1065 set fileName $test; append fileName .db 1066 catch {forcedelete $fileName} 1067 set x [catchcmdex $fileName "CREATE TABLE t1(x);\n.schema\n"] 1068 set code [lindex $x 0] 1069 set res [string trim [lindex $x 1]] 1070 if {$code ne "0"} { 1071 error "failed with error: $res" 1072 } 1073 if {$res ne "CREATE TABLE t1(x);"} { 1074 error "failed with mismatch: $res" 1075 } 1076 if {![file exists $fileName]} { 1077 error "file \"$fileName\" (Unicode) does not exist" 1078 } 1079 forcedelete $fileName 1080 } {} 1081 1082 do_test shell1-6.1 { 1083 catch {forcedelete test3.db} 1084 set x [catchcmdex test3.db \ 1085 "CREATE TABLE [encoding convertto utf-8 $test](x);\n.schema\n"] 1086 set code [lindex $x 0] 1087 set res [string trim [lindex $x 1]] 1088 if {$code ne "0"} { 1089 error "failed with error: $res" 1090 } 1091 if {$res ne "CREATE TABLE ${test}(x);"} { 1092 error "failed with mismatch: $res" 1093 } 1094 forcedelete test3.db 1095 } {} 1096 } 1097 1098 finish_test