mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-21 09:00:59 +03:00
Ensure that the correct number of columns in a UNIQUE index are checked for
uniqueness, regardless of whether or not the original table has a ROWID or if the columns are NOT NULL, etc. Ticket [9a6daf340df99ba93c]. FossilOrigin-Name: 6b785e92f279cb65746834d5cd25594fd3333342
This commit is contained in:
@@ -2712,7 +2712,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
|
||||
addr2 = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
|
||||
pKey->nField - pIndex->nKeyCol); VdbeCoverage(v);
|
||||
pIndex->nKeyCol); VdbeCoverage(v);
|
||||
sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
|
||||
}else{
|
||||
addr2 = sqlite3VdbeCurrentAddr(v);
|
||||
|
||||
12
src/vdbe.c
12
src/vdbe.c
@@ -4271,12 +4271,12 @@ case OP_ResetCount: {
|
||||
}
|
||||
|
||||
/* Opcode: SorterCompare P1 P2 P3 P4
|
||||
** Synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2
|
||||
** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2
|
||||
**
|
||||
** P1 is a sorter cursor. This instruction compares a prefix of the
|
||||
** the record blob in register P3 against a prefix of the entry that
|
||||
** the sorter cursor currently points to. The final P4 fields of both
|
||||
** the P3 and sorter record are ignored.
|
||||
** the sorter cursor currently points to. Only the first P4 fields
|
||||
** of r[P3] and the sorter record are compared.
|
||||
**
|
||||
** If either P3 or the sorter contains a NULL in one of their significant
|
||||
** fields (not counting the P4 fields at the end which are ignored) then
|
||||
@@ -4288,14 +4288,14 @@ case OP_ResetCount: {
|
||||
case OP_SorterCompare: {
|
||||
VdbeCursor *pC;
|
||||
int res;
|
||||
int nIgnore;
|
||||
int nKeyCol;
|
||||
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( isSorter(pC) );
|
||||
assert( pOp->p4type==P4_INT32 );
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
nIgnore = pOp->p4.i;
|
||||
rc = sqlite3VdbeSorterCompare(pC, pIn3, nIgnore, &res);
|
||||
nKeyCol = pOp->p4.i;
|
||||
rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res);
|
||||
VdbeBranchTaken(res!=0,2);
|
||||
if( res ){
|
||||
pc = pOp->p2-1;
|
||||
|
||||
@@ -385,7 +385,7 @@ static int vdbeSorterIterInit(
|
||||
*/
|
||||
static void vdbeSorterCompare(
|
||||
const VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
|
||||
int nIgnore, /* Ignore the last nIgnore fields */
|
||||
int nKeyCol, /* Num of columns. 0 means "all" */
|
||||
const void *pKey1, int nKey1, /* Left side of comparison */
|
||||
const void *pKey2, int nKey2, /* Right side of comparison */
|
||||
int *pRes /* OUT: Result of comparison */
|
||||
@@ -399,10 +399,9 @@ static void vdbeSorterCompare(
|
||||
sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
|
||||
}
|
||||
|
||||
if( nIgnore ){
|
||||
r2->nField = pKeyInfo->nField - nIgnore;
|
||||
assert( r2->nField>0 );
|
||||
for(i=0; i<r2->nField; i++){
|
||||
if( nKeyCol ){
|
||||
r2->nField = nKeyCol;
|
||||
for(i=0; i<nKeyCol; i++){
|
||||
if( r2->aMem[i].flags & MEM_Null ){
|
||||
*pRes = -1;
|
||||
return;
|
||||
@@ -1084,13 +1083,13 @@ int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){
|
||||
int sqlite3VdbeSorterCompare(
|
||||
const VdbeCursor *pCsr, /* Sorter cursor */
|
||||
Mem *pVal, /* Value to compare to current sorter key */
|
||||
int nIgnore, /* Ignore this many fields at the end */
|
||||
int nKeyCol, /* Only compare this many fields */
|
||||
int *pRes /* OUT: Result of comparison */
|
||||
){
|
||||
VdbeSorter *pSorter = pCsr->pSorter;
|
||||
void *pKey; int nKey; /* Sorter key to compare pVal with */
|
||||
|
||||
pKey = vdbeSorterRowkey(pSorter, &nKey);
|
||||
vdbeSorterCompare(pCsr, nIgnore, pVal->z, pVal->n, pKey, nKey, pRes);
|
||||
vdbeSorterCompare(pCsr, nKeyCol, pVal->z, pVal->n, pKey, nKey, pRes);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user