Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Enable the AUTOINCREMENT feature. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
5442b20bf685564557964e2f9ac5cdd9 |
User & Date: | drh 2013-01-20 00:07:20.463 |
Context
2013-01-20
| ||
02:38 | Fix a typo on the key-encoding documentation. check-in: b1ae0ca8c3 user: drh tags: trunk | |
00:07 | Enable the AUTOINCREMENT feature. check-in: 5442b20bf6 user: drh tags: trunk | |
2013-01-19
| ||
19:49 | Insert a value in place of NULL in an INTEGER PRIMARY KEY, even if the IPK column is omitted from the VALUES list in the INSERT statement. check-in: 4d1b506594 user: drh tags: trunk | |
Changes
Changes to main.mk.
︙ | ︙ | |||
63 64 65 66 67 68 69 | TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) TCCX += -I$(TOP)/ext/rtree -I$(TOP)/ext/icu -I$(TOP)/ext/fts3 TCCX += -I$(TOP)/ext/async TCPPX = g++ -Wall -g -I. -I$(TOP)/src $(OPTS) | > | | | | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) TCCX += -I$(TOP)/ext/rtree -I$(TOP)/ext/icu -I$(TOP)/ext/fts3 TCCX += -I$(TOP)/ext/async TCPPX = g++ -Wall -g -I. -I$(TOP)/src $(OPTS) LIBOBJ+= vdbe.o parse.o \ alter.o analyze.o attach.o auth.o \ build.o \ callback.o complete.o ctime.o date.o delete.o expr.o fault.o fkey.o \ fts5.o fts5func.o \ func.o global.o hash.o \ icu.o insert.o kv.o kvlsm.o kvmem.o legacy.o \ lsm_ckpt.o lsm_file.o lsm_log.o lsm_main.o lsm_mem.o lsm_mutex.o \ lsm_shared.o lsm_str.o lsm_sorted.o lsm_tree.o \ lsm_unix.o lsm_varint.o \ main.o malloc.o math.o mem0.o mem1.o mem2.o mem3.o mem5.o \ mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ opcodes.o os.o \ pragma.o prepare.o printf.o \ random.o resolve.o rowset.o rtree.o select.o status.o \ tokenize.o trigger.o \ update.o util.o varint.o \ vdbeapi.o vdbeaux.o vdbecodec.o vdbecursor.o \ vdbemem.o vdbetrace.o \ walker.o where.o utf.o # All of the source code files. # SRC = \ $(TOP)/src/alter.c \ |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
1073 1074 1075 1076 1077 1078 1079 | if( iCol<pTab->nCol ){ pTab->aCol[iCol].isPrimKey = i+1; pTab->aCol[iCol].notNull = 1; } } if( pList->nExpr>1 ) iCol = -1; } | < < < < > > > > > | 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 | if( iCol<pTab->nCol ){ pTab->aCol[iCol].isPrimKey = i+1; pTab->aCol[iCol].notNull = 1; } } if( pList->nExpr>1 ) iCol = -1; } pPk = sqlite4CreateIndex( pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0, 1 ); if( iCol>=0 && iCol<pTab->nCol && (zType = pTab->aCol[iCol].zType)!=0 && sqlite4StrICmp(zType, "INTEGER")==0 && sortOrder==SQLITE4_SO_ASC && pPk ){ pPk->fIndex |= IDX_IntPK; assert( autoInc==0 || autoInc==1 ); pTab->tabFlags |= (-autoInc)&TF_Autoincrement; }else if( autoInc ){ sqlite4ErrorMsg(pParse, "AUTOINCREMENT permitted on INTEGER PRIMARY KEY ASC only"); } pList = 0; primary_key_exit: sqlite4ExprListDelete(pParse->db, pList); return; } |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
20 21 22 23 24 25 26 | void sqlite4OpenTable( Parse *p, /* Generate code into this VDBE */ int iCur, /* The cursor number of the table */ int iDb, /* The database index in sqlite4.aDb[] */ Table *pTab, /* The table to be opened */ int opcode /* OP_OpenRead or OP_OpenWrite */ ){ | | > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | void sqlite4OpenTable( Parse *p, /* Generate code into this VDBE */ int iCur, /* The cursor number of the table */ int iDb, /* The database index in sqlite4.aDb[] */ Table *pTab, /* The table to be opened */ int opcode /* OP_OpenRead or OP_OpenWrite */ ){ Index *pPk = sqlite4FindPrimaryKey(pTab, 0); sqlite4OpenIndex(p, iCur, iDb, pPk, opcode); } /* ** Open VDBE cursor iCur to access index pIdx. pIdx is guaranteed to be ** a part of database iDb. */ void sqlite4OpenIndex( |
︙ | ︙ | |||
244 245 246 247 248 249 250 | ** (1) Register to hold the name of the pTab table. ** (2) Register to hold the maximum ROWID of pTab. ** (3) Register to hold the rowid in sqlite_sequence of pTab ** ** The 2nd register is the one that is returned. That is all the ** insert routine needs to know about. */ | | | 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | ** (1) Register to hold the name of the pTab table. ** (2) Register to hold the maximum ROWID of pTab. ** (3) Register to hold the rowid in sqlite_sequence of pTab ** ** The 2nd register is the one that is returned. That is all the ** insert routine needs to know about. */ static int autoIncBegin( Parse *pParse, /* Parsing context */ int iDb, /* Index of the database holding pTab */ Table *pTab /* The table we are writing to */ ){ int memId = 0; /* Register holding maximum rowid */ if( pTab->tabFlags & TF_Autoincrement ){ Parse *pToplevel = sqlite4ParseToplevel(pParse); |
︙ | ︙ | |||
318 319 320 321 322 323 324 | ** Update the maximum rowid for an autoincrement calculation. ** ** This routine should be called when the top of the stack holds a ** new rowid that is about to be inserted. If that new rowid is ** larger than the maximum rowid in the memId memory cell, then the ** memory cell is updated. The stack is unchanged. */ | | | 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 | ** Update the maximum rowid for an autoincrement calculation. ** ** This routine should be called when the top of the stack holds a ** new rowid that is about to be inserted. If that new rowid is ** larger than the maximum rowid in the memId memory cell, then the ** memory cell is updated. The stack is unchanged. */ static void autoIncStep(Parse *pParse, int memId, int regRowid){ if( memId>0 ){ sqlite4VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); } } /* ** This routine generates the code needed to write autoincrement |
︙ | ︙ | |||
513 514 515 516 517 518 519 520 521 522 523 524 | int addrInsTop = 0; /* Jump to label "D" */ int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */ int addrSelect = 0; /* Address of coroutine that implements the SELECT */ SelectDest dest; /* Destination for SELECT on rhs of INSERT */ int iDb; /* Index of database holding TABLE */ Db *pDb; /* The database containing table being inserted into */ int appendFlag = 0; /* True if the insert is likely to be an append */ /* Register allocations */ int regFromSelect = 0;/* Base register for data coming from SELECT */ int regEof = 0; /* Register recording end of SELECT data */ int *aRegIdx = 0; /* One register allocated to each index */ | > > > > < < < < < | | | | 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 | int addrInsTop = 0; /* Jump to label "D" */ int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */ int addrSelect = 0; /* Address of coroutine that implements the SELECT */ SelectDest dest; /* Destination for SELECT on rhs of INSERT */ int iDb; /* Index of database holding TABLE */ Db *pDb; /* The database containing table being inserted into */ int appendFlag = 0; /* True if the insert is likely to be an append */ int iPk; /* Cursor offset of PK index cursor */ Index *pPk; /* Primary key for table pTab */ int iIntPKCol = -1; /* Column of INTEGER PRIMARY KEY or -1 */ int bImplicitPK; /* True if table pTab has an implicit PK */ /* Register allocations */ int regFromSelect = 0;/* Base register for data coming from SELECT */ int regEof = 0; /* Register recording end of SELECT data */ int *aRegIdx = 0; /* One register allocated to each index */ int regContent; /* First register in column value array */ int regRowid; /* If bImplicitPK, register holding IPK */ int regAutoinc; /* Register holding the AUTOINCREMENT counter */ #ifndef SQLITE4_OMIT_TRIGGER int isView; /* True if attempting to insert into a view */ Trigger *pTrigger; /* List of triggers on pTab, if required */ int tmask; /* Mask of trigger times */ #endif |
︙ | ︙ | |||
625 626 627 628 629 630 631 632 633 634 635 636 637 638 | */ if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ assert( !pTrigger ); assert( pList==0 ); goto insert_end; } #endif /* SQLITE4_OMIT_XFER_OPT */ /* Figure out how many columns of data are supplied. If the data ** is coming from a SELECT statement, then generate a co-routine that ** produces a single row of the SELECT on each invocation. The ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ | > > > > > | 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 | */ if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ assert( !pTrigger ); assert( pList==0 ); goto insert_end; } #endif /* SQLITE4_OMIT_XFER_OPT */ /* If this is an AUTOINCREMENT table, look up the sequence number in the ** sqlite_sequence table and store it in memory cell regAutoinc. */ regAutoinc = autoIncBegin(pParse, iDb, pTab); /* Figure out how many columns of data are supplied. If the data ** is coming from a SELECT statement, then generate a co-routine that ** produces a single row of the SELECT on each invocation. The ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ |
︙ | ︙ | |||
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 | regRowid++; pParse->nMem++; } endOfLoop = sqlite4VdbeMakeLabel(v); for(i=0; i<pTab->nCol; i++){ j = i; if( pColumn ){ for(j=0; j<pColumn->nId; j++){ if( pColumn->a[j].idx==i ) break; } } if( nColumn==0 || (pColumn && j>=pColumn->nId) ){ | > | | | | < < < < < < > > > > > > > > > | 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 | regRowid++; pParse->nMem++; } endOfLoop = sqlite4VdbeMakeLabel(v); for(i=0; i<pTab->nCol; i++){ int regDest = regContent+i; j = i; if( pColumn ){ for(j=0; j<pColumn->nId; j++){ if( pColumn->a[j].idx==i ) break; } } if( nColumn==0 || (pColumn && j>=pColumn->nId) ){ sqlite4ExprCode(pParse, pTab->aCol[i].pDflt, regDest); }else if( useTempTable ){ sqlite4VdbeAddOp3(v, OP_Column, srcTab, j, regDest); }else if( pSelect ){ sqlite4VdbeAddOp2(v, OP_SCopy, regFromSelect+j, regDest); }else{ assert( pSelect==0 ); /* Otherwise useTempTable is true */ sqlite4ExprCodeAndCache(pParse, pList->a[j].pExpr, regDest); } } if( !isView ){ sqlite4VdbeAddOp2(v, OP_Affinity, regContent, pTab->nCol); sqlite4TableAffinityStr(v, pTab); } /* Fire BEFORE or INSTEAD OF triggers */ if( pTrigger ){ sqlite4VdbeAddOp2(v, OP_Integer, -1, regRowid); VdbeComment((v, "new.rowid value for BEFORE triggers")); sqlite4CodeRowTrigger( pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, pTab, (regRowid - pTab->nCol - 1), onError, endOfLoop ); } if( iIntPKCol>=0 ){ int regDest = regContent+iIntPKCol; int a1; a1 = sqlite4VdbeAddOp1(v, OP_NotNull, regDest); sqlite4VdbeAddOp3(v, OP_NewRowid, baseCur, regDest, regAutoinc); sqlite4VdbeJumpHere(v, a1); autoIncStep(pParse, regAutoinc, regDest); } if( bImplicitPK ){ assert( !isView ); sqlite4VdbeAddOp2(v, OP_NewRowid, baseCur+iPk, regRowid); } if( !isView ){ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
460 461 462 463 464 465 466 467 468 469 470 471 472 473 | sqlite4 *db = p->db; sqlite4DbFree(db, p->zErrMsg); p->zErrMsg = sqlite4DbStrDup(db, pVtab->zErrMsg); sqlite4_free(db->pEnv, pVtab->zErrMsg); pVtab->zErrMsg = 0; } /* ** Execute as much of a VDBE program as we can then return. ** ** sqlite4VdbeMakeReady() must be called before this routine in order to ** close the program with a final OP_Halt and to set up the callbacks ** and the error message pointer. | > > > > > > > > > > > > | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 | sqlite4 *db = p->db; sqlite4DbFree(db, p->zErrMsg); p->zErrMsg = sqlite4DbStrDup(db, pVtab->zErrMsg); sqlite4_free(db->pEnv, pVtab->zErrMsg); pVtab->zErrMsg = 0; } /* ** Return a pointer to a register in the root frame. */ static Mem *sqlite4RegisterInRootFrame(Vdbe *p, int i){ if( p->pFrame ){ VdbeFrame *pFrame; for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); return &pFrame->aMem[i]; }else{ return &p->aMem[i]; } } /* ** Execute as much of a VDBE program as we can then return. ** ** sqlite4VdbeMakeReady() must be called before this routine in order to ** close the program with a final OP_Halt and to set up the callbacks ** and the error message pointer. |
︙ | ︙ | |||
3235 3236 3237 3238 3239 3240 3241 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( p->apCsr[pOp->p1]!=0 ); pOut->u.i = p->apCsr[pOp->p1]->seqCount++; break; } | | > > > > | 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( p->apCsr[pOp->p1]!=0 ); pOut->u.i = p->apCsr[pOp->p1]->seqCount++; break; } /* Opcode: NewRowid P1 P2 P3 * * ** ** Get a new integer primary key (a.k.a "rowid") for table P1. The integer ** should not be currently in use as a primary key on that table. ** ** If P3 is not zero, then it is the number of a register in the top-level ** frame that holds a lower bound for the new rowid. In other words, the ** new rowid must be no less than reg[P3]+1. */ case OP_NewRowid: { /* out2-prerelease */ i64 v; /* The new rowid */ VdbeCursor *pC; /* Cursor of table to get the new rowid */ const KVByteArray *aKey; /* Key of an existing row */ KVSize nKey; /* Size of the existing row key */ int n; /* Number of bytes decoded */ |
︙ | ︙ | |||
3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 | if( rc==SQLITE4_OK ){ n = sqlite4VdbeDecodeIntKey(&aKey[n], nKey-n, &v); if( n==0 || v==LARGEST_INT64 ) rc = SQLITE4_FULL; } }else{ break; } pOut->flags = MEM_Int; pOut->u.i = v+1; break; } /* Opcode: NewIdxid P1 P2 * * * ** | > > > > > > > > > > > > > | 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 | if( rc==SQLITE4_OK ){ n = sqlite4VdbeDecodeIntKey(&aKey[n], nKey-n, &v); if( n==0 || v==LARGEST_INT64 ) rc = SQLITE4_FULL; } }else{ break; } #ifndef SQLITE_OMIT_AUTOINCREMENT if( pOp->p3 && rc==SQLITE4_OK ){ pIn3 = sqlite4RegisterInRootFrame(p, pOp->p3); assert( memIsValid(pIn3) ); REGISTER_TRACE(pOp->p3, pIn3); sqlite4VdbeMemIntegerify(pIn3); assert( (pIn3->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ if( pIn3->u.i==MAX_ROWID ){ rc = SQLITE4_FULL; } if( v<pIn3->u.i ) v = pIn3->u.i; } #endif pOut->flags = MEM_Int; pOut->u.i = v+1; break; } /* Opcode: NewIdxid P1 P2 * * * ** |
︙ | ︙ | |||
4266 4267 4268 4269 4270 4271 4272 | ** ** This instruction throws an error if the memory cell is not initially ** an integer. */ case OP_MemMax: { /* in2 */ Mem *pIn1; VdbeFrame *pFrame; | < < < < | < > > | 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 | ** ** This instruction throws an error if the memory cell is not initially ** an integer. */ case OP_MemMax: { /* in2 */ Mem *pIn1; VdbeFrame *pFrame; pIn1 = sqlite4RegisterInRootFrame(p, pOp->p1); assert( memIsValid(pIn1) ); sqlite4VdbeMemIntegerify(pIn1); pIn2 = &aMem[pOp->p2]; REGISTER_TRACE(pOp->p1, pIn1); sqlite4VdbeMemIntegerify(pIn2); if( pIn1->u.i<pIn2->u.i){ pIn1->u.i = pIn2->u.i; } REGISTER_TRACE(pOp->p1, pIn1); break; } #endif /* SQLITE4_OMIT_AUTOINCREMENT */ /* Opcode: IfPos P1 P2 * * * ** ** If the value of register P1 is 1 or greater, jump to P2. |
︙ | ︙ |