libgda r3232 - in trunk: . doc/C doc/C/tmpl libgda libgda/binreloc libgda/sqlite/sqlite-src libgda/sqlite/virtual po tests/data-models
- From: vivien svn gnome org
- To: svn-commits-list gnome org
- Subject: libgda r3232 - in trunk: . doc/C doc/C/tmpl libgda libgda/binreloc libgda/sqlite/sqlite-src libgda/sqlite/virtual po tests/data-models
- Date: Thu, 9 Oct 2008 18:37:46 +0000 (UTC)
Author: vivien
Date: Thu Oct 9 18:37:46 2008
New Revision: 3232
URL: http://svn.gnome.org/viewvc/libgda?rev=3232&view=rev
Log:
2008-10-09 Vivien Malerba <malerba gnome-db org>
* libgda/binreloc/Makefile.am: install gda-binreloc.h in the $prefix/libgda-4.0/libgda/
directory ao applications can use it
* libgda/binreloc/gda-binreloc.c: correctly handle specific install dir passed to the
configure script (correct fix for bug #541991, comment 2)
* libgda/sqlite/sqlite-src/: up to version 3.6.3
* libgda/information_schema.xml: added some descriptions
* libgda/gda-attributes-manager.h: added expected types description
* libgda/sqlite/virtual/gda-vprovider-data-model.c: don't use a GdaDataProxy, as it can bring some
problems when modifying the data model (errors are not reported at the correct moment)
* doc/C: doc. updates
* tests/data-models/check_virtual.c: order the expected result to avoid test failure when
comparing with expected data model
* po/: ran 'make update-po'
2008-10-09 Johannes Schmid <jhs gnome org>
* libgda/gda-data-proxy.[ch]: added class method for "filter-changed" signal, for bug #537105
Modified:
trunk/ChangeLog
trunk/NEWS
trunk/doc/C/libgda-4.0-sections.txt
trunk/doc/C/tmpl/gda-attributes-manager.sgml
trunk/libgda/binreloc/Makefile.am
trunk/libgda/binreloc/gda-binreloc.c
trunk/libgda/gda-attributes-manager.h
trunk/libgda/gda-data-proxy.c
trunk/libgda/gda-data-proxy.h
trunk/libgda/information_schema.xml
trunk/libgda/sqlite/sqlite-src/PragmasPatch
trunk/libgda/sqlite/sqlite-src/sqlite3.c
trunk/libgda/sqlite/sqlite-src/sqlite3.h
trunk/libgda/sqlite/virtual/gda-vprovider-data-model.c
trunk/po/ar.po
trunk/po/az.po
trunk/po/ca.po
trunk/po/cs.po
trunk/po/da.po
trunk/po/de.po
trunk/po/dz.po
trunk/po/el.po
trunk/po/en_CA.po
trunk/po/en_GB.po
trunk/po/es.po
trunk/po/eu.po
trunk/po/fa.po
trunk/po/fi.po
trunk/po/fr.po
trunk/po/ga.po
trunk/po/gl.po
trunk/po/hr.po
trunk/po/hu.po
trunk/po/it.po
trunk/po/ja.po
trunk/po/ko.po
trunk/po/lt.po
trunk/po/mk.po
trunk/po/ml.po
trunk/po/ms.po
trunk/po/nb.po
trunk/po/ne.po
trunk/po/nl.po
trunk/po/oc.po
trunk/po/pa.po
trunk/po/pl.po
trunk/po/pt.po
trunk/po/pt_BR.po
trunk/po/ru.po
trunk/po/rw.po
trunk/po/sk.po
trunk/po/sl.po
trunk/po/sq.po
trunk/po/sr.po
trunk/po/sr Latn po
trunk/po/sv.po
trunk/po/tr.po
trunk/po/uk.po
trunk/po/vi.po
trunk/po/zh_CN.po
trunk/po/zh_HK.po
trunk/po/zh_TW.po
trunk/tests/data-models/check_virtual.c
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Thu Oct 9 18:37:46 2008
@@ -2,6 +2,7 @@
This version includes:
- Meta data retreiving corrections
+ - now internally use SQLite 3.6.3
- A few API improvements (removed the GdaDataModelQuery object as its features are now implemented
in any result of a SELECT execution) (Massimo Cora, Vivien Malerba)
- More NR tests
@@ -10,7 +11,7 @@
- Lots of improvements to the SQL console (gda-sql-4.0)
- Lots of small bug fixes (Johannes Schmid, Vivien Malerba)
- Lots of documentation improvements
- - bug fixes: #508407, #552708, #90751, #401442
+ - bug fixes: #508407, #552708, #90751, #401442, #537159, #527002, #539754, #537105
libgda 3.99.4, 2008-09-16
Modified: trunk/doc/C/libgda-4.0-sections.txt
==============================================================================
--- trunk/doc/C/libgda-4.0-sections.txt (original)
+++ trunk/doc/C/libgda-4.0-sections.txt Thu Oct 9 18:37:46 2008
@@ -39,6 +39,7 @@
GDA_ATTRIBUTE_AUTO_INCREMENT
GDA_ATTRIBUTE_NUMERIC_PRECISION
GDA_ATTRIBUTE_NUMERIC_SCALE
+GDA_ATTRIBUTE_IS_DEFAULT
<SUBSECTION>
GdaAttributesManager
gda_attributes_manager_new
Modified: trunk/doc/C/tmpl/gda-attributes-manager.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-attributes-manager.sgml (original)
+++ trunk/doc/C/tmpl/gda-attributes-manager.sgml Thu Oct 9 18:37:46 2008
@@ -21,6 +21,9 @@
<listitem><para>the associated values are expected to be #GValue values</para></listitem>
</itemizedlist>
</para>
+<para>
+ Attibute names can be any string, but &LIBGDA; reserves some for its own usage, see below.
+</para>
<!-- ##### SECTION See_Also ##### -->
<para>
@@ -32,35 +35,42 @@
<!-- ##### MACRO GDA_ATTRIBUTE_NAME ##### -->
<para>
-
+ The corresponding attribute is the name of the object it refers to (value has a G_TYPE_STRING type).
</para>
<!-- ##### MACRO GDA_ATTRIBUTE_DESCRIPTION ##### -->
<para>
-
+ The corresponding attribute is the description of the object it refers to (value has a G_TYPE_STRING type).
</para>
<!-- ##### MACRO GDA_ATTRIBUTE_AUTO_INCREMENT ##### -->
<para>
-
+ The corresponding attribute specifies if the object it refers to is auto incremented (value has a G_TYPE_BOOLEAN type).
</para>
<!-- ##### MACRO GDA_ATTRIBUTE_NUMERIC_PRECISION ##### -->
<para>
-
+ The corresponding attribute is the number of significant digits of the object it refers to (value has a G_TYPE_INT type).
</para>
<!-- ##### MACRO GDA_ATTRIBUTE_NUMERIC_SCALE ##### -->
<para>
+ The corresponding attribute is the number of significant digits to the right of the decimal point of the object it refers to (value has a G_TYPE_INT type).
+</para>
+
+
+<!-- ##### MACRO GDA_ATTRIBUTE_IS_DEFAULT ##### -->
+<para>
+ The corresponding attribute specifies if the object it refers to has its value to default (value has a G_TYPE_BOOLEAN type).
</para>
Modified: trunk/libgda/binreloc/Makefile.am
==============================================================================
--- trunk/libgda/binreloc/Makefile.am (original)
+++ trunk/libgda/binreloc/Makefile.am Thu Oct 9 18:37:46 2008
@@ -6,12 +6,23 @@
$(LIBGDA_CFLAGS) \
$(BINRELOC_CFLAGS) \
-DLIBGDAPREFIX=\""$(prefix)"\" \
+ -DLIBGDADATA=\""$(datadir)"\" \
+ -DLIBGDALIB=\""$(libdir)"\" \
+ -DLIBGDALIBEXEC=\""$(libexecdir)"\" \
+ -DLIBGDABIN=\""$(bindir)"\" \
+ -DLIBGDASBIN=\""$(sbindir)"\" \
-DLIBGDASYSCONF=\""$(sysconfdir)"\"
noinst_LTLIBRARIES = libgda_binreloc-4.0.la
+binreloc_headers = \
+ gda-binreloc.h
+
+binrelocincludedir=$(includedir)/libgda-$(GDA_ABI_MAJOR_VERSION).$(GDA_ABI_MINOR_VERSION)/libgda
+binrelocinclude_HEADERS=$(binreloc_headers)
+
libgda_binreloc_4_0_la_SOURCES = \
gda-binreloc.c \
- gda-binreloc.h
+ $(binreloc_headers)
EXTRA_DIST = binreloc.c binreloc.h
Modified: trunk/libgda/binreloc/gda-binreloc.c
==============================================================================
--- trunk/libgda/binreloc/gda-binreloc.c (original)
+++ trunk/libgda/binreloc/gda-binreloc.c Thu Oct 9 18:37:46 2008
@@ -70,7 +70,7 @@
va_list ap;
gchar **parts;
gint size, i;
- const gchar *prefix_dir_name;
+ const gchar *prefix_dir_name = NULL;
#ifdef G_OS_WIN32
wchar_t path[MAX_PATH];
@@ -79,28 +79,50 @@
switch (where) {
default:
case GDA_NO_DIR:
- prefix_dir_name = NULL;
break;
case GDA_BIN_DIR:
- prefix_dir_name = "bin";
+ if (! g_str_has_prefix (LIBGDABIN, LIBGDAPREFIX))
+ prefix = g_strdup (LIBGDABIN);
+ else
+ prefix_dir_name = "bin";
break;
case GDA_SBIN_DIR:
- prefix_dir_name = "sbin";
+ if (! g_str_has_prefix (LIBGDASBIN, LIBGDAPREFIX))
+ prefix = g_strdup (LIBGDASBIN);
+ else
+ prefix_dir_name = "sbin";
break;
case GDA_DATA_DIR:
- prefix_dir_name = "share";
+ if (! g_str_has_prefix (LIBGDADATA, LIBGDAPREFIX))
+ prefix = g_strdup (LIBGDADATA);
+ else
+ prefix_dir_name = "share";
break;
case GDA_LOCALE_DIR:
- prefix_dir_name = "share" G_DIR_SEPARATOR_S "locale";
+ if (! g_str_has_prefix (LIBGDADATA, LIBGDAPREFIX)) {
+ prefix = g_strdup (LIBGDADATA);
+ prefix_dir_name = "locale";
+ }
+ else
+ prefix_dir_name = "share" G_DIR_SEPARATOR_S "locale";
break;
case GDA_LIB_DIR:
- prefix_dir_name = "lib";
+ if (! g_str_has_prefix (LIBGDALIB, LIBGDAPREFIX))
+ prefix = g_strdup (LIBGDALIB);
+ else
+ prefix_dir_name = "lib";
break;
case GDA_LIBEXEC_DIR:
- prefix_dir_name = "libexec";
+ if (! g_str_has_prefix (LIBGDALIBEXEC, LIBGDAPREFIX))
+ prefix = g_strdup (LIBGDALIBEXEC);
+ else
+ prefix_dir_name = "libexec";
break;
case GDA_ETC_DIR:
- prefix_dir_name = NULL;
+ if (! g_str_has_prefix (LIBGDASYSCONF, LIBGDAPREFIX))
+ prefix = g_strdup (LIBGDASYSCONF);
+ else
+ prefix_dir_name = "etc";
break;
}
@@ -109,39 +131,40 @@
#endif
- /* prefix part */
+ if (!prefix) {
+ /* prefix part for each OS */
#ifdef G_OS_WIN32
- /* Get from location of libgda DLL */
- GetModuleFileNameW (hdllmodule, path, MAX_PATH);
- prefix = g_utf16_to_utf8 (path, -1, NULL, NULL, NULL);
- if ((p = strrchr (prefix, G_DIR_SEPARATOR)) != NULL)
- *p = '\0';
-
- p = strrchr (prefix, G_DIR_SEPARATOR);
- if (p && (g_ascii_strcasecmp (p + 1, "bin") == 0 ||
- g_ascii_strcasecmp (p + 1, "lib") == 0))
- *p = '\0';
+ /* Get from location of libgda DLL */
+ GetModuleFileNameW (hdllmodule, path, MAX_PATH);
+ prefix = g_utf16_to_utf8 (path, -1, NULL, NULL, NULL);
+ if ((p = strrchr (prefix, G_DIR_SEPARATOR)) != NULL)
+ *p = '\0';
+
+ p = strrchr (prefix, G_DIR_SEPARATOR);
+ if (p && (g_ascii_strcasecmp (p + 1, "bin") == 0 ||
+ g_ascii_strcasecmp (p + 1, "lib") == 0))
+ *p = '\0';
#elif HAVE_CARBON
#define MAXLEN 500
- ProcessSerialNumber myProcess;
- FSRef bundleLocation;
- unsigned char bundlePath[MAXLEN];
-
- if ((GetCurrentProcess (&myProcess) == noErr) &&
- (GetProcessBundleLocation (&myProcess, &bundleLocation) == noErr) &&
- (FSRefMakePath (&bundleLocation, bundlePath, MAXLEN) == noErr)) {
- prefix = g_path_get_dirname ((const char*) bundlePath);
- if (g_str_has_suffix (prefix, "bin"))
- prefix [strlen (prefix) - 3] = 0;
- }
- else
- g_warning ("Could not get PREFIX (using Mac OS X Carbon)");
+ ProcessSerialNumber myProcess;
+ FSRef bundleLocation;
+ unsigned char bundlePath[MAXLEN];
+
+ if ((GetCurrentProcess (&myProcess) == noErr) &&
+ (GetProcessBundleLocation (&myProcess, &bundleLocation) == noErr) &&
+ (FSRefMakePath (&bundleLocation, bundlePath, MAXLEN) == noErr)) {
+ prefix = g_path_get_dirname ((const char*) bundlePath);
+ if (g_str_has_suffix (prefix, "bin"))
+ prefix [strlen (prefix) - 3] = 0;
+ }
+ else
+ g_warning ("Could not get PREFIX (using Mac OS X Carbon)");
#else
- if (where == GDA_ETC_DIR)
- prefix = _gda_gbr_find_prefix (LIBGDASYSCONF);
- else
- prefix = _gda_gbr_find_prefix (LIBGDAPREFIX);
+ if (!prefix)
+ prefix = _gda_gbr_find_prefix (LIBGDAPREFIX);
#endif
+ }
+
if (!prefix || !*prefix)
return NULL;
Modified: trunk/libgda/gda-attributes-manager.h
==============================================================================
--- trunk/libgda/gda-attributes-manager.h (original)
+++ trunk/libgda/gda-attributes-manager.h Thu Oct 9 18:37:46 2008
@@ -49,12 +49,12 @@
/* possible predefined attribute names for gda_holder_get_attribute() or gda_column_get_attribute() */
-#define GDA_ATTRIBUTE_DESCRIPTION "__gda_attr_descr"
-#define GDA_ATTRIBUTE_NAME "__gda_attr_name"
-#define GDA_ATTRIBUTE_NUMERIC_PRECISION "__gda_attr_numeric_precision"
-#define GDA_ATTRIBUTE_NUMERIC_SCALE "__gda_attr_numeric_scale"
-#define GDA_ATTRIBUTE_AUTO_INCREMENT "__gda_attr_autoinc"
-#define GDA_ATTRIBUTE_IS_DEFAULT "__gda_attr_is_default"
+#define GDA_ATTRIBUTE_DESCRIPTION "__gda_attr_descr" /* G_TYPE_STRING */
+#define GDA_ATTRIBUTE_NAME "__gda_attr_name" /* G_TYPE_STRING */
+#define GDA_ATTRIBUTE_NUMERIC_PRECISION "__gda_attr_numeric_precision" /* G_TYPE_INT */
+#define GDA_ATTRIBUTE_NUMERIC_SCALE "__gda_attr_numeric_scale" /* G_TYPE_INT */
+#define GDA_ATTRIBUTE_AUTO_INCREMENT "__gda_attr_autoinc" /* G_TYPE_BOOLEAN */
+#define GDA_ATTRIBUTE_IS_DEFAULT "__gda_attr_is_default" /* G_TYPE_BOOLEAN */
G_END_DECLS
Modified: trunk/libgda/gda-data-proxy.c
==============================================================================
--- trunk/libgda/gda-data-proxy.c (original)
+++ trunk/libgda/gda-data-proxy.c Thu Oct 9 18:37:46 2008
@@ -537,11 +537,11 @@
}
static void
-gda_data_proxy_class_init (GdaDataProxyClass *class)
+gda_data_proxy_class_init (GdaDataProxyClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- parent_class = g_type_class_peek_parent (class);
+ parent_class = g_type_class_peek_parent (klass);
/* signals */
gda_data_proxy_signals [ROW_DELETE_CHANGED] =
@@ -583,15 +583,16 @@
g_signal_new ("filter-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_FIRST,
- 0, /* no associated a class method */
+ G_STRUCT_OFFSET (GdaDataProxyClass, filter_changed),
NULL, NULL,
gda_marshal_VOID__VOID, G_TYPE_NONE, 0);
- class->row_delete_changed = NULL;
- class->sample_size_changed = NULL;
- class->sample_changed = NULL;
- class->validate_row_changes = m_validate_row_changes;
- class->row_changes_applied = NULL;
+ klass->row_delete_changed = NULL;
+ klass->sample_size_changed = NULL;
+ klass->sample_changed = NULL;
+ klass->validate_row_changes = m_validate_row_changes;
+ klass->row_changes_applied = NULL;
+ klass->filter_changed = NULL;
/* virtual functions */
object_class->dispose = gda_data_proxy_dispose;
Modified: trunk/libgda/gda-data-proxy.h
==============================================================================
--- trunk/libgda/gda-data-proxy.h (original)
+++ trunk/libgda/gda-data-proxy.h Thu Oct 9 18:37:46 2008
@@ -67,6 +67,8 @@
GError *(* validate_row_changes) (GdaDataProxy *proxy, gint row, gint proxied_row);
void (* row_changes_applied) (GdaDataProxy *proxy, gint row, gint proxied_row);
+
+ void (* filter_changed) (GdaDataProxy *proxy);
};
GType gda_data_proxy_get_type (void) G_GNUC_CONST;
Modified: trunk/libgda/information_schema.xml
==============================================================================
--- trunk/libgda/information_schema.xml (original)
+++ trunk/libgda/information_schema.xml Thu Oct 9 18:37:46 2008
@@ -324,8 +324,8 @@
<column name="gtype"/>
<column name="character_maximum_length" type="gint" nullok="TRUE"/>
<column name="character_octet_length" type="gint" nullok="TRUE"/>
- <column name="numeric_precision" type="gint" nullok="TRUE"/>
- <column name="numeric_scale" type="gint" nullok="TRUE"/>
+ <column name="numeric_precision" type="gint" nullok="TRUE" descr="If data_type identifies a numeric type, this column contains the precision of the type for this column (the number of significant digits)"/>
+ <column name="numeric_scale" type="gint" nullok="TRUE" descr="If data_type identifies an exact numeric type, this column contains the scale of the type for this column (the number of significant digits to the right of the decimal point)"/>
<column name="datetime_precision" type="gint" nullok="TRUE"/>
<column name="character_set_catalog" nullok="TRUE"/>
<column name="character_set_schema" nullok="TRUE"/>
Modified: trunk/libgda/sqlite/sqlite-src/PragmasPatch
==============================================================================
--- trunk/libgda/sqlite/sqlite-src/PragmasPatch (original)
+++ trunk/libgda/sqlite/sqlite-src/PragmasPatch Thu Oct 9 18:37:46 2008
@@ -1,6 +1,6 @@
---- sqlite3.c.orig 2008-08-30 18:23:34.000000000 +0200
-+++ sqlite3.c 2008-09-19 21:52:35.000000000 +0200
-@@ -66756,6 +66756,64 @@
+--- sqlite3.c.orig 2008-09-22 12:45:12.000000000 +0200
++++ sqlite3.c 2008-10-09 17:14:46.000000000 +0200
+@@ -67125,6 +67125,60 @@
#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
/*
@@ -14,11 +14,7 @@
+ ** spe_name: Specific name (unique procedure name)
+ */
+ if( sqlite3StrICmp(zLeft, "proc_list")==0 ){
-+ Hash *func_hash;
-+ HashElem *func_elem;
-+
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
-+ func_hash = &(db->aFunc);
+
+ sqlite3VdbeSetNumCols(v, 4);
+ pParse->nMem = 4;
Modified: trunk/libgda/sqlite/sqlite-src/sqlite3.c
==============================================================================
--- trunk/libgda/sqlite/sqlite-src/sqlite3.c (original)
+++ trunk/libgda/sqlite/sqlite-src/sqlite3.c Thu Oct 9 18:37:46 2008
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.6.2. By combining all the individual C code files into this
+** version 3.6.3. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a one translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -11,13 +11,13 @@
** programs, you need this file and the "sqlite3.h" header file that defines
** the programming interface to the SQLite library. (If you do not have
** the "sqlite3.h" header file at hand, you will find a copy in the first
-** 6312 lines past this header comment.) Additional code files may be
+** 6364 lines past this header comment.) Additional code files may be
** needed if you want a wrapper to interface SQLite with your choice of
** programming language. The code for the "sqlite3" command-line shell
** is also in a separate file. This file contains only code for the core
** SQLite library.
**
-** This amalgamation was generated on 2008-08-30 16:23:32 UTC.
+** This amalgamation was generated on 2008-09-22 10:45:10 UTC.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
@@ -41,7 +41,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.764 2008/08/29 18:42:30 rse Exp $
+** @(#) $Id: sqliteInt.h,v 1.772 2008/09/12 16:03:48 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -375,6 +375,16 @@
#endif
/*
+** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
+** It determines whether or not the features related to
+** SQLITE_CONFIG_MEMSTATUS are availabe by default or not. This value can
+** be overridden at runtime using the sqlite3_config() API.
+*/
+#if !defined(SQLITE_DEFAULT_MEMSTATUS)
+# define SQLITE_DEFAULT_MEMSTATUS 1
+#endif
+
+/*
** Exactly one of the following macros must be defined in order to
** specify which memory allocation subsystem to use.
**
@@ -477,7 +487,7 @@
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
-** @(#) $Id: sqlite.h.in,v 1.394 2008/08/25 21:23:02 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.398 2008/09/10 13:09:24 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
@@ -504,7 +514,7 @@
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
/* GCC added the deprecated attribute in version 3.1 */
#define SQLITE_DEPRECATED __attribute__ ((deprecated))
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) && (_MSC_VER>1200)
#define SQLITE_DEPRECATED __declspec(deprecated)
#else
#define SQLITE_DEPRECATED
@@ -517,7 +527,7 @@
/* I can confirm that it does not work on version 4.1.0... */
/* First appears in GCC docs for version 4.3.0 */
#define SQLITE_EXPERIMENTAL __attribute__ ((warning ("is experimental")))
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) && (_MSC_VER>1200)
#define SQLITE_EXPERIMENTAL __declspec(deprecated("was declared experimental"))
#else
#define SQLITE_EXPERIMENTAL
@@ -563,8 +573,8 @@
** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z
** are the major version, minor version, and release number.
*/
-#define SQLITE_VERSION "3.6.2"
-#define SQLITE_VERSION_NUMBER 3006002
+#define SQLITE_VERSION "3.6.3"
+#define SQLITE_VERSION_NUMBER 3006003
/*
** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
@@ -601,8 +611,9 @@
** CAPI3REF: Test To See If The Library Is Threadsafe {H10100} <S60100>
**
** SQLite can be compiled with or without mutexes. When
-** the [SQLITE_THREADSAFE] C preprocessor macro is true, mutexes
-** are enabled and SQLite is threadsafe. When that macro is false,
+** the [SQLITE_THREADSAFE] C preprocessor macro 1 or 2, mutexes
+** are enabled and SQLite is threadsafe. When the
+** [SQLITE_THREADSAFE] macro is 0,
** the mutexes are omitted. Without the mutexes, it is not safe
** to use SQLite concurrently from more than one thread.
**
@@ -624,12 +635,13 @@
** only the default compile-time setting, not any run-time changes
** to that setting.
**
+** See the [threading mode] documentation for additional information.
+**
** INVARIANTS:
**
** {H10101} The [sqlite3_threadsafe()] function shall return nonzero if
-** SQLite was compiled with the its mutexes enabled by default
-** or zero if SQLite was compiled such that mutexes are
-** permanently disabled.
+** and only if
+** SQLite was compiled with the its mutexes enabled by default.
**
** {H10102} The value returned by the [sqlite3_threadsafe()] function
** shall not change when mutex setting are modified at
@@ -1544,7 +1556,9 @@
** The application is responsible for serializing access to
** [database connections] and [prepared statements]. But other mutexes
** are enabled so that SQLite will be safe to use in a multi-threaded
-** environment.</dd>
+** environment as long as no two threads attempt to use the same
+** [database connection] at the same time. See the [threading mode]
+** documentation for additional information.</dd>
**
** <dt>SQLITE_CONFIG_SERIALIZED</dt>
** <dd>There are no arguments to this option. This option enables
@@ -1555,11 +1569,7 @@
** to [database connections] and [prepared statements] so that the
** application is free to use the same [database connection] or the
** same [prepared statement] in different threads at the same time.
-**
-** <p>This configuration option merely sets the default mutex
-** behavior to serialize access to [database connections]. Individual
-** [database connections] can override this setting
-** using the [SQLITE_OPEN_NOMUTEX] flag to [sqlite3_open_v2()].</p></dd>
+** See the [threading mode] documentation for additional information.</dd>
**
** <dt>SQLITE_CONFIG_MALLOC</dt>
** <dd>This option takes a single argument which is a pointer to an
@@ -2022,6 +2032,10 @@
** previously set handler. Note that calling [sqlite3_busy_timeout()]
** will also set or clear the busy handler.
**
+** The busy callback should not take any actions which modify the
+** database connection that invoked the busy handler. Any such actions
+** result in undefined behavior.
+**
** INVARIANTS:
**
** {H12311} The [sqlite3_busy_handler(D,C,A)] function shall replace
@@ -2550,6 +2564,11 @@
** previous call. Disable the authorizer by installing a NULL callback.
** The authorizer is disabled by default.
**
+** The authorizer callback must not do anything that will modify
+** the database connection that invoked the authorizer callback.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
** When [sqlite3_prepare_v2()] is used to prepare a statement, the
** statement might be reprepared during [sqlite3_step()] due to a
** schema change. Hence, the application should ensure that the
@@ -2774,7 +2793,12 @@
**
** If the progress callback returns non-zero, the operation is
** interrupted. This feature can be used to implement a
-** "Cancel" button on a GUI dialog box.
+** "Cancel" button on a GUI progress dialog box.
+**
+** The progress handler must not do anything that will modify
+** the database connection that invoked the progress handler.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
**
** INVARIANTS:
**
@@ -2837,7 +2861,7 @@
** except that it accepts two additional parameters for additional control
** over the new database connection. The flags parameter can take one of
** the following three values, optionally combined with the
-** [SQLITE_OPEN_NOMUTEX] flag:
+** [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags:
**
** <dl>
** <dt>[SQLITE_OPEN_READONLY]</dt>
@@ -2857,16 +2881,15 @@
**
** If the 3rd parameter to sqlite3_open_v2() is not one of the
** combinations shown above or one of the combinations shown above combined
-** with the [SQLITE_OPEN_NOMUTEX] flag, then the behavior is undefined.
+** with the [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags,
+** then the behavior is undefined.
**
-** If the [SQLITE_OPEN_NOMUTEX] flag is set, then mutexes on the
-** opened [database connection] are disabled and the appliation must
-** insure that access to the [database connection] and its associated
-** [prepared statements] is serialized. The [SQLITE_OPEN_NOMUTEX] flag
-** is the default behavior is SQLite is configured using the
-** [SQLITE_CONFIG_MULTITHREAD] or [SQLITE_CONFIG_SINGLETHREAD] options
-** to [sqlite3_config()]. The [SQLITE_OPEN_NOMUTEX] flag only makes a
-** difference when SQLite is in its default [SQLITE_CONFIG_SERIALIZED] mode.
+** If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
+** opens in the multi-thread [threading mode] as long as the single-thread
+** mode has not been set at compile-time or start-time. If the
+** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
+** in the serialized [threading mode] unless single-thread was
+** previously selected at compile-time or start-time.
**
** If the filename is ":memory:", then a private, temporary in-memory database
** is created for the connection. This in-memory database will vanish when
@@ -4285,7 +4308,8 @@
** characters. Any attempt to create a function with a longer name
** will result in [SQLITE_ERROR] being returned.
**
-** The third parameter is the number of arguments that the SQL function or
+** The third parameter (nArg)
+** is the number of arguments that the SQL function or
** aggregate takes. If this parameter is negative, then the SQL function or
** aggregate may take any number of arguments.
**
@@ -4316,72 +4340,91 @@
** functions with the same name but with either differing numbers of
** arguments or differing preferred text encodings. SQLite will use
** the implementation most closely matches the way in which the
-** SQL function is used.
+** SQL function is used. A function implementation with a non-negative
+** nArg parameter is a better match than a function implementation with
+** a negative nArg. A function where the preferred text encoding
+** matches the database encoding is a better
+** match than a function where the encoding is different.
+** A function where the encoding difference is between UTF16le and UTF16be
+** is a closer match than a function where the encoding difference is
+** between UTF8 and UTF16.
+**
+** Built-in functions may be overloaded by new application-defined functions.
+** The first application-defined function with a given name overrides all
+** built-in functions in the same [database connection] with the same name.
+** Subsequent application-defined functions of the same name only override
+** prior application-defined functions that are an exact match for the
+** number of parameters and preferred encoding.
+**
+** An application-defined function is permitted to call other
+** SQLite interfaces. However, such calls must not
+** close the database connection nor finalize or reset the prepared
+** statement in which the function is running.
**
** INVARIANTS:
**
-** {H16103} The [sqlite3_create_function16()] interface behaves exactly
-** like [sqlite3_create_function()] in every way except that it
-** interprets the zFunctionName argument as zero-terminated UTF-16
+** {H16103} The [sqlite3_create_function16(D,X,...)] interface shall behave
+** as [sqlite3_create_function(D,X,...)] in every way except that it
+** interprets the X argument as zero-terminated UTF-16
** native byte order instead of as zero-terminated UTF-8.
**
-** {H16106} A successful invocation of
-** the [sqlite3_create_function(D,X,N,E,...)] interface registers
+** {H16106} A successful invocation of the
+** [sqlite3_create_function(D,X,N,E,...)] interface shall register
** or replaces callback functions in the [database connection] D
** used to implement the SQL function named X with N parameters
** and having a preferred text encoding of E.
**
** {H16109} A successful call to [sqlite3_create_function(D,X,N,E,P,F,S,L)]
-** replaces the P, F, S, and L values from any prior calls with
+** shall replace the P, F, S, and L values from any prior calls with
** the same D, X, N, and E values.
**
-** {H16112} The [sqlite3_create_function(D,X,...)] interface fails with
-** a return code of [SQLITE_ERROR] if the SQL function name X is
+** {H16112} The [sqlite3_create_function(D,X,...)] interface shall fail
+** if the SQL function name X is
** longer than 255 bytes exclusive of the zero terminator.
**
-** {H16118} Either F must be NULL and S and L are non-NULL or else F
-** is non-NULL and S and L are NULL, otherwise
-** [sqlite3_create_function(D,X,N,E,P,F,S,L)] returns [SQLITE_ERROR].
+** {H16118} The [sqlite3_create_function(D,X,N,E,P,F,S,L)] interface
+** shall fail unless either F is NULL and S and L are non-NULL or
+*** F is non-NULL and S and L are NULL.
**
-** {H16121} The [sqlite3_create_function(D,...)] interface fails with an
+** {H16121} The [sqlite3_create_function(D,...)] interface shall fails with an
** error code of [SQLITE_BUSY] if there exist [prepared statements]
** associated with the [database connection] D.
**
-** {H16124} The [sqlite3_create_function(D,X,N,...)] interface fails with an
-** error code of [SQLITE_ERROR] if parameter N (specifying the number
-** of arguments to the SQL function being registered) is less
+** {H16124} The [sqlite3_create_function(D,X,N,...)] interface shall fail with
+** an error code of [SQLITE_ERROR] if parameter N is less
** than -1 or greater than 127.
**
** {H16127} When N is non-negative, the [sqlite3_create_function(D,X,N,...)]
-** interface causes callbacks to be invoked for the SQL function
+** interface shall register callbacks to be invoked for the
+** SQL function
** named X when the number of arguments to the SQL function is
** exactly N.
**
** {H16130} When N is -1, the [sqlite3_create_function(D,X,N,...)]
-** interface causes callbacks to be invoked for the SQL function
-** named X with any number of arguments.
+** interface shall register callbacks to be invoked for the SQL
+** function named X with any number of arguments.
**
** {H16133} When calls to [sqlite3_create_function(D,X,N,...)]
** specify multiple implementations of the same function X
** and when one implementation has N>=0 and the other has N=(-1)
-** the implementation with a non-zero N is preferred.
+** the implementation with a non-zero N shall be preferred.
**
** {H16136} When calls to [sqlite3_create_function(D,X,N,E,...)]
** specify multiple implementations of the same function X with
** the same number of arguments N but with different
** encodings E, then the implementation where E matches the
-** database encoding is preferred.
+** database encoding shall preferred.
**
** {H16139} For an aggregate SQL function created using
** [sqlite3_create_function(D,X,N,E,P,0,S,L)] the finalizer
-** function L will always be invoked exactly once if the
+** function L shall always be invoked exactly once if the
** step function S is called one or more times.
**
** {H16142} When SQLite invokes either the xFunc or xStep function of
** an application-defined SQL function or aggregate created
** by [sqlite3_create_function()] or [sqlite3_create_function16()],
** then the array of [sqlite3_value] objects passed as the
-** third parameter are always [protected sqlite3_value] objects.
+** third parameter shall be [protected sqlite3_value] objects.
*/
SQLITE_API int sqlite3_create_function(
sqlite3 *db,
@@ -5293,6 +5336,14 @@
** If another function was previously registered, its
** pArg value is returned. Otherwise NULL is returned.
**
+** The callback implementation must not do anything that will modify
+** the database connection that invoked the callback. Any actions
+** to modify the database connection must be deferred until after the
+** completion of the [sqlite3_step()] call that triggered the commit
+** or rollback hook in the first place.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
** Registering a NULL function disables the callback.
**
** For the purposes of this API, a transaction is said to have been
@@ -5367,6 +5418,13 @@
** The update hook is not invoked when internal system tables are
** modified (i.e. sqlite_master and sqlite_sequence).
**
+** The update hook implementation must not do anything that will modify
+** the database connection that invoked the update hook. Any actions
+** to modify the database connection must be deferred until after the
+** completion of the [sqlite3_step()] call that triggered the update hook.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
** If another function was previously registered, its pArg value
** is returned. Otherwise NULL is returned.
**
@@ -6644,6 +6702,10 @@
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+
+SQLITE_API int sqlite3_wsd_init(int N, int J);
+SQLITE_API void *sqlite3_wsd_find(void *K, int L);
+
/*
** CAPI3REF: Status Parameters {H17250} <H17200>
** EXPERIMENTAL
@@ -7244,6 +7306,30 @@
#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3DbFree)
/*
+** When SQLITE_OMIT_WSD is defined, it means that the target platform does
+** not support Writable Static Data (WSD) such as global and static variables.
+** All variables must either be on the stack or dynamically allocated from
+** the heap. When WSD is unsupported, the variable declarations scattered
+** throughout the SQLite code must become constants instead. The SQLITE_WSD
+** macro is used for this purpose. And instead of referencing the variable
+** directly, we use its constant as a key to lookup the run-time allocated
+** buffer that holds real variable. The constant is also the initializer
+** for the run-time allocated buffer.
+**
+** In the usually case where WSD is supported, the SQLITE_WSD and GLOBAL
+** macros become no-ops and have zero performance impact.
+*/
+#ifdef SQLITE_OMIT_WSD
+ #define SQLITE_WSD const
+ #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v)))
+ #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config)
+#else
+ #define SQLITE_WSD
+ #define GLOBAL(t,v) v
+ #define sqlite3GlobalConfig sqlite3Config
+#endif
+
+/*
** Forward references to structures
*/
typedef struct AggInfo AggInfo;
@@ -7922,7 +8008,7 @@
** subsystem. The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
-** @(#) $Id: pager.h,v 1.81 2008/08/27 15:16:34 danielk1977 Exp $
+** @(#) $Id: pager.h,v 1.83 2008/09/18 17:34:44 danielk1977 Exp $
*/
#ifndef _PAGER_H_
@@ -7981,7 +8067,7 @@
*/
SQLITE_PRIVATE int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, void(*)(DbPage*), int,int,int);
SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler);
-SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int));
+SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*));
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u16*);
SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
@@ -8021,7 +8107,6 @@
SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager);
-SQLITE_PRIVATE void sqlite3PagerAlwaysRollback(Pager *pPager);
#ifdef SQLITE_HAS_CODEC
SQLITE_PRIVATE void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
@@ -8066,7 +8151,7 @@
** This header file defines the interface that the sqlite page cache
** subsystem.
**
-** @(#) $Id: pcache.h,v 1.9 2008/08/29 09:10:03 danielk1977 Exp $
+** @(#) $Id: pcache.h,v 1.11 2008/09/18 17:34:44 danielk1977 Exp $
*/
#ifndef _PCACHE_H_
@@ -8107,13 +8192,12 @@
/* Bit values for PgHdr.flags */
#define PGHDR_IN_JOURNAL 0x001 /* Page is in rollback journal */
-#define PGHDR_IN_STMTJRNL 0x002 /* Page is in the statement journal */
-#define PGHDR_DIRTY 0x004 /* Page has changed */
-#define PGHDR_NEED_SYNC 0x008 /* Peed to fsync this page */
-#define PGHDR_NEED_READ 0x020 /* Content is unread */
-#define PGHDR_IS_INIT 0x040 /* pData is initialized */
-#define PGHDR_REUSE_UNLIKELY 0x080 /* Hint: Reuse is unlikely */
-#define PGHDR_DONT_WRITE 0x100 /* Do not write content to disk */
+#define PGHDR_DIRTY 0x002 /* Page has changed */
+#define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before
+ ** writing this page to the database */
+#define PGHDR_NEED_READ 0x008 /* Content is unread */
+#define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */
+#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */
/* Initialize and shutdown the page cache subsystem */
SQLITE_PRIVATE int sqlite3PcacheInitialize(void);
@@ -8168,7 +8252,7 @@
/* Routines used to implement transactions on memory-only databases. */
SQLITE_PRIVATE int sqlite3PcachePreserve(PgHdr*, int); /* Preserve current page content */
SQLITE_PRIVATE void sqlite3PcacheCommit(PCache*, int); /* Drop preserved copy */
-SQLITE_PRIVATE void sqlite3PcacheRollback(PCache*, int); /* Rollback to preserved copy */
+SQLITE_PRIVATE void sqlite3PcacheRollback(PCache*, int, void (*xReiniter)(PgHdr*));
/* Get a list of all dirty pages in the cache, sorted by page number */
SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*);
@@ -8176,11 +8260,15 @@
/* Reset and close the cache object */
SQLITE_PRIVATE void sqlite3PcacheClose(PCache*);
-/* Set flags on all pages in the page cache */
-SQLITE_PRIVATE void sqlite3PcacheSetFlags(PCache*, int andMask, int orMask);
+/* Clear flags from pages of the page cache */
+SQLITE_PRIVATE void sqlite3PcacheClearFlags(PCache*, int mask);
/* Assert flags settings on all pages. Debugging only */
-SQLITE_PRIVATE void sqlite3PcacheAssertFlags(PCache*, int trueMask, int falseMask);
+#ifndef NDEBUG
+SQLITE_PRIVATE void sqlite3PcacheAssertFlags(PCache*, int trueMask, int falseMask);
+#else
+# define sqlite3PcacheAssertFlags(A,B,C)
+#endif
/* Return true if the number of dirty pages is 0 or 1 */
SQLITE_PRIVATE int sqlite3PcacheZeroOrOneDirtyPages(PCache*);
@@ -8780,7 +8868,7 @@
char *zErrMsg; /* Most recent error message (UTF-8 encoded) */
char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */
union {
- int isInterrupted; /* True if sqlite3_interrupt has been called */
+ volatile int isInterrupted; /* True if sqlite3_interrupt has been called */
double notUsed1; /* Spacer */
} u1;
Lookaside lookaside; /* Lookaside malloc configuration */
@@ -9084,6 +9172,7 @@
char **azModuleArg; /* Text of all module args. [0] is module name */
#endif
Schema *pSchema; /* Schema that contains this table */
+ Table *pNextZombie; /* Next on the Parse.pZombieTab list */
};
/*
@@ -9802,6 +9891,7 @@
Table **apVtabLock; /* Pointer to virtual tables needing locking */
#endif
int nHeight; /* Expression tree height of current sub-select */
+ Table *pZombieTab; /* List of Table objects to delete after code gen */
};
#ifdef SQLITE_OMIT_VIRTUALTABLE
@@ -10024,11 +10114,13 @@
int szPage; /* Size of each page in pPage[] */
int nPage; /* Number of pages in pPage[] */
int isInit; /* True after initialization has finished */
+ int inProgress; /* True while initialization in progress */
int isMallocInit; /* True after malloc is initialized */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
int nRefInitMutex; /* Number of users of pInitMutex */
int nSmall; /* alloc size threshold used by mem6.c */
int mxParserStack; /* maximum depth of the parser stack */
+ int sharedCacheEnabled; /* true if shared-cache mode enabled */
};
/*
@@ -10114,6 +10206,7 @@
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys6(void);
SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
+SQLITE_PRIVATE int sqlite3MemoryAlarm(void (*)(void*, sqlite3_int64, int), void*, sqlite3_int64);
#ifndef SQLITE_MUTEX_NOOP
SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void);
@@ -10291,7 +10384,10 @@
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*);
SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int);
+
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
+#endif
#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
@@ -10416,8 +10512,8 @@
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
-SQLITE_PRIVATE struct Sqlite3Config sqlite3Config;
-SQLITE_PRIVATE FuncDefHash sqlite3GlobalFunctions;
+SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config;
+SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
#endif
SQLITE_PRIVATE void sqlite3RootPageMoved(Db*, int, int);
SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
@@ -10512,6 +10608,7 @@
SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *);
SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
+SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
@@ -10602,7 +10699,7 @@
**
** This file contains definitions of global variables and contants.
**
-** $Id: global.c,v 1.6 2008/08/21 20:21:35 drh Exp $
+** $Id: global.c,v 1.8 2008/09/04 17:17:39 danielk1977 Exp $
*/
@@ -10655,13 +10752,13 @@
** The following singleton contains the global configuration for
** the SQLite library.
*/
-SQLITE_PRIVATE struct Sqlite3Config sqlite3Config = {
- 1, /* bMemstat */
- 1, /* bCoreMutex */
- 1, /* bFullMutex */
- 0x7ffffffe, /* mxStrlen */
- 100, /* szLookaside */
- 500, /* nLookaside */
+SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
+ SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
+ 1, /* bCoreMutex */
+ SQLITE_THREADSAFE==1, /* bFullMutex */
+ 0x7ffffffe, /* mxStrlen */
+ 100, /* szLookaside */
+ 500, /* nLookaside */
/* Other fields all default to zero */
};
@@ -10671,7 +10768,7 @@
** database connections. After initialization, this table is
** read-only.
*/
-SQLITE_PRIVATE FuncDefHash sqlite3GlobalFunctions;
+SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
/************** End of global.c **********************************************/
/************** Begin file status.c ******************************************/
@@ -10690,24 +10787,40 @@
** This module implements the sqlite3_status() interface and related
** functionality.
**
-** $Id: status.c,v 1.8 2008/08/12 15:21:12 drh Exp $
+** $Id: status.c,v 1.9 2008/09/02 00:52:52 drh Exp $
*/
/*
** Variables in which to record status information.
*/
-static struct {
+typedef struct sqlite3StatType sqlite3StatType;
+static SQLITE_WSD struct sqlite3StatType {
int nowValue[9]; /* Current value */
int mxValue[9]; /* Maximum value */
-} sqlite3Stat;
+} sqlite3Stat = { {0,}, {0,} };
+
+/* The "wsdStat" macro will resolve to the status information
+** state vector. If writable static data is unsupported on the target,
+** we have to locate the state vector at run-time. In the more common
+** case where writable static data is supported, wsdStat can refer directly
+** to the "sqlite3Stat" state vector declared above.
+*/
+#ifdef SQLITE_OMIT_WSD
+# define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat)
+# define wsdStat x[0]
+#else
+# define wsdStatInit
+# define wsdStat sqlite3Stat
+#endif
/*
** Return the current value of a status parameter.
*/
SQLITE_PRIVATE int sqlite3StatusValue(int op){
- assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) );
- return sqlite3Stat.nowValue[op];
+ wsdStatInit;
+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ return wsdStat.nowValue[op];
}
/*
@@ -10715,10 +10828,11 @@
** caller holds appropriate locks.
*/
SQLITE_PRIVATE void sqlite3StatusAdd(int op, int N){
- assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) );
- sqlite3Stat.nowValue[op] += N;
- if( sqlite3Stat.nowValue[op]>sqlite3Stat.mxValue[op] ){
- sqlite3Stat.mxValue[op] = sqlite3Stat.nowValue[op];
+ wsdStatInit;
+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ wsdStat.nowValue[op] += N;
+ if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
+ wsdStat.mxValue[op] = wsdStat.nowValue[op];
}
}
@@ -10726,10 +10840,11 @@
** Set the value of a status to X.
*/
SQLITE_PRIVATE void sqlite3StatusSet(int op, int X){
- assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) );
- sqlite3Stat.nowValue[op] = X;
- if( sqlite3Stat.nowValue[op]>sqlite3Stat.mxValue[op] ){
- sqlite3Stat.mxValue[op] = sqlite3Stat.nowValue[op];
+ wsdStatInit;
+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ wsdStat.nowValue[op] = X;
+ if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
+ wsdStat.mxValue[op] = wsdStat.nowValue[op];
}
}
@@ -10741,13 +10856,14 @@
** then this routine is not threadsafe.
*/
SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
- if( op<0 || op>=ArraySize(sqlite3Stat.nowValue) ){
+ wsdStatInit;
+ if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
return SQLITE_MISUSE;
}
- *pCurrent = sqlite3Stat.nowValue[op];
- *pHighwater = sqlite3Stat.mxValue[op];
+ *pCurrent = wsdStat.nowValue[op];
+ *pHighwater = wsdStat.mxValue[op];
if( resetFlag ){
- sqlite3Stat.mxValue[op] = sqlite3Stat.nowValue[op];
+ wsdStat.mxValue[op] = wsdStat.nowValue[op];
}
return SQLITE_OK;
}
@@ -10798,7 +10914,7 @@
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: date.c,v 1.88 2008/08/21 20:21:35 drh Exp $
+** $Id: date.c,v 1.90 2008/09/03 17:11:16 drh Exp $
**
** SQLite processes all times and dates as Julian Day numbers. The
** dates and times are stored as the number of days since noon
@@ -11832,7 +11948,7 @@
** external linkage.
*/
SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
- static FuncDef aDateTimeFuncs[] = {
+ static SQLITE_WSD FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
FUNCTION(julianday, -1, 0, 0, juliandayFunc ),
FUNCTION(date, -1, 0, 0, dateFunc ),
@@ -11849,9 +11965,11 @@
#endif
};
int i;
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs);
for(i=0; i<ArraySize(aDateTimeFuncs); i++){
- sqlite3FuncDefInsert(&sqlite3GlobalFunctions, &aDateTimeFuncs[i]);
+ sqlite3FuncDefInsert(pHash, &aFunc[i]);
}
}
@@ -11872,7 +11990,7 @@
** This file contains OS interface code that is common to all
** architectures.
**
-** $Id: os.c,v 1.120 2008/07/28 19:34:53 drh Exp $
+** $Id: os.c,v 1.122 2008/09/02 17:18:52 danielk1977 Exp $
*/
#define _SQLITE_OS_C_ 1
#undef _SQLITE_OS_C_
@@ -12048,7 +12166,8 @@
/*
** The list of all registered VFS implementations.
*/
-static sqlite3_vfs *vfsList = 0;
+static sqlite3_vfs * SQLITE_WSD vfsList = 0;
+#define vfsList GLOBAL(sqlite3_vfs *, vfsList)
/*
** Locate a VFS by name. If no name is given, simply return the
@@ -12148,7 +12267,7 @@
**
*************************************************************************
**
-** $Id: fault.c,v 1.10 2008/06/22 12:37:58 drh Exp $
+** $Id: fault.c,v 1.11 2008/09/02 00:52:52 drh Exp $
*/
/*
@@ -12172,10 +12291,27 @@
/*
** Global variables.
*/
-static struct BenignMallocHooks {
+typedef struct BenignMallocHooks BenignMallocHooks;
+static SQLITE_WSD struct BenignMallocHooks {
void (*xBenignBegin)(void);
void (*xBenignEnd)(void);
-} hooks;
+} sqlite3Hooks = { 0, 0 };
+
+/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
+** structure. If writable static data is unsupported on the target,
+** we have to locate the state vector at run-time. In the more common
+** case where writable static data is supported, wsdHooks can refer directly
+** to the "sqlite3Hooks" state vector declared above.
+*/
+#ifdef SQLITE_OMIT_WSD
+# define wsdHooksInit \
+ BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
+# define wsdHooks x[0]
+#else
+# define wsdHooksInit
+# define wsdHooks sqlite3Hooks
+#endif
+
/*
** Register hooks to call when sqlite3BeginBenignMalloc() and
@@ -12185,8 +12321,9 @@
void (*xBenignBegin)(void),
void (*xBenignEnd)(void)
){
- hooks.xBenignBegin = xBenignBegin;
- hooks.xBenignEnd = xBenignEnd;
+ wsdHooksInit;
+ wsdHooks.xBenignBegin = xBenignBegin;
+ wsdHooks.xBenignEnd = xBenignEnd;
}
/*
@@ -12195,13 +12332,15 @@
** indicates that subsequent malloc failures are non-benign.
*/
SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void){
- if( hooks.xBenignBegin ){
- hooks.xBenignBegin();
+ wsdHooksInit;
+ if( wsdHooks.xBenignBegin ){
+ wsdHooks.xBenignBegin();
}
}
SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){
- if( hooks.xBenignEnd ){
- hooks.xBenignEnd();
+ wsdHooksInit;
+ if( wsdHooks.xBenignEnd ){
+ wsdHooks.xBenignEnd();
}
}
@@ -12228,7 +12367,7 @@
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
-** $Id: mem1.c,v 1.25 2008/07/25 08:49:00 danielk1977 Exp $
+** $Id: mem1.c,v 1.26 2008/09/01 18:34:20 danielk1977 Exp $
*/
/*
@@ -12348,7 +12487,7 @@
** This routine is the only routine in this file with external linkage.
**
** Populate the low-level memory allocation function pointers in
-** sqlite3Config.m with pointers to the routines in this file.
+** sqlite3GlobalConfig.m with pointers to the routines in this file.
*/
SQLITE_PRIVATE void sqlite3MemSetDefault(void){
sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault());
@@ -12379,7 +12518,7 @@
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
-** $Id: mem2.c,v 1.38 2008/08/12 15:04:59 danielk1977 Exp $
+** $Id: mem2.c,v 1.39 2008/09/01 18:34:20 danielk1977 Exp $
*/
/*
@@ -12543,7 +12682,7 @@
** Initialize the memory allocation subsystem.
*/
static int sqlite3MemInit(void *NotUsed){
- if( !sqlite3Config.bMemstat ){
+ if( !sqlite3GlobalConfig.bMemstat ){
/* If memory status is enabled, then the malloc.c wrapper will already
** hold the STATIC_MEM mutex when the routines here are invoked. */
mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
@@ -12628,7 +12767,7 @@
struct MemBlockHdr *pHdr;
void **pBt;
char *z;
- assert( sqlite3Config.bMemstat || mem.mutex!=0 );
+ assert( sqlite3GlobalConfig.bMemstat || mem.mutex!=0 );
pHdr = sqlite3MemsysGetHeader(pPrior);
pBt = (void**)pHdr;
pBt -= pHdr->nBacktraceSlots;
@@ -12698,7 +12837,7 @@
/*
** Populate the low-level memory allocation function pointers in
-** sqlite3Config.m with pointers to the routines in this file.
+** sqlite3GlobalConfig.m with pointers to the routines in this file.
*/
SQLITE_PRIVATE void sqlite3MemSetDefault(void){
sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault());
@@ -12827,7 +12966,7 @@
** This version of the memory allocation subsystem is included
** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
**
-** $Id: mem3.c,v 1.20 2008/07/18 18:56:17 drh Exp $
+** $Id: mem3.c,v 1.23 2008/09/02 17:52:52 danielk1977 Exp $
*/
/*
@@ -12902,7 +13041,14 @@
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
-static struct {
+static SQLITE_WSD struct Mem3Global {
+ /*
+ ** Memory available for allocation. nPool is the size of the array
+ ** (in Mem3Blocks) pointed to by aPool less 2.
+ */
+ u32 nPool;
+ Mem3Block *aPool;
+
/*
** True if we are evaluating an out-of-memory callback.
*/
@@ -12934,14 +13080,9 @@
*/
u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */
u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */
+} mem3 = { 97535575 };
- /*
- ** Memory available for allocation. nPool is the size of the array
- ** (in Mem3Blocks) pointed to by aPool less 2.
- */
- u32 nPool;
- Mem3Block *aPool;
-} mem3;
+#define mem3 GLOBAL(struct Mem3Global, mem3)
/*
** Unlink the chunk at mem3.aPool[i] from list it is currently
@@ -13020,10 +13161,10 @@
/*
** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
** will already be held (obtained by code in malloc.c) if
-** sqlite3Config.bMemStat is true.
+** sqlite3GlobalConfig.bMemStat is true.
*/
static void memsys3Enter(void){
- if( sqlite3Config.bMemstat==0 && mem3.mutex==0 ){
+ if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){
mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
}
sqlite3_mutex_enter(mem3.mutex);
@@ -13353,14 +13494,14 @@
** Initialize this module.
*/
static int memsys3Init(void *NotUsed){
- if( !sqlite3Config.pHeap ){
+ if( !sqlite3GlobalConfig.pHeap ){
return SQLITE_ERROR;
}
/* Store a pointer to the memory block in global structure mem3. */
assert( sizeof(Mem3Block)==8 );
- mem3.aPool = (Mem3Block *)sqlite3Config.pHeap;
- mem3.nPool = (sqlite3Config.nHeap / sizeof(Mem3Block)) - 2;
+ mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
+ mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
/* Initialize the master block. */
mem3.szMaster = mem3.nPool;
@@ -13386,8 +13527,8 @@
** Open the file indicated and write a log of all unfreed memory
** allocations into that log.
*/
-#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
+#ifdef SQLITE_DEBUG
FILE *out;
int i, j;
u32 size;
@@ -13454,15 +13595,15 @@
}else{
fclose(out);
}
-}
#endif
+}
/*
** This routine is the only routine in this file with external
** linkage.
**
** Populate the low-level memory allocation function pointers in
-** sqlite3Config.m with pointers to the routines in this file. The
+** sqlite3GlobalConfig.m with pointers to the routines in this file. The
** arguments specify the block of memory to manage.
**
** This routine is only called by sqlite3_config(), and therefore
@@ -13511,7 +13652,7 @@
** This version of the memory allocation subsystem is included
** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
**
-** $Id: mem5.c,v 1.11 2008/07/16 12:25:32 drh Exp $
+** $Id: mem5.c,v 1.14 2008/09/02 17:52:52 danielk1977 Exp $
*/
/*
@@ -13572,18 +13713,13 @@
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
-static struct {
+static SQLITE_WSD struct Mem5Global {
/*
- ** The alarm callback and its arguments. The mem5.mutex lock will
- ** be held while the callback is running. Recursive calls into
- ** the memory subsystem are allowed, but no new callbacks will be
- ** issued. The alarmBusy variable is set to prevent recursive
- ** callbacks.
+ ** Memory available for allocation
*/
- sqlite3_int64 alarmThreshold;
- void (*alarmCallback)(void*, sqlite3_int64,int);
- void *alarmArg;
- int alarmBusy;
+ int nAtom; /* Smallest possible allocation in bytes */
+ int nBlock; /* Number of nAtom sized blocks in zPool */
+ u8 *zPool;
/*
** Mutex to control access to the memory allocation subsystem.
@@ -13613,13 +13749,9 @@
*/
u8 *aCtrl;
- /*
- ** Memory available for allocation
- */
- int nAtom; /* Smallest possible allocation in bytes */
- int nBlock; /* Number of nAtom sized blocks in zPool */
- u8 *zPool;
-} mem5;
+} mem5 = { 19804167 };
+
+#define mem5 GLOBAL(struct Mem5Global, mem5)
#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.nAtom]))
@@ -13668,10 +13800,10 @@
/*
** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
** will already be held (obtained by code in malloc.c) if
-** sqlite3Config.bMemStat is true.
+** sqlite3GlobalConfig.bMemStat is true.
*/
static void memsys5Enter(void){
- if( sqlite3Config.bMemstat==0 && mem5.mutex==0 ){
+ if( sqlite3GlobalConfig.bMemstat==0 && mem5.mutex==0 ){
mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
}
sqlite3_mutex_enter(mem5.mutex);
@@ -13893,8 +14025,8 @@
*/
static int memsys5Init(void *NotUsed){
int ii;
- int nByte = sqlite3Config.nHeap;
- u8 *zByte = (u8 *)sqlite3Config.pHeap;
+ int nByte = sqlite3GlobalConfig.nHeap;
+ u8 *zByte = (u8 *)sqlite3GlobalConfig.pHeap;
int nMinLog; /* Log of minimum allocation size in bytes*/
int iOffset;
@@ -13902,7 +14034,7 @@
return SQLITE_ERROR;
}
- nMinLog = memsys5Log(sqlite3Config.mnReq);
+ nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq);
mem5.nAtom = (1<<nMinLog);
while( sizeof(Mem5Link)>mem5.nAtom ){
mem5.nAtom = mem5.nAtom << 1;
@@ -14037,7 +14169,7 @@
** fragmentation. On some systems, heap fragmentation can cause a
** significant real-time slowdown.
**
-** $Id: mem6.c,v 1.7 2008/07/28 19:34:53 drh Exp $
+** $Id: mem6.c,v 1.10 2008/09/02 17:52:52 danielk1977 Exp $
*/
#ifdef SQLITE_ENABLE_MEMSYS6
@@ -14108,13 +14240,15 @@
#define MEM6LINK(idx) ((Mem6Link *)(&pChunk->zPool[(idx)*pChunk->nAtom]))
-struct Mem6Global {
+static SQLITE_WSD struct Mem6Global {
int nMinAlloc; /* Minimum allowed allocation size */
int nThreshold; /* Allocs larger than this go to malloc() */
int nLogThreshold; /* log2 of (nThreshold/nMinAlloc) */
sqlite3_mutex *mutex;
Mem6Chunk *pChunk; /* Singly linked list of all memory chunks */
-} mem6;
+} mem6 = { 48642791 };
+
+#define mem6 GLOBAL(struct Mem6Global, mem6)
/*
** Unlink the chunk at pChunk->aPool[i] from list it is currently
@@ -14460,10 +14594,10 @@
}
static int memsys6Init(void *pCtx){
- u8 bMemstat = sqlite3Config.bMemstat;
+ u8 bMemstat = sqlite3GlobalConfig.bMemstat;
mem6.nMinAlloc = (1 << LOG2_MINALLOC);
mem6.pChunk = 0;
- mem6.nThreshold = sqlite3Config.nSmall;
+ mem6.nThreshold = sqlite3GlobalConfig.nSmall;
if( mem6.nThreshold<=0 ){
mem6.nThreshold = SMALL_MALLOC_DEFAULT_THRESHOLD;
}
@@ -14522,7 +14656,7 @@
** implementation is suitable for testing.
** debugging purposes
**
-** $Id: mutex.c,v 1.27 2008/06/19 08:51:24 danielk1977 Exp $
+** $Id: mutex.c,v 1.28 2008/09/01 18:34:20 danielk1977 Exp $
*/
#ifndef SQLITE_MUTEX_NOOP
@@ -14531,17 +14665,17 @@
*/
SQLITE_PRIVATE int sqlite3MutexInit(void){
int rc = SQLITE_OK;
- if( sqlite3Config.bCoreMutex ){
- if( !sqlite3Config.mutex.xMutexAlloc ){
+ if( sqlite3GlobalConfig.bCoreMutex ){
+ if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
/* If the xMutexAlloc method has not been set, then the user did not
** install a mutex implementation via sqlite3_config() prior to
** sqlite3_initialize() being called. This block copies pointers to
- ** the default implementation into the sqlite3Config structure.
+ ** the default implementation into the sqlite3GlobalConfig structure.
**
** The danger is that although sqlite3_config() is not a threadsafe
** API, sqlite3_initialize() is, and so multiple threads may be
** attempting to run this function simultaneously. To guard write
- ** access to the sqlite3Config structure, the 'MASTER' static mutex
+ ** access to the sqlite3GlobalConfig structure, the 'MASTER' static mutex
** is obtained before modifying it.
*/
sqlite3_mutex_methods *p = sqlite3DefaultMutex();
@@ -14552,16 +14686,16 @@
pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
assert(pMaster);
p->xMutexEnter(pMaster);
- assert( sqlite3Config.mutex.xMutexAlloc==0
- || sqlite3Config.mutex.xMutexAlloc==p->xMutexAlloc
+ assert( sqlite3GlobalConfig.mutex.xMutexAlloc==0
+ || sqlite3GlobalConfig.mutex.xMutexAlloc==p->xMutexAlloc
);
- if( !sqlite3Config.mutex.xMutexAlloc ){
- sqlite3Config.mutex = *p;
+ if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
+ sqlite3GlobalConfig.mutex = *p;
}
p->xMutexLeave(pMaster);
}
}else{
- rc = sqlite3Config.mutex.xMutexInit();
+ rc = sqlite3GlobalConfig.mutex.xMutexInit();
}
}
@@ -14574,7 +14708,7 @@
*/
SQLITE_PRIVATE int sqlite3MutexEnd(void){
int rc = SQLITE_OK;
- rc = sqlite3Config.mutex.xMutexEnd();
+ rc = sqlite3GlobalConfig.mutex.xMutexEnd();
return rc;
}
@@ -14585,14 +14719,14 @@
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
- return sqlite3Config.mutex.xMutexAlloc(id);
+ return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
}
SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
- if( !sqlite3Config.bCoreMutex ){
+ if( !sqlite3GlobalConfig.bCoreMutex ){
return 0;
}
- return sqlite3Config.mutex.xMutexAlloc(id);
+ return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
}
/*
@@ -14600,7 +14734,7 @@
*/
SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
if( p ){
- sqlite3Config.mutex.xMutexFree(p);
+ sqlite3GlobalConfig.mutex.xMutexFree(p);
}
}
@@ -14610,7 +14744,7 @@
*/
SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
if( p ){
- sqlite3Config.mutex.xMutexEnter(p);
+ sqlite3GlobalConfig.mutex.xMutexEnter(p);
}
}
@@ -14621,7 +14755,7 @@
SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
int rc = SQLITE_OK;
if( p ){
- return sqlite3Config.mutex.xMutexTry(p);
+ return sqlite3GlobalConfig.mutex.xMutexTry(p);
}
return rc;
}
@@ -14634,7 +14768,7 @@
*/
SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
if( p ){
- sqlite3Config.mutex.xMutexLeave(p);
+ sqlite3GlobalConfig.mutex.xMutexLeave(p);
}
}
@@ -14644,10 +14778,10 @@
** intended for use inside assert() statements.
*/
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
- return p==0 || sqlite3Config.mutex.xMutexHeld(p);
+ return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
}
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
- return p==0 || sqlite3Config.mutex.xMutexNotheld(p);
+ return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
}
#endif
@@ -15638,7 +15772,7 @@
**
** Memory allocation functions used throughout sqlite.
**
-** $Id: malloc.c,v 1.37 2008/08/29 17:56:13 danielk1977 Exp $
+** $Id: malloc.c,v 1.41 2008/09/04 04:32:49 shane Exp $
*/
/*
@@ -15668,9 +15802,9 @@
}
sqlite3_initialize();
if( iLimit>0 ){
- sqlite3_memory_alarm(softHeapLimitEnforcer, 0, iLimit);
+ sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, iLimit);
}else{
- sqlite3_memory_alarm(0, 0, 0);
+ sqlite3MemoryAlarm(0, 0, 0);
}
overage = sqlite3_memory_used() - n;
if( overage>0 ){
@@ -15699,7 +15833,11 @@
/*
** State information local to the memory allocation subsystem.
*/
-static struct {
+static SQLITE_WSD struct Mem0Global {
+ /* Number of free pages for scratch and page-cache memory */
+ u32 nScratchFree;
+ u32 nPageFree;
+
sqlite3_mutex *mutex; /* Mutex to serialize access */
/*
@@ -15715,65 +15853,63 @@
int alarmBusy;
/*
- ** Pointers to the end of sqlite3Config.pScratch and
- ** sqlite3Config.pPage to a block of memory that records
+ ** Pointers to the end of sqlite3GlobalConfig.pScratch and
+ ** sqlite3GlobalConfig.pPage to a block of memory that records
** which pages are available.
*/
u32 *aScratchFree;
u32 *aPageFree;
+} mem0 = { 62560955 };
- /* Number of free pages for scratch and page-cache memory */
- u32 nScratchFree;
- u32 nPageFree;
-} mem0;
+#define mem0 GLOBAL(struct Mem0Global, mem0)
/*
** Initialize the memory allocation subsystem.
*/
SQLITE_PRIVATE int sqlite3MallocInit(void){
- if( sqlite3Config.m.xMalloc==0 ){
+ if( sqlite3GlobalConfig.m.xMalloc==0 ){
sqlite3MemSetDefault();
}
memset(&mem0, 0, sizeof(mem0));
- if( sqlite3Config.bCoreMutex ){
+ if( sqlite3GlobalConfig.bCoreMutex ){
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
}
- if( sqlite3Config.pScratch && sqlite3Config.szScratch>=100
- && sqlite3Config.nScratch>=0 ){
+ if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
+ && sqlite3GlobalConfig.nScratch>=0 ){
int i;
- sqlite3Config.szScratch -= 4;
- mem0.aScratchFree = (u32*)&((char*)sqlite3Config.pScratch)
- [sqlite3Config.szScratch*sqlite3Config.nScratch];
- for(i=0; i<sqlite3Config.nScratch; i++){ mem0.aScratchFree[i] = i; }
- mem0.nScratchFree = sqlite3Config.nScratch;
+ sqlite3GlobalConfig.szScratch -= 4;
+ mem0.aScratchFree = (u32*)&((char*)sqlite3GlobalConfig.pScratch)
+ [sqlite3GlobalConfig.szScratch*sqlite3GlobalConfig.nScratch];
+ for(i=0; i<sqlite3GlobalConfig.nScratch; i++){ mem0.aScratchFree[i] = i; }
+ mem0.nScratchFree = sqlite3GlobalConfig.nScratch;
}else{
- sqlite3Config.pScratch = 0;
- sqlite3Config.szScratch = 0;
+ sqlite3GlobalConfig.pScratch = 0;
+ sqlite3GlobalConfig.szScratch = 0;
}
- if( sqlite3Config.pPage && sqlite3Config.szPage>=512
- && sqlite3Config.nPage>=1 ){
+ if( sqlite3GlobalConfig.pPage && sqlite3GlobalConfig.szPage>=512
+ && sqlite3GlobalConfig.nPage>=1 ){
int i;
int overhead;
- int sz = sqlite3Config.szPage;
- int n = sqlite3Config.nPage;
+ int sz = sqlite3GlobalConfig.szPage;
+ int n = sqlite3GlobalConfig.nPage;
overhead = (4*n + sz - 1)/sz;
- sqlite3Config.nPage -= overhead;
- mem0.aPageFree = (u32*)&((char*)sqlite3Config.pPage)
- [sqlite3Config.szPage*sqlite3Config.nPage];
- for(i=0; i<sqlite3Config.nPage; i++){ mem0.aPageFree[i] = i; }
- mem0.nPageFree = sqlite3Config.nPage;
+ sqlite3GlobalConfig.nPage -= overhead;
+ mem0.aPageFree = (u32*)&((char*)sqlite3GlobalConfig.pPage)
+ [sqlite3GlobalConfig.szPage*sqlite3GlobalConfig.nPage];
+ for(i=0; i<sqlite3GlobalConfig.nPage; i++){ mem0.aPageFree[i] = i; }
+ mem0.nPageFree = sqlite3GlobalConfig.nPage;
}else{
- sqlite3Config.pPage = 0;
- sqlite3Config.szPage = 0;
+ sqlite3GlobalConfig.pPage = 0;
+ sqlite3GlobalConfig.szPage = 0;
}
- return sqlite3Config.m.xInit(sqlite3Config.m.pAppData);
+ return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
}
/*
** Deinitialize the memory allocation subsystem.
*/
SQLITE_PRIVATE void sqlite3MallocEnd(void){
- sqlite3Config.m.xShutdown(sqlite3Config.m.pAppData);
+ sqlite3GlobalConfig.m.xShutdown(sqlite3GlobalConfig.m.pAppData);
memset(&mem0, 0, sizeof(mem0));
}
@@ -15804,7 +15940,7 @@
/*
** Change the alarm callback
*/
-SQLITE_API int sqlite3_memory_alarm(
+SQLITE_PRIVATE int sqlite3MemoryAlarm(
void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
void *pArg,
sqlite3_int64 iThreshold
@@ -15818,6 +15954,18 @@
}
/*
+** Deprecated external interface. Internal/core SQLite code
+** should call sqlite3MemoryAlarm.
+*/
+SQLITE_API int sqlite3_memory_alarm(
+ void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
+ void *pArg,
+ sqlite3_int64 iThreshold
+){
+ return sqlite3MemoryAlarm(xCallback, pArg, iThreshold);
+}
+
+/*
** Trigger the alarm
*/
static void sqlite3MallocAlarm(int nByte){
@@ -15843,7 +15991,7 @@
int nFull;
void *p;
assert( sqlite3_mutex_held(mem0.mutex) );
- nFull = sqlite3Config.m.xRoundup(n);
+ nFull = sqlite3GlobalConfig.m.xRoundup(n);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
if( mem0.alarmCallback!=0 ){
int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
@@ -15851,10 +15999,10 @@
sqlite3MallocAlarm(nFull);
}
}
- p = sqlite3Config.m.xMalloc(nFull);
+ p = sqlite3GlobalConfig.m.xMalloc(nFull);
if( p==0 && mem0.alarmCallback ){
sqlite3MallocAlarm(nFull);
- p = sqlite3Config.m.xMalloc(nFull);
+ p = sqlite3GlobalConfig.m.xMalloc(nFull);
}
if( p ){
nFull = sqlite3MallocSize(p);
@@ -15872,12 +16020,12 @@
void *p;
if( n<=0 ){
p = 0;
- }else if( sqlite3Config.bMemstat ){
+ }else if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
mallocWithAlarm(n, &p);
sqlite3_mutex_leave(mem0.mutex);
}else{
- p = sqlite3Config.m.xMalloc(n);
+ p = sqlite3GlobalConfig.m.xMalloc(n);
}
return p;
}
@@ -15925,7 +16073,7 @@
assert( scratchAllocOut==0 );
#endif
- if( sqlite3Config.szScratch<n ){
+ if( sqlite3GlobalConfig.szScratch<n ){
goto scratch_overflow;
}else{
sqlite3_mutex_enter(mem0.mutex);
@@ -15935,11 +16083,11 @@
}else{
int i;
i = mem0.aScratchFree[--mem0.nScratchFree];
- i *= sqlite3Config.szScratch;
+ i *= sqlite3GlobalConfig.szScratch;
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
sqlite3_mutex_leave(mem0.mutex);
- p = (void*)&((char*)sqlite3Config.pScratch)[i];
+ p = (void*)&((char*)sqlite3GlobalConfig.pScratch)[i];
}
}
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
@@ -15949,14 +16097,14 @@
return p;
scratch_overflow:
- if( sqlite3Config.bMemstat ){
+ if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
n = mallocWithAlarm(n, &p);
if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
sqlite3_mutex_leave(mem0.mutex);
}else{
- p = sqlite3Config.m.xMalloc(n);
+ p = sqlite3GlobalConfig.m.xMalloc(n);
}
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
scratchAllocOut = p!=0;
@@ -15975,26 +16123,26 @@
scratchAllocOut = 0;
#endif
- if( sqlite3Config.pScratch==0
- || p<sqlite3Config.pScratch
+ if( sqlite3GlobalConfig.pScratch==0
+ || p<sqlite3GlobalConfig.pScratch
|| p>=(void*)mem0.aScratchFree ){
- if( sqlite3Config.bMemstat ){
+ if( sqlite3GlobalConfig.bMemstat ){
int iSize = sqlite3MallocSize(p);
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
- sqlite3Config.m.xFree(p);
+ sqlite3GlobalConfig.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
- sqlite3Config.m.xFree(p);
+ sqlite3GlobalConfig.m.xFree(p);
}
}else{
int i;
- i = (u8 *)p - (u8 *)sqlite3Config.pScratch;
- i /= sqlite3Config.szScratch;
- assert( i>=0 && i<sqlite3Config.nScratch );
+ i = (u8 *)p - (u8 *)sqlite3GlobalConfig.pScratch;
+ i /= sqlite3GlobalConfig.szScratch;
+ assert( i>=0 && i<sqlite3GlobalConfig.nScratch );
sqlite3_mutex_enter(mem0.mutex);
- assert( mem0.nScratchFree<sqlite3Config.nScratch );
+ assert( mem0.nScratchFree<sqlite3GlobalConfig.nScratch );
mem0.aScratchFree[mem0.nScratchFree++] = i;
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
sqlite3_mutex_leave(mem0.mutex);
@@ -16015,7 +16163,7 @@
assert( (n & (n-1))==0 );
assert( n>=512 && n<=32768 );
- if( sqlite3Config.szPage<n ){
+ if( sqlite3GlobalConfig.szPage<n ){
goto page_overflow;
}else{
sqlite3_mutex_enter(mem0.mutex);
@@ -16026,57 +16174,57 @@
int i;
i = mem0.aPageFree[--mem0.nPageFree];
sqlite3_mutex_leave(mem0.mutex);
- i *= sqlite3Config.szPage;
+ i *= sqlite3GlobalConfig.szPage;
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, n);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
- p = (void*)&((char*)sqlite3Config.pPage)[i];
+ p = (void*)&((char*)sqlite3GlobalConfig.pPage)[i];
}
}
return p;
page_overflow:
- if( sqlite3Config.bMemstat ){
+ if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, n);
n = mallocWithAlarm(n, &p);
if( p ) sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, n);
sqlite3_mutex_leave(mem0.mutex);
}else{
- p = sqlite3Config.m.xMalloc(n);
+ p = sqlite3GlobalConfig.m.xMalloc(n);
}
return p;
}
SQLITE_PRIVATE void sqlite3PageFree(void *p){
if( p ){
- if( sqlite3Config.pPage==0
- || p<sqlite3Config.pPage
+ if( sqlite3GlobalConfig.pPage==0
+ || p<sqlite3GlobalConfig.pPage
|| p>=(void*)mem0.aPageFree ){
/* In this case, the page allocation was obtained from a regular
** call to sqlite3_mem_methods.xMalloc() (a page-cache-memory
** "overflow"). Free the block with sqlite3_mem_methods.xFree().
*/
- if( sqlite3Config.bMemstat ){
+ if( sqlite3GlobalConfig.bMemstat ){
int iSize = sqlite3MallocSize(p);
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
- sqlite3Config.m.xFree(p);
+ sqlite3GlobalConfig.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
- sqlite3Config.m.xFree(p);
+ sqlite3GlobalConfig.m.xFree(p);
}
}else{
- /* The page allocation was allocated from the sqlite3Config.pPage
+ /* The page allocation was allocated from the sqlite3GlobalConfig.pPage
** buffer. In this case all that is add the index of the page in
- ** the sqlite3Config.pPage array to the set of free indexes stored
+ ** the sqlite3GlobalConfig.pPage array to the set of free indexes stored
** in the mem0.aPageFree[] array.
*/
int i;
- i = (u8 *)p - (u8 *)sqlite3Config.pPage;
- i /= sqlite3Config.szPage;
- assert( i>=0 && i<sqlite3Config.nPage );
+ i = (u8 *)p - (u8 *)sqlite3GlobalConfig.pPage;
+ i /= sqlite3GlobalConfig.szPage;
+ assert( i>=0 && i<sqlite3GlobalConfig.nPage );
sqlite3_mutex_enter(mem0.mutex);
- assert( mem0.nPageFree<sqlite3Config.nPage );
+ assert( mem0.nPageFree<sqlite3GlobalConfig.nPage );
mem0.aPageFree[mem0.nPageFree++] = i;
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
sqlite3_mutex_leave(mem0.mutex);
@@ -16103,13 +16251,13 @@
** sqlite3Malloc() or sqlite3_malloc().
*/
SQLITE_PRIVATE int sqlite3MallocSize(void *p){
- return sqlite3Config.m.xSize(p);
+ return sqlite3GlobalConfig.m.xSize(p);
}
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
if( isLookaside(db, p) ){
return db->lookaside.sz;
}else{
- return sqlite3Config.m.xSize(p);
+ return sqlite3GlobalConfig.m.xSize(p);
}
}
@@ -16118,13 +16266,13 @@
*/
SQLITE_API void sqlite3_free(void *p){
if( p==0 ) return;
- if( sqlite3Config.bMemstat ){
+ if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
- sqlite3Config.m.xFree(p);
+ sqlite3GlobalConfig.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
- sqlite3Config.m.xFree(p);
+ sqlite3GlobalConfig.m.xFree(p);
}
}
@@ -16157,10 +16305,10 @@
return 0;
}
nOld = sqlite3MallocSize(pOld);
- if( sqlite3Config.bMemstat ){
+ if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
- nNew = sqlite3Config.m.xRoundup(nBytes);
+ nNew = sqlite3GlobalConfig.m.xRoundup(nBytes);
if( nOld==nNew ){
pNew = pOld;
}else{
@@ -16168,10 +16316,10 @@
mem0.alarmThreshold ){
sqlite3MallocAlarm(nNew-nOld);
}
- pNew = sqlite3Config.m.xRealloc(pOld, nNew);
+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
if( pNew==0 && mem0.alarmCallback ){
sqlite3MallocAlarm(nBytes);
- pNew = sqlite3Config.m.xRealloc(pOld, nNew);
+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
}
if( pNew ){
nNew = sqlite3MallocSize(pNew);
@@ -16180,7 +16328,7 @@
}
sqlite3_mutex_leave(mem0.mutex);
}else{
- pNew = sqlite3Config.m.xRealloc(pOld, nBytes);
+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nBytes);
}
return pNew;
}
@@ -17322,18 +17470,18 @@
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
-** $Id: random.c,v 1.25 2008/06/19 01:03:18 drh Exp $
+** $Id: random.c,v 1.26 2008/09/02 00:52:52 drh Exp $
*/
/* All threads share a single random number generator.
** This structure is the current state of the generator.
*/
-static struct sqlite3PrngType {
+static SQLITE_WSD struct sqlite3PrngType {
unsigned char isInit; /* True if initialized */
unsigned char i, j; /* State variables */
unsigned char s[256]; /* State variables */
-} sqlite3Prng;
+} sqlite3Prng = { 0, };
/*
** Get a single 8-bit random value from the RC4 PRNG. The Mutex
@@ -17355,6 +17503,20 @@
unsigned char t;
+ /* The "wsdPrng" macro will resolve to the pseudo-random number generator
+ ** state vector. If writable static data is unsupported on the target,
+ ** we have to locate the state vector at run-time. In the more common
+ ** case where writable static data is supported, wsdPrng can refer directly
+ ** to the "sqlite3Prng" state vector declared above.
+ */
+#ifdef SQLITE_OMIT_WSD
+ struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
+# define wsdPrng p[0]
+#else
+# define wsdPrng sqlite3Prng
+#endif
+
+
/* Initialize the state of the random number generator once,
** the first time this routine is called. The seed value does
** not need to contain a lot of randomness since we are not
@@ -17364,33 +17526,33 @@
** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
** number generator) not as an encryption device.
*/
- if( !sqlite3Prng.isInit ){
+ if( !wsdPrng.isInit ){
int i;
char k[256];
- sqlite3Prng.j = 0;
- sqlite3Prng.i = 0;
+ wsdPrng.j = 0;
+ wsdPrng.i = 0;
sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
for(i=0; i<256; i++){
- sqlite3Prng.s[i] = i;
+ wsdPrng.s[i] = i;
}
for(i=0; i<256; i++){
- sqlite3Prng.j += sqlite3Prng.s[i] + k[i];
- t = sqlite3Prng.s[sqlite3Prng.j];
- sqlite3Prng.s[sqlite3Prng.j] = sqlite3Prng.s[i];
- sqlite3Prng.s[i] = t;
+ wsdPrng.j += wsdPrng.s[i] + k[i];
+ t = wsdPrng.s[wsdPrng.j];
+ wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
+ wsdPrng.s[i] = t;
}
- sqlite3Prng.isInit = 1;
+ wsdPrng.isInit = 1;
}
/* Generate and return single random byte
*/
- sqlite3Prng.i++;
- t = sqlite3Prng.s[sqlite3Prng.i];
- sqlite3Prng.j += t;
- sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j];
- sqlite3Prng.s[sqlite3Prng.j] = t;
- t += sqlite3Prng.s[sqlite3Prng.i];
- return sqlite3Prng.s[t];
+ wsdPrng.i++;
+ t = wsdPrng.s[wsdPrng.i];
+ wsdPrng.j += t;
+ wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
+ wsdPrng.s[wsdPrng.j] = t;
+ t += wsdPrng.s[wsdPrng.i];
+ return wsdPrng.s[t];
}
/*
@@ -17411,19 +17573,30 @@
#ifndef SQLITE_OMIT_BUILTIN_TEST
/*
** For testing purposes, we sometimes want to preserve the state of
-** PRNG and restore the PRNG to its saved state at a later time.
+** PRNG and restore the PRNG to its saved state at a later time, or
+** to reset the PRNG to its initial state. These routines accomplish
+** those tasks.
+**
** The sqlite3_test_control() interface calls these routines to
** control the PRNG.
*/
-static struct sqlite3PrngType sqlite3SavedPrng;
+static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng = { 0, };
SQLITE_PRIVATE void sqlite3PrngSaveState(void){
- memcpy(&sqlite3SavedPrng, &sqlite3Prng, sizeof(sqlite3Prng));
+ memcpy(
+ &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
+ &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
+ sizeof(sqlite3Prng)
+ );
}
SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
- memcpy(&sqlite3Prng, &sqlite3SavedPrng, sizeof(sqlite3Prng));
+ memcpy(
+ &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
+ &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
+ sizeof(sqlite3Prng)
+ );
}
SQLITE_PRIVATE void sqlite3PrngResetState(void){
- sqlite3Prng.isInit = 0;
+ GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0;
}
#endif /* SQLITE_OMIT_BUILTIN_TEST */
@@ -21277,7 +21450,7 @@
**
** This file contains code that is specific to Unix systems.
**
-** $Id: os_unix.c,v 1.198 2008/08/22 18:41:37 aswift Exp $
+** $Id: os_unix.c,v 1.201 2008/09/15 04:20:32 danielk1977 Exp $
*/
#if SQLITE_OS_UNIX /* This file is used on unix only */
@@ -22672,9 +22845,11 @@
/* something went terribly awry, unless during file system support
* introspection, in which it actually means what it says */
#endif
+#ifdef ENOTSUP
case ENOTSUP:
/* invalid fd, unless during file system support introspection, in which
* it actually means what it says */
+#endif
case EIO:
case EBADF:
case EINVAL:
@@ -23057,7 +23232,7 @@
pLock->locktype = NO_LOCK;
}else{
int tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
@@ -23524,7 +23699,6 @@
static int flockLock(sqlite3_file *id, int locktype) {
int rc = SQLITE_OK;
- int lrc;
unixFile *pFile = (unixFile*)id;
assert( pFile );
@@ -24440,7 +24614,6 @@
static sqlite3_vfs unixVfs = UNIXVFS("unix", 0);
#ifdef SQLITE_ENABLE_LOCKING_STYLE
-#if 0
int i;
static sqlite3_vfs aVfs[] = {
UNIXVFS("unix-posix", LOCKING_STYLE_POSIX),
@@ -24453,7 +24626,6 @@
sqlite3_vfs_register(&aVfs[i], 0);
}
#endif
-#endif
sqlite3_vfs_register(&unixVfs, 1);
return SQLITE_OK;
}
@@ -24483,7 +24655,7 @@
**
** This file contains code that is specific to windows.
**
-** $Id: os_win.c,v 1.132 2008/07/31 01:34:34 shane Exp $
+** $Id: os_win.c,v 1.133 2008/09/01 22:15:19 shane Exp $
*/
#if SQLITE_OS_WIN /* This file is used for windows only */
@@ -24765,6 +24937,13 @@
/************** Continuing where we left off in os_win.c *********************/
/*
+** Some microsoft compilers lack this definition.
+*/
+#ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+#endif
+
+/*
** Determine if we are dealing with WindowsCE - which has a much
** reduced API.
*/
@@ -26665,7 +26844,7 @@
*************************************************************************
** This file implements that page cache.
**
-** @(#) $Id: pcache.c,v 1.24 2008/08/29 09:10:03 danielk1977 Exp $
+** @(#) $Id: pcache.c,v 1.31 2008/09/21 15:14:04 drh Exp $
*/
/*
@@ -26721,7 +26900,7 @@
/*
** Global data for the page cache.
*/
-static struct PCacheGlobal {
+static SQLITE_WSD struct PCacheGlobal {
int isInit; /* True when initialized */
sqlite3_mutex *mutex; /* static mutex MUTEX_STATIC_LRU */
@@ -26737,6 +26916,13 @@
} pcache = {0};
/*
+** All code in this file should access the global pcache structure via the
+** alias "pcache_g". This ensures that the WSD emulation is used when
+** compiling for systems that do not support real WSD.
+*/
+#define pcache_g (GLOBAL(struct PCacheGlobal, pcache))
+
+/*
** All global variables used by this module (all of which are grouped
** together in global structure "pcache" above) are protected by the static
** SQLITE_MUTEX_STATIC_LRU mutex. A pointer to this mutex is stored in
@@ -26752,9 +26938,9 @@
** entered more than once. The pcacheMutexHeld() macro should only be
** used within an assert() to verify that the mutex is being held.
*/
-#define pcacheEnterMutex() sqlite3_mutex_enter(pcache.mutex)
-#define pcacheExitMutex() sqlite3_mutex_leave(pcache.mutex)
-#define pcacheMutexHeld() sqlite3_mutex_held(pcache.mutex)
+#define pcacheEnterMutex() sqlite3_mutex_enter(pcache_g.mutex)
+#define pcacheExitMutex() sqlite3_mutex_leave(pcache_g.mutex)
+#define pcacheMutexHeld() sqlite3_mutex_held(pcache_g.mutex)
/*
** Some of the assert() macros in this code are too expensive to run
@@ -26970,22 +27156,22 @@
** Remove a page from the global LRU list
*/
static void pcacheRemoveFromLruList(PgHdr *pPage){
- assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
assert( (pPage->flags&PGHDR_DIRTY)==0 );
if( pPage->pCache->bPurgeable==0 ) return;
if( pPage->pNextLru ){
- assert( pcache.pLruTail!=pPage );
+ assert( pcache_g.pLruTail!=pPage );
pPage->pNextLru->pPrevLru = pPage->pPrevLru;
}else{
- assert( pcache.pLruTail==pPage );
- pcache.pLruTail = pPage->pPrevLru;
+ assert( pcache_g.pLruTail==pPage );
+ pcache_g.pLruTail = pPage->pPrevLru;
}
if( pPage->pPrevLru ){
- assert( pcache.pLruHead!=pPage );
+ assert( pcache_g.pLruHead!=pPage );
pPage->pPrevLru->pNextLru = pPage->pNextLru;
}else{
- assert( pcache.pLruHead==pPage );
- pcache.pLruHead = pPage->pNextLru;
+ assert( pcache_g.pLruHead==pPage );
+ pcache_g.pLruHead = pPage->pNextLru;
}
}
@@ -26996,31 +27182,31 @@
** to the end of the LRU list so that it will be the next to be recycled.
*/
static void pcacheAddToLruList(PgHdr *pPage){
- assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
assert( (pPage->flags&PGHDR_DIRTY)==0 );
if( pPage->pCache->bPurgeable==0 ) return;
- if( pcache.pLruTail && (pPage->flags & PGHDR_REUSE_UNLIKELY)!=0 ){
+ if( pcache_g.pLruTail && (pPage->flags & PGHDR_REUSE_UNLIKELY)!=0 ){
/* If reuse is unlikely. Put the page at the end of the LRU list
** where it will be recycled sooner rather than later.
*/
- assert( pcache.pLruHead );
+ assert( pcache_g.pLruHead );
pPage->pNextLru = 0;
- pPage->pPrevLru = pcache.pLruTail;
- pcache.pLruTail->pNextLru = pPage;
- pcache.pLruTail = pPage;
+ pPage->pPrevLru = pcache_g.pLruTail;
+ pcache_g.pLruTail->pNextLru = pPage;
+ pcache_g.pLruTail = pPage;
pPage->flags &= ~PGHDR_REUSE_UNLIKELY;
}else{
/* If reuse is possible. the page goes at the beginning of the LRU
** list so that it will be the last to be recycled.
*/
- if( pcache.pLruHead ){
- pcache.pLruHead->pPrevLru = pPage;
+ if( pcache_g.pLruHead ){
+ pcache_g.pLruHead->pPrevLru = pPage;
}
- pPage->pNextLru = pcache.pLruHead;
- pcache.pLruHead = pPage;
+ pPage->pNextLru = pcache_g.pLruHead;
+ pcache_g.pLruHead = pPage;
pPage->pPrevLru = 0;
- if( pcache.pLruTail==0 ){
- pcache.pLruTail = pPage;
+ if( pcache_g.pLruTail==0 ){
+ pcache_g.pLruTail = pPage;
}
}
}
@@ -27035,16 +27221,16 @@
SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
PgFreeslot *p;
sz &= ~7;
- pcache.szSlot = sz;
- pcache.pStart = pBuf;
- pcache.pFree = 0;
+ pcache_g.szSlot = sz;
+ pcache_g.pStart = pBuf;
+ pcache_g.pFree = 0;
while( n-- ){
p = (PgFreeslot*)pBuf;
- p->pNext = pcache.pFree;
- pcache.pFree = p;
+ p->pNext = pcache_g.pFree;
+ pcache_g.pFree = p;
pBuf = (void*)&((char*)pBuf)[sz];
}
- pcache.pEnd = pBuf;
+ pcache_g.pEnd = pBuf;
}
/*
@@ -27052,11 +27238,11 @@
** and use an element from it first if available. If nothing is available
** in the page cache memory pool, go to the general purpose memory allocator.
*/
-void *pcacheMalloc(int sz, PCache *pCache){
- assert( sqlite3_mutex_held(pcache.mutex) );
- if( sz<=pcache.szSlot && pcache.pFree ){
- PgFreeslot *p = pcache.pFree;
- pcache.pFree = p->pNext;
+static void *pcacheMalloc(int sz, PCache *pCache){
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ if( sz<=pcache_g.szSlot && pcache_g.pFree ){
+ PgFreeslot *p = pcache_g.pFree;
+ pcache_g.pFree = p->pNext;
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, sz);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
return (void*)p;
@@ -27080,7 +27266,7 @@
return p;
}
}
-SQLITE_PRIVATE void *sqlite3PageMalloc(sz){
+SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){
void *p;
pcacheEnterMutex();
p = pcacheMalloc(sz, 0);
@@ -27091,15 +27277,15 @@
/*
** Release a pager memory allocation
*/
-void pcacheFree(void *p){
- assert( sqlite3_mutex_held(pcache.mutex) );
+static void pcacheFree(void *p){
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
if( p==0 ) return;
- if( p>=pcache.pStart && p<pcache.pEnd ){
+ if( p>=pcache_g.pStart && p<pcache_g.pEnd ){
PgFreeslot *pSlot;
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
pSlot = (PgFreeslot*)p;
- pSlot->pNext = pcache.pFree;
- pcache.pFree = pSlot;
+ pSlot->pNext = pcache_g.pFree;
+ pcache_g.pFree = pSlot;
}else{
int iSize = sqlite3MallocSize(p);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
@@ -27118,14 +27304,14 @@
static PgHdr *pcachePageAlloc(PCache *pCache){
PgHdr *p;
int sz = sizeof(*p) + pCache->szPage + pCache->szExtra;
- assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
p = pcacheMalloc(sz, pCache);
if( p==0 ) return 0;
memset(p, 0, sizeof(PgHdr));
p->pData = (void*)&p[1];
p->pExtra = (void*)&((char*)p->pData)[pCache->szPage];
if( pCache->bPurgeable ){
- pcache.nCurrentPage++;
+ pcache_g.nCurrentPage++;
}
return p;
}
@@ -27134,9 +27320,9 @@
** Deallocate a page
*/
static void pcachePageFree(PgHdr *p){
- assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
if( p->pCache->bPurgeable ){
- pcache.nCurrentPage--;
+ pcache_g.nCurrentPage--;
}
pcacheFree(p->apSave[0]);
pcacheFree(p->apSave[1]);
@@ -27149,8 +27335,8 @@
** the argument is passed to pcachePageFree().
*/
static int pcachePageSize(PgHdr *p){
- assert( sqlite3_mutex_held(pcache.mutex) );
- assert( !pcache.pStart );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ assert( !pcache_g.pStart );
assert( p->apSave[0]==0 );
assert( p->apSave[1]==0 );
assert( p && p->pCache );
@@ -27171,9 +27357,9 @@
*/
static PgHdr *pcacheRecyclePage(){
PgHdr *p = 0;
- assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
- if( (p=pcache.pLruTail) ){
+ if( (p=pcache_g.pLruTail) ){
assert( (p->flags&PGHDR_DIRTY)==0 );
pcacheRemoveFromLruList(p);
pcacheRemoveFromHash(p);
@@ -27196,20 +27382,21 @@
int szPage = pCache->szPage;
int szExtra = pCache->szExtra;
- assert( pcache.isInit );
- assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( pcache_g.isInit );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
*ppPage = 0;
- /* If we have reached the limit for pinned/dirty pages, and there is at
- ** least one dirty page, invoke the xStress callback to cause a page to
- ** become clean.
+ /* If we have reached either the global or the local limit for
+ ** pinned+dirty pages, and there is at least one dirty page,
+ ** invoke the xStress callback to cause a page to become clean.
*/
expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
expensive_assert( pcacheCheckSynced(pCache) );
if( pCache->xStress
&& pCache->pDirty
- && pCache->nPinned>=(pcache.nMaxPage+pCache->nMin-pcache.nMinPage)
+ && (pCache->nPinned>=(pcache_g.nMaxPage+pCache->nMin-pcache_g.nMinPage)
+ || pCache->nPinned>=pCache->nMax)
){
PgHdr *pPg;
assert(pCache->pDirtyTail);
@@ -27232,8 +27419,11 @@
}
}
- /* If the global page limit has been reached, try to recycle a page. */
- if( pCache->bPurgeable && pcache.nCurrentPage>=pcache.nMaxPage ){
+ /* If either the local or the global page limit has been reached,
+ ** try to recycle a page.
+ */
+ if( pCache->bPurgeable && (pCache->nPage>=pCache->nMax-1 ||
+ pcache_g.nCurrentPage>=pcache_g.nMaxPage) ){
p = pcacheRecyclePage();
}
@@ -27257,19 +27447,19 @@
** functions are threadsafe.
*/
SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
- assert( pcache.isInit==0 );
- memset(&pcache, 0, sizeof(pcache));
- if( sqlite3Config.bCoreMutex ){
+ assert( pcache_g.isInit==0 );
+ memset(&pcache_g, 0, sizeof(pcache));
+ if( sqlite3GlobalConfig.bCoreMutex ){
/* No need to check the return value of sqlite3_mutex_alloc().
** Allocating a static mutex cannot fail.
*/
- pcache.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
+ pcache_g.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
}
- pcache.isInit = 1;
+ pcache_g.isInit = 1;
return SQLITE_OK;
}
SQLITE_PRIVATE void sqlite3PcacheShutdown(void){
- memset(&pcache, 0, sizeof(pcache));
+ memset(&pcache_g, 0, sizeof(pcache));
}
/*
@@ -27290,7 +27480,7 @@
void *pStress, /* Argument to xStress */
PCache *p /* Preallocated space for the PCache */
){
- assert( pcache.isInit );
+ assert( pcache_g.isInit );
memset(p, 0, sizeof(PCache));
p->szPage = szPage;
p->szExtra = szExtra;
@@ -27303,8 +27493,8 @@
pcacheEnterMutex();
if( bPurgeable ){
- pcache.nMaxPage += p->nMax;
- pcache.nMinPage += p->nMin;
+ pcache_g.nMaxPage += p->nMax;
+ pcache_g.nMinPage += p->nMin;
}
pcacheExitMutex();
@@ -27331,7 +27521,7 @@
int rc = SQLITE_OK;
PgHdr *pPage = 0;
- assert( pcache.isInit );
+ assert( pcache_g.isInit );
assert( pCache!=0 );
assert( pgno>0 );
expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
@@ -27401,7 +27591,7 @@
if( (p->flags&PGHDR_DIRTY)==0 ){
pCache->nPinned--;
pcacheEnterMutex();
- if( pcache.nCurrentPage>pcache.nMaxPage ){
+ if( pcache_g.nCurrentPage>pcache_g.nMaxPage ){
pcacheRemoveFromList(&pCache->pClean, p);
pcacheRemoveFromHash(p);
pcachePageFree(p);
@@ -27459,7 +27649,7 @@
p->flags |= PGHDR_DIRTY;
}
-void pcacheMakeClean(PgHdr *p){
+static void pcacheMakeClean(PgHdr *p){
PCache *pCache = p->pCache;
assert( p->apSave[0]==0 && p->apSave[1]==0 );
assert( p->flags & PGHDR_DIRTY );
@@ -27517,7 +27707,6 @@
pcacheRemoveFromHash(p);
p->pgno = newPgno;
if( newPgno==0 ){
- p->flags |= PGHDR_REUSE_UNLIKELY;
pcacheFree(p->apSave[0]);
pcacheFree(p->apSave[1]);
p->apSave[0] = 0;
@@ -27525,6 +27714,7 @@
if( (p->flags & PGHDR_DIRTY) ){
pcacheMakeClean(p);
}
+ p->flags = PGHDR_REUSE_UNLIKELY;
}
pcacheAddToHash(p);
pcacheExitMutex();
@@ -27533,9 +27723,9 @@
/*
** Remove all content from a page cache
*/
-void pcacheClear(PCache *pCache){
+static void pcacheClear(PCache *pCache){
PgHdr *p, *pNext;
- assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
for(p=pCache->pClean; p; p=pNext){
pNext = p->pNext;
pcacheRemoveFromLruList(p);
@@ -27595,8 +27785,8 @@
*/
static void pcacheEnforceMaxPage(){
PgHdr *p;
- assert( sqlite3_mutex_held(pcache.mutex) );
- while( pcache.nCurrentPage>pcache.nMaxPage && (p = pcacheRecyclePage()) ){
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ while( pcache_g.nCurrentPage>pcache_g.nMaxPage && (p = pcacheRecyclePage()) ){
pcachePageFree(p);
}
}
@@ -27610,8 +27800,8 @@
/* Free all the pages used by this pager and remove them from the LRU list. */
pcacheClear(pCache);
if( pCache->bPurgeable ){
- pcache.nMaxPage -= pCache->nMax;
- pcache.nMinPage -= pCache->nMin;
+ pcache_g.nMaxPage -= pCache->nMax;
+ pcache_g.nMinPage -= pCache->nMin;
pcacheEnforceMaxPage();
}
sqlite3_free(pCache->apHash);
@@ -27646,12 +27836,14 @@
*/
SQLITE_PRIVATE void sqlite3PcacheCommit(PCache *pCache, int idJournal){
PgHdr *p;
+ int mask = idJournal==0 ? ~PGHDR_IN_JOURNAL : 0xffffff;
pcacheEnterMutex(); /* Mutex is required to call pcacheFree() */
for(p=pCache->pDirty; p; p=p->pNext){
if( p->apSave[idJournal] ){
pcacheFree(p->apSave[idJournal]);
p->apSave[idJournal] = 0;
}
+ p->flags &= mask;
}
pcacheExitMutex();
}
@@ -27659,9 +27851,14 @@
/*
** Rollback a change previously preserved.
*/
-SQLITE_PRIVATE void sqlite3PcacheRollback(PCache *pCache, int idJournal){
+SQLITE_PRIVATE void sqlite3PcacheRollback(
+ PCache *pCache, /* Pager cache */
+ int idJournal, /* Which copy to rollback to */
+ void (*xReiniter)(PgHdr*) /* Called on each rolled back page */
+){
PgHdr *p;
int sz;
+ int mask = idJournal==0 ? ~PGHDR_IN_JOURNAL : 0xffffff;
pcacheEnterMutex(); /* Mutex is required to call pcacheFree() */
sz = pCache->szPage;
for(p=pCache->pDirty; p; p=p->pNext){
@@ -27669,11 +27866,16 @@
memcpy(p->pData, p->apSave[idJournal], sz);
pcacheFree(p->apSave[idJournal]);
p->apSave[idJournal] = 0;
+ if( xReiniter ){
+ xReiniter(p);
+ }
}
+ p->flags &= mask;
}
pcacheExitMutex();
}
+#ifndef NDEBUG
/*
** Assert flags settings on all pages. Debugging only.
*/
@@ -27688,6 +27890,7 @@
assert( (p->flags&falseMask)==0 );
}
}
+#endif
/*
** Discard the contents of the cache.
@@ -27820,24 +28023,23 @@
/*
** Set flags on all pages in the page cache
*/
-SQLITE_PRIVATE void sqlite3PcacheSetFlags(PCache *pCache, int andMask, int orMask){
+SQLITE_PRIVATE void sqlite3PcacheClearFlags(PCache *pCache, int mask){
PgHdr *p;
- assert( (orMask&PGHDR_NEED_SYNC)==0 );
-
/* Obtain the global mutex before modifying any PgHdr.flags variables
** or traversing the LRU list.
*/
pcacheEnterMutex();
+ mask = ~mask;
for(p=pCache->pDirty; p; p=p->pNext){
- p->flags = (p->flags&andMask)|orMask;
+ p->flags &= mask;
}
for(p=pCache->pClean; p; p=p->pNext){
- p->flags = (p->flags&andMask)|orMask;
+ p->flags &= mask;
}
- if( 0==(andMask&PGHDR_NEED_SYNC) ){
+ if( 0==(mask&PGHDR_NEED_SYNC) ){
pCache->pSynced = pCache->pDirtyTail;
assert( !pCache->pSynced || (pCache->pSynced->flags&PGHDR_NEED_SYNC)==0 );
}
@@ -27861,8 +28063,8 @@
}
if( pCache->bPurgeable ){
pcacheEnterMutex();
- pcache.nMaxPage -= pCache->nMax;
- pcache.nMaxPage += mxPage;
+ pcache_g.nMaxPage -= pCache->nMax;
+ pcache_g.nMaxPage += mxPage;
pcacheEnforceMaxPage();
pcacheExitMutex();
}
@@ -27881,7 +28083,7 @@
*/
SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
int nFree = 0;
- if( pcache.pStart==0 ){
+ if( pcache_g.pStart==0 ){
PgHdr *p;
pcacheEnterMutex();
while( (nReq<0 || nFree<nReq) && (p=pcacheRecyclePage()) ){
@@ -27903,18 +28105,17 @@
){
PgHdr *p;
int nRecyclable = 0;
- for(p=pcache.pLruHead; p; p=p->pNextLru){
+ for(p=pcache_g.pLruHead; p; p=p->pNextLru){
nRecyclable++;
}
- *pnCurrent = pcache.nCurrentPage;
- *pnMax = pcache.nMaxPage;
- *pnMin = pcache.nMinPage;
+ *pnCurrent = pcache_g.nCurrentPage;
+ *pnMax = pcache_g.nMaxPage;
+ *pnMin = pcache_g.nMinPage;
*pnRecyclable = nRecyclable;
}
#endif
-
/************** End of pcache.c **********************************************/
/************** Begin file pager.c *******************************************/
/*
@@ -27937,7 +28138,7 @@
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.485 2008/08/28 02:26:07 drh Exp $
+** @(#) $Id: pager.c,v 1.493 2008/09/19 09:14:44 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
@@ -28126,8 +28327,7 @@
int nHit, nMiss; /* Cache hits and missing */
int nRead, nWrite; /* Database pages read/written */
#endif
- void (*xDestructor)(DbPage*,int); /* Call this routine when freeing pages */
- void (*xReiniter)(DbPage*,int); /* Call this routine when reloading pages */
+ void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
#ifdef SQLITE_HAS_CODEC
void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
void *pCodecArg; /* First argument to xCodec() */
@@ -28496,7 +28696,7 @@
*/
static int zeroJournalHdr(Pager *pPager, int doTruncate){
int rc = SQLITE_OK;
- static const char zeroHdr[28];
+ static const char zeroHdr[28] = {0};
if( pPager->journalOff ){
i64 iLimit = pPager->journalSizeLimit;
@@ -28912,8 +29112,8 @@
#ifdef SQLITE_CHECK_PAGES
sqlite3PcacheIterate(pPager->pPCache, pager_set_pagehash);
#endif
- sqlite3PcacheSetFlags(pPager->pPCache,
- ~(PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC), 0
+ sqlite3PcacheClearFlags(pPager->pPCache,
+ PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC
);
pPager->dirtyCache = 0;
pPager->nRec = 0;
@@ -29077,7 +29277,7 @@
pData = pPg->pData;
memcpy(pData, aData, pPager->pageSize);
if( pPager->xReiniter ){
- pPager->xReiniter(pPg, pPager->pageSize);
+ pPager->xReiniter(pPg);
}
if( isMainJrnl ) makeClean(pPg);
#ifdef SQLITE_CHECK_PAGES
@@ -29410,6 +29610,11 @@
pPager->journalOff = szJ;
break;
}else{
+ /* If we are unable to rollback, then the database is probably
+ ** going to end up being corrupt. It is corrupt to us, anyhow.
+ ** Perhaps the next process to come along can fix it....
+ */
+ rc = SQLITE_CORRUPT;
goto end_playback;
}
}
@@ -29576,7 +29781,7 @@
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int bFullFsync){
- pPager->noSync = level==1 || pPager->tempFile;
+ pPager->noSync = level==1 || pPager->tempFile || MEMDB;
pPager->fullSync = level==3 && !pPager->tempFile;
pPager->sync_flags = (bFullFsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL);
if( pPager->noSync ) pPager->needSync = 0;
@@ -29674,6 +29879,7 @@
if( strcmp(zFilename,":memory:")==0 ){
memDb = 1;
zPathname[0] = 0;
+ useJournal = 0;
}else
#endif
{
@@ -29798,7 +30004,7 @@
}
/* pPager->journalOpen = 0; */
- pPager->useJournal = useJournal && !memDb;
+ pPager->useJournal = useJournal;
pPager->noReadlock = noReadlock && readOnly;
/* pPager->stmtOpen = 0; */
/* pPager->stmtInUse = 0; */
@@ -29853,7 +30059,7 @@
** an opportunity to restore the EXTRA section to agree with the restored
** page data.
*/
-SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*,int)){
+SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*)){
pPager->xReiniter = xReinit;
}
@@ -29863,26 +30069,28 @@
** value before returning.
*/
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize){
- int rc = SQLITE_OK;
- u16 pageSize = *pPageSize;
- assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
- if( pageSize && pageSize!=pPager->pageSize
- && (pPager->memDb==0 || pPager->dbSize==0)
- && sqlite3PcacheRefCount(pPager->pPCache)==0
- ){
- char *pNew = (char *)sqlite3PageMalloc(pageSize);
- if( !pNew ){
- rc = SQLITE_NOMEM;
- }else{
- pager_reset(pPager);
- pPager->pageSize = pageSize;
- if( !pPager->memDb ) setSectorSize(pPager);
- sqlite3PageFree(pPager->pTmpSpace);
- pPager->pTmpSpace = pNew;
- sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
+ int rc = pPager->errCode;
+ if( rc==SQLITE_OK ){
+ u16 pageSize = *pPageSize;
+ assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
+ if( pageSize && pageSize!=pPager->pageSize
+ && (pPager->memDb==0 || pPager->dbSize==0)
+ && sqlite3PcacheRefCount(pPager->pPCache)==0
+ ){
+ char *pNew = (char *)sqlite3PageMalloc(pageSize);
+ if( !pNew ){
+ rc = SQLITE_NOMEM;
+ }else{
+ pager_reset(pPager);
+ pPager->pageSize = pageSize;
+ if( !pPager->memDb ) setSectorSize(pPager);
+ sqlite3PageFree(pPager->pTmpSpace);
+ pPager->pTmpSpace = pNew;
+ sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
+ }
}
+ *pPageSize = pPager->pageSize;
}
- *pPageSize = pPager->pageSize;
return rc;
}
@@ -30233,8 +30441,7 @@
/* Erase the needSync flag from every page.
*/
- sqlite3PcacheSetFlags(pPager->pPCache, ~PGHDR_NEED_SYNC, 0);
- /* lruListSetFirstSynced(pPager); */
+ sqlite3PcacheClearFlags(pPager->pPCache, PGHDR_NEED_SYNC);
}
#ifndef NDEBUG
@@ -30244,7 +30451,6 @@
*/
else{
sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_NEED_SYNC);
- /* assert( pPager->lru.pFirstSynced==pPager->lru.pFirst ); */
}
#endif
@@ -30322,11 +30528,9 @@
#ifdef SQLITE_CHECK_PAGES
pList->pageHash = pager_pagehash(pList);
#endif
- /* makeClean(pList); */
pList = pList->pDirty;
}
- /* sqlite3PcacheCleanAll(pPager->pPCache); */
return SQLITE_OK;
}
@@ -30708,7 +30912,7 @@
** called again with noContent==0, that means that the content is needed
** and the disk read should occur at that point.
*/
-static int pagerAcquire(
+SQLITE_PRIVATE int sqlite3PagerAcquire(
Pager *pPager, /* The pager open on the database file */
Pgno pgno, /* Page number to fetch */
DbPage **ppPage, /* Write a pointer to the page here */
@@ -30756,6 +30960,7 @@
PAGER_INCR(pPager->nMiss);
pPg->pPager = pPager;
if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
+ assert( !MEMDB );
pPg->flags |= PGHDR_IN_JOURNAL;
}
memset(pPg->pExtra, 0, pPager->nExtra);
@@ -30804,18 +31009,6 @@
return SQLITE_OK;
}
-SQLITE_PRIVATE int sqlite3PagerAcquire(
- Pager *pPager, /* The pager open on the database file */
- Pgno pgno, /* Page number to fetch */
- DbPage **ppPage, /* Write a pointer to the page here */
- int noContent /* Do not bother reading content from disk if true */
-){
- int rc;
- rc = pagerAcquire(pPager, pgno, ppPage, noContent);
- return rc;
-}
-
-
/*
** Acquire a page if it is already in the in-memory cache. Do
** not read the page from disk. Return a pointer to the page,
@@ -31304,6 +31497,7 @@
** before any of them can be written out to the database file.
*/
if( needSync ){
+ assert( !MEMDB && pPager->noSync==0 );
for(ii=0; ii<nPage && needSync; ii++){
PgHdr *pPage = pager_lookup(pPager, pg1+ii);
if( pPage ) pPage->flags |= PGHDR_NEED_SYNC;
@@ -31575,8 +31769,9 @@
** If the optimization can be used, then the journal file will never
** be created for this transaction.
*/
+ int useAtomicWrite;
pPg = sqlite3PcacheDirtyList(pPager->pPCache);
- int useAtomicWrite = (
+ useAtomicWrite = (
!zMaster &&
pPager->journalOpen &&
pPager->journalOff==jrnlBufferSize(pPager) &&
@@ -31715,9 +31910,7 @@
if( MEMDB ){
sqlite3PcacheCommit(pPager->pPCache, 0);
sqlite3PcacheCleanAll(pPager->pPCache);
- sqlite3PcacheSetFlags(pPager->pPCache,
- ~(PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC), 0
- );
+ sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
pPager->state = PAGER_SHARED;
}else{
assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache );
@@ -31743,12 +31936,10 @@
int rc = SQLITE_OK;
PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
if( MEMDB ){
- sqlite3PcacheRollback(pPager->pPCache, 1);
- sqlite3PcacheRollback(pPager->pPCache, 0);
+ sqlite3PcacheRollback(pPager->pPCache, 1, pPager->xReiniter);
+ sqlite3PcacheRollback(pPager->pPCache, 0, pPager->xReiniter);
sqlite3PcacheCleanAll(pPager->pPCache);
- sqlite3PcacheSetFlags(pPager->pPCache,
- ~(PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC), 0
- );
+ sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
pPager->dbSize = pPager->origDbSize;
pager_truncate_cache(pPager);
pPager->stmtInUse = 0;
@@ -31886,7 +32077,6 @@
if( pPager->stmtInUse ){
PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
if( !MEMDB ){
- /* sqlite3OsTruncate(pPager->stfd, 0); */
sqlite3BitvecDestroy(pPager->pInStmt);
pPager->pInStmt = 0;
}else{
@@ -31907,7 +32097,7 @@
if( pPager->stmtInUse ){
PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
if( MEMDB ){
- sqlite3PcacheRollback(pPager->pPCache, 1);
+ sqlite3PcacheRollback(pPager->pPCache, 1, pPager->xReiniter);
pPager->dbSize = pPager->stmtSize;
pager_truncate_cache(pPager);
rc = SQLITE_OK;
@@ -31987,7 +32177,7 @@
**
** There must be no references to the page previously located at
** pgno (which we call pPgOld) though that page is allowed to be
-** in cache. If the page previous located at pgno is not already
+** in cache. If the page previously located at pgno is not already
** in the rollback journal, it is not put there by by this routine.
**
** References to the page pPg remain valid. Updating any
@@ -32042,6 +32232,7 @@
pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
}
if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
+ assert( !MEMDB );
pPg->flags |= PGHDR_IN_JOURNAL;
}
@@ -32084,6 +32275,7 @@
return rc;
}
pPager->needSync = 1;
+ assert( pPager->noSync==0 && !MEMDB );
pPgHdr->flags |= PGHDR_NEED_SYNC;
pPgHdr->flags |= PGHDR_IN_JOURNAL;
makeDirty(pPgHdr);
@@ -32202,7 +32394,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btreeInt.h,v 1.30 2008/08/01 20:10:08 drh Exp $
+** $Id: btreeInt.h,v 1.31 2008/09/18 17:34:44 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@@ -32485,6 +32677,18 @@
};
/*
+** Possible values for the MemPage.isInit variable. When a page is first
+** loaded or if the data stored in the MemPage struct is invalidated,
+** MemPage.isInit is set to PAGE_ISINIT_NONE. If the MemPage structure
+** is fully initialized, then MemPage.isInit is set to PAGE_ISINIT_FULL.
+** MemPage.isInit is set to PAGE_ISINIT_DATA when the MemPage struct is
+** populated, but the MemPage.pParent variable is not necessarily correct.
+*/
+#define PAGE_ISINIT_NONE 0
+#define PAGE_ISINIT_DATA 1
+#define PAGE_ISINIT_FULL 2
+
+/*
** The in-memory image of a disk page has the auxiliary information appended
** to the end. EXTRA_SIZE is the number of bytes of space needed to hold
** that extra information.
@@ -33127,7 +33331,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.504 2008/08/27 15:16:34 danielk1977 Exp $
+** $Id: btree.c,v 1.516 2008/09/19 16:39:38 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
@@ -33155,18 +33359,15 @@
#ifndef SQLITE_OMIT_SHARED_CACHE
/*
-** A flag to indicate whether or not shared cache is enabled. Also,
-** a list of BtShared objects that are eligible for participation
-** in shared cache. The variables have file scope during normal builds,
-** but the test harness needs to access these variables so we make them
-** global for test builds.
+** A list of BtShared objects that are eligible for participation
+** in shared cache. This variable has file scope during normal builds,
+** but the test harness needs to access it so we make it global for
+** test builds.
*/
#ifdef SQLITE_TEST
-SQLITE_PRIVATE BtShared *sqlite3SharedCacheList = 0;
-SQLITE_PRIVATE int sqlite3SharedCacheEnabled = 0;
+SQLITE_PRIVATE BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
#else
-static BtShared *sqlite3SharedCacheList = 0;
-static int sqlite3SharedCacheEnabled = 0;
+static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
#endif
#endif /* SQLITE_OMIT_SHARED_CACHE */
@@ -33179,7 +33380,7 @@
** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2().
*/
SQLITE_API int sqlite3_enable_shared_cache(int enable){
- sqlite3SharedCacheEnabled = enable;
+ sqlite3GlobalConfig.sharedCacheEnabled = enable;
return SQLITE_OK;
}
#endif
@@ -34058,57 +34259,63 @@
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
- if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){
+ if( pPage==pParent ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ if( (pPage->pParent!=pParent)
+ && (pPage->pParent!=0 || pPage->isInit==PAGE_ISINIT_FULL) ){
/* The parent page should never change unless the file is corrupt */
return SQLITE_CORRUPT_BKPT;
}
- if( pPage->isInit ) return SQLITE_OK;
- if( pPage->pParent==0 && pParent!=0 ){
+ if( pPage->isInit==PAGE_ISINIT_FULL ) return SQLITE_OK;
+ if( pParent!=0 ){
pPage->pParent = pParent;
sqlite3PagerRef(pParent->pDbPage);
}
- hdr = pPage->hdrOffset;
- data = pPage->aData;
- if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
- assert( pBt->pageSize>=512 && pBt->pageSize<=32768 );
- pPage->maskPage = pBt->pageSize - 1;
- pPage->nOverflow = 0;
- pPage->idxShift = 0;
- usableSize = pBt->usableSize;
- pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf;
- top = get2byte(&data[hdr+5]);
- pPage->nCell = get2byte(&data[hdr+3]);
- if( pPage->nCell>MX_CELL(pBt) ){
- /* To many cells for a single page. The page must be corrupt */
- return SQLITE_CORRUPT_BKPT;
- }
- if( pPage->nCell==0 && pParent!=0 && pParent->pgno!=1 ){
- /* All pages must have at least one cell, except for root pages */
- return SQLITE_CORRUPT_BKPT;
- }
-
- /* Compute the total free space on the page */
- pc = get2byte(&data[hdr+1]);
- nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell);
- while( pc>0 ){
- int next, size;
- if( pc>usableSize-4 ){
- /* Free block is off the page */
- return SQLITE_CORRUPT_BKPT;
+ if( pPage->isInit==PAGE_ISINIT_NONE ){
+ hdr = pPage->hdrOffset;
+ data = pPage->aData;
+ if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
+ assert( pBt->pageSize>=512 && pBt->pageSize<=32768 );
+ pPage->maskPage = pBt->pageSize - 1;
+ pPage->nOverflow = 0;
+ pPage->idxShift = 0;
+ usableSize = pBt->usableSize;
+ pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf;
+ top = get2byte(&data[hdr+5]);
+ pPage->nCell = get2byte(&data[hdr+3]);
+ if( pPage->nCell>MX_CELL(pBt) ){
+ /* To many cells for a single page. The page must be corrupt */
+ return SQLITE_CORRUPT_BKPT;
+ }
+ if( pPage->nCell==0 && pParent!=0 && pParent->pgno!=1 ){
+ /* All pages must have at least one cell, except for root pages */
+ return SQLITE_CORRUPT_BKPT;
}
- next = get2byte(&data[pc]);
- size = get2byte(&data[pc+2]);
- if( next>0 && next<=pc+size+3 ){
- /* Free blocks must be in accending order */
+
+ /* Compute the total free space on the page */
+ pc = get2byte(&data[hdr+1]);
+ nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell);
+ while( pc>0 ){
+ int next, size;
+ if( pc>usableSize-4 ){
+ /* Free block is off the page */
+ return SQLITE_CORRUPT_BKPT;
+ }
+ next = get2byte(&data[pc]);
+ size = get2byte(&data[pc+2]);
+ if( next>0 && next<=pc+size+3 ){
+ /* Free blocks must be in accending order */
+ return SQLITE_CORRUPT_BKPT;
+ }
+ nFree += size;
+ pc = next;
+ }
+ pPage->nFree = nFree;
+ if( nFree>=usableSize ){
+ /* Free space cannot exceed total page size */
return SQLITE_CORRUPT_BKPT;
}
- nFree += size;
- pc = next;
- }
- pPage->nFree = nFree;
- if( nFree>=usableSize ){
- /* Free space cannot exceed total page size */
- return SQLITE_CORRUPT_BKPT;
}
#if 0
@@ -34131,7 +34338,7 @@
}
#endif
- pPage->isInit = 1;
+ pPage->isInit = PAGE_ISINIT_FULL;
return SQLITE_OK;
}
@@ -34165,7 +34372,22 @@
pPage->maskPage = pBt->pageSize - 1;
pPage->idxShift = 0;
pPage->nCell = 0;
- pPage->isInit = 1;
+ pPage->isInit = PAGE_ISINIT_FULL;
+}
+
+
+/*
+** Convert a DbPage obtained from the pager into a MemPage used by
+** the btree layer.
+*/
+static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
+ MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
+ pPage->aData = sqlite3PagerGetData(pDbPage);
+ pPage->pDbPage = pDbPage;
+ pPage->pBt = pBt;
+ pPage->pgno = pgno;
+ pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
+ return pPage;
}
/*
@@ -34186,23 +34408,27 @@
int noContent /* Do not load page content if true */
){
int rc;
- MemPage *pPage;
DbPage *pDbPage;
assert( sqlite3_mutex_held(pBt->mutex) );
rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent);
if( rc ) return rc;
- pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage);
- pPage->aData = sqlite3PagerGetData(pDbPage);
- pPage->pDbPage = pDbPage;
- pPage->pBt = pBt;
- pPage->pgno = pgno;
- pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
- *ppPage = pPage;
+ *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
return SQLITE_OK;
}
/*
+** Return the size of the database file in pages. Or return -1 if
+** there is any kind of error.
+*/
+static int pagerPagecount(Pager *pPager){
+ int rc;
+ int nPage;
+ rc = sqlite3PagerPagecount(pPager, &nPage);
+ return (rc==SQLITE_OK?nPage:-1);
+}
+
+/*
** Get a page from the pager and initialize it. This routine
** is just a convenience wrapper around separate calls to
** sqlite3BtreeGetPage() and sqlite3BtreeInitPage().
@@ -34214,17 +34440,46 @@
MemPage *pParent /* Parent of the page */
){
int rc;
+ DbPage *pDbPage;
+ MemPage *pPage;
+
assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( !pParent || pParent->isInit==PAGE_ISINIT_FULL );
if( pgno==0 ){
return SQLITE_CORRUPT_BKPT;
}
- rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0);
- if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
- rc = sqlite3BtreeInitPage(*ppPage, pParent);
- if( rc!=SQLITE_OK ){
- releasePage(*ppPage);
- *ppPage = 0;
+
+ /* It is often the case that the page we want is already in cache.
+ ** If so, get it directly. This saves us from having to call
+ ** pagerPagecount() to make sure pgno is within limits, which results
+ ** in a measureable performance improvements.
+ */
+ pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
+ if( pDbPage ){
+ /* Page is already in cache */
+ *ppPage = pPage = btreePageFromDbPage(pDbPage, pgno, pBt);
+ rc = SQLITE_OK;
+ }else{
+ /* Page not in cache. Acquire it. */
+ if( pgno>pagerPagecount(pBt->pPager) ){
+ return SQLITE_CORRUPT_BKPT;
}
+ rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0);
+ if( rc ) return rc;
+ pPage = *ppPage;
+ }
+ if( pPage->isInit!=PAGE_ISINIT_FULL ){
+ rc = sqlite3BtreeInitPage(pPage, pParent);
+ }else if( pParent && (pPage==pParent || pPage->pParent!=pParent) ){
+ /* This condition indicates a loop in the b-tree structure (the scenario
+ ** where database corruption has caused a page to be a direct or
+ ** indirect descendant of itself).
+ */
+ rc = SQLITE_CORRUPT_BKPT;
+ }
+ if( rc!=SQLITE_OK ){
+ releasePage(pPage);
+ *ppPage = 0;
}
return rc;
}
@@ -34253,14 +34508,18 @@
MemPage *pPage;
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
if( pPage ){
- assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( pPage->isInit!=PAGE_ISINIT_FULL
+ || sqlite3_mutex_held(pPage->pBt->mutex)
+ );
if( pPage->pParent ){
MemPage *pParent = pPage->pParent;
assert( pParent->pBt==pPage->pBt );
pPage->pParent = 0;
releasePage(pParent);
}
- pPage->isInit = 0;
+ if( pPage->isInit==PAGE_ISINIT_FULL ){
+ pPage->isInit = PAGE_ISINIT_DATA;
+ }
}
}
@@ -34272,14 +34531,15 @@
** This routine needs to reset the extra data section at the end of the
** page to agree with the restored data.
*/
-static void pageReinit(DbPage *pData, int pageSize){
+static void pageReinit(DbPage *pData){
MemPage *pPage;
- assert( (pageSize & 7)==0 );
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
- if( pPage->isInit ){
+ if( pPage->isInit==PAGE_ISINIT_FULL ){
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
pPage->isInit = 0;
sqlite3BtreeInitPage(pPage, pPage->pParent);
+ }else if( pPage->isInit==PAGE_ISINIT_DATA ){
+ pPage->isInit = 0;
}
}
@@ -34349,7 +34609,7 @@
&& (db->flags & SQLITE_Vtab)==0
&& zFilename && zFilename[0]
){
- if( sqlite3SharedCacheEnabled ){
+ if( sqlite3GlobalConfig.sharedCacheEnabled ){
int nFullPathname = pVfs->mxPathname+1;
char *zFullPathname = sqlite3Malloc(nFullPathname);
sqlite3_mutex *mutexShared;
@@ -34362,7 +34622,7 @@
sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname);
mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(mutexShared);
- for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){
+ for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
assert( pBt->nRef>0 );
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
&& sqlite3PagerVfs(pBt->pPager)==pVfs ){
@@ -34457,7 +34717,7 @@
sqlite3_mutex *mutexShared;
pBt->nRef = 1;
mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
- if( SQLITE_THREADSAFE && sqlite3Config.bCoreMutex ){
+ if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
if( pBt->mutex==0 ){
rc = SQLITE_NOMEM;
@@ -34466,8 +34726,8 @@
}
}
sqlite3_mutex_enter(mutexShared);
- pBt->pNext = sqlite3SharedCacheList;
- sqlite3SharedCacheList = pBt;
+ pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList);
+ GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt;
sqlite3_mutex_leave(mutexShared);
}
#endif
@@ -34535,10 +34795,10 @@
sqlite3_mutex_enter(pMaster);
pBt->nRef--;
if( pBt->nRef<=0 ){
- if( sqlite3SharedCacheList==pBt ){
- sqlite3SharedCacheList = pBt->pNext;
+ if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){
+ GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext;
}else{
- pList = sqlite3SharedCacheList;
+ pList = GLOBAL(BtShared*,sqlite3SharedCacheList);
while( ALWAYS(pList) && pList->pNext!=pBt ){
pList=pList->pNext;
}
@@ -35136,17 +35396,6 @@
return rc;
}
-/*
-** Return the size of the database file in pages. Or return -1 if
-** there is any kind of error.
-*/
-static int pagerPagecount(Pager *pPager){
- int rc;
- int nPage;
- rc = sqlite3PagerPagecount(pPager, &nPage);
- return (rc==SQLITE_OK?nPage:-1);
-}
-
#ifndef SQLITE_OMIT_AUTOVACUUM
@@ -36291,7 +36540,7 @@
}
if( offset+amt > nKey+pCur->info.nData ){
/* Trying to read or write past the end of the data is an error */
- return SQLITE_ERROR;
+ return SQLITE_CORRUPT_BKPT;
}
/* Check if data must be read/written to/from the btree page itself. */
@@ -36636,8 +36885,22 @@
clearCursorPosition(pCur);
}
pRoot = pCur->pPage;
- if( pRoot && pRoot->pgno==pCur->pgnoRoot ){
- assert( pRoot->isInit );
+ if( pRoot && pRoot->isInit ){
+ /* If the page the cursor is currently pointing to is fully initialized,
+ ** then the root page can be found by following the MemPage.pParent
+ ** pointers. This is faster than requesting a reference to the root
+ ** page from the pager layer.
+ */
+ while( pRoot->pParent ){
+ assert( pRoot->isInit==PAGE_ISINIT_FULL );
+ pRoot = pRoot->pParent;
+ }
+ assert( pRoot->isInit==PAGE_ISINIT_FULL );
+ if( pRoot!=pCur->pPage ){
+ sqlite3PagerRef(pRoot->pDbPage);
+ releasePage(pCur->pPage);
+ pCur->pPage = pRoot;
+ }
}else{
if(
SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0))
@@ -36648,6 +36911,7 @@
releasePage(pCur->pPage);
pCur->pPage = pRoot;
}
+ assert( pCur->pPage->pgno==pCur->pgnoRoot );
pCur->idx = 0;
pCur->info.nSize = 0;
pCur->atLast = 0;
@@ -36713,7 +36977,7 @@
pCur->info.nSize = 0;
pCur->validNKey = 0;
}
- return SQLITE_OK;
+ return rc;
}
/* Move the cursor to the first entry in the table. Return SQLITE_OK
@@ -36817,13 +37081,12 @@
}
}
-
rc = moveToRoot(pCur);
if( rc ){
return rc;
}
assert( pCur->pPage );
- assert( pCur->pPage->isInit );
+ assert( pCur->pPage->isInit==PAGE_ISINIT_FULL );
if( pCur->eState==CURSOR_INVALID ){
*pRes = -1;
assert( pCur->pPage->nCell==0 );
@@ -36909,7 +37172,7 @@
pCur->idx = (lwr+upr)/2;
}
assert( lwr==upr+1 );
- assert( pPage->isInit );
+ assert( pPage->isInit==PAGE_ISINIT_FULL );
if( pPage->leaf ){
chldPg = 0;
}else if( lwr>=pPage->nCell ){
@@ -37015,7 +37278,7 @@
}
pCur->skip = 0;
- assert( pPage->isInit );
+ assert( pPage->isInit==PAGE_ISINIT_FULL );
assert( pCur->idx<pPage->nCell );
pCur->idx++;
@@ -37084,7 +37347,7 @@
pCur->skip = 0;
pPage = pCur->pPage;
- assert( pPage->isInit );
+ assert( pPage->isInit==PAGE_ISINIT_FULL );
assert( pCur->idx>=0 );
if( !pPage->leaf ){
pgno = get4byte( findCell(pPage, pCur->idx) );
@@ -37375,6 +37638,13 @@
end_allocate_page:
releasePage(pTrunk);
releasePage(pPrevTrunk);
+ if( rc==SQLITE_OK ){
+ if( (*ppPage)->isInit==PAGE_ISINIT_FULL ){
+ releasePage(*ppPage);
+ return SQLITE_CORRUPT_BKPT;
+ }
+ (*ppPage)->isInit = 0;
+ }
return rc;
}
@@ -37674,7 +37944,7 @@
pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
if( pDbPage ){
pThis = (MemPage *)sqlite3PagerGetExtra(pDbPage);
- if( pThis->isInit ){
+ if( pThis->isInit==PAGE_ISINIT_FULL ){
assert( pThis->aData==sqlite3PagerGetData(pDbPage) );
if( pThis->pParent!=pNewParent ){
if( pThis->pParent ) sqlite3PagerUnref(pThis->pParent->pDbPage);
@@ -37957,7 +38227,7 @@
*/
static int balance_quick(MemPage *pPage, MemPage *pParent){
int rc;
- MemPage *pNew;
+ MemPage *pNew = 0;
Pgno pgnoNew;
u8 *pCell;
u16 szCell;
@@ -37973,63 +38243,80 @@
** into it. Then remove the overflow cell from pPage.
*/
rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- pCell = pPage->aOvfl[0].pCell;
- szCell = cellSizePtr(pPage, pCell);
- zeroPage(pNew, pPage->aData[0]);
- assemblePage(pNew, 1, &pCell, &szCell);
- pPage->nOverflow = 0;
+ if( rc==SQLITE_OK ){
+ pCell = pPage->aOvfl[0].pCell;
+ szCell = cellSizePtr(pPage, pCell);
+ zeroPage(pNew, pPage->aData[0]);
+ assemblePage(pNew, 1, &pCell, &szCell);
+ pPage->nOverflow = 0;
+
+ /* Set the parent of the newly allocated page to pParent. */
+ pNew->pParent = pParent;
+ sqlite3PagerRef(pParent->pDbPage);
+
+ /* pPage is currently the right-child of pParent. Change this
+ ** so that the right-child is the new page allocated above and
+ ** pPage is the next-to-right child.
+ **
+ ** Ignore the return value of the call to fillInCell(). fillInCell()
+ ** may only return other than SQLITE_OK if it is required to allocate
+ ** one or more overflow pages. Since an internal table B-Tree cell
+ ** may never spill over onto an overflow page (it is a maximum of
+ ** 13 bytes in size), it is not neccessary to check the return code.
+ **
+ ** Similarly, the insertCell() function cannot fail if the page
+ ** being inserted into is already writable and the cell does not
+ ** contain an overflow pointer. So ignore this return code too.
+ */
+ assert( pPage->nCell>0 );
+ pCell = findCell(pPage, pPage->nCell-1);
+ sqlite3BtreeParseCellPtr(pPage, pCell, &info);
+ fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize);
+ assert( parentSize<64 );
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+ insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4);
+ put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno);
+ put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
+
+ /* If this is an auto-vacuum database, update the pointer map
+ ** with entries for the new page, and any pointer from the
+ ** cell on the page to an overflow page.
+ */
+ if( ISAUTOVACUUM ){
+ rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno);
+ if( rc==SQLITE_OK ){
+ rc = ptrmapPutOvfl(pNew, 0);
+ }
+ }
- /* Set the parent of the newly allocated page to pParent. */
- pNew->pParent = pParent;
- sqlite3PagerRef(pParent->pDbPage);
+ /* Release the reference to the new page. */
+ releasePage(pNew);
+ }
- /* pPage is currently the right-child of pParent. Change this
- ** so that the right-child is the new page allocated above and
- ** pPage is the next-to-right child.
- **
- ** Ignore the return value of the call to fillInCell(). fillInCell()
- ** may only return other than SQLITE_OK if it is required to allocate
- ** one or more overflow pages. Since an internal table B-Tree cell
- ** may never spill over onto an overflow page (it is a maximum of
- ** 13 bytes in size), it is not neccessary to check the return code.
+ /* At this point the pPage->nFree variable is not set correctly with
+ ** respect to the content of the page (because it was set to 0 by
+ ** insertCell). So call sqlite3BtreeInitPage() to make sure it is
+ ** correct.
**
- ** Similarly, the insertCell() function cannot fail if the page
- ** being inserted into is already writable and the cell does not
- ** contain an overflow pointer. So ignore this return code too.
- */
- assert( pPage->nCell>0 );
- pCell = findCell(pPage, pPage->nCell-1);
- sqlite3BtreeParseCellPtr(pPage, pCell, &info);
- fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize);
- assert( parentSize<64 );
- assert( sqlite3PagerIswriteable(pParent->pDbPage) );
- insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4);
- put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno);
- put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
-
- /* If this is an auto-vacuum database, update the pointer map
- ** with entries for the new page, and any pointer from the
- ** cell on the page to an overflow page.
+ ** This has to be done even if an error will be returned. Normally, if
+ ** an error occurs during tree balancing, the contents of MemPage are
+ ** not important, as they will be recalculated when the page is rolled
+ ** back. But here, in balance_quick(), it is possible that pPage has
+ ** not yet been marked dirty or written into the journal file. Therefore
+ ** it will not be rolled back and so it is important to make sure that
+ ** the page data and contents of MemPage are consistent.
*/
- if( ISAUTOVACUUM ){
- rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno);
- if( rc==SQLITE_OK ){
- rc = ptrmapPutOvfl(pNew, 0);
- }
- if( rc!=SQLITE_OK ){
- releasePage(pNew);
- return rc;
- }
- }
+ pPage->isInit = 0;
+ sqlite3BtreeInitPage(pPage, pPage->pParent);
+ sqlite3PagerUnref(pPage->pParent->pDbPage);
- /* Release the reference to the new page and balance the parent page,
- ** in case the divider cell inserted caused it to become overfull.
+ /* If everything else succeeded, balance the parent page, in
+ ** case the divider cell inserted caused it to become overfull.
*/
- releasePage(pNew);
- return balance(pParent, 0);
+ if( rc==SQLITE_OK ){
+ rc = balance(pParent, 0);
+ }
+ return rc;
}
#endif /* SQLITE_OMIT_QUICKBALANCE */
@@ -38102,7 +38389,7 @@
/*
** Find the parent page.
*/
- assert( pPage->isInit );
+ assert( pPage->isInit==PAGE_ISINIT_FULL );
assert( sqlite3PagerIswriteable(pPage->pDbPage) || pPage->nOverflow==1 );
pBt = pPage->pBt;
pParent = pPage->pParent;
@@ -38634,7 +38921,7 @@
** have been added to the freelist so it might no longer be initialized.
** But the parent page will always be initialized.
*/
- assert( pParent->isInit );
+ assert( pParent->isInit==PAGE_ISINIT_FULL );
sqlite3ScratchFree(apCell);
apCell = 0;
rc = balance(pParent, 0);
@@ -38651,9 +38938,11 @@
for(i=0; i<nNew; i++){
releasePage(apNew[i]);
}
+
releasePage(pParent);
TRACE(("BALANCE: finished with %d: old=%d new=%d cells=%d\n",
pPage->pgno, nOld, nNew, nCell));
+
return rc;
}
@@ -38787,7 +39076,7 @@
cdata = pChild->aData;
memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr);
memcpy(&cdata[cbrk], &data[cbrk], usableSize-cbrk);
- if( pChild->isInit ) return SQLITE_CORRUPT;
+ if( pChild->isInit==PAGE_ISINIT_FULL ) return SQLITE_CORRUPT;
rc = sqlite3BtreeInitPage(pChild, pPage);
if( rc ) goto balancedeeper_out;
memcpy(pChild->aOvfl, pPage->aOvfl, pPage->nOverflow*sizeof(pPage->aOvfl[0]));
@@ -38970,7 +39259,7 @@
TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
pCur->pgnoRoot, nKey, nData, pPage->pgno,
loc==0 ? "overwrite" : "new entry"));
- assert( pPage->isInit );
+ assert( pPage->isInit==PAGE_ISINIT_FULL );
allocateTempSpace(pBt);
newCell = pBt->pTmpSpace;
if( newCell==0 ) return SQLITE_NOMEM;
@@ -39024,7 +39313,7 @@
BtShared *pBt = p->pBt;
assert( cursorHoldsMutex(pCur) );
- assert( pPage->isInit );
+ assert( pPage->isInit==PAGE_ISINIT_FULL );
if( pBt->inTransaction!=TRANS_WRITE ){
/* Must start a transaction before doing a delete */
rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
@@ -39302,14 +39591,14 @@
for(i=0; i<pPage->nCell; i++){
pCell = findCell(pPage, i);
if( !pPage->leaf ){
- rc = clearDatabasePage(pBt, get4byte(pCell), pPage->pParent, 1);
+ rc = clearDatabasePage(pBt, get4byte(pCell), pPage, 1);
if( rc ) goto cleardatabasepage_out;
}
rc = clearCell(pPage, pCell);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
- rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage->pParent, 1);
+ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage, 1);
if( rc ) goto cleardatabasepage_out;
}
if( freePageFlag ){
@@ -39518,14 +39807,32 @@
}
assert( idx>=0 && idx<=15 );
- rc = sqlite3PagerGet(pBt->pPager, 1, &pDbPage);
- if( rc ){
- sqlite3BtreeLeave(p);
- return rc;
+ if( pBt->pPage1 ){
+ /* The b-tree is already holding a reference to page 1 of the database
+ ** file. In this case the required meta-data value can be read directly
+ ** from the page data of this reference. This is slightly faster than
+ ** requesting a new reference from the pager layer.
+ */
+ pP1 = (unsigned char *)pBt->pPage1->aData;
+ }else{
+ /* The b-tree does not have a reference to page 1 of the database file.
+ ** Obtain one from the pager layer.
+ */
+ rc = sqlite3PagerGet(pBt->pPager, 1, &pDbPage);
+ if( rc ){
+ sqlite3BtreeLeave(p);
+ return rc;
+ }
+ pP1 = (unsigned char *)sqlite3PagerGetData(pDbPage);
}
- pP1 = (unsigned char *)sqlite3PagerGetData(pDbPage);
*pMeta = get4byte(&pP1[36 + idx*4]);
- sqlite3PagerUnref(pDbPage);
+
+ /* If the b-tree is not holding a reference to page 1, then one was
+ ** requested from the pager layer in the above block. Release it now.
+ */
+ if( !pBt->pPage1 ){
+ sqlite3PagerUnref(pDbPage);
+ }
/* If autovacuumed is disabled in this build but we are trying to
** access an autovacuumed database, then make the database readonly.
@@ -40204,7 +40511,11 @@
}
}
- if( pToPage ) sqlite3PagerUnref(pToPage);
+ if( pToPage ){
+ MemPage *p = (MemPage *)sqlite3PagerGetExtra(pToPage);
+ p->isInit = 0;
+ sqlite3PagerUnref(pToPage);
+ }
}
}
@@ -40601,7 +40912,7 @@
** only within the VDBE. Interface routines refer to a Mem using the
** name sqlite_value
**
-** $Id: vdbemem.c,v 1.122 2008/08/22 14:41:01 drh Exp $
+** $Id: vdbemem.c,v 1.123 2008/09/16 12:06:08 danielk1977 Exp $
*/
/*
@@ -41321,22 +41632,21 @@
** comparison function directly */
return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
}else{
- u8 origEnc = pMem1->enc;
const void *v1, *v2;
int n1, n2;
- /* Convert the strings into the encoding that the comparison
- ** function expects */
- v1 = sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc);
- n1 = v1==0 ? 0 : pMem1->n;
- assert( n1==sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc) );
- v2 = sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc);
- n2 = v2==0 ? 0 : pMem2->n;
- assert( n2==sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc) );
- /* Do the comparison */
+ Mem c1;
+ Mem c2;
+ memset(&c1, 0, sizeof(c1));
+ memset(&c2, 0, sizeof(c2));
+ sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
+ sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
+ v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
+ n1 = v1==0 ? 0 : c1.n;
+ v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
+ n2 = v2==0 ? 0 : c2.n;
rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
- /* Convert the strings back into the database encoding */
- sqlite3ValueText((sqlite3_value*)pMem1, origEnc);
- sqlite3ValueText((sqlite3_value*)pMem2, origEnc);
+ sqlite3VdbeMemRelease(&c1);
+ sqlite3VdbeMemRelease(&c2);
return rc;
}
}
@@ -41643,7 +41953,7 @@
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
-** $Id: vdbeaux.c,v 1.409 2008/08/20 22:06:48 drh Exp $
+** $Id: vdbeaux.c,v 1.411 2008/09/19 18:32:27 danielk1977 Exp $
*/
@@ -42387,13 +42697,32 @@
*/
static void releaseMemArray(Mem *p, int N){
if( p && N ){
+ Mem *pEnd;
sqlite3 *db = p->db;
int malloc_failed = db->mallocFailed;
- while( N-->0 ){
- assert( N<2 || p[0].db==p[1].db );
- sqlite3VdbeMemRelease(p);
+ for(pEnd=&p[N]; p<pEnd; p++){
+ assert( (&p[1])==pEnd || p[0].db==p[1].db );
+
+ /* This block is really an inlined version of sqlite3VdbeMemRelease()
+ ** that takes advantage of the fact that the memory cell value is
+ ** being set to NULL after releasing any dynamic resources.
+ **
+ ** The justification for duplicating code is that according to
+ ** callgrind, this causes a certain test case to hit the CPU 4.7
+ ** percent less (x86 linux, gcc version 4.1.2, -O6) than if
+ ** sqlite3MemRelease() were called from here. With -O2, this jumps
+ ** to 6.6 percent. The test case is inserting 1000 rows into a table
+ ** with no indexes using a single prepared INSERT statement, bind()
+ ** and reset(). Inserts are grouped into a transaction.
+ */
+ if( p->flags&(MEM_Agg|MEM_Dyn) ){
+ sqlite3VdbeMemRelease(p);
+ }else if( p->zMalloc ){
+ sqlite3DbFree(db, p->zMalloc);
+ p->zMalloc = 0;
+ }
+
p->flags = MEM_Null;
- p++;
}
db->mallocFailed = malloc_failed;
}
@@ -42527,6 +42856,7 @@
pMem->z = pOp->zComment;
pMem->n = strlen(pMem->z);
pMem->enc = SQLITE_UTF8;
+ pMem->type = SQLITE_TEXT;
}else
#endif
{
@@ -44122,7 +44452,7 @@
** This file contains code use to implement APIs that are part of the
** VDBE.
**
-** $Id: vdbeapi.c,v 1.140 2008/08/21 12:19:44 danielk1977 Exp $
+** $Id: vdbeapi.c,v 1.141 2008/09/04 12:03:43 shane Exp $
*/
#if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
@@ -45334,7 +45664,7 @@
** If the two statements contain a different number of bindings, then
** an SQLITE_ERROR is returned.
*/
-SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
+SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
Vdbe *pFrom = (Vdbe*)pFromStmt;
Vdbe *pTo = (Vdbe*)pToStmt;
int i, rc = SQLITE_OK;
@@ -45356,6 +45686,14 @@
}
/*
+** Deprecated external interface. Internal/core SQLite code
+** should call sqlite3TransferBindings.
+*/
+SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
+ return sqlite3TransferBindings(pFromStmt, pToStmt);
+}
+
+/*
** Return the sqlite3* database handle to which the prepared statement given
** in the argument belongs. This is the same database handle that was
** the first argument to the sqlite3_prepare() that was used to create
@@ -45430,7 +45768,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.777 2008/08/21 19:28:30 drh Exp $
+** $Id: vdbe.c,v 1.779 2008/09/22 06:13:32 danielk1977 Exp $
*/
/*
@@ -45494,12 +45832,6 @@
#endif
/*
-** Release the memory associated with a register. This
-** leaves the Mem.flags field in an inconsistent state.
-*/
-#define Release(P) if((P)->flags&MEM_Dyn){ sqlite3VdbeMemRelease(P); }
-
-/*
** Convert the given register into a string if it isn't one
** already. Return non-zero if a malloc() fails.
*/
@@ -45560,7 +45892,7 @@
** from the comments following the "case OP_xxxx:" statements in
** this file.
*/
-static unsigned char opcodeProperty[] = OPFLG_INITIALIZER;
+static const unsigned char opcodeProperty[] = OPFLG_INITIALIZER;
/*
** Return true if an opcode has any of the OPFLG_xxx properties
@@ -47619,7 +47951,8 @@
** of the record (when all fields present), then we must be dealing
** with a corrupt database.
*/
- if( zIdx>zEndHdr || offset>payloadSize || (zIdx==zEndHdr && offset!=payloadSize) ){
+ if( zIdx>zEndHdr || offset>payloadSize
+ || (zIdx==zEndHdr && offset!=payloadSize) ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
}
@@ -52481,7 +52814,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.392 2008/08/29 02:14:03 drh Exp $
+** $Id: expr.c,v 1.394 2008/09/17 00:13:12 drh Exp $
*/
/*
@@ -54923,7 +55256,7 @@
Parse *pParse, /* Parsing context */
ExprList *pList, /* The expression list to be coded */
int target, /* Where to write results */
- int doHardCopy /* Call sqlite3ExprHardCopy on each element if true */
+ int doHardCopy /* Make a hard copy of every element */
){
struct ExprList_item *pItem;
int i, n;
@@ -54938,7 +55271,9 @@
}else{
sqlite3ExprCode(pParse, pItem->pExpr, target+i);
}
- if( doHardCopy ) sqlite3ExprHardCopy(pParse, target, n);
+ if( doHardCopy ){
+ sqlite3ExprHardCopy(pParse, target, n);
+ }
}
return n;
}
@@ -60842,7 +61177,7 @@
** This file contains functions used to access the internal hash tables
** of user defined functions and collation sequences.
**
-** $Id: callback.c,v 1.29 2008/08/21 20:21:35 drh Exp $
+** $Id: callback.c,v 1.31 2008/09/09 12:31:34 drh Exp $
*/
@@ -61169,7 +61504,8 @@
if( nArg<-1 ) nArg = -1;
h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
-
+ /* First search for a match amongst the application-defined functions.
+ */
p = functionSearch(&db->aFunc, h, zName, nName);
while( p ){
int score = matchQuality(p, nArg, enc);
@@ -61180,12 +61516,17 @@
p = p->pNext;
}
- /* If the createFlag parameter is false and no match was found amongst
- ** the custom functions stored in sqlite3.aFunc, try to find a built-in
- ** function to use.
+ /* If no match is found, search the built-in functions.
+ **
+ ** Except, if createFlag is true, that means that we are trying to
+ ** install a new function. Whatever FuncDef structure is returned will
+ ** have fields overwritten with new information appropriate for the
+ ** new function. But the FuncDefs for built-in functions are read-only.
+ ** So we must not search for built-ins when creating a new function.
*/
if( !createFlag && !pBest ){
- p = functionSearch(&sqlite3GlobalFunctions, h, zName, nName);
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ p = functionSearch(pHash, h, zName, nName);
while( p ){
int score = matchQuality(p, nArg, enc);
if( score>bestScore ){
@@ -61196,11 +61537,11 @@
}
}
- /* If the createFlag parameter is true, and the seach did not reveal an
+ /* If the createFlag parameter is true and the search did not reveal an
** exact match for the name, number of arguments and encoding, then add a
** new entry to the hash table and return it.
*/
- if( createFlag && bestScore<6 &&
+ if( createFlag && (bestScore<6 || pBest->nArg!=nArg) &&
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
pBest->zName = (char *)&pBest[1];
pBest->nArg = nArg;
@@ -61288,7 +61629,7 @@
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
-** $Id: delete.c,v 1.174 2008/08/29 02:14:03 drh Exp $
+** $Id: delete.c,v 1.175 2008/09/01 21:59:43 shane Exp $
*/
/*
@@ -61524,9 +61865,11 @@
/* If we are trying to delete from a view, realize that view into
** a ephemeral table.
*/
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
}
+#endif
/* Resolve the column names in the WHERE clause.
*/
@@ -61842,7 +62185,7 @@
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: func.c,v 1.199 2008/08/21 20:21:35 drh Exp $
+** $Id: func.c,v 1.203 2008/09/03 17:11:16 drh Exp $
*/
/*
@@ -62702,7 +63045,7 @@
assert( zIn==sqlite3_value_text(argv[0]) );
if( argc==1 ){
static const unsigned char lenOne[] = { 1 };
- static const unsigned char *azOne[] = { (u8*)" " };
+ static unsigned char * const azOne[] = { (u8*)" " };
nChar = 1;
aLen = (u8*)lenOne;
azChar = (unsigned char **)azOne;
@@ -62759,6 +63102,7 @@
sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT);
}
+
#ifdef SQLITE_SOUNDEX
/*
** Compute the soundex encoding of a word.
@@ -63118,75 +63462,6 @@
}
/*
-** The following array holds FuncDef structures for all of the functions
-** defined in this file.
-**
-** The array cannot be constant since changes are made to the
-** FuncDef.pHash elements at start-time. The elements of this array
-** are read-only after initialization is complete.
-*/
-static FuncDef aBuiltinFunc[] = {
- FUNCTION(ltrim, 1, 1, 0, trimFunc ),
- FUNCTION(ltrim, 2, 1, 0, trimFunc ),
- FUNCTION(rtrim, 1, 2, 0, trimFunc ),
- FUNCTION(rtrim, 2, 2, 0, trimFunc ),
- FUNCTION(trim, 1, 3, 0, trimFunc ),
- FUNCTION(trim, 2, 3, 0, trimFunc ),
- FUNCTION(min, -1, 0, 1, minmaxFunc ),
- FUNCTION(min, 0, 0, 1, 0 ),
- AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
- FUNCTION(max, -1, 1, 1, minmaxFunc ),
- FUNCTION(max, 0, 1, 1, 0 ),
- AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
- FUNCTION(typeof, 1, 0, 0, typeofFunc ),
- FUNCTION(length, 1, 0, 0, lengthFunc ),
- FUNCTION(substr, 2, 0, 0, substrFunc ),
- FUNCTION(substr, 3, 0, 0, substrFunc ),
- FUNCTION(abs, 1, 0, 0, absFunc ),
- FUNCTION(round, 1, 0, 0, roundFunc ),
- FUNCTION(round, 2, 0, 0, roundFunc ),
- FUNCTION(upper, 1, 0, 0, upperFunc ),
- FUNCTION(lower, 1, 0, 0, lowerFunc ),
- FUNCTION(coalesce, 1, 0, 0, 0 ),
- FUNCTION(coalesce, -1, 0, 0, ifnullFunc ),
- FUNCTION(coalesce, 0, 0, 0, 0 ),
- FUNCTION(hex, 1, 0, 0, hexFunc ),
- FUNCTION(ifnull, 2, 0, 1, ifnullFunc ),
- FUNCTION(random, -1, 0, 0, randomFunc ),
- FUNCTION(randomblob, 1, 0, 0, randomBlob ),
- FUNCTION(nullif, 2, 0, 1, nullifFunc ),
- FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
- FUNCTION(quote, 1, 0, 0, quoteFunc ),
- FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
- FUNCTION(changes, 0, 0, 0, changes ),
- FUNCTION(total_changes, 0, 0, 0, total_changes ),
- FUNCTION(replace, 3, 0, 0, replaceFunc ),
- FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
-#ifdef SQLITE_SOUNDEX
- FUNCTION(soundex, 1, 0, 0, soundexFunc ),
-#endif
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- FUNCTION(load_extension, 1, 0, 0, loadExt ),
- FUNCTION(load_extension, 2, 0, 0, loadExt ),
-#endif
- AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
- AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
- AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
- AGGREGATE(count, 0, 0, 0, countStep, countFinalize ),
- AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
- AGGREGATE(group_concat, -1, 0, 0, groupConcatStep, groupConcatFinalize),
-
- LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
-#ifdef SQLITE_CASE_SENSITIVE_LIKE
- LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
- LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
-#else
- LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
- LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
-#endif
-};
-
-/*
** All all of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table. This occurs at start-time (as
** a consequence of calling sqlite3_initialize()).
@@ -63194,9 +63469,81 @@
** After this routine runs
*/
SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
+ /*
+ ** The following array holds FuncDef structures for all of the functions
+ ** defined in this file.
+ **
+ ** The array cannot be constant since changes are made to the
+ ** FuncDef.pHash elements at start-time. The elements of this array
+ ** are read-only after initialization is complete.
+ */
+ static SQLITE_WSD FuncDef aBuiltinFunc[] = {
+ FUNCTION(ltrim, 1, 1, 0, trimFunc ),
+ FUNCTION(ltrim, 2, 1, 0, trimFunc ),
+ FUNCTION(rtrim, 1, 2, 0, trimFunc ),
+ FUNCTION(rtrim, 2, 2, 0, trimFunc ),
+ FUNCTION(trim, 1, 3, 0, trimFunc ),
+ FUNCTION(trim, 2, 3, 0, trimFunc ),
+ FUNCTION(min, -1, 0, 1, minmaxFunc ),
+ FUNCTION(min, 0, 0, 1, 0 ),
+ AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
+ FUNCTION(max, -1, 1, 1, minmaxFunc ),
+ FUNCTION(max, 0, 1, 1, 0 ),
+ AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
+ FUNCTION(typeof, 1, 0, 0, typeofFunc ),
+ FUNCTION(length, 1, 0, 0, lengthFunc ),
+ FUNCTION(substr, 2, 0, 0, substrFunc ),
+ FUNCTION(substr, 3, 0, 0, substrFunc ),
+ FUNCTION(abs, 1, 0, 0, absFunc ),
+ FUNCTION(round, 1, 0, 0, roundFunc ),
+ FUNCTION(round, 2, 0, 0, roundFunc ),
+ FUNCTION(upper, 1, 0, 0, upperFunc ),
+ FUNCTION(lower, 1, 0, 0, lowerFunc ),
+ FUNCTION(coalesce, 1, 0, 0, 0 ),
+ FUNCTION(coalesce, -1, 0, 0, ifnullFunc ),
+ FUNCTION(coalesce, 0, 0, 0, 0 ),
+ FUNCTION(hex, 1, 0, 0, hexFunc ),
+ FUNCTION(ifnull, 2, 0, 1, ifnullFunc ),
+ FUNCTION(random, -1, 0, 0, randomFunc ),
+ FUNCTION(randomblob, 1, 0, 0, randomBlob ),
+ FUNCTION(nullif, 2, 0, 1, nullifFunc ),
+ FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
+ FUNCTION(quote, 1, 0, 0, quoteFunc ),
+ FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
+ FUNCTION(changes, 0, 0, 0, changes ),
+ FUNCTION(total_changes, 0, 0, 0, total_changes ),
+ FUNCTION(replace, 3, 0, 0, replaceFunc ),
+ FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
+ #ifdef SQLITE_SOUNDEX
+ FUNCTION(soundex, 1, 0, 0, soundexFunc ),
+ #endif
+ #ifndef SQLITE_OMIT_LOAD_EXTENSION
+ FUNCTION(load_extension, 1, 0, 0, loadExt ),
+ FUNCTION(load_extension, 2, 0, 0, loadExt ),
+ #endif
+ AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
+ AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
+ AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
+ AGGREGATE(count, 0, 0, 0, countStep, countFinalize ),
+ AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
+ AGGREGATE(group_concat, -1, 0, 0, groupConcatStep, groupConcatFinalize),
+
+ LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ #ifdef SQLITE_CASE_SENSITIVE_LIKE
+ LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ #else
+ LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
+ LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
+ #endif
+ };
+
int i;
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc);
+
for(i=0; i<ArraySize(aBuiltinFunc); i++){
- sqlite3FuncDefInsert(&sqlite3GlobalFunctions, &aBuiltinFunc[i]);
+ sqlite3FuncDefInsert(pHash, &aFunc[i]);
}
sqlite3RegisterDateTimeFunctions();
}
@@ -65104,7 +65451,7 @@
** This file contains code used to dynamically load extensions into
** the SQLite library.
**
-** $Id: loadext.c,v 1.53 2008/08/02 03:50:39 drh Exp $
+** $Id: loadext.c,v 1.54 2008/09/02 00:52:52 drh Exp $
*/
#ifndef SQLITE_CORE
@@ -65930,10 +66277,26 @@
** This list is shared across threads. The SQLITE_MUTEX_STATIC_MASTER
** mutex must be held while accessing this list.
*/
-static struct {
+typedef struct sqlite3ExtType sqlite3ExtType;
+static SQLITE_WSD struct sqlite3ExtType {
int nExt; /* Number of entries in aExt[] */
void **aExt; /* Pointers to the extension init functions */
-} autoext = { 0, 0 };
+} sqlite3Autoext = { 0, 0 };
+
+/* The "wsdAutoext" macro will resolve to the autoextension
+** state vector. If writable static data is unsupported on the target,
+** we have to locate the state vector at run-time. In the more common
+** case where writable static data is supported, wsdStat can refer directly
+** to the "sqlite3Autoext" state vector declared above.
+*/
+#ifdef SQLITE_OMIT_WSD
+# define wsdAutoextInit \
+ sqlite3ExtType *x = &GLOBAL(sqlite3ExtType,sqlite3Autoext)
+# define wsdAutoext x[0]
+#else
+# define wsdAutoextInit
+# define wsdAutoext sqlite3Autoext
+#endif
/*
@@ -65953,20 +66316,21 @@
#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
+ wsdAutoextInit;
sqlite3_mutex_enter(mutex);
- for(i=0; i<autoext.nExt; i++){
- if( autoext.aExt[i]==xInit ) break;
+ for(i=0; i<wsdAutoext.nExt; i++){
+ if( wsdAutoext.aExt[i]==xInit ) break;
}
- if( i==autoext.nExt ){
- int nByte = (autoext.nExt+1)*sizeof(autoext.aExt[0]);
+ if( i==wsdAutoext.nExt ){
+ int nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
void **aNew;
- aNew = sqlite3_realloc(autoext.aExt, nByte);
+ aNew = sqlite3_realloc(wsdAutoext.aExt, nByte);
if( aNew==0 ){
rc = SQLITE_NOMEM;
}else{
- autoext.aExt = aNew;
- autoext.aExt[autoext.nExt] = xInit;
- autoext.nExt++;
+ wsdAutoext.aExt = aNew;
+ wsdAutoext.aExt[wsdAutoext.nExt] = xInit;
+ wsdAutoext.nExt++;
}
}
sqlite3_mutex_leave(mutex);
@@ -65986,10 +66350,11 @@
#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
+ wsdAutoextInit;
sqlite3_mutex_enter(mutex);
- sqlite3_free(autoext.aExt);
- autoext.aExt = 0;
- autoext.nExt = 0;
+ sqlite3_free(wsdAutoext.aExt);
+ wsdAutoext.aExt = 0;
+ wsdAutoext.nExt = 0;
sqlite3_mutex_leave(mutex);
}
}
@@ -66003,7 +66368,8 @@
int rc = SQLITE_OK;
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
- if( autoext.nExt==0 ){
+ wsdAutoextInit;
+ if( wsdAutoext.nExt==0 ){
/* Common case: early out without every having to acquire a mutex */
return SQLITE_OK;
}
@@ -66013,12 +66379,12 @@
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
sqlite3_mutex_enter(mutex);
- if( i>=autoext.nExt ){
+ if( i>=wsdAutoext.nExt ){
xInit = 0;
go = 0;
}else{
xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
- autoext.aExt[i];
+ wsdAutoext.aExt[i];
}
sqlite3_mutex_leave(mutex);
if( xInit && xInit(db, &zErrmsg, &sqlite3Apis) ){
@@ -66047,7 +66413,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
-** $Id: pragma.c,v 1.184 2008/08/20 16:34:24 danielk1977 Exp $
+** $Id: pragma.c,v 1.187 2008/09/16 14:38:03 danielk1977 Exp $
*/
/* Ignore this whole file if pragmas are disabled
@@ -66483,7 +66849,7 @@
*/
if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){
int eMode;
- static const char *azModeName[] = {"delete", "persist", "off"};
+ static char * const azModeName[] = {"delete", "persist", "off"};
if( zRight==0 ){
eMode = PAGER_JOURNALMODE_QUERY;
@@ -66700,10 +67066,12 @@
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
}
}else{
+#ifndef SQLITE_OMIT_WSD
if( zRight[0] ){
+ int rc;
int res;
- sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
- if( res==0 ){
+ rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
+ if( rc!=SQLITE_OK || res==0 ){
sqlite3ErrorMsg(pParse, "not a writable directory");
goto pragma_out;
}
@@ -66720,6 +67088,7 @@
}else{
sqlite3_temp_directory = 0;
}
+#endif /* SQLITE_OMIT_WSD */
}
}else
@@ -66766,11 +67135,7 @@
** spe_name: Specific name (unique procedure name)
*/
if( sqlite3StrICmp(zLeft, "proc_list")==0 ){
- Hash *func_hash;
- HashElem *func_elem;
-
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
- func_hash = &(db->aFunc);
sqlite3VdbeSetNumCols(v, 4);
pParse->nMem = 4;
@@ -67282,7 +67647,6 @@
|| sqlite3StrICmp(zLeft, "user_version")==0
|| sqlite3StrICmp(zLeft, "freelist_count")==0
){
-
int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */
sqlite3VdbeUsesBtree(v, iDb);
switch( zLeft[0] ){
@@ -67357,6 +67721,7 @@
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
+
}else
#endif
@@ -67437,7 +67802,7 @@
** interface, and routines that contribute to loading the database schema
** from disk.
**
-** $Id: prepare.c,v 1.93 2008/08/20 16:35:10 drh Exp $
+** $Id: prepare.c,v 1.97 2008/09/08 09:06:19 danielk1977 Exp $
*/
/*
@@ -67487,13 +67852,11 @@
}
assert( argc==3 );
+ assert( iDb>=0 && iDb<db->nDb );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[1]==0 ){
corruptSchema(pData, argv[0], 0);
- return 1;
- }
- assert( iDb>=0 && iDb<db->nDb );
- if( argv[2] && argv[2][0] ){
+ }else if( argv[2] && argv[2][0] ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
@@ -68114,7 +68477,7 @@
assert( pNew!=0 );
}
sqlite3VdbeSwap((Vdbe*)pNew, p);
- sqlite3_transfer_bindings(pNew, (sqlite3_stmt*)p);
+ sqlite3TransferBindings(pNew, (sqlite3_stmt*)p);
sqlite3VdbeResetStepResult((Vdbe*)pNew);
sqlite3VdbeFinalize((Vdbe*)pNew);
return 1;
@@ -68250,7 +68613,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.471 2008/08/26 12:56:14 drh Exp $
+** $Id: select.c,v 1.475 2008/09/17 00:13:12 drh Exp $
*/
@@ -68441,15 +68804,17 @@
*/
static void setQuotedToken(Parse *pParse, Token *p, const char *z){
- /* Check if the string contains any " characters. If it does, then
- ** this function will malloc space to create a quoted version of
- ** the string in. Otherwise, save a call to sqlite3MPrintf() by
- ** just copying the pointer to the string.
+ /* Check if the string appears to be quoted using "..." or `...`
+ ** or [...] or '...' or if the string contains any " characters.
+ ** If it does, then record a version of the string with the special
+ ** characters escaped.
*/
const char *z2 = z;
- while( *z2 ){
- if( *z2=='"' ) break;
- z2++;
+ if( *z2!='[' && *z2!='`' && *z2!='\'' ){
+ while( *z2 ){
+ if( *z2=='"' ) break;
+ z2++;
+ }
}
if( *z2 ){
@@ -69315,7 +69680,7 @@
if( pEList->a[i].zName ){
char *zName = pEList->a[i].zName;
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, strlen(zName));
- }else if( p->op==TK_COLUMN && pTabList ){
+ }else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) && pTabList ){
Table *pTab;
char *zCol;
int iCol = p->iColumn;
@@ -70664,6 +71029,9 @@
int iTable, /* Table to be replaced */
ExprList *pEList /* Substitute values */
){
+ SrcList *pSrc;
+ struct SrcList_item *pItem;
+ int i;
if( !p ) return;
substExprList(db, p->pEList, iTable, pEList);
substExprList(db, p->pGroupBy, iTable, pEList);
@@ -70671,6 +71039,12 @@
substExpr(db, p->pHaving, iTable, pEList);
substExpr(db, p->pWhere, iTable, pEList);
substSelect(db, p->pPrior, iTable, pEList);
+ pSrc = p->pSrc;
+ if( pSrc ){
+ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
+ substSelect(db, pItem->pSelect, iTable, pEList);
+ }
+ }
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
@@ -70955,17 +71329,31 @@
** elements we are now copying in.
*/
if( pSrc ){
+ Table *pTabToDel;
pSubitem = &pSrc->a[iFrom];
nSubSrc = pSubSrc->nSrc;
jointype = pSubitem->jointype;
- sqlite3DeleteTable(pSubitem->pTab);
sqlite3DbFree(db, pSubitem->zDatabase);
sqlite3DbFree(db, pSubitem->zName);
sqlite3DbFree(db, pSubitem->zAlias);
- pSubitem->pTab = 0;
pSubitem->zDatabase = 0;
pSubitem->zName = 0;
pSubitem->zAlias = 0;
+
+ /* If the FROM element is a subquery, defer deleting the Table
+ ** object associated with that subquery until code generation is
+ ** complete, since there may still exist Expr.pTab entires that
+ ** refer to the subquery even after flattening. Ticket #3346.
+ */
+ if( (pTabToDel = pSubitem->pTab)!=0 ){
+ if( pTabToDel->nRef==1 ){
+ pTabToDel->pNextZombie = pParse->pZombieTab;
+ pParse->pZombieTab = pTabToDel;
+ }else{
+ pTabToDel->nRef--;
+ }
+ }
+ pSubitem->pTab = 0;
}
if( nSubSrc!=1 || !pSrc ){
int extra = nSubSrc - 1;
@@ -71862,20 +72250,25 @@
** processed */
int iAbortFlag; /* Mem address which causes query abort if positive */
int groupBySort; /* Rows come from source in GROUP BY order */
+ int addrEnd; /* End of processing for this SELECT */
+ /* Remove any and all aliases between the result set and the
+ ** GROUP BY clause.
+ */
+ if( pGroupBy ){
+ int i; /* Loop counter */
+ struct ExprList_item *pItem; /* For looping over expression in a list */
- /* The following variables hold addresses or labels for parts of the
- ** virtual machine program we are putting together */
- int addrOutputRow; /* Start of subroutine that outputs a result row */
- int regOutputRow; /* Return address register for output subroutine */
- int addrSetAbort; /* Set the abort flag and return */
- int addrInitializeLoop; /* Start of code that initializes the input loop */
- int addrTopOfLoop; /* Top of the input loop */
- int addrEnd; /* End of all processing */
- int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
- int addrReset; /* Subroutine for resetting the accumulator */
- int regReset; /* Return address register for reset subroutine */
+ for(i=p->pEList->nExpr, pItem=p->pEList->a; i>0; i--, pItem++){
+ pItem->iAlias = 0;
+ }
+ for(i=pGroupBy->nExpr, pItem=pGroupBy->a; i>0; i--, pItem++){
+ pItem->iAlias = 0;
+ }
+ }
+
+ /* Create a label to jump to when we want to abort the query */
addrEnd = sqlite3VdbeMakeLabel(v);
/* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
@@ -71904,11 +72297,14 @@
*/
if( pGroupBy ){
KeyInfo *pKeyInfo; /* Keying information for the group by clause */
- int j1;
-
- /* Create labels that we will be needing
- */
- addrInitializeLoop = sqlite3VdbeMakeLabel(v);
+ int j1; /* A-vs-B comparision jump */
+ int addrOutputRow; /* Start of subroutine that outputs a result row */
+ int regOutputRow; /* Return address register for output subroutine */
+ int addrSetAbort; /* Set the abort flag and return */
+ int addrTopOfLoop; /* Top of the input loop */
+ int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
+ int addrReset; /* Subroutine for resetting the accumulator */
+ int regReset; /* Return address register for reset subroutine */
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
@@ -71925,6 +72321,10 @@
*/
iUseFlag = ++pParse->nMem;
iAbortFlag = ++pParse->nMem;
+ regOutputRow = ++pParse->nMem;
+ addrOutputRow = sqlite3VdbeMakeLabel(v);
+ regReset = ++pParse->nMem;
+ addrReset = sqlite3VdbeMakeLabel(v);
iAMem = pParse->nMem + 1;
pParse->nMem += pGroupBy->nExpr;
iBMem = pParse->nMem + 1;
@@ -71933,47 +72333,12 @@
VdbeComment((v, "clear abort flag"));
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
VdbeComment((v, "indicate accumulator empty"));
- sqlite3VdbeAddOp2(v, OP_Goto, 0, addrInitializeLoop);
-
- /* Generate a subroutine that outputs a single row of the result
- ** set. This subroutine first looks at the iUseFlag. If iUseFlag
- ** is less than or equal to zero, the subroutine is a no-op. If
- ** the processing calls for the query to abort, this subroutine
- ** increments the iAbortFlag memory location before returning in
- ** order to signal the caller to abort.
- */
- addrSetAbort = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag);
- VdbeComment((v, "set abort flag"));
- regOutputRow = ++pParse->nMem;
- sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- addrOutputRow = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
- VdbeComment((v, "Groupby result generator entry point"));
- sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- finalizeAggFunctions(pParse, &sAggInfo);
- if( pHaving ){
- sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
- }
- selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
- distinct, pDest,
- addrOutputRow+1, addrSetAbort);
- sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- VdbeComment((v, "end groupby result generator"));
-
- /* Generate a subroutine that will reset the group-by accumulator
- */
- addrReset = sqlite3VdbeCurrentAddr(v);
- regReset = ++pParse->nMem;
- resetAccumulator(pParse, &sAggInfo);
- sqlite3VdbeAddOp1(v, OP_Return, regReset);
/* Begin a loop that will extract all source rows in GROUP BY order.
** This might involve two separate loops with an OP_Sort in between, or
** it might be a single loop that uses an index to extract information
** in the right order to begin with.
*/
- sqlite3VdbeResolveLabel(v, addrInitializeLoop);
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0);
if( pWInfo==0 ) goto select_end;
@@ -72091,7 +72456,43 @@
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
VdbeComment((v, "output final row"));
-
+
+ /* Jump over the subroutines
+ */
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEnd);
+
+ /* Generate a subroutine that outputs a single row of the result
+ ** set. This subroutine first looks at the iUseFlag. If iUseFlag
+ ** is less than or equal to zero, the subroutine is a no-op. If
+ ** the processing calls for the query to abort, this subroutine
+ ** increments the iAbortFlag memory location before returning in
+ ** order to signal the caller to abort.
+ */
+ addrSetAbort = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag);
+ VdbeComment((v, "set abort flag"));
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
+ sqlite3VdbeResolveLabel(v, addrOutputRow);
+ addrOutputRow = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
+ VdbeComment((v, "Groupby result generator entry point"));
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
+ finalizeAggFunctions(pParse, &sAggInfo);
+ if( pHaving ){
+ sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
+ }
+ selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
+ distinct, pDest,
+ addrOutputRow+1, addrSetAbort);
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
+ VdbeComment((v, "end groupby result generator"));
+
+ /* Generate a subroutine that will reset the group-by accumulator
+ */
+ sqlite3VdbeResolveLabel(v, addrReset);
+ resetAccumulator(pParse, &sAggInfo);
+ sqlite3VdbeAddOp1(v, OP_Return, regReset);
+
} /* endif pGroupBy */
else {
ExprList *pMinMax = 0;
@@ -73361,7 +73762,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.183 2008/08/22 12:30:52 drh Exp $
+** $Id: update.c,v 1.184 2008/09/01 21:59:43 shane Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -73676,9 +74077,11 @@
/* If we are trying to update a view, realize that view into
** a ephemeral table.
*/
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
}
+#endif
/* Resolve the column names in all the expressions in the
** WHERE clause.
@@ -75187,7 +75590,7 @@
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
-** $Id: where.c,v 1.321 2008/08/25 12:08:22 drh Exp $
+** $Id: where.c,v 1.322 2008/09/06 14:19:11 danielk1977 Exp $
*/
/*
@@ -77593,6 +77996,7 @@
nxt = pLevel->nxt;
sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, nxt);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, nxt, r1);
+ sqlite3ReleaseTempReg(pParse, r1);
VdbeComment((v, "pk"));
pLevel->op = OP_Noop;
}else if( pLevel->flags & WHERE_ROWID_RANGE ){
@@ -81243,7 +81647,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
-** $Id: tokenize.c,v 1.151 2008/08/29 02:14:03 drh Exp $
+** $Id: tokenize.c,v 1.152 2008/09/01 15:52:11 drh Exp $
*/
/*
@@ -81845,6 +82249,11 @@
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
sqlite3DbFree(db, pParse->apVarExpr);
sqlite3DbFree(db, pParse->aAlias);
+ while( pParse->pZombieTab ){
+ Table *p = pParse->pZombieTab;
+ pParse->pZombieTab = p->pNextZombie;
+ sqlite3DeleteTable(p);
+ }
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
pParse->rc = SQLITE_ERROR;
}
@@ -82148,7 +82557,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.494 2008/08/27 19:01:58 danielk1977 Exp $
+** $Id: main.c,v 1.500 2008/09/08 08:08:09 danielk1977 Exp $
*/
#ifdef SQLITE_ENABLE_FTS3
@@ -82215,6 +82624,39 @@
/************** End of rtree.h ***********************************************/
/************** Continuing where we left off in main.c ***********************/
#endif
+#ifdef SQLITE_ENABLE_ICU
+/************** Include sqliteicu.h in the middle of main.c ******************/
+/************** Begin file sqliteicu.h ***************************************/
+/*
+** 2008 May 26
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This header file is used by programs that want to link against the
+** ICU extension. All it does is declare the sqlite3IcuInit() interface.
+*/
+
+#if 0
+extern "C" {
+#endif /* __cplusplus */
+
+SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db);
+
+#if 0
+} /* extern "C" */
+#endif /* __cplusplus */
+
+
+/************** End of sqliteicu.h *******************************************/
+/************** Continuing where we left off in main.c ***********************/
+#endif
/*
** The version of the library
@@ -82275,16 +82717,22 @@
** without blocking.
*/
SQLITE_API int sqlite3_initialize(void){
- static int inProgress = 0; /* Prevent recursion */
- sqlite3_mutex *pMaster; /* The main static mutex */
- int rc; /* Result code */
+ sqlite3_mutex *pMaster; /* The main static mutex */
+ int rc; /* Result code */
+
+#ifdef SQLITE_OMIT_WSD
+ rc = sqlite3_wsd_init(4096, 24);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+#endif
/* If SQLite is already completely initialized, then this call
** to sqlite3_initialize() should be a no-op. But the initialization
** must be complete. So isInit must not be set until the very end
** of this routine.
*/
- if( sqlite3Config.isInit ) return SQLITE_OK;
+ if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
/* Make sure the mutex subsystem is initialized. If unable to
** initialize the mutex subsystem, return early with the error.
@@ -82305,18 +82753,18 @@
*/
pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(pMaster);
- if( !sqlite3Config.isMallocInit ){
+ if( !sqlite3GlobalConfig.isMallocInit ){
rc = sqlite3MallocInit();
}
if( rc==SQLITE_OK ){
- sqlite3Config.isMallocInit = 1;
- if( !sqlite3Config.pInitMutex ){
- sqlite3Config.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
- if( sqlite3Config.bCoreMutex && !sqlite3Config.pInitMutex ){
+ sqlite3GlobalConfig.isMallocInit = 1;
+ if( !sqlite3GlobalConfig.pInitMutex ){
+ sqlite3GlobalConfig.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
+ if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){
rc = SQLITE_NOMEM;
}
}
- sqlite3Config.nRefInitMutex++;
+ sqlite3GlobalConfig.nRefInitMutex++;
}
sqlite3_mutex_leave(pMaster);
@@ -82334,31 +82782,32 @@
** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other
** recursive calls might also be possible.
*/
- sqlite3_mutex_enter(sqlite3Config.pInitMutex);
- if( sqlite3Config.isInit==0 && inProgress==0 ){
- inProgress = 1;
- memset(&sqlite3GlobalFunctions, 0, sizeof(sqlite3GlobalFunctions));
+ sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex);
+ if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ sqlite3GlobalConfig.inProgress = 1;
+ memset(pHash, 0, sizeof(sqlite3GlobalFunctions));
sqlite3RegisterGlobalFunctions();
rc = sqlite3_os_init();
if( rc==SQLITE_OK ){
rc = sqlite3PcacheInitialize();
- sqlite3PCacheBufferSetup(sqlite3Config.pPage, sqlite3Config.szPage,
- sqlite3Config.nPage);
+ sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
+ sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
}
- inProgress = 0;
- sqlite3Config.isInit = (rc==SQLITE_OK ? 1 : 0);
+ sqlite3GlobalConfig.inProgress = 0;
+ sqlite3GlobalConfig.isInit = (rc==SQLITE_OK ? 1 : 0);
}
- sqlite3_mutex_leave(sqlite3Config.pInitMutex);
+ sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex);
/* Go back under the static mutex and clean up the recursive
** mutex to prevent a resource leak.
*/
sqlite3_mutex_enter(pMaster);
- sqlite3Config.nRefInitMutex--;
- if( sqlite3Config.nRefInitMutex<=0 ){
- assert( sqlite3Config.nRefInitMutex==0 );
- sqlite3_mutex_free(sqlite3Config.pInitMutex);
- sqlite3Config.pInitMutex = 0;
+ sqlite3GlobalConfig.nRefInitMutex--;
+ if( sqlite3GlobalConfig.nRefInitMutex<=0 ){
+ assert( sqlite3GlobalConfig.nRefInitMutex==0 );
+ sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex);
+ sqlite3GlobalConfig.pInitMutex = 0;
}
sqlite3_mutex_leave(pMaster);
@@ -82389,18 +82838,18 @@
** routine is not threadsafe. Not by a long shot.
*/
SQLITE_API int sqlite3_shutdown(void){
- sqlite3Config.isMallocInit = 0;
+ sqlite3GlobalConfig.isMallocInit = 0;
sqlite3PcacheShutdown();
- if( sqlite3Config.isInit ){
+ if( sqlite3GlobalConfig.isInit ){
sqlite3_os_end();
}
- if( sqlite3Config.m.xShutdown ){
+ if( sqlite3GlobalConfig.m.xShutdown ){
sqlite3MallocEnd();
}
- if( sqlite3Config.mutex.xMutexEnd ){
+ if( sqlite3GlobalConfig.mutex.xMutexEnd ){
sqlite3MutexEnd();
}
- sqlite3Config.isInit = 0;
+ sqlite3GlobalConfig.isInit = 0;
return SQLITE_OK;
}
@@ -82419,84 +82868,84 @@
/* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
** the SQLite library is in use. */
- if( sqlite3Config.isInit ) return SQLITE_MISUSE;
+ if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE;
va_start(ap, op);
switch( op ){
case SQLITE_CONFIG_SINGLETHREAD: {
/* Disable all mutexing */
- sqlite3Config.bCoreMutex = 0;
- sqlite3Config.bFullMutex = 0;
+ sqlite3GlobalConfig.bCoreMutex = 0;
+ sqlite3GlobalConfig.bFullMutex = 0;
break;
}
case SQLITE_CONFIG_MULTITHREAD: {
/* Disable mutexing of database connections */
/* Enable mutexing of core data structures */
- sqlite3Config.bCoreMutex = 1;
- sqlite3Config.bFullMutex = 0;
+ sqlite3GlobalConfig.bCoreMutex = 1;
+ sqlite3GlobalConfig.bFullMutex = 0;
break;
}
case SQLITE_CONFIG_SERIALIZED: {
/* Enable all mutexing */
- sqlite3Config.bCoreMutex = 1;
- sqlite3Config.bFullMutex = 1;
+ sqlite3GlobalConfig.bCoreMutex = 1;
+ sqlite3GlobalConfig.bFullMutex = 1;
break;
}
case SQLITE_CONFIG_MALLOC: {
/* Specify an alternative malloc implementation */
- sqlite3Config.m = *va_arg(ap, sqlite3_mem_methods*);
+ sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*);
break;
}
case SQLITE_CONFIG_GETMALLOC: {
/* Retrieve the current malloc() implementation */
- if( sqlite3Config.m.xMalloc==0 ) sqlite3MemSetDefault();
- *va_arg(ap, sqlite3_mem_methods*) = sqlite3Config.m;
+ if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault();
+ *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m;
break;
}
case SQLITE_CONFIG_MUTEX: {
/* Specify an alternative mutex implementation */
- sqlite3Config.mutex = *va_arg(ap, sqlite3_mutex_methods*);
+ sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*);
break;
}
case SQLITE_CONFIG_GETMUTEX: {
/* Retrieve the current mutex implementation */
- *va_arg(ap, sqlite3_mutex_methods*) = sqlite3Config.mutex;
+ *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex;
break;
}
case SQLITE_CONFIG_MEMSTATUS: {
/* Enable or disable the malloc status collection */
- sqlite3Config.bMemstat = va_arg(ap, int);
+ sqlite3GlobalConfig.bMemstat = va_arg(ap, int);
break;
}
case SQLITE_CONFIG_SCRATCH: {
/* Designate a buffer for scratch memory space */
- sqlite3Config.pScratch = va_arg(ap, void*);
- sqlite3Config.szScratch = va_arg(ap, int);
- sqlite3Config.nScratch = va_arg(ap, int);
+ sqlite3GlobalConfig.pScratch = va_arg(ap, void*);
+ sqlite3GlobalConfig.szScratch = va_arg(ap, int);
+ sqlite3GlobalConfig.nScratch = va_arg(ap, int);
break;
}
case SQLITE_CONFIG_PAGECACHE: {
/* Designate a buffer for scratch memory space */
- sqlite3Config.pPage = va_arg(ap, void*);
- sqlite3Config.szPage = va_arg(ap, int);
- sqlite3Config.nPage = va_arg(ap, int);
+ sqlite3GlobalConfig.pPage = va_arg(ap, void*);
+ sqlite3GlobalConfig.szPage = va_arg(ap, int);
+ sqlite3GlobalConfig.nPage = va_arg(ap, int);
break;
}
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
case SQLITE_CONFIG_HEAP: {
/* Designate a buffer for heap memory space */
- sqlite3Config.pHeap = va_arg(ap, void*);
- sqlite3Config.nHeap = va_arg(ap, int);
- sqlite3Config.mnReq = va_arg(ap, int);
+ sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
+ sqlite3GlobalConfig.nHeap = va_arg(ap, int);
+ sqlite3GlobalConfig.mnReq = va_arg(ap, int);
- if( sqlite3Config.pHeap==0 ){
+ if( sqlite3GlobalConfig.pHeap==0 ){
/* If the heap pointer is NULL, then restore the malloc implementation
** back to NULL pointers too. This will cause the malloc to go
** back to its default implementation when sqlite3_initialize() is
** run.
*/
- memset(&sqlite3Config.m, 0, sizeof(sqlite3Config.m));
+ memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));
}else{
/* The heap pointer is not NULL, then install one of the
** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor
@@ -82504,10 +82953,10 @@
** the default case and return an error.
*/
#ifdef SQLITE_ENABLE_MEMSYS3
- sqlite3Config.m = *sqlite3MemGetMemsys3();
+ sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
#endif
#ifdef SQLITE_ENABLE_MEMSYS5
- sqlite3Config.m = *sqlite3MemGetMemsys5();
+ sqlite3GlobalConfig.m = *sqlite3MemGetMemsys5();
#endif
}
break;
@@ -82516,15 +82965,15 @@
#if defined(SQLITE_ENABLE_MEMSYS6)
case SQLITE_CONFIG_CHUNKALLOC: {
- sqlite3Config.nSmall = va_arg(ap, int);
- sqlite3Config.m = *sqlite3MemGetMemsys6();
+ sqlite3GlobalConfig.nSmall = va_arg(ap, int);
+ sqlite3GlobalConfig.m = *sqlite3MemGetMemsys6();
break;
}
#endif
case SQLITE_CONFIG_LOOKASIDE: {
- sqlite3Config.szLookaside = va_arg(ap, int);
- sqlite3Config.nLookaside = va_arg(ap, int);
+ sqlite3GlobalConfig.szLookaside = va_arg(ap, int);
+ sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
break;
}
@@ -83609,15 +84058,21 @@
sqlite3 *db;
int rc;
CollSeq *pColl;
- int isThreadsafe = 1;
+ int isThreadsafe;
#ifndef SQLITE_OMIT_AUTOINIT
rc = sqlite3_initialize();
if( rc ) return rc;
#endif
- if( flags&SQLITE_OPEN_NOMUTEX ){
+ if( sqlite3GlobalConfig.bCoreMutex==0 ){
isThreadsafe = 0;
+ }else if( flags & SQLITE_OPEN_NOMUTEX ){
+ isThreadsafe = 0;
+ }else if( flags & SQLITE_OPEN_FULLMUTEX ){
+ isThreadsafe = 1;
+ }else{
+ isThreadsafe = sqlite3GlobalConfig.bFullMutex;
}
/* Remove harmful bits from the flags parameter */
@@ -83629,13 +84084,14 @@
SQLITE_OPEN_TEMP_JOURNAL |
SQLITE_OPEN_SUBJOURNAL |
SQLITE_OPEN_MASTER_JOURNAL |
- SQLITE_OPEN_NOMUTEX
+ SQLITE_OPEN_NOMUTEX |
+ SQLITE_OPEN_FULLMUTEX
);
/* Allocate the sqlite data structure */
db = sqlite3MallocZero( sizeof(sqlite3) );
if( db==0 ) goto opendb_out;
- if( sqlite3Config.bFullMutex && isThreadsafe ){
+ if( isThreadsafe ){
db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
if( db->mutex==0 ){
sqlite3_free(db);
@@ -83764,7 +84220,6 @@
#ifdef SQLITE_ENABLE_ICU
if( !db->mallocFailed && rc==SQLITE_OK ){
- extern int sqlite3IcuInit(sqlite3*);
rc = sqlite3IcuInit(db);
}
#endif
@@ -83788,11 +84243,11 @@
#endif
/* Enable the lookaside-malloc subsystem */
- setupLookaside(db, 0, sqlite3Config.szLookaside, sqlite3Config.nLookaside);
+ setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, sqlite3GlobalConfig.nLookaside);
opendb_out:
if( db ){
- assert( db->mutex!=0 || isThreadsafe==0 || sqlite3Config.bFullMutex==0 );
+ assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
sqlite3_mutex_leave(db->mutex);
}
rc = sqlite3_errcode(db);
@@ -86339,7 +86794,7 @@
short int nPhrase; /* How many following terms are part of the same phrase */
short int iPhrase; /* This is the i-th term of a phrase. */
short int iColumn; /* Column of the index that must match this term */
- signed char nNear; /* term followed by a NEAR operator with span=(nNear-1) */
+ short int nNear; /* term followed by a NEAR operator with span=(nNear-1) */
signed char isOr; /* this term is preceded by "OR" */
signed char isNot; /* this term is preceded by "-" */
signed char isPrefix; /* this term is followed by "*" */
@@ -88320,10 +88775,10 @@
}
/*
-** Parse the text at pSegment[0..nSegment-1]. Add additional terms
+** Parse the text at zSegment[0..nSegment-1]. Add additional terms
** to the query being assemblied in pQuery.
**
-** inPhrase is true if pSegment[0..nSegement-1] is contained within
+** inPhrase is true if zSegment[0..nSegement-1] is contained within
** double-quotes. If inPhrase is true, then the first term
** is marked with the number of terms in the phrase less one and
** OR and "-" syntax is ignored. If inPhrase is false, then every
@@ -88331,7 +88786,7 @@
*/
static int tokenizeSegment(
sqlite3_tokenizer *pTokenizer, /* The tokenizer to use */
- const char *pSegment, int nSegment, /* Query expression being parsed */
+ const char *zSegment, int nSegment, /* Query expression being parsed */
int inPhrase, /* True if within "..." */
Query *pQuery /* Append results here */
){
@@ -88341,49 +88796,45 @@
int iCol;
int nTerm = 1;
- int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor);
+ int rc = pModule->xOpen(pTokenizer, zSegment, nSegment, &pCursor);
if( rc!=SQLITE_OK ) return rc;
pCursor->pTokenizer = pTokenizer;
while( 1 ){
- const char *pToken;
+ const char *zToken;
int nToken, iBegin, iEnd, iPos;
rc = pModule->xNext(pCursor,
- &pToken, &nToken,
+ &zToken, &nToken,
&iBegin, &iEnd, &iPos);
if( rc!=SQLITE_OK ) break;
if( !inPhrase &&
- pSegment[iEnd]==':' &&
- (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){
+ zSegment[iEnd]==':' &&
+ (iCol = checkColumnSpecifier(pQuery->pFts, zToken, nToken))>=0 ){
pQuery->nextColumn = iCol;
continue;
}
if( !inPhrase && pQuery->nTerms>0 && nToken==2
- && pSegment[iBegin+0]=='O'
- && pSegment[iBegin+1]=='R'
+ && zSegment[iBegin+0]=='O'
+ && zSegment[iBegin+1]=='R'
){
pQuery->nextIsOr = 1;
continue;
}
if( !inPhrase && pQuery->nTerms>0 && !pQuery->nextIsOr && nToken==4
- && pSegment[iBegin+0]=='N'
- && pSegment[iBegin+1]=='E'
- && pSegment[iBegin+2]=='A'
- && pSegment[iBegin+3]=='R'
+ && memcmp(&zSegment[iBegin], "NEAR", 4)==0
){
QueryTerm *pTerm = &pQuery->pTerms[pQuery->nTerms-1];
if( (iBegin+6)<nSegment
- && pSegment[iBegin+4] == '/'
- && pSegment[iBegin+5]>='0' && pSegment[iBegin+5]<='9'
+ && zSegment[iBegin+4] == '/'
+ && isdigit(zSegment[iBegin+5])
){
- pTerm->nNear = (pSegment[iBegin+5] - '0');
- nToken += 2;
- if( pSegment[iBegin+6]>='0' && pSegment[iBegin+6]<=9 ){
- pTerm->nNear = pTerm->nNear * 10 + (pSegment[iBegin+6] - '0');
- iEnd++;
+ int k;
+ pTerm->nNear = 0;
+ for(k=5; (iBegin+k)<=nSegment && isdigit(zSegment[iBegin+k]); k++){
+ pTerm->nNear = pTerm->nNear*10 + (zSegment[iBegin+k] - '0');
}
- pModule->xNext(pCursor, &pToken, &nToken, &iBegin, &iEnd, &iPos);
+ pModule->xNext(pCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos);
} else {
pTerm->nNear = SQLITE_FTS3_DEFAULT_NEAR_PARAM;
}
@@ -88391,11 +88842,11 @@
continue;
}
- queryAdd(pQuery, pToken, nToken);
- if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){
+ queryAdd(pQuery, zToken, nToken);
+ if( !inPhrase && iBegin>0 && zSegment[iBegin-1]=='-' ){
pQuery->pTerms[pQuery->nTerms-1].isNot = 1;
}
- if( iEnd<nSegment && pSegment[iEnd]=='*' ){
+ if( iEnd<nSegment && zSegment[iEnd]=='*' ){
pQuery->pTerms[pQuery->nTerms-1].isPrefix = 1;
}
pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm;
@@ -93352,7 +93803,7 @@
** This file contains code for implementations of the r-tree and r*-tree
** algorithms packaged as an SQLite virtual table module.
**
-** $Id: rtree.c,v 1.7 2008/07/16 14:43:35 drh Exp $
+** $Id: rtree.c,v 1.9 2008/09/08 11:07:03 danielk1977 Exp $
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE)
@@ -94454,6 +94905,13 @@
pIdxInfo->idxNum = 1;
pIdxInfo->aConstraintUsage[ii].argvIndex = 1;
pIdxInfo->aConstraintUsage[jj].omit = 1;
+
+ /* This strategy involves a two rowid lookups on an B-Tree structures
+ ** and then a linear search of an R-Tree node. This should be
+ ** considered almost as quick as a direct rowid lookup (for which
+ ** sqlite uses an internal cost of 0.0).
+ */
+ pIdxInfo->estimatedCost = 10.0;
return SQLITE_OK;
}
@@ -94507,6 +94965,8 @@
if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){
return SQLITE_NOMEM;
}
+ assert( iIdx>=0 );
+ pIdxInfo->estimatedCost = (2000000.0 / (double)(iIdx + 1));
return rc;
}
@@ -94554,6 +95014,25 @@
}
/*
+** Return true if the area covered by p2 is a subset of the area covered
+** by p1. False otherwise.
+*/
+static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
+ int ii;
+ int isInt = (pRtree->eCoordType==RTREE_COORD_INT32);
+ for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ RtreeCoord *a1 = &p1->aCoord[ii];
+ RtreeCoord *a2 = &p2->aCoord[ii];
+ if( (!isInt && (a2[0].f<a1[0].f || a2[1].f>a1[1].f))
+ || ( isInt && (a2[0].i<a1[0].i || a2[1].i>a1[1].i))
+ ){
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
** Return the amount cell p would grow by if it were unioned with pCell.
*/
static float cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){
@@ -94719,7 +95198,7 @@
int iCell = nodeParentIndex(pRtree, p);
nodeGetCell(pRtree, pParent, iCell, &cell);
- if( cellGrowth(pRtree, &cell, pCell)>0.0 ){
+ if( !cellContains(pRtree, &cell, pCell) ){
cellUnion(pRtree, &cell, pCell);
nodeOverwriteCell(pRtree, pParent, &cell, iCell);
}
Modified: trunk/libgda/sqlite/sqlite-src/sqlite3.h
==============================================================================
--- trunk/libgda/sqlite/sqlite-src/sqlite3.h (original)
+++ trunk/libgda/sqlite/sqlite-src/sqlite3.h Thu Oct 9 18:37:46 2008
@@ -57,7 +57,7 @@
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
/* GCC added the deprecated attribute in version 3.1 */
#define SQLITE_DEPRECATED __attribute__ ((deprecated))
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) && (_MSC_VER>1200)
#define SQLITE_DEPRECATED __declspec(deprecated)
#else
#define SQLITE_DEPRECATED
@@ -70,7 +70,7 @@
/* I can confirm that it does not work on version 4.1.0... */
/* First appears in GCC docs for version 4.3.0 */
#define SQLITE_EXPERIMENTAL __attribute__ ((warning ("is experimental")))
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) && (_MSC_VER>1200)
#define SQLITE_EXPERIMENTAL __declspec(deprecated("was declared experimental"))
#else
#define SQLITE_EXPERIMENTAL
@@ -116,8 +116,8 @@
** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z
** are the major version, minor version, and release number.
*/
-#define SQLITE_VERSION "3.6.2"
-#define SQLITE_VERSION_NUMBER 3006002
+#define SQLITE_VERSION "3.6.3"
+#define SQLITE_VERSION_NUMBER 3006003
/*
** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
@@ -154,8 +154,9 @@
** CAPI3REF: Test To See If The Library Is Threadsafe {H10100} <S60100>
**
** SQLite can be compiled with or without mutexes. When
-** the [SQLITE_THREADSAFE] C preprocessor macro is true, mutexes
-** are enabled and SQLite is threadsafe. When that macro is false,
+** the [SQLITE_THREADSAFE] C preprocessor macro 1 or 2, mutexes
+** are enabled and SQLite is threadsafe. When the
+** [SQLITE_THREADSAFE] macro is 0,
** the mutexes are omitted. Without the mutexes, it is not safe
** to use SQLite concurrently from more than one thread.
**
@@ -177,12 +178,13 @@
** only the default compile-time setting, not any run-time changes
** to that setting.
**
+** See the [threading mode] documentation for additional information.
+**
** INVARIANTS:
**
** {H10101} The [sqlite3_threadsafe()] function shall return nonzero if
-** SQLite was compiled with the its mutexes enabled by default
-** or zero if SQLite was compiled such that mutexes are
-** permanently disabled.
+** and only if
+** SQLite was compiled with the its mutexes enabled by default.
**
** {H10102} The value returned by the [sqlite3_threadsafe()] function
** shall not change when mutex setting are modified at
@@ -1097,7 +1099,9 @@
** The application is responsible for serializing access to
** [database connections] and [prepared statements]. But other mutexes
** are enabled so that SQLite will be safe to use in a multi-threaded
-** environment.</dd>
+** environment as long as no two threads attempt to use the same
+** [database connection] at the same time. See the [threading mode]
+** documentation for additional information.</dd>
**
** <dt>SQLITE_CONFIG_SERIALIZED</dt>
** <dd>There are no arguments to this option. This option enables
@@ -1108,11 +1112,7 @@
** to [database connections] and [prepared statements] so that the
** application is free to use the same [database connection] or the
** same [prepared statement] in different threads at the same time.
-**
-** <p>This configuration option merely sets the default mutex
-** behavior to serialize access to [database connections]. Individual
-** [database connections] can override this setting
-** using the [SQLITE_OPEN_NOMUTEX] flag to [sqlite3_open_v2()].</p></dd>
+** See the [threading mode] documentation for additional information.</dd>
**
** <dt>SQLITE_CONFIG_MALLOC</dt>
** <dd>This option takes a single argument which is a pointer to an
@@ -1575,6 +1575,10 @@
** previously set handler. Note that calling [sqlite3_busy_timeout()]
** will also set or clear the busy handler.
**
+** The busy callback should not take any actions which modify the
+** database connection that invoked the busy handler. Any such actions
+** result in undefined behavior.
+**
** INVARIANTS:
**
** {H12311} The [sqlite3_busy_handler(D,C,A)] function shall replace
@@ -2103,6 +2107,11 @@
** previous call. Disable the authorizer by installing a NULL callback.
** The authorizer is disabled by default.
**
+** The authorizer callback must not do anything that will modify
+** the database connection that invoked the authorizer callback.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
** When [sqlite3_prepare_v2()] is used to prepare a statement, the
** statement might be reprepared during [sqlite3_step()] due to a
** schema change. Hence, the application should ensure that the
@@ -2327,7 +2336,12 @@
**
** If the progress callback returns non-zero, the operation is
** interrupted. This feature can be used to implement a
-** "Cancel" button on a GUI dialog box.
+** "Cancel" button on a GUI progress dialog box.
+**
+** The progress handler must not do anything that will modify
+** the database connection that invoked the progress handler.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
**
** INVARIANTS:
**
@@ -2390,7 +2404,7 @@
** except that it accepts two additional parameters for additional control
** over the new database connection. The flags parameter can take one of
** the following three values, optionally combined with the
-** [SQLITE_OPEN_NOMUTEX] flag:
+** [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags:
**
** <dl>
** <dt>[SQLITE_OPEN_READONLY]</dt>
@@ -2410,16 +2424,15 @@
**
** If the 3rd parameter to sqlite3_open_v2() is not one of the
** combinations shown above or one of the combinations shown above combined
-** with the [SQLITE_OPEN_NOMUTEX] flag, then the behavior is undefined.
+** with the [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags,
+** then the behavior is undefined.
**
-** If the [SQLITE_OPEN_NOMUTEX] flag is set, then mutexes on the
-** opened [database connection] are disabled and the appliation must
-** insure that access to the [database connection] and its associated
-** [prepared statements] is serialized. The [SQLITE_OPEN_NOMUTEX] flag
-** is the default behavior is SQLite is configured using the
-** [SQLITE_CONFIG_MULTITHREAD] or [SQLITE_CONFIG_SINGLETHREAD] options
-** to [sqlite3_config()]. The [SQLITE_OPEN_NOMUTEX] flag only makes a
-** difference when SQLite is in its default [SQLITE_CONFIG_SERIALIZED] mode.
+** If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
+** opens in the multi-thread [threading mode] as long as the single-thread
+** mode has not been set at compile-time or start-time. If the
+** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
+** in the serialized [threading mode] unless single-thread was
+** previously selected at compile-time or start-time.
**
** If the filename is ":memory:", then a private, temporary in-memory database
** is created for the connection. This in-memory database will vanish when
@@ -3838,7 +3851,8 @@
** characters. Any attempt to create a function with a longer name
** will result in [SQLITE_ERROR] being returned.
**
-** The third parameter is the number of arguments that the SQL function or
+** The third parameter (nArg)
+** is the number of arguments that the SQL function or
** aggregate takes. If this parameter is negative, then the SQL function or
** aggregate may take any number of arguments.
**
@@ -3869,72 +3883,91 @@
** functions with the same name but with either differing numbers of
** arguments or differing preferred text encodings. SQLite will use
** the implementation most closely matches the way in which the
-** SQL function is used.
+** SQL function is used. A function implementation with a non-negative
+** nArg parameter is a better match than a function implementation with
+** a negative nArg. A function where the preferred text encoding
+** matches the database encoding is a better
+** match than a function where the encoding is different.
+** A function where the encoding difference is between UTF16le and UTF16be
+** is a closer match than a function where the encoding difference is
+** between UTF8 and UTF16.
+**
+** Built-in functions may be overloaded by new application-defined functions.
+** The first application-defined function with a given name overrides all
+** built-in functions in the same [database connection] with the same name.
+** Subsequent application-defined functions of the same name only override
+** prior application-defined functions that are an exact match for the
+** number of parameters and preferred encoding.
+**
+** An application-defined function is permitted to call other
+** SQLite interfaces. However, such calls must not
+** close the database connection nor finalize or reset the prepared
+** statement in which the function is running.
**
** INVARIANTS:
**
-** {H16103} The [sqlite3_create_function16()] interface behaves exactly
-** like [sqlite3_create_function()] in every way except that it
-** interprets the zFunctionName argument as zero-terminated UTF-16
+** {H16103} The [sqlite3_create_function16(D,X,...)] interface shall behave
+** as [sqlite3_create_function(D,X,...)] in every way except that it
+** interprets the X argument as zero-terminated UTF-16
** native byte order instead of as zero-terminated UTF-8.
**
-** {H16106} A successful invocation of
-** the [sqlite3_create_function(D,X,N,E,...)] interface registers
+** {H16106} A successful invocation of the
+** [sqlite3_create_function(D,X,N,E,...)] interface shall register
** or replaces callback functions in the [database connection] D
** used to implement the SQL function named X with N parameters
** and having a preferred text encoding of E.
**
** {H16109} A successful call to [sqlite3_create_function(D,X,N,E,P,F,S,L)]
-** replaces the P, F, S, and L values from any prior calls with
+** shall replace the P, F, S, and L values from any prior calls with
** the same D, X, N, and E values.
**
-** {H16112} The [sqlite3_create_function(D,X,...)] interface fails with
-** a return code of [SQLITE_ERROR] if the SQL function name X is
+** {H16112} The [sqlite3_create_function(D,X,...)] interface shall fail
+** if the SQL function name X is
** longer than 255 bytes exclusive of the zero terminator.
**
-** {H16118} Either F must be NULL and S and L are non-NULL or else F
-** is non-NULL and S and L are NULL, otherwise
-** [sqlite3_create_function(D,X,N,E,P,F,S,L)] returns [SQLITE_ERROR].
+** {H16118} The [sqlite3_create_function(D,X,N,E,P,F,S,L)] interface
+** shall fail unless either F is NULL and S and L are non-NULL or
+*** F is non-NULL and S and L are NULL.
**
-** {H16121} The [sqlite3_create_function(D,...)] interface fails with an
+** {H16121} The [sqlite3_create_function(D,...)] interface shall fails with an
** error code of [SQLITE_BUSY] if there exist [prepared statements]
** associated with the [database connection] D.
**
-** {H16124} The [sqlite3_create_function(D,X,N,...)] interface fails with an
-** error code of [SQLITE_ERROR] if parameter N (specifying the number
-** of arguments to the SQL function being registered) is less
+** {H16124} The [sqlite3_create_function(D,X,N,...)] interface shall fail with
+** an error code of [SQLITE_ERROR] if parameter N is less
** than -1 or greater than 127.
**
** {H16127} When N is non-negative, the [sqlite3_create_function(D,X,N,...)]
-** interface causes callbacks to be invoked for the SQL function
+** interface shall register callbacks to be invoked for the
+** SQL function
** named X when the number of arguments to the SQL function is
** exactly N.
**
** {H16130} When N is -1, the [sqlite3_create_function(D,X,N,...)]
-** interface causes callbacks to be invoked for the SQL function
-** named X with any number of arguments.
+** interface shall register callbacks to be invoked for the SQL
+** function named X with any number of arguments.
**
** {H16133} When calls to [sqlite3_create_function(D,X,N,...)]
** specify multiple implementations of the same function X
** and when one implementation has N>=0 and the other has N=(-1)
-** the implementation with a non-zero N is preferred.
+** the implementation with a non-zero N shall be preferred.
**
** {H16136} When calls to [sqlite3_create_function(D,X,N,E,...)]
** specify multiple implementations of the same function X with
** the same number of arguments N but with different
** encodings E, then the implementation where E matches the
-** database encoding is preferred.
+** database encoding shall preferred.
**
** {H16139} For an aggregate SQL function created using
** [sqlite3_create_function(D,X,N,E,P,0,S,L)] the finalizer
-** function L will always be invoked exactly once if the
+** function L shall always be invoked exactly once if the
** step function S is called one or more times.
**
** {H16142} When SQLite invokes either the xFunc or xStep function of
** an application-defined SQL function or aggregate created
** by [sqlite3_create_function()] or [sqlite3_create_function16()],
** then the array of [sqlite3_value] objects passed as the
-** third parameter are always [protected sqlite3_value] objects.
+** third parameter shall be [protected sqlite3_value] objects.
*/
int sqlite3_create_function(
sqlite3 *db,
@@ -4846,6 +4879,14 @@
** If another function was previously registered, its
** pArg value is returned. Otherwise NULL is returned.
**
+** The callback implementation must not do anything that will modify
+** the database connection that invoked the callback. Any actions
+** to modify the database connection must be deferred until after the
+** completion of the [sqlite3_step()] call that triggered the commit
+** or rollback hook in the first place.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
** Registering a NULL function disables the callback.
**
** For the purposes of this API, a transaction is said to have been
@@ -4920,6 +4961,13 @@
** The update hook is not invoked when internal system tables are
** modified (i.e. sqlite_master and sqlite_sequence).
**
+** The update hook implementation must not do anything that will modify
+** the database connection that invoked the update hook. Any actions
+** to modify the database connection must be deferred until after the
+** completion of the [sqlite3_step()] call that triggered the update hook.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
** If another function was previously registered, its pArg value
** is returned. Otherwise NULL is returned.
**
@@ -6197,6 +6245,10 @@
*/
SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+
+int sqlite3_wsd_init(int N, int J);
+void *sqlite3_wsd_find(void *K, int L);
+
/*
** CAPI3REF: Status Parameters {H17250} <H17200>
** EXPERIMENTAL
Modified: trunk/libgda/sqlite/virtual/gda-vprovider-data-model.c
==============================================================================
--- trunk/libgda/sqlite/virtual/gda-vprovider-data-model.c (original)
+++ trunk/libgda/sqlite/virtual/gda-vprovider-data-model.c Thu Oct 9 18:37:46 2008
@@ -29,7 +29,6 @@
#include <sqlite3.h>
#include <libgda/gda-connection-private.h>
#include <libgda/gda-data-model-iter.h>
-#include <libgda/gda-data-proxy.h>
#include <libgda/gda-data-access-wrapper.h>
#include <libgda/gda-blob-op.h>
#include "../gda-sqlite.h"
@@ -237,6 +236,7 @@
virtualCommit, /* xCommit - commit transaction */
virtualRollback, /* xRollback - rollback transaction */
NULL, /* xFindFunction - function overloading */
+ NULL /* Rename - Notification that the table will be given a new name */
};
static GdaConnection *
@@ -329,7 +329,7 @@
typedef struct {
sqlite3_vtab base;
GdaVconnectionDataModel *cnc;
- GdaDataProxy *proxy;
+ GdaDataModel *wrapper;
GdaVConnectionTableData *td;
} VirtualTable;
@@ -345,7 +345,7 @@
virtualCreate (sqlite3 *db, void *pAux, int argc, const char *const *argv, sqlite3_vtab **ppVtab, char **pzErr)
{
GdaVconnectionDataModel *cnc = GDA_VCONNECTION_DATA_MODEL (pAux);
- GdaDataProxy *proxy = NULL;
+ GdaDataModel *wrapper = NULL;
GString *sql;
gint i, ncols;
gchar *spec_name;
@@ -368,32 +368,20 @@
/* preparations */
if (td->spec->data_model) {
- if (GDA_IS_DATA_PROXY (td->spec->data_model)) {
- proxy = (GdaDataProxy *) (td->spec->data_model);
- g_object_ref (G_OBJECT (proxy));
+ if (gda_data_model_get_access_flags (td->spec->data_model) & GDA_DATA_MODEL_ACCESS_RANDOM) {
+ wrapper = td->spec->data_model;
+ g_object_ref (wrapper);
}
else {
- if (gda_data_model_get_access_flags (td->spec->data_model) & GDA_DATA_MODEL_ACCESS_RANDOM)
- proxy = g_object_new (GDA_TYPE_DATA_PROXY,
- "model", td->spec->data_model,
- "sample-size", 0, NULL);
- else {
- /* no random access => use a wrapper */
- GdaDataModel *wrapper;
- wrapper = gda_data_access_wrapper_new (td->spec->data_model);
- proxy = (GdaDataProxy *) gda_data_proxy_new (wrapper);
- g_object_unref (wrapper);
- }
+ /* no random access => use a wrapper */
+ GdaDataModel *wrapper;
+ wrapper = gda_data_access_wrapper_new (td->spec->data_model);
}
- ncols = gda_data_proxy_get_proxied_model_n_cols (proxy);
- /* proxy settings */
- gda_data_proxy_set_sample_size (proxy, 0);
- g_object_set (G_OBJECT (proxy), "defer-sync", FALSE, NULL);
-
+ ncols = gda_data_model_get_n_columns (wrapper);
if (ncols <= 0) {
*pzErr = sqlite3_mprintf (_("Data model must have at least one column"));
- g_object_unref (proxy);
+ g_object_unref (wrapper);
return SQLITE_ERROR;
}
td->real_model = td->spec->data_model;
@@ -431,7 +419,7 @@
if (td->columns)
column = g_list_nth_data (td->columns, i);
else
- column = gda_data_model_describe_column ((GdaDataModel*) proxy, i);
+ column = gda_data_model_describe_column (wrapper, i);
if (!column) {
*pzErr = sqlite3_mprintf (_("Can't get data model description for column %d"), i);
g_string_free (sql, TRUE);
@@ -492,7 +480,7 @@
VirtualTable *vtable;
vtable = g_new0 (VirtualTable, 1);
vtable->cnc = cnc;
- vtable->proxy = proxy;
+ vtable->wrapper = wrapper;
vtable->td = td;
*ppVtab = &(vtable->base);
@@ -525,8 +513,8 @@
TRACE ();
- if (vtable->proxy)
- g_object_unref (vtable->proxy);
+ if (vtable->wrapper)
+ g_object_unref (vtable->wrapper);
g_free (vtable);
return SQLITE_OK;
}
@@ -545,8 +533,8 @@
if (vtable->td->spec->create_model_func) {
if (vtable->td->real_model)
g_object_unref (vtable->td->real_model);
- if (vtable->proxy)
- g_object_unref (vtable->proxy);
+ if (vtable->wrapper)
+ g_object_unref (vtable->wrapper);
vtable->td->real_model = vtable->td->spec->create_model_func (vtable->td->spec);
if (! vtable->td->columns && vtable->td->spec->create_columns_func)
@@ -569,16 +557,15 @@
/*g_print ("Created real model %p for table %s\n", vtable->td->real_model, vtable->td->table_name);*/
- if (GDA_IS_DATA_PROXY (vtable->td->real_model)) {
- vtable->proxy = (GdaDataProxy *) (vtable->td->real_model);
- g_object_ref (G_OBJECT (vtable->proxy));
+ if (gda_data_model_get_access_flags (vtable->td->real_model) & GDA_DATA_MODEL_ACCESS_RANDOM) {
+ vtable->wrapper = vtable->td->real_model;
+ g_object_ref (vtable->wrapper);
+ }
+ else {
+ /* no random access => use a wrapper */
+ GdaDataModel *wrapper;
+ vtable->wrapper = gda_data_access_wrapper_new (vtable->td->real_model);
}
- else
- vtable->proxy = (GdaDataProxy *) gda_data_proxy_new (vtable->td->real_model);
-
- /* proxy settings */
- gda_data_proxy_set_sample_size (vtable->proxy, 0);
- g_object_set (G_OBJECT (vtable->proxy), "defer-sync", FALSE, NULL);
}
}
@@ -593,7 +580,7 @@
virtual_table_manage_real_data_model (vtable);
cursor = g_new0 (VirtualCursor, 1);
- cursor->iter = gda_data_model_create_iter (GDA_DATA_MODEL (vtable->proxy));
+ cursor->iter = gda_data_model_create_iter (vtable->wrapper);
cursor->ncols = gda_data_model_get_n_columns (GDA_DATA_MODEL (vtable->td->real_model));
*ppCursor = &(cursor->base);
return SQLITE_OK;
@@ -607,7 +594,7 @@
TRACE ();
g_object_unref (cursor->iter);
- /* FIXME: destroy table->spec->model and table->proxy */
+ /* FIXME: destroy table->spec->model and table->wrapper */
g_free (cur);
return SQLITE_OK;
}
@@ -748,71 +735,96 @@
virtualUpdate (sqlite3_vtab *tab, int nData, sqlite3_value **apData, sqlite_int64 *pRowid)
{
VirtualTable *vtable = (VirtualTable *) tab;
+ const gchar *api_misuse_error = NULL;
TRACE ();
- if ((nData>1) && (sqlite3_value_type (apData[0])==SQLITE_INTEGER)) {
- /* UPDATE */
- gint i;
- for (i = 2; i < nData; i++) {
- GValue *value;
- GType type;
- gint rowid = sqlite3_value_int (apData [0]);
- gboolean res;
- GError *error = NULL;
+ /* REM: when using the values of apData[], the limit is
+ * (nData -1 ) and not nData because the last column of the corresponding CREATE TABLE ...
+ * is an internal hidden field which does not correspond to any column of the real data model
+ */
- /*g_print ("%d => %s\n", i, sqlite3_value_text (apData [i]));*/
- type = gda_column_get_g_type (gda_data_model_describe_column ((GdaDataModel*) vtable->proxy, i - 2));
- value = gda_value_new_from_string ((const gchar*) sqlite3_value_text (apData [i]), type);
- res = gda_data_model_set_value_at ((GdaDataModel*) vtable->proxy, i - 2, rowid, value, &error);
- gda_value_free (value);
- if (!res) {
- g_print ("Error: %s\n", error && error->message ? error->message : "???");
- return SQLITE_READONLY;
- }
- }
- return SQLITE_OK;
- }
- else if ((nData==1) && (sqlite3_value_type (apData[0])==SQLITE_INTEGER)) {
+ if (nData == 1) {
/* DELETE */
- gint rowid = sqlite3_value_int (apData [0]);
- return gda_data_model_remove_row (GDA_DATA_MODEL (vtable->proxy), rowid, NULL) ? SQLITE_OK : SQLITE_READONLY;
+ if (sqlite3_value_type (apData[0]) == SQLITE_INTEGER) {
+ gint rowid = sqlite3_value_int (apData [0]);
+ return gda_data_model_remove_row (vtable->wrapper, rowid, NULL) ? SQLITE_OK : SQLITE_READONLY;
+ }
+ else {
+ api_misuse_error = "argc==1 and argv[0] is not an integer";
+ goto api_misuse;
+ }
}
- else if ((nData>2) && (sqlite3_value_type (apData[0])==SQLITE_NULL)) {
+ else if ((nData > 1) && (sqlite3_value_type (apData[0]) == SQLITE_NULL)) {
/* INSERT */
gint newrow, i;
GList *values = NULL;
- newrow = gda_data_model_append_row (GDA_DATA_MODEL (vtable->proxy), NULL);
+ if (sqlite3_value_type (apData[1]) != SQLITE_NULL) {
+ /* argc>1 and argv[0] is not NULL: rowid is imposed by SQLite which is not supported */
+ return SQLITE_READONLY;
+ }
+
+ newrow = gda_data_model_append_row (vtable->wrapper, NULL);
if (newrow < 0)
return SQLITE_READONLY;
- for (i = 2; i < nData; i++) {
+ for (i = 2; i < (nData - 1); i++) {
GType type;
GValue *value;
- type = gda_column_get_g_type (gda_data_model_describe_column ((GdaDataModel*) vtable->proxy, i - 2));
+ type = gda_column_get_g_type (gda_data_model_describe_column (vtable->wrapper, i - 2));
if ((type != GDA_TYPE_NULL) && sqlite3_value_text (apData [i]))
value = gda_value_new_from_string ((const gchar*) sqlite3_value_text (apData [i]), type);
else
value = gda_value_new_null ();
- /*g_print ("TXT #%s# => value %p (type=%s)\n", sqlite3_value_text (apData [i]), value,
- g_type_name (type));*/
+ /*g_print ("TXT #%s# => value %p (type=%s) apData[]=%p\n", sqlite3_value_text (apData [i]), value,
+ g_type_name (type), apData[i]);*/
values = g_list_append (values, value);
}
- gda_data_model_set_values (GDA_DATA_MODEL (vtable->proxy), newrow, values, NULL);
+ gda_data_model_set_values (vtable->wrapper, newrow, values, NULL);
g_list_foreach (values, (GFunc) gda_value_free, NULL);
g_list_free (values);
*pRowid = newrow;
}
+ else if ((nData > 1) && (sqlite3_value_type (apData[0])==SQLITE_INTEGER)) {
+ /* UPDATE */
+ gint i;
+
+ if (sqlite3_value_int (apData[0]) != sqlite3_value_int (apData[1])) {
+ /* argc>1 and argv[0]==argv[1]: rowid is imposed by SQLite which is not supported */
+ return SQLITE_READONLY;
+ }
+ for (i = 2; i < (nData - 1); i++) {
+ GValue *value;
+ GType type;
+ gint rowid = sqlite3_value_int (apData [0]);
+ gboolean res;
+ GError *error = NULL;
+
+ /*g_print ("%d => %s\n", i, sqlite3_value_text (apData [i]));*/
+ type = gda_column_get_g_type (gda_data_model_describe_column (vtable->wrapper, i - 2));
+ value = gda_value_new_from_string ((const gchar*) sqlite3_value_text (apData [i]), type);
+ res = gda_data_model_set_value_at (vtable->wrapper, i - 2, rowid, value, &error);
+ gda_value_free (value);
+ if (!res) {
+ g_print ("Error: %s\n", error && error->message ? error->message : "???");
+ return SQLITE_READONLY;
+ }
+ }
+ return SQLITE_OK;
+ }
else {
- /* error */
- /* this case should never happen... */
- g_warning ("Invalid parameters provided by SQLite...");
- return SQLITE_ERROR;
+ api_misuse_error = "argc>1 and argv[0] is not NULL and not an integer";
+ goto api_misuse;
}
return SQLITE_OK;
+
+ api_misuse:
+ g_warning ("Error in the xUpdate SQLite's virtual method: %s\n"
+ "this is an SQLite error, please report it", api_misuse_error);
+ return SQLITE_ERROR;
}
static int
@@ -829,7 +841,6 @@
virtualSync (sqlite3_vtab *tab)
{
TRACE ();
-
return SQLITE_OK;
}
@@ -839,23 +850,7 @@
VirtualTable *vtable = (VirtualTable *) tab;
TRACE ();
-
- if (vtable->proxy) {
- GError *lerror = NULL;
- if (!gda_data_proxy_apply_all_changes (vtable->proxy, &lerror)) {
- g_warning ("VirtualCommit error: %s\n",
- lerror && lerror->message ? lerror->message : "No detail");
- if (lerror)
- g_error_free (lerror);
- TO_IMPLEMENT; /* FIXME: the error code does not seem to be taken into account by SQLite
- * => maybe the xCommit is not used in the correct context! */
- return SQLITE_ERROR;
- }
- else
- return SQLITE_OK;
- }
- else
- return SQLITE_OK;
+ return SQLITE_OK;
}
static int
@@ -864,6 +859,5 @@
VirtualTable *vtable = (VirtualTable *) tab;
TRACE ();
-
- return gda_data_proxy_cancel_all_changes (vtable->proxy) ? SQLITE_OK : SQLITE_ERROR;
+ return SQLITE_OK;
}
Modified: trunk/tests/data-models/check_virtual.c
==============================================================================
--- trunk/tests/data-models/check_virtual.c (original)
+++ trunk/tests/data-models/check_virtual.c Thu Oct 9 18:37:46 2008
@@ -57,13 +57,14 @@
/* compute list of countries where population >= 1M */
- if (! run_sql_non_select (cnc, "INSERT INTO results SELECT co.name, sum (ci.population) as pop FROM country co INNER JOIN city ci ON (co.code=ci.countrycode) GROUP BY co.name HAVING sum (ci.population) > 10000000;"))
+ if (! run_sql_non_select (cnc, "INSERT INTO results SELECT co.name, sum (ci.population) as pop FROM country co INNER JOIN city ci ON (co.code=ci.countrycode) GROUP BY co.name HAVING sum (ci.population) > 10000000 ORDER BY co.name DESC"))
g_error ("Could not run computation query");
/* save resulting data model to CSV */
gchar *export, *expected;
export = gda_data_model_export_to_string (rw_model, GDA_DATA_MODEL_IO_TEXT_SEPARATED,
NULL, 0, NULL, 0, NULL);
+ g_file_set_contents ("toto.csv", export, -1, NULL);
file = g_build_filename (CHECK_FILES, "tests", "data-models", "check_virtual.csv", NULL);
if (!g_file_get_contents (file, &expected, NULL, NULL))
return EXIT_FAILURE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]