Fossil SCM

refactored db_generic_query_view() to use sqlite3 API directly so that it can treat SQL errors as non-fatal.

stephan 2008-02-06 19:37 trunk
Commit 0dc3e7a0d5a1d9886d4880e715916f38b6d6e70f
1 file changed +26 -18
+26 -18
--- src/db.c
+++ src/db.c
@@ -1139,10 +1139,12 @@
11391139
* fewer, undefined behaviour results. If a column has an entry in
11401140
* xform, then the xform function will be called to transform the
11411141
* column data before rendering it. This function takes care of freeing
11421142
* the strings created by the xform functions.
11431143
*
1144
+* Returns SQLITE_OK on success and any other value on error.
1145
+*
11441146
* Example:
11451147
*
11461148
* char const * const colnames[] = {
11471149
* "Tag ID", "Tag Name", "Something Else", "UUID"
11481150
* };
@@ -1153,56 +1155,62 @@
11531155
* strxform_link_to_uuid
11541156
* };
11551157
* db_generic_query_view( "select a,b,c,d from foo", colnames, xf );
11561158
*
11571159
*/
1158
-void db_generic_query_view(
1160
+int db_generic_query_view(
11591161
char const * sql,
11601162
char const * const * coln,
11611163
string_unary_xform_f const * xform )
11621164
{
1163
-
1164
- Stmt st;
1165
- int i = 0;
1166
- int rc = db_prepare( &st, sql );
11671165
/**
1168
- Achtung: makeheaders apparently can't pull the function
1169
- name from this:
1170
- if( SQLITE_OK != db_prepare( &st, sql ) )
1171
- */
1166
+ Reminder: we use sqlite3_stmt directly, instead
1167
+ of using db_prepare(), so that we can treat SQL
1168
+ errors as non-fatal. We are executing arbitrary
1169
+ SQL here, some of it entered via the browser,
1170
+ and we don't want to kill the app when some of
1171
+ the SQL isn't quite right.
1172
+ */
1173
+ sqlite3_stmt * st;
1174
+ int rc = sqlite3_prepare(g.db, sql, -1, &st, 0);
11721175
if( SQLITE_OK != rc )
11731176
{
1174
- @ db_generic_query_view(): Error processing SQL: [%s(sql)]
1175
- return;
1177
+ @ <span style='color:red'>db_generic_query_view() SQL error:
1178
+ @ %h(sqlite3_errmsg(g.db))</span>
1179
+ return rc;
11761180
}
1177
- int colc = db_column_count(&st);
1181
+ int colc = sqlite3_column_count(st);
11781182
@ <table class='fossil_db_generic_query_view'><tbody>
11791183
@ <tr class='header'>
1184
+ int i = 0;
11801185
for( i = 0; i < colc; ++i ) {
11811186
if( coln )
11821187
{
1183
- @ <th>%s(coln[i] ? coln[i] : db_column_name(&st,i))</th>
1188
+ @ <th>%s(coln[i] ? coln[i] : sqlite3_column_name(st,i))</th>
11841189
}
11851190
else
11861191
{
1187
- @ <td>%s(db_column_name(&st,i))</td>
1192
+ @ <td>%s(sqlite3_column_name(st,i))</td>
11881193
}
11891194
}
11901195
@ </tr>
11911196
11921197
int row = 0;
1193
- while( SQLITE_ROW == db_step(&st) ){
1198
+ char const * text = 0;
1199
+ while( SQLITE_ROW == sqlite3_step(st) ){
11941200
@ <tr class='%s( (row++%2) ? "odd" : "even")'>
11951201
for( i = 0; i < colc; ++i ) {
1202
+ text = (char const *) sqlite3_column_text(st,i);
11961203
char * xf = 0;
11971204
char const * xcf = 0;
11981205
xcf = (xform && xform[i])
1199
- ? (xf=(xform[i])(db_column_text(&st,i)))
1200
- : db_column_text(&st,i);
1206
+ ? (xf=(xform[i])(text))
1207
+ : text;
12011208
@ <td>%s(xcf)</td>
12021209
if( xf ) free( xf );
12031210
}
12041211
@ </tr>
12051212
}
1206
- db_finalize( &st );
12071213
@ </tbody></table>
1214
+ sqlite3_finalize(st);
1215
+ return SQLITE_OK;
12081216
}
12091217
--- src/db.c
+++ src/db.c
@@ -1139,10 +1139,12 @@
1139 * fewer, undefined behaviour results. If a column has an entry in
1140 * xform, then the xform function will be called to transform the
1141 * column data before rendering it. This function takes care of freeing
1142 * the strings created by the xform functions.
1143 *
 
 
1144 * Example:
1145 *
1146 * char const * const colnames[] = {
1147 * "Tag ID", "Tag Name", "Something Else", "UUID"
1148 * };
@@ -1153,56 +1155,62 @@
1153 * strxform_link_to_uuid
1154 * };
1155 * db_generic_query_view( "select a,b,c,d from foo", colnames, xf );
1156 *
1157 */
1158 void db_generic_query_view(
1159 char const * sql,
1160 char const * const * coln,
1161 string_unary_xform_f const * xform )
1162 {
1163
1164 Stmt st;
1165 int i = 0;
1166 int rc = db_prepare( &st, sql );
1167 /**
1168 Achtung: makeheaders apparently can't pull the function
1169 name from this:
1170 if( SQLITE_OK != db_prepare( &st, sql ) )
1171 */
 
 
 
 
 
1172 if( SQLITE_OK != rc )
1173 {
1174 @ db_generic_query_view(): Error processing SQL: [%s(sql)]
1175 return;
 
1176 }
1177 int colc = db_column_count(&st);
1178 @ <table class='fossil_db_generic_query_view'><tbody>
1179 @ <tr class='header'>
 
1180 for( i = 0; i < colc; ++i ) {
1181 if( coln )
1182 {
1183 @ <th>%s(coln[i] ? coln[i] : db_column_name(&st,i))</th>
1184 }
1185 else
1186 {
1187 @ <td>%s(db_column_name(&st,i))</td>
1188 }
1189 }
1190 @ </tr>
1191
1192 int row = 0;
1193 while( SQLITE_ROW == db_step(&st) ){
 
1194 @ <tr class='%s( (row++%2) ? "odd" : "even")'>
1195 for( i = 0; i < colc; ++i ) {
 
1196 char * xf = 0;
1197 char const * xcf = 0;
1198 xcf = (xform && xform[i])
1199 ? (xf=(xform[i])(db_column_text(&st,i)))
1200 : db_column_text(&st,i);
1201 @ <td>%s(xcf)</td>
1202 if( xf ) free( xf );
1203 }
1204 @ </tr>
1205 }
1206 db_finalize( &st );
1207 @ </tbody></table>
 
 
1208 }
1209
--- src/db.c
+++ src/db.c
@@ -1139,10 +1139,12 @@
1139 * fewer, undefined behaviour results. If a column has an entry in
1140 * xform, then the xform function will be called to transform the
1141 * column data before rendering it. This function takes care of freeing
1142 * the strings created by the xform functions.
1143 *
1144 * Returns SQLITE_OK on success and any other value on error.
1145 *
1146 * Example:
1147 *
1148 * char const * const colnames[] = {
1149 * "Tag ID", "Tag Name", "Something Else", "UUID"
1150 * };
@@ -1153,56 +1155,62 @@
1155 * strxform_link_to_uuid
1156 * };
1157 * db_generic_query_view( "select a,b,c,d from foo", colnames, xf );
1158 *
1159 */
1160 int db_generic_query_view(
1161 char const * sql,
1162 char const * const * coln,
1163 string_unary_xform_f const * xform )
1164 {
 
 
 
 
1165 /**
1166 Reminder: we use sqlite3_stmt directly, instead
1167 of using db_prepare(), so that we can treat SQL
1168 errors as non-fatal. We are executing arbitrary
1169 SQL here, some of it entered via the browser,
1170 and we don't want to kill the app when some of
1171 the SQL isn't quite right.
1172 */
1173 sqlite3_stmt * st;
1174 int rc = sqlite3_prepare(g.db, sql, -1, &st, 0);
1175 if( SQLITE_OK != rc )
1176 {
1177 @ <span style='color:red'>db_generic_query_view() SQL error:
1178 @ %h(sqlite3_errmsg(g.db))</span>
1179 return rc;
1180 }
1181 int colc = sqlite3_column_count(st);
1182 @ <table class='fossil_db_generic_query_view'><tbody>
1183 @ <tr class='header'>
1184 int i = 0;
1185 for( i = 0; i < colc; ++i ) {
1186 if( coln )
1187 {
1188 @ <th>%s(coln[i] ? coln[i] : sqlite3_column_name(st,i))</th>
1189 }
1190 else
1191 {
1192 @ <td>%s(sqlite3_column_name(st,i))</td>
1193 }
1194 }
1195 @ </tr>
1196
1197 int row = 0;
1198 char const * text = 0;
1199 while( SQLITE_ROW == sqlite3_step(st) ){
1200 @ <tr class='%s( (row++%2) ? "odd" : "even")'>
1201 for( i = 0; i < colc; ++i ) {
1202 text = (char const *) sqlite3_column_text(st,i);
1203 char * xf = 0;
1204 char const * xcf = 0;
1205 xcf = (xform && xform[i])
1206 ? (xf=(xform[i])(text))
1207 : text;
1208 @ <td>%s(xcf)</td>
1209 if( xf ) free( xf );
1210 }
1211 @ </tr>
1212 }
 
1213 @ </tbody></table>
1214 sqlite3_finalize(st);
1215 return SQLITE_OK;
1216 }
1217

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button