Merge the latest trunk enhancements into the bedrock branch.
FossilOrigin-Name: 707f79c70c8b0fd889aede8806148457c691a008d0ce030084ba79f1e66ec53d
This commit is contained in:
commit
7936fef022
@ -1829,8 +1829,8 @@ $(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLIT
|
||||
/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
|
||||
# <<mark>>
|
||||
sqldiff.exe: $(TOP)\tool\sqldiff.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
|
||||
sqldiff.exe: $(TOP)\tool\sqldiff.c $(TOP)\ext\consio\console_io.h $(TOP)\ext\consio\console_io.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -I$(TOP)\ext\consio $(TOP)\tool\sqldiff.c $(TOP)\ext\consio\console_io.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
|
||||
|
||||
dbhash.exe: $(TOP)\tool\dbhash.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\tool\dbhash.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
@ -2551,7 +2551,7 @@ smoketest: $(TESTPROGS)
|
||||
shelltest: $(TESTPROGS)
|
||||
.\testfixture.exe $(TOP)\test\permutations.test shell
|
||||
|
||||
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(SQLITE_TCL_DEP)
|
||||
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(TOP)\ext\consio\console_io.h $(TOP)\ext\consio\console_io.c $(SQLITE_TCL_DEP)
|
||||
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
|
||||
|
||||
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
|
||||
|
@ -24,9 +24,11 @@
|
||||
# include <stdlib.h>
|
||||
# include <limits.h>
|
||||
# include <assert.h>
|
||||
# include "console_io.h"
|
||||
# include "sqlite3.h"
|
||||
#endif
|
||||
#ifndef HAVE_CONSOLE_IO_H
|
||||
# include "console_io.h"
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
# if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
|
||||
|
@ -28,7 +28,7 @@
|
||||
** CIO_WIN_WC_XLATE is defined as 0 or 1, reflecting whether console I/O
|
||||
** translation for Windows is effected for the build.
|
||||
*/
|
||||
|
||||
#define HAVE_CONSOLE_IO_H 1
|
||||
#ifndef SQLITE_INTERNAL_LINKAGE
|
||||
# define SQLITE_INTERNAL_LINKAGE extern /* external to translation unit */
|
||||
# include <stdio.h>
|
||||
|
@ -1887,7 +1887,7 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
Fts5Expr **ppNew
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */
|
||||
Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */
|
||||
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
|
||||
TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */
|
||||
if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
|
||||
@ -1908,7 +1908,7 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
|
||||
sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){
|
||||
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
|
||||
if( pColsetOrig ){
|
||||
sqlite3_int64 nByte;
|
||||
|
@ -2732,8 +2732,8 @@ static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
|
||||
int rc = SQLITE_OK;
|
||||
fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
|
||||
fts5TripCursors(pTab);
|
||||
pTab->p.pConfig->pgsz = 0;
|
||||
if( (iSavepoint+1)<=pTab->iSavepoint ){
|
||||
pTab->p.pConfig->pgsz = 0;
|
||||
rc = sqlite3Fts5StorageRollback(pTab->pStorage);
|
||||
}
|
||||
return rc;
|
||||
|
@ -515,5 +515,25 @@ do_execsql_test 18.2 {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 19.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(text);
|
||||
CREATE TABLE t2(text);
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES('one');
|
||||
INSERT INTO t1 VALUES('two');
|
||||
INSERT INTO t1 VALUES('three');
|
||||
INSERT INTO t1 VALUES('one');
|
||||
INSERT INTO t1 VALUES('two');
|
||||
INSERT INTO t1 VALUES('three');
|
||||
SAVEPOINT one;
|
||||
INSERT INTO t2 VALUES('one');
|
||||
INSERT INTO t2 VALUES('two');
|
||||
INSERT INTO t2 VALUES('three');
|
||||
ROLLBACK TO one;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -36,6 +36,7 @@ if {[permutation]=="memsubsys1" || [permutation]=="mmap"} {
|
||||
|
||||
sqlite3_fts5_register_origintext db
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA page_size = 4096;
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize="origintext unicode61", tokendata=1
|
||||
);
|
||||
|
@ -256,7 +256,7 @@ public final class CApi {
|
||||
sqlite3_bind_nio_buffer().
|
||||
*/
|
||||
@Experimental
|
||||
public static int sqlite3_bind_blob(
|
||||
/*public*/ static int sqlite3_bind_blob(
|
||||
@NotNull sqlite3_stmt stmt, int ndx, @Nullable java.nio.ByteBuffer data,
|
||||
int begin, int n
|
||||
){
|
||||
@ -269,7 +269,7 @@ public final class CApi {
|
||||
final two arguments.
|
||||
*/
|
||||
@Experimental
|
||||
public static int sqlite3_bind_blob(
|
||||
/*public*/ static int sqlite3_bind_blob(
|
||||
@NotNull sqlite3_stmt stmt, int ndx, @Nullable java.nio.ByteBuffer data
|
||||
){
|
||||
return sqlite3_bind_nio_buffer(stmt, ndx, data, 0, -1);
|
||||
@ -346,7 +346,7 @@ public final class CApi {
|
||||
@see https://docs.oracle.com/javase/8/docs/api/java/nio/Buffer.html
|
||||
*/
|
||||
@Experimental
|
||||
public static native int sqlite3_bind_nio_buffer(
|
||||
/*public*/ static native int sqlite3_bind_nio_buffer(
|
||||
@NotNull sqlite3_stmt stmt, int ndx, @Nullable java.nio.ByteBuffer data,
|
||||
int beginPos, int howMany
|
||||
);
|
||||
@ -356,7 +356,7 @@ public final class CApi {
|
||||
contents, up to its limit() (as opposed to its capacity()).
|
||||
*/
|
||||
@Experimental
|
||||
public static int sqlite3_bind_nio_buffer(
|
||||
/*public*/ static int sqlite3_bind_nio_buffer(
|
||||
@NotNull sqlite3_stmt stmt, int ndx, @Nullable java.nio.ByteBuffer data
|
||||
){
|
||||
return sqlite3_bind_nio_buffer(stmt, ndx, data, 0, -1);
|
||||
@ -600,7 +600,7 @@ public final class CApi {
|
||||
sqlite3_blob_read() (0 on success).
|
||||
*/
|
||||
@Experimental
|
||||
public static int sqlite3_blob_read_nio_buffer(
|
||||
/*public*/ static int sqlite3_blob_read_nio_buffer(
|
||||
@NotNull sqlite3_blob src, int srcOffset,
|
||||
@NotNull java.nio.ByteBuffer tgt, int tgtOffset, int howMany
|
||||
){
|
||||
@ -624,7 +624,7 @@ public final class CApi {
|
||||
for any reason.
|
||||
*/
|
||||
@Experimental
|
||||
public static java.nio.ByteBuffer sqlite3_blob_read_nio_buffer(
|
||||
/*public*/ static java.nio.ByteBuffer sqlite3_blob_read_nio_buffer(
|
||||
@NotNull sqlite3_blob src, int srcOffset, int howMany
|
||||
){
|
||||
if( !JNI_SUPPORTS_NIO || src==null ) return null;
|
||||
@ -645,7 +645,7 @@ public final class CApi {
|
||||
Overload alias for sqlite3_blob_read_nio_buffer().
|
||||
*/
|
||||
@Experimental
|
||||
public static int sqlite3_blob_read(
|
||||
/*public*/ static int sqlite3_blob_read(
|
||||
@NotNull sqlite3_blob src, int srcOffset,
|
||||
@NotNull java.nio.ByteBuffer tgt,
|
||||
int tgtOffset, int howMany
|
||||
@ -668,7 +668,7 @@ public final class CApi {
|
||||
the result of the underlying call to sqlite3_blob_read().
|
||||
*/
|
||||
@Experimental
|
||||
public static int sqlite3_blob_read(
|
||||
/*public*/ static int sqlite3_blob_read(
|
||||
@NotNull sqlite3_blob src,
|
||||
@NotNull java.nio.ByteBuffer tgt
|
||||
){
|
||||
@ -727,7 +727,7 @@ public final class CApi {
|
||||
returns the result of the underlying call to sqlite3_blob_read().
|
||||
*/
|
||||
@Experimental
|
||||
public static int sqlite3_blob_write_nio_buffer(
|
||||
/*public*/ static int sqlite3_blob_write_nio_buffer(
|
||||
@NotNull sqlite3_blob tgt, int tgtOffset,
|
||||
@NotNull java.nio.ByteBuffer src,
|
||||
int srcOffset, int howMany
|
||||
@ -756,7 +756,7 @@ public final class CApi {
|
||||
of b.
|
||||
*/
|
||||
@Experimental
|
||||
public static int sqlite3_blob_write(
|
||||
/*public*/ static int sqlite3_blob_write(
|
||||
@NotNull sqlite3_blob tgt, int tgtOffset,
|
||||
@NotNull java.nio.ByteBuffer src
|
||||
){
|
||||
@ -770,7 +770,7 @@ public final class CApi {
|
||||
of tgt.
|
||||
*/
|
||||
@Experimental
|
||||
public static int sqlite3_blob_write(
|
||||
/*public*/ static int sqlite3_blob_write(
|
||||
@NotNull sqlite3_blob tgt,
|
||||
@NotNull java.nio.ByteBuffer src
|
||||
){
|
||||
@ -926,7 +926,7 @@ public final class CApi {
|
||||
would return null for the same inputs.
|
||||
*/
|
||||
@Experimental
|
||||
public static native java.nio.ByteBuffer sqlite3_column_nio_buffer(
|
||||
/*public*/ static native java.nio.ByteBuffer sqlite3_column_nio_buffer(
|
||||
@NotNull sqlite3_stmt stmt, int ndx
|
||||
);
|
||||
|
||||
@ -1848,7 +1848,7 @@ public final class CApi {
|
||||
then this function behaves like sqlite3_result_error_toobig().
|
||||
*/
|
||||
@Experimental
|
||||
public static native void sqlite3_result_nio_buffer(
|
||||
/*public*/ static native void sqlite3_result_nio_buffer(
|
||||
@NotNull sqlite3_context cx, @Nullable java.nio.ByteBuffer blob,
|
||||
int begin, int n
|
||||
);
|
||||
@ -1858,7 +1858,7 @@ public final class CApi {
|
||||
as the result blob content.
|
||||
*/
|
||||
@Experimental
|
||||
public static void sqlite3_result_nio_buffer(
|
||||
/*public*/ static void sqlite3_result_nio_buffer(
|
||||
@NotNull sqlite3_context cx, @Nullable java.nio.ByteBuffer blob
|
||||
){
|
||||
sqlite3_result_nio_buffer(cx, blob, 0, -1);
|
||||
@ -1963,7 +1963,7 @@ public final class CApi {
|
||||
sqlite3_result_nio_buffer().
|
||||
*/
|
||||
@Experimental
|
||||
public static void sqlite3_result_blob(
|
||||
/*public*/ static void sqlite3_result_blob(
|
||||
@NotNull sqlite3_context cx, @Nullable java.nio.ByteBuffer blob,
|
||||
int begin, int n
|
||||
){
|
||||
@ -1975,7 +1975,7 @@ public final class CApi {
|
||||
sqlite3_result_nio_buffer().
|
||||
*/
|
||||
@Experimental
|
||||
public static void sqlite3_result_blob(
|
||||
/*public*/ static void sqlite3_result_blob(
|
||||
@NotNull sqlite3_context cx, @Nullable java.nio.ByteBuffer blob
|
||||
){
|
||||
sqlite3_result_nio_buffer(cx, blob);
|
||||
@ -2387,7 +2387,7 @@ public final class CApi {
|
||||
would return null for the same input.
|
||||
*/
|
||||
@Experimental
|
||||
public static native java.nio.ByteBuffer sqlite3_value_nio_buffer(
|
||||
/*public*/ static native java.nio.ByteBuffer sqlite3_value_nio_buffer(
|
||||
@NotNull sqlite3_value v
|
||||
);
|
||||
|
||||
|
@ -625,10 +625,20 @@ public class TesterFts5 {
|
||||
"SELECT fts5_columntext(ft, 1) FROM ft('x') ORDER BY rowid",
|
||||
"[x, x, x y z, x z, x y z, x]"
|
||||
);
|
||||
do_execsql_test(db,
|
||||
"SELECT fts5_columntext(ft, 2) FROM ft('x') ORDER BY rowid",
|
||||
"[null, null, null, null, null, null]"
|
||||
);
|
||||
boolean threw = false;
|
||||
try{
|
||||
/* columntext() used to return NULLs when given an out-of bounds column
|
||||
but now results in a range error. */
|
||||
do_execsql_test(db,
|
||||
"SELECT fts5_columntext(ft, 2) FROM ft('x') ORDER BY rowid",
|
||||
"[null, null, null, null, null, null]"
|
||||
);
|
||||
}catch(Exception e){
|
||||
threw = true;
|
||||
affirm( e.getMessage().matches(".*column index out of range") );
|
||||
}
|
||||
affirm( threw );
|
||||
threw = false;
|
||||
|
||||
/* Test fts5_columntotalsize() */
|
||||
do_execsql_test(db,
|
||||
|
@ -42,7 +42,9 @@
|
||||
# 1) Consolidate the code generation for sqlite3*.*js into a script
|
||||
# which generates the makefile code, rather than using $(call) and
|
||||
# $(eval), or at least centralize the setup of the numerous vars
|
||||
# related to each build variant $(JS_BUILD_MODES).
|
||||
# related to each build variant $(JS_BUILD_MODES). (Update: an
|
||||
# external script was attempted but it's even less legible than the
|
||||
# $(eval) indirection going on in this file.
|
||||
#
|
||||
default: all
|
||||
#default: quick
|
||||
@ -51,9 +53,39 @@ MAKEFILE := $(lastword $(MAKEFILE_LIST))
|
||||
CLEAN_FILES :=
|
||||
DISTCLEAN_FILES := ./--dummy--
|
||||
release: oz
|
||||
# JS_BUILD_MODES exists solely to reduce repetition in documentation
|
||||
# below.
|
||||
|
||||
########################################################################
|
||||
# JS_BUILD_NAMES exists for documentation purposes only. It enumerates
|
||||
# the core build styles:
|
||||
#
|
||||
# - sqlite3 = canonical library build
|
||||
#
|
||||
# - sqlite3-wasmfs = WASMFS-capable library build
|
||||
#
|
||||
JS_BUILD_NAMES := sqlite3 sqlite3-wasmfs
|
||||
|
||||
########################################################################
|
||||
# JS_BUILD_MODES exists for documentation purposes only. It enumerates
|
||||
# the various "flavors" of build, each of which requires slight
|
||||
# customization of the output:
|
||||
#
|
||||
# - vanilla = plain-vanilla JS for use in browsers. This is the
|
||||
# canonical build mode.
|
||||
#
|
||||
# - esm = ES6 module, a.k.a. ESM, for use in browsers.
|
||||
#
|
||||
# - bundler-friendly = esm slightly tweaked for "bundler"
|
||||
# tools. Bundlers are invariably based on node.js, so these builds
|
||||
# are intended to be read at build-time by node.js but with a final
|
||||
# target of browsers.
|
||||
#
|
||||
# - node = for use by node.js for node.js, as opposed to by node.js on
|
||||
# behalf o browser-side code (use bundler-friendly for that). Note
|
||||
# that persistent storage (OPFS) is not available in these builds.
|
||||
#
|
||||
JS_BUILD_MODES := vanilla esm bunder-friendly node
|
||||
|
||||
########################################################################
|
||||
# Emscripten SDK home dir and related binaries...
|
||||
EMSDK_HOME ?= $(word 1,$(wildcard $(HOME)/emsdk $(HOME)/src/emsdk))
|
||||
emcc.bin ?= $(word 1,$(wildcard $(EMSDK_HOME)/upstream/emscripten/emcc) $(shell which emcc))
|
||||
@ -93,11 +125,14 @@ else
|
||||
maybe-wasm-strip = $(wasm-strip)
|
||||
endif
|
||||
|
||||
########################################################################
|
||||
# dir.top = the top dir of the canonical build tree, where
|
||||
# sqlite3.[ch] live.
|
||||
dir.top := ../..
|
||||
# Reminder: some Emscripten flags require absolute paths but we want
|
||||
# relative paths for most stuff simply to reduce noise. The
|
||||
# $(abspath...) GNU make function can transform relative paths to
|
||||
# absolute.
|
||||
# Maintenance reminder: some Emscripten flags require absolute paths
|
||||
# but we want relative paths for most stuff simply to reduce
|
||||
# noise. The $(abspath...) GNU make function can transform relative
|
||||
# paths to absolute.
|
||||
dir.wasm := $(patsubst %/,%,$(dir $(MAKEFILE)))
|
||||
dir.api := api
|
||||
dir.jacc := jaccwabyt
|
||||
@ -143,12 +178,14 @@ endif
|
||||
# Set up sqlite3.c and sqlite3.h...
|
||||
#
|
||||
# To build with SEE (https://sqlite.org/see), either put sqlite3-see.c
|
||||
# in the top of this build tree or pass
|
||||
# sqlite3.c=PATH_TO_sqlite3-see.c to the build. Note that only
|
||||
# encryption modules with no 3rd-party dependencies will currently
|
||||
# work here: AES256-OFB, AES128-OFB, and AES128-CCM. Not
|
||||
# coincidentally, those 3 modules are included in the sqlite3-see.c
|
||||
# bundle.
|
||||
# in $(dir.top) or pass sqlite3.c=PATH_TO_sqlite3-see.c to the $(MAKE)
|
||||
# invocation. Note that only encryption modules with no 3rd-party
|
||||
# dependencies will currently work here: AES256-OFB, AES128-OFB, and
|
||||
# AES128-CCM. Not coincidentally, those 3 modules are included in the
|
||||
# sqlite3-see.c bundle. Note, however, that distributing an SEE build
|
||||
# of the WASM on a public site is in violation of the SEE license
|
||||
# because it effectively provides a usable copy of the SEE build to
|
||||
# all visitors.
|
||||
#
|
||||
# A custom sqlite3.c must not have any spaces in its name.
|
||||
# $(sqlite3.canonical.c) must point to the sqlite3.c in
|
||||
@ -193,6 +230,10 @@ SQLITE_OPT = \
|
||||
# can be used to find errant uses of sqlite3_js_vfs_create_file()
|
||||
# in client code.
|
||||
|
||||
########################################################################@
|
||||
# It's important that sqlite3.h be built to completion before any
|
||||
# other parts of the build run, thus we use .NOTPARALLEL to disable
|
||||
# parallel build of that file and its dependants.
|
||||
.NOTPARALLEL: $(sqlite3.h)
|
||||
$(sqlite3.h):
|
||||
$(MAKE) -C $(dir.top) sqlite3.c
|
||||
@ -242,6 +283,7 @@ ifneq (,$(sqlite3_wasm_extra_init.c))
|
||||
cflags.wasm_extra_init := -DSQLITE_WASM_EXTRA_INIT
|
||||
endif
|
||||
|
||||
#########################################################################
|
||||
# bin.version-info = binary to output various sqlite3 version info for
|
||||
# embedding in the JS files and in building the distribution zip file.
|
||||
# It must NOT be in $(dir.tmp) because we need it to survive the
|
||||
@ -251,11 +293,12 @@ bin.version-info := $(dir.top)/version-info
|
||||
$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
|
||||
$(MAKE) -C $(dir.top) version-info
|
||||
|
||||
#########################################################################
|
||||
# bin.stripcomments is used for stripping C/C++-style comments from JS
|
||||
# files. The JS files contain large chunks of documentation which we
|
||||
# don't need for all builds. That app's -k flag is of particular
|
||||
# importance here, as it allows us to retain the opening comment
|
||||
# blocks, which contain the license header and version info.
|
||||
# block(s), which contain the license header and version info.
|
||||
bin.stripccomments := $(dir.tool)/stripccomments
|
||||
$(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE)
|
||||
$(CC) -o $@ $<
|
||||
@ -287,6 +330,9 @@ DISTCLEAN_FILES += $(bin.stripccomments)
|
||||
# c-pp.c was written specifically for the sqlite project's JavaScript
|
||||
# builds but is maintained as a standalone project:
|
||||
# https://fossil.wanderinghorse.net/r/c-pp
|
||||
#
|
||||
# Note that the SQLITE_... build flags used here have NO EFFECT on the
|
||||
# JS/WASM build. They are solely for use with $(bin.c-pp) itself.
|
||||
bin.c-pp := ./c-pp
|
||||
$(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE)
|
||||
$(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \
|
||||
@ -347,6 +393,7 @@ emcc_opt_full := $(emcc_opt) -g3
|
||||
# -Oz when small deliverable size is a priority.
|
||||
########################################################################
|
||||
|
||||
########################################################################
|
||||
# EXPORTED_FUNCTIONS.* = files for use with Emscripten's
|
||||
# -sEXPORTED_FUNCTION flag.
|
||||
EXPORTED_FUNCTIONS.api.main := $(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-api)
|
||||
@ -358,6 +405,7 @@ EXPORTED_FUNCTIONS.api := $(dir.tmp)/EXPORTED_FUNCTIONS.api
|
||||
$(EXPORTED_FUNCTIONS.api): $(EXPORTED_FUNCTIONS.api.in) $(sqlite3.c) $(MAKEFILE)
|
||||
cat $(EXPORTED_FUNCTIONS.api.in) > $@
|
||||
|
||||
########################################################################
|
||||
# sqlite3-license-version.js = generated JS file with the license
|
||||
# header and version info.
|
||||
sqlite3-license-version.js := $(dir.tmp)/sqlite3-license-version.js
|
||||
@ -370,20 +418,35 @@ sqlite3-api-build-version.js := $(dir.tmp)/sqlite3-api-build-version.js
|
||||
# sqlite3-api.jses = the list of JS files which make up
|
||||
# $(sqlite3-api.js.in), in the order they need to be assembled.
|
||||
sqlite3-api.jses := $(sqlite3-license-version.js)
|
||||
# sqlite3-api-prologue.js: initial boostrapping bits:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-api-prologue.js
|
||||
# whwhasm.js and jaccwabyt.js: Low-level utils, mostly replacing
|
||||
# Emscripten glue:
|
||||
sqlite3-api.jses += $(dir.common)/whwasmutil.js
|
||||
sqlite3-api.jses += $(dir.jacc)/jaccwabyt.js
|
||||
# sqlite3-api-glue.js Glues the previous part together:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-api-glue.js
|
||||
# $(sqlite3-api-build-version.js) = library version info
|
||||
sqlite3-api.jses += $(sqlite3-api-build-version.js)
|
||||
# sqlite3-api-oo1.js = the oo1 API:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-api-oo1.js
|
||||
# sqlite3-api-worker.js = the Worker1 API:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-api-worker1.js
|
||||
# sqlite3-v-helper = helper APIs for VFSes and VTABLEs:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-v-helper.js
|
||||
# sqlite3-vfs-opfs.c-pp.js = the first OPFS VFS:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs.c-pp.js
|
||||
# sqlite3-vfs-opfs-sahpool.c-pp.js = the second OPFS VFS:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs-sahpool.c-pp.js
|
||||
# sqlite3-api-cleanup.js = "finalizes" the build and cleans up
|
||||
# any extraneous global symbols which are needed temporarily
|
||||
# by the previous files.
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-api-cleanup.js
|
||||
|
||||
########################################################################
|
||||
# SOAP.js is an external API file which is part of our distribution
|
||||
# but not part of the sqlite3-api.js amalgamation.
|
||||
# but not part of the sqlite3-api.js amalgamation. It's a component of
|
||||
# the first OPFS VFS and necessarily an external file.
|
||||
SOAP.js := $(dir.api)/sqlite3-opfs-async-proxy.js
|
||||
SOAP.js.bld := $(dir.dout)/$(notdir $(SOAP.js))
|
||||
sqlite3-api.ext.jses += $(SOAP.js.bld)
|
||||
@ -438,7 +501,9 @@ endif
|
||||
# emcc flags for .c/.o.
|
||||
emcc.cflags :=
|
||||
emcc.cflags += -std=c99 -fPIC
|
||||
# -------------^^^^^^^^ we need c99 for $(sqlite3-wasm.c).
|
||||
# -------------^^^^^^^^ we need c99 for $(sqlite3-wasm.c), primarily
|
||||
# for variadic macros and snprintf() to implement
|
||||
# sqlite3_wasm_enum_json().
|
||||
emcc.cflags += -I. -I$(dir.top)
|
||||
########################################################################
|
||||
# emcc flags specific to building .js/.wasm files...
|
||||
@ -459,14 +524,16 @@ emcc.jsflags += -sIMPORTED_MEMORY
|
||||
emcc.jsflags += -sSTRICT_JS=0
|
||||
# STRICT_JS disabled due to:
|
||||
# https://github.com/emscripten-core/emscripten/issues/18610
|
||||
# TL;DR: does not work with MODULARIZE or EXPORT_ES6 as of version 3.1.31.
|
||||
# TL;DR: does not work with MODULARIZE or EXPORT_ES6 as of version
|
||||
# 3.1.31. The fix for that in newer emcc's is to throw a built-time
|
||||
# error if STRICT_JS is used together with those options.
|
||||
|
||||
# -sENVIRONMENT values for the various build modes:
|
||||
emcc.environment.vanilla := web,worker
|
||||
emcc.environment.bundler-friendly := $(emcc.environment.vanilla)
|
||||
emcc.environment.esm := $(emcc.environment.vanilla)
|
||||
emcc.environment.node := node
|
||||
# Note that adding "node" to the list for the other builds causes
|
||||
# Note that adding ",node" to the list for the other builds causes
|
||||
# Emscripten to generate code which confuses node: it cannot reliably
|
||||
# determine whether the build is for a browser or for node.
|
||||
|
||||
@ -518,13 +585,14 @@ emcc.jsflags += -sSTACK_SIZE=512KB
|
||||
# extern-post-js.js. However... using a temporary symbol name here
|
||||
# and then adding sqlite3InitModule() ourselves results in 2 global
|
||||
# symbols: we cannot "delete" the Emscripten-defined
|
||||
# $(sqlite3.js.init-func) because it's declared with "var".
|
||||
# $(sqlite3.js.init-func) from vanilla builds (as opposed to ESM
|
||||
# builds) because it's declared with "var".
|
||||
sqlite3.js.init-func := sqlite3InitModule
|
||||
emcc.jsflags += -sEXPORT_NAME=$(sqlite3.js.init-func)
|
||||
emcc.jsflags += -sGLOBAL_BASE=4096 # HYPOTHETICALLY keep func table indexes from overlapping w/ heap addr.
|
||||
#emcc.jsflags += -sSTRICT # fails due to missing __syscall_...()
|
||||
#emcc.jsflags += -sALLOW_UNIMPLEMENTED_SYSCALLS
|
||||
#emcc.jsflags += -sFILESYSTEM=0 # only for experimentation. sqlite3 needs the FS API
|
||||
#emcc.jsflags += -sFILESYSTEM=0 # only for experimentation. fiddle needs the FS API
|
||||
#emcc.jsflags += -sABORTING_MALLOC # only for experimentation
|
||||
emcc.jsflags += -sALLOW_TABLE_GROWTH
|
||||
# ^^^^ -sALLOW_TABLE_GROWTH is required for installing new SQL UDFs
|
||||
@ -568,15 +636,22 @@ emcc.jsflags += -sLLD_REPORT_UNDEFINED
|
||||
# -g3 debugging info, _huge_.
|
||||
########################################################################
|
||||
|
||||
########################################################################
|
||||
# $(sqlite3-api-build-version.js) injects the build version info into
|
||||
# the bundle in JSON form.
|
||||
$(sqlite3-api-build-version.js): $(bin.version-info) $(MAKEFILE)
|
||||
@echo "Making $@..."
|
||||
@{ \
|
||||
echo 'globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \
|
||||
echo -n ' sqlite3.version = '; \
|
||||
$(bin.version-info) --json; \
|
||||
echo ';'; \
|
||||
echo '});'; \
|
||||
echo 'globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \
|
||||
echo -n ' sqlite3.version = '; \
|
||||
$(bin.version-info) --json; \
|
||||
echo ';'; \
|
||||
echo '});'; \
|
||||
} > $@
|
||||
|
||||
########################################################################
|
||||
# $(sqlite3-license-version.js) contains the license header and
|
||||
# in-comment build version info.
|
||||
$(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js) \
|
||||
$(MAKEFILE)
|
||||
@echo "Making $@..."; { \
|
||||
@ -594,7 +669,11 @@ $(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js)
|
||||
########################################################################
|
||||
# --post-js and --pre-js are emcc flags we use to append/prepend JS to
|
||||
# the generated emscripten module file. These rules set up the core
|
||||
# pre/post files for use by the various builds.
|
||||
# pre/post files for use by the various builds. --pre-js is used to
|
||||
# inject code which needs to run as part of the pre-WASM-load phase.
|
||||
# --post-js injects code which runs after the WASM module is loaded
|
||||
# and includes the entirety of the library plus some
|
||||
# Emscripten-specific post-bootstrapping code.
|
||||
pre-js.js.in := $(dir.api)/pre-js.c-pp.js
|
||||
post-js.js.in := $(dir.tmp)/post-js.c-pp.js
|
||||
post-jses.js := \
|
||||
@ -612,18 +691,26 @@ $(post-js.js.in): $(post-jses.js) $(MAKEFILE)
|
||||
|
||||
########################################################################
|
||||
# call-make-pre-post is a $(call)able which creates rules for
|
||||
# pre-js-$(1)-$(2).js. $1 = the base name of the JS file on whose
|
||||
# behalf this pre-js is for (one of: sqlite3, sqlite3-wasmfs). $2 is
|
||||
# pre-js.$(1)-$(2).js. $1 = the base name of the JS file on whose
|
||||
# behalf this pre-js is for (one of: $(JS_BUILD_NAMES)). $2 is
|
||||
# the build mode: one of $(JS_BUILD_MODES). This sets up
|
||||
# --[extern-][pre/post]-js flags in $(pre-post-$(1)-$(2).flags) and
|
||||
# dependencies in $(pre-post-$(1)-$(2).deps). The resulting files get
|
||||
# filtered using $(C-PP.FILTER). Any flags necessary for such
|
||||
# filtering need to be set in $(c-pp.D.$(1)-$(2)) before $(call)ing
|
||||
# this.
|
||||
#
|
||||
# Maintenance note: a shell script was written to generate these rules
|
||||
# with the hope that it would make them more legible and maintainable,
|
||||
# but embedding makefile code in another language makes it even less
|
||||
# legible than having the level of $(eval) indirection which we have
|
||||
# here.
|
||||
define call-make-pre-post
|
||||
pre-post-$(1)-$(2).flags ?=
|
||||
pre-js.js.$(1)-$(2) := $$(dir.tmp)/pre-js.$(1)-$(2).intermediary.js
|
||||
$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2))))
|
||||
pre-js.js.$(1)-$(2).intermediary := $$(dir.tmp)/pre-js.$(1)-$(2).intermediary.js
|
||||
pre-js.js.$(1)-$(2) := $$(dir.tmp)/pre-js.$(1)-$(2).js
|
||||
#$$(error $$(pre-js.js.$(1)-$(2).intermediary) $$(pre-js.js.$(1)-$(2)))
|
||||
$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)-$(2).intermediary),$$(c-pp.D.$(1)-$(2))))
|
||||
post-js.js.$(1)-$(2) := $$(dir.tmp)/post-js.$(1)-$(2).js
|
||||
$$(eval $$(call C-PP.FILTER,$$(post-js.js.in),$$(post-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2))))
|
||||
extern-post-js.js.$(1)-$(2) := $$(dir.tmp)/extern-post-js.$(1)-$(2).js
|
||||
@ -634,8 +721,8 @@ pre-post-common.flags.$(1)-$(2) := \
|
||||
--extern-post-js=$$(extern-post-js.js.$(1)-$(2))
|
||||
pre-post-jses.$(1)-$(2).deps := $$(pre-post-jses.deps.common) \
|
||||
$$(post-js.js.$(1)-$(2)) $$(extern-post-js.js.$(1)-$(2))
|
||||
$$(dir.tmp)/pre-js-$(1)-$(2).js: $$(pre-js.js.$(1)-$(2)) $$(MAKEFILE)
|
||||
cp $$(pre-js.js.$(1)-$(2)) $$@
|
||||
$$(pre-js.js.$(1)-$(2)): $$(pre-js.js.$(1)-$(2).intermediary) $$(MAKEFILE)
|
||||
cp $$(pre-js.js.$(1)-$(2).intermediary) $$@
|
||||
@if [ sqlite3-wasmfs = $(1) ]; then \
|
||||
echo "delete Module[xNameOfInstantiateWasm] /*for WASMFS build*/;"; \
|
||||
elif [ sqlite3 != $(1) ]; then \
|
||||
@ -643,10 +730,10 @@ $$(dir.tmp)/pre-js-$(1)-$(2).js: $$(pre-js.js.$(1)-$(2)) $$(MAKEFILE)
|
||||
fi >> $$@
|
||||
pre-post-$(1)-$(2).deps := \
|
||||
$$(pre-post-jses.$(1)-$(2).deps) \
|
||||
$$(dir.tmp)/pre-js-$(1)-$(2).js
|
||||
$$(dir.tmp)/pre-js.$(1)-$(2).js
|
||||
pre-post-$(1)-$(2).flags += \
|
||||
$$(pre-post-common.flags.$(1)-$(2)) \
|
||||
--pre-js=$$(dir.tmp)/pre-js-$(1)-$(2).js
|
||||
--pre-js=$$(dir.tmp)/pre-js.$(1)-$(2).js
|
||||
endef
|
||||
# /post-js and pre-js
|
||||
########################################################################
|
||||
@ -683,8 +770,8 @@ sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles)
|
||||
# Upstream RFE:
|
||||
# https://github.com/emscripten-core/emscripten/issues/18237
|
||||
#
|
||||
# Maintenance reminder: Mac sed works differently than GNU sed, so
|
||||
# don't use sed for this.
|
||||
# Maintenance reminder: Mac sed works differently than GNU sed, so we
|
||||
# use awk instead of sed for this.
|
||||
define SQLITE3.xJS.ESM-EXPORT-DEFAULT
|
||||
if [ x1 = x$(1) ]; then \
|
||||
echo "Fragile workaround for emscripten/issues/18237. See SQLITE3.xJS.RECIPE."; \
|
||||
@ -700,6 +787,7 @@ if [ x1 = x$(1) ]; then \
|
||||
fi
|
||||
endef
|
||||
|
||||
########################################################################
|
||||
# extern-post-js* and extern-pre-js* are files for use with
|
||||
# Emscripten's --extern-pre-js and --extern-post-js flags.
|
||||
extern-pre-js.js := $(dir.api)/extern-pre-js.js
|
||||
@ -711,11 +799,12 @@ pre-post-common.flags := \
|
||||
# pre-post-jses.deps.* = a list of dependencies for the
|
||||
# --[extern-][pre/post]-js files.
|
||||
pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)
|
||||
|
||||
########################################################################
|
||||
# SETUP_LIB_BUILD_MODE is a $(call)'able which sets up numerous pieces
|
||||
# for one of the build modes.
|
||||
#
|
||||
# $1 = one of: sqlite3, sqlite3-wasmfs
|
||||
# $1 = one of: $(JS_BUILD_NAMES)
|
||||
# $2 = build mode name: one of $(JS_BUILD_MODES)
|
||||
# $3 = 1 for ESM build mode, else 0
|
||||
# $4 = resulting sqlite-api JS/MJS file
|
||||
@ -726,7 +815,8 @@ pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)
|
||||
# Maintenance reminder: be careful not to introduce spaces around args
|
||||
# ($1, $2), otherwise string concatenation will malfunction.
|
||||
#
|
||||
# emcc.environment.$(2) must be set to a value for the -sENVIRONMENT flag.
|
||||
# emcc.environment.$(2) must be set to a value for emcc's
|
||||
# -sENVIRONMENT flag.
|
||||
#
|
||||
# $(cflags.$(1)) and $(cflags.$(1).$(2)) may be defined to append
|
||||
# CFLAGS to a given build mode.
|
||||
@ -781,8 +871,7 @@ sqlite3-node.mjs := $(dir.dout)/sqlite3-node.mjs
|
||||
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,vanilla,0,\
|
||||
$(sqlite3-api.js), $(sqlite3.js)))
|
||||
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,esm,1,\
|
||||
$(sqlite3-api.mjs), $(sqlite3.mjs), \
|
||||
-Dtarget=es6-module, -sEXPORT_ES6 -sUSE_ES6_IMPORT_META))
|
||||
$(sqlite3-api.mjs), $(sqlite3.mjs), -Dtarget=es6-module))
|
||||
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,bundler-friendly,1,\
|
||||
$(sqlite3-api-bundler-friendly.mjs),$(sqlite3-bundler-friendly.mjs),\
|
||||
$(c-pp.D.sqlite3-esm) -Dtarget=es6-bundler-friendly))
|
||||
@ -798,7 +887,7 @@ $(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,node,1,\
|
||||
# -Dtarget=es6-module -Dtarget=es6-bundler-friendly: intended for
|
||||
# "bundler-friendly" ESM module build. These have some restrictions
|
||||
# on how URL() objects are constructed in some contexts: URLs which
|
||||
# refer to files which are part of this project must be references
|
||||
# refer to files which are part of this project must be referenced
|
||||
# as string literals so that bundlers' static-analysis tools can
|
||||
# find those files and include them in their bundles.
|
||||
#
|
||||
|
@ -1,3 +1,4 @@
|
||||
//#ifnot omit-oo1
|
||||
/*
|
||||
2022-07-22
|
||||
|
||||
@ -1940,4 +1941,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
}/*main-window-only bits*/
|
||||
|
||||
});
|
||||
|
||||
//#else
|
||||
/* Built with the omit-oo1 flag. */
|
||||
//#endif ifnot omit-oo1
|
||||
|
@ -1,3 +1,4 @@
|
||||
//#ifnot omit-oo1
|
||||
/**
|
||||
2022-07-22
|
||||
|
||||
@ -689,3 +690,6 @@ sqlite3.initWorker1API = function(){
|
||||
globalThis.postMessage({type:'sqlite3-api',result:'worker1-ready'});
|
||||
}.bind({sqlite3});
|
||||
});
|
||||
//#else
|
||||
/* Built with the omit-oo1 flag. */
|
||||
//#endif ifnot omit-oo1
|
||||
|
@ -1103,7 +1103,7 @@ const char * sqlite3_wasm_enum_json(void){
|
||||
M(xShadowName, "i(s)");
|
||||
} _StructBinder;
|
||||
#undef CurrentStruct
|
||||
|
||||
|
||||
/**
|
||||
** Workaround: in order to map the various inner structs from
|
||||
** sqlite3_index_info, we have to uplift those into constructs we
|
||||
|
@ -1,3 +1,4 @@
|
||||
//#ifnot omit-oo1
|
||||
/*
|
||||
2022-05-23
|
||||
|
||||
@ -48,3 +49,6 @@ import {default as sqlite3InitModule} from './sqlite3-bundler-friendly.mjs';
|
||||
}
|
||||
//#endif
|
||||
sqlite3InitModule().then(sqlite3 => sqlite3.initWorker1API());
|
||||
//#else
|
||||
/* Built with the omit-oo1 flag. */
|
||||
//#endif ifnot omit-oo1
|
||||
|
@ -206,9 +206,8 @@ const MyBinder = StructBinderFactory({
|
||||
It also offers a number of other settings, but all are optional except
|
||||
for the ones shown above. Those three config options abstract away
|
||||
details which are specific to a given WASM environment. They provide
|
||||
the WASM "heap" memory (a byte array), the memory allocator, and the
|
||||
deallocator. In a conventional Emscripten setup, that config might
|
||||
simply look like:
|
||||
the WASM "heap" memory, the memory allocator, and the deallocator. In
|
||||
a conventional Emscripten setup, that config might simply look like:
|
||||
|
||||
>
|
||||
```javascript
|
||||
|
64
manifest
64
manifest
@ -1,11 +1,11 @@
|
||||
C Merge\sthe\slatest\strunk\schanges\sinto\sthe\sbedrock\sbranch.
|
||||
D 2023-12-28T14:01:09.072
|
||||
C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\sbedrock\sbranch.
|
||||
D 2024-01-04T16:28:49.340
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
F Makefile.in 0ecf5e88fcae2cc0520c48a1c784cf7aa65818476289108a4fad2b07b075c71e
|
||||
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
||||
F Makefile.msc e727763026850c72bc3a44f6588a658e8216c2a30078062efc9338230863cec9
|
||||
F Makefile.msc e831c1ddf8dac8f6cbe646424392ac951039786d227d381384a52a7d3d2634e4
|
||||
F README.md 6358805260a03ebead84e168bbf3740ddf3f683b477e478567186aa7afb490d3
|
||||
F VERSION 73573d4545343f001bf5dc5461173a7c78c203dd046cabcf99153878cf25d3a6
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@ -53,8 +53,8 @@ F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
|
||||
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
|
||||
F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94
|
||||
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
|
||||
F ext/consio/console_io.c 097323f60037d70523421f0248958d2280851f8ff2f9a443d4ee1474c4769118 x
|
||||
F ext/consio/console_io.h 3228dff1717481202a24f6dcf45ce0b75e7a778bf6877089518a44e1473b76a3
|
||||
F ext/consio/console_io.c e1be639e79e54264b3ae97ca291728987a9aa82e6a4526458e6400f5e083e524 x
|
||||
F ext/consio/console_io.h 0548b83d7c4b7270ad544a67f2bb90cebc519637fa39b1838df4744cf0d87646
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test 0dd5cb096d66bed593e33053a3b364f6ef52ed72064bf5cf298364636dbf3cd6
|
||||
@ -97,10 +97,10 @@ F ext/fts5/fts5Int.h defa43c0932265138ee910ca416e6baccf8b774e0f3d610e74be1ab2880
|
||||
F ext/fts5/fts5_aux.c 4584e88878e54828bf7d4d0d83deedd232ec60628b7731be02bad6adb62304b1
|
||||
F ext/fts5/fts5_buffer.c 0eec58bff585f1a44ea9147eae5da2447292080ea435957f7488c70673cb6f09
|
||||
F ext/fts5/fts5_config.c 8072a207034b51ae9b7694121d1b5715c794e94b275e088f70ae532378ca5cdf
|
||||
F ext/fts5/fts5_expr.c e5fb9dd9e31e9e6ae9604bdb0d183ecec720964f3b974fc37c43ce73d8833d6d
|
||||
F ext/fts5/fts5_expr.c e91156ebdcc08d837f4f324168f69f3c0d7fdef0e521fd561efb48ef3297b696
|
||||
F ext/fts5/fts5_hash.c adda4272be401566a6e0ba1acbe70ee5cb97fce944bc2e04dc707152a0ec91b1
|
||||
F ext/fts5/fts5_index.c bb1965c3965f6fe5f64160bf1c0694a9684a790a783f293a76da1d38d319b258
|
||||
F ext/fts5/fts5_main.c 78c1a7eda00fefe56cccb4c51ff8477a3f4a933819dfe0ba612d703e7c2a53a8
|
||||
F ext/fts5/fts5_main.c a508be9e9b15d54cba47c5261278d611985434be98029cbc4c8efbd86bb3d09f
|
||||
F ext/fts5/fts5_storage.c f9e31b0d155e9b2c92d5d3a09ad7a56b937fbf1c7f962e10f4ca6281349f3934
|
||||
F ext/fts5/fts5_tcl.c cf0fd0dbe64ec272491b749e0d594f563cda03336aeb60900129e6d18b0aefb8
|
||||
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
|
||||
@ -187,7 +187,7 @@ F ext/fts5/test/fts5limits.test 8ab67cf5d311c124b6ceb0062d0297767176df4572d955fc
|
||||
F ext/fts5/test/fts5matchinfo.test 10c9a6f7fe61fb132299c4183c012770b10c4d5c2f2edb6df0b6607f683d737a
|
||||
F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
|
||||
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
|
||||
F ext/fts5/test/fts5misc.test dd97c86c9cbc3e587067e640f6ce88842cfbf5d23bb0e0fbb7f6707623b2d505
|
||||
F ext/fts5/test/fts5misc.test 89dc46e37951b7f6653809f4abf6b1ca2f1fa62259efaf719339288f76fb6be9
|
||||
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
|
||||
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
|
||||
F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd
|
||||
@ -198,7 +198,7 @@ F ext/fts5/test/fts5optimize3.test bf9c91bb927d0fb2b9a06318a217a0419183ac5913842
|
||||
F ext/fts5/test/fts5origintext.test d2796fa08ee7aecfabdc0c45bb8a2fb16a00ea8757e63fbc153b718dbe430a39
|
||||
F ext/fts5/test/fts5origintext2.test f3b9436de540828d01f0672df855b09ebc0863e126d5b56234701d71dfa73634
|
||||
F ext/fts5/test/fts5origintext3.test 0d25933506600452a5ab3873cbb418ed5f2de2446c3672b9997b1ea104b0e7f0
|
||||
F ext/fts5/test/fts5origintext4.test a33e8f64b9762e0e0c722ac2b301017e1d7745635724c1ca04b2c010b451fab4
|
||||
F ext/fts5/test/fts5origintext4.test 0c4e4514b68d9ddb15e5a538d9d234da85747a3fd62432265dbdba5c8708e457
|
||||
F ext/fts5/test/fts5origintext5.test a037bdf7235a22033c4663837bdb12d9738245464a3ac2f60c71fc40d07ede7d
|
||||
F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b
|
||||
F ext/fts5/test/fts5plan.test b65cfcca9ddd6fdaa118c61e17aeec8e8433bc5b6bb307abd116514f79c49c5a
|
||||
@ -265,7 +265,7 @@ F ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java 0b72cdff61533b564d65b63
|
||||
F ext/jni/src/org/sqlite/jni/capi/AuthorizerCallback.java c045a5b47e02bb5f1af91973814a905f12048c428a3504fbc5266d1c1be3de5a
|
||||
F ext/jni/src/org/sqlite/jni/capi/AutoExtensionCallback.java 74cc4998a73d6563542ecb90804a3c4f4e828cb4bd69e61226d1a51f4646e759
|
||||
F ext/jni/src/org/sqlite/jni/capi/BusyHandlerCallback.java 7b8e19810c42b0ad21a04b5d8c804b32ee5905d137148703f16a75b612c380ca
|
||||
F ext/jni/src/org/sqlite/jni/capi/CApi.java d428a1fd3b827f01c55d10d21ff35e33e7dac9e8a1d92a8b5c7d7255e67407d8
|
||||
F ext/jni/src/org/sqlite/jni/capi/CApi.java 27bbd944ea8c147afd25b93f17dc397f3627611ebe2878944a32ffeffc98e99e
|
||||
F ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java 57e2d275dcebe690b1fc1f3d34eb96879b2d7039bce30b563aee547bf45d8a8b
|
||||
F ext/jni/src/org/sqlite/jni/capi/CollationCallback.java e29bcfc540fdd343e2f5cca4d27235113f2886acb13380686756d5cabdfd065a
|
||||
F ext/jni/src/org/sqlite/jni/capi/CollationNeededCallback.java 5bfa226a8e7a92e804fd52d6e42b4c7b875fa7a94f8e2c330af8cc244a8920ab
|
||||
@ -301,7 +301,7 @@ F ext/jni/src/org/sqlite/jni/fts5/Fts5Context.java 338637e6e5a2cc385d962b220f3c1
|
||||
F ext/jni/src/org/sqlite/jni/fts5/Fts5ExtensionApi.java 7da0fbb5728f7c056a43e6407f13dd0c7c9c445221267786a109b987f5fc8a9d
|
||||
F ext/jni/src/org/sqlite/jni/fts5/Fts5PhraseIter.java 28045042d593a1f1b9b80d54ec77cbf1d8a1bc95e442eceefa9a3a6f56600b0e
|
||||
F ext/jni/src/org/sqlite/jni/fts5/Fts5Tokenizer.java 3c8f677ffb85b8782f865d6fcbc16200b3375d0e3c29ed541a494fde3011bf49
|
||||
F ext/jni/src/org/sqlite/jni/fts5/TesterFts5.java eaee4d641229a098eb704b96a45c9a23c6514dc39009d3611e265bab33834deb
|
||||
F ext/jni/src/org/sqlite/jni/fts5/TesterFts5.java 51e16bf9050af7cb246d17d6a19c001cfc916bf20f425c96625aaccaf74688e8
|
||||
F ext/jni/src/org/sqlite/jni/fts5/XTokenizeCallback.java 1efd1220ea328a32f2d2a1b16c735864159e929480f71daad4de9d5944839167
|
||||
F ext/jni/src/org/sqlite/jni/fts5/fts5_api.java a8e88c3783d21cec51b0748568a96653fead88f8f4953376178d9c7385b197ea
|
||||
F ext/jni/src/org/sqlite/jni/fts5/fts5_extension_function.java 9e2b954d210d572552b28aca523b272fae14bd41e318921b22f65b728d5bf978
|
||||
@ -583,7 +583,7 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
||||
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
||||
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
|
||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle 7fb73f7150ab79d83bb45a67d257553c905c78cd3d693101699243f36c5ae6c3
|
||||
F ext/wasm/GNUmakefile 62403519b233dbe23e1cac30969714c4043a96c5bc2614e551a07a81c543c493
|
||||
F ext/wasm/GNUmakefile 99aad6d6a28c43573f80825e986427c1a024a3298aaf0c69c56a0c6b336f12c8
|
||||
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
|
||||
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
|
||||
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||
@ -602,17 +602,17 @@ F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b
|
||||
F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
|
||||
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
|
||||
F ext/wasm/api/sqlite3-api-glue.js 119b91c8a7ce6648679eb66fcdd1ed07ef7fd892eb501d658fbfefcc962012d9
|
||||
F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8
|
||||
F ext/wasm/api/sqlite3-api-oo1.js 7f3bcf0549ac44cde4b9da0b642d771916738d3f6781fb8a1757c50a91e506c0
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 9aeba7b45cf41b3a26d34d7fb2525633cd1adfc544888c1ea8dbb077496f4ce9
|
||||
F ext/wasm/api/sqlite3-api-worker1.js 88770ac01fc756f89a3e060eec17111d6c1688e89ebfd34cb9d9e54d25affbb9
|
||||
F ext/wasm/api/sqlite3-api-worker1.js fd46628ef147dd5856c88f63a9a279a40f744f1fdfddd55251ad8fbc3d8200ae
|
||||
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
|
||||
F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 595953994aa3ae2287c889c4da39ab3d6f17b6461ecf4bec334b7a3faafddb02
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 46c4afa6c50d7369252c104f274ad977a97e91ccfafc38b400fe36e90bdda88e
|
||||
F ext/wasm/api/sqlite3-wasm.c f280d4ea917d213ae95668dfcd173a2c2ef21a0a4bf9aeb9fcd0edaf1b21ba4b
|
||||
F ext/wasm/api/sqlite3-wasm.c dfd1f1a225b267e8fd641dcd6c7d579fbe2b731aeaa123324135efac830a2bcf
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js f10c3ecd9df06f6320073c2ce230a7ed7c56034d8b88c1e57095f2a97faf423a
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js a541112aa51e16705f13a99bb943c64efe178aa28c86704a955f8fd9afe4ba37
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
|
||||
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
|
||||
F ext/wasm/batch-runner-sahpool.js 54a3ac228e6c4703fe72fb65c897e19156263a51fe9b7e21d2834a45e876aabd
|
||||
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
|
||||
@ -641,7 +641,7 @@ F ext/wasm/fiddle/fiddle.js 974b995119ac443685d7d94d3b3c58c6a36540e9eb3fed7069d5
|
||||
F ext/wasm/index-dist.html e91d76e4581185238fd3d42ed86ec600f7023ed3e3a944c5c356f25304bf1263
|
||||
F ext/wasm/index.html b31ce41c0da476d5ffcef23069b9d3415b419d65af5779096ebcfbcbade453a9
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.md 59a20df389abcc3606eb4eaea7fb7ba14504beb3e345dbea9b99a0618ba3bec8
|
||||
F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337
|
||||
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
|
||||
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
|
||||
@ -678,16 +678,16 @@ F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F sqlite_cfg.h.in baf2e409c63d4e7a765e17769b6ff17c5a82bbd9cbf1e284fd2e4cefaff3fcf2
|
||||
F src/alter.c 30c2333b8bb3af71e4eb9adeadee8aa20edb15917ed44b8422e5cd15f3dfcddc
|
||||
F src/analyze.c d4cc28738c29e009640ec20ebb6936ba6fcefff0d11aa93398d9bb9a5ead6c1f
|
||||
F src/analyze.c 0f15753308c3bca7674f31fa7e0807ffcb8b120c36eef7d00b62b33079ddc854
|
||||
F src/attach.c cc9d00d30da916ff656038211410ccf04ed784b7564639b9b61d1839ed69fd39
|
||||
F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/bitvec.c 501daeef838fa82a9fb53540d72f29e3d9172c8867f1e19f94f681e2e20b966e
|
||||
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
|
||||
F src/btree.c 5e63b4a87ad689d234259ee0936e6b8c2e37ada061751a5d95305be5ab941fc4 x
|
||||
F src/btree.c 5c0163ebbca4f0d8ed86ee38bff765fd5fe9c18f036babc6f3e4b3b41ad53252
|
||||
F src/btree.h d906e4d53f483c83d471d99479fa73fcdf20696305d578876f46ee283f3507cb
|
||||
F src/btreeInt.h 4e04041380c1ac1f4b2e80d7fb072c6d74c1be605a4271625347ba06b651e37a
|
||||
F src/build.c 145ed99c2857f3eb2f23c4247027ec6f5f11651321033775daee79ccec57a56d
|
||||
F src/build.c a5a67f51bd0958d2871cc441d186a026c810cf4980959203ecdec6a009975243
|
||||
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 047a0613c4c3ff65e05903d5b6931185b3df8f34b5178ad2f8d865ada4e9da44
|
||||
@ -705,10 +705,10 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
|
||||
F src/json.c bc90605da937ca0cd72ff0492216fbb38fd8f9025e6344499f9db235be98e36f
|
||||
F src/json.c 4913fd22c4f0fa30643afb93a4d78d289cd490620e782b31016c3d4b2049b1cc
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
F src/main.c cc7685733e7d9008f6d67103cd75894424790828cc7129a24c89011951252a0f
|
||||
F src/main.c e2f8c69ab61be5b9f2c62c205721083321782c7b1b3ff0dcd7ab081c90ba43b2
|
||||
F src/malloc.c f016922435dc7d1f1f5083a03338a3e91f8c67ce2c5bdcfa4cdef62e612f5fcc
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@ -732,7 +732,7 @@ F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d87210
|
||||
F src/os_unix.c 34fd19cd2ff4309909cbe901a9f5242b8d8bc37c63822aab4c6c034f0561f162
|
||||
F src/os_win.c 4a50a154aeebc66a1f8fb79c1ff6dd5fe3d005556533361e0d460d41cb6a45a8
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c e9834285f3e2e9e9c9d43d74cbb3dcd746063e3b7d4cf63beb12efa46e5c1113
|
||||
F src/pager.c 76a1c3cc5fe198c38c6d15d7bda1e864642eb0131c53c2f2a94f0bcff50930a5
|
||||
F src/pager.h a195b4396e0f374922d7162ceb66f6d48a6583242b7200fa999ab52fed6341ca
|
||||
F src/parse.y e583113148bb13280de7faab4f213fa183d9e6498483d5eee02f9578a07b9cd4
|
||||
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
|
||||
@ -750,8 +750,8 @@ F src/shell.c.in 85f8d52fa4f7773823736dd39d0a268fd739207fcae95883c9ec8ce4af59f7d
|
||||
F src/sqlite.h.in 4f050c1c3e36ead0dc721e6585edfc6784fafc9eb7b61c079024ff9df502a236
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h 90252d2fef9c1bb84a9a3c275feb33bf6b5aac40949c85181bc43960e120ddfc
|
||||
F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6
|
||||
F src/sqliteInt.h f722ed424969d5aeb857c40c50e6f12f137ac75e6cee5651f9f9f81e0a335384
|
||||
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
|
||||
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd
|
||||
@ -827,10 +827,10 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8
|
||||
F src/vdbevtab.c 2143db7db0ceed69b21422581f434baffc507a08d831565193a7a02882a1b6a7
|
||||
F src/vtab.c 11948e105f56e84099ca17f1f434b1944539ea84de26d0d767eadfbc670ce1ea
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 354ee893c2a50063c5b7c4b8e38321c39a76176936ea67ac173dd56e38da4418
|
||||
F src/wal.c 5070f3b1917b687f2f27050d0c105104726323f47422db18297c7d5904e02438
|
||||
F src/wal.h 8d02ab8c2a93a941f5898eb3345bf711c1d3f8f86f4be8d5428fb6c074962d8a
|
||||
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
||||
F src/where.c 0bfab37c7f787e320a8010e51ae97c2e51964d3b3a24fbc246b8e8fee50de4e9
|
||||
F src/where.c 217fe82a26c0fb6a3c7fd01865d821e752f9c01fb72f114af3f0b77ce234d1fb
|
||||
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
|
||||
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
|
||||
F src/whereexpr.c dc5096eca5ed503999be3bdee8a90c51361289a678d396a220912e9cb73b3c00
|
||||
@ -2152,8 +2152,8 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
|
||||
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
|
||||
F tool/split-sqlite3c.tcl 5aa60643afca558bc732b1444ae81a522326f91e1dc5665b369c54f09e20de60
|
||||
F tool/sqldiff.c fcccbc07da942b4534d0c769e9fcc21c67cbd7086ddc1c8f13372c40a83d4634
|
||||
F tool/sqlite3_analyzer.c.in f88615bf33098945e0a42f17733f472083d150b58bdaaa5555a7129d0a51621c
|
||||
F tool/sqldiff.c 985452ffc8554baee0f945d078859d393a22abc0bbf553a9f12acae1b6e1fdd0
|
||||
F tool/sqlite3_analyzer.c.in 8da2b08f56eeac331a715036cf707cc20f879f231362be0c22efd682e2b89b4f
|
||||
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
|
||||
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
|
||||
F tool/src-verify.c 41c586dee84d0b190ad13e0282ed83d4a65ec9fefde9adf4943efdf6558eea7f
|
||||
@ -2193,8 +2193,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P c2e53000f4740be9f0492fda1857c5f2f5539fe17bdaafcafdf8d14c8f3218ce 1f592dd32d165456d40a90a2757225e05cdb810518beee87f0700863dc73d2d0
|
||||
R d4e6db0569bfd9d167e4dded935e76f6
|
||||
P 5a17b972ed455aac751453cd8eaa8f059db1ac5c7f27965dce4956563e7911ea 8fb42df89a47b716c824de8742b7e3bda1a5c0f9a85ce3f328d7aa94ab735497
|
||||
R ba8e645a8dcf8de84a22d66e2ef51f4e
|
||||
U drh
|
||||
Z ae43f903a951b308637516879deb28c6
|
||||
Z 0296ceef4c551981ca78da92b346a1c6
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
5a17b972ed455aac751453cd8eaa8f059db1ac5c7f27965dce4956563e7911ea
|
||||
707f79c70c8b0fd889aede8806148457c691a008d0ce030084ba79f1e66ec53d
|
@ -264,9 +264,9 @@ static void openStatTable(
|
||||
typedef struct StatAccum StatAccum;
|
||||
typedef struct StatSample StatSample;
|
||||
struct StatSample {
|
||||
tRowcnt *anEq; /* sqlite_stat4.nEq */
|
||||
tRowcnt *anDLt; /* sqlite_stat4.nDLt */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
tRowcnt *anEq; /* sqlite_stat4.nEq */
|
||||
tRowcnt *anLt; /* sqlite_stat4.nLt */
|
||||
union {
|
||||
i64 iRowid; /* Rowid in main table of the key */
|
||||
@ -424,9 +424,9 @@ static void statInit(
|
||||
|
||||
/* Allocate the space required for the StatAccum object */
|
||||
n = sizeof(*p)
|
||||
+ sizeof(tRowcnt)*nColUp /* StatAccum.anEq */
|
||||
+ sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */
|
||||
+ sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
n += sizeof(tRowcnt)*nColUp; /* StatAccum.anEq */
|
||||
if( mxSample ){
|
||||
n += sizeof(tRowcnt)*nColUp /* StatAccum.anLt */
|
||||
+ sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */
|
||||
@ -447,9 +447,9 @@ static void statInit(
|
||||
p->nKeyCol = nKeyCol;
|
||||
p->nSkipAhead = 0;
|
||||
p->current.anDLt = (tRowcnt*)&p[1];
|
||||
p->current.anEq = &p->current.anDLt[nColUp];
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
p->current.anEq = &p->current.anDLt[nColUp];
|
||||
p->mxSample = p->nLimit==0 ? mxSample : 0;
|
||||
if( mxSample ){
|
||||
u8 *pSpace; /* Allocated space not yet assigned */
|
||||
@ -716,7 +716,9 @@ static void statPush(
|
||||
|
||||
if( p->nRow==0 ){
|
||||
/* This is the first call to this function. Do initialization. */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
|
||||
#endif
|
||||
}else{
|
||||
/* Second and subsequent calls get processed here */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
@ -725,15 +727,17 @@ static void statPush(
|
||||
|
||||
/* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
|
||||
** to the current row of the index. */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
for(i=0; i<iChng; i++){
|
||||
p->current.anEq[i]++;
|
||||
}
|
||||
#endif
|
||||
for(i=iChng; i<p->nCol; i++){
|
||||
p->current.anDLt[i]++;
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i];
|
||||
#endif
|
||||
p->current.anEq[i] = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -867,7 +871,9 @@ static void statGet(
|
||||
u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
|
||||
if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1;
|
||||
sqlite3_str_appendf(&sStat, " %llu", iVal);
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
assert( p->current.anEq[i] );
|
||||
#endif
|
||||
}
|
||||
sqlite3ResultStrAccum(context, &sStat);
|
||||
}
|
||||
@ -1556,6 +1562,16 @@ static void decodeIntArray(
|
||||
while( z[0]!=0 && z[0]!=' ' ) z++;
|
||||
while( z[0]==' ' ) z++;
|
||||
}
|
||||
|
||||
/* Set the bLowQual flag if the peak number of rows obtained
|
||||
** from a full equality match is so large that a full table scan
|
||||
** seems likely to be faster than using the index.
|
||||
*/
|
||||
if( aLog[0] > 66 /* Index has more than 100 rows */
|
||||
&& aLog[0] <= aLog[nOut-1] /* And only a single value seen */
|
||||
){
|
||||
pIndex->bLowQual = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
1
src/btree.c
Executable file → Normal file
1
src/btree.c
Executable file → Normal file
@ -5637,7 +5637,6 @@ static int accessPayload(
|
||||
assert( aWrite>=pBufStart ); /* due to (6) */
|
||||
memcpy(aSave, aWrite, 4);
|
||||
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
|
||||
if( rc && nextPage>pBt->nPage ) rc = SQLITE_CORRUPT_BKPT;
|
||||
nextPage = get4byte(aWrite);
|
||||
memcpy(aWrite, aSave, 4);
|
||||
}else
|
||||
|
@ -1655,7 +1655,8 @@ char sqlite3AffinityType(const char *zIn, Column *pCol){
|
||||
|
||||
assert( zIn!=0 );
|
||||
while( zIn[0] ){
|
||||
h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
|
||||
u8 x = *(u8*)zIn;
|
||||
h = (h<<8) + sqlite3UpperToLower[x];
|
||||
zIn++;
|
||||
if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
|
||||
aff = SQLITE_AFF_TEXT;
|
||||
|
147
src/json.c
147
src/json.c
@ -298,6 +298,7 @@ struct JsonParse {
|
||||
u32 nBlob; /* Bytes of aBlob[] actually used */
|
||||
u32 nBlobAlloc; /* Bytes allocated to aBlob[]. 0 if aBlob is external */
|
||||
char *zJson; /* Json text used for parsing */
|
||||
sqlite3 *db; /* The database connection to which this object belongs */
|
||||
int nJson; /* Length of the zJson string in bytes */
|
||||
u32 nJPRef; /* Number of references to this object */
|
||||
u32 iErr; /* Error location in zJson[] */
|
||||
@ -627,8 +628,33 @@ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
|
||||
p->zBuf[p->nUsed++] = '"';
|
||||
while( 1 /*exit-by-break*/ ){
|
||||
k = 0;
|
||||
while( k+1<N && jsonIsOk[z[k]] && jsonIsOk[z[k+1]] ){ k += 2; } /* <--, */
|
||||
while( k<N && jsonIsOk[z[k]] ){ k++; } /* <-- loop unwound for speed */
|
||||
/* The following while() is the 4-way unwound equivalent of
|
||||
**
|
||||
** while( k<N && jsonIsOk[z[k]] ){ k++; }
|
||||
*/
|
||||
while( 1 /* Exit by break */ ){
|
||||
if( k+3>=N ){
|
||||
while( k<N && jsonIsOk[z[k]] ){ k++; }
|
||||
break;
|
||||
}
|
||||
if( !jsonIsOk[z[k]] ){
|
||||
break;
|
||||
}
|
||||
if( !jsonIsOk[z[k+1]] ){
|
||||
k += 1;
|
||||
break;
|
||||
}
|
||||
if( !jsonIsOk[z[k+2]] ){
|
||||
k += 2;
|
||||
break;
|
||||
}
|
||||
if( !jsonIsOk[z[k+3]] ){
|
||||
k += 3;
|
||||
break;
|
||||
}else{
|
||||
k += 4;
|
||||
}
|
||||
}
|
||||
if( k>=N ){
|
||||
if( k>0 ){
|
||||
memcpy(&p->zBuf[p->nUsed], z, k);
|
||||
@ -798,7 +824,7 @@ static void jsonParseReset(JsonParse *pParse){
|
||||
pParse->bJsonIsRCStr = 0;
|
||||
}
|
||||
if( pParse->nBlobAlloc ){
|
||||
sqlite3_free(pParse->aBlob);
|
||||
sqlite3DbFree(pParse->db, pParse->aBlob);
|
||||
pParse->aBlob = 0;
|
||||
pParse->nBlob = 0;
|
||||
pParse->nBlobAlloc = 0;
|
||||
@ -815,7 +841,7 @@ static void jsonParseFree(JsonParse *pParse){
|
||||
pParse->nJPRef--;
|
||||
}else{
|
||||
jsonParseReset(pParse);
|
||||
sqlite3_free(pParse);
|
||||
sqlite3DbFree(pParse->db, pParse);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1046,7 +1072,7 @@ static int jsonBlobExpand(JsonParse *pParse, u32 N){
|
||||
t = pParse->nBlobAlloc*2;
|
||||
}
|
||||
if( t<N ) t = N+100;
|
||||
aNew = sqlite3_realloc64( pParse->aBlob, t );
|
||||
aNew = sqlite3DbRealloc(pParse->db, pParse->aBlob, t);
|
||||
if( aNew==0 ){ pParse->oom = 1; return 1; }
|
||||
pParse->aBlob = aNew;
|
||||
pParse->nBlobAlloc = t;
|
||||
@ -1971,14 +1997,15 @@ static void jsonReturnStringAsBlob(JsonString *pStr){
|
||||
jsonStringTerminate(pStr);
|
||||
px.zJson = pStr->zBuf;
|
||||
px.nJson = pStr->nUsed;
|
||||
px.db = sqlite3_context_db_handle(pStr->pCtx);
|
||||
(void)jsonTranslateTextToBlob(&px, 0);
|
||||
if( px.oom ){
|
||||
sqlite3_free(px.aBlob);
|
||||
sqlite3DbFree(px.db, px.aBlob);
|
||||
sqlite3_result_error_nomem(pStr->pCtx);
|
||||
}else{
|
||||
assert( px.nBlobAlloc>0 );
|
||||
assert( !px.bReadOnly );
|
||||
sqlite3_result_blob(pStr->pCtx, px.aBlob, px.nBlob, sqlite3_free);
|
||||
sqlite3_result_blob(pStr->pCtx, px.aBlob, px.nBlob, SQLITE_DYNAMIC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2594,6 +2621,7 @@ static u32 jsonCreateEditSubstructure(
|
||||
static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT };
|
||||
int rc;
|
||||
memset(pIns, 0, sizeof(*pIns));
|
||||
pIns->db = pParse->db;
|
||||
if( zTail[0]==0 ){
|
||||
/* No substructure. Just insert what is given in pParse. */
|
||||
pIns->aBlob = pParse->aIns;
|
||||
@ -2721,6 +2749,7 @@ static u32 jsonLookupStep(
|
||||
testcase( pParse->eEdit==JEDIT_INS );
|
||||
testcase( pParse->eEdit==JEDIT_SET );
|
||||
memset(&ix, 0, sizeof(ix));
|
||||
ix.db = pParse->db;
|
||||
jsonBlobAppendNode(&ix, rawKey?JSONB_TEXTRAW:JSONB_TEXT5, nKey, 0);
|
||||
pParse->oom |= ix.oom;
|
||||
rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i]);
|
||||
@ -2931,7 +2960,7 @@ static void jsonReturnFromBlob(
|
||||
char *zOut;
|
||||
u32 nOut = sz;
|
||||
z = (const char*)&pParse->aBlob[i+n];
|
||||
zOut = sqlite3_malloc( nOut+1 );
|
||||
zOut = sqlite3DbMallocRaw(db, nOut+1);
|
||||
if( zOut==0 ) goto returnfromblob_oom;
|
||||
for(iIn=iOut=0; iIn<sz; iIn++){
|
||||
char c = z[iIn];
|
||||
@ -2965,7 +2994,7 @@ static void jsonReturnFromBlob(
|
||||
} /* end for() */
|
||||
assert( iOut<=nOut );
|
||||
zOut[iOut] = 0;
|
||||
sqlite3_result_text(pCtx, zOut, iOut, sqlite3_free);
|
||||
sqlite3_result_text(pCtx, zOut, iOut, SQLITE_DYNAMIC);
|
||||
break;
|
||||
}
|
||||
case JSONB_ARRAY:
|
||||
@ -3018,6 +3047,7 @@ static int jsonFunctionArgToBlob(
|
||||
int eType = sqlite3_value_type(pArg);
|
||||
static u8 aNull[] = { 0x00 };
|
||||
memset(pParse, 0, sizeof(pParse[0]));
|
||||
pParse->db = sqlite3_context_db_handle(ctx);
|
||||
switch( eType ){
|
||||
default: {
|
||||
pParse->aBlob = aNull;
|
||||
@ -3043,7 +3073,7 @@ static int jsonFunctionArgToBlob(
|
||||
pParse->nJson = nJson;
|
||||
if( jsonConvertTextToBlob(pParse, ctx) ){
|
||||
sqlite3_result_error(ctx, "malformed JSON", -1);
|
||||
sqlite3_free(pParse->aBlob);
|
||||
sqlite3DbFree(pParse->db, pParse->aBlob);
|
||||
memset(pParse, 0, sizeof(pParse[0]));
|
||||
return 1;
|
||||
}
|
||||
@ -3200,6 +3230,7 @@ static JsonParse *jsonParseFuncArg(
|
||||
int eType; /* Datatype of pArg */
|
||||
JsonParse *p = 0; /* Value to be returned */
|
||||
JsonParse *pFromCache = 0; /* Value taken from cache */
|
||||
sqlite3 *db; /* The database connection */
|
||||
|
||||
assert( ctx!=0 );
|
||||
eType = sqlite3_value_type(pArg);
|
||||
@ -3213,14 +3244,16 @@ static JsonParse *jsonParseFuncArg(
|
||||
return pFromCache;
|
||||
}
|
||||
}
|
||||
db = sqlite3_context_db_handle(ctx);
|
||||
rebuild_from_cache:
|
||||
p = sqlite3_malloc64( sizeof(*p) );
|
||||
p = sqlite3DbMallocZero(db, sizeof(*p));
|
||||
if( p==0 ) goto json_pfa_oom;
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->db = db;
|
||||
p->nJPRef = 1;
|
||||
if( pFromCache!=0 ){
|
||||
u32 nBlob = pFromCache->nBlob;
|
||||
p->aBlob = sqlite3_malloc64( nBlob );
|
||||
p->aBlob = sqlite3DbMallocRaw(db, nBlob);
|
||||
if( p->aBlob==0 ) goto json_pfa_oom;
|
||||
memcpy(p->aBlob, pFromCache->aBlob, nBlob);
|
||||
p->nBlobAlloc = p->nBlob = nBlob;
|
||||
@ -3351,14 +3384,15 @@ static void jsonDebugPrintBlob(
|
||||
JsonParse *pParse, /* JSON content */
|
||||
u32 iStart, /* Start rendering here */
|
||||
u32 iEnd, /* Do not render this byte or any byte after this one */
|
||||
int nIndent /* Indent by this many spaces */
|
||||
int nIndent, /* Indent by this many spaces */
|
||||
sqlite3_str *pOut /* Generate output into this sqlite3_str object */
|
||||
){
|
||||
while( iStart<iEnd ){
|
||||
u32 i, n, nn, sz = 0;
|
||||
int showContent = 1;
|
||||
u8 x = pParse->aBlob[iStart] & 0x0f;
|
||||
u32 savedNBlob = pParse->nBlob;
|
||||
printf("%5d:%*s", iStart, nIndent, "");
|
||||
sqlite3_str_appendf(pOut, "%5d:%*s", iStart, nIndent, "");
|
||||
if( pParse->nBlobAlloc>pParse->nBlob ){
|
||||
pParse->nBlob = pParse->nBlobAlloc;
|
||||
}
|
||||
@ -3367,9 +3401,11 @@ static void jsonDebugPrintBlob(
|
||||
if( sz>0 && x<JSONB_ARRAY ){
|
||||
nn += sz;
|
||||
}
|
||||
for(i=0; i<nn; i++) printf(" %02x", pParse->aBlob[iStart+i]);
|
||||
for(i=0; i<nn; i++){
|
||||
sqlite3_str_appendf(pOut, " %02x", pParse->aBlob[iStart+i]);
|
||||
}
|
||||
if( n==0 ){
|
||||
printf(" ERROR invalid node size\n");
|
||||
sqlite3_str_appendf(pOut, " ERROR invalid node size\n");
|
||||
iStart = n==0 ? iStart+1 : iEnd;
|
||||
continue;
|
||||
}
|
||||
@ -3384,55 +3420,57 @@ static void jsonDebugPrintBlob(
|
||||
}
|
||||
}
|
||||
}
|
||||
printf(" <-- ");
|
||||
sqlite3_str_appendall(pOut," <-- ");
|
||||
switch( x ){
|
||||
case JSONB_NULL: printf("null"); break;
|
||||
case JSONB_TRUE: printf("true"); break;
|
||||
case JSONB_FALSE: printf("false"); break;
|
||||
case JSONB_INT: printf("int"); break;
|
||||
case JSONB_INT5: printf("int5"); break;
|
||||
case JSONB_FLOAT: printf("float"); break;
|
||||
case JSONB_FLOAT5: printf("float5"); break;
|
||||
case JSONB_TEXT: printf("text"); break;
|
||||
case JSONB_TEXTJ: printf("textj"); break;
|
||||
case JSONB_TEXT5: printf("text5"); break;
|
||||
case JSONB_TEXTRAW: printf("textraw"); break;
|
||||
case JSONB_NULL: sqlite3_str_appendall(pOut,"null"); break;
|
||||
case JSONB_TRUE: sqlite3_str_appendall(pOut,"true"); break;
|
||||
case JSONB_FALSE: sqlite3_str_appendall(pOut,"false"); break;
|
||||
case JSONB_INT: sqlite3_str_appendall(pOut,"int"); break;
|
||||
case JSONB_INT5: sqlite3_str_appendall(pOut,"int5"); break;
|
||||
case JSONB_FLOAT: sqlite3_str_appendall(pOut,"float"); break;
|
||||
case JSONB_FLOAT5: sqlite3_str_appendall(pOut,"float5"); break;
|
||||
case JSONB_TEXT: sqlite3_str_appendall(pOut,"text"); break;
|
||||
case JSONB_TEXTJ: sqlite3_str_appendall(pOut,"textj"); break;
|
||||
case JSONB_TEXT5: sqlite3_str_appendall(pOut,"text5"); break;
|
||||
case JSONB_TEXTRAW: sqlite3_str_appendall(pOut,"textraw"); break;
|
||||
case JSONB_ARRAY: {
|
||||
printf("array, %u bytes\n", sz);
|
||||
jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2);
|
||||
sqlite3_str_appendf(pOut,"array, %u bytes\n", sz);
|
||||
jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2, pOut);
|
||||
showContent = 0;
|
||||
break;
|
||||
}
|
||||
case JSONB_OBJECT: {
|
||||
printf("object, %u bytes\n", sz);
|
||||
jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2);
|
||||
sqlite3_str_appendf(pOut, "object, %u bytes\n", sz);
|
||||
jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2, pOut);
|
||||
showContent = 0;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
printf("ERROR: unknown node type\n");
|
||||
sqlite3_str_appendall(pOut, "ERROR: unknown node type\n");
|
||||
showContent = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( showContent ){
|
||||
if( sz==0 && x<=JSONB_FALSE ){
|
||||
printf("\n");
|
||||
sqlite3_str_append(pOut, "\n", 1);
|
||||
}else{
|
||||
u32 i;
|
||||
printf(": \"");
|
||||
sqlite3_str_appendall(pOut, ": \"");
|
||||
for(i=iStart+n; i<iStart+n+sz; i++){
|
||||
u8 c = pParse->aBlob[i];
|
||||
if( c<0x20 || c>=0x7f ) c = '.';
|
||||
putchar(c);
|
||||
sqlite3_str_append(pOut, (char*)&c, 1);
|
||||
}
|
||||
printf("\"\n");
|
||||
sqlite3_str_append(pOut, "\"\n", 2);
|
||||
}
|
||||
}
|
||||
iStart += n + sz;
|
||||
}
|
||||
}
|
||||
static void jsonShowParse(JsonParse *pParse){
|
||||
sqlite3_str out;
|
||||
char zBuf[1000];
|
||||
if( pParse==0 ){
|
||||
printf("NULL pointer\n");
|
||||
return;
|
||||
@ -3443,7 +3481,10 @@ static void jsonShowParse(JsonParse *pParse){
|
||||
if( pParse->nBlob==0 ) return;
|
||||
printf("content (bytes 0..%u):\n", pParse->nBlob-1);
|
||||
}
|
||||
jsonDebugPrintBlob(pParse, 0, pParse->nBlob, 0);
|
||||
sqlite3StrAccumInit(&out, 0, zBuf, sizeof(zBuf), 1000000);
|
||||
jsonDebugPrintBlob(pParse, 0, pParse->nBlob, 0, &out);
|
||||
printf("%s", sqlite3_str_value(&out));
|
||||
sqlite3_str_reset(&out);
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
@ -3451,8 +3492,8 @@ static void jsonShowParse(JsonParse *pParse){
|
||||
/*
|
||||
** SQL function: json_parse(JSON)
|
||||
**
|
||||
** Parse JSON using jsonParseFuncArg(). Then print a dump of that
|
||||
** parse on standard output.
|
||||
** Parse JSON using jsonParseFuncArg(). Return text that is a
|
||||
** human-readable dump of the binary JSONB for the input parameter.
|
||||
*/
|
||||
static void jsonParseFunc(
|
||||
sqlite3_context *ctx,
|
||||
@ -3460,10 +3501,18 @@ static void jsonParseFunc(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
JsonParse *p; /* The parse */
|
||||
sqlite3_str out;
|
||||
|
||||
assert( argc==1 );
|
||||
assert( argc>=1 );
|
||||
sqlite3StrAccumInit(&out, 0, 0, 0, 1000000);
|
||||
p = jsonParseFuncArg(ctx, argv[0], 0);
|
||||
jsonShowParse(p);
|
||||
if( p==0 ) return;
|
||||
if( argc==1 ){
|
||||
jsonDebugPrintBlob(p, 0, p->nBlob, 0, &out);
|
||||
sqlite3_result_text64(ctx, out.zText, out.nChar, SQLITE_DYNAMIC, SQLITE_UTF8);
|
||||
}else{
|
||||
jsonShowParse(p);
|
||||
}
|
||||
jsonParseFree(p);
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
@ -4279,6 +4328,7 @@ static void jsonErrorFunc(
|
||||
assert( argc==1 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.db = sqlite3_context_db_handle(ctx);
|
||||
if( jsonFuncArgMightBeBinary(argv[0]) ){
|
||||
s.aBlob = (u8*)sqlite3_value_blob(argv[0]);
|
||||
s.nBlob = sqlite3_value_bytes(argv[0]);
|
||||
@ -4568,9 +4618,9 @@ static int jsonEachConnect(
|
||||
"CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
|
||||
"json HIDDEN,root HIDDEN)");
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew = (JsonEachConnection*)(*ppVtab = sqlite3_malloc( sizeof(*pNew) ));
|
||||
pNew = (JsonEachConnection*)sqlite3DbMallocZero(db, sizeof(*pNew));
|
||||
*ppVtab = (sqlite3_vtab*)pNew;
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
|
||||
pNew->db = db;
|
||||
}
|
||||
@ -4579,7 +4629,8 @@ static int jsonEachConnect(
|
||||
|
||||
/* destructor for json_each virtual table */
|
||||
static int jsonEachDisconnect(sqlite3_vtab *pVtab){
|
||||
sqlite3_free(pVtab);
|
||||
JsonEachConnection *p = (JsonEachConnection*)pVtab;
|
||||
sqlite3DbFree(p->db, pVtab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@ -4589,9 +4640,8 @@ static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
JsonEachCursor *pCur;
|
||||
|
||||
UNUSED_PARAMETER(p);
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
pCur = sqlite3DbMallocZero(pVtab->db, sizeof(*pCur));
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
pCur->db = pVtab->db;
|
||||
jsonStringZero(&pCur->path);
|
||||
*ppCursor = &pCur->base;
|
||||
@ -4628,7 +4678,7 @@ static int jsonEachClose(sqlite3_vtab_cursor *cur){
|
||||
JsonEachCursor *p = (JsonEachCursor*)cur;
|
||||
jsonEachCursorReset(p);
|
||||
|
||||
sqlite3_free(cur);
|
||||
sqlite3DbFree(p->db, cur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@ -4962,6 +5012,7 @@ static int jsonEachFilter(
|
||||
if( idxNum==0 ) return SQLITE_OK;
|
||||
memset(&p->sParse, 0, sizeof(p->sParse));
|
||||
p->sParse.nJPRef = 1;
|
||||
p->sParse.db = p->db;
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
|
||||
if( jsonFuncArgMightBeBinary(argv[0]) ){
|
||||
p->sParse.nBlob = sqlite3_value_bytes(argv[0]);
|
||||
|
@ -4671,7 +4671,7 @@ int sqlite3_test_control(int op, ...){
|
||||
** to be the current setting.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_JSON_SELFCHECK: {
|
||||
#if defined(SQLITE_DEBUG)
|
||||
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
|
||||
int *pOnOff = va_arg(ap, int*);
|
||||
if( *pOnOff<0 ){
|
||||
*pOnOff = sqlite3Config.bJsonSelfcheck;
|
||||
|
@ -807,9 +807,8 @@ int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
if( pPager->pWal ){
|
||||
u32 iRead = 0;
|
||||
int rc;
|
||||
rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
|
||||
return (rc==SQLITE_OK && iRead==0);
|
||||
(void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
|
||||
return iRead==0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
|
@ -328,6 +328,19 @@
|
||||
# undef SQLITE_USE_SEH
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Enable SQLITE_DIRECT_OVERFLOW_READ, unless the build explicitly
|
||||
** disables it using -DSQLITE_DIRECT_OVERFLOW_READ=0
|
||||
*/
|
||||
#if defined(SQLITE_DIRECT_OVERFLOW_READ) && SQLITE_DIRECT_OVERFLOW_READ+1==1
|
||||
/* Disable if -DSQLITE_DIRECT_OVERFLOW_READ=0 */
|
||||
# undef SQLITE_DIRECT_OVERFLOW_READ
|
||||
#else
|
||||
/* In all other cases, enable */
|
||||
# define SQLITE_DIRECT_OVERFLOW_READ 1
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
|
||||
** 0 means mutexes are permanently disable and the library is never
|
||||
@ -2778,6 +2791,7 @@ struct Index {
|
||||
unsigned isCovering:1; /* True if this is a covering index */
|
||||
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
|
||||
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
|
||||
unsigned bLowQual:1; /* sqlite_stat1 says this is a low-quality index */
|
||||
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
|
||||
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
|
||||
unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
|
||||
|
@ -187,7 +187,7 @@
|
||||
** max_page_count macro.
|
||||
*/
|
||||
#ifndef SQLITE_MAX_PAGE_COUNT
|
||||
# define SQLITE_MAX_PAGE_COUNT 1073741823
|
||||
# define SQLITE_MAX_PAGE_COUNT 0xfffffffe /* 4294967294 */
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -4168,6 +4168,7 @@ static int walSearchHash(
|
||||
*piRead = iFrame;
|
||||
}
|
||||
if( (nCollide--)==0 ){
|
||||
*piRead = 0;
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
iKey = walNextHash(iKey);
|
||||
|
@ -2973,7 +2973,10 @@ static int whereLoopAddBtreeIndex(
|
||||
assert( pNew->u.btree.nBtm==0 );
|
||||
opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
|
||||
}
|
||||
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
|
||||
if( pProbe->bUnordered || pProbe->bLowQual ){
|
||||
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
|
||||
if( pProbe->bLowQual ) opMask &= ~(WO_EQ|WO_IN|WO_IS);
|
||||
}
|
||||
|
||||
assert( pNew->u.btree.nEq<pProbe->nColumn );
|
||||
assert( pNew->u.btree.nEq<pProbe->nKeyCol
|
||||
|
440
tool/sqldiff.c
440
tool/sqldiff.c
@ -13,7 +13,8 @@
|
||||
** This is a utility program that computes the differences in content
|
||||
** between two SQLite databases.
|
||||
**
|
||||
** To compile, simply link against SQLite.
|
||||
** To compile, simply link against SQLite. (Windows builds must also link
|
||||
** against ext/consio/console_io.c.)
|
||||
**
|
||||
** See the showHelp() routine below for a brief description of how to
|
||||
** run the utility.
|
||||
@ -26,6 +27,19 @@
|
||||
#include <assert.h>
|
||||
#include "sqlite3.h"
|
||||
|
||||
/* Output function substitutions that cause UTF8 characters to be rendered
|
||||
** correctly on Windows:
|
||||
**
|
||||
** fprintf() -> Wfprintf()
|
||||
**
|
||||
*/
|
||||
#if defined(_WIN32)
|
||||
# include "console_io.h"
|
||||
# define Wfprintf fPrintfUtf8
|
||||
#else
|
||||
# define Wfprintf fprintf
|
||||
#endif
|
||||
|
||||
/*
|
||||
** All global variables are gathered into the "g" singleton.
|
||||
*/
|
||||
@ -46,22 +60,10 @@ struct GlobalVars {
|
||||
#define DEBUG_DIFF_SQL 0x000002
|
||||
|
||||
/*
|
||||
** Dynamic string object
|
||||
** Clear and free an sqlite3_str object
|
||||
*/
|
||||
typedef struct Str Str;
|
||||
struct Str {
|
||||
char *z; /* Text of the string */
|
||||
int nAlloc; /* Bytes allocated in z[] */
|
||||
int nUsed; /* Bytes actually used in z[] */
|
||||
};
|
||||
|
||||
/*
|
||||
** Initialize a Str object
|
||||
*/
|
||||
static void strInit(Str *p){
|
||||
p->z = 0;
|
||||
p->nAlloc = 0;
|
||||
p->nUsed = 0;
|
||||
static void strFree(sqlite3_str *pStr){
|
||||
sqlite3_free(sqlite3_str_finish(pStr));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -69,12 +71,14 @@ static void strInit(Str *p){
|
||||
** abort the program.
|
||||
*/
|
||||
static void cmdlineError(const char *zFormat, ...){
|
||||
sqlite3_str *pOut = sqlite3_str_new(0);
|
||||
va_list ap;
|
||||
fprintf(stderr, "%s: ", g.zArgv0);
|
||||
va_start(ap, zFormat);
|
||||
vfprintf(stderr, zFormat, ap);
|
||||
sqlite3_str_vappendf(pOut, zFormat, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n\"%s --help\" for more help\n", g.zArgv0);
|
||||
Wfprintf(stderr, "%s: %s\n", g.zArgv0, sqlite3_str_value(pOut));
|
||||
strFree(pOut);
|
||||
Wfprintf(stderr, "\"%s --help\" for more help\n", g.zArgv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -83,49 +87,16 @@ static void cmdlineError(const char *zFormat, ...){
|
||||
** abort the program.
|
||||
*/
|
||||
static void runtimeError(const char *zFormat, ...){
|
||||
sqlite3_str *pOut = sqlite3_str_new(0);
|
||||
va_list ap;
|
||||
fprintf(stderr, "%s: ", g.zArgv0);
|
||||
va_start(ap, zFormat);
|
||||
vfprintf(stderr, zFormat, ap);
|
||||
sqlite3_str_vappendf(pOut, zFormat, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
Wfprintf(stderr, "%s: %s\n", g.zArgv0, sqlite3_str_value(pOut));
|
||||
strFree(pOut);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Free all memory held by a Str object
|
||||
*/
|
||||
static void strFree(Str *p){
|
||||
sqlite3_free(p->z);
|
||||
strInit(p);
|
||||
}
|
||||
|
||||
/*
|
||||
** Add formatted text to the end of a Str object
|
||||
*/
|
||||
static void strPrintf(Str *p, const char *zFormat, ...){
|
||||
int nNew;
|
||||
for(;;){
|
||||
if( p->z ){
|
||||
va_list ap;
|
||||
va_start(ap, zFormat);
|
||||
sqlite3_vsnprintf(p->nAlloc-p->nUsed, p->z+p->nUsed, zFormat, ap);
|
||||
va_end(ap);
|
||||
nNew = (int)strlen(p->z + p->nUsed);
|
||||
}else{
|
||||
nNew = p->nAlloc;
|
||||
}
|
||||
if( p->nUsed+nNew < p->nAlloc-1 ){
|
||||
p->nUsed += nNew;
|
||||
break;
|
||||
}
|
||||
p->nAlloc = p->nAlloc*2 + 1000;
|
||||
p->z = sqlite3_realloc(p->z, p->nAlloc);
|
||||
if( p->z==0 ) runtimeError("out of memory");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Safely quote an SQL identifier. Use the minimum amount of transformation
|
||||
** necessary to allow the string to be used with %s.
|
||||
@ -453,7 +424,7 @@ static void dump_table(const char *zTab, FILE *out){
|
||||
int i; /* Loop counter */
|
||||
sqlite3_stmt *pStmt; /* SQL statement */
|
||||
const char *zSep; /* Separator string */
|
||||
Str ins; /* Beginning of the INSERT statement */
|
||||
sqlite3_str *pIns; /* Beginning of the INSERT statement */
|
||||
|
||||
pStmt = db_prepare("SELECT sql FROM aux.sqlite_schema WHERE name=%Q", zTab);
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
@ -462,54 +433,53 @@ static void dump_table(const char *zTab, FILE *out){
|
||||
sqlite3_finalize(pStmt);
|
||||
if( !g.bSchemaOnly ){
|
||||
az = columnNames("aux", zTab, &nPk, 0);
|
||||
strInit(&ins);
|
||||
pIns = sqlite3_str_new(0);
|
||||
if( az==0 ){
|
||||
pStmt = db_prepare("SELECT * FROM aux.%s", zId);
|
||||
strPrintf(&ins,"INSERT INTO %s VALUES", zId);
|
||||
sqlite3_str_appendf(pIns,"INSERT INTO %s VALUES", zId);
|
||||
}else{
|
||||
Str sql;
|
||||
strInit(&sql);
|
||||
sqlite3_str *pSql = sqlite3_str_new(0);
|
||||
zSep = "SELECT";
|
||||
for(i=0; az[i]; i++){
|
||||
strPrintf(&sql, "%s %s", zSep, az[i]);
|
||||
sqlite3_str_appendf(pSql, "%s %s", zSep, az[i]);
|
||||
zSep = ",";
|
||||
}
|
||||
strPrintf(&sql," FROM aux.%s", zId);
|
||||
sqlite3_str_appendf(pSql," FROM aux.%s", zId);
|
||||
zSep = " ORDER BY";
|
||||
for(i=1; i<=nPk; i++){
|
||||
strPrintf(&sql, "%s %d", zSep, i);
|
||||
sqlite3_str_appendf(pSql, "%s %d", zSep, i);
|
||||
zSep = ",";
|
||||
}
|
||||
pStmt = db_prepare("%s", sql.z);
|
||||
strFree(&sql);
|
||||
strPrintf(&ins, "INSERT INTO %s", zId);
|
||||
pStmt = db_prepare("%s", sqlite3_str_value(pSql));
|
||||
strFree(pSql);
|
||||
sqlite3_str_appendf(pIns, "INSERT INTO %s", zId);
|
||||
zSep = "(";
|
||||
for(i=0; az[i]; i++){
|
||||
strPrintf(&ins, "%s%s", zSep, az[i]);
|
||||
sqlite3_str_appendf(pIns, "%s%s", zSep, az[i]);
|
||||
zSep = ",";
|
||||
}
|
||||
strPrintf(&ins,") VALUES");
|
||||
sqlite3_str_appendf(pIns,") VALUES");
|
||||
namelistFree(az);
|
||||
}
|
||||
nCol = sqlite3_column_count(pStmt);
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
fprintf(out, "%s",ins.z);
|
||||
Wfprintf(out, "%s",sqlite3_str_value(pIns));
|
||||
zSep = "(";
|
||||
for(i=0; i<nCol; i++){
|
||||
fprintf(out, "%s",zSep);
|
||||
Wfprintf(out, "%s",zSep);
|
||||
printQuoted(out, sqlite3_column_value(pStmt,i));
|
||||
zSep = ",";
|
||||
}
|
||||
fprintf(out, ");\n");
|
||||
Wfprintf(out, ");\n");
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
strFree(&ins);
|
||||
strFree(pIns);
|
||||
} /* endif !g.bSchemaOnly */
|
||||
pStmt = db_prepare("SELECT sql FROM aux.sqlite_schema"
|
||||
" WHERE type='index' AND tbl_name=%Q AND sql IS NOT NULL",
|
||||
zTab);
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
|
||||
Wfprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_free(zId);
|
||||
@ -531,12 +501,12 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
int nQ; /* Number of output columns in the diff query */
|
||||
int i; /* Loop counter */
|
||||
const char *zSep; /* Separator string */
|
||||
Str sql; /* Comparison query */
|
||||
sqlite3_str *pSql; /* Comparison query */
|
||||
sqlite3_stmt *pStmt; /* Query statement to do the diff */
|
||||
const char *zLead = /* Becomes line-comment for sqlite_schema */
|
||||
(g.bSchemaCompare)? "-- " : "";
|
||||
|
||||
strInit(&sql);
|
||||
pSql = sqlite3_str_new(0);
|
||||
if( g.fDebug==DEBUG_COLUMN_NAMES ){
|
||||
/* Simply run columnNames() on all tables of the origin
|
||||
** database and show the results. This is used for testing
|
||||
@ -544,14 +514,14 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
*/
|
||||
az = columnNames("aux",zTab, &nPk, 0);
|
||||
if( az==0 ){
|
||||
printf("Rowid not accessible for %s\n", zId);
|
||||
Wfprintf(stdout, "Rowid not accessible for %s\n", zId);
|
||||
}else{
|
||||
printf("%s:", zId);
|
||||
Wfprintf(stdout, "%s:", zId);
|
||||
for(i=0; az[i]; i++){
|
||||
printf(" %s", az[i]);
|
||||
if( i+1==nPk ) printf(" *");
|
||||
Wfprintf(stdout, " %s", az[i]);
|
||||
if( i+1==nPk ) Wfprintf(stdout, " *");
|
||||
}
|
||||
printf("\n");
|
||||
Wfprintf(stdout, "\n");
|
||||
}
|
||||
goto end_diff_one_table;
|
||||
}
|
||||
@ -560,19 +530,20 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
if( !sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
|
||||
/* Table missing from second database. */
|
||||
if( g.bSchemaCompare )
|
||||
fprintf(out, "-- 2nd DB has no %s table\n", zTab);
|
||||
Wfprintf(out, "-- 2nd DB has no %s table\n", zTab);
|
||||
else
|
||||
fprintf(out, "DROP TABLE %s;\n", zId);
|
||||
Wfprintf(out, "DROP TABLE %s;\n", zId);
|
||||
}
|
||||
goto end_diff_one_table;
|
||||
}
|
||||
|
||||
if( sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
|
||||
/* Table missing from source */
|
||||
if( g.bSchemaCompare )
|
||||
fprintf(out, "-- 1st DB has no %s table\n", zTab);
|
||||
else
|
||||
if( g.bSchemaCompare ){
|
||||
Wfprintf(out, "-- 1st DB has no %s table\n", zTab);
|
||||
}else{
|
||||
dump_table(zTab, out);
|
||||
}
|
||||
goto end_diff_one_table;
|
||||
}
|
||||
|
||||
@ -589,7 +560,7 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
|| az[n]
|
||||
){
|
||||
/* Schema mismatch */
|
||||
fprintf(out, "%sDROP TABLE %s; -- due to schema mismatch\n", zLead, zId);
|
||||
Wfprintf(out, "%sDROP TABLE %s; -- due to schema mismatch\n", zLead, zId);
|
||||
dump_table(zTab, out);
|
||||
goto end_diff_one_table;
|
||||
}
|
||||
@ -597,93 +568,93 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
/* Build the comparison query */
|
||||
for(n2=n; az2[n2]; n2++){
|
||||
char *zNTab = safeId(az2[n2]);
|
||||
fprintf(out, "ALTER TABLE %s ADD COLUMN %s;\n", zId, zNTab);
|
||||
Wfprintf(out, "ALTER TABLE %s ADD COLUMN %s;\n", zId, zNTab);
|
||||
sqlite3_free(zNTab);
|
||||
}
|
||||
nQ = nPk2+1+2*(n2-nPk2);
|
||||
if( n2>nPk2 ){
|
||||
zSep = "SELECT ";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%sB.%s", zSep, az[i]);
|
||||
sqlite3_str_appendf(pSql, "%sB.%s", zSep, az[i]);
|
||||
zSep = ", ";
|
||||
}
|
||||
strPrintf(&sql, ", 1 /* changed row */");
|
||||
sqlite3_str_appendf(pSql, ", 1 /* changed row */");
|
||||
while( az[i] ){
|
||||
strPrintf(&sql, ", A.%s IS NOT B.%s, B.%s",
|
||||
sqlite3_str_appendf(pSql, ", A.%s IS NOT B.%s, B.%s",
|
||||
az[i], az2[i], az2[i]);
|
||||
i++;
|
||||
}
|
||||
while( az2[i] ){
|
||||
strPrintf(&sql, ", B.%s IS NOT NULL, B.%s",
|
||||
sqlite3_str_appendf(pSql, ", B.%s IS NOT NULL, B.%s",
|
||||
az2[i], az2[i]);
|
||||
i++;
|
||||
}
|
||||
strPrintf(&sql, "\n FROM main.%s A, aux.%s B\n", zId, zId);
|
||||
sqlite3_str_appendf(pSql, "\n FROM main.%s A, aux.%s B\n", zId, zId);
|
||||
zSep = " WHERE";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
|
||||
sqlite3_str_appendf(pSql, "%s A.%s=B.%s", zSep, az[i], az[i]);
|
||||
zSep = " AND";
|
||||
}
|
||||
zSep = "\n AND (";
|
||||
while( az[i] ){
|
||||
strPrintf(&sql, "%sA.%s IS NOT B.%s%s\n",
|
||||
sqlite3_str_appendf(pSql, "%sA.%s IS NOT B.%s%s\n",
|
||||
zSep, az[i], az2[i], az2[i+1]==0 ? ")" : "");
|
||||
zSep = " OR ";
|
||||
i++;
|
||||
}
|
||||
while( az2[i] ){
|
||||
strPrintf(&sql, "%sB.%s IS NOT NULL%s\n",
|
||||
sqlite3_str_appendf(pSql, "%sB.%s IS NOT NULL%s\n",
|
||||
zSep, az2[i], az2[i+1]==0 ? ")" : "");
|
||||
zSep = " OR ";
|
||||
i++;
|
||||
}
|
||||
strPrintf(&sql, " UNION ALL\n");
|
||||
sqlite3_str_appendf(pSql, " UNION ALL\n");
|
||||
}
|
||||
zSep = "SELECT ";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%sA.%s", zSep, az[i]);
|
||||
sqlite3_str_appendf(pSql, "%sA.%s", zSep, az[i]);
|
||||
zSep = ", ";
|
||||
}
|
||||
strPrintf(&sql, ", 2 /* deleted row */");
|
||||
sqlite3_str_appendf(pSql, ", 2 /* deleted row */");
|
||||
while( az2[i] ){
|
||||
strPrintf(&sql, ", NULL, NULL");
|
||||
sqlite3_str_appendf(pSql, ", NULL, NULL");
|
||||
i++;
|
||||
}
|
||||
strPrintf(&sql, "\n FROM main.%s A\n", zId);
|
||||
strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B\n", zId);
|
||||
sqlite3_str_appendf(pSql, "\n FROM main.%s A\n", zId);
|
||||
sqlite3_str_appendf(pSql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B\n", zId);
|
||||
zSep = " WHERE";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
|
||||
sqlite3_str_appendf(pSql, "%s A.%s=B.%s", zSep, az[i], az[i]);
|
||||
zSep = " AND";
|
||||
}
|
||||
strPrintf(&sql, ")\n");
|
||||
sqlite3_str_appendf(pSql, ")\n");
|
||||
zSep = " UNION ALL\nSELECT ";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%sB.%s", zSep, az[i]);
|
||||
sqlite3_str_appendf(pSql, "%sB.%s", zSep, az[i]);
|
||||
zSep = ", ";
|
||||
}
|
||||
strPrintf(&sql, ", 3 /* inserted row */");
|
||||
sqlite3_str_appendf(pSql, ", 3 /* inserted row */");
|
||||
while( az2[i] ){
|
||||
strPrintf(&sql, ", 1, B.%s", az2[i]);
|
||||
sqlite3_str_appendf(pSql, ", 1, B.%s", az2[i]);
|
||||
i++;
|
||||
}
|
||||
strPrintf(&sql, "\n FROM aux.%s B\n", zId);
|
||||
strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A\n", zId);
|
||||
sqlite3_str_appendf(pSql, "\n FROM aux.%s B\n", zId);
|
||||
sqlite3_str_appendf(pSql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A\n", zId);
|
||||
zSep = " WHERE";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
|
||||
sqlite3_str_appendf(pSql, "%s A.%s=B.%s", zSep, az[i], az[i]);
|
||||
zSep = " AND";
|
||||
}
|
||||
strPrintf(&sql, ")\n ORDER BY");
|
||||
sqlite3_str_appendf(pSql, ")\n ORDER BY");
|
||||
zSep = " ";
|
||||
for(i=1; i<=nPk; i++){
|
||||
strPrintf(&sql, "%s%d", zSep, i);
|
||||
sqlite3_str_appendf(pSql, "%s%d", zSep, i);
|
||||
zSep = ", ";
|
||||
}
|
||||
strPrintf(&sql, ";\n");
|
||||
sqlite3_str_appendf(pSql, ";\n");
|
||||
|
||||
if( g.fDebug & DEBUG_DIFF_SQL ){
|
||||
printf("SQL for %s:\n%s\n", zId, sql.z);
|
||||
printf("SQL for %s:\n%s\n", zId, sqlite3_str_value(pSql));
|
||||
goto end_diff_one_table;
|
||||
}
|
||||
|
||||
@ -705,7 +676,7 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
|
||||
/* Run the query and output differences */
|
||||
if( !g.bSchemaOnly ){
|
||||
pStmt = db_prepare("%s", sql.z);
|
||||
pStmt = db_prepare("%s", sqlite3_str_value(pSql));
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
int iType = sqlite3_column_int(pStmt, nPk);
|
||||
if( iType==1 || iType==2 ){
|
||||
@ -763,7 +734,7 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
sqlite3_finalize(pStmt);
|
||||
|
||||
end_diff_one_table:
|
||||
strFree(&sql);
|
||||
strFree(pSql);
|
||||
sqlite3_free(zId);
|
||||
namelistFree(az);
|
||||
namelistFree(az2);
|
||||
@ -1171,15 +1142,15 @@ static int rbuDeltaCreate(
|
||||
**************************************************************************/
|
||||
|
||||
static void strPrintfArray(
|
||||
Str *pStr, /* String object to append to */
|
||||
sqlite3_str *pStr, /* String object to append to */
|
||||
const char *zSep, /* Separator string */
|
||||
const char *zFmt, /* Format for each entry */
|
||||
char **az, int n /* Array of strings & its size (or -1) */
|
||||
){
|
||||
int i;
|
||||
for(i=0; az[i] && (i<n || n<0); i++){
|
||||
if( i!=0 ) strPrintf(pStr, "%s", zSep);
|
||||
strPrintf(pStr, zFmt, az[i], az[i], az[i]);
|
||||
if( i!=0 ) sqlite3_str_appendf(pStr, "%s", zSep);
|
||||
sqlite3_str_appendf(pStr, zFmt, az[i], az[i], az[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1188,74 +1159,75 @@ static void getRbudiffQuery(
|
||||
char **azCol,
|
||||
int nPK,
|
||||
int bOtaRowid,
|
||||
Str *pSql
|
||||
sqlite3_str *pSql
|
||||
){
|
||||
int i;
|
||||
|
||||
/* First the newly inserted rows: **/
|
||||
strPrintf(pSql, "SELECT ");
|
||||
sqlite3_str_appendf(pSql, "SELECT ");
|
||||
strPrintfArray(pSql, ", ", "%s", azCol, -1);
|
||||
strPrintf(pSql, ", 0, "); /* Set ota_control to 0 for an insert */
|
||||
sqlite3_str_appendf(pSql, ", 0, "); /* Set ota_control to 0 for an insert */
|
||||
strPrintfArray(pSql, ", ", "NULL", azCol, -1);
|
||||
strPrintf(pSql, " FROM aux.%Q AS n WHERE NOT EXISTS (\n", zTab);
|
||||
strPrintf(pSql, " SELECT 1 FROM ", zTab);
|
||||
strPrintf(pSql, " main.%Q AS o WHERE ", zTab);
|
||||
sqlite3_str_appendf(pSql, " FROM aux.%Q AS n WHERE NOT EXISTS (\n", zTab);
|
||||
sqlite3_str_appendf(pSql, " SELECT 1 FROM ", zTab);
|
||||
sqlite3_str_appendf(pSql, " main.%Q AS o WHERE ", zTab);
|
||||
strPrintfArray(pSql, " AND ", "(n.%Q = o.%Q)", azCol, nPK);
|
||||
strPrintf(pSql, "\n) AND ");
|
||||
sqlite3_str_appendf(pSql, "\n) AND ");
|
||||
strPrintfArray(pSql, " AND ", "(n.%Q IS NOT NULL)", azCol, nPK);
|
||||
|
||||
/* Deleted rows: */
|
||||
strPrintf(pSql, "\nUNION ALL\nSELECT ");
|
||||
sqlite3_str_appendf(pSql, "\nUNION ALL\nSELECT ");
|
||||
strPrintfArray(pSql, ", ", "%s", azCol, nPK);
|
||||
if( azCol[nPK] ){
|
||||
strPrintf(pSql, ", ");
|
||||
sqlite3_str_appendf(pSql, ", ");
|
||||
strPrintfArray(pSql, ", ", "NULL", &azCol[nPK], -1);
|
||||
}
|
||||
strPrintf(pSql, ", 1, "); /* Set ota_control to 1 for a delete */
|
||||
sqlite3_str_appendf(pSql, ", 1, "); /* Set ota_control to 1 for a delete */
|
||||
strPrintfArray(pSql, ", ", "NULL", azCol, -1);
|
||||
strPrintf(pSql, " FROM main.%Q AS n WHERE NOT EXISTS (\n", zTab);
|
||||
strPrintf(pSql, " SELECT 1 FROM ", zTab);
|
||||
strPrintf(pSql, " aux.%Q AS o WHERE ", zTab);
|
||||
sqlite3_str_appendf(pSql, " FROM main.%Q AS n WHERE NOT EXISTS (\n", zTab);
|
||||
sqlite3_str_appendf(pSql, " SELECT 1 FROM ", zTab);
|
||||
sqlite3_str_appendf(pSql, " aux.%Q AS o WHERE ", zTab);
|
||||
strPrintfArray(pSql, " AND ", "(n.%Q = o.%Q)", azCol, nPK);
|
||||
strPrintf(pSql, "\n) AND ");
|
||||
sqlite3_str_appendf(pSql, "\n) AND ");
|
||||
strPrintfArray(pSql, " AND ", "(n.%Q IS NOT NULL)", azCol, nPK);
|
||||
|
||||
/* Updated rows. If all table columns are part of the primary key, there
|
||||
** can be no updates. In this case this part of the compound SELECT can
|
||||
** be omitted altogether. */
|
||||
if( azCol[nPK] ){
|
||||
strPrintf(pSql, "\nUNION ALL\nSELECT ");
|
||||
sqlite3_str_appendf(pSql, "\nUNION ALL\nSELECT ");
|
||||
strPrintfArray(pSql, ", ", "n.%s", azCol, nPK);
|
||||
strPrintf(pSql, ",\n");
|
||||
sqlite3_str_appendf(pSql, ",\n");
|
||||
strPrintfArray(pSql, " ,\n",
|
||||
" CASE WHEN n.%s IS o.%s THEN NULL ELSE n.%s END", &azCol[nPK], -1
|
||||
);
|
||||
|
||||
if( bOtaRowid==0 ){
|
||||
strPrintf(pSql, ", '");
|
||||
sqlite3_str_appendf(pSql, ", '");
|
||||
strPrintfArray(pSql, "", ".", azCol, nPK);
|
||||
strPrintf(pSql, "' ||\n");
|
||||
sqlite3_str_appendf(pSql, "' ||\n");
|
||||
}else{
|
||||
strPrintf(pSql, ",\n");
|
||||
sqlite3_str_appendf(pSql, ",\n");
|
||||
}
|
||||
strPrintfArray(pSql, " ||\n",
|
||||
" CASE WHEN n.%s IS o.%s THEN '.' ELSE 'x' END", &azCol[nPK], -1
|
||||
);
|
||||
strPrintf(pSql, "\nAS ota_control, ");
|
||||
sqlite3_str_appendf(pSql, "\nAS ota_control, ");
|
||||
strPrintfArray(pSql, ", ", "NULL", azCol, nPK);
|
||||
strPrintf(pSql, ",\n");
|
||||
sqlite3_str_appendf(pSql, ",\n");
|
||||
strPrintfArray(pSql, " ,\n",
|
||||
" CASE WHEN n.%s IS o.%s THEN NULL ELSE o.%s END", &azCol[nPK], -1
|
||||
);
|
||||
|
||||
strPrintf(pSql, "\nFROM main.%Q AS o, aux.%Q AS n\nWHERE ", zTab, zTab);
|
||||
sqlite3_str_appendf(pSql, "\nFROM main.%Q AS o, aux.%Q AS n\nWHERE ",
|
||||
zTab, zTab);
|
||||
strPrintfArray(pSql, " AND ", "(n.%Q = o.%Q)", azCol, nPK);
|
||||
strPrintf(pSql, " AND ota_control LIKE '%%x%%'");
|
||||
sqlite3_str_appendf(pSql, " AND ota_control LIKE '%%x%%'");
|
||||
}
|
||||
|
||||
/* Now add an ORDER BY clause to sort everything by PK. */
|
||||
strPrintf(pSql, "\nORDER BY ");
|
||||
for(i=1; i<=nPK; i++) strPrintf(pSql, "%s%d", ((i>1)?", ":""), i);
|
||||
sqlite3_str_appendf(pSql, "\nORDER BY ");
|
||||
for(i=1; i<=nPK; i++) sqlite3_str_appendf(pSql, "%s%d", ((i>1)?", ":""), i);
|
||||
}
|
||||
|
||||
static void rbudiff_one_table(const char *zTab, FILE *out){
|
||||
@ -1264,14 +1236,17 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
|
||||
char **azCol; /* NULL terminated array of col names */
|
||||
int i;
|
||||
int nCol;
|
||||
Str ct = {0, 0, 0}; /* The "CREATE TABLE data_xxx" statement */
|
||||
Str sql = {0, 0, 0}; /* Query to find differences */
|
||||
Str insert = {0, 0, 0}; /* First part of output INSERT statement */
|
||||
sqlite3_str *pCt; /* The "CREATE TABLE data_xxx" statement */
|
||||
sqlite3_str *pSql; /* Query to find differences */
|
||||
sqlite3_str *pInsert; /* First part of output INSERT statement */
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
int nRow = 0; /* Total rows in data_xxx table */
|
||||
|
||||
/* --rbu mode must use real primary keys. */
|
||||
g.bSchemaPK = 1;
|
||||
pCt = sqlite3_str_new(0);
|
||||
pSql = sqlite3_str_new(0);
|
||||
pInsert = sqlite3_str_new(0);
|
||||
|
||||
/* Check that the schemas of the two tables match. Exit early otherwise. */
|
||||
checkSchemasMatch(zTab);
|
||||
@ -1285,35 +1260,35 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
|
||||
for(nCol=0; azCol[nCol]; nCol++);
|
||||
|
||||
/* Build and output the CREATE TABLE statement for the data_xxx table */
|
||||
strPrintf(&ct, "CREATE TABLE IF NOT EXISTS 'data_%q'(", zTab);
|
||||
if( bOtaRowid ) strPrintf(&ct, "rbu_rowid, ");
|
||||
strPrintfArray(&ct, ", ", "%s", &azCol[bOtaRowid], -1);
|
||||
strPrintf(&ct, ", rbu_control);");
|
||||
sqlite3_str_appendf(pCt, "CREATE TABLE IF NOT EXISTS 'data_%q'(", zTab);
|
||||
if( bOtaRowid ) sqlite3_str_appendf(pCt, "rbu_rowid, ");
|
||||
strPrintfArray(pCt, ", ", "%s", &azCol[bOtaRowid], -1);
|
||||
sqlite3_str_appendf(pCt, ", rbu_control);");
|
||||
|
||||
/* Get the SQL for the query to retrieve data from the two databases */
|
||||
getRbudiffQuery(zTab, azCol, nPK, bOtaRowid, &sql);
|
||||
getRbudiffQuery(zTab, azCol, nPK, bOtaRowid, pSql);
|
||||
|
||||
/* Build the first part of the INSERT statement output for each row
|
||||
** in the data_xxx table. */
|
||||
strPrintf(&insert, "INSERT INTO 'data_%q' (", zTab);
|
||||
if( bOtaRowid ) strPrintf(&insert, "rbu_rowid, ");
|
||||
strPrintfArray(&insert, ", ", "%s", &azCol[bOtaRowid], -1);
|
||||
strPrintf(&insert, ", rbu_control) VALUES(");
|
||||
sqlite3_str_appendf(pInsert, "INSERT INTO 'data_%q' (", zTab);
|
||||
if( bOtaRowid ) sqlite3_str_appendf(pInsert, "rbu_rowid, ");
|
||||
strPrintfArray(pInsert, ", ", "%s", &azCol[bOtaRowid], -1);
|
||||
sqlite3_str_appendf(pInsert, ", rbu_control) VALUES(");
|
||||
|
||||
pStmt = db_prepare("%s", sql.z);
|
||||
pStmt = db_prepare("%s", sqlite3_str_value(pSql));
|
||||
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
|
||||
/* If this is the first row output, print out the CREATE TABLE
|
||||
** statement first. And then set ct.z to NULL so that it is not
|
||||
** statement first. And reset pCt so that it will not be
|
||||
** printed again. */
|
||||
if( ct.z ){
|
||||
fprintf(out, "%s\n", ct.z);
|
||||
strFree(&ct);
|
||||
if( sqlite3_str_length(pCt) ){
|
||||
fprintf(out, "%s\n", sqlite3_str_value(pCt));
|
||||
sqlite3_str_reset(pCt);
|
||||
}
|
||||
|
||||
/* Output the first part of the INSERT statement */
|
||||
fprintf(out, "%s", insert.z);
|
||||
fprintf(out, "%s", sqlite3_str_value(pInsert));
|
||||
nRow++;
|
||||
|
||||
if( sqlite3_column_type(pStmt, nCol)==SQLITE_INTEGER ){
|
||||
@ -1369,15 +1344,16 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
|
||||
|
||||
sqlite3_finalize(pStmt);
|
||||
if( nRow>0 ){
|
||||
Str cnt = {0, 0, 0};
|
||||
strPrintf(&cnt, "INSERT INTO rbu_count VALUES('data_%q', %d);", zTab, nRow);
|
||||
fprintf(out, "%s\n", cnt.z);
|
||||
strFree(&cnt);
|
||||
sqlite3_str *pCnt = sqlite3_str_new(0);
|
||||
sqlite3_str_appendf(pCnt,
|
||||
"INSERT INTO rbu_count VALUES('data_%q', %d);", zTab, nRow);
|
||||
fprintf(out, "%s\n", sqlite3_str_value(pCnt));
|
||||
strFree(pCnt);
|
||||
}
|
||||
|
||||
strFree(&ct);
|
||||
strFree(&sql);
|
||||
strFree(&insert);
|
||||
strFree(pCt);
|
||||
strFree(pSql);
|
||||
strFree(pInsert);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1399,25 +1375,25 @@ static void summarize_one_table(const char *zTab, FILE *out){
|
||||
int n2; /* Number of columns in aux */
|
||||
int i; /* Loop counter */
|
||||
const char *zSep; /* Separator string */
|
||||
Str sql; /* Comparison query */
|
||||
sqlite3_str *pSql; /* Comparison query */
|
||||
sqlite3_stmt *pStmt; /* Query statement to do the diff */
|
||||
sqlite3_int64 nUpdate; /* Number of updated rows */
|
||||
sqlite3_int64 nUnchanged; /* Number of unmodified rows */
|
||||
sqlite3_int64 nDelete; /* Number of deleted rows */
|
||||
sqlite3_int64 nInsert; /* Number of inserted rows */
|
||||
|
||||
strInit(&sql);
|
||||
pSql = sqlite3_str_new(0);
|
||||
if( sqlite3_table_column_metadata(g.db,"aux",zTab,0,0,0,0,0,0) ){
|
||||
if( !sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
|
||||
/* Table missing from second database. */
|
||||
fprintf(out, "%s: missing from second database\n", zTab);
|
||||
Wfprintf(out, "%s: missing from second database\n", zTab);
|
||||
}
|
||||
goto end_summarize_one_table;
|
||||
}
|
||||
|
||||
if( sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
|
||||
/* Table missing from source */
|
||||
fprintf(out, "%s: missing from first database\n", zTab);
|
||||
Wfprintf(out, "%s: missing from first database\n", zTab);
|
||||
goto end_summarize_one_table;
|
||||
}
|
||||
|
||||
@ -1434,57 +1410,57 @@ static void summarize_one_table(const char *zTab, FILE *out){
|
||||
|| az[n]
|
||||
){
|
||||
/* Schema mismatch */
|
||||
fprintf(out, "%s: incompatible schema\n", zTab);
|
||||
Wfprintf(out, "%s: incompatible schema\n", zTab);
|
||||
goto end_summarize_one_table;
|
||||
}
|
||||
|
||||
/* Build the comparison query */
|
||||
for(n2=n; az[n2]; n2++){}
|
||||
strPrintf(&sql, "SELECT 1, count(*)");
|
||||
sqlite3_str_appendf(pSql, "SELECT 1, count(*)");
|
||||
if( n2==nPk2 ){
|
||||
strPrintf(&sql, ", 0\n");
|
||||
sqlite3_str_appendf(pSql, ", 0\n");
|
||||
}else{
|
||||
zSep = ", sum(";
|
||||
for(i=nPk; az[i]; i++){
|
||||
strPrintf(&sql, "%sA.%s IS NOT B.%s", zSep, az[i], az[i]);
|
||||
sqlite3_str_appendf(pSql, "%sA.%s IS NOT B.%s", zSep, az[i], az[i]);
|
||||
zSep = " OR ";
|
||||
}
|
||||
strPrintf(&sql, ")\n");
|
||||
sqlite3_str_appendf(pSql, ")\n");
|
||||
}
|
||||
strPrintf(&sql, " FROM main.%s A, aux.%s B\n", zId, zId);
|
||||
sqlite3_str_appendf(pSql, " FROM main.%s A, aux.%s B\n", zId, zId);
|
||||
zSep = " WHERE";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
|
||||
sqlite3_str_appendf(pSql, "%s A.%s=B.%s", zSep, az[i], az[i]);
|
||||
zSep = " AND";
|
||||
}
|
||||
strPrintf(&sql, " UNION ALL\n");
|
||||
strPrintf(&sql, "SELECT 2, count(*), 0\n");
|
||||
strPrintf(&sql, " FROM main.%s A\n", zId);
|
||||
strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B ", zId);
|
||||
sqlite3_str_appendf(pSql, " UNION ALL\n");
|
||||
sqlite3_str_appendf(pSql, "SELECT 2, count(*), 0\n");
|
||||
sqlite3_str_appendf(pSql, " FROM main.%s A\n", zId);
|
||||
sqlite3_str_appendf(pSql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B ", zId);
|
||||
zSep = "WHERE";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
|
||||
sqlite3_str_appendf(pSql, "%s A.%s=B.%s", zSep, az[i], az[i]);
|
||||
zSep = " AND";
|
||||
}
|
||||
strPrintf(&sql, ")\n");
|
||||
strPrintf(&sql, " UNION ALL\n");
|
||||
strPrintf(&sql, "SELECT 3, count(*), 0\n");
|
||||
strPrintf(&sql, " FROM aux.%s B\n", zId);
|
||||
strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A ", zId);
|
||||
sqlite3_str_appendf(pSql, ")\n");
|
||||
sqlite3_str_appendf(pSql, " UNION ALL\n");
|
||||
sqlite3_str_appendf(pSql, "SELECT 3, count(*), 0\n");
|
||||
sqlite3_str_appendf(pSql, " FROM aux.%s B\n", zId);
|
||||
sqlite3_str_appendf(pSql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A ", zId);
|
||||
zSep = "WHERE";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
|
||||
sqlite3_str_appendf(pSql, "%s A.%s=B.%s", zSep, az[i], az[i]);
|
||||
zSep = " AND";
|
||||
}
|
||||
strPrintf(&sql, ")\n ORDER BY 1;\n");
|
||||
sqlite3_str_appendf(pSql, ")\n ORDER BY 1;\n");
|
||||
|
||||
if( (g.fDebug & DEBUG_DIFF_SQL)!=0 ){
|
||||
printf("SQL for %s:\n%s\n", zId, sql.z);
|
||||
Wfprintf(stdout, "SQL for %s:\n%s\n", zId, sqlite3_str_value(pSql));
|
||||
goto end_summarize_one_table;
|
||||
}
|
||||
|
||||
/* Run the query and output difference summary */
|
||||
pStmt = db_prepare("%s", sql.z);
|
||||
pStmt = db_prepare("%s", sqlite3_str_value(pSql));
|
||||
nUpdate = 0;
|
||||
nInsert = 0;
|
||||
nDelete = 0;
|
||||
@ -1504,11 +1480,12 @@ static void summarize_one_table(const char *zTab, FILE *out){
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
fprintf(out, "%s: %lld changes, %lld inserts, %lld deletes, %lld unchanged\n",
|
||||
Wfprintf(out,
|
||||
"%s: %lld changes, %lld inserts, %lld deletes, %lld unchanged\n",
|
||||
zTab, nUpdate, nInsert, nDelete, nUnchanged);
|
||||
|
||||
end_summarize_one_table:
|
||||
strFree(&sql);
|
||||
strFree(pSql);
|
||||
sqlite3_free(zId);
|
||||
namelistFree(az);
|
||||
namelistFree(az2);
|
||||
@ -1588,13 +1565,13 @@ static void changeset_one_table(const char *zTab, FILE *out){
|
||||
int *aiFlg = 0; /* 0 if column is not part of PK */
|
||||
int *aiPk = 0; /* Column numbers for each PK column */
|
||||
int nPk = 0; /* Number of PRIMARY KEY columns */
|
||||
Str sql; /* SQL for the diff query */
|
||||
sqlite3_str *pSql; /* SQL for the diff query */
|
||||
int i, k; /* Loop counters */
|
||||
const char *zSep; /* List separator */
|
||||
|
||||
/* Check that the schemas of the two tables match. Exit early otherwise. */
|
||||
checkSchemasMatch(zTab);
|
||||
strInit(&sql);
|
||||
pSql = sqlite3_str_new(0);
|
||||
|
||||
pStmt = db_prepare("PRAGMA main.table_info=%Q", zTab);
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
@ -1617,71 +1594,74 @@ static void changeset_one_table(const char *zTab, FILE *out){
|
||||
sqlite3_finalize(pStmt);
|
||||
if( nPk==0 ) goto end_changeset_one_table;
|
||||
if( nCol>nPk ){
|
||||
strPrintf(&sql, "SELECT %d", SQLITE_UPDATE);
|
||||
sqlite3_str_appendf(pSql, "SELECT %d", SQLITE_UPDATE);
|
||||
for(i=0; i<nCol; i++){
|
||||
if( aiFlg[i] ){
|
||||
strPrintf(&sql, ",\n A.%s", azCol[i]);
|
||||
sqlite3_str_appendf(pSql, ",\n A.%s", azCol[i]);
|
||||
}else{
|
||||
strPrintf(&sql, ",\n A.%s IS NOT B.%s, A.%s, B.%s",
|
||||
sqlite3_str_appendf(pSql, ",\n A.%s IS NOT B.%s, A.%s, B.%s",
|
||||
azCol[i], azCol[i], azCol[i], azCol[i]);
|
||||
}
|
||||
}
|
||||
strPrintf(&sql,"\n FROM main.%s A, aux.%s B\n", zId, zId);
|
||||
sqlite3_str_appendf(pSql,"\n FROM main.%s A, aux.%s B\n", zId, zId);
|
||||
zSep = " WHERE";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%s A.%s=B.%s", zSep, azCol[aiPk[i]], azCol[aiPk[i]]);
|
||||
sqlite3_str_appendf(pSql, "%s A.%s=B.%s",
|
||||
zSep, azCol[aiPk[i]], azCol[aiPk[i]]);
|
||||
zSep = " AND";
|
||||
}
|
||||
zSep = "\n AND (";
|
||||
for(i=0; i<nCol; i++){
|
||||
if( aiFlg[i] ) continue;
|
||||
strPrintf(&sql, "%sA.%s IS NOT B.%s", zSep, azCol[i], azCol[i]);
|
||||
sqlite3_str_appendf(pSql, "%sA.%s IS NOT B.%s", zSep, azCol[i], azCol[i]);
|
||||
zSep = " OR\n ";
|
||||
}
|
||||
strPrintf(&sql,")\n UNION ALL\n");
|
||||
sqlite3_str_appendf(pSql,")\n UNION ALL\n");
|
||||
}
|
||||
strPrintf(&sql, "SELECT %d", SQLITE_DELETE);
|
||||
sqlite3_str_appendf(pSql, "SELECT %d", SQLITE_DELETE);
|
||||
for(i=0; i<nCol; i++){
|
||||
if( aiFlg[i] ){
|
||||
strPrintf(&sql, ",\n A.%s", azCol[i]);
|
||||
sqlite3_str_appendf(pSql, ",\n A.%s", azCol[i]);
|
||||
}else{
|
||||
strPrintf(&sql, ",\n 1, A.%s, NULL", azCol[i]);
|
||||
sqlite3_str_appendf(pSql, ",\n 1, A.%s, NULL", azCol[i]);
|
||||
}
|
||||
}
|
||||
strPrintf(&sql, "\n FROM main.%s A\n", zId);
|
||||
strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B\n", zId);
|
||||
sqlite3_str_appendf(pSql, "\n FROM main.%s A\n", zId);
|
||||
sqlite3_str_appendf(pSql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B\n", zId);
|
||||
zSep = " WHERE";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%s A.%s=B.%s", zSep, azCol[aiPk[i]], azCol[aiPk[i]]);
|
||||
sqlite3_str_appendf(pSql, "%s A.%s=B.%s",
|
||||
zSep, azCol[aiPk[i]], azCol[aiPk[i]]);
|
||||
zSep = " AND";
|
||||
}
|
||||
strPrintf(&sql, ")\n UNION ALL\n");
|
||||
strPrintf(&sql, "SELECT %d", SQLITE_INSERT);
|
||||
sqlite3_str_appendf(pSql, ")\n UNION ALL\n");
|
||||
sqlite3_str_appendf(pSql, "SELECT %d", SQLITE_INSERT);
|
||||
for(i=0; i<nCol; i++){
|
||||
if( aiFlg[i] ){
|
||||
strPrintf(&sql, ",\n B.%s", azCol[i]);
|
||||
sqlite3_str_appendf(pSql, ",\n B.%s", azCol[i]);
|
||||
}else{
|
||||
strPrintf(&sql, ",\n 1, NULL, B.%s", azCol[i]);
|
||||
sqlite3_str_appendf(pSql, ",\n 1, NULL, B.%s", azCol[i]);
|
||||
}
|
||||
}
|
||||
strPrintf(&sql, "\n FROM aux.%s B\n", zId);
|
||||
strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A\n", zId);
|
||||
sqlite3_str_appendf(pSql, "\n FROM aux.%s B\n", zId);
|
||||
sqlite3_str_appendf(pSql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A\n", zId);
|
||||
zSep = " WHERE";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%s A.%s=B.%s", zSep, azCol[aiPk[i]], azCol[aiPk[i]]);
|
||||
sqlite3_str_appendf(pSql, "%s A.%s=B.%s",
|
||||
zSep, azCol[aiPk[i]], azCol[aiPk[i]]);
|
||||
zSep = " AND";
|
||||
}
|
||||
strPrintf(&sql, ")\n");
|
||||
strPrintf(&sql, " ORDER BY");
|
||||
sqlite3_str_appendf(pSql, ")\n");
|
||||
sqlite3_str_appendf(pSql, " ORDER BY");
|
||||
zSep = " ";
|
||||
for(i=0; i<nPk; i++){
|
||||
strPrintf(&sql, "%s %d", zSep, aiPk[i]+2);
|
||||
sqlite3_str_appendf(pSql, "%s %d", zSep, aiPk[i]+2);
|
||||
zSep = ",";
|
||||
}
|
||||
strPrintf(&sql, ";\n");
|
||||
sqlite3_str_appendf(pSql, ";\n");
|
||||
|
||||
if( g.fDebug & DEBUG_DIFF_SQL ){
|
||||
printf("SQL for %s:\n%s\n", zId, sql.z);
|
||||
Wfprintf(stdout, "SQL for %s:\n%s\n", zId, sqlite3_str_value(pSql));
|
||||
goto end_changeset_one_table;
|
||||
}
|
||||
|
||||
@ -1691,7 +1671,7 @@ static void changeset_one_table(const char *zTab, FILE *out){
|
||||
fwrite(zTab, 1, strlen(zTab), out);
|
||||
putc(0, out);
|
||||
|
||||
pStmt = db_prepare("%s", sql.z);
|
||||
pStmt = db_prepare("%s", sqlite3_str_value(pSql));
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
int iType = sqlite3_column_int(pStmt,0);
|
||||
putc(iType, out);
|
||||
@ -1758,7 +1738,7 @@ end_changeset_one_table:
|
||||
sqlite3_free(aiPk);
|
||||
sqlite3_free(zId);
|
||||
sqlite3_free(aiFlg);
|
||||
strFree(&sql);
|
||||
strFree(pSql);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1911,8 +1891,8 @@ const char *all_tables_sql(){
|
||||
** Print sketchy documentation for this utility program
|
||||
*/
|
||||
static void showHelp(void){
|
||||
printf("Usage: %s [options] DB1 DB2\n", g.zArgv0);
|
||||
printf(
|
||||
Wfprintf(stdout, "Usage: %s [options] DB1 DB2\n", g.zArgv0);
|
||||
Wfprintf(stdout,
|
||||
"Output SQL text that would transform DB1 into DB2.\n"
|
||||
"Options:\n"
|
||||
" --changeset FILE Write a CHANGESET into FILE\n"
|
||||
@ -2049,9 +2029,9 @@ int main(int argc, char **argv){
|
||||
}
|
||||
|
||||
if( neverUseTransaction ) useTransaction = 0;
|
||||
if( useTransaction ) fprintf(out, "BEGIN TRANSACTION;\n");
|
||||
if( useTransaction ) Wfprintf(out, "BEGIN TRANSACTION;\n");
|
||||
if( xDiff==rbudiff_one_table ){
|
||||
fprintf(out, "CREATE TABLE IF NOT EXISTS rbu_count"
|
||||
Wfprintf(out, "CREATE TABLE IF NOT EXISTS rbu_count"
|
||||
"(tbl TEXT PRIMARY KEY COLLATE NOCASE, cnt INTEGER) "
|
||||
"WITHOUT ROWID;\n"
|
||||
);
|
||||
@ -2066,7 +2046,7 @@ int main(int argc, char **argv){
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
if( useTransaction ) printf("COMMIT;\n");
|
||||
if( useTransaction ) Wfprintf(stdout,"COMMIT;\n");
|
||||
|
||||
/* TBD: Handle trigger differences */
|
||||
/* TBD: Handle view differences */
|
||||
|
@ -19,8 +19,55 @@ INCLUDE sqlite3.c
|
||||
#endif
|
||||
INCLUDE $ROOT/src/tclsqlite.c
|
||||
|
||||
#if defined(_WIN32)
|
||||
INCLUDE $ROOT/ext/consio/console_io.h
|
||||
INCLUDE $ROOT/ext/consio/console_io.c
|
||||
|
||||
/* Substitute "puts" command. Only these forms recognized:
|
||||
**
|
||||
** puts STRING
|
||||
** puts stderr STRING
|
||||
** puts -nonewline STRING
|
||||
*/
|
||||
static int subst_puts(
|
||||
void *NotUsed,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const*objv
|
||||
){
|
||||
FILE *pOut = stdout;
|
||||
const char *zOut;
|
||||
int addNewLine = 1;
|
||||
if( objc==2 ){
|
||||
zOut = Tcl_GetString(objv[1]);
|
||||
}else if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?stderr|-nonewline? STRING");
|
||||
return TCL_ERROR;
|
||||
}else{
|
||||
const char *zArg = Tcl_GetString(objv[1]);
|
||||
if( zArg==0 ) return TCL_ERROR;
|
||||
zOut = Tcl_GetString(objv[2]);
|
||||
if( strcmp(zArg, "stderr")==0 ){
|
||||
pOut = stderr;
|
||||
}else if( strcmp(zArg, "-nonewline")==0 ){
|
||||
addNewLine = 0;
|
||||
}else{
|
||||
Tcl_AppendResult(interp, "bad argument: ", zArg, 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
fPutsUtf8(zOut, pOut);
|
||||
if( addNewLine ) fPutsUtf8("\n", pOut);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
const char *sqlite3_analyzer_init_proc(Tcl_Interp *interp){
|
||||
#if defined(_WIN32)
|
||||
Tcl_CreateObjCommand(interp, "puts", subst_puts, 0, 0);
|
||||
#else
|
||||
(void)interp;
|
||||
#endif
|
||||
return
|
||||
BEGIN_STRING
|
||||
INCLUDE $ROOT/tool/spaceanal.tcl
|
||||
|
Loading…
x
Reference in New Issue
Block a user