Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Modify the Tcl interface to use sqlite3_prepare_v2(). (CVS 4542) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
7bb00c7df672cb8988121f30e3bbdea9 |
User & Date: | danielk1977 2007-11-13 10:30:25.000 |
Context
2007-11-14
| ||
06:48 | Add an experimental API for retrieving the SQL source from a compiled statement: sqlite3_sql(). Ticket #2769. (CVS 4543) (check-in: d31f1e0d74 user: danielk1977 tags: trunk) | |
2007-11-13
| ||
10:30 | Modify the Tcl interface to use sqlite3_prepare_v2(). (CVS 4542) (check-in: 7bb00c7df6 user: danielk1977 tags: trunk) | |
2007-11-12
| ||
21:09 | Various changes to enable compilation of SQLite library and command line shell with the Windows CE cross compiler from cegcc.sourceforge.net (CVS 4541) (check-in: 8ad0ab8cb3 user: chw tags: trunk) | |
Changes
Changes to src/pragma.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2003 April 6 ** ** 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 contains code used to implement the PRAGMA command. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2003 April 6 ** ** 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 contains code used to implement the PRAGMA command. ** ** $Id: pragma.c,v 1.150 2007/11/13 10:30:25 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* Ignore this whole file if pragmas are disabled */ #if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER) |
︙ | ︙ | |||
200 201 202 203 204 205 206 | returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 ); }else{ if( getBoolean(zRight) ){ db->flags |= p->mask; }else{ db->flags &= ~p->mask; } | | > > > > > | > > | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 ); }else{ if( getBoolean(zRight) ){ db->flags |= p->mask; }else{ db->flags &= ~p->mask; } /* Many of the flag-pragmas modify the code generated by the SQL ** compiler (eg. count_changes). So add an opcode to expire all ** compiled SQL statements after modifying a pragma value. */ sqlite3VdbeAddOp(v, OP_Expire, 0, 0); } } return 1; } } return 0; } #endif /* SQLITE_OMIT_FLAG_PRAGMAS */ |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** ** $Id: prepare.c,v 1.63 2007/11/13 10:30:26 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. |
︙ | ︙ | |||
633 634 635 636 637 638 639 640 641 642 643 644 645 646 | if( zSql==0 ){ return 0; } db = sqlite3VdbeDb(p); assert( sqlite3_mutex_held(db->mutex) ); rc = sqlite3LockAndPrepare(db, zSql, -1, 0, &pNew, 0); if( rc ){ assert( pNew==0 ); return 0; }else{ assert( pNew!=0 ); } sqlite3VdbeSwap((Vdbe*)pNew, p); sqlite3_transfer_bindings(pNew, (sqlite3_stmt*)p); | > > > | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 | if( zSql==0 ){ return 0; } db = sqlite3VdbeDb(p); assert( sqlite3_mutex_held(db->mutex) ); rc = sqlite3LockAndPrepare(db, zSql, -1, 0, &pNew, 0); if( rc ){ if( rc==SQLITE_NOMEM ){ db->mallocFailed = 1; } assert( pNew==0 ); return 0; }else{ assert( pNew!=0 ); } sqlite3VdbeSwap((Vdbe*)pNew, p); sqlite3_transfer_bindings(pNew, (sqlite3_stmt*)p); |
︙ | ︙ |
Changes to src/tclsqlite.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. ** ************************************************************************* ** A TCL Interface to SQLite. Append this file to sqlite3.c and ** compile the whole thing to build a TCL-enabled version of 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. ** ************************************************************************* ** A TCL Interface to SQLite. Append this file to sqlite3.c and ** compile the whole thing to build a TCL-enabled version of SQLite. ** ** $Id: tclsqlite.c,v 1.206 2007/11/13 10:30:26 danielk1977 Exp $ */ #include "tcl.h" #include <errno.h> /* ** Some additional include files are needed if this file is not ** appended to the amalgamation. |
︙ | ︙ | |||
882 883 884 885 886 887 888 889 890 891 892 893 894 895 | eol = 1; } } zLine = realloc( zLine, n+1 ); return zLine; } /* ** The "sqlite" command below creates a new Tcl command for each ** connection it opens to an SQLite database. This routine is invoked ** whenever one of those connection-specific commands is executed ** in Tcl. For example, if you run Tcl code like this: ** ** sqlite3 db1 "my_database" | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 | eol = 1; } } zLine = realloc( zLine, n+1 ); return zLine; } /* ** Figure out the column names for the data returned by the statement ** passed as the second argument. ** ** If parameter papColName is not NULL, then *papColName is set to point ** at an array allocated using Tcl_Alloc(). It is the callers responsibility ** to free this array using Tcl_Free(), and to decrement the reference ** count of each Tcl_Obj* member of the array. ** ** The return value of this function is the number of columns of data ** returned by pStmt (and hence the size of the *papColName array). ** ** If pArray is not NULL, then it contains the name of a Tcl array ** variable. The "*" member of this array is set to a list containing ** the names of the columns returned by the statement, in order from ** left to right. e.g. if the names of the returned columns are a, b and ** c, it does the equivalent of the tcl command: ** ** set ${pArray}(*) {a b c} */ static int computeColumnNames( Tcl_Interp *interp, sqlite3_stmt *pStmt, /* SQL statement */ Tcl_Obj ***papColName, /* OUT: Array of column names */ Tcl_Obj *pArray /* Name of array variable (may be null) */ ){ int nCol; /* Compute column names */ nCol = sqlite3_column_count(pStmt); if( papColName ){ int i; Tcl_Obj **apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol ); for(i=0; i<nCol; i++){ apColName[i] = dbTextToObj(sqlite3_column_name(pStmt,i)); Tcl_IncrRefCount(apColName[i]); } /* If results are being stored in an array variable, then create ** the array(*) entry for that array */ if( pArray ){ Tcl_Obj *pColList = Tcl_NewObj(); Tcl_Obj *pStar = Tcl_NewStringObj("*", -1); Tcl_IncrRefCount(pColList); for(i=0; i<nCol; i++){ Tcl_ListObjAppendElement(interp, pColList, apColName[i]); } Tcl_IncrRefCount(pStar); Tcl_ObjSetVar2(interp, pArray, pStar, pColList,0); Tcl_DecrRefCount(pColList); Tcl_DecrRefCount(pStar); } *papColName = apColName; } return nCol; } /* ** The "sqlite" command below creates a new Tcl command for each ** connection it opens to an SQLite database. This routine is invoked ** whenever one of those connection-specific commands is executed ** in Tcl. For example, if you run Tcl code like this: ** ** sqlite3 db1 "my_database" |
︙ | ︙ | |||
1502 1503 1504 1505 1506 1507 1508 | } Tcl_IncrRefCount(objv[2]); zSql = Tcl_GetStringFromObj(objv[2], 0); while( rc==TCL_OK && zSql[0] ){ int i; /* Loop counter */ int nVar; /* Number of bind parameters in the pStmt */ | | < < < < < | | 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 | } Tcl_IncrRefCount(objv[2]); zSql = Tcl_GetStringFromObj(objv[2], 0); while( rc==TCL_OK && zSql[0] ){ int i; /* Loop counter */ int nVar; /* Number of bind parameters in the pStmt */ int nCol = -1; /* Number of columns in the result set */ Tcl_Obj **apColName = 0; /* Array of column names */ int len; /* String length of zSql */ /* Try to find a SQL statement that has already been compiled and ** which matches the next sequence of SQL. */ pStmt = 0; len = strlen(zSql); for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pPreStmt->pNext){ int n = pPreStmt->nSql; if( len>=n && memcmp(pPreStmt->zSql, zSql, n)==0 && (zSql[n]==0 || zSql[n-1]==';') ){ pStmt = pPreStmt->pStmt; zLeft = &zSql[pPreStmt->nSql]; |
︙ | ︙ | |||
1547 1548 1549 1550 1551 1552 1553 | break; } } /* If no prepared statement was found. Compile the SQL text */ if( pStmt==0 ){ | | | 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 | break; } } /* If no prepared statement was found. Compile the SQL text */ if( pStmt==0 ){ if( SQLITE_OK!=sqlite3_prepare_v2(pDb->db, zSql, -1, &pStmt, &zLeft) ){ Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); rc = TCL_ERROR; break; } if( pStmt==0 ){ if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){ /* A compile-time error in the statement |
︙ | ︙ | |||
1621 1622 1623 1624 1625 1626 1627 | } }else{ sqlite3_bind_null( pStmt, i ); } } } | | > | < < < < < < | < | < < > > | | < < < | | < < | < < | < < < | 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 | } }else{ sqlite3_bind_null( pStmt, i ); } } } /* Execute the SQL */ while( rc==TCL_OK && pStmt && SQLITE_ROW==sqlite3_step(pStmt) ){ /* Compute column names. This must be done after the first successful ** call to sqlite3_step(), in case the query is recompiled and the ** number or names of the returned columns changes. */ assert(!pArray||pScript); if (nCol < 0) { Tcl_Obj ***ap = (pScript?&apColName:0); nCol = computeColumnNames(interp, pStmt, ap, pArray); } for(i=0; i<nCol; i++){ Tcl_Obj *pVal; /* Set pVal to contain the i'th column of this row. */ switch( sqlite3_column_type(pStmt, i) ){ case SQLITE_BLOB: { int bytes = sqlite3_column_bytes(pStmt, i); |
︙ | ︙ | |||
1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 | } if( rc==TCL_BREAK ){ rc = TCL_OK; } /* Free the column name objects */ if( pScript ){ for(i=0; i<nCol; i++){ Tcl_DecrRefCount(apColName[i]); } Tcl_Free((char*)apColName); } /* Free the bound string and blob parameters */ for(i=0; i<nParm; i++){ Tcl_DecrRefCount(apParm[i]); } if( apParm!=aParm ){ Tcl_Free((char*)apParm); } /* Reset the statement. If the result code is SQLITE_SCHEMA, then ** flush the statement cache and try the statement again. */ rc2 = sqlite3_reset(pStmt); | > > > > > > > > < < < < < < < < | | 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 | } if( rc==TCL_BREAK ){ rc = TCL_OK; } /* Free the column name objects */ if( pScript ){ /* If the query returned no rows, but an array variable was ** specified, call computeColumnNames() now to populate the ** arrayname(*) variable. */ if (pArray && nCol < 0) { Tcl_Obj ***ap = (pScript?&apColName:0); nCol = computeColumnNames(interp, pStmt, ap, pArray); } for(i=0; i<nCol; i++){ Tcl_DecrRefCount(apColName[i]); } Tcl_Free((char*)apColName); } /* Free the bound string and blob parameters */ for(i=0; i<nParm; i++){ Tcl_DecrRefCount(apParm[i]); } if( apParm!=aParm ){ Tcl_Free((char*)apParm); } /* Reset the statement. If the result code is SQLITE_SCHEMA, then ** flush the statement cache and try the statement again. */ rc2 = sqlite3_reset(pStmt); if( SQLITE_OK!=rc2 ){ /* If a run-time error occurs, report the error and stop reading ** the SQL */ Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); sqlite3_finalize(pStmt); rc = TCL_ERROR; if( pPreStmt ) Tcl_Free((char*)pPreStmt); |
︙ | ︙ | |||
1850 1851 1852 1853 1854 1855 1856 | Tcl_IncrRefCount(pScript); pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript); rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8, pFunc, tclSqlFunc, 0, 0); if( rc!=SQLITE_OK ){ rc = TCL_ERROR; Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); | < < < | 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 | Tcl_IncrRefCount(pScript); pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript); rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8, pFunc, tclSqlFunc, 0, 0); if( rc!=SQLITE_OK ){ rc = TCL_ERROR; Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); } break; } /* ** $db incrblob ?-readonly? ?DB? TABLE COLUMN ROWID */ |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
382 383 384 385 386 387 388 | return rc; } #else int sqlite3_step(sqlite3_stmt *pStmt){ int cnt = 0; int rc; Vdbe *v = (Vdbe*)pStmt; | > | > > > > > > > > > > > > > > > > > > > | | 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 | return rc; } #else int sqlite3_step(sqlite3_stmt *pStmt){ int cnt = 0; int rc; Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; sqlite3_mutex_enter(db->mutex); while( (rc = sqlite3Step(v))==SQLITE_SCHEMA && cnt++ < 5 && sqlite3Reprepare(v) ){ sqlite3_reset(pStmt); v->expired = 0; } if( rc==SQLITE_SCHEMA && v->zSql && db->pErr ){ /* This case occurs after failing to recompile an sql statement. ** The error message from the SQL compiler has already been loaded ** into the database handle. This block copies the error message ** from the database handle into the statement and sets the statement ** program counter to 0 to ensure that when the statement is ** finalized or reset the parser error message is available via ** sqlite3_errmsg() and sqlite3_errcode(). */ const char *zErr = (const char *)sqlite3_value_text(db->pErr); sqlite3_free(v->zErrMsg); if( !db->mallocFailed ){ v->zErrMsg = sqlite3DbStrDup(db, zErr); } else { v->zErrMsg = 0; v->rc = SQLITE_NOMEM; } } rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } #endif /* ** Extract the user data from a sqlite3_context structure and return a ** pointer to it. |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 | } }else if( p->rc && p->expired ){ /* The expired flag was set on the VDBE before the first call ** to sqlite3_step(). For consistency (since sqlite3_step() was ** called), set the database error in this case as well. */ sqlite3Error(db, p->rc, 0); } /* Reclaim all memory used by the VDBE */ Cleanup(p); /* Save profiling information from this VDBE run. | > > | 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 | } }else if( p->rc && p->expired ){ /* The expired flag was set on the VDBE before the first call ** to sqlite3_step(). For consistency (since sqlite3_step() was ** called), set the database error in this case as well. */ sqlite3Error(db, p->rc, 0); sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, sqlite3_free); p->zErrMsg = 0; } /* Reclaim all memory used by the VDBE */ Cleanup(p); /* Save profiling information from this VDBE run. |
︙ | ︙ |
Changes to test/alter2.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #************************************************************************* # This file implements regression tests for SQLite library. The # focus of this script is testing that SQLite can handle a subtle # file format change that may be used in the future to implement # "ALTER TABLE ... ADD COLUMN". # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #************************************************************************* # This file implements regression tests for SQLite library. The # focus of this script is testing that SQLite can handle a subtle # file format change that may be used in the future to implement # "ALTER TABLE ... ADD COLUMN". # # $Id: alter2.test,v 1.11 2007/11/13 10:30:26 danielk1977 Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl # We have to have pragmas in order to do this test ifcapable {!pragma} return |
︙ | ︙ | |||
235 236 237 238 239 240 241 | # file format is checked each time the schema is read, so changing the # file format requires incrementing the schema cookie. # do_test alter2-4.1 { set_file_format 5 } {} do_test alter2-4.2 { | > > > > > > > > > > > > | | < | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | # file format is checked each time the schema is read, so changing the # file format requires incrementing the schema cookie. # do_test alter2-4.1 { set_file_format 5 } {} do_test alter2-4.2 { # We have to run two queries here because the Tcl interface uses # sqlite3_prepare_v2(). In this case, the first query encounters an # SQLITE_SCHEMA error. Then, when trying to recompile the statement, the # "unsupported file format" error is encountered. So the error code # returned is SQLITE_SCHEMA, not SQLITE_ERROR as required by the following # test case. # # When the query is attempted a second time, the same error message is # returned but the error code is SQLITE_ERROR, because the unsupported # file format was detected during a call to sqlite3_prepare(), not # sqlite3_step(). # catchsql { SELECT * FROM sqlite_master; } catchsql { SELECT * FROM sqlite_master; } } {1 {unsupported file format}} do_test alter2-4.3 { sqlite3_errcode $::DB } {SQLITE_ERROR} do_test alter2-4.4 { set ::DB [sqlite3_connection_pointer db] catchsql { |
︙ | ︙ |
Changes to test/auth.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is testing the sqlite3_set_authorizer() API # and related functionality. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is testing the sqlite3_set_authorizer() API # and related functionality. # # $Id: auth.test,v 1.39 2007/11/13 10:30:26 danielk1977 Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl # disable this test if the SQLITE_OMIT_AUTHORIZATION macro is # defined during compilation. |
︙ | ︙ | |||
2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 | return SQLITE_IGNORE } return SQLITE_OK } catchsql {SELECT ROWID,b,c FROM t2} } {0 {{} 2 33 {} 8 9}} do_test auth-2.9.1 { proc auth {code arg1 arg2 arg3 arg4} { if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="ROWID"} { return bogus } return SQLITE_OK } catchsql {SELECT ROWID,b,c FROM t2} | > > > > > > > > > > | 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 | return SQLITE_IGNORE } return SQLITE_OK } catchsql {SELECT ROWID,b,c FROM t2} } {0 {{} 2 33 {} 8 9}} do_test auth-2.9.1 { # We have to flush the cache here in case the Tcl interface tries to # reuse a statement compiled with sqlite3_prepare_v2(). In this case, # the first error encountered is an SQLITE_SCHEMA error. Then, when # trying to recompile the statement, the authorization error is encountered. # If we do not flush the cache, the correct error message is returned, but # the error code is SQLITE_SCHEMA, not SQLITE_ERROR as required by the test # case after this one. # db cache flush proc auth {code arg1 arg2 arg3 arg4} { if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="ROWID"} { return bogus } return SQLITE_OK } catchsql {SELECT ROWID,b,c FROM t2} |
︙ | ︙ |