Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch tclRdOnly Excluding Merge-Ins
This is equivalent to a diff from 1fdeece215 to a6647539f6
2013-01-07
| ||
18:58 | Improved error message handling. Fix the "fossil server" command so that it works when run as root on a repository in the root directory. check-in: baa1ebb7d9 user: drh tags: trunk | |
17:33 | Merge updates from trunk. Leaf check-in: a6647539f6 user: mistachkin tags: tclRdOnly | |
17:21 | Merge updates from trunk. Leaf check-in: 4f365f7b77 user: mistachkin tags: th1Hooks | |
17:18 | Re-sync custom MinGW makefile. check-in: 1fdeece215 user: mistachkin tags: trunk | |
15:03 | Fix "fossil revert" so that it works on files that have been renamed. check-in: 48798b2719 user: drh tags: trunk | |
2012-12-08
| ||
06:46 | Merge updates from trunk. check-in: fc7e8d01d4 user: mistachkin tags: tclRdOnly | |
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.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
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}
markdown=0 => {Build with markdown engine enabled}
}
................................................................................
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
|
>
>
>
>
|
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
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} markdown=0 => {Build with markdown engine enabled} } ................................................................................ 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/configure.c.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
{ "adunit", CONFIGSET_SKIN }, { "adunit-omit-if-admin", CONFIGSET_SKIN }, { "adunit-omit-if-user", CONFIGSET_SKIN }, { "th1-setup", CONFIGSET_ALL }, #ifdef FOSSIL_ENABLE_TCL { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER }, { "tcl-setup", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER }, #endif { "project-name", CONFIGSET_PROJ }, { "project-description", CONFIGSET_PROJ }, { "manifest", CONFIGSET_PROJ }, { "binary-glob", CONFIGSET_PROJ }, |
> |
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
{ "adunit", CONFIGSET_SKIN },
{ "adunit-omit-if-admin", CONFIGSET_SKIN },
{ "adunit-omit-if-user", CONFIGSET_SKIN },
{ "th1-setup", CONFIGSET_ALL },
#ifdef FOSSIL_ENABLE_TCL
{ "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
{ "tcl-rdonly", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
{ "tcl-setup", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
#endif
{ "project-name", CONFIGSET_PROJ },
{ "project-description", CONFIGSET_PROJ },
{ "manifest", CONFIGSET_PROJ },
{ "binary-glob", CONFIGSET_PROJ },
|
Changes to src/db.c.
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
....
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
|
{ "self-register", 0, 0, 0, "off" },
{ "ssl-ca-location",0, 40, 0, "" },
{ "ssl-identity", 0, 40, 0, "" },
{ "ssh-command", 0, 40, 0, "" },
{ "th1-setup", 0, 40, 0, "" },
#ifdef FOSSIL_ENABLE_TCL
{ "tcl", 0, 0, 0, "off" },
{ "tcl-setup", 0, 40, 0, "" },
#endif
{ "unicode-glob", 0, 40, 1, "" },
{ "web-browser", 0, 32, 0, "" },
{ "white-foreground", 0, 0, 0, "off" },
{ 0,0,0,0,0 }
};
................................................................................
**
** 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.
**
** th1-setup This is the setup script to be evaluated after creating
** and initializing the TH1 interpreter. By default, this
|
>
>
>
>
>
>
>
>
>
>
>
>
|
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
....
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
|
{ "self-register", 0, 0, 0, "off" }, { "ssl-ca-location",0, 40, 0, "" }, { "ssl-identity", 0, 40, 0, "" }, { "ssh-command", 0, 40, 0, "" }, { "th1-setup", 0, 40, 0, "" }, #ifdef FOSSIL_ENABLE_TCL { "tcl", 0, 0, 0, "off" }, { "tcl-rdonly", 0, 0, 0, "on" }, { "tcl-setup", 0, 40, 0, "" }, #endif { "unicode-glob", 0, 40, 1, "" }, { "web-browser", 0, 32, 0, "" }, { "white-foreground", 0, 0, 0, "off" }, { 0,0,0,0,0 } }; ................................................................................ ** ** 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. ** ** th1-setup This is the setup script to be evaluated after creating ** and initializing the TH1 interpreter. By default, this |
Changes to src/makemake.tcl.
391
392
393
394
395
396
397
398
399
400
401
402
403
404
...
513
514
515
516
517
518
519
520
521
522
523
524
525
526
|
#### 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
#### Check if the workaround for the MinGW command line handling needs to
................................................................................
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
|
>
>
>
>
>
>
>
>
>
|
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
...
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
|
#### 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 #### Check if the workaround for the MinGW command line handling needs to ................................................................................ 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 678 679 680 681 682 683 684 685 .... 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 1849 1850 1851 1852 1853 .... 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 .... 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 ..... 11551 11552 11553 11554 11555 11556 11557 11558 11559 11560 11561 11562 11563 11564 ..... 12568 12569 12570 12571 12572 12573 12574 12575 12576 12577 12578 12579 12580 12581 ...... 113426 113427 113428 113429 113430 113431 113432 113433 113434 113435 113436 113437 113438 113439 ...... 115156 115157 115158 115159 115160 115161 115162 115163 115164 115165 115166 115167 115168 115169 115170 ...... 115225 115226 115227 115228 115229 115230 115231 115232 115233 115234 115235 115236 115237 115238 ...... 115423 115424 115425 115426 115427 115428 115429 115430 115431 115432 115433 115434 115435 115436 115437 115438 115439 115440 115441 115442 115443 115444 115445 ...... 115458 115459 115460 115461 115462 115463 115464 115465 115466 115467 115468 115469 115470 115471 115472 ...... 137717 137718 137719 137720 137721 137722 137723 |
** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.16" #define SQLITE_VERSION_NUMBER 3007016 #define SQLITE_SOURCE_ID "2013-01-07 13:26:23 0a1207c895d9f77586a3a2a4965175909be90503" /* ** 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 ................................................................................ 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() interface is 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. It is ** 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 first argument to sqlite3_config() 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, sqlite3_config() returns [SQLITE_OK]. ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ SQLITE_API int sqlite3_config(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 ................................................................................ ** 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> ** ................................................................................ #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_SQLLOG 21 /* xSqllog, void* */ /* ** 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. ** ................................................................................ */ 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 */ ................................................................................ */ 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 */ ................................................................................ case SQLITE_CONFIG_SQLLOG: { typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int); sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t); sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *); break; } #endif default: { rc = SQLITE_ERROR; break; } } va_end(ap); ................................................................................ ** 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 */ ){ 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() */ ................................................................................ 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 ){ ................................................................................ ** 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); } 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); } #ifndef SQLITE_OMIT_UTF16 /* ** Open a new database handle. */ SQLITE_API int sqlite3_open16( ................................................................................ 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); assert( *ppDb || rc==SQLITE_NOMEM ); if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ ENC(*ppDb) = SQLITE_UTF16NATIVE; } }else{ rc = SQLITE_NOMEM; } ................................................................................ *ppModule = &icuTokenizerModule; } #endif /* defined(SQLITE_ENABLE_ICU) */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ /************** End of fts3_icu.c ********************************************/ |
| | | | | | > > > > | | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 .... 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 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 .... 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 .... 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 ..... 11571 11572 11573 11574 11575 11576 11577 11578 11579 11580 11581 11582 11583 11584 11585 ..... 12589 12590 12591 12592 12593 12594 12595 12596 12597 12598 12599 12600 12601 12602 12603 ...... 113448 113449 113450 113451 113452 113453 113454 113455 113456 113457 113458 113459 113460 113461 113462 113463 113464 113465 113466 113467 113468 113469 113470 113471 113472 113473 113474 113475 113476 113477 113478 113479 113480 113481 113482 113483 113484 113485 113486 113487 113488 113489 113490 113491 113492 113493 113494 113495 113496 113497 113498 113499 113500 ...... 115217 115218 115219 115220 115221 115222 115223 115224 115225 115226 115227 115228 115229 115230 115231 115232 ...... 115287 115288 115289 115290 115291 115292 115293 115294 115295 115296 115297 115298 115299 115300 115301 115302 115303 115304 115305 115306 115307 115308 115309 115310 ...... 115495 115496 115497 115498 115499 115500 115501 115502 115503 115504 115505 115506 115507 115508 115509 115510 115511 115512 115513 115514 115515 115516 115517 ...... 115530 115531 115532 115533 115534 115535 115536 115537 115538 115539 115540 115541 115542 115543 115544 ...... 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 140712 140713 140714 140715 140716 140717 140718 140719 140720 140721 140722 140723 140724 140725 140726 140727 140728 140729 140730 140731 140732 140733 140734 140735 140736 140737 140738 140739 140740 140741 140742 140743 140744 140745 140746 140747 140748 140749 140750 140751 140752 140753 140754 140755 140756 140757 140758 140759 140760 140761 140762 140763 140764 140765 140766 140767 140768 140769 140770 140771 140772 140773 140774 140775 140776 140777 140778 140779 140780 140781 140782 140783 140784 140785 140786 140787 140788 140789 140790 140791 140792 140793 140794 140795 140796 140797 140798 140799 140800 140801 140802 140803 140804 140805 140806 140807 140808 140809 140810 140811 140812 140813 140814 140815 140816 140817 140818 140819 140820 140821 140822 140823 140824 140825 140826 140827 140828 140829 140830 140831 140832 140833 140834 140835 140836 140837 140838 140839 140840 140841 140842 140843 140844 140845 140846 140847 140848 140849 140850 140851 140852 140853 140854 140855 140856 140857 140858 140859 140860 140861 140862 140863 140864 140865 140866 140867 140868 140869 140870 140871 140872 140873 140874 140875 140876 140877 140878 140879 140880 140881 140882 140883 140884 140885 140886 140887 140888 140889 140890 140891 140892 140893 140894 140895 140896 140897 140898 140899 140900 140901 140902 140903 140904 140905 140906 140907 140908 140909 140910 140911 140912 140913 140914 140915 140916 140917 140918 140919 140920 140921 140922 140923 140924 140925 140926 140927 140928 140929 140930 140931 140932 140933 140934 140935 140936 140937 140938 140939 140940 140941 140942 140943 140944 140945 140946 140947 140948 140949 140950 140951 140952 140953 140954 140955 140956 140957 140958 140959 140960 140961 140962 140963 140964 140965 140966 140967 140968 140969 140970 140971 140972 140973 140974 140975 140976 140977 140978 140979 140980 140981 140982 140983 140984 140985 140986 140987 140988 140989 140990 140991 140992 140993 140994 140995 140996 140997 140998 140999 141000 141001 141002 141003 141004 141005 141006 141007 141008 141009 141010 141011 141012 141013 141014 141015 141016 141017 141018 141019 141020 141021 141022 141023 141024 141025 141026 141027 141028 141029 141030 141031 141032 141033 141034 141035 141036 141037 141038 141039 141040 141041 141042 141043 141044 141045 141046 141047 141048 141049 141050 141051 141052 141053 141054 141055 141056 141057 141058 141059 141060 141061 141062 141063 141064 141065 141066 141067 141068 141069 141070 141071 141072 141073 141074 141075 141076 141077 141078 141079 141080 141081 141082 141083 141084 141085 141086 141087 141088 141089 141090 141091 141092 141093 141094 141095 141096 141097 141098 141099 141100 141101 141102 141103 141104 141105 141106 141107 141108 141109 141110 141111 141112 141113 141114 141115 141116 141117 141118 141119 141120 141121 141122 141123 141124 141125 141126 141127 141128 141129 141130 141131 141132 141133 141134 141135 141136 141137 141138 141139 141140 141141 141142 141143 141144 141145 141146 141147 141148 141149 141150 141151 141152 141153 141154 141155 141156 141157 141158 141159 141160 141161 141162 141163 141164 141165 141166 141167 141168 141169 141170 141171 141172 141173 141174 141175 141176 141177 141178 141179 141180 141181 141182 141183 141184 141185 141186 141187 141188 141189 141190 141191 141192 141193 141194 141195 141196 141197 141198 141199 141200 141201 141202 141203 141204 141205 141206 141207 141208 141209 141210 141211 141212 141213 141214 141215 141216 141217 141218 141219 141220 141221 141222 141223 141224 141225 141226 141227 141228 141229 141230 141231 141232 141233 141234 141235 141236 141237 141238 141239 141240 141241 141242 141243 141244 141245 141246 141247 141248 141249 141250 141251 141252 141253 141254 141255 141256 141257 141258 141259 141260 141261 141262 141263 141264 141265 141266 141267 141268 141269 141270 141271 141272 141273 141274 141275 141276 141277 141278 141279 141280 141281 141282 141283 141284 141285 141286 141287 141288 141289 141290 141291 141292 141293 141294 141295 141296 141297 141298 141299 141300 141301 141302 141303 141304 141305 141306 141307 141308 141309 141310 141311 141312 141313 141314 141315 141316 141317 141318 141319 141320 141321 141322 141323 141324 141325 141326 141327 141328 141329 141330 141331 141332 141333 141334 141335 141336 141337 141338 141339 141340 141341 141342 141343 141344 141345 141346 141347 141348 141349 141350 141351 141352 141353 141354 141355 141356 141357 141358 141359 141360 141361 141362 141363 141364 141365 141366 141367 141368 141369 141370 141371 141372 141373 141374 141375 141376 141377 141378 141379 141380 141381 141382 141383 141384 141385 141386 141387 141388 141389 141390 141391 141392 141393 141394 141395 141396 141397 141398 141399 141400 141401 141402 141403 141404 141405 141406 141407 141408 141409 141410 141411 141412 141413 141414 141415 141416 141417 141418 141419 141420 141421 141422 141423 141424 141425 141426 141427 141428 141429 141430 141431 141432 141433 141434 141435 141436 141437 141438 141439 141440 141441 141442 141443 141444 141445 141446 141447 141448 141449 141450 141451 141452 141453 141454 141455 141456 141457 141458 141459 141460 141461 141462 141463 141464 141465 141466 141467 141468 141469 141470 141471 141472 141473 141474 141475 141476 141477 141478 141479 141480 141481 141482 141483 141484 141485 141486 141487 141488 141489 141490 141491 141492 141493 141494 141495 141496 141497 141498 141499 141500 141501 141502 141503 141504 141505 141506 141507 141508 141509 141510 141511 141512 141513 141514 141515 141516 141517 141518 141519 141520 141521 141522 141523 141524 141525 141526 141527 141528 141529 141530 141531 141532 141533 141534 141535 141536 141537 141538 141539 141540 141541 141542 141543 141544 141545 141546 141547 141548 141549 141550 141551 141552 141553 141554 141555 141556 141557 141558 141559 141560 141561 141562 141563 141564 141565 141566 141567 141568 141569 141570 141571 141572 141573 141574 141575 141576 141577 141578 141579 141580 141581 141582 141583 141584 141585 141586 |
** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.16" #define SQLITE_VERSION_NUMBER 3007016 #define SQLITE_SOURCE_ID "2012-12-08 06:46:05 e65db42c9fdc1d6f257c8db54a46ee4fc0d7aaf0" /* ** 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 ................................................................................ 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 ................................................................................ ** 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> ** ................................................................................ #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_SQLLOG 21 /* xSqllog, void* */ #define SQLITE_CONFIG_READONLY 22 /* 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. ** ................................................................................ */ 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 */ ................................................................................ */ 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 */ ................................................................................ case SQLITE_CONFIG_SQLLOG: { typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int); sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t); sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *); break; } #endif 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); ................................................................................ ** 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() */ ................................................................................ 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 ){ ................................................................................ ** 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( ................................................................................ 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; } ................................................................................ *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*); extern int Sqlitetestregexp_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); Sqlitetestregexp_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 112 113 114 115 116 117 118 119 .... 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 1283 1284 1285 1286 1287 .... 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 .... 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 |
** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.16" #define SQLITE_VERSION_NUMBER 3007016 #define SQLITE_SOURCE_ID "2013-01-07 13:26:23 0a1207c895d9f77586a3a2a4965175909be90503" /* ** 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 ................................................................................ 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() interface is 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. It is ** 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 first argument to sqlite3_config() 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, sqlite3_config() returns [SQLITE_OK]. ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ SQLITE_API int sqlite3_config(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 ................................................................................ ** 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> ** ................................................................................ #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_SQLLOG 21 /* xSqllog, void* */ /* ** 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. ** |
| | | | | | > > > > | | | > | > > > > > > > > > > > > > > > |
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 .... 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 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 .... 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 .... 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 |
** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.16" #define SQLITE_VERSION_NUMBER 3007016 #define SQLITE_SOURCE_ID "2012-12-08 06:46:05 e65db42c9fdc1d6f257c8db54a46ee4fc0d7aaf0" /* ** 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 ................................................................................ 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 ................................................................................ ** 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> ** ................................................................................ #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_SQLLOG 21 /* xSqllog, void* */ #define SQLITE_CONFIG_READONLY 22 /* 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.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 ... 662 663 664 665 666 667 668 669 670 671 672 673 674 675 ... 714 715 716 717 718 719 720 721 722 723 724 725 726 727 |
** This file contains an interface between the TH scripting language ** (an independent project) and fossil. */ #include "config.h" #include "th_main.h" #include "sqlite3.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; ................................................................................ Th_ErrorMessage(interp, "SQL error: ", sqlite3_errmsg(g.db), -1); return TH_ERROR; } } return res; } /* ** 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(int needConfig, int forceSetup){ ................................................................................ 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) ){ if( !g.tcl.setup ){ g.tcl.setup = db_get("tcl-setup", 0); /* Grab Tcl 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); |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ... 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 ... 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 |
** This file contains an interface between the TH scripting language ** (an independent project) and fossil. */ #include "config.h" #include "th_main.h" #include "sqlite3.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; ................................................................................ Th_ErrorMessage(interp, "SQL error: ", sqlite3_errmsg(g.db), -1); return TH_ERROR; } } return res; } #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(int needConfig, int forceSetup){ ................................................................................ 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) ){ if( !g.tcl.setup ){ g.tcl.setup = db_get("tcl-setup", 0); /* Grab Tcl 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.
57
58
59
60
61
62
63
64
65
66
67
68
69
70
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
#### 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
#### Check if the workaround for the MinGW command line handling needs to
................................................................................
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
|
>
>
>
>
>
>
>
>
>
|
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
#### 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 #### Check if the workaround for the MinGW command line handling needs to ................................................................................ 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.
57
58
59
60
61
62
63
64
65
66
67
68
69
70
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
#### 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
#### Check if the workaround for the MinGW command line handling needs to
................................................................................
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
|
>
>
>
>
>
>
>
>
>
|
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
#### 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 #### Check if the workaround for the MinGW command line handling needs to ................................................................................ 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.
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 #endif #ifdef FOSSIL_ENABLE_JSON VALUE "JsonEnabled", "Yes, cson\0" #endif #ifdef FOSSIL_ENABLE_MARKDOWN VALUE "MarkdownEnabled", "Yes\0" #endif |
> > > > > |
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
#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 #ifdef FOSSIL_ENABLE_MARKDOWN VALUE "MarkdownEnabled", "Yes\0" #endif |