/ Check-in [fd8d7440]
Login

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

Overview
Comment:Change the SQLITE_FCNTL_PRAGMA file-control so that it can return a string value.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | file-control-pragma
Files: files | file ages | folders
SHA1: fd8d7440277b17f57a6dc0a210f42adf1fa2dcd2
User & Date: drh 2012-02-22 16:58:36
Context
2012-02-22
18:21
Make benign any malloc failures inside the sqlite3_file_control() call within PRAGMA parsing. Add a couple simple tests for SQLITE_FCNTL_PRAGMA. check-in: a1f29fa6 user: drh tags: file-control-pragma
16:58
Change the SQLITE_FCNTL_PRAGMA file-control so that it can return a string value. check-in: fd8d7440 user: drh tags: file-control-pragma
14:45
Begin adding support for SQLITE_FCNTL_PRAGMA. check-in: 5be07904 user: drh tags: file-control-pragma
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

  3582   3582       case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
  3583   3583         unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg);
  3584   3584         return SQLITE_OK;
  3585   3585       }
  3586   3586       case SQLITE_FCNTL_VFSNAME: {
  3587   3587         *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
  3588   3588         return SQLITE_OK;
         3589  +    }
         3590  +    case SQLITE_FCNTL_PRAGMA: {
         3591  +      char **azArg = (char**)pArg;
         3592  +      if( sqlite3_stricmp(azArg[1], "filename")==0 ){
         3593  +        azArg[0] = sqlite3_mprintf("%s", pFile->zPath);
         3594  +        return SQLITE_OK;
         3595  +      }
         3596  +      break;
  3589   3597       }
  3590   3598   #ifndef NDEBUG
  3591   3599       /* The pager calls this method to signal that it has done
  3592   3600       ** a rollback and that the database is therefore unchanged and
  3593   3601       ** it hence it is OK for the transaction change counter to be
  3594   3602       ** unchanged.
  3595   3603       */

Changes to src/pragma.c.

   308    308     int minusFlag       /* True if a '-' sign preceded <value> */
   309    309   ){
   310    310     char *zLeft = 0;       /* Nul-terminated UTF-8 string <id> */
   311    311     char *zRight = 0;      /* Nul-terminated UTF-8 string <value>, or NULL */
   312    312     const char *zDb = 0;   /* The database name */
   313    313     Token *pId;            /* Pointer to <id> token */
   314    314     int iDb;               /* Database index for <database> */
   315         -  const char *aFcntl[3];       /* Argument to SQLITE_FCNTL_PRAGMA */
          315  +  char *aFcntl[4];       /* Argument to SQLITE_FCNTL_PRAGMA */
   316    316     int rc;                      /* return value form SQLITE_FCNTL_PRAGMA */
   317    317     sqlite3 *db = pParse->db;    /* The database connection */
   318    318     Db *pDb;                     /* The specific database being pragmaed */
   319    319     Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db);  /* Prepared statement */
   320    320   
   321    321     if( v==0 ) return;
   322    322     sqlite3VdbeRunOnlyOnce(v);
................................................................................
   349    349       goto pragma_out;
   350    350     }
   351    351   
   352    352     /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS
   353    353     ** connection.  If it returns SQLITE_OK, then assume that the VFS
   354    354     ** handled the pragma and generate a no-op prepared statement.
   355    355     */
   356         -  aFcntl[0] = zLeft;
   357         -  aFcntl[1] = zRight;
   358         -  aFcntl[2] = 0;
          356  +  aFcntl[0] = 0;
          357  +  aFcntl[1] = zLeft;
          358  +  aFcntl[2] = zRight;
          359  +  aFcntl[3] = 0;
   359    360     rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
   360    361     if( rc==SQLITE_OK ){
   361         -    zLeft = "";
   362         -  }
          362  +    if( aFcntl[0] ){
          363  +      int mem = ++pParse->nMem;
          364  +      sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0);
          365  +      sqlite3VdbeSetNumCols(v, 1);
          366  +      sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC);
          367  +      sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
          368  +      sqlite3_free(aFcntl[0]);
          369  +    }
          370  +  }else
   363    371                               
   364    372    
   365    373   #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
   366    374     /*
   367    375     **  PRAGMA [database.]default_cache_size
   368    376     **  PRAGMA [database.]default_cache_size=N
   369    377     **

Changes to src/sqlite.h.in.

  6591   6591     void *pNotifyArg                            /* Argument to pass to xNotify */
  6592   6592   );
  6593   6593   
  6594   6594   
  6595   6595   /*
  6596   6596   ** CAPI3REF: String Comparison
  6597   6597   **
  6598         -** ^The [sqlite3_strnicmp()] API allows applications and extensions to
  6599         -** compare the contents of two buffers containing UTF-8 strings in a
  6600         -** case-independent fashion, using the same definition of case independence 
  6601         -** that SQLite uses internally when comparing identifiers.
         6598  +** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications
         6599  +** and extensions to compare the contents of two buffers containing UTF-8
         6600  +** strings in a case-independent fashion, using the same definition of "case
         6601  +** independence" that SQLite uses internally when comparing identifiers.
  6602   6602   */
         6603  +int sqlite3_stricmp(const char *, const char *);
  6603   6604   int sqlite3_strnicmp(const char *, const char *, int);
  6604   6605   
  6605   6606   /*
  6606   6607   ** CAPI3REF: Error Logging Interface
  6607   6608   **
  6608   6609   ** ^The [sqlite3_log()] interface writes a message into the error log
  6609   6610   ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].

Changes to src/sqliteInt.h.

  2549   2549   # define sqlite3Isxdigit(x)  isxdigit((unsigned char)(x))
  2550   2550   # define sqlite3Tolower(x)   tolower((unsigned char)(x))
  2551   2551   #endif
  2552   2552   
  2553   2553   /*
  2554   2554   ** Internal function prototypes
  2555   2555   */
  2556         -int sqlite3StrICmp(const char *, const char *);
         2556  +#define sqlite3StrICmp sqlite3_stricmp
  2557   2557   int sqlite3Strlen30(const char*);
  2558   2558   #define sqlite3StrNICmp sqlite3_strnicmp
  2559   2559   
  2560   2560   int sqlite3MallocInit(void);
  2561   2561   void sqlite3MallocEnd(void);
  2562   2562   void *sqlite3Malloc(int);
  2563   2563   void *sqlite3MallocZero(int);

