/ Check-in [086ec2a1]
Login

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

Overview
Comment:Work on the UPDATE and INSERT logic. This is an incremental check-in so that can switch over to trunk to work on an unrelated issue there.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | omit-rowid
Files: files | file ages | folders
SHA1:086ec2a177b24ad90d5d705a99d93aa0c1545217
User & Date: drh 2013-10-26 15:40:48
Context
2013-10-28
22:39
Merge recent fixes from trunk. check-in: 9f8191d1 user: drh tags: omit-rowid
2013-10-26
15:40
Work on the UPDATE and INSERT logic. This is an incremental check-in so that can switch over to trunk to work on an unrelated issue there. check-in: 086ec2a1 user: drh tags: omit-rowid
13:36
Replace the OP_IsUnique opcode with OP_NoConflict. This code simplification might be useful to move onto trunk even if this branch is never merged. check-in: e6650e16 user: drh tags: omit-rowid
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/insert.c.

  1119   1119   #ifdef pTrigger
  1120   1120    #undef pTrigger
  1121   1121   #endif
  1122   1122   #ifdef tmask
  1123   1123    #undef tmask
  1124   1124   #endif
  1125   1125   
         1126  +/*
         1127  +** If regFirst is a set of value for a table row in table order and pPk
         1128  +** is the PRIMARY KEY index for that table, then return the index of the
         1129  +** first register in a contiguous array of registers that are the primary
         1130  +** key values for the table row.
         1131  +**
         1132  +** For the common cases where the PRIMARY KEY has only a single value or
         1133  +** where a multi-value PRIMARY KEY is contiguous in table order, this
         1134  +** routine simply returns a pointer into the regFirst array.  But if there
         1135  +** is a multi-value PRIMARY KEY with the values out-of-order, this routine
         1136  +** has to generate code that will copy PRIMARY KEY values into newly
         1137  +** allocated contiguous registers.
         1138  +*/
         1139  +static int sqlite3PrimaryKeyRegisters(Parse *pParse, Index *pPk, int regFirst){
         1140  +  int i;
         1141  +  int nKeyCol = pPk->nKeyCol;
         1142  +  int regPk;
         1143  +  assert( pParse->pVdbe!=0 );
         1144  +  if( nKeyCol==1 ){
         1145  +    return regFirst + pPk->aiColumn[0];
         1146  +  }
         1147  +  for(i=1; i<nKeyCol; i++){
         1148  +    if( pPk->aiColumn[i-1]+1!=pPk->aiColumn[i] ) break;
         1149  +  }
         1150  +  if( i==nKeyCol ){
         1151  +    return regFirst + pPk->aiColumn[0];
         1152  +  }
         1153  +  regPk = pParse->nMem+1;
         1154  +  pParse->nMem += nKeyCol;
         1155  +  for(i=0; i<nKeyCol; i++){
         1156  +    int x = pPk->aiColumn[i];
         1157  +    sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, regFirst+x, regPk+i);
         1158  +  }
         1159  +  return regPk;
         1160  +}
         1161  +
  1126   1162   
  1127   1163   /*
  1128   1164   ** Generate code to do constraint checks prior to an INSERT or an UPDATE.
  1129   1165   **
  1130   1166   ** The input is a range of consecutive registers as follows:
  1131   1167   **
  1132         -**    1.  The rowid of the row after the update.  (This register
  1133         -**        contains a NULL for WITHOUT ROWID tables.)
         1168  +**    1.  The rowid of the row after the update, or NULL
         1169  +**        for WITHOUT ROWID tables.
  1134   1170   **
  1135   1171   **    2.  The data in the first column of the entry after the update.
  1136   1172   **
  1137   1173   **    i.  Data from middle columns...
  1138   1174   **
  1139   1175   **    N.  The data in the last column of the entry after the update.
  1140   1176   **
................................................................................
  1203   1239   */
  1204   1240   void sqlite3GenerateConstraintChecks(
  1205   1241     Parse *pParse,      /* The parser context */
  1206   1242     Table *pTab,        /* the table into which we are inserting */
  1207   1243     int baseCur,        /* A read/write cursor pointing at pTab */
  1208   1244     int regRowid,       /* First register in a range holding values to insert */
  1209   1245     int *aRegIdx,       /* Register used by each index.  0 for unused indices */
  1210         -  int pkChng,         /* Non-zero if the PRIMARY KEY might collide */
         1246  +  int pkChng,         /* Non-zero if the rowid or PRIMARY KEY changed */
  1211   1247     int isUpdate,       /* True for UPDATE, False for INSERT */
  1212   1248     int overrideError,  /* Override onError to this if not OE_Default */
  1213   1249     int ignoreDest,     /* Jump to this label on an OE_Ignore resolution */
  1214   1250     int *pbMayReplace   /* OUT: Set to true if constraint may cause a replace */
  1215   1251   ){
  1216   1252     int i;              /* loop counter */
  1217   1253     Vdbe *v;            /* VDBE under constrution */
  1218   1254     int nCol;           /* Number of columns */
  1219   1255     int onError;        /* Conflict resolution strategy */
  1220   1256     int j1;             /* Addresss of jump instruction */
  1221         -  int j2 = 0, j3;     /* Addresses of jump instructions */
  1222   1257     int regData;        /* Register containing first data column */
  1223   1258     int iCur;           /* Table cursor number */
  1224   1259     Index *pIdx;         /* Pointer to one of the indices */
         1260  +  Index *pPk = 0;      /* The PRIMARY KEY index */
  1225   1261     sqlite3 *db;         /* Database connection */
  1226   1262     int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
  1227         -  int regOldRowid = (pkChng && isUpdate) ? pkChng : regRowid;
         1263  +  int regOldPk;        /* Previous rowid or PRIMARY KEY value */
         1264  +  int regNewPk = 0;    /* New PRIMARY KEY value */
         1265  +  int pkCur = 0;       /* Cursor used by the PRIMARY KEY */
  1228   1266   
         1267  +  regOldPk = (pkChng && isUpdate) ? pkChng : regRowid;
  1229   1268     db = pParse->db;
  1230   1269     v = sqlite3GetVdbe(pParse);
  1231   1270     assert( v!=0 );
  1232   1271     assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  1233   1272     nCol = pTab->nCol;
  1234   1273     regData = regRowid + 1;
         1274  +
         1275  +  /* For WITHOUT ROWID tables, we'll need to know the Index and the cursor
         1276  +  ** number for the PRIMARY KEY index */
         1277  +  if( !HasRowid(pTab) ){
         1278  +    pkCur = baseCur+1;
         1279  +    pPk = pTab->pIndex;
         1280  +    while( ALWAYS(pPk) && pPk->autoIndex!=2 ){
         1281  +      pPk=pPk->pNext;
         1282  +      pkCur++;
         1283  +    }
         1284  +  }
  1235   1285   
  1236   1286     /* Test all NOT NULL constraints.
  1237   1287     */
  1238   1288     for(i=0; i<nCol; i++){
  1239   1289       if( i==pTab->iPKey ){
  1240   1290         continue;
  1241   1291       }
................................................................................
  1305   1355       }
  1306   1356     }
  1307   1357   #endif /* !defined(SQLITE_OMIT_CHECK) */
  1308   1358   
  1309   1359     /* If we have an INTEGER PRIMARY KEY, make sure the primary key
  1310   1360     ** of the new record does not previously exist.  Except, if this
  1311   1361     ** is an UPDATE and the primary key is not changing, that is OK.
         1362  +  **
         1363  +  ** This block only runs for tables that have a rowid.
  1312   1364     */
  1313         -  if( pkChng ){
         1365  +  if( pkChng && pkCur==0 ){
         1366  +    int addrRowidOk = sqlite3VdbeMakeLabel(v);
         1367  +
  1314   1368       onError = pTab->keyConf;
  1315   1369       if( overrideError!=OE_Default ){
  1316   1370         onError = overrideError;
  1317   1371       }else if( onError==OE_Default ){
  1318   1372         onError = OE_Abort;
  1319   1373       }
  1320         -    
         1374  +
  1321   1375       if( isUpdate ){
  1322         -      j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, pkChng);
         1376  +      sqlite3VdbeAddOp3(v, OP_Eq, regRowid, addrRowidOk, pkChng);
  1323   1377       }
  1324         -    j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
         1378  +    sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, addrRowidOk, regRowid);
  1325   1379       switch( onError ){
  1326   1380         default: {
  1327   1381           onError = OE_Abort;
  1328   1382           /* Fall thru into the next case */
  1329   1383         }
  1330   1384         case OE_Rollback:
  1331   1385         case OE_Abort:
................................................................................
  1375   1429         }
  1376   1430         case OE_Ignore: {
  1377   1431           assert( seenReplace==0 );
  1378   1432           sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
  1379   1433           break;
  1380   1434         }
  1381   1435       }
  1382         -    sqlite3VdbeJumpHere(v, j3);
  1383         -    if( isUpdate ){
  1384         -      sqlite3VdbeJumpHere(v, j2);
  1385         -    }
         1436  +    sqlite3VdbeResolveLabel(v, addrRowidOk);
  1386   1437     }
  1387   1438   
  1388   1439     /* Test all UNIQUE constraints by creating entries for each UNIQUE
  1389   1440     ** index and making sure that duplicate entries do not already exist.
  1390         -  ** Add the new records to the indices as we go.
         1441  +  ** Compute the revised record entries for indices as we go.
  1391   1442     */
  1392   1443     for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
  1393   1444       int regIdx;
  1394   1445       int regR;
  1395         -    int addrSkipRow = sqlite3VdbeMakeLabel(v);
         1446  +    int idxCur = baseCur+iCur+1;
         1447  +    int addrUniqueOk = sqlite3VdbeMakeLabel(v);
  1396   1448   
  1397   1449       if( aRegIdx[iCur]==0 ) continue;  /* Skip unused indices */
  1398   1450   
  1399   1451       if( pIdx->pPartIdxWhere ){
  1400   1452         sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[iCur]);
  1401   1453         pParse->ckBase = regData;
  1402         -      sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrSkipRow,
         1454  +      sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
  1403   1455                            SQLITE_JUMPIFNULL);
  1404   1456         pParse->ckBase = 0;
  1405   1457       }
  1406   1458   
  1407   1459       /* Create a key for accessing the index entry */
  1408         -    regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1);
         1460  +    regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn);
  1409   1461       for(i=0; i<pIdx->nColumn; i++){
  1410   1462         i16 idx = pIdx->aiColumn[i];
  1411   1463         if( idx<0 || idx==pTab->iPKey ){
  1412   1464           sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
  1413   1465         }else{
  1414   1466           sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i);
  1415   1467         }
