]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the columns=N parameter to the CSV extension.
authordrh <drh@noemail.net>
Tue, 31 May 2016 18:44:33 +0000 (18:44 +0000)
committerdrh <drh@noemail.net>
Tue, 31 May 2016 18:44:33 +0000 (18:44 +0000)
FossilOrigin-Name: 28ebeadd6a4c9ff2ce9fc86a0f0fe2f6cf94d3ac

ext/misc/csv.c
manifest
manifest.uuid

index d8087664fa8326a9c5cdb847c17488990b0a3c93..81a1d9ff6365d7c46f37e5b53ede06fc6a07c451 100644 (file)
@@ -315,13 +315,16 @@ static int csv_boolean(const char *z){
 /*
 ** 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,
@@ -330,14 +333,16 @@ static int csvtabConnect(
   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++){
@@ -382,6 +387,17 @@ static int csvtabConnect(
     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;
@@ -391,18 +407,22 @@ static int csvtabConnect(
     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;
@@ -593,15 +613,26 @@ static int csvtabBestIndex(
 ){
   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;
index 6ea00aab63764b4f7c7cf6538bc0750a1fd222d8..db47b84b3f0c44941e43f5faab8098167276dcd4 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-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
@@ -206,7 +206,7 @@ F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
 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
@@ -1497,7 +1497,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 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
index 52e6a805d633ed2b7eacd497247f9d7a91ddf6e7..bc70991975d5b9aba6ba4239ddb5fc97f07d998e 100644 (file)
@@ -1 +1 @@
-b93fb2fe0df1b3bea2bc2a4e1528da74ab290593
\ No newline at end of file
+28ebeadd6a4c9ff2ce9fc86a0f0fe2f6cf94d3ac
\ No newline at end of file