Minor adjustments for clarity and test coverage.

FossilOrigin-Name: 30065716878d4058e75eb510b0b27b68e5193d04625eb173210de8061f20f499
diff --git a/src/build.c b/src/build.c
index 51398f1..ecf54fe 100644
--- a/src/build.c
+++ b/src/build.c
@@ -1628,7 +1628,7 @@
   u8 eType = COLFLAG_VIRTUAL;
   Table *pTab = pParse->pNewTable;
   Column *pCol;
-  if( pTab==0 ) goto generated_done;
+  if( NEVER(pTab==0) ) goto generated_done;
   pCol = &(pTab->aCol[pTab->nCol-1]);
   if( IN_DECLARE_VTAB ){
     sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns");
diff --git a/src/insert.c b/src/insert.c
index 5b2505b..b6fdc39 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -857,13 +857,13 @@
   if( pColumn==0 && nColumn>0 ){
     ipkColumn = pTab->iPKey;
 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
-    if( pTab->tabFlags & TF_HasGenerated ){
+    if( ipkColumn>=0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){
       testcase( pTab->tabFlags & TF_HasVirtual );
-      testcase( pTab->tabFlags & TF_HasGenerated );
+      testcase( pTab->tabFlags & TF_HasStored );
       for(i=ipkColumn-1; i>=0; i--){
         if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
           testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL );
-          testcase( pTab->aCol[i].colFlags & COLFLAG_GENERATED );
+          testcase( pTab->aCol[i].colFlags & COLFLAG_STORED );
           ipkColumn--;
         }
       }
@@ -2413,10 +2413,39 @@
       return 0;    /* Neither table may have __hidden__ columns */
     }
 #endif
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+    /* Even if tables t1 and t2 have identical schemas, if they contain
+    ** generated columns, then this statement is semantically incorrect:
+    **
+    **     INSERT INTO t2 SELECT * FROM t1;
+    **
+    ** The reason is that generated column values are returned by the
+    ** the SELECT statement on the right but the INSERT statement on the
+    ** left wants them to be omitted.
+    **
+    ** Nevertheless, this is a useful notational shorthand to tell SQLite
+    ** to do a bulk transfer all of the content from t1 over to t2.
+    ** 
+    ** We could, in theory, disable this (except for internal use by the
+    ** VACUUM command where it is actually needed).  But why do that?  It
+    ** seems harmless enough, and provides a useful service.
+    */
     if( (pDestCol->colFlags & COLFLAG_GENERATED) !=
         (pSrcCol->colFlags & COLFLAG_GENERATED) ){
-      return 0;    /* Both columns have the same generated type */
+      return 0;    /* Both columns have the same generated-column type */
     }
+    /* But the transfer is only allowed if both the source and destination
+    ** tables have the exact same expressions for generated columns.
+    ** This requirement could be relaxed for VIRTUAL columns, I suppose.
+    */
+    if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){
+      if( sqlite3ExprCompare(0, pSrcCol->pDflt, pDestCol->pDflt, -1)!=0 ){
+        testcase( pDestCol->colFlags & COLFLAG_VIRTUAL );
+        testcase( pDestCol->colFlags & COLFLAG_STORED );
+        return 0;  /* Different generator expressions */
+      }
+    }
+#endif
     if( pDestCol->affinity!=pSrcCol->affinity ){
       return 0;    /* Affinity must be the same on all columns */
     }
@@ -2437,14 +2466,6 @@
         return 0;    /* Default values must be the same for all columns */
       }
     }
-    /* Generator expressions for generated columns must match */
-    if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){
-      if( sqlite3ExprCompare(0, pSrcCol->pDflt, pDestCol->pDflt, -1)!=0 ){
-        testcase( pDestCol->colFlags & COLFLAG_VIRTUAL );
-        testcase( pDestCol->colFlags & COLFLAG_STORED );
-        return 0;  /* Different generator expressions */
-      }
-    }
   }
   for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
     if( IsUniqueIndex(pDestIdx) ){
diff --git a/src/resolve.c b/src/resolve.c
index 6577468..a9c20b1 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -633,7 +633,7 @@
     else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints";
 #endif
 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
-    else if( pNC->ncFlags & NC_GenCol ) zIn = "GENERATED ALWAYS AS columns";
+    else if( pNC->ncFlags & NC_GenCol ) zIn = "generated columns";
 #endif
     sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
   }
diff --git a/src/update.c b/src/update.c
index d690b69..816a681 100644
--- a/src/update.c
+++ b/src/update.c
@@ -314,8 +314,8 @@
         }
 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
         else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
-          testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL );
-          testcase( pTab->aCol[i].colFlags & COLFLAG_STORED );
+          testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
+          testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
           sqlite3ErrorMsg(pParse, 
              "cannot UPDATE generated column \"%s\"",
              pTab->aCol[j].zName);
diff --git a/src/vdbe.c b/src/vdbe.c
index 1082b13..7c8d2a4 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -3375,7 +3375,6 @@
       p->rc = rc = SQLITE_BUSY;
       goto vdbe_return;
     }
-    assert( db->nStatement==0 );
     sqlite3CloseSavepoints(db);
     if( p->rc==SQLITE_OK ){
       rc = SQLITE_DONE;