................................................................................
  1418   1470       sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT);
  1419   1471       sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn);
  1420   1472   
  1421   1473       /* Find out what action to take in case there is an indexing conflict */
  1422   1474       onError = pIdx->onError;
  1423   1475       if( onError==OE_None ){ 
  1424   1476         sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1);
  1425         -      sqlite3VdbeResolveLabel(v, addrSkipRow);
         1477  +      sqlite3VdbeResolveLabel(v, addrUniqueOk);
  1426   1478         continue;  /* pIdx is not a UNIQUE index */
  1427   1479       }
  1428   1480       if( overrideError!=OE_Default ){
  1429   1481         onError = overrideError;
  1430   1482       }else if( onError==OE_Default ){
  1431   1483         onError = OE_Abort;
  1432   1484       }
................................................................................
  1433   1485       if( seenReplace ){
  1434   1486         if( onError==OE_Ignore ) onError = OE_Replace;
  1435   1487         else if( onError==OE_Fail ) onError = OE_Abort;
  1436   1488       }
  1437   1489       
  1438   1490       /* Check to see if the new index entry will be unique */
  1439   1491       regR = sqlite3GetTempReg(pParse);
  1440         -    sqlite3VdbeAddOp4Int(v, OP_NoConflict, baseCur+iCur+1, addrSkipRow,
         1492  +    sqlite3VdbeAddOp4Int(v, OP_NoConflict, idxCur, addrUniqueOk,
  1441   1493                            regIdx, pIdx->nKeyCol);
  1442         -    sqlite3VdbeAddOp2(v, OP_IdxRowid, baseCur+iCur+1, regR);
  1443         -    sqlite3VdbeAddOp3(v, OP_Eq, regR, addrSkipRow, regOldRowid);
  1444         -    sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1);
         1494  +    if( HasRowid(pTab) ){
         1495  +      /* Conflict only if the rowid of the existing entry with the matching
         1496  +      ** key is different from old-rowid */
         1497  +      sqlite3VdbeAddOp2(v, OP_IdxRowid, idxCur, regR);
         1498  +      sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldPk);
         1499  +    }else if( pIdx->autoIndex==2 ){
         1500  +      /* If there is a matching entry on the PRIMARY KEY index ... */
         1501  +      int addrPkConflict = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
         1502  +      for(i=0; i<pPk->nKeyCol-1; i++){
         1503  +        sqlite3VdbeAddOp3(v, OP_Ne,
         1504  +                          regOldPk+pPk->aiColumn[i], addrPkConflict, regIdx+i);
         1505  +      }
         1506  +      sqlite3VdbeAddOp3(v, OP_Eq,
         1507  +                        regOldPk+pPk->aiColumn[i], addrUniqueOk, regIdx+i);
         1508  +    }else{
         1509  +      int addrConflict = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol*2;
         1510  +      assert( pIdx->nKeyCol + pPk->nKeyCol == pIdx->nColumn );
         1511  +      for(i=0; i<pPk->nKeyCol-1; i++){
         1512  +        sqlite3VdbeAddOp3(v, OP_Column, idxCur, pIdx->nKeyCol+i, regR);
         1513  +        sqlite3VdbeAddOp3(v, OP_Ne,
         1514  +                          regOldPk+pPk->aiColumn[i], addrConflict, regR);
         1515  +      }
         1516  +      sqlite3VdbeAddOp3(v, OP_Column, idxCur, pIdx->nKeyCol+i, regR);
         1517  +      sqlite3VdbeAddOp3(v, OP_Eq,
         1518  +                        regOldPk+pPk->aiColumn[i], addrUniqueOk, regR);
         1519  +    }
         1520  +    sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
  1445   1521   
  1446   1522       /* Generate code that executes if the new index entry is not unique */
  1447   1523       assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
  1448   1524           || onError==OE_Ignore || onError==OE_Replace );
  1449   1525       switch( onError ){
  1450   1526         case OE_Rollback:
  1451   1527         case OE_Abort:
................................................................................
  1487   1563           sqlite3GenerateRowDelete(
  1488   1564               pParse, pTab, pTrigger, baseCur, regR, 0, 0, OE_Replace
  1489   1565           );
  1490   1566           seenReplace = 1;
  1491   1567           break;
  1492   1568         }
  1493   1569       }
  1494         -    sqlite3VdbeResolveLabel(v, addrSkipRow);
         1570  +    sqlite3VdbeResolveLabel(v, addrUniqueOk);
  1495   1571       sqlite3ReleaseTempReg(pParse, regR);
  1496   1572     }
  1497   1573     
  1498   1574     if( pbMayReplace ){
  1499   1575       *pbMayReplace = seenReplace;
  1500   1576     }
  1501   1577   }

