/*
** Parameters:
** filename=FILENAME Required
-** schema=SCHEMA Optional
+** schema=SCHEMA Alternative CSV schema.
** header=YES|NO First row of CSV defines the names of
** columns if "yes". Default "no".
+** columns=N Assum the CSV file contains N columns.
** testflags=N Bitmask of test flags. Optional
**
-** If header=no and not columns are listed, then the columns are named
-** "c0", "c1", "c2", and so forth.
+** If schema= is omitted, then the columns are named "c0", "c1", "c2",
+** and so forth. If columns=N is omitted, then the file is opened and
+** the number of columns in the first row is counted to determine the
+** column count. If header=YES, then the first row is skipped.
*/
static int csvtabConnect(
sqlite3 *db,
sqlite3_vtab **ppVtab,
char **pzErr
){
- CsvTable *pNew = 0;
- int bHeader = -1;
- int rc = SQLITE_OK;
- int i;
- char *zFilename = 0;
- char *zSchema = 0;
- int tstFlags = 0;
- CsvReader sRdr;
+ CsvTable *pNew = 0; /* The CsvTable object to construct */
+ int bHeader = -1; /* header= flags. -1 means not seen yet */
+ int rc = SQLITE_OK; /* Result code from this routine */
+ int i; /* Loop counter */
+ char *zFilename = 0; /* Value of the filename= parameter */
+ char *zSchema = 0; /* Value of the schema= parameter */
+ int tstFlags = 0; /* Value of the testflags= parameter */
+ int nCol = -99; /* Value of the columns= parameter */
+ CsvReader sRdr; /* A CSV file reader used to store an error
+ ** message and/or to count the number of columns */
memset(&sRdr, 0, sizeof(sRdr));
for(i=3; i<argc; i++){
if( (zValue = csv_parameter("testflags",9,z))!=0 ){
tstFlags = (unsigned int)atoi(zValue);
}else
+ if( (zValue = csv_parameter("columns",7,z))!=0 ){
+ if( nCol>0 ){
+ csv_errmsg(&sRdr, "more than one 'columns' parameter");
+ goto csvtab_connect_error;
+ }
+ nCol = atoi(zValue);
+ if( nCol<=0 ){
+ csv_errmsg(&sRdr, "must have at least one column");
+ goto csvtab_connect_error;
+ }
+ }else
{
csv_errmsg(&sRdr, "unrecognized parameter '%s'", z);
goto csvtab_connect_error;
csv_errmsg(&sRdr, "missing 'filename' parameter");
goto csvtab_connect_error;
}
- if( csv_reader_open(&sRdr, zFilename) ){
+ if( nCol<=0 && csv_reader_open(&sRdr, zFilename) ){
goto csvtab_connect_error;
}
pNew = sqlite3_malloc( sizeof(*pNew) );
*ppVtab = (sqlite3_vtab*)pNew;
if( pNew==0 ) goto csvtab_connect_oom;
memset(pNew, 0, sizeof(*pNew));
- do{
- const char *z = csv_read_one_field(&sRdr);
- if( z==0 ) goto csvtab_connect_oom;
- pNew->nCol++;
- }while( sRdr.cTerm==',' );
+ if( nCol>0 ){
+ pNew->nCol = nCol;
+ }else{
+ do{
+ const char *z = csv_read_one_field(&sRdr);
+ if( z==0 ) goto csvtab_connect_oom;
+ pNew->nCol++;
+ }while( sRdr.cTerm==',' );
+ }
pNew->zFilename = zFilename;
pNew->tstFlags = tstFlags;
zFilename = 0;
){
CsvTable *pTab = (CsvTable*)tab;
int i;
+ int nConst = 0;
pIdxInfo->estimatedCost = 1000000;
if( (pTab->tstFlags & CSVTEST_FIDX)==0 ){
return SQLITE_OK;
}
+ /* The usual (an sensible) case is to take the "return SQLITE_OK" above.
+ ** The code below only runs when testflags=1. The following code
+ ** generates an artifical and unrealistic plan which is useful
+ ** for testing virtual table logic but is useless for real applications. */
for(i=0; i<pIdxInfo->nConstraint; i++){
+ unsigned char op;
if( pIdxInfo->aConstraint[i].usable==0 ) continue;
- if( pIdxInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ op = pIdxInfo->aConstraint[i].op;
+ if( op==SQLITE_INDEX_CONSTRAINT_EQ
+ || op==SQLITE_INDEX_CONSTRAINT_LIKE
+ || op==SQLITE_INDEX_CONSTRAINT_GLOB
+ ){
pIdxInfo->estimatedCost = 10;
- break;
+ pIdxInfo->aConstraintUsage[nConst].argvIndex = nConst+1;
+ nConst++;
}
}
return SQLITE_OK;
-C Add\sthe\stestflags\sparameter\sto\sthe\scsv\sextension.
-D 2016-05-31T18:08:35.263
+C Add\sthe\scolumns=N\sparameter\sto\sthe\sCSV\sextension.
+D 2016-05-31T18:44:33.835
F Makefile.in f59e0763ff448719fc1bd25513882b0567286317
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 306d73e854b1a92ea06e5d1e637faa5c44de53c7
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
-F ext/misc/csv.c d9b1dac6e43891174560abdd7d1d68bac20a2277
+F ext/misc/csv.c 39060a352f43e43df575484cc0f23ab61091dac3
F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 00d3570c8bb96469c984903e20de589e998d4636
-R 7c1772dc60b41e0b51f7bd702d450189
+P b93fb2fe0df1b3bea2bc2a4e1528da74ab290593
+R 65e8595850caa2b47ebf66d47e8638e5
U drh
-Z ed250383d88d82f9f9e7a2529e3cc23c
+Z b14790ed4c9841c10d8b6970f4ae5ca1