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 &lt;db.h&gt;
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-&gt;data;
108
109    /* Now set the secondary key's data to be the representative's name */
110    memset(skey, 0, sizeof(DBT));
111    skey-&gt;data = vendor-&gt;sales_rep;
112    skey-&gt;size = strlen(vendor-&gt;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-&gt;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-&gt;flags = DB_DBT_MULTIPLE | DB_DBT_APPMALLOC;
225
226    /* Point the results data field to the arrays of DBTs */
227    skey-&gt;data = tmpdbt;
228
229    /* Indicate the returned array is of size 2 */
230    skey-&gt;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