Sophie

Sophie

distrib > Mandriva > 2007.0 > x86_64 > media > main-release > by-pkgid > a4c98df40e78f6c892308fd6841f950a > files > 850

lib64db4.2-devel-4.2.52-11mdv2007.0.x86_64.rpm

<!--$Id: second.so,v 1.3 2003/09/25 15:27:52 bostic Exp $-->
<!--Copyright 1997-2003 by Sleepycat Software, Inc.-->
<!--All rights reserved.-->
<!--See the file LICENSE for redistribution information.-->
<html>
<head>
<title>Berkeley DB Reference Guide: Opening secondary key indices</title>
<meta name="description" content="Berkeley DB: An embedded database programmatic toolkit.">
<meta name="keywords" content="embedded,database,programmatic,toolkit,b+tree,btree,hash,hashing,transaction,transactions,locking,logging,access method,access methods,Java,C,C++">
</head>
<body bgcolor=white>
<a name="2"><!--meow--></a>
<table width="100%"><tr valign=top>
<td><h3><dl><dt>Berkeley DB Reference Guide:<dd>Java API Tutorial - Index</dl></h3></td>
<td align=right><a href="../bdb_index/intro.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../toc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../bdb_index/foreign.html"><img src="../../images/next.gif" alt="Next"></a>
</td></tr></table>
<p>
<h3 align=center>Opening secondary key indices</h3>
<p><i>Secondary key indices</i> are used to access a store by a key
other than the primary key.  Recall that the Supplier Number field is the
primary key of the Supplier store.  In this section, the Supplier City
field will be used as a secondary lookup key.  Given a city value, we would
like to be able to find the Suppliers in that city.  Note that more than one
Supplier may be in the same city.</p>
<p>Both stores and indices are database files containing key-value records.
The key of an index record is the secondary key, and its value is the key of
the associated record in the store.  When lookups by secondary key are
performed, the associated record in the store is transparently retrieved by
its primary key and returned to the caller.</p>
<p>Secondary indices are maintained automatically when index key fields (the
City field in this case) are added, modified or removed in the records of the
store.  However, the application must implement a
<a href="../../java/com/sleepycat/bdb/bind/KeyExtractor.html">KeyExtractor</a>
 that extracts the index key
from the store record.</p>
<p>It is useful to contrast opening an index with opening a store (as
described earlier in <a href="../bdb_basic/stores.html">Opening and closing database
stores</a>).</p>
<p><ul type=disc>
<li>A store may be associated with one or more indices.  An index is
always associated with exactly one store.
<li>For an index, a 
<a href="../../java/com/sleepycat/bdb/bind/KeyExtractor.html">KeyExtractor</a>
must be implemented by the application to extract the index key from the record
of its associated store.
<li>Both a store and an index use a 
<a href="../../java/com/sleepycat/db/Db.html">Db</a>
object to store records in a database file.
<li>For stores a 
<a href="../../java/com/sleepycat/bdb/DataStore.html">DataStore</a>
 object is
created which wraps the 
<a href="../../java/com/sleepycat/db/Db.html">Db</a>
 object.  For
indices a 
<a href="../../java/com/sleepycat/bdb/DataIndex.html">DataIndex</a>
 object is created which
wraps the 
<a href="../../java/com/sleepycat/db/Db.html">Db</a>
 object and associates it with
a 
<a href="../../java/com/sleepycat/bdb/DataStore.html">DataStore</a>
 and a
