1
2#pragma ident	"%Z%%M%	%I%	%E% SMI"
3
4/*
5** 2001 September 15
6**
7** The author disclaims copyright to this source code.  In place of
8** a legal notice, here is a blessing:
9**
10**    May you do good and not evil.
11**    May you find forgiveness for yourself and forgive others.
12**    May you share freely, never taking more than you give.
13**
14*************************************************************************
15** This file contains the sqlite_get_table() and sqlite_free_table()
16** interface routines.  These are just wrappers around the main
17** interface routine of sqlite_exec().
18**
19** These routines are in a separate files so that they will not be linked
20** if they are not used.
21*/
22#include <stdlib.h>
23#include <string.h>
24#include "sqliteInt.h"
25
26/*
27** This structure is used to pass data from sqlite_get_table() through
28** to the callback function is uses to build the result.
29*/
30typedef struct TabResult {
31  char **azResult;
32  char *zErrMsg;
33  int nResult;
34  int nAlloc;
35  int nRow;
36  int nColumn;
37  long nData;
38  int rc;
39} TabResult;
40
41/*
42** This routine is called once for each row in the result table.  Its job
43** is to fill in the TabResult structure appropriately, allocating new
44** memory as necessary.
45*/
46static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
47  TabResult *p = (TabResult*)pArg;
48  int need;
49  int i;
50  char *z;
51
52  /* Make sure there is enough space in p->azResult to hold everything
53  ** we need to remember from this invocation of the callback.
54  */
55  if( p->nRow==0 && argv!=0 ){
56    need = nCol*2;
57  }else{
58    need = nCol;
59  }
60  if( p->nData + need >= p->nAlloc ){
61    char **azNew;
62    p->nAlloc = p->nAlloc*2 + need + 1;
63    azNew = realloc( p->azResult, sizeof(char*)*p->nAlloc );
64    if( azNew==0 ){
65      p->rc = SQLITE_NOMEM;
66      return 1;
67    }
68    p->azResult = azNew;
69  }
70
71  /* If this is the first row, then generate an extra row containing
72  ** the names of all columns.
73  */
74  if( p->nRow==0 ){
75    p->nColumn = nCol;
76    for(i=0; i<nCol; i++){
77      if( colv[i]==0 ){
78        z = 0;
79      }else{
80        z = malloc( strlen(colv[i])+1 );
81        if( z==0 ){
82          p->rc = SQLITE_NOMEM;
83          return 1;
84        }
85        strcpy(z, colv[i]);
86      }
87      p->azResult[p->nData++] = z;
88    }
89  }else if( p->nColumn!=nCol ){
90    sqliteSetString(&p->zErrMsg,
91       "sqlite_get_table() called with two or more incompatible queries",
92       (char*)0);
93    p->rc = SQLITE_ERROR;
94    return 1;
95  }
96
97  /* Copy over the row data
98  */
99  if( argv!=0 ){
100    for(i=0; i<nCol; i++){
101      if( argv[i]==0 ){
102        z = 0;
103      }else{
104        z = malloc( strlen(argv[i])+1 );
105        if( z==0 ){
106          p->rc = SQLITE_NOMEM;
107          return 1;
108        }
109        strcpy(z, argv[i]);
110      }
111      p->azResult[p->nData++] = z;
112    }
113    p->nRow++;
114  }
115  return 0;
116}
117
118/*
119** Query the database.  But instead of invoking a callback for each row,
120** malloc() for space to hold the result and return the entire results
121** at the conclusion of the call.
122**
123** The result that is written to ***pazResult is held in memory obtained
124** from malloc().  But the caller cannot free this memory directly.
125** Instead, the entire table should be passed to sqlite_free_table() when
126** the calling procedure is finished using it.
127*/
128int sqlite_get_table(
129  sqlite *db,                 /* The database on which the SQL executes */
130  const char *zSql,           /* The SQL to be executed */
131  char ***pazResult,          /* Write the result table here */
132  int *pnRow,                 /* Write the number of rows in the result here */
133  int *pnColumn,              /* Write the number of columns of result here */
134  char **pzErrMsg             /* Write error messages here */
135){
136  int rc;
137  TabResult res;
138  if( pazResult==0 ){ return SQLITE_ERROR; }
139  *pazResult = 0;
140  if( pnColumn ) *pnColumn = 0;
141  if( pnRow ) *pnRow = 0;
142  res.zErrMsg = 0;
143  res.nResult = 0;
144  res.nRow = 0;
145  res.nColumn = 0;
146  res.nData = 1;
147  res.nAlloc = 20;
148  res.rc = SQLITE_OK;
149  res.azResult = malloc( sizeof(char*)*res.nAlloc );
150  if( res.azResult==0 ){
151    return SQLITE_NOMEM;
152  }
153  res.azResult[0] = 0;
154  rc = sqlite_exec(db, zSql, sqlite_get_table_cb, &res, pzErrMsg);
155  if( res.azResult ){
156    res.azResult[0] = (char*)res.nData;
157  }
158  if( rc==SQLITE_ABORT ){
159    sqlite_free_table(&res.azResult[1]);
160    if( res.zErrMsg ){
161      if( pzErrMsg ){
162        free(*pzErrMsg);
163        *pzErrMsg = res.zErrMsg;
164        sqliteStrRealloc(pzErrMsg);
165      }else{
166        sqliteFree(res.zErrMsg);
167      }
168    }
169    return res.rc;
170  }
171  sqliteFree(res.zErrMsg);
172  if( rc!=SQLITE_OK ){
173    sqlite_free_table(&res.azResult[1]);
174    return rc;
175  }
176  if( res.nAlloc>res.nData ){
177    char **azNew;
178    azNew = realloc( res.azResult, sizeof(char*)*(res.nData+1) );
179    if( azNew==0 ){
180      sqlite_free_table(&res.azResult[1]);
181      return SQLITE_NOMEM;
182    }
183    res.nAlloc = res.nData+1;
184    res.azResult = azNew;
185  }
186  *pazResult = &res.azResult[1];
187  if( pnColumn ) *pnColumn = res.nColumn;
188  if( pnRow ) *pnRow = res.nRow;
189  return rc;
190}
191
192/*
193** This routine frees the space the sqlite_get_table() malloced.
194*/
195void sqlite_free_table(
196  char **azResult             /* Result returned from from sqlite_get_table() */
197){
198  if( azResult ){
199    int i, n;
200    azResult--;
201    if( azResult==0 ) return;
202    n = (int)(long)azResult[0];
203    for(i=1; i<n; i++){ if( azResult[i] ) free(azResult[i]); }
204    free(azResult);
205  }
206}
207