public final class TriggerTracker
extends java.lang.Object
RecordBuffer
to help manage information about database triggers.
This includes determining whether triggers of various types are registered for the buffer at
any given block, and tracking information about the execution and nesting of triggers.
Although the DatabaseTriggerManager
manages much of the same information, it does so in
the context of determining whether or not to fire a given trigger, when such an event has been
requested. However, RecordBuffer
must do some (in some cases non-trivial) setup
work in order to fire a trigger. This class provides a fast way to determine whether this work
is necessary (i.e., a trigger is registered in the current block), or can be avoided.
In order to properly prevent illegal nesting of trigger execution, this class provides a
mechanism to track which triggers currently are executing for the associated buffer. The
RecordBuffer
class still does the "heavy lifting" of enforcing the rules, but the
data about trigger execution is managed here. This includes maintaining a stack of trigger
types currently executing, the names of fields currently involved in assign trigger execution,
and the names of fields whose assign triggers are currently deferred until the end of a batch
assign bracket.
Write triggers must be able to pass a DMO to the trigger procedure or block, which represents
a snapshot of the current record before the first field update was made. This snapshot is
created by RecordBuffer
, but stored here for use when the trigger is fired. The
block depth at which that snapshot was created is stored as well, so that the snapshot can be
deleted in the event the block at that level is undone/rolled back.
Modifier and Type | Field and Description |
---|---|
private java.util.Map<java.lang.String,java.lang.Boolean> |
assignTriggers
Map of property names to enable states for assign triggers
|
private java.lang.Class<? extends Buffer> |
bufferClass
Class of record buffer using this helper
|
private java.util.Deque<java.lang.String> |
fieldStack
Stack of names of fields for which assign triggers currently are executing
|
private DatabaseTriggerManager |
manager
Database trigger manager
|
private Persistable |
oldDMO
DMO representing old buffer state for a write trigger
|
private int |
oldDMODepth
Block level at which old DMO data was copied (when first assignment took place)
|
private java.util.Set<java.lang.String> |
pendingBatchFields
Names of fields assigned in batch pending assign trigger events
|
private int |
state
Bit field indicating enable and check state for all trigger types for current scope
|
private static int |
UNCHECKED
Constant indicating trigger enable status has not been checked
|
Constructor and Description |
---|
TriggerTracker(java.lang.Class<? extends Buffer> bufferClass)
Constructor.
|
Modifier and Type | Method and Description |
---|---|
void |
addPendingBatchField(java.lang.String field)
Add a field (DMO property) name to the set of fields whose assign triggers must be deferred
until the end of the current batch assign mode.
|
void |
clearPendingBatchFields()
Clear the set of field (DMO property) names whose assign triggers were deferred until the
end of the current batch assign mode.
|
void |
commit(int blockDepth)
If we are tracking an old DMO snapshot for a write trigger, and its current block or an
enclosing block is committed, track it at the depth of the current block's parent.
|
Persistable |
getOldDMO()
Get a DMO representing a snapshot of the old buffer state for a write trigger.
|
java.util.Set<java.lang.String> |
getPendingBatchFields()
Get the set of field (DMO property) names whose assign triggers were deferred until the end
of the current batch assign mode.
|
boolean |
isExecuting(DatabaseEventType eventType,
java.lang.Long id)
Determine whether any trigger of the specified type currently is executing, in order to
allow the enforcement of recursion limitations for certain combinations of trigger types.
|
boolean |
isFieldCurrentTrigger(java.lang.String field)
Determine whether the specified field (DMO property) name represents the assign trigger most
recently fired for the associated buffer, in order to allow the enforcement of recursion
limitations.
|
boolean |
isFieldInTrigger(java.lang.String field)
Determine whether the specified field (DMO property) name represents an assign trigger which
currently is executing for the associated buffer, in order to allow the enforcement of
recursion limitations.
|
boolean |
isTriggerEnabled(DatabaseEventType det,
java.lang.String property)
Indicate whether a trigger of the given event type is enabled for the associated buffer
(and property, in the case of an assign trigger), in the current scope.
|
DatabaseEventType |
peekEvent(java.lang.Long id)
Peek the most recent trigger type executed from the stack of trigger types currently
executing for the record from the associated buffer.
|
DatabaseEventType |
popEvent(java.lang.Long id)
Pop the most recent trigger type executed from the stack of trigger types currently
executing for the record in the associated record.
|
java.lang.String |
popField()
Pop the field (DMO property) name of the assign trigger most recently fired from the stack
of field names of assign triggers currently executing for the associated record buffer.
|
boolean |
pushEvent(DatabaseEventType eventType,
java.lang.Long id)
Push a trigger type onto the stack of trigger types currently executing for the record from
the associated record.
|
void |
pushField(java.lang.String field)
Push a field (DMO property) name for an assign trigger about to be executed, onto the stack
of field names of assign triggers currently executing for the associated record buffer.
|
void |
resetOldDMO()
Clear the snapshot of the most recently captured old buffer state for a write trigger and
forget the block level at which it was captured.
|
void |
resetState()
Reset the enable and check state for all trigger types for the current scope.
|
void |
rollback(int blockDepth)
If we are tracking an old DMO snapshot for a write trigger, and the block at which it is
being tracked is undone, reset the snapshot state.
|
void |
setOldDMO(Persistable oldDMO,
int blockLevel)
Set a DMO representing a snapshot of the old buffer state for a write trigger.
|
private static final int UNCHECKED
private DatabaseTriggerManager manager
private int state
private final java.lang.Class<? extends Buffer> bufferClass
private Persistable oldDMO
private int oldDMODepth
private java.util.Map<java.lang.String,java.lang.Boolean> assignTriggers
private java.util.Deque<java.lang.String> fieldStack
private java.util.Set<java.lang.String> pendingBatchFields
public TriggerTracker(java.lang.Class<? extends Buffer> bufferClass)
bufferClass
- Class of record buffer using this helper.public void resetState()
public boolean isTriggerEnabled(DatabaseEventType det, java.lang.String property)
det
- Database event type.property
- Property name, in the case of an assign trigger (not used for other trigger types
and may be null
.true
if a trigger of the given type is enabled, else false
.public boolean pushEvent(DatabaseEventType eventType, java.lang.Long id)
eventType
- Event type of the trigger about to be fired.id
- The id (rowid) of the record.true
if the operation succeeded and false
if the trigger is already
in progress for respective record or eventType == ASSIGN
.public DatabaseEventType popEvent(java.lang.Long id)
finally
, immediately after the trigger is fired.id
- The id (rowid) of the record.null
then there is a programming error (unbalanced push/pop operations).public DatabaseEventType peekEvent(java.lang.Long id)
null
).id
- The id (rowid) of the record.null
if none.public boolean isExecuting(DatabaseEventType eventType, java.lang.Long id)
eventType
- Trigger type to test.true
if a trigger of the current type is executing for the record from
the associated buffer (at any level), else false
.public void pushField(java.lang.String field)
field
- DMO property name associated with an assign trigger.public java.lang.String popField()
finally
block), immediately
after the trigger is fired.java.util.NoSuchElementException
- if the stack is empty (indicates a programming error).public boolean isFieldInTrigger(java.lang.String field)
field
- DMO property name associated with an assign trigger.true
if an assign trigger for the given field is executing for the
associated record buffer (at any level), else false
.public boolean isFieldCurrentTrigger(java.lang.String field)
field
- DMO property name associated with an assign trigger.true
if an assign trigger for the given field is the most recently
fired assign trigger for the associated record buffer, else false
.public void addPendingBatchField(java.lang.String field)
field
- DMO property name whose assign trigger is pending.public java.util.Set<java.lang.String> getPendingBatchFields()
null
,
if none.public void clearPendingBatchFields()
public Persistable getOldDMO()
null
.public void setOldDMO(Persistable oldDMO, int blockLevel)
oldDMO
- Old DMO; must not be null
.blockLevel
- Block level at which oldDMO
was copied from current record.java.lang.NullPointerException
- if oldDMO
is null
.public void resetOldDMO()
public void commit(int blockDepth)
blockDepth
- Current block depth of the buffer at the time of commit.public void rollback(int blockDepth)
blockDepth
- Current block depth, which is compared with the block depth at which the snapshot
(if any) is being tracked.