Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge leaf accidentally created by [1c4984c62f]. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
cae949ce971ca216e0f8880b2f938666 |
User & Date: | dan 2009-11-20 17:23:13.000 |
Original User & Date: | dan 2009-11-20 10:23:13.000 |
Context
2009-11-20
| ||
18:48 | When moving pages as part of autovacuum on an in-memory database, make sure that the source location is journalled so that a ROLLBACK can occur. Part of the fix for ticket [564d412f15a00] (check-in: 2f42f91fe6 user: drh tags: trunk) | |
17:23 | Merge leaf accidentally created by [1c4984c62f]. (check-in: cae949ce97 user: dan tags: trunk) | |
17:18 | Add a test to make sure a database can be attached to a single handle twice if not in shared-cache mode. (check-in: 1c4984c62f user: dan tags: trunk) | |
16:13 | Fix a bug in LIMIT 0 for compound SELECT statement. The problem was introduced by recent enhancements and has not appeared in any release. (check-in: c6ed7e2a73 user: drh tags: trunk) | |
Changes
Changes to ext/fts3/fts3_write.c.
︙ | ︙ | |||
830 831 832 833 834 835 836 837 838 839 840 841 842 843 | p->aLeavesStmt[p->nLeavesStmt++] = pReader->pStmt; } sqlite3_free(pReader->zTerm); sqlite3_free(pReader); } } int sqlite3Fts3SegReaderNew( Fts3Table *p, /* Virtual table handle */ int iAge, /* Segment "age". */ sqlite3_int64 iStartLeaf, /* First leaf to traverse */ sqlite3_int64 iEndLeaf, /* Final leaf to traverse */ sqlite3_int64 iEndBlock, /* Final block of segment */ const char *zRoot, /* Buffer containing root node */ | > > > | 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 | p->aLeavesStmt[p->nLeavesStmt++] = pReader->pStmt; } sqlite3_free(pReader->zTerm); sqlite3_free(pReader); } } /* ** Allocate a new SegReader object. */ int sqlite3Fts3SegReaderNew( Fts3Table *p, /* Virtual table handle */ int iAge, /* Segment "age". */ sqlite3_int64 iStartLeaf, /* First leaf to traverse */ sqlite3_int64 iEndLeaf, /* Final leaf to traverse */ sqlite3_int64 iEndBlock, /* Final block of segment */ const char *zRoot, /* Buffer containing root node */ |
︙ | ︙ | |||
959 960 961 962 963 964 965 | sqlite3_column_blob(pStmt, 4), sqlite3_column_bytes(pStmt, 4), ppReader ); } /* | > | | 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 | sqlite3_column_blob(pStmt, 4), sqlite3_column_bytes(pStmt, 4), ppReader ); } /* ** Compare the entries pointed to by two Fts3SegReader structures. ** Comparison is as follows: ** ** 1) EOF is greater than not EOF. ** ** 2) The current terms (if any) are compared with memcmp(). If one ** term is a prefix of another, the longer term is considered the ** larger. ** |
︙ | ︙ | |||
991 992 993 994 995 996 997 | if( rc==0 ){ rc = pRhs->iIdx - pLhs->iIdx; } assert( rc!=0 ); return rc; } | > > > > > > > > > > > | | | 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 | if( rc==0 ){ rc = pRhs->iIdx - pLhs->iIdx; } assert( rc!=0 ); return rc; } /* ** A different comparison function for SegReader structures. In this ** version, it is assumed that each SegReader points to an entry in ** a doclist for identical terms. Comparison is made as follows: ** ** 1) EOF (end of doclist in this case) is greater than not EOF. ** ** 2) By current docid. ** ** 3) By segment age. An older segment is considered larger. */ static int fts3SegReaderDoclistCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){ int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0); if( rc==0 ){ if( pLhs->iDocid==pRhs->iDocid ){ rc = pRhs->iIdx - pLhs->iIdx; }else{ rc = (pLhs->iDocid > pRhs->iDocid) ? 1 : -1; } } assert( pLhs->aNode && pRhs->aNode ); return rc; } |
︙ | ︙ | |||
1071 1072 1073 1074 1075 1076 1077 | #endif } /* ** Insert a record into the %_segments table. */ static int fts3WriteSegment( | | | | > | | 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 | #endif } /* ** Insert a record into the %_segments table. */ static int fts3WriteSegment( Fts3Table *p, /* Virtual table handle */ sqlite3_int64 iBlock, /* Block id for new block */ char *z, /* Pointer to buffer containing block data */ int n /* Size of buffer z in bytes */ ){ sqlite3_stmt *pStmt; int rc = fts3SqlStmt(p, SQL_INSERT_SEGMENTS, &pStmt, 0); if( rc==SQLITE_OK ){ sqlite3_bind_int64(pStmt, 1, iBlock); rc = sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC); if( rc==SQLITE_OK ){ sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); } } return rc; } /* ** Insert a record into the %_segdir table. */ static int fts3WriteSegdir( Fts3Table *p, /* Virtual table handle */ int iLevel, /* Value for "level" field */ int iIdx, /* Value for "idx" field */ sqlite3_int64 iStartBlock, /* Value for "start_block" field */ sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */ sqlite3_int64 iEndBlock, /* Value for "end_block" field */ char *zRoot, /* Blob value for "root" field */ int nRoot /* Number of bytes in buffer zRoot */ |
︙ | ︙ | |||
1118 1119 1120 1121 1122 1123 1124 | sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); } } return rc; } | > > > > > > > > | | | | | < | | 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 | sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); } } return rc; } /* ** Return the size of the common prefix (if any) shared by zPrev and ** zNext, in bytes. For example, ** ** fts3PrefixCompress("abc", 3, "abcdef", 6) // returns 3 ** fts3PrefixCompress("abX", 3, "abcdef", 6) // returns 2 ** fts3PrefixCompress("abX", 3, "Xbcdef", 6) // returns 0 */ static int fts3PrefixCompress( const char *zPrev, /* Buffer containing previous term */ int nPrev, /* Size of buffer zPrev in bytes */ const char *zNext, /* Buffer containing next term */ int nNext /* Size of buffer zNext in bytes */ ){ int n; for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++); return n; } /* ** Add term zTerm to the SegmentNode. It is guaranteed that zTerm is larger ** (according to memcmp) than the previous term. */ static int fts3NodeAddTerm( |
︙ | ︙ | |||
1154 1155 1156 1157 1158 1159 1160 | */ if( pTree ){ int nData = pTree->nData; /* Current size of node in bytes */ int nReq = nData; /* Required space after adding zTerm */ int nPrefix; /* Number of bytes of prefix compression */ int nSuffix; /* Suffix length */ | | | 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 | */ if( pTree ){ int nData = pTree->nData; /* Current size of node in bytes */ int nReq = nData; /* Required space after adding zTerm */ int nPrefix; /* Number of bytes of prefix compression */ int nSuffix; /* Suffix length */ nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm); nSuffix = nTerm-nPrefix; nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix; if( nReq<=INTERIOR_MAX || !pTree->zTerm ){ if( nReq>INTERIOR_MAX ){ /* An unusual case: this is the first term to be added to the node |
︙ | ︙ | |||
1259 1260 1261 1262 1263 1264 1265 | nStart = FTS3_VARINT_MAX - sqlite3Fts3VarintLen(iLeftChild); pTree->aData[nStart] = (char)iHeight; sqlite3Fts3PutVarint(&pTree->aData[nStart+1], iLeftChild); return nStart; } /* | > | > > > > > > > > > | | 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 | nStart = FTS3_VARINT_MAX - sqlite3Fts3VarintLen(iLeftChild); pTree->aData[nStart] = (char)iHeight; sqlite3Fts3PutVarint(&pTree->aData[nStart+1], iLeftChild); return nStart; } /* ** Write the buffer for the segment node pTree and all of its peers to the ** database. Then call this function recursively to write the parent of ** pTree and its peers to the database. ** ** Except, if pTree is a root node, do not write it to the database. Instead, ** set output variables *paRoot and *pnRoot to contain the root node. ** ** If successful, SQLITE_OK is returned and output variable *piLast is ** set to the largest blockid written to the database (or zero if no ** blocks were written to the db). Otherwise, an SQLite error code is ** returned. */ static int fts3NodeWrite( Fts3Table *p, /* Virtual table handle */ SegmentNode *pTree, /* SegmentNode handle */ int iHeight, /* Height of this node in tree */ sqlite3_int64 iLeaf, /* Block id of first leaf node */ sqlite3_int64 iFree, /* Block id of next free slot in %_segments */ sqlite3_int64 *piLast, /* OUT: Block id of last entry written */ char **paRoot, /* OUT: Data for root node */ int *pnRoot /* OUT: Size of root node in bytes */ |
︙ | ︙ | |||
1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 | sqlite3_free(p->zMalloc); sqlite3_free(p); p = pRight; } } } static int fts3SegWriterAdd( Fts3Table *p, /* Virtual table handle */ SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */ int isCopyTerm, /* True if buffer zTerm must be copied */ const char *zTerm, /* Pointer to buffer containing term */ int nTerm, /* Size of term in bytes */ const char *aDoclist, /* Pointer to buffer containing doclist */ | > > > > > > > > | 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 | sqlite3_free(p->zMalloc); sqlite3_free(p); p = pRight; } } } /* ** Add a term to the segment being constructed by the SegmentWriter object ** *ppWriter. When adding the first term to a segment, *ppWriter should ** be passed NULL. This function will allocate a new SegmentWriter object ** and return it via the input/output variable *ppWriter in this case. ** ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. */ static int fts3SegWriterAdd( Fts3Table *p, /* Virtual table handle */ SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */ int isCopyTerm, /* True if buffer zTerm must be copied */ const char *zTerm, /* Pointer to buffer containing term */ int nTerm, /* Size of term in bytes */ const char *aDoclist, /* Pointer to buffer containing doclist */ |
︙ | ︙ | |||
1364 1365 1366 1367 1368 1369 1370 | pWriter->iFirst = pWriter->iFree; } rc = sqlite3_reset(pStmt); if( rc!=SQLITE_OK ) return rc; } nData = pWriter->nData; | | | 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 | pWriter->iFirst = pWriter->iFree; } rc = sqlite3_reset(pStmt); if( rc!=SQLITE_OK ) return rc; } nData = pWriter->nData; nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm); nSuffix = nTerm-nPrefix; /* Figure out how many bytes are required by this new entry */ nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */ sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */ nSuffix + /* Term suffix */ sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */ |
︙ | ︙ | |||
1454 1455 1456 1457 1458 1459 1460 1461 | pWriter->zTerm = (char *)zTerm; } pWriter->nTerm = nTerm; return SQLITE_OK; } static int fts3SegWriterFlush( | > > > > > > | | | | | | > | | > | > > > > | 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 | pWriter->zTerm = (char *)zTerm; } pWriter->nTerm = nTerm; return SQLITE_OK; } /* ** Flush all data associated with the SegmentWriter object pWriter to the ** database. This function must be called after all terms have been added ** to the segment using fts3SegWriterAdd(). If successful, SQLITE_OK is ** returned. Otherwise, an SQLite error code. */ static int fts3SegWriterFlush( Fts3Table *p, /* Virtual table handle */ SegmentWriter *pWriter, /* SegmentWriter to flush to the db */ int iLevel, /* Value for 'level' column of %_segdir */ int iIdx /* Value for 'idx' column of %_segdir */ ){ int rc; /* Return code */ if( pWriter->pTree ){ sqlite3_int64 iLast; /* Largest block id written to database */ sqlite3_int64 iLastLeaf; /* Largest leaf block id written to db */ char *zRoot; /* Pointer to buffer containing root node */ int nRoot; /* Size of buffer zRoot */ iLastLeaf = pWriter->iFree; rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, pWriter->nData); if( rc==SQLITE_OK ){ rc = fts3NodeWrite(p, pWriter->pTree, 1, pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot); } if( rc==SQLITE_OK ){ rc = fts3WriteSegdir( p, iLevel, iIdx, pWriter->iFirst, iLastLeaf, iLast, zRoot, nRoot); } }else{ /* The entire tree fits on the root node. Write it to the segdir table. */ rc = fts3WriteSegdir( p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData); } return rc; } /* ** Release all memory held by the SegmentWriter object passed as the ** first argument. */ static void fts3SegWriterFree(SegmentWriter *pWriter){ if( pWriter ){ sqlite3_free(pWriter->aData); sqlite3_free(pWriter->zMalloc); fts3NodeFree(pWriter->pTree); sqlite3_free(pWriter); } |
︙ | ︙ | |||
1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 | *pisEmpty = sqlite3_column_int(pStmt, 0); } rc = sqlite3_reset(pStmt); } return rc; } static int fts3SegmentCount(Fts3Table *p, int iLevel, int *pnSegment){ sqlite3_stmt *pStmt; int rc; assert( iLevel>=0 ); rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_COUNT, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; sqlite3_bind_int(pStmt, 1, iLevel); if( SQLITE_ROW==sqlite3_step(pStmt) ){ *pnSegment = sqlite3_column_int(pStmt, 0); } return sqlite3_reset(pStmt); } static int fts3SegmentCountMax(Fts3Table *p, int *pnSegment, int *pnMax){ sqlite3_stmt *pStmt; int rc; rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_COUNT_MAX, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; if( SQLITE_ROW==sqlite3_step(pStmt) ){ *pnSegment = sqlite3_column_int(pStmt, 0); *pnMax = sqlite3_column_int(pStmt, 1); } return sqlite3_reset(pStmt); } static int fts3DeleteSegdir( | > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 | *pisEmpty = sqlite3_column_int(pStmt, 0); } rc = sqlite3_reset(pStmt); } return rc; } /* ** Set *pnSegment to the number of segments of level iLevel in the database. ** ** Return SQLITE_OK if successful, or an SQLite error code if not. */ static int fts3SegmentCount(Fts3Table *p, int iLevel, int *pnSegment){ sqlite3_stmt *pStmt; int rc; assert( iLevel>=0 ); rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_COUNT, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; sqlite3_bind_int(pStmt, 1, iLevel); if( SQLITE_ROW==sqlite3_step(pStmt) ){ *pnSegment = sqlite3_column_int(pStmt, 0); } return sqlite3_reset(pStmt); } /* ** Set *pnSegment to the total number of segments in the database. Set ** *pnMax to the largest segment level in the database (segment levels ** are stored in the 'level' column of the %_segdir table). ** ** Return SQLITE_OK if successful, or an SQLite error code if not. */ static int fts3SegmentCountMax(Fts3Table *p, int *pnSegment, int *pnMax){ sqlite3_stmt *pStmt; int rc; rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_COUNT_MAX, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; if( SQLITE_ROW==sqlite3_step(pStmt) ){ *pnSegment = sqlite3_column_int(pStmt, 0); *pnMax = sqlite3_column_int(pStmt, 1); } return sqlite3_reset(pStmt); } /* ** This function is used after merging multiple segments into a single large ** segment to delete the old, now redundant, segment b-trees. Specifically, ** it: ** ** 1) Deletes all %_segments entries for the segments associated with ** each of the SegReader objects in the array passed as the third ** argument, and ** ** 2) deletes all %_segdir entries with level iLevel, or all %_segdir ** entries regardless of level if (iLevel<0). ** ** SQLITE_OK is returned if successful, otherwise an SQLite error code. */ static int fts3DeleteSegdir( Fts3Table *p, /* Virtual table handle */ int iLevel, /* Level of %_segdir entries to delete */ Fts3SegReader **apSegment, /* Array of SegReader objects */ int nReader /* Size of array apSegment */ ){ int rc; /* Return Code */ int i; /* Iterator variable */ sqlite3_stmt *pDelete; /* SQL statement to delete rows */ rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0); for(i=0; rc==SQLITE_OK && i<nReader; i++){ |
︙ | ︙ | |||
1580 1581 1582 1583 1584 1585 1586 | }else{ rc = fts3SqlExec(p, SQL_DELETE_ALL_SEGDIR, 0); } return rc; } | > > > > > > > > > | > > > > | 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 | }else{ rc = fts3SqlExec(p, SQL_DELETE_ALL_SEGDIR, 0); } return rc; } /* ** When this function is called, buffer *ppList (size *pnList bytes) contains ** a position list that may (or may not) feature multiple columns. This ** function adjusts the pointer *ppList and the length *pnList so that they ** identify the subset of the position list that corresponds to column iCol. ** ** If there are no entries in the input position list for column iCol, then ** *pnList is set to zero before returning. */ static void fts3ColumnFilter( int iCol, /* Column to filter on */ char **ppList, /* IN/OUT: Pointer to position list */ int *pnList /* IN/OUT: Size of buffer *ppList in bytes */ ){ char *pList = *ppList; int nList = *pnList; char *pEnd = &pList[nList]; int iCurrent = 0; char *p = pList; assert( iCol>=0 ); |
︙ | ︙ | |||
1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 | p += sqlite3Fts3GetVarint32(p, &iCurrent); } *ppList = pList; *pnList = nList; } static int fts3MergeCallback( Fts3Table *p, void *pContext, char *zTerm, int nTerm, char *aDoclist, int nDoclist | > > > > | 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 | p += sqlite3Fts3GetVarint32(p, &iCurrent); } *ppList = pList; *pnList = nList; } /* ** sqlite3Fts3SegReaderIterate() callback used when merging multiple ** segments to create a single, larger segment. */ static int fts3MergeCallback( Fts3Table *p, void *pContext, char *zTerm, int nTerm, char *aDoclist, int nDoclist |
︙ | ︙ | |||
1703 1704 1705 1706 1707 1708 1709 | /* The current term of the first nMerge entries in the array ** of Fts3SegReader objects is the same. The doclists must be merged ** and a single term added to the new segment. */ for(i=0; i<nMerge; i++){ fts3SegReaderFirstDocid(apSegment[i]); } | | | 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 | /* The current term of the first nMerge entries in the array ** of Fts3SegReader objects is the same. The doclists must be merged ** and a single term added to the new segment. */ for(i=0; i<nMerge; i++){ fts3SegReaderFirstDocid(apSegment[i]); } fts3SegReaderSort(apSegment, nMerge, nMerge, fts3SegReaderDoclistCmp); while( apSegment[0]->pOffsetList ){ int j; /* Number of segments that share a docid */ char *pList; int nList; int nByte; sqlite3_int64 iDocid = apSegment[0]->iDocid; fts3SegReaderNextDocid(apSegment[0], &pList, &nList); |
︙ | ︙ | |||
1745 1746 1747 1748 1749 1750 1751 | if( isRequirePos ){ memcpy(&aBuffer[nDoclist], pList, nList); nDoclist += nList; aBuffer[nDoclist++] = '\0'; } } | | | 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 | if( isRequirePos ){ memcpy(&aBuffer[nDoclist], pList, nList); nDoclist += nList; aBuffer[nDoclist++] = '\0'; } } fts3SegReaderSort(apSegment, nMerge, j, fts3SegReaderDoclistCmp); } if( nDoclist>0 ){ rc = xFunc(p, pContext, zTerm, nTerm, aBuffer, nDoclist); if( rc!=SQLITE_OK ) goto finished; } } |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
1319 1320 1321 1322 1323 1324 1325 | sqlite3ExprCacheClear(pParse); assert( p->pOffset==0 || p->pLimit!=0 ); if( p->pLimit ){ p->iLimit = iLimit = ++pParse->nMem; v = sqlite3GetVdbe(pParse); if( NEVER(v==0) ) return; /* VDBE should have already been allocated */ if( sqlite3ExprIsInteger(p->pLimit, &n) ){ | < < < | | > > | 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 | sqlite3ExprCacheClear(pParse); assert( p->pOffset==0 || p->pLimit!=0 ); if( p->pLimit ){ p->iLimit = iLimit = ++pParse->nMem; v = sqlite3GetVdbe(pParse); if( NEVER(v==0) ) return; /* VDBE should have already been allocated */ if( sqlite3ExprIsInteger(p->pLimit, &n) ){ sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); VdbeComment((v, "LIMIT counter")); if( n==0 ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak); } }else{ sqlite3ExprCode(pParse, p->pLimit, iLimit); sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeComment((v, "LIMIT counter")); sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); } |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
539 540 541 542 543 544 545 546 547 548 549 550 551 552 | Vdbe *p /* The VDBE */ ){ int pc; /* The program counter */ Op *aOp = p->aOp; /* Copy of p->aOp */ Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 encoding = ENC(db); /* The database encoding */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK u8 checkProgress; /* True if progress callbacks are enabled */ int nProgressOps = 0; /* Opcodes executed since progress callback. */ #endif Mem *aMem = p->aMem; /* Copy of p->aMem */ Mem *pIn1 = 0; /* 1st input operand */ | > | 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 | Vdbe *p /* The VDBE */ ){ int pc; /* The program counter */ Op *aOp = p->aOp; /* Copy of p->aOp */ Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */ u8 encoding = ENC(db); /* The database encoding */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK u8 checkProgress; /* True if progress callbacks are enabled */ int nProgressOps = 0; /* Opcodes executed since progress callback. */ #endif Mem *aMem = p->aMem; /* Copy of p->aMem */ Mem *pIn1 = 0; /* 1st input operand */ |
︙ | ︙ | |||
4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 | assert( (p->btreeMask & (1<<iDb))!=0 ); rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved); pOut->flags = MEM_Int; pOut->u.i = iMoved; #ifndef SQLITE_OMIT_AUTOVACUUM if( rc==SQLITE_OK && iMoved!=0 ){ sqlite3RootPageMoved(&db->aDb[iDb], iMoved, pOp->p1); } #endif } break; } /* Opcode: Clear P1 P2 P3 | > | 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 | assert( (p->btreeMask & (1<<iDb))!=0 ); rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved); pOut->flags = MEM_Int; pOut->u.i = iMoved; #ifndef SQLITE_OMIT_AUTOVACUUM if( rc==SQLITE_OK && iMoved!=0 ){ sqlite3RootPageMoved(&db->aDb[iDb], iMoved, pOp->p1); resetSchemaOnFault = 1; } #endif } break; } /* Opcode: Clear P1 P2 P3 |
︙ | ︙ | |||
5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 | */ vdbe_error_halt: assert( rc ); p->rc = rc; sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; rc = SQLITE_ERROR; /* This is the only way out of this procedure. We have to ** release the mutexes on btrees that were acquired at the ** top. */ vdbe_return: sqlite3BtreeMutexArrayLeave(&p->aMutex); return rc; | > | 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 | */ vdbe_error_halt: assert( rc ); p->rc = rc; sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; rc = SQLITE_ERROR; if( resetSchemaOnFault ) sqlite3ResetInternalSchema(db, 0); /* This is the only way out of this procedure. We have to ** release the mutexes on btrees that were acquired at the ** top. */ vdbe_return: sqlite3BtreeMutexArrayLeave(&p->aMutex); return rc; |
︙ | ︙ |