// Update protected override void InternalExecuteUpdate(Program program, IRow oldRow, IRow newRow, BitArray valueFlags, bool checkConcurrency, bool uncheckedValue) { base.InternalExecuteUpdate(program, oldRow, newRow, valueFlags, checkConcurrency, uncheckedValue); if (PropagateUpdate) { int columnIndex; for (int index = 1; index < Nodes.Count; index++) { Schema.TableVarColumn column = TableVar.Columns[_extendColumnOffset + index - 1]; if (column.ColumnType == Schema.TableVarColumnType.Stored) { columnIndex = newRow.DataType.Columns.IndexOfName(column.Column.Name); if (columnIndex >= 0) { TableNode tableNode = Nodes[index] as TableNode; if (tableNode == null) { ExtractRowNode extractRowNode = Nodes[index] as ExtractRowNode; if (extractRowNode != null) { tableNode = (TableNode)extractRowNode.Nodes[0]; } } if (tableNode == null) { throw new RuntimeException(RuntimeException.Codes.InternalError, "Could not determine update path for extend column."); } bool referencesUpdatedColumn = ReferencesUpdatedColumn(tableNode, valueFlags); // If the value is a row // If the newValue is nil // If the oldValue is not nil // delete the table node // else // If the oldValue is nil // insert the row // else // update the row // If the value is a table // If the newValue is nil // If the oldValue is not nil // delete all rows // else // If the oldValue is nil // insert all rows // else // foreach row in oldvalue // if there is a corresponding row in new value by the clustering key // update the row // else // delete the row // for each row in newvalue // if there is no corresponding row in old value by the clustering key // insert the row if (column.DataType is Schema.IRowType) { IRow oldValue = (IRow)oldRow.GetValue(columnIndex); IRow newValue = (IRow)newRow.GetValue(columnIndex); if (newValue.IsNil) { if (!oldValue.IsNil) { PushRow(program, oldRow); try { tableNode.Delete(program, oldValue, checkConcurrency, uncheckedValue); } finally { PopRow(program); } } } else { if (oldValue.IsNil) { PushRow(program, newRow); try { tableNode.Insert(program, null, newValue, null, uncheckedValue); } finally { PopRow(program); } } else { if (referencesUpdatedColumn) { PushRow(program, oldRow); try { tableNode.Delete(program, oldValue, checkConcurrency, uncheckedValue); } finally { PopRow(program); } PushRow(program, newRow); try { tableNode.Insert(program, null, newValue, null, uncheckedValue); } finally { PopRow(program); } } else { PushRow(program, newRow); try { tableNode.Update(program, oldValue, newValue, null, checkConcurrency, uncheckedValue); } finally { PopRow(program); } } } } } else { TableValue oldValue = (TableValue)oldRow.GetValue(columnIndex); TableValue newValue = (TableValue)newRow.GetValue(columnIndex); if (newValue.IsNil) { if (!oldValue.IsNil) { PushRow(program, oldRow); try { using (ITable oldValueCursor = oldValue.OpenCursor()) { while (oldValueCursor.Next()) { using (IRow oldValueCursorRow = oldValueCursor.Select()) { tableNode.Delete(program, oldValueCursorRow, checkConcurrency, uncheckedValue); } } } } finally { PopRow(program); } } } else { if (referencesUpdatedColumn) { PushRow(program, oldRow); try { using (ITable oldValueCursor = oldValue.OpenCursor()) { while (oldValueCursor.Next()) { using (IRow oldValueCursorRow = oldValueCursor.Select()) { tableNode.Delete(program, oldValueCursorRow, checkConcurrency, uncheckedValue); } } } } finally { PopRow(program); } PushRow(program, newRow); try { using (ITable newValueCursor = newValue.OpenCursor()) { while (newValueCursor.Next()) { using (IRow newValueCursorRow = newValueCursor.Select()) { tableNode.Insert(program, null, newValueCursorRow, null, uncheckedValue); } } } } finally { PopRow(program); } } else { PushRow(program, newRow); try { if (oldValue.IsNil) { using (ITable newValueCursor = newValue.OpenCursor()) { while (newValueCursor.Next()) { using (IRow newValueCursorRow = newValueCursor.Select()) { tableNode.Insert(program, null, newValueCursorRow, null, uncheckedValue); } } } } else { using (ITable oldValueCursor = oldValue.OpenCursor()) { using (ITable newValueCursor = newValue.OpenCursor()) { while (oldValueCursor.Next()) { using (IRow oldValueCursorRow = oldValueCursor.Select()) { if (newValueCursor.FindKey(oldValueCursorRow)) { using (IRow newValueCursorRow = newValueCursor.Select()) { tableNode.Update(program, oldValueCursorRow, newValueCursorRow, null, checkConcurrency, uncheckedValue); } } else { tableNode.Delete(program, oldValueCursorRow, checkConcurrency, uncheckedValue); } } } newValueCursor.Reset(); while (newValueCursor.Next()) { using (IRow newValueCursorRow = newValueCursor.Select()) { if (!oldValueCursor.FindKey(newValueCursorRow)) { tableNode.Insert(program, null, newValueCursorRow, null, uncheckedValue); } } } } } } } finally { PopRow(program); } } } } } } } } }