-C Change\sa\ssingle\sinteger\svariable\sto\s64-bit\sin\sthe\stokenizer\sto\savoid\nany\spossibility\sof\san\sinteger\soverflow.
-D 2025-12-27T19:57:59.356
+C Improvements\sto\sthe\s.import\scommand\sof\sthe\sCLI.
+D 2025-12-28T14:01:52.978
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F src/resolve.c 47aa7fdc9ec4c19b103ac5e79d7887d30119b5675309facf5eed1118391c868b
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 85852256d860f3ba5be4a9edc1238e68dbea082a0167f31b7345c821ae45775d
-F src/shell.c.in 8aa6b2bc490271bcbb39b650b120d28976c2de0c0ae80f356a64b2971ba85023
+F src/shell.c.in b30c49e8b58c51ee12034b14960a9097eec7fc2053231a31fe6271aa7e6c319f
F src/sqlite.h.in b6599377f02ef9d545a8da48959213928b63291ad83ff65e5f3a72bf4fec595d
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 5d5330f5f8461f5ce74960436ddcfa53ecd09c2b8b23901e22ae38aec3243998
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test da4901c88f3a1db2acd39381ed260a0fe3c706bbc170b695fcbe6cb3eb6f7ab0
-F test/shell2.test f563798603950345a98f2a630d4ea746fc0063919a3dac917475d4e2166acbd7
+F test/shell2.test dc541d2681503e55466a24d35a4cbf8ca5b90b8fcdef37fc4db07373a67d31d3
F test/shell3.test 603b448e917537cf77be0f265c05c6f63bc677c63a533c8e96aae923b56f4a0e
F test/shell4.test e25580a792b7b54560c3a76b6968bd8189261f38979fe28e6bc6312c5db280db
F test/shell5.test 145a9474bab6d80b6ee452b83135507b25275d53b0936aab76520f007ac4d9dc
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c f40bccf0236f8bcc34b299781b7d34cb269ace23afe5c1b8a9d966e2fa1ce9e5
-P f41851587328f8b434e66987765324b7bf5746ecdf3a9f2869000276e0f79401
-R 0318fcb6944164fd4ebe079bcdee2867
+P 69cf692a24d714305b2e4c8c4c40f70dc6510c26b8db7e5249f32a53e44c7e5c
+R 3af252d77a85ba7bba900e37cdf35e34
U drh
-Z cb66f3935c2321391ca778a118ec4b1c
+Z 298454a73cfd919f12c3b1fa1a6bf676
# Remove this line to create a well-formed Fossil manifest.
** + Input comes from p->in.
** + Store results in p->z of length p->n. Space to hold p->z comes
** from sqlite3_malloc64().
-** + Use p->cSep as the column separator. The default is ",".
-** + Use p->rSep as the row separator. The default is "\n".
+** + Use p->cColSep as the column separator. The default is ",".
+** + Use p->cRowSep as the row separator. The default is "\n".
** + Keep track of the line number in p->nLine.
** + Store the character that terminates the field in p->cTerm. Store
** EOF on end-of-file.
** + Input comes from p->in.
** + Store results in p->z of length p->n. Space to hold p->z comes
** from sqlite3_malloc64().
-** + Use p->cSep as the column separator. The default is "\x1F".
-** + Use p->rSep as the row separator. The default is "\x1E".
+** + Use p->cColSep as the column separator. The default is "\x1F".
+** + Use p->cRowSep as the row separator. The default is "\x1E".
** + Keep track of the row number in p->nLine.
** + Store the character that terminates the field in p->cTerm. Store
** EOF on end-of-file.
** names. If FILE begins with "|" then it is a command that is run
** and the output from the command is used as the input data.
**
-** FILE is assumed to be in a CSV format, unless the current mode
-** is "ascii" or "tabs" or unless one of the options below specify
-** an alternative.
+** The content of FILE is interpreted using RFC-4180 ("CSV") quoting
+** rules unless the current mode is "ascii" or "tabs" or unless one
+** the --ascii option is used.
+**
+** The column and row separators must be single ASCII characters. If
+** multiple characters or a Unicode character are specified for the
+** separators, then only the first byte of the separator is used. Except,
+** if the row separator is \n and the mode is not --ascii, then \r\n is
+** understood as a row separator too.
**
** Options:
-** --ascii Use \037 and \036 as column and row separators on input
+** --ascii Do not use RFC-4180 quoting. Use \037 and \036
+** as column and row separators on input, unless other
+** delimiters are specified using --colsep and/or --rowsep
+** --colsep CHAR Use CHAR as the column separator.
** --csv Input is standard RFC-4180 CSV.
+** --rowsep CHAR Use CHAR as the row separator.
** --schema S When creating TABLE, put it in schema S
** --skip N Ignore the first N rows of input
** -v Verbose mode
i64 nByte; /* Number of bytes in an SQL string */
int i, j; /* Loop counters */
int needCommit; /* True to COMMIT or ROLLBACK at end */
- int nSep; /* Number of bytes in spec.zColumnSep */
char *zSql = 0; /* An SQL statement */
ImportCtx sCtx; /* Reader context */
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
int eVerbose = 0; /* Larger for more console output */
i64 nSkip = 0; /* Initial lines to skip */
- int useOutputMode = 1; /* Use output mode to determine separators */
char *zCreate = 0; /* CREATE TABLE statement text */
int rc; /* Result code */
}else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
nSkip = integerValue(azArg[++i]);
}else if( cli_strcmp(z,"-ascii")==0 ){
- sCtx.cColSep = SEP_Unit[0];
- sCtx.cRowSep = SEP_Record[0];
+ if( sCtx.cColSep==0 ) sCtx.cColSep = SEP_Unit[0];
+ if( sCtx.cRowSep==0 ) sCtx.cRowSep = SEP_Record[0];
xRead = ascii_read_one_field;
- useOutputMode = 0;
}else if( cli_strcmp(z,"-csv")==0 ){
- sCtx.cColSep = ',';
- sCtx.cRowSep = '\n';
+ if( sCtx.cColSep==0 ) sCtx.cColSep = ',';
+ if( sCtx.cRowSep==0 ) sCtx.cRowSep = '\n';
xRead = csv_read_one_field;
- useOutputMode = 0;
+ }else if( cli_strcmp(z,"-colsep")==0 ){
+ if( i==nArg-1 ){
+ dotCmdError(p, i, "missing argument", 0);
+ return 1;
+ }
+ i++;
+ sCtx.cColSep = azArg[i][0];
+ }else if( cli_strcmp(z,"-rowsep")==0 ){
+ if( i==nArg-1 ){
+ dotCmdError(p, i, "missing argument", 0);
+ return 1;
+ }
+ i++;
+ sCtx.cRowSep = azArg[i][0];
}else{
dotCmdError(p, i, "unknown option", 0);
return 1;
}
seenInterrupt = 0;
open_db(p, 0);
- if( useOutputMode ){
- /* If neither the --csv or --ascii options are specified, then set
- ** the column and row separator characters from the output mode. */
- if( p->mode.spec.zColumnSep==0 ){
- modeSetStr(&p->mode.spec.zColumnSep, ",");
- nSep = 1;
- }else if( (nSep = strlen30(p->mode.spec.zColumnSep))==0 ){
- eputz("Error: non-null column separator required for import\n");
- return 1;
- }
- if( nSep>1 ){
- eputz("Error: multi-character column separators not allowed"
- " for import\n");
- return 1;
- }
- if( p->mode.spec.zRowSep==0 ){
- modeSetStr(&p->mode.spec.zRowSep, "\n");
- nSep = 1;
- }else if( (nSep = strlen30(p->mode.spec.zRowSep))==0 ){
- eputz("Error: non-null row separator required for import\n");
- return 1;
+ if( sCtx.cColSep==0 ){
+ if( p->mode.spec.zColumnSep && p->mode.spec.zColumnSep[0]!=0 ){
+ sCtx.cColSep = p->mode.spec.zColumnSep[0];
+ }else{
+ sCtx.cColSep = ',';
}
- if( nSep==2 && p->mode.eMode==MODE_Csv
- && cli_strcmp(p->mode.spec.zRowSep,SEP_CrLf)==0
- ){
- /* When importing CSV (only), if the row separator is set to the
- ** default output row separator, change it to the default input
- ** row separator. This avoids having to maintain different input
- ** and output row separators. */
- modeSetStr(&p->mode.spec.zRowSep, SEP_Row);
- nSep = strlen30(p->mode.spec.zRowSep);
- }
- if( nSep>1 ){
- eputz("Error: multi-character row separators not allowed"
- " for import\n");
- return 1;
+ }
+ if( (sCtx.cColSep & 0x80)!=0 ){
+ eputz("Error: .import column separator must be ASCII\n");
+ return 1;
+ }
+ if( sCtx.cRowSep==0 ){
+ if( p->mode.spec.zRowSep && p->mode.spec.zRowSep[0]!=0 ){
+ sCtx.cRowSep = p->mode.spec.zRowSep[0];
+ }else{
+ sCtx.cRowSep = '\n';
}
- sCtx.cColSep = (u8)p->mode.spec.zColumnSep[0];
- sCtx.cRowSep = (u8)p->mode.spec.zRowSep[0];
+ }
+ if( sCtx.cRowSep=='\r' && xRead!=ascii_read_one_field ){
+ sCtx.cRowSep = '\n';
+ }
+ if( (sCtx.cRowSep & 0x80)!=0 ){
+ eputz("Error: .import row separator must be ASCII\n");
+ return 1;
}
sCtx.zFile = zFile;
sCtx.nLine = 1;
cli_printf(stderr,"Error: cannot open \"%s\"\n", zFile);
return 1;
}
- if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
+ if( eVerbose>=1 ){
char zSep[2];
zSep[1] = 0;
zSep[0] = sCtx.cColSep;