=== modified file 'src/main/org/h2/command/dml/Update.java'
--- old/src/main/org/h2/command/dml/Update.java	2020-10-15 15:02:18 +0000
+++ new/src/main/org/h2/command/dml/Update.java	2022-11-10 10:41:12 +0000
@@ -5,8 +5,11 @@
  */
 package org.h2.command.dml;
 
+import java.util.BitSet;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
 
@@ -154,6 +157,38 @@
                         }
                     }
                     Row newRow = table.getTemplateRow();
+                    newRow.copy(oldRow);
+                    
+                    HashSet<Integer> onUpdateColumns = null;
+                    if (table.getOnUpdateColumns() != null && !table.getOnUpdateColumns().isEmpty())
+                    {
+                       onUpdateColumns = new HashSet<>();
+                       onUpdateColumns.addAll(table.getOnUpdateColumns());
+                    }
+                    BitSet changed = new BitSet(columns.length);
+                    // TODO: all values are from the 'oldRow'
+                    for (Map.Entry<Column, Expression> entry : setClauseMap.entrySet())
+                    {
+                       Column column = entry.getKey();
+                       Expression newExpr = entry.getValue();
+                       Value newValue;
+                       if (newExpr == ValueExpression.getDefault()) 
+                       {
+                          newValue = table.getDefaultValue(session, column);
+                       }
+                       else 
+                       {
+                          newValue = newExpr.getValue(session);
+                       }
+                       newRow.setValue(column.getColumnId(), newValue);
+                       changed.set(column.getColumnId());
+                       if (onUpdateColumns != null)
+                       {
+                          onUpdateColumns.remove(column.getColumnId());
+                       }
+                    }
+                    boolean setOnUpdate = onUpdateColumns != null && !onUpdateColumns.isEmpty();
+                    /*
                     boolean setOnUpdate = false;
                     for (int i = 0; i < columnCount; i++) {
                         Column column = columns[i];
@@ -171,9 +206,10 @@
                         }
                         newRow.setValue(i, newValue);
                     }
+                    */
                     long key = oldRow.getKey();
                     newRow.setKey(key);
