TPhDbKey is an abstract base class which represents a one-to-one correspondence with the concept of a primary key in an SQL database, such as that of the Phobos database. For any TPhDbKey object, there should be one and only one object that we can extract from the database; and this object must be the same whenever we ask for it, even if more objects have been added to the database in the meantime.
A TPhDbKey (or more accurately one of its derived classes, since TPhDbKey is an abstract class) can be passed around, saved, whatever, like any ordinary TObject, without accessing the database.
A TPhKeyPtr takes a TPhDbKey, uses it to get or create its C++ object, and
then acts as a pointer to that object. C++ operators have been overridden, so that you can
use the dereference(*) and pointing (->) operators on this class. TPhKeyPtr is a
template class, with its template parameter indicating what it points to; eg the type
TPhKeyPtr<TPhFECDetector> is a key pointer to an FECDetector. If key is a
TPhDbKey, then the C++ statement:
TPhKeyPtr<TPhFECDetector> mypointer(key);
creates a new key pointer, mypointer, which points to the object referenced by key;
if the object had not previously been accessed, this statement will implicitly go to the
database, and read it from there. After this is done, one could use:
mypointer->GetFEC(3); // Returns a pointer to FEC 3
to access the object pointed to.
Often people will want to write to the database. This requires some care,
since usually a key can only point to specific kinds of objects, and the writers of the
keys and objects must take care to do that correctly (or else the program will probably
crash, or if its nice give some error message). That said, writing to database is a matter
of creating a correspondence between an object and a key. If key is a TPhDbKey
object and runptr is a pointer to the object (here of type TPhRun) we wish to
make key the key of, then:
TPhKeyPtr<TPhRun> newpointer(key,runptr);
will create the correspondence and in the process write the object to the database.
Often we do not know a priori which key corresponds directly to the object we want. We want the 'best' object given certain information; for example, we might want the best set of pedestals that we have for a given run number. This is where the TPhDbKeySelector class comes in. A KeySelector knows how to get the best key based on some information; again it is an abstract base class. Note some crucial differences from a TPhDbKey: for a given selector, the best object could change, if a new, better choice gets added to the database; and more than one selector can correspond to the same object.
Usually a key selector is returned from a specific TPhDbKey's Select
method and doesn't exist very long, but in principle it could be passed around, read and
written, etc., like any other TObject. An example of a common use of a selector:
TPhKeyPtr<TPhPedestalSet>
peds(TPhCalKey::Select("SIPED",2332));
will return a KeyPtr to the 'best' pedestal calibration set it can find for run
2332. Here, the TPhDbKeySelector does not appear directly, but is returned from
TPhCalKey::Select and passed to the constructor of the KeyPtr.
Under the hood, this call will result in at least one and possibly two calls to the database: first the KeySelector class will get called to query the database to find the best key, which it will pass back internally; that key will then get used as above to get the object, which might be cached.
This page maintained by George Heintzelman.