Quantcast

Error using multiline command line argument with dot-command

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Error using multiline command line argument with dot-command

Rob Golsteijn
Hi List,

I want to report a minor issue for the Sqlite shell. It does not handle multiline command line arguments in which the second line contains a dot-command correctly.
If the same statements are passed via stdin they are handled fine.
Tested with Sqlite 3.15.2 on Ubuntu 14.04 using Bash.

Example:

Passing statements via stdin works fine:


echo "SELECT 1;
.mode csv
SELECT 1;" | sqlite3 mydb.sq3



(no error)


Passing the statements via a command line argument gives an error:


sqlite3 mydb.sq3 "SELECT 1;
.mode csv
SELECT 1;"

Error: near ".": syntax error



Regards,
Rob Golsteijn



_______________________________________________
sqlite-users mailing list
[hidden email]
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Error using multiline command line argument with dot-command

Dan Kennedy-4
On 03/08/2017 12:03 AM, Rob Golsteijn wrote:

> Hi List,
>
> I want to report a minor issue for the Sqlite shell. It does not handle multiline command line arguments in which the second line contains a dot-command correctly.
> If the same statements are passed via stdin they are handled fine.
> Tested with Sqlite 3.15.2 on Ubuntu 14.04 using Bash.
>
> Example:
>
> Passing statements via stdin works fine:
>
>
> echo "SELECT 1;
> .mode csv
> SELECT 1;" | sqlite3 mydb.sq3
>
>
>
> (no error)
>
>
> Passing the statements via a command line argument gives an error:
>
>
> sqlite3 mydb.sq3 "SELECT 1;
> .mode csv
> SELECT 1;"
>
> Error: near ".": syntax error

A work around is:

   sqlite3 mydb.sq3 "SELECT 1" ".mode csv" "SELECT 1"

Dan.



_______________________________________________
sqlite-users mailing list
[hidden email]
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Error using multiline command line argument with dot-command

Cezary H. Noweta
Hello,

On 2017-03-07 18:16, Dan Kennedy wrote:
> On 03/08/2017 12:03 AM, Rob Golsteijn wrote:

>> I want to report a minor issue for the Sqlite shell. It does not
>> handle multiline command line arguments in which the second line
>> contains a dot-command correctly.
>> If the same statements are passed via stdin they are handled fine.
>> Tested with Sqlite 3.15.2 on Ubuntu 14.04 using Bash.

>> Passing statements via stdin works fine:

>> echo "SELECT 1;
>> .mode csv
>> SELECT 1;" | sqlite3 mydb.sq3

>> Passing the statements via a command line argument gives an error:

>> sqlite3 mydb.sq3 "SELECT 1;
>> .mode csv
>> SELECT 1;"

>> Error: near ".": syntax error

> A work around is:

>   sqlite3 mydb.sq3 "SELECT 1" ".mode csv" "SELECT 1"

Fortunately most of work is done already. It is enough to dirty patch
``fgets'':

After ``static char mainPrompt[20];'':

======
typedef struct CHNFILE {
   int     nCmd;         /* nof elems in azCmd */
   char    **azCmd;      /* arr to scan */
   int     nCmdCur;      /* nof cur elem */
   char    *zCmdCur;   /* next char to scan */
   size_t  nLenCmdCur;   /* len of cur line */
} CHNFILE;

static CHNFILE chnfile = { 0 };

/*
  * nCmd > 0 or UDB (7.1.7)
  * azCmd != NULL or UDB (7.1.7)
  */
/* !!!! MT: NOT LOCKED !!!! */
static FILE *chnfileopen(int nCmd, char *azCmd[])
{
   assert(0 < nCmd);
   assert(NULL != azCmd);

   if ( 0 != chnfile.nCmd ) {
     return NULL;
   }

   chnfile.nCmd = nCmd;
   chnfile.azCmd = azCmd;
   chnfile.nCmdCur = 0;
   chnfile.zCmdCur = strchr(azCmd[0], '\n');
   chnfile.nLenCmdCur = NULL == chnfile.zCmdCur ? strlen(azCmd[0]) :
chnfile.zCmdCur - azCmd[0];
   chnfile.zCmdCur = azCmd[0];

   return (void *)&chnfile;
}

/* !!!! MT: NOT LOCKED !!!! */
static char *chnfilegets(char *s, int n, FILE *f)
{
   if ( 0 == chnfile.nCmd || (void *)&chnfile != f ) {
     return fgets(s, n, f);
   }

   /* ``shall'' -- UDB (7.1.7) */
   assert(NULL != s || 0 >= n || (int)chnfile.nCmd <= chnfile.nCmdCur);

   /* nothing to read or EOF */
   if ( 0 >= n || (int)chnfile.nCmd <= chnfile.nCmdCur ) {
     return NULL;
   }

   /* Trailing '\0' */
   --n;
   /* Advance to the next line? */
   if ( (size_t)n > chnfile.nLenCmdCur ) {
     /* YES: Advance to the next line? */
     char *p; /* Temp helper */
     memcpy(s, chnfile.zCmdCur, chnfile.nLenCmdCur);
     s[chnfile.nLenCmdCur] = '\n';
     s[chnfile.nLenCmdCur + 1] = 0;
     /* Next line */
     if ( '\n' == chnfile.zCmdCur[chnfile.nLenCmdCur] && 0 !=
chnfile.zCmdCur[chnfile.nLenCmdCur + 1] ) {
       /* Ends with '\n' [not followed by '\0' ???] */
       chnfile.zCmdCur = &chnfile.zCmdCur[chnfile.nLenCmdCur + 1];
       p = strchr(chnfile.zCmdCur, '\n');
       chnfile.nLenCmdCur = NULL == p ? strlen(chnfile.zCmdCur) : p -
chnfile.zCmdCur;
     } else {
       /* Next element */
       if ( (int)++chnfile.nCmdCur < chnfile.nCmd ) {
         chnfile.zCmdCur = chnfile.azCmd[chnfile.nCmdCur];
         p = strchr(chnfile.zCmdCur, '\n');
         chnfile.nLenCmdCur = NULL == p ? strlen(chnfile.zCmdCur) : p -
chnfile.zCmdCur;
       }
     }
   } else {
     /* NO: Advance to the next line? */
     memcpy(s, chnfile.zCmdCur, n);
     s[n] = 0;
     chnfile.zCmdCur = &chnfile.zCmdCur[n];
     chnfile.nLenCmdCur -= n;
   }

   return s;
}

/* !!!! MT: NOT LOCKED !!!! */
static int chnfileclose(FILE *f)
{
   if ( 0 == chnfile.nCmd || &chnfile != (void *)f ) {
     return fclose(f);
   }

   chnfile.nCmd = 0;

   return 0;
}

#define fgets   chnfilegets
#define fclose  chnfileclose
======

And replace the final ``if( !readStdin ){'' block in ``main'':

======
     FILE *in;
     in = chnfileopen(nCmd, azCmd);
     if( in==0 ){
       utf8_printf(stderr, "Error: cannot process command line\n");
       rc = 1;
     } else {
       rc = process_input(&data, in);
       fclose(in);
     }
     free(azCmd);
======

A bit dirty, but works fine though not extremely tested. A cleaner
solution probably requires a bit more work, but due to a shell's thrift
it is quite easy (there is a simple, non--forking flow: main =>
process_input => one_input_line => local_getline => fgets).

-- best regards

Cezary H. Noweta
_______________________________________________
sqlite-users mailing list
[hidden email]
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
Loading...