Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Bug fix: The IN operator was not working if either side derived from an INTEGER PRIMARY KEY. (CVS 354) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
dbcfe198fbaa155874ef82a96b6a4b99 |
User & Date: | drh 2002-01-28 15:53:04.000 |
Context
2002-01-28
| ||
16:00 | Version 2.2.5 (CVS 448) (check-in: af3bb80810 user: drh tags: trunk) | |
15:53 | Bug fix: The IN operator was not working if either side derived from an INTEGER PRIMARY KEY. (CVS 354) (check-in: dbcfe198fb user: drh tags: trunk) | |
2002-01-24
| ||
00:00 | Do not escape the backslash character in shell output. (CVS 353) (check-in: 5f8c097ebe user: drh tags: trunk) | |
Changes
Changes to VERSION.
|
| | | 1 | 2.2.5 |
Changes to src/build.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.66 2002/01/28 15:53:05 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called after a single SQL statement has been ** parsed and we want to execute the VDBE code to implement |
︙ | ︙ | |||
726 727 728 729 730 731 732 | addr = sqliteVdbeAddOp(v, OP_CreateTable, 0, p->isTemp); sqliteVdbeChangeP3(v, addr, (char *)&p->tnum, P3_POINTER); p->tnum = 0; if( !p->isTemp ){ addr = sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeChangeP3(v, addr, pParse->sFirstToken.z, n); sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); | | | 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 | addr = sqliteVdbeAddOp(v, OP_CreateTable, 0, p->isTemp); sqliteVdbeChangeP3(v, addr, (char *)&p->tnum, P3_POINTER); p->tnum = 0; if( !p->isTemp ){ addr = sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeChangeP3(v, addr, pParse->sFirstToken.z, n); sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); changeCookie(db); sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0); sqliteVdbeAddOp(v, OP_Close, 0, 0); } if( (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Commit, 0, 0); } |
︙ | ︙ | |||
1070 1071 1072 1073 1074 1075 1076 | if( !isTemp ){ addr = sqliteVdbeAddOp(v, OP_String, 0, 0); if( pStart && pEnd ){ n = Addr(pEnd->z) - Addr(pStart->z) + 1; sqliteVdbeChangeP3(v, addr, pStart->z, n); } sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); | | | 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 | if( !isTemp ){ addr = sqliteVdbeAddOp(v, OP_String, 0, 0); if( pStart && pEnd ){ n = Addr(pEnd->z) - Addr(pStart->z) + 1; sqliteVdbeChangeP3(v, addr, pStart->z, n); } sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); } if( pTable ){ sqliteVdbeAddOp(v, isTemp ? OP_OpenAux : OP_Open, 2, pTab->tnum); sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC); lbl2 = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2); lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0); |
︙ | ︙ | |||
1379 1380 1381 1382 1383 1384 1385 | ** value is always pulled from the record number */ sqliteVdbeAddOp(v, OP_String, 0, 0); }else{ sqliteVdbeAddOp(v, OP_FileColumn, i, 0); } } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); | | | 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 | ** value is always pulled from the record number */ sqliteVdbeAddOp(v, OP_String, 0, 0); }else{ sqliteVdbeAddOp(v, OP_FileColumn, i, 0); } } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( pIdx->pNext ){ sqliteVdbeAddOp(v, OP_Dup, 0, 0); } for(j=0; j<pIdx->nColumn; j++){ sqliteVdbeAddOp(v, OP_FileColumn, pIdx->aiColumn[j], 0); } |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** ** $Id: insert.c,v 1.33 2002/01/28 15:53:05 drh Exp $ */ #include "sqliteInt.h" /* ** This routine is call to handle SQL of the following forms: ** ** insert into TABLE (IDLIST) values(EXPRLIST) |
︙ | ︙ | |||
248 249 250 251 252 253 254 | sqliteExprCode(pParse, pList->a[j].pExpr); } } /* Create the new record and put it into the database. */ sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); | | | 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | sqliteExprCode(pParse, pList->a[j].pExpr); } } /* Create the new record and put it into the database. */ sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqliteVdbeAddOp(v, OP_PutIntKey, base, keyColumn>=0); /* Create appropriate entries for the new data row in all indices ** of the table. */ for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ if( pIdx->pNext ){ sqliteVdbeAddOp(v, OP_Dup, 0, 0); |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** ** $Id: select.c,v 1.56 2002/01/28 15:53:05 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. */ |
︙ | ︙ | |||
126 127 128 129 130 131 132 | int lbl = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1); sqliteVdbeAddOp(v, OP_Distinct, distinct, lbl); sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, iContinue); sqliteVdbeResolveLabel(v, lbl); sqliteVdbeAddOp(v, OP_String, 0, 0); | | | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | int lbl = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1); sqliteVdbeAddOp(v, OP_Distinct, distinct, lbl); sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, iContinue); sqliteVdbeResolveLabel(v, lbl); sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0); } /* If there is an ORDER BY clause, then store the results ** in a sorter. */ if( pOrderBy ){ char *zSortOrder; |
︙ | ︙ | |||
154 155 156 157 158 159 160 | /* In this mode, write each query result to the key of the temporary ** table iParm. */ if( eDest==SRT_Union ){ sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqliteVdbeAddOp(v, OP_String, iParm, 0); | | | | | 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 | /* In this mode, write each query result to the key of the temporary ** table iParm. */ if( eDest==SRT_Union ){ sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqliteVdbeAddOp(v, OP_String, iParm, 0); sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0); }else /* Store the result as data using a unique key. */ if( eDest==SRT_Table ){ sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0); sqliteVdbeAddOp(v, OP_Pull, 1, 0); sqliteVdbeAddOp(v, OP_PutIntKey, iParm, 0); }else /* Construct a record from the query result, but instead of ** saving that record, use it as a key to delete elements from ** the temporary table iParm. */ if( eDest==SRT_Except ){ int addr = sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqliteVdbeAddOp(v, OP_NotFound, iParm, addr+3); sqliteVdbeAddOp(v, OP_Delete, iParm, 0); }else /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ if( eDest==SRT_Set ){ assert( nColumn==1 ); sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0); }else /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out ** of the scan loop. */ |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** ** $Id: update.c,v 1.28 2002/01/28 15:53:05 drh Exp $ */ #include "sqliteInt.h" /* ** Process an UPDATE statement. */ void sqliteUpdate( |
︙ | ︙ | |||
261 262 263 264 265 266 267 | sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); sqliteVdbeAddOp(v, OP_IdxPut, base+i+1, pIdx->isUnique); } /* Write the new data back into the database. */ sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); | | | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); sqliteVdbeAddOp(v, OP_IdxPut, base+i+1, pIdx->isUnique); } /* Write the new data back into the database. */ sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqliteVdbeAddOp(v, OP_PutIntKey, base, 0); /* Increment the count of rows affected by the update */ if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_AddImm, 1, 0); } |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.108 2002/01/28 15:53:05 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_MoveTo or the OP_Next opcode. The test |
︙ | ︙ | |||
848 849 850 851 852 853 854 | ** "opNames.awk" awk script which is part of the source tree to regenerate ** this array, then copy and paste it into this file, if you want. */ static char *zOpName[] = { 0, "Transaction", "Commit", "Rollback", "ReadCookie", "SetCookie", "VerifyCookie", "Open", "OpenTemp", "OpenWrite", "OpenAux", "OpenWrAux", "Close", | | | > | | | | | | | | | | | | | | | | | | | | | | | | 848 849 850 851 852 853 854 855 856 857 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 | ** "opNames.awk" awk script which is part of the source tree to regenerate ** this array, then copy and paste it into this file, if you want. */ static char *zOpName[] = { 0, "Transaction", "Commit", "Rollback", "ReadCookie", "SetCookie", "VerifyCookie", "Open", "OpenTemp", "OpenWrite", "OpenAux", "OpenWrAux", "Close", "MoveTo", "NewRecno", "PutIntKey", "PutStrKey", "Distinct", "Found", "NotFound", "NotExists", "Delete", "Column", "KeyAsData", "Recno", "FullKey", "Rewind", "Next", "Destroy", "Clear", "CreateIndex", "CreateTable", "Reorganize", "IdxPut", "IdxDelete", "IdxRecno", "IdxGT", "IdxGE", "MemLoad", "MemStore", "ListWrite", "ListRewind", "ListRead", "ListReset", "SortPut", "SortMakeRec", "SortMakeKey", "Sort", "SortNext", "SortCallback", "SortReset", "FileOpen", "FileRead", "FileColumn", "AggReset", "AggFocus", "AggIncr", "AggNext", "AggSet", "AggGet", "SetInsert", "SetFound", "SetNotFound", "MakeRecord", "MakeKey", "MakeIdxKey", "IncrKey", "Goto", "If", "Halt", "ColumnCount", "ColumnName", "Callback", "NullCallback", "Integer", "String", "Pop", "Dup", "Pull", "MustBeInt", "Add", "AddImm", "Subtract", "Multiply", "Divide", "Remainder", "BitAnd", "BitOr", "BitNot", "ShiftLeft", "ShiftRight", "AbsValue", "Precision", "Min", "Max", "Like", "Glob", "Eq", "Ne", "Lt", "Le", "Gt", "Ge", "IsNull", "NotNull", "Negative", "And", "Or", "Not", "Concat", "Noop", "Strlen", "Substr", "Limit", }; /* ** Given the name of an opcode, return its number. Return 0 if ** there is no match. ** ** This routine is used for testing and debugging. |
︙ | ︙ | |||
2641 2642 2643 2644 2645 2646 2647 | } POPSTACK; break; } /* Opcode: Distinct P1 P2 * ** | | | | | < < < < | | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 | } POPSTACK; break; } /* Opcode: Distinct P1 P2 * ** ** Use the top of the stack as a string key. If a record with that key does ** not exist in the table of cursor P1, then jump to P2. If the record ** does already exist, then fall thru. The cursor is left pointing ** at the record if it exists. The key is not popped from the stack. ** ** This operation is similar to NotFound except that this operation ** does not pop the key from the stack. ** ** See also: Found, NotFound, MoveTo */ /* Opcode: Found P1 P2 * ** ** Use the top of the stack as a string key. If a record with that key ** does exist in table of P1, then jump to P2. If the record ** does not exist, then fall thru. The cursor is left pointing ** to the record if it exists. The key is popped from the stack. ** ** See also: Distinct, NotFound, MoveTo */ /* Opcode: NotFound P1 P2 * ** ** Use the top of the stack as a string key. If a record with that key ** does not exist in table of P1, then jump to P2. If the record ** does exist, then fall thru. The cursor is left pointing to the ** record if it exists. The key is popped from the stack. ** ** The difference between this operation and Distinct is that ** Distinct does not pop the key from the stack. ** ** See also: Distinct, Found, MoveTo, NotExists */ case OP_Distinct: case OP_NotFound: case OP_Found: { int i = pOp->p1; int tos = p->tos; int alreadyExists = 0; Cursor *pC; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){ int res, rx; if( Stringify(p, tos) ) goto no_mem; rx = sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res); alreadyExists = rx==SQLITE_OK && res==0; } if( pOp->opcode==OP_Found ){ if( alreadyExists ) pc = pOp->p2 - 1; }else{ if( !alreadyExists ) pc = pOp->p2 - 1; } if( pOp->opcode!=OP_Distinct ){ POPSTACK; } break; } /* Opcode: NotExists P1 P2 * ** ** Use the top of the stack as a integer key. If a record with that key ** does not exist in table of P1, then jump to P2. If the record ** does exist, then fall thru. The cursor is left pointing to the ** record if it exists. The integer key is popped from the stack. ** ** The difference between this operation and NotFound is that this ** operation assumes the key is an integer and NotFound assumes it ** is a string. ** ** See also: Distinct, Found, MoveTo, NotExists */ case OP_NotExists: { int i = pOp->p1; int tos = p->tos; int alreadyExists = 0; Cursor *pC; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){ int res, rx, iKey; assert( aStack[tos].flags & STK_Int ); iKey = intToKey(aStack[tos].i); rx = sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res); if( rx!=SQLITE_OK || res!=0 ){ pc = pOp->p2 - 1; } } POPSTACK; break; } /* Opcode: NewRecno P1 * * ** ** Get a new integer record number used as the key to a table. ** The record number is not previously used as a key in the database ** table that cursor P1 points to. The new record number is pushed ** onto the stack. |
︙ | ︙ | |||
2766 2767 2768 2769 2770 2771 2772 | VERIFY( NeedStack(p, p->tos+1); ) p->tos++; aStack[p->tos].i = v; aStack[p->tos].flags = STK_Int; break; } | | > > > > > > > > > > > | | | > | > | 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 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 | VERIFY( NeedStack(p, p->tos+1); ) p->tos++; aStack[p->tos].i = v; aStack[p->tos].flags = STK_Int; break; } /* Opcode: PutIK P1 P2 * ** ** Write an entry into the database file P1. A new entry is ** created if it doesn't already exist or the data for an existing ** entry is overwritten. The data is the value on the top of the ** stack. The key is the next value down on the stack. The key must ** be an integer. The stack is popped twice by this instruction. ** ** If P2==1 then overwriting is prohibited. If a prior entry with ** the same key exists, an SQLITE_CONSTRAINT exception is raised. */ /* Opcode: PutSK P1 P2 * ** ** Write an entry into the database file P1. A new entry is ** created if it doesn't already exist or the data for an existing ** entry is overwritten. The data is the value on the top of the ** stack. The key is the next value down on the stack. The key must ** be a string. The stack is popped twice by this instruction. ** ** If P2==1 then overwriting is prohibited. If a prior entry with ** the same key exists, an SQLITE_CONSTRAINT exception is raised. */ case OP_PutIntKey: case OP_PutStrKey: { int tos = p->tos; int nos = p->tos-1; int i = pOp->p1; VERIFY( if( nos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor!=0 ){ char *zKey; int nKey, iKey; if( pOp->opcode==OP_PutStrKey ){ if( Stringify(p, nos) ) goto no_mem; nKey = aStack[nos].n; zKey = zStack[nos]; }else{ assert( aStack[nos].flags & STK_Int ); nKey = sizeof(int); iKey = intToKey(aStack[nos].i); zKey = (char*)&iKey; db->lastRowid = aStack[nos].i; } if( pOp->p2 ){ int res; |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** ** $Id: vdbe.h,v 1.38 2002/01/28 15:53:05 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
80 81 82 83 84 85 86 | #define OP_OpenTemp 8 #define OP_OpenWrite 9 #define OP_OpenAux 10 #define OP_OpenWrAux 11 #define OP_Close 12 #define OP_MoveTo 13 #define OP_NewRecno 14 | | > | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 | #define OP_OpenTemp 8 #define OP_OpenWrite 9 #define OP_OpenAux 10 #define OP_OpenWrAux 11 #define OP_Close 12 #define OP_MoveTo 13 #define OP_NewRecno 14 #define OP_PutIntKey 15 #define OP_PutStrKey 16 #define OP_Distinct 17 #define OP_Found 18 #define OP_NotFound 19 #define OP_NotExists 20 #define OP_Delete 21 #define OP_Column 22 #define OP_KeyAsData 23 #define OP_Recno 24 #define OP_FullKey 25 #define OP_Rewind 26 #define OP_Next 27 #define OP_Destroy 28 #define OP_Clear 29 #define OP_CreateIndex 30 #define OP_CreateTable 31 #define OP_Reorganize 32 #define OP_IdxPut 33 #define OP_IdxDelete 34 #define OP_IdxRecno 35 #define OP_IdxGT 36 #define OP_IdxGE 37 #define OP_MemLoad 38 #define OP_MemStore 39 #define OP_ListWrite 40 #define OP_ListRewind 41 #define OP_ListRead 42 #define OP_ListReset 43 #define OP_SortPut 44 #define OP_SortMakeRec 45 #define OP_SortMakeKey 46 #define OP_Sort 47 #define OP_SortNext 48 #define OP_SortCallback 49 #define OP_SortReset 50 #define OP_FileOpen 51 #define OP_FileRead 52 #define OP_FileColumn 53 #define OP_AggReset 54 #define OP_AggFocus 55 #define OP_AggIncr 56 #define OP_AggNext 57 #define OP_AggSet 58 #define OP_AggGet 59 #define OP_SetInsert 60 #define OP_SetFound 61 #define OP_SetNotFound 62 #define OP_MakeRecord 63 #define OP_MakeKey 64 #define OP_MakeIdxKey 65 #define OP_IncrKey 66 #define OP_Goto 67 #define OP_If 68 #define OP_Halt 69 #define OP_ColumnCount 70 #define OP_ColumnName 71 #define OP_Callback 72 #define OP_NullCallback 73 #define OP_Integer 74 #define OP_String 75 #define OP_Pop 76 #define OP_Dup 77 #define OP_Pull 78 #define OP_MustBeInt 79 #define OP_Add 80 #define OP_AddImm 81 #define OP_Subtract 82 #define OP_Multiply 83 #define OP_Divide 84 #define OP_Remainder 85 #define OP_BitAnd 86 #define OP_BitOr 87 #define OP_BitNot 88 #define OP_ShiftLeft 89 #define OP_ShiftRight 90 #define OP_AbsValue 91 #define OP_Precision 92 #define OP_Min 93 #define OP_Max 94 #define OP_Like 95 #define OP_Glob 96 #define OP_Eq 97 #define OP_Ne 98 #define OP_Lt 99 #define OP_Le 100 #define OP_Gt 101 #define OP_Ge 102 #define OP_IsNull 103 #define OP_NotNull 104 #define OP_Negative 105 #define OP_And 106 #define OP_Or 107 #define OP_Not 108 #define OP_Concat 109 #define OP_Noop 110 #define OP_Strlen 111 #define OP_Substr 112 #define OP_Limit 113 #define OP_MAX 113 /* ** Prototypes for the VDBE interface. See comments on the implementation ** for a description of what each of these routines does. */ Vdbe *sqliteVdbeCreate(sqlite*); void sqliteVdbeCreateCallback(Vdbe*, int*); |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. Also found here are subroutines ** to generate VDBE code to evaluate expressions. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. Also found here are subroutines ** to generate VDBE code to evaluate expressions. ** ** $Id: where.c,v 1.33 2002/01/28 15:53:05 drh Exp $ */ #include "sqliteInt.h" /* ** The query generator uses an array of instances of this structure to ** help it analyze the subexpressions of the WHERE clause. Each WHERE ** clause subexpression is separated from the others by an AND operator. |
︙ | ︙ | |||
435 436 437 438 439 440 441 442 | sqliteExprCode(pParse, aExpr[k].p->pLeft); } aExpr[k].p = 0; brk = pLevel->brk = sqliteVdbeMakeLabel(v); cont = pLevel->cont = brk; sqliteVdbeAddOp(v, OP_MustBeInt, 0, brk); if( i==pTabList->nId-1 && pushKey ){ haveKey = 1; | > > > > > > > | < > | 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 | sqliteExprCode(pParse, aExpr[k].p->pLeft); } aExpr[k].p = 0; brk = pLevel->brk = sqliteVdbeMakeLabel(v); cont = pLevel->cont = brk; sqliteVdbeAddOp(v, OP_MustBeInt, 0, brk); if( i==pTabList->nId-1 && pushKey ){ /* Note: The OP_Dup below will cause the key to be left on the ** stack if the key does not exists and the OP_NotExists jump is ** taken. This violates a general rule of the VDBE that you should ** never leave values on the stack in order to avoid a stack overflow. ** But in this case, the OP_Dup will never happen inside of a loop, ** so it is safe to leave it on the stack. */ haveKey = 1; sqliteVdbeAddOp(v, OP_Dup, 0, 0); }else{ haveKey = 0; } sqliteVdbeAddOp(v, OP_NotExists, base+idx, brk); pLevel->op = OP_Noop; }else if( pIdx!=0 && pLevel->score%4==0 ){ /* Case 2: All index constraints are equality operators. */ int start; int testOp; int nColumn = pLevel->score/4; |
︙ | ︙ |
Changes to test/in.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # 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 the IN and BETWEEN operator. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # 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 the IN and BETWEEN operator. # # $Id: in.test,v 1.6 2002/01/28 15:53:05 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Generate the test data we will need for the first squences of tests. # do_test in-1.0 { |
︙ | ︙ | |||
151 152 153 154 155 156 157 158 159 | WHERE a IN ( 'Do','an','IN','with','a','constant','RHS','but','where','the', 'has','many','elements','We','need','to','test','that', 'collisions','hash','table','are','resolved','properly', 'This','in-set','contains','thirty','one','entries','hello'); } } {hello world} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | WHERE a IN ( 'Do','an','IN','with','a','constant','RHS','but','where','the', 'has','many','elements','We','need','to','test','that', 'collisions','hash','table','are','resolved','properly', 'This','in-set','contains','thirty','one','entries','hello'); } } {hello world} # Make sure the IN operator works with INTEGER PRIMARY KEY fields. # do_test in-6.1 { execsql { CREATE TABLE ta(a INTEGER PRIMARY KEY, b); INSERT INTO ta VALUES(1,1); INSERT INTO ta VALUES(2,2); INSERT INTO ta VALUES(3,3); INSERT INTO ta VALUES(4,4); INSERT INTO ta VALUES(6,6); INSERT INTO ta VALUES(8,8); SELECT * FROM ta; } } {1 1 2 2 3 3 4 4 6 6 8 8} do_test in-6.2 { execsql { CREATE TABLE tb(a INTEGER PRIMARY KEY, b); INSERT INTO tb VALUES(1,1); INSERT INTO tb VALUES(2,2); INSERT INTO tb VALUES(3,3); INSERT INTO tb VALUES(5,5); INSERT INTO tb VALUES(7,7); INSERT INTO tb VALUES(9,9); SELECT * FROM tb; } } {1 1 2 2 3 3 5 5 7 7 9 9} do_test in-6.3 { execsql { SELECT a FROM ta WHERE b IN (SELECT a FROM tb); } } {1 2 3} do_test in-6.4 { execsql { SELECT a FROM ta WHERE b NOT IN (SELECT a FROM tb); } } {4 6 8} do_test in-6.5 { execsql { SELECT a FROM ta WHERE b IN (SELECT b FROM tb); } } {1 2 3} do_test in-6.6 { execsql { SELECT a FROM ta WHERE b NOT IN (SELECT b FROM tb); } } {4 6 8} do_test in-6.7 { execsql { SELECT a FROM ta WHERE a IN (SELECT a FROM tb); } } {1 2 3} do_test in-6.8 { execsql { SELECT a FROM ta WHERE a NOT IN (SELECT a FROM tb); } } {4 6 8} do_test in-6.9 { execsql { SELECT a FROM ta WHERE a IN (SELECT b FROM tb); } } {1 2 3} do_test in-6.10 { execsql { SELECT a FROM ta WHERE a NOT IN (SELECT b FROM tb); } } {4 6 8} finish_test |
Changes to www/changes.tcl.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | } proc chng {date desc} { puts "<DT><B>$date</B></DT>" puts "<DD><P><UL>$desc</UL></P></DD>" } chng {2002 Jan 22 (2.2.4)} { <li>The label to the right of an AS in the column list of a SELECT can now be used as part of an expression in the WHERE, ORDER BY, GROUP BY, and/or HAVING clauses.</li> <li>Fix a bug in the <b>-separator</b> command-line option to the <b>sqlite</b> command.</li> | > > > > > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | } proc chng {date desc} { puts "<DT><B>$date</B></DT>" puts "<DD><P><UL>$desc</UL></P></DD>" } chng {2002 Jan 28 (2.2.5)} { <li>Important bug fix: the IN operator was not working if either the left-hand or right-hand side was derived from an INTEGER PRIMARY KEY.</li> <li>Do not escape the backslash '\' character in the output of the <b>sqlite</b> command-line access program.</li> } chng {2002 Jan 22 (2.2.4)} { <li>The label to the right of an AS in the column list of a SELECT can now be used as part of an expression in the WHERE, ORDER BY, GROUP BY, and/or HAVING clauses.</li> <li>Fix a bug in the <b>-separator</b> command-line option to the <b>sqlite</b> command.</li> |
︙ | ︙ |