Class DBAnnotatedObject
- Direct Known Subclasses:
AbstractDBTraceSpaceBasedManager.DBTraceSpaceEntry,AbstractDBTraceSymbol,DBTraceAddressPropertyManager.DBTraceAddressPropertyEntry,DBTraceCodeManager.DBTraceCodePrototypeEntry,DBTraceEquate,DBTraceGuestPlatform,DBTraceGuestPlatform.DBTraceGuestLanguage,DBTraceGuestPlatformMappedRange,DBTraceMemoryBufferEntry,DBTraceObject,DBTraceObjectManager.DBTraceObjectSchemaEntry,DBTraceOverlaySpaceAdapter.DBTraceOverlaySpaceEntry,DBTraceRegisterContextSpace.DBTraceRegisterEntry,DBTraceSnapshot,DBTraceStaticMapping,DBTraceSymbolManager.DBTraceVariableStorageEntry,DBTreeRecord
DBRecord
Essentially, this is a data access object (DAO) for Ghidra's custom database engine. Not all
object fields necessarily have a corresponding database field. Instead, those fields are
annotated, and various methods are provided for updating the record, and conversely, re-loading
fields from the record. These objects are managed using a DBCachedObjectStore. An example
object definition:
interface Person {
// ...
}
@DBAnnotatedObjectInfo(version = 1)
public class DBPerson extends DBAnnotatedObject implements Person {
public static final String TABLE_NAME = "Person"; // Conventionally defined here
// Best practice is to define column names, then use in annotations
static final String NAME_COLUMN_NAME = "Name";
static final String ADDRESS_COLUMN_NAME = "Address";
// Column handles
@DBAnnotatedColumn(NAME_COLUMN_NAME)
static DBObjectColumn NAME_COLUMN;
@DBAnnotatedColumn(ADDRESS_COLUMN_NAME)
static DBObjectColumn ADDRESS_COLUMN;
// Column-backed fields
@DBAnnotatedField(column = NAME_COLUMN_NAME, indexed = true)
private String name;
@DBAnnotatedField(column = ADDRESS_COLUMN_NAME)
private String address;
DBPerson(DBCachedObjectStore<DBPerson> store, DBRecord record) {
super(store, record);
}
// Not required, but best practice
private void set(String name, String address) {
this.name = name;
this.address = address;
update(NAME_COLUMN, ADDRESS_COLUMN);
}
// ... other methods, getters, setters
}
See DBCachedObjectStoreFactory for example code that uses the example DBPerson
class.
All realizations of DBAnnotatedObject must be annotated with
DBAnnotatedObjectInfo. This, along with the field annotations, are used to derive the
table schema. Note the inclusion of a TABLE_NAME field. It is not required, nor is it
used implicitly. It's included in this example as a manner of demonstrating best practice. When
instantiating the object store, the field is used to provide the table name.
Next, we define the column names. These are not required nor used implicitly, but using literal strings in the column annotations is discouraged. Next, we declare variables to receive column handles. These are essentially the column numbers, but we have a named handle for each. They are initialized automatically the first time a store is created for this class.
Next we declare the variables representing the actual column values. Their initialization varies
depending on how the object is instantiated. When creating a new object, the fields remain
uninitialized. In some cases, it may be appropriate to provide an initial (default) value in the
usual fashion, e.g., private String address = "123 Pine St."; In this case, the
corresponding database field of the backing record is implicitly initialized upon creation. If
the object is being loaded from a table, its fields are initialized with values from its backing
record.
Next we define the constructor. There are no requirements on its signature, but it must call
super, so it likely takes its
containing store and its backing record. Having the same signature as its super constructor
allows the store to be created using a simple method reference, e.g., DBPerson::new.
Additional user-defined parameters may be accepted. To pass such parameters, a lambda is
recommended when creating the object store.
Finally, we demonstrate how to update the record. The record is not implicitly updated
by direct modification of an annotated field. All setters must call
update(DBObjectColumn...) after updating a field. A common practice, especially when the
object will have all its fields set at once, is to include a set method that initializes
the fields and updates the record in one update(DBObjectColumn...).
Note that there is no way to specify the primary key. For object stores, the primary key is
always the object id, and its type is always long.
-
Field Summary
Fields inherited from class ghidra.program.database.DatabaseObject
key -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedDBAnnotatedObject(DBCachedObjectStore<?> store, DBRecord record) The object constructor -
Method Summary
Modifier and TypeMethodDescriptionprotected booleanprotected voidprotected voidprotected voiddoWrite(DBObjectColumn column) protected voidfresh(boolean created) Extension point: Called when the object's fields are populated.Get an opaque unique id for this object, whose hash is immutablebooleanCheck if this object has been deletedprotected booleanrefresh()Tells the object to refresh its state from the database.protected booleanTells the object to refresh its state from the database using the specified record if not null.protected voidupdate(DBObjectColumn column) 1-arity version ofupdate(DBObjectColumn...)protected voidupdate(DBObjectColumn... columns) Write the given columns into the record and update the tableprotected voidupdate(DBObjectColumn col1, DBObjectColumn col2) 2-arity version ofupdate(DBObjectColumn...)protected voidupdate(DBObjectColumn col1, DBObjectColumn col2, DBObjectColumn col3) 3-arity version ofupdate(DBObjectColumn...)Methods inherited from class ghidra.program.database.DatabaseObject
checkDeleted, checkIsValid, checkIsValid, getKey, isDeleted, isInvalid, keyChanged, setDeleted, setInvalid, validate
-
Constructor Details
-
DBAnnotatedObject
The object constructor- Parameters:
store- the store containing this objectrecord- the record backing this object
-
-
Method Details
-
getObjectKey
Get an opaque unique id for this object, whose hash is immutable- Returns:
- the opaque object id
-
doWrite
-
update
1-arity version ofupdate(DBObjectColumn...)- Parameters:
column- the column
-
update
2-arity version ofupdate(DBObjectColumn...)- Parameters:
col1- a columncol2- another column
-
update
3-arity version ofupdate(DBObjectColumn...)- Parameters:
col1- a columncol2- another columncol3- another column
-
update
Write the given columns into the record and update the table- Parameters:
columns- the columns to update
-
doUpdateAll
- Throws:
IOException
-
doUpdated
- Throws:
IOException
-
fresh
Extension point: Called when the object's fields are populated.This provides an opportunity for the object to initialize any non-database-backed fields that depend on the database-backed fields. Note that its use may indicate a situation better solved by a custom
DBCachedObjectStoreFactory.DBFieldCodec. If both the database-backed and non-database-backed fields are used frequently, then a codec may not be indicated. If the database-backed fields are only used in this method or to encode another frequently-used field, then a codec is likely better.For a new object, the database-backed fields remain at their initial values. They will be saved after this method returns, so they may be further initialized with custom logic.
For an object loaded from the database, the database-backed fields are already populated from the record when this method is called. They are not automatically saved after this method returns. This method should not further initialize database-backed fields in this case.
- Parameters:
created-truewhen object is being created, orfalsewhen it is being loaded.- Throws:
IOException- if further initialization fails.
-
refresh
protected boolean refresh()Description copied from class:DatabaseObjectTells the object to refresh its state from the database.- Specified by:
refreshin classDatabaseObject- Returns:
- true if the object was able to refresh itself. Return false if the object was deleted. Objects that extend this class must implement a refresh method. If an object can never refresh itself, then it should always return false.
-
refresh
Description copied from class:DatabaseObjectTells the object to refresh its state from the database using the specified record if not null. NOTE: The default implementation ignores the record and invokes refresh(). Implementations of this method must take care if multiple database tables are used since the record supplied could correspond to another object. In some cases it may be best not to override this method or ignore the record provided.- Overrides:
refreshin classDatabaseObject- Parameters:
rec- valid record associated with object's key (optional, may be null to force record lookup or other refresh technique)- Returns:
- true if the object was able to refresh itself. Return false if record is null and object was deleted. Objects that extend this class must implement a refresh method. If an object can never refresh itself, then it should always return false.
-
doRefresh
- Throws:
IOException
-
isDeleted
public boolean isDeleted()Check if this object has been deleted- Returns:
- true if deleted
- See Also:
-
getTableName
-