aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/sqlite/win32/table.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/sqlite/win32/table.c')
-rwxr-xr-xlibraries/sqlite/win32/table.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/libraries/sqlite/win32/table.c b/libraries/sqlite/win32/table.c
new file mode 100755
index 0000000..a79a6ac
--- /dev/null
+++ b/libraries/sqlite/win32/table.c
@@ -0,0 +1,206 @@
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*/
29typedef struct TabResult {
30 char **azResult;
31 char *zErrMsg;
32 int nResult;
33 int nAlloc;
34 int nRow;
35 int nColumn;
36 int nData;
37 int rc;
38} TabResult;
39
40/*
41** This routine is called once for each row in the result table. Its job
42** is to fill in the TabResult structure appropriately, allocating new
43** memory as necessary.
44*/
45static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
46 TabResult *p = (TabResult*)pArg;
47 int need;
48 int i;
49 char *z;
50
51 /* Make sure there is enough space in p->azResult to hold everything
52 ** we need to remember from this invocation of the callback.
53 */
54 if( p->nRow==0 && argv!=0 ){
55 need = nCol*2;
56 }else{
57 need = nCol;
58 }
59 if( p->nData + need >= p->nAlloc ){
60 char **azNew;
61 p->nAlloc = p->nAlloc*2 + need + 1;
62 azNew = sqlite3_realloc( p->azResult, sizeof(char*)*p->nAlloc );
63 if( azNew==0 ) goto malloc_failed;
64 p->azResult = azNew;
65 }
66
67 /* If this is the first row, then generate an extra row containing
68 ** the names of all columns.
69 */
70 if( p->nRow==0 ){
71 p->nColumn = nCol;
72 for(i=0; i<nCol; i++){
73 if( colv[i]==0 ){
74 z = sqlite3_mprintf("");
75 }else{
76 z = sqlite3_mprintf("%s", colv[i]);
77 }
78 p->azResult[p->nData++] = z;
79 }
80 }else if( p->nColumn!=nCol ){
81 sqlite3SetString(&p->zErrMsg,
82 "sqlite3_get_table() called with two or more incompatible queries",
83 (char*)0);
84 p->rc = SQLITE_ERROR;
85 return 1;
86 }
87
88 /* Copy over the row data
89 */
90 if( argv!=0 ){
91 for(i=0; i<nCol; i++){
92 if( argv[i]==0 ){
93 z = 0;
94 }else{
95 int n = strlen(argv[i])+1;
96 z = sqlite3_malloc( n );
97 if( z==0 ) goto malloc_failed;
98 memcpy(z, argv[i], n);
99 }
100 p->azResult[p->nData++] = z;
101 }
102 p->nRow++;
103 }
104 return 0;
105
106malloc_failed:
107 p->rc = SQLITE_NOMEM;
108 return 1;
109}
110
111/*
112** Query the database. But instead of invoking a callback for each row,
113** malloc() for space to hold the result and return the entire results
114** at the conclusion of the call.
115**
116** The result that is written to ***pazResult is held in memory obtained
117** from malloc(). But the caller cannot free this memory directly.
118** Instead, the entire table should be passed to sqlite3_free_table() when
119** the calling procedure is finished using it.
120*/
121int sqlite3_get_table(
122 sqlite3 *db, /* The database on which the SQL executes */
123 const char *zSql, /* The SQL to be executed */
124 char ***pazResult, /* Write the result table here */
125 int *pnRow, /* Write the number of rows in the result here */
126 int *pnColumn, /* Write the number of columns of result here */
127 char **pzErrMsg /* Write error messages here */
128){
129 int rc;
130 TabResult res;
131 if( pazResult==0 ){ return SQLITE_ERROR; }
132 *pazResult = 0;
133 if( pnColumn ) *pnColumn = 0;
134 if( pnRow ) *pnRow = 0;
135 res.zErrMsg = 0;
136 res.nResult = 0;
137 res.nRow = 0;
138 res.nColumn = 0;
139 res.nData = 1;
140 res.nAlloc = 20;
141 res.rc = SQLITE_OK;
142 res.azResult = sqlite3_malloc( sizeof(char*)*res.nAlloc );
143 if( res.azResult==0 ) return SQLITE_NOMEM;
144 res.azResult[0] = 0;
145 rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg);
146#ifndef NDEBUG
147 sqlite3_mutex_enter(db->mutex);
148 assert((rc&db->errMask)==rc && (res.rc&db->errMask)==res.rc);
149 sqlite3_mutex_leave(db->mutex);
150#endif
151 if( res.azResult ){
152 assert( sizeof(res.azResult[0])>= sizeof(res.nData) );
153 res.azResult[0] = (char*)res.nData;
154 }
155 if( (rc&0xff)==SQLITE_ABORT ){
156 sqlite3_free_table(&res.azResult[1]);
157 if( res.zErrMsg ){
158 if( pzErrMsg ){
159 sqlite3_free(*pzErrMsg);
160 *pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg);
161 }
162 sqlite3_free(res.zErrMsg);
163 }
164 sqlite3_mutex_enter(db->mutex);
165 db->errCode = res.rc;
166 sqlite3_mutex_leave(db->mutex);
167 return res.rc;
168 }
169 sqlite3_free(res.zErrMsg);
170 if( rc!=SQLITE_OK ){
171 sqlite3_free_table(&res.azResult[1]);
172 return rc;
173 }
174 if( res.nAlloc>res.nData ){
175 char **azNew;
176 azNew = sqlite3_realloc( res.azResult, sizeof(char*)*(res.nData+1) );
177 if( azNew==0 ){
178 sqlite3_free_table(&res.azResult[1]);
179 return SQLITE_NOMEM;
180 }
181 res.nAlloc = res.nData+1;
182 res.azResult = azNew;
183 }
184 *pazResult = &res.azResult[1];
185 if( pnColumn ) *pnColumn = res.nColumn;
186 if( pnRow ) *pnRow = res.nRow;
187 return rc;
188}
189
190/*
191** This routine frees the space the sqlite3_get_table() malloced.
192*/
193void sqlite3_free_table(
194 char **azResult /* Result returned from from sqlite3_get_table() */
195){
196 if( azResult ){
197 int i, n;
198 azResult--;
199 if( azResult==0 ) return;
200 n = (int)azResult[0];
201 for(i=1; i<n; i++){ if( azResult[i] ) sqlite3_free(azResult[i]); }
202 sqlite3_free(azResult);
203 }
204}
205
206#endif /* SQLITE_OMIT_GET_TABLE */