00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00039 #define _GNU_SOURCE
00040 #include <glib.h>
00041 #include <string.h>
00042
00043 #include "util.h"
00044 #include "perr.h"
00045 #include "escape.h"
00046 #include "builder.h"
00047
00048
00049
00050 struct SqlBuilder_s
00051 {
00052 SqlBuilderQType qtype;
00053
00054
00055 gchar * ptag;
00056 gchar * pval;
00057
00058
00059 gshort tag_need_comma;
00060 gshort val_need_comma;
00061 gshort where_need_and;
00062 gshort got_where_term;
00063
00064
00065 gchar * tag_base;
00066 gchar * tbl_base;
00067 gchar * val_base;
00068 size_t buflen;
00069
00070
00071 sqlEscape *escape;
00072 };
00073
00074
00075
00076 #define INITIAL_BUFSZ 16300
00077
00078 SqlBuilder *
00079 sql_builder_new (void)
00080 {
00081 SqlBuilder *b = g_new (SqlBuilder, 1);
00082
00083 b->qtype = 0;
00084
00085 b->tag_base = g_malloc (INITIAL_BUFSZ);
00086 b->tbl_base = g_malloc (1000);
00087 b->val_base = g_malloc (INITIAL_BUFSZ);
00088 b->buflen = INITIAL_BUFSZ;
00089
00090 b->ptag = b->tag_base;
00091 b->pval = b->val_base;
00092
00093
00094 *(b->ptag) = 0x0;
00095 *(b->pval) = 0x0;
00096
00097 b->tag_need_comma = 0;
00098 b->val_need_comma = 0;
00099 b->where_need_and = 0;
00100 b->got_where_term = 0;
00101
00102
00103 b->escape = sqlEscape_new ();
00104 return (b);
00105 }
00106
00107
00108
00109 void
00110 sql_builder_destroy (SqlBuilder *b)
00111 {
00112 if (!b) return;
00113 g_free (b->tag_base); b->tag_base = NULL;
00114 g_free (b->tbl_base); b->tbl_base = NULL;
00115 g_free (b->val_base); b->val_base = NULL;
00116 sqlEscape_destroy (b->escape); b->escape = NULL;
00117 g_free (b);
00118 }
00119
00120
00121
00122 SqlBuilder *
00123 sql_builder_copy (SqlBuilder *orig)
00124 {
00125 SqlBuilder *b;
00126
00127 if (!orig) return sql_builder_new();
00128
00129 b = g_new (SqlBuilder, 1);
00130
00131 b->qtype = orig->qtype;
00132
00133 b->buflen = orig->buflen;
00134 b->tag_base = g_malloc (orig->buflen);
00135 b->tbl_base = g_malloc (1000);
00136 b->val_base = g_malloc (orig->buflen);
00137
00138 *(orig->ptag) = 0x0;
00139 *(orig->pval) = 0x0;
00140
00141 strcpy (b->tag_base, orig->tag_base);
00142 strcpy (b->tbl_base, orig->tbl_base);
00143 strcpy (b->val_base, orig->val_base);
00144
00145 b->ptag = b->tag_base + (orig->ptag - orig->tag_base);
00146 b->pval = b->val_base + (orig->pval - orig->val_base);
00147
00148
00149 *(b->ptag) = 0x0;
00150 *(b->pval) = 0x0;
00151
00152 b->tag_need_comma = orig->tag_need_comma;
00153 b->val_need_comma = orig->val_need_comma;
00154 b->where_need_and = orig->where_need_and;
00155 b->got_where_term = orig->got_where_term;
00156
00157
00158 b->escape = sqlEscape_new ();
00159 return (b);
00160 }
00161
00162
00163
00164 void
00165 sql_builder_table (SqlBuilder *b, const gchar *tablename, SqlBuilderQType qt)
00166 {
00167 gchar * ptbl;
00168
00169 if (!b || !tablename) return;
00170 b->qtype = qt;
00171
00172 b->ptag = b->tag_base;
00173 b->pval = b->val_base;
00174 ptbl = b->tbl_base;
00175
00176
00177 *(b->ptag) = 0x0;
00178 *(b->pval) = 0x0;
00179 *ptbl = 0x0;
00180
00181 b->tag_need_comma = 0;
00182 b->val_need_comma = 0;
00183 b->where_need_and = 0;
00184 b->got_where_term = 0;
00185
00186 switch (qt)
00187 {
00188 case SQL_INSERT:
00189 b->ptag = stpcpy(b->ptag, "INSERT INTO ");
00190 b->ptag = stpcpy(b->ptag, tablename);
00191 b->ptag = stpcpy(b->ptag, " (");
00192
00193 b->pval = stpcpy(b->pval, ") VALUES (");
00194 break;
00195
00196 case SQL_UPDATE:
00197 b->ptag = stpcpy(b->ptag, "UPDATE ");
00198 b->ptag = stpcpy(b->ptag, tablename);
00199 b->ptag = stpcpy(b->ptag, " SET ");
00200
00201 b->pval = stpcpy(b->pval, " WHERE ");
00202 break;
00203
00204 case SQL_SELECT:
00205 b->ptag = stpcpy(b->ptag, "SELECT ");
00206
00207 ptbl = stpcpy(ptbl, " FROM ");
00208 ptbl = stpcpy(ptbl, tablename);
00209
00210 b->pval = stpcpy(b->pval, " WHERE ");
00211 break;
00212
00213 case SQL_DELETE:
00214 b->ptag = stpcpy(b->ptag, "DELETE ");
00215 ptbl = stpcpy(ptbl, " FROM ");
00216 ptbl = stpcpy(ptbl, tablename);
00217
00218 b->pval = stpcpy(b->pval, " WHERE ");
00219 break;
00220
00221 };
00222
00223 }
00224
00225
00226
00227
00228 void
00229 sql_builder_set_str (SqlBuilder *b, const gchar *tag, const gchar *val)
00230 {
00231 if (!b || !tag) return;
00232 if (!val) val= "";
00233
00234 val = sqlEscapeString (b->escape, val);
00235
00236 if (b->tag_need_comma) b->ptag = stpcpy(b->ptag, ", ");
00237 b->tag_need_comma = 1;
00238
00239 switch (b->qtype)
00240 {
00241 case SQL_INSERT:
00242 b->ptag = stpcpy(b->ptag, tag);
00243
00244 if (b->val_need_comma) b->pval = stpcpy(b->pval, ", ");
00245 b->val_need_comma = 1;
00246 b->pval = stpcpy(b->pval, "'");
00247 b->pval = stpcpy(b->pval, val);
00248 b->pval = stpcpy(b->pval, "'");
00249 break;
00250
00251 case SQL_UPDATE:
00252 b->ptag = stpcpy(b->ptag, tag);
00253 b->ptag = stpcpy(b->ptag, "='");
00254 b->ptag = stpcpy(b->ptag, val);
00255 b->ptag = stpcpy(b->ptag, "' ");
00256 break;
00257
00258 case SQL_SELECT:
00259 b->ptag = stpcpy(b->ptag, tag);
00260 break;
00261
00262 case SQL_DELETE:
00263 break;
00264
00265 case 0:
00266 PERR ("must specify a table and a query type first!");
00267 break;
00268
00269 default:
00270 PERR ("mustn't happen");
00271 };
00272
00273 }
00274
00275
00276
00277 void
00278 sql_builder_set_char (SqlBuilder *b, const gchar *tag, gchar val)
00279 {
00280 gchar buf[2];
00281 buf[0] = val;
00282 buf[1] = 0x0;
00283 sql_builder_set_str (b, tag, buf);
00284 }
00285
00286
00287
00288 void
00289 sql_builder_set_date (SqlBuilder *b, const gchar *tag, time_t ts)
00290 {
00292 gchar buf[120];
00293 xxxgnc_secs_to_iso8601_buff (ts, buf);
00294 sql_builder_set_str (b, tag, buf);
00295 }
00296
00297
00298
00299 void
00300 sql_builder_set_double (SqlBuilder *b, const gchar *tag, double flt)
00301 {
00302 gchar buf[120];
00303 snprintf (buf, 120, SQL_DBL_FMT, flt);
00304 sql_builder_set_str (b, tag, buf);
00305 }
00306
00307
00308
00309 void
00310 sql_builder_set_int64 (SqlBuilder *b, const gchar *tag, gint64 nval)
00311 {
00312 gchar val[100];
00313 if (!b || !tag) return;
00314
00315 snprintf (val, 100, "%"G_GINT64_FORMAT"", nval);
00316 if (b->tag_need_comma) b->ptag = stpcpy(b->ptag, ", ");
00317 b->tag_need_comma = 1;
00318
00319 switch (b->qtype)
00320 {
00321 case SQL_INSERT:
00322 b->ptag = stpcpy(b->ptag, tag);
00323
00324 if (b->val_need_comma) b->pval = stpcpy(b->pval, ", ");
00325 b->val_need_comma = 1;
00326 b->pval = stpcpy(b->pval, val);
00327 break;
00328
00329 case SQL_UPDATE:
00330 b->ptag = stpcpy(b->ptag, tag);
00331 b->ptag = stpcpy(b->ptag, "=");
00332 b->ptag = stpcpy(b->ptag, val);
00333 break;
00334
00335 case SQL_SELECT:
00336 b->ptag = stpcpy(b->ptag, tag);
00337 break;
00338
00339 case SQL_DELETE:
00340 break;
00341
00342 case 0:
00343 PERR ("must specify a table and a query type first!");
00344 break;
00345
00346 default:
00347 PERR ("mustn't happen");
00348 };
00349 }
00350
00351
00352
00353 void
00354 sql_builder_set_int32 (SqlBuilder *b, const gchar *tag, gint32 nval)
00355 {
00356 sql_builder_set_int64 (b, tag, (gint64) nval);
00357 }
00358
00359
00360
00361 void
00362 sql_builder_where_str (SqlBuilder *b, const gchar *tag,
00363 const gchar *val, const gchar * op)
00364 {
00365 if (!b || !tag || !val) return;
00366 b->got_where_term = 1;
00367
00368 switch (b->qtype)
00369 {
00370 case SQL_INSERT:
00371
00372 sql_builder_set_str (b, tag, val);
00373 break;
00374
00375 case SQL_UPDATE:
00376 case SQL_SELECT:
00377 case SQL_DELETE:
00378 val = sqlEscapeString (b->escape, val);
00379
00380 if (b->where_need_and) b->pval = stpcpy(b->pval, " AND ");
00381 b->where_need_and = 1;
00382
00383 b->pval = stpcpy(b->pval, tag);
00384 if (op)
00385 {
00386 b->pval = stpcpy(b->pval, " ");
00387 b->pval = stpcpy(b->pval, op);
00388 b->pval = stpcpy(b->pval, " '");
00389 }
00390 else
00391 {
00392 b->pval = stpcpy(b->pval, "='");
00393 }
00394 b->pval = stpcpy(b->pval, val);
00395 b->pval = stpcpy(b->pval, "'");
00396
00397 break;
00398
00399 case 0:
00400 PERR ("must specify a table and a query type first!");
00401 break;
00402
00403
00404 default:
00405 PERR ("mustn't happen");
00406 };
00407 }
00408
00409
00410
00411 void
00412 sql_builder_where_int32 (SqlBuilder *b, const gchar *tag,
00413 gint32 val, const gchar *op)
00414 {
00415 gchar str[40];
00416 snprintf (str, 40, "%d", val);
00417 sql_builder_where_str (b, tag, str, op);
00418 }
00419
00420
00421
00422 const gchar *
00423 sql_builder_query (SqlBuilder *b)
00424 {
00425 if (!b) return NULL;
00426
00427 switch (b->qtype)
00428 {
00429 case SQL_INSERT:
00430 b->ptag = stpcpy(b->ptag, b->val_base);
00431 b->ptag = stpcpy(b->ptag, ");");
00432 break;
00433
00434 case SQL_UPDATE:
00435 case SQL_SELECT:
00436 case SQL_DELETE:
00437 b->ptag = stpcpy(b->ptag, b->tbl_base);
00438 if (b->got_where_term) b->ptag = stpcpy(b->ptag, b->val_base);
00439 b->ptag = stpcpy(b->ptag, ";");
00440 break;
00441
00442 case 0:
00443 break;
00444
00445 default:
00446 PERR ("mustn't happen");
00447 };
00448
00449 PINFO ("%s\n", b->tag_base);
00450 return b->tag_base;
00451 }
00452
00455