/ Check-in [939d8282]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add extended error codes for all SQLITE_CONSTRAINT errors.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 939d8282748b00a7032cdd72e5d3bf3086ebfc97
User & Date: drh 2013-02-11 13:47:39
Context
2013-02-12
22:09
A bug report coming from from Firefox (https://bugzilla.mozilla.org/show_bug.cgi?id=840377) describes an infinite recursion. We are unable to reproduce the problem. Nevertheless, this check-in should prevent the problem from ever occurring again. check-in: b7222a2b user: drh tags: trunk
09:46
Improve memory allocation error handling on WinCE. Closed-Leaf check-in: 09dfc0c9 user: mistachkin tags: wince
2013-02-11
13:47
Add extended error codes for all SQLITE_CONSTRAINT errors. check-in: 939d8282 user: drh tags: trunk
2013-02-09
15:37
Rename SQLITE_CONSTRAINT_RAISE to SQLITE_CONSTRAINT_TRIGGER. Put the extended constraint error codes in alphabetical order. Add many test cases for the extended constraint error codes. Closed-Leaf check-in: 3f674375 user: drh tags: constraint-error-codes
2013-02-07
09:33
Fix harmless compiler warnings. check-in: 4a7b4ee0 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/build.c.

  2443   2443     sqlite3VdbeJumpHere(v, addr1);
  2444   2444     addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
  2445   2445     if( pIndex->onError!=OE_None ){
  2446   2446       int j2 = sqlite3VdbeCurrentAddr(v) + 3;
  2447   2447       sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
  2448   2448       addr2 = sqlite3VdbeCurrentAddr(v);
  2449   2449       sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
  2450         -    sqlite3HaltConstraint(
  2451         -        pParse, OE_Abort, "indexed columns are not unique", P4_STATIC
         2450  +    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
         2451  +        OE_Abort, "indexed columns are not unique", P4_STATIC
  2452   2452       );
  2453   2453     }else{
  2454   2454       addr2 = sqlite3VdbeCurrentAddr(v);
  2455   2455     }
  2456   2456     sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
  2457   2457     sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
  2458   2458     sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
................................................................................
  2470   2470       ** (made available to the compiler for reuse) using 
  2471   2471       ** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique
  2472   2472       ** opcode use the values stored within seems dangerous. However, since
  2473   2473       ** we can be sure that no other temp registers have been allocated
  2474   2474       ** since sqlite3ReleaseTempRange() was called, it is safe to do so.
  2475   2475       */
  2476   2476       sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
  2477         -    sqlite3HaltConstraint(
  2478         -        pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
         2477  +    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
         2478  +        "indexed columns are not unique", P4_STATIC);
  2479   2479     }
  2480   2480     sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
  2481   2481     sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
  2482   2482   #endif
  2483   2483     sqlite3ReleaseTempReg(pParse, regRecord);
  2484   2484     sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
  2485   2485     sqlite3VdbeJumpHere(v, addr1);
................................................................................
  3688   3688   }
  3689   3689   
  3690   3690   /*
  3691   3691   ** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT
  3692   3692   ** error. The onError parameter determines which (if any) of the statement
  3693   3693   ** and/or current transaction is rolled back.
  3694   3694   */
  3695         -void sqlite3HaltConstraint(Parse *pParse, int onError, char *p4, int p4type){
         3695  +void sqlite3HaltConstraint(
         3696  +  Parse *pParse,    /* Parsing context */
         3697  +  int errCode,      /* extended error code */
         3698  +  int onError,      /* Constraint type */
         3699  +  char *p4,         /* Error message */
         3700  +  int p4type        /* P4_STATIC or P4_TRANSIENT */
         3701  +){
  3696   3702     Vdbe *v = sqlite3GetVdbe(pParse);
         3703  +  assert( (errCode&0xff)==SQLITE_CONSTRAINT );
  3697   3704     if( onError==OE_Abort ){
  3698   3705       sqlite3MayAbort(pParse);
  3699   3706     }
  3700         -  sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, p4, p4type);
         3707  +  sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
  3701   3708   }
  3702   3709   
  3703   3710   /*
  3704   3711   ** Check to see if pIndex uses the collating sequence pColl.  Return
  3705   3712   ** true if it does and false if it does not.
  3706   3713   */
  3707   3714   #ifndef SQLITE_OMIT_REINDEX

Changes to src/expr.c.

  2931   2931           sqlite3MayAbort(pParse);
  2932   2932         }
  2933   2933         assert( !ExprHasProperty(pExpr, EP_IntValue) );
  2934   2934         if( pExpr->affinity==OE_Ignore ){
  2935   2935           sqlite3VdbeAddOp4(
  2936   2936               v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
  2937   2937         }else{
  2938         -        sqlite3HaltConstraint(pParse, pExpr->affinity, pExpr->u.zToken, 0);
         2938  +        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
         2939  +                              pExpr->affinity, pExpr->u.zToken, 0);
  2939   2940         }
  2940   2941   
  2941   2942         break;
  2942   2943       }
  2943   2944   #endif
  2944   2945     }
  2945   2946     sqlite3ReleaseTempReg(pParse, regFree1);

Changes to src/fkey.c.

    17     17   #ifndef SQLITE_OMIT_TRIGGER
    18     18   
    19     19   /*
    20     20   ** Deferred and Immediate FKs
    21     21   ** --------------------------
    22     22   **
    23     23   ** Foreign keys in SQLite come in two flavours: deferred and immediate.
    24         -** If an immediate foreign key constraint is violated, SQLITE_CONSTRAINT
    25         -** is returned and the current statement transaction rolled back. If a 
           24  +** If an immediate foreign key constraint is violated,
           25  +** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current
           26  +** statement transaction rolled back. If a 
    26     27   ** deferred foreign key constraint is violated, no action is taken 
    27     28   ** immediately. However if the application attempts to commit the 
    28     29   ** transaction before fixing the constraint violation, the attempt fails.
    29     30   **
    30     31   ** Deferred constraints are implemented using a simple counter associated
    31     32   ** with the database handle. The counter is set to zero each time a 
    32     33   ** database transaction is opened. Each time a statement is executed 
................................................................................
    82     83   ** If a delete caused by OR REPLACE violates an FK constraint, an exception
    83     84   ** is thrown, even if the FK constraint would be satisfied after the new 
    84     85   ** row is inserted.
    85     86   **
    86     87   ** Immediate constraints are usually handled similarly. The only difference 
    87     88   ** is that the counter used is stored as part of each individual statement
    88     89   ** object (struct Vdbe). If, after the statement has run, its immediate
    89         -** constraint counter is greater than zero, it returns SQLITE_CONSTRAINT
           90  +** constraint counter is greater than zero,
           91  +** it returns SQLITE_CONSTRAINT_FOREIGNKEY
    90     92   ** and the statement transaction is rolled back. An exception is an INSERT
    91     93   ** statement that inserts a single row only (no triggers). In this case,
    92     94   ** instead of using a counter, an exception is thrown immediately if the
    93     95   ** INSERT violates a foreign key constraint. This is necessary as such
    94     96   ** an INSERT does not open a statement transaction.
    95     97   **
    96     98   ** TODO: How should dropping a table be handled? How should renaming a 
................................................................................
   422    424   
   423    425     if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
   424    426       /* Special case: If this is an INSERT statement that will insert exactly
   425    427       ** one row into the table, raise a constraint immediately instead of
   426    428       ** incrementing a counter. This is necessary as the VM code is being
   427    429       ** generated for will not open a statement transaction.  */
   428    430       assert( nIncr==1 );
   429         -    sqlite3HaltConstraint(
   430         -        pParse, OE_Abort, "foreign key constraint failed", P4_STATIC
          431  +    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
          432  +        OE_Abort, "foreign key constraint failed", P4_STATIC
   431    433       );
   432    434     }else{
   433    435       if( nIncr>0 && pFKey->isDeferred==0 ){
   434    436         sqlite3ParseToplevel(pParse)->mayAbort = 1;
   435    437       }
   436    438       sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
   437    439     }
