use of org.apache.derby.impl.sql.compile.TableName in project derby by apache.
the class DataDictionaryImpl method getTransitionVariables.
/**
* Get all columns that reference transition variables in triggers.
* The columns should be returned in the same order as in the SQL text.
*
* @param node the node in which to look for transition variables
* @param oldReferencingName the name of the old transition variable
* @param newReferencingName the name of the new transition variable
* @return all references to transition variables
*/
private static SortedSet<ColumnReference> getTransitionVariables(Visitable node, String oldReferencingName, String newReferencingName) throws StandardException {
// First get all column references.
SortedSet<ColumnReference> refs = ((QueryTreeNode) node).getOffsetOrderedNodes(ColumnReference.class);
// Then remove all that are not referencing a transition variable.
Iterator<ColumnReference> it = refs.iterator();
while (it.hasNext()) {
TableName tableName = it.next().getQualifiedTableName();
if (!isTransitionVariable(tableName, oldReferencingName, newReferencingName)) {
it.remove();
}
}
// variables.
return refs;
}
use of org.apache.derby.impl.sql.compile.TableName in project derby by apache.
the class DataDictionaryImpl method examineTriggerNodeAndCols.
/**
* Get the trigger action string associated with the trigger after the
* references to old/new transition tables/variables in trigger action
* sql provided by CREATE TRIGGER have been transformed eg
* 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)
*
* @param actionStmt This is needed to get access to the various nodes
* generated by the Parser for the trigger action sql. These nodes will be
* used to find REFERENCEs column nodes.
*
* @param oldReferencingName The name specified by the user for REFERENCEs
* to old row columns
*
* @param newReferencingName The name specified by the user for REFERENCEs
* to new row columns
*
* @param triggerDefinition The original trigger action text provided by
* the user during CREATE TRIGGER time.
*
* @param referencedCols Trigger is defined on these columns (will be null
* in case of INSERT AND DELETE Triggers. Can also be null for DELETE
* Triggers if UPDATE trigger is not defined on specific column(s))
*
* @param referencedColsInTriggerAction what columns does the trigger
* action reference through old/new transition variables (may be null)
*
* @param actionOffset offset of start of action clause
*
* @param triggerTableDescriptor Table descriptor for trigger table
*
* @param triggerEventMask TriggerDescriptor.TRIGGER_EVENT_XXX
*
* @param createTriggerTime True if here for CREATE TRIGGER,
* false if here because an invalidated row level trigger with
* REFERENCEd columns has been fired and hence trigger action
* sql associated with SPSDescriptor may be invalid too.
*
* @return Transformed trigger action sql
* @throws StandardException
*/
public int[] examineTriggerNodeAndCols(Visitable actionStmt, String oldReferencingName, String newReferencingName, String triggerDefinition, int[] referencedCols, int[] referencedColsInTriggerAction, int actionOffset, TableDescriptor triggerTableDescriptor, int triggerEventMask, boolean createTriggerTime, List<int[]> replacements) throws StandardException {
// If we are dealing with database created in 10.8 and prior,
// then we must be in soft upgrade mode. For such databases,
// we want to generate trigger action sql which assumes that
// all columns are getting read from the trigger table. We
// need to do this to maintain backward compatibility.
boolean in10_9_orHigherVersion = checkVersion(DataDictionary.DD_VERSION_DERBY_10_9, null);
StringBuilder newText = new StringBuilder();
int start = 0;
// Total Number of columns in the trigger table
int numberOfColsInTriggerTable = triggerTableDescriptor.getNumberOfColumns();
// The purpose of following array(triggerColsAndTriggerActionCols)
// is to identify all the trigger columns and all the columns from
// the trigger action which are referenced though old/new
// transition variables(in other words, accessed through the
// REFERENCING clause section of CREATE TRIGGER sql). This array
// will be initialized to -1 at the beginning. By the end of this
// method, all the columns referenced by the trigger action
// through the REFERENCING clause and all the trigger columns will
// have their column positions in the trigger table noted in this
// array.
// 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 trigger above, triggerColsAndTriggerActionCols will
// finally have [-1,2,-1,4,-1] This list will include all the
// columns that need to be fetched into memory during trigger
// execution. All the columns with their entries marked -1 will
// not be read into memory because they are not referenced in the
// trigger action through old/new transition variables and they are
// not recognized as trigger columns.
int[] triggerColsAndTriggerActionCols = new int[numberOfColsInTriggerTable];
/**
* It identifies all the trigger action columns and is initialized to -1.
*/
int[] triggerActionColsOnly = new int[numberOfColsInTriggerTable];
java.util.Arrays.fill(triggerActionColsOnly, -1);
if (referencedCols == null) {
// FOR EACH ROW UPDATE table2 SET c24=oldt.c14;
for (int i = 0; i < numberOfColsInTriggerTable; i++) {
triggerColsAndTriggerActionCols[i] = i + 1;
}
} else {
// This means that this row level trigger is an UPDATE trigger
// defined on specific column(s).
java.util.Arrays.fill(triggerColsAndTriggerActionCols, -1);
for (int i = 0; i < referencedCols.length; i++) {
// Make a note of this trigger column's column position in
// triggerColsAndTriggerActionCols. This will tell us that
// this column needs to be read in when the trigger fires.
// eg for the CREATE TRIGGER below, we will make a note of
// column c12's position in triggerColsAndTriggerActionCols
// 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;
triggerColsAndTriggerActionCols[referencedCols[i] - 1] = referencedCols[i];
}
}
if (referencedColsInTriggerAction != null) {
for (int i = 0; i < referencedColsInTriggerAction.length; i++) {
if (referencedColsInTriggerAction[i] > 0)
triggerColsAndTriggerActionCols[referencedColsInTriggerAction[i] - 1] = referencedColsInTriggerAction[i];
}
}
/* we need to sort on position in string, beetle 4324
*/
SortedSet<ColumnReference> refs = getTransitionVariables(actionStmt, oldReferencingName, newReferencingName);
if (createTriggerTime) {
// usage of trigger action columns again in 10.9
for (ColumnReference ref : refs) {
TableName tableName = ref.getQualifiedTableName();
checkInvalidTriggerReference(tableName.getTableName(), oldReferencingName, newReferencingName, triggerEventMask);
String colName = ref.getColumnName();
ColumnDescriptor triggerColDesc;
// 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_9_orHigherVersion) {
int triggerColDescPosition = triggerColDesc.getPosition();
triggerColsAndTriggerActionCols[triggerColDescPosition - 1] = triggerColDescPosition;
triggerActionColsOnly[triggerColDescPosition - 1] = triggerColDescPosition;
referencedColsInTriggerAction[triggerColDescPosition - 1] = triggerColDescPosition;
}
}
} else {
// REFERENCING clause. DERBY-4887
if (referencedCols != null && referencedColsInTriggerAction != null) {
for (int i = 0; i < referencedColsInTriggerAction.length; i++) {
triggerColsAndTriggerActionCols[referencedColsInTriggerAction[i] - 1] = referencedColsInTriggerAction[i];
}
}
}
Arrays.sort(triggerColsAndTriggerActionCols);
// 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);
return triggerColsAndTriggerActionCols;
}
use of org.apache.derby.impl.sql.compile.TableName in project derby by apache.
the class SetConstraintsConstantAction method executeConstantAction.
/**
* This is the guts of the execution time logic for SET CONSTRAINT.
*
* @param activation
*
* @see ConstantAction#executeConstantAction
*
* @exception StandardException Thrown on failure
*/
public void executeConstantAction(Activation activation) throws StandardException {
final LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
final DataDictionary dd = lcc.getDataDictionary();
final List<String> boundConstraints = new ArrayList<String>();
if (constraints != null) {
for (TableName c : constraints) {
final SchemaDescriptor sd = dd.getSchemaDescriptor(c.getSchemaName(), lcc.getTransactionExecute(), true);
final ConstraintDescriptor cd = dd.getConstraintDescriptor(c.getTableName(), sd.getUUID());
if (cd == null) {
throw StandardException.newException(SQLState.LANG_OBJECT_NOT_FOUND, "CONSTRAINT", c.getFullSQLName());
}
final String bound = IdUtil.normalToDelimited(sd.getSchemaName()) + "." + IdUtil.normalToDelimited(cd.getConstraintName());
if (boundConstraints.contains(bound)) {
throw StandardException.newException(SQLState.LANG_DB2_DUPLICATE_NAMES, cd.getConstraintName(), bound);
} else {
boundConstraints.add(bound);
}
if (deferred && !cd.deferrable()) {
throw StandardException.newException(SQLState.LANG_SET_CONSTRAINT_NOT_DEFERRABLE, cd.getConstraintName());
}
lcc.setConstraintDeferred(activation, cd, deferred);
}
} else {
lcc.setDeferredAll(activation, deferred);
}
}
use of org.apache.derby.impl.sql.compile.TableName in project derby by apache.
the class DataDictionaryImpl method getTriggerActionString.
public String getTriggerActionString(Visitable actionStmt, String oldReferencingName, String newReferencingName, String triggerDefinition, int[] referencedCols, int[] referencedColsInTriggerAction, int actionOffset, TableDescriptor triggerTableDescriptor, int triggerEventMask, boolean createTriggerTime, List<int[]> replacements, int[] cols) throws StandardException {
boolean in10_9_orHigherVersion = checkVersion(DataDictionary.DD_VERSION_DERBY_10_9, null);
StringBuilder newText = new StringBuilder();
int start = 0;
// Total Number of columns in the trigger table
int numberOfColsInTriggerTable = triggerTableDescriptor.getNumberOfColumns();
int[] triggerColsAndTriggerActionCols = new int[numberOfColsInTriggerTable];
SortedSet<ColumnReference> refs = getTransitionVariables(actionStmt, oldReferencingName, newReferencingName);
triggerColsAndTriggerActionCols = cols;
// (SELECT c FROM new TriggerOldTransitionTable OLD)
for (ColumnReference ref : refs) {
TableName tableName = ref.getQualifiedTableName();
int tableBeginOffset = tableName.getBeginOffset() - actionOffset;
String colName = ref.getColumnName();
// Add whatever we've seen after the previous replacement.
newText.append(triggerDefinition, start, tableBeginOffset);
int colPositionInRuntimeResultSet = -1;
ColumnDescriptor triggerColDesc = triggerTableDescriptor.getColumnDescriptor(colName);
// column in the trigger table.
if (triggerColDesc == null) {
throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND, tableName + "." + colName);
}
int colPositionInTriggerTable = triggerColDesc.getPosition();
// is 2. That is what the following code is doing.
if (in10_9_orHigherVersion && triggerColsAndTriggerActionCols != null) {
for (int j = 0; j < triggerColsAndTriggerActionCols.length; j++) {
if (triggerColsAndTriggerActionCols[j] == colPositionInTriggerTable)
colPositionInRuntimeResultSet = j + 1;
}
} else
colPositionInRuntimeResultSet = colPositionInTriggerTable;
// Add the replacement code that accesses a value in the
// transition variable.
final int replacementOffset = newText.length();
newText.append(genColumnReferenceSQL(triggerTableDescriptor, colName, tableName.getTableName(), tableName.getTableName().equals(oldReferencingName), colPositionInRuntimeResultSet));
start = ref.getEndOffset() + 1 - actionOffset;
if (replacements != null) {
// Record that we have made a change.
replacements.add(new int[] { // offset to replaced text
tableBeginOffset, // offset to token after replaced text
start, // offset to replacement
replacementOffset, // offset to token after replacement
newText.length() });
}
}
// By this point, we are finished transforming the trigger action if
// it has any references to old/new transition variables.
newText.append(triggerDefinition, start, triggerDefinition.length());
return newText.toString();
}
Aggregations