Changes to src/test_vfstrace.c.

   474    474       case SQLITE_FCNTL_WIN32_AV_RETRY: zOp = "WIN32_AV_RETRY";   break;
   475    475       case SQLITE_FCNTL_PERSIST_WAL:  zOp = "PERSIST_WAL";        break;
   476    476       case SQLITE_FCNTL_OVERWRITE:    zOp = "OVERWRITE";          break;
   477    477       case SQLITE_FCNTL_VFSNAME:      zOp = "VFSNAME";            break;
   478    478       case 0xca093fa0:                zOp = "DB_UNCHANGED";       break;
   479    479       case SQLITE_FCNTL_PRAGMA: {
   480    480         const char *const* a = (const char*const*)pArg;
   481         -      sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[0],a[1]);
          481  +      sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]);
   482    482         zOp = zBuf;
   483    483         break;
   484    484       }
   485    485       default: {
   486    486         sqlite3_snprintf(sizeof zBuf, zBuf, "%d", op);
   487    487         zOp = zBuf;
   488    488         break;
................................................................................
   492    492                     pInfo->zVfsName, p->zFName, zOp);
   493    493     rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
   494    494     vfstrace_print_errcode(pInfo, " -> %s\n", rc);
   495    495     if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
   496    496       *(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z",
   497    497                                       pInfo->zVfsName, *(char**)pArg);
   498    498     }
          499  +  if( op==SQLITE_FCNTL_PRAGMA && rc==SQLITE_OK && *(char**)pArg ){
          500  +    vfstrace_printf(pInfo, "%s.xFileControl(%s,%s) returns %s",
          501  +                    pInfo->zVfsName, p->zFNmae, zOp, *(char**)pArg);
          502  +  }
   499    503     return rc;
   500    504   }
   501    505   
   502    506   /*
   503    507   ** Return the sector-size in bytes for an vfstrace-file.
   504    508   */
   505    509   static int vfstraceSectorSize(sqlite3_file *pFile){

Changes to src/util.c.

   218    218   **
   219    219   ** IMPLEMENTATION-OF: R-20522-24639 The sqlite3_strnicmp() API allows
   220    220   ** applications and extensions to compare the contents of two buffers
   221    221   ** containing UTF-8 strings in a case-independent fashion, using the same
   222    222   ** definition of case independence that SQLite uses internally when
   223    223   ** comparing identifiers.
   224    224   */
   225         -int sqlite3StrICmp(const char *zLeft, const char *zRight){
          225  +int sqlite3_stricmp(const char *zLeft, const char *zRight){
   226    226     register unsigned char *a, *b;
   227    227     a = (unsigned char *)zLeft;
   228    228     b = (unsigned char *)zRight;
   229    229     while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
   230    230     return UpperToLower[*a] - UpperToLower[*b];
   231    231   }
   232    232   int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){

Changes to test/attach.test.

    65     65   } {}
    66     66   do_test attach-1.3.4 {
    67     67     file tail [sqlite3_db_filename db two]
    68     68   } {test2.db}
    69     69   do_test attach-1.3.5 {
    70     70     file tail [sqlite3_db_filename db three]
    71     71   } {}
           72  +
    72     73   
    73     74   do_test attach-1.4 {
    74     75     execsql {
    75     76       SELECT * FROM t2;
    76     77     }
    77     78   } {1 x 2 y}
    78     79   do_test attach-1.5 {
................................................................................
   266    267     } else {
   267    268       do_test attach-1.29 {
   268    269         db_list db
   269    270       } {0 main}
   270    271     }
   271    272   } ;# ifcapable schema_pragmas
   272    273   
          274  +
          275  +if {[regexp unix [file_control_vfsname db]]} {
          276  +  do_test attach-1.30.1 {
          277  +    file tail [db eval {PRAGMA main.filename}]
          278  +  } {test.db}
          279  +  do_test attach-1.30.2 {
          280  +    db eval {PRAGMA temp.filename}
          281  +  } {}
          282  +}
          283  +
   273    284   ifcapable {trigger} {  # Only do the following tests if triggers are enabled
   274    285   do_test attach-2.1 {
   275    286     execsql {
   276    287       CREATE TABLE tx(x1,x2,y1,y2);
   277    288       CREATE TRIGGER r1 AFTER UPDATE ON t2 FOR EACH ROW BEGIN
   278    289         INSERT INTO tx(x1,x2,y1,y2) VALUES(OLD.x,NEW.x,OLD.y,NEW.y);
   279    290       END;