File: keyCreator.html

package info (click to toggle)
db5.3 5.3.28%2Bdfsg1-0.8
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 158,400 kB
  • sloc: ansic: 448,406; java: 111,824; tcl: 80,544; sh: 44,326; cs: 33,697; cpp: 21,604; perl: 14,557; xml: 10,799; makefile: 4,077; javascript: 1,998; yacc: 1,003; awk: 965; sql: 801; erlang: 342; python: 216; php: 24; asm: 14
file content (263 lines) | stat: -rw-r--r-- 10,606 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Implementing Key Extractors</title>
    <link rel="stylesheet" href="gettingStarted.css" type="text/css" />
    <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
    <link rel="start" href="index.html" title="Getting Started with Berkeley DB" />
    <link rel="up" href="indexes.html" title="Chapter 5. Secondary Databases" />
    <link rel="prev" href="indexes.html" title="Chapter 5. Secondary Databases" />
    <link rel="next" href="readSecondary.html" title="Reading Secondary Databases" />
  </head>
  <body>
    <div xmlns="" class="navheader">
      <div class="libver">
        <p>Library Version 11.2.5.3</p>
      </div>
      <table width="100%" summary="Navigation header">
        <tr>
          <th colspan="3" align="center">Implementing Key 
        
        <span xmlns="http://www.w3.org/1999/xhtml">Extractors</span>
        </th>
        </tr>
        <tr>
          <td width="20%" align="left"><a accesskey="p" href="indexes.html">Prev</a> </td>
          <th width="60%" align="center">Chapter 5. Secondary Databases</th>
          <td width="20%" align="right"> <a accesskey="n" href="readSecondary.html">Next</a></td>
        </tr>
      </table>
      <hr />
    </div>
    <div class="sect1" lang="en" xml:lang="en">
      <div class="titlepage">
        <div>
          <div>
            <h2 class="title" style="clear: both"><a id="keyCreator"></a>Implementing Key 
        
        <span>Extractors</span>
        </h2>
          </div>
        </div>
      </div>
      <div class="toc">
        <dl>
          <dt>
            <span class="sect2">
              <a href="keyCreator.html#multikeys">Working with Multiple Keys</a>
            </span>
          </dt>
        </dl>
      </div>
      <p>
        You must provide every secondary database with a 
            
            <span>callback</span>
        that creates keys from primary records. You identify this 
            
            <span>callback</span>
        
        
        <span>
            when you associate your secondary database to your primary.
        </span>
     </p>
      <p>
        You can create keys using whatever data you want. Typically you will
        base your key on some information found in a record's data, but you
        can also use information found in the primary record's key. How you build
        your keys is entirely dependent upon the nature of the index that you
        want to maintain.
    </p>
      <p>
        You implement a key extractor by writing a function that extracts
        the necessary information from a primary record's key or data.
        This function must conform to a specific prototype, and it must be
        provided as a callback to the <code class="methodname">associate()</code>
        method.
    </p>
      <p>
        For example, suppose your primary database records contain data that
        uses the following structure:
    </p>
      <a id="c_index3"></a>
      <pre class="programlisting">typedef struct vendor {
    char name[MAXFIELD];             /* Vendor name */
    char street[MAXFIELD];           /* Street name and number */
    char city[MAXFIELD];             /* City */
    char state[3];                   /* Two-digit US state code */
    char zipcode[6];                 /* US zipcode */
    char phone_number[13];           /* Vendor phone number */
    char sales_rep[MAXFIELD];        /* Name of sales representative */
    char sales_rep_phone[MAXFIELD];  /* Sales rep's phone number */
} VENDOR; </pre>
      <p>
        Further suppose that you want to be able to query your primary database
        based on the name of a sales representative. Then you would write a
        function that looks like this:
    </p>
      <a id="c_index4"></a>
      <pre class="programlisting">#include &lt;db.h&gt;

...

