Back to index

lightning-sunbird  0.9+nobinonly
table.c
Go to the documentation of this file.
00001 /*
00002 ** 2001 September 15
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 *************************************************************************
00012 ** This file contains the sqlite3_get_table() and sqlite3_free_table()
00013 ** interface routines.  These are just wrappers around the main
00014 ** interface routine of sqlite3_exec().
00015 **
00016 ** These routines are in a separate files so that they will not be linked
00017 ** if they are not used.
00018 */
00019 #include "sqliteInt.h"
00020 #include <stdlib.h>
00021 #include <string.h>
00022 
00023 #ifndef SQLITE_OMIT_GET_TABLE
00024 
00025 /*
00026 ** This structure is used to pass data from sqlite3_get_table() through
00027 ** to the callback function is uses to build the result.
00028 */
00029 typedef struct TabResult {
00030   char **azResult;
00031   char *zErrMsg;
00032   int nResult;
00033   int nAlloc;
00034   int nRow;
00035   int nColumn;
00036   int nData;
00037   int rc;
00038 } TabResult;
00039 
00040 /*
00041 ** This routine is called once for each row in the result table.  Its job
00042 ** is to fill in the TabResult structure appropriately, allocating new
00043 ** memory as necessary.
00044 */
00045 static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
00046   TabResult *p = (TabResult*)pArg;
00047   int need;
00048   int i;
00049   char *z;
00050 
00051   /* Make sure there is enough space in p->azResult to hold everything
00052   ** we need to remember from this invocation of the callback.
00053   */
00054   if( p->nRow==0 && argv!=0 ){
00055     need = nCol*2;
00056   }else{
00057     need = nCol;
00058   }
00059   if( p->nData + need >= p->nAlloc ){
00060     char **azNew;
00061     p->nAlloc = p->nAlloc*2 + need + 1;
00062     azNew = realloc( p->azResult, sizeof(char*)*p->nAlloc );
00063     if( azNew==0 ) goto malloc_failed;
00064     p->azResult = azNew;
00065   }
00066 
00067   /* If this is the first row, then generate an extra row containing
00068   ** the names of all columns.
00069   */
00070   if( p->nRow==0 ){
00071     p->nColumn = nCol;
00072     for(i=0; i<nCol; i++){
00073       if( colv[i]==0 ){
00074         z = 0;
00075       }else{
00076         z = malloc( strlen(colv[i])+1 );
00077         if( z==0 ) goto malloc_failed;
00078         strcpy(z, colv[i]);
00079       }
00080       p->azResult[p->nData++] = z;
00081     }
00082   }else if( p->nColumn!=nCol ){
00083     sqlite3SetString(&p->zErrMsg,
00084        "sqlite3_get_table() called with two or more incompatible queries",
00085        (char*)0);
00086     p->rc = SQLITE_ERROR;
00087     return 1;
00088   }
00089 
00090   /* Copy over the row data
00091   */
00092   if( argv!=0 ){
00093     for(i=0; i<nCol; i++){
00094       if( argv[i]==0 ){
00095         z = 0;
00096       }else{
00097         z = malloc( strlen(argv[i])+1 );
00098         if( z==0 ) goto malloc_failed;
00099         strcpy(z, argv[i]);
00100       }
00101       p->azResult[p->nData++] = z;
00102     }
00103     p->nRow++;
00104   }
00105   return 0;
00106 
00107 malloc_failed:
00108   p->rc = SQLITE_NOMEM;
00109   return 1;
00110 }
00111 
00112 /*
00113 ** Query the database.  But instead of invoking a callback for each row,
00114 ** malloc() for space to hold the result and return the entire results
00115 ** at the conclusion of the call.
00116 **
00117 ** The result that is written to ***pazResult is held in memory obtained
00118 ** from malloc().  But the caller cannot free this memory directly.  
00119 ** Instead, the entire table should be passed to sqlite3_free_table() when
00120 ** the calling procedure is finished using it.
00121 */
00122 int sqlite3_get_table(
00123   sqlite3 *db,                /* The database on which the SQL executes */
00124   const char *zSql,           /* The SQL to be executed */
00125   char ***pazResult,          /* Write the result table here */
00126   int *pnRow,                 /* Write the number of rows in the result here */
00127   int *pnColumn,              /* Write the number of columns of result here */
00128   char **pzErrMsg             /* Write error messages here */
00129 ){
00130   int rc;
00131   TabResult res;
00132   if( pazResult==0 ){ return SQLITE_ERROR; }
00133   *pazResult = 0;
00134   if( pnColumn ) *pnColumn = 0;
00135   if( pnRow ) *pnRow = 0;
00136   res.zErrMsg = 0;
00137   res.nResult = 0;
00138   res.nRow = 0;
00139   res.nColumn = 0;
00140   res.nData = 1;
00141   res.nAlloc = 20;
00142   res.rc = SQLITE_OK;
00143   res.azResult = malloc( sizeof(char*)*res.nAlloc );
00144   if( res.azResult==0 ) return SQLITE_NOMEM;
00145   res.azResult[0] = 0;
00146   rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg);
00147   if( res.azResult ){
00148     assert( sizeof(res.azResult[0])>= sizeof(res.nData) );
00149     res.azResult[0] = (char*)res.nData;
00150   }
00151   if( rc==SQLITE_ABORT ){
00152     sqlite3_free_table(&res.azResult[1]);
00153     if( res.zErrMsg ){
00154       if( pzErrMsg ){
00155         free(*pzErrMsg);
00156         *pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg);
00157       }
00158       sqliteFree(res.zErrMsg);
00159     }
00160     db->errCode = res.rc;
00161     return res.rc;
00162   }
00163   sqliteFree(res.zErrMsg);
00164   if( rc!=SQLITE_OK ){
00165     sqlite3_free_table(&res.azResult[1]);
00166     return rc;
00167   }
00168   if( res.nAlloc>res.nData ){
00169     char **azNew;
00170     azNew = realloc( res.azResult, sizeof(char*)*(res.nData+1) );
00171     if( azNew==0 ){
00172       sqlite3_free_table(&res.azResult[1]);
00173       return SQLITE_NOMEM;
00174     }
00175     res.nAlloc = res.nData+1;
00176     res.azResult = azNew;
00177   }
00178   *pazResult = &res.azResult[1];
00179   if( pnColumn ) *pnColumn = res.nColumn;
00180   if( pnRow ) *pnRow = res.nRow;
00181   return rc;
00182 }
00183 
00184 /*
00185 ** This routine frees the space the sqlite3_get_table() malloced.
00186 */
00187 void sqlite3_free_table(
00188   char **azResult            /* Result returned from from sqlite3_get_table() */
00189 ){
00190   if( azResult ){
00191     int i, n;
00192     azResult--;
00193     if( azResult==0 ) return;
00194     n = (int)azResult[0];
00195     for(i=1; i<n; i++){ if( azResult[i] ) free(azResult[i]); }
00196     free(azResult);
00197   }
00198 }
00199 
00200 #endif /* SQLITE_OMIT_GET_TABLE */