................................................................................
   663    665       pParse->disableTriggers = 0;
   664    666   
   665    667       /* If the DELETE has generated immediate foreign key constraint 
   666    668       ** violations, halt the VDBE and return an error at this point, before
   667    669       ** any modifications to the schema are made. This is because statement
   668    670       ** transactions are not able to rollback schema changes.  */
   669    671       sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
   670         -    sqlite3HaltConstraint(
   671         -        pParse, OE_Abort, "foreign key constraint failed", P4_STATIC
          672  +    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
          673  +        OE_Abort, "foreign key constraint failed", P4_STATIC
   672    674       );
   673    675   
   674    676       if( iSkip ){
   675    677         sqlite3VdbeResolveLabel(v, iSkip);
   676    678       }
   677    679     }
   678    680   }

Changes to src/insert.c.

  1241   1241       switch( onError ){
  1242   1242         case OE_Abort:
  1243   1243           sqlite3MayAbort(pParse);
  1244   1244         case OE_Rollback:
  1245   1245         case OE_Fail: {
  1246   1246           char *zMsg;
  1247   1247           sqlite3VdbeAddOp3(v, OP_HaltIfNull,
  1248         -                                  SQLITE_CONSTRAINT, onError, regData+i);
         1248  +                          SQLITE_CONSTRAINT_NOTNULL, onError, regData+i);
  1249   1249           zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
  1250   1250                                 pTab->zName, pTab->aCol[i].zName);
  1251   1251           sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
  1252   1252           break;
  1253   1253         }
  1254   1254         case OE_Ignore: {
  1255   1255           sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest);
................................................................................
  1281   1281           char *zConsName = pCheck->a[i].zName;
  1282   1282           if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
  1283   1283           if( zConsName ){
  1284   1284             zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
  1285   1285           }else{
  1286   1286             zConsName = 0;
  1287   1287           }
  1288         -        sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
         1288  +        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
         1289  +                              onError, zConsName, P4_DYNAMIC);
  1289   1290         }
  1290   1291         sqlite3VdbeResolveLabel(v, allOk);
  1291   1292       }
  1292   1293     }
  1293   1294   #endif /* !defined(SQLITE_OMIT_CHECK) */
  1294   1295   
  1295   1296     /* If we have an INTEGER PRIMARY KEY, make sure the primary key
................................................................................
  1312   1313         default: {
  1313   1314           onError = OE_Abort;
  1314   1315           /* Fall thru into the next case */
  1315   1316         }
  1316   1317         case OE_Rollback:
  1317   1318         case OE_Abort:
  1318   1319         case OE_Fail: {
  1319         -        sqlite3HaltConstraint(
  1320         -          pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
         1320  +        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
         1321  +           onError, "PRIMARY KEY must be unique", P4_STATIC);
  1321   1322           break;
  1322   1323         }
  1323   1324         case OE_Replace: {
  1324   1325           /* If there are DELETE triggers on this table and the
  1325   1326           ** recursive-triggers flag is set, call GenerateRowDelete() to
  1326   1327           ** remove the conflicting row from the table. This will fire
  1327   1328           ** the triggers and remove both the table and index b-tree entries.
................................................................................
  1440   1441             sqlite3StrAccumAppend(&errMsg, zSep, -1);
  1441   1442             zSep = ", ";
  1442   1443             sqlite3StrAccumAppend(&errMsg, zCol, -1);
  1443   1444           }
  1444   1445           sqlite3StrAccumAppend(&errMsg,
  1445   1446               pIdx->nColumn>1 ? " are not unique" : " is not unique", -1);
  1446   1447           zErr = sqlite3StrAccumFinish(&errMsg);
  1447         -        sqlite3HaltConstraint(pParse, onError, zErr, 0);
         1448  +        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
         1449  +                              onError, zErr, 0);
  1448   1450           sqlite3DbFree(errMsg.db, zErr);
  1449   1451           break;
  1450   1452         }
  1451   1453         case OE_Ignore: {
  1452   1454           assert( seenReplace==0 );
  1453   1455           sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
  1454   1456           break;
................................................................................
  1848   1850     sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
  1849   1851     emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
  1850   1852     regData = sqlite3GetTempReg(pParse);
  1851   1853     regRowid = sqlite3GetTempReg(pParse);
  1852   1854     if( pDest->iPKey>=0 ){
  1853   1855       addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
  1854   1856       addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
  1855         -    sqlite3HaltConstraint(
  1856         -        pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
         1857  +    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
         1858  +        onError, "PRIMARY KEY must be unique", P4_STATIC);
  1857   1859       sqlite3VdbeJumpHere(v, addr2);
  1858   1860       autoIncStep(pParse, regAutoinc, regRowid);
  1859   1861     }else if( pDest->pIndex==0 ){
  1860   1862       addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
  1861   1863     }else{
  1862   1864       addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
  1863   1865       assert( (pDest->tabFlags & TF_Autoincrement)==0 );

Changes to src/sqlite.h.in.

   475    475   #define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
   476    476   #define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
   477    477   #define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
   478    478   #define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
   479    479   #define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
   480    480   #define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
   481    481   #define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
          482  +#define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
          483  +#define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
          484  +#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
          485  +#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
          486  +#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
          487  +#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))
          488  +#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
          489  +#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
          490  +#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
   482    491   
   483    492   /*
   484    493   ** CAPI3REF: Flags For File Open Operations
   485    494   **
   486    495   ** These bit values are intended for use in the
   487    496   ** 3rd parameter to the [sqlite3_open_v2()] interface and
   488    497   ** in the 4th parameter to the [sqlite3_vfs.xOpen] method.

Changes to src/sqliteInt.h.

  2900   2900   void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
  2901   2901                                        int*,int,int,int,int,int*);
  2902   2902   void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
  2903   2903   int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
  2904   2904   void sqlite3BeginWriteOperation(Parse*, int, int);
  2905   2905   void sqlite3MultiWrite(Parse*);
  2906   2906   void sqlite3MayAbort(Parse*);
  2907         -void sqlite3HaltConstraint(Parse*, int, char*, int);
         2907  +void sqlite3HaltConstraint(Parse*, int, int, char*, int);
  2908   2908   Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
  2909   2909   ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
  2910   2910   SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
  2911   2911   IdList *sqlite3IdListDup(sqlite3*,IdList*);
  2912   2912   Select *sqlite3SelectDup(sqlite3*,Select*,int);
  2913   2913   void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*);
  2914   2914   FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8);

Changes to src/test1.c.

   134    134       case SQLITE_FULL:                zName = "SQLITE_FULL";              break;
   135    135       case SQLITE_CANTOPEN:            zName = "SQLITE_CANTOPEN";          break;
   136    136       case SQLITE_PROTOCOL:            zName = "SQLITE_PROTOCOL";          break;
   137    137       case SQLITE_EMPTY:               zName = "SQLITE_EMPTY";             break;
   138    138       case SQLITE_SCHEMA:              zName = "SQLITE_SCHEMA";            break;
   139    139       case SQLITE_TOOBIG:              zName = "SQLITE_TOOBIG";            break;
   140    140       case SQLITE_CONSTRAINT:          zName = "SQLITE_CONSTRAINT";        break;
          141  +    case SQLITE_CONSTRAINT_UNIQUE:   zName = "SQLITE_CONSTRAINT_UNIQUE"; break;
          142  +    case SQLITE_CONSTRAINT_TRIGGER:  zName = "SQLITE_CONSTRAINT_TRIGGER";break;
          143  +    case SQLITE_CONSTRAINT_FOREIGNKEY:
          144  +                                 zName = "SQLITE_CONSTRAINT_FOREIGNKEY"; break;
          145  +    case SQLITE_CONSTRAINT_CHECK:    zName = "SQLITE_CONSTRAINT_CHECK";  break;
          146  +    case SQLITE_CONSTRAINT_PRIMARYKEY:
          147  +                                 zName = "SQLITE_CONSTRAINT_PRIMARYKEY"; break;
          148  +    case SQLITE_CONSTRAINT_NOTNULL:  zName = "SQLITE_CONSTRAINT_NOTNULL";break;
          149  +    case SQLITE_CONSTRAINT_COMMITHOOK:
          150  +                                 zName = "SQLITE_CONSTRAINT_COMMITHOOK"; break;
          151  +    case SQLITE_CONSTRAINT_VTAB:     zName = "SQLITE_CONSTRAINT_VTAB";   break;
          152  +    case SQLITE_CONSTRAINT_FUNCTION: zName = "SQLITE_CONSTRAINT_FUNCTION";break;
   141    153       case SQLITE_MISMATCH:            zName = "SQLITE_MISMATCH";          break;
   142    154       case SQLITE_MISUSE:              zName = "SQLITE_MISUSE";            break;
   143    155       case SQLITE_NOLFS:               zName = "SQLITE_NOLFS";             break;
   144    156       case SQLITE_AUTH:                zName = "SQLITE_AUTH";              break;
   145    157       case SQLITE_FORMAT:              zName = "SQLITE_FORMAT";            break;
   146    158       case SQLITE_RANGE:               zName = "SQLITE_RANGE";             break;
   147    159       case SQLITE_NOTADB:              zName = "SQLITE_NOTADB";            break;

Changes to src/test_spellfix.c.

  2669   2669         ** cause zWord to be NULL, so we look at the "command" column to see
  2670   2670         ** what special actions to take */
  2671   2671         const char *zCmd = 
  2672   2672            (const char*)sqlite3_value_text(argv[SPELLFIX_COL_COMMAND+2]);
  2673   2673         if( zCmd==0 ){
  2674   2674           pVTab->zErrMsg = sqlite3_mprintf("%s.word may not be NULL",
  2675   2675                                            p->zTableName);
  2676         -        return SQLITE_CONSTRAINT;
         2676  +        return SQLITE_CONSTRAINT_NOTNULL;
  2677   2677         }
  2678   2678         if( strcmp(zCmd,"reset")==0 ){
  2679   2679           /* Reset the  edit cost table (if there is one). */
  2680   2680           editDist3ConfigDelete(p->pConfig3);
  2681   2681           p->pConfig3 = 0;
  2682   2682           return SQLITE_OK;
  2683   2683         }

Changes to src/vdbe.c.

   865    865       sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql);
   866    866     }
   867    867     rc = sqlite3VdbeHalt(p);
   868    868     assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
   869    869     if( rc==SQLITE_BUSY ){
   870    870       p->rc = rc = SQLITE_BUSY;
   871    871     }else{
   872         -    assert( rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT );
          872  +    assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
   873    873       assert( rc==SQLITE_OK || db->nDeferredCons>0 );
   874    874       rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
   875    875     }
   876    876     goto vdbe_return;
   877    877   }
   878    878   
   879    879   /* Opcode: Integer P1 P2 * * *
................................................................................
  6059   6059       rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
  6060   6060       db->vtabOnConflict = vtabOnConflict;
  6061   6061       importVtabErrMsg(p, pVtab);
  6062   6062       if( rc==SQLITE_OK && pOp->p1 ){
  6063   6063         assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
  6064   6064         db->lastRowid = lastRowid = rowid;
  6065   6065       }
  6066         -    if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
         6066  +    if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
  6067   6067         if( pOp->p5==OE_Ignore ){
  6068   6068           rc = SQLITE_OK;
  6069   6069         }else{
  6070   6070           p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5);
  6071   6071         }
  6072   6072       }else{
  6073   6073         p->nChange++;

Changes to src/vdbeaux.c.

   363    363     while( (pOp = opIterNext(&sIter))!=0 ){
   364    364       int opcode = pOp->opcode;
   365    365       if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename 
   366    366   #ifndef SQLITE_OMIT_FOREIGN_KEY
   367    367        || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) 
   368    368   #endif
   369    369        || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
   370         -      && (pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
          370  +      && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
   371    371       ){
   372    372         hasAbort = 1;
   373    373         break;
   374    374       }
   375    375     }
   376    376     sqlite3DbFree(v->db, sIter.apSub);
   377    377   
................................................................................
  1766   1766       return rc;
  1767   1767     }
  1768   1768   
  1769   1769     /* If there are any write-transactions at all, invoke the commit hook */
  1770   1770     if( needXcommit && db->xCommitCallback ){
  1771   1771       rc = db->xCommitCallback(db->pCommitArg);
  1772   1772       if( rc ){
  1773         -      return SQLITE_CONSTRAINT;
         1773  +      return SQLITE_CONSTRAINT_COMMITHOOK;
  1774   1774       }
  1775   1775     }
  1776   1776   
  1777   1777     /* The simple case - no more than one database file (not counting the
  1778   1778     ** TEMP database) has a transaction active.   There is no need for the
  1779   1779     ** master-journal.
  1780   1780     **
................................................................................
  2058   2058   /*
  2059   2059   ** This function is called when a transaction opened by the database 
  2060   2060   ** handle associated with the VM passed as an argument is about to be 
  2061   2061   ** committed. If there are outstanding deferred foreign key constraint
  2062   2062   ** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
  2063   2063   **
  2064   2064   ** If there are outstanding FK violations and this function returns 
  2065         -** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT and write
  2066         -** an error message to it. Then return SQLITE_ERROR.
         2065  +** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
         2066  +** and write an error message to it. Then return SQLITE_ERROR.
  2067   2067   */
  2068   2068   #ifndef SQLITE_OMIT_FOREIGN_KEY
  2069   2069   int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
  2070   2070     sqlite3 *db = p->db;
  2071   2071     if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){
  2072         -    p->rc = SQLITE_CONSTRAINT;
         2072  +    p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
  2073   2073       p->errorAction = OE_Abort;
  2074   2074       sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
  2075   2075       return SQLITE_ERROR;
  2076   2076     }
  2077   2077     return SQLITE_OK;
  2078   2078   }
  2079   2079   #endif