int
get_sales_rep(DB *sdbp,          /* secondary db handle */
              const DBT *pkey,   /* primary db record's key */
              const DBT *pdata,  /* primary db record's data */
              DBT *skey)         /* secondary db record's key */
{
    VENDOR *vendor;

    /* First, extract the structure contained in the primary's data */
    vendor = pdata-&gt;data;

    /* Now set the secondary key's data to be the representative's name */
    memset(skey, 0, sizeof(DBT));
    skey-&gt;data = vendor-&gt;sales_rep;
    skey-&gt;size = strlen(vendor-&gt;sales_rep) + 1;

    /* Return 0 to indicate that the record can be created/updated. */
    return (0);
} </pre>
      <p>
        In order to use this function, you provide it on the
        <code class="methodname">associate()</code> method after the primary and
        secondary databases have been created and opened:
    </p>
      <a id="c_index5"></a>
      <pre class="programlisting">dbp-&gt;associate(dbp,            /* Primary database */
               NULL,           /* TXN id */
               sdbp,           /* Secondary database */
               get_sales_rep,  /* Callback used for key creation. */
               0);             /* Flags */</pre>
      <div class="sect2" lang="en" xml:lang="en">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="multikeys"></a>Working with Multiple Keys</h3>
            </div>
          </div>
        </div>
        <p>
                    Until now we have only discussed indexes as if there is
                    a one-to-one relationship between the secondary key and
                    the primary database record. In fact, it is possible to
                    generate multiple keys for any given record, provided
                    that you take appropriate steps in your key creator
                    to do so.
            </p>
        <p>
                    For example, suppose you had a database that contained
                    information about books. Suppose further that you
                    sometimes want to look up books by author. Because
                    sometimes books have multiple authors, you may want to
                    return multiple secondary keys for every book that you
                    index.
            </p>
        <p>
                    To do this, you write a key extractor that returns a
                                <span>DBT</span>
                                
                        whose <code class="literal">data</code> member points to an array of
                                <span>DBTs.</span>
                                
                        Each such member of this array contains a single secondary key.
                        In addition, the 
                                <span>DBT</span>
                                
                        returned by your key extractor must have a size field
                        equal to the number of elements contained in the 
                                <span>DBT</span>
                                
                        array. Also, the flag field for the 
                                <span>DBT</span>
                                
                        returned by the callback must include 
                        <code class="literal">DB_DBT_MULTIPLE</code>. For example:
             </p>
        <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
          <h3 class="title">Note</h3>
          <p>
                             It is important that the array of secondary
                             keys created by your callback not contain
                             repeats. That is, every element in the array
                             must be unique. If the array does not contain
                             a unique set, then the secondary can get out
                             of sync with the primary.
                     </p>
        </div>
        <pre class="programlisting">int
my_callback(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey)
{
    DBT *tmpdbt;
    char *tmpdata1, tmpdata2;

    /*
     * This example skips the step of extracting the data you
     * want to use for building your secondary keys from the
     * pkey or pdata DBT.
     *
     * Assume for the purpose of this example that the data 
     * is temporarily stored in two variables, 
     * tmpdata1 and tmpdata2.
     */

    /* 
     * Create an array of DBTs that is large enough for the
     * number of keys that you want to return. In this case, 
     * we go with an array of size two. 
     */

    tmpdbt = malloc(sizeof(DBT) * 2);
    memset(tmpdbt, 0, sizeof(DBT) * 2);

    /* Now assign secondary keys to each element of the array. */
    tmpdbt[0].data = tmpdata1;
    tmpdbt[0].size = (u_int32_t)strlen(tmpdbt[0].data) + 1;
    tmpdbt[1].data = tmpdata2;
    tmpdbt[1].size = (u_int32_t)strlen(tmpdbt[1].data) + 1;

    /* 
     * Now we set flags for the returned DBT. DB_DBT_MULTIPLE is
     * required in order for DB to know that the DBT references an 
     * array. In addition, we set DB_DBT_APPMALLOC because we
     * dynamically allocated memory for the DBT's data field.
     * DB_DBT_APPMALLOC causes DB to release that memory once it
     * is done with the returned DBT. 
     */
    skey-&gt;flags = DB_DBT_MULTIPLE | DB_DBT_APPMALLOC;

    /* Point the results data field to the arrays of DBTs */
    skey-&gt;data = tmpdbt;

    /* Indicate the returned array is of size 2 */
    skey-&gt;size = 2;

    return (0);
} </pre>
      </div>
    </div>
    <div class="navfooter">
      <hr />
      <table width="100%" summary="Navigation footer">
        <tr>
          <td width="40%" align="left"><a accesskey="p" href="indexes.html">Prev</a> </td>
          <td width="20%" align="center">
            <a accesskey="u" href="indexes.html">Up</a>
          </td>
          <td width="40%" align="right"> <a accesskey="n" href="readSecondary.html">Next</a></td>
        </tr>
        <tr>
          <td width="40%" align="left" valign="top">Chapter 5. Secondary Databases </td>
          <td width="20%" align="center">
            <a accesskey="h" href="index.html">Home</a>
          </td>
          <td width="40%" align="right" valign="top"> Reading Secondary Databases</td>
        </tr>
      </table>
    </div>
  </body>
</html>