/ Check-in [c4e2ce48]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Backport a minimal set of changes needed to get 8+3 filenames and the multiplexor shim playing well together.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | nx-devkit
Files: files | file ages | folders
SHA1: c4e2ce486217c96373836bfe641f46abf891799a
User & Date: drh 2011-12-12 20:01:12
Context
2011-12-13
01:34
Add a compile-time shutdown procedure to be called by sqlite3_shutdown() to undo the effects of the compile-time initialization procedure. check-in: c2ed86f5 user: drh tags: nx-devkit
2011-12-12
20:01
Backport a minimal set of changes needed to get 8+3 filenames and the multiplexor shim playing well together. check-in: c4e2ce48 user: drh tags: nx-devkit
2011-11-17
11:49
Improvements to the documentation of the sqlite3_db_filename() interface. check-in: 1c45b2a0 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
    **   "<path to db>-walNN"
    **
    ** where NN is a decimal number. The NN naming schemes are 
    ** used by the test_multiplex.c module.
    */
    nDb = sqlite3Strlen30(zPath) - 1; 
#ifdef SQLITE_ENABLE_8_3_NAMES
    while( nDb>0 && !sqlite3Isalnum(zPath[nDb]) ) nDb--;
    if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
#else
    while( zPath[nDb]!='-' ){
      assert( nDb>0 );
      assert( zPath[nDb]!='\n' );
      nDb--;
    }







|







4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
    **   "<path to db>-walNN"
    **
    ** where NN is a decimal number. The NN naming schemes are 
    ** used by the test_multiplex.c module.
    */
    nDb = sqlite3Strlen30(zPath) - 1; 
#ifdef SQLITE_ENABLE_8_3_NAMES
    while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--;
    if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
#else
    while( zPath[nDb]!='-' ){
      assert( nDb>0 );
      assert( zPath[nDb]!='\n' );
      nDb--;
    }

Changes to src/shell.c.

2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
....
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
  if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0
   && nArg==2
  ){
    enableTimer = booleanValue(azArg[1]);
  }else
  
  if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
    printf("SQLite %s %s\n",
        sqlite3_libversion(), sqlite3_sourceid());
  }else

  if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
    int j;
    assert( nArg<=ArraySize(azArg) );
    for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
................................................................................
    /* Run commands received from standard input
    */
    if( stdin_is_interactive ){
      char *zHome;
      char *zHistory = 0;
      int nHistory;
      printf(
        "SQLite version %s %.19s\n"
        "Enter \".help\" for instructions\n"
        "Enter SQL statements terminated with a \";\"\n",
        sqlite3_libversion(), sqlite3_sourceid()
      );
      zHome = find_home_dir();
      if( zHome ){
        nHistory = strlen30(zHome) + 20;







|







 







|







2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
....
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
  if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0
   && nArg==2
  ){
    enableTimer = booleanValue(azArg[1]);
  }else
  
  if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
    printf("SQLite %s %s\n" /*extra-version-info*/,
        sqlite3_libversion(), sqlite3_sourceid());
  }else

  if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
    int j;
    assert( nArg<=ArraySize(azArg) );
    for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
