]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
An attempt to allow the DEFAULT keyword in the VALUES clause of an INSERT.
authordrh <>
Wed, 12 Feb 2025 20:54:32 +0000 (20:54 +0000)
committerdrh <>
Wed, 12 Feb 2025 20:54:32 +0000 (20:54 +0000)
This check-in does not work right.

FossilOrigin-Name: 85c108eb0ff8e47046ba6ec702accf46bd56dc077ada0afa3360ffa4fcdc0f34

12 files changed:
manifest
manifest.uuid
src/expr.c
src/insert.c
src/parse.y
src/pragma.c
src/select.c
src/sqliteInt.h
src/vdbe.c
src/vdbe.h
src/vdbeInt.h
src/where.c

index 87b8f1ef50e018dcb58302a0517d366154738c1a..3aa5f46faddfc0872aa6888243ba0f5621329e7b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Merge\sthe\slatest\strunk\schanges\sinto\sthe\sdefault-in-values\sbranch.
-D 2025-02-12T18:22:36.262
+C An\sattempt\sto\sallow\sthe\sDEFAULT\skeyword\sin\sthe\sVALUES\sclause\sof\san\sINSERT.\nThis\scheck-in\sdoes\snot\swork\sright.
+D 2025-02-12T20:54:32.402
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
@@ -729,7 +729,7 @@ F src/date.c 842c08ac143a56a627b05ac51d68624f2b7b03e3b4cba596205e735eed64ee57
 F src/dbpage.c 2e677acb658a29965e55398bbc61161cb7819da538057c8032adac7ab8e4a8c0
 F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
 F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
-F src/expr.c ca943270395374afc65256ce86cdb152a22fa6ff146895175833b89ba870e117
+F src/expr.c c1af6df70e460d0b24a2b6d417849ac198229ab349e1ddacad3918b9f48f6ce1
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
 F src/func.c b2fb33139972d7d65640b27ea962a49f1616265428001090cab39fcf270228e1
@@ -738,7 +738,7 @@ F src/hash.c 73934a7f7ab1cb110614a9388cb516893b0cf5b7b69e4fd1a0780ac4ce166be7
 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 999ef0f0edb0093b902484bf2f7e6a77c7ed61eae348616cdd1dba3a93983f2b
 F src/json.c 2663a0c7e574cb928de944720dcdcc11c931877d877549b8f1258a4002efd6f7
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
@@ -768,22 +768,22 @@ F src/os_win.c 49c7725b500f5867e8360e75eeb30f9d70b62fa1f05c8a101da627210578df32
 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
 F src/pager.c 3a1c4e7f69af482e33c8cba8a75afe0dda0ea6391240adac22b040ce1bdeef44
 F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
-F src/parse.y c3db7ead52bf0b0568eb840d37df5dd5b6c29ea7367d891cdd66b543c933c5c6
+F src/parse.y d13928e736dad1692a4d464f0063c118aec8e53bf325ebc8e3e7c49f99edd3b9
 F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
 F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
 F src/pcache1.c 49516ad7718a3626f28f710fa7448ef1fce3c07fd169acbb4817341950264319
-F src/pragma.c ce1182217aa540e034c6da2f17515e3706bf52c837e8222361be9ccd7a9d495a
+F src/pragma.c 409e35bf91026abe6ac188bb6fb98b94df1dd4d09ce9a9f0ed8697b237ec1c78
 F src/prepare.c 1832be043fce7d489959aae6f994c452d023914714c4d5457beaed51c0f3d126
 F src/printf.c 96f7f8baeedc7639da94e4e7a4a2c200e2537c4eec9e5e1c2ffc821f40eb3105
 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c 626c24b258b111f75c22107aa5614ad89810df3026f5ca071116d3fe75925c75
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
-F src/select.c 57893cc8b099f231f7ed5b84faff14841f2aabb4776e32e17fae00aeae0a8993
+F src/select.c db244d449fcb7c7e50797becec19ec26bec512b4fda0ce117b1a51243065220a
 F src/shell.c.in b377a59822f207106424f08aead37e78b609222e98f86f04cc8a03563ccf3237
 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 dc012bb2be3842542fa5ee7cbd32e4e193eccd1861ea23184daaf0f29ae12e82
 F src/sqliteLimit.h 1bbdbf72bd0411d003267ffebc59a262f061df5653027a75627d03f48ca30523
 F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -847,9 +847,9 @@ F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
 F src/utf.c 8b29d9a5956569ea2700f869669b8ef67a9662ee5e724ff77ab3c387e27094ba
 F src/util.c 9ff6470dabcf943fd796d2da766c98bd328c8f6fe036a31e5b338e628603f989
 F src/vacuum.c b763b6457bd058d2072ef9364832351fd8d11e8abf70cbb349657360f7d55c40
