00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00029 #include "config.h"
00030
00031 #include <string.h>
00032
00033 #include <glib.h>
00034
00035 #include "builder.h"
00036 #include "estron.h"
00037 #include "dui-initdb.h"
00038 #include "duifield.h"
00039 #include "duifield-sql.h"
00040 #include "duifieldmap.h"
00041 #include "duifilter.h"
00042 #include "duiresolver.h"
00043 #include "duitxnquery.h"
00044 #include "perr.h"
00045
00046 typedef enum {
00047 QUERY_NONE,
00048 QUERY_SIMPLE,
00049 QUERY_TABLES,
00050 QUERY_FIELDS
00051 } MetaQueryType;
00052
00053
00054
00055 struct DuiTxnQuery_s
00056 {
00058 MetaQueryType meta_qtype;
00059
00063 gchar * tabname;
00064
00067 DuiField *table;
00068
00070 SqlBuilder *sql_builder;
00071
00073 SqlBuilderQType qtype;
00074
00075 GList *terms;
00076
00078 gchar * query_string;
00079
00081 DuiDatabase *database;
00082 DuiDBConnection *db_conn;
00083
00084
00087 DuiFieldMap *source_match;
00088
00090 DuiResolver * resolver;
00091 };
00092
00093
00094
00095 static void
00096 dui_txnquery_init (DuiTxnQuery *q)
00097 {
00098 q->meta_qtype = QUERY_NONE;
00099 q->tabname = NULL;
00100 q->table = NULL;
00101 q->sql_builder = NULL;
00102
00103 q->qtype = 0;
00104 q->terms = NULL;
00105
00106 q->query_string = NULL;
00107 q->database = NULL;
00108 q->db_conn = NULL;
00109
00110 q->source_match = NULL;
00111 q->resolver = NULL;
00112 }
00113
00114 DuiTxnQuery *
00115 dui_txnquery_new (void)
00116 {
00117 DuiTxnQuery *qry;
00118 qry = g_new0 (DuiTxnQuery, 1);
00119 dui_txnquery_init (qry);
00120 return qry;
00121 }
00122
00123 void
00124 dui_txnquery_destroy (DuiTxnQuery *q)
00125 {
00126 GList *node;
00127
00128 q->meta_qtype = QUERY_NONE;
00129
00130 if (q->tabname) g_free (q->tabname);
00131
00132
00133 q->table = NULL;
00134
00135 q->database = NULL;
00136 q->db_conn = NULL;
00137
00138
00139 for (node=q->terms; node; node=node->next)
00140 {
00141 DuiFieldMap *fm = node->data;
00142 dui_field_map_destroy (fm);
00143 }
00144 g_list_free (q->terms);
00145
00146 if (q->source_match) dui_field_map_destroy (q->source_match);
00147
00148 sql_builder_destroy(q->sql_builder);
00149 q->sql_builder = NULL;
00150 q->qtype = 0;
00151
00152 g_free (q);
00153 }
00154
00155
00156
00157 void
00158 dui_txnquery_set_database (DuiTxnQuery * q, DuiDatabase *db)
00159 {
00160 if (!q) return;
00161 q->database = db;
00162 }
00163
00164
00165
00166 void
00167 dui_txnquery_set_tablename (DuiTxnQuery *qry, const gchar * tablename)
00168 {
00169 ENTER ("(qry=%p, table=%s)", qry, tablename);
00170 if (!qry || !tablename) return;
00171
00172 if (qry->tabname) g_free (qry->tabname);
00173 qry->tabname = g_strdup (tablename);
00174
00175
00176
00177 if (QUERY_SIMPLE == qry->meta_qtype)
00178 {
00179 if (NULL == qry->sql_builder)
00180 {
00181 qry->sql_builder = sql_builder_new ();
00182 }
00183 sql_builder_table (qry->sql_builder, qry->tabname, qry->qtype);
00184 }
00185 }
00186
00187
00188
00189 void
00190 dui_txnquery_set_querytype (DuiTxnQuery *qry, const gchar * sql_querytype)
00191 {
00192 ENTER ("(qry=%p, type=%s)", qry, sql_querytype);
00193 if (!qry || !sql_querytype) return;
00194
00195 if (!strcasecmp (sql_querytype, "tables"))
00196 {
00197 qry->meta_qtype = QUERY_TABLES;
00198 qry->table = NULL;
00199 if (qry->tabname)
00200 {
00201 g_free (qry->tabname);
00202 qry->tabname = NULL;
00203 }
00204 return;
00205 }
00206
00207
00208
00209
00210
00211 qry->meta_qtype = QUERY_SIMPLE;
00212 if (!strcasecmp (sql_querytype, "select")) qry->qtype = SQL_SELECT;
00213 else if (!strcasecmp (sql_querytype, "insert")) qry->qtype = SQL_INSERT;
00214 else if (!strcasecmp (sql_querytype, "update")) qry->qtype = SQL_UPDATE;
00215 else if (!strcasecmp (sql_querytype, "delete")) qry->qtype = SQL_DELETE;
00216 else
00217 {
00218 SYNTAX ("unknown query type \'%s\'", sql_querytype);
00219 return;
00220 }
00221
00222
00223
00224 if (qry->tabname)
00225 {
00226 if (NULL == qry->sql_builder)
00227 {
00228 qry->sql_builder = sql_builder_new ();
00229 }
00230 sql_builder_table (qry->sql_builder, qry->tabname, qry->qtype);
00231 }
00232 }
00233
00234
00235
00236 void
00237 dui_txnquery_set_table (DuiTxnQuery *qry, DuiField * tabfld,
00238 const gchar * sql_querytype)
00239 {
00240 const gchar * tabname = NULL;
00241
00242 if (!strcasecmp (sql_querytype, "fields"))
00243 {
00244 qry->meta_qtype = QUERY_FIELDS;
00245 qry->table = tabfld;
00246 return;
00247 }
00248 g_return_if_fail (tabfld);
00249 if (!tabfld->get_field_value) return;
00250 tabname = tabfld->get_field_value(tabfld);
00251 if (!tabname) return;
00252
00253 dui_txnquery_set_tablename (qry, tabname);
00254 dui_txnquery_set_querytype (qry, sql_querytype);
00255 }
00256
00257
00258
00259
00260
00261
00262
00263 void
00264 dui_txnquery_add_term (DuiTxnQuery *qry, DuiFieldMap *fm)
00265 {
00266 if (!qry || !fm) return;
00267 dui_resolver_add_field (qry->resolver, &fm->source);
00268 dui_resolver_add_field (qry->resolver, &fm->target);
00269 dui_field_map_resolve (fm);
00270
00271
00272
00273
00274 if (DUI_FIELD_IS_TYPE(&fm->target,DUI_FIELD_CONST))
00275 {
00276 sql_builder_set_str (qry->sql_builder, fm->target.u.value, NULL);
00277 }
00278 else
00279 {
00280 qry->terms = g_list_append (qry->terms, fm);
00281 }
00282 }
00283
00284 void
00285 dui_txnquery_add_source_match_term (DuiTxnQuery *qry, DuiFieldMap *fm)
00286 {
00287 if (!qry || !fm) return;
00288
00289 if (qry->source_match)
00290 {
00291 PERR ("Source Row Matcher already specified!\n");
00292 }
00293 dui_resolver_add_field (qry->resolver, &fm->source);
00294 dui_resolver_add_field (qry->resolver, &fm->target);
00295 dui_field_map_resolve (fm);
00296
00297 qry->source_match = fm;
00298 }
00299
00300 DuiFieldMap *
00301 dui_txnquery_get_source_match_term (DuiTxnQuery *qry)
00302 {
00303 if (!qry) return NULL;
00304 return qry->source_match;
00305 }
00306
00307 void
00308 dui_txnquery_set_resolver (DuiTxnQuery *qry, DuiResolver *res)
00309 {
00310 GList *cnode;
00311 DuiFieldMap *fm;
00312 if (!qry) return;
00313 qry->resolver = res;
00314
00315
00316 fm = qry->source_match;
00317 if (fm)
00318 {
00319 dui_resolver_add_field (res, &fm->source);
00320 dui_resolver_add_field (res, &fm->target);
00321 dui_field_map_resolve (fm);
00322 }
00323
00324 for (cnode=qry->terms; cnode; cnode=cnode->next)
00325 {
00326 fm = cnode->data;
00327 dui_resolver_add_field (res, &fm->source);
00328 dui_resolver_add_field (res, &fm->target);
00329 dui_field_map_resolve (fm);
00330 }
00331 }
00332
00333
00334
00335 void
00336 dui_txnquery_do_realize (DuiTxnQuery *qry)
00337 {
00338
00339
00340
00341
00342 }
00343
00344
00345
00346 void
00347 dui_txnquery_connect (DuiTxnQuery *qry)
00348 {
00349 if (!qry) return;
00350 qry->db_conn = dui_database_do_realize (qry->database);
00351 }
00352
00353
00354
00355 static DuiDBRecordSet *
00356 dui_txnquery_run_one_query (DuiTxnQuery *qry)
00357 {
00358 DuiDBRecordSet *recs = NULL;
00359 if (!qry) return NULL;
00360
00361 ENTER ("(qry=%p)", qry);
00362 switch (qry->meta_qtype)
00363 {
00364 case QUERY_NONE: break;
00365 case QUERY_SIMPLE: break;
00366 case QUERY_TABLES:
00367 if (qry->db_conn)
00368 {
00369 recs = dui_connection_tables(qry->db_conn);
00370 return recs;
00371 }
00372 break;
00373 case QUERY_FIELDS:
00374 if ((qry->db_conn) && (qry->table->get_field_value))
00375 {
00376 const char * table;
00377 table = qry->table->get_field_value(qry->table);
00378 PINFO ("perform fields query with table=\'%s\'", table);
00379 recs = dui_connection_table_columns(qry->db_conn, table);
00380 return recs;
00381 }
00382 break;
00383 }
00384
00385
00386 if (qry->sql_builder)
00387 {
00388 GList *node;
00389 SqlBuilder *dupe;
00390 short broken_select = 0;
00391 short wild_select = 1;
00392
00393 g_free (qry->query_string);
00394 qry->query_string = NULL;
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 dupe = sql_builder_copy (qry->sql_builder);
00408
00409
00410 for (node = qry->terms; node; node=node->next)
00411 {
00412 DuiFieldMap *fm = node->data;
00413 const char * fieldval;
00414 if ((!DUI_FIELD_IS_TYPE(&fm->target,DUI_FIELD_SQL)) &&
00415 (!DUI_FIELD_IS_TYPE(&fm->target,DUI_FIELD_WHERE))) continue;
00416
00417 fieldval = dui_field_map_get_value (fm);
00418 if ((NULL == fieldval) && ((SQL_INSERT == qry->qtype) ||
00419 (SQL_UPDATE == qry->qtype)))
00420 {
00421 PERR ("Null field value for insert/update not allowed, field=%s\n",
00422 fm->target.fieldname);
00423 sql_builder_destroy (dupe);
00424 return NULL;
00425 }
00426 sql_builder_set_str (dupe, fm->target.fieldname, fieldval);
00427 PINFO ("insert/update %s=%s", fm->target.fieldname, fieldval);
00428 }
00429
00430
00431 for (node = qry->terms; node; node=node->next)
00432 {
00433 DuiFieldMap *fm = node->data;
00434 const char * fieldval;
00435
00436 if (!DUI_FIELD_IS_TYPE(&fm->target,DUI_FIELD_WHERE)) continue;
00437 wild_select = 0;
00438
00439 fieldval = dui_field_map_get_value (fm);
00440 PINFO ("where (%s %s %s)", fm->target.fieldname,
00441 dui_field_where_get_op(&fm->target), fieldval);
00442
00443 fieldval = whitespace_filter (fieldval);
00444 if (fieldval)
00445 {
00446
00447
00448 if (SQL_INSERT != qry->qtype)
00449 {
00450 sql_builder_where_str (dupe,
00451 fm->target.fieldname,
00452 fieldval, dui_field_where_get_op(&fm->target));
00453 }
00454 }
00455 else
00456 {
00457 broken_select = 1;
00458 }
00459 }
00460
00461 if (NULL == qry->db_conn)
00462 {
00463
00464 if (NULL == qry->database)
00465 {
00466 PERR ("Can't perform query, no database specified!\n");
00467 sql_builder_destroy (dupe);
00468 return NULL;
00469 }
00470 qry->db_conn = dui_database_do_realize (qry->database);
00471 }
00472
00473
00474
00475
00476
00477
00478
00479 if (wild_select || !broken_select || (SQL_SELECT == qry->qtype))
00480 {
00481 const gchar * stmt;
00482
00483
00484 stmt = sql_builder_query (dupe);
00485 qry->query_string = g_strdup (stmt);
00486
00487
00488 if (qry->db_conn)
00489 {
00490 recs = dui_connection_exec(qry->db_conn, stmt);
00491 }
00492 }
00493 else
00494 {
00495 PERR ("Can't perform query, missing WHERE term (%d %d)",
00496 wild_select, broken_select);
00497 sql_builder_destroy (dupe);
00498 return NULL;
00499 }
00500 sql_builder_destroy (dupe);
00501 }
00502 else
00503 {
00504 PERR ("Failed to specify table for query");
00505 }
00506
00507 LEAVE(" got recs=%p for query=\"%s\"\n", recs, qry->query_string);
00508
00509 return recs;
00510 }
00511
00512 DuiDBRecordSet *
00513 dui_txnquery_run (DuiTxnQuery *qry)
00514 {
00515 DuiDBRecordSet *rec_return = NULL;
00516
00517 int more_rows = 1;
00518 DuiField *iterator = NULL;
00519 if (!qry) return NULL;
00520
00521 ENTER ("(qry=%p)", qry);
00522
00523 if (qry->source_match)
00524 {
00525 iterator = &qry->source_match->target;
00526 }
00527
00528 dui_field_iter_pre (iterator, TRUE);
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 more_rows = 1;
00543 while (more_rows)
00544 {
00545 gboolean do_transfer;
00546 if (qry->source_match)
00547 {
00548 dui_field_map_transfer_data (qry->source_match);
00549 }
00550
00551 do_transfer = dui_field_iter_next (iterator);
00552
00553 if (do_transfer)
00554 {
00555 GList *node;
00556 for (node=qry->terms; node; node=node->next)
00557 {
00558 DuiFieldMap *fm = node->data;
00559 dui_field_iter_column (&fm->source, iterator);
00560 }
00561
00562 rec_return = dui_txnquery_run_one_query (qry);
00563 }
00564
00565 more_rows = 0;
00566 }
00567
00568 dui_field_iter_post (iterator);
00569 LEAVE ("(qry=%p)", qry);
00570 return rec_return;
00571 }
00572
00573
00574
00575 DuiDBRecordSet *
00576 dui_txnquery_rerun_last_query (DuiTxnQuery *qry)
00577 {
00578 DuiDBRecordSet *recs = NULL;
00579
00580 if (!qry) return NULL;
00581 if (!qry->db_conn || !qry->query_string) return NULL;
00582
00583 recs = dui_connection_exec (qry->db_conn, qry->query_string);
00584 return recs;
00585 }
00586
00587