Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Separate columns in keys using nulls instead of tabs. (CVS 249) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
8e2f3f751ea342372c94977ff27baaff |
User & Date: | drh 2001-09-15 14:43:39.000 |
Context
2001-09-16
| ||
00:13 | Disclaimed copyright. Preparing for release 2.0. (CVS 250) (check-in: 4e926efe2b user: drh tags: trunk) | |
2001-09-15
| ||
14:43 | Separate columns in keys using nulls instead of tabs. (CVS 249) (check-in: 8e2f3f751e user: drh tags: trunk) | |
13:15 | Limit the total data in a single row to 2^16-1 bytes. (CVS 248) (check-in: 8fdec4d8b6 user: drh tags: trunk) | |
Changes
Changes to src/sqliteInt.h.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.50 2001/09/15 14:43:39 drh Exp $ */ #include "sqlite.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> #include <stdlib.h> |
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 | ** Integers of known sizes. These typedefs much change for architectures ** where the sizes very. */ typedef unsigned int u32; /* 4-byte unsigned integer */ typedef unsigned short int u16; /* 2-byte unsigned integer */ typedef unsigned char u8; /* 1-byte unsigned integer */ /* ** If memory allocation problems are found, recompile with ** ** -DMEMORY_DEBUG=1 ** ** to enable some sanity checking on malloc() and free(). To ** check for memory leaks, recompile with | > > > > > > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | ** Integers of known sizes. These typedefs much change for architectures ** where the sizes very. */ typedef unsigned int u32; /* 4-byte unsigned integer */ typedef unsigned short int u16; /* 2-byte unsigned integer */ typedef unsigned char u8; /* 1-byte unsigned integer */ /* ** The maximum number of bytes of data that can be put into a single ** row of a single table. */ #define MAX_BYTES_PER_ROW 65535 /* ** If memory allocation problems are found, recompile with ** ** -DMEMORY_DEBUG=1 ** ** to enable some sanity checking on malloc() and free(). To ** check for memory leaks, recompile with |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
37 38 39 40 41 42 43 | ** inplicit conversion from one 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. ** | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | ** inplicit conversion from one 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.69 2001/09/15 14:43:39 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include <unistd.h> /* ** SQL is translated into a sequence of instructions to be |
︙ | ︙ | |||
1799 1800 1801 1802 1803 1804 1805 | for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n; } } nByte += sizeof(addr)*nField; | | | 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 | for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n; } } nByte += sizeof(addr)*nField; if( nByte>MAX_BYTES_PER_ROW ){ rc = SQLITE_TOOBIG; goto abort_due_to_error; } zNewRecord = sqliteMalloc( nByte ); if( zNewRecord==0 ) goto no_mem; j = 0; addr = sizeof(addr)*nField; |
︙ | ︙ | |||
1833 1834 1835 1836 1837 1838 1839 | break; } /* Opcode: MakeKey P1 P2 * ** ** Convert the top P1 entries of the stack into a single entry suitable ** for use as the key in an index or a sort. The top P1 records are | > | | | | 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 | break; } /* Opcode: MakeKey P1 P2 * ** ** Convert the top P1 entries of the stack into a single entry suitable ** for use as the key in an index or a sort. The top P1 records are ** converted to strings and merged. The null-terminator on each string ** is retained and used as a separator. The entire string is also ** null-terminated. ** The lowest entry in the stack is the first field and the top of the ** stack becomes the last. ** ** If P2 is not zero, then the original entries remain on the stack ** and the new key is pushed on top. If P2 is zero, the original ** data is popped off the stack first then the new key is pushed ** back in its place. ** |
︙ | ︙ | |||
1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 | for(i=p->tos-nField+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ nByte++; }else{ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n; } } zNewKey = sqliteMalloc( nByte ); if( zNewKey==0 ) goto no_mem; j = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ | > > > > | > > | | < < | | 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 | for(i=p->tos-nField+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ nByte++; }else{ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n; } } if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){ rc = SQLITE_TOOBIG; goto abort_due_to_error; } zNewKey = sqliteMalloc( nByte ); if( zNewKey==0 ) goto no_mem; j = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ zNewKey[j++] = 0; }else{ memcpy(&zNewKey[j], zStack[i], aStack[i].n); j += aStack[i].n; } } if( pOp->p2==0 ) PopStack(p, nField); VERIFY( NeedStack(p, p->tos+1); ) p->tos++; aStack[p->tos].n = nByte; aStack[p->tos].flags = STK_Str|STK_Dyn; zStack[p->tos] = zNewKey; break; } /* Opcode: MakeIdxKey P1 * * ** ** Convert the top P1 entries of the stack into a single entry suitable ** for use as the key in an index. In addition, take one additional integer ** off of the stack, treat that integer as a four-byte record number, and ** append the four bytes to the key. Thus a total of P1+1 entries are ** popped from the stack for this instruction and a single entry is pushed ** back. The first P1 entries that are popped are strings and the last ** entry (the lowest on the stack) is an integer record number. ** ** The converstion of the first P1 string entries occurs just like in ** MakeKey. Each entry is separated from the others by a null. ** The entire concatenation is null-terminated. The lowest entry ** in the stack is the first field and the top of the stack becomes the ** last. ** ** See also: MakeKey, SortMakeKey */ case OP_MakeIdxKey: { |
︙ | ︙ | |||
1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 | for(i=p->tos-nField+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ nByte++; }else{ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n; } } zNewKey = sqliteMalloc( nByte ); if( zNewKey==0 ) goto no_mem; j = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ | > > > > | > > | | < < | 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 | for(i=p->tos-nField+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ nByte++; }else{ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n; } } if( nByte>MAX_BYTES_PER_ROW ){ rc = SQLITE_TOOBIG; goto abort_due_to_error; } zNewKey = sqliteMalloc( nByte ); if( zNewKey==0 ) goto no_mem; j = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ zNewKey[j++] = 0; }else{ memcpy(&zNewKey[j], zStack[i], aStack[i].n); j += aStack[i].n; } } Integerify(p, p->tos-nField); memcpy(&zNewKey[j], &aStack[p->tos-nField].i, sizeof(u32)); PopStack(p, nField+1); VERIFY( NeedStack(p, p->tos+1); ) p->tos++; aStack[p->tos].n = nByte; aStack[p->tos].flags = STK_Str|STK_Dyn; |
︙ | ︙ | |||
2577 2578 2579 2580 2581 2582 2583 | ** record numbers onto the stack until all records with the same key ** have been returned. ** ** Note that the key for this opcode should be built using MakeKey ** but the key used for PutIdx and DeleteIdx should be built using ** MakeIdxKey. The difference is that MakeIdxKey adds a 4-bytes ** record number to the end of the key in order to specify a particular | | | > > | | | | > | > | < > | 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 | ** record numbers onto the stack until all records with the same key ** have been returned. ** ** Note that the key for this opcode should be built using MakeKey ** but the key used for PutIdx and DeleteIdx should be built using ** MakeIdxKey. The difference is that MakeIdxKey adds a 4-bytes ** record number to the end of the key in order to specify a particular ** entry in the index. MakeKey omits the 4-byte record number. ** The search that this BeginIdx instruction initiates will span all ** entries in the index where the MakeKey generated key matches all ** but the last four bytes of the MakeIdxKey generated key. */ case OP_BeginIdx: { int i = pOp->p1; int tos = p->tos; int res, rx; Cursor *pCrsr; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( i>=0 && i<p->nCursor && (pCrsr = &p->aCsr[i])->pCursor!=0 ){ if( Stringify(p, tos) ) goto no_mem; if( pCrsr->zKey ) sqliteFree(pCrsr->zKey); pCrsr->nKey = aStack[tos].n; pCrsr->zKey = sqliteMalloc( 2*pCrsr->nKey ); if( pCrsr->zKey==0 ) goto no_mem; pCrsr->zBuf = &pCrsr->zKey[pCrsr->nKey]; memcpy(pCrsr->zKey, zStack[tos], aStack[tos].n); pCrsr->zKey[aStack[tos].n] = 0; rx = sqliteBtreeMoveto(pCrsr->pCursor, zStack[tos], aStack[tos].n, &res); pCrsr->atFirst = rx==SQLITE_OK && res>0; pCrsr->recnoIsValid = 0; } POPSTACK; break; } /* Opcode: NextIdx P1 P2 * ** ** The P1 cursor points to an SQL index for which a BeginIdx operation ** has been issued. This operation retrieves the next record from that ** cursor and verifies that the key on the record matches the key that ** was pulled from the stack by the BeginIdx instruction. If they do ** match, then the last 4 bytes of the key on the record hold a record ** number and that record number is extracted and pushed on the stack. ** If the keys do not match, there is an immediate jump to instruction P2. */ case OP_NextIdx: { int i = pOp->p1; int tos = ++p->tos; Cursor *pCrsr; BtCursor *pCur; int rx, res, size; |
︙ | ︙ | |||
2632 2633 2634 2635 2636 2637 2638 | }else{ rx = sqliteBtreeNext(pCur, &res); if( rx!=SQLITE_OK ) goto abort_due_to_error; } sqliteBtreeKeySize(pCur, &size); if( res>0 || size!=pCrsr->nKey+sizeof(u32) || sqliteBtreeKey(pCur, 0, pCrsr->nKey, pCrsr->zBuf)!=pCrsr->nKey || | | | 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 | }else{ rx = sqliteBtreeNext(pCur, &res); if( rx!=SQLITE_OK ) goto abort_due_to_error; } sqliteBtreeKeySize(pCur, &size); if( res>0 || size!=pCrsr->nKey+sizeof(u32) || sqliteBtreeKey(pCur, 0, pCrsr->nKey, pCrsr->zBuf)!=pCrsr->nKey || memcmp(pCrsr->zKey, pCrsr->zBuf, pCrsr->nKey)!=0 ){ pc = pOp->p2 - 1; POPSTACK; }else{ int recno; sqliteBtreeKey(pCur, pCrsr->nKey, sizeof(u32), (char*)&recno); p->aCsr[i].lastRecno = aStack[tos].i = recno; |
︙ | ︙ | |||
3782 3783 3784 3785 3786 3787 3788 | }else if( aStack[i].flags & STK_Real ){ fprintf(p->trace, " r:%g", aStack[i].r); }else if( aStack[i].flags & STK_Str ){ int j, k; char zBuf[100]; zBuf[0] = ' '; zBuf[1] = (aStack[i].flags & STK_Dyn)!=0 ? 'z' : 's'; | | | > | 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 | }else if( aStack[i].flags & STK_Real ){ fprintf(p->trace, " r:%g", aStack[i].r); }else if( aStack[i].flags & STK_Str ){ int j, k; char zBuf[100]; zBuf[0] = ' '; zBuf[1] = (aStack[i].flags & STK_Dyn)!=0 ? 'z' : 's'; zBuf[2] = '['; k = 3; for(j=0; j<20 && j<aStack[i].n; j++){ int c = zStack[i][j]; if( c==0 && j==aStack[i].n-1 ) break; if( isprint(c) && !isspace(c) ){ zBuf[k++] = c; }else{ zBuf[k++] = '.'; } } zBuf[k++] = ']'; zBuf[k++] = 0; fprintf(p->trace, "%s", zBuf); }else{ fprintf(p->trace, " ???"); } } fprintf(p->trace,"\n"); |
︙ | ︙ |