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