blob: b921accca5f431a70bbaff1d314e00644b11f303 [file] [log] [blame]
shaneh1b8f78c2010-08-18 17:16:26 +00001# 2010 August 4
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# These tests are specific to the .import command.
14#
15# $Id: shell5.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $
16#
17
18# Test plan:
19#
20# shell5-1.*: Basic tests specific to the ".import" command.
21#
drh8df91852012-04-24 12:46:05 +000022set testdir [file dirname $argv0]
23source $testdir/tester.tcl
24if {$tcl_platform(platform)=="windows"} {
25 set CLI "sqlite3.exe"
26} else {
27 set CLI "./sqlite3"
shaneh1b8f78c2010-08-18 17:16:26 +000028}
drh8df91852012-04-24 12:46:05 +000029if {![file executable $CLI]} {
30 finish_test
31 return
shaneh1b8f78c2010-08-18 17:16:26 +000032}
drh8df91852012-04-24 12:46:05 +000033db close
34forcedelete test.db test.db-journal test.db-wal
shaneh1b8f78c2010-08-18 17:16:26 +000035
36#----------------------------------------------------------------------------
37# Test cases shell5-1.*: Basic handling of the .import and .separator commands.
38#
39
40# .import FILE TABLE Import data from FILE into TABLE
41do_test shell5-1.1.1 {
42 catchcmd "test.db" ".import"
drhc2ce0be2014-05-29 12:36:14 +000043} {1 {Usage: .import FILE TABLE}}
shaneh1b8f78c2010-08-18 17:16:26 +000044do_test shell5-1.1.2 {
45 catchcmd "test.db" ".import FOO"
drhc2ce0be2014-05-29 12:36:14 +000046} {1 {Usage: .import FILE TABLE}}
drhdb95f682013-06-26 22:46:00 +000047#do_test shell5-1.1.2 {
48# catchcmd "test.db" ".import FOO BAR"
49#} {1 {Error: no such table: BAR}}
shaneh1b8f78c2010-08-18 17:16:26 +000050do_test shell5-1.1.3 {
51 # too many arguments
52 catchcmd "test.db" ".import FOO BAR BAD"
drhc2ce0be2014-05-29 12:36:14 +000053} {1 {Usage: .import FILE TABLE}}
shaneh1b8f78c2010-08-18 17:16:26 +000054
55# .separator STRING Change separator used by output mode and .import
drhc2ce0be2014-05-29 12:36:14 +000056do_test shell5-1.2.1 {
shaneh1b8f78c2010-08-18 17:16:26 +000057 catchcmd "test.db" ".separator"
mistachkine0d68852014-12-11 03:12:33 +000058} {1 {Usage: .separator COL ?ROW?}}
drhc2ce0be2014-05-29 12:36:14 +000059do_test shell5-1.2.2 {
drh6976c212014-07-24 12:09:47 +000060 catchcmd "test.db" ".separator ONE"
shaneh1b8f78c2010-08-18 17:16:26 +000061} {0 {}}
drhc2ce0be2014-05-29 12:36:14 +000062do_test shell5-1.2.3 {
drh6976c212014-07-24 12:09:47 +000063 catchcmd "test.db" ".separator ONE TWO"
64} {0 {}}
65do_test shell5-1.2.4 {
shaneh1b8f78c2010-08-18 17:16:26 +000066 # too many arguments
drh6976c212014-07-24 12:09:47 +000067 catchcmd "test.db" ".separator ONE TWO THREE"
mistachkine0d68852014-12-11 03:12:33 +000068} {1 {Usage: .separator COL ?ROW?}}
shaneh1b8f78c2010-08-18 17:16:26 +000069
mistachkin636bf9f2014-07-19 20:15:16 +000070# column separator should default to "|"
71do_test shell5-1.3.1.1 {
shaneh1b8f78c2010-08-18 17:16:26 +000072 set res [catchcmd "test.db" ".show"]
mistachkin636bf9f2014-07-19 20:15:16 +000073 list [regexp {colseparator: \"\|\"} $res]
74} {1}
75
76# row separator should default to "\n"
77do_test shell5-1.3.1.2 {
78 set res [catchcmd "test.db" ".show"]
79 list [regexp {rowseparator: \"\\n\"} $res]
shaneh1b8f78c2010-08-18 17:16:26 +000080} {1}
81
82# set separator to different value.
83# check that .show reports new value
84do_test shell5-1.3.2 {
85 set res [catchcmd "test.db" {.separator ,
86.show}]
87 list [regexp {separator: \",\"} $res]
88} {1}
89
90# import file doesn't exist
91do_test shell5-1.4.1 {
mistachkin9ac99312013-09-13 23:26:47 +000092 forcedelete FOO
shaneh1b8f78c2010-08-18 17:16:26 +000093 set res [catchcmd "test.db" {CREATE TABLE t1(a, b);
94.import FOO t1}]
95} {1 {Error: cannot open "FOO"}}
96
97# empty import file
98do_test shell5-1.4.2 {
mistachkin9ac99312013-09-13 23:26:47 +000099 forcedelete shell5.csv
shaneh1b8f78c2010-08-18 17:16:26 +0000100 set in [open shell5.csv w]
101 close $in
102 set res [catchcmd "test.db" {.import shell5.csv t1
103SELECT COUNT(*) FROM t1;}]
104} {0 0}
105
106# import file with 1 row, 1 column (expecting 2 cols)
107do_test shell5-1.4.3 {
108 set in [open shell5.csv w]
109 puts $in "1"
110 close $in
111 set res [catchcmd "test.db" {.import shell5.csv t1}]
drhdb95f682013-06-26 22:46:00 +0000112} {1 {shell5.csv:1: expected 2 columns but found 1 - filling the rest with NULL}}
shaneh1b8f78c2010-08-18 17:16:26 +0000113
114# import file with 1 row, 3 columns (expecting 2 cols)
115do_test shell5-1.4.4 {
116 set in [open shell5.csv w]
117 puts $in "1|2|3"
118 close $in
119 set res [catchcmd "test.db" {.import shell5.csv t1}]
drhdb95f682013-06-26 22:46:00 +0000120} {1 {shell5.csv:1: expected 2 columns but found 3 - extras ignored}}
shaneh1b8f78c2010-08-18 17:16:26 +0000121
122# import file with 1 row, 2 columns
123do_test shell5-1.4.5 {
124 set in [open shell5.csv w]
125 puts $in "1|2"
126 close $in
drhdb95f682013-06-26 22:46:00 +0000127 set res [catchcmd "test.db" {DELETE FROM t1;
128.import shell5.csv t1
shaneh1b8f78c2010-08-18 17:16:26 +0000129SELECT COUNT(*) FROM t1;}]
130} {0 1}
131
132# import file with 2 rows, 2 columns
133# note we end up with 3 rows because of the 1 row
134# imported above.
135do_test shell5-1.4.6 {
136 set in [open shell5.csv w]
137 puts $in "2|3"
138 puts $in "3|4"
139 close $in
140 set res [catchcmd "test.db" {.import shell5.csv t1
141SELECT COUNT(*) FROM t1;}]
142} {0 3}
143
144# import file with 1 row, 2 columns, using a comma
145do_test shell5-1.4.7 {
146 set in [open shell5.csv w]
147 puts $in "4,5"
148 close $in
149 set res [catchcmd "test.db" {.separator ,
150.import shell5.csv t1
151SELECT COUNT(*) FROM t1;}]
152} {0 4}
153
154# import file with 1 row, 2 columns, text data
155do_test shell5-1.4.8.1 {
156 set in [open shell5.csv w]
157 puts $in "5|Now is the time for all good men to come to the aid of their country."
158 close $in
159 set res [catchcmd "test.db" {.import shell5.csv t1
160SELECT COUNT(*) FROM t1;}]
161} {0 5}
162
163do_test shell5-1.4.8.2 {
164 catchcmd "test.db" {SELECT b FROM t1 WHERE a='5';}
165} {0 {Now is the time for all good men to come to the aid of their country.}}
166
167# import file with 1 row, 2 columns, quoted text data
168# note that currently sqlite doesn't support quoted fields, and
169# imports the entire field, quotes and all.
170do_test shell5-1.4.9.1 {
171 set in [open shell5.csv w]
172 puts $in "6|'Now is the time for all good men to come to the aid of their country.'"
173 close $in
174 set res [catchcmd "test.db" {.import shell5.csv t1
175SELECT COUNT(*) FROM t1;}]
176} {0 6}
177
178do_test shell5-1.4.9.2 {
179 catchcmd "test.db" {SELECT b FROM t1 WHERE a='6';}
180} {0 {'Now is the time for all good men to come to the aid of their country.'}}
181
182# import file with 1 row, 2 columns, quoted text data
183do_test shell5-1.4.10.1 {
184 set in [open shell5.csv w]
185 puts $in "7|\"Now is the time for all good men to come to the aid of their country.\""
186 close $in
187 set res [catchcmd "test.db" {.import shell5.csv t1
188SELECT COUNT(*) FROM t1;}]
189} {0 7}
190
191do_test shell5-1.4.10.2 {
192 catchcmd "test.db" {SELECT b FROM t1 WHERE a='7';}
drh18f52e02012-01-16 16:56:31 +0000193} {0 {Now is the time for all good men to come to the aid of their country.}}
shaneh1b8f78c2010-08-18 17:16:26 +0000194
195# check importing very long field
196do_test shell5-1.5.1 {
197 set str [string repeat X 999]
198 set in [open shell5.csv w]
199 puts $in "8|$str"
200 close $in
201 set res [catchcmd "test.db" {.import shell5.csv t1
202SELECT length(b) FROM t1 WHERE a='8';}]
203} {0 999}
204
205# try importing into a table with a large number of columns.
206# This is limited by SQLITE_MAX_VARIABLE_NUMBER, which defaults to 999.
207set cols 999
208do_test shell5-1.6.1 {
shaneh1b8f78c2010-08-18 17:16:26 +0000209 set data {}
210 for {set i 1} {$i<$cols} {incr i} {
drhdb95f682013-06-26 22:46:00 +0000211 append data "c$i|"
212 }
213 append data "c$cols\n";
214 for {set i 1} {$i<$cols} {incr i} {
shaneh1b8f78c2010-08-18 17:16:26 +0000215 append data "$i|"
216 }
shaneh1b8f78c2010-08-18 17:16:26 +0000217 append data "$cols"
shaneh1b8f78c2010-08-18 17:16:26 +0000218 set in [open shell5.csv w]
219 puts $in $data
220 close $in
221 set res [catchcmd "test.db" {.import shell5.csv t2
222SELECT COUNT(*) FROM t2;}]
223} {0 1}
224
225# try importing a large number of rows
drh5bde8162013-06-27 14:07:53 +0000226set rows 9999
shaneh1b8f78c2010-08-18 17:16:26 +0000227do_test shell5-1.7.1 {
228 set in [open shell5.csv w]
drhdb95f682013-06-26 22:46:00 +0000229 puts $in a
shaneh1b8f78c2010-08-18 17:16:26 +0000230 for {set i 1} {$i<=$rows} {incr i} {
231 puts $in $i
232 }
233 close $in
drhdb95f682013-06-26 22:46:00 +0000234 set res [catchcmd "test.db" {.mode csv
shaneh1b8f78c2010-08-18 17:16:26 +0000235.import shell5.csv t3
236SELECT COUNT(*) FROM t3;}]
237} [list 0 $rows]
238
drh5bde8162013-06-27 14:07:53 +0000239# Inport from a pipe. (Unix only, as it requires "awk")
240if {$tcl_platform(platform)=="unix"} {
241 do_test shell5-1.8 {
mistachkin9ac99312013-09-13 23:26:47 +0000242 forcedelete test.db
drh5bde8162013-06-27 14:07:53 +0000243 catchcmd test.db {.mode csv
244.import "|awk 'END{print \"x,y\";for(i=1;i<=5;i++){print i \",this is \" i}}'" t1
245SELECT * FROM t1;}
246 } {0 {1,"this is 1"
2472,"this is 2"
2483,"this is 3"
2494,"this is 4"
2505,"this is 5"}}
251}
252
drhf7f8de52013-08-28 11:57:52 +0000253# Import columns containing quoted strings
254do_test shell5-1.9 {
255 set out [open shell5.csv w]
mistachkin9ac99312013-09-13 23:26:47 +0000256 fconfigure $out -translation lf
drhf7f8de52013-08-28 11:57:52 +0000257 puts $out {1,"",11}
258 puts $out {2,"x",22}
259 puts $out {3,"""",33}
260 puts $out {4,"hello",44}
drh868ccf22013-08-28 13:33:40 +0000261 puts $out "5,55,\"\"\r"
drhf7f8de52013-08-28 11:57:52 +0000262 puts $out {6,66,"x"}
263 puts $out {7,77,""""}
264 puts $out {8,88,"hello"}
265 puts $out {"",9,99}
266 puts $out {"x",10,110}
267 puts $out {"""",11,121}
268 puts $out {"hello",12,132}
269 close $out
mistachkin9ac99312013-09-13 23:26:47 +0000270 forcedelete test.db
drhf7f8de52013-08-28 11:57:52 +0000271 catchcmd test.db {.mode csv
272 CREATE TABLE t1(a,b,c);
273.import shell5.csv t1
274 }
275 sqlite3 db test.db
276 db eval {SELECT *, '|' FROM t1 ORDER BY rowid}
277} {1 {} 11 | 2 x 22 | 3 {"} 33 | 4 hello 44 | 5 55 {} | 6 66 x | 7 77 {"} | 8 88 hello | {} 9 99 | x 10 110 | {"} 11 121 | hello 12 132 |}
278db close
279
drha81ad172013-12-11 14:00:04 +0000280# Import columns containing quoted strings
281do_test shell5-1.10 {
282 set out [open shell5.csv w]
283 fconfigure $out -translation lf
284 puts $out {column1,column2,column3,column4}
285 puts $out "field1,field2,\"x3 \"\"\r\ndata\"\" 3\",field4"
286 puts $out "x1,x2,\"x3 \"\"\ndata\"\" 3\",x4"
287 close $out
288 forcedelete test.db
289 catchcmd test.db {.mode csv
290 CREATE TABLE t1(a,b,c,d);
291.import shell5.csv t1
292 }
293 sqlite3 db test.db
294 db eval {SELECT hex(c) FROM t1 ORDER BY rowid}
295} {636F6C756D6E33 783320220D0A64617461222033 783320220A64617461222033}
296
drh3852b682014-02-26 13:53:34 +0000297# Blank last column with \r\n line endings.
298do_test shell5-1.11 {
299 set out [open shell5.csv w]
300 fconfigure $out -translation binary
301 puts $out "column1,column2,column3\r"
302 puts $out "a,b, \r"
303 puts $out "x,y,\r"
304 puts $out "p,q,r\r"
305 close $out
306 catch {db close}
307 forcedelete test.db
308 catchcmd test.db {.mode csv
309.import shell5.csv t1
310 }
311 sqlite3 db test.db
312 db eval {SELECT *, '|' FROM t1}
313} {a b { } | x y {} | p q r |}
drha81ad172013-12-11 14:00:04 +0000314db close
315
dan6a8ac852014-05-26 18:27:12 +0000316#----------------------------------------------------------------------------
317#
318reset_db
319sqlite3 db test.db
320do_test shell5-2.1 {
321 set fd [open shell5.csv w]
322 puts $fd ",hello"
323 close $fd
324 catchcmd test.db [string trim {
325.mode csv
326CREATE TABLE t1(a, b);
327.import shell5.csv t1
328 }]
329 db eval { SELECT * FROM t1 }
330} {{} hello}
331
332do_test shell5-2.2 {
333 set fd [open shell5.csv w]
334 puts $fd {"",hello}
335 close $fd
336 catchcmd test.db [string trim {
337.mode csv
338CREATE TABLE t2(a, b);
339.import shell5.csv t2
340 }]
341 db eval { SELECT * FROM t2 }
342} {{} hello}
343
344do_test shell5-2.3 {
345 set fd [open shell5.csv w]
346 puts $fd {"x""y",hello}
347 close $fd
348 catchcmd test.db [string trim {
349.mode csv
350CREATE TABLE t3(a, b);
351.import shell5.csv t3
352 }]
353 db eval { SELECT * FROM t3 }
354} {x\"y hello}
355
356do_test shell5-2.4 {
357 set fd [open shell5.csv w]
358 puts $fd {"xy""",hello}
359 close $fd
360 catchcmd test.db [string trim {
361.mode csv
362CREATE TABLE t4(a, b);
363.import shell5.csv t4
364 }]
365 db eval { SELECT * FROM t4 }
366} {xy\" hello}
367
mistachkin6fe03382014-06-16 22:45:28 +0000368do_test shell5-2.5 {
369 set fd [open shell5.csv w]
370 puts $fd {"one","2"}
371 puts $fd {}
372 close $fd
373 catchcmd test.db [string trim {
374.mode csv
375CREATE TABLE t4(a, b);
376.import shell5.csv t4
377 }]
378 db eval { SELECT * FROM t4 }
379} {xy\" hello one 2 {} {}}
dan6a8ac852014-05-26 18:27:12 +0000380
mistachkin636bf9f2014-07-19 20:15:16 +0000381#----------------------------------------------------------------------------
382# Tests for the shell "ascii" import/export mode.
383#
384do_test shell5-3.1 {
385 set fd [open shell5.csv w]
386 fconfigure $fd -encoding binary -translation binary
387 puts -nonewline $fd "\"test 1\"\x1F,test 2\r\n\x1E"
388 puts -nonewline $fd "test 3\x1Ftest 4\n"
389 close $fd
390 catchcmd test.db {
391.mode ascii
392CREATE TABLE t5(a, b);
393.import shell5.csv t5
394 }
395 db eval { SELECT * FROM t5 }
396} "\{\"test 1\"} \{,test 2\r\n\} \{test 3\} \{test 4\n\}"
397
mistachkin636bf9f2014-07-19 20:15:16 +0000398do_test shell5-3.2 {
drhfa5ed022015-01-09 00:38:06 +0000399 set x [catchcmd test.db {
mistachkin636bf9f2014-07-19 20:15:16 +0000400.mode ascii
401SELECT * FROM t5;
drhfa5ed022015-01-09 00:38:06 +0000402 }]
403 # Handle platform end-of-line differences
404 regsub -all {[\n\r]?\n} $x <EOL> x
405 set x
406} "0 \{\"test 1\"\x1F,test 2<EOL>\x1Etest 3\x1Ftest 4<EOL>\x1E\}"
dan6a8ac852014-05-26 18:27:12 +0000407
mistachkina0efb1a2015-02-12 22:45:25 +0000408do_test shell5-4.1 {
409 forcedelete shell5.csv
410 set fd [open shell5.csv w]
411 puts $fd "1,2,3"
412 puts $fd "4,5"
413 puts $fd "6,7,8"
414 close $fd
415 catchcmd test.db [string trim {
416.mode csv
417CREATE TABLE t6(a, b, c);
418.import shell5.csv t6
419 }]
420 db eval { SELECT * FROM t6 ORDER BY a }
421} {1 2 3 4 5 {} 6 7 8}
422
423do_test shell5-4.2 {
424 forcedelete shell5.csv
425 set fd [open shell5.csv w]
426 puts $fd "1,2,3"
427 puts $fd "4,5"
428 puts $fd "6,7,8,9"
429 close $fd
430 catchcmd test.db [string trim {
431.mode csv
432CREATE TABLE t7(a, b, c);
433.import shell5.csv t7
434 }]
435 db eval { SELECT * FROM t7 ORDER BY a }
436} {1 2 3 4 5 {} 6 7 8}
437
drh8df91852012-04-24 12:46:05 +0000438finish_test