................................................................................
  2180   2180         if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
  2181   2181           rc = sqlite3VdbeCheckFk(p, 1);
  2182   2182           if( rc!=SQLITE_OK ){
  2183   2183             if( NEVER(p->readOnly) ){
  2184   2184               sqlite3VdbeLeave(p);
  2185   2185               return SQLITE_ERROR;
  2186   2186             }
  2187         -          rc = SQLITE_CONSTRAINT;
         2187  +          rc = SQLITE_CONSTRAINT_FOREIGNKEY;
  2188   2188           }else{ 
  2189   2189             /* The auto-commit flag is true, the vdbe program was successful 
  2190   2190             ** or hit an 'OR FAIL' constraint and there are no deferred foreign
  2191   2191             ** key constraints to hold up the transaction. This means a commit 
  2192   2192             ** is required. */
  2193   2193             rc = vdbeCommit(db, p);
  2194   2194           }
................................................................................
  2223   2223       ** do so. If this operation returns an error, and the current statement
  2224   2224       ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
  2225   2225       ** current statement error code.
  2226   2226       */
  2227   2227       if( eStatementOp ){
  2228   2228         rc = sqlite3VdbeCloseStatement(p, eStatementOp);
  2229   2229         if( rc ){
  2230         -        if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){
         2230  +        if( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ){
  2231   2231             p->rc = rc;
  2232   2232             sqlite3DbFree(db, p->zErrMsg);
  2233   2233             p->zErrMsg = 0;
  2234   2234           }
  2235   2235           sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
  2236   2236           sqlite3CloseSavepoints(db);
  2237   2237           db->autoCommit = 1;

Changes to test/capi2.test.

   231    231   
   232    232   # Update for v3: Preparing a statement does not affect the change counter.
   233    233   # (Test result changes from 0 to 1).  (Later:) change counter updates occur
   234    234   # when sqlite3_step returns, not at finalize time.
   235    235   do_test capi2-3.13b {db changes} {0}
   236    236   
   237    237   do_test capi2-3.14 {
   238         -  list [sqlite3_finalize $VM] [sqlite3_errmsg $DB]
   239         -} {SQLITE_CONSTRAINT {column a is not unique}}
          238  +  list [sqlite3_finalize $VM] [sqlite3_errmsg $DB] \
          239  +       [sqlite3_extended_errcode $DB]
          240  +} {SQLITE_CONSTRAINT {column a is not unique} SQLITE_CONSTRAINT_UNIQUE}
   240    241   do_test capi2-3.15 {
   241    242     set VM [sqlite3_prepare $DB {CREATE TABLE t2(a NOT NULL, b)} -1 TAIL]
   242    243     set TAIL
   243    244   } {}
   244    245   do_test capi2-3.16 {
   245    246     list [sqlite3_step $VM] \
   246    247          [sqlite3_column_count $VM] \
................................................................................
   254    255     set VM [sqlite3_prepare $DB {INSERT INTO t2 VALUES(NULL,2)} -1 TAIL]
   255    256     list [sqlite3_step $VM] \
   256    257          [sqlite3_column_count $VM] \
   257    258          [get_row_values $VM] \
   258    259          [get_column_names $VM]
   259    260   } {SQLITE_ERROR 0 {} {}}
   260    261   do_test capi2-3.19 {
   261         -  list [sqlite3_finalize $VM] [sqlite3_errmsg $DB]
   262         -} {SQLITE_CONSTRAINT {t2.a may not be NULL}}
          262  +  list [sqlite3_finalize $VM] [sqlite3_errmsg $DB] \
          263  +       [sqlite3_extended_errcode $DB]
          264  +} {SQLITE_CONSTRAINT {t2.a may not be NULL} SQLITE_CONSTRAINT_NOTNULL}
   263    265   
   264    266   do_test capi2-3.20 {
   265    267     execsql {
   266    268       CREATE TABLE a1(message_id, name , UNIQUE(message_id, name) );
   267    269       INSERT INTO a1 VALUES(1, 1);
   268    270     }
   269    271   } {}