<a href="../../java/com/sleepycat/bdb/bind/KeyExtractor.html">KeyExtractor</a>
.
</ul>
<hr size=1 noshade>
<p>The <b>SampleDatabase</b> class is extended to open the
Supplier-by-City secondary key index.  The following additional imports and
class members are needed.</p>
<blockquote><pre>
<b>import com.sleepycat.bdb.bind.KeyExtractor;
import com.sleepycat.bdb.bind.serial.SerialSerialKeyExtractor;
import com.sleepycat.bdb.DataIndex;
</b>...
public class SampleDatabase
{
    ...
<b>    private static final String SUPPLIER_CITY_INDEX = "supplier_city_index";
    ...
    private DataIndex supplierByCityIndex;
    private SerialFormat cityKeyFormat;
    ...
</b>    public SampleDatabase(String homeDirectory, boolean runRecovery)
        throws DbException, FileNotFoundException
    {
        ...
        int flags = Db.DB_CREATE | Db.DB_AUTO_COMMIT;
        ...
<b>        cityKeyFormat = new SerialFormat(javaCatalog, String.class);
<p>
        KeyExtractor cityExtractor = new SupplierByCityExtractor(
                                                    supplierKeyFormat,
                                                    supplierValueFormat,
                                                    cityKeyFormat);
        Db cityIndexDb = new Db(env, 0);
        cityIndexDb.setFlags(Db.DB_DUPSORT);
        cityIndexDb.open(null, SUPPLIER_CITY_INDEX, null,
                         Db.DB_BTREE, flags, 0);
<p>
        supplierByCityIndex = new DataIndex(supplierStore, cityIndexDb,
                                            cityKeyFormat, cityExtractor);
</b>    }
}
</pre></blockquote>
<p>Opening a secondary key index requires creating a
<a href="../../java/com/sleepycat/bdb/bind/serial/SerialFormat.html">SerialFormat</a>
, a
<a href="../../java/com/sleepycat/bdb/bind/KeyExtractor.html">KeyExtractor</a>
, a
<a href="../../java/com/sleepycat/db/Db.html">Db</a>
 and a 
<a href="../../java/com/sleepycat/bdb/DataIndex.html">DataIndex</a>
.</p>
<p>Like the formats created earlier for keys and values, the
<b>cityKeyFormat</b> is a 
<a href="../../java/com/sleepycat/bdb/bind/serial/SerialFormat.html">SerialFormat</a>
.  Unlike the formats created earlier, it is an example of
creating a format for a Java primitive class, 
<a href="http://java.sun.com/j2se/1.3/docs/api/java/lang/String.html">String</a>
, instead of an application-defined class.  Any serializable class may
be used.</p>
<p>The <b>cityExtractor</b> is an instance of the application class
<b>SupplierByCityExtractor</b>.  This class implements the
<a href="../../java/com/sleepycat/bdb/bind/KeyExtractor.html">KeyExtractor</a>
 interface and will be defined
below.  Recall that <b>supplierKeyFormat</b> and
<b>supplierValueFormat</b>, two of the parameters to its constructor, were
created earlier in <a href="../bdb_basic/stores.html">Opening and closing database
stores</a>.</p>
<p>The <b>cityIndexDb</b> 
<a href="../../java/com/sleepycat/db/Db.html">Db</a>
 object is
created and opened next.  If you compare these statements for opening an index
to the statements we used previously for opening a store, you'll notice only
one difference:  For an index the 
<a href="../../java/com/sleepycat/db/Db.html#setFlags">Db.setFlags</a>
 method is called, while for a store it is not.  The
<a href="../../java/com/sleepycat/db/Db.html#DB_DUPSORT">Db.DB_DUPSORT</a>
 flag is specified to allow
duplicate index keys.  This is how more than one Supplier may be in the same
City.  If this flag is not specified, the default is that the index keys of all
records must be unique.</p>
<p>For a store, duplicate keys are not normally used since a store with
duplicate keys may not have any associated indices.  If store keys are not
unique, there is no way for a secondary key to reference a specific record in
the store.</p>
<p>Note that 
<a href="../../java/com/sleepycat/db/Db.html#DB_DUPSORT">Db.DB_DUPSORT</a>
 and not
<a href="../../java/com/sleepycat/db/Db.html#DB_DUP">Db.DB_DUP</a>
 was specified.  Sorted duplicates
are always used for indices rather than unsorted duplicates, since sorting
enables optimized equality joins.</p>
<p>Finally, the <b>supplierByCityIndex</b>
<a href="../../java/com/sleepycat/bdb/DataIndex.html">DataIndex</a>
 object is created from the
