SQLite

Check-in [52d12ba9f3]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:In the fileio.c extension, change the filetype(MODE) function into lsmode(MODE). Use the new lsmode(MODE) function in shell.c.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | archive-improvements
Files: files | file ages | folders
SHA3-256: 52d12ba9f33c1f2620776e189c81f3bf991759344ecdd167ea2a6107f0972b9d
User & Date: drh 2018-01-10 17:19:16.761
Context
2018-01-10
17:39
Fix minor problems with the new ".archive" command changes. (Closed-Leaf check-in: 612b30c95f user: drh tags: archive-improvements)
17:19
In the fileio.c extension, change the filetype(MODE) function into lsmode(MODE). Use the new lsmode(MODE) function in shell.c. (check-in: 52d12ba9f3 user: drh tags: archive-improvements)
16:50
Implement the ".ar --create" command using a single "REPLACE INTO sqlar SELECT ... FROM fsdir();" statement. Add the shell_putsnl() SQL function for providing --verbose output. (check-in: 28ab930436 user: drh tags: archive-improvements)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/misc/fileio.c.
354
355
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
379
380








381
382
383
384
385
386
387
388
    }else{
      ctxErrorMsg(context, "failed to write file: %s", zFile);
    }
  }
}

/*
** SQL function:   filetype(MODE)
**
** Based on the integer mode, return one of "file", "directory", or "symlink".

*/
static void fileTypeFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zMode;
  int iMode = sqlite3_value_int(argv[0]);

  if( S_ISLNK(iMode) ){
    zMode = "symlink";
  }else if( S_ISREG(iMode) ){
    zMode = "file";
  }else if( S_ISDIR(iMode) ){
    zMode = "directory";
  }else{
    zMode = "unknown";
  }








  sqlite3_result_text(context, zMode, -1, SQLITE_STATIC);
}

#ifndef SQLITE_OMIT_VIRTUALTABLE

/* 
** Cursor type for recursively iterating through a directory structure.
*/







|

|
>

|




|

>

|

|

|

|

>
>
>
>
>
>
>
>
|







354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
    }else{
      ctxErrorMsg(context, "failed to write file: %s", zFile);
    }
  }
}

/*
** SQL function:   lsmode(MODE)
**
** Given a numberic st_mode from stat(), convert it into a human-readable
** text string in the style of "ls -l".
*/
static void lsModeFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int i;
  int iMode = sqlite3_value_int(argv[0]);
  char z[16];
  if( S_ISLNK(iMode) ){
    z[0] = 'l';
  }else if( S_ISREG(iMode) ){
    z[0] = '-';
  }else if( S_ISDIR(iMode) ){
    z[0] = 'd';
  }else{
    z[0] = '?';
  }
  for(i=0; i<3; i++){
    int m = (iMode >> ((2-i)*3));
    char *a = &z[1 + i*3];
    a[0] = (m & 0x4) ? 'r' : '-';
    a[1] = (m & 0x2) ? 'w' : '-';
    a[2] = (m & 0x1) ? 'x' : '-';
  }
  z[10] = '\0';
  sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
}

#ifndef SQLITE_OMIT_VIRTUALTABLE

/* 
** Cursor type for recursively iterating through a directory structure.
*/
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
  rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
                               readfileFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0,
                                 writefileFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "fileType", 1, SQLITE_UTF8, 0,
                                 fileTypeFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = fsdirRegister(db);
  }
  return rc;
}







|
|






799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
  rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
                               readfileFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0,
                                 writefileFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
                                 lsModeFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = fsdirRegister(db);
  }
  return rc;
}
Changes to src/shell.c.in.
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913

4914
4915
4916
4917
4918
4919
4920
        zSep = " OR ";
      }
    }
  }
  *pzWhere = zWhere;
}

/*
** Argument zMode must point to a buffer at least 11 bytes in size. This
** function populates this buffer with the string interpretation of
** the unix file mode passed as the second argument (e.g. "drwxr-xr-x").
*/
static void shellModeToString(char *zMode, int mode){
  int i;

  /* Magic numbers copied from [man 2 stat] */
  if( mode & 0040000 ){
    zMode[0] = 'd';
  }else if( (mode & 0120000)==0120000 ){
    zMode[0] = 'l';
  }else{
    zMode[0] = '-';
  }

  for(i=0; i<3; i++){
    int m = (mode >> ((2-i)*3));
    char *a = &zMode[1 + i*3];
    a[0] = (m & 0x4) ? 'r' : '-';
    a[1] = (m & 0x2) ? 'w' : '-';
    a[2] = (m & 0x1) ? 'x' : '-';
  }
  zMode[10] = '\0';
}