................................................................................
   274    276   do_test capi2-3.22 {
   275    277     sqlite3_errcode $DB
   276    278   } {SQLITE_ERROR}
   277    279   do_test capi2-3.23 {
   278    280     sqlite3_finalize $VM
   279    281   } {SQLITE_CONSTRAINT}
   280    282   do_test capi2-3.24 {
   281         -  sqlite3_errcode $DB
   282         -} {SQLITE_CONSTRAINT}
          283  +  list [sqlite3_errcode $DB] [sqlite3_extended_errcode $DB]
          284  +} {SQLITE_CONSTRAINT SQLITE_CONSTRAINT_UNIQUE}
   283    285   
   284    286   # Two or more virtual machines exists at the same time.
   285    287   #
   286    288   do_test capi2-4.1 {
   287    289     set VM1 [sqlite3_prepare $DB {INSERT INTO t2 VALUES(1,2)} -1 TAIL]
   288    290     set TAIL
   289    291   } {}

Changes to test/conflict.test.

   576    576     catchsql {
   577    577       BEGIN;
   578    578       UPDATE t3 SET x=x+1;
   579    579       INSERT INTO t2 VALUES(3,3,3,3,1);
   580    580       SELECT * FROM t2;
   581    581     }
   582    582   } {1 {column e is not unique}}
          583  +verify_ex_errcode conflict-9.21b SQLITE_CONSTRAINT_UNIQUE
   583    584   do_test conflict-9.20 {
   584    585     catch {execsql {COMMIT}}
   585    586     execsql {SELECT * FROM t3}
   586    587   } {5}
   587    588   do_test conflict-9.21 {
   588    589     catchsql {
   589    590       BEGIN;
   590    591       UPDATE t3 SET x=x+1;
   591    592       UPDATE t2 SET e=e+1 WHERE e=1;
   592    593       SELECT * FROM t2;
   593    594     }
   594    595   } {1 {column e is not unique}}
          596  +verify_ex_errcode conflict-9.21b SQLITE_CONSTRAINT_UNIQUE
   595    597   do_test conflict-9.22 {
   596    598     catch {execsql {COMMIT}}
   597    599     execsql {SELECT * FROM t3}
   598    600   } {5}
   599    601   do_test conflict-9.23 {
   600    602     catchsql {
   601    603       INSERT INTO t2 VALUES(3,3,1,3,3);
................................................................................
   777    779     }
   778    780   } {1 one 2 two}
   779    781   do_test conflict-12.3 {
   780    782     catchsql {
   781    783       UPDATE t5 SET a=a+1 WHERE a=1;
   782    784     }
   783    785   } {1 {PRIMARY KEY must be unique}}
          786  +verify_ex_errcode conflict-12.3b SQLITE_CONSTRAINT_PRIMARYKEY
   784    787   do_test conflict-12.4 {
   785    788     execsql {
   786    789       UPDATE OR REPLACE t5 SET a=a+1 WHERE a=1;
   787    790       SELECT * FROM t5;
   788    791     }
   789    792   } {2 one}
   790    793   
................................................................................
   798    801       BEGIN;
   799    802       REPLACE INTO t13 VALUES(1);
   800    803     }
   801    804     catchsql {
   802    805       REPLACE INTO t13 VALUES(2);
   803    806     }
   804    807   } {1 {constraint failed}}
          808  +verify_ex_errcode conflict-13.1b SQLITE_CONSTRAINT_CHECK
   805    809   do_test conflict-13.2 {
   806    810     execsql {
   807    811       REPLACE INTO t13 VALUES(3);
   808    812       COMMIT;
   809    813       SELECT * FROM t13;
   810    814     }
   811    815   } {1 3}
   812    816   
   813    817   
   814    818   finish_test