................................................................................
    /* Run commands received from standard input
    */
    if( stdin_is_interactive ){
      char *zHome;
      char *zHistory = 0;
      int nHistory;
      printf(
        "SQLite version %s %.19s\n" /*extra-version-info*/
        "Enter \".help\" for instructions\n"
        "Enter SQL statements terminated with a \";\"\n",
        sqlite3_libversion(), sqlite3_sourceid()
      );
      zHome = find_home_dir();
      if( zHome ){
        nHistory = strlen30(zHome) + 20;

Changes to src/test_multiplex.c.

92
93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317





318
319
320
321
322
323
324
325
326
327
...
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
...
815
816
817
818
819
820
821




822
823

824
825
826
827
828
829
830
** the xFileControl() interface.  It will be rounded up to a 
** multiple of MAX_PAGE_SIZE.  We default it here to 2GiB less 64KiB.
*/
#ifndef SQLITE_MULTIPLEX_CHUNK_SIZE
# define SQLITE_MULTIPLEX_CHUNK_SIZE 2147418112
#endif

/* Default limit on number of chunks.  Care should be taken
** so that values for chunks numbers fit in the SQLITE_MULTIPLEX_EXT_FMT
** format specifier. It may be changed by calling

** the xFileControl() interface.
*/
#ifndef SQLITE_MULTIPLEX_MAX_CHUNKS
# define SQLITE_MULTIPLEX_MAX_CHUNKS 32
#endif

/* If SQLITE_MULTIPLEX_EXT_OVWR is defined, the 
** last SQLITE_MULTIPLEX_EXT_SZ characters of the 
** filename will be overwritten, otherwise, the 
** multiplex extension is simply appended to the filename.
** Ex.  (undefined) test.db -> test.db01
**      (defined)   test.db -> test.01
** Chunk 0 does not have a modified extension.
*/
#define SQLITE_MULTIPLEX_EXT_FMT    "%02d"
#define SQLITE_MULTIPLEX_EXT_SZ     2

/************************ Object Definitions ******************************/

/* Forward declaration of all object types */
typedef struct multiplexGroup multiplexGroup;
typedef struct multiplexConn multiplexConn;

/*
................................................................................
    memset(&p[pGroup->nReal], 0, sizeof(p[0])*(iChunk+1-pGroup->nReal));
    pGroup->aReal = p;
    pGroup->nReal = iChunk+1;
  }
  if( pGroup->aReal[iChunk].z==0 ){
    char *z;
    int n = pGroup->nName;
    pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+3 );
    if( z==0 ){
      return SQLITE_NOMEM;
    }
    memcpy(z, pGroup->zName, n+1);
    if( iChunk>0 ){
#ifdef SQLITE_ENABLE_8_3_NAMES
      if( n>3 && z[n-3]=='.' ){
        n--;
      }else if( n>4 && z[n-4]=='.' ){
        n -= 2;





      }
#endif
      sqlite3_snprintf(3,&z[n],"%02d",iChunk);
    }
  }
  return SQLITE_OK;
}

/* Translate an sqlite3_file* that is really a multiplexGroup* into
** the sqlite3_file* for the underlying original VFS.
................................................................................
  if( !pGroup->bEnabled ){
    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
    if( pSubOpen==0 ){
      rc = SQLITE_IOERR_TRUNCATE;
    }else{
      rc = pSubOpen->pMethods->xTruncate(pSubOpen, size);
    }
  }else{
    int rc2;
    int i;
    sqlite3_file *pSubOpen;
    sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
    /* delete the chunks above the truncate limit */
    for(i=(int)(size / pGroup->szChunk)+1; i<pGroup->nReal; i++){
      multiplexSubClose(pGroup, i, pOrigVfs);
................................................................................
    sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;
    *pSize = 0;
    for(i=0; 1; i++){
      sqlite3_file *pSubOpen = 0;
      int exists = 0;
      rc = multiplexSubFilename(pGroup, i);
      if( rc ) break;




      rc2 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[i].z,
          SQLITE_ACCESS_EXISTS, &exists);

      if( rc2==SQLITE_OK && exists){
        /* if it exists, open it */
        pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
      }else{
        /* stop at first "gap" */
        break;
      }







|
|
|
>
|


|


<
<
<
<
<
<
<
<
<
<
<







 







|






|
|
|
|
>
>
>
>
>


|







 







|







 







>
>
>
>
|
|
>







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108











109
110
111
112
113
114
115
...
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
...
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
...
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
** the xFileControl() interface.  It will be rounded up to a 
** multiple of MAX_PAGE_SIZE.  We default it here to 2GiB less 64KiB.
*/
#ifndef SQLITE_MULTIPLEX_CHUNK_SIZE
# define SQLITE_MULTIPLEX_CHUNK_SIZE 2147418112
#endif

/* This used to be the default limit on number of chunks, but
** it is no longer enforced.  There is currently no limit to the
** number of chunks.
**
** May be changed by calling the xFileControl() interface.
*/
#ifndef SQLITE_MULTIPLEX_MAX_CHUNKS
# define SQLITE_MULTIPLEX_MAX_CHUNKS 12
#endif












/************************ Object Definitions ******************************/

/* Forward declaration of all object types */
typedef struct multiplexGroup multiplexGroup;
typedef struct multiplexConn multiplexConn;

/*
................................................................................
    memset(&p[pGroup->nReal], 0, sizeof(p[0])*(iChunk+1-pGroup->nReal));
    pGroup->aReal = p;
    pGroup->nReal = iChunk+1;
  }
  if( pGroup->aReal[iChunk].z==0 ){
    char *z;
    int n = pGroup->nName;
    pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+4 );
    if( z==0 ){
      return SQLITE_NOMEM;
    }
    memcpy(z, pGroup->zName, n+1);
    if( iChunk>0 ){
#ifdef SQLITE_ENABLE_8_3_NAMES
      int i;
      for(i=n-1; i>0 && i>=n-4 && z[i]!='.'; i--){}
      if( i>=n-4 ) n = i+1;
      if( pGroup->flags & (SQLITE_OPEN_MAIN_JOURNAL|SQLITE_OPEN_TEMP_JOURNAL) ){
        /* The extensions on overflow files for main databases are 001, 002,
        ** 003 and so forth.  To avoid name collisions, add 100 to the 
        ** extensions of journal files so that they are 101, 102, 103, ....
        */
        iChunk += 100;
      }
#endif
      sqlite3_snprintf(4,&z[n],"%03d",iChunk);
    }
  }
  return SQLITE_OK;
}

/* Translate an sqlite3_file* that is really a multiplexGroup* into
** the sqlite3_file* for the underlying original VFS.
................................................................................
  if( !pGroup->bEnabled ){
    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
    if( pSubOpen==0 ){
      rc = SQLITE_IOERR_TRUNCATE;
    }else{
      rc = pSubOpen->pMethods->xTruncate(pSubOpen, size);
    }
  }else if( (pGroup->flags & SQLITE_OPEN_MAIN_DB)==0 ){
    int rc2;
    int i;
    sqlite3_file *pSubOpen;
    sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
    /* delete the chunks above the truncate limit */
    for(i=(int)(size / pGroup->szChunk)+1; i<pGroup->nReal; i++){
      multiplexSubClose(pGroup, i, pOrigVfs);
................................................................................
    sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;
    *pSize = 0;
    for(i=0; 1; i++){
      sqlite3_file *pSubOpen = 0;
      int exists = 0;
      rc = multiplexSubFilename(pGroup, i);
      if( rc ) break;
      if( pGroup->flags & SQLITE_OPEN_DELETEONCLOSE ){
        exists = pGroup->nReal>=i && pGroup->aReal[i].p!=0;
        rc2 = SQLITE_OK;
      }else{
        rc2 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[i].z,
            SQLITE_ACCESS_EXISTS, &exists);
      }
      if( rc2==SQLITE_OK && exists){
        /* if it exists, open it */
        pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
      }else{
        /* stop at first "gap" */
        break;
      }