supplier store, index Db, index key format, and key extractor.  How to use the
index to access records will be shown in a later section.</p>
<hr size=1 noshade>
<p>The application-defined <b>SupplierByCityExtractor</b> class is shown
below.  It was used above to create the <b>cityExtractor</b> object.</p>
<blockquote><pre>
public class SampleDatabase
{
<b>    private static class SupplierByCityExtractor
        extends SerialSerialKeyExtractor
    {
        private SupplierByCityExtractor(SerialFormat primaryKeyFormat,
                                        SerialFormat valueFormat,
                                        SerialFormat indexKeyFormat)
        {
            super(primaryKeyFormat, valueFormat, indexKeyFormat);
        }
<p>
        public Object extractIndexKey(Object primaryKeyInput,
                                      Object valueInput)
            throws IOException
        {
            SupplierValue supplierValue = (SupplierValue) valueInput;
            return supplierValue.getCity();
        }
<p>
        public Object clearIndexKey(Object valueInputOutput)
            throws IOException
        {
            throw new UnsupportedOperationException();
        }
    }
</b>}
</pre></blockquote>
<p>In general, a key extractor class must implement the
<a href="../../java/com/sleepycat/bdb/bind/KeyExtractor.html">KeyExtractor</a>
 interface.  This interface
has methods that operate on the record data as raw bytes.  In practice, it is
easiest to use an abstract base class that performs the conversion of record
data to and from the format defined for the store's key and value.  The base
class implements the 
<a href="../../java/com/sleepycat/bdb/bind/KeyExtractor.html">KeyExtractor</a>
 interface
and has abstract methods that must be implemented in turn by the application.</p>
<p>In this example the 
<a href="../../java/com/sleepycat/bdb/bind/serial/SerialSerialKeyExtractor.html">SerialSerialKeyExtractor</a>
 base class is used because the store record uses the
serial format for both its key and its value.  The abstract methods of this
class have key and value parameters of type 
<a href="http://java.sun.com/j2se/1.3/docs/api/java/lang/Object.html">Object</a>
which are automatically converted to and from the raw record data by the base
class.</p>
<p>To perform the conversions properly, the key extractor must be aware of
all three formats involved:  the key format of the store record, the value
format of the store record, and the key format of the index record.  The
<a href="../../java/com/sleepycat/bdb/bind/serial/SerialSerialKeyExtractor.html">SerialSerialKeyExtractor</a>
 constructor
is given these three formats as parameters.</p>
<p>The 
<a href="../../java/com/sleepycat/bdb/bind/serial/SerialSerialKeyExtractor.html#extractIndexKey">SerialSerialKeyExtractor.extractIndexKey</a>
 method is given the key and value of the store record as
parameters, and it returns the key of the index record.  In this example, the
index key is a field in the store record value.  Since the record value is
known to be a <b>SupplierValue</b> object, it is cast to that class and the
city field is returned.</p>
<p>Note that the <b>primaryKeyInput</b> parameter is not used in the
example.  This parameter is needed only when an index key is derived from the
key of the store record.  Normally an index key is derived only from the store
record value, but it may be derived from the key, value or both.</p>
<p>The 
<a href="../../java/com/sleepycat/bdb/bind/serial/SerialSerialKeyExtractor.html#clearIndexKey">SerialSerialKeyExtractor.clearIndexKey</a>
 method is implemented only for foreign keys under certain
conditions and will be described in the next section.  In the
<b>SupplierByCityExtractor</b> class this method always throws an
exception since it should never be called.</p>
<hr size=1 noshade>
<p>The following getter methods return the index key format and index object
for use by other classes in the example program.  The format is used for
creating bindings to the index key.  The index object is used to create Java
collections for accessing records via their secondary keys.</p>
<blockquote><pre>
public class SampleDatabase
{
    ...
<b>    public final SerialFormat getCityKeyFormat()
    {
        return cityKeyFormat;
    }
<p>
    public final DataIndex getSupplierByCityIndex()
    {
        return supplierByCityIndex;
    }
</b>}
</pre></blockquote>
<hr size=1 noshade>
<p>If you're wondering why this section does not include an example of how
to close a 
<a href="../../java/com/sleepycat/bdb/DataIndex.html">DataIndex</a>
, that is because
indices are closed automatically when their associated
<a href="../../java/com/sleepycat/bdb/DataStore.html">DataStore</a>
 is closed.  There is no way to
close an index explicitly without closing the store.</p>
<table width="100%"><tr><td><br></td><td align=right><a href="../bdb_index/intro.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../toc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../bdb_index/foreign.html"><img src="../../images/next.gif" alt="Next"></a>
</td></tr></table>
<p><font size=1><a href="../../sleepycat/legal.html">Copyright (c) 1996-2003</a> <a href="http://www.sleepycat.com">Sleepycat Software, Inc.</a> - All rights reserved.</font>
</body>
</html>