pq_result_helper.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2014, 2015, 2016 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file pq/pq_result_helper.c
  18. * @brief functions to extract result values
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_pq_lib.h"
  24. /**
  25. * Function called to clean up memory allocated
  26. * by a #GNUNET_PQ_ResultConverter.
  27. *
  28. * @param cls closure
  29. * @param rd result data to clean up
  30. */
  31. static void
  32. clean_varsize_blob (void *cls,
  33. void *rd)
  34. {
  35. void **dst = rd;
  36. (void) cls;
  37. if (NULL != *dst)
  38. {
  39. GNUNET_free (*dst);
  40. *dst = NULL;
  41. }
  42. }
  43. /**
  44. * Extract data from a Postgres database @a result at row @a row.
  45. *
  46. * @param cls closure
  47. * @param result where to extract data from
  48. * @param int row to extract data from
  49. * @param fname name (or prefix) of the fields to extract from
  50. * @param[in,out] dst_size where to store size of result, may be NULL
  51. * @param[out] dst where to store the result
  52. * @return
  53. * #GNUNET_YES if all results could be extracted
  54. * #GNUNET_SYSERR if a result was invalid (non-existing field)
  55. */
  56. static int
  57. extract_varsize_blob (void *cls,
  58. PGresult *result,
  59. int row,
  60. const char *fname,
  61. size_t *dst_size,
  62. void *dst)
  63. {
  64. size_t len;
  65. const char *res;
  66. void *idst;
  67. int fnum;
  68. (void) cls;
  69. *dst_size = 0;
  70. *((void **) dst) = NULL;
  71. fnum = PQfnumber (result,
  72. fname);
  73. if (fnum < 0)
  74. {
  75. GNUNET_break (0);
  76. return GNUNET_SYSERR;
  77. }
  78. if (PQgetisnull (result,
  79. row,
  80. fnum))
  81. {
  82. /* Let's allow this for varsize */
  83. return GNUNET_OK;
  84. }
  85. /* if a field is null, continue but
  86. * remember that we now return a different result */
  87. len = PQgetlength (result,
  88. row,
  89. fnum);
  90. res = PQgetvalue (result,
  91. row,
  92. fnum);
  93. GNUNET_assert (NULL != res);
  94. *dst_size = len;
  95. idst = GNUNET_malloc (len);
  96. *((void **) dst) = idst;
  97. GNUNET_memcpy (idst,
  98. res,
  99. len);
  100. return GNUNET_OK;
  101. }
  102. /**
  103. * Variable-size result expected.
  104. *
  105. * @param name name of the field in the table
  106. * @param[out] dst where to store the result, allocated
  107. * @param[out] sptr where to store the size of @a dst
  108. * @return array entry for the result specification to use
  109. */
  110. struct GNUNET_PQ_ResultSpec
  111. GNUNET_PQ_result_spec_variable_size (const char *name,
  112. void **dst,
  113. size_t *sptr)
  114. {
  115. struct GNUNET_PQ_ResultSpec res =
  116. { &extract_varsize_blob,
  117. &clean_varsize_blob, NULL,
  118. (void *) (dst), 0, name, sptr };
  119. return res;
  120. }
  121. /**
  122. * Extract data from a Postgres database @a result at row @a row.
  123. *
  124. * @param cls closure
  125. * @param result where to extract data from
  126. * @param int row to extract data from
  127. * @param fname name (or prefix) of the fields to extract from
  128. * @param[in] dst_size desired size, never NULL
  129. * @param[out] dst where to store the result
  130. * @return
  131. * #GNUNET_YES if all results could be extracted
  132. * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
  133. */
  134. static int
  135. extract_fixed_blob (void *cls,
  136. PGresult *result,
  137. int row,
  138. const char *fname,
  139. size_t *dst_size,
  140. void *dst)
  141. {
  142. size_t len;
  143. const char *res;
  144. int fnum;
  145. (void) cls;
  146. fnum = PQfnumber (result,
  147. fname);
  148. if (fnum < 0)
  149. {
  150. GNUNET_break (0);
  151. return GNUNET_SYSERR;
  152. }
  153. if (PQgetisnull (result,
  154. row,
  155. fnum))
  156. {
  157. GNUNET_break (0);
  158. return GNUNET_SYSERR;
  159. }
  160. /* if a field is null, continue but
  161. * remember that we now return a different result */
  162. len = PQgetlength (result,
  163. row,
  164. fnum);
  165. if (*dst_size != len)
  166. {
  167. GNUNET_break (0);
  168. return GNUNET_SYSERR;
  169. }
  170. res = PQgetvalue (result,
  171. row,
  172. fnum);
  173. GNUNET_assert (NULL != res);
  174. GNUNET_memcpy (dst,
  175. res,
  176. len);
  177. return GNUNET_OK;
  178. }
  179. /**
  180. * Fixed-size result expected.
  181. *
  182. * @param name name of the field in the table
  183. * @param[out] dst where to store the result
  184. * @param dst_size number of bytes in @a dst
  185. * @return array entry for the result specification to use
  186. */
  187. struct GNUNET_PQ_ResultSpec
  188. GNUNET_PQ_result_spec_fixed_size (const char *name,
  189. void *dst,
  190. size_t dst_size)
  191. {
  192. struct GNUNET_PQ_ResultSpec res =
  193. { &extract_fixed_blob,
  194. NULL, NULL,
  195. (dst), dst_size, name, NULL };
  196. return res;
  197. }
  198. /**
  199. * Extract data from a Postgres database @a result at row @a row.
  200. *
  201. * @param cls closure
  202. * @param result where to extract data from
  203. * @param int row to extract data from
  204. * @param fname name (or prefix) of the fields to extract from
  205. * @param[in,out] dst_size where to store size of result, may be NULL
  206. * @param[out] dst where to store the result
  207. * @return
  208. * #GNUNET_YES if all results could be extracted
  209. * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
  210. */
  211. static int
  212. extract_rsa_public_key (void *cls,
  213. PGresult *result,
  214. int row,
  215. const char *fname,
  216. size_t *dst_size,
  217. void *dst)
  218. {
  219. struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
  220. size_t len;
  221. const char *res;
  222. int fnum;
  223. (void) cls;
  224. *pk = NULL;
  225. fnum = PQfnumber (result,
  226. fname);
  227. if (fnum < 0)
  228. {
  229. GNUNET_break (0);
  230. return GNUNET_SYSERR;
  231. }
  232. if (PQgetisnull (result,
  233. row,
  234. fnum))
  235. {
  236. GNUNET_break (0);
  237. return GNUNET_SYSERR;
  238. }
  239. /* if a field is null, continue but
  240. * remember that we now return a different result */
  241. len = PQgetlength (result,
  242. row,
  243. fnum);
  244. res = PQgetvalue (result,
  245. row,
  246. fnum);
  247. *pk = GNUNET_CRYPTO_rsa_public_key_decode (res,
  248. len);
  249. if (NULL == *pk)
  250. {
  251. GNUNET_break (0);
  252. return GNUNET_SYSERR;
  253. }
  254. return GNUNET_OK;
  255. }
  256. /**
  257. * Function called to clean up memory allocated
  258. * by a #GNUNET_PQ_ResultConverter.
  259. *
  260. * @param cls closure
  261. * @param rd result data to clean up
  262. */
  263. static void
  264. clean_rsa_public_key (void *cls,
  265. void *rd)
  266. {
  267. struct GNUNET_CRYPTO_RsaPublicKey **pk = rd;
  268. (void) cls;
  269. if (NULL != *pk)
  270. {
  271. GNUNET_CRYPTO_rsa_public_key_free (*pk);
  272. *pk = NULL;
  273. }
  274. }
  275. /**
  276. * RSA public key expected.
  277. *
  278. * @param name name of the field in the table
  279. * @param[out] rsa where to store the result
  280. * @return array entry for the result specification to use
  281. */
  282. struct GNUNET_PQ_ResultSpec
  283. GNUNET_PQ_result_spec_rsa_public_key (const char *name,
  284. struct GNUNET_CRYPTO_RsaPublicKey **rsa)
  285. {
  286. struct GNUNET_PQ_ResultSpec res =
  287. { &extract_rsa_public_key,
  288. &clean_rsa_public_key,
  289. NULL,
  290. (void *) rsa, 0, name, NULL };
  291. return res;
  292. }
  293. /**
  294. * Extract data from a Postgres database @a result at row @a row.
  295. *
  296. * @param cls closure
  297. * @param result where to extract data from
  298. * @param int row to extract data from
  299. * @param fname name (or prefix) of the fields to extract from
  300. * @param[in,out] dst_size where to store size of result, may be NULL
  301. * @param[out] dst where to store the result
  302. * @return
  303. * #GNUNET_YES if all results could be extracted
  304. * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
  305. */
  306. static int
  307. extract_rsa_signature (void *cls,
  308. PGresult *result,
  309. int row,
  310. const char *fname,
  311. size_t *dst_size,
  312. void *dst)
  313. {
  314. struct GNUNET_CRYPTO_RsaSignature **sig = dst;
  315. size_t len;
  316. const char *res;
  317. int fnum;
  318. (void) cls;
  319. *sig = NULL;
  320. fnum = PQfnumber (result,
  321. fname);
  322. if (fnum < 0)
  323. {
  324. GNUNET_break (0);
  325. return GNUNET_SYSERR;
  326. }
  327. if (PQgetisnull (result,
  328. row,
  329. fnum))
  330. {
  331. GNUNET_break (0);
  332. return GNUNET_SYSERR;
  333. }
  334. /* if a field is null, continue but
  335. * remember that we now return a different result */
  336. len = PQgetlength (result,
  337. row,
  338. fnum);
  339. res = PQgetvalue (result,
  340. row,
  341. fnum);
  342. *sig = GNUNET_CRYPTO_rsa_signature_decode (res,
  343. len);
  344. if (NULL == *sig)
  345. {
  346. GNUNET_break (0);
  347. return GNUNET_SYSERR;
  348. }
  349. return GNUNET_OK;
  350. }
  351. /**
  352. * Function called to clean up memory allocated
  353. * by a #GNUNET_PQ_ResultConverter.
  354. *
  355. * @param cls closure
  356. * @param rd result data to clean up
  357. */
  358. static void
  359. clean_rsa_signature (void *cls,
  360. void *rd)
  361. {
  362. struct GNUNET_CRYPTO_RsaSignature **sig = rd;
  363. (void) cls;
  364. if (NULL != *sig)
  365. {
  366. GNUNET_CRYPTO_rsa_signature_free (*sig);
  367. *sig = NULL;
  368. }
  369. }
  370. /**
  371. * RSA signature expected.
  372. *
  373. * @param name name of the field in the table
  374. * @param[out] sig where to store the result;
  375. * @return array entry for the result specification to use
  376. */
  377. struct GNUNET_PQ_ResultSpec
  378. GNUNET_PQ_result_spec_rsa_signature (const char *name,
  379. struct GNUNET_CRYPTO_RsaSignature **sig)
  380. {
  381. struct GNUNET_PQ_ResultSpec res =
  382. { &extract_rsa_signature,
  383. &clean_rsa_signature,
  384. NULL,
  385. (void *) sig, 0, (name), NULL };
  386. return res;
  387. }
  388. /**
  389. * Extract data from a Postgres database @a result at row @a row.
  390. *
  391. * @param cls closure
  392. * @param result where to extract data from
  393. * @param int row to extract data from
  394. * @param fname name (or prefix) of the fields to extract from
  395. * @param[in,out] dst_size where to store size of result, may be NULL
  396. * @param[out] dst where to store the result
  397. * @return
  398. * #GNUNET_YES if all results could be extracted
  399. * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
  400. */
  401. static int
  402. extract_string (void *cls,
  403. PGresult *result,
  404. int row,
  405. const char *fname,
  406. size_t *dst_size,
  407. void *dst)
  408. {
  409. char **str = dst;
  410. size_t len;
  411. const char *res;
  412. int fnum;
  413. (void) cls;
  414. *str = NULL;
  415. fnum = PQfnumber (result,
  416. fname);
  417. if (fnum < 0)
  418. {
  419. GNUNET_break (0);
  420. return GNUNET_SYSERR;
  421. }
  422. if (PQgetisnull (result,
  423. row,
  424. fnum))
  425. {
  426. GNUNET_break (0);
  427. return GNUNET_SYSERR;
  428. }
  429. /* if a field is null, continue but
  430. * remember that we now return a different result */
  431. len = PQgetlength (result,
  432. row,
  433. fnum);
  434. res = PQgetvalue (result,
  435. row,
  436. fnum);
  437. *str = GNUNET_strndup (res,
  438. len);
  439. if (NULL == *str)
  440. {
  441. GNUNET_break (0);
  442. return GNUNET_SYSERR;
  443. }
  444. return GNUNET_OK;
  445. }
  446. /**
  447. * Function called to clean up memory allocated
  448. * by a #GNUNET_PQ_ResultConverter.
  449. *
  450. * @param cls closure
  451. * @param rd result data to clean up
  452. */
  453. static void
  454. clean_string (void *cls,
  455. void *rd)
  456. {
  457. char **str = rd;
  458. (void) cls;
  459. if (NULL != *str)
  460. {
  461. GNUNET_free (*str);
  462. *str = NULL;
  463. }
  464. }
  465. /**
  466. * 0-terminated string expected.
  467. *
  468. * @param name name of the field in the table
  469. * @param[out] dst where to store the result, allocated
  470. * @return array entry for the result specification to use
  471. */
  472. struct GNUNET_PQ_ResultSpec
  473. GNUNET_PQ_result_spec_string (const char *name,
  474. char **dst)
  475. {
  476. struct GNUNET_PQ_ResultSpec res =
  477. { &extract_string,
  478. &clean_string,
  479. NULL,
  480. (void *) dst, 0, (name), NULL };
  481. return res;
  482. }
  483. /**
  484. * Extract data from a Postgres database @a result at row @a row.
  485. *
  486. * @param cls closure
  487. * @param result where to extract data from
  488. * @param int row to extract data from
  489. * @param fname name (or prefix) of the fields to extract from
  490. * @param[in,out] dst_size where to store size of result, may be NULL
  491. * @param[out] dst where to store the result
  492. * @return
  493. * #GNUNET_YES if all results could be extracted
  494. * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
  495. */
  496. static int
  497. extract_abs_time (void *cls,
  498. PGresult *result,
  499. int row,
  500. const char *fname,
  501. size_t *dst_size,
  502. void *dst)
  503. {
  504. struct GNUNET_TIME_Absolute *udst = dst;
  505. const int64_t *res;
  506. int fnum;
  507. (void) cls;
  508. fnum = PQfnumber (result,
  509. fname);
  510. if (fnum < 0)
  511. {
  512. GNUNET_break (0);
  513. return GNUNET_SYSERR;
  514. }
  515. if (PQgetisnull (result,
  516. row,
  517. fnum))
  518. {
  519. GNUNET_break (0);
  520. return GNUNET_SYSERR;
  521. }
  522. GNUNET_assert (NULL != dst);
  523. if (sizeof (struct GNUNET_TIME_Absolute) != *dst_size)
  524. {
  525. GNUNET_break (0);
  526. return GNUNET_SYSERR;
  527. }
  528. if (sizeof (int64_t) !=
  529. PQgetlength (result,
  530. row,
  531. fnum))
  532. {
  533. GNUNET_break (0);
  534. return GNUNET_SYSERR;
  535. }
  536. res = (int64_t *) PQgetvalue (result,
  537. row,
  538. fnum);
  539. if (INT64_MAX == *res)
  540. *udst = GNUNET_TIME_UNIT_FOREVER_ABS;
  541. else
  542. udst->abs_value_us = GNUNET_ntohll ((uint64_t) *res);
  543. return GNUNET_OK;
  544. }
  545. /**
  546. * Absolute time expected.
  547. *
  548. * @param name name of the field in the table
  549. * @param[out] at where to store the result
  550. * @return array entry for the result specification to use
  551. */
  552. struct GNUNET_PQ_ResultSpec
  553. GNUNET_PQ_result_spec_absolute_time (const char *name,
  554. struct GNUNET_TIME_Absolute *at)
  555. {
  556. struct GNUNET_PQ_ResultSpec res =
  557. { &extract_abs_time,
  558. NULL,
  559. NULL,
  560. (void *) at, sizeof (*at), (name), NULL };
  561. return res;
  562. }
  563. /**
  564. * Absolute time in network byte order expected.
  565. *
  566. * @param name name of the field in the table
  567. * @param[out] at where to store the result
  568. * @return array entry for the result specification to use
  569. */
  570. struct GNUNET_PQ_ResultSpec
  571. GNUNET_PQ_result_spec_absolute_time_nbo (const char *name,
  572. struct GNUNET_TIME_AbsoluteNBO *at)
  573. {
  574. struct GNUNET_PQ_ResultSpec res =
  575. GNUNET_PQ_result_spec_auto_from_type(name, &at->abs_value_us__);
  576. return res;
  577. }
  578. /**
  579. * Extract data from a Postgres database @a result at row @a row.
  580. *
  581. * @param cls closure
  582. * @param result where to extract data from
  583. * @param int row to extract data from
  584. * @param fname name (or prefix) of the fields to extract from
  585. * @param[in,out] dst_size where to store size of result, may be NULL
  586. * @param[out] dst where to store the result
  587. * @return
  588. * #GNUNET_YES if all results could be extracted
  589. * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
  590. */
  591. static int
  592. extract_uint16 (void *cls,
  593. PGresult *result,
  594. int row,
  595. const char *fname,
  596. size_t *dst_size,
  597. void *dst)
  598. {
  599. uint16_t *udst = dst;
  600. const uint16_t *res;
  601. int fnum;
  602. (void) cls;
  603. fnum = PQfnumber (result,
  604. fname);
  605. if (fnum < 0)
  606. {
  607. GNUNET_break (0);
  608. return GNUNET_SYSERR;
  609. }
  610. if (PQgetisnull (result,
  611. row,
  612. fnum))
  613. {
  614. GNUNET_break (0);
  615. return GNUNET_SYSERR;
  616. }
  617. GNUNET_assert (NULL != dst);
  618. if (sizeof (uint16_t) != *dst_size)
  619. {
  620. GNUNET_break (0);
  621. return GNUNET_SYSERR;
  622. }
  623. if (sizeof (uint16_t) !=
  624. PQgetlength (result,
  625. row,
  626. fnum))
  627. {
  628. GNUNET_break (0);
  629. return GNUNET_SYSERR;
  630. }
  631. res = (uint16_t *) PQgetvalue (result,
  632. row,
  633. fnum);
  634. *udst = ntohs (*res);
  635. return GNUNET_OK;
  636. }
  637. /**
  638. * uint16_t expected.
  639. *
  640. * @param name name of the field in the table
  641. * @param[out] u16 where to store the result
  642. * @return array entry for the result specification to use
  643. */
  644. struct GNUNET_PQ_ResultSpec
  645. GNUNET_PQ_result_spec_uint16 (const char *name,
  646. uint16_t *u16)
  647. {
  648. struct GNUNET_PQ_ResultSpec res =
  649. { &extract_uint16,
  650. NULL,
  651. NULL,
  652. (void *) u16, sizeof (*u16), (name), NULL };
  653. return res;
  654. }
  655. /**
  656. * Extract data from a Postgres database @a result at row @a row.
  657. *
  658. * @param cls closure
  659. * @param result where to extract data from
  660. * @param int row to extract data from
  661. * @param fname name (or prefix) of the fields to extract from
  662. * @param[in,out] dst_size where to store size of result, may be NULL
  663. * @param[out] dst where to store the result
  664. * @return
  665. * #GNUNET_YES if all results could be extracted
  666. * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
  667. */
  668. static int
  669. extract_uint32 (void *cls,
  670. PGresult *result,
  671. int row,
  672. const char *fname,
  673. size_t *dst_size,
  674. void *dst)
  675. {
  676. uint32_t *udst = dst;
  677. const uint32_t *res;
  678. int fnum;
  679. (void) cls;
  680. fnum = PQfnumber (result,
  681. fname);
  682. if (fnum < 0)
  683. {
  684. GNUNET_break (0);
  685. return GNUNET_SYSERR;
  686. }
  687. if (PQgetisnull (result,
  688. row,
  689. fnum))
  690. {
  691. GNUNET_break (0);
  692. return GNUNET_SYSERR;
  693. }
  694. GNUNET_assert (NULL != dst);
  695. if (sizeof (uint32_t) != *dst_size)
  696. {
  697. GNUNET_break (0);
  698. return GNUNET_SYSERR;
  699. }
  700. if (sizeof (uint32_t) !=
  701. PQgetlength (result,
  702. row,
  703. fnum))
  704. {
  705. GNUNET_break (0);
  706. return GNUNET_SYSERR;
  707. }
  708. res = (uint32_t *) PQgetvalue (result,
  709. row,
  710. fnum);
  711. *udst = ntohl (*res);
  712. return GNUNET_OK;
  713. }
  714. /**
  715. * uint32_t expected.
  716. *
  717. * @param name name of the field in the table
  718. * @param[out] u32 where to store the result
  719. * @return array entry for the result specification to use
  720. */
  721. struct GNUNET_PQ_ResultSpec
  722. GNUNET_PQ_result_spec_uint32 (const char *name,
  723. uint32_t *u32)
  724. {
  725. struct GNUNET_PQ_ResultSpec res =
  726. { &extract_uint32,
  727. NULL,
  728. NULL,
  729. (void *) u32, sizeof (*u32), (name), NULL };
  730. return res;
  731. }
  732. /**
  733. * Extract data from a Postgres database @a result at row @a row.
  734. *
  735. * @param cls closure
  736. * @param result where to extract data from
  737. * @param int row to extract data from
  738. * @param fname name (or prefix) of the fields to extract from
  739. * @param[in,out] dst_size where to store size of result, may be NULL
  740. * @param[out] dst where to store the result
  741. * @return
  742. * #GNUNET_YES if all results could be extracted
  743. * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
  744. */
  745. static int
  746. extract_uint64 (void *cls,
  747. PGresult *result,
  748. int row,
  749. const char *fname,
  750. size_t *dst_size,
  751. void *dst)
  752. {
  753. uint64_t *udst = dst;
  754. const uint64_t *res;
  755. int fnum;
  756. (void) cls;
  757. fnum = PQfnumber (result,
  758. fname);
  759. if (fnum < 0)
  760. {
  761. GNUNET_break (0);
  762. return GNUNET_SYSERR;
  763. }
  764. if (PQgetisnull (result,
  765. row,
  766. fnum))
  767. {
  768. GNUNET_break (0);
  769. return GNUNET_SYSERR;
  770. }
  771. GNUNET_assert (NULL != dst);
  772. if (sizeof (uint64_t) != *dst_size)
  773. {
  774. GNUNET_break (0);
  775. return GNUNET_SYSERR;
  776. }
  777. if (sizeof (uint64_t) !=
  778. PQgetlength (result,
  779. row,
  780. fnum))
  781. {
  782. GNUNET_break (0);
  783. return GNUNET_SYSERR;
  784. }
  785. res = (uint64_t *) PQgetvalue (result,
  786. row,
  787. fnum);
  788. *udst = GNUNET_ntohll (*res);
  789. return GNUNET_OK;
  790. }
  791. /**
  792. * uint64_t expected.
  793. *
  794. * @param name name of the field in the table
  795. * @param[out] u64 where to store the result
  796. * @return array entry for the result specification to use
  797. */
  798. struct GNUNET_PQ_ResultSpec
  799. GNUNET_PQ_result_spec_uint64 (const char *name,
  800. uint64_t *u64)
  801. {
  802. struct GNUNET_PQ_ResultSpec res =
  803. { &extract_uint64,
  804. NULL,
  805. NULL,
  806. (void *) u64, sizeof (*u64), (name), NULL };
  807. return res;
  808. }
  809. /* end of pq_result_helper.c */