-F src/vdbe.c b98d86de7f0e6c02fb14e0e1ae8feab6aa84669d389771a848e23f59eb70dcad
-F src/vdbe.h 3d26d5c7660c5c7bd33ffb0d8784615072d8b23c81f8110870efe2631136bc89
-F src/vdbeInt.h 078b1c15b26587b54c1c1879d0d2f4dec812b9de4c337fed9faf73fbcc3bf091
+F src/vdbe.c a068cb6614035ca83ad454dbb55147a67d7426fcaa03222c7b45101c2d7efba8
+F src/vdbe.h 8cca1d3f90b18d5215913f6d569c022ff1d5b016b0e1afed22f77274a6f205d8
+F src/vdbeInt.h 4836978baf3f70a8042d81c0649046d18e721a3ca64cc73f594869730873386f
 F src/vdbeapi.c 82fe278a7c71b653235c6f9fb5de0b5de589908dfcb011ba2a782e8becf06f86
 F src/vdbeaux.c 541d3d232714455960eab4ed10b34cb48b4bcd565d7539ef31092f5e73648e6b
 F src/vdbeblob.c 9166b6eb7054e5da82e35255892fb1ed551355a4716452539e8e3ac14f25fbe3
@@ -862,7 +862,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c 4e6181d8780ab0af2e1388d0754cbe6f2f04593d2b1ab6c41699a89942fd8997
 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
 F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
-F src/where.c 09dc313e7223ca1217c39c7026b00f16ff449a8323511a762fcba7863a00f4cd
+F src/where.c 1ca8a781c4735b2fecb5b72ce49a97c7cdc41c650b8279a93a87443f67b47d2a
 F src/whereInt.h d20cddddb1d61b18d5cb1fcfa9b77fbeebbc4afe44d996e603452a23b3009ee1
 F src/wherecode.c 5baa06f0daae7d38aca1d4814030b82ad4f127fe6bad18f0644776a474f6088b
 F src/whereexpr.c 2415c8eee5ff89a8b709d7d83d71c1ff986cd720d0520057e1d8a5371339012a
@@ -2207,8 +2207,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 2ff4129ea05c1cc5a0c58540c7de9cdd5831a808514d11ac5ba2d4a44ca20354 0cfbe349d4b740f3d2be8c714cf679901fc2465db4c64e4c3742da700d82f4e7
-R f75dcf997fa430b54d1f0e267a94a336
+P 480d7c1a1abb4b543bbc6ee37db82c5232c69d0abc2722c00e262e6c64c860ff
+R 26905e85d686434917aa2e53862e881e
 U drh
-Z 13b0f60b307c4db5960dca9f95b5d27b
+Z e749e66dd6424beae3c3ec5070e0cc40
 # Remove this line to create a well-formed Fossil manifest.
index 4ac1be53f129d2129aaa885b11f2e707991a33c9..7794ed129a6f4014f7afd12b8d71131e34eb8d10 100644 (file)
@@ -1 +1 @@
-480d7c1a1abb4b543bbc6ee37db82c5232c69d0abc2722c00e262e6c64c860ff
+85c108eb0ff8e47046ba6ec702accf46bd56dc077ada0afa3360ffa4fcdc0f34
index 3011fcd9add269189845d0cc116d40f1c937b463..d1b3d04785bacd5806d7c3260ace22b1ed43cc37 100644 (file)
@@ -4896,6 +4896,10 @@ expr_code_doover:
       sqlite3VdbeLoadString(v, target, pExpr->u.zToken);
       return target;
     }
+    case TK_DEFAULT: {
+      sqlite3VdbeAddOp2(v, OP_Null, SQLITE_NULL_DEFAULT, target);
+      return target;
+    }
     default: {
       /* Make NULL the default case so that if a bug causes an illegal
       ** Expr node to be passed into this function, it will be handled
index c1ca1897ed8c4797787287c498996e24a75faf2c..a948f8e06b76b1e234622077f60606ff4cbb5ccc 100644 (file)
@@ -791,6 +791,39 @@ static int xferOptimization(
   int iDbDest           /* The database of pDest */
 );
 
