Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Some simple inserts and queries working on WITHOUT ROWID tables. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | omit-rowid |
Files: | files | file ages | folders |
SHA1: |
3f8016dee24213ec83a02d71ad269878 |
User & Date: | drh 2013-10-23 01:57:32.661 |
Context
2013-10-23
| ||
13:30 | Some inserts and queries working for multi-column primary keys and WITHOUT ROWID. (check-in: b21d831b2a user: drh tags: omit-rowid) | |
01:57 | Some simple inserts and queries working on WITHOUT ROWID tables. (check-in: 3f8016dee2 user: drh tags: omit-rowid) | |
00:32 | Build internal data structures appropriately for WITHOUT ROWID tables. (check-in: 35a3606071 user: drh tags: omit-rowid) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 | pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0); if( pPk==0 ) return; pTab->iPKey = -1; } for(pPk=pTab->pIndex; pPk && pPk->autoIndex<2; pPk=pPk->pNext){} assert( pPk!=0 ); nPk = pPk->nKeyCol; /* Update the in-memory representation of all UNIQUE indices by converting ** the final rowid column into one or more columns of the PRIMARY KEY. */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int n; if( pIdx->autoIndex==2 ) continue; | > > > > > | 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 | pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0); if( pPk==0 ) return; pTab->iPKey = -1; } for(pPk=pTab->pIndex; pPk && pPk->autoIndex<2; pPk=pPk->pNext){} assert( pPk!=0 ); nPk = pPk->nKeyCol; /* Make sure every column of the PRIMARY KEY is NOT NULL */ for(i=0; i<nPk; i++){ pTab->aCol[pPk->aiColumn[i]].notNull = 1; } /* Update the in-memory representation of all UNIQUE indices by converting ** the final rowid column into one or more columns of the PRIMARY KEY. */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int n; if( pIdx->autoIndex==2 ) continue; |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
25 26 27 28 29 30 31 | int opcode /* OP_OpenRead or OP_OpenWrite */ ){ Vdbe *v; assert( !IsVirtual(pTab) ); v = sqlite3GetVdbe(p); assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName); | > | | | > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | int opcode /* OP_OpenRead or OP_OpenWrite */ ){ Vdbe *v; assert( !IsVirtual(pTab) ); v = sqlite3GetVdbe(p); assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName); if( HasRowid(pTab) ){ sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb); sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32); VdbeComment((v, "%s", pTab->zName)); } } /* ** Return a pointer to the column affinity string associated with index ** pIdx. A column affinity string has one character for each column in ** the table, according to the affinity of the column: ** |
︙ | ︙ | |||
437 438 439 440 441 442 443 | ** ** The code generated follows one of four templates. For a simple ** select with data coming from a VALUES clause, the code executes ** once straight down through. Pseudo-code follows (we call this ** the "1st template"): ** ** open write cursor to <table> and its indices | | | 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 | ** ** The code generated follows one of four templates. For a simple ** select with data coming from a VALUES clause, the code executes ** once straight down through. Pseudo-code follows (we call this ** the "1st template"): ** ** open write cursor to <table> and its indices ** put VALUES clause expressions into registers ** write the resulting record into <table> ** cleanup ** ** The three remaining templates assume the statement is of the form ** ** INSERT INTO <table> SELECT ... ** |
︙ | ︙ | |||
547 548 549 550 551 552 553 554 555 556 557 558 559 560 | 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 regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */ int regRowCount = 0; /* Memory cell used for the row counter */ int regIns; /* Block of regs holding rowid+data being inserted */ int regRowid; /* registers holding insert rowid */ | > | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | 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 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ /* Register allocations */ int regFromSelect = 0;/* Base register for data coming from SELECT */ int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */ int regRowCount = 0; /* Memory cell used for the row counter */ int regIns; /* Block of regs holding rowid+data being inserted */ int regRowid; /* registers holding insert rowid */ |
︙ | ︙ | |||
586 587 588 589 590 591 592 593 594 595 596 597 598 599 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb<db->nDb ); pDb = &db->aDb[iDb]; zDb = pDb->zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ goto insert_cleanup; } /* Figure out if we have any triggers and if the table being ** inserted into is a view */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask); isView = pTab->pSelect!=0; | > | 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb<db->nDb ); pDb = &db->aDb[iDb]; zDb = pDb->zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ goto insert_cleanup; } withoutRowid = !HasRowid(pTab); /* Figure out if we have any triggers and if the table being ** inserted into is a view */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask); isView = pTab->pSelect!=0; |
︙ | ︙ | |||
766 767 768 769 770 771 772 | pColumn->a[i].idx = -1; } for(i=0; i<pColumn->nId; i++){ for(j=0; j<pTab->nCol; j++){ if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){ pColumn->a[i].idx = j; if( j==pTab->iPKey ){ | | | | 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 | pColumn->a[i].idx = -1; } for(i=0; i<pColumn->nId; i++){ for(j=0; j<pTab->nCol; j++){ if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){ pColumn->a[i].idx = j; if( j==pTab->iPKey ){ keyColumn = i; assert( !withoutRowid ); } break; } } if( j>=pTab->nCol ){ if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){ keyColumn = i; }else{ sqlite3ErrorMsg(pParse, "table %S has no column named %s", pTabList, 0, pColumn->a[i].zName); pParse->checkSchema = 1; goto insert_cleanup; } |
︙ | ︙ | |||
803 804 805 806 807 808 809 | sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } /* If this is not a view, open the table and and all indices */ if( !isView ){ int nIdx; | | | 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 | sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } /* If this is not a view, open the table and and all indices */ if( !isView ){ int nIdx; baseCur = pParse->nTab - withoutRowid; nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite); aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1)); if( aRegIdx==0 ){ goto insert_cleanup; } for(i=0; i<nIdx; i++){ aRegIdx[i] = ++pParse->nMem; |
︙ | ︙ | |||
868 869 870 871 872 873 874 875 876 877 878 879 880 881 | ** we do not know what the unique ID will be (because the insert has ** not happened yet) so we substitute a rowid of -1 */ if( keyColumn<0 ){ sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); }else{ int j1; if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regCols); }else{ assert( pSelect==0 ); /* Otherwise useTempTable is true */ sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regCols); } j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); | > | 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 | ** we do not know what the unique ID will be (because the insert has ** not happened yet) so we substitute a rowid of -1 */ if( keyColumn<0 ){ sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); }else{ int j1; assert( !withoutRowid ); if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regCols); }else{ assert( pSelect==0 ); /* Otherwise useTempTable is true */ sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regCols); } j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); |
︙ | ︙ | |||
964 965 966 967 968 969 970 | sqlite3VdbeJumpHere(v, j1); }else{ j1 = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); } sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); } | | | 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 | sqlite3VdbeJumpHere(v, j1); }else{ j1 = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); } sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); } }else if( IsVirtual(pTab) || withoutRowid ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid); }else{ sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc); appendFlag = 1; } autoIncStep(pParse, regAutoinc, regRowid); |
︙ | ︙ | |||
1061 1062 1063 1064 1065 1066 1067 | }else if( pSelect ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrCont); sqlite3VdbeJumpHere(v, addrInsTop); } if( !IsVirtual(pTab) && !isView ){ /* Close all tables opened */ | | | 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 | }else if( pSelect ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrCont); sqlite3VdbeJumpHere(v, addrInsTop); } if( !IsVirtual(pTab) && !isView ){ /* Close all tables opened */ if( !withoutRowid ) sqlite3VdbeAddOp1(v, OP_Close, baseCur); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqlite3VdbeAddOp1(v, OP_Close, idx+baseCur); } } insert_end: /* Update the sqlite_sequence table by storing the content of the |
︙ | ︙ | |||
1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 | sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); } sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]); if( useSeekResult ){ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); } } regData = regRowid + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); sqlite3TableAffinityStr(v, pTab); sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); if( pParse->nested ){ pik_flags = 0; | > | 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 | sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); } sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]); if( useSeekResult ){ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); } } if( !HasRowid(pTab) ) return; regData = regRowid + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); sqlite3TableAffinityStr(v, pTab); sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); if( pParse->nested ){ pik_flags = 0; |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
61 62 63 64 65 66 67 | if( db->mallocFailed ){ corruptSchema(pData, argv[0], 0); return 1; } assert( iDb>=0 && iDb<db->nDb ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ | < < | | | 61 62 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 | if( db->mallocFailed ){ corruptSchema(pData, argv[0], 0); return 1; } assert( iDb>=0 && iDb<db->nDb ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[2] && argv[2][0] ){ /* Call the parser to process a CREATE TABLE, INDEX or VIEW. ** But because db->init.busy is set to 1, no VDBE code is generated ** or executed. All the parser does is build the internal data ** structures that describe the table, index, or view. */ int rc; sqlite3_stmt *pStmt; TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ assert( db->init.busy ); db->init.iDb = iDb; db->init.newTnum = argv[1] ? sqlite3Atoi(argv[1]) : 0; db->init.orphanTrigger = 0; TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); rc = db->errCode; assert( (rc&0xFF)==(rcp&0xFF) ); db->init.iDb = 0; if( SQLITE_OK!=rc ){ if( db->init.orphanTrigger ){ |
︙ | ︙ | |||
115 116 117 118 119 120 121 122 123 124 125 126 127 128 | ** the permanent table is hidden by the TEMP table, we can also ** safely ignore the index on the permanent table. */ /* Do Nothing */; }else if( sqlite3GetInt32(argv[1], &pIndex->tnum)==0 ){ corruptSchema(pData, argv[0], "invalid rootpage"); } } return 0; } /* ** Attempt to read the database schema and initialize internal ** data structures for a single database file. The index of the | > > > > > | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | ** the permanent table is hidden by the TEMP table, we can also ** safely ignore the index on the permanent table. */ /* Do Nothing */; }else if( sqlite3GetInt32(argv[1], &pIndex->tnum)==0 ){ corruptSchema(pData, argv[0], "invalid rootpage"); } if( pIndex->autoIndex==2 && (pIndex->pTable->tabFlags & TF_WithoutRowid)!=0 ){ pIndex->pTable->tnum = pIndex->tnum; } } return 0; } /* ** Attempt to read the database schema and initialize internal ** data structures for a single database file. The index of the |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 | # define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) # define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) #else # define IsVirtual(X) 0 # define IsHiddenColumn(X) 0 #endif /* ** Each foreign key constraint is an instance of the following structure. ** ** A foreign key is associated with two tables. The "from" table is ** the table that contains the REFERENCES clause that creates the foreign ** key. The "to" table is the table that is named in the REFERENCES clause. ** Consider this example: | > > > | 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 | # define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) # define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) #else # define IsVirtual(X) 0 # define IsHiddenColumn(X) 0 #endif /* Does the table have a rowid */ #define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0) /* ** Each foreign key constraint is an instance of the following structure. ** ** A foreign key is associated with two tables. The "from" table is ** the table that contains the REFERENCES clause that creates the foreign ** key. The "to" table is the table that is named in the REFERENCES clause. ** Consider this example: |
︙ | ︙ | |||
1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 | u16 nKeyCol; /* Number of columns forming the key */ u16 nColumn; /* Number of columns stored in the index */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ unsigned bUnordered:1; /* Use this index for == or IN queries only */ unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ unsigned isResized:1; /* True if resizeIndexObject() has been called */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ #endif }; | > | 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 | u16 nKeyCol; /* Number of columns forming the key */ u16 nColumn; /* Number of columns stored in the index */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ unsigned bUnordered:1; /* Use this index for == or IN queries only */ unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ unsigned isResized:1; /* True if resizeIndexObject() has been called */ unsigned isCovering:1; /* True if this is a covering index */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ #endif }; |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
4417 4418 4419 4420 4421 4422 4423 | /* ** Return a bitmask where 1s indicate that the corresponding column of ** the table is used by an index. Only the first 63 columns are considered. */ static Bitmask columnsInIndex(Index *pIdx){ Bitmask m = 0; int j; | | | | | | > | 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 | /* ** Return a bitmask where 1s indicate that the corresponding column of ** the table is used by an index. Only the first 63 columns are considered. */ static Bitmask columnsInIndex(Index *pIdx){ Bitmask m = 0; int j; for(j=pIdx->nColumn-1; j>=0; j--){ int x = pIdx->aiColumn[j]; if( x>=0 ){ testcase( x==BMS-1 ); testcase( x==BMS-2 ); if( x<BMS-1 ) m |= MASKBIT(x); } } return m; } /* Check to see if a partial index with pPartIndexWhere can be used ** in the current query. Return true if it can be and false if not. */ |
︙ | ︙ | |||
4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 | pTab = pSrc->pTab; pWC = pBuilder->pWC; assert( !IsVirtual(pSrc->pTab) ); if( pSrc->pIndex ){ /* An INDEXED BY clause specifies a particular index to use */ pProbe = pSrc->pIndex; }else{ /* There is no INDEXED BY clause. Create a fake Index object in local ** variable sPk to represent the rowid primary key index. Make this ** fake index the first in a chain of Index objects with all of the real ** indices to follow */ Index *pFirst; /* First of real indices on the table */ memset(&sPk, 0, sizeof(Index)); | > > | 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 | pTab = pSrc->pTab; pWC = pBuilder->pWC; assert( !IsVirtual(pSrc->pTab) ); if( pSrc->pIndex ){ /* An INDEXED BY clause specifies a particular index to use */ pProbe = pSrc->pIndex; }else if( !HasRowid(pTab) ){ pProbe = pTab->pIndex; }else{ /* There is no INDEXED BY clause. Create a fake Index object in local ** variable sPk to represent the rowid primary key index. Make this ** fake index the first in a chain of Index objects with all of the real ** indices to follow */ Index *pFirst; /* First of real indices on the table */ memset(&sPk, 0, sizeof(Index)); |
︙ | ︙ | |||
4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pOrSet && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 && pSrc->pIndex==0 && !pSrc->viaCoroutine && !pSrc->notIndexed && !pSrc->isCorrelated ){ /* Generate auto-index WhereLoops */ WhereTerm *pTerm; WhereTerm *pWCEnd = pWC->a + pWC->nTerm; for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){ if( pTerm->prereqRight & pNew->maskSelf ) continue; | > | 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pOrSet && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 && pSrc->pIndex==0 && !pSrc->viaCoroutine && !pSrc->notIndexed && HasRowid(pTab) && !pSrc->isCorrelated ){ /* Generate auto-index WhereLoops */ WhereTerm *pTerm; WhereTerm *pWCEnd = pWC->a + pWC->nTerm; for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){ if( pTerm->prereqRight & pNew->maskSelf ) continue; |
︙ | ︙ | |||
4569 4570 4571 4572 4573 4574 4575 | ** over full scans. FIXME */ pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16; whereLoopOutputAdjust(pWC, pNew); rc = whereLoopInsert(pBuilder, pNew); pNew->nOut = rSize; if( rc ) break; }else{ | > > > > > | | > | 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 | ** over full scans. FIXME */ pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16; whereLoopOutputAdjust(pWC, pNew); rc = whereLoopInsert(pBuilder, pNew); pNew->nOut = rSize; if( rc ) break; }else{ Bitmask m; if( pProbe->isCovering ){ pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; m = 0; }else{ m = pSrc->colUsed & ~columnsInIndex(pProbe); pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED; } /* Full scan via index */ if( b || ( m==0 && pProbe->bUnordered==0 && pProbe->szIdxRow<pTab->szTabRow && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 |
︙ | ︙ | |||
5518 5519 5520 5521 5522 5523 5524 | for(j=0; j<pIdx->nKeyCol; j++){ pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx); if( pTerm==0 ) break; pLoop->aLTerm[j] = pTerm; } if( j!=pIdx->nKeyCol ) continue; pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED; | | | 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 | for(j=0; j<pIdx->nKeyCol; j++){ pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx); if( pTerm==0 ) break; pLoop->aLTerm[j] = pTerm; } if( j!=pIdx->nKeyCol ) continue; pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED; if( pIdx->isCovering || (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){ pLoop->wsFlags |= WHERE_IDX_ONLY; } pLoop->nLTerm = j; pLoop->u.btree.nEq = j; pLoop->u.btree.pIndex = pIdx; /* TUNING: Cost of a unique index lookup is 15 */ pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */ |
︙ | ︙ | |||
6108 6109 6110 6111 6112 6113 6114 | last = sqlite3VdbeCurrentAddr(v); k = pLevel->addrBody; pOp = sqlite3VdbeGetOp(v, k); for(; k<last; k++, pOp++){ if( pOp->p1!=pLevel->iTabCur ) continue; if( pOp->opcode==OP_Column ){ | | | | 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 | last = sqlite3VdbeCurrentAddr(v); k = pLevel->addrBody; pOp = sqlite3VdbeGetOp(v, k); for(; k<last; k++, pOp++){ if( pOp->p1!=pLevel->iTabCur ) continue; if( pOp->opcode==OP_Column ){ for(j=0; j<pIdx->nColumn; j++){ if( pOp->p2==pIdx->aiColumn[j] ){ pOp->p2 = j; pOp->p1 = pLevel->iIdxCur; break; } } assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || j<pIdx->nColumn ); }else if( pOp->opcode==OP_Rowid ){ pOp->p1 = pLevel->iIdxCur; pOp->opcode = OP_IdxRowid; } } } } |
︙ | ︙ |
Changes to test/alter.test.
︙ | ︙ | |||
859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 | catchsql "ALTER TABLE $tbl ADD COLUMN xyz" } [list 1 "table $tbl may not be altered"] } #------------------------------------------------------------------------ # Verify that ALTER TABLE works on tables with the WITHOUT rowid option. # do_execsql_test alter-16.1 { CREATE TABLE t16a(a TEXT, b REAL, c INT, PRIMARY KEY(a,b)) WITHOUT rowid; INSERT INTO t16a VALUES('abc',1.25,99); ALTER TABLE t16a ADD COLUMN d TEXT DEFAULT 'xyzzy'; INSERT INTO t16a VALUES('cba',5.5,98,'fizzle'); SELECT * FROM t16a ORDER BY a; } {abc 1.25 99 xyzzy cba 5.5 98 fizzle} do_execsql_test alter-16.2 { ALTER TABLE t16a RENAME TO t16a_rn; SELECT * FROM t16a_rn ORDER BY a; } {abc 1.25 99 xyzzy cba 5.5 98 fizzle} finish_test | > > | 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 | catchsql "ALTER TABLE $tbl ADD COLUMN xyz" } [list 1 "table $tbl may not be altered"] } #------------------------------------------------------------------------ # Verify that ALTER TABLE works on tables with the WITHOUT rowid option. # if 0 { do_execsql_test alter-16.1 { CREATE TABLE t16a(a TEXT, b REAL, c INT, PRIMARY KEY(a,b)) WITHOUT rowid; INSERT INTO t16a VALUES('abc',1.25,99); ALTER TABLE t16a ADD COLUMN d TEXT DEFAULT 'xyzzy'; INSERT INTO t16a VALUES('cba',5.5,98,'fizzle'); SELECT * FROM t16a ORDER BY a; } {abc 1.25 99 xyzzy cba 5.5 98 fizzle} do_execsql_test alter-16.2 { ALTER TABLE t16a RENAME TO t16a_rn; SELECT * FROM t16a_rn ORDER BY a; } {abc 1.25 99 xyzzy cba 5.5 98 fizzle} } finish_test |