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;