-                    table.validateConvertUpdateSequence(session, newRow);
+                    table.validateConvertUpdateSequence(session, newRow, changed);
                     if (setOnUpdate || updateToCurrentValuesReturnsZero) {
                         setOnUpdate = false;
                         for (int i = 0; i < columnCount; i++) {
@@ -186,7 +222,7 @@
                         if (setOnUpdate) {
                             for (int i = 0; i < columnCount; i++) {
                                 Column column = columns[i];
-                                if (setClauseMap.get(column) == null) {
+                                if (!changed.get(column.getColumnId())) {
                                     if (column.getOnUpdateExpression() != null) {
                                         newRow.setValue(i, table.getOnUpdateValue(session, column));
                                     }
@@ -223,6 +259,7 @@
 
             // the cached row is already updated - we need the old values
             table.updateRows(this, session, rows);
+
             if (table.fireRow()) {
                 for (rows.reset(); rows.hasNext();) {
                     Row o = rows.next();

=== modified file 'src/main/org/h2/pagestore/db/TreeIndex.java'
--- old/src/main/org/h2/pagestore/db/TreeIndex.java	2020-10-15 15:02:18 +0000
+++ new/src/main/org/h2/pagestore/db/TreeIndex.java	2022-11-10 09:45:44 +0000
@@ -5,6 +5,8 @@
  */
 package org.h2.pagestore.db;
 
+import java.util.HashMap;
+
 import org.h2.command.dml.AllColumnsForPlan;
 import org.h2.engine.Session;
 import org.h2.index.BaseIndex;
@@ -25,6 +27,7 @@
 public class TreeIndex extends BaseIndex {
 
     private TreeNode root;
+    private HashMap<Long, TreeNode> byKey = new HashMap<>();
     private final PageStoreTable tableData;
     private long rowCount;
     private boolean closed;
@@ -41,6 +44,7 @@
     @Override
     public void close(Session session) {
         root = null;
+        byKey.clear();
         closed = true;
     }
 
@@ -50,6 +54,7 @@
             throw DbException.throwInternalError();
         }
         TreeNode i = new TreeNode(row);
+        byKey.put(row.getKey(), i);
         TreeNode n = root, x = n;
         boolean isLeft = true;
         while (true) {
@@ -157,6 +162,8 @@
         if (x == null) {
             throw DbException.throwInternalError("not found!");
         }
+        byKey.remove(row.getKey());
+        
         TreeNode n;
         if (x.left == null) {
             n = x.right;
@@ -272,6 +279,13 @@
     }
 
     private TreeNode findFirstNode(SearchRow row, boolean withKey) {
+       TreeNode k = null; 
+       if (withKey)
+       {
+          k = byKey.get(row.getKey());
+          return k;
+       }
+       
         TreeNode x = root, result = x;
         while (x != null) {
             result = x;
@@ -334,6 +348,7 @@
     @Override
     public void truncate(Session session) {
         root = null;
+        byKey.clear();
         rowCount = 0;
     }
 

=== modified file 'src/main/org/h2/res/javadoc.properties'
--- old/src/main/org/h2/res/javadoc.properties	2022-10-26 09:52:05 +0000
+++ new/src/main/org/h2/res/javadoc.properties	2022-11-10 10:24:44 +0000
@@ -1,41 +1,41 @@
-org.h2.tools.Backup=Creates a backup of a database.\nThis tool copies all database files. The database must be closed before using\n this tool. To create a backup while the database is in use, run the BACKUP\n SQL statement. In an emergency, for example if the application is not\n responding, creating a backup using the Backup tool is possible by using the\n quiet mode. However, if the database is changed while the backup is running\n in quiet mode, the backup could be corrupt.
-org.h2.jmx.DatabaseInfoMBean.listSettings=List the database settings.
-org.h2.tools.Server=Starts the H2 Console (web-) server, TCP, and PG server.
-org.h2.jmx.DatabaseInfoMBean.listSessions=List sessions, including the queries that are in\n progress, and locked tables.
-org.h2.jmx.DatabaseInfoMBean.isExclusive=Is the database open in exclusive mode?
+org.h2.jmx.DatabaseInfoMBean=Information and management operations for the given database.
 org.h2.jmx.DatabaseInfoMBean.getCacheSize=The current cache size in KB.
-org.h2.tools.DeleteDbFiles.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]   Print the list of options\n[-dir <dir>]      The directory (default\: .)\n[-db <database>]  The database name\n[-quiet]          Do not print progress information
 org.h2.jmx.DatabaseInfoMBean.getCacheSizeMax=The maximum cache size in KB.
-org.h2.tools.CreateCluster.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]       Print the list of options\n[-urlSource "<url>"]  The database URL of the source database (jdbc\:h2\:...)\n[-urlTarget "<url>"]  The database URL of the target database (jdbc\:h2\:...)\n[-user <user>]        The user name (default\: sa)\n[-password <pwd>]     The password\n[-serverList <list>]  The comma separated list of host names or IP addresses
+org.h2.jmx.DatabaseInfoMBean.getFileReadCount=The file read count since the database was opened.
+org.h2.jmx.DatabaseInfoMBean.getFileSize=The database file size in KB.
+org.h2.jmx.DatabaseInfoMBean.getFileWriteCount=The number of write operations since the database was opened.
+org.h2.jmx.DatabaseInfoMBean.getFileWriteCountTotal=The number of write operations since the database was created.
+org.h2.jmx.DatabaseInfoMBean.getLogMode=The transaction log mode (0 disabled, 1 without sync, 2 enabled).
+org.h2.jmx.DatabaseInfoMBean.getMode=The database compatibility mode (REGULAR if no compatibility mode is\n used).
 org.h2.jmx.DatabaseInfoMBean.getTraceLevel=The trace level (0 disabled, 1 error, 2 info, 3 debug).
-org.h2.tools.Server.main=When running without options, -tcp, -web, -browser and -pg are started.\nOptions are case sensitive. Supported options are\:\n[-help] or [-?]         Print the list of options\n[-web]                  Start the web server with the H2 Console\n[-webAllowOthers]       Allow other computers to connect - see below\n[-webDaemon]            Use a daemon thread\n[-webPort <port>]       The port (default\: 8082)\n[-webSSL]               Use encrypted (HTTPS) connections\n[-webAdminPassword]     Password of DB Console administrator\n[-browser]              Start a browser connecting to the web server\n[-tcp]                  Start the TCP server\n[-tcpAllowOthers]       Allow other computers to connect - see below\n[-tcpDaemon]            Use a daemon thread\n[-tcpPort <port>]       The port (default\: 9092)\n[-tcpSSL]               Use encrypted (SSL) connections\n[-tcpPassword <pwd>]    The password for shutting down a TCP server\n[-tcpShutdown "<url>"]  Stop the TCP server; example\: tcp\://localhost\n[-tcpShutdownForce]     Do not wait until all connections are closed\n[-pg]                   Start the PG server\n[-pgAllowOthers]        Allow other computers to connect - see below\n[-pgDaemon]             Use a daemon thread\n[-pgPort <port>]        The port (default\: 5435)\n[-properties "<dir>"]   Server properties (default\: ~, disable\: null)\n[-baseDir <dir>]        The base directory for H2 databases (all servers)\n[-ifExists]             Only existing databases may be opened (all servers)\n[-ifNotExists]          Databases are created when accessed\n[-trace]                Print additional trace information (all servers)\n[-key <from> <to>]      Allows to map a database name to another (all servers)\nThe options -xAllowOthers are potentially risky.\nFor details, see Advanced Topics / Protection against Remote Access.
+org.h2.jmx.DatabaseInfoMBean.getVersion=The database version.
+org.h2.jmx.DatabaseInfoMBean.isExclusive=Is the database open in exclusive mode?
+org.h2.jmx.DatabaseInfoMBean.isMultiThreaded=Is multi-threading enabled?
 org.h2.jmx.DatabaseInfoMBean.isMvcc=Is MVCC (multi version concurrency) enabled?
-org.h2.tools.Shell=Interactive command line tool to access a database using JDBC.
+org.h2.jmx.DatabaseInfoMBean.isReadOnly=Is the database read-only?
+org.h2.jmx.DatabaseInfoMBean.listSessions=List sessions, including the queries that are in\n progress, and locked tables.
+org.h2.jmx.DatabaseInfoMBean.listSettings=List the database settings.
+org.h2.tools.Backup=Creates a backup of a database.\nThis tool copies all database files. The database must be closed before using\n this tool. To create a backup while the database is in use, run the BACKUP\n SQL statement. In an emergency, for example if the application is not\n responding, creating a backup using the Backup tool is possible by using the\n quiet mode. However, if the database is changed while the backup is running\n in quiet mode, the backup could be corrupt.
+org.h2.tools.Backup.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]     Print the list of options\n[-file <filename>]  The target file name (default\: backup.zip)\n[-dir <dir>]        The source directory (default\: .)\n[-db <database>]    Source database; not required if there is only one\n[-quiet]            Do not print progress information
+org.h2.tools.ChangeFileEncryption=Allows changing the database file encryption password or algorithm.\nThis tool can not be used to change a password of a user.\n The database must be closed before using this tool.
+org.h2.tools.ChangeFileEncryption.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]   Print the list of options\n[-cipher type]    The encryption type (AES)\n[-dir <dir>]      The database directory (default\: .)\n[-db <database>]  Database name (all databases if not set)\n[-decrypt <pwd>]  The decryption password (if not set\: not yet encrypted)\n[-encrypt <pwd>]  The encryption password (if not set\: do not encrypt)\n[-quiet]          Do not print progress information
+org.h2.tools.Console=Starts the H2 Console (web-) server, as well as the TCP and PG server.
+org.h2.tools.Console.main=When running without options, -tcp, -web, -browser and -pg are started.\nOptions are case sensitive. Supported options are\:\n[-help] or [-?]  Print the list of options\n[-url]           Start a browser and connect to this URL\n[-driver]        Used together with -url\: the driver\n[-user]          Used together with -url\: the user name\n[-password]      Used together with -url\: the password\n[-web]           Start the web server with the H2 Console\n[-tool]          Start the icon or window that allows to start a browser\n[-browser]       Start a browser connecting to the web server\n[-tcp]           Start the TCP server\n[-pg]            Start the PG server\nFor each Server, additional options are available;\n for details, see the Server tool.\nIf a service can not be started, the program\n terminates with an exit code of 1.
 org.h2.tools.ConvertTraceFile=Converts a .trace.db file to a SQL script and Java source code.\nSQL statement statistics are listed as well.
-org.h2.jmx.DatabaseInfoMBean.getFileReadCount=The file read count since the database was opened.
-org.h2.jmx.DatabaseInfoMBean.getMode=The database compatibility mode (REGULAR if no compatibility mode is\n used).
-org.h2.tools.Console.main=When running without options, -tcp, -web, -browser and -pg are started.\nOptions are case sensitive. Supported options are\:\n[-help] or [-?]  Print the list of options\n[-url]           Start a browser and connect to this URL\n[-driver]        Used together with -url\: the driver\n[-user]          Used together with -url\: the user name\n[-password]      Used together with -url\: the password\n[-web]           Start the web server with the H2 Console\n[-tool]          Start the icon or window that allows to start a browser\n[-browser]       Start a browser connecting to the web server\n[-tcp]           Start the TCP server\n[-pg]            Start the PG server\nFor each Server, additional options are available;\n for details, see the Server tool.\nIf a service can not be started, the program\n terminates with an exit code of 1.
-org.h2.jmx.DatabaseInfoMBean.getLogMode=The transaction log mode (0 disabled, 1 without sync, 2 enabled).
-org.h2.tools.Restore.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]     Print the list of options\n[-file <filename>]  The source file name (default\: backup.zip)\n[-dir <dir>]        The target directory (default\: .)\n[-db <database>]    The target database name (as stored if not set)\n[-quiet]            Do not print progress information
-org.h2.tools.Restore=Restores a H2 database by extracting the database files from a .zip file.
-org.h2.tools.RunScript.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]     Print the list of options\n[-url "<url>"]      The database URL (jdbc\:...)\n[-user <user>]      The user name (default\: sa)\n[-password <pwd>]   The password\n[-script <file>]    The script file to run (default\: backup.sql)\n[-driver <class>]   The JDBC driver class to use (not required in most cases)\n[-showResults]      Show the statements and the results of queries\n[-checkResults]     Check if the query results match the expected results\n[-continueOnError]  Continue even if the script contains errors\n[-options ...]      RUNSCRIPT options (embedded H2; -*Results not supported)
-org.h2.jmx.DatabaseInfoMBean.getFileWriteCountTotal=The number of write operations since the database was created.
 org.h2.tools.ConvertTraceFile.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]      Print the list of options\n[-traceFile <file>]  The trace file name (default\: test.trace.db)\n[-script <file>]     The script file name (default\: test.sql)\n[-javaClass <file>]  The Java directory and class file name (default\: Test)
+org.h2.tools.CreateCluster=Creates a cluster from a stand-alone database.\nCopies a database to another location if required.
+org.h2.tools.CreateCluster.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]       Print the list of options\n[-urlSource "<url>"]  The database URL of the source database (jdbc\:h2\:...)\n[-urlTarget "<url>"]  The database URL of the target database (jdbc\:h2\:...)\n[-user <user>]        The user name (default\: sa)\n[-password <pwd>]     The password\n[-serverList <list>]  The comma separated list of host names or IP addresses
 org.h2.tools.DeleteDbFiles=Deletes all files belonging to a database.\nThe database must be closed before calling this tool.
-org.h2.tools.ChangeFileEncryption.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]   Print the list of options\n[-cipher type]    The encryption type (AES)\n[-dir <dir>]      The database directory (default\: .)\n[-db <database>]  Database name (all databases if not set)\n[-decrypt <pwd>]  The decryption password (if not set\: not yet encrypted)\n[-encrypt <pwd>]  The encryption password (if not set\: do not encrypt)\n[-quiet]          Do not print progress information
-org.h2.tools.Console=Starts the H2 Console (web-) server, as well as the TCP and PG server.
-org.h2.jmx.DatabaseInfoMBean.isReadOnly=Is the database read-only?
+org.h2.tools.DeleteDbFiles.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]   Print the list of options\n[-dir <dir>]      The directory (default\: .)\n[-db <database>]  The database name\n[-quiet]          Do not print progress information
+org.h2.tools.Recover=Helps recovering a corrupted database.
 org.h2.tools.Recover.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]    Print the list of options\n[-dir <dir>]       The directory (default\: .)\n[-db <database>]   The database name (all databases if not set)\n[-trace]           Print additional trace information\n[-transactionLog]  Print the transaction log\nEncrypted databases need to be decrypted first.
