From f3388144558921c9a7394494cceb6378e52124c8 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 13 Nov 2004 03:48:06 +0000 Subject: [PATCH] Autoincrement is now working and has regression tests. (CVS 2095) FossilOrigin-Name: 10c712a21961dbc3bff89c49d5ec3b84b9187c80 --- manifest | 23 +-- manifest.uuid | 2 +- src/build.c | 15 +- src/insert.c | 59 ++++-- src/parse.y | 19 +- src/test1.c | 12 +- src/vdbe.c | 5 +- test/autoinc.test | 487 ++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 562 insertions(+), 60 deletions(-) create mode 100644 test/autoinc.test diff --git a/manifest b/manifest index df853bb0df..830a1409bf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\spragmas\sschema_cookie\sand\suser_cookie\sto\sschema_version\sand\suser_version.\s(CVS\s2094) -D 2004-11-12T16:12:00 +C Autoincrement\sis\snow\sworking\sand\shas\sregression\stests.\s(CVS\s2095) +D 2004-11-13T03:48:07 F Makefile.in c4d2416860f472a1e3393714d0372074197565df F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 @@ -31,14 +31,14 @@ F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689 F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea F src/btree.c 9fd74df65bad768a441afefc3b73174d45b85d5b F src/btree.h 861e40b759a195ba63819740e484390012cf81ab -F src/build.c 45ba40523aa4f9130c5a5af8b7db5d0d878443a3 +F src/build.c a95eb1181247368b0ffe2eed121a43735976a964 F src/date.c 4fd4e90b3880dacd67305e96330940dc243ffc10 F src/delete.c f0af21a1ede15524a5edd59fe10ef486283a1ee9 F src/expr.c 4ee3e47358c92a919062255b14057a7a8f641e01 F src/func.c b68572e79ada56dd038b7e71755212215092b717 F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 -F src/insert.c e80b009f9ef2864bbaaaae836286f56125a180f6 +F src/insert.c 9524a6c3e86cbdbae3313f6a083bb9a3e7a2462b F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b F src/main.c c7dc54c62c86cab8b2e2883aef607c179eefa611 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070 @@ -54,7 +54,7 @@ F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c ee88fcecb081e3635c281bc09d604e934429e2f5 F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862 -F src/parse.y b64ebeb91d9fc1c813f4517b80e3a3659e94b032 +F src/parse.y 7978be173379fc72abf8004301577b90408d50e5 F src/pragma.c 32ce8fad1a1e05eff97a3dfe02acc61b6936eeee F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 @@ -64,7 +64,7 @@ F src/sqlite.h.in a44eac0716bf4751447160d5c8ed049ece66d45a F src/sqliteInt.h 8569ce94e891a854de71d7bd628da1d25ee6dfe4 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 F src/tclsqlite.c 7f1a1a678140e6901c8954590ca2aabe50b48f71 -F src/test1.c f4dca9e072971dd0207a2d09913da48dac7f7871 +F src/test1.c bbd404d6ee6bfe326ebf04699a0fabcc28e50a91 F src/test2.c b11fa244fff02190707dd0879987c37c75e61fc8 F src/test3.c 6f1ec93e13632a004b527049535079eda84c459d F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df @@ -75,7 +75,7 @@ F src/update.c 3cc67f6053495152e82a6a48c93ed331218e936e F src/utf.c f4f83acd73389090e32d6589d307fc55d794c7ed F src/util.c 005fdf2d008f3429d081766ad6098fdd86d8d8e6 F src/vacuum.c ecb4a2c6f1ac5cc9b394dc64d3bb14ca650c4f60 -F src/vdbe.c 0fd9437a288b19681856ef3f803bfde6858567f1 +F src/vdbe.c 312df85707ed3d2a90ac2ccec4e614b6996842d9 F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181 F src/vdbeInt.h 6017100adff362b8dfa37a69e3f1431f084bfa5b F src/vdbeapi.c 3965bf4678ae32c05f73550c1b5be3268f9f3006 @@ -88,6 +88,7 @@ F test/attach.test e305dd59a375e37c658c6d401f19f8a95880bf9a F test/attach2.test 399128a7b3b209a339a8dbf53ca2ed42eb982d1a F test/attach3.test 8a0309e284cf9aa1d7d6cc444989031881f7a21c F test/auth.test cf13e449cb253f75d6584b376202c94bbdd53ec9 +F test/autoinc.test 11330758197e0301d3600a071230d45b2f6a65b7 F test/autovacuum.test e52b8fab3b82f6b51b7fde5b7140827ce8e86b1c F test/autovacuum_crash.test 2dca85cbcc497098e45e8847c86407eb3554f3d4 F test/bigfile.test d3744a8821ce9abb8697f2826a3e3d22b719e89f @@ -256,7 +257,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25 F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c -P c4115aa3a1b010704af76c5ae9f6dcbfa4038df8 -R aad8608531c726385c6e9788af9bc8b9 -U danielk1977 -Z 1177c79f2e60c6c7d6713520bedefc82 +P 5e058318441bb5043c609cc8fba1653995e90efb +R c2b0cdd20fba53e39338d096ea4e7b99 +U drh +Z af7f52e053f24291ed6aecd06da0eb9b diff --git a/manifest.uuid b/manifest.uuid index db83ac39e6..7ba4acf28b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5e058318441bb5043c609cc8fba1653995e90efb \ No newline at end of file +10c712a21961dbc3bff89c49d5ec3b84b9187c80 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 54568b7200..1016145571 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.278 2004/11/12 15:53:37 danielk1977 Exp $ +** $Id: build.c,v 1.279 2004/11/13 03:48:07 drh Exp $ */ #include "sqliteInt.h" #include @@ -1465,13 +1465,8 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){ Db *pDb = &db->aDb[p->iDb]; if( pDb->pSeqTab==0 ){ sqlite3NestedParse(pParse, - "CREATE TABLE %Q.sqlite_sequence AS SELECT %Q AS name, 0 AS seq;", - pDb->zName, p->zName - ); - }else{ - sqlite3NestedParse(pParse, - "INSERT INTO %Q.sqlite_sequence VALUES(%Q,0)", - pDb->zName, p->zName + "CREATE TABLE %Q.sqlite_sequence(name,seq)", + pDb->zName ); } } @@ -1811,9 +1806,8 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ } } #endif - if( pTab->readOnly ){ + if( pTab->readOnly || pTab==db->aDb[iDb].pSeqTab ){ sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); - pParse->nErr++; goto exit_drop_table; } if( isView && pTab->pSelect==0 ){ @@ -3006,4 +3000,3 @@ void sqlite3AlterRenameTable( sqliteFree(zName); } #endif - diff --git a/src/insert.c b/src/insert.c index a701e1bf66..738c803d95 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.125 2004/11/12 03:56:15 drh Exp $ +** $Id: insert.c,v 1.126 2004/11/13 03:48:07 drh Exp $ */ #include "sqliteInt.h" @@ -199,6 +199,10 @@ void sqlite3Insert( int after_triggers; /* True if there are AFTER triggers */ #endif +#ifndef SQLITE_OMIT_AUTOINCREMENT + int counterRowid; /* Memory cell holding rowid of autoinc counter */ +#endif + if( pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup; db = pParse->db; @@ -275,16 +279,29 @@ void sqlite3Insert( #ifndef SQLITE_OMIT_AUTOINCREMENT /* If this is an AUTOINCREMENT table, look up the sequence number in the - ** sqlite_sequence table and store it in a memory cell. Create a new - ** sqlite_sequence table entry if one does not already exist. + ** sqlite_sequence table and store it in memory cell counterMem. Also + ** remember the rowid of the sqlite_sequence table entry in memory cell + ** counterRowid. */ if( pTab->autoInc ){ - counterMem = ++pParse->nMem; - assert( counterMem>0 ); /* Must be so for OP_NewRecno to work right */ - sqlite3NestedParse(pParse, - "SELECT seq FROM %Q.sqlite_sequence WHERE name=%Q INTO %d", - pDb->zName, pTab->zName, counterMem - ); + int iCur = pParse->nTab; + int base = sqlite3VdbeCurrentAddr(v); + counterRowid = pParse->nMem++; + counterMem = pParse->nMem++; + sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); + sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pDb->pSeqTab->tnum); + sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, 2); + sqlite3VdbeAddOp(v, OP_Rewind, iCur, base+13); + sqlite3VdbeAddOp(v, OP_Column, iCur, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); + sqlite3VdbeAddOp(v, OP_Ne, 28417, base+12); + sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); + sqlite3VdbeAddOp(v, OP_MemStore, counterRowid, 1); + sqlite3VdbeAddOp(v, OP_Column, iCur, 1); + sqlite3VdbeAddOp(v, OP_MemStore, counterMem, 1); + sqlite3VdbeAddOp(v, OP_Goto, 0, base+13); + sqlite3VdbeAddOp(v, OP_Next, iCur, base+4); + sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } #endif /* SQLITE_OMIT_AUTOINCREMENT */ @@ -566,7 +583,7 @@ void sqlite3Insert( sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem); sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); }else{ - sqlite3VdbeAddOp(v, OP_NewRecno, base, 0); + sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem); } #ifndef SQLITE_OMIT_AUTOINCREMENT if( pTab->autoInc ){ @@ -657,13 +674,25 @@ void sqlite3Insert( } #ifndef SQLITE_OMIT_AUTOINCREMENT - /* Update the sqlite_sequence table + /* Update the sqlite_sequence table by storing the content of the + ** counter value in memory counterMem back into the sqlite_sequence + ** table. */ if( pTab->autoInc ){ - sqlite3NestedParse(pParse, - "UPDATE %Q.sqlite_sequence SET seq=#-%d WHERE name=%Q", - pDb->zName, counterMem+1, pTab->zName - ); + int iCur = pParse->nTab; + int base = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); + sqlite3VdbeAddOp(v, OP_OpenWrite, iCur, pDb->pSeqTab->tnum); + sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, 2); + sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0); + sqlite3VdbeAddOp(v, OP_NotNull, -1, base+7); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_NewRecno, iCur, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); + sqlite3VdbeAddOp(v, OP_MemLoad, counterMem, 0); + sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0); + sqlite3VdbeAddOp(v, OP_PutIntKey, iCur, 0); + sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } #endif diff --git a/src/parse.y b/src/parse.y index 1ff1b0dcca..d1d61ead9c 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.154 2004/11/12 13:42:31 danielk1977 Exp $ +** @(#) $Id: parse.y,v 1.155 2004/11/13 03:48:07 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -268,7 +268,7 @@ conslist ::= conslist COMMA tcons. conslist ::= conslist tcons. conslist ::= tcons. tcons ::= CONSTRAINT nm. -tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R) autoinc(I). +tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R). {sqlite3AddPrimaryKey(pParse,X,R,I);} tcons ::= UNIQUE LP idxlist(X) RP onconf(R). {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0);} @@ -320,21 +320,6 @@ cmd ::= select(X). { sqlite3SelectDelete(X); } -%ifndef SQLITE_OMIT_AUTOINCREMENT -// The INTO clause after a select only works in nested mode. It causes -// the result of the SELECT to be stored in a memory register of the -// virtual machine. -// -cmd ::= select(X) INTO INTEGER(M). { - if( pParse->nested ){ - sqlite3Select(pParse, X, SRT_Mem, atoi(M.z), 0, 0, 0, 0); - }else{ - sqlite3ErrorMsg(pParse, "near \"INTO\": syntax error"); - } - sqlite3SelectDelete(X); -} -%endif // SQLITE_OMIT_AUTOINCREMENT - %type select {Select*} %destructor select {sqlite3SelectDelete($$);} %type oneselect {Select*} diff --git a/src/test1.c b/src/test1.c index 49c58a7a51..d2f2cf5113 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.110 2004/11/12 15:53:37 danielk1977 Exp $ +** $Id: test1.c,v 1.111 2004/11/13 03:48:07 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -2568,16 +2568,22 @@ static void set_options(Tcl_Interp *interp){ #else Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_OMIT_AUTOINCREMENT + Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_AUTOVACUUM Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY); -#if SQLITE_DEFAULT_AUTOVACUUM==0 +#endif /* SQLITE_OMIT_AUTOVACUUM */ +#if !defined(SQLITE_DEFAULT_AUTOVACCUM) || SQLITE_DEFAULT_AUTOVACUUM==0 Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY); #endif -#endif /* SQLITE_OMIT_AUTOVACUUM */ } /* diff --git a/src/vdbe.c b/src/vdbe.c index 0f4210e3c0..1bf5af1629 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.426 2004/11/12 03:56:15 drh Exp $ +** $Id: vdbe.c,v 1.427 2004/11/13 03:48:07 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -2895,6 +2895,7 @@ case OP_NewRecno: { Mem *pMem; assert( pOp->p2>0 && pOp->p2nMem ); /* P2 is a valid memory cell */ pMem = &p->aMem[pOp->p2]; + Integerify(pMem); assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P2) holds an integer */ if( pMem->i==0x7fffffffffffffff || pC->useRandomRowid ){ rc = SQLITE_FULL; @@ -4126,7 +4127,7 @@ case OP_MemMax: { assert( pTos>=p->aStack ); assert( i>=0 && inMem ); pMem = &p->aMem[i]; - assert( pMem->flags==MEM_Int ); + Integerify(pMem); Integerify(pTos); if( pMem->ii){ pMem->i = pTos->i; diff --git a/test/autoinc.test b/test/autoinc.test new file mode 100644 index 0000000000..ef99f8537c --- /dev/null +++ b/test/autoinc.test @@ -0,0 +1,487 @@ +# 2004 November 12 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#************************************************************************* +# This file implements regression tests for SQLite library. The +# focus of this script is testing the AUTOINCREMENT features. +# +# $Id: autoinc.test,v 1.1 2004/11/13 03:48:07 drh Exp $ +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# If the library is not compiled with autoincrement support then +# skip all tests in this file. +# +ifcapable {!autoinc} { + finish_test + return +} + +# The database is initially empty. +# +do_test autoinc-1.1 { + execsql { + SELECT name FROM sqlite_master WHERE type='table'; + } +} {} + +# Add a table with the AUTOINCREMENT feature. Verify that the +# SQLITE_SEQUENCE table gets created. +# +do_test autoinc-1.2 { + execsql { + CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); + SELECT name FROM sqlite_master WHERE type='table'; + } +} {t1 sqlite_sequence} + +# The SQLITE_SEQUENCE table is initially empty +# +do_test autoinc-1.3 { + execsql { + SELECT * FROM sqlite_sequence; + } +} {} + +# Close and reopen the database. Verify that everything is still there. +# +do_test autoinc-1.4 { + db close + sqlite3 db test.db + execsql { + SELECT * FROM sqlite_sequence; + } +} {} + +# We are not allowed to drop the sqlite_sequence table. +# +do_test autoinc-1.5 { + catchsql {DROP TABLE sqlite_sequence} +} {1 {table sqlite_sequence may not be dropped}} +do_test autoinc-1.6 { + execsql {SELECT name FROM sqlite_master WHERE type='table'} +} {t1 sqlite_sequence} + +# Insert an entries into the t1 table and make sure the largest key +# is always recorded in the sqlite_sequence table. +# +do_test autoinc-2.1 { + execsql { + SELECT * FROM sqlite_sequence + } +} {} +do_test autoinc-2.2 { + execsql { + INSERT INTO t1 VALUES(12,34); + SELECT * FROM sqlite_sequence; + } +} {t1 12} +do_test autoinc-2.3 { + execsql { + INSERT INTO t1 VALUES(1,23); + SELECT * FROM sqlite_sequence; + } +} {t1 12} +do_test autoinc-2.4 { + execsql { + INSERT INTO t1 VALUES(123,456); + SELECT * FROM sqlite_sequence; + } +} {t1 123} +do_test autoinc-2.5 { + execsql { + INSERT INTO t1 VALUES(NULL,567); + SELECT * FROM sqlite_sequence; + } +} {t1 124} +do_test autoinc-2.6 { + execsql { + DELETE FROM t1 WHERE y=567; + SELECT * FROM sqlite_sequence; + } +} {t1 124} +do_test autoinc-2.7 { + execsql { + INSERT INTO t1 VALUES(NULL,567); + SELECT * FROM sqlite_sequence; + } +} {t1 125} +do_test autoinc-2.8 { + execsql { + DELETE FROM t1; + SELECT * FROM sqlite_sequence; + } +} {t1 125} +do_test autoinc-2.9 { + execsql { + INSERT INTO t1 VALUES(12,34); + SELECT * FROM sqlite_sequence; + } +} {t1 125} +do_test autoinc-2.10 { + execsql { + INSERT INTO t1 VALUES(125,456); + SELECT * FROM sqlite_sequence; + } +} {t1 125} +do_test autoinc-2.11 { + execsql { + INSERT INTO t1 VALUES(-1234567,-1); + SELECT * FROM sqlite_sequence; + } +} {t1 125} +do_test autoinc-2.12 { + execsql { + INSERT INTO t1 VALUES(234,5678); + SELECT * FROM sqlite_sequence; + } +} {t1 234} +do_test autoinc-2.13 { + execsql { + DELETE FROM t1; + INSERT INTO t1 VALUES(NULL,1); + SELECT * FROM sqlite_sequence; + } +} {t1 235} +do_test autoinc-2.14 { + execsql { + SELECT * FROM t1; + } +} {235 1} + +# Manually change the autoincrement values in sqlite_sequence. +# +do_test autoinc-2.20 { + execsql { + UPDATE sqlite_sequence SET seq=1234 WHERE name='t1'; + INSERT INTO t1 VALUES(NULL,2); + SELECT * FROM t1; + } +} {235 1 1235 2} +do_test autoinc-2.21 { + execsql { + SELECT * FROM sqlite_sequence; + } +} {t1 1235} +do_test autoinc-2.22 { + execsql { + UPDATE sqlite_sequence SET seq=NULL WHERE name='t1'; + INSERT INTO t1 VALUES(NULL,3); + SELECT * FROM t1; + } +} {235 1 1235 2 1236 3} +do_test autoinc-2.23 { + execsql { + SELECT * FROM sqlite_sequence; + } +} {t1 1236} +do_test autoinc-2.24 { + execsql { + UPDATE sqlite_sequence SET seq='a-string' WHERE name='t1'; + INSERT INTO t1 VALUES(NULL,4); + SELECT * FROM t1; + } +} {235 1 1235 2 1236 3 1237 4} +do_test autoinc-2.25 { + execsql { + SELECT * FROM sqlite_sequence; + } +} {t1 1237} +do_test autoinc-2.26 { + execsql { + DELETE FROM sqlite_sequence WHERE name='t1'; + INSERT INTO t1 VALUES(NULL,5); + SELECT * FROM t1; + } +} {235 1 1235 2 1236 3 1237 4 1238 5} +do_test autoinc-2.27 { + execsql { + SELECT * FROM sqlite_sequence; + } +} {t1 1238} +do_test autoinc-2.28 { + execsql { + UPDATE sqlite_sequence SET seq='12345678901234567890' + WHERE name='t1'; + INSERT INTO t1 VALUES(NULL,6); + SELECT * FROM t1; + } +} {235 1 1235 2 1236 3 1237 4 1238 5 1239 6} +do_test autoinc-2.29 { + execsql { + SELECT * FROM sqlite_sequence; + } +} {t1 1239} + +# Test multi-row inserts +# +do_test autoinc-2.50 { + execsql { + DELETE FROM t1 WHERE y>=3; + INSERT INTO t1 SELECT NULL, y+2 FROM t1; + SELECT * FROM t1; + } +} {235 1 1235 2 1240 3 1241 4} +do_test autoinc-2.51 { + execsql { + SELECT * FROM sqlite_sequence + } +} {t1 1241} +do_test autoinc-2.52 { + execsql { + CREATE TEMP TABLE t2 AS SELECT y FROM t1; + INSERT INTO t1 SELECT NULL, y+4 FROM t2; + SELECT * FROM t1; + } +} {235 1 1235 2 1240 3 1241 4 1242 5 1243 6 1244 7 1245 8} +do_test autoinc-2.53 { + execsql { + SELECT * FROM sqlite_sequence + } +} {t1 1245} +do_test autoinc-2.54 { + execsql { + DELETE FROM t1; + INSERT INTO t1 SELECT NULL, y FROM t2; + SELECT * FROM t1; + } +} {1246 1 1247 2 1248 3 1249 4} +do_test autoinc-2.55 { + execsql { + SELECT * FROM sqlite_sequence + } +} {t1 1249} + +# Create multiple AUTOINCREMENT tables. Make sure all sequences are +# tracked separately and do not interfere with one another. +# +do_test autoinc-2.70 { + execsql { + DROP TABLE t2; + CREATE TABLE t2(d, e INTEGER PRIMARY KEY AUTOINCREMENT, f); + INSERT INTO t2(d) VALUES(1); + SELECT * FROM sqlite_sequence; + } +} {t1 1249 t2 1} +do_test autoinc-2.71 { + execsql { + INSERT INTO t2(d) VALUES(2); + SELECT * FROM sqlite_sequence; + } +} {t1 1249 t2 2} +do_test autoinc-2.72 { + execsql { + INSERT INTO t1(x) VALUES(10000); + SELECT * FROM sqlite_sequence; + } +} {t1 10000 t2 2} +do_test autoinc-2.73 { + execsql { + CREATE TABLE t3(g INTEGER PRIMARY KEY AUTOINCREMENT, h); + INSERT INTO t3(h) VALUES(1); + SELECT * FROM sqlite_sequence; + } +} {t1 10000 t2 2 t3 1} +do_test autoinc-2.74 { + execsql { + INSERT INTO t2(d,e) VALUES(3,100); + SELECT * FROM sqlite_sequence; + } +} {t1 10000 t2 100 t3 1} + + +# When a table with an AUTOINCREMENT is deleted, the corresponding entry +# in the SQLITE_SEQUENCE table should also be deleted. But the SQLITE_SEQUENCE +# table itself should remain behind. +# +do_test autoinc-3.1 { + execsql {SELECT name FROM sqlite_sequence} +} {t1 t2 t3} +do_test autoinc-3.2 { + execsql { + DROP TABLE t1; + SELECT name FROM sqlite_sequence; + } +} {t2 t3} +do_test autoinc-3.3 { + execsql { + DROP TABLE t3; + SELECT name FROM sqlite_sequence; + } +} {t2} +do_test autoinc-3.4 { + execsql { + DROP TABLE t2; + SELECT name FROM sqlite_sequence; + } +} {} + +# AUTOINCREMENT on TEMP tables. +# +do_test autoinc-4.1 { + execsql { + SELECT 1, name FROM sqlite_master WHERE type='table' + UNION ALL + SELECT 2, name FROM sqlite_temp_master WHERE type='table' + } +} {1 sqlite_sequence} +do_test autoinc-4.2 { + execsql { + CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); + CREATE TEMP TABLE t3(a INTEGER PRIMARY KEY AUTOINCREMENT, b); + SELECT 1, name FROM sqlite_master WHERE type='table' + UNION ALL + SELECT 2, name FROM sqlite_temp_master WHERE type='table' + } +} {1 sqlite_sequence 1 t1 2 t3 2 sqlite_sequence} +do_test autoinc-4.3 { + execsql { + SELECT 1, * FROM main.sqlite_sequence + UNION ALL + SELECT 2, * FROM temp.sqlite_sequence + } +} {} +do_test autoinc-4.4 { + execsql { + INSERT INTO t1 VALUES(10,1); + INSERT INTO t3 VALUES(20,2); + INSERT INTO t1 VALUES(NULL,3); + INSERT INTO t3 VALUES(NULL,4); + SELECT * FROM t1 UNION ALL SELECT * FROM t3; + } +} {10 1 11 3 20 2 21 4} +do_test autoinc-4.5 { + execsql { + SELECT 1, * FROM main.sqlite_sequence + UNION ALL + SELECT 2, * FROM temp.sqlite_sequence + } +} {1 t1 11 2 t3 21} +do_test autoinc-4.6 { + execsql { + INSERT INTO t1 SELECT * FROM t3; + SELECT 1, * FROM main.sqlite_sequence + UNION ALL + SELECT 2, * FROM temp.sqlite_sequence + } +} {1 t1 21 2 t3 21} +do_test autoinc-4.7 { + execsql { + INSERT INTO t3 SELECT x+100, y FROM t1; + SELECT 1, * FROM main.sqlite_sequence + UNION ALL + SELECT 2, * FROM temp.sqlite_sequence + } +} {1 t1 21 2 t3 121} +do_test autoinc-4.8 { + execsql { + DROP TABLE t3; + SELECT 1, * FROM main.sqlite_sequence + UNION ALL + SELECT 2, * FROM temp.sqlite_sequence + } +} {1 t1 21} +do_test autoinc-4.9 { + execsql { + CREATE TEMP TABLE t2(p INTEGER PRIMARY KEY AUTOINCREMENT, q); + INSERT INTO t2 SELECT * FROM t1; + DROP TABLE t1; + SELECT 1, * FROM main.sqlite_sequence + UNION ALL + SELECT 2, * FROM temp.sqlite_sequence + } +} {2 t2 21} +do_test autoinc-4.10 { + execsql { + DROP TABLE t2; + SELECT 1, * FROM main.sqlite_sequence + UNION ALL + SELECT 2, * FROM temp.sqlite_sequence + } +} {} + +# Make sure AUTOINCREMENT works on ATTACH-ed tables. +# +do_test autoinc-5.1 { + file delete -force test2.db + file delete -force test2.db-journal + sqlite3 db2 test2.db + execsql { + CREATE TABLE t4(m INTEGER PRIMARY KEY AUTOINCREMENT, n); + CREATE TABLE t5(o, p INTEGER PRIMARY KEY AUTOINCREMENT); + } db2; + execsql { + ATTACH 'test2.db' as aux; + SELECT 1, * FROM main.sqlite_sequence + UNION ALL + SELECT 2, * FROM temp.sqlite_sequence + UNION ALL + SELECT 3, * FROM aux.sqlite_sequence + } +} {} +do_test autoinc-5.2 { + execsql { + INSERT INTO t4 VALUES(NULL,1); + SELECT 1, * FROM main.sqlite_sequence + UNION ALL + SELECT 2, * FROM temp.sqlite_sequence + UNION ALL + SELECT 3, * FROM aux.sqlite_sequence + } +} {3 t4 1} +do_test autoinc-5.3 { + execsql { + INSERT INTO t5 VALUES(100,200); + SELECT * FROM sqlite_sequence + } db2 +} {t4 1 t5 200} +do_test autoinc-5.4 { + execsql { + SELECT 1, * FROM main.sqlite_sequence + UNION ALL + SELECT 2, * FROM temp.sqlite_sequence + UNION ALL + SELECT 3, * FROM aux.sqlite_sequence + } +} {3 t4 1 3 t5 200} + +# Requirement REQ00310: Make sure an insert fails if the sequence is +# already at its maximum value. +# +do_test autoinc-6.1 { + execsql { + CREATE TABLE t6(v INTEGER PRIMARY KEY AUTOINCREMENT, w); + INSERT INTO t6 VALUES(9223372036854775807,1); + SELECT seq FROM main.sqlite_sequence WHERE name='t6'; + } +} 9223372036854775807 +do_test autoinc-6.2 { + catchsql { + INSERT INTO t6 VALUES(NULL,1); + } +} {1 {database is full}} + +# Allow the AUTOINCREMENT keyword inside the parentheses +# on a separate PRIMARY KEY designation. +# +do_test autoinc-7.1 { + execsql { + CREATE TABLE t7(x INTEGER, y REAL, PRIMARY KEY(x AUTOINCREMENT)); + INSERT INTO t7(y) VALUES(123); + INSERT INTO t7(y) VALUES(234); + DELETE FROM t7; + INSERT INTO t7(y) VALUES(345); + SELECT * FROM t7; + } +} {3 345} + +catch {db2 close} +finish_test