~ubuntu-branches/ubuntu/maverick/evolution-data-server/maverick

« back to all changes in this revision

Viewing changes to libdb/docs/ref/am/second.html

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2010-05-17 17:02:06 UTC
  • mfrom: (1.1.79 upstream) (1.6.12 experimental)
  • Revision ID: james.westby@ubuntu.com-20100517170206-4ufr52vwrhh26yh0
Tags: 2.30.1-1ubuntu1
* Merge from debian experimental. Remaining change:
  (LP: #42199, #229669, #173703, #360344, #508494)
  + debian/control:
    - add Vcs-Bzr tag
    - don't use libgnome
    - Use Breaks instead of Conflicts against evolution 2.25 and earlier.
  + debian/evolution-data-server.install,
    debian/patches/45_libcamel_providers_version.patch:
    - use the upstream versioning, not a Debian-specific one 
  + debian/libedata-book1.2-dev.install, debian/libebackend-1.2-dev.install,
    debian/libcamel1.2-dev.install, debian/libedataserverui1.2-dev.install:
    - install html documentation
  + debian/rules:
    - don't build documentation it's shipped with the tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<!--$Id$-->
2
 
<!--Copyright 1997-2002 by Sleepycat Software, Inc.-->
3
 
<!--All rights reserved.-->
4
 
<!--See the file LICENSE for redistribution information.-->
5
 
<html>
6
 
<head>
7
 
<title>Berkeley DB Reference Guide: Secondary indices</title>
8
 
<meta name="description" content="Berkeley DB: An embedded database programmatic toolkit.">
9
 
<meta name="keywords" content="embedded,database,programmatic,toolkit,b+tree,btree,hash,hashing,transaction,transactions,locking,logging,access method,access methods,java,C,C++">
10
 
</head>
11
 
<body bgcolor=white>
12
 
<a name="2"><!--meow--></a><a name="3"><!--meow--></a>
13
 
<table width="100%"><tr valign=top>
14
 
<td><h3><dl><dt>Berkeley DB Reference Guide:<dd>Access Methods</dl></h3></td>
15
 
<td align=right><a href="../../ref/am/close.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../../reftoc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../../ref/am/cursor.html"><img src="../../images/next.gif" alt="Next"></a>
16
 
</td></tr></table>
17
 
<p>
18
 
<h1 align=center>Secondary indices</h1>
19
 
<p>A secondary index, put simply, is a way to efficiently access records
20
 
in a database (the primary) by means of some piece of information other
21
 
than the usual (primary) key.  In Berkeley DB, this index is simply another
22
 
database whose keys are these pieces of information (the secondary
23
 
keys), and whose data are the primary keys.  Secondary indices can be
24
 
(and often are) created manually by the application;  there is no
25
 
disadvantage, other than complexity, to doing so.  However, when the
26
 
secondary key can be mechanically derived from the primary key and datum
27
 
that it points to, as is frequently the case, Berkeley DB can automatically
28
 
and transparently manage secondary indices.
29
 
<p>As an example of how secondary indices might be used, consider a
30
 
database containing a list of students at a college, each of whom has
31
 
a unique student ID number.  A typical database would use the student
32
 
ID number as the key; however, one might also reasonably want to be
33
 
able to look up students by last name.  To do this, one would construct
34
 
a secondary index in which the secondary key was this last name.
35
 
<p>In SQL, this would be done by executing something like the following:
36
 
<p><blockquote><pre>CREATE TABLE students(student_id CHAR(4) NOT NULL,
37
 
        lastname CHAR(15), firstname CHAR(15), PRIMARY KEY(student_id));
38
 
CREATE INDEX lname ON students(lastname);</pre></blockquote>
39
 
<p>In Berkeley DB, this would work as follows:
40
 
<pre><p><blockquote>struct student_record {
41
 
        char student_id[4];
42
 
        char last_name[15];
43
 
        char first_name[15];
44
 
};
45
 
<p>
46
 
void
47
 
second()
48
 
{
49
 
        DB *dbp, *sdbp;
50
 
        int ret;
51
 
        <p>
52
 
        /* Open/create primary */
53
 
        if ((ret = db_create(&dbp, dbenv, 0)) != 0)
54
 
                handle_error(ret);
55
 
        if ((ret = dbp-&gt;open(dbp, NULL,
56
 
            "students.db", NULL, DB_BTREE, DB_CREATE, 0600)) != 0)
57
 
                handle_error(ret);
58
 
        <p>
59
 
        /*
60
 
         * Open/create secondary.  Note that it supports duplicate data
61
 
         * items, since last names might not be unique.
62
 
         */
63
 
        if ((ret = db_create(&sdbp, dbenv, 0)) != 0)
64
 
                handle_error(ret);
65
 
        if ((ret = sdbp-&gt;set_flags(sdbp, DB_DUP | DB_DUPSORT)) != 0)
66
 
                handle_error(ret);
67
 
        if ((ret = sdbp-&gt;open(sdbp, NULL,
68
 
            "lastname.db", NULL, DB_BTREE, DB_CREATE, 0600)) != 0)
69
 
                handle_error(ret);
70
 
        <p>
71
 
        /* Associate the secondary with the primary. */
72
 
        if ((ret = dbp-&gt;associate(dbp, NULL, sdbp, getname, 0)) != 0)
73
 
                handle_error(ret);
74
 
}
75
 
<p>
76
 
/*
77
 
 * getname -- extracts a secondary key (the last name) from a primary
78
 
 *      key/data pair
79
 
 */
80
 
int
81
 
getname(dbp, pkey, pdata, skey)
82
 
        DB *dbp;
83
 
        const DBT *pkey, *pdata;
84
 
        DBT *skey;
85
 
{
86
 
        /*
87
 
         * Since the secondary key is a simple structure member of the
88
 
         * record, we don't have to do anything fancy to return it.  If
89
 
         * we have composite keys that need to be constructed from the
90
 
         * record, rather than simply pointing into it, then the user's
91
 
         * function might need to allocate space and copy data.  In
92
 
         * this case, the DB_DBT_APPMALLOC flag should be set in the
93
 
         * secondary key DBT.
94
 
         */
95
 
        memset(skey, 0, sizeof(DBT));
96
 
        skey-&gt;data = ((struct student_record *)pdata-&gt;data)-&gt;last_name;
97
 
        skey-&gt;size = sizeof((struct student_record *)pdata-&gt;data)-&gt;last_name;
98
 
        return (0);
99
 
}</blockquote></pre>
100
 
<p>From the application's perspective, putting things into the database
101
 
works exactly as it does without a secondary index;  one can simply
102
 
insert records into the primary database.  In SQL one would do the
103
 
following:
104
 
<p><blockquote><pre>INSERT INTO student
105
 
    VALUES ("WC42", "Churchill      ", "Winston        ");</pre></blockquote>
106
 
<p>and in Berkeley DB, one does:
107
 
<p><blockquote><pre>struct student_record s;
108
 
DBT data, key;
109
 
<p>
110
 
memset(&key, 0, sizeof(DBT));
111
 
memset(&data, 0, sizeof(DBT));
112
 
memset(&s, 0, sizeof(struct student_record));
113
 
key.data = "WC42";
114
 
key.size = 4;
115
 
memcpy(&s.student_id, "WC42", sizeof(s.student_id));
116
 
memcpy(&s.last_name, "Churchill      ", sizeof(s.last_name));
117
 
memcpy(&s.first_name, "Winston        ", sizeof(s.first_name));
118
 
data.data = &s;
119
 
data.size = sizeof(s);
120
 
if ((ret = dbp-&gt;put(dbp, txn, &key, &data, 0)) != 0)
121
 
        handle_error(ret);</pre></blockquote>
122
 
<p>Internally, a record with secondary key "Churchill" is inserted into
123
 
the secondary database (in addition to the insertion of "WC42" into the
124
 
primary, of course).
125
 
<p>Deletes are similar.  The SQL clause:
126
 
<p><blockquote><pre>DELETE FROM student WHERE (student_id = "WC42");</pre></blockquote>
127
 
<p>looks like:
128
 
<p><blockquote><pre>DBT key;
129
 
<p>
130
 
memset(&key, 0, sizeof(DBT));
131
 
key.data = "WC42";
132
 
key.size = 4;
133
 
if ((ret = dbp-&gt;del(dbp, txn, &key, 0)) != 0)
134
 
        handle_error(ret);</pre></blockquote>
135
 
<p>Deletes can also be performed on the secondary index directly; a delete
136
 
done this way will delete the "real" record in the primary as well.  If
137
 
the secondary supports duplicates and there are duplicate occurrences of
138
 
the secondary key, then all records with that secondary key are removed
139
 
from both the secondary index and the primary database. In
140
 
SQL:
141
 
<p><blockquote><pre>DELETE FROM lname WHERE (lastname = "Churchill      ");</pre></blockquote>
142
 
<p>In Berkeley DB:
143
 
<p><blockquote><pre>DBT skey;
144
 
<p>
145
 
memset(&skey, 0, sizeof(DBT));
146
 
skey.data = "Churchill      ";
147
 
skey.size = 15;
148
 
if ((ret = sdbp-&gt;del(sdbp, txn, &skey, 0)) != 0)
149
 
        handle_error(ret);</pre></blockquote>
150
 
<p>Gets on a secondary automatically return the primary datum.  If
151
 
<a href="../../api_c/db_get.html">DB-&gt;pget</a> or <a href="../../api_c/dbc_get.html">DBcursor-&gt;c_pget</a> is used in lieu of <a href="../../api_c/db_get.html">DB-&gt;get</a>
152
 
or <a href="../../api_c/dbc_get.html">DBcursor-&gt;c_get</a>, the primary key is returned as well.  Thus, the
153
 
equivalent of:
154
 
<p><blockquote><pre>SELECT * from lname WHERE (lastname = "Churchill      ");</pre></blockquote>
155
 
<p>would be:
156
 
<p><blockquote><pre>DBT data, pkey, skey;
157
 
<p>
158
 
memset(&skey, 0, sizeof(DBT));
159
 
memset(&pkey, 0, sizeof(DBT));
160
 
memset(&data, 0, sizeof(DBT));
161
 
skey.data = "Churchill      ";
162
 
skey.size = 15;
163
 
if ((ret = sdbp-&gt;pget(sdbp, txn, &skey, &pkey, &data, 0)) != 0)
164
 
        handle_error(ret);
165
 
/*
166
 
 * Now pkey contains "WC42" and data contains Winston's record.
167
 
 */</pre></blockquote>
168
 
<p>To create a secondary index to a Berkeley DB database, open the database that
169
 
is to become a secondary index normally, then pass it as the "secondary"
170
 
argument to the <a href="../../api_c/db_associate.html">DB-&gt;associate</a> interface for some primary database.
171
 
<p>After a <a href="../../api_c/db_associate.html">DB-&gt;associate</a> call is made, the secondary indices become
172
 
alternate interfaces to the primary database.  All updates to the
173
 
primary will be automatically reflected in each secondary index that
174
 
has been associated with it.  All get operations using the
175
 
<a href="../../api_c/db_get.html">DB-&gt;get</a> or <a href="../../api_c/dbc_get.html">DBcursor-&gt;c_get</a> interfaces on the secondary index
176
 
return the primary datum associated with the specified (or otherwise
177
 
current, in the case of cursor operations) secondary key.  The
178
 
<a href="../../api_c/db_get.html">DB-&gt;pget</a> and <a href="../../api_c/dbc_get.html">DBcursor-&gt;c_pget</a> interfaces also become usable;
179
 
these behave just like <a href="../../api_c/db_get.html">DB-&gt;get</a> and <a href="../../api_c/dbc_get.html">DBcursor-&gt;c_get</a>, but return
180
 
the primary key in addition to the primary datum, for those applications
181
 
that need it as well.
182
 
<p>Cursor get operations on a secondary index perform as expected; although
183
 
the data returned will by default be those of the primary database, a
184
 
position in the secondary index is maintained normally, and records will
185
 
appear in the order determined by the secondary key and the comparison
186
 
function or other structure of the secondary database.
187
 
<p>Delete operations on a secondary index delete the item from the primary
188
 
database and all relevant secondaries, including the current one.
189
 
<p>Put operations of any kind are forbidden on secondary indices, as there
190
 
is no way to specify a primary key for a newly put item.  Instead, the
191
 
application should use the <a href="../../api_c/dbc_put.html">DBcursor-&gt;c_put</a> or <a href="../../api_c/db_put.html">DB-&gt;put</a> methods
192
 
on the primary database.
193
 
<p>Any number of secondary indices may be associated with a given primary
194
 
database, up to limitations on available memory and the number of open
195
 
file descriptors.
196
 
<p>Note that although Berkeley DB guarantees that updates made using any
197
 
<a href="../../api_c/db_class.html">DB</a> handle with an associated secondary will be reflected in the
198
 
that secondary, associating each primary handle with all the appropriate
199
 
secondaries is the responsibility of the application and is not enforced
200
 
by Berkeley DB.  It is generally unsafe, but not forbidden by Berkeley DB, to modify
201
 
a database that has secondary indices without having those indices open
202
 
and associated.  Similarly, it is generally unsafe, but not forbidden,
203
 
to modify a secondary index directly.  Applications that violate these
204
 
rules face the possibility of outdated or incorrect results if the
205
 
secondary indices are later used.
206
 
<p>If a secondary index becomes outdated for any reason, it should be
207
 
discarded using the <a href="../../api_c/db_remove.html">DB-&gt;remove</a> method and a new one created
208
 
using the <a href="../../api_c/db_associate.html">DB-&gt;associate</a> method.  If a secondary index is no
209
 
longer needed, all of its handles should be closed using the
210
 
<a href="../../api_c/db_close.html">DB-&gt;close</a> method, and then the database should be removed using
211
 
a new database handle and the <a href="../../api_c/db_remove.html">DB-&gt;remove</a> method.
212
 
<p>Closing a primary database handle automatically disassociates all
213
 
secondary database handles associated with it.
214
 
<table width="100%"><tr><td><br></td><td align=right><a href="../../ref/am/close.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../../reftoc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../../ref/am/cursor.html"><img src="../../images/next.gif" alt="Next"></a>
215
 
</td></tr></table>
216
 
<p><font size=1><a href="http://www.sleepycat.com">Copyright Sleepycat Software</a></font>
217
 
</body>
218
 
</html>