//soft-upgrade mode), then we do not want to collect any
//information about trigger action columns. The collection and
//usage of trigger action columns was introduced in 10.7 DERBY-1482
for (int i = 0; i < cols.length; i++)
{
ColumnReference ref = (ColumnReference) cols[i];
/*
** Only occurrences of those OLD/NEW transition tables/variables
** are of interest here. There may be intermediate nodes in the
** parse tree that have its own RCL which contains copy of
** column references(CR) from other nodes. e.g.:
**
** CREATE TRIGGER tt
** AFTER INSERT ON x
** REFERENCING NEW AS n
** FOR EACH ROW
** INSERT INTO y VALUES (n.i), (999), (333);
**
** The above trigger action will result in InsertNode that
** contains a UnionNode of RowResultSetNodes. The UnionNode
** will have a copy of the CRs from its left child and those CRs
** will not have its beginOffset set which indicates they are
** not relevant for the conversion processing here, so we can
** safely skip them.
*/
if (ref.getBeginOffset() == -1)
{
continue;
}
TableName tableName = ref.getTableNameNode();
if ((tableName == null) ||
((oldReferencingName == null || !oldReferencingName.equals(tableName.getTableName())) &&
(newReferencingName == null || !newReferencingName.equals(tableName.getTableName()))))
{
continue;
}
if (tableName.getBeginOffset() == -1)
{
continue;
}
checkInvalidTriggerReference(tableName.getTableName(),
oldReferencingName,
newReferencingName,
triggerEventMask);
String colName = ref.getColumnName();
ColumnDescriptor triggerColDesc;
//Following will catch the case where an invalid column is
//used in trigger action through the REFERENCING clause. The
//following tigger is trying to use oldt.c13 but there is no
//column c13 in trigger table table1
//CREATE TRIGGER tr1 AFTER UPDATE OF c12 ON table1
// REFERENCING OLD AS oldt NEW AS newt
// FOR EACH ROW UPDATE table2 SET c24=oldt.c14567;
if ((triggerColDesc = triggerTableDescriptor.getColumnDescriptor(colName)) ==
null) {
throw StandardException.newException(
SQLState.LANG_COLUMN_NOT_FOUND, tableName+"."+colName);
}
if (in10_7_orHigherVersion) {
int triggerColDescPosition = triggerColDesc.getPosition();
triggerColsAndTriggerActionCols[triggerColDescPosition-1]=triggerColDescPosition;
triggerActionColsOnly[triggerColDescPosition-1]=triggerColDescPosition;
referencedColsInTriggerAction[triggerColDescPosition-1] = triggerColDescPosition;
}
}
} else {
//We are here because we have come across an invalidated trigger
//which is being fired. This code gets called for such a trigger
//only if it is a row level trigger with REFERENCEs clause
//
// referencedColsInTriggerAction can be null if trigger action
// does not use any columns through REFERENCING clause. This can
// happen when we are coming here through ALTER TABLE DROP COLUMN
// and the trigger being rebuilt does not use any columns through
// REFERENCING clause. DERBY-4887
if (referencedCols != null && referencedColsInTriggerAction != null){
for (int i = 0; i < referencedColsInTriggerAction.length; i++)
{
triggerColsAndTriggerActionCols[referencedColsInTriggerAction[i]-1] = referencedColsInTriggerAction[i];
}
}
}
//Now that we know what columns we need for trigger columns and
//trigger action columns, we can get rid of remaining -1 entries
//for the remaining columns from trigger table.
//eg
//CREATE TRIGGER tr1 AFTER UPDATE OF c12 ON table1
// REFERENCING OLD AS oldt NEW AS newt
// FOR EACH ROW UPDATE table2 SET c24=oldt.c14;
//For the above trigger, before the justTheRequiredColumns() call,
//the content of triggerColsAndTriggerActionCols array were as
//follows [-1, 2, -1, 4, -1]
//After the justTheRequiredColumns() call below,
//triggerColsAndTriggerActionCols will have [2,4]. What this means
//that, at run time, during trigger execution, these are the only
//2 column positions that will be read into memory from the
//trigger table. The columns in other column positions are not
//needed for trigger execution.
triggerColsAndTriggerActionCols = justTheRequiredColumns(
triggerColsAndTriggerActionCols, triggerTableDescriptor);
//This is where we do the actual transformation of trigger action
//sql. An eg of that is
// DELETE FROM t WHERE c = old.c
// turns into
// DELETE FROM t WHERE c = org.apache.derby.iapi.db.Factory::
// getTriggerExecutionContext().getOldRow().
// getInt(columnNumberFor'C'inRuntimeResultset)
// or
// DELETE FROM t WHERE c in (SELECT c FROM OLD)
// turns into
// DELETE FROM t WHERE c in
// (SELECT c FROM new TriggerOldTransitionTable OLD)
for (int i = 0; i < cols.length; i++)
{
ColumnReference ref = (ColumnReference) cols[i];
/*
** Only occurrences of those OLD/NEW transition tables/variables
** are of interest here. There may be intermediate nodes in the
** parse tree that have its own RCL which contains copy of
** column references(CR) from other nodes. e.g.:
**
** CREATE TRIGGER tt
** AFTER INSERT ON x
** REFERENCING NEW AS n
** FOR EACH ROW
** INSERT INTO y VALUES (n.i), (999), (333);
**
** The above trigger action will result in InsertNode that
** contains a UnionNode of RowResultSetNodes. The UnionNode
** will have a copy of the CRs from its left child and those CRs
** will not have its beginOffset set which indicates they are
** not relevant for the conversion processing here, so we can
** safely skip them.
*/
if (ref.getBeginOffset() == -1)
{
continue;
}
TableName tableName = ref.getTableNameNode();
if ((tableName == null) ||
((oldReferencingName == null || !oldReferencingName.equals(tableName.getTableName())) &&
(newReferencingName == null || !newReferencingName.equals(tableName.getTableName()))))
{
continue;
}
int tokBeginOffset = tableName.getBeginOffset();
int tokEndOffset = tableName.getEndOffset();
if (tokBeginOffset == -1)
{
continue;
}
String colName = ref.getColumnName();
int columnLength = ref.getEndOffset() - ref.getBeginOffset() + 1;
newText.append(triggerDefinition.substring(start, tokBeginOffset-actionOffset));
int colPositionInRuntimeResultSet = -1;
ColumnDescriptor triggerColDesc = triggerTableDescriptor.getColumnDescriptor(colName);
//DERBY-5121 We can come here if the column being used in trigger