+org.h2.tools.Restore=Restores a H2 database by extracting the database files from a .zip file.
+org.h2.tools.Restore.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]     Print the list of options\n[-file <filename>]  The source file name (default\: backup.zip)\n[-dir <dir>]        The target directory (default\: .)\n[-db <database>]    The target database name (as stored if not set)\n[-quiet]            Do not print progress information
 org.h2.tools.RunScript=Runs a SQL script against a database.
+org.h2.tools.RunScript.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]     Print the list of options\n[-url "<url>"]      The database URL (jdbc\:...)\n[-user <user>]      The user name (default\: sa)\n[-password <pwd>]   The password\n[-script <file>]    The script file to run (default\: backup.sql)\n[-driver <class>]   The JDBC driver class to use (not required in most cases)\n[-showResults]      Show the statements and the results of queries\n[-checkResults]     Check if the query results match the expected results\n[-continueOnError]  Continue even if the script contains errors\n[-options ...]      RUNSCRIPT options (embedded H2; -*Results not supported)
+org.h2.tools.Script=Creates a SQL script file by extracting the schema and data of a database.
 org.h2.tools.Script.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]    Print the list of options\n[-url "<url>"]     The database URL (jdbc\:...)\n[-user <user>]     The user name (default\: sa)\n[-password <pwd>]  The password\n[-script <file>]   The target script file name (default\: backup.sql)\n[-options ...]     A list of options (only for embedded H2, see SCRIPT)\n[-quiet]           Do not print progress information
