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>Chapter 5. Secondary Databases</title> 7 <link rel="stylesheet" href="gettingStarted.css" type="text/css" /> 8 <meta name="generator" content="DocBook XSL Stylesheets V1.62.4" /> 9 <link rel="home" href="index.html" title="Getting Started with Berkeley DB" /> 10 <link rel="up" href="index.html" title="Getting Started with Berkeley DB" /> 11 <link rel="previous" href="CoreCursorUsage.html" title="Cursor Example" /> 12 <link rel="next" href="keyCreator.html" title="Implementing Key Extractors " /> 13 </head> 14 <body> 15 <div class="navheader"> 16 <table width="100%" summary="Navigation header"> 17 <tr> 18 <th colspan="3" align="center">Chapter 5. Secondary Databases</th> 19 </tr> 20 <tr> 21 <td width="20%" align="left"><a accesskey="p" href="CoreCursorUsage.html">Prev</a> </td> 22 <th width="60%" align="center"> </th> 23 <td width="20%" align="right"> <a accesskey="n" href="keyCreator.html">Next</a></td> 24 </tr> 25 </table> 26 <hr /> 27 </div> 28 <div class="chapter" lang="en" xml:lang="en"> 29 <div class="titlepage"> 30 <div> 31 <div> 32 <h2 class="title"><a id="indexes"></a>Chapter 5. Secondary Databases</h2> 33 </div> 34 </div> 35 <div></div> 36 </div> 37 <div class="toc"> 38 <p> 39 <b>Table of Contents</b> 40 </p> 41 <dl> 42 <dt> 43 <span class="sect1"> 44 <a href="indexes.html#CoreDbAssociate">Opening and Closing Secondary Databases</a> 45 </span> 46 </dt> 47 <dt> 48 <span class="sect1"> 49 <a href="keyCreator.html">Implementing Key 50 51 Extractors 52 </a> 53 </span> 54 </dt> 55 <dd> 56 <dl> 57 <dt> 58 <span class="sect2"> 59 <a href="keyCreator.html#multikeys">Working with Multiple Keys</a> 60 </span> 61 </dt> 62 </dl> 63 </dd> 64 <dt> 65 <span class="sect1"> 66 <a href="readSecondary.html">Reading Secondary Databases</a> 67 </span> 68 </dt> 69 <dt> 70 <span class="sect1"> 71 <a href="secondaryDelete.html">Deleting Secondary Database Records</a> 72 </span> 73 </dt> 74 <dt> 75 <span class="sect1"> 76 <a href="secondaryCursor.html"> 77 78 Using Cursors with Secondary Databases 79 </a> 80 </span> 81 </dt> 82 <dt> 83 <span class="sect1"> 84 <a href="joins.html">Database Joins</a> 85 </span> 86 </dt> 87 <dd> 88 <dl> 89 <dt> 90 <span class="sect2"> 91 <a href="joins.html#joinUsage">Using Join Cursors</a> 92 </span> 93 </dt> 94 </dl> 95 </dd> 96 <dt> 97 <span class="sect1"> 98 <a href="coreindexusage.html">Secondary Database Example</a> 99 </span> 100 </dt> 101 <dd> 102 <dl> 103 <dt> 104 <span class="sect2"> 105 <a href="coreindexusage.html#edlWIndexes">Secondary Databases with example_database_load</a> 106 </span> 107 </dt> 108 <dt> 109 <span class="sect2"> 110 <a href="coreindexusage.html#edrWIndexes">Secondary Databases with example_database_read</a> 111 </span> 112 </dt> 113 </dl> 114 </dd> 115 </dl> 116 </div> 117 <p> 118 Usually you find database records by means of the record's key. However, 119 the key that you use for your record will not always contain the 120 information required to provide you with rapid access to the data that you 121 want to retrieve. For example, suppose your 122 123 <span>database</span> 124 contains records related to users. The key might be a string that is some 125 unique identifier for the person, such as a user ID. Each record's data, 126 however, would likely contain a complex object containing details about 127 people such as names, addresses, phone numbers, and so forth. 128 While your application may frequently want to query a person by user 129 ID (that is, by the information stored in the key), it may also on occasion 130 want to locate people by, say, their name. 131 </p> 132 <p> 133 Rather than iterate through all of the records in your database, examining 134 each in turn for a given person's name, you create indexes based on names 135 and then just search that index for the name that you want. You can do this 136 using secondary databases. In DB, the 137 138 <span>database</span> 139 that contains your data is called a 140 <span class="emphasis"><em>primary database</em></span>. A database that provides an 141 alternative set of keys to access that data is called a <span class="emphasis"><em>secondary 142 database</em></span><span>.</span> In a secondary database, the keys are your alternative 143 (or secondary) index, and the data corresponds to a primary record's key. 144 </p> 145 <p> 146 You create a secondary database by creating the database, opening it, and 147 then <span class="emphasis"><em>associating</em></span> the database with 148 the <span class="emphasis"><em>primary</em></span> database (that is, the database for which 149 you are creating the index). As a part of associating 150 the secondary database to the primary, you must provide a callback that is 151 used to create the secondary database keys. Typically this callback creates 152 a key based on data found in the primary database record's key or data. 153 </p> 154 <p> 155 Once opened, DB manages secondary databases for you. Adding or deleting 156 records in your primary database causes DB to update the secondary as 157 necessary. Further, changing a record's data in the primary database may cause 158 DB to modify a record in the secondary, depending on whether the change 159 forces a modification of a key in the secondary database. 160 </p> 161 <p> 162 Note that you can not write directly to a secondary database. 163 164 165 166 <span>Any attempt to write to a secondary database 167 results in a non-zero status return.</span> 168 169 To change the data referenced by a 170 171 <span>secondary</span> 172 record, modify the primary database instead. The exception to this rule is 173 that delete operations are allowed on the 174 175 <span>secondary database.</span> 176 177 See <a href="secondaryDelete.html">Deleting Secondary Database Records</a> for more 178 information. 179 </p> 180 <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"> 181 <h3 class="title">Note</h3> 182 <p> 183 184 Secondary database records are updated/created by DB 185 only if the 186 187 <span>key creator callback function</span> 188 returns 189 190 <span><tt class="literal">0</tt>.</span> 191 If 192 193 <span>a value other than <tt class="literal">0</tt></span> 194 is returned, then DB will not add the key to the secondary database, and 195 in the event of a record update it will remove any existing key. 196 197 <span>Note that the callback can use either 198 <tt class="literal">DB_DONOTINDEX</tt> or some error code outside of DB's 199 name space to indicate that the entry should not be indexed.</span> 200 201 </p> 202 <p> 203 See <a href="keyCreator.html">Implementing Key 204 205 <span>Extractors</span> 206 </a> for more 207 208 <span>information.</span> 209 210 </p> 211 </div> 212 <p> 213 When you read a record from a secondary database, DB automatically 214 returns 215 216 <span>the data and optionally the key</span> 217 from the corresponding record in the primary database. 218 219 </p> 220 <div class="sect1" lang="en" xml:lang="en"> 221 <div class="titlepage"> 222 <div> 223 <div> 224 <h2 class="title" style="clear: both"><a id="CoreDbAssociate"></a>Opening and Closing Secondary Databases</h2> 225 </div> 226 </div> 227 <div></div> 228 </div> 229 <p> 230 You manage secondary database opens and closes in the same way as you 231 would any normal database. The only difference is that: 232 </p> 233 <div class="itemizedlist"> 234 <ul type="disc"> 235 <li> 236 <p> 237 You must associate the secondary to a primary database using 238 <span><tt class="methodname">DB->associate()</tt>.</span> 239 240 </p> 241 </li> 242 <li> 243 <p> 244 When closing your databases, it is a good idea to make sure you 245 close your secondaries before closing your primaries. This is 246 particularly true if your database closes are not single 247 threaded. 248 </p> 249 </li> 250 </ul> 251 </div> 252 <p> 253 When you associate a secondary to a primary database, you must provide a 254 callback that is used to generate the secondary's keys. These 255 callbacks are described in the next section. 256 </p> 257 <p> 258 For example, to open a secondary database and associate it to a primary 259 database: 260 </p> 261 <a id="c_index1"></a> 262 <pre class="programlisting">#include <db.h> 263 264... 265 266DB *dbp, *sdbp; /* Primary and secondary DB handles */ 267u_int32_t flags; /* Primary database open flags */ 268int ret; /* Function return value */ 269 270/* Primary */ 271ret = db_create(&dbp, NULL, 0); 272if (ret != 0) { 273 /* Error handling goes here */ 274} 275 276/* Secondary */ 277ret = db_create(&sdbp, NULL, 0); 278if (ret != 0) { 279 /* Error handling goes here */ 280} 281 282/* Usually we want to support duplicates for secondary databases */ 283ret = sdbp->set_flags(sdbp, DB_DUPSORT); 284if (ret != 0) { 285 /* Error handling goes here */ 286} 287 288 289/* Database open flags */ 290flags = DB_CREATE; /* If the database does not exist, 291 * create it.*/ 292 293/* open the primary database */ 294ret = dbp->open(dbp, /* DB structure pointer */ 295 NULL, /* Transaction pointer */ 296 "my_db.db", /* On-disk file that holds the database. */ 297 NULL, /* Optional logical database name */ 298 DB_BTREE, /* Database access method */ 299 flags, /* Open flags */ 300 0); /* File mode (using defaults) */ 301if (ret != 0) { 302 /* Error handling goes here */ 303} 304 305/* open the secondary database */ 306ret = sdbp->open(sdbp, /* DB structure pointer */ 307 NULL, /* Transaction pointer */ 308 "my_secdb.db", /* On-disk file that holds the database. */ 309 NULL, /* Optional logical database name */ 310 DB_BTREE, /* Database access method */ 311 flags, /* Open flags */ 312 0); /* File mode (using defaults) */ 313if (ret != 0) { 314 /* Error handling goes here */ 315} 316 317/* Now associate the secondary to the primary */ 318dbp->associate(dbp, /* Primary database */ 319 NULL, /* TXN id */ 320 sdbp, /* Secondary database */ 321 get_sales_rep, /* Callback used for key creation. Not 322 * defined in this example. See the next 323 * section. */ 324 0); /* Flags */</pre> 325 <p> 326 Closing the primary and secondary databases is accomplished exactly as you 327 would for any database: 328 </p> 329 <a id="c_index2"></a> 330 <pre class="programlisting">/* Close the secondary before the primary */ 331if (sdbp != NULL) 332 sdbp->close(sdbp, 0); 333if (dbp != NULL) 334 dbp->close(dbp, 0); </pre> 335 </div> 336 </div> 337 <div class="navfooter"> 338 <hr /> 339 <table width="100%" summary="Navigation footer"> 340 <tr> 341 <td width="40%" align="left"><a accesskey="p" href="CoreCursorUsage.html">Prev</a> </td> 342 <td width="20%" align="center"> 343 <a accesskey="u" href="index.html">Up</a> 344 </td> 345 <td width="40%" align="right"> <a accesskey="n" href="keyCreator.html">Next</a></td> 346 </tr> 347 <tr> 348 <td width="40%" align="left" valign="top">Cursor Example </td> 349 <td width="20%" align="center"> 350 <a accesskey="h" href="index.html">Home</a> 351 </td> 352 <td width="40%" align="right" valign="top"> Implementing Key 353 354 Extractors 355 </td> 356 </tr> 357 </table> 358 </div> 359 </body> 360</html> 361