Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Implement indices that occur in sort order and the LIMIT...OFFSET clause of SELECT statements. (CVS 301) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
eb07768ae93f14bf6c150c1c43299488 |
User & Date: | drh 2001-11-06 04:00:18.000 |
Context
2001-11-06
| ||
14:10 | Added support for LIMIT. (CVS 302) (check-in: 177012249a user: drh tags: trunk) | |
04:00 | Implement indices that occur in sort order and the LIMIT...OFFSET clause of SELECT statements. (CVS 301) (check-in: eb07768ae9 user: drh tags: trunk) | |
2001-11-04
| ||
18:32 | Increase maximum row size to 1MB. (CVS 300) (check-in: 7dd58fad39 user: drh tags: trunk) | |
Changes
Changes to src/parse.y.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** | | > > > > > | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.38 2001/11/06 04:00:18 drh Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { sqliteSetString(&pParse->zErrMsg,"syntax error",0); pParse->sErrToken = TOKEN; } %name sqliteParser %include { #include "sqliteInt.h" #include "parse.h" /* ** A structure for holding two integers */ struct twoint { int a,b; }; } // These are extra tokens used by the lexer but never seen by the // parser. We put them in a rule so that the parser generator will // add them to the parse.h output file. // %nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION |
︙ | ︙ | |||
92 93 94 95 96 97 98 99 100 101 102 103 104 105 | id(A) ::= VACUUM(X). {A = X;} id(A) ::= BEGIN(X). {A = X;} id(A) ::= END(X). {A = X;} id(A) ::= PRAGMA(X). {A = X;} id(A) ::= CLUSTER(X). {A = X;} id(A) ::= ID(X). {A = X;} id(A) ::= TEMP(X). {A = X;} // And "ids" is an identifer-or-string. // %type ids {Token} ids(A) ::= id(X). {A = X;} ids(A) ::= STRING(X). {A = X;} | > | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | id(A) ::= VACUUM(X). {A = X;} id(A) ::= BEGIN(X). {A = X;} id(A) ::= END(X). {A = X;} id(A) ::= PRAGMA(X). {A = X;} id(A) ::= CLUSTER(X). {A = X;} id(A) ::= ID(X). {A = X;} id(A) ::= TEMP(X). {A = X;} id(A) ::= OFFSET(X). {A = X;} // And "ids" is an identifer-or-string. // %type ids {Token} ids(A) ::= id(X). {A = X;} ids(A) ::= STRING(X). {A = X;} |
︙ | ︙ | |||
175 176 177 178 179 180 181 | } %type joinop {int} joinop(A) ::= UNION. {A = TK_UNION;} joinop(A) ::= UNION ALL. {A = TK_ALL;} joinop(A) ::= INTERSECT. {A = TK_INTERSECT;} joinop(A) ::= EXCEPT. {A = TK_EXCEPT;} oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y) | | | | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | } %type joinop {int} joinop(A) ::= UNION. {A = TK_UNION;} joinop(A) ::= UNION ALL. {A = TK_ALL;} joinop(A) ::= INTERSECT. {A = TK_INTERSECT;} joinop(A) ::= EXCEPT. {A = TK_EXCEPT;} oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y) groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). { A = sqliteSelectNew(W,X,Y,P,Q,Z,D,L.a,L.b); } // The "distinct" nonterminal is true (1) if the DISTINCT keyword is // present and false (0) if it is not. // %type distinct {int} distinct(A) ::= DISTINCT. {A = 1;} |
︙ | ︙ | |||
254 255 256 257 258 259 260 261 262 263 264 265 266 267 | groupby_opt(A) ::= . {A = 0;} groupby_opt(A) ::= GROUP BY exprlist(X). {A = X;} %type having_opt {Expr*} %destructor having_opt {sqliteExprDelete($$);} having_opt(A) ::= . {A = 0;} having_opt(A) ::= HAVING expr(X). {A = X;} /////////////////////////// The DELETE statement ///////////////////////////// // cmd ::= DELETE FROM ids(X) where_opt(Y). {sqliteDeleteFrom(pParse, &X, Y);} %type where_opt {Expr*} | > > > > > > > > | 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | groupby_opt(A) ::= . {A = 0;} groupby_opt(A) ::= GROUP BY exprlist(X). {A = X;} %type having_opt {Expr*} %destructor having_opt {sqliteExprDelete($$);} having_opt(A) ::= . {A = 0;} having_opt(A) ::= HAVING expr(X). {A = X;} %type limit_opt {struct twoint} limit_opt(A) ::= . {A.a = -1; A.b = 0;} limit_opt(A) ::= LIMIT INTEGER(X). {A.a = atoi(X.z); A.b = 0;} limit_opt(A) ::= LIMIT INTEGER(X) limit_sep INTEGER(Y). {A.a = atoi(X.z); A.b = atoi(Y.z);} limit_sep ::= OFFSET. limit_sep ::= COMMA. /////////////////////////// The DELETE statement ///////////////////////////// // cmd ::= DELETE FROM ids(X) where_opt(Y). {sqliteDeleteFrom(pParse, &X, Y);} %type where_opt {Expr*} |
︙ | ︙ |
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 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | ** 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.46 2001/11/06 04:00:19 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. */ Select *sqliteSelectNew( ExprList *pEList, /* which columns to include in the result */ IdList *pSrc, /* the FROM clause -- which tables to scan */ Expr *pWhere, /* the WHERE clause */ ExprList *pGroupBy, /* the GROUP BY clause */ Expr *pHaving, /* the HAVING clause */ ExprList *pOrderBy, /* the ORDER BY clause */ int isDistinct, /* true if the DISTINCT keyword is present */ int nLimit, /* LIMIT value. -1 means not used */ int nOffset /* OFFSET value. -1 means not used */ ){ Select *pNew; pNew = sqliteMalloc( sizeof(*pNew) ); if( pNew==0 ){ sqliteExprListDelete(pEList); sqliteIdListDelete(pSrc); sqliteExprDelete(pWhere); sqliteExprListDelete(pGroupBy); sqliteExprDelete(pHaving); sqliteExprListDelete(pOrderBy); }else{ pNew->pEList = pEList; pNew->pSrc = pSrc; pNew->pWhere = pWhere; pNew->pGroupBy = pGroupBy; pNew->pHaving = pHaving; pNew->pOrderBy = pOrderBy; pNew->isDistinct = isDistinct; pNew->op = TK_SELECT; pNew->nLimit = nLimit; pNew->nOffset = nOffset; } return pNew; } /* ** Delete the given Select structure and all of its substructures. */ |
︙ | ︙ | |||
199 200 201 202 203 204 205 | sqliteVdbeAddOp(v, OP_MemStore, iParm, 0); sqliteVdbeAddOp(v, OP_Goto, 0, iBreak); }else /* If none of the above, send the data to the callback function. */ { | | | | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | sqliteVdbeAddOp(v, OP_MemStore, iParm, 0); sqliteVdbeAddOp(v, OP_Goto, 0, iBreak); }else /* If none of the above, send the data to the callback function. */ { sqliteVdbeAddOp(v, OP_Callback, nColumn, iBreak); } return 0; } /* ** If the inner loop was generated using a non-null pOrderBy argument, ** then the results were placed in a sorter. After the loop is terminated ** we need to run the sorter and output the results. The following ** routine generates the code needed to do that. */ static void generateSortTail(Vdbe *v, int nColumn){ int end = sqliteVdbeMakeLabel(v); int addr; sqliteVdbeAddOp(v, OP_Sort, 0, 0); addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end); sqliteVdbeAddOp(v, OP_SortCallback, nColumn, end); sqliteVdbeAddOp(v, OP_Goto, 0, addr); sqliteVdbeResolveLabel(v, end); sqliteVdbeAddOp(v, OP_SortReset, 0, 0); } /* ** Generate code that will tell the VDBE how many columns there |
︙ | ︙ | |||
849 850 851 852 853 854 855 856 857 858 859 860 861 862 | } } /* Begin generating code. */ v = sqliteGetVdbe(pParse); if( v==0 ) return 1; /* Identify column names if we will be using in the callback. This ** step is skipped if the output is going to a table or a memory cell. */ if( eDest==SRT_Callback ){ generateColumnNames(pParse, pTabList, pEList); } | > > > > > > > > > > | 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 | } } /* Begin generating code. */ v = sqliteGetVdbe(pParse); if( v==0 ) return 1; /* Set the limiter */ if( p->nLimit<=0 ){ p->nOffset = 0; }else{ if( p->nOffset<0 ) p->nOffset = 0; sqliteVdbeAddOp(v, OP_Limit, p->nLimit, p->nOffset); } /* Identify column names if we will be using in the callback. This ** step is skipped if the output is going to a table or a memory cell. */ if( eDest==SRT_Callback ){ generateColumnNames(pParse, pTabList, pEList); } |
︙ | ︙ |
Changes to src/sqliteInt.h.
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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.67 2001/11/06 04:00:19 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> |
︙ | ︙ | |||
324 325 326 327 328 329 330 331 332 333 334 335 336 337 | IdList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ ExprList *pGroupBy; /* The GROUP BY clause */ Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ int op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ Select *pPrior; /* Prior select in a compound select statement */ }; /* ** The results of a select can be distributed in several ways. */ #define SRT_Callback 1 /* Invoke a callback with each row of result */ #define SRT_Mem 2 /* Store result in a memory cell */ | > | 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | IdList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ ExprList *pGroupBy; /* The GROUP BY clause */ Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ int op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ Select *pPrior; /* Prior select in a compound select statement */ int nLimit, nOffset; /* LIMIT and OFFSET values. -1 means not used */ }; /* ** The results of a select can be distributed in several ways. */ #define SRT_Callback 1 /* Invoke a callback with each row of result */ #define SRT_Mem 2 /* Store result in a memory cell */ |
︙ | ︙ | |||
403 404 405 406 407 408 409 410 411 412 413 414 415 416 | ** Internal function prototypes */ int sqliteStrICmp(const char *, const char *); int sqliteStrNICmp(const char *, const char *, int); int sqliteHashNoCase(const char *, int); int sqliteCompare(const char *, const char *); int sqliteSortCompare(const char *, const char *); #ifdef MEMORY_DEBUG void *sqliteMalloc_(int,char*,int); void sqliteFree_(void*,char*,int); void *sqliteRealloc_(void*,int,char*,int); char *sqliteStrDup_(const char*,char*,int); char *sqliteStrNDup_(const char*, int,char*,int); #else | > | 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | ** Internal function prototypes */ int sqliteStrICmp(const char *, const char *); int sqliteStrNICmp(const char *, const char *, int); int sqliteHashNoCase(const char *, int); int sqliteCompare(const char *, const char *); int sqliteSortCompare(const char *, const char *); void sqliteRealToSortable(double r, char *); #ifdef MEMORY_DEBUG void *sqliteMalloc_(int,char*,int); void sqliteFree_(void*,char*,int); void *sqliteRealloc_(void*,int,char*,int); char *sqliteStrDup_(const char*,char*,int); char *sqliteStrNDup_(const char*, int,char*,int); #else |
︙ | ︙ | |||
445 446 447 448 449 450 451 | void sqliteInsert(Parse*, Token*, ExprList*, Select*, IdList*); IdList *sqliteIdListAppend(IdList*, Token*); void sqliteIdListAddAlias(IdList*, Token*); void sqliteIdListDelete(IdList*); void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, int, Token*, Token*); void sqliteDropIndex(Parse*, Token*); int sqliteSelect(Parse*, Select*, int, int); | | > | 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 | void sqliteInsert(Parse*, Token*, ExprList*, Select*, IdList*); IdList *sqliteIdListAppend(IdList*, Token*); void sqliteIdListAddAlias(IdList*, Token*); void sqliteIdListDelete(IdList*); void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, int, Token*, Token*); void sqliteDropIndex(Parse*, Token*); int sqliteSelect(Parse*, Select*, int, int); Select *sqliteSelectNew(ExprList*,IdList*,Expr*,ExprList*,Expr*,ExprList*, int,int,int); void sqliteSelectDelete(Select*); void sqliteDeleteFrom(Parse*, Token*, Expr*); void sqliteUpdate(Parse*, Token*, ExprList*, Expr*); WhereInfo *sqliteWhereBegin(Parse*, IdList*, Expr*, int); void sqliteWhereEnd(WhereInfo*); void sqliteExprCode(Parse*, Expr*); void sqliteExprIfTrue(Parse*, Expr*, int); |
︙ | ︙ |
Changes to src/tokenize.c.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** ** $Id: tokenize.c,v 1.32 2001/11/06 04:00:19 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include <stdlib.h> /* |
︙ | ︙ | |||
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | { "INSERT", 0, TK_INSERT, 0 }, { "INTERSECT", 0, TK_INTERSECT, 0 }, { "INTO", 0, TK_INTO, 0 }, { "IS", 0, TK_IS, 0 }, { "ISNULL", 0, TK_ISNULL, 0 }, { "KEY", 0, TK_KEY, 0 }, { "LIKE", 0, TK_LIKE, 0 }, { "NOT", 0, TK_NOT, 0 }, { "NOTNULL", 0, TK_NOTNULL, 0 }, { "NULL", 0, TK_NULL, 0 }, { "ON", 0, TK_ON, 0 }, { "OR", 0, TK_OR, 0 }, { "ORDER", 0, TK_ORDER, 0 }, { "PRAGMA", 0, TK_PRAGMA, 0 }, { "PRIMARY", 0, TK_PRIMARY, 0 }, { "ROLLBACK", 0, TK_ROLLBACK, 0 }, { "SELECT", 0, TK_SELECT, 0 }, | > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | { "INSERT", 0, TK_INSERT, 0 }, { "INTERSECT", 0, TK_INTERSECT, 0 }, { "INTO", 0, TK_INTO, 0 }, { "IS", 0, TK_IS, 0 }, { "ISNULL", 0, TK_ISNULL, 0 }, { "KEY", 0, TK_KEY, 0 }, { "LIKE", 0, TK_LIKE, 0 }, { "LIMIT", 0, TK_LIMIT, 0 }, { "NOT", 0, TK_NOT, 0 }, { "NOTNULL", 0, TK_NOTNULL, 0 }, { "NULL", 0, TK_NULL, 0 }, { "OFFSET", 0, TK_OFFSET, 0 }, { "ON", 0, TK_ON, 0 }, { "OR", 0, TK_OR, 0 }, { "ORDER", 0, TK_ORDER, 0 }, { "PRAGMA", 0, TK_PRAGMA, 0 }, { "PRIMARY", 0, TK_PRIMARY, 0 }, { "ROLLBACK", 0, TK_ROLLBACK, 0 }, { "SELECT", 0, TK_SELECT, 0 }, |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.31 2001/11/06 04:00:19 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* ** If malloc() ever fails, this global variable gets set to 1. |
︙ | ︙ | |||
749 750 751 752 753 754 755 756 757 758 759 760 761 762 | a += len; b += len; } } if( *a=='-' ) res = -res; return res; } #ifdef SQLITE_UTF8 /* ** X is a pointer to the first byte of a UTF-8 character. Increment ** X so that it points to the next character. This only works right ** if X points to a well-formed UTF-8 string. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 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 | a += len; b += len; } } if( *a=='-' ) res = -res; return res; } /* ** Some powers of 64. These numbers and their recipricals should ** all have exact representations in the floating point format. */ #define _64e3 (64.0 * 64.0 * 64.0) #define _64e4 (64.0 * 64.0 * 64.0 * 64.0) #define _64e15 (_64e3 * _64e4 * _64e4 * _64e4) #define _64e16 (_64e4 * _64e4 * _64e4 * _64e4) #define _64e63 (_64e15 * _64e16 * _64e16 * _64e16) #define _64e64 (_64e16 * _64e16 * _64e16 * _64e16) /* ** The following procedure converts a double-precision floating point ** number into a string. The resulting string has the property that ** two such strings comparied using strcmp() or memcmp() will give the ** same results as comparing the original floating point numbers. ** ** This routine is used to generate database keys from floating point ** numbers such that the keys sort in the same order as the original ** floating point numbers even though the keys are compared using ** memcmp(). ** ** The calling function should have allocated at least 14 characters ** of space for the buffer z[]. */ void sqliteRealToSortable(double r, char *z){ int neg; int exp; int cnt = 0; /* This array maps integers between 0 and 63 into base-64 digits. ** The digits must be chosen such at their ASCII codes are increasing. ** This means we can not use the traditional base-64 digit set. */ static const char zDigit[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "|~"; if( r<0.0 ){ neg = 1; r = -r; *z++ = '-'; } else { neg = 0; *z++ = '0'; } exp = 0; if( r==0.0 ){ exp = -1024; }else if( r<(0.5/64.0) ){ while( r < 0.5/_64e64 && exp > -961 ){ r *= _64e64; exp -= 64; } while( r < 0.5/_64e16 && exp > -1009 ){ r *= _64e16; exp -= 16; } while( r < 0.5/_64e4 && exp > -1021 ){ r *= _64e4; exp -= 4; } while( r < 0.5/64.0 && exp > -1024 ){ r *= 64.0; exp -= 1; } }else if( r>=0.5 ){ while( r >= 0.5*_64e63 && exp < 960 ){ r *= 1.0/_64e64; exp += 64; } while( r >= 0.5*_64e15 && exp < 1008 ){ r *= 1.0/_64e16; exp += 16; } while( r >= 0.5*_64e3 && exp < 1020 ){ r *= 1.0/_64e4; exp += 4; } while( r >= 0.5 && exp < 1023 ){ r *= 1.0/64.0; exp += 1; } } if( neg ){ exp = -exp; r = -r; } exp += 1024; r += 0.5; if( exp<0 ) return; if( exp>=2048 || r>=1.0 ){ strcpy(z, "~~~~~~~~~~~~"); return; } *z++ = zDigit[(exp>>6)&0x3f]; *z++ = zDigit[exp & 0x3f]; while( r>0.0 && cnt<10 ){ int digit; r *= 64.0; digit = r; assert( digit>=0 && digit<64 ); *z++ = zDigit[digit & 0x3f]; r -= digit; cnt++; } *z = 0; } #ifdef SQLITE_UTF8 /* ** X is a pointer to the first byte of a UTF-8 character. Increment ** X so that it points to the next character. This only works right ** if X points to a well-formed UTF-8 string. */ |
︙ | ︙ |
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.93 2001/11/06 04:00:19 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** SQL is translated into a sequence of instructions to be ** executed by a virtual machine. Each instruction is an instance |
︙ | ︙ | |||
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 | }; /* ** Number of buckets used for merge-sort. */ #define NSORT 30 /* ** A single level of the stack is an instance of the following ** structure. Except, string values are stored on a separate ** list of of pointers to character. The reason for storing ** strings separately is so that they can be easily passed ** to the callback function. */ struct Stack { int i; /* Integer value */ int n; /* Number of characters in string value, including '\0' */ int flags; /* Some combination of STK_Null, STK_Str, STK_Dyn, etc. */ double r; /* Real value */ }; typedef struct Stack Stack; /* ** Memory cells use the same structure as the stack except that space ** for an arbitrary string is added. */ | > > > > > > > > | 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 | }; /* ** Number of buckets used for merge-sort. */ #define NSORT 30 /* ** Number of bytes of string storage space available to each stack ** layer without having to malloc. NBFS is short for Number of Bytes ** For Strings. */ #define NBFS 30 /* ** A single level of the stack is an instance of the following ** structure. Except, string values are stored on a separate ** list of of pointers to character. The reason for storing ** strings separately is so that they can be easily passed ** to the callback function. */ struct Stack { int i; /* Integer value */ int n; /* Number of characters in string value, including '\0' */ int flags; /* Some combination of STK_Null, STK_Str, STK_Dyn, etc. */ double r; /* Real value */ char z[NBFS]; /* Space for short strings */ }; typedef struct Stack Stack; /* ** Memory cells use the same structure as the stack except that space ** for an arbitrary string is added. */ |
︙ | ︙ | |||
116 117 118 119 120 121 122 123 124 125 126 127 128 129 | ** Allowed values for Stack.flags */ #define STK_Null 0x0001 /* Value is NULL */ #define STK_Str 0x0002 /* Value is a string */ #define STK_Int 0x0004 /* Value is an integer */ #define STK_Real 0x0008 /* Value is a real number */ #define STK_Dyn 0x0010 /* Need to call sqliteFree() on zStack[*] */ /* ** An Agg structure describes an Aggregator. Each Agg consists of ** zero or more Aggregator elements (AggElem). Each AggElem contains ** a key and one or more values. The values are used in processing ** aggregate functions in a SELECT. The key is used to implement ** the GROUP BY clause of a select. | > | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | ** Allowed values for Stack.flags */ #define STK_Null 0x0001 /* Value is NULL */ #define STK_Str 0x0002 /* Value is a string */ #define STK_Int 0x0004 /* Value is an integer */ #define STK_Real 0x0008 /* Value is a real number */ #define STK_Dyn 0x0010 /* Need to call sqliteFree() on zStack[*] */ #define STK_Static 0x0020 /* zStack[] points to a static string */ /* ** An Agg structure describes an Aggregator. Each Agg consists of ** zero or more Aggregator elements (AggElem). Each AggElem contains ** a key and one or more values. The values are used in processing ** aggregate functions in a SELECT. The key is used to implement ** the GROUP BY clause of a select. |
︙ | ︙ | |||
197 198 199 200 201 202 203 204 205 206 207 208 209 210 | int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ Agg agg; /* Aggregate information */ int nSet; /* Number of sets allocated */ Set *aSet; /* An array of sets */ int nFetch; /* Number of OP_Fetch instructions executed */ int nCallback; /* Number of callbacks invoked so far */ }; /* ** Create a new virtual database engine. */ Vdbe *sqliteVdbeCreate(sqlite *db){ Vdbe *p; | > > | 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ Agg agg; /* Aggregate information */ int nSet; /* Number of sets allocated */ Set *aSet; /* An array of sets */ int nFetch; /* Number of OP_Fetch instructions executed */ int nCallback; /* Number of callbacks invoked so far */ int iLimit; /* Limit on the number of callbacks remaining */ int iOffset; /* Offset before beginning to do callbacks */ }; /* ** Create a new virtual database engine. */ Vdbe *sqliteVdbeCreate(sqlite *db){ Vdbe *p; |
︙ | ︙ | |||
530 531 532 533 534 535 536 | ** NULLs are converted into an empty string. */ #define Stringify(P,I) \ ((P->aStack[I].flags & STK_Str)==0 ? hardStringify(P,I) : 0) static int hardStringify(Vdbe *p, int i){ Stack *pStack = &p->aStack[i]; char **pzStack = &p->zStack[i]; | < | | < | < < | < | | | 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 | ** NULLs are converted into an empty string. */ #define Stringify(P,I) \ ((P->aStack[I].flags & STK_Str)==0 ? hardStringify(P,I) : 0) static int hardStringify(Vdbe *p, int i){ Stack *pStack = &p->aStack[i]; char **pzStack = &p->zStack[i]; int fg = pStack->flags; if( fg & STK_Real ){ sprintf(pStack->z,"%.15g",pStack->r); }else if( fg & STK_Int ){ sprintf(pStack->z,"%d",pStack->i); }else{ pStack->z[0] = 0; } *pzStack = pStack->z; pStack->n = strlen(*pzStack)+1; pStack->flags = STK_Str; return 0; } /* ** Release the memory associated with the given stack level */ #define Release(P,I) if((P)->aStack[I].flags&STK_Dyn){ hardRelease(P,I); } static void hardRelease(Vdbe *p, int i){ sqliteFree(p->zStack[i]); p->zStack[i] = 0; p->aStack[i].flags &= ~(STK_Str|STK_Dyn|STK_Static); } /* ** Convert the given stack entity into a integer if it isn't one ** already. ** ** Any prior string or real representation is invalidated. |
︙ | ︙ | |||
670 671 672 673 674 675 676 677 678 679 680 681 682 683 | for(i=oldAlloc; i<p->nStackAlloc; i++){ p->zStack[i] = 0; p->aStack[i].flags = 0; } } return 0; } /* ** Delete a keylist */ static void KeylistFree(Keylist *p){ while( p ){ Keylist *pNext = p->pNext; | > > > > > > > > > > > > > > > > > > > > > | 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 | for(i=oldAlloc; i<p->nStackAlloc; i++){ p->zStack[i] = 0; p->aStack[i].flags = 0; } } return 0; } /* ** Return TRUE if zNum is a floating-point or integer number. */ static int isNumber(const char *zNum){ if( *zNum=='-' || *zNum=='+' ) zNum++; if( !isdigit(*zNum) ) return 0; while( isdigit(*zNum) ) zNum++; if( *zNum==0 ) return 1; if( *zNum!='.' ) return 0; zNum++; if( !isdigit(*zNum) ) return 0; while( isdigit(*zNum) ) zNum++; if( *zNum==0 ) return 1; if( *zNum!='e' && *zNum!='E' ) return 0; zNum++; if( *zNum=='-' || *zNum=='+' ) zNum++; if( !isdigit(*zNum) ) return 0; while( isdigit(*zNum) ) zNum++; return *zNum==0; } /* ** Delete a keylist */ static void KeylistFree(Keylist *p){ while( p ){ Keylist *pNext = p->pNext; |
︙ | ︙ | |||
818 819 820 821 822 823 824 | "Column", "KeyAsData", "Recno", "FullKey", "Rewind", "Next", "Destroy", "Clear", "CreateIndex", "CreateTable", "Reorganize", "BeginIdx", "NextIdx", "PutIdx", "DeleteIdx", "MemLoad", "MemStore", "ListWrite", "ListRewind", "ListRead", "ListReset", "SortPut", "SortMakeRec", "SortMakeKey", "Sort", "SortNext", "SortCallback", "SortReset", | | | | | | | < | | | | | | | | | > | 845 846 847 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 | "Column", "KeyAsData", "Recno", "FullKey", "Rewind", "Next", "Destroy", "Clear", "CreateIndex", "CreateTable", "Reorganize", "BeginIdx", "NextIdx", "PutIdx", "DeleteIdx", "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", "Goto", "If", "Halt", "ColumnCount", "ColumnName", "Callback", "NullCallback", "Integer", "String", "Pop", "Dup", "Pull", "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. |
︙ | ︙ | |||
1115 1116 1117 1118 1119 1120 1121 | z = pOp->p3; if( z==0 ){ zStack[i] = 0; aStack[i].flags = STK_Null; }else{ zStack[i] = z; aStack[i].n = strlen(z) + 1; | | < < < < < < < < < < < < < < | 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 | z = pOp->p3; if( z==0 ){ zStack[i] = 0; aStack[i].flags = STK_Null; }else{ zStack[i] = z; aStack[i].n = strlen(z) + 1; aStack[i].flags = STK_Str | STK_Static; } break; } /* Opcode: Pop P1 * * ** ** P1 elements are popped off of the top of stack and discarded. */ case OP_Pop: { PopStack(p, pOp->p1); break; |
︙ | ︙ | |||
1158 1159 1160 1161 1162 1163 1164 | ** Also see the Pull instruction. */ case OP_Dup: { int i = p->tos - pOp->p1; int j = ++p->tos; VERIFY( if( i<0 ) goto not_enough_stack; ) VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) | > > > > > > > | | > | | | < | > | 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 | ** Also see the Pull instruction. */ case OP_Dup: { int i = p->tos - pOp->p1; int j = ++p->tos; VERIFY( if( i<0 ) goto not_enough_stack; ) VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) memcpy(&aStack[j], &aStack[i], sizeof(aStack[i])-NBFS); if( aStack[j].flags & STK_Str ){ if( aStack[j].flags & STK_Static ){ zStack[j] = zStack[i]; aStack[j].flags = STK_Str | STK_Static; }else if( aStack[i].n<=NBFS ){ memcpy(aStack[j].z, zStack[i], aStack[j].n); zStack[j] = aStack[j].z; aStack[j].flags = STK_Str; }else{ zStack[j] = sqliteMalloc( aStack[j].n ); if( zStack[j]==0 ) goto no_mem; memcpy(zStack[j], zStack[i], aStack[j].n); aStack[j].flags = STK_Str | STK_Dyn; } } break; } /* Opcode: Pull P1 * * ** ** The P1-th element is removed from its current location on |
︙ | ︙ | |||
1190 1191 1192 1193 1194 1195 1196 | Stack ts; char *tz; VERIFY( if( from<0 ) goto not_enough_stack; ) ts = aStack[from]; tz = zStack[from]; for(i=from; i<to; i++){ aStack[i] = aStack[i+1]; | > | > > | > > | > > > | 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 | Stack ts; char *tz; VERIFY( if( from<0 ) goto not_enough_stack; ) ts = aStack[from]; tz = zStack[from]; for(i=from; i<to; i++){ aStack[i] = aStack[i+1]; if( aStack[i].flags & (STK_Dyn|STK_Static) ){ zStack[i] = zStack[i+1]; }else{ zStack[i] = aStack[i].z; } } aStack[to] = ts; if( aStack[to].flags & (STK_Dyn|STK_Static) ){ zStack[to] = tz; }else{ zStack[to] = aStack[to].z; } break; } /* Opcode: ColumnCount P1 * * ** ** Specify the number of column values that will appear in the ** array passed as the 4th parameter to the callback. No checking |
︙ | ︙ | |||
1226 1227 1228 1229 1230 1231 1232 | */ case OP_ColumnName: { p->azColName[pOp->p1] = pOp->p3 ? pOp->p3 : ""; p->nCallback = 0; break; } | | > > > > > > > > > > | | | | > > > > > > > | 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 | */ case OP_ColumnName: { p->azColName[pOp->p1] = pOp->p3 ? pOp->p3 : ""; p->nCallback = 0; break; } /* Opcode: Callback P1 P2 * ** ** Pop P1 values off the stack and form them into an array. Then ** invoke the callback function using the newly formed array as the ** 3rd parameter. ** ** If the offset counter (set by the OP_Limit opcode) is positive, ** then decrement the counter and do not invoke the callback. ** ** If the callback is invoked, then after the callback returns ** decrement the limit counter. When the limit counter reaches ** zero, jump to address P2. */ case OP_Callback: { int i = p->tos - pOp->p1 + 1; int j; VERIFY( if( i<0 ) goto not_enough_stack; ) VERIFY( if( NeedStack(p, p->tos+2) ) goto no_mem; ) for(j=i; j<=p->tos; j++){ if( (aStack[j].flags & STK_Null)==0 ){ if( Stringify(p, j) ) goto no_mem; } } zStack[p->tos+1] = 0; if( xCallback!=0 ){ if( p->iOffset>0 ){ p->iOffset--; }else{ if( xCallback(pArg, pOp->p1, &zStack[i], p->azColName)!=0 ){ rc = SQLITE_ABORT; } p->nCallback++; if( p->iLimit>0 ){ p->iLimit--; if( p->iLimit==0 ){ pc = pOp->p2 - 1; } } } } PopStack(p, pOp->p1); if( sqlite_malloc_failed ) goto no_mem; break; } /* Opcode: NullCallback P1 * * |
︙ | ︙ | |||
1458 1459 1460 1461 1462 1463 1464 1465 | ** specified by the integer and push the floating-point number back onto ** the stack. */ case OP_Precision: { int tos = p->tos; int nos = tos - 1; int nDigit; double v; | > | | > > > > | > > > | | > > > > > > > > | | < < < < | < < < < < < < < < < < < < | | | < < < < < < < < < < < < < < | | | > | > > > | 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 | ** specified by the integer and push the floating-point number back onto ** the stack. */ case OP_Precision: { int tos = p->tos; int nos = tos - 1; int nDigit; int len; double v; char *zNew; VERIFY( if( nos<0 ) goto not_enough_stack; ) Realify(p, tos); Integerify(p, nos); nDigit = aStack[nos].i; if( nDigit<0 ) nDigit = 0; if( nDigit>30 ) nDigit = 30; v = aStack[tos].r; zNew = sqlite_mprintf("%.*f", nDigit, v); if( zNew==0 ) goto no_mem; POPSTACK; Release(p, nos); aStack[nos].n = len = strlen(zNew) + 1; if( len<=NBFS ){ strcpy(aStack[nos].z, zNew); zStack[nos] = aStack[nos].z; aStack[nos].flags = STK_Str; sqliteFree(zNew); }else{ zStack[nos] = zNew; aStack[nos].flags = STK_Str | STK_Dyn; } break; } /* Opcode: Max * * * ** ** Pop the top two elements from the stack then push back the ** largest of the two. */ /* Opcode: Min * * * ** ** Pop the top two elements from the stack then push back the ** smaller of the two. */ case OP_Min: case OP_Max: { int tos = p->tos; int nos = tos - 1; int a,b; int ft, fn; int copy = 0; VERIFY( if( nos<0 ) goto not_enough_stack; ) ft = aStack[tos].flags; fn = aStack[nos].flags; if( pOp->opcode==OP_Max ){ a = tos; b = nos; }else{ a = nos; b = tos; } if( fn & STK_Null ){ copy = 1; }else if( ft & STK_Null ){ copy = 0; }else if( (ft & fn & STK_Int)==STK_Int ){ copy = aStack[a].i>aStack[b].i; }else if( ( (ft|fn) & (STK_Int|STK_Real) ) !=0 ){ Realify(p, tos); Realify(p, nos); copy = aStack[a].r>aStack[b].r; }else{ if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem; copy = sqliteCompare(zStack[a],zStack[b])>0; } if( copy ){ Release(p, nos); aStack[nos] = aStack[tos]; if( aStack[nos].flags & (STK_Dyn|STK_Static) ){ zStack[nos] = zStack[tos]; }else{ zStack[nos] = aStack[nos].z; } zStack[tos] = 0; aStack[tos].flags = 0; }else{ Release(p, tos); } p->tos = nos; break; |
︙ | ︙ | |||
2012 2013 2014 2015 2016 2017 2018 | ** 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. ** ** See also: MakeIdxKey, SortMakeKey */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | > > < > | | > > > | | > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > | > > | > > | | | > | | 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 | ** 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. ** ** See also: MakeIdxKey, SortMakeKey */ /* 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: case OP_MakeKey: { char *zNewKey; int nByte; int nField; int addRowid; int i, j; addRowid = pOp->opcode==OP_MakeIdxKey; nField = pOp->p1; VERIFY( if( p->tos+1+addRowid<nField ) goto not_enough_stack; ) nByte = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ int flags = aStack[i].flags; int len; char *z; if( flags & STK_Null ){ nByte += 2; }else if( flags & STK_Real ){ z = aStack[i].z; sqliteRealToSortable(aStack[i].r, &z[1]); z[0] = 0; Release(p, i); len = strlen(&z[1]); zStack[i] = 0; aStack[i].flags = STK_Real; aStack[i].n = len+2; nByte += aStack[i].n; }else if( flags & STK_Int ){ z = aStack[i].z; aStack[i].r = aStack[i].i; sqliteRealToSortable(aStack[i].r, &z[1]); z[0] = 0; Release(p, i); len = strlen(&z[1]); zStack[i] = 0; aStack[i].flags = STK_Int; aStack[i].n = len+2; nByte += aStack[i].n; }else{ assert( flags & STK_Str ); if( isNumber(zStack[i]) ){ aStack[i].r = atof(zStack[i]); Release(p, i); z = aStack[i].z; sqliteRealToSortable(aStack[i].r, &z[1]); z[0] = 0; len = strlen(&z[1]); zStack[i] = 0; aStack[i].flags = STK_Real; aStack[i].n = len+2; } nByte += aStack[i].n; } } if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){ rc = SQLITE_TOOBIG; goto abort_due_to_error; } if( addRowid ) nByte += sizeof(u32); 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; zNewKey[j++] = 0; }else{ memcpy(&zNewKey[j], zStack[i] ? zStack[i] : aStack[i].z, aStack[i].n); j += aStack[i].n; } } if( addRowid ){ u32 iKey; Integerify(p, p->tos-nField); iKey = bigEndian(aStack[p->tos-nField].i); memcpy(&zNewKey[j], &iKey, sizeof(u32)); } if( pOp->p2==0 ) PopStack(p, nField+addRowid); 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; } |
︙ | ︙ | |||
2682 2683 2684 2685 2686 2687 2688 | ** in the data. ** ** If the KeyAsData opcode has previously executed on this cursor, ** then the field might be extracted from the key rather than the ** data. */ case OP_Column: { | | | 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 | ** in the data. ** ** If the KeyAsData opcode has previously executed on this cursor, ** then the field might be extracted from the key rather than the ** data. */ case OP_Column: { int amt, offset, end, payloadSize; int i = pOp->p1; int p2 = pOp->p2; int tos = p->tos+1; Cursor *pC; BtCursor *pCrsr; int idxWidth; unsigned char aHdr[10]; |
︙ | ︙ | |||
2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 | } /* amt and offset now hold the offset to the start of data and the ** amount of data. Go get the data and put it on the stack. */ if( amt==0 ){ aStack[tos].flags = STK_Null; }else{ char *z = sqliteMalloc( amt ); if( z==0 ) goto no_mem; (*xRead)(pCrsr, offset, amt, z); aStack[tos].flags = STK_Str | STK_Dyn; zStack[tos] = z; aStack[tos].n = amt; | > > > > > | 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 | } /* amt and offset now hold the offset to the start of data and the ** amount of data. Go get the data and put it on the stack. */ if( amt==0 ){ aStack[tos].flags = STK_Null; }else if( amt<=NBFS ){ (*xRead)(pCrsr, offset, amt, aStack[tos].z); aStack[tos].flags = STK_Str; zStack[tos] = aStack[tos].z; aStack[tos].n = amt; }else{ char *z = sqliteMalloc( amt ); if( z==0 ) goto no_mem; (*xRead)(pCrsr, offset, amt, z); aStack[tos].flags = STK_Str | STK_Dyn; zStack[tos] = z; aStack[tos].n = amt; |
︙ | ︙ | |||
2811 2812 2813 2814 2815 2816 2817 | char *z; sqliteBtreeKeySize(pCrsr, &amt); if( amt<=0 ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } | > | > > > > > < | 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 | char *z; sqliteBtreeKeySize(pCrsr, &amt); if( amt<=0 ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } if( amt>NBFS ){ z = sqliteMalloc( amt ); aStack[tos].flags = STK_Str | STK_Dyn; }else{ z = aStack[tos].z; aStack[tos].flags = STK_Str; } sqliteBtreeKey(pCrsr, 0, amt, z); zStack[tos] = z; aStack[tos].n = amt; } break; } /* Opcode: Rewind P1 * * ** |
︙ | ︙ | |||
3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 | ** ** In the current implementation, this is a no-op. */ case OP_Reorganize: { /* This is currently a no-op */ break; } /* Opcode: ListWrite * * * ** ** Write the integer on the top of the stack ** into the temporary storage list. */ case OP_ListWrite: { | > > > > > > > > > > > > > > > > > > > | 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 | ** ** In the current implementation, this is a no-op. */ case OP_Reorganize: { /* This is currently a no-op */ break; } /* Opcode: Limit P1 P2 * ** ** Set a limit and offset on callbacks. P1 is the limit and P2 is ** the offset. If the offset counter is positive, no callbacks are ** invoked but instead the counter is decremented. Once the offset ** counter reaches zero, callbacks are invoked and the limit ** counter is decremented. When the limit counter reaches zero, ** the OP_Callback or OP_SortCallback instruction executes a jump ** that should end the query. ** ** This opcode is used to implement the "LIMIT x OFFSET y" clause ** of a SELECT statement. */ case OP_Limit: { p->iLimit = pOp->p1; p->iOffset = pOp->p2; break; } /* Opcode: ListWrite * * * ** ** Write the integer on the top of the stack ** into the temporary storage list. */ case OP_ListWrite: { |
︙ | ︙ | |||
3179 3180 3181 3182 3183 3184 3185 | } break; } /* Opcode: SortPut * * * ** ** The TOS is the key and the NOS is the data. Pop both from the stack | | > > > | 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 | } break; } /* Opcode: SortPut * * * ** ** The TOS is the key and the NOS is the data. Pop both from the stack ** and put them on the sorter. The key and data should have been ** made using SortMakeKey and SortMakeRec, respectively. */ case OP_SortPut: { int tos = p->tos; int nos = tos - 1; Sorter *pSorter; VERIFY( if( tos<1 ) goto not_enough_stack; ) if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem; pSorter = sqliteMalloc( sizeof(Sorter) ); if( pSorter==0 ) goto no_mem; pSorter->pNext = p->pSort; p->pSort = pSorter; assert( aStack[tos].flags & STK_Dyn ); assert( aStack[nos].flags & STK_Dyn ); pSorter->nKey = aStack[tos].n; pSorter->zKey = zStack[tos]; pSorter->nData = aStack[nos].n; pSorter->pData = zStack[nos]; aStack[tos].flags = 0; aStack[nos].flags = 0; zStack[tos] = 0; |
︙ | ︙ | |||
3355 3356 3357 3358 3359 3360 3361 | sqliteFree(pSorter); }else{ pc = pOp->p2 - 1; } break; } | | > > > > > > > > > > | | > > > > > > > > | 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 | sqliteFree(pSorter); }else{ pc = pOp->p2 - 1; } break; } /* Opcode: SortCallback P1 P2 * ** ** The top of the stack contains a callback record built using ** the SortMakeRec operation with the same P1 value as this ** instruction. Pop this record from the stack and invoke the ** callback on it. ** ** If the offset counter (set by the OP_Limit opcode) is positive, ** then decrement the counter and do not invoke the callback. ** ** If the callback is invoked, then after the callback returns ** decrement the limit counter. When the limit counter reaches ** zero, jump to address P2. */ case OP_SortCallback: { int i = p->tos; VERIFY( if( i<0 ) goto not_enough_stack; ) if( xCallback!=0 ){ if( p->iOffset>0 ){ p->iOffset--; }else{ if( xCallback(pArg, pOp->p1, (char**)zStack[i], p->azColName)!=0 ){ rc = SQLITE_ABORT; } p->nCallback++; if( p->iLimit>0 ){ p->iLimit--; if( p->iLimit==0 ){ pc = pOp->p2 - 1; } } } p->nCallback++; } POPSTACK; if( sqlite_malloc_failed ) goto no_mem; break; } |
︙ | ︙ | |||
3409 3410 3411 3412 3413 3414 3415 | sqliteSetString(pzErrMsg,"unable to open file: ", pOp->p3, 0); rc = SQLITE_ERROR; goto cleanup; } break; } | < < < < < < < < < < < < < < < < < < < < < < < < < | 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 | sqliteSetString(pzErrMsg,"unable to open file: ", pOp->p3, 0); rc = SQLITE_ERROR; goto cleanup; } break; } /* Opcode: FileRead P1 P2 P3 ** ** Read a single line of input from the open file (the file opened using ** FileOpen). If we reach end-of-file, jump immediately to P2. If ** we are able to get another line, split the line apart using P3 as ** a delimiter. There should be P1 fields. If the input line contains ** more than P1 fields, ignore the excess. If the input line contains |
︙ | ︙ | |||
3557 3558 3559 3560 3561 3562 3563 | ** Pop a single value of the stack and store that value into memory ** location P1. P1 should be a small integer since space is allocated ** for all memory locations between 0 and P1 inclusive. */ case OP_MemStore: { int i = pOp->p1; int tos = p->tos; | < > | | > | > > | > > > > | 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 | ** Pop a single value of the stack and store that value into memory ** location P1. P1 should be a small integer since space is allocated ** for all memory locations between 0 and P1 inclusive. */ case OP_MemStore: { int i = pOp->p1; int tos = p->tos; char *zOld; Mem *pMem; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( i>=p->nMem ){ int nOld = p->nMem; Mem *aMem; p->nMem = i + 5; aMem = sqliteRealloc(p->aMem, p->nMem*sizeof(p->aMem[0])); if( aMem==0 ) goto no_mem; p->aMem = aMem; if( nOld<p->nMem ){ memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld)); } } pMem = &p->aMem[i]; if( pMem->s.flags & STK_Dyn ){ zOld = pMem->z; }else{ zOld = 0; } pMem->s = aStack[tos]; if( pMem->s.flags & (STK_Static|STK_Dyn) ){ pMem->z = zStack[tos]; }else{ pMem->z = pMem->s.z; } if( zOld ) sqliteFree(zOld); zStack[tos] = 0; aStack[tos].flags = 0; POPSTACK; break; } /* Opcode: MemLoad P1 * * ** ** Push a copy of the value in memory location P1 onto the stack. */ case OP_MemLoad: { int tos = ++p->tos; int i = pOp->p1; VERIFY( if( NeedStack(p, tos) ) goto no_mem; ) if( i<0 || i>=p->nMem ){ aStack[tos].flags = STK_Null; zStack[tos] = 0; }else{ aStack[tos] = p->aMem[i].s; if( aStack[tos].flags & STK_Dyn ){ char *z = sqliteMalloc(aStack[tos].n); if( z==0 ) goto no_mem; memcpy(z, p->aMem[i].z, aStack[tos].n); zStack[tos] = z; aStack[tos].flags |= STK_Dyn; }else if( aStack[tos].flags & STK_Static ){ zStack[tos] = p->aMem[i].z; }else if( aStack[tos].flags & STK_Str ){ zStack[tos] = aStack[tos].z; } } break; } /* Opcode: AggReset * P2 * ** |
︙ | ︙ | |||
3708 3709 3710 3711 3712 3713 3714 | char *zOld; if( pMem->s.flags & STK_Dyn ){ zOld = pMem->z; }else{ zOld = 0; } pMem->s = aStack[tos]; | | > > | | | < | > | 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 | char *zOld; if( pMem->s.flags & STK_Dyn ){ zOld = pMem->z; }else{ zOld = 0; } pMem->s = aStack[tos]; if( pMem->s.flags & STK_Dyn ){ pMem->z = zStack[tos]; zStack[tos] = 0; aStack[tos].flags = 0; }else if( pMem->s.flags & STK_Static ){ pMem->z = zStack[tos]; }else if( pMem->s.flags & STK_Str ){ pMem->z = pMem->s.z; } if( zOld ) sqliteFree(zOld); } POPSTACK; break; } |
︙ | ︙ | |||
3768 3769 3770 3771 3772 3773 3774 | pc = pOp->p2 - 1; } else { p->agg.pCurrent = sqliteHashData(p->agg.pSearch); } break; } | < < < < < < < < < < < < < < | 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 | pc = pOp->p2 - 1; } else { p->agg.pCurrent = sqliteHashData(p->agg.pSearch); } break; } /* Opcode: SetInsert P1 * P3 ** ** If Set P1 does not exist then create it. Then insert value ** P3 into that set. If P3 is NULL, then insert the top of the ** stack into the set. */ case OP_SetInsert: { |
︙ | ︙ |
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.33 2001/11/06 04:00:19 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
123 124 125 126 127 128 129 | #define OP_SortNext 46 #define OP_SortCallback 47 #define OP_SortReset 48 #define OP_FileOpen 49 #define OP_FileRead 50 #define OP_FileColumn 51 | < | | | | | | | | | < | | | | | | | | | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > | 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 | #define OP_SortNext 46 #define OP_SortCallback 47 #define OP_SortReset 48 #define OP_FileOpen 49 #define OP_FileRead 50 #define OP_FileColumn 51 #define OP_AggReset 52 #define OP_AggFocus 53 #define OP_AggIncr 54 #define OP_AggNext 55 #define OP_AggSet 56 #define OP_AggGet 57 #define OP_SetInsert 58 #define OP_SetFound 59 #define OP_SetNotFound 60 #define OP_MakeRecord 61 #define OP_MakeKey 62 #define OP_MakeIdxKey 63 #define OP_Goto 64 #define OP_If 65 #define OP_Halt 66 #define OP_ColumnCount 67 #define OP_ColumnName 68 #define OP_Callback 69 #define OP_NullCallback 70 #define OP_Integer 71 #define OP_String 72 #define OP_Pop 73 #define OP_Dup 74 #define OP_Pull 75 #define OP_Add 76 #define OP_AddImm 77 #define OP_Subtract 78 #define OP_Multiply 79 #define OP_Divide 80 #define OP_Remainder 81 #define OP_BitAnd 82 #define OP_BitOr 83 #define OP_BitNot 84 #define OP_ShiftLeft 85 #define OP_ShiftRight 86 #define OP_AbsValue 87 #define OP_Precision 88 #define OP_Min 89 #define OP_Max 90 #define OP_Like 91 #define OP_Glob 92 #define OP_Eq 93 #define OP_Ne 94 #define OP_Lt 95 #define OP_Le 96 #define OP_Gt 97 #define OP_Ge 98 #define OP_IsNull 99 #define OP_NotNull 100 #define OP_Negative 101 #define OP_And 102 #define OP_Or 103 #define OP_Not 104 #define OP_Concat 105 #define OP_Noop 106 #define OP_Strlen 107 #define OP_Substr 108 #define OP_Limit 109 #define OP_MAX 111 /* ** Prototypes for the VDBE interface. See comments on the implementation ** for a description of what each of these routines does. */ |
︙ | ︙ |