-org.h2.jmx.DatabaseInfoMBean.getFileWriteCount=The number of write operations since the database was opened.
-org.h2.tools.Script=Creates a SQL script file by extracting the schema and data of a database.
-org.h2.tools.Recover=Helps recovering a corrupted database.
-org.h2.tools.ChangeFileEncryption=Allows changing the database file encryption password or algorithm.\nThis tool can not be used to change a password of a user.\n The database must be closed before using this tool.
-org.h2.jmx.DatabaseInfoMBean.isMultiThreaded=Is multi-threading enabled?
-org.h2.jmx.DatabaseInfoMBean.getVersion=The database version.
+org.h2.tools.Server=Starts the H2 Console (web-) server, TCP, and PG server.
+org.h2.tools.Server.main=When running without options, -tcp, -web, -browser and -pg are started.\nOptions are case sensitive. Supported options are\:\n[-help] or [-?]         Print the list of options\n[-web]                  Start the web server with the H2 Console\n[-webAllowOthers]       Allow other computers to connect - see below\n[-webDaemon]            Use a daemon thread\n[-webPort <port>]       The port (default\: 8082)\n[-webSSL]               Use encrypted (HTTPS) connections\n[-webAdminPassword]     Password of DB Console administrator\n[-browser]              Start a browser connecting to the web server\n[-tcp]                  Start the TCP server\n[-tcpAllowOthers]       Allow other computers to connect - see below\n[-tcpDaemon]            Use a daemon thread\n[-tcpPort <port>]       The port (default\: 9092)\n[-tcpSSL]               Use encrypted (SSL) connections\n[-tcpPassword <pwd>]    The password for shutting down a TCP server\n[-tcpShutdown "<url>"]  Stop the TCP server; example\: tcp\://localhost\n[-tcpShutdownForce]     Do not wait until all connections are closed\n[-pg]                   Start the PG server\n[-pgAllowOthers]        Allow other computers to connect - see below\n[-pgDaemon]             Use a daemon thread\n[-pgPort <port>]        The port (default\: 5435)\n[-properties "<dir>"]   Server properties (default\: ~, disable\: null)\n[-baseDir <dir>]        The base directory for H2 databases (all servers)\n[-ifExists]             Only existing databases may be opened (all servers)\n[-ifNotExists]          Databases are created when accessed\n[-trace]                Print additional trace information (all servers)\n[-key <from> <to>]      Allows to map a database name to another (all servers)\nThe options -xAllowOthers are potentially risky.\nFor details, see Advanced Topics / Protection against Remote Access.
+org.h2.tools.Shell=Interactive command line tool to access a database using JDBC.
 org.h2.tools.Shell.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]        Print the list of options\n[-url "<url>"]         The database URL (jdbc\:h2\:...)\n[-user <user>]         The user name\n[-password <pwd>]      The password\n[-driver <class>]      The JDBC driver class to use (not required in most cases)\n[-sql "<statements>"]  Execute the SQL statements and exit\n[-properties "<dir>"]  Load the server properties from this directory\nIf special characters don't work as expected, you may need to use\n -Dfile.encoding\=UTF-8 (Mac OS X) or CP850 (Windows).
