Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge latest trunk changes with this branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sqlite_stat4 |
Files: | files | file ages | folders |
SHA1: |
08f74c45ecf711a2373af578d44470ad |
User & Date: | dan 2013-08-07 18:42:27.752 |
Context
2013-08-07
| ||
19:46 | Replace variable Index.avgEq (average number of rows in keys for which there is no sample in sqlite_stat4) with vector Index.aAvgEq. (check-in: 7b70b419c4 user: dan tags: sqlite_stat4) | |
18:42 | Merge latest trunk changes with this branch. (check-in: 08f74c45ec user: dan tags: sqlite_stat4) | |
16:38 | Fix typos in a comment in analyze.c. No code changes. (check-in: 812ed0c58f user: dan tags: sqlite_stat4) | |
14:18 | Add a guard #ifndef to test_intarray.h to prevent harm if it is #included more than once. Add a comment on the closing #endif of the guards on sqlite3.h and test_multiplex.h. (check-in: 0ad83ceb79 user: drh tags: trunk) | |
Changes
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.8.0. # # 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.8.0' PACKAGE_STRING='sqlite 3.8.0' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> |
︙ | ︙ | |||
1480 1481 1482 1483 1484 1485 1486 | # # 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 | | | 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 | # # 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.8.0 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. |
︙ | ︙ | |||
1545 1546 1547 1548 1549 1550 1551 | --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 | | | 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 | --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.8.0:";; 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] |
︙ | ︙ | |||
1661 1662 1663 1664 1665 1666 1667 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF | | | | 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 1687 1688 1689 | 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.8.0 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.8.0, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { |
︙ | ︙ | |||
14028 14029 14030 14031 14032 14033 14034 | 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=" | | | 14028 14029 14030 14031 14032 14033 14034 14035 14036 14037 14038 14039 14040 14041 14042 | 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.8.0, 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 $@ |
︙ | ︙ | |||
14081 14082 14083 14084 14085 14086 14087 | $config_commands Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ | | | 14081 14082 14083 14084 14085 14086 14087 14088 14089 14090 14091 14092 14093 14094 14095 | $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.8.0 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 ext/misc/vtshim.c.
︙ | ︙ | |||
425 426 427 428 429 430 431 432 433 434 435 436 437 438 | /* The destructor function for a disposible module */ static void vtshimAuxDestructor(void *pXAux){ vtshim_aux *pAux = (vtshim_aux*)pXAux; assert( pAux->pAllVtab==0 ); if( !pAux->bDisposed && pAux->xChildDestroy ){ pAux->xChildDestroy(pAux->pChildAux); } sqlite3_free(pAux->zName); sqlite3_free(pAux->pMod); sqlite3_free(pAux); } static int vtshimCopyModule( | > | 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | /* The destructor function for a disposible module */ static void vtshimAuxDestructor(void *pXAux){ vtshim_aux *pAux = (vtshim_aux*)pXAux; assert( pAux->pAllVtab==0 ); if( !pAux->bDisposed && pAux->xChildDestroy ){ pAux->xChildDestroy(pAux->pChildAux); pAux->xChildDestroy = 0; } sqlite3_free(pAux->zName); sqlite3_free(pAux->pMod); sqlite3_free(pAux); } static int vtshimCopyModule( |
︙ | ︙ | |||
523 524 525 526 527 528 529 | for(pVtab=pAux->pAllVtab; pVtab; pVtab=pVtab->pNext){ for(pCur=pVtab->pAllCur; pCur; pCur=pCur->pNext){ pAux->pMod->xClose(pCur->pChild); } pAux->pMod->xDisconnect(pVtab->pChild); } pAux->bDisposed = 1; | | > > > | 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 | for(pVtab=pAux->pAllVtab; pVtab; pVtab=pVtab->pNext){ for(pCur=pVtab->pAllCur; pCur; pCur=pCur->pNext){ pAux->pMod->xClose(pCur->pChild); } pAux->pMod->xDisconnect(pVtab->pChild); } pAux->bDisposed = 1; if( pAux->xChildDestroy ){ pAux->xChildDestroy(pAux->pChildAux); pAux->xChildDestroy = 0; } } } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifdef _WIN32 |
︙ | ︙ |
Changes to mkopcodeh.awk.
︙ | ︙ | |||
31 32 33 34 35 36 37 | # properties apply to that opcode. Set corresponding flags using the # OPFLG_INITIALIZER macro. # # Remember the TK_ values from the parse.h file /^#define TK_/ { | | | > | | | > | 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 | # properties apply to that opcode. Set corresponding flags using the # OPFLG_INITIALIZER macro. # # Remember the TK_ values from the parse.h file /^#define TK_/ { tk[$2] = 0+$3 # tk[x] holds the numeric value for TK symbol X } # Scan for "case OP_aaaa:" lines in the vdbe.c file /^case OP_/ { name = $2 sub(/:/,"",name) sub("\r","",name) op[name] = -1 # op[x] holds the numeric value for OP symbol x jump[name] = 0 out2_prerelease[name] = 0 in1[name] = 0 in2[name] = 0 in3[name] = 0 out2[name] = 0 out3[name] = 0 for(i=3; i<NF; i++){ if($i=="same" && $(i+1)=="as"){ sym = $(i+2) sub(/,/,"",sym) val = tk[sym] op[name] = val used[val] = 1 sameas[val] = sym def[val] = name } x = $i sub(",","",x) if(x=="jump"){ jump[name] = 1 }else if(x=="out2-prerelease"){ out2_prerelease[name] = 1 |
︙ | ︙ | |||
86 87 88 89 90 91 92 93 94 95 96 97 98 | max = 0 print "/* Automatically generated. Do not edit */" print "/* See the mkopcodeh.awk script for details */" op["OP_Noop"] = -1; order[n_op++] = "OP_Noop"; op["OP_Explain"] = -1; order[n_op++] = "OP_Explain"; for(i=0; i<n_op; i++){ name = order[i]; if( op[name]<0 ){ cnt++ while( used[cnt] ) cnt++ op[name] = cnt | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | | < < < | < | < | | < < | | | > > | > | < | < < < | | 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 | max = 0 print "/* Automatically generated. Do not edit */" print "/* See the mkopcodeh.awk script for details */" op["OP_Noop"] = -1; order[n_op++] = "OP_Noop"; op["OP_Explain"] = -1; order[n_op++] = "OP_Explain"; # Assign small values to opcodes that are processed by resolveP2Values() # to make code generation for the switch() statement smaller and faster. for(i=0; i<n_op; i++){ name = order[i]; if( op[name]>=0 ) continue; if( name=="OP_Function" \ || name=="OP_AggStep" \ || name=="OP_Transaction" \ || name=="OP_AutoCommit" \ || name=="OP_Savepoint" \ || name=="OP_Checkpoint" \ || name=="OP_Vacuum" \ || name=="OP_JournalMode" \ || name=="OP_VUpdate" \ || name=="OP_VFilter" \ || name=="OP_Next" \ || name=="OP_SorterNext" \ || name=="OP_Prev" \ ){ cnt++ while( used[cnt] ) cnt++ op[name] = cnt used[cnt] = 1 def[cnt] = name } } # Generate the numeric values for opcodes for(i=0; i<n_op; i++){ name = order[i]; if( op[name]<0 ){ cnt++ while( used[cnt] ) cnt++ op[name] = cnt used[cnt] = 1 def[cnt] = name } } max = cnt for(i=1; i<=max; i++){ if( !used[i] ){ def[i] = "OP_NotUsed_" i } printf "#define %-25s %15d", def[i], i if( sameas[i] ){ printf " /* same as %-12s*/", sameas[i] } printf "\n" } # Generate the bitvectors: # # bit 0: jump # bit 1: pushes a result onto stack # bit 2: output to p1. release p1 before opcode runs # for(i=0; i<=max; i++){ name = def[i] a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0 if( jump[name] ) a0 = 1; if( out2_prerelease[name] ) a1 = 2; if( in1[name] ) a2 = 4; if( in2[name] ) a3 = 8; if( in3[name] ) a4 = 16; if( out2[name] ) a5 = 32; if( out3[name] ) a6 = 64; bv[i] = a0+a1+a2+a3+a4+a5+a6+a7; } print "\n" print "/* Properties such as \"out2\" or \"jump\" that are specified in" print "** comments following the \"case\" for each opcode in the vdbe.c" print "** are encoded into bitvectors as follows:" print "*/" print "#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */" |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
3801 3802 3803 3804 3805 3806 3807 | ** pointer. If an error occurs (out of memory or missing collation ** sequence), NULL is returned and the state of pParse updated to reflect ** the error. */ KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ int i; int nCol = pIdx->nColumn; | < < | > < < < < | | 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 | ** pointer. If an error occurs (out of memory or missing collation ** sequence), NULL is returned and the state of pParse updated to reflect ** the error. */ KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ int i; int nCol = pIdx->nColumn; KeyInfo *pKey; pKey = sqlite3KeyInfoAlloc(pParse->db, nCol); if( pKey ){ for(i=0; i<nCol; i++){ char *zColl = pIdx->azColl[i]; assert( zColl ); pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl); pKey->aSortOrder[i] = pIdx->aSortOrder[i]; } } if( pParse->nErr ){ sqlite3DbFree(pParse->db, pKey); pKey = 0; } return pKey; } |
Changes to src/expr.c.
︙ | ︙ | |||
1688 1689 1690 1691 1692 1693 1694 | sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); } #endif switch( pExpr->op ){ case TK_IN: { char affinity; /* Affinity of the LHS of the IN */ | < < > | 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 | sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); } #endif switch( pExpr->op ){ case TK_IN: { char affinity; /* Affinity of the LHS of the IN */ int addr; /* Address of OP_OpenEphemeral instruction */ Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */ KeyInfo *pKeyInfo = 0; /* Key information */ if( rMayHaveNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull); } affinity = sqlite3ExprAffinity(pLeft); |
︙ | ︙ | |||
1715 1716 1717 1718 1719 1720 1721 | ** if either column has NUMERIC or INTEGER affinity. If neither ** 'x' nor the SELECT... statement are columns, then numeric affinity ** is used. */ pExpr->iTable = pParse->nTab++; addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED); | < | < > > > > | | | < > | < > | 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 | ** if either column has NUMERIC or INTEGER affinity. If neither ** 'x' nor the SELECT... statement are columns, then numeric affinity ** is used. */ pExpr->iTable = pParse->nTab++; addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED); pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* Case 1: expr IN (SELECT ...) ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ SelectDest dest; ExprList *pEList; assert( !isRowid ); sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); dest.affSdst = (u8)affinity; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); pExpr->x.pSelect->iLimit = 0; testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){ sqlite3DbFree(pParse->db, pKeyInfo); return 0; } pEList = pExpr->x.pSelect->pEList; assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */ assert( pEList!=0 ); assert( pEList->nExpr>0 ); pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pEList->a[0].pExpr); }else if( ALWAYS(pExpr->x.pList!=0) ){ /* Case 2: expr IN (exprlist) ** ** For each expression, build an index key from the evaluation and ** store it in the temporary table. If <expr> is a column, then use ** that columns affinity when building index keys. If <expr> is not ** a column, use numeric affinity. */ int i; ExprList *pList = pExpr->x.pList; struct ExprList_item *pItem; int r1, r2, r3; if( !affinity ){ affinity = SQLITE_AFF_NONE; } if( pKeyInfo ){ pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft); } /* Loop through each expression in <exprlist>. */ r1 = sqlite3GetTempReg(pParse); r2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Null, 0, r2); for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ Expr *pE2 = pItem->pExpr; |
︙ | ︙ | |||
1797 1798 1799 1800 1801 1802 1803 | sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); } } } sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); } | | | | 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 | sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); } } } sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); } if( pKeyInfo ){ sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO_HANDOFF); } break; } case TK_EXISTS: case TK_SELECT: default: { |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
413 414 415 416 417 418 419 420 421 422 423 424 425 426 | select(A) ::= oneselect(X). {A = X;} %ifndef SQLITE_OMIT_COMPOUND_SELECT select(A) ::= select(X) multiselect_op(Y) oneselect(Z). { if( Z ){ Z->op = (u8)Y; Z->pPrior = X; }else{ sqlite3SelectDelete(pParse->db, X); } A = Z; } %type multiselect_op {int} multiselect_op(A) ::= UNION(OP). {A = @OP;} | > | 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 | select(A) ::= oneselect(X). {A = X;} %ifndef SQLITE_OMIT_COMPOUND_SELECT select(A) ::= select(X) multiselect_op(Y) oneselect(Z). { if( Z ){ Z->op = (u8)Y; Z->pPrior = X; if( Y!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, X); } A = Z; } %type multiselect_op {int} multiselect_op(A) ::= UNION(OP). {A = @OP;} |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 | ** there is a sorter, in which case the sorter has already limited ** the output for us. */ if( pOrderBy==0 && p->iLimit ){ sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); } } /* ** Given an expression list, generate a KeyInfo structure that records ** the collating sequence for each expression in that expression list. ** ** If the ExprList is an ORDER BY or GROUP BY clause then the resulting ** KeyInfo structure is appropriate for initializing a virtual index to ** implement that clause. If the ExprList is the result set of a SELECT ** then the KeyInfo structure is appropriate for initializing a virtual ** index to implement a DISTINCT test. ** ** Space to hold the KeyInfo structure is obtain from malloc. The calling ** function is responsible for seeing that this structure is eventually ** freed. Add the KeyInfo structure to the P4 field of an opcode using ** P4_KEYINFO_HANDOFF is the usual way of dealing with this. */ static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){ | > > > > > > > > > > > > > > > > > > > < > | < < < < < | < | 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 | ** there is a sorter, in which case the sorter has already limited ** the output for us. */ if( pOrderBy==0 && p->iLimit ){ sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); } } /* ** Allocate a KeyInfo object sufficient for an index of N columns. ** ** Actually, always allocate one extra column for the rowid at the end ** of the index. So the KeyInfo returned will have space sufficient for ** N+1 columns. */ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N){ KeyInfo *p = sqlite3DbMallocZero(db, sizeof(KeyInfo) + (N+1)*(sizeof(CollSeq*)+1)); if( p ){ p->aSortOrder = (u8*)&p->aColl[N+1]; p->nField = (u16)N; p->enc = ENC(db); p->db = db; } return p; } /* ** Given an expression list, generate a KeyInfo structure that records ** the collating sequence for each expression in that expression list. ** ** If the ExprList is an ORDER BY or GROUP BY clause then the resulting ** KeyInfo structure is appropriate for initializing a virtual index to ** implement that clause. If the ExprList is the result set of a SELECT ** then the KeyInfo structure is appropriate for initializing a virtual ** index to implement a DISTINCT test. ** ** Space to hold the KeyInfo structure is obtain from malloc. The calling ** function is responsible for seeing that this structure is eventually ** freed. Add the KeyInfo structure to the P4 field of an opcode using ** P4_KEYINFO_HANDOFF is the usual way of dealing with this. */ static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){ int nExpr; KeyInfo *pInfo; struct ExprList_item *pItem; sqlite3 *db = pParse->db; int i; nExpr = pList->nExpr; pInfo = sqlite3KeyInfoAlloc(db, nExpr); if( pInfo ){ for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){ CollSeq *pColl; pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); if( !pColl ) pColl = db->pDfltColl; pInfo->aColl[i] = pColl; pInfo->aSortOrder[i] = pItem->sortOrder; } } return pInfo; } |
︙ | ︙ | |||
1938 1939 1940 1941 1942 1943 1944 | KeyInfo *pKeyInfo; /* Collating sequence for the result set */ Select *pLoop; /* For looping through SELECT statements */ CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ int nCol; /* Number of columns in result set */ assert( p->pRightmost==p ); nCol = p->pEList->nExpr; | | < < < < < < | 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 | KeyInfo *pKeyInfo; /* Collating sequence for the result set */ Select *pLoop; /* For looping through SELECT statements */ CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ int nCol; /* Number of columns in result set */ assert( p->pRightmost==p ); nCol = p->pEList->nExpr; pKeyInfo = sqlite3KeyInfoAlloc(db, nCol); if( !pKeyInfo ){ rc = SQLITE_NOMEM; goto multi_select_end; } for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){ *apColl = multiSelectCollSeq(pParse, p, i); if( 0==*apColl ){ *apColl = db->pDfltColl; } } for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ for(i=0; i<2; i++){ int addr = pLoop->addrOpenEphm[i]; if( addr<0 ){ /* If [0] is unused then [1] is also unused. So we can ** always safely abort as soon as the first unused slot is found */ |
︙ | ︙ | |||
2323 2324 2325 2326 2327 2328 2329 | aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy); if( aPermute ){ struct ExprList_item *pItem; for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){ assert( pItem->iOrderByCol>0 && pItem->iOrderByCol<=p->pEList->nExpr ); aPermute[i] = pItem->iOrderByCol - 1; } | | < < < < | 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 | aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy); if( aPermute ){ struct ExprList_item *pItem; for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){ assert( pItem->iOrderByCol>0 && pItem->iOrderByCol<=p->pEList->nExpr ); aPermute[i] = pItem->iOrderByCol - 1; } pKeyMerge = sqlite3KeyInfoAlloc(db, nOrderBy); if( pKeyMerge ){ for(i=0; i<nOrderBy; i++){ CollSeq *pColl; Expr *pTerm = pOrderBy->a[i].pExpr; if( pTerm->flags & EP_Collate ){ pColl = sqlite3ExprCollSeq(pParse, pTerm); }else{ pColl = multiSelectCollSeq(pParse, p, aPermute[i]); |
︙ | ︙ | |||
2365 2366 2367 2368 2369 2370 2371 | regPrev = 0; }else{ int nExpr = p->pEList->nExpr; assert( nOrderBy>=nExpr || db->mallocFailed ); regPrev = pParse->nMem+1; pParse->nMem += nExpr+1; sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev); | | < < < < | 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 | regPrev = 0; }else{ int nExpr = p->pEList->nExpr; assert( nOrderBy>=nExpr || db->mallocFailed ); regPrev = pParse->nMem+1; pParse->nMem += nExpr+1; sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev); pKeyDup = sqlite3KeyInfoAlloc(db, nExpr); if( pKeyDup ){ for(i=0; i<nExpr; i++){ pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i); pKeyDup->aSortOrder[i] = 0; } } } |
︙ | ︙ | |||
3636 3637 3638 3639 3640 3641 3642 | ** If anything goes wrong, an error message is written into pParse. ** The calling function can detect the problem by looking at pParse->nErr ** and/or pParse->db->mallocFailed. */ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ Walker w; memset(&w, 0, sizeof(w)); | < > > | > | 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 | ** If anything goes wrong, an error message is written into pParse. ** The calling function can detect the problem by looking at pParse->nErr ** and/or pParse->db->mallocFailed. */ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ Walker w; memset(&w, 0, sizeof(w)); w.xExprCallback = exprWalkNoop; w.pParse = pParse; if( pParse->hasCompound ){ w.xSelectCallback = convertCompoundSelectToSubquery; sqlite3WalkSelect(&w, pSelect); } w.xSelectCallback = selectExpander; sqlite3WalkSelect(&w, pSelect); } #ifndef SQLITE_OMIT_SUBQUERY /* |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
49 50 51 52 53 54 55 | # include <editline/editline.h> #endif #if defined(HAVE_READLINE) && HAVE_READLINE==1 # include <readline/readline.h> # include <readline/history.h> #endif #if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1) | < | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | # include <editline/editline.h> #endif #if defined(HAVE_READLINE) && HAVE_READLINE==1 # include <readline/readline.h> # include <readline/history.h> #endif #if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1) # define add_history(X) # define read_history(X) # define write_history(X) # define stifle_history(X) #endif #if defined(_WIN32) || defined(WIN32) |
︙ | ︙ | |||
333 334 335 336 337 338 339 | /* ** This routine reads a line of text from FILE in, stores ** the text in memory obtained from malloc() and returns a pointer ** to the text. NULL is returned at end of file, or if malloc() ** fails. ** | | | | < | | < < < < < < < < < | < < < | < | | > > > > > > > > | | < < < | < < > > | > > > > > | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 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 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | /* ** This routine reads a line of text from FILE in, stores ** the text in memory obtained from malloc() and returns a pointer ** to the text. NULL is returned at end of file, or if malloc() ** fails. ** ** If zLine is not NULL then it is a malloced buffer returned from ** a previous call to this routine that may be reused. */ static char *local_getline(char *zLine, FILE *in){ int nLine = zLine==0 ? 0 : 100; int n = 0; while( 1 ){ if( n+100>nLine ){ nLine = nLine*2 + 100; zLine = realloc(zLine, nLine); if( zLine==0 ) return 0; } if( fgets(&zLine[n], nLine - n, in)==0 ){ if( n==0 ){ free(zLine); return 0; } zLine[n] = 0; break; } while( zLine[n] ) n++; if( n>0 && zLine[n-1]=='\n' ){ n--; if( n>0 && zLine[n-1]=='\r' ) n--; zLine[n] = 0; break; } } return zLine; } /* ** Retrieve a single line of input text. ** ** If in==0 then read from standard input and prompt before each line. ** If isContinuation is true, then a continuation prompt is appropriate. ** If isContinuation is zero, then the main prompt should be used. ** ** If zPrior is not NULL then it is a buffer from a prior call to this ** routine that can be reused. ** ** The result is stored in space obtained from malloc() and must either ** be freed by the caller or else passed back into this routine via the ** zPrior argument for reuse. */ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ char *zPrompt; char *zResult; if( in!=0 ){ zResult = local_getline(zPrior, in); }else{ zPrompt = isContinuation ? continuePrompt : mainPrompt; #if defined(HAVE_READLINE) && HAVE_READLINE==1 free(zPrior); zResult = readline(zPrompt); if( zResult && *zResult ) add_history(zResult); #else printf("%s", zPrompt); fflush(stdout); zResult = local_getline(zPrior, stdin); #endif } return zResult; } struct previous_mode_data { int valid; /* Is there legit data in here? */ int mode; int showHeader; |
︙ | ︙ | |||
1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 | if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){ char *zTable = azArg[2]; /* Insert data into this table */ char *zFile = azArg[1]; /* Name of file to extra content from */ sqlite3_stmt *pStmt = NULL; /* A statement */ int nCol; /* Number of columns in the table */ int nByte; /* Number of bytes in an SQL string */ int i, j; /* Loop counters */ int nSep; /* Number of bytes in p->separator[] */ char *zSql; /* An SQL statement */ CSVReader sCsv; /* Reader context */ int (*xCloser)(FILE*); /* Procedure to close th3 connection */ seenInterrupt = 0; memset(&sCsv, 0, sizeof(sCsv)); | > | 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 | if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){ char *zTable = azArg[2]; /* Insert data into this table */ char *zFile = azArg[1]; /* Name of file to extra content from */ sqlite3_stmt *pStmt = NULL; /* A statement */ int nCol; /* Number of columns in the table */ int nByte; /* Number of bytes in an SQL string */ int i, j; /* Loop counters */ int needCommit; /* True to COMMIT or ROLLBACK at end */ int nSep; /* Number of bytes in p->separator[] */ char *zSql; /* An SQL statement */ CSVReader sCsv; /* Reader context */ int (*xCloser)(FILE*); /* Procedure to close th3 connection */ seenInterrupt = 0; memset(&sCsv, 0, sizeof(sCsv)); |
︙ | ︙ | |||
2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 | sqlite3_free(zSql); if( rc ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); if (pStmt) sqlite3_finalize(pStmt); xCloser(sCsv.in); return 1; } do{ int startLine = sCsv.nLine; for(i=0; i<nCol; i++){ char *z = csv_read_one_field(&sCsv); if( z==0 && i==0 ) break; sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); if( i<nCol-1 && sCsv.cTerm!=sCsv.cSeparator ){ | > > | 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 | sqlite3_free(zSql); if( rc ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); if (pStmt) sqlite3_finalize(pStmt); xCloser(sCsv.in); return 1; } needCommit = sqlite3_get_autocommit(db); if( needCommit ) sqlite3_exec(db, "BEGIN", 0, 0, 0); do{ int startLine = sCsv.nLine; for(i=0; i<nCol; i++){ char *z = csv_read_one_field(&sCsv); if( z==0 && i==0 ) break; sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); if( i<nCol-1 && sCsv.cTerm!=sCsv.cSeparator ){ |
︙ | ︙ | |||
2128 2129 2130 2131 2132 2133 2134 | } } }while( sCsv.cTerm!=EOF ); xCloser(sCsv.in); sqlite3_free(sCsv.z); sqlite3_finalize(pStmt); | | | 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 | } } }while( sCsv.cTerm!=EOF ); xCloser(sCsv.in); sqlite3_free(sCsv.z); sqlite3_finalize(pStmt); if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0); }else if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){ struct callback_data data; char *zErrMsg = 0; open_db(p); memcpy(&data, p, sizeof(data)); |
︙ | ︙ | |||
2777 2778 2779 2780 2781 2782 2783 | return rc; } /* ** Return TRUE if a semicolon occurs anywhere in the first N characters ** of string z[]. */ | | | 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 | return rc; } /* ** Return TRUE if a semicolon occurs anywhere in the first N characters ** of string z[]. */ static int line_contains_semicolon(const char *z, int N){ int i; for(i=0; i<N; i++){ if( z[i]==';' ) return 1; } return 0; } /* ** Test to see if a line consists entirely of whitespace. |
︙ | ︙ | |||
2812 2813 2814 2815 2816 2817 2818 | } /* ** Return TRUE if the line typed in is an SQL command terminator other ** than a semi-colon. The SQL Server style "go" command is understood ** as is the Oracle "/". */ | | | | | > | > | | | | | | < | | | < < < < < | | > > | | | | > > > > > | | < > < < < < < < | | | | 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 | } /* ** Return TRUE if the line typed in is an SQL command terminator other ** than a semi-colon. The SQL Server style "go" command is understood ** as is the Oracle "/". */ static int line_is_command_terminator(const char *zLine){ while( IsSpace(zLine[0]) ){ zLine++; }; if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){ return 1; /* Oracle */ } if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' && _all_whitespace(&zLine[2]) ){ return 1; /* SQL Server */ } return 0; } /* ** Return true if zSql is a complete SQL statement. Return false if it ** ends in the middle of a string literal or C-style comment. */ static int line_is_complete(char *zSql, int nSql){ int rc; if( zSql==0 ) return 1; zSql[nSql] = ';'; zSql[nSql+1] = 0; rc = sqlite3_complete(zSql); zSql[nSql] = 0; return rc; } /* ** Read input from *in and process it. If *in==0 then input ** is interactive - the user is typing it it. Otherwise, input ** is coming from a file or device. A prompt is issued and history ** is saved only if input is interactive. An interrupt signal will ** cause this routine to exit immediately, unless input is interactive. ** ** Return the number of errors. */ static int process_input(struct callback_data *p, FILE *in){ char *zLine = 0; /* A single input line */ char *zSql = 0; /* Accumulated SQL text */ int nLine; /* Length of current line */ int nSql = 0; /* Bytes of zSql[] used */ int nAlloc = 0; /* Allocated zSql[] space */ int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */ char *zErrMsg; /* Error message returned */ int rc; /* Error code */ int errCnt = 0; /* Number of errors seen */ int lineno = 0; /* Current line number */ int startline = 0; /* Line number for start of current input */ while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){ fflush(p->out); zLine = one_input_line(in, zLine, nSql>0); if( zLine==0 ){ /* End of input */ if( stdin_is_interactive ) printf("\n"); break; } if( seenInterrupt ){ if( in!=0 ) break; seenInterrupt = 0; } lineno++; if( nSql==0 && _all_whitespace(zLine) ) continue; if( zLine && zLine[0]=='.' && nSql==0 ){ if( p->echoOn ) printf("%s\n", zLine); rc = do_meta_command(zLine, p); if( rc==2 ){ /* exit requested */ break; }else if( rc ){ errCnt++; } continue; } if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){ memcpy(zLine,";",2); } nLine = strlen30(zLine); if( nSql+nLine+2>=nAlloc ){ nAlloc = nSql+nLine+100; zSql = realloc(zSql, nAlloc); if( zSql==0 ){ fprintf(stderr, "Error: out of memory\n"); exit(1); } } nSqlPrior = nSql; if( nSql==0 ){ int i; for(i=0; zLine[i] && IsSpace(zLine[i]); i++){} memcpy(zSql, zLine+i, nLine+1-i); startline = lineno; nSql = nLine-i; }else{ zSql[nSql++] = '\n'; memcpy(zSql+nSql, zLine, nLine+1); nSql += nLine; } if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) && sqlite3_complete(zSql) ){ p->cnt = 0; open_db(p); BEGIN_TIMER; rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); END_TIMER; if( rc || zErrMsg ){ |
︙ | ︙ | |||
2935 2936 2937 2938 2939 2940 2941 | sqlite3_free(zErrMsg); zErrMsg = 0; }else{ fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); } errCnt++; } | < < | < < | | 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 | sqlite3_free(zErrMsg); zErrMsg = 0; }else{ fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); } errCnt++; } nSql = 0; }else if( nSql && _all_whitespace(zSql) ){ nSql = 0; } } if( nSql ){ if( !_all_whitespace(zSql) ){ fprintf(stderr, "Error: incomplete SQL: %s\n", zSql); } free(zSql); } free(zLine); return errCnt>0; |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
7224 7225 7226 7227 7228 7229 7230 | #ifdef SQLITE_OMIT_FLOATING_POINT # undef double #endif #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif | | | 7224 7225 7226 7227 7228 7229 7230 7231 | #ifdef SQLITE_OMIT_FLOATING_POINT # undef double #endif #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif /* _SQLITE3_H_ */ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 | #define OE_Default 99 /* Do whatever the default action is */ /* ** An instance of the following structure is passed as the first ** argument to sqlite3VdbeKeyCompare and is used to control the ** comparison of the two index keys. */ struct KeyInfo { sqlite3 *db; /* The database connection */ u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ | > > > > | | | 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 | #define OE_Default 99 /* Do whatever the default action is */ /* ** An instance of the following structure is passed as the first ** argument to sqlite3VdbeKeyCompare and is used to control the ** comparison of the two index keys. ** ** Note that aSortOrder[] and aColl[] have nField+1 slots. There ** are nField slots for the columns of an index then one extra slot ** for the rowid at the end. */ struct KeyInfo { sqlite3 *db; /* The database connection */ u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ u16 nField; /* Maximum index for aColl[] and aSortOrder[] */ u8 *aSortOrder; /* Sort order for each column. */ CollSeq *aColl[1]; /* Collating sequence for each term of the key */ }; /* ** An instance of the following structure holds information about a ** single index record that has already been parsed out into individual ** values. |
︙ | ︙ | |||
2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 | #define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */ #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ #define SF_UseSorter 0x0040 /* Sort using a sorter */ #define SF_Values 0x0080 /* Synthesized from VALUES clause */ #define SF_Materialize 0x0100 /* Force materialization of views */ #define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */ /* ** The results of a select can be distributed in several ways. The ** "SRT" prefix means "SELECT Result Type". */ #define SRT_Union 1 /* Store result as keys in an index */ | > | 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 | #define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */ #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ #define SF_UseSorter 0x0040 /* Sort using a sorter */ #define SF_Values 0x0080 /* Synthesized from VALUES clause */ #define SF_Materialize 0x0100 /* Force materialization of views */ #define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */ #define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */ /* ** The results of a select can be distributed in several ways. The ** "SRT" prefix means "SELECT Result Type". */ #define SRT_Union 1 /* Store result as keys in an index */ |
︙ | ︙ | |||
2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 | u8 nested; /* Number of nested calls to the parser/code generator */ u8 nTempReg; /* Number of temporary registers in aTempReg[] */ u8 nTempInUse; /* Number of aTempReg[] currently checked out */ u8 nColCache; /* Number of entries in aColCache[] */ u8 iColCache; /* Next entry in aColCache[] to replace */ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ int aTempReg[8]; /* Holding area for temporary registers */ int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ | > | 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 | u8 nested; /* Number of nested calls to the parser/code generator */ u8 nTempReg; /* Number of temporary registers in aTempReg[] */ u8 nTempInUse; /* Number of aTempReg[] currently checked out */ u8 nColCache; /* Number of entries in aColCache[] */ u8 iColCache; /* Next entry in aColCache[] to replace */ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ int aTempReg[8]; /* Holding area for temporary registers */ int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ |
︙ | ︙ | |||
3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 | void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); void sqlite3MinimumFileFormat(Parse*, int, int); void sqlite3SchemaClear(void *); Schema *sqlite3SchemaGet(sqlite3 *, Btree *); int sqlite3SchemaToIndex(sqlite3 *db, Schema *); KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *); int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), FuncDestructor *pDestructor ); int sqlite3ApiExit(sqlite3 *db, int); | > | 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 | void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); void sqlite3MinimumFileFormat(Parse*, int, int); void sqlite3SchemaClear(void *); Schema *sqlite3SchemaGet(sqlite3 *, Btree *); int sqlite3SchemaToIndex(sqlite3 *db, Schema *); KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int); KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *); int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), FuncDestructor *pDestructor ); int sqlite3ApiExit(sqlite3 *db, int); |
︙ | ︙ |
Changes to src/test_autoext.c.
︙ | ︙ | |||
204 205 206 207 208 209 210 | #ifndef SQLITE_OMIT_LOAD_EXTENSION Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_sqr", autoExtSqrObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_cube", autoExtCubeObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_broken", autoExtBrokenObjCmd, 0, 0); | < > | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | #ifndef SQLITE_OMIT_LOAD_EXTENSION Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_sqr", autoExtSqrObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_cube", autoExtCubeObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_broken", autoExtBrokenObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_cancel_auto_extension_sqr", cancelAutoExtSqrObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_cancel_auto_extension_cube", cancelAutoExtCubeObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_cancel_auto_extension_broken", cancelAutoExtBrokenObjCmd, 0, 0); #endif Tcl_CreateObjCommand(interp, "sqlite3_reset_auto_extension", resetAutoExtObjCmd, 0, 0); return TCL_OK; } |
Changes to src/test_demovfs.c.
︙ | ︙ | |||
532 533 534 535 536 537 538 | int nPathOut, /* Size of output buffer in bytes */ char *zPathOut /* Pointer to output buffer */ ){ char zDir[MAXPATHNAME+1]; if( zPath[0]=='/' ){ zDir[0] = '\0'; }else{ | | | 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 | int nPathOut, /* Size of output buffer in bytes */ char *zPathOut /* Pointer to output buffer */ ){ char zDir[MAXPATHNAME+1]; if( zPath[0]=='/' ){ zDir[0] = '\0'; }else{ if( getcwd(zDir, sizeof(zDir))==0 ) return SQLITE_IOERR; } zDir[MAXPATHNAME] = '\0'; sqlite3_snprintf(nPathOut, zPathOut, "%s/%s", zDir, zPath); zPathOut[nPathOut-1] = '\0'; return SQLITE_OK; |
︙ | ︙ |
Changes to src/test_fs.c.
︙ | ︙ | |||
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 | assert( i==0 || i==1 ); if( i==0 ){ sqlite3_result_value(ctx, sqlite3_column_value(pCur->pStmt, 0)); }else{ const char *zFile = (const char *)sqlite3_column_text(pCur->pStmt, 1); struct stat sbuf; int fd; fd = open(zFile, O_RDONLY); if( fd<0 ) return SQLITE_IOERR; fstat(fd, &sbuf); if( sbuf.st_size>=pCur->nAlloc ){ int nNew = sbuf.st_size*2; char *zNew; if( nNew<1024 ) nNew = 1024; zNew = sqlite3Realloc(pCur->zBuf, nNew); if( zNew==0 ){ close(fd); return SQLITE_NOMEM; } pCur->zBuf = zNew; pCur->nAlloc = nNew; } | > | > | 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 | assert( i==0 || i==1 ); if( i==0 ){ sqlite3_result_value(ctx, sqlite3_column_value(pCur->pStmt, 0)); }else{ const char *zFile = (const char *)sqlite3_column_text(pCur->pStmt, 1); struct stat sbuf; int fd; int n; fd = open(zFile, O_RDONLY); if( fd<0 ) return SQLITE_IOERR; fstat(fd, &sbuf); if( sbuf.st_size>=pCur->nAlloc ){ int nNew = sbuf.st_size*2; char *zNew; if( nNew<1024 ) nNew = 1024; zNew = sqlite3Realloc(pCur->zBuf, nNew); if( zNew==0 ){ close(fd); return SQLITE_NOMEM; } pCur->zBuf = zNew; pCur->nAlloc = nNew; } n = (int)read(fd, pCur->zBuf, sbuf.st_size); close(fd); if( n!=sbuf.st_size ) return SQLITE_ERROR; pCur->nBuf = sbuf.st_size; pCur->zBuf[pCur->nBuf] = '\0'; sqlite3_result_text(ctx, pCur->zBuf, -1, SQLITE_TRANSIENT); } return SQLITE_OK; } |
︙ | ︙ |
Changes to src/test_intarray.h.
︙ | ︙ | |||
71 72 73 74 75 76 77 78 79 80 81 82 83 84 | ** The intarray object is automatically destroyed when its corresponding ** virtual table is dropped. Since the virtual tables are created in the ** TEMP database, they are automatically dropped when the database connection ** closes so the application does not normally need to take any special ** action to free the intarray objects. */ #include "sqlite3.h" /* ** Make sure we can call this stuff from C++. */ #ifdef __cplusplus extern "C" { #endif | > > | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | ** The intarray object is automatically destroyed when its corresponding ** virtual table is dropped. Since the virtual tables are created in the ** TEMP database, they are automatically dropped when the database connection ** closes so the application does not normally need to take any special ** action to free the intarray objects. */ #include "sqlite3.h" #ifndef _INTARRAY_H_ #define _INTARRAY_H_ /* ** Make sure we can call this stuff from C++. */ #ifdef __cplusplus extern "C" { #endif |
︙ | ︙ | |||
119 120 121 122 123 124 125 | sqlite3_int64 *aElements, /* Content of the intarray */ void (*xFree)(void*) /* How to dispose of the intarray when done */ ); #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif | > | 121 122 123 124 125 126 127 128 | sqlite3_int64 *aElements, /* Content of the intarray */ void (*xFree)(void*) /* How to dispose of the intarray when done */ ); #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif /* _INTARRAY_H_ */ |
Changes to src/test_multiplex.h.
︙ | ︙ | |||
92 93 94 95 96 97 98 | */ extern int sqlite3_multiplex_shutdown(void); #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif | | | 92 93 94 95 96 97 98 99 | */ extern int sqlite3_multiplex_shutdown(void); #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif /* _TEST_MULTIPLEX_H */ |
Changes to src/test_rtree.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. */ #include <sqlite3.h> /* Solely for the UNUSED_PARAMETER() macro. */ #include "sqliteInt.h" #ifdef SQLITE_ENABLE_RTREE /* ** Type used to cache parameter information for the "circle" r-tree geometry | > | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. */ #include <sqlite3.h> #include <tcl.h> /* Solely for the UNUSED_PARAMETER() macro. */ #include "sqliteInt.h" #ifdef SQLITE_ENABLE_RTREE /* ** Type used to cache parameter information for the "circle" r-tree geometry |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
551 552 553 554 555 556 557 | int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ int iCompare = 0; /* Result of last OP_Compare operation */ unsigned nVmStep = 0; /* Number of virtual machine steps */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK | | | 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 | int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ int iCompare = 0; /* Result of last OP_Compare operation */ unsigned nVmStep = 0; /* Number of virtual machine steps */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */ #endif Mem *aMem = p->aMem; /* Copy of p->aMem */ Mem *pIn1 = 0; /* 1st input operand */ Mem *pIn2 = 0; /* 2nd input operand */ Mem *pIn3 = 0; /* 3rd input operand */ Mem *pOut = 0; /* Output operand */ int *aPermute = 0; /* Permutation of columns for OP_Compare */ |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
403 404 405 406 407 408 409 | Op *pOp; int *aLabel = p->aLabel; p->readOnly = 1; p->bIsReader = 0; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ u8 opcode = pOp->opcode; | > > | | > | > > | | < > > | > | < < > > | < > > | | > > | | > > | | | | | | > > > | | | > > | | | > | | > > | 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 | Op *pOp; int *aLabel = p->aLabel; p->readOnly = 1; p->bIsReader = 0; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ u8 opcode = pOp->opcode; /* NOTE: Be sure to update mkopcodeh.awk when adding or removing ** cases from this switch! */ switch( opcode ){ case OP_Function: case OP_AggStep: { if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5; break; } case OP_Transaction: { if( pOp->p2!=0 ) p->readOnly = 0; /* fall thru */ } case OP_AutoCommit: case OP_Savepoint: { p->bIsReader = 1; break; } #ifndef SQLITE_OMIT_WAL case OP_Checkpoint: #endif case OP_Vacuum: case OP_JournalMode: { p->readOnly = 0; p->bIsReader = 1; break; } #ifndef SQLITE_OMIT_VIRTUALTABLE case OP_VUpdate: { if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; break; } case OP_VFilter: { int n; assert( p->nOp - i >= 3 ); assert( pOp[-1].opcode==OP_Integer ); n = pOp[-1].p1; if( n>nMaxArgs ) nMaxArgs = n; break; } #endif case OP_Next: case OP_SorterNext: { pOp->p4.xAdvance = sqlite3BtreeNext; pOp->p4type = P4_ADVANCE; break; } case OP_Prev: { pOp->p4.xAdvance = sqlite3BtreePrevious; pOp->p4type = P4_ADVANCE; break; } } pOp->opflags = sqlite3OpcodeProperty[opcode]; if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){ assert( -1-pOp->p2<p->nLabel ); pOp->p2 = aLabel[-1-pOp->p2]; } } sqlite3DbFree(p->db, p->aLabel); p->aLabel = 0; |
︙ | ︙ | |||
725 726 727 728 729 730 731 | ** that was cast to a (const char *). */ pOp->p4.i = SQLITE_PTR_TO_INT(zP4); pOp->p4type = P4_INT32; }else if( zP4==0 ){ pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; }else if( n==P4_KEYINFO ){ | | < | < < | | < | | < < < | 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 | ** that was cast to a (const char *). */ pOp->p4.i = SQLITE_PTR_TO_INT(zP4); pOp->p4type = P4_INT32; }else if( zP4==0 ){ pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; }else if( n==P4_KEYINFO ){ KeyInfo *pOrig, *pNew; pOrig = (KeyInfo*)zP4; pOp->p4.pKeyInfo = pNew = sqlite3KeyInfoAlloc(db, pOrig->nField); if( pNew ){ memcpy(pNew->aColl, pOrig->aColl, pOrig->nField*sizeof(pNew->aColl[0])); memcpy(pNew->aSortOrder, pOrig->aSortOrder, pOrig->nField); pOp->p4type = P4_KEYINFO; }else{ p->db->mallocFailed = 1; pOp->p4type = P4_NOTUSED; } }else if( n==P4_KEYINFO_HANDOFF ){ pOp->p4.p = (void*)zP4; |
︙ | ︙ | |||
2989 2990 2991 2992 2993 2994 2995 | int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2 /* Right key */ ){ u32 d1; /* Offset into aKey[] of next data element */ u32 idx1; /* Offset into aKey[] of next header element */ u32 szHdr1; /* Number of bytes in header */ int i = 0; | < | 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 | int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2 /* Right key */ ){ u32 d1; /* Offset into aKey[] of next data element */ u32 idx1; /* Offset into aKey[] of next header element */ u32 szHdr1; /* Number of bytes in header */ int i = 0; int rc = 0; const unsigned char *aKey1 = (const unsigned char *)pKey1; KeyInfo *pKeyInfo; Mem mem1; pKeyInfo = pPKey2->pKeyInfo; mem1.enc = pKeyInfo->enc; |
︙ | ︙ | |||
3012 3013 3014 3015 3016 3017 3018 | ** impact, since this routine is a very high runner. And so, we choose ** to ignore the compiler warnings and leave this variable uninitialized. */ /* mem1.u.i = 0; // not needed, here to silence compiler warning */ idx1 = getVarint32(aKey1, szHdr1); d1 = szHdr1; | | > > > > > > > > | > > > | < | | 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 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 | ** impact, since this routine is a very high runner. And so, we choose ** to ignore the compiler warnings and leave this variable uninitialized. */ /* mem1.u.i = 0; // not needed, here to silence compiler warning */ idx1 = getVarint32(aKey1, szHdr1); d1 = szHdr1; assert( pKeyInfo->nField+1>=pPKey2->nField ); assert( pKeyInfo->aSortOrder!=0 ); while( idx1<szHdr1 && i<pPKey2->nField ){ u32 serial_type1; /* Read the serial types for the next element in each key. */ idx1 += getVarint32( aKey1+idx1, serial_type1 ); /* Verify that there is enough key space remaining to avoid ** a buffer overread. The "d1+serial_type1+2" subexpression will ** always be greater than or equal to the amount of required key space. ** Use that approximation to avoid the more expensive call to ** sqlite3VdbeSerialTypeLen() in the common case. */ if( d1+serial_type1+2>(u32)nKey1 && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1 ){ break; } /* Extract the values to be compared. */ d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); /* Do the comparison */ rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]); if( rc!=0 ){ assert( mem1.zMalloc==0 ); /* See comment below */ /* Invert the result if we are using DESC sort order. */ if( pKeyInfo->aSortOrder[i] ){ rc = -rc; } /* If the PREFIX_SEARCH flag is set and all fields except the final ** rowid field were equal, then clear the PREFIX_SEARCH flag and set ** pPKey2->rowid to the value of the rowid field in (pKey1, nKey1). ** This is used by the OP_IsUnique opcode. |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
29 30 31 32 33 34 35 | && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) # define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X # define WHERETRACE_ENABLED 1 #else # define WHERETRACE(K,X) #endif | | | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) # define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X # define WHERETRACE_ENABLED 1 #else # define WHERETRACE(K,X) #endif /* Forward references */ typedef struct WhereClause WhereClause; typedef struct WhereMaskSet WhereMaskSet; typedef struct WhereOrInfo WhereOrInfo; typedef struct WhereAndInfo WhereAndInfo; typedef struct WhereLevel WhereLevel; typedef struct WhereLoop WhereLoop; |
︙ | ︙ | |||
51 52 53 54 55 56 57 | /* ** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The ** maximum cost for ordinary tables is 64*(2**63) which becomes 6900. ** (Virtual tables can return a larger cost, but let's assume they do not.) ** So all costs can be stored in a 16-bit unsigned integer without risk ** of overflow. ** | | | | | | | > | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | /* ** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The ** maximum cost for ordinary tables is 64*(2**63) which becomes 6900. ** (Virtual tables can return a larger cost, but let's assume they do not.) ** So all costs can be stored in a 16-bit unsigned integer without risk ** of overflow. ** ** Costs are estimates, so no effort is made to compute 10*log2(X) exactly. ** Instead, a close estimate is used. Any value of X<=1 is stored as 0. ** X=2 is 10. X=3 is 16. X=1000 is 99. etc. ** ** The tool/wherecosttest.c source file implements a command-line program ** that will convert WhereCosts to integers, convert integers to WhereCosts ** and do addition and multiplication on WhereCost values. The wherecosttest ** command-line program is a useful utility to have around when working with ** this module. */ typedef unsigned short int WhereCost; /* ** This object contains information needed to implement a single nested ** loop in WHERE clause. ** |
︙ | ︙ | |||
161 162 163 164 165 166 167 | struct WhereOrCost { Bitmask prereq; /* Prerequisites */ WhereCost rRun; /* Cost of running this subquery */ WhereCost nOut; /* Number of outputs for this subquery */ }; /* The WhereOrSet object holds a set of possible WhereOrCosts that | | | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | struct WhereOrCost { Bitmask prereq; /* Prerequisites */ WhereCost rRun; /* Cost of running this subquery */ WhereCost nOut; /* Number of outputs for this subquery */ }; /* The WhereOrSet object holds a set of possible WhereOrCosts that ** correspond to the subquery(s) of OR-clause processing. Only the ** best N_OR_COST elements are retained. */ #define N_OR_COST 3 struct WhereOrSet { u16 n; /* Number of valid a[] entries */ WhereOrCost a[N_OR_COST]; /* Set of best costs */ }; |
︙ | ︙ | |||
228 229 230 231 232 233 234 | ** use of a bitmask encoding for the operator allows us to search ** quickly for terms that match any of several different operators. ** ** A WhereTerm might also be two or more subterms connected by OR: ** ** (t1.X <op> <expr>) OR (t1.Y <op> <expr>) OR .... ** | | | | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | ** use of a bitmask encoding for the operator allows us to search ** quickly for terms that match any of several different operators. ** ** A WhereTerm might also be two or more subterms connected by OR: ** ** (t1.X <op> <expr>) OR (t1.Y <op> <expr>) OR .... ** ** In this second case, wtFlag has the TERM_ORINFO bit set and eOperator==WO_OR ** and the WhereTerm.u.pOrInfo field points to auxiliary information that ** is collected about the OR clause. ** ** If a term in the WHERE clause does not match either of the two previous ** categories, then eOperator==0. The WhereTerm.pExpr field is still set ** to the original subexpression content and wtFlags is set up appropriately ** but no other fields in the WhereTerm object are meaningful. ** ** When eOperator!=0, prereqRight and prereqAll record sets of cursor numbers, |
︙ | ︙ | |||
747 748 749 750 751 752 753 | */ static void createMask(WhereMaskSet *pMaskSet, int iCursor){ assert( pMaskSet->n < ArraySize(pMaskSet->ix) ); pMaskSet->ix[pMaskSet->n++] = iCursor; } /* | | | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 | */ static void createMask(WhereMaskSet *pMaskSet, int iCursor){ assert( pMaskSet->n < ArraySize(pMaskSet->ix) ); pMaskSet->ix[pMaskSet->n++] = iCursor; } /* ** These routines walk (recursively) an expression tree and generate ** a bitmask indicating which tables are used in that expression ** tree. */ static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*); static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*); static Bitmask exprTableUsage(WhereMaskSet *pMaskSet, Expr *p){ Bitmask mask = 0; |
︙ | ︙ | |||
1264 1265 1266 1267 1268 1269 1270 | ** subsubterms at least one of which is indexable. Indexable AND ** subterms have their eOperator set to WO_AND and they have ** u.pAndInfo set to a dynamically allocated WhereAndTerm object. ** ** From another point of view, "indexable" means that the subterm could ** potentially be used with an index if an appropriate index exists. ** This analysis does not consider whether or not the index exists; that | | | | | 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 | ** subsubterms at least one of which is indexable. Indexable AND ** subterms have their eOperator set to WO_AND and they have ** u.pAndInfo set to a dynamically allocated WhereAndTerm object. ** ** From another point of view, "indexable" means that the subterm could ** potentially be used with an index if an appropriate index exists. ** This analysis does not consider whether or not the index exists; that ** is decided elsewhere. This analysis only looks at whether subterms ** appropriate for indexing exist. ** ** All examples A through E above satisfy case 2. But if a term ** also statisfies case 1 (such as B) we know that the optimizer will ** always prefer case 1, so in that case we pretend that case 2 is not ** satisfied. ** ** It might be the case that multiple tables are indexable. For example, ** (E) above is indexable on tables P, Q, and R. ** |
︙ | ︙ | |||
1934 1935 1936 1937 1938 1939 1940 | } } return 0; } /* | | | 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 | } } return 0; } /* ** Find (an approximate) sum of two WhereCosts. This computation is ** not a simple "+" operator because WhereCost is stored as a logarithmic ** value. ** */ static WhereCost whereCostAdd(WhereCost a, WhereCost b){ static const unsigned char x[] = { 10, 10, /* 0,1 */ |
︙ | ︙ |
Changes to test/index6.test.
︙ | ︙ | |||
140 141 142 143 144 145 146 | } {800} do_test index6-2.2 { execsql { EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE a=5; } } {/.* TABLE t2 USING INDEX t2a1 .*/} | > | | | | | | > > > > > > > > | 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 | } {800} do_test index6-2.2 { execsql { EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE a=5; } } {/.* TABLE t2 USING INDEX t2a1 .*/} ifcapable stat4 { do_test index6-2.3stat4 { execsql { EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE a IS NOT NULL; } } {/.* TABLE t2 USING INDEX t2a1 .*/} } else { do_test index6-2.3stat4 { execsql { EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE a IS NOT NULL AND a>0; } } {/.* TABLE t2 USING INDEX t2a1 .*/} } do_test index6-2.4 { execsql { EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE a IS NULL; } } {~/.*INDEX t2a1.*/} |
︙ | ︙ |