1 /* 2 * WARNING: automatically generated by ort 0.14.1. 3 * DO NOT EDIT! 4 */ 5 #include <sys/queue.h> 6 7 #include <assert.h> 8 /* 9 * Required for b64_ntop(). 10 */ 11 #include <ctype.h> 12 #include <netinet/in.h> 13 #include <resolv.h> 14 #include <stdio.h> 15 #include <stdint.h> /* int64_t */ 16 #include <stdlib.h> 17 #include <string.h> 18 #include <time.h> /* _XOPEN_SOURCE and gmtime_r()*/ 19 #include <unistd.h> 20 21 #include <sqlbox.h> 22 23 #include "db.h" 24 25 /* 26 * All SQL statements we'll later define in "stmts". 27 */ 28 enum stmt { 29 STMT_company_BY_UNIQUE_id, 30 STMT_company_BY_SEARCH_0, 31 STMT_company_INSERT, 32 STMT_company_DELETE_0, 33 STMT_user_BY_UNIQUE_email, 34 STMT_user_BY_UNIQUE_uid, 35 STMT_user_BY_SEARCH_0, 36 STMT_user_BY_SEARCH_1, 37 STMT_user_BY_SEARCH_2, 38 STMT_user_INSERT, 39 STMT_user_UPDATE_0, 40 STMT_user_UPDATE_1, 41 STMT_user_DELETE_0, 42 STMT_session_BY_UNIQUE_id, 43 STMT_session_BY_SEARCH_0, 44 STMT_session_INSERT, 45 STMT_session_DELETE_0, 46 STMT__MAX 47 }; 48 49 /* 50 * Definition of our opaque "ort", which contains role information. 51 */ 52 struct ort { 53 /* Hidden database connection */ 54 struct sqlbox *db; 55 }; 56 57 /* 58 * Table columns. 59 * The macro accepts a table name because we use AS statements a lot. 60 * This is because tables can appear multiple times in a single query and 61 * need aliasing. 62 */ 63 #define DB_SCHEMA_company(_x) \ 64 #_x ".name" "," \ 65 #_x ".id" "," \ 66 #_x ".somenum" 67 #define DB_SCHEMA_user(_x) \ 68 #_x ".cid" "," \ 69 #_x ".sex" "," \ 70 #_x ".hash" "," \ 71 #_x ".email" "," \ 72 #_x ".image" "," \ 73 #_x ".name" "," \ 74 #_x ".uid" 75 #define DB_SCHEMA_session(_x) \ 76 #_x ".userid" "," \ 77 #_x ".token" "," \ 78 #_x ".mtime" "," \ 79 #_x ".id" 80 81 /* 82 * Our full set of SQL statements. 83 * We define these beforehand because that's how sqlbox(3) handles 84 * statement generation. 85 * Notice the "AS" part: this allows for multiple inner joins without 86 * ambiguity. 87 */ 88 static const char *const stmts[STMT__MAX] = { 89 /* STMT_company_BY_UNIQUE_id */ 90 "SELECT " DB_SCHEMA_company(company) " FROM company WHERE company.id = ?", 91 /* STMT_company_BY_SEARCH_0 */ 92 "SELECT " DB_SCHEMA_company(company) " FROM company " 93 "WHERE company.somenum ISNULL", 94 /* STMT_company_INSERT */ 95 "INSERT INTO company (name,somenum) VALUES (?,?)", 96 /* STMT_company_DELETE_0 */ 97 "DELETE FROM company", 98 /* STMT_user_BY_UNIQUE_email */ 99 "SELECT " DB_SCHEMA_user(user) "," DB_SCHEMA_company(_a) " FROM user " 100 "INNER JOIN company AS _a ON _a.id=user.cid " 101 "WHERE user.email = ?", 102 /* STMT_user_BY_UNIQUE_uid */ 103 "SELECT " DB_SCHEMA_user(user) "," DB_SCHEMA_company(_a) " FROM user " 104 "INNER JOIN company AS _a ON _a.id=user.cid " 105 "WHERE user.uid = ?", 106 /* STMT_user_BY_SEARCH_0 */ 107 "SELECT " DB_SCHEMA_user(user) "," DB_SCHEMA_company(_a) " FROM user " 108 "INNER JOIN company AS _a ON _a.id=user.cid " 109 "WHERE user.name = ? LIMIT 5", 110 /* STMT_user_BY_SEARCH_1 */ 111 "SELECT " DB_SCHEMA_user(user) "," DB_SCHEMA_company(_a) " FROM user " 112 "INNER JOIN company AS _a ON _a.id=user.cid " 113 "WHERE user.email = ?", 114 /* STMT_user_BY_SEARCH_2 */ 115 "SELECT " DB_SCHEMA_user(user) "," DB_SCHEMA_company(_a) " FROM user " 116 "INNER JOIN company AS _a ON _a.id=user.cid " 117 "WHERE user.uid = ? ORDER BY _a.name ASC", 118 /* STMT_user_INSERT */ 119 "INSERT INTO user (cid,sex,hash,email,image,name) VALUES (?,?,?,?," 120 " ?,?)", 121 /* STMT_user_UPDATE_0 */ 122 "UPDATE user SET hash = ? WHERE uid = ?", 123 /* STMT_user_UPDATE_1 */ 124 "UPDATE user SET email = ? WHERE uid = ?", 125 /* STMT_user_DELETE_0 */ 126 "DELETE FROM user", 127 /* STMT_session_BY_UNIQUE_id */ 128 "SELECT " DB_SCHEMA_session(session) "," DB_SCHEMA_user(_b) "," 129 DB_SCHEMA_company(_c) " FROM session " 130 "INNER JOIN user AS _b ON _b.uid=session.userid " 131 "INNER JOIN company AS _c ON _c.id=_b.cid " 132 "WHERE session.id = ?", 133 /* STMT_session_BY_SEARCH_0 */ 134 "SELECT " DB_SCHEMA_session(session) "," DB_SCHEMA_user(_b) "," 135 DB_SCHEMA_company(_c) " FROM session " 136 "INNER JOIN user AS _b ON _b.uid=session.userid " 137 "INNER JOIN company AS _c ON _c.id=_b.cid " 138 "WHERE _c.name = ? AND session.mtime = ?", 139 /* STMT_session_INSERT */ 140 "INSERT INTO session (userid,token,mtime) VALUES (?,?,?)", 141 /* STMT_session_DELETE_0 */ 142 "DELETE FROM session WHERE id = ?", 143 }; 144 145 /* 146 * Finally, all of the functions we'll use. 147 * All of the non-static functions are documented in the associated 148 * header file. 149 */ 150 151 void 152 db_trans_open(struct ort *ctx, size_t id, int mode) 153 { 154 struct sqlbox *db = ctx->db; 155 int c; 156 157 if (mode < 0) 158 c = sqlbox_trans_exclusive(db, 0, id); 159 else if (mode > 0) 160 c = sqlbox_trans_immediate(db, 0, id); 161 else 162 c = sqlbox_trans_deferred(db, 0, id); 163 if (!c) 164 exit(EXIT_FAILURE); 165 } 166 167 void 168 db_trans_rollback(struct ort *ctx, size_t id) 169 { 170 struct sqlbox *db = ctx->db; 171 172 if (!sqlbox_trans_rollback(db, 0, id)) 173 exit(EXIT_FAILURE); 174 } 175 176 void 177 db_trans_commit(struct ort *ctx, size_t id) 178 { 179 struct sqlbox *db = ctx->db; 180 181 if (!sqlbox_trans_commit(db, 0, id)) 182 exit(EXIT_FAILURE); 183 } 184 185 void 186 db_logging_data(struct ort *ort, const void *arg, size_t sz) 187 { 188 189 if (!sqlbox_msg_set_dat(ort->db, arg, sz)) 190 exit(EXIT_FAILURE); 191 } 192 193 struct ort * 194 db_open(const char *file) 195 { 196 197 return db_open_logging(file, NULL, NULL, NULL); 198 } 199 200 struct ort * 201 db_open_logging(const char *file, 202 void (*log)(const char *, void *), 203 void (*log_short)(const char *, ...), void *log_arg) 204 { 205 size_t i; 206 struct ort *ctx = NULL; 207 struct sqlbox_cfg cfg; 208 struct sqlbox *db = NULL; 209 struct sqlbox_pstmt pstmts[STMT__MAX]; 210 struct sqlbox_src srcs[1] = { 211 { .fname = (char *)file, 212 .mode = SQLBOX_SRC_RW } 213 }; 214 215 memset(&cfg, 0, sizeof(struct sqlbox_cfg)); 216 cfg.msg.func = log; 217 cfg.msg.func_short = log_short; 218 cfg.msg.dat = log_arg; 219 cfg.srcs.srcs = srcs; 220 cfg.srcs.srcsz = 1; 221 cfg.stmts.stmts = pstmts; 222 cfg.stmts.stmtsz = STMT__MAX; 223 224 for (i = 0; i < STMT__MAX; i++) 225 pstmts[i].stmt = (char *)stmts[i]; 226 227 ctx = malloc(sizeof(struct ort)); 228 if (ctx == NULL) 229 goto err; 230 231 if ((db = sqlbox_alloc(&cfg)) == NULL) 232 goto err; 233 ctx->db = db; 234 235 /* 236 * Now actually open the database. 237 * If this succeeds, then we're good to go. 238 */ 239 240 if (sqlbox_open_async(db, 0)) 241 return ctx; 242 err: 243 sqlbox_free(db); 244 free(ctx); 245 return NULL; 246 } 247 248 void 249 db_close(struct ort *p) 250 { 251 if (p == NULL) 252 return; 253 sqlbox_free(p->db); 254 free(p); 255 } 256 257 /* 258 * Fill in a company from an open statement "stmt". 259 * This starts grabbing results from "pos", which may be NULL to start 260 * from zero. 261 * This follows DB_SCHEMA_company's order for columns. 262 */ 263 static void 264 db_company_fill(struct ort *ctx, struct company *p, const struct sqlbox_parmset *set, size_t *pos) 265 { 266 size_t i = 0; 267 int64_t tmpint; 268 269 if (pos == NULL) 270 pos = &i; 271 memset(p, 0, sizeof(*p)); 272 if (sqlbox_parm_string_alloc 273 (&set->ps[(*pos)++], &p->name, NULL) == -1) 274 exit(EXIT_FAILURE); 275 if (sqlbox_parm_int(&set->ps[(*pos)++], &tmpint) == -1) 276 exit(EXIT_FAILURE); 277 ORT_SET_company_id(p, tmpint); 278 p->has_somenum = set->ps[*pos].type != SQLBOX_PARM_NULL; 279 if (p->has_somenum) { 280 if (sqlbox_parm_int(&set->ps[(*pos)++], &tmpint) == -1) 281 exit(EXIT_FAILURE); 282 ORT_SET_company_somenum(p, tmpint); 283 } else 284 (*pos)++; 285 } 286 287 static void 288 db_company_fill_r(struct ort *ctx, struct company *p, 289 const struct sqlbox_parmset *res, size_t *pos) 290 { 291 size_t i = 0; 292 293 if (pos == NULL) 294 pos = &i; 295 db_company_fill(ctx, p, res, pos); 296 } 297 298 /* 299 * Free resources from "p" and all nested objects. 300 * Does not free the "p" pointer itself. 301 * Has no effect if "p" is NULL. 302 */ 303 static void 304 db_company_unfill(struct company *p) 305 { 306 if (p == NULL) 307 return; 308 free(p->name); 309 } 310 311 static void 312 db_company_unfill_r(struct company *p) 313 { 314 if (p == NULL) 315 return; 316 db_company_unfill(p); 317 } 318 319 void 320 db_company_free(struct company *p) 321 { 322 db_company_unfill_r(p); 323 free(p); 324 } 325 326 void 327 db_company_freeq(struct company_q *q) 328 { 329 struct company *p; 330 331 if (q == NULL) 332 return; 333 while ((p = TAILQ_FIRST(q)) != NULL) { 334 TAILQ_REMOVE(q, p, _entries); 335 db_company_free(p); 336 } 337 free(q); 338 } 339 340 int64_t 341 db_company_insert(struct ort *ctx, const char *v1, company_somenum *v2) 342 { 343 enum sqlbox_code rc; 344 int64_t id = -1; 345 struct sqlbox *db = ctx->db; 346 struct sqlbox_parm parms[2]; 347 348 memset(parms, 0, sizeof(parms)); 349 parms[0].sparm = v1; 350 parms[0].type = SQLBOX_PARM_STRING; 351 if (v2 == NULL) { 352 parms[1].type = SQLBOX_PARM_NULL; 353 } else { 354 parms[1].iparm = ORT_GETV_company_somenum(*v2); 355 parms[1].type = SQLBOX_PARM_INT; 356 } 357 358 rc = sqlbox_exec(db, 0, STMT_company_INSERT, 359 2, parms, SQLBOX_STMT_CONSTRAINT); 360 if (rc == SQLBOX_CODE_ERROR) 361 exit(EXIT_FAILURE); 362 else if (rc != SQLBOX_CODE_OK) 363 return (-1); 364 if (!sqlbox_lastid(db, 0, &id)) 365 exit(EXIT_FAILURE); 366 return id; 367 } 368 369 struct company_q * 370 db_company_list_by_somenum_isnull(struct ort *ctx) 371 { 372 struct company *p; 373 struct company_q *q; 374 const struct sqlbox_parmset *res; 375 struct sqlbox *db = ctx->db; 376 377 q = malloc(sizeof(struct company_q)); 378 if (q == NULL) { 379 perror(NULL); 380 exit(EXIT_FAILURE); 381 } 382 TAILQ_INIT(q); 383 384 if (!sqlbox_prepare_bind_async 385 (db, 0, STMT_company_BY_SEARCH_0, 386 0, NULL, SQLBOX_STMT_MULTI)) 387 exit(EXIT_FAILURE); 388 while ((res = sqlbox_step(db, 0)) != NULL && res->psz) { 389 p = malloc(sizeof(struct company)); 390 if (p == NULL) { 391 perror(NULL); 392 exit(EXIT_FAILURE); 393 } 394 db_company_fill_r(ctx, p, res, NULL); 395 TAILQ_INSERT_TAIL(q, p, _entries); 396 } 397 if (res == NULL) 398 exit(EXIT_FAILURE); 399 if (!sqlbox_finalise(db, 0)) 400 exit(EXIT_FAILURE); 401 return q; 402 } 403 404 void 405 db_company_delete(struct ort *ctx) 406 { 407 enum sqlbox_code c; 408 struct sqlbox *db = ctx->db; 409 410 411 c = sqlbox_exec 412 (db, 0, STMT_company_DELETE_0, 0, NULL, 0); 413 if (c != SQLBOX_CODE_OK) 414 exit(EXIT_FAILURE); 415 } 416 417 /* 418 * Fill in a user from an open statement "stmt". 419 * This starts grabbing results from "pos", which may be NULL to start 420 * from zero. 421 * This follows DB_SCHEMA_user's order for columns. 422 */ 423 static void 424 db_user_fill(struct ort *ctx, struct user *p, const struct sqlbox_parmset *set, size_t *pos) 425 { 426 size_t i = 0; 427 int64_t tmpint; 428 429 if (pos == NULL) 430 pos = &i; 431 memset(p, 0, sizeof(*p)); 432 if (sqlbox_parm_int(&set->ps[(*pos)++], &tmpint) == -1) 433 exit(EXIT_FAILURE); 434 ORT_SET_user_cid(p, tmpint); 435 if (sqlbox_parm_int(&set->ps[(*pos)++], &tmpint) == -1) 436 exit(EXIT_FAILURE); 437 p->sex = (enum sex)tmpint; 438 if (sqlbox_parm_string_alloc 439 (&set->ps[(*pos)++], &p->hash, NULL) == -1) 440 exit(EXIT_FAILURE); 441 if (sqlbox_parm_string_alloc 442 (&set->ps[(*pos)++], &p->email, NULL) == -1) 443 exit(EXIT_FAILURE); 444 p->has_image = set->ps[*pos].type != SQLBOX_PARM_NULL; 445 if (p->has_image) { 446 if (sqlbox_parm_blob_alloc(&set->ps[(*pos)++], 447 &p->image, &p->image_sz) == -1) 448 exit(EXIT_FAILURE); 449 } else 450 (*pos)++; 451 if (sqlbox_parm_string_alloc 452 (&set->ps[(*pos)++], &p->name, NULL) == -1) 453 exit(EXIT_FAILURE); 454 if (sqlbox_parm_int(&set->ps[(*pos)++], &tmpint) == -1) 455 exit(EXIT_FAILURE); 456 ORT_SET_user_uid(p, tmpint); 457 } 458 459 static void 460 db_user_fill_r(struct ort *ctx, struct user *p, 461 const struct sqlbox_parmset *res, size_t *pos) 462 { 463 size_t i = 0; 464 465 if (pos == NULL) 466 pos = &i; 467 db_user_fill(ctx, p, res, pos); 468 db_company_fill_r(ctx, &p->company, res, pos); 469 } 470 471 /* 472 * Free resources from "p" and all nested objects. 473 * Does not free the "p" pointer itself. 474 * Has no effect if "p" is NULL. 475 */ 476 static void 477 db_user_unfill(struct user *p) 478 { 479 if (p == NULL) 480 return; 481 free(p->hash); 482 free(p->email); 483 free(p->image); 484 free(p->name); 485 } 486 487 static void 488 db_user_unfill_r(struct user *p) 489 { 490 if (p == NULL) 491 return; 492 db_user_unfill(p); 493 db_company_unfill_r(&p->company); 494 } 495 496 void 497 db_user_free(struct user *p) 498 { 499 db_user_unfill_r(p); 500 free(p); 501 } 502 503 int64_t 504 db_user_insert(struct ort *ctx, company_id v1, enum sex v2, const char *v3, 505 const char *v4, 506 size_t v5_sz, const void **v5, 507 const char *v6) 508 { 509 enum sqlbox_code rc; 510 int64_t id = -1; 511 struct sqlbox *db = ctx->db; 512 struct sqlbox_parm parms[6]; 513 char hash1[64]; 514 515 crypt_newhash(v3, "blowfish,a", hash1, sizeof(hash1)); 516 517 memset(parms, 0, sizeof(parms)); 518 parms[0].iparm = ORT_GETV_user_cid(v1); 519 parms[0].type = SQLBOX_PARM_INT; 520 parms[1].iparm = v2; 521 parms[1].type = SQLBOX_PARM_INT; 522 parms[2].sparm = hash1; 523 parms[2].type = SQLBOX_PARM_STRING; 524 parms[3].sparm = v4; 525 parms[3].type = SQLBOX_PARM_STRING; 526 if (v5 == NULL) { 527 parms[4].type = SQLBOX_PARM_NULL; 528 } else { 529 parms[4].bparm = *v5; 530 parms[4].type = SQLBOX_PARM_BLOB; 531 parms[4].sz = v5_sz; 532 } 533 parms[5].sparm = v6; 534 parms[5].type = SQLBOX_PARM_STRING; 535 536 rc = sqlbox_exec(db, 0, STMT_user_INSERT, 537 6, parms, SQLBOX_STMT_CONSTRAINT); 538 if (rc == SQLBOX_CODE_ERROR) 539 exit(EXIT_FAILURE); 540 else if (rc != SQLBOX_CODE_OK) 541 return (-1); 542 if (!sqlbox_lastid(db, 0, &id)) 543 exit(EXIT_FAILURE); 544 return id; 545 } 546 547 void 548 db_user_iterate_by_name_eq(struct ort *ctx, user_cb cb, void *arg, const char *v1) 549 { 550 struct user p; 551 const struct sqlbox_parmset *res; 552 struct sqlbox *db = ctx->db; 553 struct sqlbox_parm parms[1]; 554 555 memset(parms, 0, sizeof(parms)); 556 parms[0].sparm = v1; 557 parms[0].type = SQLBOX_PARM_STRING; 558 559 if (!sqlbox_prepare_bind_async 560 (db, 0, STMT_user_BY_SEARCH_0, 561 1, parms, SQLBOX_STMT_MULTI)) 562 exit(EXIT_FAILURE); 563 while ((res = sqlbox_step(db, 0)) != NULL && res->psz) { 564 db_user_fill_r(ctx, &p, res, NULL); 565 (*cb)(&p, arg); 566 db_user_unfill_r(&p); 567 } 568 if (res == NULL) 569 exit(EXIT_FAILURE); 570 if (!sqlbox_finalise(db, 0)) 571 exit(EXIT_FAILURE); 572 } 573 574 struct user * 575 db_user_get_creds(struct ort *ctx, const char *v1, const char *v2) 576 { 577 struct user *p = NULL; 578 const struct sqlbox_parmset *res; 579 struct sqlbox *db = ctx->db; 580 struct sqlbox_parm parms[1]; 581 582 memset(parms, 0, sizeof(parms)); 583 parms[0].sparm = v1; 584 parms[0].type = SQLBOX_PARM_STRING; 585 586 if (!sqlbox_prepare_bind_async 587 (db, 0, STMT_user_BY_SEARCH_1, 1, parms, 0)) 588 exit(EXIT_FAILURE); 589 if ((res = sqlbox_step(db, 0)) != NULL && res->psz) { 590 p = malloc(sizeof(struct user)); 591 if (p == NULL) { 592 perror(NULL); 593 exit(EXIT_FAILURE); 594 } 595 db_user_fill_r(ctx, p, res, NULL); 596 if (v2 == NULL || crypt_checkpass(v2, p->hash) == -1) { 597 db_user_free(p); 598 p = NULL; 599 } 600 } 601 if (res == NULL) 602 exit(EXIT_FAILURE); 603 if (!sqlbox_finalise(db, 0)) 604 exit(EXIT_FAILURE); 605 return p; 606 } 607 608 struct user * 609 db_user_get_by_uid_eq(struct ort *ctx, user_uid v1) 610 { 611 struct user *p = NULL; 612 const struct sqlbox_parmset *res; 613 struct sqlbox *db = ctx->db; 614 struct sqlbox_parm parms[1]; 615 616 memset(parms, 0, sizeof(parms)); 617 parms[0].iparm = ORT_GETV_user_uid(v1); 618 parms[0].type = SQLBOX_PARM_INT; 619 620 if (!sqlbox_prepare_bind_async 621 (db, 0, STMT_user_BY_SEARCH_2, 1, parms, 0)) 622 exit(EXIT_FAILURE); 623 if ((res = sqlbox_step(db, 0)) != NULL && res->psz) { 624 p = malloc(sizeof(struct user)); 625 if (p == NULL) { 626 perror(NULL); 627 exit(EXIT_FAILURE); 628 } 629 db_user_fill_r(ctx, p, res, NULL); 630 } 631 if (res == NULL) 632 exit(EXIT_FAILURE); 633 if (!sqlbox_finalise(db, 0)) 634 exit(EXIT_FAILURE); 635 return p; 636 } 637 638 int 639 db_user_update_hash_set_by_uid_eq(struct ort *ctx, const char *v1, user_uid v2) 640 { 641 enum sqlbox_code c; 642 struct sqlbox *db = ctx->db; 643 struct sqlbox_parm parms[2]; 644 char hash1[64]; 645 646 crypt_newhash(v1, "blowfish,a", hash1, sizeof(hash1)); 647 648 memset(parms, 0, sizeof(parms)); 649 parms[0].sparm = hash1; 650 parms[0].type = SQLBOX_PARM_STRING; 651 parms[1].iparm = ORT_GETV_user_uid(v2); 652 parms[1].type = SQLBOX_PARM_INT; 653 654 c = sqlbox_exec 655 (db, 0, STMT_user_UPDATE_0, 656 2, parms, SQLBOX_STMT_CONSTRAINT); 657 if (c == SQLBOX_CODE_ERROR) 658 exit(EXIT_FAILURE); 659 return (c == SQLBOX_CODE_OK) ? 1 : 0; 660 } 661 662 int 663 db_user_update_email_set_by_uid_eq(struct ort *ctx, const char *v1, user_uid v2) 664 { 665 enum sqlbox_code c; 666 struct sqlbox *db = ctx->db; 667 struct sqlbox_parm parms[2]; 668 669 memset(parms, 0, sizeof(parms)); 670 parms[0].sparm = v1; 671 parms[0].type = SQLBOX_PARM_STRING; 672 parms[1].iparm = ORT_GETV_user_uid(v2); 673 parms[1].type = SQLBOX_PARM_INT; 674 675 c = sqlbox_exec 676 (db, 0, STMT_user_UPDATE_1, 677 2, parms, SQLBOX_STMT_CONSTRAINT); 678 if (c == SQLBOX_CODE_ERROR) 679 exit(EXIT_FAILURE); 680 return (c == SQLBOX_CODE_OK) ? 1 : 0; 681 } 682 683 void 684 db_user_delete(struct ort *ctx) 685 { 686 enum sqlbox_code c; 687 struct sqlbox *db = ctx->db; 688 689 690 c = sqlbox_exec 691 (db, 0, STMT_user_DELETE_0, 0, NULL, 0); 692 if (c != SQLBOX_CODE_OK) 693 exit(EXIT_FAILURE); 694 } 695 696 /* 697 * Fill in a session from an open statement "stmt". 698 * This starts grabbing results from "pos", which may be NULL to start 699 * from zero. 700 * This follows DB_SCHEMA_session's order for columns. 701 */ 702 static void 703 db_session_fill(struct ort *ctx, struct session *p, const struct sqlbox_parmset *set, size_t *pos) 704 { 705 size_t i = 0; 706 int64_t tmpint; 707 708 if (pos == NULL) 709 pos = &i; 710 memset(p, 0, sizeof(*p)); 711 if (sqlbox_parm_int(&set->ps[(*pos)++], &tmpint) == -1) 712 exit(EXIT_FAILURE); 713 ORT_SET_session_userid(p, tmpint); 714 if (sqlbox_parm_int(&set->ps[(*pos)++], &tmpint) == -1) 715 exit(EXIT_FAILURE); 716 ORT_SET_session_token(p, tmpint); 717 if (sqlbox_parm_int(&set->ps[(*pos)++], &tmpint) == -1) 718 exit(EXIT_FAILURE); 719 ORT_SET_session_mtime(p, (time_t)tmpint); 720 if (sqlbox_parm_int(&set->ps[(*pos)++], &tmpint) == -1) 721 exit(EXIT_FAILURE); 722 ORT_SET_session_id(p, tmpint); 723 } 724 725 static void 726 db_session_fill_r(struct ort *ctx, struct session *p, 727 const struct sqlbox_parmset *res, size_t *pos) 728 { 729 size_t i = 0; 730 731 if (pos == NULL) 732 pos = &i; 733 db_session_fill(ctx, p, res, pos); 734 db_user_fill_r(ctx, &p->user, res, pos); 735 } 736 737 /* 738 * Free resources from "p" and all nested objects. 739 * Does not free the "p" pointer itself. 740 * Has no effect if "p" is NULL. 741 */ 742 static void 743 db_session_unfill(struct session *p) 744 { 745 if (p == NULL) 746 return; 747 } 748 749 static void 750 db_session_unfill_r(struct session *p) 751 { 752 if (p == NULL) 753 return; 754 db_session_unfill(p); 755 db_user_unfill_r(&p->user); 756 } 757 758 void 759 db_session_free(struct session *p) 760 { 761 db_session_unfill_r(p); 762 free(p); 763 } 764 765 int64_t 766 db_session_insert(struct ort *ctx, user_uid v1, session_token v2, session_mtime v3) 767 { 768 enum sqlbox_code rc; 769 int64_t id = -1; 770 struct sqlbox *db = ctx->db; 771 struct sqlbox_parm parms[3]; 772 773 memset(parms, 0, sizeof(parms)); 774 parms[0].iparm = ORT_GETV_session_userid(v1); 775 parms[0].type = SQLBOX_PARM_INT; 776 parms[1].iparm = ORT_GETV_session_token(v2); 777 parms[1].type = SQLBOX_PARM_INT; 778 parms[2].iparm = (time_t)ORT_GETV_session_mtime(v3); 779 parms[2].type = SQLBOX_PARM_INT; 780 781 rc = sqlbox_exec(db, 0, STMT_session_INSERT, 782 3, parms, SQLBOX_STMT_CONSTRAINT); 783 if (rc == SQLBOX_CODE_ERROR) 784 exit(EXIT_FAILURE); 785 else if (rc != SQLBOX_CODE_OK) 786 return (-1); 787 if (!sqlbox_lastid(db, 0, &id)) 788 exit(EXIT_FAILURE); 789 return id; 790 } 791 792 void 793 db_session_iterate_foo(struct ort *ctx, session_cb cb, void *arg, const char *v1, 794 session_mtime v2) 795 { 796 struct session p; 797 const struct sqlbox_parmset *res; 798 struct sqlbox *db = ctx->db; 799 struct sqlbox_parm parms[2]; 800 801 memset(parms, 0, sizeof(parms)); 802 parms[0].sparm = v1; 803 parms[0].type = SQLBOX_PARM_STRING; 804 parms[1].iparm = (time_t)ORT_GETV_session_mtime(v2); 805 parms[1].type = SQLBOX_PARM_INT; 806 807 if (!sqlbox_prepare_bind_async 808 (db, 0, STMT_session_BY_SEARCH_0, 809 2, parms, SQLBOX_STMT_MULTI)) 810 exit(EXIT_FAILURE); 811 while ((res = sqlbox_step(db, 0)) != NULL && res->psz) { 812 db_session_fill_r(ctx, &p, res, NULL); 813 (*cb)(&p, arg); 814 db_session_unfill_r(&p); 815 } 816 if (res == NULL) 817 exit(EXIT_FAILURE); 818 if (!sqlbox_finalise(db, 0)) 819 exit(EXIT_FAILURE); 820 } 821 822 void 823 db_session_delete_by_id_eq(struct ort *ctx, session_id v1) 824 { 825 enum sqlbox_code c; 826 struct sqlbox *db = ctx->db; 827 struct sqlbox_parm parms[1]; 828 829 memset(parms, 0, sizeof(parms)); 830 parms[0].iparm = ORT_GETV_session_id(v1); 831 parms[0].type = SQLBOX_PARM_INT; 832 833 c = sqlbox_exec 834 (db, 0, STMT_session_DELETE_0, 1, parms, 0); 835 if (c != SQLBOX_CODE_OK) 836 exit(EXIT_FAILURE); 837 } 838