diff options
Diffstat (limited to 'libraries/sqlite/win32/table.c')
-rwxr-xr-x | libraries/sqlite/win32/table.c | 206 |
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 | */ | ||
29 | typedef 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 | */ | ||
45 | static 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 | |||
106 | malloc_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 | */ | ||
121 | int 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 | */ | ||
193 | void 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 */ | ||