1 /*
    2  * WARNING: automatically generated by ort 0.12.10.
    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 
  268 	if (pos == NULL)
  269 		pos = &i;
  270 	memset(p, 0, sizeof(*p));
  271 	if (sqlbox_parm_string_alloc
  272 	    (&set->ps[(*pos)++], &p->name, NULL) == -1)
  273 		exit(EXIT_FAILURE);
  274 	if (sqlbox_parm_int(&set->ps[(*pos)++], &p->id) == -1)
  275 		exit(EXIT_FAILURE);
  276 	p->has_somenum = set->ps[*pos].type != SQLBOX_PARM_NULL;
  277 	if (p->has_somenum) {
  278 		if (sqlbox_parm_int(&set->ps[(*pos)++], &p->somenum) == -1)
  279 			exit(EXIT_FAILURE);
  280 	} else
  281 		(*pos)++;
  282 }
  283 
  284 static void
  285 db_company_fill_r(struct ort *ctx, struct company *p,
  286 	const struct sqlbox_parmset *res, size_t *pos)
  287 {
  288 	size_t i = 0;
  289 
  290 	if (pos == NULL)
  291 		pos = &i;
  292 	db_company_fill(ctx, p, res, pos);
  293 }
  294 
  295 /*
  296  * Free resources from "p" and all nested objects.
  297  * Does not free the "p" pointer itself.
  298  * Has no effect if "p" is NULL.
  299  */
  300 static void
  301 db_company_unfill(struct company *p)
  302 {
  303 	if (p == NULL)
  304 		return;
  305 	free(p->name);
  306 }
  307 
  308 static void
  309 db_company_unfill_r(struct company *p)
  310 {
  311 	if (p == NULL)
  312 		return;
  313 	db_company_unfill(p);
  314 }
  315 
  316 void
  317 db_company_free(struct company *p)
  318 {
  319 	db_company_unfill_r(p);
  320 	free(p);
  321 }
  322 
  323 void
  324 db_company_freeq(struct company_q *q)
  325 {
  326 	struct company *p;
  327 
  328 	if (q == NULL)
  329 		return;
  330 	while ((p = TAILQ_FIRST(q)) != NULL) {
  331 		TAILQ_REMOVE(q, p, _entries);
  332 		db_company_free(p);
  333 	}
  334 	free(q);
  335 }
  336 
  337 int64_t
  338 db_company_insert(struct ort *ctx, const char *v1, int64_t *v2)
  339 {
  340 	int rc;
  341 	int64_t id = -1;
  342 	struct sqlbox *db = ctx->db;
  343 	struct sqlbox_parm parms[2];
  344 
  345 	memset(parms, 0, sizeof(parms));
  346 	parms[0].sparm = v1;
  347 	parms[0].type = SQLBOX_PARM_STRING;
  348 	if (v2 == NULL) {
  349 		parms[1].type = SQLBOX_PARM_NULL;
  350 	} else {
  351 		parms[1].iparm = *v2;
  352 		parms[1].type = SQLBOX_PARM_INT;
  353 	}
  354 
  355 	rc = sqlbox_exec(db, 0, STMT_company_INSERT, 
  356 	     2, parms, SQLBOX_STMT_CONSTRAINT);
  357 	if (rc == SQLBOX_CODE_ERROR)
  358 		exit(EXIT_FAILURE);
  359 	else if (rc != SQLBOX_CODE_OK)
  360 		return (-1);
  361 	if (!sqlbox_lastid(db, 0, &id))
  362 		exit(EXIT_FAILURE);
  363 	return id;
  364 }
  365 
  366 struct company_q *
  367 db_company_list_by_somenum_isnull(struct ort *ctx)
  368 {
  369 	struct company *p;
  370 	struct company_q *q;
  371 	const struct sqlbox_parmset *res;
  372 	struct sqlbox *db = ctx->db;
  373 
  374 	q = malloc(sizeof(struct company_q));
  375 	if (q == NULL) {
  376 		perror(NULL);
  377 		exit(EXIT_FAILURE);
  378 	}
  379 	TAILQ_INIT(q);
  380 
  381 	if (!sqlbox_prepare_bind_async
  382 	    (db, 0, STMT_company_BY_SEARCH_0,
  383 	     0, NULL, SQLBOX_STMT_MULTI))
  384 		exit(EXIT_FAILURE);
  385 	while ((res = sqlbox_step(db, 0)) != NULL && res->psz) {
  386 		p = malloc(sizeof(struct company));
  387 		if (p == NULL) {
  388 			perror(NULL);
  389 			exit(EXIT_FAILURE);
  390 		}
  391 		db_company_fill_r(ctx, p, res, NULL);
  392 		TAILQ_INSERT_TAIL(q, p, _entries);
  393 	}
  394 	if (res == NULL)
  395 		exit(EXIT_FAILURE);
  396 	if (!sqlbox_finalise(db, 0))
  397 		exit(EXIT_FAILURE);
  398 	return q;
  399 }
  400 
  401 void
  402 db_company_delete(struct ort *ctx)
  403 {
  404 	enum sqlbox_code c;
  405 	struct sqlbox *db = ctx->db;
  406 
  407 
  408 	c = sqlbox_exec
  409 		(db, 0, STMT_company_DELETE_0, 0, NULL, 0);
  410 	if (c != SQLBOX_CODE_OK)
  411 		exit(EXIT_FAILURE);
  412 }
  413 
  414 /*
  415  * Fill in a user from an open statement "stmt".
  416  * This starts grabbing results from "pos", which may be NULL to start 
  417  * from zero.
  418  * This follows DB_SCHEMA_user's order for columns.
  419  */
  420 static void
  421 db_user_fill(struct ort *ctx, struct user *p, const struct sqlbox_parmset *set, size_t *pos)
  422 {
  423 	size_t i = 0;
  424 	int64_t tmpint;
  425 
  426 	if (pos == NULL)
  427 		pos = &i;
  428 	memset(p, 0, sizeof(*p));
  429 	if (sqlbox_parm_int(&set->ps[(*pos)++], &p->cid) == -1)
  430 		exit(EXIT_FAILURE);
  431 	if (sqlbox_parm_int(&set->ps[(*pos)++], &tmpint) == -1)
  432 		exit(EXIT_FAILURE);
  433 	p->sex = tmpint;
  434 	if (sqlbox_parm_string_alloc
  435 	    (&set->ps[(*pos)++], &p->hash, NULL) == -1)
  436 		exit(EXIT_FAILURE);
  437 	if (sqlbox_parm_string_alloc
  438 	    (&set->ps[(*pos)++], &p->email, NULL) == -1)
  439 		exit(EXIT_FAILURE);
  440 	p->has_image = set->ps[*pos].type != SQLBOX_PARM_NULL;
  441 	if (p->has_image) {
  442 		if (sqlbox_parm_blob_alloc(&set->ps[(*pos)++],
  443 		    &p->image, &p->image_sz) == -1)
  444 			exit(EXIT_FAILURE);
  445 	} else
  446 		(*pos)++;
  447 	if (sqlbox_parm_string_alloc
  448 	    (&set->ps[(*pos)++], &p->name, NULL) == -1)
  449 		exit(EXIT_FAILURE);
  450 	if (sqlbox_parm_int(&set->ps[(*pos)++], &p->uid) == -1)
  451 		exit(EXIT_FAILURE);
  452 }
  453 
  454 static void
  455 db_user_fill_r(struct ort *ctx, struct user *p,
  456 	const struct sqlbox_parmset *res, size_t *pos)
  457 {
  458 	size_t i = 0;
  459 
  460 	if (pos == NULL)
  461 		pos = &i;
  462 	db_user_fill(ctx, p, res, pos);
  463 	db_company_fill_r(ctx, &p->company, res, pos);
  464 }
  465 
  466 /*
  467  * Free resources from "p" and all nested objects.
  468  * Does not free the "p" pointer itself.
  469  * Has no effect if "p" is NULL.
  470  */
  471 static void
  472 db_user_unfill(struct user *p)
  473 {
  474 	if (p == NULL)
  475 		return;
  476 	free(p->hash);
  477 	free(p->email);
  478 	free(p->image);
  479 	free(p->name);
  480 }
  481 
  482 static void
  483 db_user_unfill_r(struct user *p)
  484 {
  485 	if (p == NULL)
  486 		return;
  487 	db_user_unfill(p);
  488 	db_company_unfill_r(&p->company);
  489 }
  490 
  491 void
  492 db_user_free(struct user *p)
  493 {
  494 	db_user_unfill_r(p);
  495 	free(p);
  496 }
  497 
  498 int64_t
  499 db_user_insert(struct ort *ctx, int64_t v1, enum sex v2, const char *v3,
  500      const char *v4,
  501      size_t v5_sz, const void **v5,
  502      const char *v6)
  503 {
  504 	int rc;
  505 	int64_t id = -1;
  506 	struct sqlbox *db = ctx->db;
  507 	struct sqlbox_parm parms[6];
  508 	char hash1[64];
  509 
  510 	crypt_newhash(v3, "blowfish,a", hash1, sizeof(hash1));
  511 
  512 	memset(parms, 0, sizeof(parms));
  513 	parms[0].iparm = v1;
  514 	parms[0].type = SQLBOX_PARM_INT;
  515 	parms[1].iparm = v2;
  516 	parms[1].type = SQLBOX_PARM_INT;
  517 	parms[2].sparm = hash1;
  518 	parms[2].type = SQLBOX_PARM_STRING;
  519 	parms[3].sparm = v4;
  520 	parms[3].type = SQLBOX_PARM_STRING;
  521 	if (v5 == NULL) {
  522 		parms[4].type = SQLBOX_PARM_NULL;
  523 	} else {
  524 		parms[4].bparm = *v5;
  525 		parms[4].type = SQLBOX_PARM_BLOB;
  526 		parms[4].sz = v5_sz;
  527 	}
  528 	parms[5].sparm = v6;
  529 	parms[5].type = SQLBOX_PARM_STRING;
  530 
  531 	rc = sqlbox_exec(db, 0, STMT_user_INSERT, 
  532 	     6, parms, SQLBOX_STMT_CONSTRAINT);
  533 	if (rc == SQLBOX_CODE_ERROR)
  534 		exit(EXIT_FAILURE);
  535 	else if (rc != SQLBOX_CODE_OK)
  536 		return (-1);
  537 	if (!sqlbox_lastid(db, 0, &id))
  538 		exit(EXIT_FAILURE);
  539 	return id;
  540 }
  541 
  542 void
  543 db_user_iterate_by_name_eq(struct ort *ctx, user_cb cb, void *arg, const char *v1)
  544 {
  545 	struct user p;
  546 	const struct sqlbox_parmset *res;
  547 	struct sqlbox *db = ctx->db;
  548 	struct sqlbox_parm parms[1];
  549 
  550 	memset(parms, 0, sizeof(parms));
  551 	parms[0].sparm = v1;
  552 	parms[0].type = SQLBOX_PARM_STRING;
  553 
  554 	if (!sqlbox_prepare_bind_async
  555 	    (db, 0, STMT_user_BY_SEARCH_0,
  556 	     1, parms, SQLBOX_STMT_MULTI))
  557 		exit(EXIT_FAILURE);
  558 	while ((res = sqlbox_step(db, 0)) != NULL && res->psz) {
  559 		db_user_fill_r(ctx, &p, res, NULL);
  560 		(*cb)(&p, arg);
  561 		db_user_unfill_r(&p);
  562 	}
  563 	if (res == NULL)
  564 		exit(EXIT_FAILURE);
  565 	if (!sqlbox_finalise(db, 0))
  566 		exit(EXIT_FAILURE);
  567 }
  568 
  569 struct user *
  570 db_user_get_creds(struct ort *ctx, const char *v1, const char *v2)
  571 {
  572 	struct user *p = NULL;
  573 	const struct sqlbox_parmset *res;
  574 	struct sqlbox *db = ctx->db;
  575 	struct sqlbox_parm parms[1];
  576 
  577 	memset(parms, 0, sizeof(parms));
  578 	parms[0].sparm = v1;
  579 	parms[0].type = SQLBOX_PARM_STRING;
  580 
  581 	if (!sqlbox_prepare_bind_async
  582 	    (db, 0, STMT_user_BY_SEARCH_1, 1, parms, 0))
  583 		exit(EXIT_FAILURE);
  584 	if ((res = sqlbox_step(db, 0)) != NULL && res->psz) {
  585 		p = malloc(sizeof(struct user));
  586 		if (p == NULL) {
  587 			perror(NULL);
  588 			exit(EXIT_FAILURE);
  589 		}
  590 		db_user_fill_r(ctx, p, res, NULL);
  591 		if (v2 == NULL || crypt_checkpass(v2, p->hash) == -1) {
  592 			db_user_free(p);
  593 			p = NULL;
  594 		}
  595 	}
  596 	if (res == NULL)
  597 		exit(EXIT_FAILURE);
  598 	if (!sqlbox_finalise(db, 0))
  599 		exit(EXIT_FAILURE);
  600 	return p;
  601 }
  602 
  603 struct user *
  604 db_user_get_by_uid_eq(struct ort *ctx, int64_t v1)
  605 {
  606 	struct user *p = NULL;
  607 	const struct sqlbox_parmset *res;
  608 	struct sqlbox *db = ctx->db;
  609 	struct sqlbox_parm parms[1];
  610 
  611 	memset(parms, 0, sizeof(parms));
  612 	parms[0].iparm = v1;
  613 	parms[0].type = SQLBOX_PARM_INT;
  614 
  615 	if (!sqlbox_prepare_bind_async
  616 	    (db, 0, STMT_user_BY_SEARCH_2, 1, parms, 0))
  617 		exit(EXIT_FAILURE);
  618 	if ((res = sqlbox_step(db, 0)) != NULL && res->psz) {
  619 		p = malloc(sizeof(struct user));
  620 		if (p == NULL) {
  621 			perror(NULL);
  622 			exit(EXIT_FAILURE);
  623 		}
  624 		db_user_fill_r(ctx, p, res, NULL);
  625 	}
  626 	if (res == NULL)
  627 		exit(EXIT_FAILURE);
  628 	if (!sqlbox_finalise(db, 0))
  629 		exit(EXIT_FAILURE);
  630 	return p;
  631 }
  632 
  633 int
  634 db_user_update_hash_set_by_uid_eq(struct ort *ctx, const char *v1, int64_t v2)
  635 {
  636 	enum sqlbox_code c;
  637 	struct sqlbox *db = ctx->db;
  638 	struct sqlbox_parm parms[2];
  639 	char hash1[64];
  640 
  641 	crypt_newhash(v1, "blowfish,a", hash1, sizeof(hash1));
  642 
  643 	memset(parms, 0, sizeof(parms));
  644 	parms[0].sparm = hash1;
  645 	parms[0].type = SQLBOX_PARM_STRING;
  646 	parms[1].iparm = v2;
  647 	parms[1].type = SQLBOX_PARM_INT;
  648 
  649 	c = sqlbox_exec
  650 		(db, 0, STMT_user_UPDATE_0,
  651 		 2, parms, SQLBOX_STMT_CONSTRAINT);
  652 	if (c == SQLBOX_CODE_ERROR)
  653 		exit(EXIT_FAILURE);
  654 	return (c == SQLBOX_CODE_OK) ? 1 : 0;
  655 }
  656 
  657 int
  658 db_user_update_email_set_by_uid_eq(struct ort *ctx, const char *v1, int64_t v2)
  659 {
  660 	enum sqlbox_code c;
  661 	struct sqlbox *db = ctx->db;
  662 	struct sqlbox_parm parms[2];
  663 
  664 	memset(parms, 0, sizeof(parms));
  665 	parms[0].sparm = v1;
  666 	parms[0].type = SQLBOX_PARM_STRING;
  667 	parms[1].iparm = v2;
  668 	parms[1].type = SQLBOX_PARM_INT;
  669 
  670 	c = sqlbox_exec
  671 		(db, 0, STMT_user_UPDATE_1,
  672 		 2, parms, SQLBOX_STMT_CONSTRAINT);
  673 	if (c == SQLBOX_CODE_ERROR)
  674 		exit(EXIT_FAILURE);
  675 	return (c == SQLBOX_CODE_OK) ? 1 : 0;
  676 }
  677 
  678 void
  679 db_user_delete(struct ort *ctx)
  680 {
  681 	enum sqlbox_code c;
  682 	struct sqlbox *db = ctx->db;
  683 
  684 
  685 	c = sqlbox_exec
  686 		(db, 0, STMT_user_DELETE_0, 0, NULL, 0);
  687 	if (c != SQLBOX_CODE_OK)
  688 		exit(EXIT_FAILURE);
  689 }
  690 
  691 /*
  692  * Fill in a session from an open statement "stmt".
  693  * This starts grabbing results from "pos", which may be NULL to start 
  694  * from zero.
  695  * This follows DB_SCHEMA_session's order for columns.
  696  */
  697 static void
  698 db_session_fill(struct ort *ctx, struct session *p, const struct sqlbox_parmset *set, size_t *pos)
  699 {
  700 	size_t i = 0;
  701 	int64_t tmpint;
  702 
  703 	if (pos == NULL)
  704 		pos = &i;
  705 	memset(p, 0, sizeof(*p));
  706 	if (sqlbox_parm_int(&set->ps[(*pos)++], &p->userid) == -1)
  707 		exit(EXIT_FAILURE);
  708 	if (sqlbox_parm_int(&set->ps[(*pos)++], &p->token) == -1)
  709 		exit(EXIT_FAILURE);
  710 	if (sqlbox_parm_int(&set->ps[(*pos)++], &tmpint) == -1)
  711 		exit(EXIT_FAILURE);
  712 	p->mtime = tmpint;
  713 	if (sqlbox_parm_int(&set->ps[(*pos)++], &p->id) == -1)
  714 		exit(EXIT_FAILURE);
  715 }
  716 
  717 static void
  718 db_session_fill_r(struct ort *ctx, struct session *p,
  719 	const struct sqlbox_parmset *res, size_t *pos)
  720 {
  721 	size_t i = 0;
  722 
  723 	if (pos == NULL)
  724 		pos = &i;
  725 	db_session_fill(ctx, p, res, pos);
  726 	db_user_fill_r(ctx, &p->user, res, pos);
  727 }
  728 
  729 /*
  730  * Free resources from "p" and all nested objects.
  731  * Does not free the "p" pointer itself.
  732  * Has no effect if "p" is NULL.
  733  */
  734 static void
  735 db_session_unfill(struct session *p)
  736 {
  737 	if (p == NULL)
  738 		return;
  739 }
  740 
  741 static void
  742 db_session_unfill_r(struct session *p)
  743 {
  744 	if (p == NULL)
  745 		return;
  746 	db_session_unfill(p);
  747 	db_user_unfill_r(&p->user);
  748 }
  749 
  750 void
  751 db_session_free(struct session *p)
  752 {
  753 	db_session_unfill_r(p);
  754 	free(p);
  755 }
  756 
  757 int64_t
  758 db_session_insert(struct ort *ctx, int64_t v1, int64_t v2, time_t v3)
  759 {
  760 	int rc;
  761 	int64_t id = -1;
  762 	struct sqlbox *db = ctx->db;
  763 	struct sqlbox_parm parms[3];
  764 
  765 	memset(parms, 0, sizeof(parms));
  766 	parms[0].iparm = v1;
  767 	parms[0].type = SQLBOX_PARM_INT;
  768 	parms[1].iparm = v2;
  769 	parms[1].type = SQLBOX_PARM_INT;
  770 	parms[2].iparm = v3;
  771 	parms[2].type = SQLBOX_PARM_INT;
  772 
  773 	rc = sqlbox_exec(db, 0, STMT_session_INSERT, 
  774 	     3, parms, SQLBOX_STMT_CONSTRAINT);
  775 	if (rc == SQLBOX_CODE_ERROR)
  776 		exit(EXIT_FAILURE);
  777 	else if (rc != SQLBOX_CODE_OK)
  778 		return (-1);
  779 	if (!sqlbox_lastid(db, 0, &id))
  780 		exit(EXIT_FAILURE);
  781 	return id;
  782 }
  783 
  784 void
  785 db_session_iterate_foo(struct ort *ctx, session_cb cb, void *arg, const char *v1,
  786      time_t v2)
  787 {
  788 	struct session p;
  789 	const struct sqlbox_parmset *res;
  790 	struct sqlbox *db = ctx->db;
  791 	struct sqlbox_parm parms[2];
  792 
  793 	memset(parms, 0, sizeof(parms));
  794 	parms[0].sparm = v1;
  795 	parms[0].type = SQLBOX_PARM_STRING;
  796 	parms[1].iparm = v2;
  797 	parms[1].type = SQLBOX_PARM_INT;
  798 
  799 	if (!sqlbox_prepare_bind_async
  800 	    (db, 0, STMT_session_BY_SEARCH_0,
  801 	     2, parms, SQLBOX_STMT_MULTI))
  802 		exit(EXIT_FAILURE);
  803 	while ((res = sqlbox_step(db, 0)) != NULL && res->psz) {
  804 		db_session_fill_r(ctx, &p, res, NULL);
  805 		(*cb)(&p, arg);
  806 		db_session_unfill_r(&p);
  807 	}
  808 	if (res == NULL)
  809 		exit(EXIT_FAILURE);
  810 	if (!sqlbox_finalise(db, 0))
  811 		exit(EXIT_FAILURE);
  812 }
  813 
  814 void
  815 db_session_delete_by_id_eq(struct ort *ctx, int64_t v1)
  816 {
  817 	enum sqlbox_code c;
  818 	struct sqlbox *db = ctx->db;
  819 	struct sqlbox_parm parms[1];
  820 
  821 	memset(parms, 0, sizeof(parms));
  822 	parms[0].iparm = v1;
  823 	parms[0].type = SQLBOX_PARM_INT;
  824 
  825 	c = sqlbox_exec
  826 		(db, 0, STMT_session_DELETE_0, 1, parms, 0);
  827 	if (c != SQLBOX_CODE_OK)
  828 		exit(EXIT_FAILURE);
  829 }
  830