mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
In UPDATE processing, include generated columns in the set of columns being
updated if and only if their generator expressions reference some other column that is being updated. FossilOrigin-Name: d38176e93a628e03f1bd8b689fbc4152a1495388da917c2d89cefed04353d2d6
This commit is contained in:
14
manifest
14
manifest
@@ -1,5 +1,5 @@
|
|||||||
C New\stestcase()\smacros.\s\sFix\sa\sproblem\swith\sINSERT\swhen\sthe\sIPK\sis\sto\sthe\nright\sof\sgenerated\scolumns.
|
C In\sUPDATE\sprocessing,\sinclude\sgenerated\scolumns\sin\sthe\sset\sof\scolumns\sbeing\nupdated\sif\sand\sonly\sif\stheir\sgenerator\sexpressions\sreference\ssome\sother\ncolumn\sthat\sis\sbeing\supdated.
|
||||||
D 2019-10-22T13:01:24.252
|
D 2019-10-22T13:59:23.530
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@@ -469,7 +469,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
|||||||
F src/btree.c a8a9c2ce62bdf54c8cf9795143d7cb10b7473a1230a0572f702d061ffcceefe5
|
F src/btree.c a8a9c2ce62bdf54c8cf9795143d7cb10b7473a1230a0572f702d061ffcceefe5
|
||||||
F src/btree.h f27a33c49280209a93385e218306c4ee5f46ba8d7649d2f81a7166b282232484
|
F src/btree.h f27a33c49280209a93385e218306c4ee5f46ba8d7649d2f81a7166b282232484
|
||||||
F src/btreeInt.h 91806f01fd1145a9a86ba3042f25c38d8faf6002701bf5e780742cf88bcff437
|
F src/btreeInt.h 91806f01fd1145a9a86ba3042f25c38d8faf6002701bf5e780742cf88bcff437
|
||||||
F src/build.c acf54f35164aff7f0b06b82aae357e76e08b74e4c904bafd96643d4e155f34f8
|
F src/build.c 27471914e516d7d0f21d16c74f9e84bdfda1160bfd11e33a74cbe1d5a08dbc9e
|
||||||
F src/callback.c 88615dfc0a82167b65b452b4b305dbf86be77200b3343c6ffc6d03e92a01d181
|
F src/callback.c 88615dfc0a82167b65b452b4b305dbf86be77200b3343c6ffc6d03e92a01d181
|
||||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||||
F src/ctime.c 1b0724e66f95f33b160b1af85caaf9cceb325d22abf39bd24df4f54a73982251
|
F src/ctime.c 1b0724e66f95f33b160b1af85caaf9cceb325d22abf39bd24df4f54a73982251
|
||||||
@@ -592,7 +592,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
|||||||
F src/tokenize.c 7b17f6e2f20f6cbcb0b215025a86b7457c38451fc7622f705e553d7a488c572d
|
F src/tokenize.c 7b17f6e2f20f6cbcb0b215025a86b7457c38451fc7622f705e553d7a488c572d
|
||||||
F src/treeview.c fddeb413159c3eeeaea3f496172f121cf3695606c461dc4e6dcee51417952df5
|
F src/treeview.c fddeb413159c3eeeaea3f496172f121cf3695606c461dc4e6dcee51417952df5
|
||||||
F src/trigger.c 845ccc08f60716c58aa28fe6470385c18ef8c4e1d88c93dcf449bc13d464eb2e
|
F src/trigger.c 845ccc08f60716c58aa28fe6470385c18ef8c4e1d88c93dcf449bc13d464eb2e
|
||||||
F src/update.c 287146d2ce191228f0afaa34ffcaaaa196e2c2e2664008914e925dea6a64403e
|
F src/update.c 3a5e1fa8e29413ee633f049bf9f0e1eb33a03a53cb55b6ea290120b324fbf46e
|
||||||
F src/upsert.c b445315c8958d8f17ec3297d06842e61dacaad0633ccaec1e4e160de7e562212
|
F src/upsert.c b445315c8958d8f17ec3297d06842e61dacaad0633ccaec1e4e160de7e562212
|
||||||
F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507
|
F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507
|
||||||
F src/util.c 10d910e04a4f3842042485e0df01a484f57f912c10b60b3a09ccddd5019bd138
|
F src/util.c 10d910e04a4f3842042485e0df01a484f57f912c10b60b3a09ccddd5019bd138
|
||||||
@@ -1847,7 +1847,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P ba123b8c201053d8f9387de38f3513b06f7721b28d79fab8489f96d336105117
|
P 412799fc5527aaca987e4e04b8a4f774dcdb70fb80e3a126dc3a26d48a66935c
|
||||||
R c1cc6d4a971f76b9e92c16fa65923060
|
R d35fda238d05afc96b47f324f26c5dfe
|
||||||
U drh
|
U drh
|
||||||
Z 35d27d665bc3fbce0f6de471df281b5a
|
Z 00de734fe264a9e4a103cd3816a6d374
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
412799fc5527aaca987e4e04b8a4f774dcdb70fb80e3a126dc3a26d48a66935c
|
d38176e93a628e03f1bd8b689fbc4152a1495388da917c2d89cefed04353d2d6
|
||||||
10
src/build.c
10
src/build.c
@@ -1405,6 +1405,12 @@ void sqlite3AddDefaultValue(
|
|||||||
if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){
|
if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){
|
||||||
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
|
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
|
||||||
pCol->zName);
|
pCol->zName);
|
||||||
|
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||||
|
}else if( pCol->colFlags & COLFLAG_GENERATED ){
|
||||||
|
testcase( pCol->colflags & COLFLAG_VIRTUAL );
|
||||||
|
testcase( pCol->colflags & COLFLAG_STORED );
|
||||||
|
sqlite3ErrorMsg(pParse, "cannot use DEFAULT on a generated column");
|
||||||
|
#endif
|
||||||
}else{
|
}else{
|
||||||
/* A copy of pExpr is used instead of the original, as pExpr contains
|
/* A copy of pExpr is used instead of the original, as pExpr contains
|
||||||
** tokens that point to volatile memory.
|
** tokens that point to volatile memory.
|
||||||
@@ -1633,14 +1639,14 @@ void sqlite3AddGenerated(Parse *pParse, Expr *pExpr, Token *pType){
|
|||||||
goto generated_done;
|
goto generated_done;
|
||||||
|
|
||||||
generated_error:
|
generated_error:
|
||||||
sqlite3ErrorMsg(pParse, "incorrect GENERATED ALWAYS AS on column \"%s\"",
|
sqlite3ErrorMsg(pParse, "error in generated column \"%s\"",
|
||||||
pCol->zName);
|
pCol->zName);
|
||||||
generated_done:
|
generated_done:
|
||||||
sqlite3ExprDelete(pParse->db, pExpr);
|
sqlite3ExprDelete(pParse->db, pExpr);
|
||||||
#else
|
#else
|
||||||
/* Throw and error for the GENERATED ALWAYS AS clause if the
|
/* Throw and error for the GENERATED ALWAYS AS clause if the
|
||||||
** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */
|
** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */
|
||||||
sqlite3ErrorMsg(pParse, "GENERATED ALWAYS AS not supported");
|
sqlite3ErrorMsg(pParse, "generated columns not supported");
|
||||||
sqlite3ExprDelete(pParse->db, pExpr);
|
sqlite3ExprDelete(pParse->db, pExpr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
28
src/update.c
28
src/update.c
@@ -356,6 +356,33 @@ void sqlite3Update(
|
|||||||
assert( chngPk==0 || chngPk==1 );
|
assert( chngPk==0 || chngPk==1 );
|
||||||
chngKey = chngRowid + chngPk;
|
chngKey = chngRowid + chngPk;
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||||
|
/* Mark generated columns as changing if their generator expressions
|
||||||
|
** reference any changing column. The actual aXRef[] value for
|
||||||
|
** generated expressions is not used, other than to check to see that it
|
||||||
|
** is non-negative, so the value of aXRef[] for generated columns can be
|
||||||
|
** set to any non-negative number. We use 99999 so that the value is
|
||||||
|
** obvious when looking at aXRef[] in a symbolic debugger.
|
||||||
|
*/
|
||||||
|
if( pTab->tabFlags & TF_HasGenerated ){
|
||||||
|
int bProgress;
|
||||||
|
testcase( pTab->tabFlags & TF_HasVirtual );
|
||||||
|
testcase( pTab->tabFlags & TF_HasStored );
|
||||||
|
do{
|
||||||
|
bProgress = 0;
|
||||||
|
for(i=0; i<pTab->nCol; i++){
|
||||||
|
if( aXRef[i]>=0 ) continue;
|
||||||
|
if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue;
|
||||||
|
if( sqlite3ExprReferencesUpdatedColumn(pTab->aCol[i].pDflt,
|
||||||
|
aXRef, chngRowid) ){
|
||||||
|
aXRef[i] = 99999;
|
||||||
|
bProgress = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}while( bProgress );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The SET expressions are not actually used inside the WHERE loop.
|
/* The SET expressions are not actually used inside the WHERE loop.
|
||||||
** So reset the colUsed mask. Unless this is a virtual table. In that
|
** So reset the colUsed mask. Unless this is a virtual table. In that
|
||||||
** case, set all bits of the colUsed mask (to ensure that the virtual
|
** case, set all bits of the colUsed mask (to ensure that the virtual
|
||||||
@@ -952,6 +979,7 @@ static void updateVirtualTable(
|
|||||||
|
|
||||||
/* Populate the argument registers. */
|
/* Populate the argument registers. */
|
||||||
for(i=0; i<pTab->nCol; i++){
|
for(i=0; i<pTab->nCol; i++){
|
||||||
|
assert( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 );
|
||||||
if( aXRef[i]>=0 ){
|
if( aXRef[i]>=0 ){
|
||||||
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
|
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
Reference in New Issue
Block a user