Changes to test/errmsg.test.

    76     76   }
    77     77   do_test 2.2 {
    78     78     error_messages "INSERT INTO t1 VALUES('ghi', 'def')"
    79     79   } [list {*}{
    80     80       SQLITE_ERROR      {SQL logic error or missing database} 
    81     81       SQLITE_CONSTRAINT {column b is not unique}
    82     82   }]
           83  +verify_ex_errcode 2.2b SQLITE_CONSTRAINT_UNIQUE
    83     84   do_test 2.3 {
    84     85     error_messages_v2 "INSERT INTO t1 VALUES('ghi', 'def')"
    85     86   } [list {*}{
    86     87       SQLITE_CONSTRAINT {column b is not unique}
    87     88       SQLITE_CONSTRAINT {column b is not unique}
    88     89   }]
           90  +verify_ex_errcode 2.3b SQLITE_CONSTRAINT_UNIQUE
    89     91   
    90     92   #-------------------------------------------------------------------------
    91     93   # Test SQLITE_SCHEMA errors. And, for _v2(), test that if the schema
    92     94   # change invalidates the SQL statement itself the error message is returned
    93     95   # correctly.
    94     96   #
    95     97   do_execsql_test 3.1.1 {

Changes to test/fkey2.test.

  1429   1429       INSERT INTO one VALUES(1, 2, 3);
  1430   1430     }
  1431   1431   } {1}
  1432   1432   do_test fkey2-17.1.2 {
  1433   1433     set STMT [sqlite3_prepare_v2 db "INSERT INTO two VALUES(4, 5, 6)" -1 dummy]
  1434   1434     sqlite3_step $STMT
  1435   1435   } {SQLITE_CONSTRAINT}
         1436  +verify_ex_errcode fkey2-17.1.2b SQLITE_CONSTRAINT_FOREIGNKEY
  1436   1437   ifcapable autoreset {
  1437   1438     do_test fkey2-17.1.3 {
  1438   1439       sqlite3_step $STMT
  1439   1440     } {SQLITE_CONSTRAINT}
         1441  +  verify_ex_errcode fkey2-17.1.3b SQLITE_CONSTRAINT_FOREIGNKEY
  1440   1442   } else {
  1441   1443     do_test fkey2-17.1.3 {
  1442   1444       sqlite3_step $STMT
  1443   1445     } {SQLITE_MISUSE}
  1444   1446   }
  1445   1447   do_test fkey2-17.1.4 {
  1446   1448     sqlite3_finalize $STMT
  1447   1449   } {SQLITE_CONSTRAINT}
         1450  +verify_ex_errcode fkey2-17.1.4b SQLITE_CONSTRAINT_FOREIGNKEY
  1448   1451   do_test fkey2-17.1.5 {
  1449   1452     execsql {
  1450   1453       INSERT INTO one VALUES(2, 3, 4);
  1451   1454       INSERT INTO one VALUES(3, 4, 5);
  1452   1455       INSERT INTO two VALUES(1, 2, 3);
  1453   1456       INSERT INTO two VALUES(2, 3, 4);
  1454   1457       INSERT INTO two VALUES(3, 4, 5);
................................................................................
  1484   1487   } {SQLITE_ROW}
  1485   1488   do_test fkey2-17.1.12 {
  1486   1489     sqlite3_column_text $STMT 0
  1487   1490   } {1}
  1488   1491   do_test fkey2-17.1.13 {
  1489   1492     sqlite3_step $STMT
  1490   1493   } {SQLITE_CONSTRAINT}
         1494  +verify_ex_errcode fkey2-17.1.13b SQLITE_CONSTRAINT_FOREIGNKEY
  1491   1495   do_test fkey2-17.1.14 {
  1492   1496     sqlite3_finalize $STMT
  1493   1497   } {SQLITE_CONSTRAINT}
         1498  +verify_ex_errcode fkey2-17.1.14b SQLITE_CONSTRAINT_FOREIGNKEY
  1494   1499   
  1495   1500   drop_all_tables
  1496   1501   do_test fkey2-17.2.1 {
  1497   1502     execsql {
  1498   1503       CREATE TABLE high("a'b!" PRIMARY KEY, b);
  1499   1504       CREATE TABLE low(
  1500   1505         c, 
................................................................................
  1640   1645     }
  1641   1646   } {}
  1642   1647   do_test fkey2-19.2 {
  1643   1648     set S [sqlite3_prepare_v2 db "DELETE FROM main WHERE id = ?" -1 dummy]
  1644   1649     sqlite3_bind_int $S 1 2
  1645   1650     sqlite3_step $S
  1646   1651   } {SQLITE_CONSTRAINT}
         1652  +verify_ex_errcode fkey2-19.2b SQLITE_CONSTRAINT_FOREIGNKEY
  1647   1653   do_test fkey2-19.3 {
  1648   1654     sqlite3_reset $S
  1649   1655   } {SQLITE_CONSTRAINT}
         1656  +verify_ex_errcode fkey2-19.3b SQLITE_CONSTRAINT_FOREIGNKEY
  1650   1657   do_test fkey2-19.4 {
  1651   1658     sqlite3_bind_int $S 1 1
  1652   1659     sqlite3_step $S
  1653   1660   } {SQLITE_DONE}
  1654   1661   do_test fkey2-19.4 {
  1655   1662     sqlite3_finalize $S
  1656   1663   } {SQLITE_OK}

Changes to test/fkey4.test.

    38     38   
    39     39   do_test fkey4-1.2 {
    40     40     set ::DB [sqlite3_connection_pointer db]
    41     41     set ::SQL {INSERT INTO t2 VALUES(2,4)}
    42     42     set ::STMT1 [sqlite3_prepare_v2 $::DB $::SQL -1 TAIL]
    43     43     sqlite3_step $::STMT1
    44     44   } {SQLITE_CONSTRAINT}
           45  +verify_ex_errcode fkey4-1.2b SQLITE_CONSTRAINT_FOREIGNKEY
    45     46   do_test fkey4-1.3 {
    46     47     set ::STMT2 [sqlite3_prepare_v2 $::DB $::SQL -1 TAIL]
    47     48     sqlite3_step $::STMT2
    48     49   } {SQLITE_CONSTRAINT}
           50  +verify_ex_errcode fkey4-1.3b SQLITE_CONSTRAINT_FOREIGNKEY
    49     51   do_test fkey4-1.4 {
    50     52     db eval {SELECT * FROM t2}
    51     53   } {1 3}
    52     54   sqlite3_finalize $::STMT1
    53     55   sqlite3_finalize $::STMT2
    54     56   
    55     57   finish_test

Changes to test/hook.test.

    70     70       set ::commit_cnt [execsql {SELECT * FROM t2}] 
    71     71       return 1
    72     72     }
    73     73     catchsql {
    74     74       INSERT INTO t2 VALUES(6,7);
    75     75     }
    76     76   } {1 {constraint failed}}
           77  +verify_ex_errcode hook-3.6b SQLITE_CONSTRAINT_COMMITHOOK
    77     78   do_test hook-3.7 {
    78     79     set ::commit_cnt
    79     80   } {1 2 2 3 3 4 4 5 5 6 6 7}
    80     81   do_test hook-3.8 {
    81     82     execsql {SELECT * FROM t2}
    82     83   } {1 2 2 3 3 4 4 5 5 6}
    83     84   

Changes to test/notnull.test.

    44     44   do_test notnull-1.2 {
    45     45     catchsql {
    46     46       DELETE FROM t1;
    47     47       INSERT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    48     48       SELECT * FROM t1 order by a;
    49     49     }
    50     50   } {1 {t1.a may not be NULL}}
           51  +verify_ex_errcode notnull-1.2b SQLITE_CONSTRAINT_NOTNULL
    51     52   do_test notnull-1.3 {
    52     53     catchsql {
    53     54       DELETE FROM t1;
    54     55       INSERT OR IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    55     56       SELECT * FROM t1 order by a;
    56     57     }
    57     58   } {0 {}}
................................................................................
    58     59   do_test notnull-1.4 {
    59     60     catchsql {
    60     61       DELETE FROM t1;
    61     62       INSERT OR REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    62     63       SELECT * FROM t1 order by a;
    63     64     }
    64     65   } {1 {t1.a may not be NULL}}
           66  +verify_ex_errcode notnull-1.4b SQLITE_CONSTRAINT_NOTNULL
    65     67   do_test notnull-1.5 {
    66     68     catchsql {
    67     69       DELETE FROM t1;
    68     70       INSERT OR ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    69     71       SELECT * FROM t1 order by a;
    70     72     }
    71     73   } {1 {t1.a may not be NULL}}
           74  +verify_ex_errcode notnull-1.5b SQLITE_CONSTRAINT_NOTNULL
    72     75   do_test notnull-1.6 {
    73     76     catchsql {
    74     77       DELETE FROM t1;
    75     78       INSERT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    76     79       SELECT * FROM t1 order by a;
    77     80     }
    78     81   } {0 {1 5 3 4 5}}
................................................................................
   100    103   do_test notnull-1.10 {
   101    104     catchsql {
   102    105       DELETE FROM t1;
   103    106       INSERT INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
   104    107       SELECT * FROM t1 order by a;
   105    108     }
   106    109   } {1 {t1.b may not be NULL}}
          110  +verify_ex_errcode notnull-1.10b SQLITE_CONSTRAINT_NOTNULL
   107    111   do_test notnull-1.11 {
   108    112     catchsql {
   109    113       DELETE FROM t1;
   110    114       INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
   111    115       SELECT * FROM t1 order by a;
   112    116     }
   113    117   } {0 {}}
................................................................................
   142    146   do_test notnull-1.16 {
   143    147     catchsql {
   144    148       DELETE FROM t1;
   145    149       INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
   146    150       SELECT * FROM t1 order by a;
   147    151     }
   148    152   } {1 {t1.c may not be NULL}}
          153  +verify_ex_errcode notnull-1.16b SQLITE_CONSTRAINT_NOTNULL
   149    154   do_test notnull-1.17 {
   150    155     catchsql {
   151    156       DELETE FROM t1;
   152    157       INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
   153    158       SELECT * FROM t1 order by a;
   154    159     }
   155    160   } {1 {t1.d may not be NULL}}
          161  +verify_ex_errcode notnull-1.17b SQLITE_CONSTRAINT_NOTNULL
   156    162   do_test notnull-1.18 {
   157    163     catchsql {
   158    164       DELETE FROM t1;
   159    165       INSERT OR ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
   160    166       SELECT * FROM t1 order by a;
   161    167     }
   162    168   } {0 {1 2 3 7 5}}