Changes to src/vdbe.c.

  3733   3733   ** rowid P3 then jump immediately to P2.  If P1 does contain a record
  3734   3734   ** with rowid P3 then leave the cursor pointing at that record and fall
  3735   3735   ** through to the next instruction.
  3736   3736   **
  3737   3737   ** The OP_NotFound opcode performs the same operation on index btrees
  3738   3738   ** (with arbitrary multi-value keys).
  3739   3739   **
  3740         -** See also: Found, NotFound, IsUnique
         3740  +** See also: Found, NotFound, NoConflict
  3741   3741   */
  3742   3742   case OP_NotExists: {        /* jump, in3 */
  3743   3743     VdbeCursor *pC;
  3744   3744     BtCursor *pCrsr;
  3745   3745     int res;
  3746   3746     u64 iKey;
  3747   3747   

Changes to src/vdbeInt.h.

    78     78     sqlite3_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
    79     79     const sqlite3_module *pModule;     /* Module for cursor pVtabCursor */
    80     80     i64 seqCount;         /* Sequence counter */
    81     81     i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
    82     82     i64 lastRowid;        /* Last rowid from a Next or NextIdx operation */
    83     83     VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */
    84     84   
    85         -  /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or 
    86         -  ** OP_IsUnique opcode on this cursor. */
           85  +  /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists */
    87     86     int seekResult;
    88     87   
    89     88     /* Cached information about the header for the data record that the
    90     89     ** cursor is currently pointing to.  Only valid if cacheStatus matches
    91     90     ** Vdbe.cacheCtr.  Vdbe.cacheCtr will never take on the value of
    92     91     ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that
    93     92     ** the cache is out of date.