dvander@1203: /* dvander@1203: ** 2001 September 15 dvander@1203: ** dvander@1203: ** The author disclaims copyright to this source code. In place of dvander@1203: ** a legal notice, here is a blessing: dvander@1203: ** dvander@1203: ** May you do good and not evil. dvander@1203: ** May you find forgiveness for yourself and forgive others. dvander@1203: ** May you share freely, never taking more than you give. dvander@1203: ** dvander@1203: ************************************************************************* dvander@1203: ** This file contains the sqlite3_get_table() and sqlite3_free_table() dvander@1203: ** interface routines. These are just wrappers around the main dvander@1203: ** interface routine of sqlite3_exec(). dvander@1203: ** dvander@1203: ** These routines are in a separate files so that they will not be linked dvander@1203: ** if they are not used. dvander@1203: */ dvander@1203: #include "sqliteInt.h" dvander@1203: #include dvander@1203: #include dvander@1203: dvander@1203: #ifndef SQLITE_OMIT_GET_TABLE dvander@1203: dvander@1203: /* dvander@1203: ** This structure is used to pass data from sqlite3_get_table() through dvander@1203: ** to the callback function is uses to build the result. dvander@1203: */ dvander@1203: typedef struct TabResult { dvander@1203: char **azResult; dvander@1203: char *zErrMsg; dvander@1203: int nResult; dvander@1203: int nAlloc; dvander@1203: int nRow; dvander@1203: int nColumn; dvander@1203: int nData; dvander@1203: int rc; dvander@1203: } TabResult; dvander@1203: dvander@1203: /* dvander@1203: ** This routine is called once for each row in the result table. Its job dvander@1203: ** is to fill in the TabResult structure appropriately, allocating new dvander@1203: ** memory as necessary. dvander@1203: */ dvander@1203: static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ dvander@1203: TabResult *p = (TabResult*)pArg; dvander@1203: int need; dvander@1203: int i; dvander@1203: char *z; dvander@1203: dvander@1203: /* Make sure there is enough space in p->azResult to hold everything dvander@1203: ** we need to remember from this invocation of the callback. dvander@1203: */ dvander@1203: if( p->nRow==0 && argv!=0 ){ dvander@1203: need = nCol*2; dvander@1203: }else{ dvander@1203: need = nCol; dvander@1203: } dvander@1203: if( p->nData + need >= p->nAlloc ){ dvander@1203: char **azNew; dvander@1203: p->nAlloc = p->nAlloc*2 + need + 1; dvander@1203: azNew = sqlite3_realloc( p->azResult, sizeof(char*)*p->nAlloc ); dvander@1203: if( azNew==0 ) goto malloc_failed; dvander@1203: p->azResult = azNew; dvander@1203: } dvander@1203: dvander@1203: /* If this is the first row, then generate an extra row containing dvander@1203: ** the names of all columns. dvander@1203: */ dvander@1203: if( p->nRow==0 ){ dvander@1203: p->nColumn = nCol; dvander@1203: for(i=0; iazResult[p->nData++] = z; dvander@1203: } dvander@1203: }else if( p->nColumn!=nCol ){ dvander@1203: sqlite3SetString(&p->zErrMsg, dvander@1203: "sqlite3_get_table() called with two or more incompatible queries", dvander@1203: (char*)0); dvander@1203: p->rc = SQLITE_ERROR; dvander@1203: return 1; dvander@1203: } dvander@1203: dvander@1203: /* Copy over the row data dvander@1203: */ dvander@1203: if( argv!=0 ){ dvander@1203: for(i=0; iazResult[p->nData++] = z; dvander@1203: } dvander@1203: p->nRow++; dvander@1203: } dvander@1203: return 0; dvander@1203: dvander@1203: malloc_failed: dvander@1203: p->rc = SQLITE_NOMEM; dvander@1203: return 1; dvander@1203: } dvander@1203: dvander@1203: /* dvander@1203: ** Query the database. But instead of invoking a callback for each row, dvander@1203: ** malloc() for space to hold the result and return the entire results dvander@1203: ** at the conclusion of the call. dvander@1203: ** dvander@1203: ** The result that is written to ***pazResult is held in memory obtained dvander@1203: ** from malloc(). But the caller cannot free this memory directly. dvander@1203: ** Instead, the entire table should be passed to sqlite3_free_table() when dvander@1203: ** the calling procedure is finished using it. dvander@1203: */ dvander@1203: int sqlite3_get_table( dvander@1203: sqlite3 *db, /* The database on which the SQL executes */ dvander@1203: const char *zSql, /* The SQL to be executed */ dvander@1203: char ***pazResult, /* Write the result table here */ dvander@1203: int *pnRow, /* Write the number of rows in the result here */ dvander@1203: int *pnColumn, /* Write the number of columns of result here */ dvander@1203: char **pzErrMsg /* Write error messages here */ dvander@1203: ){ dvander@1203: int rc; dvander@1203: TabResult res; dvander@1203: if( pazResult==0 ){ return SQLITE_ERROR; } dvander@1203: *pazResult = 0; dvander@1203: if( pnColumn ) *pnColumn = 0; dvander@1203: if( pnRow ) *pnRow = 0; dvander@1203: res.zErrMsg = 0; dvander@1203: res.nResult = 0; dvander@1203: res.nRow = 0; dvander@1203: res.nColumn = 0; dvander@1203: res.nData = 1; dvander@1203: res.nAlloc = 20; dvander@1203: res.rc = SQLITE_OK; dvander@1203: res.azResult = sqlite3_malloc( sizeof(char*)*res.nAlloc ); dvander@1203: if( res.azResult==0 ) return SQLITE_NOMEM; dvander@1203: res.azResult[0] = 0; dvander@1203: rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg); dvander@1645: #ifndef NDEBUG dvander@1645: sqlite3_mutex_enter(db->mutex); dvander@1645: assert((rc&db->errMask)==rc && (res.rc&db->errMask)==res.rc); dvander@1645: sqlite3_mutex_leave(db->mutex); dvander@1645: #endif dvander@1203: if( res.azResult ){ dvander@1203: assert( sizeof(res.azResult[0])>= sizeof(res.nData) ); dvander@1203: res.azResult[0] = (char*)res.nData; dvander@1203: } dvander@1203: if( (rc&0xff)==SQLITE_ABORT ){ dvander@1203: sqlite3_free_table(&res.azResult[1]); dvander@1203: if( res.zErrMsg ){ dvander@1203: if( pzErrMsg ){ dvander@1203: sqlite3_free(*pzErrMsg); dvander@1203: *pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg); dvander@1203: } dvander@1645: sqlite3_free(res.zErrMsg); dvander@1203: } dvander@1645: sqlite3_mutex_enter(db->mutex); dvander@1203: db->errCode = res.rc; dvander@1645: sqlite3_mutex_leave(db->mutex); dvander@1645: return res.rc; dvander@1203: } dvander@1645: sqlite3_free(res.zErrMsg); dvander@1203: if( rc!=SQLITE_OK ){ dvander@1203: sqlite3_free_table(&res.azResult[1]); dvander@1645: return rc; dvander@1203: } dvander@1203: if( res.nAlloc>res.nData ){ dvander@1203: char **azNew; dvander@1203: azNew = sqlite3_realloc( res.azResult, sizeof(char*)*(res.nData+1) ); dvander@1203: if( azNew==0 ){ dvander@1203: sqlite3_free_table(&res.azResult[1]); dvander@1203: return SQLITE_NOMEM; dvander@1203: } dvander@1203: res.nAlloc = res.nData+1; dvander@1203: res.azResult = azNew; dvander@1203: } dvander@1203: *pazResult = &res.azResult[1]; dvander@1203: if( pnColumn ) *pnColumn = res.nColumn; dvander@1203: if( pnRow ) *pnRow = res.nRow; dvander@1645: return rc; dvander@1203: } dvander@1203: dvander@1203: /* dvander@1203: ** This routine frees the space the sqlite3_get_table() malloced. dvander@1203: */ dvander@1203: void sqlite3_free_table( dvander@1203: char **azResult /* Result returned from from sqlite3_get_table() */ dvander@1203: ){ dvander@1203: if( azResult ){ dvander@1203: int i, n; dvander@1203: azResult--; dvander@1203: if( azResult==0 ) return; dvander@1203: n = (int)azResult[0]; dvander@1203: for(i=1; i