-C Remove\stea\sversion\scheck\sfrom\stool/srctree-check.tcl,\sas\sit's\sobsoleted\sby\s[be265559].
-D 2025-02-15T17:29:56.489
+C An\salternative\simplementation\sof\sthe\sdefault-in-values\sfeature\sthat\sis\ncleaner\s(it\savoids\sdodgy\spoking\sabout\sin\sthe\sparser\sLALR\sstack\slooking\sfor\nerrors)\sand\shas\sless\sperformance\simpact\sin\sthe\scommon\scase\swhere\sDEFAULT\sis\nnot\sused.
+D 2025-02-15T20:31:25.346
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
F src/dbpage.c 2e677acb658a29965e55398bbc61161cb7819da538057c8032adac7ab8e4a8c0
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
-F src/expr.c ca943270395374afc65256ce86cdb152a22fa6ff146895175833b89ba870e117
+F src/expr.c 22cb9d1d3fd849b3c244454e76ddfad3f454af779862424f93ef6a89d754e297
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
F src/func.c b2fb33139972d7d65640b27ea962a49f1616265428001090cab39fcf270228e1
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c 05e04ef637cbc0dccb9a5c5d188a5a2608891e554c8ec17c7a71afe2cf896a06
+F src/insert.c a0d16840019e2906569a4275c1804c80b0cbbd4ad48cc44d585dd0b3fa6aac8c
F src/json.c 2663a0c7e574cb928de944720dcdcc11c931877d877549b8f1258a4002efd6f7
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 3a1c4e7f69af482e33c8cba8a75afe0dda0ea6391240adac22b040ce1bdeef44
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
-F src/parse.y f84673f1454e2bcf517623d4346e67fb2d73e57826ea103681ad5848238f6029
+F src/parse.y 8febc26b44b19137aaffd4f14b067eaf0c110fe318c5df9802d1298c7d9599e9
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 49516ad7718a3626f28f710fa7448ef1fce3c07fd169acbb4817341950264319
F src/sqlite.h.in d2902f13ace94d3d3609646bd6d12a2d7a4f6cbdf6a5a4097580ac305f54c3f0
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
-F src/sqliteInt.h 8cbfef6c26efd539eb93011905f4d3ce7fdb77475d1280764d86f9e7954c464b
+F src/sqliteInt.h a844632bfd2814d13fcad0c535ea0654b869930142a827c41818a1e8d1bcb1a2
F src/sqliteLimit.h 1bbdbf72bd0411d003267ffebc59a262f061df5653027a75627d03f48ca30523
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P be265559a334eda127862ae54edb58c46051f74445642daa84a9f61a81df1bac
-R ec0de275110a891612615fec90c077b9
-U stephan
-Z db33573bd4969af02b51c5852b05ae57
+P 1860ea060bd373f49d0b5d41367409a4607e9a0a0cb606af99927af15de1e21e
+R 3cb064185b620b2a38969a214589fa36
+T *branch * default-in-values-2
+T *sym-default-in-values-2 *
+T -sym-trunk *
+U drh
+Z d4065c99bc92bee52eb7b186d29eccbe
# Remove this line to create a well-formed Fossil manifest.
** because the complex rules SQLite uses (see function
** sqlite3SubqueryColumnTypes() in select.c) to determine the effective
** affinity of such a column for all rows require access to all values in
-** the column simultaneously.
+** the column simultaneously.
+**
+** e) The DEFAULT keyword cannot have been used in any of the terms
+** of the VALUES clause. This optimization won't work in that case
+** because we do not yet know the mapping from VALUES-clause terms
+** into table columns, so we cannot construct the mapping.
*/
Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){
if( pParse->bHasWith /* condition (a) above */
+ || pParse->bDfltInExpr /* condition (e) above */
|| pParse->db->init.busy /* condition (b) above */
|| exprListIsConstant(pParse,pRow)==0 /* condition (c) above */
|| (pLeft->pSrc->nSrc==0 &&
return pLeft;
}
+/*
+** The aTabColMap[] array maps table columns into terms of the IDLIST
+** of an INSERT. For example, if we have:
+**
+** CREATE TABLE t1(a,b,c,d,e,f,g);
+** \/ \___________/
+** pTab----' `-------- pTab->aCol[]
+**
+** And we do:
+**
+** INSERT INTO t1(e,b,g) ....
+** \/ \___/
+** pTab---' `----- IDLIST in pColumn
+**
+** Then aTabColMap[] contains: { 0, 2, 0, 0, 1, 0, 3 }
+** Thus aTabColMap provides a one-based mapping of table column indexes into
+** IDLIST entries. 0 means "none" because there are often table columns
+** that are not in the IDLIST. The left-most table columns is 1, and
+** the next table columns is 2 and so forth.
+**
+** This routine creates a new array (obtained from sqlite3DbMalloc() -
+** the caller must free it) that inverts the mapping. The returned
+** array aColTabMap[] would be {4, 1, 6}. This new mapping is zero-based.
+**
+** The aTabColMap and pColumn inputs might both be NULL. This means
+** that the IDLIST on the INSERT is omitted. This routine still
+** constructs a column map, but in this case it maps "insertable"
+** columns of the table into actual columns. Hidden and computed
+** columns are not "insertable" and are thus skipped.
+*/
+static int *computeColTabMap(
+ Parse *pParse, /* Parsing context */
+ int *const aTabColMap, /* Mapping from table column to IDList column */
+ Table *pTab, /* The table */
+ IdList *pColumn /* The IDLIST */
+){
+ int *aColTabMap;
+
+ if( pParse->nErr ) return 0;
+ assert( aTabColMap!=0 || pColumn==0 );
+ assert( pColumn!=0 || aTabColMap==0 );
+ assert( pTab->nCol>0 );
+ aColTabMap = sqlite3DbMallocZero(pParse->db, sizeof(int)*pTab->nCol);
+ if( aColTabMap==0 ) return 0;
+ if( aTabColMap ){
+ int i;
+ assert( sqlite3DbMallocSize(pParse->db, aTabColMap) >=
+ sizeof(int)*pTab->nCol );
+ for(i=0; i<pTab->nCol; i++){
+ if( aTabColMap[i]>0 ){
+ assert( aTabColMap[i]<=pColumn->nId );
+ aColTabMap[aTabColMap[i]-1] = i;
+ }
+ }
+ }else{
+ int nHidden = 0;
+ int i, j;
+ for(i=j=0; i<pTab->nCol; i++){
+ if( (pTab->aCol[i].colFlags & COLFLAG_NOINSERT)!=0 ){
+ nHidden++;
+ }else{
+ aColTabMap[j++] = i - nHidden;
+ }
+ }
+ }
+ return aColTabMap;
+}
+
+/*
+** Scan all expressions in pList. If any is just a DEFAULT keyword,
+** convert that expression into a new expressionthat evaluates to
+** the default value of the corresponding table.
+*/
+static void convertDefaultExpr(
+ Parse *pParse, /* Parsing context */
+ int *aColTabMap, /* Mapping from pList entry to pTab column number */
+ Table *pTab, /* Table being inserted into */
+ ExprList *pList /* The list to scan */
+){
+ int i, iCol;
+ for(i=0; i<pList->nExpr; i++){
+ Expr *p = pList->a[i].pExpr;
+ if( p->op!=TK_DEFAULT ) continue;
+ iCol = aColTabMap[i];
+ assert( iCol>=0 && iCol<pTab->nCol );
+ if( pTab->aCol[iCol].iDflt==0 ){
+ p->op = TK_NULL;
+ }else{
+ p->op = TK_UPLUS;
+ assert( p->pLeft==0 );
+ p->pLeft = sqlite3ExprDup(pParse->db,
+ sqlite3ColumnExpr(pTab, &pTab->aCol[iCol]), 0);
+ }
+ }
+}
+
/* Forward declaration */
static int xferOptimization(
Parse *pParse, /* Parser context */
**
** The 3rd template is for when the second template does not apply
** and the SELECT clause does not read from <table> at any time.
-** The generated code follows this template:
+** This template is also used when the INSERT has a VALUES clause with
+** two or more rows. Pseudocode for this, the 3rd template is:
**
** X <- A
** goto B
**
** The 4th template is used if the insert statement takes its
** values from a SELECT but the data is being inserted into a table
-** that is also read as part of the SELECT. In the third form,
+** that is also read as part of the SELECT. In the fourth form,
** we have to use an intermediate table to store the results of
** the select. The template is like this:
**
}
}
+ /* If there are DEFAULT keywords within VALUES clauses on the right-hand
+ ** side of this INSERT, convert them into the corresponding column default
+ ** values.
+ */
+ if( pParse->bDfltInExpr ){
+ int *aColTabMap = computeColTabMap(pParse, aTabColMap, pTab, pColumn);
+ if( aColTabMap==0 ){
+ assert( pParse->nErr && pParse->db->mallocFailed );
+ }else if( pSelect==0 ){
+ /* A single-row VALUES clause in pList */
+ convertDefaultExpr(pParse, aColTabMap, pTab, pList);
+ }else if( (pSelect->selFlags & SF_Values)!=0 ){
+ /* A multi-row VALUES clause in pSelect */
+ Select *pS = pSelect;
+ do{
+ convertDefaultExpr(pParse, aColTabMap, pTab, pS->pEList);
+ pS = pS->pPrior;
+ }while( pS );
+ }
+ sqlite3DbFree(db, aColTabMap);
+ }
+
/* Figure out how many columns of data are supplied. If the data
** is coming from a SELECT statement, then generate a co-routine that
** produces a single row of the SELECT on each invocation. The