2
0

dbase.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  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: sql://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) + sizeof(struct con_postgres), NULL);
  216. memset(res, 0, sizeof(db_con_t) + sizeof(struct con_postgres));
  217. if (connect_db(res, _sqlurl) < 0)
  218. {
  219. PLOG("db_init", "Error while trying to open database, FATAL\n");
  220. aug_free(res);
  221. return((db_con_t *) 0);
  222. }
  223. return res;
  224. }
  225. /*
  226. ** db_close last function to call when db is no longer needed
  227. **
  228. ** Arguments :
  229. ** db_con_t * the connection to shut down, as supplied by db_init()
  230. **
  231. ** Returns :
  232. ** (void)
  233. **
  234. ** Notes :
  235. ** All memory and resources are freed.
  236. */
  237. void db_close(db_con_t* _h)
  238. {
  239. DLOG("db_close", "entry");
  240. if(! _h)
  241. {
  242. PLOG("db_close", "no handle passed, ignored");
  243. return;
  244. }
  245. disconnect_db(_h);
  246. aug_free(_h);
  247. }
  248. /*
  249. ** submit_query run a query
  250. **
  251. ** Arguments :
  252. ** db_con_t * as previously supplied by db_init()
  253. ** char *_s the text query to run
  254. **
  255. ** Returns :
  256. ** 0 upon success
  257. ** negative number upon failure
  258. */
  259. static int submit_query(db_con_t* _h, const char* _s)
  260. {
  261. int rv;
  262. /*
  263. ** this bit of nonsense in case our connection get screwed up
  264. */
  265. switch(rv = PQstatus(CON_CONNECTION(_h)))
  266. {
  267. case CONNECTION_OK: break;
  268. case CONNECTION_BAD:
  269. PLOG("submit_query", "connection reset");
  270. PQreset(CON_CONNECTION(_h));
  271. break;
  272. }
  273. /*
  274. ** free any previous query that is laying about
  275. */
  276. if(CON_RESULT(_h))
  277. {
  278. free_query(_h);
  279. }
  280. /*
  281. ** exec the query
  282. */
  283. CON_RESULT(_h) = PQexec(CON_CONNECTION(_h), _s);
  284. rv = 0;
  285. if(PQresultStatus(CON_RESULT(_h)) == 0)
  286. {
  287. PLOG("submit_query", "initial failure, FATAL");
  288. /*
  289. ** terrible error??
  290. */
  291. rv = -3;
  292. }
  293. else
  294. {
  295. /*
  296. ** the query ran, get the status
  297. */
  298. switch(PQresultStatus(CON_RESULT(_h)))
  299. {
  300. case PGRES_EMPTY_QUERY: rv = -9; break;
  301. case PGRES_COMMAND_OK: rv = 0; break;
  302. case PGRES_TUPLES_OK: rv = 0; break;
  303. case PGRES_COPY_OUT: rv = -4; break;
  304. case PGRES_COPY_IN: rv = -5; break;
  305. case PGRES_BAD_RESPONSE: rv = -6; break;
  306. case PGRES_NONFATAL_ERROR: rv = -7; break;
  307. case PGRES_FATAL_ERROR: rv = -8; break;
  308. default: rv = -2; break;
  309. }
  310. }
  311. if(rv < 0)
  312. {
  313. /*
  314. ** log the error
  315. */
  316. char buf[256];
  317. sprintf(buf, "query '%s', result '%s'\n",
  318. _s, PQerrorMessage(CON_CONNECTION(_h)));
  319. PLOG("submit_query", buf);
  320. }
  321. return(rv);
  322. }
  323. /*
  324. ** free_query clear the db channel and clear any old query result status
  325. **
  326. ** Arguments :
  327. ** db_con_t * as previously supplied by db_init()
  328. **
  329. ** Returns :
  330. ** 0 upon success
  331. ** negative number upon failure
  332. */
  333. static int free_query(db_con_t* _h)
  334. {
  335. if(CON_RESULT(_h))
  336. {
  337. PQclear(CON_RESULT(_h));
  338. CON_RESULT(_h) = 0;
  339. }
  340. return 0;
  341. }
  342. /*
  343. ** db_free_query free the query and free the result memory
  344. **
  345. ** Arguments :
  346. ** db_con_t * as previously supplied by db_init()
  347. ** db_res_t * the result of a query
  348. **
  349. ** Returns :
  350. ** 0 upon success
  351. ** negative number upon failure
  352. */
  353. int db_free_query(db_con_t* _h, db_res_t* _r)
  354. {
  355. free_query(_h);
  356. free_result(_r);
  357. return 0;
  358. }
  359. /*
  360. ** begin_transaction begin transaction
  361. **
  362. ** Arguments :
  363. ** db_con_t * as previously supplied by db_init()
  364. ** char * this is just in case an error message
  365. ** is printed, we will know which query
  366. ** was going to be run, giving us a code debug hint
  367. **
  368. ** Returns :
  369. ** 0 upon success
  370. ** negative number upon failure
  371. **
  372. ** Notes :
  373. ** This function may be called with a messed up communication
  374. ** channel. Therefore, alot of this function is dealing with
  375. ** that. Wen the layering gets corrected later this stuff
  376. ** should continue to work correctly, it will just be
  377. ** way to defensive.
  378. */
  379. static int begin_transaction(db_con_t * _h, char *_s)
  380. {
  381. PGresult *mr;
  382. int rv;
  383. /*
  384. ** Note:
  385. ** The upper layers of code may attempt a transaction
  386. ** before opening or having a valid connection to the
  387. ** database. We try to sense this, and open the database
  388. ** if we have the sqlurl in the _h structure. Otherwise,
  389. ** all we can do is return an error.
  390. */
  391. if(_h)
  392. {
  393. if(CON_CONNECTED(_h))
  394. {
  395. mr = PQexec(CON_CONNECTION(_h), "BEGIN");
  396. if(!mr || PQresultStatus(mr) != PGRES_COMMAND_OK)
  397. {
  398. /*
  399. ** We get here if the connection to the
  400. ** db is corrupt, which can happen a few
  401. ** different ways, but all of them are
  402. ** related to the parent process forking,
  403. ** or being forked.
  404. */
  405. PLOG("begin_transaction","corrupt connection");
  406. CON_CONNECTED(_h) = 0;
  407. }
  408. else
  409. {
  410. /*
  411. ** this is the normal way out.
  412. ** the transaction ran fine.
  413. */
  414. PQclear(mr);
  415. return(0);
  416. }
  417. }
  418. else
  419. {
  420. DLOG("begin_transaction", "called before db_init");
  421. }
  422. /*
  423. ** if we get here we have a corrupt db connection,
  424. ** but we probably have a valid db_con_t structure.
  425. ** attempt to open the db.
  426. */
  427. if((rv = connect_db(_h, CON_SQLURL(_h))) != 0)
  428. {
  429. /*
  430. ** our attempt to fix the connection failed
  431. */
  432. char buf[256];
  433. sprintf(buf, "no connection, FATAL %d!", rv);
  434. PLOG("begin_transaction",buf);
  435. return(rv);
  436. }
  437. }
  438. else
  439. {
  440. PLOG("begin_transaction","must call db_init first!");
  441. return(-1);
  442. }
  443. /*
  444. ** we get here if the database connection was corrupt,
  445. ** i didn't want to use recursion ...
  446. */
  447. mr = PQexec(CON_CONNECTION(_h), "BEGIN");
  448. if(!mr || PQresultStatus(mr) != PGRES_COMMAND_OK)
  449. {
  450. char buf[256];
  451. sprintf("FATAL %s, '%s'!\n",
  452. PQerrorMessage(CON_CONNECTION(_h)), _s);
  453. PLOG("begin_transaction", buf);
  454. return(-1);
  455. }
  456. DLOG("begin_transaction", "db channel reset successful");
  457. PQclear(mr);
  458. return(0);
  459. }
  460. /*
  461. ** commit_transaction any begin_transaction must be terminated with this
  462. **
  463. ** Arguments :
  464. ** db_con_t * as previously supplied by db_init()
  465. **
  466. ** Returns :
  467. ** 0 upon success
  468. ** negative number upon failure
  469. */
  470. static int commit_transaction(db_con_t * _h)
  471. {
  472. PGresult *mr;
  473. mr = PQexec(CON_CONNECTION(_h), "COMMIT");
  474. if(!mr || PQresultStatus(mr) != PGRES_COMMAND_OK)
  475. {
  476. PLOG("commit_transaction", "error");
  477. return -1;
  478. }
  479. PQclear(mr);
  480. return(0);
  481. }
  482. /*
  483. * Print list of columns separated by comma
  484. */
  485. static int print_columns(char* _b, int _l, db_key_t* _c, int _n)
  486. {
  487. int i;
  488. int res = 0;
  489. for(i = 0; i < _n; i++) {
  490. if (i == (_n - 1)) {
  491. res += snprintf(_b + res, _l - res, "%s ", _c[i]);
  492. } else {
  493. res += snprintf(_b + res, _l - res, "%s,", _c[i]);
  494. }
  495. }
  496. return res;
  497. }
  498. /*
  499. * Print list of values separated by comma
  500. */
  501. static int print_values(char* _b, int _l, db_val_t* _v, int _n)
  502. {
  503. int i, res = 0, l;
  504. for(i = 0; i < _n; i++) {
  505. l = _l - res;
  506. /* LOG(L_ERR, "%d sizes l = _l - res %d = %d - %d\n", i, l,_l,res);
  507. */
  508. if (val2str(_v + i, _b + res, &l) < 0) {
  509. LOG(L_ERR,
  510. "print_values(): Error converting value to string\n");
  511. return 0;
  512. }
  513. res += l;
  514. if (i != (_n - 1)) {
  515. *(_b + res) = ',';
  516. res++;
  517. }
  518. }
  519. return res;
  520. }
  521. /*
  522. * Print where clause of SQL statement
  523. */
  524. static int print_where(char* _b, int _l, db_key_t* _k,
  525. db_op_t* _o, db_val_t* _v, int _n)
  526. {
  527. int i;
  528. int res = 0;
  529. int l;
  530. for(i = 0; i < _n; i++) {
  531. if (_o) {
  532. res += snprintf(_b + res, _l - res, "%s%s",
  533. _k[i], _o[i]);
  534. } else {
  535. res += snprintf(_b + res, _l - res, "%s=", _k[i]);
  536. }
  537. l = _l - res;
  538. val2str(&(_v[i]), _b + res, &l);
  539. res += l;
  540. if (i != (_n - 1)) {
  541. res += snprintf(_b + res, _l - res, " AND ");
  542. }
  543. }
  544. return res;
  545. }
  546. /*
  547. * Print set clause of update SQL statement
  548. */
  549. static int print_set(char* _b, int _l, db_key_t* _k,
  550. db_val_t* _v, int _n)
  551. {
  552. int i;
  553. int res = 0;
  554. int l;
  555. for(i = 0; i < _n; i++) {
  556. res += snprintf(_b + res, _l - res, "%s=", _k[i]);
  557. l = _l - res;
  558. val2str(&(_v[i]), _b + res, &l);
  559. res += l;
  560. if (i != (_n - 1)) {
  561. if ((_l - res) >= 1) {
  562. *(_b + res++) = ',';
  563. }
  564. }
  565. }
  566. return res;
  567. }
  568. /*
  569. * Query table for specified rows
  570. * _h: structure representing database connection
  571. * _k: key names
  572. * _op: operators
  573. * _v: values of the keys that must match
  574. * _c: column names to return
  575. * _n: nmber of key=values pairs to compare
  576. * _nc: number of columns to return
  577. * _o: order by the specified column
  578. */
  579. int db_query(db_con_t* _h, db_key_t* _k, db_op_t* _op,
  580. db_val_t* _v, db_key_t* _c, int _n, int _nc,
  581. db_key_t _o, db_res_t** _r)
  582. {
  583. int off, rv;
  584. if (!_c) {
  585. off = snprintf(sql_buf, SQL_BUF_LEN,
  586. "select * from %s ", CON_TABLE(_h));
  587. } else {
  588. off = snprintf(sql_buf, SQL_BUF_LEN, "select ");
  589. off += print_columns(sql_buf + off, SQL_BUF_LEN - off, _c, _nc);
  590. off += snprintf(sql_buf + off, SQL_BUF_LEN - off,
  591. "from %s ", CON_TABLE(_h));
  592. }
  593. if (_n) {
  594. off += snprintf(sql_buf + off, SQL_BUF_LEN - off, "where ");
  595. off += print_where(sql_buf + off, SQL_BUF_LEN - off,
  596. _k, _op, _v, _n);
  597. }
  598. if (_o) {
  599. off += snprintf(sql_buf + off, SQL_BUF_LEN - off,
  600. "order by %s", _o);
  601. }
  602. if(begin_transaction(_h, sql_buf)) return(-1);
  603. if (submit_query(_h, sql_buf) < 0) {
  604. LOG(L_ERR, "db_query(): Error while submitting query\n");
  605. return -2;
  606. }
  607. rv = get_result(_h, _r);
  608. free_query(_h);
  609. commit_transaction(_h);
  610. return(rv);
  611. }
  612. /*
  613. * Execute a raw SQL query
  614. */
  615. int db_raw_query(db_con_t* _h, char* _s, db_res_t** _r)
  616. {
  617. int rv;
  618. if(begin_transaction(_h, sql_buf)) return(-1);
  619. if (submit_query(_h, _s) < 0) {
  620. LOG(L_ERR, "db_raw_query(): Error while submitting query\n");
  621. return -2;
  622. }
  623. rv = get_result(_h, _r);
  624. free_query(_h);
  625. commit_transaction(_h);
  626. return(rv);
  627. }
  628. /*
  629. * Retrieve result set
  630. */
  631. int get_result(db_con_t* _h, db_res_t** _r)
  632. {
  633. *_r = new_result_pg(CON_SQLURL(_h));
  634. if (!CON_RESULT(_h)) {
  635. LOG(L_ERR, "get_result(): error");
  636. free_result(*_r);
  637. *_r = 0;
  638. return -3;
  639. }
  640. if (convert_result(_h, *_r) < 0) {
  641. LOG(L_ERR, "get_result(): Error while converting result\n");
  642. free_result(*_r);
  643. *_r = 0;
  644. return -4;
  645. }
  646. return 0;
  647. }
  648. /*
  649. * Insert a row into specified table
  650. * _h: structure representing database connection
  651. * _k: key names
  652. * _v: values of the keys
  653. * _n: number of key=value pairs
  654. */
  655. int db_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n)
  656. {
  657. int off;
  658. off = snprintf(sql_buf, SQL_BUF_LEN, "insert into %s (", CON_TABLE(_h));
  659. off += print_columns(sql_buf + off, SQL_BUF_LEN - off, _k, _n);
  660. off += snprintf(sql_buf + off, SQL_BUF_LEN - off, ") values (");
  661. off += print_values(sql_buf + off, SQL_BUF_LEN - off, _v, _n);
  662. *(sql_buf + off++) = ')';
  663. *(sql_buf + off) = '\0';
  664. if(begin_transaction(_h, sql_buf)) return(-1);
  665. if (submit_query(_h, sql_buf) < 0) {
  666. LOG(L_ERR, "db_insert(): Error while inserting\n");
  667. return -2;
  668. }
  669. free_query(_h);
  670. commit_transaction(_h);
  671. return(0);
  672. }
  673. /*
  674. * Delete a row from the specified table
  675. * _h: structure representing database connection
  676. * _k: key names
  677. * _o: operators
  678. * _v: values of the keys that must match
  679. * _n: number of key=value pairs
  680. */
  681. int db_delete(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n)
  682. {
  683. int off;
  684. off = snprintf(sql_buf, SQL_BUF_LEN, "delete from %s", CON_TABLE(_h));
  685. if (_n) {
  686. off += snprintf(sql_buf + off, SQL_BUF_LEN - off, " where ");
  687. off += print_where(sql_buf + off, SQL_BUF_LEN - off, _k,
  688. _o, _v, _n);
  689. }
  690. if(begin_transaction(_h, sql_buf)) return(-1);
  691. if (submit_query(_h, sql_buf) < 0) {
  692. LOG(L_ERR, "db_delete(): Error while deleting\n");
  693. return -2;
  694. }
  695. free_query(_h);
  696. commit_transaction(_h);
  697. return(0);
  698. }
  699. /*
  700. * Update some rows in the specified table
  701. * _h: structure representing database connection
  702. * _k: key names
  703. * _o: operators
  704. * _v: values of the keys that must match
  705. * _uk: updated columns
  706. * _uv: updated values of the columns
  707. * _n: number of key=value pairs
  708. * _un: number of columns to update
  709. */
  710. int db_update(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v,
  711. db_key_t* _uk, db_val_t* _uv, int _n, int _un)
  712. {
  713. int off;
  714. off = snprintf(sql_buf, SQL_BUF_LEN, "update %s set ", CON_TABLE(_h));
  715. off += print_set(sql_buf + off, SQL_BUF_LEN - off, _uk, _uv, _un);
  716. if (_n) {
  717. off += snprintf(sql_buf + off, SQL_BUF_LEN - off, " where ");
  718. off += print_where(sql_buf + off, SQL_BUF_LEN - off, _k,
  719. _o, _v, _n);
  720. *(sql_buf + off) = '\0';
  721. }
  722. if(begin_transaction(_h, sql_buf)) return(-1);
  723. if (submit_query(_h, sql_buf) < 0) {
  724. LOG(L_ERR, "db_update(): Error while updating\n");
  725. return -2;
  726. }
  727. free_query(_h);
  728. commit_transaction(_h);
  729. return(0);
  730. }