Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | The callback-free API is now working, though much more testing is need. (CVS 853) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
162b259188e6967fe9c3722da26b81aa |
User & Date: | drh 2003-01-29 14:06:08.000 |
Context
2003-01-29
| ||
18:46 | Better error messages on constraint violations. Additional tests and bug fixes for the callback-free API. (CVS 854) (check-in: ccc82f1ab4 user: drh tags: trunk) | |
14:06 | The callback-free API is now working, though much more testing is need. (CVS 853) (check-in: 162b259188 user: drh tags: trunk) | |
2003-01-28
| ||
23:13 | First code for the new callback-free API. All regression tests pass but the new API is mostly untested and is unlikely to work. (CVS 852) (check-in: 065fa818ff user: drh tags: trunk) | |
Changes
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.111 2003/01/29 14:06:08 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** A pointer to this structure is used to communicate information |
︙ | ︙ | |||
618 619 620 621 622 623 624 | } } if( db->file_format<3 ){ sqliteSafetyOff(db); sqliteSetString(pzErrMsg, "obsolete database file format", 0); return SQLITE_ERROR; } | | < > < | | | 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 | } } if( db->file_format<3 ){ sqliteSafetyOff(db); sqliteSetString(pzErrMsg, "obsolete database file format", 0); return SQLITE_ERROR; } if( db->pVdbe==0 ){ db->nChange = 0; } memset(&sParse, 0, sizeof(sParse)); sParse.db = db; sParse.pBe = db->pBe; sParse.xCallback = xCallback; sParse.pArg = pArg; sParse.useCallback = ppVm==0; #ifndef SQLITE_OMIT_TRACE if( db->xTrace ) db->xTrace(db->pTraceArg, zSql); #endif sqliteRunParser(&sParse, zSql, pzErrMsg); if( sqlite_malloc_failed ){ sqliteSetString(pzErrMsg, "out of memory", 0); sParse.rc = SQLITE_NOMEM; sqliteBtreeRollback(db->pBe); if( db->pBeTemp ) sqliteBtreeRollback(db->pBeTemp); db->flags &= ~SQLITE_InTrans; sqliteResetInternalSchema(db); } if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){ sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), 0); } sqliteStrRealloc(pzErrMsg); if( sParse.rc==SQLITE_SCHEMA ){ sqliteResetInternalSchema(db); } if( sParse.useCallback==0 ){ assert( ppVm ); *ppVm = (sqlite_vm*)sParse.pVdbe; *pzTail = sParse.zTail; } if( sqliteSafetyOff(db) ) goto exec_misuse; return sParse.rc; exec_misuse: if( pzErrMsg ){ *pzErrMsg = 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.124 2003/01/29 14:06:09 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. |
︙ | ︙ | |||
693 694 695 696 697 698 699 | Parse *pParse, /* Parser context */ int base, /* VDBE cursor corresponding to first entry in pTabList */ SrcList *pTabList, /* List of tables */ ExprList *pEList /* Expressions defining the result set */ ){ Vdbe *v = pParse->pVdbe; int i; | | > > | 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 | Parse *pParse, /* Parser context */ int base, /* VDBE cursor corresponding to first entry in pTabList */ SrcList *pTabList, /* List of tables */ ExprList *pEList /* Expressions defining the result set */ ){ Vdbe *v = pParse->pVdbe; int i; if( pParse->useCallback && (pParse->db->flags & SQLITE_ReportTypes)==0 ){ return; } for(i=0; i<pEList->nExpr; i++){ Expr *p = pEList->a[i].pExpr; char *zType = 0; if( p==0 ) continue; if( p->op==TK_COLUMN && pTabList ){ Table *pTab = pTabList->a[p->iTable - base].pTab; int iCol = p->iColumn; |
︙ | ︙ | |||
1452 1453 1454 1455 1456 1457 1458 | selectOpName(p->op), " do not have the same number of result columns", 0); pParse->nErr++; return 1; } /* Issue a null callback if that is what the user wants. */ | > | > | 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 | selectOpName(p->op), " do not have the same number of result columns", 0); pParse->nErr++; return 1; } /* Issue a null callback if that is what the user wants. */ if( eDest==SRT_Callback && (pParse->useCallback==0 || (pParse->db->flags & SQLITE_NullCallback)!=0) ){ sqliteVdbeAddOp(v, OP_NullCallback, p->pEList->nExpr, 0); } return 0; } /* ** Recursively scan through an expression tree. For every reference |
︙ | ︙ | |||
2302 2303 2304 2305 2306 2307 2308 | if( pOrderBy ){ generateSortTail(p, v, pEList->nExpr, eDest, iParm); } /* Issue a null callback if that is what the user wants. */ | > | > | 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 | if( pOrderBy ){ generateSortTail(p, v, pEList->nExpr, eDest, iParm); } /* Issue a null callback if that is what the user wants. */ if( eDest==SRT_Callback && (pParse->useCallback==0 || (pParse->db->flags & SQLITE_NullCallback)!=0) ){ sqliteVdbeAddOp(v, OP_NullCallback, pEList->nExpr, 0); } /* The SELECT was successfully coded. Set the return code to 0 ** to indicate no errors. */ rc = 0; |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
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 header file defines the interface that the SQLite library ** presents to client programs. ** | | | 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 header file defines the interface that the SQLite library ** presents to client programs. ** ** @(#) $Id: sqlite.h.in,v 1.41 2003/01/29 14:06:09 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ #include <stdarg.h> /* Needed for the definition of va_list */ /* ** Make sure we can call this stuff from C++. |
︙ | ︙ | |||
584 585 586 587 588 589 590 591 592 593 594 595 596 597 | ** ** *pzTail is made to point to the first character past the end of the first ** SQL statement in zSql. This routine only compiles the first statement ** in zSql, so *pzTail is left pointing to what remains uncompiled. ** ** *ppVm is left pointing to a "virtual machine" that can be used to execute ** the compiled statement. Or if there is an error, *ppVm may be set to NULL. ** ** If any errors are detected during compilation, an error message is written ** into space obtained from malloc() and *pzErrMsg is made to point to that ** error message. The calling routine is responsible for freeing the text ** of this message when it has finished with it. Use sqlite_freemem() to ** free the message. pzErrMsg may be NULL in which case no error message ** will be generated. | > > | 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 | ** ** *pzTail is made to point to the first character past the end of the first ** SQL statement in zSql. This routine only compiles the first statement ** in zSql, so *pzTail is left pointing to what remains uncompiled. ** ** *ppVm is left pointing to a "virtual machine" that can be used to execute ** the compiled statement. Or if there is an error, *ppVm may be set to NULL. ** If the input text contained no SQL (if the input is and empty string or ** a comment) then *ppVm is set to NULL. ** ** If any errors are detected during compilation, an error message is written ** into space obtained from malloc() and *pzErrMsg is made to point to that ** error message. The calling routine is responsible for freeing the text ** of this message when it has finished with it. Use sqlite_freemem() to ** free the message. pzErrMsg may be NULL in which case no error message ** will be generated. |
︙ | ︙ |
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.158 2003/01/29 14:06:09 drh Exp $ */ #include "config.h" #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" |
︙ | ︙ | |||
220 221 222 223 224 225 226 | Hash aFunc; /* All functions that can be in SQL exprs */ Hash aFKey; /* Foreign keys indexed by to-table */ int lastRowid; /* ROWID of most recent insert */ int priorNewRowid; /* Last randomly generated ROWID */ int onError; /* Default conflict algorithm */ int magic; /* Magic number for detect library misuse */ int nChange; /* Number of rows changed */ | | | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | Hash aFunc; /* All functions that can be in SQL exprs */ Hash aFKey; /* Foreign keys indexed by to-table */ int lastRowid; /* ROWID of most recent insert */ int priorNewRowid; /* Last randomly generated ROWID */ int onError; /* Default conflict algorithm */ int magic; /* Magic number for detect library misuse */ int nChange; /* Number of rows changed */ struct Vdbe *pVdbe; /* List of active virtual machines */ #ifndef SQLITE_OMIT_TRACE void (*xTrace)(void*,const char*); /* Trace function */ void *pTraceArg; /* Argument to the trace function */ #endif #ifndef SQLITE_OMIT_AUTHORIZATION int (*xAuth)(void*,int,const char*,const char*); /* Access Auth function */ void *pAuthArg; /* 1st argument to the access auth function */ |
︙ | ︙ | |||
733 734 735 736 737 738 739 740 741 742 743 744 745 746 | int rc; /* Return code from execution */ sqlite_callback xCallback; /* The callback function */ void *pArg; /* First argument to the callback function */ char *zErrMsg; /* An error message */ Token sErrToken; /* The token at which the error occurred */ Token sFirstToken; /* The first token parsed */ Token sLastToken; /* The last token parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Vdbe *pVdbe; /* An engine for executing database bytecode */ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ u8 explain; /* True if the EXPLAIN flag is found on the query */ u8 initFlag; /* True if reparsing CREATE TABLEs */ u8 nameClash; /* A permanent table name clashes with temp table name */ u8 useAgg; /* If true, extract field values from the aggregator | > | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 | int rc; /* Return code from execution */ sqlite_callback xCallback; /* The callback function */ void *pArg; /* First argument to the callback function */ char *zErrMsg; /* An error message */ Token sErrToken; /* The token at which the error occurred */ Token sFirstToken; /* The first token parsed */ Token sLastToken; /* The last token parsed */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Vdbe *pVdbe; /* An engine for executing database bytecode */ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ u8 explain; /* True if the EXPLAIN flag is found on the query */ u8 initFlag; /* True if reparsing CREATE TABLEs */ u8 nameClash; /* A permanent table name clashes with temp table name */ u8 useAgg; /* If true, extract field values from the aggregator |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | | 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. ** ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test1.c,v 1.18 2003/01/29 14:06:09 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> /* |
︙ | ︙ | |||
729 730 731 732 733 734 735 | if( rc ){ assert( vm==0 ); sprintf(zBuf, "(%d) ", rc); Tcl_AppendResult(interp, zBuf, zErr, 0); sqlite_freemem(zErr); return TCL_ERROR; } | > | | > | 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 | if( rc ){ assert( vm==0 ); sprintf(zBuf, "(%d) ", rc); Tcl_AppendResult(interp, zBuf, zErr, 0); sqlite_freemem(zErr); return TCL_ERROR; } if( vm ){ sprintf(zBuf, "%p", vm); Tcl_AppendResult(interp, zBuf, 0); } Tcl_SetVar(interp, argv[3], zTail, 0); return TCL_OK; } /* ** Usage: sqlite_step VM NVAR VALUEVAR COLNAMEVAR ** |
︙ | ︙ | |||
761 762 763 764 765 766 767 | if( argc!=5 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " VM NVAR VALUEVAR COLNAMEVAR", 0); return TCL_ERROR; } if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR; rc = sqlite_step(vm, &N, &azValue, &azColName); | | | | | | | 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 | if( argc!=5 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " VM NVAR VALUEVAR COLNAMEVAR", 0); return TCL_ERROR; } if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR; rc = sqlite_step(vm, &N, &azValue, &azColName); if( rc==SQLITE_DONE || rc==SQLITE_ROW ){ sprintf(zBuf, "%d", N); Tcl_SetVar(interp, argv[2], zBuf, 0); Tcl_SetVar(interp, argv[3], "", 0); if( rc==SQLITE_ROW ){ for(i=0; i<N; i++){ Tcl_SetVar(interp, argv[3], azValue[i] ? azValue[i] : "", TCL_APPEND_VALUE | TCL_LIST_ELEMENT); } } Tcl_SetVar(interp, argv[4], "", 0); for(i=0; i<N*2; i++){ Tcl_SetVar(interp, argv[4], azColName[i] ? azColName[i] : "", TCL_APPEND_VALUE | TCL_LIST_ELEMENT); } } switch( rc ){ case SQLITE_DONE: zRc = "SQLITE_DONE"; break; case SQLITE_BUSY: zRc = "SQLITE_BUSY"; break; case SQLITE_ROW: zRc = "SQLITE_ROW"; break; case SQLITE_ERROR: zRc = "SQLITE_ERROR"; break; case SQLITE_MISUSE: zRc = "SQLITE_MISUSE"; break; default: zRc = "unknown"; break; } Tcl_AppendResult(interp, zRc, 0); return TCL_OK; } |
︙ | ︙ | |||
805 806 807 808 809 810 811 | char **argv /* Text of each argument */ ){ sqlite_vm *vm; int rc; char *zErrMsg = 0; if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], | | | 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 | char **argv /* Text of each argument */ ){ sqlite_vm *vm; int rc; char *zErrMsg = 0; if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " VM\"", 0); return TCL_ERROR; } if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR; rc = sqlite_finalize(vm, &zErrMsg); if( rc ){ char zBuf[50]; sprintf(zBuf, "(%d) ", rc); |
︙ | ︙ |
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.55 2003/01/29 14:06:09 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include <stdlib.h> /* |
︙ | ︙ | |||
418 419 420 421 422 423 424 425 426 427 428 429 430 431 | i = 0; pEngine = sqliteParserAlloc((void*(*)(int))malloc); if( pEngine==0 ){ sqliteSetString(pzErrMsg, "out of memory", 0); return 1; } pParse->sLastToken.dyn = 0; while( sqlite_malloc_failed==0 && zSql[i]!=0 ){ assert( i>=0 ); pParse->sLastToken.z = &zSql[i]; assert( pParse->sLastToken.dyn==0 ); pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType); i += pParse->sLastToken.n; | > | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 | i = 0; pEngine = sqliteParserAlloc((void*(*)(int))malloc); if( pEngine==0 ){ sqliteSetString(pzErrMsg, "out of memory", 0); return 1; } pParse->sLastToken.dyn = 0; pParse->zTail = zSql; while( sqlite_malloc_failed==0 && zSql[i]!=0 ){ assert( i>=0 ); pParse->sLastToken.z = &zSql[i]; assert( pParse->sLastToken.dyn==0 ); pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType); i += pParse->sLastToken.n; |
︙ | ︙ | |||
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 | } case TK_ILLEGAL: { sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1, pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0); nErr++; goto abort_parse; } default: { sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse); lastTokenParsed = tokenType; if( pParse->rc!=SQLITE_OK ){ goto abort_parse; } break; } } } abort_parse: if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ if( lastTokenParsed!=TK_SEMI ){ sqliteParser(pEngine, TK_SEMI, pParse->sLastToken, pParse); } sqliteParser(pEngine, 0, pParse->sLastToken, pParse); } sqliteParserFree(pEngine, free); if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ sqliteSetString(&pParse->zErrMsg, sqlite_error_string(pParse->rc), 0); } | > > > > > | 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | } case TK_ILLEGAL: { sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1, pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0); nErr++; goto abort_parse; } case TK_SEMI: { pParse->zTail = &zSql[i]; /* Fall thru into the default case */ } default: { sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse); lastTokenParsed = tokenType; if( pParse->rc!=SQLITE_OK ){ goto abort_parse; } break; } } } abort_parse: if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ if( lastTokenParsed!=TK_SEMI ){ sqliteParser(pEngine, TK_SEMI, pParse->sLastToken, pParse); pParse->zTail = &zSql[i]; } sqliteParser(pEngine, 0, pParse->sLastToken, pParse); } sqliteParserFree(pEngine, free); if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ sqliteSetString(&pParse->zErrMsg, sqlite_error_string(pParse->rc), 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.57 2003/01/29 14:06:09 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* ** If malloc() ever fails, this global variable gets set to 1. |
︙ | ︙ | |||
1192 1193 1194 1195 1196 1197 1198 | ** sqlite.magic to SQLITE_MAGIC_ERROR. This will cause a complete ** shutdown of the database. ** ** This routine is used to try to detect when API routines are called ** at the wrong time or in the wrong sequence. */ int sqliteSafetyCheck(sqlite *db){ | | | 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 | ** sqlite.magic to SQLITE_MAGIC_ERROR. This will cause a complete ** shutdown of the database. ** ** This routine is used to try to detect when API routines are called ** at the wrong time or in the wrong sequence. */ int sqliteSafetyCheck(sqlite *db){ if( db->pVdbe!=0 ){ db->magic = SQLITE_MAGIC_ERROR; return 1; } return 0; } |
Changes to src/vdbe.c.
︙ | ︙ | |||
32 33 34 35 36 37 38 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.201 2003/01/29 14:06:09 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The makefile scans this source file and creates the following ** array of string constants which are the names of all VDBE opcodes. |
︙ | ︙ | |||
238 239 240 241 242 243 244 245 246 247 248 249 250 251 | ** state of the virtual machine. ** ** The "sqlite_vm" structure pointer that is returned by sqlite_compile() ** is really a pointer to an instance of this structure. */ struct Vdbe { sqlite *db; /* The whole database */ Btree *pBt; /* Opaque context structure used by DB backend */ FILE *trace; /* Write an execution trace here, if not NULL */ int nOp; /* Number of instructions in the program */ int nOpAlloc; /* Number of slots allocated for aOp[] */ Op *aOp; /* Space to hold the virtual machine's program */ int nLabel; /* Number of labels used */ int nLabelAlloc; /* Number of slots allocated in aLabel[] */ | > | 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | ** state of the virtual machine. ** ** The "sqlite_vm" structure pointer that is returned by sqlite_compile() ** is really a pointer to an instance of this structure. */ struct Vdbe { sqlite *db; /* The whole database */ Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ Btree *pBt; /* Opaque context structure used by DB backend */ FILE *trace; /* Write an execution trace here, if not NULL */ int nOp; /* Number of instructions in the program */ int nOpAlloc; /* Number of slots allocated for aOp[] */ Op *aOp; /* Space to hold the virtual machine's program */ int nLabel; /* Number of labels used */ int nLabelAlloc; /* Number of slots allocated in aLabel[] */ |
︙ | ︙ | |||
312 313 314 315 316 317 318 319 320 321 322 323 324 325 | */ Vdbe *sqliteVdbeCreate(sqlite *db){ Vdbe *p; p = sqliteMalloc( sizeof(Vdbe) ); if( p==0 ) return 0; p->pBt = db->pBe; p->db = db; p->magic = VDBE_MAGIC_INIT; return p; } /* ** Turn tracing on or off */ | > > > > > > | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | */ Vdbe *sqliteVdbeCreate(sqlite *db){ Vdbe *p; p = sqliteMalloc( sizeof(Vdbe) ); if( p==0 ) return 0; p->pBt = db->pBe; p->db = db; if( db->pVdbe ){ db->pVdbe->pPrev = p; } p->pNext = db->pVdbe; p->pPrev = 0; db->pVdbe = p; p->magic = VDBE_MAGIC_INIT; return p; } /* ** Turn tracing on or off */ |
︙ | ︙ | |||
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 | int sqlite_step( sqlite_vm *pVm, /* The virtual machine to execute */ int *pN, /* OUT: Number of columns in result */ const char ***pazValue, /* OUT: Column data */ const char ***pazColName /* OUT: Column names and datatypes */ ){ Vdbe *p = (Vdbe*)pVm; int rc; if( p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_MISUSE; } if( p->explain ){ rc = sqliteVdbeList(p); }else{ rc = sqliteVdbeExec(p); } | > > > > > | > > > | 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 | int sqlite_step( sqlite_vm *pVm, /* The virtual machine to execute */ int *pN, /* OUT: Number of columns in result */ const char ***pazValue, /* OUT: Column data */ const char ***pazColName /* OUT: Column names and datatypes */ ){ Vdbe *p = (Vdbe*)pVm; sqlite *db; int rc; if( p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_MISUSE; } db = p->db; if( sqliteSafetyOn(db) ){ return SQLITE_MISUSE; } if( p->explain ){ rc = sqliteVdbeList(p); }else{ rc = sqliteVdbeExec(p); } if( rc==SQLITE_DONE || rc==SQLITE_ROW ){ *pazColName = (const char**)p->azColName; *pN = p->nResColumn; }else{ *pN = 0; *pazColName = 0; } if( rc==SQLITE_ROW ){ *pazValue = (const char**)p->azResColumn; }else{ *pazValue = 0; } if( sqliteSafetyOff(db) ){ return SQLITE_MISUSE; } return rc; } /* ** Reset an Agg structure. Delete all its contents. ** |
︙ | ︙ | |||
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 | /* ** Delete an entire VDBE. */ void sqliteVdbeDelete(Vdbe *p){ int i; if( p==0 ) return; Cleanup(p); if( p->nOpAlloc==0 ){ p->aOp = 0; p->nOp = 0; } for(i=0; i<p->nOp; i++){ if( p->aOp[i].p3type==P3_DYNAMIC ){ sqliteFree(p->aOp[i].p3); | > > > > > > > > > > | 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 | /* ** Delete an entire VDBE. */ void sqliteVdbeDelete(Vdbe *p){ int i; if( p==0 ) return; Cleanup(p); if( p->pPrev ){ p->pPrev->pNext = p->pNext; }else{ assert( p->db->pVdbe==p ); p->db->pVdbe = p->pNext; } if( p->pNext ){ p->pNext->pPrev = p->pPrev; } p->pPrev = p->pNext = 0; if( p->nOpAlloc==0 ){ p->aOp = 0; p->nOp = 0; } for(i=0; i<p->nOp; i++){ if( p->aOp[i].p3type==P3_DYNAMIC ){ sqliteFree(p->aOp[i].p3); |
︙ | ︙ | |||
1251 1252 1253 1254 1255 1256 1257 | p->zStack[4] = p->aOp[i].p3; } p->zStack[1] = sqliteOpcodeNames[p->aOp[i].opcode]; if( p->xCallback==0 ){ p->pc = i+1; p->azResColumn = p->zStack; p->nResColumn = 5; | | | 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 | p->zStack[4] = p->aOp[i].p3; } p->zStack[1] = sqliteOpcodeNames[p->aOp[i].opcode]; if( p->xCallback==0 ){ p->pc = i+1; p->azResColumn = p->zStack; p->nResColumn = 5; return SQLITE_ROW; } if( sqliteSafetyOff(db) ){ p->rc = SQLITE_MISUSE; break; } if( p->xCallback(p->pCbArg, 5, p->zStack, p->azColName) ){ p->rc = SQLITE_ABORT; |
︙ | ︙ | |||
1449 1450 1451 1452 1453 1454 1455 | ** Prepare a virtual machine for execution. This involves things such ** as allocating stack space and initializing the program counter. ** After the VDBE has be prepped, it can be executed by one or more ** calls to sqliteVdbeExec(). ** ** The behavior of sqliteVdbeExec() is influenced by the parameters to ** this routine. If xCallback is NULL, then sqliteVdbeExec() will return | | | 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 | ** Prepare a virtual machine for execution. This involves things such ** as allocating stack space and initializing the program counter. ** After the VDBE has be prepped, it can be executed by one or more ** calls to sqliteVdbeExec(). ** ** The behavior of sqliteVdbeExec() is influenced by the parameters to ** this routine. If xCallback is NULL, then sqliteVdbeExec() will return ** with SQLITE_ROW whenever there is a row of the result set ready ** to be delivered. p->azResColumn will point to the row and ** p->nResColumn gives the number of columns in the row. If xCallback ** is not NULL, then the xCallback() routine is invoked to process each ** row in the result set. */ void sqliteVdbeMakeReady( Vdbe *p, /* The VDBE */ |
︙ | ︙ | |||
1519 1520 1521 1522 1523 1524 1525 | ** ** sqliteVdbeMakeReady() must be called before this routine in order to ** close the program with a final OP_Halt and to set up the callbacks ** and the error message pointer. ** ** Whenever a row or result data is available, this routine will either ** invoke the result callback (if there is one) or return with | | | 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 | ** ** sqliteVdbeMakeReady() must be called before this routine in order to ** close the program with a final OP_Halt and to set up the callbacks ** and the error message pointer. ** ** Whenever a row or result data is available, this routine will either ** invoke the result callback (if there is one) or return with ** SQLITE_ROW. ** ** If an attempt is made to open a locked database, then this routine ** will either invoke the busy callback (if there is one) or it will ** return SQLITE_BUSY. ** ** If an error occurs, an error message is written to memory obtained ** from sqliteMalloc() and p->zErrMsg is made to point to that memory. |
︙ | ︙ | |||
1883 1884 1885 1886 1887 1888 1889 | } zStack[p->tos+1] = 0; if( p->xCallback==0 ){ p->azResColumn = &zStack[i]; p->nResColumn = pOp->p1; p->popStack = pOp->p1; p->pc = pc + 1; | | | 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 | } zStack[p->tos+1] = 0; if( p->xCallback==0 ){ p->azResColumn = &zStack[i]; p->nResColumn = pOp->p1; p->popStack = pOp->p1; p->pc = pc + 1; return SQLITE_ROW; } if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; if( p->xCallback(p->pCbArg, pOp->p1, &zStack[i], p->azColName)!=0 ){ rc = SQLITE_ABORT; } if( sqliteSafetyOn(db) ) goto abort_due_to_misuse; p->nCallback++; |
︙ | ︙ | |||
1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 | if( p->xCallback(p->pCbArg, pOp->p1, 0, p->azColName)!=0 ){ rc = SQLITE_ABORT; } if( sqliteSafetyOn(db) ) goto abort_due_to_misuse; p->nCallback++; if( sqlite_malloc_failed ) goto no_mem; } break; } /* Opcode: Concat P1 P2 P3 ** ** Look at the first P1 elements of the stack. Append them all ** together with the lowest element first. Use P3 as a separator. | > | 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 | if( p->xCallback(p->pCbArg, pOp->p1, 0, p->azColName)!=0 ){ rc = SQLITE_ABORT; } if( sqliteSafetyOn(db) ) goto abort_due_to_misuse; p->nCallback++; if( sqlite_malloc_failed ) goto no_mem; } p->nResColumn = pOp->p1; break; } /* Opcode: Concat P1 P2 P3 ** ** Look at the first P1 elements of the stack. Append them all ** together with the lowest element first. Use P3 as a separator. |
︙ | ︙ | |||
4839 4840 4841 4842 4843 4844 4845 | int i = p->tos; VERIFY( if( i<0 ) goto not_enough_stack; ) if( p->xCallback==0 ){ p->pc = pc+1; p->azResColumn = (char**)zStack[i]; p->nResColumn = pOp->p1; p->popStack = 1; | | | 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 | int i = p->tos; VERIFY( if( i<0 ) goto not_enough_stack; ) if( p->xCallback==0 ){ p->pc = pc+1; p->azResColumn = (char**)zStack[i]; p->nResColumn = pOp->p1; p->popStack = 1; return SQLITE_ROW; }else{ if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; if( p->xCallback(p->pCbArg, pOp->p1, (char**)zStack[i], p->azColName)!=0 ){ rc = SQLITE_ABORT; } if( sqliteSafetyOn(db) ) goto abort_due_to_misuse; p->nCallback++; |
︙ | ︙ |
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.63 2003/01/29 14:06:10 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
58 59 60 61 62 63 64 | ** The following macro converts a relative address in the p2 field ** of a VdbeOp structure into a negative number so that ** sqliteVdbeAddOpList() knows that the address is relative. Calling ** the macro again restores the address. */ #define ADDR(X) (-1-(X)) | < < < < < < < | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | ** The following macro converts a relative address in the p2 field ** of a VdbeOp structure into a negative number so that ** sqliteVdbeAddOpList() knows that the address is relative. Calling ** the macro again restores the address. */ #define ADDR(X) (-1-(X)) /* ** The makefile scans the vdbe.c source file and creates the "opcodes.h" ** header file that defines a number for each opcode used by the VDBE. */ #include "opcodes.h" /* |
︙ | ︙ |
Added test/capi2.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | # 2003 January 29 # # 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 script testing the callback-free C/C++ API. # # $Id: capi2.test,v 1.1 2003/01/29 14:06:10 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl # Check basic functionality # do_test capi2-1.1 { db close set ::DB [sqlite db test.db] execsql {CREATE TABLE t1(a,b,c)} set ::VM [sqlite_compile $::DB {SELECT name, rowid FROM sqlite_master} tail] set tail } {} do_test capi2-1.2 { sqlite_step $::VM ::N ::VALUES ::COLNAMES } {SQLITE_ROW} do_test capi2-1.3 { set ::N } {2} do_test capi2-1.4 { set ::VALUES } {t1 1} do_test capi2-1.5 { set ::COLNAMES } {name rowid text INTEGER} do_test capi2-1.6 { set ::N x set ::VALUES y set ::COLNAMES z sqlite_step $::VM ::N ::VALUES ::COLNAMES } {SQLITE_DONE} do_test capi2-1.7 { list $::N $::VALUES $::COLNAMES } {2 {} {name rowid text INTEGER}} do_test capi2-1.8 { set ::N x set ::VALUES y set ::COLNAMES z sqlite_step $::VM ::N ::VALUES ::COLNAMES } {SQLITE_MISUSE} do_test capi2-1.9 { list $::N $::VALUES $::COLNAMES } {x y z} do_test capi2-1.10 { sqlite_finalize $::VM } {} # Check to make sure that the "tail" of a multi-statement SQL script # is returned by sqlite_compile. # do_test capi2-2.1 { set ::SQL { SELECT name, rowid FROM sqlite_master; SELECT name, rowid FROM sqlite_temp_master; -- A comment at the end } set ::VM [sqlite_compile $::DB $::SQL ::SQL] set ::SQL } { SELECT name, rowid FROM sqlite_temp_master; -- A comment at the end } do_test capi2-2.2 { set r [sqlite_step $::VM n val colname] lappend r $n $val $colname } {SQLITE_ROW 2 {t1 1} {name rowid text INTEGER}} do_test capi2-2.3 { set r [sqlite_step $::VM n val colname] lappend r $n $val $colname } {SQLITE_DONE 2 {} {name rowid text INTEGER}} do_test capi2-2.4 { sqlite_finalize $::VM } {} do_test capi2-2.5 { set ::VM [sqlite_compile $::DB $::SQL ::SQL] set ::SQL } { -- A comment at the end } do_test capi2-2.6 { set r [sqlite_step $::VM n val colname] lappend r $n $val $colname } {SQLITE_DONE 2 {} {name rowid text INTEGER}} do_test capi2-2.7 { sqlite_finalize $::VM } {} do_test capi2-2.8 { set ::VM [sqlite_compile $::DB $::SQL ::SQL] list $::SQL $::VM } {{} {}} finish_test |