1<?xml version="1.0" encoding="UTF-8" standalone="no"?> 2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 6 <title>Implementing Key 7 8 Extractors 9 </title> 10 <link rel="stylesheet" href="gettingStarted.css" type="text/css" /> 11 <meta name="generator" content="DocBook XSL Stylesheets V1.62.4" /> 12 <link rel="home" href="index.html" title="Getting Started with Berkeley DB" /> 13 <link rel="up" href="indexes.html" title="Chapter��5.��Secondary Databases" /> 14 <link rel="previous" href="indexes.html" title="Chapter��5.��Secondary Databases" /> 15 <link rel="next" href="readSecondary.html" title="Reading Secondary Databases" /> 16 </head> 17 <body> 18 <div class="navheader"> 19 <table width="100%" summary="Navigation header"> 20 <tr> 21 <th colspan="3" align="center">Implementing Key 22 23 Extractors 24 </th> 25 </tr> 26 <tr> 27 <td width="20%" align="left"><a accesskey="p" href="indexes.html">Prev</a>��</td> 28 <th width="60%" align="center">Chapter��5.��Secondary Databases</th> 29 <td width="20%" align="right">��<a accesskey="n" href="readSecondary.html">Next</a></td> 30 </tr> 31 </table> 32 <hr /> 33 </div> 34 <div class="sect1" lang="en" xml:lang="en"> 35 <div class="titlepage"> 36 <div> 37 <div> 38 <h2 class="title" style="clear: both"><a id="keyCreator"></a>Implementing Key 39 40 <span>Extractors</span> 41 </h2> 42 </div> 43 </div> 44 <div></div> 45 </div> 46 <p> 47 You must provide every secondary database with a 48 49 <span>callback</span> 50 that creates keys from primary records. You identify this 51 52 <span>callback</span> 53 54 55 <span> 56 when you associate your secondary database to your primary. 57 </span> 58 </p> 59 <p> 60 You can create keys using whatever data you want. Typically you will 61 base your key on some information found in a record's data, but you 62 can also use information found in the primary record's key. How you build 63 your keys is entirely dependent upon the nature of the index that you 64 want to maintain. 65 </p> 66 <p> 67 You implement a key extractor by writing a function that extracts 68 the necessary information from a primary record's key or data. 69 This function must conform to a specific prototype, and it must be 70 provided as a callback to the <tt class="methodname">associate()</tt> 71 method. 72 </p> 73 <p> 74 For example, suppose your primary database records contain data that 75 uses the following structure: 76 </p> 77 <a id="c_index3"></a> 78 <pre class="programlisting">typedef struct vendor { 79 char name[MAXFIELD]; /* Vendor name */ 80 char street[MAXFIELD]; /* Street name and number */ 81 char city[MAXFIELD]; /* City */ 82 char state[3]; /* Two-digit US state code */ 83 char zipcode[6]; /* US zipcode */ 84 char phone_number[13]; /* Vendor phone number */ 85 char sales_rep[MAXFIELD]; /* Name of sales representative */ 86 char sales_rep_phone[MAXFIELD]; /* Sales rep's phone number */ 87} VENDOR; </pre> 88 <p> 89 Further suppose that you want to be able to query your primary database 90 based on the name of a sales representative. Then you would write a 91 function that looks like this: 92 </p> 93 <a id="c_index4"></a> 94 <pre class="programlisting">#include <db.h> 95 96... 97 98int 99get_sales_rep(DB *sdbp, /* secondary db handle */ 100 const DBT *pkey, /* primary db record's key */ 101 const DBT *pdata, /* primary db record's data */ 102 DBT *skey) /* secondary db record's key */ 103{ 104 VENDOR *vendor; 105 106 /* First, extract the structure contained in the primary's data */ 107 vendor = pdata->data; 108 109 /* Now set the secondary key's data to be the representative's name */ 110 memset(skey, 0, sizeof(DBT)); 111 skey->data = vendor->sales_rep; 112 skey->size = strlen(vendor->sales_rep) + 1; 113 114 /* Return 0 to indicate that the record can be created/updated. */ 115 return (0); 116} </pre> 117 <p> 118 In order to use this function, you provide it on the 119 <tt class="methodname">associate()</tt> method after the primary and 120 secondary databases have been created and opened: 121 </p> 122 <a id="c_index5"></a> 123 <pre class="programlisting">dbp->associate(dbp, /* Primary database */ 124 NULL, /* TXN id */ 125 sdbp, /* Secondary database */ 126 get_sales_rep, /* Callback used for key creation. */ 127 0); /* Flags */</pre> 128 <div class="sect2" lang="en" xml:lang="en"> 129 <div class="titlepage"> 130 <div> 131 <div> 132 <h3 class="title"><a id="multikeys"></a>Working with Multiple Keys</h3> 133 </div> 134 </div> 135 <div></div> 136 </div> 137 <p> 138 Until now we have only discussed indexes as if there is 139 a one-to-one relationship between the secondary key and 140 the primary database record. In fact, it is possible to 141 generate multiple keys for any given record, provided 142 that you take appropriate steps in your key creator 143 to do so. 144 </p> 145 <p> 146 For example, suppose you had a database that contained 147 information about books. Suppose further that you 148 sometimes want to look up books by author. Because 149 sometimes books have multiple authors, you may want to 150 return multiple secondary keys for every book that you 151 index. 152 </p> 153 <p> 154 To do this, you write a key extractor that returns a 155 <span>DBT</span> 156 157 whose <tt class="literal">data</tt> member points to an array of 158 <span>DBTs.</span> 159 160 Each such member of this array contains a single secondary key. 161 In addition, the 162 <span>DBT</span> 163 164 returned by your key extractor must have a size field 165 equal to the number of elements contained in the 166 <span>DBT</span> 167 168 array. Also, the flag field for the 169 <span>DBT</span> 170 171 returned by the callback must include 172 <tt class="literal">DB_DBT_MULTIPLE</tt>. For example: 173 </p> 174 <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"> 175 <h3 class="title">Note</h3> 176 <p> 177 It is important that the array of secondary 178 keys created by your callback not contain 179 repeats. That is, every element in the array 180 must be unique. If the array does not contain 181 a unique set, then the secondary can get out 182 of sync with the primary. 183 </p> 184 </div> 185 <pre class="programlisting">int 186my_callback(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey) 187{ 188 DBT *tmpdbt; 189 char *tmpdata1, tmpdata2; 190 191 /* 192 * This example skips the step of extracting the data you 193 * want to use for building your secondary keys from the 194 * pkey or pdata DBT. 195 * 196 * Assume for the purpose of this example that the data 197 * is temporarily stored in two variables, 198 * tmpdata1 and tmpdata2. 199 */ 200 201 /* 202 * Create an array of DBTs that is large enough for the 203 * number of keys that you want to return. In this case, 204 * we go with an array of size two. 205 */ 206 207 tmpdbt = malloc(sizeof(DBT) * 2); 208 memset(tmpdbt, 0, sizeof(DBT) * 2); 209 210 /* Now assign secondary keys to each element of the array. */ 211 tmpdbt[0].data = tmpdata1; 212 tmpdbt[0].size = (u_int32_t)strlen(tmpdbt[0].data) + 1; 213 tmpdbt[1].data = tmpdata2; 214 tmpdbt[1].size = (u_int32_t)strlen(tmpdbt[1].data) + 1; 215 216 /* 217 * Now we set flags for the returned DBT. DB_DBT_MULTIPLE is 218 * required in order for DB to know that the DBT references an 219 * array. In addition, we set DB_DBT_APPMALLOC because we 220 * dynamically allocated memory for the DBT's data field. 221 * DB_DBT_APPMALLOC causes DB to release that memory once it 222 * is done with the returned DBT. 223 */ 224 skey->flags = DB_DBT_MULTIPLE | DB_DBT_APPMALLOC; 225 226 /* Point the results data field to the arrays of DBTs */ 227 skey->data = tmpdbt; 228 229 /* Indicate the returned array is of size 2 */ 230 skey->size = 2; 231 232 return (0); 233} </pre> 234 </div> 235 </div> 236 <div class="navfooter"> 237 <hr /> 238 <table width="100%" summary="Navigation footer"> 239 <tr> 240 <td width="40%" align="left"><a accesskey="p" href="indexes.html">Prev</a>��</td> 241 <td width="20%" align="center"> 242 <a accesskey="u" href="indexes.html">Up</a> 243 </td> 244 <td width="40%" align="right">��<a accesskey="n" href="readSecondary.html">Next</a></td> 245 </tr> 246 <tr> 247 <td width="40%" align="left" valign="top">Chapter��5.��Secondary Databases��</td> 248 <td width="20%" align="center"> 249 <a accesskey="h" href="index.html">Home</a> 250 </td> 251 <td width="40%" align="right" valign="top">��Reading Secondary Databases</td> 252 </tr> 253 </table> 254 </div> 255 </body> 256</html> 257