Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Experimental proof-of-concept for the 'tcl-rdonly' setting and related functionality. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | tclRdOnly |
| Files: | files | file ages | folders |
| SHA1: |
851e0755e5f4c3b8fe2d7ecc777e72a5 |
| User & Date: | mistachkin 2012-10-07 14:22:39.417 |
Context
|
2012-10-07
| ||
| 14:49 | Add the new 'tcl-rdonly' setting to the list of those that should be transferred. check-in: 2335ae4f22 user: mistachkin tags: tclRdOnly | |
| 14:22 | Experimental proof-of-concept for the 'tcl-rdonly' setting and related functionality. check-in: 851e0755e5 user: mistachkin tags: tclRdOnly | |
| 13:55 | Enhance Tcl integration with support for notifications before and after Tcl scripts are evaluated. check-in: 49c63f8c78 user: mistachkin tags: trunk | |
Changes
Changes to Makefile.in.
| ︙ | ︙ | |||
40 41 42 43 44 45 46 47 48 49 50 51 | LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ TCC += @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H INSTALLDIR = $(DESTDIR)@prefix@/bin USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@ FOSSIL_ENABLE_TCL = @FOSSIL_ENABLE_TCL@ FOSSIL_ENABLE_TCL_STUBS = @FOSSIL_ENABLE_TCL_STUBS@ include $(SRCDIR)/main.mk distclean: clean rm -f autoconfig.h config.log Makefile | > | 40 41 42 43 44 45 46 47 48 49 50 51 52 | LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ TCC += @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H INSTALLDIR = $(DESTDIR)@prefix@/bin USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@ FOSSIL_ENABLE_TCL = @FOSSIL_ENABLE_TCL@ FOSSIL_ENABLE_TCL_STUBS = @FOSSIL_ENABLE_TCL_STUBS@ FOSSIL_ENABLE_TCL_SQLITE = @FOSSIL_ENABLE_TCL_SQLITE@ include $(SRCDIR)/main.mk distclean: clean rm -f autoconfig.h config.log Makefile |
Changes to auto.def.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# System autoconfiguration. Try: ./configure --help
use cc cc-lib
options {
with-openssl:path|auto|none
=> {Look for openssl in the given path, or auto or none}
with-zlib:path => {Look for zlib in the given path}
with-tcl:path => {Enable Tcl integration, with Tcl in the specified path}
with-tcl-stubs=0 => {Enable Tcl integration via stubs mechanism}
internal-sqlite=1 => {Don't use the internal sqlite, use the system one}
static=0 => {Link a static executable}
lineedit=1 => {Disable line editing}
fossil-debug=0 => {Build with fossil debugging enabled}
json=0 => {Build with fossil JSON API enabled}
}
| > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# System autoconfiguration. Try: ./configure --help
use cc cc-lib
options {
with-openssl:path|auto|none
=> {Look for openssl in the given path, or auto or none}
with-zlib:path => {Look for zlib in the given path}
with-tcl:path => {Enable Tcl integration, with Tcl in the specified path}
with-tcl-stubs=0 => {Enable Tcl integration via stubs mechanism}
with-tcl-sqlite=0 => {Provide the SQLite package to Tcl}
internal-sqlite=1 => {Don't use the internal sqlite, use the system one}
static=0 => {Link a static executable}
lineedit=1 => {Disable line editing}
fossil-debug=0 => {Build with fossil debugging enabled}
json=0 => {Build with fossil JSON API enabled}
}
|
| ︙ | ︙ | |||
123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
user-error "Cannot find a usable Tcl stubs library $msg"
}
} else {
if {![cc-check-functions Tcl_CreateInterp]} {
user-error "Cannot find a usable Tcl library $msg"
}
}
}
set version $tclconfig(TCL_VERSION)$tclconfig(TCL_PATCH_LEVEL)
msg-result "Found Tcl $version at $tclconfig(TCL_PREFIX)"
define-append LIBS $libs
define-append EXTRA_CFLAGS $cflags
define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS)
define FOSSIL_ENABLE_TCL
| > > > | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
user-error "Cannot find a usable Tcl stubs library $msg"
}
} else {
if {![cc-check-functions Tcl_CreateInterp]} {
user-error "Cannot find a usable Tcl library $msg"
}
}
}
if {[opt-bool with-tcl-sqlite]} {
define FOSSIL_ENABLE_TCL_SQLITE
}
set version $tclconfig(TCL_VERSION)$tclconfig(TCL_PATCH_LEVEL)
msg-result "Found Tcl $version at $tclconfig(TCL_PREFIX)"
define-append LIBS $libs
define-append EXTRA_CFLAGS $cflags
define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS)
define FOSSIL_ENABLE_TCL
|
| ︙ | ︙ |
Changes to src/db.c.
| ︙ | ︙ | |||
2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 |
{ "repo-cksum", 0, 0, 0, "on" },
{ "self-register", 0, 0, 0, "off" },
{ "ssl-ca-location",0, 40, 0, "" },
{ "ssl-identity", 0, 40, 0, "" },
{ "ssh-command", 0, 32, 0, "" },
#ifdef FOSSIL_ENABLE_TCL
{ "tcl", 0, 0, 0, "off" },
{ "tcl-setup", 0, 40, 0, "" },
#endif
{ "web-browser", 0, 32, 0, "" },
{ "white-foreground", 0, 0, 0, "off" },
{ 0,0,0,0,0 }
};
| > | 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 |
{ "repo-cksum", 0, 0, 0, "on" },
{ "self-register", 0, 0, 0, "off" },
{ "ssl-ca-location",0, 40, 0, "" },
{ "ssl-identity", 0, 40, 0, "" },
{ "ssh-command", 0, 32, 0, "" },
#ifdef FOSSIL_ENABLE_TCL
{ "tcl", 0, 0, 0, "off" },
{ "tcl-rdonly", 0, 0, 0, "on" },
{ "tcl-setup", 0, 40, 0, "" },
#endif
{ "web-browser", 0, 32, 0, "" },
{ "white-foreground", 0, 0, 0, "off" },
{ 0,0,0,0,0 }
};
|
| ︙ | ︙ | |||
2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 | ** ** tcl If enabled (and Fossil was compiled with Tcl support), ** Tcl integration commands will be added to the TH1 ** interpreter, allowing arbitrary Tcl expressions and ** scripts to be evaluated from TH1. Additionally, the Tcl ** interpreter will be able to evaluate arbitrary TH1 ** expressions and scripts. Default: off. ** ** tcl-setup This is the setup script to be evaluated after creating ** and initializing the Tcl interpreter. By default, this ** is empty and no extra setup is performed. ** ** web-browser A shell command used to launch your preferred ** web browser when given a URL as an argument. | > > > > > > > > > > > | 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 | ** ** tcl If enabled (and Fossil was compiled with Tcl support), ** Tcl integration commands will be added to the TH1 ** interpreter, allowing arbitrary Tcl expressions and ** scripts to be evaluated from TH1. Additionally, the Tcl ** interpreter will be able to evaluate arbitrary TH1 ** expressions and scripts. Default: off. ** ** tcl-rdonly If enabled (and Fossil was compiled with support for the ** SQLite package for Tcl), Tcl scripts using the SQLite ** package in the Fossil process will not be able to write ** to any of the databases used by the repository. This ** feature is designed to provide some protection against ** accidentally writing to a repository database; however, ** it is not a security feature and does not guarantee that ** writing to a repository database will be impossible if ** somebody is determined to do so. ** Default: on. ** ** tcl-setup This is the setup script to be evaluated after creating ** and initializing the Tcl interpreter. By default, this ** is empty and no extra setup is performed. ** ** web-browser A shell command used to launch your preferred ** web browser when given a URL as an argument. |
| ︙ | ︙ |
Changes to src/makemake.tcl.
| ︙ | ︙ | |||
377 378 379 380 381 382 383 384 385 386 387 388 389 390 | #### Enable scripting support via Tcl/Tk # # FOSSIL_ENABLE_TCL = 1 #### Load Tcl using the stubs mechanism # # FOSSIL_ENABLE_TCL_STUBS = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. # FOSSIL_TCL_SOURCE = 1 #### The directories where the zlib include and library files are located. | > > > > | 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | #### Enable scripting support via Tcl/Tk # # FOSSIL_ENABLE_TCL = 1 #### Load Tcl using the stubs mechanism # # FOSSIL_ENABLE_TCL_STUBS = 1 #### Provide the SQLite package to Tcl # # FOSSIL_ENABLE_TCL_SQLITE = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. # FOSSIL_TCL_SOURCE = 1 #### The directories where the zlib include and library files are located. |
| ︙ | ︙ | |||
480 481 482 483 484 485 486 487 488 489 490 491 492 493 | ifdef FOSSIL_ENABLE_TCL_STUBS TCC += -DFOSSIL_ENABLE_TCL_STUBS=1 -DUSE_TCL_STUBS RCC += -DFOSSIL_ENABLE_TCL_STUBS=1 -DUSE_TCL_STUBS else TCC += -DSTATIC_BUILD RCC += -DSTATIC_BUILD endif endif # With JSON support ifdef FOSSIL_ENABLE_JSON TCC += -DFOSSIL_ENABLE_JSON=1 RCC += -DFOSSIL_ENABLE_JSON=1 endif | > > > > > | 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | ifdef FOSSIL_ENABLE_TCL_STUBS TCC += -DFOSSIL_ENABLE_TCL_STUBS=1 -DUSE_TCL_STUBS RCC += -DFOSSIL_ENABLE_TCL_STUBS=1 -DUSE_TCL_STUBS else TCC += -DSTATIC_BUILD RCC += -DSTATIC_BUILD endif # Provide the SQLite package to Tcl ifdef FOSSIL_ENABLE_TCL_SQLITE TCC += -DFOSSIL_ENABLE_TCL_SQLITE=1 -DBUILD_sqlite=1 RCC += -DFOSSIL_ENABLE_TCL_SQLITE=1 -DBUILD_sqlite=1 endif endif # With JSON support ifdef FOSSIL_ENABLE_JSON TCC += -DFOSSIL_ENABLE_JSON=1 RCC += -DFOSSIL_ENABLE_JSON=1 endif |
| ︙ | ︙ |
Changes to src/sqlite3.c.
| ︙ | ︙ | |||
671 672 673 674 675 676 677 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.15" #define SQLITE_VERSION_NUMBER 3007015 | | | 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.15" #define SQLITE_VERSION_NUMBER 3007015 #define SQLITE_SOURCE_ID "2012-10-07 14:14:44 bbb0d189b7b6aecfc0e0b6c2bcd9f49aaea8c34a" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| ︙ | ︙ | |||
1802 1803 1804 1805 1806 1807 1808 | SQLITE_API int sqlite3_shutdown(void); SQLITE_API int sqlite3_os_init(void); SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library ** | | | | | | > > > > | | | > | > | 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 | SQLITE_API int sqlite3_shutdown(void); SQLITE_API int sqlite3_os_init(void); SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library ** ** The sqlite3_config() and sqlite3_reconfig() interfaces are used to make ** global configuration changes to SQLite in order to tune SQLite to the ** specific needs of the application. The default configuration is recommended ** for most applications and so this routine is usually not necessary. They ** are provided to support rare applications with unusual needs. ** ** The sqlite3_config() interface is not threadsafe. The application ** must insure that no other SQLite interfaces are invoked by other ** threads while sqlite3_config() is running. Furthermore, sqlite3_config() ** may only be invoked prior to library initialization using ** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. ** ^If sqlite3_config() is called after [sqlite3_initialize()] and before ** [sqlite3_shutdown()] then it will return SQLITE_MISUSE. ** Note, however, that ^sqlite3_config() can be called as part of the ** implementation of an application-defined [sqlite3_os_init()]. ** ** The sqlite3_reconfig() interface is threadsafe and may be called at any ** time. However, it supports only a small subset of the configuration ** options available for use with sqlite3_config(). ** ** The first argument to both sqlite3_config() and sqlite3_reconfig() is an ** integer [configuration option] that determines ** what property of SQLite is to be configured. Subsequent arguments ** vary depending on the [configuration option] ** in the first argument. ** ** ^When a configuration option is set, both sqlite3_config() and ** sqlite3_reconfig() return [SQLITE_OK]. ** ^If the option is unknown or SQLite is unable to set the option ** then these routines returns a non-zero [error code]. */ SQLITE_API int sqlite3_config(int, ...); SQLITE_API int sqlite3_reconfig(int, ...); /* ** CAPI3REF: Configure database connections ** ** The sqlite3_db_config() interface is used to make configuration ** changes to a [database connection]. The interface is similar to ** [sqlite3_config()] except that the changes apply to a single |
| ︙ | ︙ | |||
2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans ** is because some incorrectly coded legacy applications might malfunction ** malfunction when the optimization is enabled. Providing the ability to ** disable the optimization allows the older, buggy application code to work ** without change even with newer versions of SQLite. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** </dl> */ | > > > > > > > > > > > > > | 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans ** is because some incorrectly coded legacy applications might malfunction ** malfunction when the optimization is enabled. Providing the ability to ** disable the optimization allows the older, buggy application code to work ** without change even with newer versions of SQLite. ** ** [[SQLITE_CONFIG_READONLY]] <dt>SQLITE_CONFIG_READONLY ** <dd> This option takes a single argument of type int. If non-zero, then ** read-only mode for opening databases is globally enabled. If the parameter ** is zero, then read-only mode for opening databases is globally disabled. If ** read-only mode for opening databases is globally enabled, all databases ** opened by [sqlite3_open()], [sqlite3_open16()], or specified as part of ** [ATTACH] commands will be opened in read-only mode. Additionally, all calls ** to [sqlite3_open_v2()] must have the [SQLITE_OPEN_READONLY] flag set in the ** third argument; otherwise, a [SQLITE_READONLY] error will be returned. If it ** is globally disabled, [sqlite3_open()], [sqlite3_open16()], ** [sqlite3_open_v2()], and [ATTACH] commands will function normally. By ** default, read-only mode is globally disabled. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** </dl> */ |
| ︙ | ︙ | |||
2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 | #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** | > | 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 | #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ #define SQLITE_CONFIG_READONLY 21 /* int */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** |
| ︙ | ︙ | |||
10903 10904 10905 10906 10907 10908 10909 10910 10911 10912 10913 10914 10915 10916 |
** In the colUsed field, the high-order bit (bit 63) is set if the table
** contains more than 63 columns and the 64-th or later column is used.
*/
struct SrcList {
i16 nSrc; /* Number of tables or subqueries in the FROM clause */
i16 nAlloc; /* Number of entries allocated in a[] below */
struct SrcList_item {
char *zDatabase; /* Name of database holding this table */
char *zName; /* Name of the table */
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
Table *pTab; /* An SQL table corresponding to zName */
Select *pSelect; /* A SELECT statement used in place of a table name */
int addrFillSub; /* Address of subroutine to manifest a subquery */
int regReturn; /* Register holding return address of addrFillSub */
| > | 10923 10924 10925 10926 10927 10928 10929 10930 10931 10932 10933 10934 10935 10936 10937 |
** In the colUsed field, the high-order bit (bit 63) is set if the table
** contains more than 63 columns and the 64-th or later column is used.
*/
struct SrcList {
i16 nSrc; /* Number of tables or subqueries in the FROM clause */
i16 nAlloc; /* Number of entries allocated in a[] below */
struct SrcList_item {
Schema *pSchema; /* Schema to which this item is fixed */
char *zDatabase; /* Name of database holding this table */
char *zName; /* Name of the table */
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
Table *pTab; /* An SQL table corresponding to zName */
Select *pSelect; /* A SELECT statement used in place of a table name */
int addrFillSub; /* Address of subroutine to manifest a subquery */
int regReturn; /* Register holding return address of addrFillSub */
|
| ︙ | ︙ | |||
11471 11472 11473 11474 11475 11476 11477 11478 11479 11480 11481 11482 11483 11484 |
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.
*/
typedef struct DbFixer DbFixer;
struct DbFixer {
Parse *pParse; /* The parsing context. Error messages written here */
const char *zDb; /* Make sure all objects are contained in this database */
const char *zType; /* Type of the container - used for error messages */
const Token *pName; /* Name of the container - used for error messages */
};
/*
** An objected used to accumulate the text of a string where we
| > | 11492 11493 11494 11495 11496 11497 11498 11499 11500 11501 11502 11503 11504 11505 11506 |
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.
*/
typedef struct DbFixer DbFixer;
struct DbFixer {
Parse *pParse; /* The parsing context. Error messages written here */
Schema *pSchema; /* Fix items to this schema */
const char *zDb; /* Make sure all objects are contained in this database */
const char *zType; /* Type of the container - used for error messages */
const Token *pName; /* Name of the container - used for error messages */
};
/*
** An objected used to accumulate the text of a string where we
|
| ︙ | ︙ | |||
11514 11515 11516 11517 11518 11519 11520 11521 11522 11523 11524 11525 11526 11527 |
*/
struct Sqlite3Config {
int bMemstat; /* True to enable memory status */
int bCoreMutex; /* True to enable core mutexing */
int bFullMutex; /* True to enable full mutexing */
int bOpenUri; /* True to interpret filenames as URIs */
int bUseCis; /* Use covering indices for full-scans */
int mxStrlen; /* Maximum string length */
int szLookaside; /* Default lookaside buffer size */
int nLookaside; /* Default lookaside buffer count */
sqlite3_mem_methods m; /* Low-level memory allocation interface */
sqlite3_mutex_methods mutex; /* Low-level mutex interface */
sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */
void *pHeap; /* Heap storage space */
| > | 11536 11537 11538 11539 11540 11541 11542 11543 11544 11545 11546 11547 11548 11549 11550 |
*/
struct Sqlite3Config {
int bMemstat; /* True to enable memory status */
int bCoreMutex; /* True to enable core mutexing */
int bFullMutex; /* True to enable full mutexing */
int bOpenUri; /* True to interpret filenames as URIs */
int bUseCis; /* Use covering indices for full-scans */
int bReadOnly; /* True to force read-only mode */
int mxStrlen; /* Maximum string length */
int szLookaside; /* Default lookaside buffer size */
int nLookaside; /* Default lookaside buffer count */
sqlite3_mem_methods m; /* Low-level memory allocation interface */
sqlite3_mutex_methods mutex; /* Low-level mutex interface */
sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */
void *pHeap; /* Heap storage space */
|
| ︙ | ︙ | |||
11881 11882 11883 11884 11885 11886 11887 11888 11889 11890 11891 11892 11893 11894 | SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse*, Expr*); SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int); SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int); SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*); SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*); SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3Vacuum(Parse*); SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*); SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*); SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*); | > | 11904 11905 11906 11907 11908 11909 11910 11911 11912 11913 11914 11915 11916 11917 11918 | SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse*, Expr*); SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int); SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int); SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*); SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*); SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *); SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3Vacuum(Parse*); SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*); SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*); SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*); |
| ︙ | ︙ | |||
12111 12112 12113 12114 12115 12116 12117 | SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); | | | 12135 12136 12137 12138 12139 12140 12141 12142 12143 12144 12145 12146 12147 12148 12149 | SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); SQLITE_PRIVATE char sqlite3AffinityType(const char*); SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*); SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *); SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3*,Index*); |
| ︙ | ︙ | |||
12518 12519 12520 12521 12522 12523 12524 12525 12526 12527 12528 12529 12530 12531 |
*/
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
1, /* bCoreMutex */
SQLITE_THREADSAFE==1, /* bFullMutex */
SQLITE_USE_URI, /* bOpenUri */
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0x7ffffffe, /* mxStrlen */
128, /* szLookaside */
500, /* nLookaside */
{0,0,0,0,0,0,0,0}, /* m */
{0,0,0,0,0,0,0,0,0}, /* mutex */
{0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */
(void*)0, /* pHeap */
| > | 12542 12543 12544 12545 12546 12547 12548 12549 12550 12551 12552 12553 12554 12555 12556 |
*/
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
1, /* bCoreMutex */
SQLITE_THREADSAFE==1, /* bFullMutex */
SQLITE_USE_URI, /* bOpenUri */
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0, /* bReadOnly */
0x7ffffffe, /* mxStrlen */
128, /* szLookaside */
500, /* nLookaside */
{0,0,0,0,0,0,0,0}, /* m */
{0,0,0,0,0,0,0,0,0}, /* mutex */
{0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */
(void*)0, /* pHeap */
|
| ︙ | ︙ | |||
30335 30336 30337 30338 30339 30340 30341 30342 30343 30344 30345 30346 30347 30348 30349 |
#else
{ "FormatMessageW", (SYSCALL)0, 0 },
#endif
#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
DWORD,va_list*))aSyscall[15].pCurrent)
{ "FreeLibrary", (SYSCALL)FreeLibrary, 0 },
#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
{ "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 },
#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
| > > > > | 30360 30361 30362 30363 30364 30365 30366 30367 30368 30369 30370 30371 30372 30373 30374 30375 30376 30377 30378 |
#else
{ "FormatMessageW", (SYSCALL)0, 0 },
#endif
#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
DWORD,va_list*))aSyscall[15].pCurrent)
#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "FreeLibrary", (SYSCALL)FreeLibrary, 0 },
#else
{ "FreeLibrary", (SYSCALL)0, 0 },
#endif
#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
{ "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 },
#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
|
| ︙ | ︙ | |||
30416 30417 30418 30419 30420 30421 30422 30423 30424 30425 30426 30427 30428 30429 30430 30431 30432 30433 30434 30435 30436 30437 |
#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
LPWSTR*))aSyscall[25].pCurrent)
{ "GetLastError", (SYSCALL)GetLastError, 0 },
#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
#if SQLITE_OS_WINCE
/* The GetProcAddressA() routine is only available on Windows CE. */
{ "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 },
#else
/* All other Windows platforms expect GetProcAddress() to take
** an ANSI string regardless of the _UNICODE setting */
{ "GetProcAddressA", (SYSCALL)GetProcAddress, 0 },
#endif
#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
LPCSTR))aSyscall[27].pCurrent)
#if !SQLITE_OS_WINRT
{ "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
#else
| > > > > | 30445 30446 30447 30448 30449 30450 30451 30452 30453 30454 30455 30456 30457 30458 30459 30460 30461 30462 30463 30464 30465 30466 30467 30468 30469 30470 |
#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
LPWSTR*))aSyscall[25].pCurrent)
{ "GetLastError", (SYSCALL)GetLastError, 0 },
#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
#if SQLITE_OS_WINCE
/* The GetProcAddressA() routine is only available on Windows CE. */
{ "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 },
#else
/* All other Windows platforms expect GetProcAddress() to take
** an ANSI string regardless of the _UNICODE setting */
{ "GetProcAddressA", (SYSCALL)GetProcAddress, 0 },
#endif
#else
{ "GetProcAddressA", (SYSCALL)0, 0 },
#endif
#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
LPCSTR))aSyscall[27].pCurrent)
#if !SQLITE_OS_WINRT
{ "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
#else
|
| ︙ | ︙ | |||
30527 30528 30529 30530 30531 30532 30533 |
#else
{ "HeapValidate", (SYSCALL)0, 0 },
#endif
#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
LPCVOID))aSyscall[41].pCurrent)
| | | > | 30560 30561 30562 30563 30564 30565 30566 30567 30568 30569 30570 30571 30572 30573 30574 30575 30576 30577 30578 30579 30580 30581 30582 30583 |
#else
{ "HeapValidate", (SYSCALL)0, 0 },
#endif
#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
LPCVOID))aSyscall[41].pCurrent)
#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 },
#else
{ "LoadLibraryA", (SYSCALL)0, 0 },
#endif
#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
!defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 },
#else
{ "LoadLibraryW", (SYSCALL)0, 0 },
#endif
#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
|
| ︙ | ︙ | |||
30724 30725 30726 30727 30728 30729 30730 |
#else
{ "CreateFile2", (SYSCALL)0, 0 },
#endif
#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
| | | 30758 30759 30760 30761 30762 30763 30764 30765 30766 30767 30768 30769 30770 30771 30772 |
#else
{ "CreateFile2", (SYSCALL)0, 0 },
#endif
#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 },
#else
{ "LoadPackagedLibrary", (SYSCALL)0, 0 },
#endif
#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
DWORD))aSyscall[67].pCurrent)
|
| ︙ | ︙ | |||
60048 60049 60050 60051 60052 60053 60054 60055 60056 60057 60058 60059 60060 60061 60062 |
** file is required for an atomic commit.
*/
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( sqlite3BtreeIsInTrans(pBt) ){
needXcommit = 1;
if( i!=1 ) nTrans++;
rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt));
}
}
if( rc!=SQLITE_OK ){
return rc;
}
/* If there are any write-transactions at all, invoke the commit hook */
| > > | 60082 60083 60084 60085 60086 60087 60088 60089 60090 60091 60092 60093 60094 60095 60096 60097 60098 |
** file is required for an atomic commit.
*/
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( sqlite3BtreeIsInTrans(pBt) ){
needXcommit = 1;
if( i!=1 ) nTrans++;
sqlite3BtreeEnter(pBt);
rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt));
sqlite3BtreeLeave(pBt);
}
}
if( rc!=SQLITE_OK ){
return rc;
}
/* If there are any write-transactions at all, invoke the commit hook */
|
| ︙ | ︙ | |||
74360 74361 74362 74363 74364 74365 74366 74367 74368 74369 74370 74371 74372 74373 |
pNew = sqlite3DbMallocRaw(db, nByte );
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; i<p->nSrc; i++){
struct SrcList_item *pNewItem = &pNew->a[i];
struct SrcList_item *pOldItem = &p->a[i];
Table *pTab;
pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
pNewItem->jointype = pOldItem->jointype;
pNewItem->iCursor = pOldItem->iCursor;
pNewItem->addrFillSub = pOldItem->addrFillSub;
pNewItem->regReturn = pOldItem->regReturn;
| > | 74396 74397 74398 74399 74400 74401 74402 74403 74404 74405 74406 74407 74408 74409 74410 |
pNew = sqlite3DbMallocRaw(db, nByte );
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; i<p->nSrc; i++){
struct SrcList_item *pNewItem = &pNew->a[i];
struct SrcList_item *pOldItem = &p->a[i];
Table *pTab;
pNewItem->pSchema = pOldItem->pSchema;
pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
pNewItem->jointype = pOldItem->jointype;
pNewItem->iCursor = pOldItem->iCursor;
pNewItem->addrFillSub = pOldItem->addrFillSub;
pNewItem->regReturn = pOldItem->regReturn;
|
| ︙ | ︙ | |||
77986 77987 77988 77989 77990 77991 77992 | int savedDbFlags; /* Saved value of db->flags */ savedDbFlags = db->flags; if( NEVER(db->mallocFailed) ) goto exit_rename_table; assert( pSrc->nSrc==1 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); | | | 78023 78024 78025 78026 78027 78028 78029 78030 78031 78032 78033 78034 78035 78036 78037 | int savedDbFlags; /* Saved value of db->flags */ savedDbFlags = db->flags; if( NEVER(db->mallocFailed) ) goto exit_rename_table; assert( pSrc->nSrc==1 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_rename_table; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); zDb = db->aDb[iDb].zName; db->flags |= SQLITE_PreferBuiltin; /* Get a NULL terminated version of the new table name. */ zName = sqlite3NameFromToken(db, pName); |
| ︙ | ︙ | |||
78329 78330 78331 78332 78333 78334 78335 | int nAlloc; sqlite3 *db = pParse->db; /* Look up the table being altered. */ assert( pParse->pNewTable==0 ); assert( sqlite3BtreeHoldsAllMutexes(db) ); if( db->mallocFailed ) goto exit_begin_add_column; | | | 78366 78367 78368 78369 78370 78371 78372 78373 78374 78375 78376 78377 78378 78379 78380 |
int nAlloc;
sqlite3 *db = pParse->db;
/* Look up the table being altered. */
assert( pParse->pNewTable==0 );
assert( sqlite3BtreeHoldsAllMutexes(db) );
if( db->mallocFailed ) goto exit_begin_add_column;
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
if( !pTab ) goto exit_begin_add_column;
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
goto exit_begin_add_column;
}
|
| ︙ | ︙ | |||
79960 79961 79962 79963 79964 79965 79966 79967 79968 79969 79970 79971 79972 79973 | sqlite3 *db; if( NEVER(iDb<0) || iDb==1 ) return 0; db = pParse->db; assert( db->nDb>iDb ); pFix->pParse = pParse; pFix->zDb = db->aDb[iDb].zName; pFix->zType = zType; pFix->pName = pName; return 1; } /* ** The following set of routines walk through the parse tree and assign | > | 79997 79998 79999 80000 80001 80002 80003 80004 80005 80006 80007 80008 80009 80010 80011 | sqlite3 *db; if( NEVER(iDb<0) || iDb==1 ) return 0; db = pParse->db; assert( db->nDb>iDb ); pFix->pParse = pParse; pFix->zDb = db->aDb[iDb].zName; pFix->pSchema = db->aDb[iDb].pSchema; pFix->zType = zType; pFix->pName = pName; return 1; } /* ** The following set of routines walk through the parse tree and assign |
| ︙ | ︙ | |||
79990 79991 79992 79993 79994 79995 79996 |
int i;
const char *zDb;
struct SrcList_item *pItem;
if( NEVER(pList==0) ) return 0;
zDb = pFix->zDb;
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
| | < < > > > | 80028 80029 80030 80031 80032 80033 80034 80035 80036 80037 80038 80039 80040 80041 80042 80043 80044 80045 80046 80047 80048 80049 80050 |
int i;
const char *zDb;
struct SrcList_item *pItem;
if( NEVER(pList==0) ) return 0;
zDb = pFix->zDb;
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",
pFix->zType, pFix->pName, pItem->zDatabase);
return 1;
}
sqlite3_free(pItem->zDatabase);
pItem->zDatabase = 0;
pItem->pSchema = pFix->pSchema;
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
#endif
}
return 0;
}
|
| ︙ | ︙ | |||
80654 80655 80656 80657 80658 80659 80660 80661 80662 80663 80664 80665 80666 80667 |
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
}
pParse->checkSchema = 1;
}
return p;
}
/*
** Locate the in-memory structure that describes
** a particular index given the name of that index
** and the name of the database that contains the index.
** Return NULL if not found.
**
| > > > > > > > > > > > > > > > > > > > > > > > > > | 80693 80694 80695 80696 80697 80698 80699 80700 80701 80702 80703 80704 80705 80706 80707 80708 80709 80710 80711 80712 80713 80714 80715 80716 80717 80718 80719 80720 80721 80722 80723 80724 80725 80726 80727 80728 80729 80730 80731 |
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
}
pParse->checkSchema = 1;
}
return p;
}
/*
** Locate the table identified by *p.
**
** This is a wrapper around sqlite3LocateTable(). The difference between
** sqlite3LocateTable() and this function is that this function restricts
** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be
** non-NULL if it is part of a view or trigger program definition. See
** sqlite3FixSrcList() for details.
*/
SQLITE_PRIVATE Table *sqlite3LocateTableItem(
Parse *pParse,
int isView,
struct SrcList_item *p
){
const char *zDb;
assert( p->pSchema==0 || p->zDatabase==0 );
if( p->pSchema ){
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
zDb = pParse->db->aDb[iDb].zName;
}else{
zDb = p->zDatabase;
}
return sqlite3LocateTable(pParse, isView, p->zName, zDb);
}
/*
** Locate the in-memory structure that describes
** a particular index given the name of that index
** and the name of the database that contains the index.
** Return NULL if not found.
**
|
| ︙ | ︙ | |||
81631 81632 81633 81634 81635 81636 81637 |
sqlite3 *db = pParse->db;
u8 enc = ENC(db);
u8 initbusy = db->init.busy;
CollSeq *pColl;
pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
if( !initbusy && (!pColl || !pColl->xCmp) ){
| | < < < | 81695 81696 81697 81698 81699 81700 81701 81702 81703 81704 81705 81706 81707 81708 81709 |
sqlite3 *db = pParse->db;
u8 enc = ENC(db);
u8 initbusy = db->init.busy;
CollSeq *pColl;
pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
if( !initbusy && (!pColl || !pColl->xCmp) ){
pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
}
return pColl;
}
/*
|
| ︙ | ︙ | |||
82450 82451 82452 82453 82454 82455 82456 |
if( db->mallocFailed ){
goto exit_drop_table;
}
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
if( noErr ) db->suppressErr++;
| | < | 82511 82512 82513 82514 82515 82516 82517 82518 82519 82520 82521 82522 82523 82524 82525 |
if( db->mallocFailed ){
goto exit_drop_table;
}
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
if( noErr ) db->suppressErr++;
pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
if( noErr ) db->suppressErr--;
if( pTab==0 ){
if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
goto exit_drop_table;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
| ︙ | ︙ | |||
82891 82892 82893 82894 82895 82896 82897 |
if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
sqlite3FixSrcList(&sFix, pTblName)
){
/* Because the parser constructs pTblName from a single identifier,
** sqlite3FixSrcList can never fail. */
assert(0);
}
| | < | 82951 82952 82953 82954 82955 82956 82957 82958 82959 82960 82961 82962 82963 82964 82965 |
if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
sqlite3FixSrcList(&sFix, pTblName)
){
/* Because the parser constructs pTblName from a single identifier,
** sqlite3FixSrcList can never fail. */
assert(0);
}
pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
if( !pTab || db->mallocFailed ) goto exit_create_index;
assert( db->aDb[iDb].pSchema==pTab->pSchema );
}else{
assert( pName==0 );
assert( pStart==0 );
pTab = pParse->pNewTable;
if( !pTab ) goto exit_create_index;
|
| ︙ | ︙ | |||
84252 84253 84254 84255 84256 84257 84258 | ** requested collation sequence is not available in the desired encoding. ** ** If it is not NULL, then pColl must point to the database native encoding ** collation sequence with name zName, length nName. ** ** The return value is either the collation sequence to be used in database ** db for collation type name zName, length nName, or NULL, if no collation | | | > > > > | < < | 84311 84312 84313 84314 84315 84316 84317 84318 84319 84320 84321 84322 84323 84324 84325 84326 84327 84328 84329 84330 84331 84332 84333 84334 84335 84336 84337 84338 84339 84340 84341 84342 84343 84344 84345 84346 84347 84348 84349 84350 84351 84352 84353 84354 84355 84356 84357 84358 84359 84360 84361 84362 84363 84364 84365 84366 84367 84368 84369 84370 84371 84372 84373 84374 84375 |
** requested collation sequence is not available in the desired encoding.
**
** If it is not NULL, then pColl must point to the database native encoding
** collation sequence with name zName, length nName.
**
** The return value is either the collation sequence to be used in database
** db for collation type name zName, length nName, or NULL, if no collation
** sequence can be found. If no collation is found, leave an error message.
**
** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
*/
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
Parse *pParse, /* Parsing context */
u8 enc, /* The desired encoding for the collating sequence */
CollSeq *pColl, /* Collating sequence with native encoding, or NULL */
const char *zName /* Collating sequence name */
){
CollSeq *p;
sqlite3 *db = pParse->db;
p = pColl;
if( !p ){
p = sqlite3FindCollSeq(db, enc, zName, 0);
}
if( !p || !p->xCmp ){
/* No collation sequence of this type for this encoding is registered.
** Call the collation factory to see if it can supply us with one.
*/
callCollNeeded(db, enc, zName);
p = sqlite3FindCollSeq(db, enc, zName, 0);
}
if( p && !p->xCmp && synthCollSeq(db, p) ){
p = 0;
}
assert( !p || p->xCmp );
if( p==0 ){
sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
}
return p;
}
/*
** This routine is called on a collation sequence before it is used to
** check that it is defined. An undefined collation sequence exists when
** a database is loaded that contains references to collation sequences
** that have not been defined by sqlite3_create_collation() etc.
**
** If required, this routine calls the 'collation needed' callback to
** request a definition of the collating sequence. If this doesn't work,
** an equivalent collating sequence that uses a text encoding different
** from the main database is substituted, if one is available.
*/
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
if( pColl ){
const char *zName = pColl->zName;
sqlite3 *db = pParse->db;
CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName);
if( !p ){
return SQLITE_ERROR;
}
assert( p==pColl );
}
return SQLITE_OK;
}
|
| ︙ | ︙ | |||
84687 84688 84689 84690 84691 84692 84693 |
** pSrc->a[0].pIndex Pointer to the INDEXED BY index, if there is one
**
*/
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
struct SrcList_item *pItem = pSrc->a;
Table *pTab;
assert( pItem && pSrc->nSrc==1 );
| | | 84748 84749 84750 84751 84752 84753 84754 84755 84756 84757 84758 84759 84760 84761 84762 |
** pSrc->a[0].pIndex Pointer to the INDEXED BY index, if there is one
**
*/
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
struct SrcList_item *pItem = pSrc->a;
Table *pTab;
assert( pItem && pSrc->nSrc==1 );
pTab = sqlite3LocateTableItem(pParse, 0, pItem);
sqlite3DeleteTable(pParse->db, pItem->pTab);
pItem->pTab = pTab;
if( pTab ){
pTab->nRef++;
}
if( sqlite3IndexedByLookup(pParse, pItem) ){
pTab = 0;
|
| ︙ | ︙ | |||
89413 89414 89415 89416 89417 89418 89419 |
#ifndef SQLITE_OMIT_CHECK
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
ExprList *pCheck = pTab->pCheck;
pParse->ckBase = regData;
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
for(i=0; i<pCheck->nExpr; i++){
int allOk = sqlite3VdbeMakeLabel(v);
| > > | > | 89474 89475 89476 89477 89478 89479 89480 89481 89482 89483 89484 89485 89486 89487 89488 89489 89490 89491 89492 89493 89494 89495 89496 89497 89498 89499 89500 89501 89502 89503 89504 |
#ifndef SQLITE_OMIT_CHECK
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
ExprList *pCheck = pTab->pCheck;
pParse->ckBase = regData;
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
for(i=0; i<pCheck->nExpr; i++){
int allOk = sqlite3VdbeMakeLabel(v);
Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0);
if( pDup==0 ) break;
sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL);
if( onError==OE_Ignore ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
}else{
char *zConsName = pCheck->a[i].zName;
if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
if( zConsName ){
zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
}else{
zConsName = 0;
}
sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
}
sqlite3VdbeResolveLabel(v, allOk);
sqlite3ExprDelete(db, pDup);
}
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
/* If we have an INTEGER PRIMARY KEY, make sure the primary key
** of the new record does not previously exist. Except, if this
** is an UPDATE and the primary key is not changing, that is OK.
|
| ︙ | ︙ | |||
89882 89883 89884 89885 89886 89887 89888 | } /* At this point we have established that the statement is of the ** correct syntactic form to participate in this optimization. Now ** we have to check the semantics. */ pItem = pSelect->pSrc->a; | | | 89946 89947 89948 89949 89950 89951 89952 89953 89954 89955 89956 89957 89958 89959 89960 |
}
/* At this point we have established that the statement is of the
** correct syntactic form to participate in this optimization. Now
** we have to check the semantics.
*/
pItem = pSelect->pSrc->a;
pSrc = sqlite3LocateTableItem(pParse, 0, pItem);
if( pSrc==0 ){
return 0; /* FROM clause does not contain a real table */
}
if( pSrc==pDest ){
return 0; /* tab1 and tab2 may not be the same table */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| ︙ | ︙ | |||
97151 97152 97153 97154 97155 97156 97157 |
pTab->iPKey = -1;
pTab->nRowEst = 1000000;
pTab->tabFlags |= TF_Ephemeral;
#endif
}else{
/* An ordinary table or view name in the FROM clause */
assert( pFrom->pTab==0 );
| | < | 97215 97216 97217 97218 97219 97220 97221 97222 97223 97224 97225 97226 97227 97228 97229 |
pTab->iPKey = -1;
pTab->nRowEst = 1000000;
pTab->tabFlags |= TF_Ephemeral;
#endif
}else{
/* An ordinary table or view name in the FROM clause */
assert( pFrom->pTab==0 );
pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
if( pTab==0 ) return WRC_Abort;
pTab->nRef++;
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
if( pTab->pSelect || IsVirtual(pTab) ){
/* We reach here if the named table is a really a view */
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->pSelect==0 );
|
| ︙ | ︙ | |||
101093 101094 101095 101096 101097 101098 101099 101100 101101 101102 101103 101104 101105 101106 |
** in the list are moved to the sqlite3.pDisconnect list of the associated
** database connection.
*/
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
if( p->azModuleArg ){
int i;
for(i=0; i<p->nModuleArg; i++){
sqlite3DbFree(db, p->azModuleArg[i]);
}
sqlite3DbFree(db, p->azModuleArg);
}
}
| > | 101156 101157 101158 101159 101160 101161 101162 101163 101164 101165 101166 101167 101168 101169 101170 |
** in the list are moved to the sqlite3.pDisconnect list of the associated
** database connection.
*/
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
if( p->azModuleArg ){
int i;
assert( p->nModuleArg<2 || p->azModuleArg[1]==0 );
for(i=0; i<p->nModuleArg; i++){
sqlite3DbFree(db, p->azModuleArg[i]);
}
sqlite3DbFree(db, p->azModuleArg);
}
}
|
| ︙ | ︙ | |||
101154 101155 101156 101157 101158 101159 101160 | db = pParse->db; iDb = sqlite3SchemaToIndex(db, pTable->pSchema); assert( iDb>=0 ); pTable->tabFlags |= TF_Virtual; pTable->nModuleArg = 0; addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); | | | 101218 101219 101220 101221 101222 101223 101224 101225 101226 101227 101228 101229 101230 101231 101232 | db = pParse->db; iDb = sqlite3SchemaToIndex(db, pTable->pSchema); assert( iDb>=0 ); pTable->tabFlags |= TF_Virtual; pTable->nModuleArg = 0; addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); addModuleArgument(db, pTable, 0); addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); pParse->sNameToken.n = (int)(&pModuleName->z[pModuleName->n] - pName1->z); #ifndef SQLITE_OMIT_AUTHORIZATION /* Creating a virtual table invokes the authorization callback twice. ** The first invocation, to obtain permission to INSERT a row into the ** sqlite_master table, has already been made by sqlite3StartTable(). |
| ︙ | ︙ | |||
101311 101312 101313 101314 101315 101316 101317 101318 101319 101320 101321 101322 101323 101324 101325 101326 101327 101328 101329 101330 101331 101332 101333 101334 101335 101336 101337 101338 101339 101340 101341 101342 101343 101344 101345 101346 101347 |
VtabCtx sCtx, *pPriorCtx;
VTable *pVTable;
int rc;
const char *const*azArg = (const char *const*)pTab->azModuleArg;
int nArg = pTab->nModuleArg;
char *zErr = 0;
char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
if( !zModuleName ){
return SQLITE_NOMEM;
}
pVTable = sqlite3DbMallocZero(db, sizeof(VTable));
if( !pVTable ){
sqlite3DbFree(db, zModuleName);
return SQLITE_NOMEM;
}
pVTable->db = db;
pVTable->pMod = pMod;
/* Invoke the virtual table constructor */
assert( &db->pVtabCtx );
assert( xConstruct );
sCtx.pTab = pTab;
sCtx.pVTable = pVTable;
pPriorCtx = db->pVtabCtx;
db->pVtabCtx = &sCtx;
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
db->pVtabCtx = pPriorCtx;
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
if( SQLITE_OK!=rc ){
if( zErr==0 ){
*pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
}else {
*pzErr = sqlite3MPrintf(db, "%s", zErr);
sqlite3_free(zErr);
| > > > > > > | 101375 101376 101377 101378 101379 101380 101381 101382 101383 101384 101385 101386 101387 101388 101389 101390 101391 101392 101393 101394 101395 101396 101397 101398 101399 101400 101401 101402 101403 101404 101405 101406 101407 101408 101409 101410 101411 101412 101413 101414 101415 101416 101417 |
VtabCtx sCtx, *pPriorCtx;
VTable *pVTable;
int rc;
const char *const*azArg = (const char *const*)pTab->azModuleArg;
int nArg = pTab->nModuleArg;
char *zErr = 0;
char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
int iDb;
if( !zModuleName ){
return SQLITE_NOMEM;
}
pVTable = sqlite3DbMallocZero(db, sizeof(VTable));
if( !pVTable ){
sqlite3DbFree(db, zModuleName);
return SQLITE_NOMEM;
}
pVTable->db = db;
pVTable->pMod = pMod;
assert( pTab->azModuleArg[1]==0 );
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
pTab->azModuleArg[1] = db->aDb[iDb].zName;
/* Invoke the virtual table constructor */
assert( &db->pVtabCtx );
assert( xConstruct );
sCtx.pTab = pTab;
sCtx.pVTable = pVTable;
pPriorCtx = db->pVtabCtx;
db->pVtabCtx = &sCtx;
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
db->pVtabCtx = pPriorCtx;
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
pTab->azModuleArg[1] = 0;
if( SQLITE_OK!=rc ){
if( zErr==0 ){
*pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
}else {
*pzErr = sqlite3MPrintf(db, "%s", zErr);
sqlite3_free(zErr);
|
| ︙ | ︙ | |||
104342 104343 104344 104345 104346 104347 104348 |
CollSeq *pColl;
const u8 *z;
if( eType==SQLITE_BLOB ){
z = (const u8 *)sqlite3_value_blob(pVal);
pColl = db->pDfltColl;
assert( pColl->enc==SQLITE_UTF8 );
}else{
| | < < | 104412 104413 104414 104415 104416 104417 104418 104419 104420 104421 104422 104423 104424 104425 104426 104427 |
CollSeq *pColl;
const u8 *z;
if( eType==SQLITE_BLOB ){
z = (const u8 *)sqlite3_value_blob(pVal);
pColl = db->pDfltColl;
assert( pColl->enc==SQLITE_UTF8 );
}else{
pColl = sqlite3GetCollSeq(pParse, SQLITE_UTF8, 0, *pIdx->azColl);
if( pColl==0 ){
return SQLITE_ERROR;
}
z = (const u8 *)sqlite3ValueText(pVal, pColl->enc);
if( !z ){
return SQLITE_NOMEM;
}
assert( z && pColl && pColl->xCmp );
|
| ︙ | ︙ | |||
112543 112544 112545 112546 112547 112548 112549 112550 112551 112552 112553 112554 112555 112556 |
break;
}
case SQLITE_CONFIG_COVERING_INDEX_SCAN: {
sqlite3GlobalConfig.bUseCis = va_arg(ap, int);
break;
}
default: {
rc = SQLITE_ERROR;
break;
}
}
va_end(ap);
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 112611 112612 112613 112614 112615 112616 112617 112618 112619 112620 112621 112622 112623 112624 112625 112626 112627 112628 112629 112630 112631 112632 112633 112634 112635 112636 112637 112638 112639 112640 112641 112642 112643 112644 112645 112646 112647 112648 112649 112650 112651 112652 112653 112654 112655 112656 112657 112658 112659 112660 112661 112662 112663 |
break;
}
case SQLITE_CONFIG_COVERING_INDEX_SCAN: {
sqlite3GlobalConfig.bUseCis = va_arg(ap, int);
break;
}
case SQLITE_CONFIG_READONLY: {
sqlite3GlobalConfig.bReadOnly = va_arg(ap, int);
break;
}
default: {
rc = SQLITE_ERROR;
break;
}
}
va_end(ap);
return rc;
}
/*
** This API allows applications to modify the global configuration of
** the SQLite library at run-time.
**
** This routine differs from sqlite3_config() in that it may be called when
** there are outstanding database connections and/or memory allocations.
** This routine is threadsafe.
*/
SQLITE_API int sqlite3_reconfig(int op, ...){
va_list ap;
int rc = SQLITE_OK;
va_start(ap, op);
switch( op ){
case SQLITE_CONFIG_READONLY: {
/*
** On platforms where assignment of an integer value is atomic, there
** is no need for a mutex here. On other platforms, there could be a
** subtle race condition here; however, the effect would simply be that
** a call to open a database would fail with SQLITE_READONLY.
*/
sqlite3GlobalConfig.bReadOnly = va_arg(ap, int);
break;
}
default: {
rc = SQLITE_ERROR;
break;
}
}
va_end(ap);
|
| ︙ | ︙ | |||
114266 114267 114268 114269 114270 114271 114272 | ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" ** is UTF-8 encoded. */ static int openDatabase( const char *zFilename, /* Database filename UTF-8 encoded */ sqlite3 **ppDb, /* OUT: Returned database handle */ unsigned int flags, /* Operational flags */ | | > | 114373 114374 114375 114376 114377 114378 114379 114380 114381 114382 114383 114384 114385 114386 114387 114388 |
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
** is UTF-8 encoded.
*/
static int openDatabase(
const char *zFilename, /* Database filename UTF-8 encoded */
sqlite3 **ppDb, /* OUT: Returned database handle */
unsigned int flags, /* Operational flags */
const char *zVfs, /* Name of the VFS to use */
int defaultFlags /* Zero if opening via sqlite3_open_v2 */
){
sqlite3 *db; /* Store allocated handle here */
int rc; /* Return code */
int isThreadsafe; /* True for threadsafe connections */
char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
|
| ︙ | ︙ | |||
114335 114336 114337 114338 114339 114340 114341 114342 114343 114344 114345 114346 114347 114348 |
SQLITE_OPEN_TEMP_JOURNAL |
SQLITE_OPEN_SUBJOURNAL |
SQLITE_OPEN_MASTER_JOURNAL |
SQLITE_OPEN_NOMUTEX |
SQLITE_OPEN_FULLMUTEX |
SQLITE_OPEN_WAL
);
/* Allocate the sqlite data structure */
db = sqlite3MallocZero( sizeof(sqlite3) );
if( db==0 ) goto opendb_out;
if( isThreadsafe ){
db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
if( db->mutex==0 ){
| > > > > > > > > > > | 114443 114444 114445 114446 114447 114448 114449 114450 114451 114452 114453 114454 114455 114456 114457 114458 114459 114460 114461 114462 114463 114464 114465 114466 |
SQLITE_OPEN_TEMP_JOURNAL |
SQLITE_OPEN_SUBJOURNAL |
SQLITE_OPEN_MASTER_JOURNAL |
SQLITE_OPEN_NOMUTEX |
SQLITE_OPEN_FULLMUTEX |
SQLITE_OPEN_WAL
);
/* Check for global read-only mode */
if( sqlite3GlobalConfig.bReadOnly ){
if( defaultFlags ){
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
flags |= SQLITE_OPEN_READONLY;
}else if( flags & SQLITE_OPEN_READWRITE ){
return SQLITE_READONLY;
}
}
/* Allocate the sqlite data structure */
db = sqlite3MallocZero( sizeof(sqlite3) );
if( db==0 ) goto opendb_out;
if( isThreadsafe ){
db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
if( db->mutex==0 ){
|
| ︙ | ︙ | |||
114526 114527 114528 114529 114530 114531 114532 |
** Open a new database handle.
*/
SQLITE_API int sqlite3_open(
const char *zFilename,
sqlite3 **ppDb
){
return openDatabase(zFilename, ppDb,
| | | | 114644 114645 114646 114647 114648 114649 114650 114651 114652 114653 114654 114655 114656 114657 114658 114659 114660 114661 114662 114663 114664 114665 114666 |
** Open a new database handle.
*/
SQLITE_API int sqlite3_open(
const char *zFilename,
sqlite3 **ppDb
){
return openDatabase(zFilename, ppDb,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0, 1);
}
SQLITE_API int sqlite3_open_v2(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb, /* OUT: SQLite db handle */
int flags, /* Flags */
const char *zVfs /* Name of VFS module to use */
){
return openDatabase(filename, ppDb, (unsigned int)flags, zVfs, 0);
}
#ifndef SQLITE_OMIT_UTF16
/*
** Open a new database handle.
*/
SQLITE_API int sqlite3_open16(
|
| ︙ | ︙ | |||
114561 114562 114563 114564 114565 114566 114567 |
if( rc ) return rc;
#endif
pVal = sqlite3ValueNew(0);
sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC);
zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8);
if( zFilename8 ){
rc = openDatabase(zFilename8, ppDb,
| | | 114679 114680 114681 114682 114683 114684 114685 114686 114687 114688 114689 114690 114691 114692 114693 |
if( rc ) return rc;
#endif
pVal = sqlite3ValueNew(0);
sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC);
zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8);
if( zFilename8 ){
rc = openDatabase(zFilename8, ppDb,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0, 1);
assert( *ppDb || rc==SQLITE_NOMEM );
if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){
ENC(*ppDb) = SQLITE_UTF16NATIVE;
}
}else{
rc = SQLITE_NOMEM;
}
|
| ︙ | ︙ | |||
136798 136799 136800 136801 136802 136803 136804 | *ppModule = &icuTokenizerModule; } #endif /* defined(SQLITE_ENABLE_ICU) */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ /************** End of fts3_icu.c ********************************************/ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 136916 136917 136918 136919 136920 136921 136922 136923 136924 136925 136926 136927 136928 136929 136930 136931 136932 136933 136934 136935 136936 136937 136938 136939 136940 136941 136942 136943 136944 136945 136946 136947 136948 136949 136950 136951 136952 136953 136954 136955 136956 136957 136958 136959 136960 136961 136962 136963 136964 136965 136966 136967 136968 136969 136970 136971 136972 136973 136974 136975 136976 136977 136978 136979 136980 136981 136982 136983 136984 136985 136986 136987 136988 136989 136990 136991 136992 136993 136994 136995 136996 136997 136998 136999 137000 137001 137002 137003 137004 137005 137006 137007 137008 137009 137010 137011 137012 137013 137014 137015 137016 137017 137018 137019 137020 137021 137022 137023 137024 137025 137026 137027 137028 137029 137030 137031 137032 137033 137034 137035 137036 137037 137038 137039 137040 137041 137042 137043 137044 137045 137046 137047 137048 137049 137050 137051 137052 137053 137054 137055 137056 137057 137058 137059 137060 137061 137062 137063 137064 137065 137066 137067 137068 137069 137070 137071 137072 137073 137074 137075 137076 137077 137078 137079 137080 137081 137082 137083 137084 137085 137086 137087 137088 137089 137090 137091 137092 137093 137094 137095 137096 137097 137098 137099 137100 137101 137102 137103 137104 137105 137106 137107 137108 137109 137110 137111 137112 137113 137114 137115 137116 137117 137118 137119 137120 137121 137122 137123 137124 137125 137126 137127 137128 137129 137130 137131 137132 137133 137134 137135 137136 137137 137138 137139 137140 137141 137142 137143 137144 137145 137146 137147 137148 137149 137150 137151 137152 137153 137154 137155 137156 137157 137158 137159 137160 137161 137162 137163 137164 137165 137166 137167 137168 137169 137170 137171 137172 137173 137174 137175 137176 137177 137178 137179 137180 137181 137182 137183 137184 137185 137186 137187 137188 137189 137190 137191 137192 137193 137194 137195 137196 137197 137198 137199 137200 137201 137202 137203 137204 137205 137206 137207 137208 137209 137210 137211 137212 137213 137214 137215 137216 137217 137218 137219 137220 137221 137222 137223 137224 137225 137226 137227 137228 137229 137230 137231 137232 137233 137234 137235 137236 137237 137238 137239 137240 137241 137242 137243 137244 137245 137246 137247 137248 137249 137250 137251 137252 137253 137254 137255 137256 137257 137258 137259 137260 137261 137262 137263 137264 137265 137266 137267 137268 137269 137270 137271 137272 137273 137274 137275 137276 137277 137278 137279 137280 137281 137282 137283 137284 137285 137286 137287 137288 137289 137290 137291 137292 137293 137294 137295 137296 137297 137298 137299 137300 137301 137302 137303 137304 137305 137306 137307 137308 137309 137310 137311 137312 137313 137314 137315 137316 137317 137318 137319 137320 137321 137322 137323 137324 137325 137326 137327 137328 137329 137330 137331 137332 137333 137334 137335 137336 137337 137338 137339 137340 137341 137342 137343 137344 137345 137346 137347 137348 137349 137350 137351 137352 137353 137354 137355 137356 137357 137358 137359 137360 137361 137362 137363 137364 137365 137366 137367 137368 137369 137370 137371 137372 137373 137374 137375 137376 137377 137378 137379 137380 137381 137382 137383 137384 137385 137386 137387 137388 137389 137390 137391 137392 137393 137394 137395 137396 137397 137398 137399 137400 137401 137402 137403 137404 137405 137406 137407 137408 137409 137410 137411 137412 137413 137414 137415 137416 137417 137418 137419 137420 137421 137422 137423 137424 137425 137426 137427 137428 137429 137430 137431 137432 137433 137434 137435 137436 137437 137438 137439 137440 137441 137442 137443 137444 137445 137446 137447 137448 137449 137450 137451 137452 137453 137454 137455 137456 137457 137458 137459 137460 137461 137462 137463 137464 137465 137466 137467 137468 137469 137470 137471 137472 137473 137474 137475 137476 137477 137478 137479 137480 137481 137482 137483 137484 137485 137486 137487 137488 137489 137490 137491 137492 137493 137494 137495 137496 137497 137498 137499 137500 137501 137502 137503 137504 137505 137506 137507 137508 137509 137510 137511 137512 137513 137514 137515 137516 137517 137518 137519 137520 137521 137522 137523 137524 137525 137526 137527 137528 137529 137530 137531 137532 137533 137534 137535 137536 137537 137538 137539 137540 137541 137542 137543 137544 137545 137546 137547 137548 137549 137550 137551 137552 137553 137554 137555 137556 137557 137558 137559 137560 137561 137562 137563 137564 137565 137566 137567 137568 137569 137570 137571 137572 137573 137574 137575 137576 137577 137578 137579 137580 137581 137582 137583 137584 137585 137586 137587 137588 137589 137590 137591 137592 137593 137594 137595 137596 137597 137598 137599 137600 137601 137602 137603 137604 137605 137606 137607 137608 137609 137610 137611 137612 137613 137614 137615 137616 137617 137618 137619 137620 137621 137622 137623 137624 137625 137626 137627 137628 137629 137630 137631 137632 137633 137634 137635 137636 137637 137638 137639 137640 137641 137642 137643 137644 137645 137646 137647 137648 137649 137650 137651 137652 137653 137654 137655 137656 137657 137658 137659 137660 137661 137662 137663 137664 137665 137666 137667 137668 137669 137670 137671 137672 137673 137674 137675 137676 137677 137678 137679 137680 137681 137682 137683 137684 137685 137686 137687 137688 137689 137690 137691 137692 137693 137694 137695 137696 137697 137698 137699 137700 137701 137702 137703 137704 137705 137706 137707 137708 137709 137710 137711 137712 137713 137714 137715 137716 137717 137718 137719 137720 137721 137722 137723 137724 137725 137726 137727 137728 137729 137730 137731 137732 137733 137734 137735 137736 137737 137738 137739 137740 137741 137742 137743 137744 137745 137746 137747 137748 137749 137750 137751 137752 137753 137754 137755 137756 137757 137758 137759 137760 137761 137762 137763 137764 137765 137766 137767 137768 137769 137770 137771 137772 137773 137774 137775 137776 137777 137778 137779 137780 137781 137782 137783 137784 137785 137786 137787 137788 137789 137790 137791 137792 137793 137794 137795 137796 137797 137798 137799 137800 137801 137802 137803 137804 137805 137806 137807 137808 137809 137810 137811 137812 137813 137814 137815 137816 137817 137818 137819 137820 137821 137822 137823 137824 137825 137826 137827 137828 137829 137830 137831 137832 137833 137834 137835 137836 137837 137838 137839 137840 137841 137842 137843 137844 137845 137846 137847 137848 137849 137850 137851 137852 137853 137854 137855 137856 137857 137858 137859 137860 137861 137862 137863 137864 137865 137866 137867 137868 137869 137870 137871 137872 137873 137874 137875 137876 137877 137878 137879 137880 137881 137882 137883 137884 137885 137886 137887 137888 137889 137890 137891 137892 137893 137894 137895 137896 137897 137898 137899 137900 137901 137902 137903 137904 137905 137906 137907 137908 137909 137910 137911 137912 137913 137914 137915 137916 137917 137918 137919 137920 137921 137922 137923 137924 137925 137926 137927 137928 137929 137930 137931 137932 137933 137934 137935 137936 137937 137938 137939 137940 137941 137942 137943 137944 137945 137946 137947 137948 137949 137950 137951 137952 137953 137954 137955 137956 137957 137958 137959 137960 137961 137962 137963 137964 137965 137966 137967 137968 137969 137970 137971 137972 137973 137974 137975 137976 137977 137978 137979 137980 137981 137982 137983 137984 137985 137986 137987 137988 137989 137990 137991 137992 137993 137994 137995 137996 137997 137998 137999 138000 138001 138002 138003 138004 138005 138006 138007 138008 138009 138010 138011 138012 138013 138014 138015 138016 138017 138018 138019 138020 138021 138022 138023 138024 138025 138026 138027 138028 138029 138030 138031 138032 138033 138034 138035 138036 138037 138038 138039 138040 138041 138042 138043 138044 138045 138046 138047 138048 138049 138050 138051 138052 138053 138054 138055 138056 138057 138058 138059 138060 138061 138062 138063 138064 138065 138066 138067 138068 138069 138070 138071 138072 138073 138074 138075 138076 138077 138078 138079 138080 138081 138082 138083 138084 138085 138086 138087 138088 138089 138090 138091 138092 138093 138094 138095 138096 138097 138098 138099 138100 138101 138102 138103 138104 138105 138106 138107 138108 138109 138110 138111 138112 138113 138114 138115 138116 138117 138118 138119 138120 138121 138122 138123 138124 138125 138126 138127 138128 138129 138130 138131 138132 138133 138134 138135 138136 138137 138138 138139 138140 138141 138142 138143 138144 138145 138146 138147 138148 138149 138150 138151 138152 138153 138154 138155 138156 138157 138158 138159 138160 138161 138162 138163 138164 138165 138166 138167 138168 138169 138170 138171 138172 138173 138174 138175 138176 138177 138178 138179 138180 138181 138182 138183 138184 138185 138186 138187 138188 138189 138190 138191 138192 138193 138194 138195 138196 138197 138198 138199 138200 138201 138202 138203 138204 138205 138206 138207 138208 138209 138210 138211 138212 138213 138214 138215 138216 138217 138218 138219 138220 138221 138222 138223 138224 138225 138226 138227 138228 138229 138230 138231 138232 138233 138234 138235 138236 138237 138238 138239 138240 138241 138242 138243 138244 138245 138246 138247 138248 138249 138250 138251 138252 138253 138254 138255 138256 138257 138258 138259 138260 138261 138262 138263 138264 138265 138266 138267 138268 138269 138270 138271 138272 138273 138274 138275 138276 138277 138278 138279 138280 138281 138282 138283 138284 138285 138286 138287 138288 138289 138290 138291 138292 138293 138294 138295 138296 138297 138298 138299 138300 138301 138302 138303 138304 138305 138306 138307 138308 138309 138310 138311 138312 138313 138314 138315 138316 138317 138318 138319 138320 138321 138322 138323 138324 138325 138326 138327 138328 138329 138330 138331 138332 138333 138334 138335 138336 138337 138338 138339 138340 138341 138342 138343 138344 138345 138346 138347 138348 138349 138350 138351 138352 138353 138354 138355 138356 138357 138358 138359 138360 138361 138362 138363 138364 138365 138366 138367 138368 138369 138370 138371 138372 138373 138374 138375 138376 138377 138378 138379 138380 138381 138382 138383 138384 138385 138386 138387 138388 138389 138390 138391 138392 138393 138394 138395 138396 138397 138398 138399 138400 138401 138402 138403 138404 138405 138406 138407 138408 138409 138410 138411 138412 138413 138414 138415 138416 138417 138418 138419 138420 138421 138422 138423 138424 138425 138426 138427 138428 138429 138430 138431 138432 138433 138434 138435 138436 138437 138438 138439 138440 138441 138442 138443 138444 138445 138446 138447 138448 138449 138450 138451 138452 138453 138454 138455 138456 138457 138458 138459 138460 138461 138462 138463 138464 138465 138466 138467 138468 138469 138470 138471 138472 138473 138474 138475 138476 138477 138478 138479 138480 138481 138482 138483 138484 138485 138486 138487 138488 138489 138490 138491 138492 138493 138494 138495 138496 138497 138498 138499 138500 138501 138502 138503 138504 138505 138506 138507 138508 138509 138510 138511 138512 138513 138514 138515 138516 138517 138518 138519 138520 138521 138522 138523 138524 138525 138526 138527 138528 138529 138530 138531 138532 138533 138534 138535 138536 138537 138538 138539 138540 138541 138542 138543 138544 138545 138546 138547 138548 138549 138550 138551 138552 138553 138554 138555 138556 138557 138558 138559 138560 138561 138562 138563 138564 138565 138566 138567 138568 138569 138570 138571 138572 138573 138574 138575 138576 138577 138578 138579 138580 138581 138582 138583 138584 138585 138586 138587 138588 138589 138590 138591 138592 138593 138594 138595 138596 138597 138598 138599 138600 138601 138602 138603 138604 138605 138606 138607 138608 138609 138610 138611 138612 138613 138614 138615 138616 138617 138618 138619 138620 138621 138622 138623 138624 138625 138626 138627 138628 138629 138630 138631 138632 138633 138634 138635 138636 138637 138638 138639 138640 138641 138642 138643 138644 138645 138646 138647 138648 138649 138650 138651 138652 138653 138654 138655 138656 138657 138658 138659 138660 138661 138662 138663 138664 138665 138666 138667 138668 138669 138670 138671 138672 138673 138674 138675 138676 138677 138678 138679 138680 138681 138682 138683 138684 138685 138686 138687 138688 138689 138690 138691 138692 138693 138694 138695 138696 138697 138698 138699 138700 138701 138702 138703 138704 138705 138706 138707 138708 138709 138710 138711 138712 138713 138714 138715 138716 138717 138718 138719 138720 138721 138722 138723 138724 138725 138726 138727 138728 138729 138730 138731 138732 138733 138734 138735 138736 138737 138738 138739 138740 138741 138742 138743 138744 138745 138746 138747 138748 138749 138750 138751 138752 138753 138754 138755 138756 138757 138758 138759 138760 138761 138762 138763 138764 138765 138766 138767 138768 138769 138770 138771 138772 138773 138774 138775 138776 138777 138778 138779 138780 138781 138782 138783 138784 138785 138786 138787 138788 138789 138790 138791 138792 138793 138794 138795 138796 138797 138798 138799 138800 138801 138802 138803 138804 138805 138806 138807 138808 138809 138810 138811 138812 138813 138814 138815 138816 138817 138818 138819 138820 138821 138822 138823 138824 138825 138826 138827 138828 138829 138830 138831 138832 138833 138834 138835 138836 138837 138838 138839 138840 138841 138842 138843 138844 138845 138846 138847 138848 138849 138850 138851 138852 138853 138854 138855 138856 138857 138858 138859 138860 138861 138862 138863 138864 138865 138866 138867 138868 138869 138870 138871 138872 138873 138874 138875 138876 138877 138878 138879 138880 138881 138882 138883 138884 138885 138886 138887 138888 138889 138890 138891 138892 138893 138894 138895 138896 138897 138898 138899 138900 138901 138902 138903 138904 138905 138906 138907 138908 138909 138910 138911 138912 138913 138914 138915 138916 138917 138918 138919 138920 138921 138922 138923 138924 138925 138926 138927 138928 138929 138930 138931 138932 138933 138934 138935 138936 138937 138938 138939 138940 138941 138942 138943 138944 138945 138946 138947 138948 138949 138950 138951 138952 138953 138954 138955 138956 138957 138958 138959 138960 138961 138962 138963 138964 138965 138966 138967 138968 138969 138970 138971 138972 138973 138974 138975 138976 138977 138978 138979 138980 138981 138982 138983 138984 138985 138986 138987 138988 138989 138990 138991 138992 138993 138994 138995 138996 138997 138998 138999 139000 139001 139002 139003 139004 139005 139006 139007 139008 139009 139010 139011 139012 139013 139014 139015 139016 139017 139018 139019 139020 139021 139022 139023 139024 139025 139026 139027 139028 139029 139030 139031 139032 139033 139034 139035 139036 139037 139038 139039 139040 139041 139042 139043 139044 139045 139046 139047 139048 139049 139050 139051 139052 139053 139054 139055 139056 139057 139058 139059 139060 139061 139062 139063 139064 139065 139066 139067 139068 139069 139070 139071 139072 139073 139074 139075 139076 139077 139078 139079 139080 139081 139082 139083 139084 139085 139086 139087 139088 139089 139090 139091 139092 139093 139094 139095 139096 139097 139098 139099 139100 139101 139102 139103 139104 139105 139106 139107 139108 139109 139110 139111 139112 139113 139114 139115 139116 139117 139118 139119 139120 139121 139122 139123 139124 139125 139126 139127 139128 139129 139130 139131 139132 139133 139134 139135 139136 139137 139138 139139 139140 139141 139142 139143 139144 139145 139146 139147 139148 139149 139150 139151 139152 139153 139154 139155 139156 139157 139158 139159 139160 139161 139162 139163 139164 139165 139166 139167 139168 139169 139170 139171 139172 139173 139174 139175 139176 139177 139178 139179 139180 139181 139182 139183 139184 139185 139186 139187 139188 139189 139190 139191 139192 139193 139194 139195 139196 139197 139198 139199 139200 139201 139202 139203 139204 139205 139206 139207 139208 139209 139210 139211 139212 139213 139214 139215 139216 139217 139218 139219 139220 139221 139222 139223 139224 139225 139226 139227 139228 139229 139230 139231 139232 139233 139234 139235 139236 139237 139238 139239 139240 139241 139242 139243 139244 139245 139246 139247 139248 139249 139250 139251 139252 139253 139254 139255 139256 139257 139258 139259 139260 139261 139262 139263 139264 139265 139266 139267 139268 139269 139270 139271 139272 139273 139274 139275 139276 139277 139278 139279 139280 139281 139282 139283 139284 139285 139286 139287 139288 139289 139290 139291 139292 139293 139294 139295 139296 139297 139298 139299 139300 139301 139302 139303 139304 139305 139306 139307 139308 139309 139310 139311 139312 139313 139314 139315 139316 139317 139318 139319 139320 139321 139322 139323 139324 139325 139326 139327 139328 139329 139330 139331 139332 139333 139334 139335 139336 139337 139338 139339 139340 139341 139342 139343 139344 139345 139346 139347 139348 139349 139350 139351 139352 139353 139354 139355 139356 139357 139358 139359 139360 139361 139362 139363 139364 139365 139366 139367 139368 139369 139370 139371 139372 139373 139374 139375 139376 139377 139378 139379 139380 139381 139382 139383 139384 139385 139386 139387 139388 139389 139390 139391 139392 139393 139394 139395 139396 139397 139398 139399 139400 139401 139402 139403 139404 139405 139406 139407 139408 139409 139410 139411 139412 139413 139414 139415 139416 139417 139418 139419 139420 139421 139422 139423 139424 139425 139426 139427 139428 139429 139430 139431 139432 139433 139434 139435 139436 139437 139438 139439 139440 139441 139442 139443 139444 139445 139446 139447 139448 139449 139450 139451 139452 139453 139454 139455 139456 139457 139458 139459 139460 139461 139462 139463 139464 139465 139466 139467 139468 139469 139470 139471 139472 139473 139474 139475 139476 139477 139478 139479 139480 139481 139482 139483 139484 139485 139486 139487 139488 139489 139490 139491 139492 139493 139494 139495 139496 139497 139498 139499 139500 139501 139502 139503 139504 139505 139506 139507 139508 139509 139510 139511 139512 139513 139514 139515 139516 139517 139518 139519 139520 139521 139522 139523 139524 139525 139526 139527 139528 139529 139530 139531 139532 139533 139534 139535 139536 139537 139538 139539 139540 139541 139542 139543 139544 139545 139546 139547 139548 139549 139550 139551 139552 139553 139554 139555 139556 139557 139558 139559 139560 139561 139562 139563 139564 139565 139566 139567 139568 139569 139570 139571 139572 139573 139574 139575 139576 139577 139578 139579 139580 139581 139582 139583 139584 139585 139586 139587 139588 139589 139590 139591 139592 139593 139594 139595 139596 139597 139598 139599 139600 139601 139602 139603 139604 139605 139606 139607 139608 139609 139610 139611 139612 139613 139614 139615 139616 139617 139618 139619 139620 139621 139622 139623 139624 139625 139626 139627 139628 139629 139630 139631 139632 139633 139634 139635 139636 139637 139638 139639 139640 139641 139642 139643 139644 139645 139646 139647 139648 139649 139650 139651 139652 139653 139654 139655 139656 139657 139658 139659 139660 139661 139662 139663 139664 139665 139666 139667 139668 139669 139670 139671 139672 139673 139674 139675 139676 139677 139678 139679 139680 139681 139682 139683 139684 139685 139686 139687 139688 139689 139690 139691 139692 139693 139694 139695 139696 139697 139698 139699 139700 139701 139702 139703 139704 139705 139706 139707 139708 139709 139710 139711 139712 139713 139714 139715 139716 139717 139718 139719 139720 139721 139722 139723 139724 139725 139726 139727 139728 139729 139730 139731 139732 139733 139734 139735 139736 139737 139738 139739 139740 139741 139742 139743 139744 139745 139746 139747 139748 139749 139750 139751 139752 139753 139754 139755 139756 139757 139758 139759 139760 139761 139762 139763 139764 139765 139766 139767 139768 139769 139770 139771 139772 139773 139774 139775 139776 139777 139778 139779 139780 139781 139782 139783 139784 139785 139786 139787 139788 139789 139790 139791 139792 139793 139794 139795 139796 139797 139798 139799 139800 139801 139802 139803 139804 139805 139806 139807 139808 139809 139810 139811 139812 139813 139814 139815 139816 139817 139818 139819 139820 139821 139822 139823 139824 139825 139826 139827 139828 139829 139830 139831 139832 139833 139834 139835 139836 139837 139838 139839 139840 139841 139842 139843 139844 139845 139846 139847 139848 139849 139850 139851 139852 139853 139854 139855 139856 139857 139858 139859 139860 139861 139862 139863 139864 139865 139866 139867 139868 139869 139870 139871 139872 139873 139874 139875 139876 139877 139878 139879 139880 139881 139882 139883 139884 139885 139886 139887 139888 139889 139890 139891 139892 139893 139894 139895 139896 139897 139898 139899 139900 139901 139902 139903 139904 139905 139906 139907 139908 139909 139910 139911 139912 139913 139914 139915 139916 139917 139918 139919 139920 139921 139922 139923 139924 139925 139926 139927 139928 139929 139930 139931 139932 139933 139934 139935 139936 139937 139938 139939 139940 139941 139942 139943 139944 139945 139946 139947 139948 139949 139950 139951 139952 139953 139954 139955 139956 139957 139958 139959 139960 139961 139962 139963 139964 139965 139966 139967 139968 139969 139970 139971 139972 139973 139974 139975 139976 139977 139978 139979 139980 139981 139982 139983 139984 139985 139986 139987 139988 139989 139990 139991 139992 139993 139994 139995 139996 139997 139998 139999 140000 140001 140002 140003 140004 140005 140006 140007 140008 140009 140010 140011 140012 140013 140014 140015 140016 140017 140018 140019 140020 140021 140022 140023 140024 140025 140026 140027 140028 140029 140030 140031 140032 140033 140034 140035 140036 140037 140038 140039 140040 140041 140042 140043 140044 140045 140046 140047 140048 140049 140050 140051 140052 140053 140054 140055 140056 140057 140058 140059 140060 140061 140062 140063 140064 140065 140066 140067 140068 140069 140070 140071 140072 140073 140074 140075 140076 140077 140078 140079 140080 140081 140082 140083 140084 140085 140086 140087 140088 140089 140090 140091 140092 140093 140094 140095 140096 140097 140098 140099 140100 140101 140102 140103 140104 140105 140106 140107 140108 140109 140110 140111 140112 140113 140114 140115 140116 140117 140118 140119 140120 140121 140122 140123 140124 140125 140126 140127 140128 140129 140130 140131 140132 140133 140134 140135 140136 140137 140138 140139 140140 140141 140142 140143 140144 140145 140146 140147 140148 140149 140150 140151 140152 140153 140154 140155 140156 140157 140158 140159 140160 140161 140162 140163 140164 140165 140166 140167 140168 140169 140170 140171 140172 140173 140174 140175 140176 140177 140178 140179 140180 140181 140182 140183 140184 140185 140186 140187 140188 140189 140190 140191 140192 140193 140194 140195 140196 140197 140198 140199 140200 140201 140202 140203 140204 140205 140206 140207 140208 140209 140210 140211 140212 140213 140214 140215 140216 140217 140218 140219 140220 140221 140222 140223 140224 140225 140226 140227 140228 140229 140230 140231 140232 140233 140234 140235 140236 140237 140238 140239 140240 140241 140242 140243 140244 140245 140246 140247 140248 140249 140250 140251 140252 140253 140254 140255 140256 140257 140258 140259 140260 140261 140262 140263 140264 140265 140266 140267 140268 140269 140270 140271 140272 140273 140274 140275 140276 140277 140278 140279 140280 140281 140282 140283 140284 140285 140286 140287 140288 140289 140290 140291 140292 140293 140294 140295 140296 140297 140298 140299 140300 140301 140302 140303 140304 140305 140306 140307 140308 140309 140310 140311 140312 140313 140314 140315 140316 140317 140318 140319 140320 140321 140322 140323 140324 140325 140326 140327 140328 140329 140330 140331 140332 140333 140334 140335 140336 140337 140338 140339 140340 140341 140342 140343 140344 140345 140346 140347 140348 140349 140350 140351 140352 140353 140354 140355 140356 140357 140358 140359 140360 140361 140362 140363 140364 140365 140366 140367 140368 140369 140370 140371 140372 140373 140374 140375 140376 140377 140378 140379 140380 140381 140382 140383 140384 140385 140386 140387 140388 140389 140390 140391 140392 140393 140394 140395 140396 140397 140398 140399 140400 140401 140402 140403 140404 140405 140406 140407 140408 140409 140410 140411 140412 140413 140414 140415 140416 140417 140418 140419 140420 140421 140422 140423 140424 140425 140426 140427 140428 140429 140430 140431 140432 140433 140434 140435 140436 140437 140438 140439 140440 140441 140442 140443 140444 140445 140446 140447 140448 140449 140450 140451 140452 140453 140454 140455 140456 140457 140458 140459 140460 140461 140462 140463 140464 140465 140466 140467 140468 140469 140470 140471 140472 140473 140474 140475 140476 140477 140478 140479 140480 140481 140482 140483 140484 140485 140486 140487 140488 140489 140490 140491 140492 140493 140494 140495 140496 140497 140498 140499 140500 140501 140502 140503 140504 140505 140506 140507 140508 140509 140510 140511 140512 140513 140514 140515 140516 140517 140518 140519 140520 140521 140522 140523 140524 140525 140526 140527 140528 140529 140530 140531 140532 140533 140534 140535 140536 140537 140538 140539 140540 140541 140542 140543 140544 140545 140546 140547 140548 140549 140550 140551 140552 140553 140554 140555 140556 140557 140558 140559 140560 140561 140562 140563 140564 140565 140566 140567 140568 140569 140570 140571 140572 140573 140574 140575 140576 140577 140578 140579 140580 140581 140582 140583 140584 140585 140586 140587 140588 140589 140590 140591 140592 140593 140594 140595 140596 140597 140598 140599 140600 140601 140602 140603 140604 140605 140606 140607 140608 140609 140610 140611 140612 140613 140614 140615 140616 140617 140618 140619 140620 140621 140622 140623 140624 140625 140626 140627 140628 140629 140630 140631 140632 140633 140634 140635 140636 140637 140638 140639 140640 140641 140642 140643 140644 140645 140646 140647 140648 140649 140650 140651 140652 140653 140654 140655 140656 140657 140658 140659 140660 140661 140662 140663 140664 140665 140666 140667 140668 140669 140670 140671 140672 140673 140674 140675 140676 140677 140678 140679 140680 140681 140682 140683 140684 140685 140686 140687 140688 140689 140690 140691 140692 140693 140694 140695 140696 140697 140698 140699 140700 140701 140702 140703 140704 140705 140706 140707 140708 140709 140710 140711 |
*ppModule = &icuTokenizerModule;
}
#endif /* defined(SQLITE_ENABLE_ICU) */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
/************** End of fts3_icu.c ********************************************/
/*
** 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.
**
*************************************************************************
** A TCL Interface to SQLite. Append this file to sqlite3.c and
** compile the whole thing to build a TCL-enabled version of SQLite.
**
** Compile-time options:
**
** -DTCLSH=1 Add a "main()" routine that works as a tclsh.
**
** -DSQLITE_TCLMD5 When used in conjuction with -DTCLSH=1, add
** four new commands to the TCL interpreter for
** generating MD5 checksums: md5, md5file,
** md5-10x8, and md5file-10x8.
**
** -DSQLITE_TEST When used in conjuction with -DTCLSH=1, add
** hundreds of new commands used for testing
** SQLite. This option implies -DSQLITE_TCLMD5.
*/
#include "tcl.h"
#include <errno.h>
/*
** Some additional include files are needed if this file is not
** appended to the amalgamation.
*/
#ifndef SQLITE_AMALGAMATION
# include "sqlite3.h"
# include <stdlib.h>
# include <string.h>
# include <assert.h>
typedef unsigned char u8;
#endif
#include <ctype.h>
/*
* Windows needs to know which symbols to export. Unix does not.
* BUILD_sqlite should be undefined for Unix.
*/
#ifdef BUILD_sqlite
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT
#endif /* BUILD_sqlite */
#define NUM_PREPARED_STMTS 10
#define MAX_PREPARED_STMTS 100
/* Forward declaration */
typedef struct SqliteDb SqliteDb;
/*
** New SQL functions can be created as TCL scripts. Each such function
** is described by an instance of the following structure.
*/
typedef struct SqlFunc SqlFunc;
struct SqlFunc {
Tcl_Interp *interp; /* The TCL interpret to execute the function */
Tcl_Obj *pScript; /* The Tcl_Obj representation of the script */
SqliteDb *pDb; /* Database connection that owns this function */
int useEvalObjv; /* True if it is safe to use Tcl_EvalObjv */
char *zName; /* Name of this function */
SqlFunc *pNext; /* Next function on the list of them all */
};
/*
** New collation sequences function can be created as TCL scripts. Each such
** function is described by an instance of the following structure.
*/
typedef struct SqlCollate SqlCollate;
struct SqlCollate {
Tcl_Interp *interp; /* The TCL interpret to execute the function */
char *zScript; /* The script to be run */
SqlCollate *pNext; /* Next function on the list of them all */
};
/*
** Prepared statements are cached for faster execution. Each prepared
** statement is described by an instance of the following structure.
*/
typedef struct SqlPreparedStmt SqlPreparedStmt;
struct SqlPreparedStmt {
SqlPreparedStmt *pNext; /* Next in linked list */
SqlPreparedStmt *pPrev; /* Previous on the list */
sqlite3_stmt *pStmt; /* The prepared statement */
int nSql; /* chars in zSql[] */
const char *zSql; /* Text of the SQL statement */
int nParm; /* Size of apParm array */
Tcl_Obj **apParm; /* Array of referenced object pointers */
};
typedef struct IncrblobChannel IncrblobChannel;
/*
** There is one instance of this structure for each SQLite database
** that has been opened by the SQLite TCL interface.
**
** If this module is built with SQLITE_TEST defined (to create the SQLite
** testfixture executable), then it may be configured to use either
** sqlite3_prepare_v2() or sqlite3_prepare() to prepare SQL statements.
** If SqliteDb.bLegacyPrepare is true, sqlite3_prepare() is used.
*/
struct SqliteDb {
sqlite3 *db; /* The "real" database structure. MUST BE FIRST */
Tcl_Interp *interp; /* The interpreter used for this database */
char *zBusy; /* The busy callback routine */
char *zCommit; /* The commit hook callback routine */
char *zTrace; /* The trace callback routine */
char *zProfile; /* The profile callback routine */
char *zProgress; /* The progress callback routine */
char *zAuth; /* The authorization callback routine */
int disableAuth; /* Disable the authorizer if it exists */
char *zNull; /* Text to substitute for an SQL NULL value */
SqlFunc *pFunc; /* List of SQL functions */
Tcl_Obj *pUpdateHook; /* Update hook script (if any) */
Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */
Tcl_Obj *pWalHook; /* WAL hook script (if any) */
Tcl_Obj *pUnlockNotify; /* Unlock notify script (if any) */
SqlCollate *pCollate; /* List of SQL collation functions */
int rc; /* Return code of most recent sqlite3_exec() */
Tcl_Obj *pCollateNeeded; /* Collation needed script */
SqlPreparedStmt *stmtList; /* List of prepared statements*/
SqlPreparedStmt *stmtLast; /* Last statement in the list */
int maxStmt; /* The next maximum number of stmtList */
int nStmt; /* Number of statements in stmtList */
IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */
int nStep, nSort, nIndex; /* Statistics for most recent operation */
int nTransaction; /* Number of nested [transaction] methods */
#ifdef SQLITE_TEST
int bLegacyPrepare; /* True to use sqlite3_prepare() */
#endif
};
struct IncrblobChannel {
sqlite3_blob *pBlob; /* sqlite3 blob handle */
SqliteDb *pDb; /* Associated database connection */
int iSeek; /* Current seek offset */
Tcl_Channel channel; /* Channel identifier */
IncrblobChannel *pNext; /* Linked list of all open incrblob channels */
IncrblobChannel *pPrev; /* Linked list of all open incrblob channels */
};
/*
** Compute a string length that is limited to what can be stored in
** lower 30 bits of a 32-bit signed integer.
*/
static int strlen30(const char *z){
const char *z2 = z;
while( *z2 ){ z2++; }
return 0x3fffffff & (int)(z2 - z);
}
#ifndef SQLITE_OMIT_INCRBLOB
/*
** Close all incrblob channels opened using database connection pDb.
** This is called when shutting down the database connection.
*/
static void closeIncrblobChannels(SqliteDb *pDb){
IncrblobChannel *p;
IncrblobChannel *pNext;
for(p=pDb->pIncrblob; p; p=pNext){
pNext = p->pNext;
/* Note: Calling unregister here call Tcl_Close on the incrblob channel,
** which deletes the IncrblobChannel structure at *p. So do not
** call Tcl_Free() here.
*/
Tcl_UnregisterChannel(pDb->interp, p->channel);
}
}
/*
** Close an incremental blob channel.
*/
static int incrblobClose(ClientData instanceData, Tcl_Interp *interp){
IncrblobChannel *p = (IncrblobChannel *)instanceData;
int rc = sqlite3_blob_close(p->pBlob);
sqlite3 *db = p->pDb->db;
/* Remove the channel from the SqliteDb.pIncrblob list. */
if( p->pNext ){
p->pNext->pPrev = p->pPrev;
}
if( p->pPrev ){
p->pPrev->pNext = p->pNext;
}
if( p->pDb->pIncrblob==p ){
p->pDb->pIncrblob = p->pNext;
}
/* Free the IncrblobChannel structure */
Tcl_Free((char *)p);
if( rc!=SQLITE_OK ){
Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Read data from an incremental blob channel.
*/
static int incrblobInput(
ClientData instanceData,
char *buf,
int bufSize,
int *errorCodePtr
){
IncrblobChannel *p = (IncrblobChannel *)instanceData;
int nRead = bufSize; /* Number of bytes to read */
int nBlob; /* Total size of the blob */
int rc; /* sqlite error code */
nBlob = sqlite3_blob_bytes(p->pBlob);
if( (p->iSeek+nRead)>nBlob ){
nRead = nBlob-p->iSeek;
}
if( nRead<=0 ){
return 0;
}
rc = sqlite3_blob_read(p->pBlob, (void *)buf, nRead, p->iSeek);
if( rc!=SQLITE_OK ){
*errorCodePtr = rc;
return -1;
}
p->iSeek += nRead;
return nRead;
}
/*
** Write data to an incremental blob channel.
*/
static int incrblobOutput(
ClientData instanceData,
CONST char *buf,
int toWrite,
int *errorCodePtr
){
IncrblobChannel *p = (IncrblobChannel *)instanceData;
int nWrite = toWrite; /* Number of bytes to write */
int nBlob; /* Total size of the blob */
int rc; /* sqlite error code */
nBlob = sqlite3_blob_bytes(p->pBlob);
if( (p->iSeek+nWrite)>nBlob ){
*errorCodePtr = EINVAL;
return -1;
}
if( nWrite<=0 ){
return 0;
}
rc = sqlite3_blob_write(p->pBlob, (void *)buf, nWrite, p->iSeek);
if( rc!=SQLITE_OK ){
*errorCodePtr = EIO;
return -1;
}
p->iSeek += nWrite;
return nWrite;
}
/*
** Seek an incremental blob channel.
*/
static int incrblobSeek(
ClientData instanceData,
long offset,
int seekMode,
int *errorCodePtr
){
IncrblobChannel *p = (IncrblobChannel *)instanceData;
switch( seekMode ){
case SEEK_SET:
p->iSeek = offset;
break;
case SEEK_CUR:
p->iSeek += offset;
break;
case SEEK_END:
p->iSeek = sqlite3_blob_bytes(p->pBlob) + offset;
break;
default: assert(!"Bad seekMode");
}
return p->iSeek;
}
static void incrblobWatch(ClientData instanceData, int mode){
/* NO-OP */
}
static int incrblobHandle(ClientData instanceData, int dir, ClientData *hPtr){
return TCL_ERROR;
}
static Tcl_ChannelType IncrblobChannelType = {
"incrblob", /* typeName */
TCL_CHANNEL_VERSION_2, /* version */
incrblobClose, /* closeProc */
incrblobInput, /* inputProc */
incrblobOutput, /* outputProc */
incrblobSeek, /* seekProc */
0, /* setOptionProc */
0, /* getOptionProc */
incrblobWatch, /* watchProc (this is a no-op) */
incrblobHandle, /* getHandleProc (always returns error) */
0, /* close2Proc */
0, /* blockModeProc */
0, /* flushProc */
0, /* handlerProc */
0, /* wideSeekProc */
};
/*
** Create a new incrblob channel.
*/
static int createIncrblobChannel(
Tcl_Interp *interp,
SqliteDb *pDb,
const char *zDb,
const char *zTable,
const char *zColumn,
sqlite_int64 iRow,
int isReadonly
){
IncrblobChannel *p;
sqlite3 *db = pDb->db;
sqlite3_blob *pBlob;
int rc;
int flags = TCL_READABLE|(isReadonly ? 0 : TCL_WRITABLE);
/* This variable is used to name the channels: "incrblob_[incr count]" */
static int count = 0;
char zChannel[64];
rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRow, !isReadonly, &pBlob);
if( rc!=SQLITE_OK ){
Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
return TCL_ERROR;
}
p = (IncrblobChannel *)Tcl_Alloc(sizeof(IncrblobChannel));
p->iSeek = 0;
p->pBlob = pBlob;
sqlite3_snprintf(sizeof(zChannel), zChannel, "incrblob_%d", ++count);
p->channel = Tcl_CreateChannel(&IncrblobChannelType, zChannel, p, flags);
Tcl_RegisterChannel(interp, p->channel);
/* Link the new channel into the SqliteDb.pIncrblob list. */
p->pNext = pDb->pIncrblob;
p->pPrev = 0;
if( p->pNext ){
p->pNext->pPrev = p;
}
pDb->pIncrblob = p;
p->pDb = pDb;
Tcl_SetResult(interp, (char *)Tcl_GetChannelName(p->channel), TCL_VOLATILE);
return TCL_OK;
}
#else /* else clause for "#ifndef SQLITE_OMIT_INCRBLOB" */
#define closeIncrblobChannels(pDb)
#endif
/*
** Look at the script prefix in pCmd. We will be executing this script
** after first appending one or more arguments. This routine analyzes
** the script to see if it is safe to use Tcl_EvalObjv() on the script
** rather than the more general Tcl_EvalEx(). Tcl_EvalObjv() is much
** faster.
**
** Scripts that are safe to use with Tcl_EvalObjv() consists of a
** command name followed by zero or more arguments with no [...] or $
** or {...} or ; to be seen anywhere. Most callback scripts consist
** of just a single procedure name and they meet this requirement.
*/
static int safeToUseEvalObjv(Tcl_Interp *interp, Tcl_Obj *pCmd){
/* We could try to do something with Tcl_Parse(). But we will instead
** just do a search for forbidden characters. If any of the forbidden
** characters appear in pCmd, we will report the string as unsafe.
*/
const char *z;
int n;
z = Tcl_GetStringFromObj(pCmd, &n);
while( n-- > 0 ){
int c = *(z++);
if( c=='$' || c=='[' || c==';' ) return 0;
}
return 1;
}
/*
** Find an SqlFunc structure with the given name. Or create a new
** one if an existing one cannot be found. Return a pointer to the
** structure.
*/
static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){
SqlFunc *p, *pNew;
int i;
pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + strlen30(zName) + 1 );
pNew->zName = (char*)&pNew[1];
for(i=0; zName[i]; i++){ pNew->zName[i] = tolower(zName[i]); }
pNew->zName[i] = 0;
for(p=pDb->pFunc; p; p=p->pNext){
if( strcmp(p->zName, pNew->zName)==0 ){
Tcl_Free((char*)pNew);
return p;
}
}
pNew->interp = pDb->interp;
pNew->pDb = pDb;
pNew->pScript = 0;
pNew->pNext = pDb->pFunc;
pDb->pFunc = pNew;
return pNew;
}
/*
** Free a single SqlPreparedStmt object.
*/
static void dbFreeStmt(SqlPreparedStmt *pStmt){
#ifdef SQLITE_TEST
if( sqlite3_sql(pStmt->pStmt)==0 ){
Tcl_Free((char *)pStmt->zSql);
}
#endif
sqlite3_finalize(pStmt->pStmt);
Tcl_Free((char *)pStmt);
}
/*
** Finalize and free a list of prepared statements
*/
static void flushStmtCache(SqliteDb *pDb){
SqlPreparedStmt *pPreStmt;
SqlPreparedStmt *pNext;
for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pNext){
pNext = pPreStmt->pNext;
dbFreeStmt(pPreStmt);
}
pDb->nStmt = 0;
pDb->stmtLast = 0;
pDb->stmtList = 0;
}
/*
** TCL calls this procedure when an sqlite3 database command is
** deleted.
*/
static void DbDeleteCmd(void *db){
SqliteDb *pDb = (SqliteDb*)db;
flushStmtCache(pDb);
closeIncrblobChannels(pDb);
sqlite3_close(pDb->db);
while( pDb->pFunc ){
SqlFunc *pFunc = pDb->pFunc;
pDb->pFunc = pFunc->pNext;
assert( pFunc->pDb==pDb );
Tcl_DecrRefCount(pFunc->pScript);
Tcl_Free((char*)pFunc);
}
while( pDb->pCollate ){
SqlCollate *pCollate = pDb->pCollate;
pDb->pCollate = pCollate->pNext;
Tcl_Free((char*)pCollate);
}
if( pDb->zBusy ){
Tcl_Free(pDb->zBusy);
}
if( pDb->zTrace ){
Tcl_Free(pDb->zTrace);
}
if( pDb->zProfile ){
Tcl_Free(pDb->zProfile);
}
if( pDb->zAuth ){
Tcl_Free(pDb->zAuth);
}
if( pDb->zNull ){
Tcl_Free(pDb->zNull);
}
if( pDb->pUpdateHook ){
Tcl_DecrRefCount(pDb->pUpdateHook);
}
if( pDb->pRollbackHook ){
Tcl_DecrRefCount(pDb->pRollbackHook);
}
if( pDb->pWalHook ){
Tcl_DecrRefCount(pDb->pWalHook);
}
if( pDb->pCollateNeeded ){
Tcl_DecrRefCount(pDb->pCollateNeeded);
}
Tcl_Free((char*)pDb);
}
/*
** This routine is called when a database file is locked while trying
** to execute SQL.
*/
static int DbBusyHandler(void *cd, int nTries){
SqliteDb *pDb = (SqliteDb*)cd;
int rc;
char zVal[30];
sqlite3_snprintf(sizeof(zVal), zVal, "%d", nTries);
rc = Tcl_VarEval(pDb->interp, pDb->zBusy, " ", zVal, (char*)0);
if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
return 0;
}
return 1;
}
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/*
** This routine is invoked as the 'progress callback' for the database.
*/
static int DbProgressHandler(void *cd){
SqliteDb *pDb = (SqliteDb*)cd;
int rc;
assert( pDb->zProgress );
rc = Tcl_Eval(pDb->interp, pDb->zProgress);
if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
return 1;
}
return 0;
}
#endif
#ifndef SQLITE_OMIT_TRACE
/*
** This routine is called by the SQLite trace handler whenever a new
** block of SQL is executed. The TCL script in pDb->zTrace is executed.
*/
static void DbTraceHandler(void *cd, const char *zSql){
SqliteDb *pDb = (SqliteDb*)cd;
Tcl_DString str;
Tcl_DStringInit(&str);
Tcl_DStringAppend(&str, pDb->zTrace, -1);
Tcl_DStringAppendElement(&str, zSql);
Tcl_Eval(pDb->interp, Tcl_DStringValue(&str));
Tcl_DStringFree(&str);
Tcl_ResetResult(pDb->interp);
}
#endif
#ifndef SQLITE_OMIT_TRACE
/*
** This routine is called by the SQLite profile handler after a statement
** SQL has executed. The TCL script in pDb->zProfile is evaluated.
*/
static void DbProfileHandler(void *cd, const char *zSql, sqlite_uint64 tm){
SqliteDb *pDb = (SqliteDb*)cd;
Tcl_DString str;
char zTm[100];
sqlite3_snprintf(sizeof(zTm)-1, zTm, "%lld", tm);
Tcl_DStringInit(&str);
Tcl_DStringAppend(&str, pDb->zProfile, -1);
Tcl_DStringAppendElement(&str, zSql);
Tcl_DStringAppendElement(&str, zTm);
Tcl_Eval(pDb->interp, Tcl_DStringValue(&str));
Tcl_DStringFree(&str);
Tcl_ResetResult(pDb->interp);
}
#endif
/*
** This routine is called when a transaction is committed. The
** TCL script in pDb->zCommit is executed. If it returns non-zero or
** if it throws an exception, the transaction is rolled back instead
** of being committed.
*/
static int DbCommitHandler(void *cd){
SqliteDb *pDb = (SqliteDb*)cd;
int rc;
rc = Tcl_Eval(pDb->interp, pDb->zCommit);
if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
return 1;
}
return 0;
}
static void DbRollbackHandler(void *clientData){
SqliteDb *pDb = (SqliteDb*)clientData;
assert(pDb->pRollbackHook);
if( TCL_OK!=Tcl_EvalObjEx(pDb->interp, pDb->pRollbackHook, 0) ){
Tcl_BackgroundError(pDb->interp);
}
}
/*
** This procedure handles wal_hook callbacks.
*/
static int DbWalHandler(
void *clientData,
sqlite3 *db,
const char *zDb,
int nEntry
){
int ret = SQLITE_OK;
Tcl_Obj *p;
SqliteDb *pDb = (SqliteDb*)clientData;
Tcl_Interp *interp = pDb->interp;
assert(pDb->pWalHook);
p = Tcl_DuplicateObj(pDb->pWalHook);
Tcl_IncrRefCount(p);
Tcl_ListObjAppendElement(interp, p, Tcl_NewStringObj(zDb, -1));
Tcl_ListObjAppendElement(interp, p, Tcl_NewIntObj(nEntry));
if( TCL_OK!=Tcl_EvalObjEx(interp, p, 0)
|| TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &ret)
){
Tcl_BackgroundError(interp);
}
Tcl_DecrRefCount(p);
return ret;
}
#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY)
static void setTestUnlockNotifyVars(Tcl_Interp *interp, int iArg, int nArg){
char zBuf[64];
sprintf(zBuf, "%d", iArg);
Tcl_SetVar(interp, "sqlite_unlock_notify_arg", zBuf, TCL_GLOBAL_ONLY);
sprintf(zBuf, "%d", nArg);
Tcl_SetVar(interp, "sqlite_unlock_notify_argcount", zBuf, TCL_GLOBAL_ONLY);
}
#else
# define setTestUnlockNotifyVars(x,y,z)
#endif
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
static void DbUnlockNotify(void **apArg, int nArg){
int i;
for(i=0; i<nArg; i++){
const int flags = (TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
SqliteDb *pDb = (SqliteDb *)apArg[i];
setTestUnlockNotifyVars(pDb->interp, i, nArg);
assert( pDb->pUnlockNotify);
Tcl_EvalObjEx(pDb->interp, pDb->pUnlockNotify, flags);
Tcl_DecrRefCount(pDb->pUnlockNotify);
pDb->pUnlockNotify = 0;
}
}
#endif
static void DbUpdateHandler(
void *p,
int op,
const char *zDb,
const char *zTbl,
sqlite_int64 rowid
){
SqliteDb *pDb = (SqliteDb *)p;
Tcl_Obj *pCmd;
assert( pDb->pUpdateHook );
assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );
pCmd = Tcl_DuplicateObj(pDb->pUpdateHook);
Tcl_IncrRefCount(pCmd);
Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(
( (op==SQLITE_INSERT)?"INSERT":(op==SQLITE_UPDATE)?"UPDATE":"DELETE"), -1));
Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));
Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));
Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(rowid));
Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
Tcl_DecrRefCount(pCmd);
}
static void tclCollateNeeded(
void *pCtx,
sqlite3 *db,
int enc,
const char *zName
){
SqliteDb *pDb = (SqliteDb *)pCtx;
Tcl_Obj *pScript = Tcl_DuplicateObj(pDb->pCollateNeeded);
Tcl_IncrRefCount(pScript);
Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zName, -1));
Tcl_EvalObjEx(pDb->interp, pScript, 0);
Tcl_DecrRefCount(pScript);
}
/*
** This routine is called to evaluate an SQL collation function implemented
** using TCL script.
*/
static int tclSqlCollate(
void *pCtx,
int nA,
const void *zA,
int nB,
const void *zB
){
SqlCollate *p = (SqlCollate *)pCtx;
Tcl_Obj *pCmd;
pCmd = Tcl_NewStringObj(p->zScript, -1);
Tcl_IncrRefCount(pCmd);
Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA));
Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB));
Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);
Tcl_DecrRefCount(pCmd);
return (atoi(Tcl_GetStringResult(p->interp)));
}
/*
** This routine is called to evaluate an SQL function implemented
** using TCL script.
*/
static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
SqlFunc *p = sqlite3_user_data(context);
Tcl_Obj *pCmd;
int i;
int rc;
if( argc==0 ){
/* If there are no arguments to the function, call Tcl_EvalObjEx on the
** script object directly. This allows the TCL compiler to generate
** bytecode for the command on the first invocation and thus make
** subsequent invocations much faster. */
pCmd = p->pScript;
Tcl_IncrRefCount(pCmd);
rc = Tcl_EvalObjEx(p->interp, pCmd, 0);
Tcl_DecrRefCount(pCmd);
}else{
/* If there are arguments to the function, make a shallow copy of the
** script object, lappend the arguments, then evaluate the copy.
**
** By "shallow" copy, we mean a only the outer list Tcl_Obj is duplicated.
** The new Tcl_Obj contains pointers to the original list elements.
** That way, when Tcl_EvalObjv() is run and shimmers the first element
** of the list to tclCmdNameType, that alternate representation will
** be preserved and reused on the next invocation.
*/
Tcl_Obj **aArg;
int nArg;
if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){
sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
return;
}
pCmd = Tcl_NewListObj(nArg, aArg);
Tcl_IncrRefCount(pCmd);
for(i=0; i<argc; i++){
sqlite3_value *pIn = argv[i];
Tcl_Obj *pVal;
/* Set pVal to contain the i'th column of this row. */
switch( sqlite3_value_type(pIn) ){
case SQLITE_BLOB: {
int bytes = sqlite3_value_bytes(pIn);
pVal = Tcl_NewByteArrayObj(sqlite3_value_blob(pIn), bytes);
break;
}
case SQLITE_INTEGER: {
sqlite_int64 v = sqlite3_value_int64(pIn);
if( v>=-2147483647 && v<=2147483647 ){
pVal = Tcl_NewIntObj((int)v);
}else{
pVal = Tcl_NewWideIntObj(v);
}
break;
}
case SQLITE_FLOAT: {
double r = sqlite3_value_double(pIn);
pVal = Tcl_NewDoubleObj(r);
break;
}
case SQLITE_NULL: {
pVal = Tcl_NewStringObj(p->pDb->zNull, -1);
break;
}
default: {
int bytes = sqlite3_value_bytes(pIn);
pVal = Tcl_NewStringObj((char *)sqlite3_value_text(pIn), bytes);
break;
}
}
rc = Tcl_ListObjAppendElement(p->interp, pCmd, pVal);
if( rc ){
Tcl_DecrRefCount(pCmd);
sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
return;
}
}
if( !p->useEvalObjv ){
/* Tcl_EvalObjEx() will automatically call Tcl_EvalObjv() if pCmd
** is a list without a string representation. To prevent this from
** happening, make sure pCmd has a valid string representation */
Tcl_GetString(pCmd);
}
rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);
Tcl_DecrRefCount(pCmd);
}
if( rc && rc!=TCL_RETURN ){
sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
}else{
Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
int n;
u8 *data;
const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
char c = zType[0];
if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
/* Only return a BLOB type if the Tcl variable is a bytearray and
** has no string representation. */
data = Tcl_GetByteArrayFromObj(pVar, &n);
sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT);
}else if( c=='b' && strcmp(zType,"boolean")==0 ){
Tcl_GetIntFromObj(0, pVar, &n);
sqlite3_result_int(context, n);
}else if( c=='d' && strcmp(zType,"double")==0 ){
double r;
Tcl_GetDoubleFromObj(0, pVar, &r);
sqlite3_result_double(context, r);
}else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
(c=='i' && strcmp(zType,"int")==0) ){
Tcl_WideInt v;
Tcl_GetWideIntFromObj(0, pVar, &v);
sqlite3_result_int64(context, v);
}else{
data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
sqlite3_result_text(context, (char *)data, n, SQLITE_TRANSIENT);
}
}
}
#ifndef SQLITE_OMIT_AUTHORIZATION
/*
** This is the authentication function. It appends the authentication
** type code and the two arguments to zCmd[] then invokes the result
** on the interpreter. The reply is examined to determine if the
** authentication fails or succeeds.
*/
static int auth_callback(
void *pArg,
int code,
const char *zArg1,
const char *zArg2,
const char *zArg3,
const char *zArg4
){
char *zCode;
Tcl_DString str;
int rc;
const char *zReply;
SqliteDb *pDb = (SqliteDb*)pArg;
if( pDb->disableAuth ) return SQLITE_OK;
switch( code ){
case SQLITE_COPY : zCode="SQLITE_COPY"; break;
case SQLITE_CREATE_INDEX : zCode="SQLITE_CREATE_INDEX"; break;
case SQLITE_CREATE_TABLE : zCode="SQLITE_CREATE_TABLE"; break;
case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break;
case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break;
case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break;
case SQLITE_CREATE_TEMP_VIEW : zCode="SQLITE_CREATE_TEMP_VIEW"; break;
case SQLITE_CREATE_TRIGGER : zCode="SQLITE_CREATE_TRIGGER"; break;
case SQLITE_CREATE_VIEW : zCode="SQLITE_CREATE_VIEW"; break;
case SQLITE_DELETE : zCode="SQLITE_DELETE"; break;
case SQLITE_DROP_INDEX : zCode="SQLITE_DROP_INDEX"; break;
case SQLITE_DROP_TABLE : zCode="SQLITE_DROP_TABLE"; break;
case SQLITE_DROP_TEMP_INDEX : zCode="SQLITE_DROP_TEMP_INDEX"; break;
case SQLITE_DROP_TEMP_TABLE : zCode="SQLITE_DROP_TEMP_TABLE"; break;
case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break;
case SQLITE_DROP_TEMP_VIEW : zCode="SQLITE_DROP_TEMP_VIEW"; break;
case SQLITE_DROP_TRIGGER : zCode="SQLITE_DROP_TRIGGER"; break;
case SQLITE_DROP_VIEW : zCode="SQLITE_DROP_VIEW"; break;
case SQLITE_INSERT : zCode="SQLITE_INSERT"; break;
case SQLITE_PRAGMA : zCode="SQLITE_PRAGMA"; break;
case SQLITE_READ : zCode="SQLITE_READ"; break;
case SQLITE_SELECT : zCode="SQLITE_SELECT"; break;
case SQLITE_TRANSACTION : zCode="SQLITE_TRANSACTION"; break;
case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break;
case SQLITE_ATTACH : zCode="SQLITE_ATTACH"; break;
case SQLITE_DETACH : zCode="SQLITE_DETACH"; break;
case SQLITE_ALTER_TABLE : zCode="SQLITE_ALTER_TABLE"; break;
case SQLITE_REINDEX : zCode="SQLITE_REINDEX"; break;
case SQLITE_ANALYZE : zCode="SQLITE_ANALYZE"; break;
case SQLITE_CREATE_VTABLE : zCode="SQLITE_CREATE_VTABLE"; break;
case SQLITE_DROP_VTABLE : zCode="SQLITE_DROP_VTABLE"; break;
case SQLITE_FUNCTION : zCode="SQLITE_FUNCTION"; break;
case SQLITE_SAVEPOINT : zCode="SQLITE_SAVEPOINT"; break;
default : zCode="????"; break;
}
Tcl_DStringInit(&str);
Tcl_DStringAppend(&str, pDb->zAuth, -1);
Tcl_DStringAppendElement(&str, zCode);
Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : "");
Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : "");
Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : "");
Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : "");
rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str));
Tcl_DStringFree(&str);
zReply = rc==TCL_OK ? Tcl_GetStringResult(pDb->interp) : "SQLITE_DENY";
if( strcmp(zReply,"SQLITE_OK")==0 ){
rc = SQLITE_OK;
}else if( strcmp(zReply,"SQLITE_DENY")==0 ){
rc = SQLITE_DENY;
}else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){
rc = SQLITE_IGNORE;
}else{
rc = 999;
}
return rc;
}
#endif /* SQLITE_OMIT_AUTHORIZATION */
/*
** This routine reads a line of text from FILE in, stores
** the text in memory obtained from malloc() and returns a pointer
** to the text. NULL is returned at end of file, or if malloc()
** fails.
**
** The interface is like "readline" but no command-line editing
** is done.
**
** copied from shell.c from '.import' command
*/
static char *local_getline(char *zPrompt, FILE *in){
char *zLine;
int nLine;
int n;
nLine = 100;
zLine = malloc( nLine );
if( zLine==0 ) return 0;
n = 0;
while( 1 ){
if( n+100>nLine ){
nLine = nLine*2 + 100;
zLine = realloc(zLine, nLine);
if( zLine==0 ) return 0;
}
if( fgets(&zLine[n], nLine - n, in)==0 ){
if( n==0 ){
free(zLine);
return 0;
}
zLine[n] = 0;
break;
}
while( zLine[n] ){ n++; }
if( n>0 && zLine[n-1]=='\n' ){
n--;
zLine[n] = 0;
break;
}
}
zLine = realloc( zLine, n+1 );
return zLine;
}
/*
** This function is part of the implementation of the command:
**
** $db transaction [-deferred|-immediate|-exclusive] SCRIPT
**
** It is invoked after evaluating the script SCRIPT to commit or rollback
** the transaction or savepoint opened by the [transaction] command.
*/
static int DbTransPostCmd(
ClientData data[], /* data[0] is the Sqlite3Db* for $db */
Tcl_Interp *interp, /* Tcl interpreter */
int result /* Result of evaluating SCRIPT */
){
static const char *azEnd[] = {
"RELEASE _tcl_transaction", /* rc==TCL_ERROR, nTransaction!=0 */
"COMMIT", /* rc!=TCL_ERROR, nTransaction==0 */
"ROLLBACK TO _tcl_transaction ; RELEASE _tcl_transaction",
"ROLLBACK" /* rc==TCL_ERROR, nTransaction==0 */
};
SqliteDb *pDb = (SqliteDb*)data[0];
int rc = result;
const char *zEnd;
pDb->nTransaction--;
zEnd = azEnd[(rc==TCL_ERROR)*2 + (pDb->nTransaction==0)];
pDb->disableAuth++;
if( sqlite3_exec(pDb->db, zEnd, 0, 0, 0) ){
/* This is a tricky scenario to handle. The most likely cause of an
** error is that the exec() above was an attempt to commit the
** top-level transaction that returned SQLITE_BUSY. Or, less likely,
** that an IO-error has occured. In either case, throw a Tcl exception
** and try to rollback the transaction.
**
** But it could also be that the user executed one or more BEGIN,
** COMMIT, SAVEPOINT, RELEASE or ROLLBACK commands that are confusing
** this method's logic. Not clear how this would be best handled.
*/
if( rc!=TCL_ERROR ){
Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0);
rc = TCL_ERROR;
}
sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0);
}
pDb->disableAuth--;
return rc;
}
/*
** Unless SQLITE_TEST is defined, this function is a simple wrapper around
** sqlite3_prepare_v2(). If SQLITE_TEST is defined, then it uses either
** sqlite3_prepare_v2() or legacy interface sqlite3_prepare(), depending
** on whether or not the [db_use_legacy_prepare] command has been used to
** configure the connection.
*/
static int dbPrepare(
SqliteDb *pDb, /* Database object */
const char *zSql, /* SQL to compile */
sqlite3_stmt **ppStmt, /* OUT: Prepared statement */
const char **pzOut /* OUT: Pointer to next SQL statement */
){
#ifdef SQLITE_TEST
if( pDb->bLegacyPrepare ){
return sqlite3_prepare(pDb->db, zSql, -1, ppStmt, pzOut);
}
#endif
return sqlite3_prepare_v2(pDb->db, zSql, -1, ppStmt, pzOut);
}
/*
** Search the cache for a prepared-statement object that implements the
** first SQL statement in the buffer pointed to by parameter zIn. If
** no such prepared-statement can be found, allocate and prepare a new
** one. In either case, bind the current values of the relevant Tcl
** variables to any $var, :var or @var variables in the statement. Before
** returning, set *ppPreStmt to point to the prepared-statement object.
**
** Output parameter *pzOut is set to point to the next SQL statement in
** buffer zIn, or to the '\0' byte at the end of zIn if there is no
** next statement.
**
** If successful, TCL_OK is returned. Otherwise, TCL_ERROR is returned
** and an error message loaded into interpreter pDb->interp.
*/
static int dbPrepareAndBind(
SqliteDb *pDb, /* Database object */
char const *zIn, /* SQL to compile */
char const **pzOut, /* OUT: Pointer to next SQL statement */
SqlPreparedStmt **ppPreStmt /* OUT: Object used to cache statement */
){
const char *zSql = zIn; /* Pointer to first SQL statement in zIn */
sqlite3_stmt *pStmt; /* Prepared statement object */
SqlPreparedStmt *pPreStmt; /* Pointer to cached statement */
int nSql; /* Length of zSql in bytes */
int nVar; /* Number of variables in statement */
int iParm = 0; /* Next free entry in apParm */
int i;
Tcl_Interp *interp = pDb->interp;
*ppPreStmt = 0;
/* Trim spaces from the start of zSql and calculate the remaining length. */
while( isspace(zSql[0]) ){ zSql++; }
nSql = strlen30(zSql);
for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pPreStmt->pNext){
int n = pPreStmt->nSql;
if( nSql>=n
&& memcmp(pPreStmt->zSql, zSql, n)==0
&& (zSql[n]==0 || zSql[n-1]==';')
){
pStmt = pPreStmt->pStmt;
*pzOut = &zSql[pPreStmt->nSql];
/* When a prepared statement is found, unlink it from the
** cache list. It will later be added back to the beginning
** of the cache list in order to implement LRU replacement.
*/
if( pPreStmt->pPrev ){
pPreStmt->pPrev->pNext = pPreStmt->pNext;
}else{
pDb->stmtList = pPreStmt->pNext;
}
if( pPreStmt->pNext ){
pPreStmt->pNext->pPrev = pPreStmt->pPrev;
}else{
pDb->stmtLast = pPreStmt->pPrev;
}
pDb->nStmt--;
nVar = sqlite3_bind_parameter_count(pStmt);
break;
}
}
/* If no prepared statement was found. Compile the SQL text. Also allocate
** a new SqlPreparedStmt structure. */
if( pPreStmt==0 ){
int nByte;
if( SQLITE_OK!=dbPrepare(pDb, zSql, &pStmt, pzOut) ){
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
return TCL_ERROR;
}
if( pStmt==0 ){
if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
/* A compile-time error in the statement. */
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
return TCL_ERROR;
}else{
/* The statement was a no-op. Continue to the next statement
** in the SQL string.
*/
return TCL_OK;
}
}
assert( pPreStmt==0 );
nVar = sqlite3_bind_parameter_count(pStmt);
nByte = sizeof(SqlPreparedStmt) + nVar*sizeof(Tcl_Obj *);
pPreStmt = (SqlPreparedStmt*)Tcl_Alloc(nByte);
memset(pPreStmt, 0, nByte);
pPreStmt->pStmt = pStmt;
pPreStmt->nSql = (int)(*pzOut - zSql);
pPreStmt->zSql = sqlite3_sql(pStmt);
pPreStmt->apParm = (Tcl_Obj **)&pPreStmt[1];
#ifdef SQLITE_TEST
if( pPreStmt->zSql==0 ){
char *zCopy = Tcl_Alloc(pPreStmt->nSql + 1);
memcpy(zCopy, zSql, pPreStmt->nSql);
zCopy[pPreStmt->nSql] = '\0';
pPreStmt->zSql = zCopy;
}
#endif
}
assert( pPreStmt );
assert( strlen30(pPreStmt->zSql)==pPreStmt->nSql );
assert( 0==memcmp(pPreStmt->zSql, zSql, pPreStmt->nSql) );
/* Bind values to parameters that begin with $ or : */
for(i=1; i<=nVar; i++){
const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){
Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);
if( pVar ){
int n;
u8 *data;
const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
char c = zType[0];
if( zVar[0]=='@' ||
(c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0) ){
/* Load a BLOB type if the Tcl variable is a bytearray and
** it has no string representation or the host
** parameter name begins with "@". */
data = Tcl_GetByteArrayFromObj(pVar, &n);
sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC);
Tcl_IncrRefCount(pVar);
pPreStmt->apParm[iParm++] = pVar;
}else if( c=='b' && strcmp(zType,"boolean")==0 ){
Tcl_GetIntFromObj(interp, pVar, &n);
sqlite3_bind_int(pStmt, i, n);
}else if( c=='d' && strcmp(zType,"double")==0 ){
double r;
Tcl_GetDoubleFromObj(interp, pVar, &r);
sqlite3_bind_double(pStmt, i, r);
}else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
(c=='i' && strcmp(zType,"int")==0) ){
Tcl_WideInt v;
Tcl_GetWideIntFromObj(interp, pVar, &v);
sqlite3_bind_int64(pStmt, i, v);
}else{
data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
sqlite3_bind_text(pStmt, i, (char *)data, n, SQLITE_STATIC);
Tcl_IncrRefCount(pVar);
pPreStmt->apParm[iParm++] = pVar;
}
}else{
sqlite3_bind_null(pStmt, i);
}
}
}
pPreStmt->nParm = iParm;
*ppPreStmt = pPreStmt;
return TCL_OK;
}
/*
** Release a statement reference obtained by calling dbPrepareAndBind().
** There should be exactly one call to this function for each call to
** dbPrepareAndBind().
**
** If the discard parameter is non-zero, then the statement is deleted
** immediately. Otherwise it is added to the LRU list and may be returned
** by a subsequent call to dbPrepareAndBind().
*/
static void dbReleaseStmt(
SqliteDb *pDb, /* Database handle */
SqlPreparedStmt *pPreStmt, /* Prepared statement handle to release */
int discard /* True to delete (not cache) the pPreStmt */
){
int i;
/* Free the bound string and blob parameters */
for(i=0; i<pPreStmt->nParm; i++){
Tcl_DecrRefCount(pPreStmt->apParm[i]);
}
pPreStmt->nParm = 0;
if( pDb->maxStmt<=0 || discard ){
/* If the cache is turned off, deallocated the statement */
dbFreeStmt(pPreStmt);
}else{
/* Add the prepared statement to the beginning of the cache list. */
pPreStmt->pNext = pDb->stmtList;
pPreStmt->pPrev = 0;
if( pDb->stmtList ){
pDb->stmtList->pPrev = pPreStmt;
}
pDb->stmtList = pPreStmt;
if( pDb->stmtLast==0 ){
assert( pDb->nStmt==0 );
pDb->stmtLast = pPreStmt;
}else{
assert( pDb->nStmt>0 );
}
pDb->nStmt++;
/* If we have too many statement in cache, remove the surplus from
** the end of the cache list. */
while( pDb->nStmt>pDb->maxStmt ){
SqlPreparedStmt *pLast = pDb->stmtLast;
pDb->stmtLast = pLast->pPrev;
pDb->stmtLast->pNext = 0;
pDb->nStmt--;
dbFreeStmt(pLast);
}
}
}
/*
** Structure used with dbEvalXXX() functions:
**
** dbEvalInit()
** dbEvalStep()
** dbEvalFinalize()
** dbEvalRowInfo()
** dbEvalColumnValue()
*/
typedef struct DbEvalContext DbEvalContext;
struct DbEvalContext {
SqliteDb *pDb; /* Database handle */
Tcl_Obj *pSql; /* Object holding string zSql */
const char *zSql; /* Remaining SQL to execute */
SqlPreparedStmt *pPreStmt; /* Current statement */
int nCol; /* Number of columns returned by pStmt */
Tcl_Obj *pArray; /* Name of array variable */
Tcl_Obj **apColName; /* Array of column names */
};
/*
** Release any cache of column names currently held as part of
** the DbEvalContext structure passed as the first argument.
*/
static void dbReleaseColumnNames(DbEvalContext *p){
if( p->apColName ){
int i;
for(i=0; i<p->nCol; i++){
Tcl_DecrRefCount(p->apColName[i]);
}
Tcl_Free((char *)p->apColName);
p->apColName = 0;
}
p->nCol = 0;
}
/*
** Initialize a DbEvalContext structure.
**
** 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 as part of each
** call to dbEvalStep(), 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 void dbEvalInit(
DbEvalContext *p, /* Pointer to structure to initialize */
SqliteDb *pDb, /* Database handle */
Tcl_Obj *pSql, /* Object containing SQL script */
Tcl_Obj *pArray /* Name of Tcl array to set (*) element of */
){
memset(p, 0, sizeof(DbEvalContext));
p->pDb = pDb;
p->zSql = Tcl_GetString(pSql);
p->pSql = pSql;
Tcl_IncrRefCount(pSql);
if( pArray ){
p->pArray = pArray;
Tcl_IncrRefCount(pArray);
}
}
/*
** Obtain information about the row that the DbEvalContext passed as the
** first argument currently points to.
*/
static void dbEvalRowInfo(
DbEvalContext *p, /* Evaluation context */
int *pnCol, /* OUT: Number of column names */
Tcl_Obj ***papColName /* OUT: Array of column names */
){
/* Compute column names */
if( 0==p->apColName ){
sqlite3_stmt *pStmt = p->pPreStmt->pStmt;
int i; /* Iterator variable */
int nCol; /* Number of columns returned by pStmt */
Tcl_Obj **apColName = 0; /* Array of column names */
p->nCol = nCol = sqlite3_column_count(pStmt);
if( nCol>0 && (papColName || p->pArray) ){
apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol );
for(i=0; i<nCol; i++){
apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1);
Tcl_IncrRefCount(apColName[i]);
}
p->apColName = apColName;
}
/* If results are being stored in an array variable, then create
** the array(*) entry for that array
*/
if( p->pArray ){
Tcl_Interp *interp = p->pDb->interp;
Tcl_Obj *pColList = Tcl_NewObj();
Tcl_Obj *pStar = Tcl_NewStringObj("*", -1);
for(i=0; i<nCol; i++){
Tcl_ListObjAppendElement(interp, pColList, apColName[i]);
}
Tcl_IncrRefCount(pStar);
Tcl_ObjSetVar2(interp, p->pArray, pStar, pColList, 0);
Tcl_DecrRefCount(pStar);
}
}
if( papColName ){
*papColName = p->apColName;
}
if( pnCol ){
*pnCol = p->nCol;
}
}
/*
** Return one of TCL_OK, TCL_BREAK or TCL_ERROR. If TCL_ERROR is
** returned, then an error message is stored in the interpreter before
** returning.
**
** A return value of TCL_OK means there is a row of data available. The
** data may be accessed using dbEvalRowInfo() and dbEvalColumnValue(). This
** is analogous to a return of SQLITE_ROW from sqlite3_step(). If TCL_BREAK
** is returned, then the SQL script has finished executing and there are
** no further rows available. This is similar to SQLITE_DONE.
*/
static int dbEvalStep(DbEvalContext *p){
const char *zPrevSql = 0; /* Previous value of p->zSql */
while( p->zSql[0] || p->pPreStmt ){
int rc;
if( p->pPreStmt==0 ){
zPrevSql = (p->zSql==zPrevSql ? 0 : p->zSql);
rc = dbPrepareAndBind(p->pDb, p->zSql, &p->zSql, &p->pPreStmt);
if( rc!=TCL_OK ) return rc;
}else{
int rcs;
SqliteDb *pDb = p->pDb;
SqlPreparedStmt *pPreStmt = p->pPreStmt;
sqlite3_stmt *pStmt = pPreStmt->pStmt;
rcs = sqlite3_step(pStmt);
if( rcs==SQLITE_ROW ){
return TCL_OK;
}
if( p->pArray ){
dbEvalRowInfo(p, 0, 0);
}
rcs = sqlite3_reset(pStmt);
pDb->nStep = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_FULLSCAN_STEP,1);
pDb->nSort = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_SORT,1);
pDb->nIndex = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_AUTOINDEX,1);
dbReleaseColumnNames(p);
p->pPreStmt = 0;
if( rcs!=SQLITE_OK ){
/* If a run-time error occurs, report the error and stop reading
** the SQL. */
dbReleaseStmt(pDb, pPreStmt, 1);
#if SQLITE_TEST
if( p->pDb->bLegacyPrepare && rcs==SQLITE_SCHEMA && zPrevSql ){
/* If the runtime error was an SQLITE_SCHEMA, and the database
** handle is configured to use the legacy sqlite3_prepare()
** interface, retry prepare()/step() on the same SQL statement.
** This only happens once. If there is a second SQLITE_SCHEMA
** error, the error will be returned to the caller. */
p->zSql = zPrevSql;
continue;
}
#endif
Tcl_SetObjResult(pDb->interp,
Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
return TCL_ERROR;
}else{
dbReleaseStmt(pDb, pPreStmt, 0);
}
}
}
/* Finished */
return TCL_BREAK;
}
/*
** Free all resources currently held by the DbEvalContext structure passed
** as the first argument. There should be exactly one call to this function
** for each call to dbEvalInit().
*/
static void dbEvalFinalize(DbEvalContext *p){
if( p->pPreStmt ){
sqlite3_reset(p->pPreStmt->pStmt);
dbReleaseStmt(p->pDb, p->pPreStmt, 0);
p->pPreStmt = 0;
}
if( p->pArray ){
Tcl_DecrRefCount(p->pArray);
p->pArray = 0;
}
Tcl_DecrRefCount(p->pSql);
dbReleaseColumnNames(p);
}
/*
** Return a pointer to a Tcl_Obj structure with ref-count 0 that contains
** the value for the iCol'th column of the row currently pointed to by
** the DbEvalContext structure passed as the first argument.
*/
static Tcl_Obj *dbEvalColumnValue(DbEvalContext *p, int iCol){
sqlite3_stmt *pStmt = p->pPreStmt->pStmt;
switch( sqlite3_column_type(pStmt, iCol) ){
case SQLITE_BLOB: {
int bytes = sqlite3_column_bytes(pStmt, iCol);
const char *zBlob = sqlite3_column_blob(pStmt, iCol);
if( !zBlob ) bytes = 0;
return Tcl_NewByteArrayObj((u8*)zBlob, bytes);
}
case SQLITE_INTEGER: {
sqlite_int64 v = sqlite3_column_int64(pStmt, iCol);
if( v>=-2147483647 && v<=2147483647 ){
return Tcl_NewIntObj((int)v);
}else{
return Tcl_NewWideIntObj(v);
}
}
case SQLITE_FLOAT: {
return Tcl_NewDoubleObj(sqlite3_column_double(pStmt, iCol));
}
case SQLITE_NULL: {
return Tcl_NewStringObj(p->pDb->zNull, -1);
}
}
return Tcl_NewStringObj((char*)sqlite3_column_text(pStmt, iCol), -1);
}
/*
** If using Tcl version 8.6 or greater, use the NR functions to avoid
** recursive evalution of scripts by the [db eval] and [db trans]
** commands. Even if the headers used while compiling the extension
** are 8.6 or newer, the code still tests the Tcl version at runtime.
** This allows stubs-enabled builds to be used with older Tcl libraries.
*/
#if TCL_MAJOR_VERSION>8 || (TCL_MAJOR_VERSION==8 && TCL_MINOR_VERSION>=6)
# define SQLITE_TCL_NRE 1
static int DbUseNre(void){
int major, minor;
Tcl_GetVersion(&major, &minor, 0, 0);
return( (major==8 && minor>=6) || major>8 );
}
#else
/*
** Compiling using headers earlier than 8.6. In this case NR cannot be
** used, so DbUseNre() to always return zero. Add #defines for the other
** Tcl_NRxxx() functions to prevent them from causing compilation errors,
** even though the only invocations of them are within conditional blocks
** of the form:
**
** if( DbUseNre() ) { ... }
*/
# define SQLITE_TCL_NRE 0
# define DbUseNre() 0
# define Tcl_NRAddCallback(a,b,c,d,e,f) 0
# define Tcl_NREvalObj(a,b,c) 0
# define Tcl_NRCreateCommand(a,b,c,d,e,f) 0
#endif
/*
** This function is part of the implementation of the command:
**
** $db eval SQL ?ARRAYNAME? SCRIPT
*/
static int DbEvalNextCmd(
ClientData data[], /* data[0] is the (DbEvalContext*) */
Tcl_Interp *interp, /* Tcl interpreter */
int result /* Result so far */
){
int rc = result; /* Return code */
/* The first element of the data[] array is a pointer to a DbEvalContext
** structure allocated using Tcl_Alloc(). The second element of data[]
** is a pointer to a Tcl_Obj containing the script to run for each row
** returned by the queries encapsulated in data[0]. */
DbEvalContext *p = (DbEvalContext *)data[0];
Tcl_Obj *pScript = (Tcl_Obj *)data[1];
Tcl_Obj *pArray = p->pArray;
while( (rc==TCL_OK || rc==TCL_CONTINUE) && TCL_OK==(rc = dbEvalStep(p)) ){
int i;
int nCol;
Tcl_Obj **apColName;
dbEvalRowInfo(p, &nCol, &apColName);
for(i=0; i<nCol; i++){
Tcl_Obj *pVal = dbEvalColumnValue(p, i);
if( pArray==0 ){
Tcl_ObjSetVar2(interp, apColName[i], 0, pVal, 0);
}else{
Tcl_ObjSetVar2(interp, pArray, apColName[i], pVal, 0);
}
}
/* The required interpreter variables are now populated with the data
** from the current row. If using NRE, schedule callbacks to evaluate
** script pScript, then to invoke this function again to fetch the next
** row (or clean up if there is no next row or the script throws an
** exception). After scheduling the callbacks, return control to the
** caller.
**
** If not using NRE, evaluate pScript directly and continue with the
** next iteration of this while(...) loop. */
if( DbUseNre() ){
Tcl_NRAddCallback(interp, DbEvalNextCmd, (void*)p, (void*)pScript, 0, 0);
return Tcl_NREvalObj(interp, pScript, 0);
}else{
rc = Tcl_EvalObjEx(interp, pScript, 0);
}
}
Tcl_DecrRefCount(pScript);
dbEvalFinalize(p);
Tcl_Free((char *)p);
if( rc==TCL_OK || rc==TCL_BREAK ){
Tcl_ResetResult(interp);
rc = TCL_OK;
}
return rc;
}
/*
** 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"
** db1 close
**
** The first command opens a connection to the "my_database" database
** and calls that connection "db1". The second command causes this
** subroutine to be invoked.
*/
static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
SqliteDb *pDb = (SqliteDb*)cd;
int choice;
int rc = TCL_OK;
static const char *DB_strs[] = {
"authorizer", "backup", "busy",
"cache", "changes", "close",
"collate", "collation_needed", "commit_hook",
"complete", "copy", "enable_load_extension",
"errorcode", "eval", "exists",
"function", "incrblob", "interrupt",
"last_insert_rowid", "nullvalue", "onecolumn",
"profile", "progress", "rekey",
"restore", "rollback_hook", "status",
"timeout", "total_changes", "trace",
"transaction", "unlock_notify", "update_hook",
"version", "wal_hook", 0
};
enum DB_enum {
DB_AUTHORIZER, DB_BACKUP, DB_BUSY,
DB_CACHE, DB_CHANGES, DB_CLOSE,
DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK,
DB_COMPLETE, DB_COPY, DB_ENABLE_LOAD_EXTENSION,
DB_ERRORCODE, DB_EVAL, DB_EXISTS,
DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT,
DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN,
DB_PROFILE, DB_PROGRESS, DB_REKEY,
DB_RESTORE, DB_ROLLBACK_HOOK, DB_STATUS,
DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK,
DB_VERSION, DB_WAL_HOOK
};
/* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
if( objc<2 ){
Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
return TCL_ERROR;
}
if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){
return TCL_ERROR;
}
switch( (enum DB_enum)choice ){
/* $db authorizer ?CALLBACK?
**
** Invoke the given callback to authorize each SQL operation as it is
** compiled. 5 arguments are appended to the callback before it is
** invoked:
**
** (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...)
** (2) First descriptive name (depends on authorization type)
** (3) Second descriptive name
** (4) Name of the database (ex: "main", "temp")
** (5) Name of trigger that is doing the access
**
** The callback should return on of the following strings: SQLITE_OK,
** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error.
**
** If this method is invoked with no arguments, the current authorization
** callback string is returned.
*/
case DB_AUTHORIZER: {
#ifdef SQLITE_OMIT_AUTHORIZATION
Tcl_AppendResult(interp, "authorization not available in this build", 0);
return TCL_ERROR;
#else
if( objc>3 ){
Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
return TCL_ERROR;
}else if( objc==2 ){
if( pDb->zAuth ){
Tcl_AppendResult(interp, pDb->zAuth, 0);
}
}else{
char *zAuth;
int len;
if( pDb->zAuth ){
Tcl_Free(pDb->zAuth);
}
zAuth = Tcl_GetStringFromObj(objv[2], &len);
if( zAuth && len>0 ){
pDb->zAuth = Tcl_Alloc( len + 1 );
memcpy(pDb->zAuth, zAuth, len+1);
}else{
pDb->zAuth = 0;
}
if( pDb->zAuth ){
pDb->interp = interp;
sqlite3_set_authorizer(pDb->db, auth_callback, pDb);
}else{
sqlite3_set_authorizer(pDb->db, 0, 0);
}
}
#endif
break;
}
/* $db backup ?DATABASE? FILENAME
**
** Open or create a database file named FILENAME. Transfer the
** content of local database DATABASE (default: "main") into the
** FILENAME database.
*/
case DB_BACKUP: {
const char *zDestFile;
const char *zSrcDb;
sqlite3 *pDest;
sqlite3_backup *pBackup;
if( objc==3 ){
zSrcDb = "main";
zDestFile = Tcl_GetString(objv[2]);
}else if( objc==4 ){
zSrcDb = Tcl_GetString(objv[2]);
zDestFile = Tcl_GetString(objv[3]);
}else{
Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
return TCL_ERROR;
}
rc = sqlite3_open(zDestFile, &pDest);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "cannot open target database: ",
sqlite3_errmsg(pDest), (char*)0);
sqlite3_close(pDest);
return TCL_ERROR;
}
pBackup = sqlite3_backup_init(pDest, "main", pDb->db, zSrcDb);
if( pBackup==0 ){
Tcl_AppendResult(interp, "backup failed: ",
sqlite3_errmsg(pDest), (char*)0);
sqlite3_close(pDest);
return TCL_ERROR;
}
while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
sqlite3_backup_finish(pBackup);
if( rc==SQLITE_DONE ){
rc = TCL_OK;
}else{
Tcl_AppendResult(interp, "backup failed: ",
sqlite3_errmsg(pDest), (char*)0);
rc = TCL_ERROR;
}
sqlite3_close(pDest);
break;
}
/* $db busy ?CALLBACK?
**
** Invoke the given callback if an SQL statement attempts to open
** a locked database file.
*/
case DB_BUSY: {
if( objc>3 ){
Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK");
return TCL_ERROR;
}else if( objc==2 ){
if( pDb->zBusy ){
Tcl_AppendResult(interp, pDb->zBusy, 0);
}
}else{
char *zBusy;
int len;
if( pDb->zBusy ){
Tcl_Free(pDb->zBusy);
}
zBusy = Tcl_GetStringFromObj(objv[2], &len);
if( zBusy && len>0 ){
pDb->zBusy = Tcl_Alloc( len + 1 );
memcpy(pDb->zBusy, zBusy, len+1);
}else{
pDb->zBusy = 0;
}
if( pDb->zBusy ){
pDb->interp = interp;
sqlite3_busy_handler(pDb->db, DbBusyHandler, pDb);
}else{
sqlite3_busy_handler(pDb->db, 0, 0);
}
}
break;
}
/* $db cache flush
** $db cache size n
**
** Flush the prepared statement cache, or set the maximum number of
** cached statements.
*/
case DB_CACHE: {
char *subCmd;
int n;
if( objc<=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "cache option ?arg?");
return TCL_ERROR;
}
subCmd = Tcl_GetStringFromObj( objv[2], 0 );
if( *subCmd=='f' && strcmp(subCmd,"flush")==0 ){
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "flush");
return TCL_ERROR;
}else{
flushStmtCache( pDb );
}
}else if( *subCmd=='s' && strcmp(subCmd,"size")==0 ){
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 2, objv, "size n");
return TCL_ERROR;
}else{
if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){
Tcl_AppendResult( interp, "cannot convert \"",
Tcl_GetStringFromObj(objv[3],0), "\" to integer", 0);
return TCL_ERROR;
}else{
if( n<0 ){
flushStmtCache( pDb );
n = 0;
}else if( n>MAX_PREPARED_STMTS ){
n = MAX_PREPARED_STMTS;
}
pDb->maxStmt = n;
}
}
}else{
Tcl_AppendResult( interp, "bad option \"",
Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size", 0);
return TCL_ERROR;
}
break;
}
/* $db changes
**
** Return the number of rows that were modified, inserted, or deleted by
** the most recent INSERT, UPDATE or DELETE statement, not including
** any changes made by trigger programs.
*/
case DB_CHANGES: {
Tcl_Obj *pResult;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 2, objv, "");
return TCL_ERROR;
}
pResult = Tcl_GetObjResult(interp);
Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db));
break;
}
/* $db close
**
** Shutdown the database
*/
case DB_CLOSE: {
Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0));
break;
}
/*
** $db collate NAME SCRIPT
**
** Create a new SQL collation function called NAME. Whenever
** that function is called, invoke SCRIPT to evaluate the function.
*/
case DB_COLLATE: {
SqlCollate *pCollate;
char *zName;
char *zScript;
int nScript;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT");
return TCL_ERROR;
}
zName = Tcl_GetStringFromObj(objv[2], 0);
zScript = Tcl_GetStringFromObj(objv[3], &nScript);
pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 );
if( pCollate==0 ) return TCL_ERROR;
pCollate->interp = interp;
pCollate->pNext = pDb->pCollate;
pCollate->zScript = (char*)&pCollate[1];
pDb->pCollate = pCollate;
memcpy(pCollate->zScript, zScript, nScript+1);
if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8,
pCollate, tclSqlCollate) ){
Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
return TCL_ERROR;
}
break;
}
/*
** $db collation_needed SCRIPT
**
** Create a new SQL collation function called NAME. Whenever
** that function is called, invoke SCRIPT to evaluate the function.
*/
case DB_COLLATION_NEEDED: {
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "SCRIPT");
return TCL_ERROR;
}
if( pDb->pCollateNeeded ){
Tcl_DecrRefCount(pDb->pCollateNeeded);
}
pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]);
Tcl_IncrRefCount(pDb->pCollateNeeded);
sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded);
break;
}
/* $db commit_hook ?CALLBACK?
**
** Invoke the given callback just before committing every SQL transaction.
** If the callback throws an exception or returns non-zero, then the
** transaction is aborted. If CALLBACK is an empty string, the callback
** is disabled.
*/
case DB_COMMIT_HOOK: {
if( objc>3 ){
Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
return TCL_ERROR;
}else if( objc==2 ){
if( pDb->zCommit ){
Tcl_AppendResult(interp, pDb->zCommit, 0);
}
}else{
char *zCommit;
int len;
if( pDb->zCommit ){
Tcl_Free(pDb->zCommit);
}
zCommit = Tcl_GetStringFromObj(objv[2], &len);
if( zCommit && len>0 ){
pDb->zCommit = Tcl_Alloc( len + 1 );
memcpy(pDb->zCommit, zCommit, len+1);
}else{
pDb->zCommit = 0;
}
if( pDb->zCommit ){
pDb->interp = interp;
sqlite3_commit_hook(pDb->db, DbCommitHandler, pDb);
}else{
sqlite3_commit_hook(pDb->db, 0, 0);
}
}
break;
}
/* $db complete SQL
**
** Return TRUE if SQL is a complete SQL statement. Return FALSE if
** additional lines of input are needed. This is similar to the
** built-in "info complete" command of Tcl.
*/
case DB_COMPLETE: {
#ifndef SQLITE_OMIT_COMPLETE
Tcl_Obj *pResult;
int isComplete;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "SQL");
return TCL_ERROR;
}
isComplete = sqlite3_complete( Tcl_GetStringFromObj(objv[2], 0) );
pResult = Tcl_GetObjResult(interp);
Tcl_SetBooleanObj(pResult, isComplete);
#endif
break;
}
/* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR?
**
** Copy data into table from filename, optionally using SEPARATOR
** as column separators. If a column contains a null string, or the
** value of NULLINDICATOR, a NULL is inserted for the column.
** conflict-algorithm is one of the sqlite conflict algorithms:
** rollback, abort, fail, ignore, replace
** On success, return the number of lines processed, not necessarily same
** as 'db changes' due to conflict-algorithm selected.
**
** This code is basically an implementation/enhancement of
** the sqlite3 shell.c ".import" command.
**
** This command usage is equivalent to the sqlite2.x COPY statement,
** which imports file data into a table using the PostgreSQL COPY file format:
** $db copy $conflit_algo $table_name $filename \t \\N
*/
case DB_COPY: {
char *zTable; /* Insert data into this table */
char *zFile; /* The file from which to extract data */
char *zConflict; /* The conflict algorithm to use */
sqlite3_stmt *pStmt; /* A statement */
int nCol; /* Number of columns in the table */
int nByte; /* Number of bytes in an SQL string */
int i, j; /* Loop counters */
int nSep; /* Number of bytes in zSep[] */
int nNull; /* Number of bytes in zNull[] */
char *zSql; /* An SQL statement */
char *zLine; /* A single line of input from the file */
char **azCol; /* zLine[] broken up into columns */
char *zCommit; /* How to commit changes */
FILE *in; /* The input file */
int lineno = 0; /* Line number of input file */
char zLineNum[80]; /* Line number print buffer */
Tcl_Obj *pResult; /* interp result */
char *zSep;
char *zNull;
if( objc<5 || objc>7 ){
Tcl_WrongNumArgs(interp, 2, objv,
"CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?");
return TCL_ERROR;
}
if( objc>=6 ){
zSep = Tcl_GetStringFromObj(objv[5], 0);
}else{
zSep = "\t";
}
if( objc>=7 ){
zNull = Tcl_GetStringFromObj(objv[6], 0);
}else{
zNull = "";
}
zConflict = Tcl_GetStringFromObj(objv[2], 0);
zTable = Tcl_GetStringFromObj(objv[3], 0);
zFile = Tcl_GetStringFromObj(objv[4], 0);
nSep = strlen30(zSep);
nNull = strlen30(zNull);
if( nSep==0 ){
Tcl_AppendResult(interp,"Error: non-null separator required for copy",0);
return TCL_ERROR;
}
if(strcmp(zConflict, "rollback") != 0 &&
strcmp(zConflict, "abort" ) != 0 &&
strcmp(zConflict, "fail" ) != 0 &&
strcmp(zConflict, "ignore" ) != 0 &&
strcmp(zConflict, "replace" ) != 0 ) {
Tcl_AppendResult(interp, "Error: \"", zConflict,
"\", conflict-algorithm must be one of: rollback, "
"abort, fail, ignore, or replace", 0);
return TCL_ERROR;
}
zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
if( zSql==0 ){
Tcl_AppendResult(interp, "Error: no such table: ", zTable, 0);
return TCL_ERROR;
}
nByte = strlen30(zSql);
rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
nCol = 0;
}else{
nCol = sqlite3_column_count(pStmt);
}
sqlite3_finalize(pStmt);
if( nCol==0 ) {
return TCL_ERROR;
}
zSql = malloc( nByte + 50 + nCol*2 );
if( zSql==0 ) {
Tcl_AppendResult(interp, "Error: can't malloc()", 0);
return TCL_ERROR;
}
sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?",
zConflict, zTable);
j = strlen30(zSql);
for(i=1; i<nCol; i++){
zSql[j++] = ',';
zSql[j++] = '?';
}
zSql[j++] = ')';
zSql[j] = 0;
rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
free(zSql);
if( rc ){
Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
sqlite3_finalize(pStmt);
return TCL_ERROR;
}
in = fopen(zFile, "rb");
if( in==0 ){
Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, NULL);
sqlite3_finalize(pStmt);
return TCL_ERROR;
}
azCol = malloc( sizeof(azCol[0])*(nCol+1) );
if( azCol==0 ) {
Tcl_AppendResult(interp, "Error: can't malloc()", 0);
fclose(in);
return TCL_ERROR;
}
(void)sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0);
zCommit = "COMMIT";
while( (zLine = local_getline(0, in))!=0 ){
char *z;
lineno++;
azCol[0] = zLine;
for(i=0, z=zLine; *z; z++){
if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){
*z = 0;
i++;
if( i<nCol ){
azCol[i] = &z[nSep];
z += nSep-1;
}
}
}
if( i+1!=nCol ){
char *zErr;
int nErr = strlen30(zFile) + 200;
zErr = malloc(nErr);
if( zErr ){
sqlite3_snprintf(nErr, zErr,
"Error: %s line %d: expected %d columns of data but found %d",
zFile, lineno, nCol, i+1);
Tcl_AppendResult(interp, zErr, 0);
free(zErr);
}
zCommit = "ROLLBACK";
break;
}
for(i=0; i<nCol; i++){
/* check for null data, if so, bind as null */
if( (nNull>0 && strcmp(azCol[i], zNull)==0)
|| strlen30(azCol[i])==0
){
sqlite3_bind_null(pStmt, i+1);
}else{
sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);
}
}
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
free(zLine);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), 0);
zCommit = "ROLLBACK";
break;
}
}
free(azCol);
fclose(in);
sqlite3_finalize(pStmt);
(void)sqlite3_exec(pDb->db, zCommit, 0, 0, 0);
if( zCommit[0] == 'C' ){
/* success, set result as number of lines processed */
pResult = Tcl_GetObjResult(interp);
Tcl_SetIntObj(pResult, lineno);
rc = TCL_OK;
}else{
/* failure, append lineno where failed */
sqlite3_snprintf(sizeof(zLineNum), zLineNum,"%d",lineno);
Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,0);
rc = TCL_ERROR;
}
break;
}
/*
** $db enable_load_extension BOOLEAN
**
** Turn the extension loading feature on or off. It if off by
** default.
*/
case DB_ENABLE_LOAD_EXTENSION: {
#ifndef SQLITE_OMIT_LOAD_EXTENSION
int onoff;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "BOOLEAN");
return TCL_ERROR;
}
if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
return TCL_ERROR;
}
sqlite3_enable_load_extension(pDb->db, onoff);
break;
#else
Tcl_AppendResult(interp, "extension loading is turned off at compile-time",
0);
return TCL_ERROR;
#endif
}
/*
** $db errorcode
**
** Return the numeric error code that was returned by the most recent
** call to sqlite3_exec().
*/
case DB_ERRORCODE: {
Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db)));
break;
}
/*
** $db exists $sql
** $db onecolumn $sql
**
** The onecolumn method is the equivalent of:
** lindex [$db eval $sql] 0
*/
case DB_EXISTS:
case DB_ONECOLUMN: {
DbEvalContext sEval;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "SQL");
return TCL_ERROR;
}
dbEvalInit(&sEval, pDb, objv[2], 0);
rc = dbEvalStep(&sEval);
if( choice==DB_ONECOLUMN ){
if( rc==TCL_OK ){
Tcl_SetObjResult(interp, dbEvalColumnValue(&sEval, 0));
}else if( rc==TCL_BREAK ){
Tcl_ResetResult(interp);
}
}else if( rc==TCL_BREAK || rc==TCL_OK ){
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc==TCL_OK));
}
dbEvalFinalize(&sEval);
if( rc==TCL_BREAK ){
rc = TCL_OK;
}
break;
}
/*
** $db eval $sql ?array? ?{ ...code... }?
**
** The SQL statement in $sql is evaluated. For each row, the values are
** placed in elements of the array named "array" and ...code... is executed.
** If "array" and "code" are omitted, then no callback is every invoked.
** If "array" is an empty string, then the values are placed in variables
** that have the same name as the fields extracted by the query.
*/
case DB_EVAL: {
if( objc<3 || objc>5 ){
Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME? ?SCRIPT?");
return TCL_ERROR;
}
if( objc==3 ){
DbEvalContext sEval;
Tcl_Obj *pRet = Tcl_NewObj();
Tcl_IncrRefCount(pRet);
dbEvalInit(&sEval, pDb, objv[2], 0);
while( TCL_OK==(rc = dbEvalStep(&sEval)) ){
int i;
int nCol;
dbEvalRowInfo(&sEval, &nCol, 0);
for(i=0; i<nCol; i++){
Tcl_ListObjAppendElement(interp, pRet, dbEvalColumnValue(&sEval, i));
}
}
dbEvalFinalize(&sEval);
if( rc==TCL_BREAK ){
Tcl_SetObjResult(interp, pRet);
rc = TCL_OK;
}
Tcl_DecrRefCount(pRet);
}else{
ClientData cd[2];
DbEvalContext *p;
Tcl_Obj *pArray = 0;
Tcl_Obj *pScript;
if( objc==5 && *(char *)Tcl_GetString(objv[3]) ){
pArray = objv[3];
}
pScript = objv[objc-1];
Tcl_IncrRefCount(pScript);
p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext));
dbEvalInit(p, pDb, objv[2], pArray);
cd[0] = (void *)p;
cd[1] = (void *)pScript;
rc = DbEvalNextCmd(cd, interp, TCL_OK);
}
break;
}
/*
** $db function NAME [-argcount N] SCRIPT
**
** Create a new SQL function called NAME. Whenever that function is
** called, invoke SCRIPT to evaluate the function.
*/
case DB_FUNCTION: {
SqlFunc *pFunc;
Tcl_Obj *pScript;
char *zName;
int nArg = -1;
if( objc==6 ){
const char *z = Tcl_GetString(objv[3]);
int n = strlen30(z);
if( n>2 && strncmp(z, "-argcount",n)==0 ){
if( Tcl_GetIntFromObj(interp, objv[4], &nArg) ) return TCL_ERROR;
if( nArg<0 ){
Tcl_AppendResult(interp, "number of arguments must be non-negative",
(char*)0);
return TCL_ERROR;
}
}
pScript = objv[5];
}else if( objc!=4 ){
Tcl_WrongNumArgs(interp, 2, objv, "NAME [-argcount N] SCRIPT");
return TCL_ERROR;
}else{
pScript = objv[3];
}
zName = Tcl_GetStringFromObj(objv[2], 0);
pFunc = findSqlFunc(pDb, zName);
if( pFunc==0 ) return TCL_ERROR;
if( pFunc->pScript ){
Tcl_DecrRefCount(pFunc->pScript);
}
pFunc->pScript = pScript;
Tcl_IncrRefCount(pScript);
pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript);
rc = sqlite3_create_function(pDb->db, zName, nArg, 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
*/
case DB_INCRBLOB: {
#ifdef SQLITE_OMIT_INCRBLOB
Tcl_AppendResult(interp, "incrblob not available in this build", 0);
return TCL_ERROR;
#else
int isReadonly = 0;
const char *zDb = "main";
const char *zTable;
const char *zColumn;
Tcl_WideInt iRow;
/* Check for the -readonly option */
if( objc>3 && strcmp(Tcl_GetString(objv[2]), "-readonly")==0 ){
isReadonly = 1;
}
if( objc!=(5+isReadonly) && objc!=(6+isReadonly) ){
Tcl_WrongNumArgs(interp, 2, objv, "?-readonly? ?DB? TABLE COLUMN ROWID");
return TCL_ERROR;
}
if( objc==(6+isReadonly) ){
zDb = Tcl_GetString(objv[2]);
}
zTable = Tcl_GetString(objv[objc-3]);
zColumn = Tcl_GetString(objv[objc-2]);
rc = Tcl_GetWideIntFromObj(interp, objv[objc-1], &iRow);
if( rc==TCL_OK ){
rc = createIncrblobChannel(
interp, pDb, zDb, zTable, zColumn, iRow, isReadonly
);
}
#endif
break;
}
/*
** $db interrupt
**
** Interrupt the execution of the inner-most SQL interpreter. This
** causes the SQL statement to return an error of SQLITE_INTERRUPT.
*/
case DB_INTERRUPT: {
sqlite3_interrupt(pDb->db);
break;
}
/*
** $db nullvalue ?STRING?
**
** Change text used when a NULL comes back from the database. If ?STRING?
** is not present, then the current string used for NULL is returned.
** If STRING is present, then STRING is returned.
**
*/
case DB_NULLVALUE: {
if( objc!=2 && objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "NULLVALUE");
return TCL_ERROR;
}
if( objc==3 ){
int len;
char *zNull = Tcl_GetStringFromObj(objv[2], &len);
if( pDb->zNull ){
Tcl_Free(pDb->zNull);
}
if( zNull && len>0 ){
pDb->zNull = Tcl_Alloc( len + 1 );
memcpy(pDb->zNull, zNull, len);
pDb->zNull[len] = '\0';
}else{
pDb->zNull = 0;
}
}
Tcl_SetObjResult(interp, Tcl_NewStringObj(pDb->zNull, -1));
break;
}
/*
** $db last_insert_rowid
**
** Return an integer which is the ROWID for the most recent insert.
*/
case DB_LAST_INSERT_ROWID: {
Tcl_Obj *pResult;
Tcl_WideInt rowid;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 2, objv, "");
return TCL_ERROR;
}
rowid = sqlite3_last_insert_rowid(pDb->db);
pResult = Tcl_GetObjResult(interp);
Tcl_SetWideIntObj(pResult, rowid);
break;
}
/*
** The DB_ONECOLUMN method is implemented together with DB_EXISTS.
*/
/* $db progress ?N CALLBACK?
**
** Invoke the given callback every N virtual machine opcodes while executing
** queries.
*/
case DB_PROGRESS: {
if( objc==2 ){
if( pDb->zProgress ){
Tcl_AppendResult(interp, pDb->zProgress, 0);
}
}else if( objc==4 ){
char *zProgress;
int len;
int N;
if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){
return TCL_ERROR;
};
if( pDb->zProgress ){
Tcl_Free(pDb->zProgress);
}
zProgress = Tcl_GetStringFromObj(objv[3], &len);
if( zProgress && len>0 ){
pDb->zProgress = Tcl_Alloc( len + 1 );
memcpy(pDb->zProgress, zProgress, len+1);
}else{
pDb->zProgress = 0;
}
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( pDb->zProgress ){
pDb->interp = interp;
sqlite3_progress_handler(pDb->db, N, DbProgressHandler, pDb);
}else{
sqlite3_progress_handler(pDb->db, 0, 0, 0);
}
#endif
}else{
Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK");
return TCL_ERROR;
}
break;
}
/* $db profile ?CALLBACK?
**
** Make arrangements to invoke the CALLBACK routine after each SQL statement
** that has run. The text of the SQL and the amount of elapse time are
** appended to CALLBACK before the script is run.
*/
case DB_PROFILE: {
if( objc>3 ){
Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
return TCL_ERROR;
}else if( objc==2 ){
if( pDb->zProfile ){
Tcl_AppendResult(interp, pDb->zProfile, 0);
}
}else{
char *zProfile;
int len;
if( pDb->zProfile ){
Tcl_Free(pDb->zProfile);
}
zProfile = Tcl_GetStringFromObj(objv[2], &len);
if( zProfile && len>0 ){
pDb->zProfile = Tcl_Alloc( len + 1 );
memcpy(pDb->zProfile, zProfile, len+1);
}else{
pDb->zProfile = 0;
}
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
if( pDb->zProfile ){
pDb->interp = interp;
sqlite3_profile(pDb->db, DbProfileHandler, pDb);
}else{
sqlite3_profile(pDb->db, 0, 0);
}
#endif
}
break;
}
/*
** $db rekey KEY
**
** Change the encryption key on the currently open database.
*/
case DB_REKEY: {
#ifdef SQLITE_HAS_CODEC
int nKey;
void *pKey;
#endif
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "KEY");
return TCL_ERROR;
}
#ifdef SQLITE_HAS_CODEC
pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
rc = sqlite3_rekey(pDb->db, pKey, nKey);
if( rc ){
Tcl_AppendResult(interp, sqlite3_errstr(rc), 0);
rc = TCL_ERROR;
}
#endif
break;
}
/* $db restore ?DATABASE? FILENAME
**
** Open a database file named FILENAME. Transfer the content
** of FILENAME into the local database DATABASE (default: "main").
*/
case DB_RESTORE: {
const char *zSrcFile;
const char *zDestDb;
sqlite3 *pSrc;
sqlite3_backup *pBackup;
int nTimeout = 0;
if( objc==3 ){
zDestDb = "main";
zSrcFile = Tcl_GetString(objv[2]);
}else if( objc==4 ){
zDestDb = Tcl_GetString(objv[2]);
zSrcFile = Tcl_GetString(objv[3]);
}else{
Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
return TCL_ERROR;
}
rc = sqlite3_open_v2(zSrcFile, &pSrc, SQLITE_OPEN_READONLY, 0);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "cannot open source database: ",
sqlite3_errmsg(pSrc), (char*)0);
sqlite3_close(pSrc);
return TCL_ERROR;
}
pBackup = sqlite3_backup_init(pDb->db, zDestDb, pSrc, "main");
if( pBackup==0 ){
Tcl_AppendResult(interp, "restore failed: ",
sqlite3_errmsg(pDb->db), (char*)0);
sqlite3_close(pSrc);
return TCL_ERROR;
}
while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
|| rc==SQLITE_BUSY ){
if( rc==SQLITE_BUSY ){
if( nTimeout++ >= 3 ) break;
sqlite3_sleep(100);
}
}
sqlite3_backup_finish(pBackup);
if( rc==SQLITE_DONE ){
rc = TCL_OK;
}else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
Tcl_AppendResult(interp, "restore failed: source database busy",
(char*)0);
rc = TCL_ERROR;
}else{
Tcl_AppendResult(interp, "restore failed: ",
sqlite3_errmsg(pDb->db), (char*)0);
rc = TCL_ERROR;
}
sqlite3_close(pSrc);
break;
}
/*
** $db status (step|sort|autoindex)
**
** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or
** SQLITE_STMTSTATUS_SORT for the most recent eval.
*/
case DB_STATUS: {
int v;
const char *zOp;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "(step|sort|autoindex)");
return TCL_ERROR;
}
zOp = Tcl_GetString(objv[2]);
if( strcmp(zOp, "step")==0 ){
v = pDb->nStep;
}else if( strcmp(zOp, "sort")==0 ){
v = pDb->nSort;
}else if( strcmp(zOp, "autoindex")==0 ){
v = pDb->nIndex;
}else{
Tcl_AppendResult(interp,
"bad argument: should be autoindex, step, or sort",
(char*)0);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(v));
break;
}
/*
** $db timeout MILLESECONDS
**
** Delay for the number of milliseconds specified when a file is locked.
*/
case DB_TIMEOUT: {
int ms;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS");
return TCL_ERROR;
}
if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR;
sqlite3_busy_timeout(pDb->db, ms);
break;
}
/*
** $db total_changes
**
** Return the number of rows that were modified, inserted, or deleted
** since the database handle was created.
*/
case DB_TOTAL_CHANGES: {
Tcl_Obj *pResult;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 2, objv, "");
return TCL_ERROR;
}
pResult = Tcl_GetObjResult(interp);
Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db));
break;
}
/* $db trace ?CALLBACK?
**
** Make arrangements to invoke the CALLBACK routine for each SQL statement
** that is executed. The text of the SQL is appended to CALLBACK before
** it is executed.
*/
case DB_TRACE: {
if( objc>3 ){
Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
return TCL_ERROR;
}else if( objc==2 ){
if( pDb->zTrace ){
Tcl_AppendResult(interp, pDb->zTrace, 0);
}
}else{
char *zTrace;
int len;
if( pDb->zTrace ){
Tcl_Free(pDb->zTrace);
}
zTrace = Tcl_GetStringFromObj(objv[2], &len);
if( zTrace && len>0 ){
pDb->zTrace = Tcl_Alloc( len + 1 );
memcpy(pDb->zTrace, zTrace, len+1);
}else{
pDb->zTrace = 0;
}
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
if( pDb->zTrace ){
pDb->interp = interp;
sqlite3_trace(pDb->db, DbTraceHandler, pDb);
}else{
sqlite3_trace(pDb->db, 0, 0);
}
#endif
}
break;
}
/* $db transaction [-deferred|-immediate|-exclusive] SCRIPT
**
** Start a new transaction (if we are not already in the midst of a
** transaction) and execute the TCL script SCRIPT. After SCRIPT
** completes, either commit the transaction or roll it back if SCRIPT
** throws an exception. Or if no new transation was started, do nothing.
** pass the exception on up the stack.
**
** This command was inspired by Dave Thomas's talk on Ruby at the
** 2005 O'Reilly Open Source Convention (OSCON).
*/
case DB_TRANSACTION: {
Tcl_Obj *pScript;
const char *zBegin = "SAVEPOINT _tcl_transaction";
if( objc!=3 && objc!=4 ){
Tcl_WrongNumArgs(interp, 2, objv, "[TYPE] SCRIPT");
return TCL_ERROR;
}
if( pDb->nTransaction==0 && objc==4 ){
static const char *TTYPE_strs[] = {
"deferred", "exclusive", "immediate", 0
};
enum TTYPE_enum {
TTYPE_DEFERRED, TTYPE_EXCLUSIVE, TTYPE_IMMEDIATE
};
int ttype;
if( Tcl_GetIndexFromObj(interp, objv[2], TTYPE_strs, "transaction type",
0, &ttype) ){
return TCL_ERROR;
}
switch( (enum TTYPE_enum)ttype ){
case TTYPE_DEFERRED: /* no-op */; break;
case TTYPE_EXCLUSIVE: zBegin = "BEGIN EXCLUSIVE"; break;
case TTYPE_IMMEDIATE: zBegin = "BEGIN IMMEDIATE"; break;
}
}
pScript = objv[objc-1];
/* Run the SQLite BEGIN command to open a transaction or savepoint. */
pDb->disableAuth++;
rc = sqlite3_exec(pDb->db, zBegin, 0, 0, 0);
pDb->disableAuth--;
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0);
return TCL_ERROR;
}
pDb->nTransaction++;
/* If using NRE, schedule a callback to invoke the script pScript, then
** a second callback to commit (or rollback) the transaction or savepoint
** opened above. If not using NRE, evaluate the script directly, then
** call function DbTransPostCmd() to commit (or rollback) the transaction
** or savepoint. */
if( DbUseNre() ){
Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0);
Tcl_NREvalObj(interp, pScript, 0);
}else{
rc = DbTransPostCmd(&cd, interp, Tcl_EvalObjEx(interp, pScript, 0));
}
break;
}
/*
** $db unlock_notify ?script?
*/
case DB_UNLOCK_NOTIFY: {
#ifndef SQLITE_ENABLE_UNLOCK_NOTIFY
Tcl_AppendResult(interp, "unlock_notify not available in this build", 0);
rc = TCL_ERROR;
#else
if( objc!=2 && objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
rc = TCL_ERROR;
}else{
void (*xNotify)(void **, int) = 0;
void *pNotifyArg = 0;
if( pDb->pUnlockNotify ){
Tcl_DecrRefCount(pDb->pUnlockNotify);
pDb->pUnlockNotify = 0;
}
if( objc==3 ){
xNotify = DbUnlockNotify;
pNotifyArg = (void *)pDb;
pDb->pUnlockNotify = objv[2];
Tcl_IncrRefCount(pDb->pUnlockNotify);
}
if( sqlite3_unlock_notify(pDb->db, xNotify, pNotifyArg) ){
Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0);
rc = TCL_ERROR;
}
}
#endif
break;
}
/*
** $db wal_hook ?script?
** $db update_hook ?script?
** $db rollback_hook ?script?
*/
case DB_WAL_HOOK:
case DB_UPDATE_HOOK:
case DB_ROLLBACK_HOOK: {
/* set ppHook to point at pUpdateHook or pRollbackHook, depending on
** whether [$db update_hook] or [$db rollback_hook] was invoked.
*/
Tcl_Obj **ppHook;
if( choice==DB_UPDATE_HOOK ){
ppHook = &pDb->pUpdateHook;
}else if( choice==DB_WAL_HOOK ){
ppHook = &pDb->pWalHook;
}else{
ppHook = &pDb->pRollbackHook;
}
if( objc!=2 && objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
return TCL_ERROR;
}
if( *ppHook ){
Tcl_SetObjResult(interp, *ppHook);
if( objc==3 ){
Tcl_DecrRefCount(*ppHook);
*ppHook = 0;
}
}
if( objc==3 ){
assert( !(*ppHook) );
if( Tcl_GetCharLength(objv[2])>0 ){
*ppHook = objv[2];
Tcl_IncrRefCount(*ppHook);
}
}
sqlite3_update_hook(pDb->db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb);
sqlite3_rollback_hook(pDb->db,(pDb->pRollbackHook?DbRollbackHandler:0),pDb);
sqlite3_wal_hook(pDb->db,(pDb->pWalHook?DbWalHandler:0),pDb);
break;
}
/* $db version
**
** Return the version string for this database.
*/
case DB_VERSION: {
Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC);
break;
}
} /* End of the SWITCH statement */
return rc;
}
#if SQLITE_TCL_NRE
/*
** Adaptor that provides an objCmd interface to the NRE-enabled
** interface implementation.
*/
static int DbObjCmdAdaptor(
void *cd,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const*objv
){
return Tcl_NRCallObjProc(interp, DbObjCmd, cd, objc, objv);
}
#endif /* SQLITE_TCL_NRE */
/*
** sqlite3 DBNAME FILENAME ?-vfs VFSNAME? ?-key KEY? ?-readonly BOOLEAN?
** ?-create BOOLEAN? ?-nomutex BOOLEAN?
**
** This is the main Tcl command. When the "sqlite" Tcl command is
** invoked, this routine runs to process that command.
**
** The first argument, DBNAME, is an arbitrary name for a new
** database connection. This command creates a new command named
** DBNAME that is used to control that connection. The database
** connection is deleted when the DBNAME command is deleted.
**
** The second argument is the name of the database file.
**
*/
static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
SqliteDb *p;
const char *zArg;
char *zErrMsg;
int i;
const char *zFile;
const char *zVfs = 0;
int flags;
Tcl_DString translatedFilename;
#ifdef SQLITE_HAS_CODEC
void *pKey = 0;
int nKey = 0;
#endif
int rc;
/* In normal use, each TCL interpreter runs in a single thread. So
** by default, we can turn of mutexing on SQLite database connections.
** However, for testing purposes it is useful to have mutexes turned
** on. So, by default, mutexes default off. But if compiled with
** SQLITE_TCL_DEFAULT_FULLMUTEX then mutexes default on.
*/
#ifdef SQLITE_TCL_DEFAULT_FULLMUTEX
flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX;
#else
flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX;
#endif
if( objc==2 ){
zArg = Tcl_GetStringFromObj(objv[1], 0);
if( strcmp(zArg,"-version")==0 ){
Tcl_AppendResult(interp,sqlite3_version,0);
return TCL_OK;
}
if( strcmp(zArg,"-has-codec")==0 ){
#ifdef SQLITE_HAS_CODEC
Tcl_AppendResult(interp,"1",0);
#else
Tcl_AppendResult(interp,"0",0);
#endif
return TCL_OK;
}
}
for(i=3; i+1<objc; i+=2){
zArg = Tcl_GetString(objv[i]);
if( strcmp(zArg,"-key")==0 ){
#ifdef SQLITE_HAS_CODEC
pKey = Tcl_GetByteArrayFromObj(objv[i+1], &nKey);
#endif
}else if( strcmp(zArg, "-vfs")==0 ){
zVfs = Tcl_GetString(objv[i+1]);
}else if( strcmp(zArg, "-readonly")==0 ){
int b;
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR;
if( b ){
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
flags |= SQLITE_OPEN_READONLY;
}else{
flags &= ~SQLITE_OPEN_READONLY;
flags |= SQLITE_OPEN_READWRITE;
}
}else if( strcmp(zArg, "-create")==0 ){
int b;
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR;
if( b && (flags & SQLITE_OPEN_READONLY)==0 ){
flags |= SQLITE_OPEN_CREATE;
}else{
flags &= ~SQLITE_OPEN_CREATE;
}
}else if( strcmp(zArg, "-nomutex")==0 ){
int b;
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR;
if( b ){
flags |= SQLITE_OPEN_NOMUTEX;
flags &= ~SQLITE_OPEN_FULLMUTEX;
}else{
flags &= ~SQLITE_OPEN_NOMUTEX;
}
}else if( strcmp(zArg, "-fullmutex")==0 ){
int b;
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR;
if( b ){
flags |= SQLITE_OPEN_FULLMUTEX;
flags &= ~SQLITE_OPEN_NOMUTEX;
}else{
flags &= ~SQLITE_OPEN_FULLMUTEX;
}
}else if( strcmp(zArg, "-uri")==0 ){
int b;
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR;
if( b ){
flags |= SQLITE_OPEN_URI;
}else{
flags &= ~SQLITE_OPEN_URI;
}
}else{
Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0);
return TCL_ERROR;
}
}
if( objc<3 || (objc&1)!=1 ){
Tcl_WrongNumArgs(interp, 1, objv,
"HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
" ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
#ifdef SQLITE_HAS_CODEC
" ?-key CODECKEY?"
#endif
);
return TCL_ERROR;
}
zErrMsg = 0;
p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
if( p==0 ){
Tcl_SetResult(interp, "malloc failed", TCL_STATIC);
return TCL_ERROR;
}
memset(p, 0, sizeof(*p));
zFile = Tcl_GetStringFromObj(objv[2], 0);
zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs);
Tcl_DStringFree(&translatedFilename);
if( p->db ){
if( SQLITE_OK!=sqlite3_errcode(p->db) ){
zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
sqlite3_close(p->db);
p->db = 0;
}
}else{
zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc));
}
#ifdef SQLITE_HAS_CODEC
if( p->db ){
sqlite3_key(p->db, pKey, nKey);
}
#endif
if( p->db==0 ){
Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
Tcl_Free((char*)p);
sqlite3_free(zErrMsg);
return TCL_ERROR;
}
p->maxStmt = NUM_PREPARED_STMTS;
p->interp = interp;
zArg = Tcl_GetStringFromObj(objv[1], 0);
if( DbUseNre() ){
Tcl_NRCreateCommand(interp, zArg, DbObjCmdAdaptor, DbObjCmd,
(char*)p, DbDeleteCmd);
}else{
Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd);
}
return TCL_OK;
}
/*
** Provide a dummy Tcl_InitStubs if we are using this as a static
** library.
*/
#ifndef USE_TCL_STUBS
# undef Tcl_InitStubs
# define Tcl_InitStubs(a,b,c)
#endif
/*
** Make sure we have a PACKAGE_VERSION macro defined. This will be
** defined automatically by the TEA makefile. But other makefiles
** do not define it.
*/
#ifndef PACKAGE_VERSION
# define PACKAGE_VERSION SQLITE_VERSION
#endif
/*
** Initialize this module.
**
** This Tcl module contains only a single new Tcl command named "sqlite".
** (Hence there is no namespace. There is no point in using a namespace
** if the extension only supplies one new name!) The "sqlite" command is
** used to open a new SQLite database. See the DbMain() routine above
** for additional information.
**
** The EXTERN macros are required by TCL in order to work on windows.
*/
EXTERN int Sqlite3_Init(Tcl_Interp *interp){
Tcl_InitStubs(interp, "8.4", 0);
Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
Tcl_PkgProvide(interp, "sqlite3", PACKAGE_VERSION);
#ifndef SQLITE_3_SUFFIX_ONLY
/* The "sqlite" alias is undocumented. It is here only to support
** legacy scripts. All new scripts should use only the "sqlite3"
** command.
*/
Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0);
#endif
return TCL_OK;
}
EXTERN int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
EXTERN int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
EXTERN int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
/* Because it accesses the file-system and uses persistent state, SQLite
** is not considered appropriate for safe interpreters. Hence, we deliberately
** omit the _SafeInit() interfaces.
*/
#ifndef SQLITE_3_SUFFIX_ONLY
int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
#endif
#ifdef TCLSH
/*****************************************************************************
** All of the code that follows is used to build standalone TCL interpreters
** that are statically linked with SQLite. Enable these by compiling
** with -DTCLSH=n where n can be 1 or 2. An n of 1 generates a standard
** tclsh but with SQLite built in. An n of 2 generates the SQLite space
** analysis program.
*/
#if defined(SQLITE_TEST) || defined(SQLITE_TCLMD5)
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
/*
* If compiled on a machine that doesn't have a 32-bit integer,
* you just set "uint32" to the appropriate datatype for an
* unsigned 32-bit integer. For example:
*
* cc -Duint32='unsigned long' md5.c
*
*/
#ifndef uint32
# define uint32 unsigned int
#endif
struct MD5Context {
int isInit;
uint32 buf[4];
uint32 bits[2];
unsigned char in[64];
};
typedef struct MD5Context MD5Context;
/*
* Note: this code is harmless on little-endian machines.
*/
static void byteReverse (unsigned char *buf, unsigned longs){
uint32 t;
do {
t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 |
((unsigned)buf[1]<<8 | buf[0]);
*(uint32 *)buf = t;
buf += 4;
} while (--longs);
}
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
static void MD5Transform(uint32 buf[4], const uint32 in[16]){
register uint32 a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
static void MD5Init(MD5Context *ctx){
ctx->isInit = 1;
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
static
void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
uint32 t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((uint32)len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if ( t ) {
unsigned char *p = (unsigned char *)ctx->in + t;
t = 64-t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *)ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *)ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
static void MD5Final(unsigned char digest[16], MD5Context *ctx){
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *)ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count-8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
((uint32 *)ctx->in)[ 14 ] = ctx->bits[0];
((uint32 *)ctx->in)[ 15 ] = ctx->bits[1];
MD5Transform(ctx->buf, (uint32 *)ctx->in);
byteReverse((unsigned char *)ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(ctx)); /* In case it is sensitive */
}
/*
** Convert a 128-bit MD5 digest into a 32-digit base-16 number.
*/
static void MD5DigestToBase16(unsigned char *digest, char *zBuf){
static char const zEncode[] = "0123456789abcdef";
int i, j;
for(j=i=0; i<16; i++){
int a = digest[i];
zBuf[j++] = zEncode[(a>>4)&0xf];
zBuf[j++] = zEncode[a & 0xf];
}
zBuf[j] = 0;
}
/*
** Convert a 128-bit MD5 digest into sequency of eight 5-digit integers
** each representing 16 bits of the digest and separated from each
** other by a "-" character.
*/
static void MD5DigestToBase10x8(unsigned char digest[16], char zDigest[50]){
int i, j;
unsigned int x;
for(i=j=0; i<16; i+=2){
x = digest[i]*256 + digest[i+1];
if( i>0 ) zDigest[j++] = '-';
sprintf(&zDigest[j], "%05u", x);
j += 5;
}
zDigest[j] = 0;
}
/*
** A TCL command for md5. The argument is the text to be hashed. The
** Result is the hash in base64.
*/
static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){
MD5Context ctx;
unsigned char digest[16];
char zBuf[50];
void (*converter)(unsigned char*, char*);
if( argc!=2 ){
Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
" TEXT\"", 0);
return TCL_ERROR;
}
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1]));
MD5Final(digest, &ctx);
converter = (void(*)(unsigned char*,char*))cd;
converter(digest, zBuf);
Tcl_AppendResult(interp, zBuf, (char*)0);
return TCL_OK;
}
/*
** A TCL command to take the md5 hash of a file. The argument is the
** name of the file.
*/
static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){
FILE *in;
MD5Context ctx;
void (*converter)(unsigned char*, char*);
unsigned char digest[16];
char zBuf[10240];
if( argc!=2 ){
Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
" FILENAME\"", 0);
return TCL_ERROR;
}
in = fopen(argv[1],"rb");
if( in==0 ){
Tcl_AppendResult(interp,"unable to open file \"", argv[1],
"\" for reading", 0);
return TCL_ERROR;
}
MD5Init(&ctx);
for(;;){
int n;
n = (int)fread(zBuf, 1, sizeof(zBuf), in);
if( n<=0 ) break;
MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
}
fclose(in);
MD5Final(digest, &ctx);
converter = (void(*)(unsigned char*,char*))cd;
converter(digest, zBuf);
Tcl_AppendResult(interp, zBuf, (char*)0);
return TCL_OK;
}
/*
** Register the four new TCL commands for generating MD5 checksums
** with the TCL interpreter.
*/
int Md5_Init(Tcl_Interp *interp){
Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd,
MD5DigestToBase16, 0);
Tcl_CreateCommand(interp, "md5-10x8", (Tcl_CmdProc*)md5_cmd,
MD5DigestToBase10x8, 0);
Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd,
MD5DigestToBase16, 0);
Tcl_CreateCommand(interp, "md5file-10x8", (Tcl_CmdProc*)md5file_cmd,
MD5DigestToBase10x8, 0);
return TCL_OK;
}
#endif /* defined(SQLITE_TEST) || defined(SQLITE_TCLMD5) */
#if defined(SQLITE_TEST)
/*
** During testing, the special md5sum() aggregate function is available.
** inside SQLite. The following routines implement that function.
*/
static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){
MD5Context *p;
int i;
if( argc<1 ) return;
p = sqlite3_aggregate_context(context, sizeof(*p));
if( p==0 ) return;
if( !p->isInit ){
MD5Init(p);
}
for(i=0; i<argc; i++){
const char *zData = (char*)sqlite3_value_text(argv[i]);
if( zData ){
MD5Update(p, (unsigned char*)zData, (int)strlen(zData));
}
}
}
static void md5finalize(sqlite3_context *context){
MD5Context *p;
unsigned char digest[16];
char zBuf[33];
p = sqlite3_aggregate_context(context, sizeof(*p));
MD5Final(digest,p);
MD5DigestToBase16(digest, zBuf);
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
int Md5_Register(sqlite3 *db){
int rc = sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0,
md5step, md5finalize);
sqlite3_overload_function(db, "md5sum", -1); /* To exercise this API */
return rc;
}
#endif /* defined(SQLITE_TEST) */
/*
** If the macro TCLSH is one, then put in code this for the
** "main" routine that will initialize Tcl and take input from
** standard input, or if a file is named on the command line
** the TCL interpreter reads and evaluates that file.
*/
#if TCLSH==1
static const char *tclsh_main_loop(void){
static const char zMainloop[] =
"set line {}\n"
"while {![eof stdin]} {\n"
"if {$line!=\"\"} {\n"
"puts -nonewline \"> \"\n"
"} else {\n"
"puts -nonewline \"% \"\n"
"}\n"
"flush stdout\n"
"append line [gets stdin]\n"
"if {[info complete $line]} {\n"
"if {[catch {uplevel #0 $line} result]} {\n"
"puts stderr \"Error: $result\"\n"
"} elseif {$result!=\"\"} {\n"
"puts $result\n"
"}\n"
"set line {}\n"
"} else {\n"
"append line \\n\n"
"}\n"
"}\n"
;
return zMainloop;
}
#endif
#if TCLSH==2
static const char *tclsh_main_loop(void);
#endif
#ifdef SQLITE_TEST
static void init_all(Tcl_Interp *);
static int init_all_cmd(
ClientData cd,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
Tcl_Interp *slave;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "SLAVE");
return TCL_ERROR;
}
slave = Tcl_GetSlave(interp, Tcl_GetString(objv[1]));
if( !slave ){
return TCL_ERROR;
}
init_all(slave);
return TCL_OK;
}
/*
** Tclcmd: db_use_legacy_prepare DB BOOLEAN
**
** The first argument to this command must be a database command created by
** [sqlite3]. If the second argument is true, then the handle is configured
** to use the sqlite3_prepare_v2() function to prepare statements. If it
** is false, sqlite3_prepare().
*/
static int db_use_legacy_prepare_cmd(
ClientData cd,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
Tcl_CmdInfo cmdInfo;
SqliteDb *pDb;
int bPrepare;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
return TCL_ERROR;
}
if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
Tcl_AppendResult(interp, "no such db: ", Tcl_GetString(objv[1]), (char*)0);
return TCL_ERROR;
}
pDb = (SqliteDb*)cmdInfo.objClientData;
if( Tcl_GetBooleanFromObj(interp, objv[2], &bPrepare) ){
return TCL_ERROR;
}
pDb->bLegacyPrepare = bPrepare;
Tcl_ResetResult(interp);
return TCL_OK;
}
#endif
/*
** Configure the interpreter passed as the first argument to have access
** to the commands and linked variables that make up:
**
** * the [sqlite3] extension itself,
**
** * If SQLITE_TCLMD5 or SQLITE_TEST is defined, the Md5 commands, and
**
** * If SQLITE_TEST is set, the various test interfaces used by the Tcl
** test suite.
*/
static void init_all(Tcl_Interp *interp){
Sqlite3_Init(interp);
#if defined(SQLITE_TEST) || defined(SQLITE_TCLMD5)
Md5_Init(interp);
#endif
/* Install the [register_dbstat_vtab] command to access the implementation
** of virtual table dbstat (source file test_stat.c). This command is
** required for testfixture and sqlite3_analyzer, but not by the production
** Tcl extension. */
#if defined(SQLITE_TEST) || TCLSH==2
{
extern int SqlitetestStat_Init(Tcl_Interp*);
SqlitetestStat_Init(interp);
}
#endif
#ifdef SQLITE_TEST
{
extern int Sqliteconfig_Init(Tcl_Interp*);
extern int Sqlitetest1_Init(Tcl_Interp*);
extern int Sqlitetest2_Init(Tcl_Interp*);
extern int Sqlitetest3_Init(Tcl_Interp*);
extern int Sqlitetest4_Init(Tcl_Interp*);
extern int Sqlitetest5_Init(Tcl_Interp*);
extern int Sqlitetest6_Init(Tcl_Interp*);
extern int Sqlitetest7_Init(Tcl_Interp*);
extern int Sqlitetest8_Init(Tcl_Interp*);
extern int Sqlitetest9_Init(Tcl_Interp*);
extern int Sqlitetestasync_Init(Tcl_Interp*);
extern int Sqlitetest_autoext_Init(Tcl_Interp*);
extern int Sqlitetest_demovfs_Init(Tcl_Interp *);
extern int Sqlitetest_func_Init(Tcl_Interp*);
extern int Sqlitetest_hexio_Init(Tcl_Interp*);
extern int Sqlitetest_init_Init(Tcl_Interp*);
extern int Sqlitetest_malloc_Init(Tcl_Interp*);
extern int Sqlitetest_mutex_Init(Tcl_Interp*);
extern int Sqlitetestschema_Init(Tcl_Interp*);
extern int Sqlitetestsse_Init(Tcl_Interp*);
extern int Sqlitetesttclvar_Init(Tcl_Interp*);
extern int SqlitetestThread_Init(Tcl_Interp*);
extern int SqlitetestOnefile_Init();
extern int SqlitetestOsinst_Init(Tcl_Interp*);
extern int Sqlitetestbackup_Init(Tcl_Interp*);
extern int Sqlitetestintarray_Init(Tcl_Interp*);
extern int Sqlitetestvfs_Init(Tcl_Interp *);
extern int Sqlitetestrtree_Init(Tcl_Interp*);
extern int Sqlitequota_Init(Tcl_Interp*);
extern int Sqlitemultiplex_Init(Tcl_Interp*);
extern int SqliteSuperlock_Init(Tcl_Interp*);
extern int SqlitetestSyscall_Init(Tcl_Interp*);
extern int Sqlitetestfuzzer_Init(Tcl_Interp*);
extern int Sqlitetestwholenumber_Init(Tcl_Interp*);
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
#endif
#ifdef SQLITE_ENABLE_ZIPVFS
extern int Zipvfs_Init(Tcl_Interp*);
Zipvfs_Init(interp);
#endif
Sqliteconfig_Init(interp);
Sqlitetest1_Init(interp);
Sqlitetest2_Init(interp);
Sqlitetest3_Init(interp);
Sqlitetest4_Init(interp);
Sqlitetest5_Init(interp);
Sqlitetest6_Init(interp);
Sqlitetest7_Init(interp);
Sqlitetest8_Init(interp);
Sqlitetest9_Init(interp);
Sqlitetestasync_Init(interp);
Sqlitetest_autoext_Init(interp);
Sqlitetest_demovfs_Init(interp);
Sqlitetest_func_Init(interp);
Sqlitetest_hexio_Init(interp);
Sqlitetest_init_Init(interp);
Sqlitetest_malloc_Init(interp);
Sqlitetest_mutex_Init(interp);
Sqlitetestschema_Init(interp);
Sqlitetesttclvar_Init(interp);
SqlitetestThread_Init(interp);
SqlitetestOnefile_Init(interp);
SqlitetestOsinst_Init(interp);
Sqlitetestbackup_Init(interp);
Sqlitetestintarray_Init(interp);
Sqlitetestvfs_Init(interp);
Sqlitetestrtree_Init(interp);
Sqlitequota_Init(interp);
Sqlitemultiplex_Init(interp);
SqliteSuperlock_Init(interp);
SqlitetestSyscall_Init(interp);
Sqlitetestfuzzer_Init(interp);
Sqlitetestwholenumber_Init(interp);
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
Sqlitetestfts3_Init(interp);
#endif
Tcl_CreateObjCommand(
interp, "load_testfixture_extensions", init_all_cmd, 0, 0
);
Tcl_CreateObjCommand(
interp, "db_use_legacy_prepare", db_use_legacy_prepare_cmd, 0, 0
);
#ifdef SQLITE_SSE
Sqlitetestsse_Init(interp);
#endif
}
#endif
}
#define TCLSH_MAIN main /* Needed to fake out mktclapp */
int TCLSH_MAIN(int argc, char **argv){
Tcl_Interp *interp;
/* Call sqlite3_shutdown() once before doing anything else. This is to
** test that sqlite3_shutdown() can be safely called by a process before
** sqlite3_initialize() is. */
sqlite3_shutdown();
Tcl_FindExecutable(argv[0]);
interp = Tcl_CreateInterp();
#if TCLSH==2
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
#endif
init_all(interp);
if( argc>=2 ){
int i;
char zArgc[32];
sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-(3-TCLSH));
Tcl_SetVar(interp,"argc", zArgc, TCL_GLOBAL_ONLY);
Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
for(i=3-TCLSH; i<argc; i++){
Tcl_SetVar(interp, "argv", argv[i],
TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
}
if( TCLSH==1 && Tcl_EvalFile(interp, argv[1])!=TCL_OK ){
const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
if( zInfo==0 ) zInfo = Tcl_GetStringResult(interp);
fprintf(stderr,"%s: %s\n", *argv, zInfo);
return 1;
}
}
if( TCLSH==2 || argc<=1 ){
Tcl_GlobalEval(interp, tclsh_main_loop());
}
return 0;
}
#endif /* TCLSH */
|
Changes to src/sqlite3.h.
| ︙ | ︙ | |||
105 106 107 108 109 110 111 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.15" #define SQLITE_VERSION_NUMBER 3007015 | | | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.15" #define SQLITE_VERSION_NUMBER 3007015 #define SQLITE_SOURCE_ID "2012-10-07 14:14:44 bbb0d189b7b6aecfc0e0b6c2bcd9f49aaea8c34a" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| ︙ | ︙ | |||
1236 1237 1238 1239 1240 1241 1242 | SQLITE_API int sqlite3_shutdown(void); SQLITE_API int sqlite3_os_init(void); SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library ** | | | | | | > > > > | | | > | > | 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 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 | SQLITE_API int sqlite3_shutdown(void); SQLITE_API int sqlite3_os_init(void); SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library ** ** The sqlite3_config() and sqlite3_reconfig() interfaces are used to make ** global configuration changes to SQLite in order to tune SQLite to the ** specific needs of the application. The default configuration is recommended ** for most applications and so this routine is usually not necessary. They ** are provided to support rare applications with unusual needs. ** ** The sqlite3_config() interface is not threadsafe. The application ** must insure that no other SQLite interfaces are invoked by other ** threads while sqlite3_config() is running. Furthermore, sqlite3_config() ** may only be invoked prior to library initialization using ** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. ** ^If sqlite3_config() is called after [sqlite3_initialize()] and before ** [sqlite3_shutdown()] then it will return SQLITE_MISUSE. ** Note, however, that ^sqlite3_config() can be called as part of the ** implementation of an application-defined [sqlite3_os_init()]. ** ** The sqlite3_reconfig() interface is threadsafe and may be called at any ** time. However, it supports only a small subset of the configuration ** options available for use with sqlite3_config(). ** ** The first argument to both sqlite3_config() and sqlite3_reconfig() is an ** integer [configuration option] that determines ** what property of SQLite is to be configured. Subsequent arguments ** vary depending on the [configuration option] ** in the first argument. ** ** ^When a configuration option is set, both sqlite3_config() and ** sqlite3_reconfig() return [SQLITE_OK]. ** ^If the option is unknown or SQLite is unable to set the option ** then these routines returns a non-zero [error code]. */ SQLITE_API int sqlite3_config(int, ...); SQLITE_API int sqlite3_reconfig(int, ...); /* ** CAPI3REF: Configure database connections ** ** The sqlite3_db_config() interface is used to make configuration ** changes to a [database connection]. The interface is similar to ** [sqlite3_config()] except that the changes apply to a single |
| ︙ | ︙ | |||
1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans ** is because some incorrectly coded legacy applications might malfunction ** malfunction when the optimization is enabled. Providing the ability to ** disable the optimization allows the older, buggy application code to work ** without change even with newer versions of SQLite. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** </dl> */ | > > > > > > > > > > > > > | 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans ** is because some incorrectly coded legacy applications might malfunction ** malfunction when the optimization is enabled. Providing the ability to ** disable the optimization allows the older, buggy application code to work ** without change even with newer versions of SQLite. ** ** [[SQLITE_CONFIG_READONLY]] <dt>SQLITE_CONFIG_READONLY ** <dd> This option takes a single argument of type int. If non-zero, then ** read-only mode for opening databases is globally enabled. If the parameter ** is zero, then read-only mode for opening databases is globally disabled. If ** read-only mode for opening databases is globally enabled, all databases ** opened by [sqlite3_open()], [sqlite3_open16()], or specified as part of ** [ATTACH] commands will be opened in read-only mode. Additionally, all calls ** to [sqlite3_open_v2()] must have the [SQLITE_OPEN_READONLY] flag set in the ** third argument; otherwise, a [SQLITE_READONLY] error will be returned. If it ** is globally disabled, [sqlite3_open()], [sqlite3_open16()], ** [sqlite3_open_v2()], and [ATTACH] commands will function normally. By ** default, read-only mode is globally disabled. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** </dl> */ |
| ︙ | ︙ | |||
1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 | #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** | > | 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 | #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ #define SQLITE_CONFIG_READONLY 21 /* int */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** |
| ︙ | ︙ |
Changes to src/th_main.c.
| ︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ** ** This file contains an interface between the TH scripting language ** (an independent project) and fossil. */ #include "config.h" #include "th_main.h" /* ** Global variable counting the number of outstanding calls to malloc() ** made by the th1 implementation. This is used to catch memory leaks ** in the interpreter. Obviously, it also means th1 is not threadsafe. */ static int nOutstandingMalloc = 0; | > > > > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ** ** This file contains an interface between the TH scripting language ** (an independent project) and fossil. */ #include "config.h" #include "th_main.h" #ifdef FOSSIL_ENABLE_TCL # include <sqlite3.h> #endif /* ** Global variable counting the number of outstanding calls to malloc() ** made by the th1 implementation. This is used to catch memory leaks ** in the interpreter. Obviously, it also means th1 is not threadsafe. */ static int nOutstandingMalloc = 0; |
| ︙ | ︙ | |||
419 420 421 422 423 424 425 426 427 428 429 430 431 432 |
}
if( openRepository ) db_find_and_open_repository(OPEN_OK_NOT_FOUND, 0);
}
Th_SetResult(interp, g.zRepositoryName, -1);
return TH_OK;
}
/*
** Make sure the interpreter has been initialized. Initialize it if
** it has not been already.
**
** The interpreter is stored in the g.interp global variable.
*/
void Th_FossilInit(void){
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 |
}
if( openRepository ) db_find_and_open_repository(OPEN_OK_NOT_FOUND, 0);
}
Th_SetResult(interp, g.zRepositoryName, -1);
return TH_OK;
}
#ifdef FOSSIL_ENABLE_TCL
static int wasReconfigured = 0;
static int Th_PreTclEval(
void *pContext,
Th_Interp *interp, /* NOT USED */
void *ctx, /* NOT USED */
int argc, /* NOT USED */
const char **argv, /* NOT USED */
int *argl, /* NOT USED */
int rc
){
#if SQLITE_VERSION_NUMBER >= 3007015
int *pbReconfigured = pContext;
if( pbReconfigured ) *pbReconfigured = 0;
if( db_get_boolean("tcl-rdonly", 1) ){
int rc2;
if ( (rc2=sqlite3_reconfig(SQLITE_CONFIG_READONLY, 1))==SQLITE_OK ){
if( pbReconfigured ) *pbReconfigured = 1;
}else{
Th_ErrorMessage(interp,
"failed to reconfigure SQLite:", sqlite3_errstr(rc2), -1);
return TH_ERROR;
}
}
#endif
return rc;
}
static int Th_PostTclEval(
void *pContext,
Th_Interp *interp, /* NOT USED */
void *ctx, /* NOT USED */
int argc, /* NOT USED */
const char **argv, /* NOT USED */
int *argl, /* NOT USED */
int rc
){
#if SQLITE_VERSION_NUMBER >= 3007015
int *pbReconfigured = pContext;
if( pbReconfigured && *pbReconfigured ){
int rc2;
if ( (rc2=sqlite3_reconfig(SQLITE_CONFIG_READONLY, 0))==SQLITE_OK ){
if( pbReconfigured ) *pbReconfigured = 0;
}else{
Th_ErrorMessage(interp,
"failed to reconfigure SQLite:", sqlite3_errstr(rc2), -1);
return TH_ERROR;
}
}
#endif
return rc;
}
#endif
/*
** Make sure the interpreter has been initialized. Initialize it if
** it has not been already.
**
** The interpreter is stored in the g.interp global variable.
*/
void Th_FossilInit(void){
|
| ︙ | ︙ | |||
452 453 454 455 456 457 458 459 460 461 462 463 464 465 |
if( g.interp==0 ){
int i;
g.interp = Th_CreateInterp(&vtab);
th_register_language(g.interp); /* Basic scripting commands. */
#ifdef FOSSIL_ENABLE_TCL
if( getenv("TH1_ENABLE_TCL")!=0 || db_get_boolean("tcl", 0) ){
g.tcl.setup = db_get("tcl-setup", 0); /* Grab optional setup script. */
th_register_tcl(g.interp, &g.tcl); /* Tcl integration commands. */
}
#endif
for(i=0; i<sizeof(aCommand)/sizeof(aCommand[0]); i++){
if ( !aCommand[i].zName || !aCommand[i].xProc ) continue;
Th_CreateCommand(g.interp, aCommand[i].zName, aCommand[i].xProc,
aCommand[i].pContext, 0);
| > > > > | 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 |
if( g.interp==0 ){
int i;
g.interp = Th_CreateInterp(&vtab);
th_register_language(g.interp); /* Basic scripting commands. */
#ifdef FOSSIL_ENABLE_TCL
if( getenv("TH1_ENABLE_TCL")!=0 || db_get_boolean("tcl", 0) ){
g.tcl.setup = db_get("tcl-setup", 0); /* Grab optional setup script. */
g.tcl.xPreEval = Th_PreTclEval;
g.tcl.pPreContext = &wasReconfigured;
g.tcl.xPostEval = Th_PostTclEval;
g.tcl.pPostContext = &wasReconfigured;
th_register_tcl(g.interp, &g.tcl); /* Tcl integration commands. */
}
#endif
for(i=0; i<sizeof(aCommand)/sizeof(aCommand[0]); i++){
if ( !aCommand[i].zName || !aCommand[i].xProc ) continue;
Th_CreateCommand(g.interp, aCommand[i].zName, aCommand[i].xProc,
aCommand[i].pContext, 0);
|
| ︙ | ︙ |
Changes to src/th_tcl.c.
| ︙ | ︙ | |||
688 689 690 691 692 693 694 695 696 697 698 699 700 701 |
if( Tcl_Init(tclInterp)!=TCL_OK ){
Th_ErrorMessage(interp,
"Tcl initialization error:", Tcl_GetStringResult(tclInterp), -1);
Tcl_DeleteInterp(tclInterp);
tclContext->interp = tclInterp = 0;
return TH_ERROR;
}
if( setTclArguments(tclInterp, argc, argv)!=TCL_OK ){
Th_ErrorMessage(interp,
"Tcl error setting arguments:", Tcl_GetStringResult(tclInterp), -1);
Tcl_DeleteInterp(tclInterp);
tclContext->interp = tclInterp = 0;
return TH_ERROR;
}
| > > > > > > > > > > > > > > > | 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 |
if( Tcl_Init(tclInterp)!=TCL_OK ){
Th_ErrorMessage(interp,
"Tcl initialization error:", Tcl_GetStringResult(tclInterp), -1);
Tcl_DeleteInterp(tclInterp);
tclContext->interp = tclInterp = 0;
return TH_ERROR;
}
#ifdef FOSSIL_ENABLE_TCL_SQLITE
/*
** Make sure the Tcl interpreter uses the SQLite package for Tcl that we
** are statically linked with rather than another one that may be present
** on the system.
*/
extern int Sqlite3_Init(Tcl_Interp *interp);
if( Sqlite3_Init(tclInterp)!=TCL_OK ){
Th_ErrorMessage(interp,
"SQLite package for Tcl error:", Tcl_GetStringResult(tclInterp), -1);
Tcl_DeleteInterp(tclInterp);
tclContext->interp = tclInterp = 0;
return TH_ERROR;
}
#endif
if( setTclArguments(tclInterp, argc, argv)!=TCL_OK ){
Th_ErrorMessage(interp,
"Tcl error setting arguments:", Tcl_GetStringResult(tclInterp), -1);
Tcl_DeleteInterp(tclInterp);
tclContext->interp = tclInterp = 0;
return TH_ERROR;
}
|
| ︙ | ︙ |
Changes to test/th1-tcl.test.
| ︙ | ︙ | |||
102 103 104 105 106 107 108 |
###############################################################################
fossil test-th-render [file nativename [file join $dir th1-tcl9.txt]]
test th1-tcl-9 {[string trim $RESULT] eq [list [file tail $fossilexe] 2 \
[list test-th-render [file nativename [file join $dir th1-tcl9.txt]]]]}
| > > > > > > > | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
###############################################################################
fossil test-th-render [file nativename [file join $dir th1-tcl9.txt]]
test th1-tcl-9 {[string trim $RESULT] eq [list [file tail $fossilexe] 2 \
[list test-th-render [file nativename [file join $dir th1-tcl9.txt]]]]}
###############################################################################
fossil test-th-render [file nativename [file join $dir th1-tclA.txt]]
test th1-tcl-A {[string trim $RESULT] eq \
"1 {attempt to write a readonly database}"}
|
Added test/th1-tclA.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
<th1>
#
# This is a "TH1 fragment" used to test the Tcl integration features of TH1.
# The corresponding test file executes this file using the test-th-render
# Fossil command.
#
# NOTE: This test requires that the SQLite package be available for the Tcl
# interpreter that is linked to the Fossil executable.
#
tclInvoke set repository_name [repository 1]
proc doOut {msg} {puts $msg; puts \n}
doOut [tclEval {
package require sqlite3
set c [catch {
sqlite3 db $repository_name
set m [clock seconds]
db eval {
INSERT INTO config (name, value, mtime)
VALUES('test-rdonly', 'no', $m);
}
db close
} x]
return [list $c $x]
}]
</th1>
|
Changes to win/Makefile.mingw.
| ︙ | ︙ | |||
49 50 51 52 53 54 55 56 57 58 59 60 61 62 | #### Enable scripting support via Tcl/Tk # # FOSSIL_ENABLE_TCL = 1 #### Load Tcl using the stubs mechanism # # FOSSIL_ENABLE_TCL_STUBS = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. # FOSSIL_TCL_SOURCE = 1 #### The directories where the zlib include and library files are located. | > > > > | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #### Enable scripting support via Tcl/Tk # # FOSSIL_ENABLE_TCL = 1 #### Load Tcl using the stubs mechanism # # FOSSIL_ENABLE_TCL_STUBS = 1 #### Provide the SQLite package to Tcl # # FOSSIL_ENABLE_TCL_SQLITE = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. # FOSSIL_TCL_SOURCE = 1 #### The directories where the zlib include and library files are located. |
| ︙ | ︙ | |||
152 153 154 155 156 157 158 159 160 161 162 163 164 165 | ifdef FOSSIL_ENABLE_TCL_STUBS TCC += -DFOSSIL_ENABLE_TCL_STUBS=1 -DUSE_TCL_STUBS RCC += -DFOSSIL_ENABLE_TCL_STUBS=1 -DUSE_TCL_STUBS else TCC += -DSTATIC_BUILD RCC += -DSTATIC_BUILD endif endif # With JSON support ifdef FOSSIL_ENABLE_JSON TCC += -DFOSSIL_ENABLE_JSON=1 RCC += -DFOSSIL_ENABLE_JSON=1 endif | > > > > > | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | ifdef FOSSIL_ENABLE_TCL_STUBS TCC += -DFOSSIL_ENABLE_TCL_STUBS=1 -DUSE_TCL_STUBS RCC += -DFOSSIL_ENABLE_TCL_STUBS=1 -DUSE_TCL_STUBS else TCC += -DSTATIC_BUILD RCC += -DSTATIC_BUILD endif # Provide the SQLite package to Tcl ifdef FOSSIL_ENABLE_TCL_SQLITE TCC += -DFOSSIL_ENABLE_TCL_SQLITE=1 -DBUILD_sqlite=1 RCC += -DFOSSIL_ENABLE_TCL_SQLITE=1 -DBUILD_sqlite=1 endif endif # With JSON support ifdef FOSSIL_ENABLE_JSON TCC += -DFOSSIL_ENABLE_JSON=1 RCC += -DFOSSIL_ENABLE_JSON=1 endif |
| ︙ | ︙ |
Changes to win/Makefile.mingw.mistachkin.
| ︙ | ︙ | |||
49 50 51 52 53 54 55 56 57 58 59 60 61 62 | #### Enable scripting support via Tcl/Tk # FOSSIL_ENABLE_TCL = 1 #### Load Tcl using the stubs mechanism # FOSSIL_ENABLE_TCL_STUBS = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. # FOSSIL_TCL_SOURCE = 1 #### The directories where the zlib include and library files are located. | > > > > | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #### Enable scripting support via Tcl/Tk # FOSSIL_ENABLE_TCL = 1 #### Load Tcl using the stubs mechanism # FOSSIL_ENABLE_TCL_STUBS = 1 #### Provide the SQLite package to Tcl # FOSSIL_ENABLE_TCL_SQLITE = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. # FOSSIL_TCL_SOURCE = 1 #### The directories where the zlib include and library files are located. |
| ︙ | ︙ | |||
152 153 154 155 156 157 158 159 160 161 162 163 164 165 | ifdef FOSSIL_ENABLE_TCL_STUBS TCC += -DFOSSIL_ENABLE_TCL_STUBS=1 -DUSE_TCL_STUBS RCC += -DFOSSIL_ENABLE_TCL_STUBS=1 -DUSE_TCL_STUBS else TCC += -DSTATIC_BUILD RCC += -DSTATIC_BUILD endif endif # With JSON support ifdef FOSSIL_ENABLE_JSON TCC += -DFOSSIL_ENABLE_JSON=1 RCC += -DFOSSIL_ENABLE_JSON=1 endif | > > > > > | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | ifdef FOSSIL_ENABLE_TCL_STUBS TCC += -DFOSSIL_ENABLE_TCL_STUBS=1 -DUSE_TCL_STUBS RCC += -DFOSSIL_ENABLE_TCL_STUBS=1 -DUSE_TCL_STUBS else TCC += -DSTATIC_BUILD RCC += -DSTATIC_BUILD endif # Provide the SQLite package to Tcl ifdef FOSSIL_ENABLE_TCL_SQLITE TCC += -DFOSSIL_ENABLE_TCL_SQLITE=1 -DBUILD_sqlite=1 RCC += -DFOSSIL_ENABLE_TCL_SQLITE=1 -DBUILD_sqlite=1 endif endif # With JSON support ifdef FOSSIL_ENABLE_JSON TCC += -DFOSSIL_ENABLE_JSON=1 RCC += -DFOSSIL_ENABLE_JSON=1 endif |
| ︙ | ︙ |
Changes to win/fossil.rc.
| ︙ | ︙ | |||
93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
#ifdef FOSSIL_ENABLE_TCL
VALUE "TclEnabled", "Yes, Tcl " TCL_PATCH_LEVEL "\0"
#ifdef FOSSIL_ENABLE_TCL_STUBS
VALUE "TclStubsEnabled", "Yes\0"
#else
VALUE "TclStubsEnabled", "No\0"
#endif
#endif
#ifdef FOSSIL_ENABLE_JSON
VALUE "JsonEnabled", "Yes, cson\0"
#endif
END
END
BLOCK "VarFileInfo"
| > > > > > | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
#ifdef FOSSIL_ENABLE_TCL
VALUE "TclEnabled", "Yes, Tcl " TCL_PATCH_LEVEL "\0"
#ifdef FOSSIL_ENABLE_TCL_STUBS
VALUE "TclStubsEnabled", "Yes\0"
#else
VALUE "TclStubsEnabled", "No\0"
#endif
#ifdef FOSSIL_ENABLE_TCL_SQLITE
VALUE "TclSqlitePackage", "Yes\0"
#else
VALUE "TclSqlitePackage", "No\0"
#endif
#endif
#ifdef FOSSIL_ENABLE_JSON
VALUE "JsonEnabled", "Yes, cson\0"
#endif
END
END
BLOCK "VarFileInfo"
|
| ︙ | ︙ |