/* * $Id: t-bdb-secondary-0.c,v 1.1 2005/07/29 22:05:44 ca Exp $ */ /* ** Just an example program how to use a secondary index; ** taken from the BDB docs. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: t-bdb-secondary-0.c,v 1.1 2005/07/29 22:05:44 ca Exp $") #include #include "sm/bdb.h" struct student_record { char student_id[4]; char last_name[15]; char first_name[15]; }; typedef struct student_record student_record_T; void handle_error(int ret) { fprintf(stderr, "fail: %d\n", ret); exit(ret); } /* * getname -- extracts a secondary key (the last name) from a primary key/data * pair */ static int getname(DB * dbp, const DBT * pkey, const DBT * pdata, DBT * skey) { /* * Since the secondary key is a simple structure member of the record, * we don't have to do anything fancy to return it. If we have * composite keys that need to be constructed from the record, rather * than simply pointing into it, then the user's function might need to * allocate space and copy data. In this case, the DB_DBT_APPMALLOC * flag should be set in the secondary key DBT. */ memset(skey, 0, sizeof(DBT)); skey->data = ((struct student_record *) pdata->data)->last_name; skey->size = sizeof((struct student_record *) pdata->data)->last_name; return (0); } static DB *dbp, *sdbp; void second(void) { int ret; #define dbenv NULL /* Open/create primary */ if ((ret = db_create(&dbp, dbenv, 0)) != 0) handle_error(ret); if ((ret = dbp->open(dbp, NULL, "students.db", NULL, DB_BTREE, DB_CREATE, 0600)) != 0) handle_error(ret); /* * Open/create secondary. Note that it supports duplicate data * items, * since last names might not be unique. */ if ((ret = db_create(&sdbp, dbenv, 0)) != 0) handle_error(ret); if ((ret = sdbp->set_flags(sdbp, DB_DUP | DB_DUPSORT)) != 0) handle_error(ret); if ((ret = sdbp->open(sdbp, NULL, "lastname.db", NULL, DB_BTREE, DB_CREATE, 0600)) != 0) handle_error(ret); /* Associate the secondary with the primary. */ if ((ret = dbp->associate(dbp, NULL, sdbp, getname, 0)) != 0) handle_error(ret); } #define new_student(st, id, last, first) \ do { \ strlcpy((st).student_id, (id), sizeof((st).student_id)); \ strlcpy((st).last_name, (last), sizeof((st).last_name)); \ strlcpy((st).first_name, (first), sizeof((st).first_name)); \ } while (0) static void closedb(void) { int ret; if ((ret = dbp->close(dbp, 0)) != 0) handle_error(ret); } static void putst(student_record_T * s0) { int ret; DBT data, key; #define txn NULL memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); key.data = s0->student_id; key.size = sizeof(s0->student_id); data.data = s0; data.size = sizeof(*s0); if ((ret = dbp->put(dbp, txn, &key, &data, 0)) != 0) handle_error(ret); } static void bdb0(void) { int ret; DBT data, key; DBC *dbcp; student_record_T s0, s1, s2; new_student(s0, "id0", "last0", "first0"); new_student(s1, "id1", "last1", "first1"); new_student(s2, "id2", "last2", "first2"); second(); putst(&s0); putst(&s2); putst(&s1); /* Acquire a cursor for the database. */ if ((ret = dbp->cursor(sdbp, NULL, &dbcp, 0)) != 0) { sdbp->err(sdbp, ret, "DB->cursor"); goto err; } /* Initialize the key/data return pair. */ memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); #if 0 while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) printf("%.*s : %.*s\n", (int)key.size, (char *)key.data, (int)data.size, (char *)data.data); if (ret != DB_NOTFOUND) { sdbp->err(sdbp, ret, "DBcursor->get"); goto err; } #else if ((ret = dbcp->c_get(dbcp, &key, &data, DB_LAST)) == 0) printf("%.*s : %.*s\n", (int)key.size, (char *)key.data, (int)data.size, (char *)data.data); if ((ret = dbcp->c_del(dbcp, 0)) != 0) sdbp->err(sdbp, ret, "DBcursor->c_del"); if ((ret = dbcp->c_get(dbcp, &key, &data, DB_LAST)) == 0) printf("%.*s : %.*s\n", (int)key.size, (char *)key.data, (int)data.size, (char *)data.data); #endif err: if ((ret = dbcp->c_close(dbcp)) != 0) { sdbp->err(sdbp, ret, "DBcursor->close"); } closedb(); } static void usage(const char *prg) { exit(-1); } int main(int argc, char **argv) { int ch; while ((ch = getopt(argc, argv, "V")) != -1) { switch (ch) { default: usage(argv[0]); return -1; } } bdb0(); return (0); }