................................................................................
   170    176   do_test notnull-1.20 {
   171    177     catchsql {
   172    178       DELETE FROM t1;
   173    179       INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,null);
   174    180       SELECT * FROM t1 order by a;
   175    181     }
   176    182   } {1 {t1.e may not be NULL}}
          183  +verify_ex_errcode notnull-1.20b SQLITE_CONSTRAINT_NOTNULL
   177    184   do_test notnull-1.21 {
   178    185     catchsql {
   179    186       DELETE FROM t1;
   180    187       INSERT OR REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
   181    188       SELECT * FROM t1 order by a;
   182    189     }
   183    190   } {0 {5 5 3 2 1}}
................................................................................
   186    193     catchsql {
   187    194       DELETE FROM t1;
   188    195       INSERT INTO t1 VALUES(1,2,3,4,5);
   189    196       UPDATE t1 SET a=null;
   190    197       SELECT * FROM t1 ORDER BY a;
   191    198     }
   192    199   } {1 {t1.a may not be NULL}}
          200  +verify_ex_errcode notnull-2.1b SQLITE_CONSTRAINT_NOTNULL
   193    201   do_test notnull-2.2 {
   194    202     catchsql {
   195    203       DELETE FROM t1;
   196    204       INSERT INTO t1 VALUES(1,2,3,4,5);
   197    205       UPDATE OR REPLACE t1 SET a=null;
   198    206       SELECT * FROM t1 ORDER BY a;
   199    207     }
   200    208   } {1 {t1.a may not be NULL}}
          209  +verify_ex_errcode notnull-2.2b SQLITE_CONSTRAINT_NOTNULL
   201    210   do_test notnull-2.3 {
   202    211     catchsql {
   203    212       DELETE FROM t1;
   204    213       INSERT INTO t1 VALUES(1,2,3,4,5);
   205    214       UPDATE OR IGNORE t1 SET a=null;
   206    215       SELECT * FROM t1 ORDER BY a;
   207    216     }
................................................................................
   210    219     catchsql {
   211    220       DELETE FROM t1;
   212    221       INSERT INTO t1 VALUES(1,2,3,4,5);
   213    222       UPDATE OR ABORT t1 SET a=null;
   214    223       SELECT * FROM t1 ORDER BY a;
   215    224     }
   216    225   } {1 {t1.a may not be NULL}}
          226  +verify_ex_errcode notnull-2.4b SQLITE_CONSTRAINT_NOTNULL
   217    227   do_test notnull-2.5 {
   218    228     catchsql {
   219    229       DELETE FROM t1;
   220    230       INSERT INTO t1 VALUES(1,2,3,4,5);
   221    231       UPDATE t1 SET b=null;
   222    232       SELECT * FROM t1 ORDER BY a;
   223    233     }
   224    234   } {1 {t1.b may not be NULL}}
          235  +verify_ex_errcode notnull-2.6b SQLITE_CONSTRAINT_NOTNULL
   225    236   do_test notnull-2.6 {
   226    237     catchsql {
   227    238       DELETE FROM t1;
   228    239       INSERT INTO t1 VALUES(1,2,3,4,5);
   229    240       UPDATE OR REPLACE t1 SET b=null, d=e, e=d;
   230    241       SELECT * FROM t1 ORDER BY a;
   231    242     }
................................................................................
   258    269     catchsql {
   259    270       DELETE FROM t1;
   260    271       INSERT INTO t1 VALUES(1,2,3,4,5);
   261    272       UPDATE t1 SET e=null, a=b, b=a;
   262    273       SELECT * FROM t1 ORDER BY a;
   263    274     }
   264    275   } {1 {t1.e may not be NULL}}
          276  +verify_ex_errcode notnull-2.10b SQLITE_CONSTRAINT_NOTNULL
   265    277   
   266    278   do_test notnull-3.0 {
   267    279     execsql {
   268    280       CREATE INDEX t1a ON t1(a);
   269    281       CREATE INDEX t1b ON t1(b);
   270    282       CREATE INDEX t1c ON t1(c);
   271    283       CREATE INDEX t1d ON t1(d);
................................................................................
   283    295   do_test notnull-3.2 {
   284    296     catchsql {
   285    297       DELETE FROM t1;
   286    298       INSERT INTO t1(b,c,d,e) VALUES(2,3,4,5);
   287    299       SELECT * FROM t1 order by a;
   288    300     }
   289    301   } {1 {t1.a may not be NULL}}
          302  +verify_ex_errcode notnull-3.2b SQLITE_CONSTRAINT_NOTNULL
   290    303   do_test notnull-3.3 {
   291    304     catchsql {
   292    305       DELETE FROM t1;
   293    306       INSERT OR IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
   294    307       SELECT * FROM t1 order by a;
   295    308     }
   296    309   } {0 {}}
................................................................................
   297    310   do_test notnull-3.4 {
   298    311     catchsql {
   299    312       DELETE FROM t1;
   300    313       INSERT OR REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
   301    314       SELECT * FROM t1 order by a;
   302    315     }
   303    316   } {1 {t1.a may not be NULL}}
          317  +verify_ex_errcode notnull-3.4b SQLITE_CONSTRAINT_NOTNULL
   304    318   do_test notnull-3.5 {
   305    319     catchsql {
   306    320       DELETE FROM t1;
   307    321       INSERT OR ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
   308    322       SELECT * FROM t1 order by a;
   309    323     }
   310    324   } {1 {t1.a may not be NULL}}
          325  +verify_ex_errcode notnull-3.5b SQLITE_CONSTRAINT_NOTNULL
   311    326   do_test notnull-3.6 {
   312    327     catchsql {
   313    328       DELETE FROM t1;
   314    329       INSERT INTO t1(a,c,d,e) VALUES(1,3,4,5);
   315    330       SELECT * FROM t1 order by a;
   316    331     }
   317    332   } {0 {1 5 3 4 5}}
................................................................................
   339    354   do_test notnull-3.10 {
   340    355     catchsql {
   341    356       DELETE FROM t1;
   342    357       INSERT INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
   343    358       SELECT * FROM t1 order by a;
   344    359     }
   345    360   } {1 {t1.b may not be NULL}}
          361  +verify_ex_errcode notnull-3.10b SQLITE_CONSTRAINT_NOTNULL
   346    362   do_test notnull-3.11 {
   347    363     catchsql {
   348    364       DELETE FROM t1;
   349    365       INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
   350    366       SELECT * FROM t1 order by a;
   351    367     }
   352    368   } {0 {}}
................................................................................
   381    397   do_test notnull-3.16 {
   382    398     catchsql {
   383    399       DELETE FROM t1;
   384    400       INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
   385    401       SELECT * FROM t1 order by a;
   386    402     }
   387    403   } {1 {t1.c may not be NULL}}
          404  +verify_ex_errcode notnull-3.16b SQLITE_CONSTRAINT_NOTNULL
   388    405   do_test notnull-3.17 {
   389    406     catchsql {
   390    407       DELETE FROM t1;
   391    408       INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
   392    409       SELECT * FROM t1 order by a;
   393    410     }
   394    411   } {1 {t1.d may not be NULL}}
          412  +verify_ex_errcode notnull-3.17b SQLITE_CONSTRAINT_NOTNULL
   395    413   do_test notnull-3.18 {
   396    414     catchsql {
   397    415       DELETE FROM t1;
   398    416       INSERT OR ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
   399    417       SELECT * FROM t1 order by a;
   400    418     }
   401    419   } {0 {1 2 3 7 5}}
................................................................................
   409    427   do_test notnull-3.20 {
   410    428     catchsql {
   411    429       DELETE FROM t1;
   412    430       INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,null);
   413    431       SELECT * FROM t1 order by a;
   414    432     }
   415    433   } {1 {t1.e may not be NULL}}
          434  +verify_ex_errcode notnull-3.20b SQLITE_CONSTRAINT_NOTNULL
   416    435   do_test notnull-3.21 {
   417    436     catchsql {
   418    437       DELETE FROM t1;
   419    438       INSERT OR REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
   420    439       SELECT * FROM t1 order by a;
   421    440     }
   422    441   } {0 {5 5 3 2 1}}
................................................................................
   425    444     catchsql {
   426    445       DELETE FROM t1;
   427    446       INSERT INTO t1 VALUES(1,2,3,4,5);
   428    447       UPDATE t1 SET a=null;
   429    448       SELECT * FROM t1 ORDER BY a;
   430    449     }
   431    450   } {1 {t1.a may not be NULL}}
          451  +verify_ex_errcode notnull-4.1b SQLITE_CONSTRAINT_NOTNULL
   432    452   do_test notnull-4.2 {
   433    453     catchsql {
   434    454       DELETE FROM t1;
   435    455       INSERT INTO t1 VALUES(1,2,3,4,5);
   436    456       UPDATE OR REPLACE t1 SET a=null;
   437    457       SELECT * FROM t1 ORDER BY a;
   438    458     }
   439    459   } {1 {t1.a may not be NULL}}
          460  +verify_ex_errcode notnull-4.2b SQLITE_CONSTRAINT_NOTNULL
   440    461   do_test notnull-4.3 {
   441    462     catchsql {
   442    463       DELETE FROM t1;
   443    464       INSERT INTO t1 VALUES(1,2,3,4,5);
   444    465       UPDATE OR IGNORE t1 SET a=null;
   445    466       SELECT * FROM t1 ORDER BY a;
   446    467     }
................................................................................
   449    470     catchsql {
   450    471       DELETE FROM t1;
   451    472       INSERT INTO t1 VALUES(1,2,3,4,5);
   452    473       UPDATE OR ABORT t1 SET a=null;
   453    474       SELECT * FROM t1 ORDER BY a;
   454    475     }
   455    476   } {1 {t1.a may not be NULL}}
          477  +verify_ex_errcode notnull-4.4b SQLITE_CONSTRAINT_NOTNULL
   456    478   do_test notnull-4.5 {
   457    479     catchsql {
   458    480       DELETE FROM t1;
   459    481       INSERT INTO t1 VALUES(1,2,3,4,5);
   460    482       UPDATE t1 SET b=null;
   461    483       SELECT * FROM t1 ORDER BY a;
   462    484     }
   463    485   } {1 {t1.b may not be NULL}}
          486  +verify_ex_errcode notnull-4.5b SQLITE_CONSTRAINT_NOTNULL
   464    487   do_test notnull-4.6 {
   465    488     catchsql {
   466    489       DELETE FROM t1;
   467    490       INSERT INTO t1 VALUES(1,2,3,4,5);
   468    491       UPDATE OR REPLACE t1 SET b=null, d=e, e=d;
   469    492       SELECT * FROM t1 ORDER BY a;
   470    493     }
................................................................................
   497    520     catchsql {
   498    521       DELETE FROM t1;
   499    522       INSERT INTO t1 VALUES(1,2,3,4,5);
   500    523       UPDATE t1 SET e=null, a=b, b=a;
   501    524       SELECT * FROM t1 ORDER BY a;
   502    525     }
   503    526   } {1 {t1.e may not be NULL}}
          527  +verify_ex_errcode notnull-4.10b SQLITE_CONSTRAINT_NOTNULL
   504    528   
   505    529   # Test that bug 29ab7be99f is fixed.
   506    530   #
   507    531   do_test notnull-5.1 {
   508    532     execsql {
   509    533       DROP TABLE IF EXISTS t1;
   510    534       CREATE TABLE t1(a, b NOT NULL);
................................................................................
   515    539   }  {}
   516    540   do_test notnull-5.2 {
   517    541     catchsql {
   518    542       INSERT INTO t1 VALUES(1, 2);
   519    543       INSERT INTO t1 SELECT * FROM t2;
   520    544     }
   521    545   } {1 {t1.b may not be NULL}}
          546  +verify_ex_errcode notnull-5.2b SQLITE_CONSTRAINT_NOTNULL
   522    547   do_test notnull-5.3 {
   523    548     execsql { SELECT * FROM t1 }
   524    549   } {1 2}
   525    550   do_test notnull-5.4 {
   526    551     catchsql {
   527    552       DELETE FROM t1;
   528    553       BEGIN;
   529    554         INSERT INTO t1 VALUES(1, 2);
   530    555         INSERT INTO t1 SELECT * FROM t2;
   531    556       COMMIT;
   532    557     }
   533    558   } {1 {t1.b may not be NULL}}
          559  +verify_ex_errcode notnull-5.4b SQLITE_CONSTRAINT_NOTNULL
   534    560   do_test notnull-5.5 {
   535    561     execsql { SELECT * FROM t1 }
   536    562   } {1 2}
   537    563   
   538    564   finish_test
   539         -

Changes to test/tester.tcl.

    50     50   #      execsql                SQL ?DB?
    51     51   #
    52     52   # Commands to run test cases:
    53     53   #
    54     54   #      do_ioerr_test          TESTNAME ARGS...
    55     55   #      crashsql               ARGS...
    56     56   #      integrity_check        TESTNAME ?DB?
           57  +#      verify_ex_errcode      TESTNAME EXPECTED ?DB?
    57     58   #      do_test                TESTNAME SCRIPT EXPECTED
    58     59   #      do_execsql_test        TESTNAME SQL EXPECTED
    59     60   #      do_catchsql_test       TESTNAME SQL EXPECTED
    60     61   #
    61     62   # Commands providing a lower level interface to the global test counters:
    62     63   #
    63     64   #      set_test_counter       COUNTER ?VALUE?
................................................................................
   963    964   # Do an integrity check of the entire database
   964    965   #
   965    966   proc integrity_check {name {db db}} {
   966    967     ifcapable integrityck {
   967    968       do_test $name [list execsql {PRAGMA integrity_check} $db] {ok}
   968    969     }
   969    970   }
          971  +
          972  +# Check the extended error code
          973  +#
          974  +proc verify_ex_errcode {name expected {db db}} {
          975  +  do_test $name [list sqlite3_extended_errcode $db] $expected
          976  +}
   970    977   
   971    978   
   972    979   # Return true if the SQL statement passed as the second argument uses a
   973    980   # statement transaction.
   974    981   #
   975    982   proc sql_uses_stmt {db sql} {
   976    983     set stmt [sqlite3_prepare $db $sql -1 dummy]

Changes to test/trigger1.test.

   419    419       END;
   420    420       SELECT type, name FROM sqlite_master;
   421    421     }
   422    422   } [concat $view_v1 {table t2 trigger t2}]
   423    423   do_test trigger1-6.3 {
   424    424     catchsql {DELETE FROM t2}
   425    425   } {1 {deletes are not permitted}}
          426  +verify_ex_errcode trigger1-6.3b SQLITE_CONSTRAINT_TRIGGER
   426    427   do_test trigger1-6.4 {
   427    428     execsql {SELECT * FROM t2}
   428    429   } {3 4 7 8}
   429    430   do_test trigger1-6.5 {
   430    431     db close
   431    432     sqlite3 db test.db
   432    433     execsql {SELECT type, name FROM sqlite_master}

Changes to test/trigger3.test.

    41     41   do_test trigger3-1.1 {
    42     42       catchsql {
    43     43           BEGIN;
    44     44           INSERT INTO tbl VALUES (5, 5, 6);
    45     45           INSERT INTO tbl VALUES (1, 5, 6);
    46     46       }
    47     47   } {1 {Trigger abort}}
           48  +verify_ex_errcode trigger3-1.1b SQLITE_CONSTRAINT_TRIGGER
    48     49   do_test trigger3-1.2 {
    49     50       execsql {
    50     51           SELECT * FROM tbl;
    51     52           ROLLBACK;
    52     53       }
    53     54   } {5 5 6}
    54     55   do_test trigger3-1.3 {
................................................................................
    59     60   do_test trigger3-2.1 {
    60     61       catchsql {
    61     62           BEGIN;
    62     63           INSERT INTO tbl VALUES (5, 5, 6);
    63     64           INSERT INTO tbl VALUES (2, 5, 6);
    64     65       }
    65     66   } {1 {Trigger fail}}
           67  +verify_ex_errcode trigger3-2.1b SQLITE_CONSTRAINT_TRIGGER
    66     68   do_test trigger3-2.2 {
    67     69       execsql {
    68     70           SELECT * FROM tbl;
    69     71           ROLLBACK;
    70     72       }
    71     73   } {5 5 6 2 5 6}
    72     74   # ROLLBACK
................................................................................
    73     75   do_test trigger3-3.1 {
    74     76       catchsql {
    75     77           BEGIN;
    76     78           INSERT INTO tbl VALUES (5, 5, 6);
    77     79           INSERT INTO tbl VALUES (3, 5, 6);
    78     80       }
    79     81   } {1 {Trigger rollback}}
           82  +verify_ex_errcode trigger3-3.1b SQLITE_CONSTRAINT_TRIGGER
    80     83   do_test trigger3-3.2 {
    81     84       execsql {
    82     85           SELECT * FROM tbl;
    83     86       }
    84     87   } {}
    85     88   
    86     89   # Verify that a ROLLBACK trigger works like a FAIL trigger if
................................................................................
    88     91   #
    89     92   do_test trigger3-3.3 {
    90     93       catchsql {COMMIT}
    91     94       catchsql {
    92     95           INSERT INTO tbl VALUES (3, 9, 10);
    93     96       }
    94     97   } {1 {Trigger rollback}}
           98  +verify_ex_errcode trigger3-3.3b SQLITE_CONSTRAINT_TRIGGER
    95     99   do_test trigger3-3.4 {
    96    100       execsql {SELECT * FROM tbl}
    97    101   } {}
    98    102   
    99    103   # IGNORE
   100    104   do_test trigger3-4.1 {
   101    105       catchsql {
................................................................................
   168    172   }
   169    173   
   170    174   do_test trigger3-7.1 {
   171    175       catchsql {
   172    176           INSERT INTO tbl_view VALUES(1, 2, 3);
   173    177       }
   174    178   } {1 {View rollback}}
          179  +verify_ex_errcode trigger3-7.1b SQLITE_CONSTRAINT_TRIGGER
   175    180   do_test trigger3-7.2 {
   176    181       catchsql {
   177    182           INSERT INTO tbl_view VALUES(2, 2, 3);
   178    183       }
   179    184   } {0 {}}
   180    185   do_test trigger3-7.3 {
   181    186       catchsql {
   182    187           INSERT INTO tbl_view VALUES(3, 2, 3);
   183    188       }
   184    189   } {1 {View abort}}
          190  +verify_ex_errcode trigger3-7.3b SQLITE_CONSTRAINT_TRIGGER
   185    191   
   186    192   } ;# ifcapable view
   187    193   
   188    194   integrity_check trigger3-8.1
   189    195   
   190    196   catchsql { DROP TABLE tbl; } 
   191    197   catchsql { DROP TABLE tbl2; } 
   192    198   catchsql { DROP VIEW tbl_view; }
   193    199   
   194    200   finish_test

Changes to test/unique.test.

    44     44     }
    45     45   } {0 {}}
    46     46   do_test unique-1.3 {
    47     47     catchsql {
    48     48       INSERT INTO t1(a,b,c) VALUES(1,3,4)
    49     49     }
    50     50   } {1 {column a is not unique}}
           51  +verify_ex_errcode unique-1.3b SQLITE_CONSTRAINT_UNIQUE
    51     52   do_test unique-1.4 {
    52     53     execsql {
    53     54       SELECT * FROM t1 ORDER BY a;
    54     55     }
    55     56   } {1 2 3}
    56     57   do_test unique-1.5 {
    57     58     catchsql {
    58     59       INSERT INTO t1(a,b,c) VALUES(3,2,4)
    59     60     }
    60     61   } {1 {column b is not unique}}
           62  +verify_ex_errcode unique-1.5b SQLITE_CONSTRAINT_UNIQUE
    61     63   do_test unique-1.6 {
    62     64     execsql {
    63     65       SELECT * FROM t1 ORDER BY a;
    64     66     }
    65     67   } {1 2 3}
    66     68   do_test unique-1.7 {
    67     69     catchsql {
................................................................................
    95     97     }
    96     98   } {0 {1 2 3 4}}
    97     99   do_test unique-2.3 {
    98    100     catchsql {
    99    101       INSERT INTO t2 VALUES(1,5);
   100    102     }
   101    103   } {1 {column a is not unique}}
          104  +verify_ex_errcode unique-2.3b SQLITE_CONSTRAINT_UNIQUE
   102    105   do_test unique-2.4 {
   103    106     catchsql {
   104    107       SELECT * FROM t2 ORDER BY a
   105    108     }
   106    109   } {0 {1 2 3 4}}
   107    110   do_test unique-2.5 {
   108    111     catchsql {
................................................................................
   121    124     }
   122    125   } {0 {1 2 1 5 3 4}}
   123    126   do_test unique-2.8 {
   124    127     catchsql {
   125    128       CREATE UNIQUE INDEX i2 ON t2(a);
   126    129     }
   127    130   } {1 {indexed columns are not unique}}
          131  +verify_ex_errcode unique-2.8b SQLITE_CONSTRAINT_UNIQUE
   128    132   do_test unique-2.9 {
   129    133     catchsql {
   130    134       CREATE INDEX i2 ON t2(a);
   131    135     }
   132    136   } {0 {}}
   133    137   integrity_check unique-2.10
   134    138   
