Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge changes through release 3.7.2 into the apple-osx branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | apple-osx |
Files: | files | file ages | folders |
SHA1: |
415c448dc45a297bd1b0bbce25c4572e |
User & Date: | drh 2010-08-24 01:08:11.000 |
References
2010-09-09
| ||
23:31 | The merge for check-in [415c448dc4] did not do exactly write, resulting in a subtle bug in the SQLITE_FCNTL_SIZE_HINT logic. This check-in is the fix. (check-in: badaaa18fd user: drh tags: apple-osx) | |
Context
2010-08-24
| ||
01:51 | Merge in the R-tree fix from the trunk. (check-in: 02ee0bd5a3 user: drh tags: apple-osx) | |
01:08 | Merge changes through release 3.7.2 into the apple-osx branch. (check-in: 415c448dc4 user: drh tags: apple-osx) | |
00:40 | Version 3.7.2 (check-in: 42537b6056 user: drh tags: trunk, release, version-3.7.2) | |
2010-08-18
| ||
00:24 | Merge the 3.7.1 pre-release snapshot changes as of 2010-08-18 into the apple-osx branch. (check-in: 866e9286ae user: drh tags: apple-osx) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
758 759 760 761 762 763 764 | tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR) $(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR) $(LTCOMPILE) -DTCLSH=1 -o $@ -c $(TOP)/src/tclsqlite.c tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR) | | | 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 | tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR) $(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR) $(LTCOMPILE) -DTCLSH=1 -o $@ -c $(TOP)/src/tclsqlite.c tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR) $(LTCOMPILE) -DUSE_TCL_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c tclsqlite3$(TEXE): tclsqlite-shell.lo libsqlite3.la $(LTLINK) -o $@ tclsqlite-shell.lo \ libsqlite3.la $(LIBTCL) # Rules to build opcodes.c and opcodes.h # |
︙ | ︙ |
Changes to VERSION.
|
| | | 1 | 3.7.2 |
Changes to configure.
1 2 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. | | | 1 2 3 4 5 6 7 8 9 10 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.62 for sqlite 3.7.2. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## |
︙ | ︙ | |||
739 740 741 742 743 744 745 | MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' | | | | 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 | MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' PACKAGE_VERSION='3.7.2' PACKAGE_STRING='sqlite 3.7.2' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> |
︙ | ︙ | |||
1483 1484 1485 1486 1487 1488 1489 | # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF | | | 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 | # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures sqlite 3.7.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. |
︙ | ︙ | |||
1548 1549 1550 1551 1552 1553 1554 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in | | | 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of sqlite 3.7.2:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] |
︙ | ︙ | |||
1666 1667 1668 1669 1670 1671 1672 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF | | | | 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF sqlite configure 3.7.2 generated by GNU Autoconf 2.62 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by sqlite $as_me 3.7.2, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { |
︙ | ︙ | |||
13968 13969 13970 13971 13972 13973 13974 | exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" | | | 13968 13969 13970 13971 13972 13973 13974 13975 13976 13977 13978 13979 13980 13981 13982 | exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by sqlite $as_me 3.7.2, which was generated by GNU Autoconf 2.62. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ |
︙ | ︙ | |||
14021 14022 14023 14024 14025 14026 14027 | $config_commands Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ | | | 14021 14022 14023 14024 14025 14026 14027 14028 14029 14030 14031 14032 14033 14034 14035 | $config_commands Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ sqlite config.status 3.7.2 configured by $0, generated by GNU Autoconf 2.62, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2008 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." |
︙ | ︙ |
Changes to src/backup.c.
︙ | ︙ | |||
216 217 218 219 220 221 222 223 224 225 226 227 228 229 | /* Catch the case where the destination is an in-memory database and the ** page sizes of the source and destination differ. */ if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){ rc = SQLITE_READONLY; } /* This loop runs once for each destination page spanned by the source ** page. For each iteration, variable iOff is set to the byte offset ** of the destination page. */ for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){ DbPage *pDestPg = 0; | > > > > > > > > > | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | /* Catch the case where the destination is an in-memory database and the ** page sizes of the source and destination differ. */ if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){ rc = SQLITE_READONLY; } #ifdef SQLITE_HAS_CODEC /* Backup is not possible if the page size of the destination is changing ** a a codec is in use. */ if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){ rc = SQLITE_READONLY; } #endif /* This loop runs once for each destination page spanned by the source ** page. For each iteration, variable iOff is set to the byte offset ** of the destination page. */ for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){ DbPage *pDestPg = 0; |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 | } #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Given a page number of a regular database page, return the page ** number for the pointer-map page that contains the entry for the ** input page number. */ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ int nPagesPerMapPage; Pgno iPtrMap, ret; assert( sqlite3_mutex_held(pBt->mutex) ); nPagesPerMapPage = (pBt->usableSize/5)+1; iPtrMap = (pgno-2)/nPagesPerMapPage; ret = (iPtrMap*nPagesPerMapPage) + 2; if( ret==PENDING_BYTE_PAGE(pBt) ){ ret++; } return ret; | > > > > > | 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 | } #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Given a page number of a regular database page, return the page ** number for the pointer-map page that contains the entry for the ** input page number. ** ** Return 0 (not a valid page) for pgno==1 since there is ** no pointer map associated with page 1. The integrity_check logic ** requires that ptrmapPageno(*,1)!=1. */ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ int nPagesPerMapPage; Pgno iPtrMap, ret; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno<2 ) return 0; nPagesPerMapPage = (pBt->usableSize/5)+1; iPtrMap = (pgno-2)/nPagesPerMapPage; ret = (iPtrMap*nPagesPerMapPage) + 2; if( ret==PENDING_BYTE_PAGE(pBt) ){ ret++; } return ret; |
︙ | ︙ | |||
1378 1379 1380 1381 1382 1383 1384 | if( !pPage->isInit ){ u16 pc; /* Address of a freeblock within pPage->aData[] */ u8 hdr; /* Offset to beginning of page header */ u8 *data; /* Equal to pPage->aData */ BtShared *pBt; /* The main btree structure */ int usableSize; /* Amount of usable space on each page */ | | | 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 | if( !pPage->isInit ){ u16 pc; /* Address of a freeblock within pPage->aData[] */ u8 hdr; /* Offset to beginning of page header */ u8 *data; /* Equal to pPage->aData */ BtShared *pBt; /* The main btree structure */ int usableSize; /* Amount of usable space on each page */ u16 cellOffset; /* Offset from start of page to first cell pointer */ int nFree; /* Number of unused bytes on the page */ int top; /* First byte of the cell content area */ int iCellFirst; /* First allowable cell or freeblock offset */ int iCellLast; /* Last possible cell or freeblock offset */ pBt = pPage->pBt; |
︙ | ︙ | |||
1493 1494 1495 1496 1497 1498 1499 | memset(&data[hdr], 0, pBt->usableSize - hdr); } data[hdr] = (char)flags; first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0); memset(&data[hdr+1], 0, 4); data[hdr+7] = 0; put2byte(&data[hdr+5], pBt->usableSize); | | | 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 | memset(&data[hdr], 0, pBt->usableSize - hdr); } data[hdr] = (char)flags; first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0); memset(&data[hdr+1], 0, 4); data[hdr+7] = 0; put2byte(&data[hdr+5], pBt->usableSize); pPage->nFree = (u16)(pBt->usableSize - first); decodeFlags(pPage, flags); pPage->hdrOffset = hdr; pPage->cellOffset = first; pPage->nOverflow = 0; assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); pPage->maskPage = (u16)(pBt->pageSize - 1); pPage->nCell = 0; |
︙ | ︙ | |||
2322 2323 2324 2325 2326 2327 2328 | || pageSize>SQLITE_MAX_PAGE_SIZE || pageSize<=256 ){ goto page1_init_failed; } assert( (pageSize & 7)==0 ); usableSize = pageSize - page1[20]; | | | 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 | || pageSize>SQLITE_MAX_PAGE_SIZE || pageSize<=256 ){ goto page1_init_failed; } assert( (pageSize & 7)==0 ); usableSize = pageSize - page1[20]; if( (u32)pageSize!=pBt->pageSize ){ /* After reading the first page of the database assuming a page size ** of BtShared.pageSize, we have discovered that the page-size is ** actually pageSize. Unlock the database, leave pBt->pPage1 at ** zero and return SQLITE_OK. The caller will call this function ** again with the correct page-size. */ releasePage(pPage1); |
︙ | ︙ | |||
2361 2362 2363 2364 2365 2366 2367 | ** cells can will fit on one page. We assume a 10-byte page header. ** Besides the payload, the cell must store: ** 2-byte pointer to the cell ** 4-byte child pointer ** 9-byte nKey value ** 4-byte nData value ** 4-byte overflow page pointer | | | | | | | 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 | ** cells can will fit on one page. We assume a 10-byte page header. ** Besides the payload, the cell must store: ** 2-byte pointer to the cell ** 4-byte child pointer ** 9-byte nKey value ** 4-byte nData value ** 4-byte overflow page pointer ** So a cell consists of a 2-byte pointer, a header which is as much as ** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow ** page pointer. */ pBt->maxLocal = (u16)((pBt->usableSize-12)*64/255 - 23); pBt->minLocal = (u16)((pBt->usableSize-12)*32/255 - 23); pBt->maxLeaf = (u16)(pBt->usableSize - 35); pBt->minLeaf = (u16)((pBt->usableSize-12)*32/255 - 23); assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) ); pBt->pPage1 = pPage1; pBt->nPage = nPage; return SQLITE_OK; page1_init_failed: releasePage(pPage1); |
︙ | ︙ | |||
2421 2422 2423 2424 2425 2426 2427 | pP1 = pBt->pPage1; assert( pP1!=0 ); data = pP1->aData; rc = sqlite3PagerWrite(pP1->pDbPage); if( rc ) return rc; memcpy(data, zMagicHeader, sizeof(zMagicHeader)); assert( sizeof(zMagicHeader)==16 ); | | | | 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 | pP1 = pBt->pPage1; assert( pP1!=0 ); data = pP1->aData; rc = sqlite3PagerWrite(pP1->pDbPage); if( rc ) return rc; memcpy(data, zMagicHeader, sizeof(zMagicHeader)); assert( sizeof(zMagicHeader)==16 ); data[16] = (u8)((pBt->pageSize>>8)&0xff); data[17] = (u8)((pBt->pageSize>>16)&0xff); data[18] = 1; data[19] = 1; assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize); data[20] = (u8)(pBt->pageSize - pBt->usableSize); data[21] = 64; data[22] = 32; data[23] = 32; |
︙ | ︙ | |||
4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 | if( rc ){ goto end_allocate_page; } if( k==0 ){ if( !pPrevTrunk ){ memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); }else{ memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4); } }else{ /* The trunk page is required by the caller but it contains ** pointers to free-list leaves. The first leaf becomes a trunk ** page in this case. */ | > > > > | 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 | if( rc ){ goto end_allocate_page; } if( k==0 ){ if( !pPrevTrunk ){ memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); }else{ rc = sqlite3PagerWrite(pPrevTrunk->pDbPage); if( rc!=SQLITE_OK ){ goto end_allocate_page; } memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4); } }else{ /* The trunk page is required by the caller but it contains ** pointers to free-list leaves. The first leaf becomes a trunk ** page in this case. */ |
︙ | ︙ | |||
5104 5105 5106 5107 5108 5109 5110 | */ static int clearCell(MemPage *pPage, unsigned char *pCell){ BtShared *pBt = pPage->pBt; CellInfo info; Pgno ovflPgno; int rc; int nOvfl; | | | 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 | */ static int clearCell(MemPage *pPage, unsigned char *pCell){ BtShared *pBt = pPage->pBt; CellInfo info; Pgno ovflPgno; int rc; int nOvfl; u32 ovflPageSize; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); btreeParseCellPtr(pPage, pCell, &info); if( info.iOverflow==0 ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ } ovflPgno = get4byte(&pCell[info.iOverflow]); |
︙ | ︙ | |||
5556 5557 5558 5559 5560 5561 5562 | Pgno pgnoNew; /* Page number of pNew */ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); assert( pPage->nOverflow==1 ); /* This error condition is now caught prior to reaching this function */ | | | 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 | Pgno pgnoNew; /* Page number of pNew */ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); assert( pPage->nOverflow==1 ); /* This error condition is now caught prior to reaching this function */ if( pPage->nCell<=0 ) return SQLITE_CORRUPT_BKPT; /* Allocate a new page. This page will become the right-sibling of ** pPage. Make the parent page writable, so that the new divider cell ** may be inserted. If both these operations are successful, proceed. */ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); |
︙ | ︙ | |||
5964 5965 5966 5967 5968 5969 5970 | if( i<nOld-1 && !leafData){ u16 sz = (u16)szNew[i]; u8 *pTemp; assert( nCell<nMaxCells ); szCell[nCell] = sz; pTemp = &aSpace1[iSpace1]; iSpace1 += sz; | | | 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 | if( i<nOld-1 && !leafData){ u16 sz = (u16)szNew[i]; u8 *pTemp; assert( nCell<nMaxCells ); szCell[nCell] = sz; pTemp = &aSpace1[iSpace1]; iSpace1 += sz; assert( sz<=pBt->maxLocal+23 ); assert( iSpace1<=pBt->pageSize ); memcpy(pTemp, apDiv[i], sz); apCell[nCell] = pTemp+leafCorrection; assert( leafCorrection==0 || leafCorrection==4 ); szCell[nCell] = szCell[nCell] - leafCorrection; if( !pOld->leaf ){ assert( leafCorrection==0 ); |
︙ | ︙ | |||
6210 6211 6212 6213 6214 6215 6216 | */ if( szCell[j]==4 ){ assert(leafCorrection==4); sz = cellSizePtr(pParent, pCell); } } iOvflSpace += sz; | | | 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 | */ if( szCell[j]==4 ){ assert(leafCorrection==4); sz = cellSizePtr(pParent, pCell); } } iOvflSpace += sz; assert( sz<=pBt->maxLocal+23 ); assert( iOvflSpace<=pBt->pageSize ); insertCell(pParent, nxDiv, pCell, sz, pTemp, pNew->pgno, &rc); if( rc!=SQLITE_OK ) goto balance_cleanup; assert( sqlite3PagerIswriteable(pParent->pDbPage) ); j++; nxDiv++; |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
562 563 564 565 566 567 568 | testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); } if( i>pParse->nVar ){ | | | 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 | testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); } if( i>pParse->nVar ){ pParse->nVar = (int)i; } }else{ /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable ** number as the prior appearance of the same name, or if the name ** has never appeared before, reuse the same variable number */ int i; |
︙ | ︙ |
Changes to src/mem2.c.
︙ | ︙ | |||
374 375 376 377 378 379 380 | sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); } /* ** Set the "type" of an allocation. */ void sqlite3MemdebugSetType(void *p, u8 eType){ | | | | 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); } /* ** Set the "type" of an allocation. */ void sqlite3MemdebugSetType(void *p, u8 eType){ if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){ struct MemBlockHdr *pHdr; pHdr = sqlite3MemsysGetHeader(p); assert( pHdr->iForeGuard==FOREGUARD ); pHdr->eType = eType; } } /* ** Return TRUE if the mask of type in eType matches the type of the ** allocation p. Also return true if p==NULL. ** ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** ** assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); */ int sqlite3MemdebugHasType(void *p, u8 eType){ int rc = 1; if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){ struct MemBlockHdr *pHdr; pHdr = sqlite3MemsysGetHeader(p); assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ if( (pHdr->eType&eType)==0 ){ rc = 0; } } |
︙ | ︙ | |||
415 416 417 418 419 420 421 | ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** ** assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) ); */ int sqlite3MemdebugNoType(void *p, u8 eType){ int rc = 1; | | | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 | ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** ** assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) ); */ int sqlite3MemdebugNoType(void *p, u8 eType){ int rc = 1; if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){ struct MemBlockHdr *pHdr; pHdr = sqlite3MemsysGetHeader(p); assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ if( (pHdr->eType&eType)!=0 ){ rc = 0; } } |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
1053 1054 1055 1056 1057 1058 1059 | assert( !pPager->exclusiveMode ); assert( eLock==NO_LOCK || eLock==SHARED_LOCK ); assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 ); if( isOpen(pPager->fd) ){ assert( pPager->eLock>=eLock ); rc = sqlite3OsUnlock(pPager->fd, eLock); if( pPager->eLock!=UNKNOWN_LOCK ){ | | | 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 | assert( !pPager->exclusiveMode ); assert( eLock==NO_LOCK || eLock==SHARED_LOCK ); assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 ); if( isOpen(pPager->fd) ){ assert( pPager->eLock>=eLock ); rc = sqlite3OsUnlock(pPager->fd, eLock); if( pPager->eLock!=UNKNOWN_LOCK ){ pPager->eLock = (u8)eLock; } IOTRACE(("UNLOCK %p %d\n", pPager, eLock)) } return rc; } /* |
︙ | ︙ | |||
1077 1078 1079 1080 1081 1082 1083 | static int pagerLockDb(Pager *pPager, int eLock){ int rc = SQLITE_OK; assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK ); if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){ rc = sqlite3OsLock(pPager->fd, eLock); if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){ | | | 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 | static int pagerLockDb(Pager *pPager, int eLock){ int rc = SQLITE_OK; assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK ); if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){ rc = sqlite3OsLock(pPager->fd, eLock); if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){ pPager->eLock = (u8)eLock; IOTRACE(("LOCK %p %d\n", pPager, eLock)) } } return rc; } /* |
︙ | ︙ | |||
1157 1158 1159 1160 1161 1162 1163 | ** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES ** is defined, and NDEBUG is not defined, an assert() statement checks ** that the page is either dirty or still matches the calculated page-hash. */ #define CHECK_PAGE(x) checkPage(x) static void checkPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; | | | > | 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 | ** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES ** is defined, and NDEBUG is not defined, an assert() statement checks ** that the page is either dirty or still matches the calculated page-hash. */ #define CHECK_PAGE(x) checkPage(x) static void checkPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; assert( pPager->eState!=PAGER_ERROR ); assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) ); } #else #define pager_datahash(X,Y) 0 #define pager_pagehash(X) 0 #define pager_set_pagehash(X) #define CHECK_PAGE(x) #endif /* SQLITE_CHECK_PAGES */ /* ** When this is called the journal file for pager pPager must be open. ** This function attempts to read a master journal file name from the ** end of the file and, if successful, copies it into memory supplied |
︙ | ︙ | |||
1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 | /* Read the page-size and sector-size journal header fields. */ if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize)) || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize)) ){ return rc; } /* Check that the values read from the page-size and sector-size fields ** are within range. To be 'in range', both values need to be a power ** of two greater than or equal to 512 or 32, and not greater than their ** respective compile time maximum limits. */ if( iPageSize<512 || iSectorSize<32 | > > > > > > > > | 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 | /* Read the page-size and sector-size journal header fields. */ if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize)) || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize)) ){ return rc; } /* Versions of SQLite prior to 3.5.8 set the page-size field of the ** journal header to zero. In this case, assume that the Pager.pageSize ** variable is already set to the correct page size. */ if( iPageSize==0 ){ iPageSize = pPager->pageSize; } /* Check that the values read from the page-size and sector-size fields ** are within range. To be 'in range', both values need to be a power ** of two greater than or equal to 512 or 32, and not greater than their ** respective compile time maximum limits. */ if( iPageSize<512 || iSectorSize<32 |
︙ | ︙ | |||
1925 1926 1927 1928 1929 1930 1931 | || pPager->journalMode==PAGER_JOURNALMODE_WAL ); sqlite3OsClose(pPager->jfd); if( !pPager->tempFile ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); } } | | > | > > > > > > > | | 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 | || pPager->journalMode==PAGER_JOURNALMODE_WAL ); sqlite3OsClose(pPager->jfd); if( !pPager->tempFile ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); } } } #ifdef SQLITE_CHECK_PAGES sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){ PgHdr *p = pager_lookup(pPager, 1); if( p ){ p->pageHash = 0; sqlite3PagerUnref(p); } } #endif sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; pPager->nRec = 0; sqlite3PcacheCleanAll(pPager->pPCache); sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); if( pagerUseWal(pPager) ){ |
︙ | ︙ | |||
2276 2277 2278 2279 2280 2281 2282 | ** be written out into the database file before its journal file ** segment is synced. If a crash occurs during or following this, ** database corruption may ensue. */ assert( !pagerUseWal(pPager) ); sqlite3PcacheMakeClean(pPg); } | < | | | 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 | ** be written out into the database file before its journal file ** segment is synced. If a crash occurs during or following this, ** database corruption may ensue. */ assert( !pagerUseWal(pPager) ); sqlite3PcacheMakeClean(pPg); } pager_set_pagehash(pPg); /* If this was page 1, then restore the value of Pager.dbFileVers. ** Do this before any decoding. */ if( pgno==1 ){ memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers)); } /* Decode the page just read from disk */ |
︙ | ︙ | |||
2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 | ); if( rc==SQLITE_OK && pPager->pBackup ){ PgHdr *p; for(p=pList; p; p=p->pDirty){ sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); } } return rc; } /* ** Begin a read transaction on the WAL. ** ** This routine used to be called "pagerOpenSnapshot()" because it essentially | > > > > > > > > | 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 | ); if( rc==SQLITE_OK && pPager->pBackup ){ PgHdr *p; for(p=pList; p; p=p->pDirty){ sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); } } #ifdef SQLITE_CHECK_PAGES { PgHdr *p; for(p=pList; p; p=p->pDirty) pager_set_pagehash(p); } #endif return rc; } /* ** Begin a read transaction on the WAL. ** ** This routine used to be called "pagerOpenSnapshot()" because it essentially |
︙ | ︙ | |||
3362 3363 3364 3365 3366 3367 3368 | u32 pageSize = *pPageSize; assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); if( (pPager->memDb==0 || pPager->dbSize==0) && sqlite3PcacheRefCount(pPager->pPCache)==0 && pageSize && pageSize!=(u32)pPager->pageSize ){ | | | | 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 | u32 pageSize = *pPageSize; assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); if( (pPager->memDb==0 || pPager->dbSize==0) && sqlite3PcacheRefCount(pPager->pPCache)==0 && pageSize && pageSize!=(u32)pPager->pageSize ){ char *pNew = NULL; /* New temp space */ i64 nByte = 0; if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){ rc = sqlite3OsFileSize(pPager->fd, &nByte); } if( rc==SQLITE_OK ){ pNew = (char *)sqlite3PageMalloc(pageSize); if( !pNew ) rc = SQLITE_NOMEM; } if( rc==SQLITE_OK ){ pager_reset(pPager); pPager->dbSize = (Pgno)(nByte/pageSize); pPager->pageSize = pageSize; sqlite3PageFree(pPager->pTmpSpace); pPager->pTmpSpace = pNew; sqlite3PcacheSetPageSize(pPager->pPCache, pageSize); } } |
︙ | ︙ | |||
3948 3949 3950 3951 3952 3953 3954 | PAGERID(pPager), pgno, pager_pagehash(pList))); IOTRACE(("PGOUT %p %d\n", pPager, pgno)); PAGER_INCR(sqlite3_pager_writedb_count); PAGER_INCR(pPager->nWrite); }else{ PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno)); } | < | < | 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 | PAGERID(pPager), pgno, pager_pagehash(pList))); IOTRACE(("PGOUT %p %d\n", pPager, pgno)); PAGER_INCR(sqlite3_pager_writedb_count); PAGER_INCR(pPager->nWrite); }else{ PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno)); } pager_set_pagehash(pList); pList = pList->pDirty; } return rc; } /* |
︙ | ︙ | |||
4139 4140 4141 4142 4143 4144 4145 | /* Mark the page as clean. */ if( rc==SQLITE_OK ){ PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno)); sqlite3PcacheMakeClean(pPg); } | | | 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 | /* Mark the page as clean. */ if( rc==SQLITE_OK ){ PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno)); sqlite3PcacheMakeClean(pPg); } return pager_error(pPager, rc); } /* ** Allocate and initialize a new Pager object and put a pointer to it ** in *ppPager. The pager should eventually be freed by passing it ** to sqlite3PagerClose(). |
︙ | ︙ | |||
4938 4939 4940 4941 4942 4943 4944 | }else{ assert( pPg->pPager==pPager ); rc = readDbPage(pPg); if( rc!=SQLITE_OK ){ goto pager_acquire_err; } } | < | < | 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 | }else{ assert( pPg->pPager==pPager ); rc = readDbPage(pPg); if( rc!=SQLITE_OK ){ goto pager_acquire_err; } } pager_set_pagehash(pPg); } return SQLITE_OK; pager_acquire_err: assert( rc!=SQLITE_OK ); if( pPg ){ |
︙ | ︙ | |||
5438 5439 5440 5441 5442 5443 5444 | */ void sqlite3PagerDontWrite(PgHdr *pPg){ Pager *pPager = pPg->pPager; if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){ PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager))); IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) pPg->flags |= PGHDR_DONT_WRITE; | < | < | 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 | */ void sqlite3PagerDontWrite(PgHdr *pPg){ Pager *pPager = pPg->pPager; if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){ PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager))); IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) pPg->flags |= PGHDR_DONT_WRITE; pager_set_pagehash(pPg); } } /* ** This routine is called to increment the value of the database file ** change-counter, stored as a 4-byte big-endian integer starting at ** byte offset 24 of the pager file. |
︙ | ︙ |
Changes to src/pcache1.c.
︙ | ︙ | |||
196 197 198 199 200 201 202 203 204 205 206 207 208 209 | sqlite3MemdebugSetType(p, MEMTYPE_HEAP); iSize = sqlite3MallocSize(p); sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize); sqlite3_free(p); } } /* ** Allocate a new page object initially associated with cache pCache. */ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){ int nByte = sizeof(PgHdr1) + pCache->szPage; void *pPg = pcache1Alloc(nByte); PgHdr1 *p; | > > > > > > > > > > > > > > > > > > > | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | sqlite3MemdebugSetType(p, MEMTYPE_HEAP); iSize = sqlite3MallocSize(p); sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize); sqlite3_free(p); } } #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* ** Return the size of a pache allocation */ static int pcache1MemSize(void *p){ assert( sqlite3_mutex_held(pcache1.mutex) ); if( p>=pcache1.pStart && p<pcache1.pEnd ){ return pcache1.szSlot; }else{ int iSize; assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); iSize = sqlite3MallocSize(p); sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); return iSize; } } #endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ /* ** Allocate a new page object initially associated with cache pCache. */ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){ int nByte = sizeof(PgHdr1) + pCache->szPage; void *pPg = pcache1Alloc(nByte); PgHdr1 *p; |
︙ | ︙ | |||
744 745 746 747 748 749 750 | */ int sqlite3PcacheReleaseMemory(int nReq){ int nFree = 0; if( pcache1.pStart==0 ){ PgHdr1 *p; pcache1EnterMutex(); while( (nReq<0 || nFree<nReq) && (p=pcache1.pLruTail) ){ | | | 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 | */ int sqlite3PcacheReleaseMemory(int nReq){ int nFree = 0; if( pcache1.pStart==0 ){ PgHdr1 *p; pcache1EnterMutex(); while( (nReq<0 || nFree<nReq) && (p=pcache1.pLruTail) ){ nFree += pcache1MemSize(PGHDR1_TO_PAGE(p)); pcache1PinPage(p); pcache1RemoveFromHash(p); pcache1FreePage(p); } pcache1LeaveMutex(); } return nFree; |
︙ | ︙ |
Changes to src/sqliteLimit.h.
︙ | ︙ | |||
132 133 134 135 136 137 138 | #ifndef SQLITE_MAX_VARIABLE_NUMBER # define SQLITE_MAX_VARIABLE_NUMBER 999 #endif /* Maximum page size. The upper bound on this value is 65536. This a limit ** imposed by the use of 16-bit offsets within each page. ** | > > | | | | | < | | > | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | #ifndef SQLITE_MAX_VARIABLE_NUMBER # define SQLITE_MAX_VARIABLE_NUMBER 999 #endif /* Maximum page size. The upper bound on this value is 65536. This a limit ** imposed by the use of 16-bit offsets within each page. ** ** Earlier versions of SQLite allowed the user to change this value at ** compile time. This is no longer permitted, on the grounds that it creates ** a library that is technically incompatible with an SQLite library ** compiled with a different limit. If a process operating on a database ** with a page-size of 65536 bytes crashes, then an instance of SQLite ** compiled with the default page-size limit will not be able to rollback ** the aborted transaction. This could lead to database corruption. */ #ifdef SQLITE_MAX_PAGE_SIZE # undef SQLITE_MAX_PAGE_SIZE #endif #define SQLITE_MAX_PAGE_SIZE 65536 /* ** The default size of a database page. */ #ifndef SQLITE_DEFAULT_PAGE_SIZE # define SQLITE_DEFAULT_PAGE_SIZE 1024 |
︙ | ︙ |
Changes to src/tclsqlite.c.
︙ | ︙ | |||
3011 3012 3013 3014 3015 3016 3017 | ** ** This Tcl module contains only a single new Tcl command named "sqlite". ** (Hence there is no namespace. There is no point in using a namespace ** if the extension only supplies one new name!) The "sqlite" command is ** used to open a new SQLite database. See the DbMain() routine above ** for additional information. */ | | | | | | | | | | | | | | | | | | 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 | ** ** This Tcl module contains only a single new Tcl command named "sqlite". ** (Hence there is no namespace. There is no point in using a namespace ** if the extension only supplies one new name!) The "sqlite" command is ** used to open a new SQLite database. See the DbMain() routine above ** for additional information. */ int Sqlite3_Init(Tcl_Interp *interp){ Tcl_InitStubs(interp, "8.4", 0); Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0); Tcl_PkgProvide(interp, "sqlite3", PACKAGE_VERSION); Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0); Tcl_PkgProvide(interp, "sqlite", PACKAGE_VERSION); return TCL_OK; } int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; } int Tclsqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; } int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK; } int Tclsqlite3_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK;} #ifndef SQLITE_3_SUFFIX_ONLY int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; } int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; } int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } int Sqlite_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK; } int Tclsqlite_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK;} #endif #ifdef TCLSH /***************************************************************************** ** All of the code that follows is used to build standalone TCL interpreters ** that are statically linked with SQLite. Enable these by compiling ** with -DTCLSH=n where n can be 1 or 2. An n of 1 generates a standard |
︙ | ︙ |
Changes to src/wal.c.
︙ | ︙ | |||
1131 1132 1133 1134 1135 1136 1137 | rc = walIndexAppend(pWal, ++iFrame, pgno); if( rc!=SQLITE_OK ) break; /* If nTruncate is non-zero, this is a commit record. */ if( nTruncate ){ pWal->hdr.mxFrame = iFrame; pWal->hdr.nPage = nTruncate; | | | 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 | rc = walIndexAppend(pWal, ++iFrame, pgno); if( rc!=SQLITE_OK ) break; /* If nTruncate is non-zero, this is a commit record. */ if( nTruncate ){ pWal->hdr.mxFrame = iFrame; pWal->hdr.nPage = nTruncate; pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); testcase( szPage<=32768 ); testcase( szPage>=65536 ); aFrameCksum[0] = pWal->hdr.aFrameCksum[0]; aFrameCksum[1] = pWal->hdr.aFrameCksum[1]; } } |
︙ | ︙ | |||
2558 2559 2560 2561 2562 2563 2564 | iFrame++; nLast--; rc = walIndexAppend(pWal, iFrame, pLast->pgno); } if( rc==SQLITE_OK ){ /* Update the private copy of the header. */ | | | 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 | iFrame++; nLast--; rc = walIndexAppend(pWal, iFrame, pLast->pgno); } if( rc==SQLITE_OK ){ /* Update the private copy of the header. */ pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); testcase( szPage<=32768 ); testcase( szPage>=65536 ); pWal->hdr.mxFrame = iFrame; if( isCommit ){ pWal->hdr.iChange++; pWal->hdr.nPage = nTruncate; } |
︙ | ︙ |
Added test/backcompat.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | # 2010 August 19 # # 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 file is testing that the current version of SQLite # is capable of reading and writing databases created by previous # versions, and vice-versa. # # To use this test, old versions of the testfixture process should be # copied into the working directory alongside the new version. The old # versions should be named "testfixtureXXX" (or testfixtureXXX.exe on # windows), where XXX can be any string. # # This test file uses the tcl code for controlling a second testfixture # process located in lock_common.tcl. See the commments in lock_common.tcl # for documentation of the available commands. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/malloc_common.tcl db close # Search for binaries to test against. Any executable files that match # our naming convention are assumed to be testfixture binaries to test # against. # set binaries [list] set pattern "[file tail [info nameofexec]]?*" if {$tcl_platform(platform)=="windows"} { set pattern [string map {\.exe {}} $pattern] } foreach file [glob -nocomplain $pattern] { if {[file executable $file]} {lappend binaries $file} } if {[llength $binaries]==0} { puts "WARNING: No historical binaries to test against." puts "WARNING: No backwards-compatibility tests have been run." finish_test return } proc get_version {binary} { set chan [launch_testfixture $binary] set v [testfixture $chan { sqlite3 -version }] close $chan set v } foreach bin $binaries { puts -nonewline "Testing against $bin - " flush stdout puts "version [get_version $bin]" } proc do_backcompat_test {rv bin1 bin2 script} { file delete -force test.db if {$bin1 != ""} { set ::bc_chan1 [launch_testfixture $bin1] } set ::bc_chan2 [launch_testfixture $bin2] if { $rv } { proc code2 {tcl} { uplevel #0 $tcl } if {$bin1 != ""} { proc code2 {tcl} { testfixture $::bc_chan1 $tcl } } proc code1 {tcl} { testfixture $::bc_chan2 $tcl } } else { proc code1 {tcl} { uplevel #0 $tcl } if {$bin1 != ""} { proc code1 {tcl} { testfixture $::bc_chan1 $tcl } } proc code2 {tcl} { testfixture $::bc_chan2 $tcl } } proc sql1 sql { code1 [list db eval $sql] } proc sql2 sql { code2 [list db eval $sql] } code1 { sqlite3 db test.db } code2 { sqlite3 db test.db } uplevel $script catch { code1 { db close } } catch { code2 { db close } } catch { close $::bc_chan2 } catch { close $::bc_chan1 } } array set ::incompatible [list] proc do_allbackcompat_test {script} { foreach bin $::binaries { set nErr [set_test_counter errors] foreach dir {0 1} { set bintag [string map {testfixture {}} $bin] set bintag [string map {\.exe {}} $bintag] if {$bintag == ""} {set bintag self} set ::bcname ".$bintag.$dir." rename do_test _do_test proc do_test {nm sql res} { set nm [regsub {\.} $nm $::bcname] uplevel [list _do_test $nm $sql $res] } do_backcompat_test $dir {} $bin $script rename do_test {} rename _do_test do_test } if { $nErr < [set_test_counter errors] } { set ::incompatible([get_version $bin]) 1 } } } proc read_file {zFile} { set zData {} if {[file exists $zFile]} { set fd [open $zFile] fconfigure $fd -translation binary -encoding binary if {[file size $zFile]<=$::sqlite_pending_byte || $zFile != "test.db"} { set zData [read $fd] } else { set zData [read $fd $::sqlite_pending_byte] append zData [string repeat x 512] seek $fd [expr $::sqlite_pending_byte+512] start append zData [read $fd] } close $fd } return $zData } proc write_file {zFile zData} { set fd [open $zFile w] fconfigure $fd -translation binary -encoding binary puts -nonewline $fd $zData close $fd } proc read_file_system {} { set ret [list] foreach f {test.db test.db-journal test.db-wal} { lappend ret [read_file $f] } set ret } proc write_file_system {data} { foreach f {test.db test.db-journal test.db-wal} d $data { if {[string length $d] == 0} { file delete -force $f } else { write_file $f $d } } } #------------------------------------------------------------------------- # Actual tests begin here. # # This first block of tests checks to see that the same database and # journal files can be used by old and new versions. WAL and wal-index # files are tested separately below. # do_allbackcompat_test { # Test that database files are backwards compatible. # do_test backcompat-1.1.1 { sql1 { CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); INSERT INTO t1 VALUES('abc', 'def'); } } {} do_test backcompat-1.1.2 { sql2 { SELECT * FROM t1; } } {abc def} do_test backcompat-1.1.3 { sql2 { INSERT INTO t1 VALUES('ghi', 'jkl'); } } {} do_test backcompat-1.1.4 { sql1 { SELECT * FROM t1; } } {abc def ghi jkl} do_test backcompat-1.1.5 { sql1 { PRAGMA integrity_check } } {ok} do_test backcompat-1.1.6 { sql2 { PRAGMA integrity_check } } {ok} # Test that one version can roll back a hot-journal file left in the # file-system by the other version. # # Each test case is named "backcompat-1.X...", where X is either 0 or # 1. If it is 0, then the current version creates a journal file that # the old versions try to read. Otherwise, if X is 1, then the old version # creates the journal file and we try to read it with the current version. # do_test backcompat-1.2.1 { sql1 { PRAGMA cache_size = 10; BEGIN; INSERT INTO t1 VALUES(randomblob(400), randomblob(400)); INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1; INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1; INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1; INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1; COMMIT; } } {} set cksum1 [sql1 {SELECT md5sum(a), md5sum(b) FROM t1}] set cksum2 [sql2 {SELECT md5sum(a), md5sum(b) FROM t1}] do_test backcompat-1.2.2 [list string compare $cksum1 $cksum2] 0 do_test backcompat-1.2.3 { sql1 { BEGIN; UPDATE t1 SET a = randomblob(500); } } {} set data [read_file_system] do_test backcompat-1.2.4 { sql1 { COMMIT } } {} set same [expr {[sql2 {SELECT md5sum(a), md5sum(b) FROM t1}] == $cksum2}] do_test backcompat-1.2.5 [list set {} $same] 0 code1 { db close } code2 { db close } write_file_system $data code1 { sqlite3 db test.db } code2 { sqlite3 db test.db } set same [expr {[sql2 {SELECT md5sum(a), md5sum(b) FROM t1}] == $cksum2}] do_test backcompat-1.2.6 [list set {} $same] 1 do_test backcompat-1.2.7 { sql1 { PRAGMA integrity_check } } {ok} do_test backcompat-1.2.8 { sql2 { PRAGMA integrity_check } } {ok} } foreach k [lsort [array names ::incompatible]] { puts "ERROR: Detected journal incompatibility with version $k" } unset ::incompatible #------------------------------------------------------------------------- # Test that WAL and wal-index files may be shared between different # SQLite versions. # do_allbackcompat_test { if {[code1 {sqlite3 -version}] >= "3.7.0" && [code2 {sqlite3 -version}] >= "3.7.0" } { do_test backcompat-2.1.1 { sql1 { PRAGMA journal_mode = WAL; CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); INSERT INTO t1 VALUES('I', 1); INSERT INTO t1 VALUES('II', 2); INSERT INTO t1 VALUES('III', 3); SELECT * FROM t1; } } {wal I 1 II 2 III 3} do_test backcompat-2.1.2 { sql2 { SELECT * FROM t1; } } {I 1 II 2 III 3} set data [read_file_system] code1 {db close} code2 {db close} write_file_system $data code1 {sqlite3 db test.db} code2 {sqlite3 db test.db} # The WAL file now in the file-system was created by the [code1] # process. Check that the [code2] process can recover the log. # do_test backcompat-2.1.3 { sql2 { SELECT * FROM t1; } } {I 1 II 2 III 3} do_test backcompat-2.1.4 { sql1 { SELECT * FROM t1; } } {I 1 II 2 III 3} } } finish_test |
Changes to test/e_expr.test.
︙ | ︙ | |||
858 859 860 861 862 863 864 | do_execsql_test e_expr-13.2.7 { SELECT 5 BETWEEN 0 AND 0 != 1 } 1 do_execsql_test e_expr-13.2.8 { SELECT (5 BETWEEN 0 AND 0) != 1 } 1 do_execsql_test e_expr-13.2.9 { SELECT 5 BETWEEN 0 AND (0 != 1) } 0 do_execsql_test e_expr-13.2.10 { SELECT 1 != 0 BETWEEN 0 AND 2 } 1 do_execsql_test e_expr-13.2.11 { SELECT (1 != 0) BETWEEN 0 AND 2 } 1 do_execsql_test e_expr-13.2.12 { SELECT 1 != (0 BETWEEN 0 AND 2) } 0 | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | | | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > | 858 859 860 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 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 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 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 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 1103 1104 1105 1106 | do_execsql_test e_expr-13.2.7 { SELECT 5 BETWEEN 0 AND 0 != 1 } 1 do_execsql_test e_expr-13.2.8 { SELECT (5 BETWEEN 0 AND 0) != 1 } 1 do_execsql_test e_expr-13.2.9 { SELECT 5 BETWEEN 0 AND (0 != 1) } 0 do_execsql_test e_expr-13.2.10 { SELECT 1 != 0 BETWEEN 0 AND 2 } 1 do_execsql_test e_expr-13.2.11 { SELECT (1 != 0) BETWEEN 0 AND 2 } 1 do_execsql_test e_expr-13.2.12 { SELECT 1 != (0 BETWEEN 0 AND 2) } 0 do_execsql_test e_expr-13.2.13 { SELECT 1 LIKE 10 BETWEEN 0 AND 2 } 1 do_execsql_test e_expr-13.2.14 { SELECT (1 LIKE 10) BETWEEN 0 AND 2 } 1 do_execsql_test e_expr-13.2.15 { SELECT 1 LIKE (10 BETWEEN 0 AND 2) } 0 do_execsql_test e_expr-13.2.16 { SELECT 6 BETWEEN 4 AND 8 LIKE 1 } 1 do_execsql_test e_expr-13.2.17 { SELECT (6 BETWEEN 4 AND 8) LIKE 1 } 1 do_execsql_test e_expr-13.2.18 { SELECT 6 BETWEEN 4 AND (8 LIKE 1) } 0 do_execsql_test e_expr-13.2.19 { SELECT 0 AND 0 BETWEEN 0 AND 1 } 0 do_execsql_test e_expr-13.2.20 { SELECT 0 AND (0 BETWEEN 0 AND 1) } 0 do_execsql_test e_expr-13.2.21 { SELECT (0 AND 0) BETWEEN 0 AND 1 } 1 do_execsql_test e_expr-13.2.22 { SELECT 0 BETWEEN -1 AND 1 AND 0 } 0 do_execsql_test e_expr-13.2.23 { SELECT (0 BETWEEN -1 AND 1) AND 0 } 0 do_execsql_test e_expr-13.2.24 { SELECT 0 BETWEEN -1 AND (1 AND 0) } 1 do_execsql_test e_expr-13.2.25 { SELECT 2 < 3 BETWEEN 0 AND 1 } 1 do_execsql_test e_expr-13.2.26 { SELECT (2 < 3) BETWEEN 0 AND 1 } 1 do_execsql_test e_expr-13.2.27 { SELECT 2 < (3 BETWEEN 0 AND 1) } 0 do_execsql_test e_expr-13.2.28 { SELECT 2 BETWEEN 1 AND 2 < 3 } 0 do_execsql_test e_expr-13.2.29 { SELECT 2 BETWEEN 1 AND (2 < 3) } 0 do_execsql_test e_expr-13.2.30 { SELECT (2 BETWEEN 1 AND 2) < 3 } 1 #------------------------------------------------------------------------- # Test the statements related to the LIKE and GLOB operators. # # EVIDENCE-OF: R-16584-60189 The LIKE operator does a pattern matching # comparison. # # EVIDENCE-OF: R-11295-04657 The operand to the right of the LIKE # operator contains the pattern and the left hand operand contains the # string to match against the pattern. # do_execsql_test e_expr-14.1.1 { SELECT 'abc%' LIKE 'abcde' } 0 do_execsql_test e_expr-14.1.2 { SELECT 'abcde' LIKE 'abc%' } 1 # EVIDENCE-OF: R-55406-38524 A percent symbol ("%") in the LIKE pattern # matches any sequence of zero or more characters in the string. # do_execsql_test e_expr-14.2.1 { SELECT 'abde' LIKE 'ab%de' } 1 do_execsql_test e_expr-14.2.2 { SELECT 'abXde' LIKE 'ab%de' } 1 do_execsql_test e_expr-14.2.3 { SELECT 'abABCde' LIKE 'ab%de' } 1 # EVIDENCE-OF: R-30433-25443 An underscore ("_") in the LIKE pattern # matches any single character in the string. # do_execsql_test e_expr-14.3.1 { SELECT 'abde' LIKE 'ab_de' } 0 do_execsql_test e_expr-14.3.2 { SELECT 'abXde' LIKE 'ab_de' } 1 do_execsql_test e_expr-14.3.3 { SELECT 'abABCde' LIKE 'ab_de' } 0 # EVIDENCE-OF: R-59007-20454 Any other character matches itself or its # lower/upper case equivalent (i.e. case-insensitive matching). # do_execsql_test e_expr-14.4.1 { SELECT 'abc' LIKE 'aBc' } 1 do_execsql_test e_expr-14.4.2 { SELECT 'aBc' LIKE 'aBc' } 1 do_execsql_test e_expr-14.4.3 { SELECT 'ac' LIKE 'aBc' } 0 # EVIDENCE-OF: R-23648-58527 SQLite only understands upper/lower case # for ASCII characters by default. # # EVIDENCE-OF: R-04532-11527 The LIKE operator is case sensitive by # default for unicode characters that are beyond the ASCII range. # # EVIDENCE-OF: R-44381-11669 the expression # 'a' LIKE 'A' is TRUE but # 'æ' LIKE 'Æ' is FALSE. # do_execsql_test e_expr-14.5.1 { SELECT 'A' LIKE 'a' } 1 do_execsql_test e_expr-14.5.2 "SELECT '\u00c6' LIKE '\u00e6'" 0 # EVIDENCE-OF: R-56683-13731 If the optional ESCAPE clause is present, # then the expression following the ESCAPE keyword must evaluate to a # string consisting of a single character. # do_catchsql_test e_expr-14.6.1 { SELECT 'A' LIKE 'a' ESCAPE '12' } {1 {ESCAPE expression must be a single character}} do_catchsql_test e_expr-14.6.2 { SELECT 'A' LIKE 'a' ESCAPE '' } {1 {ESCAPE expression must be a single character}} do_catchsql_test e_expr-14.6.3 { SELECT 'A' LIKE 'a' ESCAPE 'x' } {0 1} do_catchsql_test e_expr-14.6.4 "SELECT 'A' LIKE 'a' ESCAPE '\u00e6'" {0 1} # EVIDENCE-OF: R-02045-23762 This character may be used in the LIKE # pattern to include literal percent or underscore characters. # # EVIDENCE-OF: R-13345-31830 The escape character followed by a percent # symbol (%), underscore (_), or a second instance of the escape # character itself matches a literal percent symbol, underscore, or a # single escape character, respectively. # do_execsql_test e_expr-14.7.1 { SELECT 'abc%' LIKE 'abcX%' ESCAPE 'X' } 1 do_execsql_test e_expr-14.7.2 { SELECT 'abc5' LIKE 'abcX%' ESCAPE 'X' } 0 do_execsql_test e_expr-14.7.3 { SELECT 'abc' LIKE 'abcX%' ESCAPE 'X' } 0 do_execsql_test e_expr-14.7.4 { SELECT 'abcX%' LIKE 'abcX%' ESCAPE 'X' } 0 do_execsql_test e_expr-14.7.5 { SELECT 'abc%%' LIKE 'abcX%' ESCAPE 'X' } 0 do_execsql_test e_expr-14.7.6 { SELECT 'abc_' LIKE 'abcX_' ESCAPE 'X' } 1 do_execsql_test e_expr-14.7.7 { SELECT 'abc5' LIKE 'abcX_' ESCAPE 'X' } 0 do_execsql_test e_expr-14.7.8 { SELECT 'abc' LIKE 'abcX_' ESCAPE 'X' } 0 do_execsql_test e_expr-14.7.9 { SELECT 'abcX_' LIKE 'abcX_' ESCAPE 'X' } 0 do_execsql_test e_expr-14.7.10 { SELECT 'abc__' LIKE 'abcX_' ESCAPE 'X' } 0 do_execsql_test e_expr-14.7.11 { SELECT 'abcX' LIKE 'abcXX' ESCAPE 'X' } 1 do_execsql_test e_expr-14.7.12 { SELECT 'abc5' LIKE 'abcXX' ESCAPE 'X' } 0 do_execsql_test e_expr-14.7.13 { SELECT 'abc' LIKE 'abcXX' ESCAPE 'X' } 0 do_execsql_test e_expr-14.7.14 { SELECT 'abcXX' LIKE 'abcXX' ESCAPE 'X' } 0 # EVIDENCE-OF: R-51359-17496 The infix LIKE operator is implemented by # calling the application-defined SQL functions like(Y,X) or like(Y,X,Z). # proc likefunc {args} { eval lappend ::likeargs $args return 1 } db func like likefunc set ::likeargs [list] do_execsql_test e_expr-15.1.1 { SELECT 'abc' LIKE 'def' } 1 do_test e_expr-15.1.2 { set likeargs } {def abc} set ::likeargs [list] do_execsql_test e_expr-15.1.3 { SELECT 'abc' LIKE 'def' ESCAPE 'X' } 1 do_test e_expr-15.1.4 { set likeargs } {def abc X} db close sqlite3 db test.db # EVIDENCE-OF: R-22868-25880 The LIKE operator can be made case # sensitive using the case_sensitive_like pragma. # do_execsql_test e_expr-16.1.1 { SELECT 'abcxyz' LIKE 'ABC%' } 1 do_execsql_test e_expr-16.1.2 { PRAGMA case_sensitive_like = 1 } {} do_execsql_test e_expr-16.1.3 { SELECT 'abcxyz' LIKE 'ABC%' } 0 do_execsql_test e_expr-16.1.4 { SELECT 'ABCxyz' LIKE 'ABC%' } 1 do_execsql_test e_expr-16.1.5 { PRAGMA case_sensitive_like = 0 } {} do_execsql_test e_expr-16.1.6 { SELECT 'abcxyz' LIKE 'ABC%' } 1 do_execsql_test e_expr-16.1.7 { SELECT 'ABCxyz' LIKE 'ABC%' } 1 # EVIDENCE-OF: R-52087-12043 The GLOB operator is similar to LIKE but # uses the Unix file globbing syntax for its wildcards. # # EVIDENCE-OF: R-09813-17279 Also, GLOB is case sensitive, unlike LIKE. # do_execsql_test e_expr-17.1.1 { SELECT 'abcxyz' GLOB 'abc%' } 0 do_execsql_test e_expr-17.1.2 { SELECT 'abcxyz' GLOB 'abc*' } 1 do_execsql_test e_expr-17.1.3 { SELECT 'abcxyz' GLOB 'abc___' } 0 do_execsql_test e_expr-17.1.4 { SELECT 'abcxyz' GLOB 'abc???' } 1 do_execsql_test e_expr-17.1.5 { SELECT 'abcxyz' GLOB 'abc*' } 1 do_execsql_test e_expr-17.1.6 { SELECT 'ABCxyz' GLOB 'abc*' } 0 do_execsql_test e_expr-17.1.7 { SELECT 'abcxyz' GLOB 'ABC*' } 0 # EVIDENCE-OF: R-39616-20555 Both GLOB and LIKE may be preceded by the # NOT keyword to invert the sense of the test. # do_execsql_test e_expr-17.2.1 { SELECT 'abcxyz' NOT GLOB 'ABC*' } 1 do_execsql_test e_expr-17.2.2 { SELECT 'abcxyz' NOT GLOB 'abc*' } 0 do_execsql_test e_expr-17.2.3 { SELECT 'abcxyz' NOT LIKE 'ABC%' } 0 do_execsql_test e_expr-17.2.4 { SELECT 'abcxyz' NOT LIKE 'abc%' } 0 do_execsql_test e_expr-17.2.5 { SELECT 'abdxyz' NOT LIKE 'abc%' } 1 db nullvalue null do_execsql_test e_expr-17.2.6 { SELECT 'abcxyz' NOT GLOB NULL } null do_execsql_test e_expr-17.2.7 { SELECT 'abcxyz' NOT LIKE NULL } null do_execsql_test e_expr-17.2.8 { SELECT NULL NOT GLOB 'abc*' } null do_execsql_test e_expr-17.2.9 { SELECT NULL NOT LIKE 'ABC%' } null db nullvalue {} # EVIDENCE-OF: R-39414-35489 The infix GLOB operator is implemented by # calling the function glob(Y,X) and can be modified by overriding that # function. proc globfunc {args} { eval lappend ::globargs $args return 1 } db func glob -argcount 2 globfunc set ::globargs [list] do_execsql_test e_expr-17.3.1 { SELECT 'abc' GLOB 'def' } 1 do_test e_expr-17.3.2 { set globargs } {def abc} set ::globargs [list] do_execsql_test e_expr-17.3.3 { SELECT 'X' NOT GLOB 'Y' } 0 do_test e_expr-17.3.4 { set globargs } {Y X} sqlite3 db test.db # EVIDENCE-OF: R-41650-20872 No regexp() user function is defined by # default and so use of the REGEXP operator will normally result in an # error message. # do_catchsql_test e_expr-18.1.1 { SELECT regexp('abc', 'def') } {1 {no such function: regexp}} do_catchsql_test e_expr-18.1.2 { SELECT 'abc' REGEXP 'def' } {1 {no such function: REGEXP}} # EVIDENCE-OF: R-33693-50180 The REGEXP operator is a special syntax for # the regexp() user function. # # EVIDENCE-OF: R-57289-13578 If a application-defined SQL function named # "regexp" is added at run-time, that function will be called in order # to implement the REGEXP operator. # proc regexpfunc {args} { eval lappend ::regexpargs $args return 1 } db func regexp -argcount 2 regexpfunc set ::regexpargs [list] do_execsql_test e_expr-18.2.1 { SELECT 'abc' REGEXP 'def' } 1 do_test e_expr-18.2.2 { set regexpargs } {def abc} set ::regexpargs [list] do_execsql_test e_expr-18.2.3 { SELECT 'X' NOT REGEXP 'Y' } 0 do_test e_expr-18.2.4 { set regexpargs } {Y X} sqlite3 db test.db # EVIDENCE-OF: R-42037-37826 The default match() function implementation # raises an exception and is not really useful for anything. # do_catchsql_test e_expr-19.1.1 { SELECT 'abc' MATCH 'def' } {1 {unable to use function MATCH in the requested context}} do_catchsql_test e_expr-19.1.2 { SELECT match('abc', 'def') } {1 {unable to use function MATCH in the requested context}} # EVIDENCE-OF: R-37916-47407 The MATCH operator is a special syntax for # the match() application-defined function. # # EVIDENCE-OF: R-06021-09373 But extensions can override the match() # function with more helpful logic. # proc matchfunc {args} { eval lappend ::matchargs $args return 1 } db func match -argcount 2 matchfunc set ::matchargs [list] do_execsql_test e_expr-19.2.1 { SELECT 'abc' MATCH 'def' } 1 do_test e_expr-19.2.2 { set matchargs } {def abc} set ::matchargs [list] do_execsql_test e_expr-19.2.3 { SELECT 'X' NOT MATCH 'Y' } 0 do_test e_expr-19.2.4 { set matchargs } {Y X} sqlite3 db test.db finish_test |
Changes to test/ioerr5.test.
︙ | ︙ | |||
125 126 127 128 129 130 131 | # from UTF-16 text. To do this, SQLite will need to reclaim memory # from the pager that is in error state. Including that associated # with the dirty page. # do_test ioerr5-1.$locking_mode-$iFail.3 { sqlite3_soft_heap_limit 1024 compilesql16 "SELECT 10" | | | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | # from UTF-16 text. To do this, SQLite will need to reclaim memory # from the pager that is in error state. Including that associated # with the dirty page. # do_test ioerr5-1.$locking_mode-$iFail.3 { sqlite3_soft_heap_limit 1024 compilesql16 "SELECT 10" } {SQLITE_OK} close $channel # Ensure that nothing was written to the database while reclaiming # memory from the pager in error state. # do_test ioerr5-1.$locking_mode-$iFail.4 { |
︙ | ︙ |
Changes to test/lock_common.tcl.
︙ | ︙ | |||
61 62 63 64 65 66 67 | } } # Launch another testfixture process to be controlled by this one. A # channel name is returned that may be passed as the first argument to proc # 'testfixture' to execute a command. The child testfixture process is shut # down by closing the channel. | | | | | < > | > > > > | 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 | } } # Launch another testfixture process to be controlled by this one. A # channel name is returned that may be passed as the first argument to proc # 'testfixture' to execute a command. The child testfixture process is shut # down by closing the channel. proc launch_testfixture {{prg ""}} { write_main_loop if {$prg eq ""} { set prg [info nameofexec] } if {$prg eq ""} { set prg testfixture } if {[file tail $prg]==$prg} { set prg [file join . $prg] } set chan [open "|$prg tf_main.tcl" r+] fconfigure $chan -buffering line set rc [catch { testfixture $chan "sqlite3_test_control_pending_byte $::sqlite_pending_byte" }] if {$rc} { testfixture $chan "set ::sqlite_pending_byte $::sqlite_pending_byte" } return $chan } # Execute a command in a child testfixture process, connected by two-way # channel $chan. Return the result of the command, or an error message. # proc testfixture {chan cmd} { |
︙ | ︙ |
Changes to test/pagerfault.test.
︙ | ︙ | |||
48 49 50 51 52 53 54 | faultsim_save_and_close } {} do_faultsim_test pagerfault-1 -prep { faultsim_restore_and_reopen } -body { execsql { SELECT count(*) FROM t1 } } -test { | | | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | faultsim_save_and_close } {} do_faultsim_test pagerfault-1 -prep { faultsim_restore_and_reopen } -body { execsql { SELECT count(*) FROM t1 } } -test { faultsim_test_result {0 4} faultsim_integrity_check if {[db one { SELECT count(*) FROM t1 }] != 4} { error "Database content appears incorrect" } } #------------------------------------------------------------------------- |
︙ | ︙ | |||
1225 1226 1227 1228 1229 1230 1231 | error "Expected file size to be 3072 or 12288 bytes - actual size $sz bytes" } if {$testrc==0 && $sz!=4096*3} { error "Expected file size to be 12288 bytes - actual size $sz bytes" } } | > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > | 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 | error "Expected file size to be 3072 or 12288 bytes - actual size $sz bytes" } if {$testrc==0 && $sz!=4096*3} { error "Expected file size to be 12288 bytes - actual size $sz bytes" } } do_test pagerfault-27-pre { faultsim_delete_and_reopen db func a_string a_string execsql { PRAGMA page_size = 1024; CREATE TABLE t1(a, b); CREATE TABLE t2(a UNIQUE, b UNIQUE); INSERT INTO t2 VALUES( a_string(800), a_string(800) ); INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; INSERT INTO t1 VALUES (a_string(20000), a_string(20000)); } faultsim_save_and_close } {} do_faultsim_test pagerfault-27 -faults ioerr-persistent -prep { faultsim_restore_and_reopen db func a_string a_string execsql { PRAGMA cache_size = 10; BEGIN EXCLUSIVE; } set ::channel [db incrblob t1 a 1] } -body { puts $::channel [string repeat abc 6000] flush $::channel } -test { catchsql { UPDATE t2 SET a = a_string(800), b = a_string(800) } catch { close $::channel } catchsql { ROLLBACK } faultsim_integrity_check } finish_test |
Added test/tkt-5e10420e8d.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | # 2010 August 23 # # 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl do_execsql_test tkt-5e10420e8d.1 { PRAGMA page_size = 1024; PRAGMA auto_vacuum = incremental; CREATE TABLE t1(x); CREATE TABLE t2(x); CREATE TABLE t3(x); } {} do_execsql_test tkt-5e10420e8d.2 { INSERT INTO t3 VALUES(randomblob(500 + 1024*248)); INSERT INTO t1 VALUES(randomblob(1500)); INSERT INTO t2 VALUES(randomblob(500 + 1024*248)); DELETE FROM t3; DELETE FROM t2; DELETE FROM t1; } {} do_execsql_test tkt-5e10420e8d.3 { PRAGMA incremental_vacuum(248) } {} do_execsql_test tkt-5e10420e8d.4 { PRAGMA incremental_vacuum(1) } {} db close sqlite3 db test.db do_execsql_test tkt-5e10420e8d.5 { PRAGMA integrity_check; } {ok} finish_test |
Changes to test/wal.test.
︙ | ︙ | |||
1472 1473 1474 1475 1476 1477 1478 | }] } #------------------------------------------------------------------------- # Test that when 1 or more pages are recovered from a WAL file, # sqlite3_log() is invoked to report this to the user. # | | | 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 | }] } #------------------------------------------------------------------------- # Test that when 1 or more pages are recovered from a WAL file, # sqlite3_log() is invoked to report this to the user. # set walfile [file nativename [file join [pwd] test.db-wal]] catch {db close} file delete -force test.db do_test wal-23.1 { faultsim_delete_and_reopen execsql { CREATE TABLE t1(a, b); PRAGMA journal_mode = WAL; |
︙ | ︙ | |||
1499 1500 1501 1502 1503 1504 1505 1506 1507 | do_test wal-23.3 { db close set ::log [list] faultsim_restore_and_reopen execsql { SELECT * FROM t1 } } {1 2 3 4} do_test wal-23.4 { set ::log | > | | 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 | do_test wal-23.3 { db close set ::log [list] faultsim_restore_and_reopen execsql { SELECT * FROM t1 } } {1 2 3 4} set nPage [expr 2+$AUTOVACUUM] do_test wal-23.4 { set ::log } [list SQLITE_OK "Recovered $nPage frames from WAL file $walfile"] db close sqlite3_shutdown test_sqlite3_log sqlite3_initialize finish_test |
Changes to tool/shell4.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2010 July 28 # # 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. # #*********************************************************************** # # The focus of this file is testing the CLI shell tool. # # $Id: shell4.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $ # # Test plan: # # shell4-1.*: Basic tests specific to the "stats" command. # | > < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | # 2010 July 28 # # 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. # #*********************************************************************** # # The focus of this file is testing the CLI shell tool. # These tests are specific to the .stats command. # # $Id: shell4.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $ # # Test plan: # # shell4-1.*: Basic tests specific to the "stats" command. # set CLI "./sqlite3" proc do_test {name cmd expected} { puts -nonewline "$name ..." set res [uplevel $cmd] if {$res eq $expected} { puts Ok } else { puts Error puts " Got: $res" puts " Expected: $expected" exit } } proc catchcmd {db {cmd ""}} { global CLI set out [open cmds.txt w] puts $out $cmd close $out set line "exec $CLI $db < cmds.txt" set rc [catch { eval $line } msg] list $rc $msg } file delete -force test.db test.db.journal #---------------------------------------------------------------------------- # Test cases shell4-1.*: Tests specific to the "stats" command. # # should default to off do_test shell4-1.1.1 { |
︙ | ︙ |
Added tool/shell5.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | # 2010 August 4 # # 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. # #*********************************************************************** # # The focus of this file is testing the CLI shell tool. # These tests are specific to the .import command. # # $Id: shell5.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $ # # Test plan: # # shell5-1.*: Basic tests specific to the ".import" command. # set CLI "./sqlite3" proc do_test {name cmd expected} { puts -nonewline "$name ..." set res [uplevel $cmd] if {$res eq $expected} { puts Ok } else { puts Error puts " Got: $res" puts " Expected: $expected" exit } } proc catchcmd {db {cmd ""}} { global CLI set out [open cmds.txt w] puts $out $cmd close $out set line "exec $CLI $db < cmds.txt" set rc [catch { eval $line } msg] list $rc $msg } file delete -force test.db test.db.journal #---------------------------------------------------------------------------- # Test cases shell5-1.*: Basic handling of the .import and .separator commands. # # .import FILE TABLE Import data from FILE into TABLE do_test shell5-1.1.1 { catchcmd "test.db" ".import" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} do_test shell5-1.1.2 { catchcmd "test.db" ".import FOO" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} do_test shell5-1.1.2 { catchcmd "test.db" ".import FOO BAR" } {1 {Error: no such table: BAR}} do_test shell5-1.1.3 { # too many arguments catchcmd "test.db" ".import FOO BAR BAD" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} # .separator STRING Change separator used by output mode and .import do_test shell1-1.2.1 { catchcmd "test.db" ".separator" } {1 {Error: unknown command or invalid arguments: "separator". Enter ".help" for help}} do_test shell1-1.2.2 { catchcmd "test.db" ".separator FOO" } {0 {}} do_test shell1-1.2.3 { # too many arguments catchcmd "test.db" ".separator FOO BAD" } {1 {Error: unknown command or invalid arguments: "separator". Enter ".help" for help}} # separator should default to "|" do_test shell5-1.3.1 { set res [catchcmd "test.db" ".show"] list [regexp {separator: \"\|\"} $res] } {1} # set separator to different value. # check that .show reports new value do_test shell5-1.3.2 { set res [catchcmd "test.db" {.separator , .show}] list [regexp {separator: \",\"} $res] } {1} # import file doesn't exist do_test shell5-1.4.1 { file delete -force FOO set res [catchcmd "test.db" {CREATE TABLE t1(a, b); .import FOO t1}] } {1 {Error: cannot open "FOO"}} # empty import file do_test shell5-1.4.2 { file delete -force shell5.csv set in [open shell5.csv w] close $in set res [catchcmd "test.db" {.import shell5.csv t1 SELECT COUNT(*) FROM t1;}] } {0 0} # import file with 1 row, 1 column (expecting 2 cols) do_test shell5-1.4.3 { set in [open shell5.csv w] puts $in "1" close $in set res [catchcmd "test.db" {.import shell5.csv t1}] } {1 {Error: shell5.csv line 1: expected 2 columns of data but found 1}} # import file with 1 row, 3 columns (expecting 2 cols) do_test shell5-1.4.4 { set in [open shell5.csv w] puts $in "1|2|3" close $in set res [catchcmd "test.db" {.import shell5.csv t1}] } {1 {Error: shell5.csv line 1: expected 2 columns of data but found 3}} # import file with 1 row, 2 columns do_test shell5-1.4.5 { set in [open shell5.csv w] puts $in "1|2" close $in set res [catchcmd "test.db" {.import shell5.csv t1 SELECT COUNT(*) FROM t1;}] } {0 1} # import file with 2 rows, 2 columns # note we end up with 3 rows because of the 1 row # imported above. do_test shell5-1.4.6 { set in [open shell5.csv w] puts $in "2|3" puts $in "3|4" close $in set res [catchcmd "test.db" {.import shell5.csv t1 SELECT COUNT(*) FROM t1;}] } {0 3} # import file with 1 row, 2 columns, using a comma do_test shell5-1.4.7 { set in [open shell5.csv w] puts $in "4,5" close $in set res [catchcmd "test.db" {.separator , .import shell5.csv t1 SELECT COUNT(*) FROM t1;}] } {0 4} # import file with 1 row, 2 columns, text data do_test shell5-1.4.8.1 { set in [open shell5.csv w] puts $in "5|Now is the time for all good men to come to the aid of their country." close $in set res [catchcmd "test.db" {.import shell5.csv t1 SELECT COUNT(*) FROM t1;}] } {0 5} do_test shell5-1.4.8.2 { catchcmd "test.db" {SELECT b FROM t1 WHERE a='5';} } {0 {Now is the time for all good men to come to the aid of their country.}} # import file with 1 row, 2 columns, quoted text data # note that currently sqlite doesn't support quoted fields, and # imports the entire field, quotes and all. do_test shell5-1.4.9.1 { set in [open shell5.csv w] puts $in "6|'Now is the time for all good men to come to the aid of their country.'" close $in set res [catchcmd "test.db" {.import shell5.csv t1 SELECT COUNT(*) FROM t1;}] } {0 6} do_test shell5-1.4.9.2 { catchcmd "test.db" {SELECT b FROM t1 WHERE a='6';} } {0 {'Now is the time for all good men to come to the aid of their country.'}} # import file with 1 row, 2 columns, quoted text data do_test shell5-1.4.10.1 { set in [open shell5.csv w] puts $in "7|\"Now is the time for all good men to come to the aid of their country.\"" close $in set res [catchcmd "test.db" {.import shell5.csv t1 SELECT COUNT(*) FROM t1;}] } {0 7} do_test shell5-1.4.10.2 { catchcmd "test.db" {SELECT b FROM t1 WHERE a='7';} } {0 {"Now is the time for all good men to come to the aid of their country."}} # check importing very long field do_test shell5-1.5.1 { set str [string repeat X 999] set in [open shell5.csv w] puts $in "8|$str" close $in set res [catchcmd "test.db" {.import shell5.csv t1 SELECT length(b) FROM t1 WHERE a='8';}] } {0 999} # try importing into a table with a large number of columns. # This is limited by SQLITE_MAX_VARIABLE_NUMBER, which defaults to 999. set cols 999 do_test shell5-1.6.1 { set sql {CREATE TABLE t2(} set data {} for {set i 1} {$i<$cols} {incr i} { append sql "c$i," append data "$i|" } append sql "c$cols);" append data "$cols" catchcmd "test.db" $sql set in [open shell5.csv w] puts $in $data close $in set res [catchcmd "test.db" {.import shell5.csv t2 SELECT COUNT(*) FROM t2;}] } {0 1} # try importing a large number of rows set rows 999999 do_test shell5-1.7.1 { set in [open shell5.csv w] for {set i 1} {$i<=$rows} {incr i} { puts $in $i } close $in set res [catchcmd "test.db" {CREATE TABLE t3(a); .import shell5.csv t3 SELECT COUNT(*) FROM t3;}] } [list 0 $rows] puts "CLI tests completed successfully" |
Changes to tool/showdb.c.
︙ | ︙ | |||
30 31 32 33 34 35 36 37 38 39 40 41 42 43 | v = (v<<7) + (z[i]&0x7f); if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; } } v = (v<<8) + (z[i]&0xff); *pVal = v; return 9; } /* Report an out-of-memory error and die. */ static void out_of_memory(void){ fprintf(stderr,"Out of memory...\n"); exit(1); } | > > > > > > > | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | v = (v<<7) + (z[i]&0x7f); if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; } } v = (v<<8) + (z[i]&0xff); *pVal = v; return 9; } /* ** Extract a big-endian 32-bit integer */ static unsigned int decodeInt32(const unsigned char *z){ return (z[0]<<24) + (z[1]<<16) + (z[2]<<8) + z[3]; } /* Report an out-of-memory error and die. */ static void out_of_memory(void){ fprintf(stderr,"Out of memory...\n"); exit(1); } |
︙ | ︙ | |||
241 242 243 244 245 246 247 248 249 250 251 252 | int cofst = iCellPtr + i*2; char *zDesc; cofst = a[cofst]*256 + a[cofst+1]; describeCell(a[0], &a[cofst-hdrSize], &zDesc); printf(" %03x: cell[%d] %s\n", cofst, i, zDesc); } } int main(int argc, char **argv){ struct stat sbuf; unsigned char zPgSz[2]; if( argc<2 ){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | int cofst = iCellPtr + i*2; char *zDesc; cofst = a[cofst]*256 + a[cofst+1]; describeCell(a[0], &a[cofst-hdrSize], &zDesc); printf(" %03x: cell[%d] %s\n", cofst, i, zDesc); } } /* ** Decode a freelist trunk page. */ static void decode_trunk_page( int pgno, /* The page number */ int pagesize, /* Size of each page */ int detail, /* Show leaf pages if true */ int recursive /* Follow the trunk change if true */ ){ int n, i, k; unsigned char *a; while( pgno>0 ){ a = getContent((pgno-1)*pagesize, pagesize); printf("Decode of freelist trunk page %d:\n", pgno); print_decode_line(a, 0, 4, "Next freelist trunk page"); print_decode_line(a, 4, 4, "Number of entries on this page"); if( detail ){ n = (int)decodeInt32(&a[4]); for(i=0; i<n; i++){ unsigned int x = decodeInt32(&a[8+4*i]); char zIdx[10]; sprintf(zIdx, "[%d]", i); printf(" %5s %7u", zIdx, x); if( i%5==4 ) printf("\n"); } if( i%5!=0 ) printf("\n"); } if( !recursive ){ pgno = 0; }else{ pgno = (int)decodeInt32(&a[0]); } free(a); } } /* ** Print a usage comment */ static void usage(const char *argv0){ fprintf(stderr, "Usage %s FILENAME ?args...?\n\n", argv0); fprintf(stderr, "args:\n" " dbheader Show database header\n" " NNN..MMM Show hex of pages NNN through MMM\n" " NNN..end Show hex of pages NNN through end of file\n" " NNNb Decode btree page NNN\n" " NNNt Decode freelist trunk page NNN\n" " NNNtd Show leave freelist pages on the decode\n" " NNNtr Recurisvely decode freelist starting at NNN\n" ); } int main(int argc, char **argv){ struct stat sbuf; unsigned char zPgSz[2]; if( argc<2 ){ usage(argv[0]); exit(1); } db = open(argv[1], O_RDONLY); if( db<0 ){ fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]); exit(1); } zPgSz[0] = 0; zPgSz[1] = 0; lseek(db, 16, SEEK_SET); read(db, zPgSz, 2); pagesize = zPgSz[0]*256 + zPgSz[1]*65536; if( pagesize==0 ) pagesize = 1024; printf("Pagesize: %d\n", pagesize); fstat(db, &sbuf); mxPage = sbuf.st_size/pagesize; printf("Available pages: 1..%d\n", mxPage); if( argc==2 ){ int i; |
︙ | ︙ | |||
300 301 302 303 304 305 306 307 308 309 310 311 312 313 | ofst = (iStart-1)*pagesize; nByte = pagesize; } a = getContent(ofst, nByte); decode_btree_page(a, iStart, hdrSize); free(a); continue; }else{ iEnd = iStart; } if( iStart<1 || iEnd<iStart || iEnd>mxPage ){ fprintf(stderr, "Page argument should be LOWER?..UPPER?. Range 1 to %d\n", mxPage); | > > > > > > > > > > > | 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | ofst = (iStart-1)*pagesize; nByte = pagesize; } a = getContent(ofst, nByte); decode_btree_page(a, iStart, hdrSize); free(a); continue; }else if( zLeft && zLeft[0]=='t' ){ unsigned char *a; int detail = 0; int recursive = 0; int i; for(i=1; zLeft[i]; i++){ if( zLeft[i]=='r' ) recursive = 1; if( zLeft[i]=='d' ) detail = 1; } decode_trunk_page(iStart, pagesize, detail, recursive); continue; }else{ iEnd = iStart; } if( iStart<1 || iEnd<iStart || iEnd>mxPage ){ fprintf(stderr, "Page argument should be LOWER?..UPPER?. Range 1 to %d\n", mxPage); |
︙ | ︙ |