-org.h2.tools.CreateCluster=Creates a cluster from a stand-alone database.\nCopies a database to another location if required.
-org.h2.jmx.DatabaseInfoMBean=Information and management operations for the given database.
-org.h2.tools.Backup.main=Options are case sensitive. Supported options are\:\n[-help] or [-?]     Print the list of options\n[-file <filename>]  The target file name (default\: backup.zip)\n[-dir <dir>]        The source directory (default\: .)\n[-db <database>]    Source database; not required if there is only one\n[-quiet]            Do not print progress information
-org.h2.jmx.DatabaseInfoMBean.getFileSize=The database file size in KB.

=== modified file 'src/main/org/h2/result/Row.java'
--- old/src/main/org/h2/result/Row.java	2020-10-15 15:02:18 +0000
+++ new/src/main/org/h2/result/Row.java	2022-11-10 09:01:07 +0000
@@ -66,4 +66,6 @@
      */
     boolean hasSharedData(Row other);
 
+   void copy(Row oldRow);
+
 }

=== modified file 'src/main/org/h2/result/RowImpl.java'
--- old/src/main/org/h2/result/RowImpl.java	2020-10-15 15:02:18 +0000
+++ new/src/main/org/h2/result/RowImpl.java	2022-11-10 09:04:22 +0000
@@ -25,6 +25,12 @@
     }
 
     @Override
