Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -4893,10 +4893,14 @@ #endif case TK_STRING: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3VdbeLoadString(v, target, pExpr->u.zToken); return target; + } + case TK_DEFAULT: { + sqlite3VdbeAddOp1(v, OP_DfltNull, 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 ** sanely and not crash. But keep the assert() to bring the problem Index: src/insert.c ================================================================== --- src/insert.c +++ src/insert.c @@ -788,10 +788,41 @@ Table *pDest, /* The table we are inserting into */ Select *pSelect, /* A SELECT statement to use as the data source */ int onError, /* How to handle constraint errors */ 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 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( iColnCol ); + + pCol = &pTab->aCol[iCol]; + sqlite3ValueFromExpr(db, + sqlite3ColumnExpr(pTab,pCol), ENC(db), + pCol->affinity, &pValue); + sqlite3VdbeAddOp1(v, OP_ToDefault, iReg); + sqlite3VdbeAppendP4(v, pValue, P4_MEM); +} /* ** This routine is called to handle SQL of the following forms: ** ** insert into TABLE (IDLIST) values(EXPRLIST),(EXPRLIST),... @@ -1421,13 +1452,24 @@ sqlite3VdbeAddOp3(v, OP_Column, srcTab, k, iRegStore); }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: src/parse.y ================================================================== --- src/parse.y +++ src/parse.y @@ -118,11 +118,13 @@ /* ** Generate a syntax error */ static void parserSyntaxError(Parse *pParse, Token *p){ - sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", p); + if( sqlite3_strglob("*syntax error*", pParse->zErrMsg)!=0 ){ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", p); + } } /* ** Disable lookaside memory allocation for objects that might be ** shared across database connections. @@ -1530,10 +1532,77 @@ nexprlist(A) ::= nexprlist(A) COMMA expr(Y). {A = sqlite3ExprListAppend(pParse,A,Y);} nexprlist(A) ::= expr(Y). {A = sqlite3ExprListAppend(pParse,0,Y); /*A-overwrites-Y*/} + +%include { + /* Forward declaration */ + static SQLITE_NOINLINE void parserRequireInsertContext( + Parse *pParse, /* The SQLite parsing context */ + void *pLemon, /* The LEMON parser state */ + Token *pErrToken, /* Token that might be a syntax error */ + int nRhs /* Number of RHS tokens on the ruls */ + ); +} +%code { + /* This routine checks to see if the parser stack looks like either of these: + ** + ** insert_cmd INTO xfullname idlist_opt VALUES LP + ** insert_cmd INTO xfullname idlist_opt values COMMA LP + ** + ** If the parser stack is different from both of these, then raise a syntax error + ** on pErrToken. + */ + static SQLITE_NOINLINE void parserRequireInsertContext( + Parse *pParse, /* The SQLite parsing context */ + void *pLemon, /* The LEMON parser state */ + Token *pErrToken, /* Token that might be a syntax error */ + int nRhs /* Number of RHS tokens on the ruls */ + ){ + yyParser *yypParser = (yyParser*)pLemon; + yyStackEntry *yytos = yypParser->yytos - nRhs; + int bFault = 0; + if( (yytos - yypParser->yystack) < 6 + || yytos[0].major!=TK_LP + ){ + bFault = 1; + }else + if( yytos[-1].major==TK_COMMA + && (yytos[-2].major==YYNT_values || yytos[-2].major==YYNT_mvalues) + && yytos[-3].major==YYNT_idlist_opt + ){ + /* This is ok */ + }else + if( yytos[-1].major==TK_VALUES + && yytos[-2].major==YYNT_idlist_opt + ){ + /* This is ok */ + }else + { + bFault = 1; /* Cannot match */ + } + if( bFault ) parserSyntaxError(pParse, pErrToken); + pParse->bValuesDflt = 1; + } +} + +// The following reduction rules only succeed if the previous two +// tokens are "VALUES LP". If the previous two tokens are anything +// different, a syntax error is raised. +// +nexprlist(A) ::= nexprlist(A) COMMA DEFAULT(D). { + Expr *p = sqlite3PExpr(pParse,TK_DEFAULT,0,0); + parserRequireInsertContext(pParse, yypParser, &D, 3); + A = sqlite3ExprListAppend(pParse,A,p); +} +nexprlist(A) ::= DEFAULT(D). { + Expr *p = sqlite3PExpr(pParse,TK_DEFAULT,0,0); + parserRequireInsertContext(pParse, yypParser, &D, 1); + A = sqlite3ExprListAppend(pParse,0,p); +} + %ifndef SQLITE_OMIT_SUBQUERY /* A paren_exprlist is an optional expression list contained inside ** of parenthesis */ %type paren_exprlist {ExprList*} %destructor paren_exprlist {sqlite3ExprListDelete(pParse->db, $$);} Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -1819,11 +1819,12 @@ pPk = 0; r2 = 0; }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); /* reg[7] counts the number of entries in the table. ** reg[8+i] counts the number of entries in the i-th index Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -1023,11 +1023,11 @@ ** bit on the first register of the previous value. This will cause the ** OP_Ne added in codeDistinct() to always fail on the first iteration of ** 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: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -3853,10 +3853,11 @@ #endif bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */ 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 */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -579,11 +579,15 @@ */ static void memTracePrint(Mem *p){ if( p->flags & MEM_Undefined ){ printf(" undefined"); }else if( p->flags & MEM_Null ){ - printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL"); + if( p->flags==(MEM_Null|MEM_Term|MEM_Subtype) && p->eSubtype==0 ){ + printf(" NULL-default"); + }else{ + printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL"); + } }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ printf(" si:%lld", p->u.i); }else if( (p->flags & (MEM_IntReal))!=0 ){ printf(" ir:%lld", p->u.i); }else if( p->flags & MEM_Int ){ @@ -599,11 +603,15 @@ char zBuf[1000]; sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); sqlite3VdbeMemPrettyPrint(p, &acc); printf(" %s", sqlite3StrAccumFinish(&acc)); } - if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype); + if( (p->flags & MEM_Subtype)!=0 + && (p->eSubtype!=0 || (p->flags & MEM_Null)==0) + ){ + printf(" subtype=0x%02x", p->eSubtype); + } } static void registerTrace(int iReg, Mem *p){ printf("R[%d] = ", iReg); memTracePrint(p); if( p->pScopyFrom ){ @@ -1471,22 +1479,25 @@ ** Write a NULL into registers P2. If P3 greater than P2, then also write ** NULL into register P3 and every register in between P2 and P3. If P3 ** 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. */ case OP_BeginSubrtn: case OP_Null: { /* out2 */ int cnt; u16 nullFlag; 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 ); + assert( SQLITE_NULL_CLEARED==MEM_Cleared ); + pOut->flags = nullFlag = pOp->p1 | MEM_Null; pOut->n = 0; #ifdef SQLITE_DEBUG pOut->uTemp = 0; #endif while( cnt>0 ){ @@ -1512,10 +1523,49 @@ assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); pOut = &aMem[pOp->p1]; pOut->flags = (pOut->flags&~(MEM_Undefined|MEM_AffMask))|MEM_Null; break; } + +/* Opcode: DfltNull P1 * * * * +** Synopsis: r[P1]=DEFAULT-NULL +** +** Set register P1 to have the value NULL that has a special pointer +** value to indicate that it originated as a DEFAULT keyword in a VALUES +** clause. +*/ +case OP_DfltNull: { + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); + pOut = &aMem[pOp->p1]; + memAboutToChange(p, pOut); + sqlite3VdbeMemSetNull(pOut); + pOut->flags = MEM_Null|MEM_Term|MEM_Subtype; + pOut->eSubtype = 0; + break; +} + +/* Opcode: ToDefault P1 * * P4 * +** Synopsis: if r[P1]==DEFAULT then r[P1]=P4 +** +** If register P1 contains the special NULL value created by the +** OP_DfltNull opcode 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_TypeMask|MEM_Term))==(MEM_Null|MEM_Term|MEM_Subtype) + && pIn1->eSubtype==0 + ){ + memAboutToChange(p, pIn1); + sqlite3VdbeMemShallowCopy(pIn1, pOp->p4.pMem, MEM_Static); + UPDATE_MAX_BLOBSIZE(pIn1); + REGISTER_TRACE(pOp->p1, pIn1); + } + break; +} /* Opcode: Blob P1 P2 * P4 * ** Synopsis: r[P2]=P4 (len=P1) ** ** P4 points to a blob of data P1 bytes long. Store this Index: src/vdbe.h ================================================================== --- src/vdbe.h +++ src/vdbe.h @@ -186,10 +186,15 @@ ** Additional non-public SQLITE_PREPARE_* flags */ #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_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. */ Vdbe *sqlite3VdbeCreate(Parse*); Index: src/vdbeInt.h ================================================================== --- src/vdbeInt.h +++ src/vdbeInt.h @@ -257,12 +257,13 @@ /* One or more of the following flags are set to indicate the ** representations of the value stored in the Mem struct. ** ** * 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 ** sqlite3_value_pointer(). ** Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -747,10 +747,11 @@ pOp->opcode = OP_Sequence; pOp->p1 = iAutoidxCur; #ifdef SQLITE_ALLOW_ROWID_IN_VIEW if( iAutoidxCur==0 ){ pOp->opcode = OP_Null; + pOp->p1 = 0; pOp->p3 = 0; } #endif } } Index: tool/lemon.c ================================================================== --- tool/lemon.c +++ tool/lemon.c @@ -4931,10 +4931,18 @@ */ for(i=0; insymbol; i++){ fprintf(out," /* %4d */ \"%s\",\n",i, lemp->symbols[i]->name); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); + + /* Generate internal #defines for every non-terminal symbol. + */ + for(i=0; insymbol; i++){ + if( !ISLOWER(lemp->symbols[i]->name[0]) ) continue; + fprintf(out,"#define YYNT_%-20s %4d\n",lemp->symbols[i]->name, i);lineno++; + } + tplt_xfer(lemp->name,in,out,&lineno); /* Generate a table containing a text string that describes every ** rule in the rule set of the grammar. This information is used ** when tracing REDUCE actions. */ Index: tool/lempar.c ================================================================== --- tool/lempar.c +++ tool/lempar.c @@ -277,10 +277,13 @@ ** are required. The following table supplies these names */ static const char *const yyTokenName[] = { %% }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ + +/* Numeric values assigned to non-terminal symbols. */ +%% #ifndef NDEBUG /* For tracing reduce actions, the names of all rules are required. */ static const char *const yyRuleName[] = {