+/*
+** If the iCol-th column of pTab has a default value, then add
+** code that checks the content of register iReg to see if it
+** is a SQLITE_NULL_DEFAULT and if it is, changes the content
+** of iReg to the default value of the iCol-th column of pTab.
+*/
+static SQLITE_NOINLINE void insertResolveValuesDflt(
+  Parse *pParse,         /* Parsing context */
+  Table *pTab,           /* Table being inserted into */
+  int iCol,              /* Column being inserted into */
+  int iReg               /* Register containing the value to insert */
+){
+  Vdbe *v = pParse->pVdbe;
+  sqlite3 *db = pParse->db;
+  sqlite3_value *pValue = 0;
+  Column *pCol;
+
+  assert( pParse->bValuesDflt );
+  assert( pParse->pVdbe!=0 );
+  assert( pTab->aCol[iCol].iDflt>0 );
+  assert( !IsView(pTab) );
+  assert( iCol<pTab->nCol );
+
+  pCol = &pTab->aCol[iCol];
+  sqlite3ValueFromExpr(db,
+                       sqlite3ColumnExpr(pTab,pCol), ENC(db),
+                       pCol->affinity, &pValue);
+  if( pValue ){
+    sqlite3VdbeAddOp1(v, OP_ToDefault, iReg);
+    sqlite3VdbeAppendP4(v, pValue, P4_MEM);
+  }
+}
+
 /*
 ** This routine is called to handle SQL of the following forms:
 **
@@ -1422,10 +1455,21 @@ void sqlite3Insert(
     }else if( pSelect ){
       if( regFromSelect!=regData ){
         sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+k, iRegStore);
+        if( pParse->bValuesDflt && pTab->aCol[i].iDflt ){
+          insertResolveValuesDflt(pParse, pTab, i, iRegStore);
+        }
       }
     }else{
       Expr *pX = pList->a[k].pExpr;
-      int y = sqlite3ExprCodeTarget(pParse, pX, iRegStore);
+      int y;
+      if( pX->op==TK_DEFAULT ){
+        Expr *pDflt = sqlite3ColumnExpr(pTab, &pTab->aCol[i]);
+        if( pDflt ){
+          sqlite3ExprCodeFactorable(pParse, pDflt, iRegStore);
+          continue;
+        }
+      }
+      y = sqlite3ExprCodeTarget(pParse, pX, iRegStore);
       if( y!=iRegStore ){
         sqlite3VdbeAddOp2(v,
           ExprHasProperty(pX, EP_Subquery) ? OP_Copy : OP_SCopy, y, iRegStore);
index e1beef00cd910356d3ae7ad2a2280e25e860178d..a861a026bf5d26d9768454f0c11b048fba521c0d 100644 (file)
@@ -1566,7 +1566,7 @@ nexprlist(A) ::= expr(Y).
       bFault = 1;
     }else
     if( yytos[-1].major==TK_COMMA
-     && yytos[-2].major==YYNT_values
+     && (yytos[-2].major==YYNT_values || yytos[-2].major==YYNT_mvalues)
      && yytos[-3].major==YYNT_idlist_opt
     ){
       /* This is ok */
@@ -1580,6 +1580,7 @@ nexprlist(A) ::= expr(Y).
       bFault = 1;  /* Cannot match */
     }
     if( bFault ) parserSyntaxError(pParse, pErrToken);
+    pParse->bValuesDflt = 1;
   }
 }
 
index 291ccf7af17a8acd59ed3c014efad81f6956adbc..e0f4565d0f272241782d99e70b07df7ce31b3fa7 100644 (file)
@@ -1821,7 +1821,8 @@ void sqlite3Pragma(
         }else{
           pPk = sqlite3PrimaryKeyIndex(pTab);
           r2 = sqlite3GetTempRange(pParse, pPk->nKeyCol);
-          sqlite3VdbeAddOp3(v, OP_Null, 1, r2, r2+pPk->nKeyCol-1);
+          sqlite3VdbeAddOp3(v, OP_Null,
+                            SQLITE_NULL_CLEARED, r2, r2+pPk->nKeyCol-1);
         }
         sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
                                    1, 0, &iDataCur, &iIdxCur);
index e47a9b6be29acff83bcdc157316ca7c8c1034155..de645482716b80e7d006c15430904ed505c3df3b 100644 (file)
@@ -1025,7 +1025,7 @@ static void fixDistinctOpenEph(
       ** the loop even if the first row is all NULLs.  */
       VdbeOp *pOp = sqlite3VdbeGetOp(v, iOpenEphAddr);
       pOp->opcode = OP_Null;
-      pOp->p1 = 1;
+      pOp->p1 = SQLITE_NULL_CLEARED;
       pOp->p2 = iVal;
     }
   }