................................................................................
   159    163   } {0 {1 2 3 4 1 2 3 5}}
   160    164   do_test unique-3.4 {
   161    165     catchsql {
   162    166       INSERT INTO t3(a,b,c,d) VALUES(1,4,3,5);
   163    167       SELECT * FROM t3 ORDER BY a,b,c,d;
   164    168     }
   165    169   } {1 {columns a, c, d are not unique}}
          170  +verify_ex_errcode unique-3.4b SQLITE_CONSTRAINT_UNIQUE
   166    171   integrity_check unique-3.5
   167    172   
   168    173   # Make sure NULLs are distinct as far as the UNIQUE tests are
   169    174   # concerned.
   170    175   #
   171    176   do_test unique-4.1 {
   172    177     execsql {
................................................................................
   213    218   } {0 {}}
   214    219   do_test unique-4.9 {
   215    220     catchsql {CREATE UNIQUE INDEX i4b ON t4(a,b,c)}
   216    221   } {0 {}}
   217    222   do_test unique-4.10 {
   218    223     catchsql {CREATE UNIQUE INDEX i4c ON t4(b)}
   219    224   } {1 {indexed columns are not unique}}
          225  +verify_ex_errcode unique-4.10b SQLITE_CONSTRAINT_UNIQUE
   220    226   integrity_check unique-4.99
   221    227   
   222    228   # Test the error message generation logic.  In particular, make sure we
   223    229   # do not overflow the static buffer used to generate the error message.
   224    230   #
   225    231   do_test unique-5.1 {
   226    232     execsql {
................................................................................
   245    251     }
   246    252   } {1 2 3 4 5 6}
   247    253   do_test unique-5.2 {
   248    254     catchsql {
   249    255       INSERT INTO t5 VALUES(1,2,3,4,5,6);
   250    256     }
   251    257   } {1 {columns first_column_with_long_name, second_column_with_long_name, third_column_with_long_name, fourth_column_with_long_name, fifth_column_with_long_name, sixth_column_with_long_name are not unique}}
          258  +verify_ex_errcode unique-5.2b SQLITE_CONSTRAINT_UNIQUE
          259  +
   252    260   
   253    261   finish_test