/*
** Implementation of .ar "lisT" command. 
*/
static int arListCommand(ArCommand *pAr){
  const char *zSql = "SELECT %s FROM %s WHERE %s"; 
  const char *azCols[] = {
    "name",
    "mode, sz, datetime(mtime, 'unixepoch'), name"
  };

  char *zWhere = 0;
  sqlite3_stmt *pSql = 0;
  int rc;

  rc = arCheckEntries(pAr);
  arWhereClause(&rc, pAr, &zWhere);

  shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
                     pAr->zSrcTable, zWhere);
  if( pAr->bDryRun ){
    utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
  }else{
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
      if( pAr->bVerbose ){
        char zMode[11];
        shellModeToString(zMode, sqlite3_column_int(pSql, 0));
  
        utf8_printf(pAr->p->out, "%s % 10d  %s  %s\n", zMode,

            sqlite3_column_int(pSql, 1), 
            sqlite3_column_text(pSql, 2),
            sqlite3_column_text(pSql, 3)
        );
      }else{
        utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
      }







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







|
















<
<
<
|
>







4852
4853
4854
4855
4856
4857
4858



























4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882



4883
4884
4885
4886
4887
4888
4889
4890
4891
        zSep = " OR ";
      }
    }
  }
  *pzWhere = zWhere;
}




























/*
** Implementation of .ar "lisT" command. 
*/
static int arListCommand(ArCommand *pAr){
  const char *zSql = "SELECT %s FROM %s WHERE %s"; 
  const char *azCols[] = {
    "name",
    "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
  };

  char *zWhere = 0;
  sqlite3_stmt *pSql = 0;
  int rc;

  rc = arCheckEntries(pAr);
  arWhereClause(&rc, pAr, &zWhere);

  shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
                     pAr->zSrcTable, zWhere);
  if( pAr->bDryRun ){
    utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
  }else{
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
      if( pAr->bVerbose ){



        utf8_printf(pAr->p->out, "%s % 10d  %s  %s\n",
            sqlite3_column_text(pSql, 0),
            sqlite3_column_int(pSql, 1), 
            sqlite3_column_text(pSql, 2),
            sqlite3_column_text(pSql, 3)
        );
      }else{
        utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
      }
5001
5002
5003
5004
5005
5006
5007

5008




5009
5010
5011
5012
5013
5014
5015
*/
static int arExecSql(ArCommand *pAr, const char *zSql){
  int rc;
  if( pAr->bDryRun ){
    utf8_printf(pAr->p->out, "%s\n", zSql);
    rc = SQLITE_OK;
  }else{

    rc = sqlite3_exec(pAr->db, zSql, 0, 0, 0);




  }
  return rc;
}


/*
** Implementation of .ar "create" and "update" commands.







>
|
>
>
>
>







4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
*/
static int arExecSql(ArCommand *pAr, const char *zSql){
  int rc;
  if( pAr->bDryRun ){
    utf8_printf(pAr->p->out, "%s\n", zSql);
    rc = SQLITE_OK;
  }else{
    char *zErr = 0;
    rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
    if( zErr ){
      utf8_printf(stdout, "ERROR: %s\n", zErr);
      sqlite3_free(zErr);
    }
  }
  return rc;
}


/*
** Implementation of .ar "create" and "update" commands.
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
  const char *zDrop = "DROP TABLE IF EXISTS sqlar";
  const char *zInsertFmt = 
     "REPLACE INTO sqlar(name,mode,mtime,sz,data)\n"
     "  SELECT\n"
     "    %s,\n"
     "    mode,\n"
     "    mtime,\n"
     "    CASE filetype(mode)\n"
     "      WHEN 'file' THEN length(data)\n"
     "      WHEN 'directory' THEN 0\n"
     "      ELSE -1 END,\n"
     "    CASE WHEN filetype(mode)<>'directory' THEN data ELSE NULL END\n"
     "  FROM fsdir(%Q,%Q)\n"
     "  WHERE filetype(mode)<>'unknown'";
  int i;                          /* For iterating through azFile[] */
  int rc;                         /* Return code */

  rc = arExecSql(pAr, "SAVEPOINT ar;");
  if( rc!=SQLITE_OK ) return rc;
  if( bUpdate==0 ){
    rc = arExecSql(pAr, zDrop);







|
|
|

|

|







5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
  const char *zDrop = "DROP TABLE IF EXISTS sqlar";
  const char *zInsertFmt = 
     "REPLACE INTO sqlar(name,mode,mtime,sz,data)\n"
     "  SELECT\n"
     "    %s,\n"
     "    mode,\n"
     "    mtime,\n"
     "    CASE substr(lsmode(mode),1,1)\n"
     "      WHEN '-' THEN length(data)\n"
     "      WHEN 'd' THEN 0\n"
     "      ELSE -1 END,\n"
     "    CASE WHEN lsmode(mode) LIKE 'd%%' THEN NULL else data END\n"
     "  FROM fsdir(%Q,%Q)\n"
     "  WHERE lsmode(mode) NOT LIKE '?%%';";
  int i;                          /* For iterating through azFile[] */
  int rc;                         /* Return code */

  rc = arExecSql(pAr, "SAVEPOINT ar;");
  if( rc!=SQLITE_OK ) return rc;
  if( bUpdate==0 ){
    rc = arExecSql(pAr, zDrop);