dbase.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. /*
  2. * $Id$
  3. *
  4. * POSTGRES module, portions of this code were templated using
  5. * the mysql module, thus it's similarity.
  6. *
  7. *
  8. * Copyright (C) 2003 August.Net Services, LLC
  9. *
  10. * This file is part of ser, a free SIP server.
  11. *
  12. * ser is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version
  16. *
  17. * For a license to use the ser software under conditions
  18. * other than those described here, or to purchase support for this
  19. * software, please contact iptel.org by e-mail at the following addresses:
  20. * [email protected]
  21. *
  22. * ser is distributed in the hope that it will be useful,
  23. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. * GNU General Public License for more details.
  26. *
  27. * You should have received a copy of the GNU General Public License
  28. * along with this program; if not, write to the Free Software
  29. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  30. *
  31. * ---
  32. *
  33. * History
  34. * -------
  35. * 2003-04-06 initial code written (Greg Fausak/Andy Fullford)
  36. *
  37. */
  38. #define MAXCOLUMNS 512
  39. #include <string.h>
  40. #include <stdlib.h>
  41. #include <stdio.h>
  42. #include "../../dprint.h"
  43. #include "../../mem/mem.h"
  44. #include "db_utils.h"
  45. #include "defs.h"
  46. #include "dbase.h"
  47. #include "con_postgres.h"
  48. #include "aug_std.h"
  49. long getpid();
  50. static char sql_buf[SQL_BUF_LEN];
  51. static int submit_query(db_con_t* _h, const char* _s);
  52. static int connect_db(db_con_t* _h, const char* _db_url);
  53. static int disconnect_db(db_con_t* _h);
  54. static int free_query(db_con_t* _h);
  55. /*
  56. ** connect_db Connect to a database
  57. **
  58. ** Arguments :
  59. ** db_con_t * as previously supplied by db_init()
  60. ** char *_db_url the database to connect to
  61. **
  62. ** Returns :
  63. ** 0 upon success
  64. ** negative number upon failure
  65. **
  66. ** Notes :
  67. ** If currently connected, a disconnect is done first
  68. ** if this process did the connection, otherwise the
  69. ** disconnect is not done before the new connect.
  70. ** This is important, as the process that owns the connection
  71. ** should clean up after itself.
  72. */
  73. static int connect_db(db_con_t* _h, const char* _db_url)
  74. {
  75. char* user, *password, *host, *port, *database;
  76. if(! _h)
  77. {
  78. PLOG("connect_db", "must pass db_con_t!");
  79. return(-1);
  80. }
  81. if(CON_CONNECTED(_h))
  82. {
  83. DLOG("connect_db", "disconnect first!");
  84. disconnect_db(_h);
  85. }
  86. /*
  87. ** CON_CONNECTED(_h) is now 0, set by disconnect_db()
  88. */
  89. /*
  90. ** Note :
  91. ** Make a scratch pad copy of given SQL URL.
  92. ** all memory allocated to this connection is rooted
  93. ** from this.
  94. ** This is an important concept.
  95. ** as long as you always allocate memory using the function:
  96. ** mem = aug_alloc(size, CON_SQLURL(_h)) or
  97. ** str = aug_strdup(string, CON_SQLURL(_h))
  98. ** where size is the amount of memory, then in the future
  99. ** when CON_SQLURL(_h) is freed (in the function disconnect_db())
  100. ** all other memory allocated in this manner is freed.
  101. ** this will keep memory leaks from happening.
  102. */
  103. CON_SQLURL(_h) = aug_strdup((char *) _db_url, (char *) _h);
  104. /*
  105. ** get the connection parameters parsed from the db_url string
  106. ** it looks like: postgres://username:userpass@dbhost:dbport/dbname
  107. ** username/userpass : name and password for the database
  108. ** dbhost : the host name or ip address hosting the database
  109. ** dbport : the port to connect to database on
  110. ** dbname : the name of the database
  111. */
  112. if(parse_sql_url(CON_SQLURL(_h),
  113. &user,&password,&host,&port,&database) < 0)
  114. {
  115. char buf[256];
  116. sprintf(buf, "Error while parsing %s", _db_url);
  117. PLOG("connect_db", buf);
  118. aug_free(CON_SQLURL(_h));
  119. return -3;
  120. }
  121. /*
  122. ** finally, actually connect to the database
  123. */
  124. CON_CONNECTION(_h) =
  125. PQsetdbLogin(host,port,NULL,NULL,database,user, password);
  126. if(CON_CONNECTION(_h) == 0
  127. || PQstatus(CON_CONNECTION(_h)) != CONNECTION_OK)
  128. {
  129. PLOG("connect_db", PQerrorMessage(CON_CONNECTION(_h)));
  130. PQfinish(CON_CONNECTION(_h));
  131. aug_free(CON_SQLURL(_h));
  132. return -4;
  133. }
  134. CON_PID(_h) = getpid();
  135. /*
  136. ** all is well, database was connected, we can now submit_query's
  137. */
  138. CON_CONNECTED(_h) = 1;
  139. return 0;
  140. }
  141. /*
  142. ** disconnect_db Disconnect a database
  143. **
  144. ** Arguments :
  145. ** db_con_t * as previously supplied by db_init()
  146. **
  147. ** Returns :
  148. ** 0 upon success
  149. ** negative number upon failure
  150. **
  151. ** Notes :
  152. ** All memory associated with CON_SQLURL is freed.
  153. **
  154. */
  155. static int disconnect_db(db_con_t* _h)
  156. {
  157. if(! _h)
  158. {
  159. DLOG("disconnect_db", "null db_con_t, ignored!\n");
  160. return(0);
  161. }
  162. /*
  163. ** free lingering memory tree if it exists
  164. */
  165. if(CON_SQLURL(_h))
  166. {
  167. aug_free(CON_SQLURL(_h));
  168. CON_SQLURL(_h) = (char *) 0;
  169. }
  170. /*
  171. ** ignore if there is no current connection
  172. */
  173. if(CON_CONNECTED(_h) != 1)
  174. {
  175. DLOG("disconnect_db", "not connected, ignored!\n");
  176. return 0;
  177. }
  178. /*
  179. ** make sure we are trying to close a connection that was opened
  180. ** by our process ID
  181. */
  182. if(CON_PID(_h) == getpid())
  183. {
  184. PQfinish(CON_CONNECTION(_h));
  185. CON_CONNECTED(_h) = 0;
  186. }
  187. else
  188. {
  189. DLOG("disconnect_db",
  190. "attempt to release connection not owned, ignored!\n");
  191. }
  192. return 0;
  193. }
  194. /*
  195. ** db_init initialize database for future queries
  196. **
  197. ** Arguments :
  198. ** char *_sqlurl; sql database to open
  199. **
  200. ** Returns :
  201. ** db_con_t * NULL upon error
  202. ** db_con_t * if successful
  203. **
  204. ** Notes :
  205. ** db_init must be called prior to any database
  206. ** functions.
  207. */
  208. db_con_t *db_init(const char* _sqlurl)
  209. {
  210. db_con_t* res;
  211. DLOG("db_init", "entry");
  212. /*
  213. ** this is the root memory for this database connection.
  214. */
  215. res = aug_alloc(sizeof(db_con_t), 0);
  216. memset(res, 0, sizeof(db_con_t));
  217. (struct con_postgres*)res->tail = aug_alloc(sizeof(struct con_postgres), (char*)res);
  218. memset((struct con_postgres*)res->tail, 0, sizeof(struct con_postgres));
  219. if (connect_db(res, _sqlurl) < 0)
  220. {
  221. PLOG("db_init", "Error while trying to open database, FATAL\n");
  222. aug_free(res);
  223. return((db_con_t *) 0);
  224. }
  225. return res;
  226. }
  227. /*
  228. ** db_close last function to call when db is no longer needed
  229. **
  230. ** Arguments :
  231. ** db_con_t * the connection to shut down, as supplied by db_init()
  232. **
  233. ** Returns :
  234. ** (void)
  235. **
  236. ** Notes :
  237. ** All memory and resources are freed.
  238. */
  239. void db_close(db_con_t* _h)
  240. {
  241. DLOG("db_close", "entry");
  242. if(! _h)
  243. {
  244. PLOG("db_close", "no handle passed, ignored");
  245. return;
  246. }
  247. disconnect_db(_h);
  248. aug_free(_h);
  249. }
  250. /*
  251. ** submit_query run a query
  252. **
  253. ** Arguments :
  254. ** db_con_t * as previously supplied by db_init()
  255. ** char *_s the text query to run
  256. **
  257. ** Returns :
  258. ** 0 upon success
  259. ** negative number upon failure
  260. */
  261. static int submit_query(db_con_t* _h, const char* _s)
  262. {
  263. int rv;
  264. /*
  265. ** this bit of nonsense in case our connection get screwed up
  266. */
  267. switch(rv = PQstatus(CON_CONNECTION(_h)))
  268. {
  269. case CONNECTION_OK: break;
  270. case CONNECTION_BAD:
  271. PLOG("submit_query", "connection reset");
  272. PQreset(CON_CONNECTION(_h));
  273. break;
  274. }
  275. /*
  276. ** free any previous query that is laying about
  277. */
  278. if(CON_RESULT(_h))
  279. {
  280. free_query(_h);
  281. }
  282. /*
  283. ** exec the query
  284. */
  285. CON_RESULT(_h) = PQexec(CON_CONNECTION(_h), _s);
  286. rv = 0;
  287. if(PQresultStatus(CON_RESULT(_h)) == 0)
  288. {
  289. PLOG("submit_query", "initial failure, FATAL");
  290. /*
  291. ** terrible error??
  292. */
  293. rv = -3;
  294. }
  295. else
  296. {
  297. /*
  298. ** the query ran, get the status
  299. */
  300. switch(PQresultStatus(CON_RESULT(_h)))
  301. {
  302. case PGRES_EMPTY_QUERY: rv = -9; break;
  303. case PGRES_COMMAND_OK: rv = 0; break;
  304. case PGRES_TUPLES_OK: rv = 0; break;
  305. case PGRES_COPY_OUT: rv = -4; break;
  306. case PGRES_COPY_IN: rv = -5; break;
  307. case PGRES_BAD_RESPONSE: rv = -6; break;
  308. case PGRES_NONFATAL_ERROR: rv = -7; break;
  309. case PGRES_FATAL_ERROR: rv = -8; break;
  310. default: rv = -2; break;
  311. }
  312. }
  313. if(rv < 0)
  314. {
  315. /*
  316. ** log the error
  317. */
  318. char buf[256];
  319. sprintf(buf, "query '%s', result '%s'\n",
  320. _s, PQerrorMessage(CON_CONNECTION(_h)));
  321. PLOG("submit_query", buf);
  322. }
  323. return(rv);
  324. }
  325. /*
  326. ** free_query clear the db channel and clear any old query result status
  327. **
  328. ** Arguments :
  329. ** db_con_t * as previously supplied by db_init()
  330. **
  331. ** Returns :
  332. ** 0 upon success
  333. ** negative number upon failure
  334. */
  335. static int free_query(db_con_t* _h)
  336. {
  337. if(CON_RESULT(_h))
  338. {
  339. PQclear(CON_RESULT(_h));
  340. CON_RESULT(_h) = 0;
  341. }
  342. return 0;
  343. }
  344. /*
  345. ** db_free_query free the query and free the result memory
  346. **
  347. ** Arguments :
  348. ** db_con_t * as previously supplied by db_init()
  349. ** db_res_t * the result of a query
  350. **
  351. ** Returns :
  352. ** 0 upon success
  353. ** negative number upon failure
  354. */
  355. int db_free_query(db_con_t* _h, db_res_t* _r)
  356. {
  357. free_query(_h);
  358. free_result(_r);
  359. return 0;
  360. }
  361. /*
  362. ** begin_transaction begin transaction
  363. **
  364. ** Arguments :
  365. ** db_con_t * as previously supplied by db_init()
  366. ** char * this is just in case an error message
  367. ** is printed, we will know which query
  368. ** was going to be run, giving us a code debug hint
  369. **
  370. ** Returns :
  371. ** 0 upon success
  372. ** negative number upon failure
  373. **
  374. ** Notes :
  375. ** This function may be called with a messed up communication
  376. ** channel. Therefore, alot of this function is dealing with
  377. ** that. Wen the layering gets corrected later this stuff
  378. ** should continue to work correctly, it will just be
  379. ** way to defensive.
  380. */
  381. static int begin_transaction(db_con_t * _h, char *_s)
  382. {
  383. PGresult *mr;
  384. int rv;
  385. /*
  386. ** Note:
  387. ** The upper layers of code may attempt a transaction
  388. ** before opening or having a valid connection to the
  389. ** database. We try to sense this, and open the database
  390. ** if we have the sqlurl in the _h structure. Otherwise,
  391. ** all we can do is return an error.
  392. */
  393. if(_h)
  394. {
  395. if(CON_CONNECTED(_h))
  396. {
  397. mr = PQexec(CON_CONNECTION(_h), "BEGIN");
  398. if(!mr || PQresultStatus(mr) != PGRES_COMMAND_OK)
  399. {
  400. /*
  401. ** We get here if the connection to the
  402. ** db is corrupt, which can happen a few
  403. ** different ways, but all of them are
  404. ** related to the parent process forking,
  405. ** or being forked.
  406. */
  407. PLOG("begin_transaction","corrupt connection");
  408. CON_CONNECTED(_h) = 0;
  409. }
  410. else
  411. {
  412. /*
  413. ** this is the normal way out.
  414. ** the transaction ran fine.
  415. */
  416. PQclear(mr);
  417. return(0);
  418. }
  419. }
  420. else
  421. {
  422. DLOG("begin_transaction", "called before db_init");
  423. }
  424. /*
  425. ** if we get here we have a corrupt db connection,
  426. ** but we probably have a valid db_con_t structure.
  427. ** attempt to open the db.
  428. */
  429. if((rv = connect_db(_h, CON_SQLURL(_h))) != 0)
  430. {
  431. /*
  432. ** our attempt to fix the connection failed
  433. */
  434. char buf[256];
  435. sprintf(buf, "no connection, FATAL %d!", rv);
  436. PLOG("begin_transaction",buf);
  437. return(rv);
  438. }
  439. }
  440. else
  441. {
  442. PLOG("begin_transaction","must call db_init first!");
  443. return(-1);
  444. }
  445. /*
  446. ** we get here if the database connection was corrupt,
  447. ** i didn't want to use recursion ...
  448. */
  449. mr = PQexec(CON_CONNECTION(_h), "BEGIN");
  450. if(!mr || PQresultStatus(mr) != PGRES_COMMAND_OK)
  451. {
  452. char buf[256];
  453. sprintf("FATAL %s, '%s'!\n",
  454. PQerrorMessage(CON_CONNECTION(_h)), _s);
  455. PLOG("begin_transaction", buf);
  456. return(-1);
  457. }
  458. DLOG("begin_transaction", "db channel reset successful");
  459. PQclear(mr);
  460. return(0);
  461. }
  462. /*
  463. ** commit_transaction any begin_transaction must be terminated with this
  464. **
  465. ** Arguments :
  466. ** db_con_t * as previously supplied by db_init()
  467. **
  468. ** Returns :
  469. ** 0 upon success
  470. ** negative number upon failure
  471. */
  472. static int commit_transaction(db_con_t * _h)
  473. {
  474. PGresult *mr;
  475. mr = PQexec(CON_CONNECTION(_h), "COMMIT");
  476. if(!mr || PQresultStatus(mr) != PGRES_COMMAND_OK)
  477. {
  478. PLOG("commit_transaction", "error");
  479. return -1;
  480. }
  481. PQclear(mr);
  482. return(0);
  483. }
  484. /*
  485. * Print list of columns separated by comma
  486. */
  487. static int print_columns(char* _b, int _l, db_key_t* _c, int _n)
  488. {
  489. int i;
  490. int res = 0;
  491. for(i = 0; i < _n; i++) {
  492. if (i == (_n - 1)) {
  493. res += snprintf(_b + res, _l - res, "%s ", _c[i]);
  494. } else {
  495. res += snprintf(_b + res, _l - res, "%s,", _c[i]);
  496. }
  497. }
  498. return res;
  499. }
  500. /*
  501. * Print list of values separated by comma
  502. */
  503. static int print_values(char* _b, int _l, db_val_t* _v, int _n)
  504. {
  505. int i, res = 0, l;
  506. for(i = 0; i < _n; i++) {
  507. l = _l - res;
  508. /* LOG(L_ERR, "%d sizes l = _l - res %d = %d - %d\n", i, l,_l,res);
  509. */
  510. if (val2str(_v + i, _b + res, &l) < 0) {
  511. LOG(L_ERR,
  512. "print_values(): Error converting value to string\n");
  513. return 0;
  514. }
  515. res += l;
  516. if (i != (_n - 1)) {
  517. *(_b + res) = ',';
  518. res++;
  519. }
  520. }
  521. return res;
  522. }
  523. /*
  524. * Print where clause of SQL statement
  525. */
  526. static int print_where(char* _b, int _l, db_key_t* _k,
  527. db_op_t* _o, db_val_t* _v, int _n)
  528. {
  529. int i;
  530. int res = 0;
  531. int l;
  532. for(i = 0; i < _n; i++) {
  533. if (_o) {
  534. res += snprintf(_b + res, _l - res, "%s%s",
  535. _k[i], _o[i]);
  536. } else {
  537. res += snprintf(_b + res, _l - res, "%s=", _k[i]);
  538. }
  539. l = _l - res;
  540. val2str(&(_v[i]), _b + res, &l);
  541. res += l;
  542. if (i != (_n - 1)) {
  543. res += snprintf(_b + res, _l - res, " AND ");
  544. }
  545. }
  546. return res;
  547. }
  548. /*
  549. * Print set clause of update SQL statement
  550. */
  551. static int print_set(char* _b, int _l, db_key_t* _k,
  552. db_val_t* _v, int _n)
  553. {
  554. int i;
  555. int res = 0;
  556. int l;
  557. for(i = 0; i < _n; i++) {
  558. res += snprintf(_b + res, _l - res, "%s=", _k[i]);
  559. l = _l - res;
  560. val2str(&(_v[i]), _b + res, &l);
  561. res += l;
  562. if (i != (_n - 1)) {
  563. if ((_l - res) >= 1) {
  564. *(_b + res++) = ',';
  565. }
  566. }
  567. }
  568. return res;
  569. }
  570. /*
  571. * Query table for specified rows
  572. * _h: structure representing database connection
  573. * _k: key names
  574. * _op: operators
  575. * _v: values of the keys that must match
  576. * _c: column names to return
  577. * _n: nmber of key=values pairs to compare
  578. * _nc: number of columns to return
  579. * _o: order by the specified column
  580. */
  581. int db_query(db_con_t* _h, db_key_t* _k, db_op_t* _op,
  582. db_val_t* _v, db_key_t* _c, int _n, int _nc,
  583. db_key_t _o, db_res_t** _r)
  584. {
  585. int off, rv;
  586. if (!_c) {
  587. off = snprintf(sql_buf, SQL_BUF_LEN,
  588. "select * from %s ", CON_TABLE(_h));
  589. } else {
  590. off = snprintf(sql_buf, SQL_BUF_LEN, "select ");
  591. off += print_columns(sql_buf + off, SQL_BUF_LEN - off, _c, _nc);
  592. off += snprintf(sql_buf + off, SQL_BUF_LEN - off,
  593. "from %s ", CON_TABLE(_h));
  594. }
  595. if (_n) {
  596. off += snprintf(sql_buf + off, SQL_BUF_LEN - off, "where ");
  597. off += print_where(sql_buf + off, SQL_BUF_LEN - off,
  598. _k, _op, _v, _n);
  599. }
  600. if (_o) {
  601. off += snprintf(sql_buf + off, SQL_BUF_LEN - off,
  602. "order by %s", _o);
  603. }
  604. if(begin_transaction(_h, sql_buf)) return(-1);
  605. if (submit_query(_h, sql_buf) < 0) {
  606. LOG(L_ERR, "db_query(): Error while submitting query\n");
  607. return -2;
  608. }
  609. rv = get_result(_h, _r);
  610. free_query(_h);
  611. commit_transaction(_h);
  612. return(rv);
  613. }
  614. /*
  615. * Execute a raw SQL query
  616. */
  617. int db_raw_query(db_con_t* _h, char* _s, db_res_t** _r)
  618. {
  619. int rv;
  620. if(begin_transaction(_h, sql_buf)) return(-1);
  621. if (submit_query(_h, _s) < 0) {
  622. LOG(L_ERR, "db_raw_query(): Error while submitting query\n");
  623. return -2;
  624. }
  625. rv = get_result(_h, _r);
  626. free_query(_h);
  627. commit_transaction(_h);
  628. return(rv);
  629. }
  630. /*
  631. * Retrieve result set
  632. */
  633. int get_result(db_con_t* _h, db_res_t** _r)
  634. {
  635. *_r = new_result_pg(CON_SQLURL(_h));
  636. if (!CON_RESULT(_h)) {
  637. LOG(L_ERR, "get_result(): error");
  638. free_result(*_r);
  639. *_r = 0;
  640. return -3;
  641. }
  642. if (convert_result(_h, *_r) < 0) {
  643. LOG(L_ERR, "get_result(): Error while converting result\n");
  644. free_result(*_r);
  645. *_r = 0;
  646. return -4;
  647. }
  648. return 0;
  649. }
  650. /*
  651. * Insert a row into specified table
  652. * _h: structure representing database connection
  653. * _k: key names
  654. * _v: values of the keys
  655. * _n: number of key=value pairs
  656. */
  657. int db_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n)
  658. {
  659. int off;
  660. off = snprintf(sql_buf, SQL_BUF_LEN, "insert into %s (", CON_TABLE(_h));
  661. off += print_columns(sql_buf + off, SQL_BUF_LEN - off, _k, _n);
  662. off += snprintf(sql_buf + off, SQL_BUF_LEN - off, ") values (");
  663. off += print_values(sql_buf + off, SQL_BUF_LEN - off, _v, _n);
  664. *(sql_buf + off++) = ')';
  665. *(sql_buf + off) = '\0';
  666. if(begin_transaction(_h, sql_buf)) return(-1);
  667. if (submit_query(_h, sql_buf) < 0) {
  668. LOG(L_ERR, "db_insert(): Error while inserting\n");
  669. return -2;
  670. }
  671. free_query(_h);
  672. commit_transaction(_h);
  673. return(0);
  674. }
  675. /*
  676. * Delete a row from the specified table
  677. * _h: structure representing database connection
  678. * _k: key names
  679. * _o: operators
  680. * _v: values of the keys that must match
  681. * _n: number of key=value pairs
  682. */
  683. int db_delete(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n)
  684. {
  685. int off;
  686. off = snprintf(sql_buf, SQL_BUF_LEN, "delete from %s", CON_TABLE(_h));
  687. if (_n) {
  688. off += snprintf(sql_buf + off, SQL_BUF_LEN - off, " where ");
  689. off += print_where(sql_buf + off, SQL_BUF_LEN - off, _k,
  690. _o, _v, _n);
  691. }
  692. if(begin_transaction(_h, sql_buf)) return(-1);
  693. if (submit_query(_h, sql_buf) < 0) {
  694. LOG(L_ERR, "db_delete(): Error while deleting\n");
  695. return -2;
  696. }
  697. free_query(_h);
  698. commit_transaction(_h);
  699. return(0);
  700. }
  701. /*
  702. * Update some rows in the specified table
  703. * _h: structure representing database connection
  704. * _k: key names
  705. * _o: operators
  706. * _v: values of the keys that must match
  707. * _uk: updated columns
  708. * _uv: updated values of the columns
  709. * _n: number of key=value pairs
  710. * _un: number of columns to update
  711. */
  712. int db_update(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v,
  713. db_key_t* _uk, db_val_t* _uv, int _n, int _un)
  714. {
  715. int off;
  716. off = snprintf(sql_buf, SQL_BUF_LEN, "update %s set ", CON_TABLE(_h));
  717. off += print_set(sql_buf + off, SQL_BUF_LEN - off, _uk, _uv, _un);
  718. if (_n) {
  719. off += snprintf(sql_buf + off, SQL_BUF_LEN - off, " where ");
  720. off += print_where(sql_buf + off, SQL_BUF_LEN - off, _k,
  721. _o, _v, _n);
  722. *(sql_buf + off) = '\0';
  723. }
  724. if(begin_transaction(_h, sql_buf)) return(-1);
  725. if (submit_query(_h, sql_buf) < 0) {
  726. LOG(L_ERR, "db_update(): Error while updating\n");
  727. return -2;
  728. }
  729. free_query(_h);
  730. commit_transaction(_h);
  731. return(0);
  732. }