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>Database Joins</title>
7    <link rel="stylesheet" href="gettingStarted.css" type="text/css" />
8    <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
9    <link rel="start" href="index.html" title="Getting Started with Berkeley DB" />
10    <link rel="up" href="indexes.html" title="Chapter 5. Secondary Databases" />
11    <link rel="prev" href="secondaryCursor.html" title="Using Cursors with Secondary Databases" />
12    <link rel="next" href="coreindexusage.html" title="Secondary Database Example" />
13  </head>
14  <body>
15    <div class="navheader">
16      <table width="100%" summary="Navigation header">
17        <tr>
18          <th colspan="3" align="center">Database Joins</th>
19        </tr>
20        <tr>
21          <td width="20%" align="left"><a accesskey="p" href="secondaryCursor.html">Prev</a> </td>
22          <th width="60%" align="center">Chapter 5. Secondary Databases</th>
23          <td width="20%" align="right"> <a accesskey="n" href="coreindexusage.html">Next</a></td>
24        </tr>
25      </table>
26      <hr />
27    </div>
28    <div class="sect1" lang="en" xml:lang="en">
29      <div class="titlepage">
30        <div>
31          <div>
32            <h2 class="title" style="clear: both"><a id="joins"></a>Database Joins</h2>
33          </div>
34        </div>
35      </div>
36      <div class="toc">
37        <dl>
38          <dt>
39            <span class="sect2">
40              <a href="joins.html#joinUsage">Using Join Cursors</a>
41            </span>
42          </dt>
43        </dl>
44      </div>
45      <p>
46        If you have two or more secondary databases associated with a primary
47        database, then you can retrieve primary records based on the intersection of 
48        multiple secondary entries. You do this using a
49        
50        <span>join cursor.</span>
51    </p>
52      <p>
53        Throughout this document we have presented a 
54            
55            <span>structure</span>
56        that stores 
57            
58        information on grocery
59            
60            <span>vendors.</span>
61        That 
62            
63            <span>structure</span>
64        is fairly simple with a limited
65        number of data members, few of which would be interesting from a query
66        perspective. But suppose, instead, that we were storing 
67        information on something with many more characteristics that can be queried, such
68        as an automobile. In that case, you may be storing information such as
69        color, number of doors, fuel mileage, automobile type, number of
70        passengers, make, model, and year, to name just a few.
71    </p>
72      <p>
73        In this case, you would still likely be using some unique value to key your
74        primary entries (in the United States, the automobile's VIN would be
75        ideal for this purpose). You would then create a 
76            
77            <span>structure</span>
78        that identifies
79        all the characteristics of the automobiles in your inventory. 
80        
81        
82    </p>
83      <p>
84        To query this data, you might then create multiple secondary databases,
85        one for each of the characteristics that you want to query. For
86        example, you might create a secondary for color, another for number of
87        doors, another for number of passengers, and so forth. Of course, you
88        will need a unique 
89            
90            <span>key extractor function</span>
91        for each such secondary database. You do
92        all of this using the concepts and techniques described throughout this
93        chapter.
94    </p>
95      <p>
96        Once you have created this primary database and all interesting
97        secondaries, what you have is the ability to retrieve automobile records
98        based on a single characteristic. You can, for example, find all the
99        automobiles that are red. Or you can find all the automobiles that have
100        four doors. Or all the automobiles that are minivans. 
101    </p>
102      <p>
103        The next most natural step, then, is to form compound queries, or joins.
104        For example, you might want to find all the automobiles that are red,
105        and that were built by Toyota, and that are minivans. You can do this
106        using a 
107            
108            <span>join cursor.</span>
109    </p>
110      <div class="sect2" lang="en" xml:lang="en">
111        <div class="titlepage">
112          <div>
113            <div>
114              <h3 class="title"><a id="joinUsage"></a>Using Join Cursors</h3>
115            </div>
116          </div>
117        </div>
118        <p>
119            To use a join cursor:
120        </p>
121        <div class="itemizedlist">
122          <ul type="disc">
123            <li>
124              <p>
125                    Open two or more 
126                        
127                    cursors 
128                        
129                        <span>for</span> 
130                    secondary databases that are associated with
131                    the same primary database.
132                </p>
133            </li>
134            <li>
135              <p>
136                    Position each such cursor to the secondary key
137                    value in which you are interested. For example, to build on
138                    the previous description, the cursor for the color
139                    database is positioned to the <code class="literal">red</code> records
140                    while the cursor for the model database is positioned to the
141                    <code class="literal">minivan</code> records, and the cursor for the
142                    make database is positioned to <code class="literal">Toyota</code>.
143                </p>
144            </li>
145            <li>
146              <p>
147
148                    Create an array of  cursors, and
149                    place in it each of the cursors that are participating in your join query. 
150                    <span>Note that this array must be null terminated.</span>
151
152                </p>
153            </li>
154            <li>
155              <p>
156
157                    Obtain a join cursor. You do this using the 
158                         
159                        <code class="methodname">DB-&gt;join()</code> 
160                         
161                    method.  You must pass this method the array of secondary cursors that you
162                    opened and positioned in the previous steps.
163                </p>
164            </li>
165            <li>
166              <p>
167                    Iterate over the set of matching records
168                        
169                    until
170                    
171                    <span>the return code is not <code class="literal">0</code>.</span>
172                </p>
173            </li>
174            <li>
175              <p>
176                    Close your  cursor.
177                </p>
178            </li>
179            <li>
180              <p>
181                    If you are done with them, close all your  cursors.
182                </p>
183            </li>
184          </ul>
185        </div>
186        <p>
187            For example:
188        </p>
189        <a id="c_index9"></a>
190        <pre class="programlisting">#include &lt;db.h&gt;
191#include &lt;string.h&gt;
192
193...
194
195DB *automotiveDB;
196DB *automotiveColorDB;
197DB *automotiveMakeDB;
198DB *automotiveTypeDB;
199DBC *color_curs, *make_curs, *type_curs, *join_curs;
200DBC *carray[4];
201DBT key, data;
202int ret;
203
204char *the_color = "red";
205char *the_type = "minivan";
206char *the_make = "Toyota";
207
208/* Database and secondary database opens omitted for brevity.
209 * Assume a primary database handle:
210 *   automotiveDB
211 * Assume 3 secondary database handles:
212 *   automotiveColorDB  -- secondary database based on automobile color
213 *   automotiveMakeDB  -- secondary database based on the manufacturer
214 *   automotiveTypeDB  -- secondary database based on automobile type
215 */
216
217/* initialize pointers and structures */
218color_curs = NULL;
219make_curs = NULL;
220type_curs = NULL;
221join_curs = NULL;
222
223memset(&amp;key, 0, sizeof(DBT));
224memset(&amp;data, 0, sizeof(DBT));
225
226/* open the cursors */
227if (( ret =
228    automotiveColorDB-&gt;cursor(automotiveColorDB, NULL, 
229      &amp;color_curs, 0)) != 0) {
230        /* Error handling goes here */
231}
232
233if (( ret =
234    automotiveMakeDB-&gt;cursor(automotiveMakeDB, NULL, 
235      &amp;make_curs, 0)) != 0) {
236        /* Error handling goes here */
237}
238
239if (( ret =
240    automotiveTypeDB-&gt;cursor(automotiveTypeDB, NULL, 
241      &amp;type_curs, 0)) != 0) {
242        /* Error handling goes here */
243}
244
245/* Position the cursors */
246key.data = the_color;
247key.size = strlen(the_color) + 1;
248if ((ret = color_curs-&gt;get(color_curs, &amp;key, &amp;data, DB_SET)) != 0)
249    /* Error handling goes here */
250
251key.data = the_make;
252key.size = strlen(the_make) + 1;
253if ((ret = make_curs-&gt;get(make_curs, &amp;key, &amp;data, DB_SET)) != 0)
254    /* Error handling goes here */
255
256key.data = the_type;
257key.size = strlen(the_type) + 1;
258if ((ret = type_curs-&gt;get(type_curs, &amp;key, &amp;data, DB_SET)) != 0)
259    /* Error handling goes here */
260
261/* Set up the cursor array */
262carray[0] = color_curs;
263carray[1] = make_curs;
264carray[2] = type_curs;
265carray[3] = NULL;
266
267/* Create the join */
268if ((ret = automotiveDB-&gt;join(automotiveDB, carray, &amp;join_curs, 0)) != 0)
269    /* Error handling goes here */
270
271/* Iterate using the join cursor */
272while ((ret = join_curs-&gt;get(join_curs, &amp;key, &amp;data, 0)) == 0) {
273    /* Do interesting things with the key and data */
274}
275
276/*
277 * If we exited the loop because we ran out of records,
278 * then it has completed successfully.
279 */
280if (ret == DB_NOTFOUND) {
281    /* 
282     * Close all our cursors and databases as is appropriate,  and 
283     * then exit with a normal exit status (0). 
284     */
285} </pre>
286      </div>
287    </div>
288    <div class="navfooter">
289      <hr />
290      <table width="100%" summary="Navigation footer">
291        <tr>
292          <td width="40%" align="left"><a accesskey="p" href="secondaryCursor.html">Prev</a> </td>
293          <td width="20%" align="center">
294            <a accesskey="u" href="indexes.html">Up</a>
295          </td>
296          <td width="40%" align="right"> <a accesskey="n" href="coreindexusage.html">Next</a></td>
297        </tr>
298        <tr>
299          <td width="40%" align="left" valign="top">
300        
301        <span>Using Cursors with Secondary Databases</span>
302     </td>
303          <td width="20%" align="center">
304            <a accesskey="h" href="index.html">Home</a>
305          </td>
306          <td width="40%" align="right" valign="top"> Secondary Database Example</td>
307        </tr>
308      </table>
309    </div>
310  </body>
311</html>
312