index c8ecaf85712e3f819cb6a282b732fb6befde7552..e0219d1bd4b1404945a346f52eb99c7c5b649887 100644 (file)
@@ -3855,6 +3855,7 @@ struct Parse {
   bft bHasWith :1;      /* True if statement contains WITH */
   bft okConstFactor :1; /* OK to factor out constants */
   bft checkSchema :1;   /* Causes schema cookie check after an error */
+  bft bValuesDflt :1;   /* DEFAULT keyword appears in a VALUES clause */
   int nRangeReg;       /* Size of the temporary register block */
   int iRangeReg;       /* First register in temporary register block */
   int nErr;            /* Number of errors seen */
index ec871c5a6e8f51183f58cfb20af7e20f89ccb754..e88c4b71b1faa3c99b12770992b0f08c4e7ca7e9 100644 (file)
@@ -1473,9 +1473,11 @@ case OP_String: {          /* out2 */
 ** is less than P2 (typically P3 is zero) then only register P2 is
 ** set to NULL.
 **
-** If the P1 value is non-zero, then also set the MEM_Cleared flag so that
-** NULL values will not compare equal even if SQLITE_NULLEQ is set on
-** OP_Ne or OP_Eq.
+** If the P1 value can be SQLITE_NULL_CLEARED to create a NULL value that 
+** will not compare equal even if SQLITE_NULLEQ is set on OP_Ne or OP_Eq.
+** In other words, SQLITE_NULL_CLEARED creates a NULL that never compares
+** equal to any other NULL.  Or P1 can be SQLITE_NULL_DEFAULT to indicate
+** that the NULL value started as a DEFAULT keyword.
 */
 case OP_BeginSubrtn:
 case OP_Null: {           /* out2 */
@@ -1484,7 +1486,10 @@ case OP_Null: {           /* out2 */
   pOut = out2Prerelease(p, pOp);
   cnt = pOp->p3-pOp->p2;
   assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
-  pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
+  assert( pOp->p1==0 || pOp->p1==MEM_Cleared || pOp->p1==MEM_Zero );
+  assert( SQLITE_NULL_CLEARED==MEM_Cleared );
+  assert( SQLITE_NULL_DEFAULT==MEM_Zero );
+  pOut->flags = nullFlag = pOp->p1 | MEM_Null;
   pOut->n = 0;
 #ifdef SQLITE_DEBUG
   pOut->uTemp = 0;
@@ -2849,6 +2854,25 @@ case OP_NotNull: {            /* same as TK_NOTNULL, jump, in1 */
   break;
 }
 
+/* Opcode: ToDefault P1 * * P4 *
+** Synopsis: if r[P1]==DEFAULT then r[P1]=P4
+**
+** If register P1 contains the special NULL value that indicates
+** that it originated from the DEFAULT keyword in a VALUES clause,
+** then change its value to the value in P4.
+*/
+case OP_ToDefault: {            /* in1 */
+  assert( pOp->p4type==P4_MEM );
+  pIn1 = &aMem[pOp->p1];
+  if( (pIn1->flags & (MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero) ){
+    memAboutToChange(p, pIn1);
+    sqlite3VdbeMemShallowCopy(pIn1, pOp->p4.pMem, MEM_Static);
+    UPDATE_MAX_BLOBSIZE(pIn1);
+    REGISTER_TRACE(pOp->p1, pIn1);
+  }
+  break;
+}
+
 /* Opcode: IfNullRow P1 P2 P3 * *
 ** Synopsis: if P1.nullRow then r[P3]=NULL, goto P2
 **
index 476f1b4ea2da2fd5212775b98f866e1f80b19449..28b3e7335e4a5d63bc4a465fbccf38e0bfbf710b 100644 (file)
@@ -188,6 +188,12 @@ typedef struct VdbeOpList VdbeOpList;
 #define SQLITE_PREPARE_SAVESQL  0x80  /* Preserve SQL text */
 #define SQLITE_PREPARE_MASK     0x1f  /* Mask of public flags */
 
+/*
+** Allowed P1 arguments to OP_Null for special kinds of NULLs.
+*/
+#define SQLITE_NULL_DEFAULT  0x0400   /* NULL is really the DEFAULT keyword */
+#define SQLITE_NULL_CLEARED  0x0100   /* NULL always <> to other NULLs */
+
 /*
 ** Prototypes for the VDBE interface.  See comments on the implementation
 ** for a description of what each of these routines does.
index 12af82726867cf16185a0145d475927a8a7a0f37..69f82133092ecacc147f4ca7e51f7f0f46487a19 100644 (file)
@@ -259,8 +259,9 @@ struct sqlite3_value {
 **
 **  *  MEM_Null                An SQL NULL value
 **
-**  *  MEM_Null|MEM_Zero       An SQL NULL with the virtual table
-**                             UPDATE no-change flag set
+**  *  MEM_Null|MEM_Zero       An SQL NULL with flag that indicates
+**                             UPDATE no-change for virtual tables and
+**                             DEFAULT for ordinary tables.
 **
 **  *  MEM_Null|MEM_Term|      An SQL NULL, but also contains a
 **        MEM_Subtype          pointer accessible using
index 5cb52b8adb0a933f1a7a35b809e01ea7fbb2cbd6..b6cdccb6c8f3c625e31754ff3dd7c11dd7114cf4 100644 (file)
@@ -749,6 +749,7 @@ static void translateColumnToCopy(
 #ifdef SQLITE_ALLOW_ROWID_IN_VIEW
       if( iAutoidxCur==0 ){
         pOp->opcode = OP_Null;
+        pOp->p1 = 0;
         pOp->p3 = 0;
       }
 #endif