+   public void copy(Row src)
+   {
+       System.arraycopy(((RowImpl) src).data, 0, data, 0, data.length);
+   }
+    
+    @Override
     public void setKey(SearchRow row) {
         setKey(row.getKey());
     }

=== modified file 'src/main/org/h2/table/Table.java'
--- old/src/main/org/h2/table/Table.java	2020-11-13 14:04:32 +0000
+++ new/src/main/org/h2/table/Table.java	2022-11-10 09:03:25 +0000
@@ -62,7 +62,9 @@
     /**
      * The indexes of the computed columns
      */
-    protected List<Integer> computedColumns = new ArrayList<>();
+    protected List<Integer> computedColumns = null;
+    
+    private List<Integer> onUpdateColumns = null;
 
     /**
      * The compare mode used for this table.
@@ -271,6 +273,11 @@
      */
     public abstract ArrayList<Index> getIndexes();
 
+    public List<Integer> getOnUpdateColumns()
+   {
+      return onUpdateColumns;
+   }
+    
     /**
      * Get an index by name.
      *
@@ -435,9 +442,13 @@
         if (columnMap.size() > 0) {
             columnMap.clear();
         }
-        if (computedColumns.size() > 0) {
+        if (computedColumns != null && computedColumns.size() > 0) {
            computedColumns.clear();
         }
+        if (onUpdateColumns != null && onUpdateColumns.size() > 0)
+        {
+           onUpdateColumns.clear();
+        }
         
         for (int i = 0; i < columns.length; i++) {
             Column col = columns[i];
@@ -453,8 +464,20 @@
             }
             columnMap.put(columnName, col);
             if (col.getComputed()) {
+               if (computedColumns == null)
+               {
+                  computedColumns = new ArrayList<>();
+               }
                computedColumns.add(i);
             }
+            if (col.getOnUpdateExpression() != null)
+            {
+               if (onUpdateColumns == null)
+               {
+                  onUpdateColumns = new ArrayList<>();
+               }
+               onUpdateColumns.add(i);
+            }
         }
     }
 
@@ -841,13 +864,45 @@
      * @param row the row
      */
     public void validateConvertUpdateSequence(Session session, Row row) {
-        for (int i = 0; i < computedColumns.size(); i++)
-        {
-            int idx = computedColumns.get(i);
-            row.setValue(idx, columns[idx].computeValue(session, row));
-        }
-        
+       validateConvertUpdateSequence(session, row, null);
+    }
+    
+    /**
+     * Validate all values in this row, convert the values if required, and
+     * update the sequence values if required. This call will also set the
+     * default values if required and set the computed column if there are any.
+     *
+     * @param session the session
+     * @param row the row
+     */
+    public void validateConvertUpdateSequence(Session session, Row row, BitSet setCols) {
+       BitSet changed = null;
+       if (setCols != null)
+       {
+          changed = new BitSet();
+          changed.or(setCols);
+       }
+       
+       if (computedColumns != null)
+       {
+           for (int i = 0; i < computedColumns.size(); i++)
+           {
+               int idx = computedColumns.get(i);
+               row.setValue(idx, columns[idx].computeValue(session, row));
+               if (changed != null)
+               {
+                  changed.set(idx);
+               }
+           }
+       }
+       
         for (int i = 0; i < columns.length; i++) {
+           if (changed != null && !changed.get(i))
+           {
+              // only changed columns
+              continue;
+           }
+           
            Value value = row.getValue(i);
            Value v2 = columns[i].validateConvertUpdateSequence(session, value);
            if (v2 != value) {

