Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merged in trunk. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | version-cmd-describe |
| Files: | files | file ages | folders |
| SHA3-256: |
6bdb2fbe99fccf7c4c837bddb441721b |
| User & Date: | danield 2022-06-17 09:43:42.006 |
Context
|
2022-06-17
| ||
| 10:57 | Create a placeholder manifest.descr file via auto.def, analog to [a198cde661ca]. ... (Leaf check-in: 56614cb6a9 user: stephan tags: version-cmd-describe) | |
| 09:43 | Merged in trunk. ... (check-in: 6bdb2fbe99 user: danield tags: version-cmd-describe) | |
| 09:32 | Add generation of manifest.descr to Makefile.msc (via makemake.tcl); this can be removed after 'version --describe' support gets built in. ... (check-in: a198cde661 user: danield tags: version-cmd-describe) | |
|
2022-06-15
| ||
| 17:37 | Update the built-in SQLite to the latest 3.39.0 beta, for testing. ... (check-in: b0f84d8d17 user: drh tags: trunk) | |
Changes
Changes to .fossil-settings/binary-glob.
1 2 3 4 5 6 7 8 9 10 11 12 | *.gif *.ico *.jpg *.odp *.dia *.pdf *.png *.wav compat/zlib/contrib/blast/test.pk compat/zlib/contrib/dotzlib/DotZLib.chm compat/zlib/contrib/puff/zeros.raw compat/zlib/zlib.3.pdf | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 | *.gif *.ico *.jpg *.odp *.dia *.pdf *.png *.wav compat/zlib/contrib/blast/test.pk compat/zlib/contrib/dotzlib/DotZLib.chm compat/zlib/contrib/puff/zeros.raw compat/zlib/zlib.3.pdf extsrc/pikchr.wasm |
Changes to Makefile.in.
| ︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | TCLSH = @TCLSH@ CFLAGS = @CFLAGS@ CFLAGS_INCLUDE = @CFLAGS_INCLUDE@ LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ BCCFLAGS = @CPPFLAGS@ $(CFLAGS) TCCFLAGS = @EXTRA_CFLAGS@ @CPPFLAGS@ $(CFLAGS) -DHAVE_AUTOCONFIG_H -D_HAVE_SQLITE_CONFIG_H INSTALLDIR = $(DESTDIR)@prefix@/bin USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@ SQLITE3_SRC.2 = @SQLITE3_SRC.2@ SQLITE3_OBJ.2 = @SQLITE3_OBJ.2@ SQLITE3_SHELL_SRC.2 = @SQLITE3_SHELL_SRC.2@ SQLITE3_ORIGIN = @SQLITE3_ORIGIN@ # SQLITE3_ORIGIN changes... # SQLITE3_SRC: # 0=src/sqlite3.c, 1=src/sqlite3-see.c, 2=$(SQLITE3_SRC.2) # SQLITE3_SHELL_SRC: # 0=src/shell.c, 1=src/shell-see.c, 2=$(SQLITE3_SHELL_SRC.2) USE_LINENOISE = @USE_LINENOISE@ USE_MMAN_H = @USE_MMAN_H@ USE_SEE = @USE_SEE@ APPNAME = fossil .PHONY: all tags include $(SRCDIR)/main.mk distclean: clean -rm -f autoconfig.h config.log Makefile | > > > > > > > > > > > > > > > > > > > > > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | TCLSH = @TCLSH@ CFLAGS = @CFLAGS@ CFLAGS_INCLUDE = @CFLAGS_INCLUDE@ LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ BCCFLAGS = @CPPFLAGS@ $(CFLAGS) TCCFLAGS = @EXTRA_CFLAGS@ @CPPFLAGS@ $(CFLAGS) -DHAVE_AUTOCONFIG_H -D_HAVE_SQLITE_CONFIG_H # # Fuzzing may be enable by appending -fsanitize=fuzzer -DFOSSIL_FUZZ # to the TCCFLAGS variable. # For more thorouth (but also slower) investigation # -fsanitize=fuzzer,undefined,address # might be more useful. INSTALLDIR = $(DESTDIR)@prefix@/bin USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@ SQLITE3_SRC.2 = @SQLITE3_SRC.2@ SQLITE3_OBJ.2 = @SQLITE3_OBJ.2@ SQLITE3_SHELL_SRC.2 = @SQLITE3_SHELL_SRC.2@ SQLITE3_ORIGIN = @SQLITE3_ORIGIN@ # SQLITE3_ORIGIN changes... # SQLITE3_SRC: # 0=src/sqlite3.c, 1=src/sqlite3-see.c, 2=$(SQLITE3_SRC.2) # SQLITE3_SHELL_SRC: # 0=src/shell.c, 1=src/shell-see.c, 2=$(SQLITE3_SHELL_SRC.2) USE_LINENOISE = @USE_LINENOISE@ USE_MMAN_H = @USE_MMAN_H@ USE_SEE = @USE_SEE@ APPNAME = fossil # # APPNAME = fossil-fuzz # may be more appropriate for fuzzing. #### Emscripten stuff for optionally doing in-tree builds # of any WASM components. We store precompiled WASM in the the SCM, so # this is only useful for people who actively work on WASM # components. EMSDK_ENV refers to the "environment" script which comes # with the Emscripten SDK package: # https://emscripten.org/docs/getting_started/downloads.html EMSDK_HOME = @EMSDK_HOME@ EMSDK_ENV = @EMSDK_ENV@ EMCC_OPT = @EMCC_OPT@ EMCC_WRAPPER = $(SRCDIR_tools)/emcc.sh .PHONY: all tags include $(SRCDIR)/main.mk distclean: clean -rm -f autoconfig.h config.log Makefile |
| ︙ | ︙ |
Changes to auto.def.
| ︙ | ︙ | |||
26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
=> {print the minimum SQLite version number required, and exit}
internal-sqlite=1 => {Don't use the internal SQLite, use the system one}
static=0 => {Link a static executable}
fusefs=1 => {Disable the Fuse Filesystem}
fossil-debug=0 => {Build with fossil debugging enabled}
no-opt=0 => {Build without optimization}
json=0 => {Build with fossil JSON API enabled}
}
# Update the minimum required SQLite version number here, and also
# in src/main.c near the sqlite3_libversion_number() call. Take care
# that both places agree!
define MINIMUM_SQLITE_VERSION "3.38.0"
| > | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
=> {print the minimum SQLite version number required, and exit}
internal-sqlite=1 => {Don't use the internal SQLite, use the system one}
static=0 => {Link a static executable}
fusefs=1 => {Disable the Fuse Filesystem}
fossil-debug=0 => {Build with fossil debugging enabled}
no-opt=0 => {Build without optimization}
json=0 => {Build with fossil JSON API enabled}
with-emsdk:path => {Directory containing the Emscripten SDK}
}
# Update the minimum required SQLite version number here, and also
# in src/main.c near the sqlite3_libversion_number() call. Take care
# that both places agree!
define MINIMUM_SQLITE_VERSION "3.38.0"
|
| ︙ | ︙ | |||
630 631 632 633 634 635 636 637 638 639 640 641 642 643 |
# be checked for near the bottom of this file.
#
set tclconfig(TCL_LD_FLAGS) [string map [list -ldl ""] \
$tclconfig(TCL_LD_FLAGS)]
define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS)
define FOSSIL_ENABLE_TCL
}
# Network functions require libraries on some systems
cc-check-function-in-lib gethostbyname nsl
if {![cc-check-function-in-lib socket {socket network}]} {
# Last resort, may be Windows
if {[is_mingw]} {
define-append LIBS -lwsock32
| > > > > > > > > > > > > > > > > > > > > > > > > > > > | 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 |
# be checked for near the bottom of this file.
#
set tclconfig(TCL_LD_FLAGS) [string map [list -ldl ""] \
$tclconfig(TCL_LD_FLAGS)]
define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS)
define FOSSIL_ENABLE_TCL
}
# Emscripten is a purely optional component used only for doing
# in-tree builds of WASM stuff, as opposed to WASM binaries we import
# from other places. This is only set up for Unix-style OSes and is
# untested anywhere but Linux.
set emsdkHome [opt-val with-emsdk]
define EMSDK_HOME ""
define EMSDK_ENV ""
define EMCC_OPT "-Oz"
if {$emsdkHome eq "" && [info exists ::env(EMSDK)]} {
# Fall back to checking the environment. $EMSDK gets set
# by sourcing emsdk_env.sh.
set emsdkHome $::env(EMSDK)
}
if {$emsdkHome ne ""} {
define EMSDK_HOME $emsdkHome
set emsdkEnv "$emsdkHome/emsdk_env.sh"
if {[file exists $emsdkEnv]} {
puts "Using Emscripten SDK environment from $emsdkEnv."
define EMSDK_ENV $emsdkEnv
if {[info exists ::env(EMCC_OPT)]} {
define EMCC_OPT $::env(EMCC_OPT)
}
} else {
puts "emsdk_env.sh not found. Assuming emcc is in the PATH."
}
}
# Network functions require libraries on some systems
cc-check-function-in-lib gethostbyname nsl
if {![cc-check-function-in-lib socket {socket network}]} {
# Last resort, may be Windows
if {[is_mingw]} {
define-append LIBS -lwsock32
|
| ︙ | ︙ | |||
724 725 726 727 728 729 730 731 732 733 |
}
if {[opt-bool static]} {
# Linux can only infer the dependency on pthread from OpenSSL when
# doing dynamic linkage.
define-append LIBS -lpthread
}
make-template Makefile.in
make-config-header autoconfig.h -auto {USE_* FOSSIL_*}
| > > > > > > > > | 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 |
}
if {[opt-bool static]} {
# Linux can only infer the dependency on pthread from OpenSSL when
# doing dynamic linkage.
define-append LIBS -lpthread
}
if {[get-define EMSDK_HOME] ne ""} {
define EMCC_WRAPPER $::autosetup(dir)/../tools/emcc.sh
make-template tools/emcc.sh.in
catch {exec chmod u+x tools/emcc.sh}
} else {
define EMCC_WRAPPER ""
catch {exec rm -f tools/emcc.sh}
}
make-template Makefile.in
make-config-header autoconfig.h -auto {USE_* FOSSIL_*}
|
Added extsrc/pikchr-worker.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
/*
2022-05-20
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
This is a JS Worker file for use with the pikchr wasm build. It
loads the pikchr wasm module and offers access to it via the Worker
message-passing interface.
Because we can have only a single message handler, as opposed to an
arbitrary number of discrete event listeners like with DOM elements,
we have to define a lower-level message API. Messages abstractly
look like:
{ type: string, data: type-specific value }
Where 'type' is used for dispatching and 'data' is a
'type'-dependent value.
The 'type' values expected by each side of the main/worker
connection vary. The types are described below but subject to
change at any time as this experiment evolves.
Main-to-Worker message types:
- pikchr: data=pikchr-format text to render or an object:
{
pikchr: source code for the pikchr,
darkMode: boolean true to adjust colors for a dark color scheme,
cssClass: CSS class name to add to the SVG
}
Workers-to-Main types
- stdout, stderr: indicate stdout/stderr output from the wasm
layer. The data property is the string of the output, noting
that the emscripten binding emits these one line at a time. Thus,
if a C-side puts() emits multiple lines in a single call, the JS
side will see that as multiple calls. Example:
{type:'stdout', data: 'Hi, world.'}
- module: Status text. This is intended to alert the main thread
about module loading status so that, e.g., the main thread can
update a progress widget and DTRT when the module is finished
loading and available for work. Status messages come in the form
{type:'module', data:{
type:'status',
data: {text:string|null, step:1-based-integer}
}
with an incrementing step value for each subsequent message. When
the module loading is complete, a message with a text value of
null is posted.
- pikchr:
{type: 'pikchr',
data:{
pikchr: input text,
result: rendered result (SVG on success, HTML on error),
isError: bool, true if .result holds an error report,
flags: integer: flags used to configure the pikchr rendering,
width: if !isError, width (integer pixels) of the SVG,
height: if !isError, height (integer pixels) of the SVG
}
}
*/
"use strict";
(function(){
/**
Posts a message in the form {type,data} unless passed more than
2 args, in which case it posts {type, data:[arg1...argN]}.
*/
const wMsg = function(type,data){
postMessage({
type,
data: arguments.length<3
? data
: Array.prototype.slice.call(arguments,1)
});
};
const stderr = function(){wMsg('stderr', Array.prototype.slice.call(arguments));};
self.onerror = function(/*message, source, lineno, colno, error*/) {
const err = arguments[4];
if(err && 'ExitStatus'==err.name){
/* This "cannot happen" for this wasm binding, but just in
case... */
pikchrModule.isDead = true;
stderr("FATAL ERROR:", err.message);
stderr("Restarting the app requires reloading the page.");
wMsg('error', err);
}
pikchrModule.setStatus('Exception thrown, see JavaScript console: '+err);
};
self.onmessage = function f(ev){
ev = ev.data;
switch(ev.type){
/**
Runs the given text through pikchr and emits a 'pikchr'
message result (output format documented above).
Fires a working/start event before it starts and
working/end event when it finishes.
*/
case 'pikchr':
if(pikchrModule.isDead){
stderr("wasm module has exit()ed. Cannot pikchr.");
return;
}
if(!f._){
f._ = pikchrModule.cwrap('pikchr', 'string', [
'string'/*script*/, 'string'/*CSS class*/, 'number'/*flags*/,
'number'/*output: SVG width*/, 'number'/*output: SVG height*/
]);
}
wMsg('working','start');
const stack = pikchrModule.stackSave();
try {
const pnWidth = pikchrModule.stackAlloc(4),
pnHeight = pikchrModule.stackAlloc(4);
let script = '', flags = 0, cssClass = null;
if('string'===typeof ev.data){
script = ev.data;
}else if(ev.data && 'object'===typeof ev.data){
script = ev.data.pikchr;
flags = ev.data.darkMode ? 0x02 : 0;
if(ev.data.cssClass) cssClass = ev.data.cssClass;
}
pikchrModule.setValue(pnWidth, 0, "i32");
pikchrModule.setValue(pnHeight, 0, "i32");
const msg = {
pikchr: script,
result: (f._(script, cssClass, flags, pnWidth, pnHeight) || "").trim(),
flags: flags
};
msg.isError = !!(msg.result && msg.result.startsWith('<div'));
if(msg.isError){
msg.width = msg.height = null;
}else{
msg.width = pikchrModule.getValue(pnWidth, "i32");
msg.height = pikchrModule.getValue(pnHeight, "i32");
}
wMsg('pikchr', msg);
} finally {
pikchrModule.stackRestore(stack);
wMsg('working','end');
}
return;
};
console.warn("Unknown pikchr-worker message type:",ev);
};
/**
emscripten module for use with build mode -sMODULARIZE.
*/
const pikchrModule = {
print: function(){wMsg('stdout', Array.prototype.slice.call(arguments));},
printErr: stderr,
/**
Intercepts status updates from the emscripting module init
and fires worker events with a type of 'status' and a
payload of:
{
text: string | null, // null at end of load process
step: integer // starts at 1, increments 1 per call
}
We have no way of knowing in advance how many steps will
be processed/posted, so creating a "percentage done" view is
not really practical. One can be approximated by giving it a
current value of message.step and max value of message.step+1,
though.
When work is finished, a message with a text value of null is
submitted.
After a message with text==null is posted, the module may later
post messages about fatal problems, e.g. an exit() being
triggered, so it is recommended that UI elements for posting
status messages not be outright removed from the DOM when
text==null, and that they instead be hidden until/unless
text!=null.
*/
setStatus: function f(text){
if(!f.last) f.last = { step: 0, text: '' };
else if(text === f.last.text) return;
f.last.text = text;
wMsg('module',{
type:'status',
data:{step: ++f.last.step, text: text||null}
});
}
};
importScripts('pikchr.js');
/**
initPikchrModule() is installed via pikchr.js due to
building with:
emcc ... -sMODULARIZE=1 -sEXPORT_NAME=initPikchrModule
*/
initPikchrModule(pikchrModule).then(function(thisModule){
wMsg('pikchrshow-ready');
});
})();
|
Changes to extsrc/pikchr.c.
| ︙ | ︙ | |||
122 123 124 125 126 127 128 129 130 131 132 133 134 135 | #include <ctype.h> #include <math.h> #include <assert.h> #define count(X) (sizeof(X)/sizeof(X[0])) #ifndef M_PI # define M_PI 3.1415926535897932385 #endif /* Tag intentionally unused parameters with this macro to prevent ** compiler warnings with -Wextra */ #define UNUSED_PARAMETER(X) (void)(X) typedef struct Pik Pik; /* Complete parsing context */ typedef struct PToken PToken; /* A single token */ | > > > > > > > > > | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | #include <ctype.h> #include <math.h> #include <assert.h> #define count(X) (sizeof(X)/sizeof(X[0])) #ifndef M_PI # define M_PI 3.1415926535897932385 #endif /* Limit the number of tokens in a single script to avoid run-away ** macro expansion attacks. See forum post ** https://pikchr.org/home/forumpost/ef8684c6955a411a */ #ifndef PIKCHR_TOKEN_LIMIT # define PIKCHR_TOKEN_LIMIT 100000 #endif /* Tag intentionally unused parameters with this macro to prevent ** compiler warnings with -Wextra */ #define UNUSED_PARAMETER(X) (void)(X) typedef struct Pik Pik; /* Complete parsing context */ typedef struct PToken PToken; /* A single token */ |
| ︙ | ︙ | |||
339 340 341 342 343 344 345 346 347 348 349 350 351 352 |
};
/* Each call to the pikchr() subroutine uses an instance of the following
** object to pass around context to all of its subroutines.
*/
struct Pik {
unsigned nErr; /* Number of errors seen */
PToken sIn; /* Input Pikchr-language text */
char *zOut; /* Result accumulates here */
unsigned int nOut; /* Bytes written to zOut[] so far */
unsigned int nOutAlloc; /* Space allocated to zOut[] */
unsigned char eDir; /* Current direction */
unsigned int mFlags; /* Flags passed to pikchr() */
PObj *cur; /* Object under construction */
| > | 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
};
/* Each call to the pikchr() subroutine uses an instance of the following
** object to pass around context to all of its subroutines.
*/
struct Pik {
unsigned nErr; /* Number of errors seen */
unsigned nToken; /* Number of tokens parsed */
PToken sIn; /* Input Pikchr-language text */
char *zOut; /* Result accumulates here */
unsigned int nOut; /* Bytes written to zOut[] so far */
unsigned int nOutAlloc; /* Space allocated to zOut[] */
unsigned char eDir; /* Current direction */
unsigned int mFlags; /* Flags passed to pikchr() */
PObj *cur; /* Object under construction */
|
| ︙ | ︙ | |||
477 478 479 480 481 482 483 | static void pik_behind(Pik*,PObj*); static PObj *pik_assert(Pik*,PNum,PToken*,PNum); static PObj *pik_position_assert(Pik*,PPoint*,PToken*,PPoint*); static PNum pik_dist(PPoint*,PPoint*); static void pik_add_macro(Pik*,PToken *pId,PToken *pCode); | | | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 | static void pik_behind(Pik*,PObj*); static PObj *pik_assert(Pik*,PNum,PToken*,PNum); static PObj *pik_position_assert(Pik*,PPoint*,PToken*,PPoint*); static PNum pik_dist(PPoint*,PPoint*); static void pik_add_macro(Pik*,PToken *pId,PToken *pCode); #line 520 "pikchr.c" /**************** End of %include directives **********************************/ /* These constants specify the various numeric values for terminal symbols. ***************** Begin token definitions *************************************/ #ifndef T_ID #define T_ID 1 #define T_EDGEPT 2 #define T_OF 3 |
| ︙ | ︙ | |||
1706 1707 1708 1709 1710 1711 1712 |
** Note: during a reduce, the only symbols destroyed are those
** which appear on the RHS of the rule, but which are *not* used
** inside the C code.
*/
/********* Begin destructor definitions ***************************************/
case 99: /* statement_list */
{
| | | | | | 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 |
** Note: during a reduce, the only symbols destroyed are those
** which appear on the RHS of the rule, but which are *not* used
** inside the C code.
*/
/********* Begin destructor definitions ***************************************/
case 99: /* statement_list */
{
#line 509 "pikchr.y"
pik_elist_free(p,(yypminor->yy227));
#line 1750 "pikchr.c"
}
break;
case 100: /* statement */
case 101: /* unnamed_statement */
case 102: /* basetype */
{
#line 511 "pikchr.y"
pik_elem_free(p,(yypminor->yy36));
#line 1759 "pikchr.c"
}
break;
/********* End destructor definitions *****************************************/
default: break; /* If no destructor action specified: do nothing */
}
}
|
| ︙ | ︙ | |||
1935 1936 1937 1938 1939 1940 1941 |
fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
}
#endif
while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will execute if the parser
** stack every overflows */
/******** Begin %stack_overflow code ******************************************/
| | | | 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 |
fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
}
#endif
while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will execute if the parser
** stack every overflows */
/******** Begin %stack_overflow code ******************************************/
#line 543 "pikchr.y"
pik_error(p, 0, "parser stack overflow");
#line 1980 "pikchr.c"
/******** End %stack_overflow code ********************************************/
pik_parserARG_STORE /* Suppress warning about unused %extra_argument var */
pik_parserCTX_STORE
}
/*
** Print tracing information for a SHIFT action
|
| ︙ | ︙ | |||
2418 2419 2420 2421 2422 2423 2424 |
** { ... } // User supplied code
** #line <lineno> <thisfile>
** break;
*/
/********** Begin reduce actions **********************************************/
YYMINORTYPE yylhsminor;
case 0: /* document ::= statement_list */
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 |
** { ... } // User supplied code
** #line <lineno> <thisfile>
** break;
*/
/********** Begin reduce actions **********************************************/
YYMINORTYPE yylhsminor;
case 0: /* document ::= statement_list */
#line 547 "pikchr.y"
{pik_render(p,yymsp[0].minor.yy227);}
#line 2462 "pikchr.c"
break;
case 1: /* statement_list ::= statement */
#line 550 "pikchr.y"
{ yylhsminor.yy227 = pik_elist_append(p,0,yymsp[0].minor.yy36); }
#line 2467 "pikchr.c"
yymsp[0].minor.yy227 = yylhsminor.yy227;
break;
case 2: /* statement_list ::= statement_list EOL statement */
#line 552 "pikchr.y"
{ yylhsminor.yy227 = pik_elist_append(p,yymsp[-2].minor.yy227,yymsp[0].minor.yy36); }
#line 2473 "pikchr.c"
yymsp[-2].minor.yy227 = yylhsminor.yy227;
break;
case 3: /* statement ::= */
#line 555 "pikchr.y"
{ yymsp[1].minor.yy36 = 0; }
#line 2479 "pikchr.c"
break;
case 4: /* statement ::= direction */
#line 556 "pikchr.y"
{ pik_set_direction(p,yymsp[0].minor.yy0.eCode); yylhsminor.yy36=0; }
#line 2484 "pikchr.c"
yymsp[0].minor.yy36 = yylhsminor.yy36;
break;
case 5: /* statement ::= lvalue ASSIGN rvalue */
#line 557 "pikchr.y"
{pik_set_var(p,&yymsp[-2].minor.yy0,yymsp[0].minor.yy153,&yymsp[-1].minor.yy0); yylhsminor.yy36=0;}
#line 2490 "pikchr.c"
yymsp[-2].minor.yy36 = yylhsminor.yy36;
break;
case 6: /* statement ::= PLACENAME COLON unnamed_statement */
#line 559 "pikchr.y"
{ yylhsminor.yy36 = yymsp[0].minor.yy36; pik_elem_setname(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0); }
#line 2496 "pikchr.c"
yymsp[-2].minor.yy36 = yylhsminor.yy36;
break;
case 7: /* statement ::= PLACENAME COLON position */
#line 561 "pikchr.y"
{ yylhsminor.yy36 = pik_elem_new(p,0,0,0);
if(yylhsminor.yy36){ yylhsminor.yy36->ptAt = yymsp[0].minor.yy79; pik_elem_setname(p,yylhsminor.yy36,&yymsp[-2].minor.yy0); }}
#line 2503 "pikchr.c"
yymsp[-2].minor.yy36 = yylhsminor.yy36;
break;
case 8: /* statement ::= unnamed_statement */
#line 563 "pikchr.y"
{yylhsminor.yy36 = yymsp[0].minor.yy36;}
#line 2509 "pikchr.c"
yymsp[0].minor.yy36 = yylhsminor.yy36;
break;
case 9: /* statement ::= print prlist */
#line 564 "pikchr.y"
{pik_append(p,"<br>\n",5); yymsp[-1].minor.yy36=0;}
#line 2515 "pikchr.c"
break;
case 10: /* statement ::= ASSERT LP expr EQ expr RP */
#line 569 "pikchr.y"
{yymsp[-5].minor.yy36=pik_assert(p,yymsp[-3].minor.yy153,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy153);}
#line 2520 "pikchr.c"
break;
case 11: /* statement ::= ASSERT LP position EQ position RP */
#line 571 "pikchr.y"
{yymsp[-5].minor.yy36=pik_position_assert(p,&yymsp[-3].minor.yy79,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy79);}
#line 2525 "pikchr.c"
break;
case 12: /* statement ::= DEFINE ID CODEBLOCK */
#line 572 "pikchr.y"
{yymsp[-2].minor.yy36=0; pik_add_macro(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
#line 2530 "pikchr.c"
break;
case 13: /* rvalue ::= PLACENAME */
#line 583 "pikchr.y"
{yylhsminor.yy153 = pik_lookup_color(p,&yymsp[0].minor.yy0);}
#line 2535 "pikchr.c"
yymsp[0].minor.yy153 = yylhsminor.yy153;
break;
case 14: /* pritem ::= FILL */
case 15: /* pritem ::= COLOR */ yytestcase(yyruleno==15);
case 16: /* pritem ::= THICKNESS */ yytestcase(yyruleno==16);
#line 588 "pikchr.y"
{pik_append_num(p,"",pik_value(p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.n,0));}
#line 2543 "pikchr.c"
break;
case 17: /* pritem ::= rvalue */
#line 591 "pikchr.y"
{pik_append_num(p,"",yymsp[0].minor.yy153);}
#line 2548 "pikchr.c"
break;
case 18: /* pritem ::= STRING */
#line 592 "pikchr.y"
{pik_append_text(p,yymsp[0].minor.yy0.z+1,yymsp[0].minor.yy0.n-2,0);}
#line 2553 "pikchr.c"
break;
case 19: /* prsep ::= COMMA */
#line 593 "pikchr.y"
{pik_append(p, " ", 1);}
#line 2558 "pikchr.c"
break;
case 20: /* unnamed_statement ::= basetype attribute_list */
#line 596 "pikchr.y"
{yylhsminor.yy36 = yymsp[-1].minor.yy36; pik_after_adding_attributes(p,yylhsminor.yy36);}
#line 2563 "pikchr.c"
yymsp[-1].minor.yy36 = yylhsminor.yy36;
break;
case 21: /* basetype ::= CLASSNAME */
#line 598 "pikchr.y"
{yylhsminor.yy36 = pik_elem_new(p,&yymsp[0].minor.yy0,0,0); }
#line 2569 "pikchr.c"
yymsp[0].minor.yy36 = yylhsminor.yy36;
break;
case 22: /* basetype ::= STRING textposition */
#line 600 "pikchr.y"
{yymsp[-1].minor.yy0.eCode = yymsp[0].minor.yy164; yylhsminor.yy36 = pik_elem_new(p,0,&yymsp[-1].minor.yy0,0); }
#line 2575 "pikchr.c"
yymsp[-1].minor.yy36 = yylhsminor.yy36;
break;
case 23: /* basetype ::= LB savelist statement_list RB */
#line 602 "pikchr.y"
{ p->list = yymsp[-2].minor.yy227; yymsp[-3].minor.yy36 = pik_elem_new(p,0,0,yymsp[-1].minor.yy227); if(yymsp[-3].minor.yy36) yymsp[-3].minor.yy36->errTok = yymsp[0].minor.yy0; }
#line 2581 "pikchr.c"
break;
case 24: /* savelist ::= */
#line 607 "pikchr.y"
{yymsp[1].minor.yy227 = p->list; p->list = 0;}
#line 2586 "pikchr.c"
break;
case 25: /* relexpr ::= expr */
#line 614 "pikchr.y"
{yylhsminor.yy10.rAbs = yymsp[0].minor.yy153; yylhsminor.yy10.rRel = 0;}
#line 2591 "pikchr.c"
yymsp[0].minor.yy10 = yylhsminor.yy10;
break;
case 26: /* relexpr ::= expr PERCENT */
#line 615 "pikchr.y"
{yylhsminor.yy10.rAbs = 0; yylhsminor.yy10.rRel = yymsp[-1].minor.yy153/100;}
#line 2597 "pikchr.c"
yymsp[-1].minor.yy10 = yylhsminor.yy10;
break;
case 27: /* optrelexpr ::= */
#line 617 "pikchr.y"
{yymsp[1].minor.yy10.rAbs = 0; yymsp[1].minor.yy10.rRel = 1.0;}
#line 2603 "pikchr.c"
break;
case 28: /* attribute_list ::= relexpr alist */
#line 619 "pikchr.y"
{pik_add_direction(p,0,&yymsp[-1].minor.yy10);}
#line 2608 "pikchr.c"
break;
case 29: /* attribute ::= numproperty relexpr */
#line 623 "pikchr.y"
{ pik_set_numprop(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy10); }
#line 2613 "pikchr.c"
break;
case 30: /* attribute ::= dashproperty expr */
#line 624 "pikchr.y"
{ pik_set_dashed(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy153); }
#line 2618 "pikchr.c"
break;
case 31: /* attribute ::= dashproperty */
#line 625 "pikchr.y"
{ pik_set_dashed(p,&yymsp[0].minor.yy0,0); }
#line 2623 "pikchr.c"
break;
case 32: /* attribute ::= colorproperty rvalue */
#line 626 "pikchr.y"
{ pik_set_clrprop(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy153); }
#line 2628 "pikchr.c"
break;
case 33: /* attribute ::= go direction optrelexpr */
#line 627 "pikchr.y"
{ pik_add_direction(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy10);}
#line 2633 "pikchr.c"
break;
case 34: /* attribute ::= go direction even position */
#line 628 "pikchr.y"
{pik_evenwith(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy79);}
#line 2638 "pikchr.c"
break;
case 35: /* attribute ::= CLOSE */
#line 629 "pikchr.y"
{ pik_close_path(p,&yymsp[0].minor.yy0); }
#line 2643 "pikchr.c"
break;
case 36: /* attribute ::= CHOP */
#line 630 "pikchr.y"
{ p->cur->bChop = 1; }
#line 2648 "pikchr.c"
break;
case 37: /* attribute ::= FROM position */
#line 631 "pikchr.y"
{ pik_set_from(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy79); }
#line 2653 "pikchr.c"
break;
case 38: /* attribute ::= TO position */
#line 632 "pikchr.y"
{ pik_add_to(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy79); }
#line 2658 "pikchr.c"
break;
case 39: /* attribute ::= THEN */
#line 633 "pikchr.y"
{ pik_then(p, &yymsp[0].minor.yy0, p->cur); }
#line 2663 "pikchr.c"
break;
case 40: /* attribute ::= THEN optrelexpr HEADING expr */
case 42: /* attribute ::= GO optrelexpr HEADING expr */ yytestcase(yyruleno==42);
#line 635 "pikchr.y"
{pik_move_hdg(p,&yymsp[-2].minor.yy10,&yymsp[-1].minor.yy0,yymsp[0].minor.yy153,0,&yymsp[-3].minor.yy0);}
#line 2669 "pikchr.c"
break;
case 41: /* attribute ::= THEN optrelexpr EDGEPT */
case 43: /* attribute ::= GO optrelexpr EDGEPT */ yytestcase(yyruleno==43);
#line 636 "pikchr.y"
{pik_move_hdg(p,&yymsp[-1].minor.yy10,0,0,&yymsp[0].minor.yy0,&yymsp[-2].minor.yy0);}
#line 2675 "pikchr.c"
break;
case 44: /* attribute ::= AT position */
#line 641 "pikchr.y"
{ pik_set_at(p,0,&yymsp[0].minor.yy79,&yymsp[-1].minor.yy0); }
#line 2680 "pikchr.c"
break;
case 45: /* attribute ::= SAME */
#line 643 "pikchr.y"
{pik_same(p,0,&yymsp[0].minor.yy0);}
#line 2685 "pikchr.c"
break;
case 46: /* attribute ::= SAME AS object */
#line 644 "pikchr.y"
{pik_same(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);}
#line 2690 "pikchr.c"
break;
case 47: /* attribute ::= STRING textposition */
#line 645 "pikchr.y"
{pik_add_txt(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy164);}
#line 2695 "pikchr.c"
break;
case 48: /* attribute ::= FIT */
#line 646 "pikchr.y"
{pik_size_to_fit(p,&yymsp[0].minor.yy0,3); }
#line 2700 "pikchr.c"
break;
case 49: /* attribute ::= BEHIND object */
#line 647 "pikchr.y"
{pik_behind(p,yymsp[0].minor.yy36);}
#line 2705 "pikchr.c"
break;
case 50: /* withclause ::= DOT_E edge AT position */
case 51: /* withclause ::= edge AT position */ yytestcase(yyruleno==51);
#line 655 "pikchr.y"
{ pik_set_at(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy79,&yymsp[-1].minor.yy0); }
#line 2711 "pikchr.c"
break;
case 52: /* numproperty ::= HEIGHT|WIDTH|RADIUS|DIAMETER|THICKNESS */
#line 659 "pikchr.y"
{yylhsminor.yy0 = yymsp[0].minor.yy0;}
#line 2716 "pikchr.c"
yymsp[0].minor.yy0 = yylhsminor.yy0;
break;
case 53: /* boolproperty ::= CW */
#line 670 "pikchr.y"
{p->cur->cw = 1;}
#line 2722 "pikchr.c"
break;
case 54: /* boolproperty ::= CCW */
#line 671 "pikchr.y"
{p->cur->cw = 0;}
#line 2727 "pikchr.c"
break;
case 55: /* boolproperty ::= LARROW */
#line 672 "pikchr.y"
{p->cur->larrow=1; p->cur->rarrow=0; }
#line 2732 "pikchr.c"
break;
case 56: /* boolproperty ::= RARROW */
#line 673 "pikchr.y"
{p->cur->larrow=0; p->cur->rarrow=1; }
#line 2737 "pikchr.c"
break;
case 57: /* boolproperty ::= LRARROW */
#line 674 "pikchr.y"
{p->cur->larrow=1; p->cur->rarrow=1; }
#line 2742 "pikchr.c"
break;
case 58: /* boolproperty ::= INVIS */
#line 675 "pikchr.y"
{p->cur->sw = 0.0;}
#line 2747 "pikchr.c"
break;
case 59: /* boolproperty ::= THICK */
#line 676 "pikchr.y"
{p->cur->sw *= 1.5;}
#line 2752 "pikchr.c"
break;
case 60: /* boolproperty ::= THIN */
#line 677 "pikchr.y"
{p->cur->sw *= 0.67;}
#line 2757 "pikchr.c"
break;
case 61: /* boolproperty ::= SOLID */
#line 678 "pikchr.y"
{p->cur->sw = pik_value(p,"thickness",9,0);
p->cur->dotted = p->cur->dashed = 0.0;}
#line 2763 "pikchr.c"
break;
case 62: /* textposition ::= */
#line 681 "pikchr.y"
{yymsp[1].minor.yy164 = 0;}
#line 2768 "pikchr.c"
break;
case 63: /* textposition ::= textposition CENTER|LJUST|RJUST|ABOVE|BELOW|ITALIC|BOLD|ALIGNED|BIG|SMALL */
#line 684 "pikchr.y"
{yylhsminor.yy164 = (short int)pik_text_position(yymsp[-1].minor.yy164,&yymsp[0].minor.yy0);}
#line 2773 "pikchr.c"
yymsp[-1].minor.yy164 = yylhsminor.yy164;
break;
case 64: /* position ::= expr COMMA expr */
#line 687 "pikchr.y"
{yylhsminor.yy79.x=yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[0].minor.yy153;}
#line 2779 "pikchr.c"
yymsp[-2].minor.yy79 = yylhsminor.yy79;
break;
case 65: /* position ::= place PLUS expr COMMA expr */
#line 689 "pikchr.y"
{yylhsminor.yy79.x=yymsp[-4].minor.yy79.x+yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[-4].minor.yy79.y+yymsp[0].minor.yy153;}
#line 2785 "pikchr.c"
yymsp[-4].minor.yy79 = yylhsminor.yy79;
break;
case 66: /* position ::= place MINUS expr COMMA expr */
#line 690 "pikchr.y"
{yylhsminor.yy79.x=yymsp[-4].minor.yy79.x-yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[-4].minor.yy79.y-yymsp[0].minor.yy153;}
#line 2791 "pikchr.c"
yymsp[-4].minor.yy79 = yylhsminor.yy79;
break;
case 67: /* position ::= place PLUS LP expr COMMA expr RP */
#line 692 "pikchr.y"
{yylhsminor.yy79.x=yymsp[-6].minor.yy79.x+yymsp[-3].minor.yy153; yylhsminor.yy79.y=yymsp[-6].minor.yy79.y+yymsp[-1].minor.yy153;}
#line 2797 "pikchr.c"
yymsp[-6].minor.yy79 = yylhsminor.yy79;
break;
case 68: /* position ::= place MINUS LP expr COMMA expr RP */
#line 694 "pikchr.y"
{yylhsminor.yy79.x=yymsp[-6].minor.yy79.x-yymsp[-3].minor.yy153; yylhsminor.yy79.y=yymsp[-6].minor.yy79.y-yymsp[-1].minor.yy153;}
#line 2803 "pikchr.c"
yymsp[-6].minor.yy79 = yylhsminor.yy79;
break;
case 69: /* position ::= LP position COMMA position RP */
#line 695 "pikchr.y"
{yymsp[-4].minor.yy79.x=yymsp[-3].minor.yy79.x; yymsp[-4].minor.yy79.y=yymsp[-1].minor.yy79.y;}
#line 2809 "pikchr.c"
break;
case 70: /* position ::= LP position RP */
#line 696 "pikchr.y"
{yymsp[-2].minor.yy79=yymsp[-1].minor.yy79;}
#line 2814 "pikchr.c"
break;
case 71: /* position ::= expr between position AND position */
#line 698 "pikchr.y"
{yylhsminor.yy79 = pik_position_between(yymsp[-4].minor.yy153,yymsp[-2].minor.yy79,yymsp[0].minor.yy79);}
#line 2819 "pikchr.c"
yymsp[-4].minor.yy79 = yylhsminor.yy79;
break;
case 72: /* position ::= expr LT position COMMA position GT */
#line 700 "pikchr.y"
{yylhsminor.yy79 = pik_position_between(yymsp[-5].minor.yy153,yymsp[-3].minor.yy79,yymsp[-1].minor.yy79);}
#line 2825 "pikchr.c"
yymsp[-5].minor.yy79 = yylhsminor.yy79;
break;
case 73: /* position ::= expr ABOVE position */
#line 701 "pikchr.y"
{yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.y += yymsp[-2].minor.yy153;}
#line 2831 "pikchr.c"
yymsp[-2].minor.yy79 = yylhsminor.yy79;
break;
case 74: /* position ::= expr BELOW position */
#line 702 "pikchr.y"
{yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.y -= yymsp[-2].minor.yy153;}
#line 2837 "pikchr.c"
yymsp[-2].minor.yy79 = yylhsminor.yy79;
break;
case 75: /* position ::= expr LEFT OF position */
#line 703 "pikchr.y"
{yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.x -= yymsp[-3].minor.yy153;}
#line 2843 "pikchr.c"
yymsp[-3].minor.yy79 = yylhsminor.yy79;
break;
case 76: /* position ::= expr RIGHT OF position */
#line 704 "pikchr.y"
{yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.x += yymsp[-3].minor.yy153;}
#line 2849 "pikchr.c"
yymsp[-3].minor.yy79 = yylhsminor.yy79;
break;
case 77: /* position ::= expr ON HEADING EDGEPT OF position */
#line 706 "pikchr.y"
{yylhsminor.yy79 = pik_position_at_hdg(yymsp[-5].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);}
#line 2855 "pikchr.c"
yymsp[-5].minor.yy79 = yylhsminor.yy79;
break;
case 78: /* position ::= expr HEADING EDGEPT OF position */
#line 708 "pikchr.y"
{yylhsminor.yy79 = pik_position_at_hdg(yymsp[-4].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);}
#line 2861 "pikchr.c"
yymsp[-4].minor.yy79 = yylhsminor.yy79;
break;
case 79: /* position ::= expr EDGEPT OF position */
#line 710 "pikchr.y"
{yylhsminor.yy79 = pik_position_at_hdg(yymsp[-3].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);}
#line 2867 "pikchr.c"
yymsp[-3].minor.yy79 = yylhsminor.yy79;
break;
case 80: /* position ::= expr ON HEADING expr FROM position */
#line 712 "pikchr.y"
{yylhsminor.yy79 = pik_position_at_angle(yymsp[-5].minor.yy153,yymsp[-2].minor.yy153,yymsp[0].minor.yy79);}
#line 2873 "pikchr.c"
yymsp[-5].minor.yy79 = yylhsminor.yy79;
break;
case 81: /* position ::= expr HEADING expr FROM position */
#line 714 "pikchr.y"
{yylhsminor.yy79 = pik_position_at_angle(yymsp[-4].minor.yy153,yymsp[-2].minor.yy153,yymsp[0].minor.yy79);}
#line 2879 "pikchr.c"
yymsp[-4].minor.yy79 = yylhsminor.yy79;
break;
case 82: /* place ::= edge OF object */
#line 726 "pikchr.y"
{yylhsminor.yy79 = pik_place_of_elem(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);}
#line 2885 "pikchr.c"
yymsp[-2].minor.yy79 = yylhsminor.yy79;
break;
case 83: /* place2 ::= object */
#line 727 "pikchr.y"
{yylhsminor.yy79 = pik_place_of_elem(p,yymsp[0].minor.yy36,0);}
#line 2891 "pikchr.c"
yymsp[0].minor.yy79 = yylhsminor.yy79;
break;
case 84: /* place2 ::= object DOT_E edge */
#line 728 "pikchr.y"
{yylhsminor.yy79 = pik_place_of_elem(p,yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);}
#line 2897 "pikchr.c"
yymsp[-2].minor.yy79 = yylhsminor.yy79;
break;
case 85: /* place2 ::= NTH VERTEX OF object */
#line 729 "pikchr.y"
{yylhsminor.yy79 = pik_nth_vertex(p,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,yymsp[0].minor.yy36);}
#line 2903 "pikchr.c"
yymsp[-3].minor.yy79 = yylhsminor.yy79;
break;
case 86: /* object ::= nth */
#line 741 "pikchr.y"
{yylhsminor.yy36 = pik_find_nth(p,0,&yymsp[0].minor.yy0);}
#line 2909 "pikchr.c"
yymsp[0].minor.yy36 = yylhsminor.yy36;
break;
case 87: /* object ::= nth OF|IN object */
#line 742 "pikchr.y"
{yylhsminor.yy36 = pik_find_nth(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);}
#line 2915 "pikchr.c"
yymsp[-2].minor.yy36 = yylhsminor.yy36;
break;
case 88: /* objectname ::= THIS */
#line 744 "pikchr.y"
{yymsp[0].minor.yy36 = p->cur;}
#line 2921 "pikchr.c"
break;
case 89: /* objectname ::= PLACENAME */
#line 745 "pikchr.y"
{yylhsminor.yy36 = pik_find_byname(p,0,&yymsp[0].minor.yy0);}
#line 2926 "pikchr.c"
yymsp[0].minor.yy36 = yylhsminor.yy36;
break;
case 90: /* objectname ::= objectname DOT_U PLACENAME */
#line 747 "pikchr.y"
{yylhsminor.yy36 = pik_find_byname(p,yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);}
#line 2932 "pikchr.c"
yymsp[-2].minor.yy36 = yylhsminor.yy36;
break;
case 91: /* nth ::= NTH CLASSNAME */
#line 749 "pikchr.y"
{yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-1].minor.yy0); }
#line 2938 "pikchr.c"
yymsp[-1].minor.yy0 = yylhsminor.yy0;
break;
case 92: /* nth ::= NTH LAST CLASSNAME */
#line 750 "pikchr.y"
{yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-2].minor.yy0); }
#line 2944 "pikchr.c"
yymsp[-2].minor.yy0 = yylhsminor.yy0;
break;
case 93: /* nth ::= LAST CLASSNAME */
#line 751 "pikchr.y"
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.eCode = -1;}
#line 2950 "pikchr.c"
break;
case 94: /* nth ::= LAST */
#line 752 "pikchr.y"
{yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -1;}
#line 2955 "pikchr.c"
yymsp[0].minor.yy0 = yylhsminor.yy0;
break;
case 95: /* nth ::= NTH LB RB */
#line 753 "pikchr.y"
{yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-2].minor.yy0);}
#line 2961 "pikchr.c"
yymsp[-2].minor.yy0 = yylhsminor.yy0;
break;
case 96: /* nth ::= NTH LAST LB RB */
#line 754 "pikchr.y"
{yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-3].minor.yy0);}
#line 2967 "pikchr.c"
yymsp[-3].minor.yy0 = yylhsminor.yy0;
break;
case 97: /* nth ::= LAST LB RB */
#line 755 "pikchr.y"
{yymsp[-2].minor.yy0=yymsp[-1].minor.yy0; yymsp[-2].minor.yy0.eCode = -1; }
#line 2973 "pikchr.c"
break;
case 98: /* expr ::= expr PLUS expr */
#line 757 "pikchr.y"
{yylhsminor.yy153=yymsp[-2].minor.yy153+yymsp[0].minor.yy153;}
#line 2978 "pikchr.c"
yymsp[-2].minor.yy153 = yylhsminor.yy153;
break;
case 99: /* expr ::= expr MINUS expr */
#line 758 "pikchr.y"
{yylhsminor.yy153=yymsp[-2].minor.yy153-yymsp[0].minor.yy153;}
#line 2984 "pikchr.c"
yymsp[-2].minor.yy153 = yylhsminor.yy153;
break;
case 100: /* expr ::= expr STAR expr */
#line 759 "pikchr.y"
{yylhsminor.yy153=yymsp[-2].minor.yy153*yymsp[0].minor.yy153;}
#line 2990 "pikchr.c"
yymsp[-2].minor.yy153 = yylhsminor.yy153;
break;
case 101: /* expr ::= expr SLASH expr */
#line 760 "pikchr.y"
{
if( yymsp[0].minor.yy153==0.0 ){ pik_error(p, &yymsp[-1].minor.yy0, "division by zero"); yylhsminor.yy153 = 0.0; }
else{ yylhsminor.yy153 = yymsp[-2].minor.yy153/yymsp[0].minor.yy153; }
}
#line 2999 "pikchr.c"
yymsp[-2].minor.yy153 = yylhsminor.yy153;
break;
case 102: /* expr ::= MINUS expr */
#line 764 "pikchr.y"
{yymsp[-1].minor.yy153=-yymsp[0].minor.yy153;}
#line 3005 "pikchr.c"
break;
case 103: /* expr ::= PLUS expr */
#line 765 "pikchr.y"
{yymsp[-1].minor.yy153=yymsp[0].minor.yy153;}
#line 3010 "pikchr.c"
break;
case 104: /* expr ::= LP expr RP */
#line 766 "pikchr.y"
{yymsp[-2].minor.yy153=yymsp[-1].minor.yy153;}
#line 3015 "pikchr.c"
break;
case 105: /* expr ::= LP FILL|COLOR|THICKNESS RP */
#line 767 "pikchr.y"
{yymsp[-2].minor.yy153=pik_get_var(p,&yymsp[-1].minor.yy0);}
#line 3020 "pikchr.c"
break;
case 106: /* expr ::= NUMBER */
#line 768 "pikchr.y"
{yylhsminor.yy153=pik_atof(&yymsp[0].minor.yy0);}
#line 3025 "pikchr.c"
yymsp[0].minor.yy153 = yylhsminor.yy153;
break;
case 107: /* expr ::= ID */
#line 769 "pikchr.y"
{yylhsminor.yy153=pik_get_var(p,&yymsp[0].minor.yy0);}
#line 3031 "pikchr.c"
yymsp[0].minor.yy153 = yylhsminor.yy153;
break;
case 108: /* expr ::= FUNC1 LP expr RP */
#line 770 "pikchr.y"
{yylhsminor.yy153 = pik_func(p,&yymsp[-3].minor.yy0,yymsp[-1].minor.yy153,0.0);}
#line 3037 "pikchr.c"
yymsp[-3].minor.yy153 = yylhsminor.yy153;
break;
case 109: /* expr ::= FUNC2 LP expr COMMA expr RP */
#line 771 "pikchr.y"
{yylhsminor.yy153 = pik_func(p,&yymsp[-5].minor.yy0,yymsp[-3].minor.yy153,yymsp[-1].minor.yy153);}
#line 3043 "pikchr.c"
yymsp[-5].minor.yy153 = yylhsminor.yy153;
break;
case 110: /* expr ::= DIST LP position COMMA position RP */
#line 772 "pikchr.y"
{yymsp[-5].minor.yy153 = pik_dist(&yymsp[-3].minor.yy79,&yymsp[-1].minor.yy79);}
#line 3049 "pikchr.c"
break;
case 111: /* expr ::= place2 DOT_XY X */
#line 773 "pikchr.y"
{yylhsminor.yy153 = yymsp[-2].minor.yy79.x;}
#line 3054 "pikchr.c"
yymsp[-2].minor.yy153 = yylhsminor.yy153;
break;
case 112: /* expr ::= place2 DOT_XY Y */
#line 774 "pikchr.y"
{yylhsminor.yy153 = yymsp[-2].minor.yy79.y;}
#line 3060 "pikchr.c"
yymsp[-2].minor.yy153 = yylhsminor.yy153;
break;
case 113: /* expr ::= object DOT_L numproperty */
case 114: /* expr ::= object DOT_L dashproperty */ yytestcase(yyruleno==114);
case 115: /* expr ::= object DOT_L colorproperty */ yytestcase(yyruleno==115);
#line 775 "pikchr.y"
{yylhsminor.yy153=pik_property_of(yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);}
#line 3068 "pikchr.c"
yymsp[-2].minor.yy153 = yylhsminor.yy153;
break;
default:
/* (116) lvalue ::= ID */ yytestcase(yyruleno==116);
/* (117) lvalue ::= FILL */ yytestcase(yyruleno==117);
/* (118) lvalue ::= COLOR */ yytestcase(yyruleno==118);
/* (119) lvalue ::= THICKNESS */ yytestcase(yyruleno==119);
|
| ︙ | ︙ | |||
3129 3130 3131 3132 3133 3134 3135 |
int yymajor, /* The major type of the error token */
pik_parserTOKENTYPE yyminor /* The minor type of the error token */
){
pik_parserARG_FETCH
pik_parserCTX_FETCH
#define TOKEN yyminor
/************ Begin %syntax_error code ****************************************/
| | | | 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 |
int yymajor, /* The major type of the error token */
pik_parserTOKENTYPE yyminor /* The minor type of the error token */
){
pik_parserARG_FETCH
pik_parserCTX_FETCH
#define TOKEN yyminor
/************ Begin %syntax_error code ****************************************/
#line 535 "pikchr.y"
if( TOKEN.z && TOKEN.z[0] ){
pik_error(p, &TOKEN, "syntax error");
}else{
pik_error(p, 0, "syntax error");
}
UNUSED_PARAMETER(yymajor);
#line 3179 "pikchr.c"
/************ End %syntax_error code ******************************************/
pik_parserARG_STORE /* Suppress warning about unused %extra_argument variable */
pik_parserCTX_STORE
}
/*
** The following is executed when the parser accepts
|
| ︙ | ︙ | |||
3370 3371 3372 3373 3374 3375 3376 | assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); return yyFallback[iToken]; #else (void)iToken; return 0; #endif } | | | 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 | assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); return yyFallback[iToken]; #else (void)iToken; return 0; #endif } #line 780 "pikchr.y" /* Chart of the 148 official CSS color names with their ** corresponding RGB values thru Color Module Level 4: ** https://developer.mozilla.org/en-US/docs/Web/CSS/color_value ** |
| ︙ | ︙ | |||
3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 |
pObj->h = pObj->w;
pObj->rad = 0.5*pObj->w;
}
static void circleNumProp(Pik *p, PObj *pObj, PToken *pId){
/* For a circle, the width must equal the height and both must
** be twice the radius. Enforce those constraints. */
switch( pId->eType ){
case T_RADIUS:
pObj->w = pObj->h = 2.0*pObj->rad;
break;
case T_WIDTH:
pObj->h = pObj->w;
pObj->rad = 0.5*pObj->w;
break;
| > | 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 |
pObj->h = pObj->w;
pObj->rad = 0.5*pObj->w;
}
static void circleNumProp(Pik *p, PObj *pObj, PToken *pId){
/* For a circle, the width must equal the height and both must
** be twice the radius. Enforce those constraints. */
switch( pId->eType ){
case T_DIAMETER:
case T_RADIUS:
pObj->w = pObj->h = 2.0*pObj->rad;
break;
case T_WIDTH:
pObj->h = pObj->w;
pObj->rad = 0.5*pObj->w;
break;
|
| ︙ | ︙ | |||
4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 |
p->zOut = z;
p->nOutAlloc = nNew;
}
memcpy(p->zOut+p->nOut, zText, n);
p->nOut += n;
p->zOut[p->nOut] = 0;
}
/*
** Append text to zOut with HTML characters escaped.
**
** * The space character is changed into non-breaking space (U+00a0)
** if mFlags has the 0x01 bit set. This is needed when outputting
** text to preserve leading and trailing whitespace. Turns out we
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 |
p->zOut = z;
p->nOutAlloc = nNew;
}
memcpy(p->zOut+p->nOut, zText, n);
p->nOut += n;
p->zOut[p->nOut] = 0;
}
/*
** Given a string and its length, returns true if the string begins
** with a construct which syntactically matches an HTML entity escape
** sequence (without checking for whether it's a known entity). Always
** returns false if zText[0] is false or n<4. Entities match the
** equivalent of the regexes `&#[0-9]{2,};` and
** `&[a-zA-Z][a-zA-Z0-9]+;`.
*/
static int pik_isentity(char const * zText, int n){
int i = 0;
if( n<4 || '&'!=zText[0] ) return 0;
n--;
zText++;
if( '#'==zText[0] ){
zText++;
n--;
for(i=0; i<n; i++){
if( i>1 && ';'==zText[i] ) return 1;
else if( zText[i]<'0' || zText[i]>'9' ) return 0;
/* Note that &#nn; values nn<32d are not legal entities. */
}
}else{
for(i=0; i<n; i++){
if( i>1 && ';'==zText[i] ) return 1;
else if( i>0 && zText[i]>='0' && zText[i]<='9' ){
continue;
}else if( zText[i]<'A' || zText[i]>'z'
|| (zText[i]>'Z' && zText[i]<'a') ) return 0;
}
}
return 0;
}
/*
** Append text to zOut with HTML characters escaped.
**
** * The space character is changed into non-breaking space (U+00a0)
** if mFlags has the 0x01 bit set. This is needed when outputting
** text to preserve leading and trailing whitespace. Turns out we
|
| ︙ | ︙ | |||
4551 4552 4553 4554 4555 4556 4557 |
if( c=='&' && bQAmp ) break;
}
if( i ) pik_append(p, zText, i);
if( i==n ) break;
switch( c ){
case '<': { pik_append(p, "<", 4); break; }
case '>': { pik_append(p, ">", 4); break; }
| < > > > | 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 |
if( c=='&' && bQAmp ) break;
}
if( i ) pik_append(p, zText, i);
if( i==n ) break;
switch( c ){
case '<': { pik_append(p, "<", 4); break; }
case '>': { pik_append(p, ">", 4); break; }
case ' ': { pik_append(p, "\302\240;", 2); break; }
case '&':
if( pik_isentity(zText+i, n-i) ){ pik_append(p, "&", 1); }
else { pik_append(p, "&", 5); }
}
i++;
n -= i;
zText += i;
i = 0;
}
}
|
| ︙ | ︙ | |||
7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 |
}else{
#if 0
printf("******** Token %s (%d): \"%.*s\" **************\n",
yyTokenName[token.eType], token.eType,
(int)(isspace(token.z[0]) ? 0 : sz), token.z);
#endif
token.n = (unsigned short)(sz & 0xffff);
pik_parser(pParser, token.eType, token);
}
}
}
/*
** Parse the PIKCHR script contained in zText[]. Return a rendering. Or
| > > > > | 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 |
}else{
#if 0
printf("******** Token %s (%d): \"%.*s\" **************\n",
yyTokenName[token.eType], token.eType,
(int)(isspace(token.z[0]) ? 0 : sz), token.z);
#endif
token.n = (unsigned short)(sz & 0xffff);
if( p->nToken++ > PIKCHR_TOKEN_LIMIT ){
pik_error(p, &token, "script is too complex");
break;
}
pik_parser(pParser, token.eType, token);
}
}
}
/*
** Parse the PIKCHR script contained in zText[]. Return a rendering. Or
|
| ︙ | ︙ | |||
8079 8080 8081 8082 8083 8084 8085 | return TCL_OK; } #endif /* PIKCHR_TCL */ | | | 8129 8130 8131 8132 8133 8134 8135 8136 | return TCL_OK; } #endif /* PIKCHR_TCL */ #line 8161 "pikchr.c" |
Added extsrc/pikchr.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 |
var initPikchrModule = (() => {
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
return (
function(initPikchrModule) {
initPikchrModule = initPikchrModule || {};
var Module = typeof initPikchrModule != "undefined" ? initPikchrModule : {};
var readyPromiseResolve, readyPromiseReject;
Module["ready"] = new Promise(function(resolve, reject) {
readyPromiseResolve = resolve;
readyPromiseReject = reject;
});
var moduleOverrides = Object.assign({}, Module);
var arguments_ = [];
var thisProgram = "./this.program";
var quit_ = (status, toThrow) => {
throw toThrow;
};
var ENVIRONMENT_IS_WEB = true;
var ENVIRONMENT_IS_WORKER = false;
var scriptDirectory = "";
function locateFile(path) {
if (Module["locateFile"]) {
return Module["locateFile"](path, scriptDirectory);
}
return scriptDirectory + path;
}
var read_, readAsync, readBinary, setWindowTitle;
if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
if (ENVIRONMENT_IS_WORKER) {
scriptDirectory = self.location.href;
} else if (typeof document != "undefined" && document.currentScript) {
scriptDirectory = document.currentScript.src;
}
if (_scriptDir) {
scriptDirectory = _scriptDir;
}
if (scriptDirectory.indexOf("blob:") !== 0) {
scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1);
} else {
scriptDirectory = "";
}
{
read_ = url => {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.send(null);
return xhr.responseText;
};
if (ENVIRONMENT_IS_WORKER) {
readBinary = url => {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.responseType = "arraybuffer";
xhr.send(null);
return new Uint8Array(xhr.response);
};
}
readAsync = (url, onload, onerror) => {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer";
xhr.onload = () => {
if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
onload(xhr.response);
return;
}
onerror();
};
xhr.onerror = onerror;
xhr.send(null);
};
}
setWindowTitle = title => document.title = title;
} else {}
var out = Module["print"] || console.log.bind(console);
var err = Module["printErr"] || console.warn.bind(console);
Object.assign(Module, moduleOverrides);
moduleOverrides = null;
if (Module["arguments"]) arguments_ = Module["arguments"];
if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
if (Module["quit"]) quit_ = Module["quit"];
var wasmBinary;
if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
var noExitRuntime = Module["noExitRuntime"] || true;
if (typeof WebAssembly != "object") {
abort("no native wasm support detected");
}
var wasmMemory;
var ABORT = false;
var EXITSTATUS;
function getCFunc(ident) {
var func = Module["_" + ident];
return func;
}
function ccall(ident, returnType, argTypes, args, opts) {
var toC = {
"string": function(str) {
var ret = 0;
if (str !== null && str !== undefined && str !== 0) {
var len = (str.length << 2) + 1;
ret = stackAlloc(len);
stringToUTF8(str, ret, len);
}
return ret;
},
"array": function(arr) {
var ret = stackAlloc(arr.length);
writeArrayToMemory(arr, ret);
return ret;
}
};
function convertReturnValue(ret) {
if (returnType === "string") {
return UTF8ToString(ret);
}
if (returnType === "boolean") return Boolean(ret);
return ret;
}
var func = getCFunc(ident);
var cArgs = [];
var stack = 0;
if (args) {
for (var i = 0; i < args.length; i++) {
var converter = toC[argTypes[i]];
if (converter) {
if (stack === 0) stack = stackSave();
cArgs[i] = converter(args[i]);
} else {
cArgs[i] = args[i];
}
}
}
var ret = func.apply(null, cArgs);
function onDone(ret) {
if (stack !== 0) stackRestore(stack);
return convertReturnValue(ret);
}
ret = onDone(ret);
return ret;
}
function cwrap(ident, returnType, argTypes, opts) {
argTypes = argTypes || [];
var numericArgs = argTypes.every(function(type) {
return type === "number";
});
var numericRet = returnType !== "string";
if (numericRet && numericArgs && !opts) {
return getCFunc(ident);
}
return function() {
return ccall(ident, returnType, argTypes, arguments, opts);
};
}
var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined;
function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) {
var endIdx = idx + maxBytesToRead;
var endPtr = idx;
while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
} else {
var str = "";
while (idx < endPtr) {
var u0 = heapOrArray[idx++];
if (!(u0 & 128)) {
str += String.fromCharCode(u0);
continue;
}
var u1 = heapOrArray[idx++] & 63;
if ((u0 & 224) == 192) {
str += String.fromCharCode((u0 & 31) << 6 | u1);
continue;
}
var u2 = heapOrArray[idx++] & 63;
if ((u0 & 240) == 224) {
u0 = (u0 & 15) << 12 | u1 << 6 | u2;
} else {
u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63;
}
if (u0 < 65536) {
str += String.fromCharCode(u0);
} else {
var ch = u0 - 65536;
str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
}
}
}
return str;
}
function UTF8ToString(ptr, maxBytesToRead) {
return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
}
function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
if (!(maxBytesToWrite > 0)) return 0;
var startIdx = outIdx;
var endIdx = outIdx + maxBytesToWrite - 1;
for (var i = 0; i < str.length; ++i) {
var u = str.charCodeAt(i);
if (u >= 55296 && u <= 57343) {
var u1 = str.charCodeAt(++i);
u = 65536 + ((u & 1023) << 10) | u1 & 1023;
}
if (u <= 127) {
if (outIdx >= endIdx) break;
heap[outIdx++] = u;
} else if (u <= 2047) {
if (outIdx + 1 >= endIdx) break;
heap[outIdx++] = 192 | u >> 6;
heap[outIdx++] = 128 | u & 63;
} else if (u <= 65535) {
if (outIdx + 2 >= endIdx) break;
heap[outIdx++] = 224 | u >> 12;
heap[outIdx++] = 128 | u >> 6 & 63;
heap[outIdx++] = 128 | u & 63;
} else {
if (outIdx + 3 >= endIdx) break;
heap[outIdx++] = 240 | u >> 18;
heap[outIdx++] = 128 | u >> 12 & 63;
heap[outIdx++] = 128 | u >> 6 & 63;
heap[outIdx++] = 128 | u & 63;
}
}
heap[outIdx] = 0;
return outIdx - startIdx;
}
function stringToUTF8(str, outPtr, maxBytesToWrite) {
return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
}
function writeArrayToMemory(array, buffer) {
HEAP8.set(array, buffer);
}
var buffer, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
function updateGlobalBufferAndViews(buf) {
buffer = buf;
Module["HEAP8"] = HEAP8 = new Int8Array(buf);
Module["HEAP16"] = HEAP16 = new Int16Array(buf);
Module["HEAP32"] = HEAP32 = new Int32Array(buf);
Module["HEAPU8"] = HEAPU8 = new Uint8Array(buf);
Module["HEAPU16"] = HEAPU16 = new Uint16Array(buf);
Module["HEAPU32"] = HEAPU32 = new Uint32Array(buf);
Module["HEAPF32"] = HEAPF32 = new Float32Array(buf);
Module["HEAPF64"] = HEAPF64 = new Float64Array(buf);
}
var INITIAL_MEMORY = Module["INITIAL_MEMORY"] || 16777216;
var wasmTable;
var __ATPRERUN__ = [];
var __ATINIT__ = [];
var __ATPOSTRUN__ = [];
var runtimeInitialized = false;
function keepRuntimeAlive() {
return noExitRuntime;
}
function preRun() {
if (Module["preRun"]) {
if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
while (Module["preRun"].length) {
addOnPreRun(Module["preRun"].shift());
}
}
callRuntimeCallbacks(__ATPRERUN__);
}
function initRuntime() {
runtimeInitialized = true;
callRuntimeCallbacks(__ATINIT__);
}
function postRun() {
if (Module["postRun"]) {
if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
while (Module["postRun"].length) {
addOnPostRun(Module["postRun"].shift());
}
}
callRuntimeCallbacks(__ATPOSTRUN__);
}
function addOnPreRun(cb) {
__ATPRERUN__.unshift(cb);
}
function addOnInit(cb) {
__ATINIT__.unshift(cb);
}
function addOnPostRun(cb) {
__ATPOSTRUN__.unshift(cb);
}
var runDependencies = 0;
var runDependencyWatcher = null;
var dependenciesFulfilled = null;
function addRunDependency(id) {
runDependencies++;
if (Module["monitorRunDependencies"]) {
Module["monitorRunDependencies"](runDependencies);
}
}
function removeRunDependency(id) {
runDependencies--;
if (Module["monitorRunDependencies"]) {
Module["monitorRunDependencies"](runDependencies);
}
if (runDependencies == 0) {
if (runDependencyWatcher !== null) {
clearInterval(runDependencyWatcher);
runDependencyWatcher = null;
}
if (dependenciesFulfilled) {
var callback = dependenciesFulfilled;
dependenciesFulfilled = null;
callback();
}
}
}
function abort(what) {
{
if (Module["onAbort"]) {
Module["onAbort"](what);
}
}
what = "Aborted(" + what + ")";
err(what);
ABORT = true;
EXITSTATUS = 1;
what += ". Build with -sASSERTIONS for more info.";
var e = new WebAssembly.RuntimeError(what);
readyPromiseReject(e);
throw e;
}
var dataURIPrefix = "data:application/octet-stream;base64,";
function isDataURI(filename) {
return filename.startsWith(dataURIPrefix);
}
var wasmBinaryFile;
wasmBinaryFile = "pikchr.wasm";
if (!isDataURI(wasmBinaryFile)) {
wasmBinaryFile = locateFile(wasmBinaryFile);
}
function getBinary(file) {
try {
if (file == wasmBinaryFile && wasmBinary) {
return new Uint8Array(wasmBinary);
}
if (readBinary) {
return readBinary(file);
} else {
throw "both async and sync fetching of the wasm failed";
}
} catch (err) {
abort(err);
}
}
function getBinaryPromise() {
if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
if (typeof fetch == "function") {
return fetch(wasmBinaryFile, {
credentials: "same-origin"
}).then(function(response) {
if (!response["ok"]) {
throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
}
return response["arrayBuffer"]();
}).catch(function() {
return getBinary(wasmBinaryFile);
});
}
}
return Promise.resolve().then(function() {
return getBinary(wasmBinaryFile);
});
}
function createWasm() {
var info = {
"a": asmLibraryArg
};
function receiveInstance(instance, module) {
var exports = instance.exports;
Module["asm"] = exports;
wasmMemory = Module["asm"]["d"];
updateGlobalBufferAndViews(wasmMemory.buffer);
wasmTable = Module["asm"]["g"];
addOnInit(Module["asm"]["e"]);
removeRunDependency("wasm-instantiate");
}
addRunDependency("wasm-instantiate");
function receiveInstantiationResult(result) {
receiveInstance(result["instance"]);
}
function instantiateArrayBuffer(receiver) {
return getBinaryPromise().then(function(binary) {
return WebAssembly.instantiate(binary, info);
}).then(function(instance) {
return instance;
}).then(receiver, function(reason) {
err("failed to asynchronously prepare wasm: " + reason);
abort(reason);
});
}
function instantiateAsync() {
if (!wasmBinary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(wasmBinaryFile) && typeof fetch == "function") {
return fetch(wasmBinaryFile, {
credentials: "same-origin"
}).then(function(response) {
var result = WebAssembly.instantiateStreaming(response, info);
return result.then(receiveInstantiationResult, function(reason) {
err("wasm streaming compile failed: " + reason);
err("falling back to ArrayBuffer instantiation");
return instantiateArrayBuffer(receiveInstantiationResult);
});
});
} else {
return instantiateArrayBuffer(receiveInstantiationResult);
}
}
if (Module["instantiateWasm"]) {
try {
var exports = Module["instantiateWasm"](info, receiveInstance);
return exports;
} catch (e) {
err("Module.instantiateWasm callback failed with error: " + e);
return false;
}
}
instantiateAsync().catch(readyPromiseReject);
return {};
}
var tempDouble;
var tempI64;
function callRuntimeCallbacks(callbacks) {
while (callbacks.length > 0) {
var callback = callbacks.shift();
if (typeof callback == "function") {
callback(Module);
continue;
}
var func = callback.func;
if (typeof func == "number") {
if (callback.arg === undefined) {
getWasmTableEntry(func)();
} else {
getWasmTableEntry(func)(callback.arg);
}
} else {
func(callback.arg === undefined ? null : callback.arg);
}
}
}
function getValue(ptr, type = "i8") {
if (type.endsWith("*")) type = "i32";
switch (type) {
case "i1":
return HEAP8[ptr >> 0];
case "i8":
return HEAP8[ptr >> 0];
case "i16":
return HEAP16[ptr >> 1];
case "i32":
return HEAP32[ptr >> 2];
case "i64":
return HEAP32[ptr >> 2];
case "float":
return HEAPF32[ptr >> 2];
case "double":
return Number(HEAPF64[ptr >> 3]);
default:
abort("invalid type for getValue: " + type);
}
return null;
}
function getWasmTableEntry(funcPtr) {
return wasmTable.get(funcPtr);
}
function setValue(ptr, value, type = "i8") {
if (type.endsWith("*")) type = "i32";
switch (type) {
case "i1":
HEAP8[ptr >> 0] = value;
break;
case "i8":
HEAP8[ptr >> 0] = value;
break;
case "i16":
HEAP16[ptr >> 1] = value;
break;
case "i32":
HEAP32[ptr >> 2] = value;
break;
case "i64":
tempI64 = [ value >>> 0, (tempDouble = value, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1];
break;
case "float":
HEAPF32[ptr >> 2] = value;
break;
case "double":
HEAPF64[ptr >> 3] = value;
break;
default:
abort("invalid type for setValue: " + type);
}
}
function ___assert_fail(condition, filename, line, func) {
abort("Assertion failed: " + UTF8ToString(condition) + ", at: " + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);
}
function abortOnCannotGrowMemory(requestedSize) {
abort("OOM");
}
function _emscripten_resize_heap(requestedSize) {
var oldSize = HEAPU8.length;
requestedSize = requestedSize >>> 0;
abortOnCannotGrowMemory(requestedSize);
}
function _exit(status) {
exit(status);
}
var asmLibraryArg = {
"a": ___assert_fail,
"b": _emscripten_resize_heap,
"c": _exit
};
var asm = createWasm();
var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function() {
return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["e"]).apply(null, arguments);
};
var _pikchr = Module["_pikchr"] = function() {
return (_pikchr = Module["_pikchr"] = Module["asm"]["f"]).apply(null, arguments);
};
var stackSave = Module["stackSave"] = function() {
return (stackSave = Module["stackSave"] = Module["asm"]["h"]).apply(null, arguments);
};
var stackRestore = Module["stackRestore"] = function() {
return (stackRestore = Module["stackRestore"] = Module["asm"]["i"]).apply(null, arguments);
};
var stackAlloc = Module["stackAlloc"] = function() {
return (stackAlloc = Module["stackAlloc"] = Module["asm"]["j"]).apply(null, arguments);
};
Module["cwrap"] = cwrap;
Module["stackSave"] = stackSave;
Module["stackRestore"] = stackRestore;
Module["setValue"] = setValue;
Module["getValue"] = getValue;
var calledRun;
function ExitStatus(status) {
this.name = "ExitStatus";
this.message = "Program terminated with exit(" + status + ")";
this.status = status;
}
dependenciesFulfilled = function runCaller() {
if (!calledRun) run();
if (!calledRun) dependenciesFulfilled = runCaller;
};
function run(args) {
args = args || arguments_;
if (runDependencies > 0) {
return;
}
preRun();
if (runDependencies > 0) {
return;
}
function doRun() {
if (calledRun) return;
calledRun = true;
Module["calledRun"] = true;
if (ABORT) return;
initRuntime();
readyPromiseResolve(Module);
if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"]();
postRun();
}
if (Module["setStatus"]) {
Module["setStatus"]("Running...");
setTimeout(function() {
setTimeout(function() {
Module["setStatus"]("");
}, 1);
doRun();
}, 1);
} else {
doRun();
}
}
Module["run"] = run;
function exit(status, implicit) {
EXITSTATUS = status;
procExit(status);
}
function procExit(code) {
EXITSTATUS = code;
if (!keepRuntimeAlive()) {
if (Module["onExit"]) Module["onExit"](code);
ABORT = true;
}
quit_(code, new ExitStatus(code));
}
if (Module["preInit"]) {
if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
while (Module["preInit"].length > 0) {
Module["preInit"].pop()();
}
}
run();
return initPikchrModule.ready
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
module.exports = initPikchrModule;
else if (typeof define === 'function' && define['amd'])
define([], function() { return initPikchrModule; });
else if (typeof exports === 'object')
exports["initPikchrModule"] = initPikchrModule;
|
Added extsrc/pikchr.wasm.
cannot compute difference between binary files
Changes to extsrc/shell.c.
| ︙ | ︙ | |||
243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
_setmode(_fileno(file), _O_TEXT);
}
#else
# define setBinaryMode(X,Y)
# define setTextMode(X,Y)
#endif
/* True if the timer is enabled */
static int enableTimer = 0;
/* Return the current wall-clock time */
static sqlite3_int64 timeOfDay(void){
static sqlite3_vfs *clockVfs = 0;
| > > > > > > > > > > | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
_setmode(_fileno(file), _O_TEXT);
}
#else
# define setBinaryMode(X,Y)
# define setTextMode(X,Y)
#endif
/*
** When compiling with emcc (a.k.a. emscripten), we're building a
** WebAssembly (WASM) bundle and need to disable and rewire a few
** things.
*/
#ifdef __EMSCRIPTEN__
#define SQLITE_SHELL_WASM_MODE
#else
#undef SQLITE_SHELL_WASM_MODE
#endif
/* True if the timer is enabled */
static int enableTimer = 0;
/* Return the current wall-clock time */
static sqlite3_int64 timeOfDay(void){
static sqlite3_vfs *clockVfs = 0;
|
| ︙ | ︙ | |||
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 |
** If zPrior is not NULL then it is a buffer from a prior call to this
** routine that can be reused.
**
** The result is stored in space obtained from malloc() and must either
** be freed by the caller or else passed back into this routine via the
** zPrior argument for reuse.
*/
static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
char *zPrompt;
char *zResult;
if( in!=0 ){
zResult = local_getline(zPrior, in);
}else{
zPrompt = isContinuation ? continuePrompt : mainPrompt;
#if SHELL_USE_LOCAL_GETLINE
printf("%s", zPrompt);
fflush(stdout);
zResult = local_getline(zPrior, stdin);
#else
free(zPrior);
zResult = shell_readline(zPrompt);
if( zResult && *zResult ) shell_add_history(zResult);
#endif
}
return zResult;
}
| > | | 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 |
** If zPrior is not NULL then it is a buffer from a prior call to this
** routine that can be reused.
**
** The result is stored in space obtained from malloc() and must either
** be freed by the caller or else passed back into this routine via the
** zPrior argument for reuse.
*/
#ifndef SQLITE_SHELL_WASM_MODE
static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
char *zPrompt;
char *zResult;
if( in!=0 ){
zResult = local_getline(zPrior, in);
}else{
zPrompt = isContinuation ? continuePrompt : mainPrompt;
#if SHELL_USE_LOCAL_GETLINE
printf("%s", zPrompt);
fflush(stdout);
zResult = local_getline(zPrior, stdin);
#else
free(zPrior);
zResult = shell_readline(zPrompt);
if( zResult && *zResult ) shell_add_history(zResult);
#endif
}
return zResult;
}
#endif /* !SQLITE_SHELL_WASM_MODE */
/*
** Return the value of a hexadecimal digit. Return -1 if the input
** is not a hex digit.
*/
static int hexDigitValue(char c){
if( c>='0' && c<='9' ) return c - '0';
|
| ︙ | ︙ | |||
812 813 814 815 816 817 818 | ** from malloc(), or a NULL pointer. The string pointed to by zAppend is ** added to zIn, and the result returned in memory obtained from malloc(). ** zIn, if it was not NULL, is freed. ** ** If the third argument, quote, is not '\0', then it is used as a ** quote character for zAppend. */ | | | 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 |
** from malloc(), or a NULL pointer. The string pointed to by zAppend is
** added to zIn, and the result returned in memory obtained from malloc().
** zIn, if it was not NULL, is freed.
**
** If the third argument, quote, is not '\0', then it is used as a
** quote character for zAppend.
*/
static void appendText(ShellText *p, const char *zAppend, char quote){
int len;
int i;
int nAppend = strlen30(zAppend);
len = nAppend+p->n+1;
if( quote ){
len += 2;
|
| ︙ | ︙ | |||
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 | } #endif /* defined(WIN32) && defined(_MSC_VER) */ /************************* End test_windirent.c ********************/ #define dirent DIRENT #endif /************************* Begin ../ext/misc/shathree.c ******************/ /* ** 2017-03-08 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 |
}
#endif /* defined(WIN32) && defined(_MSC_VER) */
/************************* End test_windirent.c ********************/
#define dirent DIRENT
#endif
/************************* Begin ../ext/misc/memtrace.c ******************/
/*
** 2019-01-21
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
** mechanism to add a tracing layer on top of SQLite. If this extension
** is registered prior to sqlite3_initialize(), it will cause all memory
** allocation activities to be logged on standard output, or to some other
** FILE specified by the initializer.
**
** This file needs to be compiled into the application that uses it.
**
** This extension is used to implement the --memtrace option of the
** command-line shell.
*/
#include <assert.h>
#include <string.h>
#include <stdio.h>
/* The original memory allocation routines */
static sqlite3_mem_methods memtraceBase;
static FILE *memtraceOut;
/* Methods that trace memory allocations */
static void *memtraceMalloc(int n){
if( memtraceOut ){
fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n",
memtraceBase.xRoundup(n));
}
return memtraceBase.xMalloc(n);
}
static void memtraceFree(void *p){
if( p==0 ) return;
if( memtraceOut ){
fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
}
memtraceBase.xFree(p);
}
static void *memtraceRealloc(void *p, int n){
if( p==0 ) return memtraceMalloc(n);
if( n==0 ){
memtraceFree(p);
return 0;
}
if( memtraceOut ){
fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
memtraceBase.xSize(p), memtraceBase.xRoundup(n));
}
return memtraceBase.xRealloc(p, n);
}
static int memtraceSize(void *p){
return memtraceBase.xSize(p);
}
static int memtraceRoundup(int n){
return memtraceBase.xRoundup(n);
}
static int memtraceInit(void *p){
return memtraceBase.xInit(p);
}
static void memtraceShutdown(void *p){
memtraceBase.xShutdown(p);
}
/* The substitute memory allocator */
static sqlite3_mem_methods ersaztMethods = {
memtraceMalloc,
memtraceFree,
memtraceRealloc,
memtraceSize,
memtraceRoundup,
memtraceInit,
memtraceShutdown,
0
};
/* Begin tracing memory allocations to out. */
int sqlite3MemTraceActivate(FILE *out){
int rc = SQLITE_OK;
if( memtraceBase.xMalloc==0 ){
rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
if( rc==SQLITE_OK ){
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
}
}
memtraceOut = out;
return rc;
}
/* Deactivate memory tracing */
int sqlite3MemTraceDeactivate(void){
int rc = SQLITE_OK;
if( memtraceBase.xMalloc!=0 ){
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
if( rc==SQLITE_OK ){
memset(&memtraceBase, 0, sizeof(memtraceBase));
}
}
memtraceOut = 0;
return rc;
}
/************************* End ../ext/misc/memtrace.c ********************/
/************************* Begin ../ext/misc/shathree.c ******************/
/*
** 2017-03-08
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
|
| ︙ | ︙ | |||
2104 2105 2106 2107 2108 2109 2110 |
SQLITE_UTF8 | SQLITE_DIRECTONLY,
0, sha3QueryFunc, 0, 0);
}
return rc;
}
/************************* End ../ext/misc/shathree.c ********************/
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 |
SQLITE_UTF8 | SQLITE_DIRECTONLY,
0, sha3QueryFunc, 0, 0);
}
return rc;
}
/************************* End ../ext/misc/shathree.c ********************/
/************************* Begin ../ext/misc/uint.c ******************/
/*
** 2020-04-14
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
|
| ︙ | ︙ | |||
6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 |
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
(void*)db, re_sql_func, 0, 0);
}
return rc;
}
/************************* End ../ext/misc/regexp.c ********************/
#ifdef SQLITE_HAVE_ZLIB
/************************* Begin ../ext/misc/zipfile.c ******************/
/*
** 2017-12-26
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 |
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
(void*)db, re_sql_func, 0, 0);
}
return rc;
}
/************************* End ../ext/misc/regexp.c ********************/
#ifndef SQLITE_SHELL_WASM_MODE
/************************* Begin ../ext/misc/fileio.c ******************/
/*
** 2014-06-13
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This SQLite extension implements SQL functions readfile() and
** writefile(), and eponymous virtual type "fsdir".
**
** WRITEFILE(FILE, DATA [, MODE [, MTIME]]):
**
** If neither of the optional arguments is present, then this UDF
** function writes blob DATA to file FILE. If successful, the number
** of bytes written is returned. If an error occurs, NULL is returned.
**
** If the first option argument - MODE - is present, then it must
** be passed an integer value that corresponds to a POSIX mode
** value (file type + permissions, as returned in the stat.st_mode
** field by the stat() system call). Three types of files may
** be written/created:
**
** regular files: (mode & 0170000)==0100000
** symbolic links: (mode & 0170000)==0120000
** directories: (mode & 0170000)==0040000
**
** For a directory, the DATA is ignored. For a symbolic link, it is
** interpreted as text and used as the target of the link. For a
** regular file, it is interpreted as a blob and written into the
** named file. Regardless of the type of file, its permissions are
** set to (mode & 0777) before returning.
**
** If the optional MTIME argument is present, then it is interpreted
** as an integer - the number of seconds since the unix epoch. The
** modification-time of the target file is set to this value before
** returning.
**
** If three or more arguments are passed to this function and an
** error is encountered, an exception is raised.
**
** READFILE(FILE):
**
** Read and return the contents of file FILE (type blob) from disk.
**
** FSDIR:
**
** Used as follows:
**
** SELECT * FROM fsdir($path [, $dir]);
**
** Parameter $path is an absolute or relative pathname. If the file that it
** refers to does not exist, it is an error. If the path refers to a regular
** file or symbolic link, it returns a single row. Or, if the path refers
** to a directory, it returns one row for the directory, and one row for each
** file within the hierarchy rooted at $path.
**
** Each row has the following columns:
**
** name: Path to file or directory (text value).
** mode: Value of stat.st_mode for directory entry (an integer).
** mtime: Value of stat.st_mtime for directory entry (an integer).
** data: For a regular file, a blob containing the file data. For a
** symlink, a text value containing the text of the link. For a
** directory, NULL.
**
** If a non-NULL value is specified for the optional $dir parameter and
** $path is a relative path, then $path is interpreted relative to $dir.
** And the paths returned in the "name" column of the table are also
** relative to directory $dir.
**
** Notes on building this extension for Windows:
** Unless linked statically with the SQLite library, a preprocessor
** symbol, FILEIO_WIN32_DLL, must be #define'd to create a stand-alone
** DLL form of this extension for WIN32. See its use below for details.
*/
/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if !defined(_WIN32) && !defined(WIN32)
# include <unistd.h>
# include <dirent.h>
# include <utime.h>
# include <sys/time.h>
#else
# include "windows.h"
# include <io.h>
# include <direct.h>
/* # include "test_windirent.h" */
# define dirent DIRENT
# ifndef chmod
# define chmod _chmod
# endif
# ifndef stat
# define stat _stat
# endif
# define mkdir(path,mode) _mkdir(path)
# define lstat(path,buf) stat(path,buf)
#endif
#include <time.h>
#include <errno.h>
/*
** Structure of the fsdir() table-valued function
*/
/* 0 1 2 3 4 5 */
#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
#define FSDIR_COLUMN_NAME 0 /* Name of the file */
#define FSDIR_COLUMN_MODE 1 /* Access mode */
#define FSDIR_COLUMN_MTIME 2 /* Last modification time */
#define FSDIR_COLUMN_DATA 3 /* File content */
#define FSDIR_COLUMN_PATH 4 /* Path to top of search */
#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
/*
** Set the result stored by context ctx to a blob containing the
** contents of file zName. Or, leave the result unchanged (NULL)
** if the file does not exist or is unreadable.
**
** If the file exceeds the SQLite blob size limit, through an
** SQLITE_TOOBIG error.
**
** Throw an SQLITE_IOERR if there are difficulties pulling the file
** off of disk.
*/
static void readFileContents(sqlite3_context *ctx, const char *zName){
FILE *in;
sqlite3_int64 nIn;
void *pBuf;
sqlite3 *db;
int mxBlob;
in = fopen(zName, "rb");
if( in==0 ){
/* File does not exist or is unreadable. Leave the result set to NULL. */
return;
}
fseek(in, 0, SEEK_END);
nIn = ftell(in);
rewind(in);
db = sqlite3_context_db_handle(ctx);
mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
if( nIn>mxBlob ){
sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
fclose(in);
return;
}
pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
if( pBuf==0 ){
sqlite3_result_error_nomem(ctx);
fclose(in);
return;
}
if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
}else{
sqlite3_result_error_code(ctx, SQLITE_IOERR);
sqlite3_free(pBuf);
}
fclose(in);
}
/*
** Implementation of the "readfile(X)" SQL function. The entire content
** of the file named X is read and returned as a BLOB. NULL is returned
** if the file does not exist or is unreadable.
*/
static void readfileFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zName;
(void)(argc); /* Unused parameter */
zName = (const char*)sqlite3_value_text(argv[0]);
if( zName==0 ) return;
readFileContents(context, zName);
}
/*
** Set the error message contained in context ctx to the results of
** vprintf(zFmt, ...).
*/
static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
char *zMsg = 0;
va_list ap;
va_start(ap, zFmt);
zMsg = sqlite3_vmprintf(zFmt, ap);
sqlite3_result_error(ctx, zMsg, -1);
sqlite3_free(zMsg);
va_end(ap);
}
#if defined(_WIN32)
/*
** This function is designed to convert a Win32 FILETIME structure into the
** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC).
*/
static sqlite3_uint64 fileTimeToUnixTime(
LPFILETIME pFileTime
){
SYSTEMTIME epochSystemTime;
ULARGE_INTEGER epochIntervals;
FILETIME epochFileTime;
ULARGE_INTEGER fileIntervals;
memset(&epochSystemTime, 0, sizeof(SYSTEMTIME));
epochSystemTime.wYear = 1970;
epochSystemTime.wMonth = 1;
epochSystemTime.wDay = 1;
SystemTimeToFileTime(&epochSystemTime, &epochFileTime);
epochIntervals.LowPart = epochFileTime.dwLowDateTime;
epochIntervals.HighPart = epochFileTime.dwHighDateTime;
fileIntervals.LowPart = pFileTime->dwLowDateTime;
fileIntervals.HighPart = pFileTime->dwHighDateTime;
return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
}
#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
# /* To allow a standalone DLL, use this next replacement function: */
# undef sqlite3_win32_utf8_to_unicode
# define sqlite3_win32_utf8_to_unicode utf8_to_utf16
#
LPWSTR utf8_to_utf16(const char *z){
int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0);
LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR));
if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) )
return rv;
sqlite3_free(rv);
return 0;
}
#endif
/*
** This function attempts to normalize the time values found in the stat()
** buffer to UTC. This is necessary on Win32, where the runtime library
** appears to return these values as local times.
*/
static void statTimesToUtc(
const char *zPath,
struct stat *pStatBuf
){
HANDLE hFindFile;
WIN32_FIND_DATAW fd;
LPWSTR zUnicodeName;
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
if( zUnicodeName ){
memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
hFindFile = FindFirstFileW(zUnicodeName, &fd);
if( hFindFile!=NULL ){
pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
FindClose(hFindFile);
}
sqlite3_free(zUnicodeName);
}
}
#endif
/*
** This function is used in place of stat(). On Windows, special handling
** is required in order for the included time to be returned as UTC. On all
** other systems, this function simply calls stat().
*/
static int fileStat(
const char *zPath,
struct stat *pStatBuf
){
#if defined(_WIN32)
int rc = stat(zPath, pStatBuf);
if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
return rc;
#else
return stat(zPath, pStatBuf);
#endif
}
/*
** This function is used in place of lstat(). On Windows, special handling
** is required in order for the included time to be returned as UTC. On all
** other systems, this function simply calls lstat().
*/
static int fileLinkStat(
const char *zPath,
struct stat *pStatBuf
){
#if defined(_WIN32)
int rc = lstat(zPath, pStatBuf);
if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
return rc;
#else
return lstat(zPath, pStatBuf);
#endif
}
/*
** Argument zFile is the name of a file that will be created and/or written
** by SQL function writefile(). This function ensures that the directory
** zFile will be written to exists, creating it if required. The permissions
** for any path components created by this function are set in accordance
** with the current umask.
**
** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
** SQLITE_OK is returned if the directory is successfully created, or
** SQLITE_ERROR otherwise.
*/
static int makeDirectory(
const char *zFile
){
char *zCopy = sqlite3_mprintf("%s", zFile);
int rc = SQLITE_OK;
if( zCopy==0 ){
rc = SQLITE_NOMEM;
}else{
int nCopy = (int)strlen(zCopy);
int i = 1;
while( rc==SQLITE_OK ){
struct stat sStat;
int rc2;
for(; zCopy[i]!='/' && i<nCopy; i++);
if( i==nCopy ) break;
zCopy[i] = '\0';
rc2 = fileStat(zCopy, &sStat);
if( rc2!=0 ){
if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
}else{
if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
}
zCopy[i] = '/';
i++;
}
sqlite3_free(zCopy);
}
return rc;
}
/*
** This function does the work for the writefile() UDF. Refer to
** header comments at the top of this file for details.
*/
static int writeFile(
sqlite3_context *pCtx, /* Context to return bytes written in */
const char *zFile, /* File to write */
sqlite3_value *pData, /* Data to write */
mode_t mode, /* MODE parameter passed to writefile() */
sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */
){
if( zFile==0 ) return 1;
#if !defined(_WIN32) && !defined(WIN32)
if( S_ISLNK(mode) ){
const char *zTo = (const char*)sqlite3_value_text(pData);
if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
}else
#endif
{
if( S_ISDIR(mode) ){
if( mkdir(zFile, mode) ){
/* The mkdir() call to create the directory failed. This might not
** be an error though - if there is already a directory at the same
** path and either the permissions already match or can be changed
** to do so using chmod(), it is not an error. */
struct stat sStat;
if( errno!=EEXIST
|| 0!=fileStat(zFile, &sStat)
|| !S_ISDIR(sStat.st_mode)
|| ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777))
){
return 1;
}
}
}else{
sqlite3_int64 nWrite = 0;
const char *z;
int rc = 0;
FILE *out = fopen(zFile, "wb");
if( out==0 ) return 1;
z = (const char*)sqlite3_value_blob(pData);
if( z ){
sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out);
nWrite = sqlite3_value_bytes(pData);
if( nWrite!=n ){
rc = 1;
}
}
fclose(out);
if( rc==0 && mode && chmod(zFile, mode & 0777) ){
rc = 1;
}
if( rc ) return 2;
sqlite3_result_int64(pCtx, nWrite);
}
}
if( mtime>=0 ){
#if defined(_WIN32)
#if !SQLITE_OS_WINRT
/* Windows */
FILETIME lastAccess;
FILETIME lastWrite;
SYSTEMTIME currentTime;
LONGLONG intervals;
HANDLE hFile;
LPWSTR zUnicodeName;
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
GetSystemTime(¤tTime);
SystemTimeToFileTime(¤tTime, &lastAccess);
intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
lastWrite.dwLowDateTime = (DWORD)intervals;
lastWrite.dwHighDateTime = intervals >> 32;
zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
if( zUnicodeName==0 ){
return 1;
}
hFile = CreateFileW(
zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL
);
sqlite3_free(zUnicodeName);
if( hFile!=INVALID_HANDLE_VALUE ){
BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
CloseHandle(hFile);
return !bResult;
}else{
return 1;
}
#endif
#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
/* Recent unix */
struct timespec times[2];
times[0].tv_nsec = times[1].tv_nsec = 0;
times[0].tv_sec = time(0);
times[1].tv_sec = mtime;
if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
return 1;
}
#else
/* Legacy unix */
struct timeval times[2];
times[0].tv_usec = times[1].tv_usec = 0;
times[0].tv_sec = time(0);
times[1].tv_sec = mtime;
if( utimes(zFile, times) ){
return 1;
}
#endif
}
return 0;
}
/*
** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.
** Refer to header comments at the top of this file for details.
*/
static void writefileFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zFile;
mode_t mode = 0;
int res;
sqlite3_int64 mtime = -1;
if( argc<2 || argc>4 ){
sqlite3_result_error(context,
"wrong number of arguments to function writefile()", -1
);
return;
}
zFile = (const char*)sqlite3_value_text(argv[0]);
if( zFile==0 ) return;
if( argc>=3 ){
mode = (mode_t)sqlite3_value_int(argv[2]);
}
if( argc==4 ){
mtime = sqlite3_value_int64(argv[3]);
}
res = writeFile(context, zFile, argv[1], mode, mtime);
if( res==1 && errno==ENOENT ){
if( makeDirectory(zFile)==SQLITE_OK ){
res = writeFile(context, zFile, argv[1], mode, mtime);
}
}
if( argc>2 && res!=0 ){
if( S_ISLNK(mode) ){
ctxErrorMsg(context, "failed to create symlink: %s", zFile);
}else if( S_ISDIR(mode) ){
ctxErrorMsg(context, "failed to create directory: %s", zFile);
}else{
ctxErrorMsg(context, "failed to write file: %s", zFile);
}
}
}
/*
** SQL function: lsmode(MODE)
**
** Given a numberic st_mode from stat(), convert it into a human-readable
** text string in the style of "ls -l".
*/
static void lsModeFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int i;
int iMode = sqlite3_value_int(argv[0]);
char z[16];
(void)argc;
if( S_ISLNK(iMode) ){
z[0] = 'l';
}else if( S_ISREG(iMode) ){
z[0] = '-';
}else if( S_ISDIR(iMode) ){
z[0] = 'd';
}else{
z[0] = '?';
}
for(i=0; i<3; i++){
int m = (iMode >> ((2-i)*3));
char *a = &z[1 + i*3];
a[0] = (m & 0x4) ? 'r' : '-';
a[1] = (m & 0x2) ? 'w' : '-';
a[2] = (m & 0x1) ? 'x' : '-';
}
z[10] = '\0';
sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Cursor type for recursively iterating through a directory structure.
*/
typedef struct fsdir_cursor fsdir_cursor;
typedef struct FsdirLevel FsdirLevel;
struct FsdirLevel {
DIR *pDir; /* From opendir() */
char *zDir; /* Name of directory (nul-terminated) */
};
struct fsdir_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
int nLvl; /* Number of entries in aLvl[] array */
int iLvl; /* Index of current entry */
FsdirLevel *aLvl; /* Hierarchy of directories being traversed */
const char *zBase;
int nBase;
struct stat sStat; /* Current lstat() results */
char *zPath; /* Path to current entry */
sqlite3_int64 iRowid; /* Current rowid */
};
typedef struct fsdir_tab fsdir_tab;
struct fsdir_tab {
sqlite3_vtab base; /* Base class - must be first */
};
/*
** Construct a new fsdir virtual table object.
*/
static int fsdirConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
fsdir_tab *pNew = 0;
int rc;
(void)pAux;
(void)argc;
(void)argv;
(void)pzErr;
rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
if( rc==SQLITE_OK ){
pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
}
*ppVtab = (sqlite3_vtab*)pNew;
return rc;
}
/*
** This method is the destructor for fsdir vtab objects.
*/
static int fsdirDisconnect(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return SQLITE_OK;
}
/*
** Constructor for a new fsdir_cursor object.
*/
static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
fsdir_cursor *pCur;
(void)p;
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
pCur->iLvl = -1;
*ppCursor = &pCur->base;
return SQLITE_OK;
}
/*
** Reset a cursor back to the state it was in when first returned
** by fsdirOpen().
*/
static void fsdirResetCursor(fsdir_cursor *pCur){
int i;
for(i=0; i<=pCur->iLvl; i++){
FsdirLevel *pLvl = &pCur->aLvl[i];
if( pLvl->pDir ) closedir(pLvl->pDir);
sqlite3_free(pLvl->zDir);
}
sqlite3_free(pCur->zPath);
sqlite3_free(pCur->aLvl);
pCur->aLvl = 0;
pCur->zPath = 0;
pCur->zBase = 0;
pCur->nBase = 0;
pCur->nLvl = 0;
pCur->iLvl = -1;
pCur->iRowid = 1;
}
/*
** Destructor for an fsdir_cursor.
*/
static int fsdirClose(sqlite3_vtab_cursor *cur){
fsdir_cursor *pCur = (fsdir_cursor*)cur;
fsdirResetCursor(pCur);
sqlite3_free(pCur);
return SQLITE_OK;
}
/*
** Set the error message for the virtual table associated with cursor
** pCur to the results of vprintf(zFmt, ...).
*/
static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){
va_list ap;
va_start(ap, zFmt);
pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
va_end(ap);
}
/*
** Advance an fsdir_cursor to its next row of output.
*/
static int fsdirNext(sqlite3_vtab_cursor *cur){
fsdir_cursor *pCur = (fsdir_cursor*)cur;
mode_t m = pCur->sStat.st_mode;
pCur->iRowid++;
if( S_ISDIR(m) ){
/* Descend into this directory */
int iNew = pCur->iLvl + 1;
FsdirLevel *pLvl;
if( iNew>=pCur->nLvl ){
int nNew = iNew+1;
sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
if( aNew==0 ) return SQLITE_NOMEM;
memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
pCur->aLvl = aNew;
pCur->nLvl = nNew;
}
pCur->iLvl = iNew;
pLvl = &pCur->aLvl[iNew];
pLvl->zDir = pCur->zPath;
pCur->zPath = 0;
pLvl->pDir = opendir(pLvl->zDir);
if( pLvl->pDir==0 ){
fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath);
return SQLITE_ERROR;
}
}
while( pCur->iLvl>=0 ){
FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl];
struct dirent *pEntry = readdir(pLvl->pDir);
if( pEntry ){
if( pEntry->d_name[0]=='.' ){
if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue;
if( pEntry->d_name[1]=='\0' ) continue;
}
sqlite3_free(pCur->zPath);
pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
if( pCur->zPath==0 ) return SQLITE_NOMEM;
if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
return SQLITE_ERROR;
}
return SQLITE_OK;
}
closedir(pLvl->pDir);
sqlite3_free(pLvl->zDir);
pLvl->pDir = 0;
pLvl->zDir = 0;
pCur->iLvl--;
}
/* EOF */
sqlite3_free(pCur->zPath);
pCur->zPath = 0;
return SQLITE_OK;
}
/*
** Return values of columns for the row at which the series_cursor
** is currently pointing.
*/
static int fsdirColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int i /* Which column to return */
){
fsdir_cursor *pCur = (fsdir_cursor*)cur;
switch( i ){
case FSDIR_COLUMN_NAME: {
sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
break;
}
case FSDIR_COLUMN_MODE:
sqlite3_result_int64(ctx, pCur->sStat.st_mode);
break;
case FSDIR_COLUMN_MTIME:
sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
break;
case FSDIR_COLUMN_DATA: {
mode_t m = pCur->sStat.st_mode;
if( S_ISDIR(m) ){
sqlite3_result_null(ctx);
#if !defined(_WIN32) && !defined(WIN32)
}else if( S_ISLNK(m) ){
char aStatic[64];
char *aBuf = aStatic;
sqlite3_int64 nBuf = 64;
int n;
while( 1 ){
n = readlink(pCur->zPath, aBuf, nBuf);
if( n<nBuf ) break;
if( aBuf!=aStatic ) sqlite3_free(aBuf);
nBuf = nBuf*2;
aBuf = sqlite3_malloc64(nBuf);
if( aBuf==0 ){
sqlite3_result_error_nomem(ctx);
return SQLITE_NOMEM;
}
}
sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
if( aBuf!=aStatic ) sqlite3_free(aBuf);
#endif
}else{
readFileContents(ctx, pCur->zPath);
}
}
case FSDIR_COLUMN_PATH:
default: {
/* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
** always return their values as NULL */
break;
}
}
return SQLITE_OK;
}
/*
** Return the rowid for the current row. In this implementation, the
** first row returned is assigned rowid value 1, and each subsequent
** row a value 1 more than that of the previous.
*/
static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
fsdir_cursor *pCur = (fsdir_cursor*)cur;
*pRowid = pCur->iRowid;
return SQLITE_OK;
}
/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int fsdirEof(sqlite3_vtab_cursor *cur){
fsdir_cursor *pCur = (fsdir_cursor*)cur;
return (pCur->zPath==0);
}
/*
** xFilter callback.
**
** idxNum==1 PATH parameter only
** idxNum==2 Both PATH and DIR supplied
*/
static int fsdirFilter(
sqlite3_vtab_cursor *cur,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
const char *zDir = 0;
fsdir_cursor *pCur = (fsdir_cursor*)cur;
(void)idxStr;
fsdirResetCursor(pCur);
if( idxNum==0 ){
fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
return SQLITE_ERROR;
}
assert( argc==idxNum && (argc==1 || argc==2) );
zDir = (const char*)sqlite3_value_text(argv[0]);
if( zDir==0 ){
fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
return SQLITE_ERROR;
}
if( argc==2 ){
pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
}
if( pCur->zBase ){
pCur->nBase = (int)strlen(pCur->zBase)+1;
pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir);
}else{
pCur->zPath = sqlite3_mprintf("%s", zDir);
}
if( pCur->zPath==0 ){
return SQLITE_NOMEM;
}
if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
return SQLITE_ERROR;
}
return SQLITE_OK;
}
/*
** SQLite will invoke this method one or more times while planning a query
** that uses the generate_series virtual table. This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
**
** In this implementation idxNum is used to represent the
** query plan. idxStr is unused.
**
** The query plan is represented by values of idxNum:
**
** (1) The path value is supplied by argv[0]
** (2) Path is in argv[0] and dir is in argv[1]
*/
static int fsdirBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
int i; /* Loop over constraints */
int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */
int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */
int seenPath = 0; /* True if an unusable PATH= constraint is seen */
int seenDir = 0; /* True if an unusable DIR= constraint is seen */
const struct sqlite3_index_constraint *pConstraint;
(void)tab;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
switch( pConstraint->iColumn ){
case FSDIR_COLUMN_PATH: {
if( pConstraint->usable ){
idxPath = i;
seenPath = 0;
}else if( idxPath<0 ){
seenPath = 1;
}
break;
}
case FSDIR_COLUMN_DIR: {
if( pConstraint->usable ){
idxDir = i;
seenDir = 0;
}else if( idxDir<0 ){
seenDir = 1;
}
break;
}
}
}
if( seenPath || seenDir ){
/* If input parameters are unusable, disallow this plan */
return SQLITE_CONSTRAINT;
}
if( idxPath<0 ){
pIdxInfo->idxNum = 0;
/* The pIdxInfo->estimatedCost should have been initialized to a huge
** number. Leave it unchanged. */
pIdxInfo->estimatedRows = 0x7fffffff;
}else{
pIdxInfo->aConstraintUsage[idxPath].omit = 1;
pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
if( idxDir>=0 ){
pIdxInfo->aConstraintUsage[idxDir].omit = 1;
pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
pIdxInfo->idxNum = 2;
pIdxInfo->estimatedCost = 10.0;
}else{
pIdxInfo->idxNum = 1;
pIdxInfo->estimatedCost = 100.0;
}
}
return SQLITE_OK;
}
/*
** Register the "fsdir" virtual table.
*/
static int fsdirRegister(sqlite3 *db){
static sqlite3_module fsdirModule = {
0, /* iVersion */
0, /* xCreate */
fsdirConnect, /* xConnect */
fsdirBestIndex, /* xBestIndex */
fsdirDisconnect, /* xDisconnect */
0, /* xDestroy */
fsdirOpen, /* xOpen - open a cursor */
fsdirClose, /* xClose - close a cursor */
fsdirFilter, /* xFilter - configure scan constraints */
fsdirNext, /* xNext - advance a cursor */
fsdirEof, /* xEof - check for end of scan */
fsdirColumn, /* xColumn - read data */
fsdirRowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
};
int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
return rc;
}
#else /* SQLITE_OMIT_VIRTUALTABLE */
# define fsdirRegister(x) SQLITE_OK
#endif
#ifdef _WIN32
#endif
int sqlite3_fileio_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "readfile", 1,
SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
readfileFunc, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "writefile", -1,
SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
writefileFunc, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
lsModeFunc, 0, 0);
}
if( rc==SQLITE_OK ){
rc = fsdirRegister(db);
}
return rc;
}
#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
/* To allow a standalone DLL, make test_windirent.c use the same
* redefined SQLite API calls as the above extension code does.
* Just pull in this .c to accomplish this. As a beneficial side
* effect, this extension becomes a single translation unit. */
# include "test_windirent.c"
#endif
/************************* End ../ext/misc/fileio.c ********************/
/************************* Begin ../ext/misc/completion.c ******************/
/*
** 2017-07-10
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements an eponymous virtual table that returns suggested
** completions for a partial SQL input.
**
** Suggested usage:
**
** SELECT DISTINCT candidate COLLATE nocase
** FROM completion($prefix,$wholeline)
** ORDER BY 1;
**
** The two query parameters are optional. $prefix is the text of the
** current word being typed and that is to be completed. $wholeline is
** the complete input line, used for context.
**
** The raw completion() table might return the same candidate multiple
** times, for example if the same column name is used to two or more
** tables. And the candidates are returned in an arbitrary order. Hence,
** the DISTINCT and ORDER BY are recommended.
**
** This virtual table operates at the speed of human typing, and so there
** is no attempt to make it fast. Even a slow implementation will be much
** faster than any human can type.
**
*/
/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <ctype.h>
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* completion_vtab is a subclass of sqlite3_vtab which will
** serve as the underlying representation of a completion virtual table
*/
typedef struct completion_vtab completion_vtab;
struct completion_vtab {
sqlite3_vtab base; /* Base class - must be first */
sqlite3 *db; /* Database connection for this completion vtab */
};
/* completion_cursor is a subclass of sqlite3_vtab_cursor which will
** serve as the underlying representation of a cursor that scans
** over rows of the result
*/
typedef struct completion_cursor completion_cursor;
struct completion_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
sqlite3 *db; /* Database connection for this cursor */
int nPrefix, nLine; /* Number of bytes in zPrefix and zLine */
char *zPrefix; /* The prefix for the word we want to complete */
char *zLine; /* The whole that we want to complete */
const char *zCurrentRow; /* Current output row */
int szRow; /* Length of the zCurrentRow string */
sqlite3_stmt *pStmt; /* Current statement */
sqlite3_int64 iRowid; /* The rowid */
int ePhase; /* Current phase */
int j; /* inter-phase counter */
};
/* Values for ePhase:
*/
#define COMPLETION_FIRST_PHASE 1
#define COMPLETION_KEYWORDS 1
#define COMPLETION_PRAGMAS 2
#define COMPLETION_FUNCTIONS 3
#define COMPLETION_COLLATIONS 4
#define COMPLETION_INDEXES 5
#define COMPLETION_TRIGGERS 6
#define COMPLETION_DATABASES 7
#define COMPLETION_TABLES 8 /* Also VIEWs and TRIGGERs */
#define COMPLETION_COLUMNS 9
#define COMPLETION_MODULES 10
#define COMPLETION_EOF 11
/*
** The completionConnect() method is invoked to create a new
** completion_vtab that describes the completion virtual table.
**
** Think of this routine as the constructor for completion_vtab objects.
**
** All this routine needs to do is:
**
** (1) Allocate the completion_vtab object and initialize all fields.
**
** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
** result set of queries against completion will look like.
*/
static int completionConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
completion_vtab *pNew;
int rc;
(void)(pAux); /* Unused parameter */
(void)(argc); /* Unused parameter */
(void)(argv); /* Unused parameter */
(void)(pzErr); /* Unused parameter */
/* Column numbers */
#define COMPLETION_COLUMN_CANDIDATE 0 /* Suggested completion of the input */
#define COMPLETION_COLUMN_PREFIX 1 /* Prefix of the word to be completed */
#define COMPLETION_COLUMN_WHOLELINE 2 /* Entire line seen so far */
#define COMPLETION_COLUMN_PHASE 3 /* ePhase - used for debugging only */
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x("
" candidate TEXT,"
" prefix TEXT HIDDEN,"
" wholeline TEXT HIDDEN,"
" phase INT HIDDEN" /* Used for debugging only */
")");
if( rc==SQLITE_OK ){
pNew = sqlite3_malloc( sizeof(*pNew) );
*ppVtab = (sqlite3_vtab*)pNew;
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
pNew->db = db;
}
return rc;
}
/*
** This method is the destructor for completion_cursor objects.
*/
static int completionDisconnect(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return SQLITE_OK;
}
/*
** Constructor for a new completion_cursor object.
*/
static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
completion_cursor *pCur;
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
pCur->db = ((completion_vtab*)p)->db;
*ppCursor = &pCur->base;
return SQLITE_OK;
}
/*
** Reset the completion_cursor.
*/
static void completionCursorReset(completion_cursor *pCur){
sqlite3_free(pCur->zPrefix); pCur->zPrefix = 0; pCur->nPrefix = 0;
sqlite3_free(pCur->zLine); pCur->zLine = 0; pCur->nLine = 0;
sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
pCur->j = 0;
}
/*
** Destructor for a completion_cursor.
*/
static int completionClose(sqlite3_vtab_cursor *cur){
completionCursorReset((completion_cursor*)cur);
sqlite3_free(cur);
return SQLITE_OK;
}
/*
** Advance a completion_cursor to its next row of output.
**
** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
** record the current state of the scan. This routine sets ->zCurrentRow
** to the current row of output and then returns. If no more rows remain,
** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
** table that has reached the end of its scan.
**
** The current implementation just lists potential identifiers and
** keywords and filters them by zPrefix. Future enhancements should
** take zLine into account to try to restrict the set of identifiers and
** keywords based on what would be legal at the current point of input.
*/
static int completionNext(sqlite3_vtab_cursor *cur){
completion_cursor *pCur = (completion_cursor*)cur;
int eNextPhase = 0; /* Next phase to try if current phase reaches end */
int iCol = -1; /* If >=0, step pCur->pStmt and use the i-th column */
pCur->iRowid++;
while( pCur->ePhase!=COMPLETION_EOF ){
switch( pCur->ePhase ){
case COMPLETION_KEYWORDS: {
if( pCur->j >= sqlite3_keyword_count() ){
pCur->zCurrentRow = 0;
pCur->ePhase = COMPLETION_DATABASES;
}else{
sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow);
}
iCol = -1;
break;
}
case COMPLETION_DATABASES: {
if( pCur->pStmt==0 ){
sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
&pCur->pStmt, 0);
}
iCol = 1;
eNextPhase = COMPLETION_TABLES;
break;
}
case COMPLETION_TABLES: {
if( pCur->pStmt==0 ){
sqlite3_stmt *pS2;
char *zSql = 0;
const char *zSep = "";
sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
while( sqlite3_step(pS2)==SQLITE_ROW ){
const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
zSql = sqlite3_mprintf(
"%z%s"
"SELECT name FROM \"%w\".sqlite_schema",
zSql, zSep, zDb
);
if( zSql==0 ) return SQLITE_NOMEM;
zSep = " UNION ";
}
sqlite3_finalize(pS2);
sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
sqlite3_free(zSql);
}
iCol = 0;
eNextPhase = COMPLETION_COLUMNS;
break;
}
case COMPLETION_COLUMNS: {
if( pCur->pStmt==0 ){
sqlite3_stmt *pS2;
char *zSql = 0;
const char *zSep = "";
sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
while( sqlite3_step(pS2)==SQLITE_ROW ){
const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
zSql = sqlite3_mprintf(
"%z%s"
"SELECT pti.name FROM \"%w\".sqlite_schema AS sm"
" JOIN pragma_table_info(sm.name,%Q) AS pti"
" WHERE sm.type='table'",
zSql, zSep, zDb, zDb
);
if( zSql==0 ) return SQLITE_NOMEM;
zSep = " UNION ";
}
sqlite3_finalize(pS2);
sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
sqlite3_free(zSql);
}
iCol = 0;
eNextPhase = COMPLETION_EOF;
break;
}
}
if( iCol<0 ){
/* This case is when the phase presets zCurrentRow */
if( pCur->zCurrentRow==0 ) continue;
}else{
if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
/* Extract the next row of content */
pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol);
}else{
/* When all rows are finished, advance to the next phase */
sqlite3_finalize(pCur->pStmt);
pCur->pStmt = 0;
pCur->ePhase = eNextPhase;
continue;
}
}
if( pCur->nPrefix==0 ) break;
if( pCur->nPrefix<=pCur->szRow
&& sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0
){
break;
}
}
return SQLITE_OK;
}
/*
** Return values of columns for the row at which the completion_cursor
** is currently pointing.
*/
static int completionColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int i /* Which column to return */
){
completion_cursor *pCur = (completion_cursor*)cur;
switch( i ){
case COMPLETION_COLUMN_CANDIDATE: {
sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT);
break;
}
case COMPLETION_COLUMN_PREFIX: {
sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
break;
}
case COMPLETION_COLUMN_WHOLELINE: {
sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
break;
}
case COMPLETION_COLUMN_PHASE: {
sqlite3_result_int(ctx, pCur->ePhase);
break;
}
}
return SQLITE_OK;
}
/*
** Return the rowid for the current row. In this implementation, the
** rowid is the same as the output value.
*/
static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
completion_cursor *pCur = (completion_cursor*)cur;
*pRowid = pCur->iRowid;
return SQLITE_OK;
}
/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int completionEof(sqlite3_vtab_cursor *cur){
completion_cursor *pCur = (completion_cursor*)cur;
return pCur->ePhase >= COMPLETION_EOF;
}
/*
** This method is called to "rewind" the completion_cursor object back
** to the first row of output. This method is always called at least
** once prior to any call to completionColumn() or completionRowid() or
** completionEof().
*/
static int completionFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
completion_cursor *pCur = (completion_cursor *)pVtabCursor;
int iArg = 0;
(void)(idxStr); /* Unused parameter */
(void)(argc); /* Unused parameter */
completionCursorReset(pCur);
if( idxNum & 1 ){
pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
if( pCur->nPrefix>0 ){
pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
}
iArg = 1;
}
if( idxNum & 2 ){
pCur->nLine = sqlite3_value_bytes(argv[iArg]);
if( pCur->nLine>0 ){
pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
if( pCur->zLine==0 ) return SQLITE_NOMEM;
}
}
if( pCur->zLine!=0 && pCur->zPrefix==0 ){
int i = pCur->nLine;
while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
i--;
}
pCur->nPrefix = pCur->nLine - i;
if( pCur->nPrefix>0 ){
pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
}
}
pCur->iRowid = 0;
pCur->ePhase = COMPLETION_FIRST_PHASE;
return completionNext(pVtabCursor);
}
/*
** SQLite will invoke this method one or more times while planning a query
** that uses the completion virtual table. This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
**
** There are two hidden parameters that act as arguments to the table-valued
** function: "prefix" and "wholeline". Bit 0 of idxNum is set if "prefix"
** is available and bit 1 is set if "wholeline" is available.
*/
static int completionBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
int i; /* Loop over constraints */
int idxNum = 0; /* The query plan bitmask */
int prefixIdx = -1; /* Index of the start= constraint, or -1 if none */
int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
int nArg = 0; /* Number of arguments that completeFilter() expects */
const struct sqlite3_index_constraint *pConstraint;
(void)(tab); /* Unused parameter */
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
if( pConstraint->usable==0 ) continue;
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
switch( pConstraint->iColumn ){
case COMPLETION_COLUMN_PREFIX:
prefixIdx = i;
idxNum |= 1;
break;
case COMPLETION_COLUMN_WHOLELINE:
wholelineIdx = i;
idxNum |= 2;
break;
}
}
if( prefixIdx>=0 ){
pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
}
if( wholelineIdx>=0 ){
pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
}
pIdxInfo->idxNum = idxNum;
pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
pIdxInfo->estimatedRows = 500 - 100*nArg;
return SQLITE_OK;
}
/*
** This following structure defines all the methods for the
** completion virtual table.
*/
static sqlite3_module completionModule = {
0, /* iVersion */
0, /* xCreate */
completionConnect, /* xConnect */
completionBestIndex, /* xBestIndex */
completionDisconnect, /* xDisconnect */
0, /* xDestroy */
completionOpen, /* xOpen - open a cursor */
completionClose, /* xClose - close a cursor */
completionFilter, /* xFilter - configure scan constraints */
completionNext, /* xNext - advance a cursor */
completionEof, /* xEof - check for end of scan */
completionColumn, /* xColumn - read data */
completionRowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
int sqlite3CompletionVtabInit(sqlite3 *db){
int rc = SQLITE_OK;
#ifndef SQLITE_OMIT_VIRTUALTABLE
rc = sqlite3_create_module(db, "completion", &completionModule, 0);
#endif
return rc;
}
#ifdef _WIN32
#endif
int sqlite3_completion_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)(pzErrMsg); /* Unused parameter */
#ifndef SQLITE_OMIT_VIRTUALTABLE
rc = sqlite3CompletionVtabInit(db);
#endif
return rc;
}
/************************* End ../ext/misc/completion.c ********************/
/************************* Begin ../ext/misc/appendvfs.c ******************/
/*
** 2017-10-20
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file implements a VFS shim that allows an SQLite database to be
** appended onto the end of some other file, such as an executable.
**
** A special record must appear at the end of the file that identifies the
** file as an appended database and provides the offset to the first page
** of the exposed content. (Or, it is the length of the content prefix.)
** For best performance page 1 should be located at a disk page boundary,
** though that is not required.
**
** When opening a database using this VFS, the connection might treat
** the file as an ordinary SQLite database, or it might treat it as a
** database appended onto some other file. The decision is made by
** applying the following rules in order:
**
** (1) An empty file is an ordinary database.
**
** (2) If the file ends with the appendvfs trailer string
** "Start-Of-SQLite3-NNNNNNNN" that file is an appended database.
**
** (3) If the file begins with the standard SQLite prefix string
** "SQLite format 3", that file is an ordinary database.
**
** (4) If none of the above apply and the SQLITE_OPEN_CREATE flag is
** set, then a new database is appended to the already existing file.
**
** (5) Otherwise, SQLITE_CANTOPEN is returned.
**
** To avoid unnecessary complications with the PENDING_BYTE, the size of
** the file containing the database is limited to 1GiB. (1073741824 bytes)
** This VFS will not read or write past the 1GiB mark. This restriction
** might be lifted in future versions. For now, if you need a larger
** database, then keep it in a separate file.
**
** If the file being opened is a plain database (not an appended one), then
** this shim is a pass-through into the default underlying VFS. (rule 3)
**/
/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <string.h>
#include <assert.h>
/* The append mark at the end of the database is:
**
** Start-Of-SQLite3-NNNNNNNN
** 123456789 123456789 12345
**
** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
** the offset to page 1, and also the length of the prefix content.
*/
#define APND_MARK_PREFIX "Start-Of-SQLite3-"
#define APND_MARK_PREFIX_SZ 17
#define APND_MARK_FOS_SZ 8
#define APND_MARK_SIZE (APND_MARK_PREFIX_SZ+APND_MARK_FOS_SZ)
/*
** Maximum size of the combined prefix + database + append-mark. This
** must be less than 0x40000000 to avoid locking issues on Windows.
*/
#define APND_MAX_SIZE (0x40000000)
/*
** Try to align the database to an even multiple of APND_ROUNDUP bytes.
*/
#ifndef APND_ROUNDUP
#define APND_ROUNDUP 4096
#endif
#define APND_ALIGN_MASK ((sqlite3_int64)(APND_ROUNDUP-1))
#define APND_START_ROUNDUP(fsz) (((fsz)+APND_ALIGN_MASK) & ~APND_ALIGN_MASK)
/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlite3_vfs ApndVfs;
typedef struct ApndFile ApndFile;
/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
/* An open appendvfs file
**
** An instance of this structure describes the appended database file.
** A separate sqlite3_file object is always appended. The appended
** sqlite3_file object (which can be accessed using ORIGFILE()) describes
** the entire file, including the prefix, the database, and the
** append-mark.
**
** The structure of an AppendVFS database is like this:
**
** +-------------+---------+----------+-------------+
** | prefix-file | padding | database | append-mark |
** +-------------+---------+----------+-------------+
** ^ ^
** | |
** iPgOne iMark
**
**
** "prefix file" - file onto which the database has been appended.
** "padding" - zero or more bytes inserted so that "database"
** starts on an APND_ROUNDUP boundary
** "database" - The SQLite database file
** "append-mark" - The 25-byte "Start-Of-SQLite3-NNNNNNNN" that indicates
** the offset from the start of prefix-file to the start
** of "database".
**
** The size of the database is iMark - iPgOne.
**
** The NNNNNNNN in the "Start-Of-SQLite3-NNNNNNNN" suffix is the value
** of iPgOne stored as a big-ending 64-bit integer.
**
** iMark will be the size of the underlying file minus 25 (APND_MARKSIZE).
** Or, iMark is -1 to indicate that it has not yet been written.
*/
struct ApndFile {
sqlite3_file base; /* Subclass. MUST BE FIRST! */
sqlite3_int64 iPgOne; /* Offset to the start of the database */
sqlite3_int64 iMark; /* Offset of the append mark. -1 if unwritten */
/* Always followed by another sqlite3_file that describes the whole file */
};
/*
** Methods for ApndFile
*/
static int apndClose(sqlite3_file*);
static int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
static int apndTruncate(sqlite3_file*, sqlite3_int64 size);
static int apndSync(sqlite3_file*, int flags);
static int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize);
static int apndLock(sqlite3_file*, int);
static int apndUnlock(sqlite3_file*, int);
static int apndCheckReservedLock(sqlite3_file*, int *pResOut);
static int apndFileControl(sqlite3_file*, int op, void *pArg);
static int apndSectorSize(sqlite3_file*);
static int apndDeviceCharacteristics(sqlite3_file*);
static int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
static int apndShmLock(sqlite3_file*, int offset, int n, int flags);
static void apndShmBarrier(sqlite3_file*);
static int apndShmUnmap(sqlite3_file*, int deleteFlag);
static int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
static int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
/*
** Methods for ApndVfs
*/
static int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int apndDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *);
static int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
static void *apndDlOpen(sqlite3_vfs*, const char *zFilename);
static void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
static void apndDlClose(sqlite3_vfs*, void*);
static int apndRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int apndSleep(sqlite3_vfs*, int microseconds);
static int apndCurrentTime(sqlite3_vfs*, double*);
static int apndGetLastError(sqlite3_vfs*, int, char *);
static int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
static int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
static sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z);
static const char *apndNextSystemCall(sqlite3_vfs*, const char *zName);
static sqlite3_vfs apnd_vfs = {
3, /* iVersion (set when registered) */
0, /* szOsFile (set when registered) */
1024, /* mxPathname */
0, /* pNext */
"apndvfs", /* zName */
0, /* pAppData (set when registered) */
apndOpen, /* xOpen */
apndDelete, /* xDelete */
apndAccess, /* xAccess */
apndFullPathname, /* xFullPathname */
apndDlOpen, /* xDlOpen */
apndDlError, /* xDlError */
apndDlSym, /* xDlSym */
apndDlClose, /* xDlClose */
apndRandomness, /* xRandomness */
apndSleep, /* xSleep */
apndCurrentTime, /* xCurrentTime */
apndGetLastError, /* xGetLastError */
apndCurrentTimeInt64, /* xCurrentTimeInt64 */
apndSetSystemCall, /* xSetSystemCall */
apndGetSystemCall, /* xGetSystemCall */
apndNextSystemCall /* xNextSystemCall */
};
static const sqlite3_io_methods apnd_io_methods = {
3, /* iVersion */
apndClose, /* xClose */
apndRead, /* xRead */
apndWrite, /* xWrite */
apndTruncate, /* xTruncate */
apndSync, /* xSync */
apndFileSize, /* xFileSize */
apndLock, /* xLock */
apndUnlock, /* xUnlock */
apndCheckReservedLock, /* xCheckReservedLock */
apndFileControl, /* xFileControl */
apndSectorSize, /* xSectorSize */
apndDeviceCharacteristics, /* xDeviceCharacteristics */
apndShmMap, /* xShmMap */
apndShmLock, /* xShmLock */
apndShmBarrier, /* xShmBarrier */
apndShmUnmap, /* xShmUnmap */
apndFetch, /* xFetch */
apndUnfetch /* xUnfetch */
};
/*
** Close an apnd-file.
*/
static int apndClose(sqlite3_file *pFile){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xClose(pFile);
}
/*
** Read data from an apnd-file.
*/
static int apndRead(
sqlite3_file *pFile,
void *zBuf,
int iAmt,
sqlite_int64 iOfst
){
ApndFile *paf = (ApndFile *)pFile;
pFile = ORIGFILE(pFile);
return pFile->pMethods->xRead(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
}
/*
** Add the append-mark onto what should become the end of the file.
* If and only if this succeeds, internal ApndFile.iMark is updated.
* Parameter iWriteEnd is the appendvfs-relative offset of the new mark.
*/
static int apndWriteMark(
ApndFile *paf,
sqlite3_file *pFile,
sqlite_int64 iWriteEnd
){
sqlite_int64 iPgOne = paf->iPgOne;
unsigned char a[APND_MARK_SIZE];
int i = APND_MARK_FOS_SZ;
int rc;
assert(pFile == ORIGFILE(paf));
memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
while( --i >= 0 ){
a[APND_MARK_PREFIX_SZ+i] = (unsigned char)(iPgOne & 0xff);
iPgOne >>= 8;
}
iWriteEnd += paf->iPgOne;
if( SQLITE_OK==(rc = pFile->pMethods->xWrite
(pFile, a, APND_MARK_SIZE, iWriteEnd)) ){
paf->iMark = iWriteEnd;
}
return rc;
}
/*
** Write data to an apnd-file.
*/
static int apndWrite(
sqlite3_file *pFile,
const void *zBuf,
int iAmt,
sqlite_int64 iOfst
){
ApndFile *paf = (ApndFile *)pFile;
sqlite_int64 iWriteEnd = iOfst + iAmt;
if( iWriteEnd>=APND_MAX_SIZE ) return SQLITE_FULL;
pFile = ORIGFILE(pFile);
/* If append-mark is absent or will be overwritten, write it. */
if( paf->iMark < 0 || paf->iPgOne + iWriteEnd > paf->iMark ){
int rc = apndWriteMark(paf, pFile, iWriteEnd);
if( SQLITE_OK!=rc ) return rc;
}
return pFile->pMethods->xWrite(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
}
/*
** Truncate an apnd-file.
*/
static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
ApndFile *paf = (ApndFile *)pFile;
pFile = ORIGFILE(pFile);
/* The append mark goes out first so truncate failure does not lose it. */
if( SQLITE_OK!=apndWriteMark(paf, pFile, size) ) return SQLITE_IOERR;
/* Truncate underlying file just past append mark */
return pFile->pMethods->xTruncate(pFile, paf->iMark+APND_MARK_SIZE);
}
/*
** Sync an apnd-file.
*/
static int apndSync(sqlite3_file *pFile, int flags){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xSync(pFile, flags);
}
/*
** Return the current file-size of an apnd-file.
** If the append mark is not yet there, the file-size is 0.
*/
static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
ApndFile *paf = (ApndFile *)pFile;
*pSize = ( paf->iMark >= 0 )? (paf->iMark - paf->iPgOne) : 0;
return SQLITE_OK;
}
/*
** Lock an apnd-file.
*/
static int apndLock(sqlite3_file *pFile, int eLock){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xLock(pFile, eLock);
}
/*
** Unlock an apnd-file.
*/
static int apndUnlock(sqlite3_file *pFile, int eLock){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xUnlock(pFile, eLock);
}
/*
** Check if another file-handle holds a RESERVED lock on an apnd-file.
*/
static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
}
/*
** File control method. For custom operations on an apnd-file.
*/
static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
ApndFile *paf = (ApndFile *)pFile;
int rc;
pFile = ORIGFILE(pFile);
if( op==SQLITE_FCNTL_SIZE_HINT ) *(sqlite3_int64*)pArg += paf->iPgOne;
rc = pFile->pMethods->xFileControl(pFile, op, pArg);
if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
*(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", paf->iPgOne,*(char**)pArg);
}
return rc;
}
/*
** Return the sector-size in bytes for an apnd-file.
*/
static int apndSectorSize(sqlite3_file *pFile){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xSectorSize(pFile);
}
/*
** Return the device characteristic flags supported by an apnd-file.
*/
static int apndDeviceCharacteristics(sqlite3_file *pFile){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xDeviceCharacteristics(pFile);
}
/* Create a shared memory file mapping */
static int apndShmMap(
sqlite3_file *pFile,
int iPg,
int pgsz,
int bExtend,
void volatile **pp
){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
}
/* Perform locking on a shared-memory segment */
static int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xShmLock(pFile,offset,n,flags);
}
/* Memory barrier operation on shared memory */
static void apndShmBarrier(sqlite3_file *pFile){
pFile = ORIGFILE(pFile);
pFile->pMethods->xShmBarrier(pFile);
}
/* Unmap a shared memory segment */
static int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
}
/* Fetch a page of a memory-mapped file */
static int apndFetch(
sqlite3_file *pFile,
sqlite3_int64 iOfst,
int iAmt,
void **pp
){
ApndFile *p = (ApndFile *)pFile;
if( p->iMark < 0 || iOfst+iAmt > p->iMark ){
return SQLITE_IOERR; /* Cannot read what is not yet there. */
}
pFile = ORIGFILE(pFile);
return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
}
/* Release a memory-mapped page */
static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
ApndFile *p = (ApndFile *)pFile;
pFile = ORIGFILE(pFile);
return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
}
/*
** Try to read the append-mark off the end of a file. Return the
** start of the appended database if the append-mark is present.
** If there is no valid append-mark, return -1;
**
** An append-mark is only valid if the NNNNNNNN start-of-database offset
** indicates that the appended database contains at least one page. The
** start-of-database value must be a multiple of 512.
*/
static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
int rc, i;
sqlite3_int64 iMark;
int msbs = 8 * (APND_MARK_FOS_SZ-1);
unsigned char a[APND_MARK_SIZE];
if( APND_MARK_SIZE!=(sz & 0x1ff) ) return -1;
rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
if( rc ) return -1;
if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ] & 0x7f)) << msbs;
for(i=1; i<8; i++){
msbs -= 8;
iMark |= (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<msbs;
}
if( iMark > (sz - APND_MARK_SIZE - 512) ) return -1;
if( iMark & 0x1ff ) return -1;
return iMark;
}
static const char apvfsSqliteHdr[] = "SQLite format 3";
/*
** Check to see if the file is an appendvfs SQLite database file.
** Return true iff it is such. Parameter sz is the file's size.
*/
static int apndIsAppendvfsDatabase(sqlite3_int64 sz, sqlite3_file *pFile){
int rc;
char zHdr[16];
sqlite3_int64 iMark = apndReadMark(sz, pFile);
if( iMark>=0 ){
/* If file has the correct end-marker, the expected odd size, and the
** SQLite DB type marker where the end-marker puts it, then it
** is an appendvfs database.
*/
rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), iMark);
if( SQLITE_OK==rc
&& memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0
&& (sz & 0x1ff) == APND_MARK_SIZE
&& sz>=512+APND_MARK_SIZE
){
return 1; /* It's an appendvfs database */
}
}
return 0;
}
/*
** Check to see if the file is an ordinary SQLite database file.
** Return true iff so. Parameter sz is the file's size.
*/
static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
char zHdr[16];
if( apndIsAppendvfsDatabase(sz, pFile) /* rule 2 */
|| (sz & 0x1ff) != 0
|| SQLITE_OK!=pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0)
|| memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))!=0
){
return 0;
}else{
return 1;
}
}
/*
** Open an apnd file handle.
*/
static int apndOpen(
sqlite3_vfs *pApndVfs,
const char *zName,
sqlite3_file *pFile,
int flags,
int *pOutFlags
){
ApndFile *pApndFile = (ApndFile*)pFile;
sqlite3_file *pBaseFile = ORIGFILE(pFile);
sqlite3_vfs *pBaseVfs = ORIGVFS(pApndVfs);
int rc;
sqlite3_int64 sz = 0;
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
/* The appendvfs is not to be used for transient or temporary databases.
** Just use the base VFS open to initialize the given file object and
** open the underlying file. (Appendvfs is then unused for this file.)
*/
return pBaseVfs->xOpen(pBaseVfs, zName, pFile, flags, pOutFlags);
}
memset(pApndFile, 0, sizeof(ApndFile));
pFile->pMethods = &apnd_io_methods;
pApndFile->iMark = -1; /* Append mark not yet written */
rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
if( rc==SQLITE_OK ){
rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
if( rc ){
pBaseFile->pMethods->xClose(pBaseFile);
}
}
if( rc ){
pFile->pMethods = 0;
return rc;
}
if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){
/* The file being opened appears to be just an ordinary DB. Copy
** the base dispatch-table so this instance mimics the base VFS.
*/
memmove(pApndFile, pBaseFile, pBaseVfs->szOsFile);
return SQLITE_OK;
}
pApndFile->iPgOne = apndReadMark(sz, pFile);
if( pApndFile->iPgOne>=0 ){
pApndFile->iMark = sz - APND_MARK_SIZE; /* Append mark found */
return SQLITE_OK;
}
if( (flags & SQLITE_OPEN_CREATE)==0 ){
pBaseFile->pMethods->xClose(pBaseFile);
rc = SQLITE_CANTOPEN;
pFile->pMethods = 0;
}else{
/* Round newly added appendvfs location to #define'd page boundary.
** Note that nothing has yet been written to the underlying file.
** The append mark will be written along with first content write.
** Until then, paf->iMark value indicates it is not yet written.
*/
pApndFile->iPgOne = APND_START_ROUNDUP(sz);
}
return rc;
}
/*
** Delete an apnd file.
** For an appendvfs, this could mean delete the appendvfs portion,
** leaving the appendee as it was before it gained an appendvfs.
** For now, this code deletes the underlying file too.
*/
static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
}
/*
** All other VFS methods are pass-thrus.
*/
static int apndAccess(
sqlite3_vfs *pVfs,
const char *zPath,
int flags,
int *pResOut
){
return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
}
static int apndFullPathname(
sqlite3_vfs *pVfs,
const char *zPath,
int nOut,
char *zOut
){
return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
}
static void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){
return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
}
static void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
}
static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
}
static void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){
ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
}
static int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
}
static int apndSleep(sqlite3_vfs *pVfs, int nMicro){
return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
}
static int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
}
static int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){
return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
}
static int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
}
static int apndSetSystemCall(
sqlite3_vfs *pVfs,
const char *zName,
sqlite3_syscall_ptr pCall
){
return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
}
static sqlite3_syscall_ptr apndGetSystemCall(
sqlite3_vfs *pVfs,
const char *zName
){
return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
}
static const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
}
#ifdef _WIN32
#endif
/*
** This routine is called when the extension is loaded.
** Register the new VFS.
*/
int sqlite3_appendvfs_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
sqlite3_vfs *pOrig;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg;
(void)db;
pOrig = sqlite3_vfs_find(0);
if( pOrig==0 ) return SQLITE_ERROR;
apnd_vfs.iVersion = pOrig->iVersion;
apnd_vfs.pAppData = pOrig;
apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
rc = sqlite3_vfs_register(&apnd_vfs, 0);
#ifdef APPENDVFS_TEST
if( rc==SQLITE_OK ){
rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister);
}
#endif
if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
return rc;
}
/************************* End ../ext/misc/appendvfs.c ********************/
#endif
#ifdef SQLITE_HAVE_ZLIB
/************************* Begin ../ext/misc/zipfile.c ******************/
/*
** 2017-12-26
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
|
| ︙ | ︙ | |||
12233 12234 12235 12236 12237 12238 12239 12240 12241 12242 12243 12244 12245 12246 12247 |
*pAuxDb; /* Currently active database connection */
int *aiIndent; /* Array of indents used in MODE_Explain */
int nIndent; /* Size of array aiIndent[] */
int iIndent; /* Index of current op in aiIndent[] */
char *zNonce; /* Nonce for temporary safe-mode excapes */
EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
};
/* Allowed values for ShellState.autoEQP
*/
#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
#define AUTOEQP_on 1 /* Automatic EQP is on */
#define AUTOEQP_trigger 2 /* On and also show plans for triggers */
| > > > > > > > > > > | 12246 12247 12248 12249 12250 12251 12252 12253 12254 12255 12256 12257 12258 12259 12260 12261 12262 12263 12264 12265 12266 12267 12268 12269 12270 |
*pAuxDb; /* Currently active database connection */
int *aiIndent; /* Array of indents used in MODE_Explain */
int nIndent; /* Size of array aiIndent[] */
int iIndent; /* Index of current op in aiIndent[] */
char *zNonce; /* Nonce for temporary safe-mode excapes */
EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
#ifdef SQLITE_SHELL_WASM_MODE
struct {
const char * zInput; /* Input string from wasm/JS proxy */
const char * zPos; /* Cursor pos into zInput */
} wasm;
#endif
};
#ifdef SQLITE_SHELL_WASM_MODE
static ShellState shellState;
#endif
/* Allowed values for ShellState.autoEQP
*/
#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
#define AUTOEQP_on 1 /* Automatic EQP is on */
#define AUTOEQP_trigger 2 /* On and also show plans for triggers */
|
| ︙ | ︙ | |||
12275 12276 12277 12278 12279 12280 12281 | */ #define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */ #define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */ #define SHFLG_Backslash 0x00000004 /* The --backslash option is used */ #define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */ #define SHFLG_Newlines 0x00000010 /* .dump --newline flag */ #define SHFLG_CountChanges 0x00000020 /* .changes setting */ | | | 12298 12299 12300 12301 12302 12303 12304 12305 12306 12307 12308 12309 12310 12311 12312 | */ #define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */ #define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */ #define SHFLG_Backslash 0x00000004 /* The --backslash option is used */ #define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */ #define SHFLG_Newlines 0x00000010 /* .dump --newline flag */ #define SHFLG_CountChanges 0x00000020 /* .changes setting */ #define SHFLG_Echo 0x00000040 /* .echo on/off, or --echo setting */ #define SHFLG_HeaderSet 0x00000080 /* showHeader has been specified */ #define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */ #define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */ /* ** Macros for testing and setting shellFlgs */ |
| ︙ | ︙ | |||
12899 12900 12901 12902 12903 12904 12905 12906 12907 12908 12909 12910 12911 12912 12913 |
"zipfile_cds",
};
UNUSED_PARAMETER(zA2);
UNUSED_PARAMETER(zA3);
UNUSED_PARAMETER(zA4);
switch( op ){
case SQLITE_ATTACH: {
failIfSafeMode(p, "cannot run ATTACH in safe mode");
break;
}
case SQLITE_FUNCTION: {
int i;
for(i=0; i<ArraySize(azProhibitedFunctions); i++){
if( sqlite3_stricmp(zA1, azProhibitedFunctions[i])==0 ){
failIfSafeMode(p, "cannot use the %s() function in safe mode",
| > > > > | 12922 12923 12924 12925 12926 12927 12928 12929 12930 12931 12932 12933 12934 12935 12936 12937 12938 12939 12940 |
"zipfile_cds",
};
UNUSED_PARAMETER(zA2);
UNUSED_PARAMETER(zA3);
UNUSED_PARAMETER(zA4);
switch( op ){
case SQLITE_ATTACH: {
#ifndef SQLITE_SHELL_WASM_MODE
/* In WASM builds the filesystem is a virtual sandbox, so
** there's no harm in using ATTACH. */
failIfSafeMode(p, "cannot run ATTACH in safe mode");
#endif
break;
}
case SQLITE_FUNCTION: {
int i;
for(i=0; i<ArraySize(azProhibitedFunctions); i++){
if( sqlite3_stricmp(zA1, azProhibitedFunctions[i])==0 ){
failIfSafeMode(p, "cannot use the %s() function in safe mode",
|
| ︙ | ︙ | |||
14027 14028 14029 14030 14031 14032 14033 14034 14035 14036 14037 14038 14039 14040 14041 14042 14043 14044 14045 14046 14047 14048 |
** spaces each opcode should be indented before it is output.
**
** The indenting rules are:
**
** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
** all opcodes that occur between the p2 jump destination and the opcode
** itself by 2 spaces.
**
** * For each "Goto", if the jump destination is earlier in the program
** and ends on one of:
** Yield SeekGt SeekLt RowSetRead Rewind
** or if the P1 parameter is one instead of zero,
** then indent all opcodes between the earlier instruction
** and "Goto" by 2 spaces.
*/
static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
const char *zSql; /* The text of the SQL statement */
const char *z; /* Used to check if this is an EXPLAIN */
int *abYield = 0; /* True if op is an OP_Yield */
int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
int iOp; /* Index of operation in p->aiIndent[] */
| > > > | > | 14054 14055 14056 14057 14058 14059 14060 14061 14062 14063 14064 14065 14066 14067 14068 14069 14070 14071 14072 14073 14074 14075 14076 14077 14078 14079 14080 14081 14082 14083 14084 14085 14086 14087 |
** spaces each opcode should be indented before it is output.
**
** The indenting rules are:
**
** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
** all opcodes that occur between the p2 jump destination and the opcode
** itself by 2 spaces.
**
** * Do the previous for "Return" instructions for when P2 is positive.
** See tag-20220407a in wherecode.c and vdbe.c.
**
** * For each "Goto", if the jump destination is earlier in the program
** and ends on one of:
** Yield SeekGt SeekLt RowSetRead Rewind
** or if the P1 parameter is one instead of zero,
** then indent all opcodes between the earlier instruction
** and "Goto" by 2 spaces.
*/
static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
const char *zSql; /* The text of the SQL statement */
const char *z; /* Used to check if this is an EXPLAIN */
int *abYield = 0; /* True if op is an OP_Yield */
int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
int iOp; /* Index of operation in p->aiIndent[] */
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
"Return", 0 };
const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
"Rewind", 0 };
const char *azGoto[] = { "Goto", 0 };
/* Try to figure out if this is really an EXPLAIN statement. If this
** cannot be verified, return early. */
if( sqlite3_column_count(pSql)!=8 ){
|
| ︙ | ︙ | |||
14100 14101 14102 14103 14104 14105 14106 |
abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
shell_check_oom(abYield);
}
abYield[iOp] = str_in_array(zOp, azYield);
p->aiIndent[iOp] = 0;
p->nIndent = iOp+1;
| | | 14131 14132 14133 14134 14135 14136 14137 14138 14139 14140 14141 14142 14143 14144 14145 |
abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
shell_check_oom(abYield);
}
abYield[iOp] = str_in_array(zOp, azYield);
p->aiIndent[iOp] = 0;
p->nIndent = iOp+1;
if( str_in_array(zOp, azNext) && p2op>0 ){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
}
if( str_in_array(zOp, azGoto) && p2op<p->nIndent
&& (abYield[p2op] || sqlite3_column_int(pSql, 2))
){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
}
|
| ︙ | ︙ | |||
14126 14127 14128 14129 14130 14131 14132 | sqlite3_free(p->aiIndent); p->aiIndent = 0; p->nIndent = 0; p->iIndent = 0; } /* | | | 14157 14158 14159 14160 14161 14162 14163 14164 14165 14166 14167 14168 14169 14170 14171 |
sqlite3_free(p->aiIndent);
p->aiIndent = 0;
p->nIndent = 0;
p->iIndent = 0;
}
/*
** Disable and restore .wheretrace and .treetrace/.selecttrace settings.
*/
static unsigned int savedSelectTrace;
static unsigned int savedWhereTrace;
static void disable_debug_trace_modes(void){
unsigned int zero = 0;
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
|
| ︙ | ︙ | |||
14430 14431 14432 14433 14434 14435 14436 14437 14438 14439 14440 14441 14442 14443 | int j, nTotal, w, n; const char *colSep = 0; const char *rowSep = 0; const unsigned char **azNextLine = 0; int bNextLine = 0; int bMultiLineRowExists = 0; int bw = p->cmOpts.bWordWrap; rc = sqlite3_step(pStmt); if( rc!=SQLITE_ROW ) return; nColumn = sqlite3_column_count(pStmt); nAlloc = nColumn*4; if( nAlloc<=0 ) nAlloc = 1; azData = sqlite3_malloc64( nAlloc*sizeof(char*) ); | > > | 14461 14462 14463 14464 14465 14466 14467 14468 14469 14470 14471 14472 14473 14474 14475 14476 | int j, nTotal, w, n; const char *colSep = 0; const char *rowSep = 0; const unsigned char **azNextLine = 0; int bNextLine = 0; int bMultiLineRowExists = 0; int bw = p->cmOpts.bWordWrap; const char *zEmpty = ""; const char *zShowNull = p->nullValue; rc = sqlite3_step(pStmt); if( rc!=SQLITE_ROW ) return; nColumn = sqlite3_column_count(pStmt); nAlloc = nColumn*4; if( nAlloc<=0 ) nAlloc = 1; azData = sqlite3_malloc64( nAlloc*sizeof(char*) ); |
| ︙ | ︙ | |||
14491 14492 14493 14494 14495 14496 14497 14498 14499 14500 14501 14502 14503 14504 14505 14506 14507 14508 14509 14510 14511 14512 14513 14514 14515 14516 |
int wx = p->colWidth[i];
if( wx==0 ){
wx = p->cmOpts.iWrap;
}
if( wx<0 ) wx = -wx;
if( useNextLine ){
uz = azNextLine[i];
}else if( p->cmOpts.bQuote ){
sqlite3_free(azQuoted[i]);
azQuoted[i] = quoted_column(pStmt,i);
uz = (const unsigned char*)azQuoted[i];
}else{
uz = (const unsigned char*)sqlite3_column_text(pStmt,i);
}
azData[nRow*nColumn + i]
= translateForDisplayAndDup(uz, &azNextLine[i], wx, bw);
if( azNextLine[i] ){
bNextLine = 1;
abRowDiv[nRow-1] = 0;
bMultiLineRowExists = 1;
}
}
}while( bNextLine || sqlite3_step(pStmt)==SQLITE_ROW );
nTotal = nColumn*(nRow+1);
for(i=0; i<nTotal; i++){
z = azData[i];
| > > | | 14524 14525 14526 14527 14528 14529 14530 14531 14532 14533 14534 14535 14536 14537 14538 14539 14540 14541 14542 14543 14544 14545 14546 14547 14548 14549 14550 14551 14552 14553 14554 14555 14556 14557 14558 14559 |
int wx = p->colWidth[i];
if( wx==0 ){
wx = p->cmOpts.iWrap;
}
if( wx<0 ) wx = -wx;
if( useNextLine ){
uz = azNextLine[i];
if( uz==0 ) uz = (u8*)zEmpty;
}else if( p->cmOpts.bQuote ){
sqlite3_free(azQuoted[i]);
azQuoted[i] = quoted_column(pStmt,i);
uz = (const unsigned char*)azQuoted[i];
}else{
uz = (const unsigned char*)sqlite3_column_text(pStmt,i);
if( uz==0 ) uz = (u8*)zShowNull;
}
azData[nRow*nColumn + i]
= translateForDisplayAndDup(uz, &azNextLine[i], wx, bw);
if( azNextLine[i] ){
bNextLine = 1;
abRowDiv[nRow-1] = 0;
bMultiLineRowExists = 1;
}
}
}while( bNextLine || sqlite3_step(pStmt)==SQLITE_ROW );
nTotal = nColumn*(nRow+1);
for(i=0; i<nTotal; i++){
z = azData[i];
if( z==0 ) z = (char*)zEmpty;
n = strlenChar(z);
j = i%nColumn;
if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
}
if( seenInterrupt ) goto columnar_end;
if( nColumn==0 ) goto columnar_end;
switch( p->cMode ){
|
| ︙ | ︙ | |||
14614 14615 14616 14617 14618 14619 14620 |
print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
}
columnar_end:
if( seenInterrupt ){
utf8_printf(p->out, "Interrupt\n");
}
nData = (nRow+1)*nColumn;
| | > > > | 14649 14650 14651 14652 14653 14654 14655 14656 14657 14658 14659 14660 14661 14662 14663 14664 14665 14666 |
print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
}
columnar_end:
if( seenInterrupt ){
utf8_printf(p->out, "Interrupt\n");
}
nData = (nRow+1)*nColumn;
for(i=0; i<nData; i++){
z = azData[i];
if( z!=zEmpty && z!=zShowNull ) free(azData[i]);
}
sqlite3_free(azData);
sqlite3_free((void*)azNextLine);
sqlite3_free(abRowDiv);
if( azQuoted ){
for(i=0; i<nColumn; i++) sqlite3_free(azQuoted[i]);
sqlite3_free(azQuoted);
}
|
| ︙ | ︙ | |||
14893 14894 14895 14896 14897 14898 14899 |
/* save off the prepared statment handle and reset row count */
if( pArg ){
pArg->pStmt = pStmt;
pArg->cnt = 0;
}
| < < < < < | 14931 14932 14933 14934 14935 14936 14937 14938 14939 14940 14941 14942 14943 14944 |
/* save off the prepared statment handle and reset row count */
if( pArg ){
pArg->pStmt = pStmt;
pArg->cnt = 0;
}
/* Show the EXPLAIN QUERY PLAN if .eqp is on */
if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
sqlite3_stmt *pExplain;
char *zEQP;
int triggerEQP = 0;
disable_debug_trace_modes();
sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
|
| ︙ | ︙ | |||
15296 15297 15298 15299 15300 15301 15302 | return rc; } /* ** Text of help messages. ** ** The help text for each individual command begins with a line that starts | | | > | 15329 15330 15331 15332 15333 15334 15335 15336 15337 15338 15339 15340 15341 15342 15343 15344 15345 15346 15347 15348 15349 15350 |
return rc;
}
/*
** Text of help messages.
**
** The help text for each individual command begins with a line that starts
** with ".". Subsequent lines are supplemental information.
**
** There must be two or more spaces between the end of the command and the
** start of the description of what that command does.
*/
static const char *(azHelp[]) = {
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) \
&& !defined(SQLITE_SHELL_WASM_MODE)
".archive ... Manage SQL archives",
" Each command must have exactly one of the following options:",
" -c, --create Create a new archive",
" -u, --update Add or update files with changed mtime",
" -i, --insert Like -u but always add even if unchanged",
" -r, --remove Remove files from archive",
" -t, --list List contents of archive",
|
| ︙ | ︙ | |||
15328 15329 15330 15331 15332 15333 15334 15335 15336 15337 15338 15339 15340 15341 15342 15343 15344 15345 15346 15347 15348 15349 15350 15351 15352 15353 15354 15355 15356 15357 15358 15359 15360 15361 15362 15363 15364 15365 15366 15367 15368 15369 15370 15371 15372 15373 15374 15375 15376 15377 15378 15379 15380 15381 15382 15383 15384 15385 15386 15387 15388 15389 15390 15391 15392 15393 15394 15395 15396 15397 15398 15399 15400 15401 15402 | " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE", " See also:", " http://sqlite.org/cli.html#sqlite_archive_support", #endif #ifndef SQLITE_OMIT_AUTHORIZATION ".auth ON|OFF Show authorizer callbacks", #endif ".backup ?DB? FILE Backup DB (default \"main\") to FILE", " Options:", " --append Use the appendvfs", " --async Write to FILE without journal and fsync()", ".bail on|off Stop after hitting an error. Default OFF", ".binary on|off Turn binary output on or off. Default OFF", ".cd DIRECTORY Change the working directory to DIRECTORY", ".changes on|off Show number of rows changed by SQL", ".check GLOB Fail if output since .testcase does not match", ".clone NEWDB Clone data into NEWDB from the existing database", ".connection [close] [#] Open or close an auxiliary database connection", ".databases List names and files of attached databases", ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", ".dbinfo ?DB? Show status information about the database", ".dump ?OBJECTS? Render database content as SQL", " Options:", " --data-only Output only INSERT statements", " --newlines Allow unescaped newline characters in output", " --nosys Omit system tables (ex: \"sqlite_stat1\")", " --preserve-rowids Include ROWID values in the output", " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump", " Additional LIKE patterns can be given in subsequent arguments", ".echo on|off Turn command echo on or off", ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN", " Other Modes:", #ifdef SQLITE_DEBUG " test Show raw EXPLAIN QUERY PLAN output", " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"", #endif " trigger Like \"full\" but also show trigger bytecode", ".excel Display the output of next command in spreadsheet", " --bom Put a UTF8 byte-order mark on intermediate file", ".exit ?CODE? Exit this program with return-code CODE", ".expert EXPERIMENTAL. Suggest indexes for queries", ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto", ".filectrl CMD ... Run various sqlite3_file_control() operations", " --schema SCHEMA Use SCHEMA instead of \"main\"", " --help Show CMD details", ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", ".headers on|off Turn display of headers on or off", ".help ?-all? ?PATTERN? Show help text for PATTERN", ".import FILE TABLE Import data from FILE into TABLE", " Options:", " --ascii Use \\037 and \\036 as column and row separators", " --csv Use , and \\n as column and row separators", " --skip N Skip the first N rows of input", " --schema S Target table to be S.TABLE", " -v \"Verbose\" - increase auxiliary output", " Notes:", " * If TABLE does not exist, it is created. The first row of input", " determines the column names.", " * If neither --csv or --ascii are used, the input mode is derived", " from the \".mode\" output mode", " * If FILE begins with \"|\" then it is a command that generates the", " input text.", #ifndef SQLITE_OMIT_TEST_CONTROL ".imposter INDEX TABLE Create imposter table TABLE on index INDEX", #endif ".indexes ?TABLE? Show names of indexes", " If TABLE is specified, only show indexes for", " tables matching TABLE using the LIKE operator.", #ifdef SQLITE_ENABLE_IOTRACE ".iotrace FILE Enable I/O diagnostic logging to FILE", #endif ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT", ".lint OPTIONS Report potential schema issues.", " Options:", " fkey-indexes Find missing foreign key indexes", | > > > > > > > > > > > > > > | > > | 15362 15363 15364 15365 15366 15367 15368 15369 15370 15371 15372 15373 15374 15375 15376 15377 15378 15379 15380 15381 15382 15383 15384 15385 15386 15387 15388 15389 15390 15391 15392 15393 15394 15395 15396 15397 15398 15399 15400 15401 15402 15403 15404 15405 15406 15407 15408 15409 15410 15411 15412 15413 15414 15415 15416 15417 15418 15419 15420 15421 15422 15423 15424 15425 15426 15427 15428 15429 15430 15431 15432 15433 15434 15435 15436 15437 15438 15439 15440 15441 15442 15443 15444 15445 15446 15447 15448 15449 15450 15451 15452 15453 15454 15455 15456 15457 15458 15459 15460 15461 15462 15463 | " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE", " See also:", " http://sqlite.org/cli.html#sqlite_archive_support", #endif #ifndef SQLITE_OMIT_AUTHORIZATION ".auth ON|OFF Show authorizer callbacks", #endif #ifndef SQLITE_SHELL_WASM_MODE ".backup ?DB? FILE Backup DB (default \"main\") to FILE", " Options:", " --append Use the appendvfs", " --async Write to FILE without journal and fsync()", #endif ".bail on|off Stop after hitting an error. Default OFF", ".binary on|off Turn binary output on or off. Default OFF", #ifndef SQLITE_SHELL_WASM_MODE ".cd DIRECTORY Change the working directory to DIRECTORY", #endif ".changes on|off Show number of rows changed by SQL", #ifndef SQLITE_SHELL_WASM_MODE ".check GLOB Fail if output since .testcase does not match", ".clone NEWDB Clone data into NEWDB from the existing database", #endif ".connection [close] [#] Open or close an auxiliary database connection", ".databases List names and files of attached databases", ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) ".dbinfo ?DB? Show status information about the database", #endif ".dump ?OBJECTS? Render database content as SQL", " Options:", " --data-only Output only INSERT statements", " --newlines Allow unescaped newline characters in output", " --nosys Omit system tables (ex: \"sqlite_stat1\")", " --preserve-rowids Include ROWID values in the output", " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump", " Additional LIKE patterns can be given in subsequent arguments", ".echo on|off Turn command echo on or off", ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN", " Other Modes:", #ifdef SQLITE_DEBUG " test Show raw EXPLAIN QUERY PLAN output", " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"", #endif " trigger Like \"full\" but also show trigger bytecode", #ifndef SQLITE_SHELL_WASM_MODE ".excel Display the output of next command in spreadsheet", " --bom Put a UTF8 byte-order mark on intermediate file", #endif #ifndef SQLITE_SHELL_WASM_MODE ".exit ?CODE? Exit this program with return-code CODE", #endif ".expert EXPERIMENTAL. Suggest indexes for queries", ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto", ".filectrl CMD ... Run various sqlite3_file_control() operations", " --schema SCHEMA Use SCHEMA instead of \"main\"", " --help Show CMD details", ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", ".headers on|off Turn display of headers on or off", ".help ?-all? ?PATTERN? Show help text for PATTERN", #ifndef SQLITE_SHELL_WASM_MODE ".import FILE TABLE Import data from FILE into TABLE", " Options:", " --ascii Use \\037 and \\036 as column and row separators", " --csv Use , and \\n as column and row separators", " --skip N Skip the first N rows of input", " --schema S Target table to be S.TABLE", " -v \"Verbose\" - increase auxiliary output", " Notes:", " * If TABLE does not exist, it is created. The first row of input", " determines the column names.", " * If neither --csv or --ascii are used, the input mode is derived", " from the \".mode\" output mode", " * If FILE begins with \"|\" then it is a command that generates the", " input text.", #endif #ifndef SQLITE_OMIT_TEST_CONTROL ".imposter INDEX TABLE Create imposter table TABLE on index INDEX", #endif ".indexes ?TABLE? Show names of indexes", " If TABLE is specified, only show indexes for", " tables matching TABLE using the LIKE operator.", #ifdef SQLITE_ENABLE_IOTRACE ".iotrace FILE Enable I/O diagnostic logging to FILE", #endif ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT", ".lint OPTIONS Report potential schema issues.", " Options:", " fkey-indexes Find missing foreign key indexes", #if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_WASM_MODE) ".load FILE ?ENTRY? Load an extension library", #endif #ifndef SQLITE_SHELL_WASM_MODE ".log FILE|off Turn logging on or off. FILE can be stderr/stdout", #endif ".mode MODE ?OPTIONS? Set output mode", " MODE is one of:", " ascii Columns/rows delimited by 0x1F and 0x1E", " box Tables using unicode box-drawing characters", " csv Comma-separated values", " column Output in columns. (See .width)", " html HTML <table> code", |
| ︙ | ︙ | |||
15424 15425 15426 15427 15428 15429 15430 15431 15432 15433 15434 15435 15436 15437 15438 15439 15440 15441 15442 15443 15444 15445 15446 15447 15448 15449 15450 15451 15452 15453 15454 15455 15456 15457 15458 15459 15460 15461 15462 15463 15464 15465 15466 15467 15468 15469 15470 15471 15472 15473 15474 15475 15476 15477 15478 15479 15480 15481 15482 15483 15484 15485 15486 15487 15488 15489 15490 15491 | " OPTIONS: (for columnar modes or insert mode):", " --wrap N Wrap output lines to no longer than N characters", " --wordwrap B Wrap or not at word boundaries per B (on/off)", " --ww Shorthand for \"--wordwrap 1\"", " --quote Quote output text as SQL literals", " --noquote Do not quote output text", " TABLE The name of SQL table used for \"insert\" mode", ".nonce STRING Suspend safe mode for one command if nonce matches", ".nullvalue STRING Use STRING in place of NULL values", ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE", " If FILE begins with '|' then open as a pipe", " --bom Put a UTF8 byte-order mark at the beginning", " -e Send output to the system text editor", " -x Send output as CSV to a spreadsheet (same as \".excel\")", ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", " Options:", " --append Use appendvfs to append database to the end of FILE", #ifndef SQLITE_OMIT_DESERIALIZE " --deserialize Load into memory using sqlite3_deserialize()", " --hexdb Load the output of \"dbtotxt\" as an in-memory db", " --maxsize N Maximum size for --hexdb or --deserialized database", #endif " --new Initialize FILE to an empty database", " --nofollow Do not follow symbolic links", " --readonly Open FILE readonly", " --zip FILE is a ZIP archive", ".output ?FILE? Send output to FILE or stdout if FILE is omitted", " If FILE begins with '|' then open it as a pipe.", " Options:", " --bom Prefix output with a UTF8 byte-order mark", " -e Send output to the system text editor", " -x Send output as CSV to a spreadsheet", ".parameter CMD ... Manage SQL parameter bindings", " clear Erase all bindings", " init Initialize the TEMP table that holds bindings", " list List the current parameter bindings", " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE", " PARAMETER should start with one of: $ : @ ?", " unset PARAMETER Remove PARAMETER from the binding table", ".print STRING... Print literal STRING", #ifndef SQLITE_OMIT_PROGRESS_CALLBACK ".progress N Invoke progress handler after every N opcodes", " --limit N Interrupt after N progress callbacks", " --once Do no more than one progress interrupt", " --quiet|-q No output except at interrupts", " --reset Reset the count for each input and interrupt", #endif ".prompt MAIN CONTINUE Replace the standard prompts", ".quit Exit this program", ".read FILE Read input from FILE or command output", " If FILE begins with \"|\", it is a command that generates the input.", #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) ".recover Recover as much data as possible from corrupt db.", " --freelist-corrupt Assume the freelist is corrupt", " --recovery-db NAME Store recovery metadata in database file NAME", " --lost-and-found TABLE Alternative name for the lost-and-found table", " --no-rowids Do not attempt to recover rowid values", " that are not also INTEGER PRIMARY KEYs", #endif ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", ".save ?OPTIONS? FILE Write database to FILE (an alias for .backup ...)", ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off", ".schema ?PATTERN? Show the CREATE statements matching PATTERN", " Options:", " --indent Try to pretty-print the schema", " --nosys Omit objects whose names start with \"sqlite_\"", ".selftest ?OPTIONS? Run tests defined in the SELFTEST table", " Options:", | > > > > > > > > > > > > > | 15474 15475 15476 15477 15478 15479 15480 15481 15482 15483 15484 15485 15486 15487 15488 15489 15490 15491 15492 15493 15494 15495 15496 15497 15498 15499 15500 15501 15502 15503 15504 15505 15506 15507 15508 15509 15510 15511 15512 15513 15514 15515 15516 15517 15518 15519 15520 15521 15522 15523 15524 15525 15526 15527 15528 15529 15530 15531 15532 15533 15534 15535 15536 15537 15538 15539 15540 15541 15542 15543 15544 15545 15546 15547 15548 15549 15550 15551 15552 15553 15554 | " OPTIONS: (for columnar modes or insert mode):", " --wrap N Wrap output lines to no longer than N characters", " --wordwrap B Wrap or not at word boundaries per B (on/off)", " --ww Shorthand for \"--wordwrap 1\"", " --quote Quote output text as SQL literals", " --noquote Do not quote output text", " TABLE The name of SQL table used for \"insert\" mode", #ifndef SQLITE_SHELL_WASM_MODE ".nonce STRING Suspend safe mode for one command if nonce matches", #endif ".nullvalue STRING Use STRING in place of NULL values", #ifndef SQLITE_SHELL_WASM_MODE ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE", " If FILE begins with '|' then open as a pipe", " --bom Put a UTF8 byte-order mark at the beginning", " -e Send output to the system text editor", " -x Send output as CSV to a spreadsheet (same as \".excel\")", /* Note that .open is (partially) available in WASM builds but is ** currently only intended to be used by the fiddle tool, not ** end users, so is "undocumented." */ ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", " Options:", " --append Use appendvfs to append database to the end of FILE", #endif #ifndef SQLITE_OMIT_DESERIALIZE " --deserialize Load into memory using sqlite3_deserialize()", " --hexdb Load the output of \"dbtotxt\" as an in-memory db", " --maxsize N Maximum size for --hexdb or --deserialized database", #endif " --new Initialize FILE to an empty database", " --nofollow Do not follow symbolic links", " --readonly Open FILE readonly", " --zip FILE is a ZIP archive", #ifndef SQLITE_SHELL_WASM_MODE ".output ?FILE? Send output to FILE or stdout if FILE is omitted", " If FILE begins with '|' then open it as a pipe.", " Options:", " --bom Prefix output with a UTF8 byte-order mark", " -e Send output to the system text editor", " -x Send output as CSV to a spreadsheet", #endif ".parameter CMD ... Manage SQL parameter bindings", " clear Erase all bindings", " init Initialize the TEMP table that holds bindings", " list List the current parameter bindings", " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE", " PARAMETER should start with one of: $ : @ ?", " unset PARAMETER Remove PARAMETER from the binding table", ".print STRING... Print literal STRING", #ifndef SQLITE_OMIT_PROGRESS_CALLBACK ".progress N Invoke progress handler after every N opcodes", " --limit N Interrupt after N progress callbacks", " --once Do no more than one progress interrupt", " --quiet|-q No output except at interrupts", " --reset Reset the count for each input and interrupt", #endif ".prompt MAIN CONTINUE Replace the standard prompts", #ifndef SQLITE_SHELL_WASM_MODE ".quit Exit this program", ".read FILE Read input from FILE or command output", " If FILE begins with \"|\", it is a command that generates the input.", #endif #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) ".recover Recover as much data as possible from corrupt db.", " --freelist-corrupt Assume the freelist is corrupt", " --recovery-db NAME Store recovery metadata in database file NAME", " --lost-and-found TABLE Alternative name for the lost-and-found table", " --no-rowids Do not attempt to recover rowid values", " that are not also INTEGER PRIMARY KEYs", #endif #ifndef SQLITE_SHELL_WASM_MODE ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", ".save ?OPTIONS? FILE Write database to FILE (an alias for .backup ...)", #endif ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off", ".schema ?PATTERN? Show the CREATE statements matching PATTERN", " Options:", " --indent Try to pretty-print the schema", " --nosys Omit objects whose names start with \"sqlite_\"", ".selftest ?OPTIONS? Run tests defined in the SELFTEST table", " Options:", |
| ︙ | ︙ | |||
15511 15512 15513 15514 15515 15516 15517 | " Options:", " --schema Also hash the sqlite_schema table", " --sha3-224 Use the sha3-224 algorithm", " --sha3-256 Use the sha3-256 algorithm (default)", " --sha3-384 Use the sha3-384 algorithm", " --sha3-512 Use the sha3-512 algorithm", " Any other argument is a LIKE pattern for tables to hash", | | | > > | 15574 15575 15576 15577 15578 15579 15580 15581 15582 15583 15584 15585 15586 15587 15588 15589 15590 15591 15592 15593 15594 15595 15596 15597 15598 15599 15600 15601 15602 15603 | " Options:", " --schema Also hash the sqlite_schema table", " --sha3-224 Use the sha3-224 algorithm", " --sha3-256 Use the sha3-256 algorithm (default)", " --sha3-384 Use the sha3-384 algorithm", " --sha3-512 Use the sha3-512 algorithm", " Any other argument is a LIKE pattern for tables to hash", #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_WASM_MODE) ".shell CMD ARGS... Run CMD ARGS... in a system shell", #endif ".show Show the current values for various settings", ".stats ?ARG? Show stats or turn stats on or off", " off Turn off automatic stat display", " on Turn on automatic stat display", " stmt Show statement stats", " vmstep Show the virtual machine step count only", #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_WASM_MODE) ".system CMD ARGS... Run CMD ARGS... in a system shell", #endif ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", #ifndef SQLITE_SHELL_WASM_MODE ".testcase NAME Begin redirecting output to 'testcase-out.txt'", #endif ".testctrl CMD ... Run various sqlite3_test_control() operations", " Run \".testctrl\" with no arguments for details", ".timeout MS Try opening locked tables for MS milliseconds", ".timer on|off Turn SQL timer on or off", #ifndef SQLITE_OMIT_TRACE ".trace ?OPTIONS? Output each SQL statement as it is run", " FILE Send output to FILE", |
| ︙ | ︙ | |||
16069 16070 16071 16072 16073 16074 16075 |
return;
}
exit(1);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3_enable_load_extension(p->db, 1);
#endif
| < < > > > > | 16134 16135 16136 16137 16138 16139 16140 16141 16142 16143 16144 16145 16146 16147 16148 16149 16150 16151 16152 16153 16154 16155 16156 16157 |
return;
}
exit(1);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3_enable_load_extension(p->db, 1);
#endif
sqlite3_shathree_init(p->db, 0, 0);
sqlite3_uint_init(p->db, 0, 0);
sqlite3_decimal_init(p->db, 0, 0);
sqlite3_regexp_init(p->db, 0, 0);
sqlite3_ieee_init(p->db, 0, 0);
sqlite3_series_init(p->db, 0, 0);
#ifndef SQLITE_SHELL_WASM_MODE
sqlite3_fileio_init(p->db, 0, 0);
sqlite3_completion_init(p->db, 0, 0);
#endif
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
sqlite3_dbdata_init(p->db, 0, 0);
#endif
#ifdef SQLITE_HAVE_ZLIB
if( !p->bSafeModePersist ){
sqlite3_zipfile_init(p->db, 0, 0);
sqlite3_sqlar_init(p->db, 0, 0);
|
| ︙ | ︙ | |||
16854 16855 16856 16857 16858 16859 16860 16861 16862 16863 16864 16865 16866 16867 |
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
res = sqlite3_column_int(pStmt,0);
}
sqlite3_finalize(pStmt);
return res;
}
/*
** Convert a 2-byte or 4-byte big-endian integer into a native integer
*/
static unsigned int get2byteInt(unsigned char *a){
return (a[0]<<8) + a[1];
}
static unsigned int get4byteInt(unsigned char *a){
| > | 16921 16922 16923 16924 16925 16926 16927 16928 16929 16930 16931 16932 16933 16934 16935 |
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
res = sqlite3_column_int(pStmt,0);
}
sqlite3_finalize(pStmt);
return res;
}
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
/*
** Convert a 2-byte or 4-byte big-endian integer into a native integer
*/
static unsigned int get2byteInt(unsigned char *a){
return (a[0]<<8) + a[1];
}
static unsigned int get4byteInt(unsigned char *a){
|
| ︙ | ︙ | |||
16960 16961 16962 16963 16964 16965 16966 16967 16968 16969 16970 16971 16972 16973 |
utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
}
sqlite3_free(zSchemaTab);
sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
return 0;
}
/*
** Print the current sqlite3_errmsg() value to stderr and return 1.
*/
static int shellDatabaseError(sqlite3 *db){
const char *zErr = sqlite3_errmsg(db);
utf8_printf(stderr, "Error: %s\n", zErr);
| > > | 17028 17029 17030 17031 17032 17033 17034 17035 17036 17037 17038 17039 17040 17041 17042 17043 |
utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
}
sqlite3_free(zSchemaTab);
sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
return 0;
}
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE)
&& defined(SQLITE_ENABLE_DBPAGE_VTAB) */
/*
** Print the current sqlite3_errmsg() value to stderr and return 1.
*/
static int shellDatabaseError(sqlite3 *db){
const char *zErr = sqlite3_errmsg(db);
utf8_printf(stderr, "Error: %s\n", zErr);
|
| ︙ | ︙ | |||
18913 18914 18915 18916 18917 18918 18919 | } sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0); return rc; } #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */ | | | 18983 18984 18985 18986 18987 18988 18989 18990 18991 18992 18993 18994 18995 18996 18997 | } sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0); return rc; } #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */ /* * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it. * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE, * close db and set it to 0, and return the columns spec, to later * be sqlite3_free()'ed by the caller. * The return is 0 when either: * (a) The db was not initialized and zCol==0 (There are no columns.) * (b) zCol!=0 (Column was added, db initialized as needed.) |
| ︙ | ︙ | |||
18996 18997 18998 18999 19000 19001 19002 19003 19004 19005 19006 19007 19008 19009 |
COLLATE NOCASE\
)\
";
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
static const char * const zColDigits = "\
SELECT CAST(ceil(log(count(*)+0.5)) AS INT) FROM ColNames \
";
#endif
static const char * const zRenameRank =
#ifdef SHELL_COLUMN_RENAME_CLEAN
"UPDATE ColNames AS t SET suff="
"iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')"
#else /* ...RENAME_MINIMAL_ONE_PASS */
"WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */
| > > > > > > > | 19066 19067 19068 19069 19070 19071 19072 19073 19074 19075 19076 19077 19078 19079 19080 19081 19082 19083 19084 19085 19086 |
COLLATE NOCASE\
)\
";
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
static const char * const zColDigits = "\
SELECT CAST(ceil(log(count(*)+0.5)) AS INT) FROM ColNames \
";
#else
/* Counting on SQLITE_MAX_COLUMN < 100,000 here. (32767 is the hard limit.) */
static const char * const zColDigits = "\
SELECT CASE WHEN (nc < 10) THEN 1 WHEN (nc < 100) THEN 2 \
WHEN (nc < 1000) THEN 3 WHEN (nc < 10000) THEN 4 \
ELSE 5 FROM (SELECT count(*) AS nc FROM ColNames) \
";
#endif
static const char * const zRenameRank =
#ifdef SHELL_COLUMN_RENAME_CLEAN
"UPDATE ColNames AS t SET suff="
"iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')"
#else /* ...RENAME_MINIMAL_ONE_PASS */
"WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */
|
| ︙ | ︙ | |||
19042 19043 19044 19045 19046 19047 19048 |
SELECT\
'('||x'0a'\
|| group_concat(\
cname||' TEXT',\
','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
||')' AS ColsSpec \
FROM (\
| | | | 19119 19120 19121 19122 19123 19124 19125 19126 19127 19128 19129 19130 19131 19132 19133 19134 19135 19136 19137 19138 |
SELECT\
'('||x'0a'\
|| group_concat(\
cname||' TEXT',\
','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
||')' AS ColsSpec \
FROM (\
SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
FROM ColNames ORDER BY cpos\
)";
static const char * const zRenamesDone =
"SELECT group_concat("
" printf('\"%w\" to \"%w\"',name,printf('%!.*s%s', nlen-chop, name, suff)),"
" ','||x'0a')"
"FROM ColNames WHERE suff<>'' OR chop!=0"
;
int rc;
sqlite3_stmt *pStmt = 0;
assert(pDb!=0);
if( zColNew ){
|
| ︙ | ︙ | |||
19081 19082 19083 19084 19085 19086 19087 |
return 0;
}else if( *pDb==0 ){
return 0;
}else{
/* Formulate the columns spec, close the DB, zero *pDb. */
char *zColsSpec = 0;
int hasDupes = db_int(*pDb, zHasDupes);
| < < < < | 19158 19159 19160 19161 19162 19163 19164 19165 19166 19167 19168 19169 19170 19171 19172 |
return 0;
}else if( *pDb==0 ){
return 0;
}else{
/* Formulate the columns spec, close the DB, zero *pDb. */
char *zColsSpec = 0;
int hasDupes = db_int(*pDb, zHasDupes);
int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0;
if( hasDupes ){
#ifdef SHELL_COLUMN_RENAME_CLEAN
rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
rc_err_oom_die(rc);
#endif
rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0);
rc_err_oom_die(rc);
|
| ︙ | ︙ | |||
19196 19197 19198 19199 19200 19201 19202 |
sqlite3_set_authorizer(p->db, safeModeAuth, p);
}else{
sqlite3_set_authorizer(p->db, 0, 0);
}
}else
#endif
| | > > | 19269 19270 19271 19272 19273 19274 19275 19276 19277 19278 19279 19280 19281 19282 19283 19284 19285 19286 19287 19288 19289 19290 19291 19292 |
sqlite3_set_authorizer(p->db, safeModeAuth, p);
}else{
sqlite3_set_authorizer(p->db, 0, 0);
}
}else
#endif
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) \
&& !defined(SQLITE_SHELL_WASM_MODE)
if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
open_db(p, 0);
failIfSafeMode(p, "cannot run .archive in safe mode");
rc = arDotCommand(p, 0, azArg, nArg);
}else
#endif
#ifndef SQLITE_SHELL_WASM_MODE
if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
|| (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
){
const char *zDestFile = 0;
const char *zDb = 0;
sqlite3 *pDest;
sqlite3_backup *pBackup;
|
| ︙ | ︙ | |||
19272 19273 19274 19275 19276 19277 19278 19279 19280 19281 19282 19283 19284 19285 |
rc = 0;
}else{
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
rc = 1;
}
close_db(pDest);
}else
if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
if( nArg==2 ){
bail_on_error = booleanValue(azArg[1]);
}else{
raw_printf(stderr, "Usage: .bail on|off\n");
rc = 1;
| > | 19347 19348 19349 19350 19351 19352 19353 19354 19355 19356 19357 19358 19359 19360 19361 |
rc = 0;
}else{
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
rc = 1;
}
close_db(pDest);
}else
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
if( nArg==2 ){
bail_on_error = booleanValue(azArg[1]);
}else{
raw_printf(stderr, "Usage: .bail on|off\n");
rc = 1;
|
| ︙ | ︙ | |||
19302 19303 19304 19305 19306 19307 19308 19309 19310 19311 19312 19313 19314 19315 19316 19317 19318 19319 19320 19321 19322 19323 19324 19325 19326 19327 19328 19329 19330 19331 19332 19333 19334 19335 19336 19337 19338 19339 19340 19341 19342 19343 19344 |
/* The undocumented ".breakpoint" command causes a call to the no-op
** routine named test_breakpoint().
*/
if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
test_breakpoint();
}else
if( c=='c' && strcmp(azArg[0],"cd")==0 ){
failIfSafeMode(p, "cannot run .cd in safe mode");
if( nArg==2 ){
#if defined(_WIN32) || defined(WIN32)
wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
rc = !SetCurrentDirectoryW(z);
sqlite3_free(z);
#else
rc = chdir(azArg[1]);
#endif
if( rc ){
utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
rc = 1;
}
}else{
raw_printf(stderr, "Usage: .cd DIRECTORY\n");
rc = 1;
}
}else
if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
if( nArg==2 ){
setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
}else{
raw_printf(stderr, "Usage: .changes on|off\n");
rc = 1;
}
}else
/* Cancel output redirection, if it is currently set (by .testcase)
** Then read the content of the testcase-out.txt file and compare against
** azArg[1]. If there are differences, report an error and exit.
*/
if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
char *zRes = 0;
output_reset(p);
| > > > | 19378 19379 19380 19381 19382 19383 19384 19385 19386 19387 19388 19389 19390 19391 19392 19393 19394 19395 19396 19397 19398 19399 19400 19401 19402 19403 19404 19405 19406 19407 19408 19409 19410 19411 19412 19413 19414 19415 19416 19417 19418 19419 19420 19421 19422 19423 |
/* The undocumented ".breakpoint" command causes a call to the no-op
** routine named test_breakpoint().
*/
if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
test_breakpoint();
}else
#ifndef SQLITE_SHELL_WASM_MODE
if( c=='c' && strcmp(azArg[0],"cd")==0 ){
failIfSafeMode(p, "cannot run .cd in safe mode");
if( nArg==2 ){
#if defined(_WIN32) || defined(WIN32)
wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
rc = !SetCurrentDirectoryW(z);
sqlite3_free(z);
#else
rc = chdir(azArg[1]);
#endif
if( rc ){
utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
rc = 1;
}
}else{
raw_printf(stderr, "Usage: .cd DIRECTORY\n");
rc = 1;
}
}else
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
if( nArg==2 ){
setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
}else{
raw_printf(stderr, "Usage: .changes on|off\n");
rc = 1;
}
}else
#ifndef SQLITE_SHELL_WASM_MODE
/* Cancel output redirection, if it is currently set (by .testcase)
** Then read the content of the testcase-out.txt file and compare against
** azArg[1]. If there are differences, report an error and exit.
*/
if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
char *zRes = 0;
output_reset(p);
|
| ︙ | ︙ | |||
19355 19356 19357 19358 19359 19360 19361 19362 19363 19364 19365 19366 19367 19368 19369 19370 19371 19372 19373 19374 19375 19376 19377 19378 |
rc = 1;
}else{
utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
p->nCheck++;
}
sqlite3_free(zRes);
}else
if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
failIfSafeMode(p, "cannot run .clone in safe mode");
if( nArg==2 ){
tryToClone(p, azArg[1]);
}else{
raw_printf(stderr, "Usage: .clone FILENAME\n");
rc = 1;
}
}else
if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
if( nArg==1 ){
/* List available connections */
int i;
for(i=0; i<ArraySize(p->aAuxDb); i++){
const char *zFile = p->aAuxDb[i].zDbFilename;
| > > > | 19434 19435 19436 19437 19438 19439 19440 19441 19442 19443 19444 19445 19446 19447 19448 19449 19450 19451 19452 19453 19454 19455 19456 19457 19458 19459 19460 |
rc = 1;
}else{
utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
p->nCheck++;
}
sqlite3_free(zRes);
}else
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
#ifndef SQLITE_SHELL_WASM_MODE
if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
failIfSafeMode(p, "cannot run .clone in safe mode");
if( nArg==2 ){
tryToClone(p, azArg[1]);
}else{
raw_printf(stderr, "Usage: .clone FILENAME\n");
rc = 1;
}
}else
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
if( nArg==1 ){
/* List available connections */
int i;
for(i=0; i<ArraySize(p->aAuxDb); i++){
const char *zFile = p->aAuxDb[i].zDbFilename;
|
| ︙ | ︙ | |||
19490 19491 19492 19493 19494 19495 19496 19497 19498 19499 19500 |
}
if( nArg>1 && ii==ArraySize(aDbConfig) ){
utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
}
}else
if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
rc = shell_dbinfo_command(p, nArg, azArg);
}else
| > < | | 19572 19573 19574 19575 19576 19577 19578 19579 19580 19581 19582 19583 19584 19585 19586 19587 19588 19589 19590 19591 19592 19593 19594 19595 19596 19597 19598 19599 19600 19601 19602 19603 |
}
if( nArg>1 && ii==ArraySize(aDbConfig) ){
utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
}
}else
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
rc = shell_dbinfo_command(p, nArg, azArg);
}else
if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
open_db(p, 0);
rc = recoverDatabaseCmd(p, nArg, azArg);
}else
#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
char *zLike = 0;
char *zSql;
int i;
int savedShowHeader = p->showHeader;
int savedShellFlags = p->shellFlgs;
ShellClearFlag(p,
SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
|SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
for(i=1; i<nArg; i++){
if( azArg[i][0]=='-' ){
const char *z = azArg[i]+1;
if( z[0]=='-' ) z++;
if( strcmp(z,"preserve-rowids")==0 ){
|
| ︙ | ︙ | |||
19653 19654 19655 19656 19657 19658 19659 19660 19661 19662 19663 19664 19665 19666 19667 19668 19669 19670 |
}
}else{
raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
rc = 1;
}
}else
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
rc = 2;
}else
/* The ".explain" command is automatic now. It is largely pointless. It
** retained purely for backwards compatibility */
if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
int val = 1;
if( nArg>=2 ){
if( strcmp(azArg[1],"auto")==0 ){
| > > | 19735 19736 19737 19738 19739 19740 19741 19742 19743 19744 19745 19746 19747 19748 19749 19750 19751 19752 19753 19754 |
}
}else{
raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
rc = 1;
}
}else
#ifndef SQLITE_SHELL_WASM_MODE
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
rc = 2;
}else
#endif
/* The ".explain" command is automatic now. It is largely pointless. It
** retained purely for backwards compatibility */
if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
int val = 1;
if( nArg>=2 ){
if( strcmp(azArg[1],"auto")==0 ){
|
| ︙ | ︙ | |||
19911 19912 19913 19914 19915 19916 19917 19918 19919 19920 19921 19922 19923 19924 |
utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
}
}else{
showHelp(p->out, 0);
}
}else
if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
char *zTable = 0; /* Insert data into this table */
char *zSchema = 0; /* within this schema (may default to "main") */
char *zFile = 0; /* Name of file to extra content from */
sqlite3_stmt *pStmt = NULL; /* A statement */
int nCol; /* Number of columns in the table */
int nByte; /* Number of bytes in an SQL string */
| > | 19995 19996 19997 19998 19999 20000 20001 20002 20003 20004 20005 20006 20007 20008 20009 |
utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
}
}else{
showHelp(p->out, 0);
}
}else
#ifndef SQLITE_SHELL_WASM_MODE
if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
char *zTable = 0; /* Insert data into this table */
char *zSchema = 0; /* within this schema (may default to "main") */
char *zFile = 0; /* Name of file to extra content from */
sqlite3_stmt *pStmt = NULL; /* A statement */
int nCol; /* Number of columns in the table */
int nByte; /* Number of bytes in an SQL string */
|
| ︙ | ︙ | |||
19932 19933 19934 19935 19936 19937 19938 |
int eVerbose = 0; /* Larger for more console output */
int nSkip = 0; /* Initial lines to skip */
int useOutputMode = 1; /* Use output mode to determine separators */
char *zCreate = 0; /* CREATE TABLE statement text */
failIfSafeMode(p, "cannot run .import in safe mode");
memset(&sCtx, 0, sizeof(sCtx));
| < < < < < > < | 20017 20018 20019 20020 20021 20022 20023 20024 20025 20026 20027 20028 20029 20030 20031 20032 20033 20034 20035 20036 20037 20038 20039 20040 20041 20042 20043 20044 20045 20046 20047 |
int eVerbose = 0; /* Larger for more console output */
int nSkip = 0; /* Initial lines to skip */
int useOutputMode = 1; /* Use output mode to determine separators */
char *zCreate = 0; /* CREATE TABLE statement text */
failIfSafeMode(p, "cannot run .import in safe mode");
memset(&sCtx, 0, sizeof(sCtx));
if( p->mode==MODE_Ascii ){
xRead = ascii_read_one_field;
}else{
xRead = csv_read_one_field;
}
rc = 1;
for(i=1; i<nArg; i++){
char *z = azArg[i];
if( z[0]=='-' && z[1]=='-' ) z++;
if( z[0]!='-' ){
if( zFile==0 ){
zFile = z;
}else if( zTable==0 ){
zTable = z;
}else{
utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
showHelp(p->out, "import");
goto meta_command_exit;
}
}else if( strcmp(z,"-v")==0 ){
eVerbose++;
}else if( strcmp(z,"-schema")==0 && i<nArg-1 ){
zSchema = azArg[++i];
}else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
|
| ︙ | ︙ | |||
19975 19976 19977 19978 19979 19980 19981 |
sCtx.cColSep = ',';
sCtx.cRowSep = '\n';
xRead = csv_read_one_field;
useOutputMode = 0;
}else{
utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
showHelp(p->out, "import");
| < < < | < < < < < < > > > > > | 20055 20056 20057 20058 20059 20060 20061 20062 20063 20064 20065 20066 20067 20068 20069 20070 20071 20072 20073 20074 20075 20076 20077 20078 20079 20080 20081 20082 20083 20084 20085 20086 20087 20088 20089 20090 20091 20092 20093 20094 20095 20096 20097 20098 20099 20100 20101 20102 20103 20104 20105 20106 20107 20108 20109 20110 20111 20112 20113 20114 20115 20116 20117 20118 20119 20120 20121 20122 20123 20124 20125 20126 20127 20128 20129 20130 20131 20132 20133 20134 20135 20136 20137 20138 20139 20140 20141 20142 20143 20144 20145 20146 20147 20148 20149 20150 |
sCtx.cColSep = ',';
sCtx.cRowSep = '\n';
xRead = csv_read_one_field;
useOutputMode = 0;
}else{
utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
showHelp(p->out, "import");
goto meta_command_exit;
}
}
if( zTable==0 ){
utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
zFile==0 ? "FILE" : "TABLE");
showHelp(p->out, "import");
goto meta_command_exit;
}
seenInterrupt = 0;
open_db(p, 0);
if( useOutputMode ){
/* If neither the --csv or --ascii options are specified, then set
** the column and row separator characters from the output mode. */
nSep = strlen30(p->colSeparator);
if( nSep==0 ){
raw_printf(stderr,
"Error: non-null column separator required for import\n");
goto meta_command_exit;
}
if( nSep>1 ){
raw_printf(stderr,
"Error: multi-character column separators not allowed"
" for import\n");
goto meta_command_exit;
}
nSep = strlen30(p->rowSeparator);
if( nSep==0 ){
raw_printf(stderr,
"Error: non-null row separator required for import\n");
goto meta_command_exit;
}
if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
/* When importing CSV (only), if the row separator is set to the
** default output row separator, change it to the default input
** row separator. This avoids having to maintain different input
** and output row separators. */
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
nSep = strlen30(p->rowSeparator);
}
if( nSep>1 ){
raw_printf(stderr, "Error: multi-character row separators not allowed"
" for import\n");
goto meta_command_exit;
}
sCtx.cColSep = p->colSeparator[0];
sCtx.cRowSep = p->rowSeparator[0];
}
sCtx.zFile = zFile;
sCtx.nLine = 1;
if( sCtx.zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
raw_printf(stderr, "Error: pipes are not supported in this OS\n");
goto meta_command_exit;
#else
sCtx.in = popen(sCtx.zFile+1, "r");
sCtx.zFile = "<pipe>";
sCtx.xCloser = pclose;
#endif
}else{
sCtx.in = fopen(sCtx.zFile, "rb");
sCtx.xCloser = fclose;
}
if( sCtx.in==0 ){
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
goto meta_command_exit;
}
if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
char zSep[2];
zSep[1] = 0;
zSep[0] = sCtx.cColSep;
utf8_printf(p->out, "Column separator ");
output_c_string(p->out, zSep);
utf8_printf(p->out, ", row separator ");
zSep[0] = sCtx.cRowSep;
output_c_string(p->out, zSep);
utf8_printf(p->out, "\n");
}
sCtx.z = sqlite3_malloc64(120);
if( sCtx.z==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
}
/* Below, resources must be freed before exit. */
while( (nSkip--)>0 ){
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
}
if( zSchema!=0 ){
zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
|
| ︙ | ︙ | |||
20210 20211 20212 20213 20214 20215 20216 20217 20218 20219 20220 20221 20222 20223 |
if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
if( eVerbose>0 ){
utf8_printf(p->out,
"Added %d rows with %d errors using %d lines of input\n",
sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
}
}else
#ifndef SQLITE_UNTESTABLE
if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
char *zSql;
char *zCollist = 0;
sqlite3_stmt *pStmt;
int tnum = 0;
| > | 20286 20287 20288 20289 20290 20291 20292 20293 20294 20295 20296 20297 20298 20299 20300 |
if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
if( eVerbose>0 ){
utf8_printf(p->out,
"Added %d rows with %d errors using %d lines of input\n",
sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
}
}else
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
#ifndef SQLITE_UNTESTABLE
if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
char *zSql;
char *zCollist = 0;
sqlite3_stmt *pStmt;
int tnum = 0;
|
| ︙ | ︙ | |||
20399 20400 20401 20402 20403 20404 20405 |
}else
if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
open_db(p, 0);
lintDotCommand(p, azArg, nArg);
}else
| | | 20476 20477 20478 20479 20480 20481 20482 20483 20484 20485 20486 20487 20488 20489 20490 |
}else
if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
open_db(p, 0);
lintDotCommand(p, azArg, nArg);
}else
#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_WASM_MODE)
if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
const char *zFile, *zProc;
char *zErrMsg = 0;
failIfSafeMode(p, "cannot run .load in safe mode");
if( nArg<2 ){
raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
rc = 1;
|
| ︙ | ︙ | |||
20421 20422 20423 20424 20425 20426 20427 20428 20429 20430 20431 20432 20433 20434 20435 20436 20437 20438 20439 20440 20441 20442 20443 20444 20445 |
utf8_printf(stderr, "Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
rc = 1;
}
}else
#endif
if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
failIfSafeMode(p, "cannot run .log in safe mode");
if( nArg!=2 ){
raw_printf(stderr, "Usage: .log FILENAME\n");
rc = 1;
}else{
const char *zFile = azArg[1];
output_file_close(p->pLog);
p->pLog = output_file_open(zFile, 0);
}
}else
if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
const char *zMode = 0;
const char *zTabname = 0;
int i, n2;
ColModeOpts cmOpts = ColModeOpts_default;
for(i=1; i<nArg; i++){
| > > | 20498 20499 20500 20501 20502 20503 20504 20505 20506 20507 20508 20509 20510 20511 20512 20513 20514 20515 20516 20517 20518 20519 20520 20521 20522 20523 20524 |
utf8_printf(stderr, "Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
rc = 1;
}
}else
#endif
#ifndef SQLITE_SHELL_WASM_MODE
if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
failIfSafeMode(p, "cannot run .log in safe mode");
if( nArg!=2 ){
raw_printf(stderr, "Usage: .log FILENAME\n");
rc = 1;
}else{
const char *zFile = azArg[1];
output_file_close(p->pLog);
p->pLog = output_file_open(zFile, 0);
}
}else
#endif
if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
const char *zMode = 0;
const char *zTabname = 0;
int i, n2;
ColModeOpts cmOpts = ColModeOpts_default;
for(i=1; i<nArg; i++){
|
| ︙ | ︙ | |||
20556 20557 20558 20559 20560 20561 20562 20563 20564 20565 20566 20567 20568 20569 20570 20571 20572 20573 20574 20575 20576 20577 20578 20579 20580 20581 20582 20583 |
"ascii box column csv html insert json line list markdown "
"qbox quote table tabs tcl\n");
rc = 1;
}
p->cMode = p->mode;
}else
if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
if( nArg!=2 ){
raw_printf(stderr, "Usage: .nonce NONCE\n");
rc = 1;
}else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
p->lineno, azArg[1]);
exit(1);
}else{
p->bSafeMode = 0;
return 0; /* Return immediately to bypass the safe mode reset
** at the end of this procedure */
}
}else
if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
if( nArg==2 ){
sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
"%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
}else{
raw_printf(stderr, "Usage: .nullvalue STRING\n");
| > > | 20635 20636 20637 20638 20639 20640 20641 20642 20643 20644 20645 20646 20647 20648 20649 20650 20651 20652 20653 20654 20655 20656 20657 20658 20659 20660 20661 20662 20663 20664 |
"ascii box column csv html insert json line list markdown "
"qbox quote table tabs tcl\n");
rc = 1;
}
p->cMode = p->mode;
}else
#ifndef SQLITE_SHELL_WASM_MODE
if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
if( nArg!=2 ){
raw_printf(stderr, "Usage: .nonce NONCE\n");
rc = 1;
}else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
p->lineno, azArg[1]);
exit(1);
}else{
p->bSafeMode = 0;
return 0; /* Return immediately to bypass the safe mode reset
** at the end of this procedure */
}
}else
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
if( nArg==2 ){
sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
"%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
}else{
raw_printf(stderr, "Usage: .nullvalue STRING\n");
|
| ︙ | ︙ | |||
20591 20592 20593 20594 20595 20596 20597 20598 20599 20600 20601 20602 20603 20604 20605 20606 20607 20608 20609 20610 20611 20612 20613 20614 20615 20616 20617 |
int iName = 1; /* Index in azArg[] of the filename */
int newFlag = 0; /* True to delete file before opening */
int openMode = SHELL_OPEN_UNSPEC;
/* Check for command-line arguments */
for(iName=1; iName<nArg; iName++){
const char *z = azArg[iName];
if( optionMatch(z,"new") ){
newFlag = 1;
#ifdef SQLITE_HAVE_ZLIB
}else if( optionMatch(z, "zip") ){
openMode = SHELL_OPEN_ZIPFILE;
#endif
}else if( optionMatch(z, "append") ){
openMode = SHELL_OPEN_APPENDVFS;
}else if( optionMatch(z, "readonly") ){
openMode = SHELL_OPEN_READONLY;
}else if( optionMatch(z, "nofollow") ){
p->openFlags |= SQLITE_OPEN_NOFOLLOW;
#ifndef SQLITE_OMIT_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){
openMode = SHELL_OPEN_DESERIALIZE;
}else if( optionMatch(z, "hexdb") ){
openMode = SHELL_OPEN_HEXDB;
}else if( optionMatch(z, "maxsize") && iName+1<nArg ){
p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_OMIT_DESERIALIZE */
| > > > | | 20672 20673 20674 20675 20676 20677 20678 20679 20680 20681 20682 20683 20684 20685 20686 20687 20688 20689 20690 20691 20692 20693 20694 20695 20696 20697 20698 20699 20700 20701 20702 20703 20704 20705 20706 20707 20708 20709 |
int iName = 1; /* Index in azArg[] of the filename */
int newFlag = 0; /* True to delete file before opening */
int openMode = SHELL_OPEN_UNSPEC;
/* Check for command-line arguments */
for(iName=1; iName<nArg; iName++){
const char *z = azArg[iName];
#ifndef SQLITE_SHELL_WASM_MODE
if( optionMatch(z,"new") ){
newFlag = 1;
#ifdef SQLITE_HAVE_ZLIB
}else if( optionMatch(z, "zip") ){
openMode = SHELL_OPEN_ZIPFILE;
#endif
}else if( optionMatch(z, "append") ){
openMode = SHELL_OPEN_APPENDVFS;
}else if( optionMatch(z, "readonly") ){
openMode = SHELL_OPEN_READONLY;
}else if( optionMatch(z, "nofollow") ){
p->openFlags |= SQLITE_OPEN_NOFOLLOW;
#ifndef SQLITE_OMIT_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){
openMode = SHELL_OPEN_DESERIALIZE;
}else if( optionMatch(z, "hexdb") ){
openMode = SHELL_OPEN_HEXDB;
}else if( optionMatch(z, "maxsize") && iName+1<nArg ){
p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_OMIT_DESERIALIZE */
}else
#endif /* !SQLITE_SHELL_WASM_MODE */
if( z[0]=='-' ){
utf8_printf(stderr, "unknown option: %s\n", z);
rc = 1;
goto meta_command_exit;
}else if( zFN ){
utf8_printf(stderr, "extra argument: \"%s\"\n", z);
rc = 1;
goto meta_command_exit;
|
| ︙ | ︙ | |||
20638 20639 20640 20641 20642 20643 20644 20645 20646 20647 20648 20649 20650 20651 20652 20653 20654 20655 20656 20657 20658 |
p->openMode = openMode;
p->openFlags = 0;
p->szMax = 0;
/* If a filename is specified, try to open it first */
if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN);
if( p->bSafeMode
&& p->openMode!=SHELL_OPEN_HEXDB
&& zFN
&& strcmp(zFN,":memory:")!=0
){
failIfSafeMode(p, "cannot open disk-based database files in safe mode");
}
if( zFN ){
zNewFilename = sqlite3_mprintf("%s", zFN);
shell_check_oom(zNewFilename);
}else{
zNewFilename = 0;
}
p->pAuxDb->zDbFilename = zNewFilename;
| > > > > | 20722 20723 20724 20725 20726 20727 20728 20729 20730 20731 20732 20733 20734 20735 20736 20737 20738 20739 20740 20741 20742 20743 20744 20745 20746 |
p->openMode = openMode;
p->openFlags = 0;
p->szMax = 0;
/* If a filename is specified, try to open it first */
if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN);
#ifndef SQLITE_SHELL_WASM_MODE
if( p->bSafeMode
&& p->openMode!=SHELL_OPEN_HEXDB
&& zFN
&& strcmp(zFN,":memory:")!=0
){
failIfSafeMode(p, "cannot open disk-based database files in safe mode");
}
#else
/* WASM mode has its own sandboxed pseudo-filesystem. */
#endif
if( zFN ){
zNewFilename = sqlite3_mprintf("%s", zFN);
shell_check_oom(zNewFilename);
}else{
zNewFilename = 0;
}
p->pAuxDb->zDbFilename = zNewFilename;
|
| ︙ | ︙ | |||
20667 20668 20669 20670 20671 20672 20673 20674 20675 20676 20677 20678 20679 20680 |
if( p->db==0 ){
/* As a fall-back open a TEMP database */
p->pAuxDb->zDbFilename = 0;
open_db(p, 0);
}
}else
if( (c=='o'
&& (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
|| (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
){
char *zFile = 0;
int bTxtMode = 0;
int i;
| > | 20755 20756 20757 20758 20759 20760 20761 20762 20763 20764 20765 20766 20767 20768 20769 |
if( p->db==0 ){
/* As a fall-back open a TEMP database */
p->pAuxDb->zDbFilename = 0;
open_db(p, 0);
}
}else
#ifndef SQLITE_SHELL_WASM_MODE
if( (c=='o'
&& (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
|| (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
){
char *zFile = 0;
int bTxtMode = 0;
int i;
|
| ︙ | ︙ | |||
20782 20783 20784 20785 20786 20787 20788 20789 20790 20791 20792 20793 20794 20795 |
} else {
if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
}
}
sqlite3_free(zFile);
}else
if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
open_db(p,0);
if( nArg<=1 ) goto parameter_syntax_error;
/* .parameter clear
** Clear all bind parameters by dropping the TEMP table that holds them.
| > | 20871 20872 20873 20874 20875 20876 20877 20878 20879 20880 20881 20882 20883 20884 20885 |
} else {
if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
}
}
sqlite3_free(zFile);
}else
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
open_db(p,0);
if( nArg<=1 ) goto parameter_syntax_error;
/* .parameter clear
** Clear all bind parameters by dropping the TEMP table that holds them.
|
| ︙ | ︙ | |||
20951 20952 20953 20954 20955 20956 20957 20958 20959 20960 20961 20962 20963 20964 20965 20966 20967 20968 |
strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
}
if( nArg >= 3) {
strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
}
}else
if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
rc = 2;
}else
if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
FILE *inSaved = p->in;
int savedLineno = p->lineno;
failIfSafeMode(p, "cannot run .read in safe mode");
if( nArg!=2 ){
raw_printf(stderr, "Usage: .read FILE\n");
rc = 1;
| > > > | 21041 21042 21043 21044 21045 21046 21047 21048 21049 21050 21051 21052 21053 21054 21055 21056 21057 21058 21059 21060 21061 |
strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
}
if( nArg >= 3) {
strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
}
}else
#ifndef SQLITE_SHELL_WASM_MODE
if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
rc = 2;
}else
#endif
#ifndef SQLITE_SHELL_WASM_MODE
if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
FILE *inSaved = p->in;
int savedLineno = p->lineno;
failIfSafeMode(p, "cannot run .read in safe mode");
if( nArg!=2 ){
raw_printf(stderr, "Usage: .read FILE\n");
rc = 1;
|
| ︙ | ︙ | |||
20989 20990 20991 20992 20993 20994 20995 20996 20997 20998 20999 21000 21001 21002 21003 |
}else{
rc = process_input(p);
fclose(p->in);
}
p->in = inSaved;
p->lineno = savedLineno;
}else
if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
const char *zSrcFile;
const char *zDb;
sqlite3 *pSrc;
sqlite3_backup *pBackup;
int nTimeout = 0;
| > > | 21082 21083 21084 21085 21086 21087 21088 21089 21090 21091 21092 21093 21094 21095 21096 21097 21098 |
}else{
rc = process_input(p);
fclose(p->in);
}
p->in = inSaved;
p->lineno = savedLineno;
}else
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
#ifndef SQLITE_SHELL_WASM_MODE
if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
const char *zSrcFile;
const char *zDb;
sqlite3 *pSrc;
sqlite3_backup *pBackup;
int nTimeout = 0;
|
| ︙ | ︙ | |||
21041 21042 21043 21044 21045 21046 21047 21048 21049 21050 21051 21052 21053 21054 |
rc = 1;
}else{
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
rc = 1;
}
close_db(pSrc);
}else
if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
if( nArg==2 ){
p->scanstatsOn = (u8)booleanValue(azArg[1]);
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
#endif
| > | 21136 21137 21138 21139 21140 21141 21142 21143 21144 21145 21146 21147 21148 21149 21150 |
rc = 1;
}else{
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
rc = 1;
}
close_db(pSrc);
}else
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
if( nArg==2 ){
p->scanstatsOn = (u8)booleanValue(azArg[1]);
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
#endif
|
| ︙ | ︙ | |||
21197 21198 21199 21200 21201 21202 21203 |
raw_printf(stderr,"Error: querying schema information\n");
rc = 1;
}else{
rc = 0;
}
}else
| | > > | 21293 21294 21295 21296 21297 21298 21299 21300 21301 21302 21303 21304 21305 21306 21307 21308 21309 |
raw_printf(stderr,"Error: querying schema information\n");
rc = 1;
}else{
rc = 0;
}
}else
if( (c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0)
|| (c=='t' && n==9 && strncmp(azArg[0], "treetrace", n)==0)
){
unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
}else
#if defined(SQLITE_ENABLE_SESSION)
if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
struct AuxDb *pAuxDb = p->pAuxDb;
|
| ︙ | ︙ | |||
21664 21665 21666 21667 21668 21669 21670 |
utf8_printf(p->out, "%s\n", zSql);
}else{
shell_exec(p, zSql, 0);
}
sqlite3_free(zSql);
}else
| | | | | 21762 21763 21764 21765 21766 21767 21768 21769 21770 21771 21772 21773 21774 21775 21776 21777 21778 21779 21780 21781 21782 21783 21784 21785 21786 21787 21788 21789 21790 21791 21792 21793 21794 21795 21796 21797 21798 21799 21800 21801 21802 21803 21804 21805 21806 21807 21808 21809 |
utf8_printf(p->out, "%s\n", zSql);
}else{
shell_exec(p, zSql, 0);
}
sqlite3_free(zSql);
}else
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_WASM_MODE)
if( c=='s'
&& (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
){
char *zCmd;
int i, x;
failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
if( nArg<2 ){
raw_printf(stderr, "Usage: .system COMMAND\n");
rc = 1;
goto meta_command_exit;
}
zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
for(i=2; i<nArg && zCmd!=0; i++){
zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
zCmd, azArg[i]);
}
x = zCmd!=0 ? system(zCmd) : 1;
sqlite3_free(zCmd);
if( x ) raw_printf(stderr, "System command returns %d\n", x);
}else
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_WASM_MODE) */
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
static const char *azBool[] = { "off", "on", "trigger", "full"};
const char *zOut;
int i;
if( nArg!=1 ){
raw_printf(stderr, "Usage: .show\n");
rc = 1;
goto meta_command_exit;
}
utf8_printf(p->out, "%12.12s: %s\n","echo",
azBool[ShellHasFlag(p, SHFLG_Echo)]);
utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
utf8_printf(p->out, "%12.12s: %s\n","explain",
p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
if( p->mode==MODE_Column
|| (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
){
|
| ︙ | ︙ | |||
21865 21866 21867 21868 21869 21870 21871 21872 21873 21874 21875 21876 21877 21878 21879 21880 21881 21882 21883 21884 21885 21886 21887 21888 21889 21890 21891 |
}
}
for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
sqlite3_free(azResult);
}else
/* Begin redirecting output to the file "testcase-out.txt" */
if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
output_reset(p);
p->out = output_file_open("testcase-out.txt", 0);
if( p->out==0 ){
raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
}
if( nArg>=2 ){
sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
}else{
sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
}
}else
#ifndef SQLITE_UNTESTABLE
if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
static const struct {
const char *zCtrlName; /* Name of a test-control option */
int ctrlCode; /* Integer code for that option */
int unSafe; /* Not valid for --safe mode */
| > > | 21963 21964 21965 21966 21967 21968 21969 21970 21971 21972 21973 21974 21975 21976 21977 21978 21979 21980 21981 21982 21983 21984 21985 21986 21987 21988 21989 21990 21991 |
}
}
for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
sqlite3_free(azResult);
}else
#ifndef SQLITE_SHELL_WASM_MODE
/* Begin redirecting output to the file "testcase-out.txt" */
if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
output_reset(p);
p->out = output_file_open("testcase-out.txt", 0);
if( p->out==0 ){
raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
}
if( nArg>=2 ){
sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
}else{
sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
}
}else
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
#ifndef SQLITE_UNTESTABLE
if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
static const struct {
const char *zCtrlName; /* Name of a test-control option */
int ctrlCode; /* Integer code for that option */
int unSafe; /* Not valid for --safe mode */
|
| ︙ | ︙ | |||
22447 22448 22449 22450 22451 22452 22453 |
continue;
}
/* fall thru */
case ']':
cWait = 0;
qss = QSS_SETV(qss, 0);
goto PlainScan;
| | | | 22547 22548 22549 22550 22551 22552 22553 22554 22555 22556 22557 22558 22559 22560 22561 22562 22563 22564 22565 22566 22567 22568 22569 22570 22571 22572 22573 22574 22575 22576 22577 22578 22579 22580 22581 22582 |
continue;
}
/* fall thru */
case ']':
cWait = 0;
qss = QSS_SETV(qss, 0);
goto PlainScan;
default: assert(0);
}
}
}
}
return qss;
}
/*
** Return TRUE if the line typed in is an SQL command terminator other
** than a semi-colon. The SQL Server style "go" command is understood
** as is the Oracle "/".
*/
static int line_is_command_terminator(char *zLine){
while( IsSpace(zLine[0]) ){ zLine++; };
if( zLine[0]=='/' )
zLine += 1; /* Oracle */
else if ( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' )
zLine += 2; /* SQL Server */
else
return 0;
return quickscan(zLine, QSS_Start)==QSS_Start;
}
/*
** We need a default sqlite3_complete() implementation to use in case
** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
** any arbitrary text is a complete SQL statement. This is not very
** user-friendly, but it does seem to work.
|
| ︙ | ︙ | |||
22545 22546 22547 22548 22549 22550 22551 22552 22553 22554 22555 22556 22557 22558 |
"changes: %lld total_changes: %lld",
sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
raw_printf(p->out, "%s\n", zLineBuf);
}
return 0;
}
/*
** Read input from *in and process it. If *in==0 then input
** is interactive - the user is typing it it. Otherwise, input
** is coming from a file or device. A prompt is issued and history
** is saved only if input is interactive. An interrupt signal will
** cause this routine to exit immediately, unless input is interactive.
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 22645 22646 22647 22648 22649 22650 22651 22652 22653 22654 22655 22656 22657 22658 22659 22660 22661 22662 22663 22664 22665 22666 22667 22668 22669 22670 22671 22672 22673 22674 22675 22676 22677 22678 22679 22680 22681 22682 22683 22684 22685 22686 22687 22688 22689 22690 22691 22692 22693 22694 |
"changes: %lld total_changes: %lld",
sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
raw_printf(p->out, "%s\n", zLineBuf);
}
return 0;
}
static void echo_group_input(ShellState *p, const char *zDo){
if( ShellHasFlag(p, SHFLG_Echo) ) utf8_printf(p->out, "%s\n", zDo);
}
#ifdef SQLITE_SHELL_WASM_MODE
/*
** Alternate one_input_line() impl for wasm mode. This is not in the primary impl
** because we need the global shellState and cannot access it from that function
** without moving lots of code around (creating a larger/messier diff).
*/
static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
/* Parse the next line from shellState.wasm.zInput. */
const char *zBegin = shellState.wasm.zPos;
const char *z = zBegin;
char *zLine = 0;
int nZ = 0;
UNUSED_PARAMETER(in);
UNUSED_PARAMETER(isContinuation);
if(!z || !*z){
return 0;
}
while(*z && isspace(*z)) ++z;
zBegin = z;
for(; *z && '\n'!=*z; ++nZ, ++z){}
if(nZ>0 && '\r'==zBegin[nZ-1]){
--nZ;
}
shellState.wasm.zPos = z;
zLine = realloc(zPrior, nZ+1);
shell_check_oom(zLine);
memcpy(zLine, zBegin, (size_t)nZ);
zLine[nZ] = 0;
return zLine;
}
#endif /* SQLITE_SHELL_WASM_MODE */
/*
** Read input from *in and process it. If *in==0 then input
** is interactive - the user is typing it it. Otherwise, input
** is coming from a file or device. A prompt is issued and history
** is saved only if input is interactive. An interrupt signal will
** cause this routine to exit immediately, unless input is interactive.
|
| ︙ | ︙ | |||
22594 22595 22596 22597 22598 22599 22600 |
if( QSS_INPLAIN(qss)
&& line_is_command_terminator(zLine)
&& line_is_complete(zSql, nSql) ){
memcpy(zLine,";",2);
}
qss = quickscan(zLine, qss);
if( QSS_PLAINWHITE(qss) && nSql==0 ){
| < < > | | 22730 22731 22732 22733 22734 22735 22736 22737 22738 22739 22740 22741 22742 22743 22744 22745 22746 22747 22748 22749 22750 |
if( QSS_INPLAIN(qss)
&& line_is_command_terminator(zLine)
&& line_is_complete(zSql, nSql) ){
memcpy(zLine,";",2);
}
qss = quickscan(zLine, qss);
if( QSS_PLAINWHITE(qss) && nSql==0 ){
/* Just swallow single-line whitespace */
echo_group_input(p, zLine);
qss = QSS_Start;
continue;
}
if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
echo_group_input(p, zLine);
if( zLine[0]=='.' ){
rc = do_meta_command(zLine, p);
if( rc==2 ){ /* exit requested */
break;
}else if( rc ){
errCnt++;
}
|
| ︙ | ︙ | |||
22634 22635 22636 22637 22638 22639 22640 22641 22642 22643 22644 22645 22646 22647 22648 22649 22650 22651 |
nSql = nLine-i;
}else{
zSql[nSql++] = '\n';
memcpy(zSql+nSql, zLine, nLine+1);
nSql += nLine;
}
if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
errCnt += runOneSqlLine(p, zSql, p->in, startline);
nSql = 0;
if( p->outCount ){
output_reset(p);
p->outCount = 0;
}else{
clearTempFile(p);
}
p->bSafeMode = p->bSafeModePersist;
qss = QSS_Start;
}else if( nSql && QSS_PLAINWHITE(qss) ){
| > | > | 22769 22770 22771 22772 22773 22774 22775 22776 22777 22778 22779 22780 22781 22782 22783 22784 22785 22786 22787 22788 22789 22790 22791 22792 22793 22794 22795 22796 22797 22798 22799 22800 22801 22802 |
nSql = nLine-i;
}else{
zSql[nSql++] = '\n';
memcpy(zSql+nSql, zLine, nLine+1);
nSql += nLine;
}
if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
echo_group_input(p, zSql);
errCnt += runOneSqlLine(p, zSql, p->in, startline);
nSql = 0;
if( p->outCount ){
output_reset(p);
p->outCount = 0;
}else{
clearTempFile(p);
}
p->bSafeMode = p->bSafeModePersist;
qss = QSS_Start;
}else if( nSql && QSS_PLAINWHITE(qss) ){
echo_group_input(p, zSql);
nSql = 0;
qss = QSS_Start;
}
}
if( nSql ){
/* This may be incomplete. Let the SQL parser deal with that. */
echo_group_input(p, zSql);
errCnt += runOneSqlLine(p, zSql, p->in, startline);
}
free(zSql);
free(zLine);
--p->inputNesting;
return errCnt>0;
}
|
| ︙ | ︙ | |||
22790 22791 22792 22793 22794 22795 22796 | " -box set output mode to 'box'\n" " -column set output mode to 'column'\n" " -cmd COMMAND run \"COMMAND\" before reading stdin\n" " -csv set output mode to 'csv'\n" #if !defined(SQLITE_OMIT_DESERIALIZE) " -deserialize open the database using sqlite3_deserialize()\n" #endif | | | 22927 22928 22929 22930 22931 22932 22933 22934 22935 22936 22937 22938 22939 22940 22941 | " -box set output mode to 'box'\n" " -column set output mode to 'column'\n" " -cmd COMMAND run \"COMMAND\" before reading stdin\n" " -csv set output mode to 'csv'\n" #if !defined(SQLITE_OMIT_DESERIALIZE) " -deserialize open the database using sqlite3_deserialize()\n" #endif " -echo print inputs before execution\n" " -init FILENAME read/process named file\n" " -[no]header turn headers on or off\n" #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) " -heap SIZE Size of heap for memsys3 or memsys5\n" #endif " -help show this message\n" " -html set output mode to HTML\n" |
| ︙ | ︙ | |||
22925 22926 22927 22928 22929 22930 22931 22932 22933 22934 22935 22936 22937 22938 22939 22940 22941 22942 22943 22944 22945 22946 22947 22948 22949 22950 22951 22952 22953 22954 22955 22956 22957 22958 22959 22960 22961 22962 22963 22964 |
# if (defined(_WIN32) || defined(WIN32)) \
&& (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
# define SQLITE_SHELL_IS_UTF8 (0)
# else
# define SQLITE_SHELL_IS_UTF8 (1)
# endif
#endif
#if SQLITE_SHELL_IS_UTF8
int SQLITE_CDECL main(int argc, char **argv){
#else
int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
char **argv;
#endif
char *zErrMsg = 0;
ShellState data;
const char *zInitFile = 0;
int i;
int rc = 0;
int warnInmemoryDb = 0;
int readStdin = 1;
int nCmd = 0;
char **azCmd = 0;
const char *zVfs = 0; /* Value of -vfs command-line option */
#if !SQLITE_SHELL_IS_UTF8
char **argvToFree = 0;
int argcToFree = 0;
#endif
setBinaryMode(stdin, 0);
setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
stdin_is_interactive = isatty(0);
stdout_is_console = isatty(1);
#if !defined(_WIN32_WCE)
if( getenv("SQLITE_DEBUG_BREAK") ){
if( isatty(0) && isatty(2) ){
fprintf(stderr,
"attach debugger to process %d and press any key to continue.\n",
GETPID());
| > > > > > > > > > > > > > > > > | 23062 23063 23064 23065 23066 23067 23068 23069 23070 23071 23072 23073 23074 23075 23076 23077 23078 23079 23080 23081 23082 23083 23084 23085 23086 23087 23088 23089 23090 23091 23092 23093 23094 23095 23096 23097 23098 23099 23100 23101 23102 23103 23104 23105 23106 23107 23108 23109 23110 23111 23112 23113 23114 23115 23116 23117 |
# if (defined(_WIN32) || defined(WIN32)) \
&& (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
# define SQLITE_SHELL_IS_UTF8 (0)
# else
# define SQLITE_SHELL_IS_UTF8 (1)
# endif
#endif
#ifdef SQLITE_SHELL_WASM_MODE
# define main fiddle_main
#endif
#if SQLITE_SHELL_IS_UTF8
int SQLITE_CDECL main(int argc, char **argv){
#else
int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
char **argv;
#endif
#ifdef SQLITE_DEBUG
sqlite3_uint64 mem_main_enter = sqlite3_memory_used();
#endif
char *zErrMsg = 0;
#ifdef SQLITE_SHELL_WASM_MODE
# define data shellState
#else
ShellState data;
#endif
const char *zInitFile = 0;
int i;
int rc = 0;
int warnInmemoryDb = 0;
int readStdin = 1;
int nCmd = 0;
char **azCmd = 0;
const char *zVfs = 0; /* Value of -vfs command-line option */
#if !SQLITE_SHELL_IS_UTF8
char **argvToFree = 0;
int argcToFree = 0;
#endif
setBinaryMode(stdin, 0);
setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
#ifdef SQLITE_SHELL_WASM_MODE
stdin_is_interactive = 0;
stdout_is_console = 1;
#else
stdin_is_interactive = isatty(0);
stdout_is_console = isatty(1);
#endif
#if !defined(_WIN32_WCE)
if( getenv("SQLITE_DEBUG_BREAK") ){
if( isatty(0) && isatty(2) ){
fprintf(stderr,
"attach debugger to process %d and press any key to continue.\n",
GETPID());
|
| ︙ | ︙ | |||
23206 23207 23208 23209 23210 23211 23212 23213 23214 23215 23216 23217 23218 23219 23220 |
warnInmemoryDb = argc==1;
#else
utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
return 1;
#endif
}
data.out = stdout;
sqlite3_appendvfs_init(0,0,0);
/* Go ahead and open the database file if it already exists. If the
** file does not exist, delay opening it. This prevents empty database
** files from being created if a user mistypes the database name argument
** to the sqlite command-line tool.
*/
if( access(data.pAuxDb->zDbFilename, 0)==0 ){
| > > | 23359 23360 23361 23362 23363 23364 23365 23366 23367 23368 23369 23370 23371 23372 23373 23374 23375 |
warnInmemoryDb = argc==1;
#else
utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
return 1;
#endif
}
data.out = stdout;
#ifndef SQLITE_SHELL_WASM_MODE
sqlite3_appendvfs_init(0,0,0);
#endif
/* Go ahead and open the database file if it already exists. If the
** file does not exist, delay opening it. This prevents empty database
** files from being created if a user mistypes the database name argument
** to the sqlite command-line tool.
*/
if( access(data.pAuxDb->zDbFilename, 0)==0 ){
|
| ︙ | ︙ | |||
23472 23473 23474 23475 23476 23477 23478 23479 23480 23481 23482 23483 23484 23485 |
free(zHistory);
}
}else{
data.in = stdin;
rc = process_input(&data);
}
}
free(azCmd);
set_table_name(&data, 0);
if( data.db ){
session_close_all(&data, -1);
close_db(data.db);
}
for(i=0; i<ArraySize(data.aAuxDb); i++){
| > > > | 23627 23628 23629 23630 23631 23632 23633 23634 23635 23636 23637 23638 23639 23640 23641 23642 23643 |
free(zHistory);
}
}else{
data.in = stdin;
rc = process_input(&data);
}
}
#ifndef SQLITE_SHELL_WASM_MODE
/* In WASM mode we have to leave the db state in place so that
** client code can "push" SQL into it after this call returns. */
free(azCmd);
set_table_name(&data, 0);
if( data.db ){
session_close_all(&data, -1);
close_db(data.db);
}
for(i=0; i<ArraySize(data.aAuxDb); i++){
|
| ︙ | ︙ | |||
23498 23499 23500 23501 23502 23503 23504 23505 23506 | free(argvToFree); #endif free(data.colWidth); free(data.zNonce); /* Clear the global data structure so that valgrind will detect memory ** leaks */ memset(&data, 0, sizeof(data)); return rc; } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 23656 23657 23658 23659 23660 23661 23662 23663 23664 23665 23666 23667 23668 23669 23670 23671 23672 23673 23674 23675 23676 23677 23678 23679 23680 23681 23682 23683 23684 23685 23686 23687 23688 23689 23690 23691 23692 23693 23694 23695 23696 23697 23698 23699 23700 23701 23702 23703 23704 23705 23706 23707 23708 23709 23710 23711 23712 23713 23714 23715 23716 23717 23718 23719 23720 23721 23722 23723 23724 23725 23726 23727 23728 23729 23730 23731 23732 23733 23734 23735 23736 23737 23738 23739 23740 23741 23742 23743 23744 23745 23746 23747 23748 23749 23750 23751 23752 23753 23754 23755 23756 23757 23758 23759 23760 23761 23762 23763 23764 23765 23766 23767 23768 23769 23770 23771 23772 23773 23774 23775 23776 23777 23778 23779 23780 23781 23782 23783 23784 23785 23786 23787 23788 23789 23790 23791 23792 23793 23794 23795 |
free(argvToFree);
#endif
free(data.colWidth);
free(data.zNonce);
/* Clear the global data structure so that valgrind will detect memory
** leaks */
memset(&data, 0, sizeof(data));
#ifdef SQLITE_DEBUG
if( sqlite3_memory_used()>mem_main_enter ){
utf8_printf(stderr, "Memory leaked: %u bytes\n",
(unsigned int)(sqlite3_memory_used()-mem_main_enter));
}
#endif
#endif /* !SQLITE_SHELL_WASM_MODE */
return rc;
}
#ifdef SQLITE_SHELL_WASM_MODE
/* Only for emcc experimentation purposes. */
int fiddle_experiment(int a,int b){
return a + b;
}
/* Only for emcc experimentation purposes.
Define this function in JS using:
emcc ... --js-library somefile.js
containing:
mergeInto(LibraryManager.library, {
my_foo: function(){
console.debug("my_foo()",arguments);
}
});
*/
/*extern void my_foo(sqlite3 *);*/
/* Only for emcc experimentation purposes. */
sqlite3 * fiddle_the_db(){
printf("fiddle_the_db(%p)\n", (const void*)globalDb);
/*my_foo(globalDb);*/
return globalDb;
}
/* Only for emcc experimentation purposes. */
sqlite3 * fiddle_db_arg(sqlite3 *arg){
printf("fiddle_db_arg(%p)\n", (const void*)arg);
return arg;
}
/*
** Intended to be called via a SharedWorker() while a separate
** SharedWorker() (which manages the wasm module) is performing work
** which should be interrupted. Unfortunately, SharedWorker is not
** portable enough to make real use of.
*/
void fiddle_interrupt(void){
if(globalDb) sqlite3_interrupt(globalDb);
}
/*
** Returns the filename of the given db name, assuming "main" if
** zDbName is NULL. Returns NULL if globalDb is not opened.
*/
const char * fiddle_db_filename(const char * zDbName){
return globalDb
? sqlite3_db_filename(globalDb, zDbName ? zDbName : "main")
: NULL;
}
/*
** Closes, unlinks, and reopens the db using its current filename (or
** the default if the db is currently closed). It is assumed, for
** purposes of the fiddle build, that the file is in a transient
** virtual filesystem within the browser.
*/
void fiddle_reset_db(void){
char *zFilename = 0;
if(0==globalDb){
shellState.pAuxDb->zDbFilename = "/fiddle.sqlite3";
}else{
zFilename =
sqlite3_mprintf("%s", sqlite3_db_filename(globalDb, "main"));
shell_check_oom(zFilename);
close_db(globalDb);
shellDeleteFile(zFilename);
shellState.db = 0;
shellState.pAuxDb->zDbFilename = zFilename;
}
open_db(&shellState, 0);
sqlite3_free(zFilename);
}
/*
** Trivial exportable function for emscripten. Needs to be exported using:
**
** emcc ..flags... -sEXPORTED_FUNCTIONS=_fiddle_exec -sEXPORTED_RUNTIME_METHODS=ccall,cwrap
**
** (Note the underscore before the function name.) It processes zSql
** as if it were input to the sqlite3 shell and redirects all output
** to the wasm binding.
*/
void fiddle_exec(const char * zSql){
static int once = 0;
int rc = 0;
if(!once){
/* Simulate an argv array for main() */
static char * argv[] = {"fiddle",
"-bail",
"-safe"};
rc = fiddle_main((int)(sizeof(argv)/sizeof(argv[0])), argv);
once = rc ? -1 : 1;
memset(&shellState.wasm, 0, sizeof(shellState.wasm));
printf(
"SQLite version %s %.19s\n" /*extra-version-info*/,
sqlite3_libversion(), sqlite3_sourceid()
);
puts("WASM shell");
puts("Enter \".help\" for usage hints.");
if(once>0){
fiddle_reset_db();
}
if(shellState.db){
printf("Connected to %s.\n", fiddle_db_filename(NULL));
}else{
fprintf(stderr,"ERROR initializing db!\n");
return;
}
}
if(once<0){
puts("DB init failed. Not executing SQL.");
}else if(zSql && *zSql){
shellState.wasm.zInput = zSql;
shellState.wasm.zPos = zSql;
process_input(&shellState);
memset(&shellState.wasm, 0, sizeof(shellState.wasm));
}
}
#endif /* SQLITE_SHELL_WASM_MODE */
|
Changes to extsrc/sqlite3.c.
| ︙ | ︙ | |||
450 451 452 453 454 455 456 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.39.0" #define SQLITE_VERSION_NUMBER 3039000 | | | 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.39.0" #define SQLITE_VERSION_NUMBER 3039000 #define SQLITE_SOURCE_ID "2022-06-15 16:26:37 56c60a35ea457f06db58ec3f694a1ae16fd03e6625da1d7879d63d72bbcb1c62" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| ︙ | ︙ | |||
6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 | ** returned by sqlite3_db_handle is the same [database connection] ** that was the first argument ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection ** METHOD: sqlite3 ** ** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename ** associated with database N of connection D. ** ^If there is no attached database N on the database | > > > > > > > > > > > > > > > > > > > > > > | 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 | ** returned by sqlite3_db_handle is the same [database connection] ** that was the first argument ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Schema Name For A Database Connection ** METHOD: sqlite3 ** ** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name ** for the N-th database on database connection D, or a NULL pointer of N is ** out of range. An N alue of 0 means the main database file. An N of 1 is ** the "temp" schema. Larger values of N correspond to various ATTACH-ed ** databases. ** ** Space to hold the string that is returned by sqlite3_db_name() is managed ** by SQLite itself. The string might be deallocated by any operation that ** changes the schema, including [ATTACH] or [DETACH] or calls to ** [sqlite3_serialize()] or [sqlite3_deserialize()], even operations that ** occur on a different thread. Applications that need to ** remember the string long-term should make their own copy. Applications that ** are accessing the same database connection simultaneously on multiple ** threads should mutex-protect calls to this API and should make their own ** private copy of the result prior to releasing the mutex. */ SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N); /* ** CAPI3REF: Return The Filename For A Database Connection ** METHOD: sqlite3 ** ** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename ** associated with database N of connection D. ** ^If there is no attached database N on the database |
| ︙ | ︙ | |||
14361 14362 14363 14364 14365 14366 14367 14368 14369 14370 14371 14372 14373 14374 14375 14376 | #define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) #define LARGEST_UINT64 (0xffffffff|(((u64)0xffffffff)<<32)) #define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) /* ** Round up a number to the next larger multiple of 8. This is used ** to force 8-byte alignment on 64-bit architectures. */ #define ROUND8(x) (((x)+7)&~7) /* ** Round down to the nearest multiple of 8 */ #define ROUNDDOWN8(x) ((x)&~7) /* | > > > > > > > > > > > | 14383 14384 14385 14386 14387 14388 14389 14390 14391 14392 14393 14394 14395 14396 14397 14398 14399 14400 14401 14402 14403 14404 14405 14406 14407 14408 14409 | #define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) #define LARGEST_UINT64 (0xffffffff|(((u64)0xffffffff)<<32)) #define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) /* ** Round up a number to the next larger multiple of 8. This is used ** to force 8-byte alignment on 64-bit architectures. ** ** ROUND8() always does the rounding, for any argument. ** ** ROUND8P() assumes that the argument is already an integer number of ** pointers in size, and so it is a no-op on systems where the pointer ** size is 8. */ #define ROUND8(x) (((x)+7)&~7) #if SQLITE_PTRSIZE==8 # define ROUND8P(x) (x) #else # define ROUND8P(x) (((x)+7)&~7) #endif /* ** Round down to the nearest multiple of 8 */ #define ROUNDDOWN8(x) ((x)&~7) /* |
| ︙ | ︙ | |||
14425 14426 14427 14428 14429 14430 14431 | #endif #if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE # undef SQLITE_DEFAULT_MMAP_SIZE # define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE #endif /* | | | | | > | | | | 14458 14459 14460 14461 14462 14463 14464 14465 14466 14467 14468 14469 14470 14471 14472 14473 14474 14475 14476 14477 14478 14479 14480 14481 14482 14483 14484 14485 14486 14487 14488 |
#endif
#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
# undef SQLITE_DEFAULT_MMAP_SIZE
# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE
#endif
/*
** TREETRACE_ENABLED will be either 1 or 0 depending on whether or not
** the Abstract Syntax Tree tracing logic is turned on.
*/
#if !defined(SQLITE_AMALGAMATION)
SQLITE_PRIVATE u32 sqlite3TreeTrace;
#endif
#if defined(SQLITE_DEBUG) \
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE) \
|| defined(SQLITE_ENABLE_TREETRACE))
# define TREETRACE_ENABLED 1
# define SELECTTRACE(K,P,S,X) \
if(sqlite3TreeTrace&(K)) \
sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
sqlite3DebugPrintf X
#else
# define SELECTTRACE(K,P,S,X)
# define TREETRACE_ENABLED 0
#endif
/*
** Macros for "wheretrace"
*/
SQLITE_PRIVATE u32 sqlite3WhereTrace;
#if defined(SQLITE_DEBUG) \
|
| ︙ | ︙ | |||
14601 14602 14603 14604 14605 14606 14607 14608 14609 14610 14611 14612 14613 14614 | typedef struct IndexSample IndexSample; typedef struct KeyClass KeyClass; typedef struct KeyInfo KeyInfo; typedef struct Lookaside Lookaside; typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; typedef struct Parse Parse; typedef struct ParseCleanup ParseCleanup; typedef struct PreUpdate PreUpdate; typedef struct PrintfArguments PrintfArguments; typedef struct RenameToken RenameToken; typedef struct Returning Returning; typedef struct RowSet RowSet; | > | 14635 14636 14637 14638 14639 14640 14641 14642 14643 14644 14645 14646 14647 14648 14649 | typedef struct IndexSample IndexSample; typedef struct KeyClass KeyClass; typedef struct KeyInfo KeyInfo; typedef struct Lookaside Lookaside; typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; typedef struct OnOrUsing OnOrUsing; typedef struct Parse Parse; typedef struct ParseCleanup ParseCleanup; typedef struct PreUpdate PreUpdate; typedef struct PrintfArguments PrintfArguments; typedef struct RenameToken RenameToken; typedef struct Returning Returning; typedef struct RowSet RowSet; |
| ︙ | ︙ | |||
15579 15580 15581 15582 15583 15584 15585 | #define OP_Init 64 /* jump, synopsis: Start at P2 */ #define OP_PureFunc 65 /* synopsis: r[P3]=func(r[P2@NP]) */ #define OP_Function 66 /* synopsis: r[P3]=func(r[P2@NP]) */ #define OP_Return 67 #define OP_EndCoroutine 68 #define OP_HaltIfNull 69 /* synopsis: if r[P3]=null halt */ #define OP_Halt 70 | | < | | > | | 15614 15615 15616 15617 15618 15619 15620 15621 15622 15623 15624 15625 15626 15627 15628 15629 15630 15631 15632 15633 15634 15635 15636 15637 15638 15639 15640 15641 15642 15643 15644 15645 15646 15647 15648 15649 15650 15651 | #define OP_Init 64 /* jump, synopsis: Start at P2 */ #define OP_PureFunc 65 /* synopsis: r[P3]=func(r[P2@NP]) */ #define OP_Function 66 /* synopsis: r[P3]=func(r[P2@NP]) */ #define OP_Return 67 #define OP_EndCoroutine 68 #define OP_HaltIfNull 69 /* synopsis: if r[P3]=null halt */ #define OP_Halt 70 #define OP_Integer 71 /* synopsis: r[P2]=P1 */ #define OP_Int64 72 /* synopsis: r[P2]=P4 */ #define OP_String 73 /* synopsis: r[P2]='P4' (len=P1) */ #define OP_BeginSubrtn 74 /* synopsis: r[P2]=NULL */ #define OP_Null 75 /* synopsis: r[P2..P3]=NULL */ #define OP_SoftNull 76 /* synopsis: r[P1]=NULL */ #define OP_Blob 77 /* synopsis: r[P2]=P4 (len=P1) */ #define OP_Variable 78 /* synopsis: r[P2]=parameter(P1,P4) */ #define OP_Move 79 /* synopsis: r[P2@P3]=r[P1@P3] */ #define OP_Copy 80 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ #define OP_SCopy 81 /* synopsis: r[P2]=r[P1] */ #define OP_IntCopy 82 /* synopsis: r[P2]=r[P1] */ #define OP_FkCheck 83 #define OP_ResultRow 84 /* synopsis: output=r[P1@P2] */ #define OP_CollSeq 85 #define OP_AddImm 86 /* synopsis: r[P1]=r[P1]+P2 */ #define OP_RealAffinity 87 #define OP_Cast 88 /* synopsis: affinity(r[P1]) */ #define OP_Permutation 89 #define OP_Compare 90 /* synopsis: r[P1@P3] <-> r[P2@P3] */ #define OP_IsTrue 91 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ #define OP_ZeroOrNull 92 /* synopsis: r[P2] = 0 OR NULL */ #define OP_Offset 93 /* synopsis: r[P3] = sqlite_offset(P1) */ #define OP_Column 94 /* synopsis: r[P3]=PX cursor P1 column P2 */ #define OP_TypeCheck 95 /* synopsis: typecheck(r[P1@P2]) */ #define OP_Affinity 96 /* synopsis: affinity(r[P1@P2]) */ #define OP_MakeRecord 97 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ #define OP_Count 98 /* synopsis: r[P2]=count() */ #define OP_ReadCookie 99 #define OP_SetCookie 100 #define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */ |
| ︙ | ︙ | |||
15643 15644 15645 15646 15647 15648 15649 | #define OP_Insert 128 /* synopsis: intkey=r[P3] data=r[P2] */ #define OP_RowCell 129 #define OP_Delete 130 #define OP_ResetCount 131 #define OP_SorterCompare 132 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ #define OP_SorterData 133 /* synopsis: r[P2]=data */ #define OP_RowData 134 /* synopsis: r[P2]=data */ | | | 15678 15679 15680 15681 15682 15683 15684 15685 15686 15687 15688 15689 15690 15691 15692 | #define OP_Insert 128 /* synopsis: intkey=r[P3] data=r[P2] */ #define OP_RowCell 129 #define OP_Delete 130 #define OP_ResetCount 131 #define OP_SorterCompare 132 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ #define OP_SorterData 133 /* synopsis: r[P2]=data */ #define OP_RowData 134 /* synopsis: r[P2]=data */ #define OP_Rowid 135 /* synopsis: r[P2]=PX rowid of P1 */ #define OP_NullRow 136 #define OP_SeekEnd 137 #define OP_IdxInsert 138 /* synopsis: key=r[P2] */ #define OP_SorterInsert 139 /* synopsis: key=r[P2] */ #define OP_IdxDelete 140 /* synopsis: key=r[P2@P3] */ #define OP_DeferredSeek 141 /* synopsis: Move P3 to P1.rowid if needed */ #define OP_IdxRowid 142 /* synopsis: r[P2]=rowid */ |
| ︙ | ︙ | |||
15687 15688 15689 15690 15691 15692 15693 | #define OP_VDestroy 172 #define OP_VOpen 173 #define OP_VInitIn 174 /* synopsis: r[P2]=ValueList(P1,P3) */ #define OP_VColumn 175 /* synopsis: r[P3]=vcolumn(P2) */ #define OP_VRename 176 #define OP_Pagecount 177 #define OP_MaxPgcnt 178 | > | | | | | | | | | | | | 15722 15723 15724 15725 15726 15727 15728 15729 15730 15731 15732 15733 15734 15735 15736 15737 15738 15739 15740 15741 15742 15743 15744 15745 15746 15747 15748 15749 15750 15751 15752 15753 15754 15755 15756 15757 15758 15759 15760 15761 15762 15763 15764 15765 15766 15767 15768 15769 15770 15771 15772 15773 15774 15775 15776 15777 15778 15779 |
#define OP_VDestroy 172
#define OP_VOpen 173
#define OP_VInitIn 174 /* synopsis: r[P2]=ValueList(P1,P3) */
#define OP_VColumn 175 /* synopsis: r[P3]=vcolumn(P2) */
#define OP_VRename 176
#define OP_Pagecount 177
#define OP_MaxPgcnt 178
#define OP_ClrSubtype 179 /* synopsis: r[P1].subtype = 0 */
#define OP_FilterAdd 180 /* synopsis: filter(P1) += key(P3@P4) */
#define OP_Trace 181
#define OP_CursorHint 182
#define OP_ReleaseReg 183 /* synopsis: release r[P1@P2] mask P3 */
#define OP_Noop 184
#define OP_Explain 185
#define OP_Abortable 186
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
** are encoded into bitvectors as follows:
*/
#define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */
#define OPFLG_IN1 0x02 /* in1: P1 is an input */
#define OPFLG_IN2 0x04 /* in2: P2 is an input */
#define OPFLG_IN3 0x08 /* in3: P3 is an input */
#define OPFLG_OUT2 0x10 /* out2: P2 is an output */
#define OPFLG_OUT3 0x20 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,\
/* 8 */ 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03,\
/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x09, 0x09, 0x09, 0x09,\
/* 24 */ 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x01,\
/* 32 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
/* 40 */ 0x01, 0x01, 0x01, 0x26, 0x26, 0x23, 0x0b, 0x01,\
/* 48 */ 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x01, 0x01,\
/* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\
/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\
/* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x00, 0x00,\
/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x26, 0x26,\
/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
/* 112 */ 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00,\
/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\
/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
/* 136 */ 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00,\
/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
/* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,\
/* 176 */ 0x00, 0x10, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00,\
/* 184 */ 0x00, 0x00, 0x00,}
/* The resolve3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
** JUMP opcode the better, so the mkopcodeh.tcl script that
** generated this include file strives to group all JUMP opcodes
** together near the beginning of the list.
*/
|
| ︙ | ︙ | |||
15775 15776 15777 15778 15779 15780 15781 15782 15783 15784 15785 15786 15787 15788 15789 15790 | SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p); #else # define sqlite3VdbeVerifyNoMallocRequired(A,B) # define sqlite3VdbeVerifyNoResultRow(A) #endif #if defined(SQLITE_DEBUG) SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int); #else # define sqlite3VdbeVerifyAbortable(A,B) #endif SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno); #ifndef SQLITE_OMIT_EXPLAIN SQLITE_PRIVATE void sqlite3VdbeExplain(Parse*,u8,const char*,...); SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse*); SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse*); # define ExplainQueryPlan(P) sqlite3VdbeExplain P | > > | 15811 15812 15813 15814 15815 15816 15817 15818 15819 15820 15821 15822 15823 15824 15825 15826 15827 15828 | SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p); #else # define sqlite3VdbeVerifyNoMallocRequired(A,B) # define sqlite3VdbeVerifyNoResultRow(A) #endif #if defined(SQLITE_DEBUG) SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int); SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn(Vdbe*,int,int,int); #else # define sqlite3VdbeVerifyAbortable(A,B) # define sqlite3VdbeNoJumpsOutsideSubrtn(A,B,C,D) #endif SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno); #ifndef SQLITE_OMIT_EXPLAIN SQLITE_PRIVATE void sqlite3VdbeExplain(Parse*,u8,const char*,...); SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse*); SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse*); # define ExplainQueryPlan(P) sqlite3VdbeExplain P |
| ︙ | ︙ | |||
15821 15822 15823 15824 15825 15826 15827 | SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*); SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse*); SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); | < | 15859 15860 15861 15862 15863 15864 15865 15866 15867 15868 15869 15870 15871 15872 | SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*); SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse*); SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*); SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); #endif |
| ︙ | ︙ | |||
16269 16270 16271 16272 16273 16274 16275 16276 16277 16278 16279 16280 16281 16282 | #endif /* Maximum pathname length. Note: FILENAME_MAX defined by stdio.h */ #ifndef SQLITE_MAX_PATHLEN # define SQLITE_MAX_PATHLEN FILENAME_MAX #endif /* ** The default size of a disk sector */ #ifndef SQLITE_DEFAULT_SECTOR_SIZE # define SQLITE_DEFAULT_SECTOR_SIZE 4096 #endif | > > > > > > > | 16306 16307 16308 16309 16310 16311 16312 16313 16314 16315 16316 16317 16318 16319 16320 16321 16322 16323 16324 16325 16326 | #endif /* Maximum pathname length. Note: FILENAME_MAX defined by stdio.h */ #ifndef SQLITE_MAX_PATHLEN # define SQLITE_MAX_PATHLEN FILENAME_MAX #endif /* Maximum number of symlinks that will be resolved while trying to ** expand a filename in xFullPathname() in the VFS. */ #ifndef SQLITE_MAX_SYMLINK # define SQLITE_MAX_SYMLINK 200 #endif /* ** The default size of a disk sector */ #ifndef SQLITE_DEFAULT_SECTOR_SIZE # define SQLITE_DEFAULT_SECTOR_SIZE 4096 #endif |
| ︙ | ︙ | |||
17036 17037 17038 17039 17040 17041 17042 17043 17044 17045 17046 17047 17048 17049 | #define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */ #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */ #define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */ /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */ #define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */ #define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */ #define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) | > > > | 17080 17081 17082 17083 17084 17085 17086 17087 17088 17089 17090 17091 17092 17093 17094 17095 17096 | #define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */ #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */ #define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */ /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */ #define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */ #define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */ #define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */ #define SQLITE_ReleaseReg 0x00400000 /* Use OP_ReleaseReg for testing */ #define SQLITE_FlttnUnionAll 0x00800000 /* Disable the UNION ALL flattener */ /* TH3 expects this value ^^^^^^^^^^ See flatten04.test */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) |
| ︙ | ︙ | |||
17138 17139 17140 17141 17142 17143 17144 |
/* 0x0200 -- available for reuse */
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
** single query - might change over time */
#define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */
| | > | 17185 17186 17187 17188 17189 17190 17191 17192 17193 17194 17195 17196 17197 17198 17199 17200 17201 17202 17203 17204 17205 17206 17207 17208 17209 17210 17211 17212 17213 17214 17215 17216 |
/* 0x0200 -- available for reuse */
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
** single query - might change over time */
#define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */
/* 0x8000 -- available for reuse */
#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
#define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
#define SQLITE_FUNC_BUILTIN 0x00800000 /* This is a built-in function */
#define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */
/* Identifier numbers for each in-line function */
#define INLINEFUNC_coalesce 0
#define INLINEFUNC_implies_nonnull_row 1
#define INLINEFUNC_expr_implies_expr 2
#define INLINEFUNC_expr_compare 3
#define INLINEFUNC_affinity 4
#define INLINEFUNC_iif 5
#define INLINEFUNC_sqlite_offset 6
#define INLINEFUNC_unlikely 99 /* Default case */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
** used to create the initializers for the FuncDef structures.
**
** FUNCTION(zName, nArg, iArg, bNC, xFunc)
|
| ︙ | ︙ | |||
17381 17382 17383 17384 17385 17386 17387 17388 17389 17390 17391 17392 17393 17394 | #define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */ #define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */ #define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */ #define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */ #define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */ #define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */ #define COLFLAG_HASCOLL 0x0200 /* Has collating sequence name in zCnName */ #define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */ #define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */ /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. | > | 17429 17430 17431 17432 17433 17434 17435 17436 17437 17438 17439 17440 17441 17442 17443 | #define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */ #define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */ #define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */ #define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */ #define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */ #define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */ #define COLFLAG_HASCOLL 0x0200 /* Has collating sequence name in zCnName */ #define COLFLAG_NOEXPAND 0x0400 /* Omit this column when expanding "*" */ #define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */ #define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */ /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. |
| ︙ | ︙ | |||
18100 18101 18102 18103 18104 18105 18106 |
** TK_SELECT_COLUMN: Number of columns on the LHS
** TK_SELECT: 1st register of result vector */
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
** TK_VARIABLE: variable number (always >= 1).
** TK_SELECT_COLUMN: column of the result vector */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
union {
| | | > | | < > | | | | | | | | | < > | | | | | | < | 18149 18150 18151 18152 18153 18154 18155 18156 18157 18158 18159 18160 18161 18162 18163 18164 18165 18166 18167 18168 18169 18170 18171 18172 18173 18174 18175 18176 18177 18178 18179 18180 18181 18182 18183 18184 18185 18186 18187 18188 18189 18190 18191 18192 18193 18194 18195 18196 18197 18198 18199 18200 18201 18202 18203 18204 18205 18206 |
** TK_SELECT_COLUMN: Number of columns on the LHS
** TK_SELECT: 1st register of result vector */
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
** TK_VARIABLE: variable number (always >= 1).
** TK_SELECT_COLUMN: column of the result vector */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
union {
int iJoin; /* If EP_OuterON or EP_InnerON, the right table */
int iOfst; /* else: start of token from start of statement */
} w;
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
union {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
** for a column of an index on an expression */
Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */
struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
int iAddr; /* Subroutine entry address */
int regReturn; /* Register used to hold return address */
} sub;
} y;
};
/* The following are the meanings of bits in the Expr.flags field.
** Value restrictions:
**
** EP_Agg == NC_HasAgg == SF_HasAgg
** EP_Win == NC_HasWin
*/
#define EP_OuterON 0x000001 /* Originates in ON/USING clause of outer join */
#define EP_InnerON 0x000002 /* Originates in ON/USING of an inner join */
#define EP_Distinct 0x000004 /* Aggregate function with DISTINCT keyword */
#define EP_HasFunc 0x000008 /* Contains one or more functions of any kind */
#define EP_Agg 0x000010 /* Contains one or more aggregate functions */
#define EP_FixedCol 0x000020 /* TK_Column with a known fixed value */
#define EP_VarSelect 0x000040 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x000080 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000100 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate 0x000200 /* Tree contains a TK_COLLATE operator */
#define EP_Commuted 0x000400 /* Comparison operator has been commuted */
#define EP_IntValue 0x000800 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x001000 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip 0x002000 /* Operator does not contribute to affinity */
#define EP_Reduced 0x004000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
#define EP_Win 0x008000 /* Contains window functions */
#define EP_TokenOnly 0x010000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_MemToken 0x020000 /* Need to sqlite3DbFree() Expr.zToken */
#define EP_IfNullRow 0x040000 /* The TK_IF_NULL_ROW opcode */
#define EP_Unlikely 0x080000 /* unlikely() or likelihood() function */
#define EP_ConstFunc 0x100000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
#define EP_CanBeNull 0x200000 /* Can be null despite NOT NULL constraint */
#define EP_Subquery 0x400000 /* Tree contains a TK_SELECT operator */
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */
#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
|
| ︙ | ︙ | |||
18166 18167 18168 18169 18170 18171 18172 | /* Macros can be used to test, set, or clear bits in the ** Expr.flags field. */ #define ExprHasProperty(E,P) (((E)->flags&(P))!=0) #define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P)) #define ExprSetProperty(E,P) (E)->flags|=(P) #define ExprClearProperty(E,P) (E)->flags&=~(P) | | | | 18215 18216 18217 18218 18219 18220 18221 18222 18223 18224 18225 18226 18227 18228 18229 18230 | /* Macros can be used to test, set, or clear bits in the ** Expr.flags field. */ #define ExprHasProperty(E,P) (((E)->flags&(P))!=0) #define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P)) #define ExprSetProperty(E,P) (E)->flags|=(P) #define ExprClearProperty(E,P) (E)->flags&=~(P) #define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue) #define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse) /* Macros used to ensure that the correct members of unions are accessed ** in Expr. */ #define ExprUseUToken(E) (((E)->flags&EP_IntValue)==0) #define ExprUseUValue(E) (((E)->flags&EP_IntValue)!=0) #define ExprUseXList(E) (((E)->flags&EP_xIsSelect)==0) |
| ︙ | ︙ | |||
18254 18255 18256 18257 18258 18259 18260 |
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
int nAlloc; /* Number of a[] slots allocated */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
char *zEName; /* Token associated with this expression */
| > | | | | | | > > > > > | 18303 18304 18305 18306 18307 18308 18309 18310 18311 18312 18313 18314 18315 18316 18317 18318 18319 18320 18321 18322 18323 18324 18325 18326 18327 18328 |
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
int nAlloc; /* Number of a[] slots allocated */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
char *zEName; /* Token associated with this expression */
struct {
u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */
unsigned eEName :2; /* Meaning of zEName */
unsigned done :1; /* Indicates when processing is finished */
unsigned reusable :1; /* Constant expression is reusable */
unsigned bSorterRef :1; /* Defer evaluation until after sorting */
unsigned bNulls :1; /* True if explicit "NULLS FIRST/LAST" */
unsigned bUsed :1; /* This column used in a SF_NestedFrom subquery */
unsigned bUsingTerm:1; /* Term from the USING clause of a NestedFrom */
unsigned bNoExpand: 1; /* Term is an auxiliary in NestedFrom and should
** not be expanded by "*" in parent queries */
} fg;
union {
struct { /* Used by any ExprList other than Parse.pConsExpr */
u16 iOrderByCol; /* For ORDER BY, column number in result set */
u16 iAlias; /* Index into Parse.aAlias[] for zName */
} x;
int iConstExprReg; /* Register in which Expr value is cached. Used only
** by Parse.pConstExpr */
|
| ︙ | ︙ | |||
18294 18295 18296 18297 18298 18299 18300 18301 18302 |
** column names after a table name in an INSERT statement. In the statement
**
** INSERT INTO t(a,b,c) ...
**
** If "a" is the k-th column of table "t", then IdList.a[0].idx==k.
*/
struct IdList {
struct IdList_item {
char *zName; /* Name of the identifier */
| > > > | > | < > > > > > > > > > | 18349 18350 18351 18352 18353 18354 18355 18356 18357 18358 18359 18360 18361 18362 18363 18364 18365 18366 18367 18368 18369 18370 18371 18372 18373 18374 18375 18376 18377 18378 18379 18380 18381 |
** column names after a table name in an INSERT statement. In the statement
**
** INSERT INTO t(a,b,c) ...
**
** If "a" is the k-th column of table "t", then IdList.a[0].idx==k.
*/
struct IdList {
int nId; /* Number of identifiers on the list */
u8 eU4; /* Which element of a.u4 is valid */
struct IdList_item {
char *zName; /* Name of the identifier */
union {
int idx; /* Index in some Table.aCol[] of a column named zName */
Expr *pExpr; /* Expr to implement a USING variable -- NOT USED */
} u4;
} a[1];
};
/*
** Allowed values for IdList.eType, which determines which value of the a.u4
** is valid.
*/
#define EU4_NONE 0 /* Does not use IdList.a.u4 */
#define EU4_IDX 1 /* Uses IdList.a.u4.idx */
#define EU4_EXPR 2 /* Uses IdList.a.u4.pExpr -- NOT CURRENTLY USED */
/*
** The SrcItem object represents a single term in the FROM clause of a query.
** The SrcList object is mostly an array of SrcItems.
**
** Union member validity:
**
** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc
|
| ︙ | ︙ | |||
18328 18329 18330 18331 18332 18333 18334 18335 18336 18337 18338 18339 18340 18341 |
int regResult; /* Registers holding results of a co-routine */
struct {
u8 jointype; /* Type of join between this table and the previous */
unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
unsigned isTabFunc :1; /* True if table-valued-function syntax */
unsigned isCorrelated :1; /* True if sub-query is correlated */
unsigned viaCoroutine :1; /* Implemented as a co-routine */
unsigned isRecursive :1; /* True for recursive reference in WITH */
unsigned fromDDL :1; /* Comes from sqlite_schema */
unsigned isCte :1; /* This is a CTE */
unsigned notCte :1; /* This item may not match a CTE */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
| > > > > > > | | > > > > > > > > > > | 18395 18396 18397 18398 18399 18400 18401 18402 18403 18404 18405 18406 18407 18408 18409 18410 18411 18412 18413 18414 18415 18416 18417 18418 18419 18420 18421 18422 18423 18424 18425 18426 18427 18428 18429 18430 18431 18432 18433 18434 18435 18436 18437 18438 18439 18440 18441 18442 18443 |
int regResult; /* Registers holding results of a co-routine */
struct {
u8 jointype; /* Type of join between this table and the previous */
unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
unsigned isTabFunc :1; /* True if table-valued-function syntax */
unsigned isCorrelated :1; /* True if sub-query is correlated */
unsigned isMaterialized:1; /* This is a materialized view */
unsigned viaCoroutine :1; /* Implemented as a co-routine */
unsigned isRecursive :1; /* True for recursive reference in WITH */
unsigned fromDDL :1; /* Comes from sqlite_schema */
unsigned isCte :1; /* This is a CTE */
unsigned notCte :1; /* This item may not match a CTE */
unsigned isUsing :1; /* u3.pUsing is valid */
unsigned isOn :1; /* u3.pOn was once valid and non-NULL */
unsigned isSynthUsing :1; /* u3.pUsing is synthensized from NATURAL */
unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
union {
Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
} u3;
Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
union {
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
ExprList *pFuncArg; /* Arguments to table-valued-function */
} u1;
union {
Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
CteUse *pCteUse; /* CTE Usage info info fg.isCte is true */
} u2;
};
/*
** The OnOrUsing object represents either an ON clause or a USING clause.
** It can never be both at the same time, but it can be neither.
*/
struct OnOrUsing {
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
};
/*
** The following structure describes the FROM clause of a SELECT statement.
** Each table or subquery in the FROM clause is a separate element of
** the SrcList.a[] array.
**
** With the addition of multiple database support, the following structure
|
| ︙ | ︙ | |||
18376 18377 18378 18379 18380 18381 18382 | u32 nAlloc; /* Number of entries allocated in a[] below */ SrcItem a[1]; /* One entry for each identifier on the list */ }; /* ** Permitted values of the SrcList.a.jointype field */ | | | | | | | > > | < | 18459 18460 18461 18462 18463 18464 18465 18466 18467 18468 18469 18470 18471 18472 18473 18474 18475 18476 18477 18478 18479 18480 18481 |
u32 nAlloc; /* Number of entries allocated in a[] below */
SrcItem a[1]; /* One entry for each identifier on the list */
};
/*
** Permitted values of the SrcList.a.jointype field
*/
#define JT_INNER 0x01 /* Any kind of inner or cross join */
#define JT_CROSS 0x02 /* Explicit use of the CROSS keyword */
#define JT_NATURAL 0x04 /* True for a "natural" join */
#define JT_LEFT 0x08 /* Left outer join */
#define JT_RIGHT 0x10 /* Right outer join */
#define JT_OUTER 0x20 /* The "OUTER" keyword is present */
#define JT_LTORJ 0x40 /* One of the LEFT operands of a RIGHT JOIN
** Mnemonic: Left Table Of Right Join */
#define JT_ERROR 0x80 /* unknown or unsupported join type */
/*
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
** and the WhereInfo.wctrlFlags member.
**
** Value constraints (enforced via assert()):
** WHERE_USE_LIMIT == SF_FixedLimit
|
| ︙ | ︙ | |||
18406 18407 18408 18409 18410 18411 18412 |
** the OR optimization */
#define WHERE_GROUPBY 0x0040 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
| | | 18490 18491 18492 18493 18494 18495 18496 18497 18498 18499 18500 18501 18502 18503 18504 |
** the OR optimization */
#define WHERE_GROUPBY 0x0040 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
#define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */
/* 0x2000 not currently used */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
/* Allowed return values from sqlite3WhereIsDistinct()
*/
#define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */
|
| ︙ | ︙ | |||
18602 18603 18604 18605 18606 18607 18608 18609 18610 18611 18612 18613 18614 18615 | #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */ #define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */ #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */ #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */ /* ** The results of a SELECT can be distributed in several ways, as defined ** by one of the following macros. The "SRT" prefix means "SELECT Result ** Type". ** ** SRT_Union Store results as a key in a temporary index ** identified by pDest->iSDParm. | > > > | 18686 18687 18688 18689 18690 18691 18692 18693 18694 18695 18696 18697 18698 18699 18700 18701 18702 | #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */ #define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */ #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */ #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */ /* True if S exists and has SF_NestedFrom */ #define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0) /* ** The results of a SELECT can be distributed in several ways, as defined ** by one of the following macros. The "SRT" prefix means "SELECT Result ** Type". ** ** SRT_Union Store results as a key in a temporary index ** identified by pDest->iSDParm. |
| ︙ | ︙ | |||
18813 18814 18815 18816 18817 18818 18819 18820 18821 18822 18823 18824 18825 18826 | u8 nTempReg; /* Number of temporary registers in aTempReg[] */ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 okConstFactor; /* OK to factor out constants */ u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 disableVtab; /* Disable all virtual tables for this parse */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ #endif int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ | > | 18900 18901 18902 18903 18904 18905 18906 18907 18908 18909 18910 18911 18912 18913 18914 | u8 nTempReg; /* Number of temporary registers in aTempReg[] */ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 okConstFactor; /* OK to factor out constants */ u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 disableVtab; /* Disable all virtual tables for this parse */ u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ #endif int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ |
| ︙ | ︙ | |||
18985 18986 18987 18988 18989 18990 18991 | #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ #define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */ #define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */ #define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */ #define OPFLAG_PREFORMAT 0x80 /* OP_Insert uses preformatted cell */ /* | | | | | | | | | | | | | | | | 19073 19074 19075 19076 19077 19078 19079 19080 19081 19082 19083 19084 19085 19086 19087 19088 19089 19090 19091 19092 19093 19094 19095 19096 19097 19098 19099 19100 |
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */
#define OPFLAG_PREFORMAT 0x80 /* OP_Insert uses preformatted cell */
/*
** Each trigger present in the database schema is stored as an instance of
** struct Trigger.
**
** Pointers to instances of struct Trigger are stored in two ways.
** 1. In the "trigHash" hash table (part of the sqlite3* that represents the
** database). This allows Trigger structures to be retrieved by name.
** 2. All triggers associated with a single table form a linked list, using the
** pNext member of struct Trigger. A pointer to the first element of the
** linked list is stored as the "pTrigger" member of the associated
** struct Table.
**
** The "step_list" member points to the first element of a linked list
** containing the SQL statements specified as the trigger program.
*/
struct Trigger {
char *zName; /* The name of the trigger */
char *table; /* The table or view to which the trigger applies */
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */
u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
u8 bReturning; /* This trigger implements a RETURNING clause */
Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */
|
| ︙ | ︙ | |||
19025 19026 19027 19028 19029 19030 19031 | ** If there are multiple triggers, you might of some BEFORE and some AFTER. ** In that cases, the constants below can be ORed together. */ #define TRIGGER_BEFORE 1 #define TRIGGER_AFTER 2 /* | | | | | | | | | | | | | | | | | | < < | | | < < | < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > | | 19113 19114 19115 19116 19117 19118 19119 19120 19121 19122 19123 19124 19125 19126 19127 19128 19129 19130 19131 19132 19133 19134 19135 19136 19137 19138 19139 19140 19141 19142 19143 19144 19145 19146 19147 19148 19149 19150 19151 19152 19153 19154 19155 19156 19157 19158 19159 19160 19161 19162 19163 19164 19165 19166 19167 19168 |
** If there are multiple triggers, you might of some BEFORE and some AFTER.
** In that cases, the constants below can be ORed together.
*/
#define TRIGGER_BEFORE 1
#define TRIGGER_AFTER 2
/*
** An instance of struct TriggerStep is used to store a single SQL statement
** that is a part of a trigger-program.
**
** Instances of struct TriggerStep are stored in a singly linked list (linked
** using the "pNext" member) referenced by the "step_list" member of the
** associated struct Trigger instance. The first element of the linked list is
** the first step of the trigger-program.
**
** The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
** "SELECT" statement. The meanings of the other members is determined by the
** value of "op" as follows:
**
** (op == TK_INSERT)
** orconf -> stores the ON CONFLICT algorithm
** pSelect -> The content to be inserted - either a SELECT statement or
** a VALUES clause.
** zTarget -> Dequoted name of the table to insert into.
** pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
** statement, then this stores the column-names to be
** inserted into.
** pUpsert -> The ON CONFLICT clauses for an Upsert
**
** (op == TK_DELETE)
** zTarget -> Dequoted name of the table to delete from.
** pWhere -> The WHERE clause of the DELETE statement if one is specified.
** Otherwise NULL.
**
** (op == TK_UPDATE)
** zTarget -> Dequoted name of the table to update.
** pWhere -> The WHERE clause of the UPDATE statement if one is specified.
** Otherwise NULL.
** pExprList -> A list of the columns to update and the expressions to update
** them to. See sqlite3Update() documentation of "pChanges"
** argument.
**
** (op == TK_SELECT)
** pSelect -> The SELECT statement
**
** (op == TK_RETURNING)
** pExprList -> The list of expressions that follow the RETURNING keyword.
**
*/
struct TriggerStep {
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT,
** or TK_RETURNING */
u8 orconf; /* OE_Rollback etc. */
Trigger *pTrig; /* The trigger that this step is a part of */
Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
|
| ︙ | ︙ | |||
19671 19672 19673 19674 19675 19676 19677 19678 19679 19680 19681 19682 19683 19684 19685 19686 19687 19688 | SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); #endif #if defined(SQLITE_TEST) SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); #endif #if defined(SQLITE_DEBUG) SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*); SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView*, const SrcList*); SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8); SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8); #ifndef SQLITE_OMIT_WINDOWFUNC SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView*, const Window*, u8); SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8); #endif #endif | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | 19764 19765 19766 19767 19768 19769 19770 19771 19772 19773 19774 19775 19776 19777 19778 19779 19780 19781 19782 19783 19784 19785 19786 19787 19788 19789 19790 19791 19792 19793 19794 19795 19796 19797 19798 19799 19800 19801 19802 19803 19804 19805 19806 19807 19808 19809 19810 19811 19812 19813 19814 19815 19816 19817 19818 19819 19820 19821 19822 |
SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...);
#endif
#if defined(SQLITE_TEST)
SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*);
#endif
#if defined(SQLITE_DEBUG)
SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView*, const char *zFormat, ...);
SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*);
SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
SQLITE_PRIVATE void sqlite3TreeViewBareIdList(TreeView*, const IdList*, const char*);
SQLITE_PRIVATE void sqlite3TreeViewIdList(TreeView*, const IdList*, u8, const char*);
SQLITE_PRIVATE void sqlite3TreeViewColumnList(TreeView*, const Column*, int, u8);
SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView*, const SrcList*);
SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8);
SQLITE_PRIVATE void sqlite3TreeViewUpsert(TreeView*, const Upsert*, u8);
SQLITE_PRIVATE void sqlite3TreeViewDelete(const With*, const SrcList*, const Expr*,
const ExprList*,const Expr*, const Trigger*);
SQLITE_PRIVATE void sqlite3TreeViewInsert(const With*, const SrcList*,
const IdList*, const Select*, const ExprList*,
int, const Upsert*, const Trigger*);
SQLITE_PRIVATE void sqlite3TreeViewUpdate(const With*, const SrcList*, const ExprList*,
const Expr*, int, const ExprList*, const Expr*,
const Upsert*, const Trigger*);
#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3TreeViewTriggerStep(TreeView*, const TriggerStep*, u8, u8);
SQLITE_PRIVATE void sqlite3TreeViewTrigger(TreeView*, const Trigger*, u8, u8);
#endif
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView*, const Window*, u8);
SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8);
#endif
SQLITE_PRIVATE void sqlite3ShowExpr(const Expr*);
SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList*);
SQLITE_PRIVATE void sqlite3ShowIdList(const IdList*);
SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList*);
SQLITE_PRIVATE void sqlite3ShowSelect(const Select*);
SQLITE_PRIVATE void sqlite3ShowWith(const With*);
SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert*);
#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3ShowTriggerStep(const TriggerStep*);
SQLITE_PRIVATE void sqlite3ShowTriggerStepList(const TriggerStep*);
SQLITE_PRIVATE void sqlite3ShowTrigger(const Trigger*);
SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger*);
#endif
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE void sqlite3ShowWindow(const Window*);
SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window*);
#endif
#endif
SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*);
SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...);
SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int);
SQLITE_PRIVATE void sqlite3Dequote(char*);
SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*);
SQLITE_PRIVATE void sqlite3DequoteToken(Token*);
|
| ︙ | ︙ | |||
19831 19832 19833 19834 19835 19836 19837 | SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse*, IdList*, Token*); SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*); SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int); SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2); SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*); SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, | | | > | 19957 19958 19959 19960 19961 19962 19963 19964 19965 19966 19967 19968 19969 19970 19971 19972 19973 19974 19975 19976 19977 19978 |
SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
Token*, Select*, OnOrUsing*);
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, SrcItem *);
SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(Parse*,SrcList*);
SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*);
SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*);
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Expr*, int, int, u8);
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
|
| ︙ | ︙ | |||
19937 19938 19939 19940 19941 19942 19943 19944 19945 19946 19947 19948 19949 19950 | SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*); SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int); #ifdef SQLITE_ENABLE_CURSOR_HINTS SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); #endif SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); SQLITE_PRIVATE int sqlite3IsRowid(const char*); | > | 20064 20065 20066 20067 20068 20069 20070 20071 20072 20073 20074 20075 20076 20077 20078 | SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*); SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int); SQLITE_PRIVATE int sqlite3ExprIsTableConstraint(Expr*,const SrcItem*); #ifdef SQLITE_ENABLE_CURSOR_HINTS SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); #endif SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); SQLITE_PRIVATE int sqlite3IsRowid(const char*); |
| ︙ | ︙ | |||
20034 20035 20036 20037 20038 20039 20040 | # define sqlite3IsToplevel(p) 1 # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 # define sqlite3TriggerStepSrc(A,B) 0 #endif SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol); | > | | 20162 20163 20164 20165 20166 20167 20168 20169 20170 20171 20172 20173 20174 20175 20176 20177 | # define sqlite3IsToplevel(p) 1 # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 # define sqlite3TriggerStepSrc(A,B) 0 #endif SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol); SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem*,int); SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr*,int,u32); SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int); #ifndef SQLITE_OMIT_AUTHORIZATION SQLITE_PRIVATE void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*); SQLITE_PRIVATE int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*); SQLITE_PRIVATE void sqlite3AuthContextPush(Parse*, AuthContext*, const char*); SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext*); |
| ︙ | ︙ | |||
20380 20381 20382 20383 20384 20385 20386 |
SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*);
SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *);
SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
| | | 20509 20510 20511 20512 20513 20514 20515 20516 20517 20518 20519 20520 20521 20522 20523 |
SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*);
SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *);
SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(sqlite3_index_info*);
#endif
SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse*,sqlite3*);
SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse*);
SQLITE_PRIVATE void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*);
|
| ︙ | ︙ | |||
21128 21129 21130 21131 21132 21133 21134 | #endif #ifdef SQLITE_ENABLE_RBU "ENABLE_RBU", #endif #ifdef SQLITE_ENABLE_RTREE "ENABLE_RTREE", #endif | < < < > > > | 21257 21258 21259 21260 21261 21262 21263 21264 21265 21266 21267 21268 21269 21270 21271 21272 21273 21274 21275 21276 21277 21278 21279 21280 21281 21282 21283 21284 21285 21286 21287 21288 21289 21290 21291 21292 21293 | #endif #ifdef SQLITE_ENABLE_RBU "ENABLE_RBU", #endif #ifdef SQLITE_ENABLE_RTREE "ENABLE_RTREE", #endif #ifdef SQLITE_ENABLE_SESSION "ENABLE_SESSION", #endif #ifdef SQLITE_ENABLE_SNAPSHOT "ENABLE_SNAPSHOT", #endif #ifdef SQLITE_ENABLE_SORTER_REFERENCES "ENABLE_SORTER_REFERENCES", #endif #ifdef SQLITE_ENABLE_SQLLOG "ENABLE_SQLLOG", #endif #ifdef SQLITE_ENABLE_STAT4 "ENABLE_STAT4", #endif #ifdef SQLITE_ENABLE_STMTVTAB "ENABLE_STMTVTAB", #endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS "ENABLE_STMT_SCANSTATUS", #endif #ifdef SQLITE_ENABLE_TREETRACE "ENABLE_TREETRACE", #endif #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION "ENABLE_UNKNOWN_SQL_FUNCTION", #endif #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY "ENABLE_UNLOCK_NOTIFY", #endif |
| ︙ | ︙ | |||
21958 21959 21960 21961 21962 21963 21964 | #ifndef SQLITE_OMIT_WSD SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000; #endif /* ** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS. */ | | | 22087 22088 22089 22090 22091 22092 22093 22094 22095 22096 22097 22098 22099 22100 22101 | #ifndef SQLITE_OMIT_WSD SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000; #endif /* ** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS. */ SQLITE_PRIVATE u32 sqlite3TreeTrace = 0; SQLITE_PRIVATE u32 sqlite3WhereTrace = 0; /* #include "opcodes.h" */ /* ** Properties of opcodes. The OPFLG_INITIALIZER macro is ** created by mkopcodeh.awk during compilation. Data is obtained ** from the comments following the "case OP_xxxx:" statements in |
| ︙ | ︙ | |||
22125 22126 22127 22128 22129 22130 22131 | #ifdef SQLITE_DEBUG u8 seekOp; /* Most recent seek operation on this cursor */ u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ #endif Bool isEphemeral:1; /* True for an ephemeral table */ Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */ Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ | | | 22254 22255 22256 22257 22258 22259 22260 22261 22262 22263 22264 22265 22266 22267 22268 |
#ifdef SQLITE_DEBUG
u8 seekOp; /* Most recent seek operation on this cursor */
u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */
#endif
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
Bool noReuse:1; /* OpenEphemeral may not reuse this cursor */
u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
union { /* pBtx for isEphermeral. pAltMap otherwise */
Btree *pBtx; /* Separate file holding temporary table */
u32 *aAltMap; /* Mapping from table to index column numbers */
} ub;
i64 seqCount; /* Sequence counter */
|
| ︙ | ︙ | |||
22173 22174 22175 22176 22177 22178 22179 22180 22181 22182 22183 22184 22185 22186 | /* 2*nField extra array elements allocated for aType[], beyond the one ** static element declared in the structure. nField total array slots for ** aType[] and nField+1 array slots for aOffset[] */ u32 aType[1]; /* Type values record decode. MUST BE LAST */ }; /* ** A value for VdbeCursor.cacheStatus that means the cache is always invalid. */ #define CACHE_STALE 0 /* | > > > > > | 22302 22303 22304 22305 22306 22307 22308 22309 22310 22311 22312 22313 22314 22315 22316 22317 22318 22319 22320 | /* 2*nField extra array elements allocated for aType[], beyond the one ** static element declared in the structure. nField total array slots for ** aType[] and nField+1 array slots for aOffset[] */ u32 aType[1]; /* Type values record decode. MUST BE LAST */ }; /* Return true if P is a null-only cursor */ #define IsNullCursor(P) \ ((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0) /* ** A value for VdbeCursor.cacheStatus that means the cache is always invalid. */ #define CACHE_STALE 0 /* |
| ︙ | ︙ | |||
22408 22409 22410 22411 22412 22413 22414 22415 22416 22417 22418 22419 22420 22421 |
struct sqlite3_context {
Mem *pOut; /* The return value is stored here */
FuncDef *pFunc; /* Pointer to function information */
Mem *pMem; /* Memory cell used to store aggregate context */
Vdbe *pVdbe; /* The VM that owns this context */
int iOp; /* Instruction number of OP_Function */
int isError; /* Error code returned by the function. */
u8 skipFlag; /* Skip accumulator loading if true */
u8 argc; /* Number of arguments */
sqlite3_value *argv[1]; /* Argument set */
};
/* A bitfield type for use inside of structures. Always follow with :N where
** N is the number of bits.
| > | 22542 22543 22544 22545 22546 22547 22548 22549 22550 22551 22552 22553 22554 22555 22556 |
struct sqlite3_context {
Mem *pOut; /* The return value is stored here */
FuncDef *pFunc; /* Pointer to function information */
Mem *pMem; /* Memory cell used to store aggregate context */
Vdbe *pVdbe; /* The VM that owns this context */
int iOp; /* Instruction number of OP_Function */
int isError; /* Error code returned by the function. */
u8 enc; /* Encoding to use for results */
u8 skipFlag; /* Skip accumulator loading if true */
u8 argc; /* Number of arguments */
sqlite3_value *argv[1]; /* Argument set */
};
/* A bitfield type for use inside of structures. Always follow with :N where
** N is the number of bits.
|
| ︙ | ︙ | |||
22456 22457 22458 22459 22460 22461 22462 |
** is really a pointer to an instance of this structure.
*/
struct Vdbe {
sqlite3 *db; /* The database connection that owns this statement */
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
Parse *pParse; /* Parsing context used to create this Vdbe */
ynVar nVar; /* Number of entries in aVar[] */
| < | 22591 22592 22593 22594 22595 22596 22597 22598 22599 22600 22601 22602 22603 22604 |
** is really a pointer to an instance of this structure.
*/
struct Vdbe {
sqlite3 *db; /* The database connection that owns this statement */
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
Parse *pParse; /* Parsing context used to create this Vdbe */
ynVar nVar; /* Number of entries in aVar[] */
int nMem; /* Number of memory locations currently allocated */
int nCursor; /* Number of slots in apCsr[] */
u32 cacheCtr; /* VdbeCursor row cache generation counter */
int pc; /* The program counter */
int rc; /* Value to return */
i64 nChange; /* Number of db changes made since last reset */
int iStatement; /* Statement number (or 0 if has no opened stmt) */
|
| ︙ | ︙ | |||
22494 22495 22496 22497 22498 22499 22500 | int rcApp; /* errcode set by sqlite3_result_error_code() */ u32 nWrite; /* Number of write operations that have occurred */ #endif u16 nResColumn; /* Number of columns in one row of the result set */ u8 errorAction; /* Recovery action to do in case of an error */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ | | < | 22628 22629 22630 22631 22632 22633 22634 22635 22636 22637 22638 22639 22640 22641 22642 22643 22644 22645 | int rcApp; /* errcode set by sqlite3_result_error_code() */ u32 nWrite; /* Number of write operations that have occurred */ #endif u16 nResColumn; /* Number of columns in one row of the result set */ u8 errorAction; /* Recovery action to do in case of an error */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ u8 eVdbeState; /* On of the VDBE_*_STATE values */ bft expired:2; /* 1: recompile VM immediately 2: when convenient */ bft explain:2; /* True if EXPLAIN present on SQL command */ bft changeCntOn:1; /* True to update the change-counter */ bft usesStmtJournal:1; /* True if uses a statement journal */ bft readOnly:1; /* True for statements that do not write */ bft bIsReader:1; /* True for statements that read */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ u32 aCounter[9]; /* Counters used by sqlite3_stmt_status() */ char *zSql; /* Text of the SQL statement that generated this */ |
| ︙ | ︙ | |||
22525 22526 22527 22528 22529 22530 22531 | i64 *anExec; /* Number of times each op has been executed */ int nScan; /* Entries in aScan[] */ ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */ #endif }; /* | | | | | | < | 22658 22659 22660 22661 22662 22663 22664 22665 22666 22667 22668 22669 22670 22671 22672 22673 22674 22675 22676 22677 |
i64 *anExec; /* Number of times each op has been executed */
int nScan; /* Entries in aScan[] */
ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */
#endif
};
/*
** The following are allowed values for Vdbe.eVdbeState
*/
#define VDBE_INIT_STATE 0 /* Prepared statement under construction */
#define VDBE_READY_STATE 1 /* Ready to run but not yet started */
#define VDBE_RUN_STATE 2 /* Run in progress */
#define VDBE_HALT_STATE 3 /* Finished. Need reset() or finalize() */
/*
** Structure used to store the context required by the
** sqlite3_preupdate_*() API functions.
*/
struct PreUpdate {
Vdbe *v;
|
| ︙ | ︙ | |||
22572 22573 22574 22575 22576 22577 22578 22579 22580 22581 22582 22583 22584 22585 22586 22587 22588 22589 |
*/
typedef struct ValueList ValueList;
struct ValueList {
BtCursor *pCsr; /* An ephemeral table holding all values */
sqlite3_value *pOut; /* Register to hold each decoded output value */
};
/*
** Function prototypes
*/
SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...);
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p);
SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*);
SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*);
SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8);
| > > > > > > > > > | > > > > | 22704 22705 22706 22707 22708 22709 22710 22711 22712 22713 22714 22715 22716 22717 22718 22719 22720 22721 22722 22723 22724 22725 22726 22727 22728 22729 22730 22731 22732 22733 22734 22735 22736 22737 22738 22739 22740 22741 22742 |
*/
typedef struct ValueList ValueList;
struct ValueList {
BtCursor *pCsr; /* An ephemeral table holding all values */
sqlite3_value *pOut; /* Register to hold each decoded output value */
};
/* Size of content associated with serial types that fit into a
** single-byte varint.
*/
#ifndef SQLITE_AMALGAMATION
SQLITE_PRIVATE const u8 sqlite3SmallTypeSizes[];
#endif
/*
** Function prototypes
*/
SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...);
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
SQLITE_PRIVATE void sqlite3VdbeFreeCursorNN(Vdbe*,VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p);
SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*);
SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*);
SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8);
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
SQLITE_PRIVATE u64 sqlite3FloatSwap(u64 in);
# define swapMixedEndianFloat(X) X = sqlite3FloatSwap(X)
#else
# define swapMixedEndianFloat(X)
#endif
SQLITE_PRIVATE void sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
|
| ︙ | ︙ | |||
23044 23045 23046 23047 23048 23049 23050 |
*/
case SQLITE_DBSTATUS_STMT_USED: {
struct Vdbe *pVdbe; /* Used to iterate through VMs */
int nByte = 0; /* Used to accumulate return value */
db->pnBytesFreed = &nByte;
for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
| | < | 23189 23190 23191 23192 23193 23194 23195 23196 23197 23198 23199 23200 23201 23202 23203 |
*/
case SQLITE_DBSTATUS_STMT_USED: {
struct Vdbe *pVdbe; /* Used to iterate through VMs */
int nByte = 0; /* Used to accumulate return value */
db->pnBytesFreed = &nByte;
for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
sqlite3VdbeDelete(pVdbe);
}
db->pnBytesFreed = 0;
*pHighwater = 0; /* IMP: R-64479-57858 */
*pCurrent = nByte;
break;
|
| ︙ | ︙ | |||
27000 27001 27002 27003 27004 27005 27006 |
**
** All allocations must be a power of two and must be expressed by a
** 32-bit signed integer. Hence the largest allocation is 0x40000000
** or 1073741824 bytes.
*/
static int memsys5Roundup(int n){
int iFullSz;
| > > > > | | > | 27144 27145 27146 27147 27148 27149 27150 27151 27152 27153 27154 27155 27156 27157 27158 27159 27160 27161 27162 27163 27164 |
**
** All allocations must be a power of two and must be expressed by a
** 32-bit signed integer. Hence the largest allocation is 0x40000000
** or 1073741824 bytes.
*/
static int memsys5Roundup(int n){
int iFullSz;
if( n<=mem5.szAtom*2 ){
if( n<=mem5.szAtom ) return mem5.szAtom;
return mem5.szAtom*2;
}
if( n>0x40000000 ) return 0;
for(iFullSz=mem5.szAtom*8; iFullSz<n; iFullSz *= 4);
if( (iFullSz/2)>=n ) return iFullSz/2;
return iFullSz;
}
/*
** Return the ceiling of the logarithm base 2 of iValue.
**
** Examples: memsys5Log(1) -> 0
|
| ︙ | ︙ | |||
29382 29383 29384 29385 29386 29387 29388 29389 |
return sqlite3DbStrNDup(db, zStart, n);
}
/*
** Free any prior content in *pz and replace it with a copy of zNew.
*/
SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
sqlite3DbFree(db, *pz);
| > | | 29531 29532 29533 29534 29535 29536 29537 29538 29539 29540 29541 29542 29543 29544 29545 29546 29547 |
return sqlite3DbStrNDup(db, zStart, n);
}
/*
** Free any prior content in *pz and replace it with a copy of zNew.
*/
SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
char *z = sqlite3DbStrDup(db, zNew);
sqlite3DbFree(db, *pz);
*pz = z;
}
/*
** Call this routine to record the fact that an OOM (out-of-memory) error
** has happened. This routine will set db->mallocFailed, and also
** temporarily disable the lookaside memory allocator and interrupt
** any running VDBEs.
|
| ︙ | ︙ | |||
30355 30356 30357 30358 30359 30360 30361 |
if( pItem->zDatabase ){
sqlite3_str_appendall(pAccum, pItem->zDatabase);
sqlite3_str_append(pAccum, ".", 1);
}
sqlite3_str_appendall(pAccum, pItem->zName);
}else if( pItem->zAlias ){
sqlite3_str_appendall(pAccum, pItem->zAlias);
| > | > > | > > > | 30505 30506 30507 30508 30509 30510 30511 30512 30513 30514 30515 30516 30517 30518 30519 30520 30521 30522 30523 30524 30525 30526 |
if( pItem->zDatabase ){
sqlite3_str_appendall(pAccum, pItem->zDatabase);
sqlite3_str_append(pAccum, ".", 1);
}
sqlite3_str_appendall(pAccum, pItem->zName);
}else if( pItem->zAlias ){
sqlite3_str_appendall(pAccum, pItem->zAlias);
}else{
Select *pSel = pItem->pSelect;
assert( pSel!=0 );
if( pSel->selFlags & SF_NestedFrom ){
sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
}else{
sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId);
}
}
length = width = 0;
break;
}
default: {
assert( xtype==etINVALID );
return;
|
| ︙ | ︙ | |||
30419 30420 30421 30422 30423 30424 30425 |
}
/*
** If pExpr has a byte offset for the start of a token, record that as
** as the error offset.
*/
SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){
| | > > | 30575 30576 30577 30578 30579 30580 30581 30582 30583 30584 30585 30586 30587 30588 30589 30590 30591 |
}
/*
** If pExpr has a byte offset for the start of a token, record that as
** as the error offset.
*/
SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){
while( pExpr
&& (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)
){
pExpr = pExpr->pLeft;
}
if( pExpr==0 ) return;
db->errByteOffset = pExpr->w.iOfst;
}
/*
|
| ︙ | ︙ | |||
30879 30880 30881 30882 30883 30884 30885 | /* #include "sqliteInt.h" */ #ifdef SQLITE_DEBUG /* ** Add a new subitem to the tree. The moreToFollow flag indicates that this ** is not the last item in the tree. */ | | > | | < | > | > > > | | 31037 31038 31039 31040 31041 31042 31043 31044 31045 31046 31047 31048 31049 31050 31051 31052 31053 31054 31055 31056 31057 31058 31059 31060 31061 31062 31063 31064 31065 31066 31067 31068 31069 31070 31071 31072 31073 31074 31075 31076 31077 31078 31079 31080 31081 |
/* #include "sqliteInt.h" */
#ifdef SQLITE_DEBUG
/*
** Add a new subitem to the tree. The moreToFollow flag indicates that this
** is not the last item in the tree.
*/
static void sqlite3TreeViewPush(TreeView **pp, u8 moreToFollow){
TreeView *p = *pp;
if( p==0 ){
*pp = p = sqlite3_malloc64( sizeof(*p) );
if( p==0 ) return;
memset(p, 0, sizeof(*p));
}else{
p->iLevel++;
}
assert( moreToFollow==0 || moreToFollow==1 );
if( p->iLevel<(int)sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
}
/*
** Finished with one layer of the tree
*/
static void sqlite3TreeViewPop(TreeView **pp){
TreeView *p = *pp;
if( p==0 ) return;
p->iLevel--;
if( p->iLevel<0 ){
sqlite3_free(p);
*pp = 0;
}
}
/*
** Generate a single line of output for the tree, with a prefix that contains
** all the appropriate tree lines
*/
SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_list ap;
int i;
StrAccum acc;
char zBuf[500];
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
if( p ){
for(i=0; i<p->iLevel && i<(int)sizeof(p->bLine)-1; i++){
|
| ︙ | ︙ | |||
30933 30934 30935 30936 30937 30938 30939 |
fflush(stdout);
}
/*
** Shorthand for starting a new tree item that consists of a single label
*/
static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | | > > > > | > > > > > > > > > > > > > > > > > > > > | | | | | | 31095 31096 31097 31098 31099 31100 31101 31102 31103 31104 31105 31106 31107 31108 31109 31110 31111 31112 31113 31114 31115 31116 31117 31118 31119 31120 31121 31122 31123 31124 31125 31126 31127 31128 31129 31130 31131 31132 31133 31134 31135 31136 31137 31138 31139 31140 31141 31142 31143 31144 31145 31146 31147 31148 31149 31150 31151 31152 31153 31154 31155 31156 31157 31158 31159 31160 31161 31162 31163 31164 31165 31166 31167 31168 31169 31170 31171 31172 31173 31174 31175 31176 31177 31178 31179 31180 31181 31182 31183 31184 31185 31186 31187 31188 31189 31190 31191 31192 31193 31194 31195 31196 31197 31198 31199 31200 31201 31202 31203 31204 31205 31206 31207 31208 31209 31210 31211 31212 31213 31214 31215 31216 31217 31218 31219 31220 31221 31222 31223 31224 31225 31226 31227 31228 31229 31230 31231 31232 31233 31234 31235 31236 31237 31238 31239 31240 31241 31242 31243 31244 31245 31246 31247 31248 31249 31250 31251 31252 31253 31254 31255 31256 31257 31258 31259 31260 31261 31262 31263 31264 31265 31266 31267 31268 31269 31270 31271 31272 31273 31274 31275 31276 31277 31278 31279 31280 31281 31282 31283 31284 31285 31286 31287 31288 31289 31290 31291 31292 31293 31294 31295 31296 31297 |
fflush(stdout);
}
/*
** Shorthand for starting a new tree item that consists of a single label
*/
static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
sqlite3TreeViewPush(&p, moreFollows);
sqlite3TreeViewLine(p, "%s", zLabel);
}
/*
** Show a list of Column objects in tree format.
*/
SQLITE_PRIVATE void sqlite3TreeViewColumnList(
TreeView *pView,
const Column *aCol,
int nCol,
u8 moreToFollow
){
int i;
sqlite3TreeViewPush(&pView, moreToFollow);
sqlite3TreeViewLine(pView, "COLUMNS");
for(i=0; i<nCol; i++){
u16 flg = aCol[i].colFlags;
int moreToFollow = i<(nCol - 1);
sqlite3TreeViewPush(&pView, moreToFollow);
sqlite3TreeViewLine(pView, 0);
printf(" %s", aCol[i].zCnName);
switch( aCol[i].eCType ){
case COLTYPE_ANY: printf(" ANY"); break;
case COLTYPE_BLOB: printf(" BLOB"); break;
case COLTYPE_INT: printf(" INT"); break;
case COLTYPE_INTEGER: printf(" INTEGER"); break;
case COLTYPE_REAL: printf(" REAL"); break;
case COLTYPE_TEXT: printf(" TEXT"); break;
case COLTYPE_CUSTOM: {
if( flg & COLFLAG_HASTYPE ){
const char *z = aCol[i].zCnName;
z += strlen(z)+1;
printf(" X-%s", z);
break;
}
}
}
if( flg & COLFLAG_PRIMKEY ) printf(" PRIMARY KEY");
if( flg & COLFLAG_HIDDEN ) printf(" HIDDEN");
#ifdef COLFLAG_NOEXPAND
if( flg & COLFLAG_NOEXPAND ) printf(" NO-EXPAND");
#endif
if( flg ) printf(" flags=%04x", flg);
printf("\n");
fflush(stdout);
sqlite3TreeViewPop(&pView);
}
sqlite3TreeViewPop(&pView);
}
/*
** Generate a human-readable description of a WITH clause.
*/
SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
int i;
if( pWith==0 ) return;
if( pWith->nCte==0 ) return;
if( pWith->pOuter ){
sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter);
}else{
sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith);
}
if( pWith->nCte>0 ){
sqlite3TreeViewPush(&pView, moreToFollow);
for(i=0; i<pWith->nCte; i++){
StrAccum x;
char zLine[1000];
const struct Cte *pCte = &pWith->a[i];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
sqlite3_str_appendf(&x, "%s", pCte->zName);
if( pCte->pCols && pCte->pCols->nExpr>0 ){
char cSep = '(';
int j;
for(j=0; j<pCte->pCols->nExpr; j++){
sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zEName);
cSep = ',';
}
sqlite3_str_appendf(&x, ")");
}
if( pCte->eM10d!=M10d_Any ){
sqlite3_str_appendf(&x, " %sMATERIALIZED",
pCte->eM10d==M10d_No ? "NOT " : "");
}
if( pCte->pUse ){
sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse,
pCte->pUse->nUse);
}
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
sqlite3TreeViewPop(&pView);
}
sqlite3TreeViewPop(&pView);
}
}
/*
** Generate a human-readable description of a SrcList object.
*/
SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
int i;
if( pSrc==0 ) return;
for(i=0; i<pSrc->nSrc; i++){
const SrcItem *pItem = &pSrc->a[i];
StrAccum x;
int n = 0;
char zLine[100];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
x.printfFlags |= SQLITE_PRINTF_INTERNAL;
sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
if( pItem->pTab ){
sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
}
if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){
sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");
}else if( pItem->fg.jointype & JT_LEFT ){
sqlite3_str_appendf(&x, " LEFT-JOIN");
}else if( pItem->fg.jointype & JT_RIGHT ){
sqlite3_str_appendf(&x, " RIGHT-JOIN");
}else if( pItem->fg.jointype & JT_CROSS ){
sqlite3_str_appendf(&x, " CROSS-JOIN");
}
if( pItem->fg.jointype & JT_LTORJ ){
sqlite3_str_appendf(&x, " LTORJ");
}
if( pItem->fg.fromDDL ){
sqlite3_str_appendf(&x, " DDL");
}
if( pItem->fg.isCte ){
sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
}
if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
sqlite3_str_appendf(&x, " ON");
}
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
n = 0;
if( pItem->pSelect ) n++;
if( pItem->fg.isTabFunc ) n++;
if( pItem->fg.isUsing ) n++;
if( pItem->fg.isUsing ){
sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
}
if( pItem->pSelect ){
if( pItem->pTab ){
Table *pTab = pItem->pTab;
sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
}
assert( pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
}
if( pItem->fg.isTabFunc ){
sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
}
sqlite3TreeViewPop(&pView);
}
}
/*
** Generate a human-readable description of a Select object.
*/
SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
int cnt = 0;
if( p==0 ){
sqlite3TreeViewLine(pView, "nil-SELECT");
return;
}
sqlite3TreeViewPush(&pView, moreToFollow);
if( p->pWith ){
sqlite3TreeViewWith(pView, p->pWith, 1);
cnt = 1;
sqlite3TreeViewPush(&pView, 1);
}
do{
if( p->selFlags & SF_WhereBegin ){
sqlite3TreeViewLine(pView, "sqlite3WhereBegin()");
}else{
sqlite3TreeViewLine(pView,
"SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
p->selId, p, p->selFlags,
(int)p->nSelectRow
);
}
if( cnt++ ) sqlite3TreeViewPop(&pView);
if( p->pPrior ){
n = 1000;
}else{
n = 0;
if( p->pSrc && p->pSrc->nSrc ) n++;
if( p->pWhere ) n++;
if( p->pGroupBy ) n++;
|
| ︙ | ︙ | |||
31069 31070 31071 31072 31073 31074 31075 |
if( p->pEList ){
sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set");
}
n--;
#ifndef SQLITE_OMIT_WINDOWFUNC
if( p->pWin ){
Window *pX;
| | | | | | | | | | | | | | | > | | | | | | | | > | | | | | > > > | | 31306 31307 31308 31309 31310 31311 31312 31313 31314 31315 31316 31317 31318 31319 31320 31321 31322 31323 31324 31325 31326 31327 31328 31329 31330 31331 31332 31333 31334 31335 31336 31337 31338 31339 31340 31341 31342 31343 31344 31345 31346 31347 31348 31349 31350 31351 31352 31353 31354 31355 31356 31357 31358 31359 31360 31361 31362 31363 31364 31365 31366 31367 31368 31369 31370 31371 31372 31373 31374 31375 31376 31377 31378 31379 31380 31381 31382 31383 31384 31385 31386 31387 31388 31389 31390 31391 31392 31393 31394 31395 31396 31397 31398 31399 31400 31401 31402 31403 31404 31405 31406 31407 31408 31409 31410 31411 31412 31413 31414 31415 31416 31417 31418 31419 31420 31421 31422 31423 31424 31425 31426 31427 31428 31429 31430 31431 31432 31433 31434 31435 31436 31437 31438 31439 31440 31441 31442 31443 31444 31445 31446 31447 31448 31449 31450 31451 31452 31453 31454 31455 31456 31457 31458 31459 31460 31461 31462 31463 31464 31465 31466 31467 31468 31469 31470 31471 31472 31473 31474 31475 31476 31477 31478 31479 31480 31481 31482 31483 31484 31485 31486 31487 31488 31489 31490 31491 31492 31493 31494 31495 31496 31497 31498 31499 31500 31501 31502 31503 31504 31505 31506 31507 31508 31509 31510 31511 31512 31513 31514 31515 31516 31517 31518 31519 31520 31521 31522 31523 |
if( p->pEList ){
sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set");
}
n--;
#ifndef SQLITE_OMIT_WINDOWFUNC
if( p->pWin ){
Window *pX;
sqlite3TreeViewPush(&pView, (n--)>0);
sqlite3TreeViewLine(pView, "window-functions");
for(pX=p->pWin; pX; pX=pX->pNextWin){
sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0);
}
sqlite3TreeViewPop(&pView);
}
#endif
if( p->pSrc && p->pSrc->nSrc ){
sqlite3TreeViewPush(&pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
sqlite3TreeViewSrcList(pView, p->pSrc);
sqlite3TreeViewPop(&pView);
}
if( p->pWhere ){
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
sqlite3TreeViewExpr(pView, p->pWhere, 0);
sqlite3TreeViewPop(&pView);
}
if( p->pGroupBy ){
sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
}
if( p->pHaving ){
sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
sqlite3TreeViewExpr(pView, p->pHaving, 0);
sqlite3TreeViewPop(&pView);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( p->pWinDefn ){
Window *pX;
sqlite3TreeViewItem(pView, "WINDOW", (n--)>0);
for(pX=p->pWinDefn; pX; pX=pX->pNextWin){
sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0);
}
sqlite3TreeViewPop(&pView);
}
#endif
if( p->pOrderBy ){
sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
}
if( p->pLimit ){
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
if( p->pLimit->pRight ){
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
sqlite3TreeViewPop(&pView);
}
sqlite3TreeViewPop(&pView);
}
if( p->pPrior ){
const char *zOp = "UNION";
switch( p->op ){
case TK_ALL: zOp = "UNION ALL"; break;
case TK_INTERSECT: zOp = "INTERSECT"; break;
case TK_EXCEPT: zOp = "EXCEPT"; break;
}
sqlite3TreeViewItem(pView, zOp, 1);
}
p = p->pPrior;
}while( p!=0 );
sqlite3TreeViewPop(&pView);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** Generate a description of starting or stopping bounds
*/
SQLITE_PRIVATE void sqlite3TreeViewBound(
TreeView *pView, /* View context */
u8 eBound, /* UNBOUNDED, CURRENT, PRECEDING, FOLLOWING */
Expr *pExpr, /* Value for PRECEDING or FOLLOWING */
u8 moreToFollow /* True if more to follow */
){
switch( eBound ){
case TK_UNBOUNDED: {
sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow);
sqlite3TreeViewPop(&pView);
break;
}
case TK_CURRENT: {
sqlite3TreeViewItem(pView, "CURRENT", moreToFollow);
sqlite3TreeViewPop(&pView);
break;
}
case TK_PRECEDING: {
sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow);
sqlite3TreeViewExpr(pView, pExpr, 0);
sqlite3TreeViewPop(&pView);
break;
}
case TK_FOLLOWING: {
sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow);
sqlite3TreeViewExpr(pView, pExpr, 0);
sqlite3TreeViewPop(&pView);
break;
}
}
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** Generate a human-readable explanation for a Window object
*/
SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){
int nElement = 0;
if( pWin==0 ) return;
if( pWin->pFilter ){
sqlite3TreeViewItem(pView, "FILTER", 1);
sqlite3TreeViewExpr(pView, pWin->pFilter, 0);
sqlite3TreeViewPop(&pView);
}
sqlite3TreeViewPush(&pView, more);
if( pWin->zName ){
sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin);
}else{
sqlite3TreeViewLine(pView, "OVER (%p)", pWin);
}
if( pWin->zBase ) nElement++;
if( pWin->pOrderBy ) nElement++;
if( pWin->eFrmType ) nElement++;
if( pWin->eExclude ) nElement++;
if( pWin->zBase ){
sqlite3TreeViewPush(&pView, (--nElement)>0);
sqlite3TreeViewLine(pView, "window: %s", pWin->zBase);
sqlite3TreeViewPop(&pView);
}
if( pWin->pPartition ){
sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY");
}
if( pWin->pOrderBy ){
sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY");
}
if( pWin->eFrmType ){
char zBuf[30];
const char *zFrmType = "ROWS";
if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE";
if( pWin->eFrmType==TK_GROUPS ) zFrmType = "GROUPS";
sqlite3_snprintf(sizeof(zBuf),zBuf,"%s%s",zFrmType,
pWin->bImplicitFrame ? " (implied)" : "");
sqlite3TreeViewItem(pView, zBuf, (--nElement)>0);
sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1);
sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0);
sqlite3TreeViewPop(&pView);
}
if( pWin->eExclude ){
char zBuf[30];
const char *zExclude;
switch( pWin->eExclude ){
case TK_NO: zExclude = "NO OTHERS"; break;
case TK_CURRENT: zExclude = "CURRENT ROW"; break;
case TK_GROUP: zExclude = "GROUP"; break;
case TK_TIES: zExclude = "TIES"; break;
default:
sqlite3_snprintf(sizeof(zBuf),zBuf,"invalid(%d)", pWin->eExclude);
zExclude = zBuf;
break;
}
sqlite3TreeViewPush(&pView, 0);
sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude);
sqlite3TreeViewPop(&pView);
}
sqlite3TreeViewPop(&pView);
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** Generate a human-readable explanation for a Window Function object
*/
SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){
if( pWin==0 ) return;
sqlite3TreeViewPush(&pView, more);
sqlite3TreeViewLine(pView, "WINFUNC %s(%d)",
pWin->pWFunc->zName, pWin->pWFunc->nArg);
sqlite3TreeViewWindow(pView, pWin, 0);
sqlite3TreeViewPop(&pView);
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
/*
** Generate a human-readable explanation of an expression tree.
*/
SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
const char *zBinOp = 0; /* Binary operator */
const char *zUniOp = 0; /* Unary operator */
char zFlgs[200];
sqlite3TreeViewPush(&pView, moreToFollow);
if( pExpr==0 ){
sqlite3TreeViewLine(pView, "nil");
sqlite3TreeViewPop(&pView);
return;
}
if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags ){
StrAccum x;
sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0);
sqlite3_str_appendf(&x, " fg.af=%x.%c",
pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');
if( ExprHasProperty(pExpr, EP_OuterON) ){
sqlite3_str_appendf(&x, " outer.iJoin=%d", pExpr->w.iJoin);
}
if( ExprHasProperty(pExpr, EP_InnerON) ){
sqlite3_str_appendf(&x, " inner.iJoin=%d", pExpr->w.iJoin);
}
if( ExprHasProperty(pExpr, EP_FromDDL) ){
sqlite3_str_appendf(&x, " DDL");
}
if( ExprHasVVAProperty(pExpr, EP_Immutable) ){
sqlite3_str_appendf(&x, " IMMUTABLE");
}
|
| ︙ | ︙ | |||
31491 31492 31493 31494 31495 31496 31497 |
case TK_SELECT: {
assert( ExprUseXSelect(pExpr) );
sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
| > > > > > > > > > | > | 31733 31734 31735 31736 31737 31738 31739 31740 31741 31742 31743 31744 31745 31746 31747 31748 31749 31750 31751 31752 31753 31754 31755 31756 31757 |
case TK_SELECT: {
assert( ExprUseXSelect(pExpr) );
sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
sqlite3_str *pStr = sqlite3_str_new(0);
char *z;
sqlite3_str_appendf(pStr, "IN flags=0x%x", pExpr->flags);
if( pExpr->iTable ) sqlite3_str_appendf(pStr, " iTable=%d",pExpr->iTable);
if( ExprHasProperty(pExpr, EP_Subrtn) ){
sqlite3_str_appendf(pStr, " subrtn(%d,%d)",
pExpr->y.sub.regReturn, pExpr->y.sub.iAddr);
}
z = sqlite3_str_finish(pStr);
sqlite3TreeViewLine(pView, z);
sqlite3_free(z);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
if( ExprUseXSelect(pExpr) ){
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
}else{
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
}
break;
|
| ︙ | ︙ | |||
31615 31616 31617 31618 31619 31620 31621 |
sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
}else if( zUniOp ){
sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
| | | 31867 31868 31869 31870 31871 31872 31873 31874 31875 31876 31877 31878 31879 31880 31881 |
sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
}else if( zUniOp ){
sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
sqlite3TreeViewPop(&pView);
}
/*
** Generate a human-readable explanation of an expression list.
*/
SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
|
| ︙ | ︙ | |||
31637 31638 31639 31640 31641 31642 31643 |
}else{
int i;
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nExpr; i++){
int j = pList->a[i].u.x.iOrderByCol;
char *zName = pList->a[i].zEName;
int moreToFollow = i<pList->nExpr - 1;
| < | > > | > > > > > > > > > > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 31889 31890 31891 31892 31893 31894 31895 31896 31897 31898 31899 31900 31901 31902 31903 31904 31905 31906 31907 31908 31909 31910 31911 31912 31913 31914 31915 31916 31917 31918 31919 31920 31921 31922 31923 31924 31925 31926 31927 31928 31929 31930 31931 31932 31933 31934 31935 31936 31937 31938 31939 31940 31941 31942 31943 31944 31945 31946 31947 31948 31949 31950 31951 31952 31953 31954 31955 31956 31957 31958 31959 31960 31961 31962 31963 31964 31965 31966 31967 31968 31969 31970 31971 31972 31973 31974 31975 31976 31977 31978 31979 31980 31981 31982 31983 31984 31985 31986 31987 31988 31989 31990 31991 31992 31993 31994 31995 31996 31997 31998 31999 32000 32001 32002 32003 32004 32005 32006 32007 32008 32009 32010 32011 32012 32013 32014 32015 32016 32017 32018 32019 32020 32021 32022 32023 32024 32025 32026 32027 32028 32029 32030 32031 32032 32033 32034 32035 32036 32037 32038 32039 32040 32041 32042 32043 32044 32045 32046 32047 32048 32049 32050 32051 32052 32053 32054 32055 32056 32057 32058 32059 32060 32061 32062 32063 32064 32065 32066 32067 32068 32069 32070 32071 32072 32073 32074 32075 32076 32077 32078 32079 32080 32081 32082 32083 32084 32085 32086 32087 32088 32089 32090 32091 32092 32093 32094 32095 32096 32097 32098 32099 32100 32101 32102 32103 32104 32105 32106 32107 32108 32109 32110 32111 32112 32113 32114 32115 32116 32117 32118 32119 32120 32121 32122 32123 32124 32125 32126 32127 32128 32129 32130 32131 32132 32133 32134 32135 32136 32137 32138 32139 32140 32141 32142 32143 32144 32145 32146 32147 32148 32149 32150 32151 32152 32153 32154 32155 32156 32157 32158 32159 32160 32161 32162 32163 32164 32165 32166 32167 32168 32169 32170 32171 32172 32173 32174 32175 32176 32177 32178 32179 32180 32181 32182 32183 32184 32185 32186 32187 32188 32189 32190 32191 32192 32193 32194 32195 32196 32197 32198 32199 32200 32201 32202 32203 32204 32205 32206 32207 32208 32209 32210 32211 32212 32213 32214 32215 32216 32217 32218 32219 32220 32221 32222 32223 32224 32225 32226 32227 32228 32229 32230 32231 32232 32233 32234 32235 32236 32237 32238 32239 32240 32241 32242 32243 32244 32245 32246 32247 32248 32249 32250 32251 32252 32253 32254 32255 32256 32257 32258 32259 32260 32261 32262 32263 32264 32265 32266 32267 32268 32269 32270 32271 32272 32273 32274 32275 32276 32277 32278 32279 32280 32281 32282 32283 32284 32285 32286 32287 32288 32289 32290 32291 32292 32293 32294 32295 32296 32297 32298 32299 32300 32301 32302 32303 32304 32305 32306 32307 |
}else{
int i;
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nExpr; i++){
int j = pList->a[i].u.x.iOrderByCol;
char *zName = pList->a[i].zEName;
int moreToFollow = i<pList->nExpr - 1;
if( j || zName ){
sqlite3TreeViewPush(&pView, moreToFollow);
moreToFollow = 0;
sqlite3TreeViewLine(pView, 0);
if( zName ){
switch( pList->a[i].fg.eEName ){
default:
fprintf(stdout, "AS %s ", zName);
break;
case ENAME_TAB:
fprintf(stdout, "TABLE-ALIAS-NAME(\"%s\") ", zName);
if( pList->a[i].fg.bUsed ) fprintf(stdout, "(used) ");
if( pList->a[i].fg.bUsingTerm ) fprintf(stdout, "(USING-term) ");
if( pList->a[i].fg.bNoExpand ) fprintf(stdout, "(NoExpand) ");
break;
case ENAME_SPAN:
fprintf(stdout, "SPAN(\"%s\") ", zName);
break;
}
}
if( j ){
fprintf(stdout, "iOrderByCol=%d", j);
}
fprintf(stdout, "\n");
fflush(stdout);
}
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
if( j || zName ){
sqlite3TreeViewPop(&pView);
}
}
}
}
SQLITE_PRIVATE void sqlite3TreeViewExprList(
TreeView *pView,
const ExprList *pList,
u8 moreToFollow,
const char *zLabel
){
sqlite3TreeViewPush(&pView, moreToFollow);
sqlite3TreeViewBareExprList(pView, pList, zLabel);
sqlite3TreeViewPop(&pView);
}
/*
** Generate a human-readable explanation of an id-list.
*/
SQLITE_PRIVATE void sqlite3TreeViewBareIdList(
TreeView *pView,
const IdList *pList,
const char *zLabel
){
if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
if( pList==0 ){
sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
}else{
int i;
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nId; i++){
char *zName = pList->a[i].zName;
int moreToFollow = i<pList->nId - 1;
if( zName==0 ) zName = "(null)";
sqlite3TreeViewPush(&pView, moreToFollow);
sqlite3TreeViewLine(pView, 0);
if( pList->eU4==EU4_NONE ){
fprintf(stdout, "%s\n", zName);
}else if( pList->eU4==EU4_IDX ){
fprintf(stdout, "%s (%d)\n", zName, pList->a[i].u4.idx);
}else{
assert( pList->eU4==EU4_EXPR );
if( pList->a[i].u4.pExpr==0 ){
fprintf(stdout, "%s (pExpr=NULL)\n", zName);
}else{
fprintf(stdout, "%s\n", zName);
sqlite3TreeViewPush(&pView, i<pList->nId-1);
sqlite3TreeViewExpr(pView, pList->a[i].u4.pExpr, 0);
sqlite3TreeViewPop(&pView);
}
}
sqlite3TreeViewPop(&pView);
}
}
}
SQLITE_PRIVATE void sqlite3TreeViewIdList(
TreeView *pView,
const IdList *pList,
u8 moreToFollow,
const char *zLabel
){
sqlite3TreeViewPush(&pView, moreToFollow);
sqlite3TreeViewBareIdList(pView, pList, zLabel);
sqlite3TreeViewPop(&pView);
}
/*
** Generate a human-readable explanation of a list of Upsert objects
*/
SQLITE_PRIVATE void sqlite3TreeViewUpsert(
TreeView *pView,
const Upsert *pUpsert,
u8 moreToFollow
){
if( pUpsert==0 ) return;
sqlite3TreeViewPush(&pView, moreToFollow);
while( pUpsert ){
int n;
sqlite3TreeViewPush(&pView, pUpsert->pNextUpsert!=0 || moreToFollow);
sqlite3TreeViewLine(pView, "ON CONFLICT DO %s",
pUpsert->isDoUpdate ? "UPDATE" : "NOTHING");
n = (pUpsert->pUpsertSet!=0) + (pUpsert->pUpsertWhere!=0);
sqlite3TreeViewExprList(pView, pUpsert->pUpsertTarget, (n--)>0, "TARGET");
sqlite3TreeViewExprList(pView, pUpsert->pUpsertSet, (n--)>0, "SET");
if( pUpsert->pUpsertWhere ){
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
sqlite3TreeViewExpr(pView, pUpsert->pUpsertWhere, 0);
sqlite3TreeViewPop(&pView);
}
sqlite3TreeViewPop(&pView);
pUpsert = pUpsert->pNextUpsert;
}
sqlite3TreeViewPop(&pView);
}
/*
** Generate a human-readable diagram of the data structure that go
** into generating an DELETE statement.
*/
SQLITE_PRIVATE void sqlite3TreeViewDelete(
const With *pWith,
const SrcList *pTabList,
const Expr *pWhere,
const ExprList *pOrderBy,
const Expr *pLimit,
const Trigger *pTrigger
){
int n = 0;
TreeView *pView = 0;
sqlite3TreeViewPush(&pView, 0);
sqlite3TreeViewLine(pView, "DELETE");
if( pWith ) n++;
if( pTabList ) n++;
if( pWhere ) n++;
if( pOrderBy ) n++;
if( pLimit ) n++;
if( pTrigger ) n++;
if( pWith ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewWith(pView, pWith, 0);
sqlite3TreeViewPop(&pView);
}
if( pTabList ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewLine(pView, "FROM");
sqlite3TreeViewSrcList(pView, pTabList);
sqlite3TreeViewPop(&pView);
}
if( pWhere ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewLine(pView, "WHERE");
sqlite3TreeViewExpr(pView, pWhere, 0);
sqlite3TreeViewPop(&pView);
}
if( pOrderBy ){
sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
}
if( pLimit ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewLine(pView, "LIMIT");
sqlite3TreeViewExpr(pView, pLimit, 0);
sqlite3TreeViewPop(&pView);
}
if( pTrigger ){
sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
}
sqlite3TreeViewPop(&pView);
}
/*
** Generate a human-readable diagram of the data structure that go
** into generating an INSERT statement.
*/
SQLITE_PRIVATE void sqlite3TreeViewInsert(
const With *pWith,
const SrcList *pTabList,
const IdList *pColumnList,
const Select *pSelect,
const ExprList *pExprList,
int onError,
const Upsert *pUpsert,
const Trigger *pTrigger
){
TreeView *pView = 0;
int n = 0;
const char *zLabel = "INSERT";
switch( onError ){
case OE_Replace: zLabel = "REPLACE"; break;
case OE_Ignore: zLabel = "INSERT OR IGNORE"; break;
case OE_Rollback: zLabel = "INSERT OR ROLLBACK"; break;
case OE_Abort: zLabel = "INSERT OR ABORT"; break;
case OE_Fail: zLabel = "INSERT OR FAIL"; break;
}
sqlite3TreeViewPush(&pView, 0);
sqlite3TreeViewLine(pView, zLabel);
if( pWith ) n++;
if( pTabList ) n++;
if( pColumnList ) n++;
if( pSelect ) n++;
if( pExprList ) n++;
if( pUpsert ) n++;
if( pTrigger ) n++;
if( pWith ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewWith(pView, pWith, 0);
sqlite3TreeViewPop(&pView);
}
if( pTabList ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewLine(pView, "INTO");
sqlite3TreeViewSrcList(pView, pTabList);
sqlite3TreeViewPop(&pView);
}
if( pColumnList ){
sqlite3TreeViewIdList(pView, pColumnList, (--n)>0, "COLUMNS");
}
if( pSelect ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewLine(pView, "DATA-SOURCE");
sqlite3TreeViewSelect(pView, pSelect, 0);
sqlite3TreeViewPop(&pView);
}
if( pExprList ){
sqlite3TreeViewExprList(pView, pExprList, (--n)>0, "VALUES");
}
if( pUpsert ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewLine(pView, "UPSERT");
sqlite3TreeViewUpsert(pView, pUpsert, 0);
sqlite3TreeViewPop(&pView);
}
if( pTrigger ){
sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
}
sqlite3TreeViewPop(&pView);
}
/*
** Generate a human-readable diagram of the data structure that go
** into generating an UPDATE statement.
*/
SQLITE_PRIVATE void sqlite3TreeViewUpdate(
const With *pWith,
const SrcList *pTabList,
const ExprList *pChanges,
const Expr *pWhere,
int onError,
const ExprList *pOrderBy,
const Expr *pLimit,
const Upsert *pUpsert,
const Trigger *pTrigger
){
int n = 0;
TreeView *pView = 0;
const char *zLabel = "UPDATE";
switch( onError ){
case OE_Replace: zLabel = "UPDATE OR REPLACE"; break;
case OE_Ignore: zLabel = "UPDATE OR IGNORE"; break;
case OE_Rollback: zLabel = "UPDATE OR ROLLBACK"; break;
case OE_Abort: zLabel = "UPDATE OR ABORT"; break;
case OE_Fail: zLabel = "UPDATE OR FAIL"; break;
}
sqlite3TreeViewPush(&pView, 0);
sqlite3TreeViewLine(pView, zLabel);
if( pWith ) n++;
if( pTabList ) n++;
if( pChanges ) n++;
if( pWhere ) n++;
if( pOrderBy ) n++;
if( pLimit ) n++;
if( pUpsert ) n++;
if( pTrigger ) n++;
if( pWith ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewWith(pView, pWith, 0);
sqlite3TreeViewPop(&pView);
}
if( pTabList ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewLine(pView, "FROM");
sqlite3TreeViewSrcList(pView, pTabList);
sqlite3TreeViewPop(&pView);
}
if( pChanges ){
sqlite3TreeViewExprList(pView, pChanges, (--n)>0, "SET");
}
if( pWhere ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewLine(pView, "WHERE");
sqlite3TreeViewExpr(pView, pWhere, 0);
sqlite3TreeViewPop(&pView);
}
if( pOrderBy ){
sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
}
if( pLimit ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewLine(pView, "LIMIT");
sqlite3TreeViewExpr(pView, pLimit, 0);
sqlite3TreeViewPop(&pView);
}
if( pUpsert ){
sqlite3TreeViewPush(&pView, (--n)>0);
sqlite3TreeViewLine(pView, "UPSERT");
sqlite3TreeViewUpsert(pView, pUpsert, 0);
sqlite3TreeViewPop(&pView);
}
if( pTrigger ){
sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
}
sqlite3TreeViewPop(&pView);
}
#ifndef SQLITE_OMIT_TRIGGER
/*
** Show a human-readable graph of a TriggerStep
*/
SQLITE_PRIVATE void sqlite3TreeViewTriggerStep(
TreeView *pView,
const TriggerStep *pStep,
u8 moreToFollow,
u8 showFullList
){
int cnt = 0;
if( pStep==0 ) return;
sqlite3TreeViewPush(&pView,
moreToFollow || (showFullList && pStep->pNext!=0));
do{
if( cnt++ && pStep->pNext==0 ){
sqlite3TreeViewPop(&pView);
sqlite3TreeViewPush(&pView, 0);
}
sqlite3TreeViewLine(pView, "%s", pStep->zSpan ? pStep->zSpan : "RETURNING");
}while( showFullList && (pStep = pStep->pNext)!=0 );
sqlite3TreeViewPop(&pView);
}
/*
** Show a human-readable graph of a Trigger
*/
SQLITE_PRIVATE void sqlite3TreeViewTrigger(
TreeView *pView,
const Trigger *pTrigger,
u8 moreToFollow,
u8 showFullList
){
int cnt = 0;
if( pTrigger==0 ) return;
sqlite3TreeViewPush(&pView,
moreToFollow || (showFullList && pTrigger->pNext!=0));
do{
if( cnt++ && pTrigger->pNext==0 ){
sqlite3TreeViewPop(&pView);
sqlite3TreeViewPush(&pView, 0);
}
sqlite3TreeViewLine(pView, "TRIGGER %s", pTrigger->zName);
sqlite3TreeViewPush(&pView, 0);
sqlite3TreeViewTriggerStep(pView, pTrigger->step_list, 0, 1);
sqlite3TreeViewPop(&pView);
}while( showFullList && (pTrigger = pTrigger->pNext)!=0 );
sqlite3TreeViewPop(&pView);
}
#endif /* SQLITE_OMIT_TRIGGER */
/*
** These simplified versions of the tree-view routines omit unnecessary
** parameters. These variants are intended to be used from a symbolic
** debugger, such as "gdb", during interactive debugging sessions.
**
** This routines are given external linkage so that they will always be
** accessible to the debugging, and to avoid warnings about unused
** functions. But these routines only exist in debugging builds, so they
** do not contaminate the interface.
*/
SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); }
SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); }
SQLITE_PRIVATE void sqlite3ShowSelect(const Select *p){ sqlite3TreeViewSelect(0,p,0); }
SQLITE_PRIVATE void sqlite3ShowWith(const With *p){ sqlite3TreeViewWith(0,p,0); }
SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert *p){ sqlite3TreeViewUpsert(0,p,0); }
#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3ShowTriggerStep(const TriggerStep *p){
sqlite3TreeViewTriggerStep(0,p,0,0);
}
SQLITE_PRIVATE void sqlite3ShowTriggerStepList(const TriggerStep *p){
sqlite3TreeViewTriggerStep(0,p,0,1);
}
SQLITE_PRIVATE void sqlite3ShowTrigger(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,0); }
SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,1);}
#endif
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE void sqlite3ShowWindow(const Window *p){ sqlite3TreeViewWindow(0,p,0); }
SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window *p){ sqlite3TreeViewWinFunc(0,p,0); }
#endif
#endif /* SQLITE_DEBUG */
/************** End of treeview.c ********************************************/
/************** Begin file random.c ******************************************/
/*
** 2001 September 15
**
|
| ︙ | ︙ | |||
34703 34704 34705 34706 34707 34708 34709 |
/* 64 */ "Init" OpHelp("Start at P2"),
/* 65 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
/* 66 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
/* 67 */ "Return" OpHelp(""),
/* 68 */ "EndCoroutine" OpHelp(""),
/* 69 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
/* 70 */ "Halt" OpHelp(""),
| < | | | > | | 35328 35329 35330 35331 35332 35333 35334 35335 35336 35337 35338 35339 35340 35341 35342 35343 35344 35345 35346 35347 35348 35349 35350 35351 35352 35353 35354 35355 35356 35357 35358 35359 35360 35361 35362 35363 35364 35365 |
/* 64 */ "Init" OpHelp("Start at P2"),
/* 65 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
/* 66 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
/* 67 */ "Return" OpHelp(""),
/* 68 */ "EndCoroutine" OpHelp(""),
/* 69 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
/* 70 */ "Halt" OpHelp(""),
/* 71 */ "Integer" OpHelp("r[P2]=P1"),
/* 72 */ "Int64" OpHelp("r[P2]=P4"),
/* 73 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
/* 74 */ "BeginSubrtn" OpHelp("r[P2]=NULL"),
/* 75 */ "Null" OpHelp("r[P2..P3]=NULL"),
/* 76 */ "SoftNull" OpHelp("r[P1]=NULL"),
/* 77 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
/* 78 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
/* 79 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
/* 80 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
/* 81 */ "SCopy" OpHelp("r[P2]=r[P1]"),
/* 82 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
/* 83 */ "FkCheck" OpHelp(""),
/* 84 */ "ResultRow" OpHelp("output=r[P1@P2]"),
/* 85 */ "CollSeq" OpHelp(""),
/* 86 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
/* 87 */ "RealAffinity" OpHelp(""),
/* 88 */ "Cast" OpHelp("affinity(r[P1])"),
/* 89 */ "Permutation" OpHelp(""),
/* 90 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
/* 91 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
/* 92 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"),
/* 93 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
/* 94 */ "Column" OpHelp("r[P3]=PX cursor P1 column P2"),
/* 95 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"),
/* 96 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
/* 97 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
/* 98 */ "Count" OpHelp("r[P2]=count()"),
/* 99 */ "ReadCookie" OpHelp(""),
/* 100 */ "SetCookie" OpHelp(""),
/* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
|
| ︙ | ︙ | |||
34767 34768 34769 34770 34771 34772 34773 |
/* 128 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
/* 129 */ "RowCell" OpHelp(""),
/* 130 */ "Delete" OpHelp(""),
/* 131 */ "ResetCount" OpHelp(""),
/* 132 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
/* 133 */ "SorterData" OpHelp("r[P2]=data"),
/* 134 */ "RowData" OpHelp("r[P2]=data"),
| | | 35392 35393 35394 35395 35396 35397 35398 35399 35400 35401 35402 35403 35404 35405 35406 |
/* 128 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
/* 129 */ "RowCell" OpHelp(""),
/* 130 */ "Delete" OpHelp(""),
/* 131 */ "ResetCount" OpHelp(""),
/* 132 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
/* 133 */ "SorterData" OpHelp("r[P2]=data"),
/* 134 */ "RowData" OpHelp("r[P2]=data"),
/* 135 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"),
/* 136 */ "NullRow" OpHelp(""),
/* 137 */ "SeekEnd" OpHelp(""),
/* 138 */ "IdxInsert" OpHelp("key=r[P2]"),
/* 139 */ "SorterInsert" OpHelp("key=r[P2]"),
/* 140 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
/* 141 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
/* 142 */ "IdxRowid" OpHelp("r[P2]=rowid"),
|
| ︙ | ︙ | |||
34811 34812 34813 34814 34815 34816 34817 |
/* 172 */ "VDestroy" OpHelp(""),
/* 173 */ "VOpen" OpHelp(""),
/* 174 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
/* 175 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
/* 176 */ "VRename" OpHelp(""),
/* 177 */ "Pagecount" OpHelp(""),
/* 178 */ "MaxPgcnt" OpHelp(""),
| > | | | | | | | | 35436 35437 35438 35439 35440 35441 35442 35443 35444 35445 35446 35447 35448 35449 35450 35451 35452 35453 35454 35455 35456 35457 |
/* 172 */ "VDestroy" OpHelp(""),
/* 173 */ "VOpen" OpHelp(""),
/* 174 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
/* 175 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
/* 176 */ "VRename" OpHelp(""),
/* 177 */ "Pagecount" OpHelp(""),
/* 178 */ "MaxPgcnt" OpHelp(""),
/* 179 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"),
/* 180 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"),
/* 181 */ "Trace" OpHelp(""),
/* 182 */ "CursorHint" OpHelp(""),
/* 183 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
/* 184 */ "Noop" OpHelp(""),
/* 185 */ "Explain" OpHelp(""),
/* 186 */ "Abortable" OpHelp(""),
};
return azName[i];
}
#endif
/************** End of opcodes.c *********************************************/
/************** Begin file os_unix.c *****************************************/
|
| ︙ | ︙ | |||
41250 41251 41252 41253 41254 41255 41256 |
}else{
*pResOut = osAccess(zPath, W_OK|R_OK)==0;
}
return SQLITE_OK;
}
/*
| | < < > > > > | | | > | < | < < | | > > > > > > > > > > > > > > > > | < < < < < < < | < < < < < < < | < | < < | < < | | | > > > > > > > > > > > | < < < > > > > | < > | | > > > | > | < < < < | < | > | > > > > > | < > > | < < < < > > > | | | < < > > | < > | < | < > < < < < < < < < | < | < < < < < < | < < < < | < < < < < < | < | < < | < < | < < | < < < | < < < < < < < < < < | < < < < | < | | < < < < < | < | < | | < < | 41876 41877 41878 41879 41880 41881 41882 41883 41884 41885 41886 41887 41888 41889 41890 41891 41892 41893 41894 41895 41896 41897 41898 41899 41900 41901 41902 41903 41904 41905 41906 41907 41908 41909 41910 41911 41912 41913 41914 41915 41916 41917 41918 41919 41920 41921 41922 41923 41924 41925 41926 41927 41928 41929 41930 41931 41932 41933 41934 41935 41936 41937 41938 41939 41940 41941 41942 41943 41944 41945 41946 41947 41948 41949 41950 41951 41952 41953 41954 41955 41956 41957 41958 41959 41960 41961 41962 41963 41964 41965 41966 41967 41968 41969 41970 41971 41972 41973 41974 41975 41976 41977 41978 41979 41980 41981 41982 41983 41984 41985 41986 41987 41988 41989 41990 41991 41992 41993 41994 41995 41996 41997 41998 41999 42000 42001 42002 42003 42004 42005 42006 42007 42008 42009 42010 42011 42012 42013 42014 42015 42016 42017 42018 42019 |
}else{
*pResOut = osAccess(zPath, W_OK|R_OK)==0;
}
return SQLITE_OK;
}
/*
** A pathname under construction
*/
typedef struct DbPath DbPath;
struct DbPath {
int rc; /* Non-zero following any error */
int nSymlink; /* Number of symlinks resolved */
char *zOut; /* Write the pathname here */
int nOut; /* Bytes of space available to zOut[] */
int nUsed; /* Bytes of zOut[] currently being used */
};
/* Forward reference */
static void appendAllPathElements(DbPath*,const char*);
/*
** Append a single path element to the DbPath under construction
*/
static void appendOnePathElement(
DbPath *pPath, /* Path under construction, to which to append zName */
const char *zName, /* Name to append to pPath. Not zero-terminated */
int nName /* Number of significant bytes in zName */
){
assert( nName>0 );
assert( zName!=0 );
if( zName[0]=='.' ){
if( nName==1 ) return;
if( zName[1]=='.' && nName==2 ){
if( pPath->nUsed<=1 ){
pPath->rc = SQLITE_ERROR;
return;
}
assert( pPath->zOut[0]=='/' );
while( pPath->zOut[--pPath->nUsed]!='/' ){}
return;
}
}
if( pPath->nUsed + nName + 2 >= pPath->nOut ){
pPath->rc = SQLITE_ERROR;
return;
}
pPath->zOut[pPath->nUsed++] = '/';
memcpy(&pPath->zOut[pPath->nUsed], zName, nName);
pPath->nUsed += nName;
#if defined(HAVE_READLINK) && defined(HAVE_LSTAT)
if( pPath->rc==SQLITE_OK ){
const char *zIn;
struct stat buf;
pPath->zOut[pPath->nUsed] = 0;
zIn = pPath->zOut;
if( osLstat(zIn, &buf)!=0 ){
if( errno!=ENOENT ){
pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
}
}else if( S_ISLNK(buf.st_mode) ){
ssize_t got;
char zLnk[SQLITE_MAX_PATHLEN+2];
if( pPath->nSymlink++ > SQLITE_MAX_SYMLINK ){
pPath->rc = SQLITE_CANTOPEN_BKPT;
return;
}
got = osReadlink(zIn, zLnk, sizeof(zLnk)-2);
if( got<=0 || got>=(ssize_t)sizeof(zLnk)-2 ){
pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
return;
}
zLnk[got] = 0;
if( zLnk[0]=='/' ){
pPath->nUsed = 0;
}else{
pPath->nUsed -= nName + 1;
}
appendAllPathElements(pPath, zLnk);
}
}
#endif
}
/*
** Append all path elements in zPath to the DbPath under construction.
*/
static void appendAllPathElements(
DbPath *pPath, /* Path under construction, to which to append zName */
const char *zPath /* Path to append to pPath. Is zero-terminated */
){
int i = 0;
int j = 0;
do{
while( zPath[i] && zPath[i]!='/' ){ i++; }
if( i>j ){
appendOnePathElement(pPath, &zPath[j], i-j);
}
j = i+1;
}while( zPath[i++] );
}
/*
** Turn a relative pathname into a full pathname. The relative path
** is stored as a nul-terminated string in the buffer pointed to by
** zPath.
**
** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
** (in this case, MAX_PATHNAME bytes). The full-path is written to
** this buffer before returning.
*/
static int unixFullPathname(
sqlite3_vfs *pVfs, /* Pointer to vfs object */
const char *zPath, /* Possibly relative input path */
int nOut, /* Size of output buffer in bytes */
char *zOut /* Output buffer */
){
DbPath path;
UNUSED_PARAMETER(pVfs);
path.rc = 0;
path.nUsed = 0;
path.nSymlink = 0;
path.nOut = nOut;
path.zOut = zOut;
if( zPath[0]!='/' ){
char zPwd[SQLITE_MAX_PATHLEN+2];
if( osGetcwd(zPwd, sizeof(zPwd)-2)==0 ){
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
}
appendAllPathElements(&path, zPwd);
}
appendAllPathElements(&path, zPath);
zOut[path.nUsed] = 0;
if( path.rc || path.nUsed<2 ) return SQLITE_CANTOPEN_BKPT;
if( path.nSymlink ) return SQLITE_OK_SYMLINK;
return SQLITE_OK;
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Interfaces for opening a shared library, finding entry points
** within the shared library, and closing the shared library.
*/
#include <dlfcn.h>
|
| ︙ | ︙ | |||
55886 55887 55888 55889 55890 55891 55892 55893 55894 55895 55896 55897 55898 55899 |
if( currentSize>newSize ){
rc = sqlite3OsTruncate(pPager->fd, newSize);
}else if( (currentSize+szPage)<=newSize ){
char *pTmp = pPager->pTmpSpace;
memset(pTmp, 0, szPage);
testcase( (newSize-szPage) == currentSize );
testcase( (newSize-szPage) > currentSize );
rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
}
if( rc==SQLITE_OK ){
pPager->dbFileSize = nPage;
}
}
}
| > | 56466 56467 56468 56469 56470 56471 56472 56473 56474 56475 56476 56477 56478 56479 56480 |
if( currentSize>newSize ){
rc = sqlite3OsTruncate(pPager->fd, newSize);
}else if( (currentSize+szPage)<=newSize ){
char *pTmp = pPager->pTmpSpace;
memset(pTmp, 0, szPage);
testcase( (newSize-szPage) == currentSize );
testcase( (newSize-szPage) > currentSize );
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &newSize);
rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
}
if( rc==SQLITE_OK ){
pPager->dbFileSize = nPage;
}
}
}
|
| ︙ | ︙ | |||
67862 67863 67864 67865 67866 67867 67868 67869 67870 67871 67872 67873 67874 67875 |
** number of bytes in fragments may not exceed 60. */
if( aData[hdr+7]>57 ) return 0;
/* Remove the slot from the free-list. Update the number of
** fragmented bytes within the page. */
memcpy(&aData[iAddr], &aData[pc], 2);
aData[hdr+7] += (u8)x;
}else if( x+pc > maxPC ){
/* This slot extends off the end of the usable part of the page */
*pRc = SQLITE_CORRUPT_PAGE(pPg);
return 0;
}else{
/* The slot remains on the free-list. Reduce its size to account
** for the portion used by the new allocation. */
| > > | 68443 68444 68445 68446 68447 68448 68449 68450 68451 68452 68453 68454 68455 68456 68457 68458 |
** number of bytes in fragments may not exceed 60. */
if( aData[hdr+7]>57 ) return 0;
/* Remove the slot from the free-list. Update the number of
** fragmented bytes within the page. */
memcpy(&aData[iAddr], &aData[pc], 2);
aData[hdr+7] += (u8)x;
testcase( pc+x>maxPC );
return &aData[pc];
}else if( x+pc > maxPC ){
/* This slot extends off the end of the usable part of the page */
*pRc = SQLITE_CORRUPT_PAGE(pPg);
return 0;
}else{
/* The slot remains on the free-list. Reduce its size to account
** for the portion used by the new allocation. */
|
| ︙ | ︙ | |||
70136 70137 70138 70139 70140 70141 70142 70143 70144 70145 70146 70147 70148 70149 70150 70151 70152 70153 70154 70155 |
*/
if( bCommit==0 ){
eMode = BTALLOC_LE;
iNear = nFin;
}
do {
MemPage *pFreePg;
rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
if( rc!=SQLITE_OK ){
releasePage(pLastPg);
return rc;
}
releasePage(pFreePg);
}while( bCommit && iFreePg>nFin );
assert( iFreePg<iLastPg );
rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
releasePage(pLastPg);
if( rc!=SQLITE_OK ){
return rc;
| > > > > > | 70719 70720 70721 70722 70723 70724 70725 70726 70727 70728 70729 70730 70731 70732 70733 70734 70735 70736 70737 70738 70739 70740 70741 70742 70743 |
*/
if( bCommit==0 ){
eMode = BTALLOC_LE;
iNear = nFin;
}
do {
MemPage *pFreePg;
Pgno dbSize = btreePagecount(pBt);
rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
if( rc!=SQLITE_OK ){
releasePage(pLastPg);
return rc;
}
releasePage(pFreePg);
if( iFreePg>dbSize ){
releasePage(pLastPg);
return SQLITE_CORRUPT_BKPT;
}
}while( bCommit && iFreePg>nFin );
assert( iFreePg<iLastPg );
rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
releasePage(pLastPg);
if( rc!=SQLITE_OK ){
return rc;
|
| ︙ | ︙ | |||
72172 72173 72174 72175 72176 72177 72178 |
if( lwr>upr ) break;
assert( lwr+upr>=0 );
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
}
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
| | | 72760 72761 72762 72763 72764 72765 72766 72767 72768 72769 72770 72771 72772 72773 72774 |
if( lwr>upr ) break;
assert( lwr+upr>=0 );
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
}
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
assert( pCur->ix<pCur->pPage->nCell || CORRUPT_DB );
pCur->ix = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
goto moveto_index_finish;
}
if( lwr>=pPage->nCell ){
chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
| ︙ | ︙ | |||
74696 74697 74698 74699 74700 74701 74702 |
assert(leafCorrection==4);
sz = pParent->xCellSize(pParent, pCell);
}
}
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
| | | 75284 75285 75286 75287 75288 75289 75290 75291 75292 75293 75294 75295 75296 75297 75298 |
assert(leafCorrection==4);
sz = pParent->xCellSize(pParent, pCell);
}
}
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
for(k=0; b.ixNx[k]<=j && ALWAYS(k<NB*2); k++){}
pSrcEnd = b.apEnd[k];
if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
rc = SQLITE_CORRUPT_BKPT;
goto balance_cleanup;
}
insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
if( rc!=SQLITE_OK ) goto balance_cleanup;
|
| ︙ | ︙ | |||
74947 74948 74949 74950 74951 74952 74953 |
**
** balance_quick()
** balance_deeper()
** balance_nonroot()
*/
static int balance(BtCursor *pCur){
int rc = SQLITE_OK;
| < | > > > > | 75535 75536 75537 75538 75539 75540 75541 75542 75543 75544 75545 75546 75547 75548 75549 75550 75551 75552 75553 75554 75555 75556 75557 75558 75559 75560 75561 75562 75563 75564 |
**
** balance_quick()
** balance_deeper()
** balance_nonroot()
*/
static int balance(BtCursor *pCur){
int rc = SQLITE_OK;
u8 aBalanceQuickSpace[13];
u8 *pFree = 0;
VVA_ONLY( int balance_quick_called = 0 );
VVA_ONLY( int balance_deeper_called = 0 );
do {
int iPage;
MemPage *pPage = pCur->pPage;
if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break;
if( pPage->nOverflow==0 && pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){
/* No rebalance required as long as:
** (1) There are no overflow cells
** (2) The amount of free space on the page is less than 2/3rds of
** the total usable space on the page. */
break;
}else if( (iPage = pCur->iPage)==0 ){
if( pPage->nOverflow && (rc = anotherValidCursor(pCur))==SQLITE_OK ){
/* The root page of the b-tree is overfull. In this case call the
** balance_deeper() function to create a new child for the root-page
** and copy the current contents of the root-page to it. The
** next iteration of the do-loop will balance the child page.
|
| ︙ | ︙ | |||
75365 75366 75367 75368 75369 75370 75371 |
}
if( rc ) return rc;
}
TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno,
loc==0 ? "overwrite" : "new entry"));
| | | 75956 75957 75958 75959 75960 75961 75962 75963 75964 75965 75966 75967 75968 75969 75970 |
}
if( rc ) return rc;
}
TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno,
loc==0 ? "overwrite" : "new entry"));
assert( pPage->isInit || CORRUPT_DB );
newCell = pBt->pTmpSpace;
assert( newCell!=0 );
if( flags & BTREE_PREFORMAT ){
rc = SQLITE_OK;
szNew = pBt->nPreformatSize;
if( szNew<4 ) szNew = 4;
if( ISAUTOVACUUM && szNew>pPage->maxLocal ){
|
| ︙ | ︙ | |||
75516 75517 75518 75519 75520 75521 75522 | BtShared *pBt = pDest->pBt; u8 *aOut = pBt->pTmpSpace; /* Pointer to next output buffer */ const u8 *aIn; /* Pointer to next input buffer */ u32 nIn; /* Size of input buffer aIn[] */ u32 nRem; /* Bytes of data still to copy */ getCellInfo(pSrc); | > > > | > | 76107 76108 76109 76110 76111 76112 76113 76114 76115 76116 76117 76118 76119 76120 76121 76122 76123 76124 76125 |
BtShared *pBt = pDest->pBt;
u8 *aOut = pBt->pTmpSpace; /* Pointer to next output buffer */
const u8 *aIn; /* Pointer to next input buffer */
u32 nIn; /* Size of input buffer aIn[] */
u32 nRem; /* Bytes of data still to copy */
getCellInfo(pSrc);
if( pSrc->info.nPayload<0x80 ){
*(aOut++) = pSrc->info.nPayload;
}else{
aOut += sqlite3PutVarint(aOut, pSrc->info.nPayload);
}
if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey);
nIn = pSrc->info.nLocal;
aIn = pSrc->info.pPayload;
if( aIn+nIn>pSrc->pPage->aDataEnd ){
return SQLITE_CORRUPT_BKPT;
}
nRem = pSrc->info.nPayload;
|
| ︙ | ︙ | |||
75773 75774 75775 75776 75777 75778 75779 | ** tricky as the leaf node may be underfull, and the internal node may ** be either under or overfull. In this case run the balancing algorithm ** on the leaf node first. If the balance proceeds far enough up the ** tree that we can be sure that any problem in the internal node has ** been corrected, so be it. Otherwise, after balancing the leaf node, ** walk the cursor up the tree to the internal node and balance it as ** well. */ | > > > > > > > | > | 76368 76369 76370 76371 76372 76373 76374 76375 76376 76377 76378 76379 76380 76381 76382 76383 76384 76385 76386 76387 76388 76389 76390 |
** tricky as the leaf node may be underfull, and the internal node may
** be either under or overfull. In this case run the balancing algorithm
** on the leaf node first. If the balance proceeds far enough up the
** tree that we can be sure that any problem in the internal node has
** been corrected, so be it. Otherwise, after balancing the leaf node,
** walk the cursor up the tree to the internal node and balance it as
** well. */
assert( pCur->pPage->nOverflow==0 );
assert( pCur->pPage->nFree>=0 );
if( pCur->pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){
/* Optimization: If the free space is less than 2/3rds of the page,
** then balance() will always be a no-op. No need to invoke it. */
rc = SQLITE_OK;
}else{
rc = balance(pCur);
}
if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
releasePageNotNull(pCur->pPage);
pCur->iPage--;
while( pCur->iPage>iCellDepth ){
releasePage(pCur->apPage[pCur->iPage--]);
}
pCur->pPage = pCur->apPage[pCur->iPage];
|
| ︙ | ︙ | |||
78268 78269 78270 78271 78272 78273 78274 |
#ifndef SQLITE_OMIT_UTF16
int rc;
#endif
assert( pMem!=0 );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
|| desiredEnc==SQLITE_UTF16BE );
| | > > > > | 78871 78872 78873 78874 78875 78876 78877 78878 78879 78880 78881 78882 78883 78884 78885 78886 78887 78888 78889 |
#ifndef SQLITE_OMIT_UTF16
int rc;
#endif
assert( pMem!=0 );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
|| desiredEnc==SQLITE_UTF16BE );
if( !(pMem->flags&MEM_Str) ){
pMem->enc = desiredEnc;
return SQLITE_OK;
}
if( pMem->enc==desiredEnc ){
return SQLITE_OK;
}
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
#ifdef SQLITE_OMIT_UTF16
return SQLITE_ERROR;
#else
|
| ︙ | ︙ | |||
78517 78518 78519 78520 78521 78522 78523 78524 78525 |
** otherwise.
*/
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
sqlite3_context ctx;
Mem t;
assert( pFunc!=0 );
assert( pMem!=0 );
assert( pFunc->xFinalize!=0 );
assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
| > | > | 79124 79125 79126 79127 79128 79129 79130 79131 79132 79133 79134 79135 79136 79137 79138 79139 79140 79141 79142 79143 79144 79145 79146 79147 79148 79149 |
** otherwise.
*/
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
sqlite3_context ctx;
Mem t;
assert( pFunc!=0 );
assert( pMem!=0 );
assert( pMem->db!=0 );
assert( pFunc->xFinalize!=0 );
assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
assert( sqlite3_mutex_held(pMem->db->mutex) );
memset(&ctx, 0, sizeof(ctx));
memset(&t, 0, sizeof(t));
t.flags = MEM_Null;
t.db = pMem->db;
ctx.pOut = &t;
ctx.pMem = pMem;
ctx.pFunc = pFunc;
ctx.enc = ENC(t.db);
pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
assert( (pMem->flags & MEM_Dyn)==0 );
if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
memcpy(pMem, &t, sizeof(t));
return ctx.isError;
}
|
| ︙ | ︙ | |||
78548 78549 78550 78551 78552 78553 78554 |
*/
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){
sqlite3_context ctx;
assert( pFunc!=0 );
assert( pFunc->xValue!=0 );
assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef );
| > | > | 79157 79158 79159 79160 79161 79162 79163 79164 79165 79166 79167 79168 79169 79170 79171 79172 79173 79174 79175 79176 79177 79178 |
*/
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){
sqlite3_context ctx;
assert( pFunc!=0 );
assert( pFunc->xValue!=0 );
assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef );
assert( pAccum->db!=0 );
assert( sqlite3_mutex_held(pAccum->db->mutex) );
memset(&ctx, 0, sizeof(ctx));
sqlite3VdbeMemSetNull(pOut);
ctx.pOut = pOut;
ctx.pMem = pAccum;
ctx.pFunc = pFunc;
ctx.enc = ENC(pAccum->db);
pFunc->xValue(&ctx);
return ctx.isError;
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
/*
** If the memory cell contains a value that must be freed by
|
| ︙ | ︙ | |||
79171 79172 79173 79174 79175 79176 79177 79178 79179 79180 79181 79182 79183 79184 79185 79186 79187 |
** pointer copied.
**
** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH
** size limit) then no memory allocation occurs. If the string can be
** stored without allocating memory, then it is. If a memory allocation
** is required to store the string, then value of pMem is unchanged. In
** either case, SQLITE_TOOBIG is returned.
*/
SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
Mem *pMem, /* Memory cell to set to string value */
const char *z, /* String pointer */
i64 n, /* Bytes in string, or negative */
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
i64 nByte = n; /* New value for pMem->n */
int iLimit; /* Maximum allowed string or blob size */
| > > > > > > > | > < > > | > > > > > > > > > > > > > > < < < | 79782 79783 79784 79785 79786 79787 79788 79789 79790 79791 79792 79793 79794 79795 79796 79797 79798 79799 79800 79801 79802 79803 79804 79805 79806 79807 79808 79809 79810 79811 79812 79813 79814 79815 79816 79817 79818 79819 79820 79821 79822 79823 79824 79825 79826 79827 79828 79829 79830 79831 79832 79833 79834 79835 79836 79837 79838 79839 79840 79841 79842 79843 79844 79845 79846 79847 79848 79849 79850 79851 79852 79853 79854 79855 79856 79857 79858 79859 79860 79861 79862 79863 79864 79865 |
** pointer copied.
**
** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH
** size limit) then no memory allocation occurs. If the string can be
** stored without allocating memory, then it is. If a memory allocation
** is required to store the string, then value of pMem is unchanged. In
** either case, SQLITE_TOOBIG is returned.
**
** The "enc" parameter is the text encoding for the string, or zero
** to store a blob.
**
** If n is negative, then the string consists of all bytes up to but
** excluding the first zero character. The n parameter must be
** non-negative for blobs.
*/
SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
Mem *pMem, /* Memory cell to set to string value */
const char *z, /* String pointer */
i64 n, /* Bytes in string, or negative */
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
i64 nByte = n; /* New value for pMem->n */
int iLimit; /* Maximum allowed string or blob size */
u16 flags; /* New value for pMem->flags */
assert( pMem!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( enc!=0 || n>=0 );
/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
if( !z ){
sqlite3VdbeMemSetNull(pMem);
return SQLITE_OK;
}
if( pMem->db ){
iLimit = pMem->db->aLimit[SQLITE_LIMIT_LENGTH];
}else{
iLimit = SQLITE_MAX_LENGTH;
}
if( nByte<0 ){
assert( enc!=0 );
if( enc==SQLITE_UTF8 ){
nByte = strlen(z);
}else{
for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
}
flags= MEM_Str|MEM_Term;
}else if( enc==0 ){
flags = MEM_Blob;
enc = SQLITE_UTF8;
}else{
flags = MEM_Str;
}
if( nByte>iLimit ){
if( xDel && xDel!=SQLITE_TRANSIENT ){
if( xDel==SQLITE_DYNAMIC ){
sqlite3DbFree(pMem->db, (void*)z);
}else{
xDel((void*)z);
}
}
sqlite3VdbeMemSetNull(pMem);
return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG);
}
/* The following block sets the new values of Mem.z and Mem.xDel. It
** also sets a flag in local variable "flags" to indicate the memory
** management (one of MEM_Dyn or MEM_Static).
*/
if( xDel==SQLITE_TRANSIENT ){
i64 nAlloc = nByte;
if( flags&MEM_Term ){
nAlloc += (enc==SQLITE_UTF8?1:2);
}
testcase( nAlloc==0 );
testcase( nAlloc==31 );
testcase( nAlloc==32 );
if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){
return SQLITE_NOMEM_BKPT;
}
memcpy(pMem->z, z, nAlloc);
|
| ︙ | ︙ | |||
79242 79243 79244 79245 79246 79247 79248 |
pMem->xDel = xDel;
flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
}
}
pMem->n = (int)(nByte & 0x7fffffff);
pMem->flags = flags;
| < | < < < < < < < < < < < | 79873 79874 79875 79876 79877 79878 79879 79880 79881 79882 79883 79884 79885 79886 79887 79888 79889 79890 79891 79892 79893 79894 |
pMem->xDel = xDel;
flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
}
}
pMem->n = (int)(nByte & 0x7fffffff);
pMem->flags = flags;
pMem->enc = enc;
#ifndef SQLITE_OMIT_UTF16
if( enc>SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
return SQLITE_NOMEM_BKPT;
}
#endif
return SQLITE_OK;
}
/*
** Move data out of a btree key or data field and into a Mem structure.
** The data is payload from the entry that pCur is currently pointing
|
| ︙ | ︙ | |||
79543 79544 79545 79546 79547 79548 79549 79550 79551 79552 79553 79554 79555 79556 |
goto value_from_function_out;
}
assert( pCtx->pParse->rc==SQLITE_OK );
memset(&ctx, 0, sizeof(ctx));
ctx.pOut = pVal;
ctx.pFunc = pFunc;
pFunc->xSFunc(&ctx, nVal, apVal);
if( ctx.isError ){
rc = ctx.isError;
sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal));
}else{
sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8);
assert( rc==SQLITE_OK );
| > | 80162 80163 80164 80165 80166 80167 80168 80169 80170 80171 80172 80173 80174 80175 80176 |
goto value_from_function_out;
}
assert( pCtx->pParse->rc==SQLITE_OK );
memset(&ctx, 0, sizeof(ctx));
ctx.pOut = pVal;
ctx.pFunc = pFunc;
ctx.enc = ENC(db);
pFunc->xSFunc(&ctx, nVal, apVal);
if( ctx.isError ){
rc = ctx.isError;
sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal));
}else{
sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8);
assert( rc==SQLITE_OK );
|
| ︙ | ︙ | |||
79618 79619 79620 79621 79622 79623 79624 |
if( op==TK_CAST ){
u8 aff;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
aff = sqlite3AffinityType(pExpr->u.zToken,0);
rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx);
testcase( rc!=SQLITE_OK );
if( *ppVal ){
| | | | 80238 80239 80240 80241 80242 80243 80244 80245 80246 80247 80248 80249 80250 80251 80252 80253 |
if( op==TK_CAST ){
u8 aff;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
aff = sqlite3AffinityType(pExpr->u.zToken,0);
rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx);
testcase( rc!=SQLITE_OK );
if( *ppVal ){
sqlite3VdbeMemCast(*ppVal, aff, enc);
sqlite3ValueApplyAffinity(*ppVal, affinity, enc);
}
return rc;
}
/* Handle negative integers in a single step. This is needed in the
** case when the value is -9223372036854775808.
*/
|
| ︙ | ︙ | |||
80053 80054 80055 80056 80057 80058 80059 |
p->db = db;
if( db->pVdbe ){
db->pVdbe->pPrev = p;
}
p->pNext = db->pVdbe;
p->pPrev = 0;
db->pVdbe = p;
| | | 80673 80674 80675 80676 80677 80678 80679 80680 80681 80682 80683 80684 80685 80686 80687 |
p->db = db;
if( db->pVdbe ){
db->pVdbe->pPrev = p;
}
p->pNext = db->pVdbe;
p->pPrev = 0;
db->pVdbe = p;
assert( p->eVdbeState==VDBE_INIT_STATE );
p->pParse = pParse;
pParse->pVdbe = p;
assert( pParse->aLabel==0 );
assert( pParse->nLabel==0 );
assert( p->nOpAlloc==0 );
assert( pParse->szOpAlloc==0 );
sqlite3VdbeAddOp2(p, OP_Init, 0, 1);
|
| ︙ | ︙ | |||
80254 80255 80256 80257 80258 80259 80260 |
return sqlite3VdbeAddOp3(p, op, p1, p2, p3);
}
SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
int i;
VdbeOp *pOp;
i = p->nOp;
| | | 80874 80875 80876 80877 80878 80879 80880 80881 80882 80883 80884 80885 80886 80887 80888 |
return sqlite3VdbeAddOp3(p, op, p1, p2, p3);
}
SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
int i;
VdbeOp *pOp;
i = p->nOp;
assert( p->eVdbeState==VDBE_INIT_STATE );
assert( op>=0 && op<0xff );
if( p->nOpAlloc<=i ){
return growOp3(p, op, p1, p2, p3);
}
assert( p->aOp!=0 );
p->nOp++;
pOp = &p->aOp[i];
|
| ︙ | ︙ | |||
80586 80587 80588 80589 80590 80591 80592 |
p->nLabelAlloc = nNewSize;
p->aLabel[j] = v->nOp;
}
}
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){
Parse *p = v->pParse;
int j = ADDR(x);
| | | > > > | > > > | 81206 81207 81208 81209 81210 81211 81212 81213 81214 81215 81216 81217 81218 81219 81220 81221 81222 81223 81224 81225 81226 81227 81228 81229 81230 81231 81232 81233 81234 81235 81236 81237 81238 81239 81240 81241 81242 81243 81244 81245 81246 81247 81248 81249 81250 81251 81252 81253 |
p->nLabelAlloc = nNewSize;
p->aLabel[j] = v->nOp;
}
}
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){
Parse *p = v->pParse;
int j = ADDR(x);
assert( v->eVdbeState==VDBE_INIT_STATE );
assert( j<-p->nLabel );
assert( j>=0 );
#ifdef SQLITE_DEBUG
if( p->db->flags & SQLITE_VdbeAddopTrace ){
printf("RESOLVE LABEL %d to %d\n", x, v->nOp);
}
#endif
if( p->nLabelAlloc + p->nLabel < 0 ){
resizeResolveLabel(p,v,j);
}else{
assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */
p->aLabel[j] = v->nOp;
}
}
/*
** Mark the VDBE as one that can only be run one time.
*/
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){
sqlite3VdbeAddOp2(p, OP_Expire, 1, 1);
}
/*
** Mark the VDBE as one that can only be run multiple times.
*/
SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe *p){
int i;
for(i=1; ALWAYS(i<p->nOp); i++){
if( ALWAYS(p->aOp[i].opcode==OP_Expire) ){
p->aOp[1].opcode = OP_Noop;
break;
}
}
}
#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */
/*
** The following type and function are used to iterate through all opcodes
** in a Vdbe main program and each of the sub-programs (triggers) it may
|
| ︙ | ︙ | |||
80717 80718 80719 80720 80721 80722 80723 80724 80725 80726 80727 80728 80729 80730 |
int hasAbort = 0;
int hasFkCounter = 0;
int hasCreateTable = 0;
int hasCreateIndex = 0;
int hasInitCoroutine = 0;
Op *pOp;
VdbeOpIter sIter;
memset(&sIter, 0, sizeof(sIter));
sIter.v = v;
while( (pOp = opIterNext(&sIter))!=0 ){
int opcode = pOp->opcode;
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
|| opcode==OP_VDestroy
| > > | 81343 81344 81345 81346 81347 81348 81349 81350 81351 81352 81353 81354 81355 81356 81357 81358 |
int hasAbort = 0;
int hasFkCounter = 0;
int hasCreateTable = 0;
int hasCreateIndex = 0;
int hasInitCoroutine = 0;
Op *pOp;
VdbeOpIter sIter;
if( v==0 ) return 0;
memset(&sIter, 0, sizeof(sIter));
sIter.v = v;
while( (pOp = opIterNext(&sIter))!=0 ){
int opcode = pOp->opcode;
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
|| opcode==OP_VDestroy
|
| ︙ | ︙ | |||
80881 80882 80883 80884 80885 80886 80887 |
** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
** have non-negative values for P2. */
assert( (sqlite3OpcodeProperty[pOp->opcode]&OPFLG_JUMP)==0 || pOp->p2>=0);
}
if( pOp==p->aOp ) break;
pOp--;
}
| > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 81509 81510 81511 81512 81513 81514 81515 81516 81517 81518 81519 81520 81521 81522 81523 81524 81525 81526 81527 81528 81529 81530 81531 81532 81533 81534 81535 81536 81537 81538 81539 81540 81541 81542 81543 81544 81545 81546 81547 81548 81549 81550 81551 81552 81553 81554 81555 81556 81557 81558 81559 81560 81561 81562 81563 81564 81565 81566 81567 81568 81569 81570 81571 81572 81573 81574 81575 81576 81577 81578 81579 81580 81581 81582 81583 81584 81585 81586 81587 81588 81589 81590 81591 81592 81593 81594 81595 81596 81597 81598 81599 81600 81601 81602 81603 81604 81605 81606 81607 81608 81609 81610 81611 81612 81613 81614 81615 81616 81617 81618 81619 81620 |
** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
** have non-negative values for P2. */
assert( (sqlite3OpcodeProperty[pOp->opcode]&OPFLG_JUMP)==0 || pOp->p2>=0);
}
if( pOp==p->aOp ) break;
pOp--;
}
if( aLabel ){
sqlite3DbFreeNN(p->db, pParse->aLabel);
pParse->aLabel = 0;
}
pParse->nLabel = 0;
*pMaxFuncArgs = nMaxArgs;
assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
}
#ifdef SQLITE_DEBUG
/*
** Check to see if a subroutine contains a jump to a location outside of
** the subroutine. If a jump outside the subroutine is detected, add code
** that will cause the program to halt with an error message.
**
** The subroutine consists of opcodes between iFirst and iLast. Jumps to
** locations within the subroutine are acceptable. iRetReg is a register
** that contains the return address. Jumps to outside the range of iFirst
** through iLast are also acceptable as long as the jump destination is
** an OP_Return to iReturnAddr.
**
** A jump to an unresolved label means that the jump destination will be
** beyond the current address. That is normally a jump to an early
** termination and is consider acceptable.
**
** This routine only runs during debug builds. The purpose is (of course)
** to detect invalid escapes out of a subroutine. The OP_Halt opcode
** is generated rather than an assert() or other error, so that ".eqp full"
** will still work to show the original bytecode, to aid in debugging.
*/
SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn(
Vdbe *v, /* The byte-code program under construction */
int iFirst, /* First opcode of the subroutine */
int iLast, /* Last opcode of the subroutine */
int iRetReg /* Subroutine return address register */
){
VdbeOp *pOp;
Parse *pParse;
int i;
sqlite3_str *pErr = 0;
assert( v!=0 );
pParse = v->pParse;
assert( pParse!=0 );
if( pParse->nErr ) return;
assert( iLast>=iFirst );
assert( iLast<v->nOp );
pOp = &v->aOp[iFirst];
for(i=iFirst; i<=iLast; i++, pOp++){
if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 ){
int iDest = pOp->p2; /* Jump destination */
if( iDest==0 ) continue;
if( pOp->opcode==OP_Gosub ) continue;
if( iDest<0 ){
int j = ADDR(iDest);
assert( j>=0 );
if( j>=-pParse->nLabel || pParse->aLabel[j]<0 ){
continue;
}
iDest = pParse->aLabel[j];
}
if( iDest<iFirst || iDest>iLast ){
int j = iDest;
for(; j<v->nOp; j++){
VdbeOp *pX = &v->aOp[j];
if( pX->opcode==OP_Return ){
if( pX->p1==iRetReg ) break;
continue;
}
if( pX->opcode==OP_Noop ) continue;
if( pX->opcode==OP_Explain ) continue;
if( pErr==0 ){
pErr = sqlite3_str_new(0);
}else{
sqlite3_str_appendchar(pErr, 1, '\n');
}
sqlite3_str_appendf(pErr,
"Opcode at %d jumps to %d which is outside the "
"subroutine at %d..%d",
i, iDest, iFirst, iLast);
break;
}
}
}
}
if( pErr ){
char *zErr = sqlite3_str_finish(pErr);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_INTERNAL, OE_Abort, 0, zErr, 0);
sqlite3_free(zErr);
sqlite3MayAbort(pParse);
}
}
#endif /* SQLITE_DEBUG */
/*
** Return the address of the next instruction to be inserted.
*/
SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){
assert( p->eVdbeState==VDBE_INIT_STATE );
return p->nOp;
}
/*
** Verify that at least N opcode slots are available in p without
** having to malloc for more space (except when compiled using
** SQLITE_TEST_REALLOC_STRESS). This interface is used during testing
|
| ︙ | ︙ | |||
80977 80978 80979 80980 80981 80982 80983 |
int nOp, /* Number of opcodes to add */
VdbeOpList const *aOp, /* The opcodes to be added */
int iLineno /* Source-file line number of first opcode */
){
int i;
VdbeOp *pOut, *pFirst;
assert( nOp>0 );
| | | 81691 81692 81693 81694 81695 81696 81697 81698 81699 81700 81701 81702 81703 81704 81705 |
int nOp, /* Number of opcodes to add */
VdbeOpList const *aOp, /* The opcodes to be added */
int iLineno /* Source-file line number of first opcode */
){
int i;
VdbeOp *pOut, *pFirst;
assert( nOp>0 );
assert( p->eVdbeState==VDBE_INIT_STATE );
if( p->nOp + nOp > p->nOpAlloc && growOpArray(p, nOp) ){
return 0;
}
pFirst = pOut = &p->aOp[p->nOp];
for(i=0; i<nOp; i++, aOp++, pOut++){
pOut->opcode = aOp->opcode;
pOut->p1 = aOp->p1;
|
| ︙ | ︙ | |||
81168 81169 81170 81171 81172 81173 81174 81175 |
/*
** Free the space allocated for aOp and any p4 values allocated for the
** opcodes contained within. If aOp is not NULL it is assumed to contain
** nOp entries.
*/
static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
if( aOp ){
| > | < > > > | 81882 81883 81884 81885 81886 81887 81888 81889 81890 81891 81892 81893 81894 81895 81896 81897 81898 81899 81900 81901 81902 81903 81904 81905 |
/*
** Free the space allocated for aOp and any p4 values allocated for the
** opcodes contained within. If aOp is not NULL it is assumed to contain
** nOp entries.
*/
static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
assert( nOp>=0 );
if( aOp ){
Op *pOp = &aOp[nOp-1];
while(1){ /* Exit via break */
if( pOp->p4type <= P4_FREE_IF_LE ) freeP4(db, pOp->p4type, pOp->p4.p);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
sqlite3DbFree(db, pOp->zComment);
#endif
if( pOp==aOp ) break;
pOp--;
}
sqlite3DbFreeNN(db, aOp);
}
}
/*
** Link the SubProgram object passed as the second argument into the linked
|
| ︙ | ︙ | |||
81236 81237 81238 81239 81240 81241 81242 |
SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters(
Parse *pParse, /* Parsing context */
int iFirst, /* Index of first register to be released */
int N, /* Number of registers to release */
u32 mask, /* Mask of registers to NOT release */
int bUndefine /* If true, mark registers as undefined */
){
| | | 81953 81954 81955 81956 81957 81958 81959 81960 81961 81962 81963 81964 81965 81966 81967 |
SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters(
Parse *pParse, /* Parsing context */
int iFirst, /* Index of first register to be released */
int N, /* Number of registers to release */
u32 mask, /* Mask of registers to NOT release */
int bUndefine /* If true, mark registers as undefined */
){
if( N==0 || OptimizationDisabled(pParse->db, SQLITE_ReleaseReg) ) return;
assert( pParse->pVdbe );
assert( iFirst>=1 );
assert( iFirst+N-1<=pParse->nMem );
if( N<=31 && mask!=0 ){
while( N>0 && (mask&1)!=0 ){
mask >>= 1;
iFirst++;
|
| ︙ | ︙ | |||
81300 81301 81302 81303 81304 81305 81306 |
}
}
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
Op *pOp;
sqlite3 *db;
assert( p!=0 );
db = p->db;
| | | 82017 82018 82019 82020 82021 82022 82023 82024 82025 82026 82027 82028 82029 82030 82031 |
}
}
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
Op *pOp;
sqlite3 *db;
assert( p!=0 );
db = p->db;
assert( p->eVdbeState==VDBE_INIT_STATE );
assert( p->aOp!=0 || db->mallocFailed );
if( db->mallocFailed ){
if( n!=P4_VTAB ) freeP4(db, n, (void*)*(char**)&zP4);
return;
}
assert( p->nOp>0 );
assert( addr<p->nOp );
|
| ︙ | ︙ | |||
81428 81429 81430 81431 81432 81433 81434 |
** dummy will never be written to. This is verified by code inspection and
** by running with Valgrind.
*/
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
/* C89 specifies that the constant "dummy" will be initialized to all
** zeros, which is correct. MSVC generates a warning, nevertheless. */
static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
| | | 82145 82146 82147 82148 82149 82150 82151 82152 82153 82154 82155 82156 82157 82158 82159 |
** dummy will never be written to. This is verified by code inspection and
** by running with Valgrind.
*/
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
/* C89 specifies that the constant "dummy" will be initialized to all
** zeros, which is correct. MSVC generates a warning, nevertheless. */
static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
assert( p->eVdbeState==VDBE_INIT_STATE );
if( addr<0 ){
addr = p->nOp - 1;
}
assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
if( p->db->mallocFailed ){
return (VdbeOp*)&dummy;
}else{
|
| ︙ | ︙ | |||
81495 81496 81497 81498 81499 81500 81501 |
}
for(ii=0; (c = zSynopsis[ii])!=0; ii++){
if( c=='P' ){
c = zSynopsis[++ii];
if( c=='4' ){
sqlite3_str_appendall(&x, zP4);
}else if( c=='X' ){
| > | | > > | 82212 82213 82214 82215 82216 82217 82218 82219 82220 82221 82222 82223 82224 82225 82226 82227 82228 82229 82230 |
}
for(ii=0; (c = zSynopsis[ii])!=0; ii++){
if( c=='P' ){
c = zSynopsis[++ii];
if( c=='4' ){
sqlite3_str_appendall(&x, zP4);
}else if( c=='X' ){
if( pOp->zComment && pOp->zComment[0] ){
sqlite3_str_appendall(&x, pOp->zComment);
seenCom = 1;
break;
}
}else{
int v1 = translateP(c, pOp);
int v2;
if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){
ii += 3;
v2 = translateP(zSynopsis[ii], pOp);
if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){
|
| ︙ | ︙ | |||
82091 82092 82093 82094 82095 82096 82097 |
*/
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame *p){
int i;
Mem *aMem = VdbeFrameMem(p);
VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
assert( sqlite3VdbeFrameIsValid(p) );
for(i=0; i<p->nChildCsr; i++){
| | | 82811 82812 82813 82814 82815 82816 82817 82818 82819 82820 82821 82822 82823 82824 82825 |
*/
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame *p){
int i;
Mem *aMem = VdbeFrameMem(p);
VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
assert( sqlite3VdbeFrameIsValid(p) );
for(i=0; i<p->nChildCsr; i++){
if( apCsr[i] ) sqlite3VdbeFreeCursorNN(p->v, apCsr[i]);
}
releaseMemArray(aMem, p->nChildMem);
sqlite3VdbeDeleteAuxData(p->v->db, &p->pAuxData, -1, 0);
sqlite3DbFree(p->v->db, p);
}
#ifndef SQLITE_OMIT_EXPLAIN
|
| ︙ | ︙ | |||
82130 82131 82132 82133 82134 82135 82136 | int rc = SQLITE_OK; /* Return code */ Mem *pMem = &p->aMem[1]; /* First Mem of result set */ int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0); Op *aOp; /* Array of opcodes */ Op *pOp; /* Current opcode */ assert( p->explain ); | | | 82850 82851 82852 82853 82854 82855 82856 82857 82858 82859 82860 82861 82862 82863 82864 | int rc = SQLITE_OK; /* Return code */ Mem *pMem = &p->aMem[1]; /* First Mem of result set */ int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0); Op *aOp; /* Array of opcodes */ Op *pOp; /* Current opcode */ assert( p->explain ); assert( p->eVdbeState==VDBE_RUN_STATE ); assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); /* Even though this opcode does not use dynamic strings for ** the result, result columns may become dynamic if the user calls ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ releaseMemArray(pMem, 8); |
| ︙ | ︙ | |||
82285 82286 82287 82288 82289 82290 82291 | ** This allocator is employed to repurpose unused slots at the end of the ** opcode array of prepared state for other memory needs of the prepared ** statement. */ static void *allocSpace( struct ReusableSpace *p, /* Bulk memory available for allocation */ void *pBuf, /* Pointer to a prior allocation */ | | | | > > < | | 83005 83006 83007 83008 83009 83010 83011 83012 83013 83014 83015 83016 83017 83018 83019 83020 83021 83022 83023 83024 83025 83026 83027 83028 83029 83030 83031 83032 83033 83034 83035 83036 83037 83038 83039 83040 83041 83042 83043 83044 83045 83046 83047 83048 83049 83050 83051 83052 |
** This allocator is employed to repurpose unused slots at the end of the
** opcode array of prepared state for other memory needs of the prepared
** statement.
*/
static void *allocSpace(
struct ReusableSpace *p, /* Bulk memory available for allocation */
void *pBuf, /* Pointer to a prior allocation */
sqlite3_int64 nByte /* Bytes of memory needed. */
){
assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) );
if( pBuf==0 ){
nByte = ROUND8P(nByte);
if( nByte <= p->nFree ){
p->nFree -= nByte;
pBuf = &p->pSpace[p->nFree];
}else{
p->nNeeded += nByte;
}
}
assert( EIGHT_BYTE_ALIGNMENT(pBuf) );
return pBuf;
}
/*
** Rewind the VDBE back to the beginning in preparation for
** running it.
*/
SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
int i;
#endif
assert( p!=0 );
assert( p->eVdbeState==VDBE_INIT_STATE
|| p->eVdbeState==VDBE_READY_STATE
|| p->eVdbeState==VDBE_HALT_STATE );
/* There should be at least one opcode.
*/
assert( p->nOp>0 );
p->eVdbeState = VDBE_READY_STATE;
#ifdef SQLITE_DEBUG
for(i=0; i<p->nMem; i++){
assert( p->aMem[i].db==p->db );
}
#endif
p->pc = -1;
|
| ︙ | ︙ | |||
82373 82374 82375 82376 82377 82378 82379 | int nArg; /* Number of arguments in subprograms */ int n; /* Loop counter */ struct ReusableSpace x; /* Reusable bulk memory */ assert( p!=0 ); assert( p->nOp>0 ); assert( pParse!=0 ); | | | 83094 83095 83096 83097 83098 83099 83100 83101 83102 83103 83104 83105 83106 83107 83108 | int nArg; /* Number of arguments in subprograms */ int n; /* Loop counter */ struct ReusableSpace x; /* Reusable bulk memory */ assert( p!=0 ); assert( p->nOp>0 ); assert( pParse!=0 ); assert( p->eVdbeState==VDBE_INIT_STATE ); assert( pParse==p->pParse ); p->pVList = pParse->pVList; pParse->pVList = 0; db = p->db; assert( db->mallocFailed==0 ); nVar = pParse->nVar; nMem = pParse->nMem; |
| ︙ | ︙ | |||
82396 82397 82398 82399 82400 82401 82402 | nMem += nCursor; if( nCursor==0 && nMem>0 ) nMem++; /* Space for aMem[0] even if not used */ /* Figure out how much reusable memory is available at the end of the ** opcode array. This extra memory will be reallocated for other elements ** of the prepared statement. */ | | | 83117 83118 83119 83120 83121 83122 83123 83124 83125 83126 83127 83128 83129 83130 83131 | nMem += nCursor; if( nCursor==0 && nMem>0 ) nMem++; /* Space for aMem[0] even if not used */ /* Figure out how much reusable memory is available at the end of the ** opcode array. This extra memory will be reallocated for other elements ** of the prepared statement. */ n = ROUND8P(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ assert( x.nFree>=0 ); assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); resolveP2Values(p, &nArg); |
| ︙ | ︙ | |||
82484 82485 82486 82487 82488 82489 82490 |
}
/*
** Close a VDBE cursor and release all the resources that cursor
** happens to hold.
*/
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
| | < | > | 83205 83206 83207 83208 83209 83210 83211 83212 83213 83214 83215 83216 83217 83218 83219 83220 83221 |
}
/*
** Close a VDBE cursor and release all the resources that cursor
** happens to hold.
*/
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
if( pCx ) sqlite3VdbeFreeCursorNN(p,pCx);
}
SQLITE_PRIVATE void sqlite3VdbeFreeCursorNN(Vdbe *p, VdbeCursor *pCx){
switch( pCx->eCurType ){
case CURTYPE_SORTER: {
sqlite3VdbeSorterClose(p->db, pCx);
break;
}
case CURTYPE_BTREE: {
assert( pCx->uc.pCursor!=0 );
|
| ︙ | ︙ | |||
82514 82515 82516 82517 82518 82519 82520 |
}
}
/*
** Close all cursors in the current frame.
*/
static void closeCursorsInFrame(Vdbe *p){
| < | | | | | | < | 83235 83236 83237 83238 83239 83240 83241 83242 83243 83244 83245 83246 83247 83248 83249 83250 83251 83252 83253 83254 |
}
}
/*
** Close all cursors in the current frame.
*/
static void closeCursorsInFrame(Vdbe *p){
int i;
for(i=0; i<p->nCursor; i++){
VdbeCursor *pC = p->apCsr[i];
if( pC ){
sqlite3VdbeFreeCursorNN(p, pC);
p->apCsr[i] = 0;
}
}
}
/*
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
** is used, for example, when a trigger sub-program is halted to restore
|
| ︙ | ︙ | |||
82570 82571 82572 82573 82574 82575 82576 |
for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
sqlite3VdbeFrameRestore(pFrame);
p->pFrame = 0;
p->nFrame = 0;
}
assert( p->nFrame==0 );
closeCursorsInFrame(p);
| < | < | 83289 83290 83291 83292 83293 83294 83295 83296 83297 83298 83299 83300 83301 83302 83303 |
for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
sqlite3VdbeFrameRestore(pFrame);
p->pFrame = 0;
p->nFrame = 0;
}
assert( p->nFrame==0 );
closeCursorsInFrame(p);
releaseMemArray(p->aMem, p->nMem);
while( p->pDelFrame ){
VdbeFrame *pDel = p->pDelFrame;
p->pDelFrame = pDel->pParent;
sqlite3VdbeFrameDelete(pDel);
}
/* Delete any auxdata allocations made by the VM */
|
| ︙ | ︙ | |||
83012 83013 83014 83015 83016 83017 83018 83019 83020 83021 83022 83023 83024 83025 |
sqlite3 *db = p->db;
if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0)
|| (!deferred && p->nFkConstraint>0)
){
p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
p->errorAction = OE_Abort;
sqlite3VdbeError(p, "FOREIGN KEY constraint failed");
return SQLITE_CONSTRAINT_FOREIGNKEY;
}
return SQLITE_OK;
}
#endif
/*
| > | 83729 83730 83731 83732 83733 83734 83735 83736 83737 83738 83739 83740 83741 83742 83743 |
sqlite3 *db = p->db;
if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0)
|| (!deferred && p->nFkConstraint>0)
){
p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
p->errorAction = OE_Abort;
sqlite3VdbeError(p, "FOREIGN KEY constraint failed");
if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ) return SQLITE_ERROR;
return SQLITE_CONSTRAINT_FOREIGNKEY;
}
return SQLITE_OK;
}
#endif
/*
|
| ︙ | ︙ | |||
83051 83052 83053 83054 83055 83056 83057 | ** SQLITE_INTERRUPT ** ** Then the internal cache might have been left in an inconsistent ** state. We need to rollback the statement transaction, if there is ** one, or the complete transaction if there is no statement transaction. */ | | < < | | 83769 83770 83771 83772 83773 83774 83775 83776 83777 83778 83779 83780 83781 83782 83783 83784 83785 83786 83787 83788 83789 83790 83791 83792 |
** SQLITE_INTERRUPT
**
** Then the internal cache might have been left in an inconsistent
** state. We need to rollback the statement transaction, if there is
** one, or the complete transaction if there is no statement transaction.
*/
assert( p->eVdbeState==VDBE_RUN_STATE );
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
}
closeAllCursors(p);
checkActiveVdbeCnt(db);
/* No commit or rollback needed if the program never started or if the
** SQL statement does not read or write a database file. */
if( p->bIsReader ){
int mrc; /* Primary error code from p->rc */
int eStatementOp = 0;
int isSpecialError; /* Set to true if a 'special' error */
/* Lock all btrees used by the statement */
sqlite3VdbeEnter(p);
|
| ︙ | ︙ | |||
83210 83211 83212 83213 83214 83215 83216 |
}
/* Release the locks */
sqlite3VdbeLeave(p);
}
/* We have successfully halted and closed the VM. Record this fact. */
| < | | | | | | < | | 83926 83927 83928 83929 83930 83931 83932 83933 83934 83935 83936 83937 83938 83939 83940 83941 83942 83943 83944 83945 83946 |
}
/* Release the locks */
sqlite3VdbeLeave(p);
}
/* We have successfully halted and closed the VM. Record this fact. */
db->nVdbeActive--;
if( !p->readOnly ) db->nVdbeWrite--;
if( p->bIsReader ) db->nVdbeRead--;
assert( db->nVdbeActive>=db->nVdbeRead );
assert( db->nVdbeRead>=db->nVdbeWrite );
assert( db->nVdbeWrite>=0 );
p->eVdbeState = VDBE_HALT_STATE;
checkActiveVdbeCnt(db);
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
}
/* If the auto-commit flag is set to true, then any locks that were held
** by connection db have now been released. Call sqlite3ConnectionUnlocked()
|
| ︙ | ︙ | |||
83300 83301 83302 83303 83304 83305 83306 | ** Clean up a VDBE after execution but do not delete the VDBE just yet. ** Write any error messages into *pzErrMsg. Return the result code. ** ** After this routine is run, the VDBE should be ready to be executed ** again. ** ** To look at it another way, this routine resets the state of the | | | | < < < < < < < | 84014 84015 84016 84017 84018 84019 84020 84021 84022 84023 84024 84025 84026 84027 84028 84029 84030 84031 84032 84033 84034 84035 84036 84037 84038 84039 84040 84041 84042 84043 84044 84045 84046 84047 84048 84049 84050 84051 84052 84053 84054 84055 84056 |
** Clean up a VDBE after execution but do not delete the VDBE just yet.
** Write any error messages into *pzErrMsg. Return the result code.
**
** After this routine is run, the VDBE should be ready to be executed
** again.
**
** To look at it another way, this routine resets the state of the
** virtual machine from VDBE_RUN_STATE or VDBE_HALT_STATE back to
** VDBE_READY_STATE.
*/
SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
int i;
#endif
sqlite3 *db;
db = p->db;
/* If the VM did not run to completion or if it encountered an
** error, then it might not have been halted properly. So halt
** it now.
*/
if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p);
/* If the VDBE has been run even partially, then transfer the error code
** and error message from the VDBE into the main database structure. But
** if the VDBE has just been set to run but has not actually executed any
** instructions yet, leave the main database error information unchanged.
*/
if( p->pc>=0 ){
vdbeInvokeSqllog(p);
if( db->pErr || p->zErrMsg ){
sqlite3VdbeTransferError(p);
}else{
db->errCode = p->rc;
}
}
/* Reset register contents and reclaim error message memory.
*/
#ifdef SQLITE_DEBUG
/* Execute assert() statements to ensure that the Vdbe.apCsr[] and
** Vdbe.aMem[] arrays have already been cleaned up. */
|
| ︙ | ︙ | |||
83392 83393 83394 83395 83396 83397 83398 |
fprintf(out, "%s", zHdr);
sqlite3VdbePrintOp(out, i, &p->aOp[i]);
}
fclose(out);
}
}
#endif
| < > > > | | 84099 84100 84101 84102 84103 84104 84105 84106 84107 84108 84109 84110 84111 84112 84113 84114 84115 84116 84117 84118 84119 84120 84121 84122 84123 84124 84125 |
fprintf(out, "%s", zHdr);
sqlite3VdbePrintOp(out, i, &p->aOp[i]);
}
fclose(out);
}
}
#endif
return p->rc & db->errMask;
}
/*
** Clean up and delete a VDBE after execution. Return an integer which is
** the result code. Write any error message text into *pzErrMsg.
*/
SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){
int rc = SQLITE_OK;
assert( VDBE_RUN_STATE>VDBE_READY_STATE );
assert( VDBE_HALT_STATE>VDBE_READY_STATE );
assert( VDBE_INIT_STATE<VDBE_READY_STATE );
if( p->eVdbeState>=VDBE_READY_STATE ){
rc = sqlite3VdbeReset(p);
assert( (rc & p->db->errMask)==rc );
}
sqlite3VdbeDelete(p);
return rc;
}
|
| ︙ | ︙ | |||
83454 83455 83456 83457 83458 83459 83460 | ** Free all memory associated with the Vdbe passed as the second argument, ** except for object itself, which is preserved. ** ** The difference between this function and sqlite3VdbeDelete() is that ** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with ** the database connection and frees the object itself. */ | | > | > > | | | < | 84163 84164 84165 84166 84167 84168 84169 84170 84171 84172 84173 84174 84175 84176 84177 84178 84179 84180 84181 84182 84183 84184 84185 84186 84187 84188 84189 84190 84191 84192 84193 84194 |
** Free all memory associated with the Vdbe passed as the second argument,
** except for object itself, which is preserved.
**
** The difference between this function and sqlite3VdbeDelete() is that
** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
** the database connection and frees the object itself.
*/
static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
SubProgram *pSub, *pNext;
assert( p->db==0 || p->db==db );
if( p->aColName ){
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
sqlite3DbFreeNN(db, p->aColName);
}
for(pSub=p->pProgram; pSub; pSub=pNext){
pNext = pSub->pNext;
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
sqlite3DbFree(db, pSub);
}
if( p->eVdbeState!=VDBE_INIT_STATE ){
releaseMemArray(p->aVar, p->nVar);
if( p->pVList ) sqlite3DbFreeNN(db, p->pVList);
if( p->pFree ) sqlite3DbFreeNN(db, p->pFree);
}
vdbeFreeOpArray(db, p->aOp, p->nOp);
sqlite3DbFree(db, p->zSql);
#ifdef SQLITE_ENABLE_NORMALIZE
sqlite3DbFree(db, p->zNormSql);
{
DblquoteStr *pThis, *pNext;
for(pThis=p->pDblStr; pThis; pThis=pNext){
pNext = pThis->pNextStr;
|
| ︙ | ︙ | |||
83502 83503 83504 83505 83506 83507 83508 |
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
sqlite3 *db;
assert( p!=0 );
db = p->db;
assert( sqlite3_mutex_held(db->mutex) );
sqlite3VdbeClearObject(db, p);
| > | | | | | | | | | < < > | 84213 84214 84215 84216 84217 84218 84219 84220 84221 84222 84223 84224 84225 84226 84227 84228 84229 84230 84231 84232 84233 84234 84235 84236 84237 |
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
sqlite3 *db;
assert( p!=0 );
db = p->db;
assert( sqlite3_mutex_held(db->mutex) );
sqlite3VdbeClearObject(db, p);
if( db->pnBytesFreed==0 ){
if( p->pPrev ){
p->pPrev->pNext = p->pNext;
}else{
assert( db->pVdbe==p );
db->pVdbe = p->pNext;
}
if( p->pNext ){
p->pNext->pPrev = p->pPrev;
}
}
sqlite3DbFreeNN(db, p);
}
/*
** The cursor "p" has a pending seek operation that has not yet been
** carried out. Seek the cursor now. If an error occurs, return
** the appropriate error code.
|
| ︙ | ︙ | |||
83563 83564 83565 83566 83567 83568 83569 |
}
/*
** Check to ensure that the cursor is valid. Restore the cursor
** if need be. Return any I/O error from the restore operation.
*/
SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){
| | | | 84274 84275 84276 84277 84278 84279 84280 84281 84282 84283 84284 84285 84286 84287 84288 84289 84290 84291 84292 84293 84294 84295 84296 84297 84298 84299 84300 84301 |
}
/*
** Check to ensure that the cursor is valid. Restore the cursor
** if need be. Return any I/O error from the restore operation.
*/
SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){
assert( p->eCurType==CURTYPE_BTREE || IsNullCursor(p) );
if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
return sqlite3VdbeHandleMovedCursor(p);
}
return SQLITE_OK;
}
/*
** The following functions:
**
** sqlite3VdbeSerialType()
** sqlite3VdbeSerialTypeLen()
** sqlite3VdbeSerialLen()
** sqlite3VdbeSerialPut() <--- in-lined into OP_MakeRecord as of 2022-04-02
** sqlite3VdbeSerialGet()
**
** encapsulate the code that serializes values for storage in SQLite
** data and index records. Each serialized value consists of a
** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned
** integer, stored as a varint.
**
|
| ︙ | ︙ | |||
83688 83689 83690 83691 83692 83693 83694 | return ((n*2) + 12 + ((flags&MEM_Str)!=0)); } #endif /* inlined into OP_MakeRecord */ /* ** The sizes for serial types less than 128 */ | | | 84399 84400 84401 84402 84403 84404 84405 84406 84407 84408 84409 84410 84411 84412 84413 |
return ((n*2) + 12 + ((flags&MEM_Str)!=0));
}
#endif /* inlined into OP_MakeRecord */
/*
** The sizes for serial types less than 128
*/
SQLITE_PRIVATE const u8 sqlite3SmallTypeSizes[128] = {
/* 0 1 2 3 4 5 6 7 8 9 */
/* 0 */ 0, 1, 2, 3, 4, 6, 8, 8, 0, 0,
/* 10 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
/* 20 */ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
/* 30 */ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
/* 40 */ 14, 14, 15, 15, 16, 16, 17, 17, 18, 18,
/* 50 */ 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
|
| ︙ | ︙ | |||
83757 83758 83759 83760 83761 83762 83763 | ** the necessary byte swapping is carried out using a 64-bit integer ** rather than a 64-bit float. Frank assures us that the code here ** works for him. We, the developers, have no way to independently ** verify this, but Frank seems to know what he is talking about ** so we trust him. */ #ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT | | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 84468 84469 84470 84471 84472 84473 84474 84475 84476 84477 84478 84479 84480 84481 84482 84483 84484 84485 84486 84487 84488 84489 84490 84491 84492 84493 84494 84495 84496 |
** the necessary byte swapping is carried out using a 64-bit integer
** rather than a 64-bit float. Frank assures us that the code here
** works for him. We, the developers, have no way to independently
** verify this, but Frank seems to know what he is talking about
** so we trust him.
*/
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
SQLITE_PRIVATE u64 sqlite3FloatSwap(u64 in){
union {
u64 r;
u32 i[2];
} u;
u32 t;
u.r = in;
t = u.i[0];
u.i[0] = u.i[1];
u.i[1] = t;
return u.r;
}
#endif /* SQLITE_MIXED_ENDIAN_64BIT_FLOAT */
/* Input "x" is a sequence of unsigned characters that represent a
** big-endian integer. Return the equivalent native integer
*/
#define ONE_BYTE_INT(x) ((i8)(x)[0])
#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1])
#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
|
| ︙ | ︙ | |||
83988 83989 83990 83991 83992 83993 83994 |
** If an OOM error occurs, NULL is returned.
*/
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
KeyInfo *pKeyInfo /* Description of the record */
){
UnpackedRecord *p; /* Unpacked record to return */
int nByte; /* Number of bytes required for *p */
| | | | 84648 84649 84650 84651 84652 84653 84654 84655 84656 84657 84658 84659 84660 84661 84662 84663 84664 84665 |
** If an OOM error occurs, NULL is returned.
*/
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
KeyInfo *pKeyInfo /* Description of the record */
){
UnpackedRecord *p; /* Unpacked record to return */
int nByte; /* Number of bytes required for *p */
nByte = ROUND8P(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1);
p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( !p ) return 0;
p->aMem = (Mem*)&((char*)p)[ROUND8P(sizeof(UnpackedRecord))];
assert( pKeyInfo->aSortFlags!=0 );
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nKeyField + 1;
return p;
}
/*
|
| ︙ | ︙ | |||
84489 84490 84491 84492 84493 84494 84495 |
const unsigned char *aKey1 = (const unsigned char *)pKey1;
Mem mem1;
/* If bSkip is true, then the caller has already determined that the first
** two elements in the keys are equal. Fix the various stack variables so
** that this routine begins comparing at the second field. */
if( bSkip ){
| | > > > | > > | > > > | 85149 85150 85151 85152 85153 85154 85155 85156 85157 85158 85159 85160 85161 85162 85163 85164 85165 85166 85167 85168 85169 85170 85171 85172 85173 85174 85175 85176 85177 85178 |
const unsigned char *aKey1 = (const unsigned char *)pKey1;
Mem mem1;
/* If bSkip is true, then the caller has already determined that the first
** two elements in the keys are equal. Fix the various stack variables so
** that this routine begins comparing at the second field. */
if( bSkip ){
u32 s1 = aKey1[1];
if( s1<0x80 ){
idx1 = 2;
}else{
idx1 = 1 + sqlite3GetVarint32(&aKey1[1], &s1);
}
szHdr1 = aKey1[0];
d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1);
i = 1;
pRhs++;
}else{
if( (szHdr1 = aKey1[0])<0x80 ){
idx1 = 1;
}else{
idx1 = sqlite3GetVarint32(aKey1, &szHdr1);
}
d1 = szHdr1;
i = 0;
}
if( d1>(unsigned)nKey1 ){
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}
|
| ︙ | ︙ | |||
85636 85637 85638 85639 85640 85641 85642 |
static void setResultStrOrError(
sqlite3_context *pCtx, /* Function context */
const char *z, /* String pointer */
int n, /* Bytes in string, or negative */
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
| > | > > > > > | 86304 86305 86306 86307 86308 86309 86310 86311 86312 86313 86314 86315 86316 86317 86318 86319 86320 86321 86322 86323 86324 86325 86326 86327 86328 86329 86330 86331 86332 86333 |
static void setResultStrOrError(
sqlite3_context *pCtx, /* Function context */
const char *z, /* String pointer */
int n, /* Bytes in string, or negative */
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
Mem *pOut = pCtx->pOut;
int rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel);
if( rc ){
if( rc==SQLITE_TOOBIG ){
sqlite3_result_error_toobig(pCtx);
}else{
/* The only errors possible from sqlite3VdbeMemSetStr are
** SQLITE_TOOBIG and SQLITE_NOMEM */
assert( rc==SQLITE_NOMEM );
sqlite3_result_error_nomem(pCtx);
}
return;
}
sqlite3VdbeChangeEncoding(pOut, pCtx->enc);
if( sqlite3VdbeMemTooBig(pOut) ){
sqlite3_result_error_toobig(pCtx);
}
}
static int invokeValueDestructor(
const void *p, /* Value to destroy */
void (*xDel)(void*), /* The destructor */
sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if no NULL */
){
|
| ︙ | ︙ | |||
85789 85790 85791 85792 85793 85794 85795 85796 |
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel);
}
#endif /* SQLITE_OMIT_UTF16 */
SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
| > | > > > | > | < > | | | 86463 86464 86465 86466 86467 86468 86469 86470 86471 86472 86473 86474 86475 86476 86477 86478 86479 86480 86481 86482 86483 86484 86485 86486 86487 86488 86489 86490 86491 86492 86493 86494 86495 86496 86497 86498 86499 86500 86501 86502 86503 86504 86505 86506 86507 86508 86509 |
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel);
}
#endif /* SQLITE_OMIT_UTF16 */
SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
Mem *pOut = pCtx->pOut;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemCopy(pOut, pValue);
sqlite3VdbeChangeEncoding(pOut, pCtx->enc);
if( sqlite3VdbeMemTooBig(pOut) ){
sqlite3_result_error_toobig(pCtx);
}
}
SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
sqlite3_result_zeroblob64(pCtx, n>0 ? n : 0);
}
SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){
Mem *pOut = pCtx->pOut;
assert( sqlite3_mutex_held(pOut->db->mutex) );
if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(pCtx);
return SQLITE_TOOBIG;
}
#ifndef SQLITE_OMIT_INCRBLOB
sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
return SQLITE_OK;
#else
return sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
#endif
}
SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
pCtx->isError = errCode ? errCode : -1;
#ifdef SQLITE_DEBUG
if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
#endif
if( pCtx->pOut->flags & MEM_Null ){
setResultStrOrError(pCtx, sqlite3ErrStr(errCode), -1, SQLITE_UTF8,
SQLITE_STATIC);
}
}
/* Force an SQLITE_TOOBIG error. */
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
pCtx->isError = SQLITE_TOOBIG;
|
| ︙ | ︙ | |||
85890 85891 85892 85893 85894 85895 85896 |
** outer sqlite3_step() wrapper procedure.
*/
static int sqlite3Step(Vdbe *p){
sqlite3 *db;
int rc;
assert(p);
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | 86569 86570 86571 86572 86573 86574 86575 86576 86577 86578 86579 86580 86581 86582 86583 86584 86585 86586 86587 86588 86589 86590 86591 86592 86593 86594 86595 86596 86597 86598 86599 86600 86601 86602 86603 86604 86605 86606 86607 86608 86609 86610 86611 86612 86613 86614 86615 86616 86617 86618 86619 86620 86621 86622 86623 86624 86625 86626 86627 86628 86629 86630 86631 86632 86633 86634 86635 86636 86637 86638 86639 86640 86641 86642 86643 86644 86645 86646 86647 86648 86649 86650 86651 86652 86653 86654 86655 86656 86657 86658 86659 86660 86661 86662 86663 86664 86665 86666 86667 86668 86669 86670 86671 86672 86673 86674 86675 86676 86677 86678 86679 |
** outer sqlite3_step() wrapper procedure.
*/
static int sqlite3Step(Vdbe *p){
sqlite3 *db;
int rc;
assert(p);
db = p->db;
if( p->eVdbeState!=VDBE_RUN_STATE ){
restart_step:
if( p->eVdbeState==VDBE_READY_STATE ){
if( p->expired ){
p->rc = SQLITE_SCHEMA;
rc = SQLITE_ERROR;
if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){
/* If this statement was prepared using saved SQL and an
** error has occurred, then return the error code in p->rc to the
** caller. Set the error code in the database handle to the same
** value.
*/
rc = sqlite3VdbeTransferError(p);
}
goto end_of_step;
}
/* If there are no other statements currently running, then
** reset the interrupt flag. This prevents a call to sqlite3_interrupt
** from interrupting a statement that has not yet started.
*/
if( db->nVdbeActive==0 ){
AtomicStore(&db->u1.isInterrupted, 0);
}
assert( db->nVdbeWrite>0 || db->autoCommit==0
|| (db->nDeferredCons==0 && db->nDeferredImmCons==0)
);
#ifndef SQLITE_OMIT_TRACE
if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0
&& !db->init.busy && p->zSql ){
sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
}else{
assert( p->startTime==0 );
}
#endif
db->nVdbeActive++;
if( p->readOnly==0 ) db->nVdbeWrite++;
if( p->bIsReader ) db->nVdbeRead++;
p->pc = 0;
p->eVdbeState = VDBE_RUN_STATE;
}else
if( ALWAYS(p->eVdbeState==VDBE_HALT_STATE) ){
/* We used to require that sqlite3_reset() be called before retrying
** sqlite3_step() after any error or after SQLITE_DONE. But beginning
** with version 3.7.0, we changed this so that sqlite3_reset() would
** be called automatically instead of throwing the SQLITE_MISUSE error.
** This "automatic-reset" change is not technically an incompatibility,
** since any application that receives an SQLITE_MISUSE is broken by
** definition.
**
** Nevertheless, some published applications that were originally written
** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
** returns, and those were broken by the automatic-reset change. As a
** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
** legacy behavior of returning SQLITE_MISUSE for cases where the
** previous sqlite3_step() returned something other than a SQLITE_LOCKED
** or SQLITE_BUSY error.
*/
#ifdef SQLITE_OMIT_AUTORESET
if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){
sqlite3_reset((sqlite3_stmt*)p);
}else{
return SQLITE_MISUSE_BKPT;
}
#else
sqlite3_reset((sqlite3_stmt*)p);
#endif
assert( p->eVdbeState==VDBE_READY_STATE );
goto restart_step;
}
}
#ifdef SQLITE_DEBUG
p->rcApp = SQLITE_OK;
#endif
#ifndef SQLITE_OMIT_EXPLAIN
if( p->explain ){
rc = sqlite3VdbeList(p);
}else
#endif /* SQLITE_OMIT_EXPLAIN */
{
db->nVdbeExec++;
rc = sqlite3VdbeExec(p);
db->nVdbeExec--;
}
if( rc==SQLITE_ROW ){
assert( p->rc==SQLITE_OK );
assert( db->mallocFailed==0 );
db->errCode = SQLITE_ROW;
return SQLITE_ROW;
}else{
#ifndef SQLITE_OMIT_TRACE
/* If the statement completed successfully, invoke the profile callback */
checkProfileCallback(db, p);
#endif
if( rc==SQLITE_DONE && db->autoCommit ){
assert( p->rc==SQLITE_OK );
|
| ︙ | ︙ | |||
86030 86031 86032 86033 86034 86035 86036 |
sqlite3 *db; /* The database connection */
if( vdbeSafetyNotNull(v) ){
return SQLITE_MISUSE_BKPT;
}
db = v->db;
sqlite3_mutex_enter(db->mutex);
| < | 86717 86718 86719 86720 86721 86722 86723 86724 86725 86726 86727 86728 86729 86730 |
sqlite3 *db; /* The database connection */
if( vdbeSafetyNotNull(v) ){
return SQLITE_MISUSE_BKPT;
}
db = v->db;
sqlite3_mutex_enter(db->mutex);
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < SQLITE_MAX_SCHEMA_RETRY ){
int savedPc = v->pc;
rc = sqlite3Reprepare(v);
if( rc!=SQLITE_OK ){
/* This case occurs after failing to recompile an sql statement.
** The error message from the SQL compiler has already been loaded
|
| ︙ | ︙ | |||
86056 86057 86058 86059 86060 86061 86062 |
} else {
v->zErrMsg = 0;
v->rc = rc = SQLITE_NOMEM_BKPT;
}
break;
}
sqlite3_reset(pStmt);
| | > > > > > > | 86742 86743 86744 86745 86746 86747 86748 86749 86750 86751 86752 86753 86754 86755 86756 86757 86758 86759 86760 86761 86762 |
} else {
v->zErrMsg = 0;
v->rc = rc = SQLITE_NOMEM_BKPT;
}
break;
}
sqlite3_reset(pStmt);
if( savedPc>=0 ){
/* Setting minWriteFileFormat to 254 is a signal to the OP_Init and
** OP_Trace opcodes to *not* perform SQLITE_TRACE_STMT because one
** should output has already occurred due to SQLITE_SCHEMA.
** tag-20220401a */
v->minWriteFileFormat = 254;
}
assert( v->expired==0 );
}
sqlite3_mutex_leave(db->mutex);
return rc;
}
|
| ︙ | ︙ | |||
86670 86671 86672 86673 86674 86675 86676 |
*/
static int vdbeUnbind(Vdbe *p, int i){
Mem *pVar;
if( vdbeSafetyNotNull(p) ){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(p->db->mutex);
| | | 87362 87363 87364 87365 87366 87367 87368 87369 87370 87371 87372 87373 87374 87375 87376 |
*/
static int vdbeUnbind(Vdbe *p, int i){
Mem *pVar;
if( vdbeSafetyNotNull(p) ){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(p->db->mutex);
if( p->eVdbeState!=VDBE_READY_STATE ){
sqlite3Error(p->db, SQLITE_MISUSE);
sqlite3_mutex_leave(p->db->mutex);
sqlite3_log(SQLITE_MISUSE,
"bind on a busy prepared statement: [%s]", p->zSql);
return SQLITE_MISUSE_BKPT;
}
if( i<1 || i>p->nVar ){
|
| ︙ | ︙ | |||
87023 87024 87025 87026 87027 87028 87029 |
}
/*
** Return true if the prepared statement is in need of being reset.
*/
SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
Vdbe *v = (Vdbe*)pStmt;
| | | 87715 87716 87717 87718 87719 87720 87721 87722 87723 87724 87725 87726 87727 87728 87729 |
}
/*
** Return true if the prepared statement is in need of being reset.
*/
SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
Vdbe *v = (Vdbe*)pStmt;
return v!=0 && v->eVdbeState==VDBE_RUN_STATE;
}
/*
** Return a pointer to the next prepared statement after pStmt associated
** with database connection pDb. If pStmt is NULL, return the first
** prepared statement for the database connection. Return NULL if there
** are no more.
|
| ︙ | ︙ | |||
87069 87070 87071 87072 87073 87074 87075 |
}
#endif
if( op==SQLITE_STMTSTATUS_MEMUSED ){
sqlite3 *db = pVdbe->db;
sqlite3_mutex_enter(db->mutex);
v = 0;
db->pnBytesFreed = (int*)&v;
| | < | 87761 87762 87763 87764 87765 87766 87767 87768 87769 87770 87771 87772 87773 87774 87775 |
}
#endif
if( op==SQLITE_STMTSTATUS_MEMUSED ){
sqlite3 *db = pVdbe->db;
sqlite3_mutex_enter(db->mutex);
v = 0;
db->pnBytesFreed = (int*)&v;
sqlite3VdbeDelete(pVdbe);
db->pnBytesFreed = 0;
sqlite3_mutex_leave(db->mutex);
}else{
v = pVdbe->aCounter[op];
if( resetFlag ) pVdbe->aCounter[op] = 0;
}
return (int)v;
|
| ︙ | ︙ | |||
87863 87864 87865 87866 87867 87868 87869 | ** Cursor 2 is at Mem[p->nMem-2]. And so forth. */ Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem; int nByte; VdbeCursor *pCx = 0; nByte = | | | | 88554 88555 88556 88557 88558 88559 88560 88561 88562 88563 88564 88565 88566 88567 88568 88569 88570 88571 88572 88573 |
** Cursor 2 is at Mem[p->nMem-2]. And so forth.
*/
Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem;
int nByte;
VdbeCursor *pCx = 0;
nByte =
ROUND8P(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
(eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
assert( iCur>=0 && iCur<p->nCursor );
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
sqlite3VdbeFreeCursorNN(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
/* There used to be a call to sqlite3VdbeMemClearAndResize() to make sure
** the pMem used to hold space for the cursor has enough storage available
** in pMem->zMalloc. But for the special case of the aMem[] entries used
** to hold cursors, it is faster to in-line the logic. */
|
| ︙ | ︙ | |||
87898 87899 87900 87901 87902 87903 87904 |
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
pCx->eCurType = eCurType;
pCx->nField = nField;
pCx->aOffset = &pCx->aType[nField];
if( eCurType==CURTYPE_BTREE ){
pCx->uc.pCursor = (BtCursor*)
| | | 88589 88590 88591 88592 88593 88594 88595 88596 88597 88598 88599 88600 88601 88602 88603 |
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
pCx->eCurType = eCurType;
pCx->nField = nField;
pCx->aOffset = &pCx->aType[nField];
if( eCurType==CURTYPE_BTREE ){
pCx->uc.pCursor = (BtCursor*)
&pMem->z[ROUND8P(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
sqlite3BtreeCursorZero(pCx->uc.pCursor);
}
return pCx;
}
/*
** The string in pRec is known to look like an integer and to have a
|
| ︙ | ︙ | |||
88337 88338 88339 88340 88341 88342 88343 | Mem *pIn3 = 0; /* 3rd input operand */ Mem *pOut = 0; /* Output operand */ #ifdef VDBE_PROFILE u64 start; /* CPU clock count at start of opcode */ #endif /*** INSERT STACK UNION HERE ***/ | | | 89028 89029 89030 89031 89032 89033 89034 89035 89036 89037 89038 89039 89040 89041 89042 |
Mem *pIn3 = 0; /* 3rd input operand */
Mem *pOut = 0; /* Output operand */
#ifdef VDBE_PROFILE
u64 start; /* CPU clock count at start of opcode */
#endif
/*** INSERT STACK UNION HERE ***/
assert( p->eVdbeState==VDBE_RUN_STATE ); /* sqlite3_step() verifies this */
sqlite3VdbeEnter(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( db->xProgress ){
u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
assert( 0 < db->nProgressOps );
nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
}else{
|
| ︙ | ︙ | |||
88580 88581 88582 88583 88584 88585 88586 | assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); pIn1 = &aMem[pOp->p1]; assert( VdbeMemDynamic(pIn1)==0 ); memAboutToChange(p, pIn1); pIn1->flags = MEM_Int; pIn1->u.i = (int)(pOp-aOp); REGISTER_TRACE(pOp->p1, pIn1); | < < < | < < | | > > > > > > > > > | | < > > > > > | | > | < > > > | 89271 89272 89273 89274 89275 89276 89277 89278 89279 89280 89281 89282 89283 89284 89285 89286 89287 89288 89289 89290 89291 89292 89293 89294 89295 89296 89297 89298 89299 89300 89301 89302 89303 89304 89305 89306 89307 89308 89309 89310 89311 89312 89313 89314 89315 89316 89317 |
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
pIn1 = &aMem[pOp->p1];
assert( VdbeMemDynamic(pIn1)==0 );
memAboutToChange(p, pIn1);
pIn1->flags = MEM_Int;
pIn1->u.i = (int)(pOp-aOp);
REGISTER_TRACE(pOp->p1, pIn1);
goto jump_to_p2_and_check_for_interrupt;
}
/* Opcode: Return P1 P2 P3 * *
**
** Jump to the address stored in register P1. If P1 is a return address
** register, then this accomplishes a return from a subroutine.
**
** If P3 is 1, then the jump is only taken if register P1 holds an integer
** values, otherwise execution falls through to the next opcode, and the
** OP_Return becomes a no-op. If P3 is 0, then register P1 must hold an
** integer or else an assert() is raised. P3 should be set to 1 when
** this opcode is used in combination with OP_BeginSubrtn, and set to 0
** otherwise.
**
** The value in register P1 is unchanged by this opcode.
**
** P2 is not used by the byte-code engine. However, if P2 is positive
** and also less than the current address, then the "EXPLAIN" output
** formatter in the CLI will indent all opcodes from the P2 opcode up
** to be not including the current Return. P2 should be the first opcode
** in the subroutine from which this opcode is returnning. Thus the P2
** value is a byte-code indentation hint. See tag-20220407a in
** wherecode.c and shell.c.
*/
case OP_Return: { /* in1 */
pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Int ){
if( pOp->p3 ){ VdbeBranchTaken(1, 2); }
pOp = &aOp[pIn1->u.i];
}else if( ALWAYS(pOp->p3) ){
VdbeBranchTaken(0, 2);
}
break;
}
/* Opcode: InitCoroutine P1 P2 P3 * *
**
** Set up register P1 so that it will Yield to the coroutine
** located at address P3.
|
| ︙ | ︙ | |||
88624 88625 88626 88627 88628 88629 88630 | assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); assert( pOp->p2>=0 && pOp->p2<p->nOp ); assert( pOp->p3>=0 && pOp->p3<p->nOp ); pOut = &aMem[pOp->p1]; assert( !VdbeMemDynamic(pOut) ); pOut->u.i = pOp->p3 - 1; pOut->flags = MEM_Int; | > > > > | > > > | 89326 89327 89328 89329 89330 89331 89332 89333 89334 89335 89336 89337 89338 89339 89340 89341 89342 89343 89344 89345 89346 89347 | assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); assert( pOp->p2>=0 && pOp->p2<p->nOp ); assert( pOp->p3>=0 && pOp->p3<p->nOp ); pOut = &aMem[pOp->p1]; assert( !VdbeMemDynamic(pOut) ); pOut->u.i = pOp->p3 - 1; pOut->flags = MEM_Int; if( pOp->p2==0 ) break; /* Most jump operations do a goto to this spot in order to update ** the pOp pointer. */ jump_to_p2: assert( pOp->p2>0 ); /* There are never any jumps to instruction 0 */ assert( pOp->p2<p->nOp ); /* Jumps must be in range */ pOp = &aOp[pOp->p2 - 1]; break; } /* Opcode: EndCoroutine P1 * * * * ** ** The instruction at the address in register P1 is a Yield. ** Jump to the P2 parameter of that Yield. |
| ︙ | ︙ | |||
88726 88727 88728 88729 88730 88731 88732 |
** every program. So a jump past the last instruction of the program
** is the same as executing Halt.
*/
case OP_Halt: {
VdbeFrame *pFrame;
int pcx;
| < | | 89435 89436 89437 89438 89439 89440 89441 89442 89443 89444 89445 89446 89447 89448 89449 89450 89451 89452 |
** every program. So a jump past the last instruction of the program
** is the same as executing Halt.
*/
case OP_Halt: {
VdbeFrame *pFrame;
int pcx;
#ifdef SQLITE_DEBUG
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif
if( p->pFrame && pOp->p1==SQLITE_OK ){
/* Halt the sub-program. Return control to the parent frame. */
pFrame = p->pFrame;
p->pFrame = pFrame->pParent;
p->nFrame--;
sqlite3VdbeSetChanges(db, p->nChange);
pcx = sqlite3VdbeFrameRestore(pFrame);
if( pOp->p2==OE_Ignore ){
|
| ︙ | ︙ | |||
88752 88753 88754 88755 88756 88757 88758 |
aOp = p->aOp;
aMem = p->aMem;
pOp = &aOp[pcx];
break;
}
p->rc = pOp->p1;
p->errorAction = (u8)pOp->p2;
| < > < < < < < < < < < < < | 89460 89461 89462 89463 89464 89465 89466 89467 89468 89469 89470 89471 89472 89473 89474 89475 89476 89477 89478 89479 89480 89481 89482 89483 89484 89485 89486 89487 89488 89489 89490 89491 89492 89493 89494 89495 89496 89497 89498 89499 89500 89501 89502 89503 89504 89505 89506 89507 89508 89509 |
aOp = p->aOp;
aMem = p->aMem;
pOp = &aOp[pcx];
break;
}
p->rc = pOp->p1;
p->errorAction = (u8)pOp->p2;
assert( pOp->p5<=4 );
if( p->rc ){
if( pOp->p5 ){
static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
"FOREIGN KEY" };
testcase( pOp->p5==1 );
testcase( pOp->p5==2 );
testcase( pOp->p5==3 );
testcase( pOp->p5==4 );
sqlite3VdbeError(p, "%s constraint failed", azType[pOp->p5-1]);
if( pOp->p4.z ){
p->zErrMsg = sqlite3MPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z);
}
}else{
sqlite3VdbeError(p, "%s", pOp->p4.z);
}
pcx = (int)(pOp - aOp);
sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
if( rc==SQLITE_BUSY ){
p->rc = SQLITE_BUSY;
}else{
assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 );
rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
}
goto vdbe_return;
}
/* Opcode: Integer P1 P2 * * *
** Synopsis: r[P2]=P1
**
** The 32-bit integer value P1 is written into register P2.
*/
case OP_Integer: { /* out2 */
pOut = out2Prerelease(p, pOp);
pOut->u.i = pOp->p1;
break;
}
/* Opcode: Int64 * P2 * P4 *
|
| ︙ | ︙ | |||
88905 88906 88907 88908 88909 88910 88911 88912 88913 88914 88915 88916 88917 88918 88919 88920 88921 88922 88923 88924 88925 88926 88927 88928 88929 88930 |
assert( pIn3->flags & MEM_Int );
if( pIn3->u.i==pOp->p5 ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
}
#endif
break;
}
/* Opcode: Null P1 P2 P3 * *
** Synopsis: r[P2..P3]=NULL
**
** Write a NULL into registers P2. If P3 greater than P2, then also write
** NULL into register P3 and every register in between P2 and P3. If P3
** is less than P2 (typically P3 is zero) then only register P2 is
** set to NULL.
**
** If the P1 value is non-zero, then also set the MEM_Cleared flag so that
** NULL values will not compare equal even if SQLITE_NULLEQ is set on
** OP_Ne or OP_Eq.
*/
case OP_Null: { /* out2 */
int cnt;
u16 nullFlag;
pOut = out2Prerelease(p, pOp);
cnt = pOp->p3-pOp->p2;
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
| > > > > > > > > > > > > > > > > > > > > > > > | 89602 89603 89604 89605 89606 89607 89608 89609 89610 89611 89612 89613 89614 89615 89616 89617 89618 89619 89620 89621 89622 89623 89624 89625 89626 89627 89628 89629 89630 89631 89632 89633 89634 89635 89636 89637 89638 89639 89640 89641 89642 89643 89644 89645 89646 89647 89648 89649 89650 |
assert( pIn3->flags & MEM_Int );
if( pIn3->u.i==pOp->p5 ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
}
#endif
break;
}
/* Opcode: BeginSubrtn * P2 * * *
** Synopsis: r[P2]=NULL
**
** Mark the beginning of a subroutine that can be entered in-line
** or that can be called using OP_Gosub. The subroutine should
** be terminated by an OP_Return instruction that has a P1 operand that
** is the same as the P2 operand to this opcode and that has P3 set to 1.
** If the subroutine is entered in-line, then the OP_Return will simply
** fall through. But if the subroutine is entered using OP_Gosub, then
** the OP_Return will jump back to the first instruction after the OP_Gosub.
**
** This routine works by loading a NULL into the P2 register. When the
** return address register contains a NULL, the OP_Return instruction is
** a no-op that simply falls through to the next instruction (assuming that
** the OP_Return opcode has a P3 value of 1). Thus if the subroutine is
** entered in-line, then the OP_Return will cause in-line execution to
** continue. But if the subroutine is entered via OP_Gosub, then the
** OP_Return will cause a return to the address following the OP_Gosub.
**
** This opcode is identical to OP_Null. It has a different name
** only to make the byte code easier to read and verify.
*/
/* Opcode: Null P1 P2 P3 * *
** Synopsis: r[P2..P3]=NULL
**
** Write a NULL into registers P2. If P3 greater than P2, then also write
** NULL into register P3 and every register in between P2 and P3. If P3
** is less than P2 (typically P3 is zero) then only register P2 is
** set to NULL.
**
** If the P1 value is non-zero, then also set the MEM_Cleared flag so that
** NULL values will not compare equal even if SQLITE_NULLEQ is set on
** OP_Ne or OP_Eq.
*/
case OP_BeginSubrtn:
case OP_Null: { /* out2 */
int cnt;
u16 nullFlag;
pOut = out2Prerelease(p, pOp);
cnt = pOp->p3-pOp->p2;
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
|
| ︙ | ︙ | |||
89047 89048 89049 89050 89051 89052 89053 |
REGISTER_TRACE(p2++, pOut);
pIn1++;
pOut++;
}while( --n );
break;
}
| | > > > > > > > > | 89767 89768 89769 89770 89771 89772 89773 89774 89775 89776 89777 89778 89779 89780 89781 89782 89783 89784 89785 89786 89787 89788 89789 89790 89791 89792 89793 89794 89795 89796 89797 89798 89799 89800 89801 89802 89803 89804 89805 89806 89807 |
REGISTER_TRACE(p2++, pOut);
pIn1++;
pOut++;
}while( --n );
break;
}
/* Opcode: Copy P1 P2 P3 * P5
** Synopsis: r[P2@P3+1]=r[P1@P3+1]
**
** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
**
** If the 0x0002 bit of P5 is set then also clear the MEM_Subtype flag in the
** destination. The 0x0001 bit of P5 indicates that this Copy opcode cannot
** be merged. The 0x0001 bit is used by the query planner and does not
** come into play during query execution.
**
** This instruction makes a deep copy of the value. A duplicate
** is made of any string or blob constant. See also OP_SCopy.
*/
case OP_Copy: {
int n;
n = pOp->p3;
pIn1 = &aMem[pOp->p1];
pOut = &aMem[pOp->p2];
assert( pOut!=pIn1 );
while( 1 ){
memAboutToChange(p, pOut);
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
Deephemeralize(pOut);
if( (pOut->flags & MEM_Subtype)!=0 && (pOp->p5 & 0x0002)!=0 ){
pOut->flags &= ~MEM_Subtype;
}
#ifdef SQLITE_DEBUG
pOut->pScopyFrom = 0;
#endif
REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut);
if( (n--)==0 ) break;
pOut++;
pIn1++;
|
| ︙ | ︙ | |||
89146 89147 89148 89149 89150 89151 89152 |
** The registers P1 through P1+P2-1 contain a single row of
** results. This opcode causes the sqlite3_step() call to terminate
** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
** structure to provide access to the r(P1)..r(P1+P2-1) values as
** the result row.
*/
case OP_ResultRow: {
| < < < > > | < < < < | > | | < < < < | < | | | | | | < | < | > > < < < < | 89874 89875 89876 89877 89878 89879 89880 89881 89882 89883 89884 89885 89886 89887 89888 89889 89890 89891 89892 89893 89894 89895 89896 89897 89898 89899 89900 89901 89902 89903 89904 89905 89906 89907 89908 89909 89910 89911 89912 89913 |
** The registers P1 through P1+P2-1 contain a single row of
** results. This opcode causes the sqlite3_step() call to terminate
** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
** structure to provide access to the r(P1)..r(P1+P2-1) values as
** the result row.
*/
case OP_ResultRow: {
assert( p->nResColumn==pOp->p2 );
assert( pOp->p1>0 || CORRUPT_DB );
assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
p->cacheCtr = (p->cacheCtr + 2)|1;
p->pResultSet = &aMem[pOp->p1];
#ifdef SQLITE_DEBUG
{
Mem *pMem = p->pResultSet;
int i;
for(i=0; i<pOp->p2; i++){
assert( memIsValid(&pMem[i]) );
REGISTER_TRACE(pOp->p1+i, &pMem[i]);
/* The registers in the result will not be used again when the
** prepared statement restarts. This is because sqlite3_column()
** APIs might have caused type conversions of made other changes to
** the register values. Therefore, we can go ahead and break any
** OP_SCopy dependencies. */
pMem[i].pScopyFrom = 0;
}
}
#endif
if( db->mallocFailed ) goto no_mem;
if( db->mTrace & SQLITE_TRACE_ROW ){
db->trace.xV2(SQLITE_TRACE_ROW, db->pTraceArg, p, 0);
}
p->pc = (int)(pOp - aOp) + 1;
rc = SQLITE_ROW;
goto vdbe_return;
}
/* Opcode: Concat P1 P2 P3 * *
** Synopsis: r[P3]=r[P2]+r[P1]
|
| ︙ | ︙ | |||
89698 89699 89700 89701 89702 89703 89704 |
pIn3 = &aMem[pOp->p3];
flags1 = pIn1->flags;
flags3 = pIn3->flags;
if( (flags1 & flags3 & MEM_Int)!=0 ){
assert( (pOp->p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_TEXT || CORRUPT_DB );
/* Common case of comparison of two integers */
if( pIn3->u.i > pIn1->u.i ){
| < > < > < > | 90413 90414 90415 90416 90417 90418 90419 90420 90421 90422 90423 90424 90425 90426 90427 90428 90429 90430 90431 90432 90433 90434 90435 90436 90437 90438 90439 90440 90441 90442 90443 |
pIn3 = &aMem[pOp->p3];
flags1 = pIn1->flags;
flags3 = pIn3->flags;
if( (flags1 & flags3 & MEM_Int)!=0 ){
assert( (pOp->p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_TEXT || CORRUPT_DB );
/* Common case of comparison of two integers */
if( pIn3->u.i > pIn1->u.i ){
if( sqlite3aGTb[pOp->opcode] ){
VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
goto jump_to_p2;
}
iCompare = +1;
}else if( pIn3->u.i < pIn1->u.i ){
if( sqlite3aLTb[pOp->opcode] ){
VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
goto jump_to_p2;
}
iCompare = -1;
}else{
if( sqlite3aEQb[pOp->opcode] ){
VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
goto jump_to_p2;
}
iCompare = 0;
}
VdbeBranchTaken(0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
break;
}
if( (flags1 | flags3)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
|
| ︙ | ︙ | |||
89741 89742 89743 89744 89745 89746 89747 |
res = ((flags3 & MEM_Null) ? -1 : +1); /* Operands are not equal */
}
}else{
/* SQLITE_NULLEQ is clear and at least one operand is NULL,
** then the result is always NULL.
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/
| < > | 90456 90457 90458 90459 90460 90461 90462 90463 90464 90465 90466 90467 90468 90469 90470 90471 90472 90473 90474 |
res = ((flags3 & MEM_Null) ? -1 : +1); /* Operands are not equal */
}
}else{
/* SQLITE_NULLEQ is clear and at least one operand is NULL,
** then the result is always NULL.
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/
VdbeBranchTaken(2,3);
if( pOp->p5 & SQLITE_JUMPIFNULL ){
goto jump_to_p2;
}
iCompare = 1; /* Operands are not equal */
break;
}
}else{
/* Neither operand is NULL and we couldn't do the special high-speed
** integer comparison case. So do a general-case comparison. */
affinity = pOp->p5 & SQLITE_AFF_MASK;
if( affinity>=SQLITE_AFF_NUMERIC ){
|
| ︙ | ︙ | |||
89851 89852 89853 89854 89855 89856 89857 | /* Opcode: Permutation * * * P4 * ** ** Set the permutation used by the OP_Compare operator in the next ** instruction. The permutation is stored in the P4 operand. ** | | | < | 90566 90567 90568 90569 90570 90571 90572 90573 90574 90575 90576 90577 90578 90579 90580 90581 |
/* Opcode: Permutation * * * P4 *
**
** Set the permutation used by the OP_Compare operator in the next
** instruction. The permutation is stored in the P4 operand.
**
** The permutation is only valid for the next opcode which must be
** an OP_Compare that has the OPFLAG_PERMUTE bit set in P5.
**
** The first integer in the P4 integer array is the length of the array
** and does not become part of the permutation.
*/
case OP_Permutation: {
assert( pOp->p4type==P4_INTARRAY );
assert( pOp->p4.ai );
|
| ︙ | ︙ | |||
89885 89886 89887 89888 89889 89890 89891 89892 89893 89894 89895 89896 89897 89898 |
** P4 is a KeyInfo structure that defines collating sequences and sort
** orders for the comparison. The permutation applies to registers
** only. The KeyInfo elements are used sequentially.
**
** The comparison is a sort comparison, so NULLs compare equal,
** NULLs are less than numbers, numbers are less than strings,
** and strings are less than blobs.
*/
case OP_Compare: {
int n;
int i;
int p1;
int p2;
const KeyInfo *pKeyInfo;
| > > | 90599 90600 90601 90602 90603 90604 90605 90606 90607 90608 90609 90610 90611 90612 90613 90614 |
** P4 is a KeyInfo structure that defines collating sequences and sort
** orders for the comparison. The permutation applies to registers
** only. The KeyInfo elements are used sequentially.
**
** The comparison is a sort comparison, so NULLs compare equal,
** NULLs are less than numbers, numbers are less than strings,
** and strings are less than blobs.
**
** This opcode must be immediately followed by an OP_Jump opcode.
*/
case OP_Compare: {
int n;
int i;
int p1;
int p2;
const KeyInfo *pKeyInfo;
|
| ︙ | ︙ | |||
89943 89944 89945 89946 89947 89948 89949 89950 89951 89952 89953 89954 89955 89956 89957 89958 89959 89960 89961 89962 89963 89964 89965 89966 |
){
iCompare = -iCompare;
}
if( bRev ) iCompare = -iCompare;
break;
}
}
break;
}
/* Opcode: Jump P1 P2 P3 * *
**
** Jump to the instruction at address P1, P2, or P3 depending on whether
** in the most recent OP_Compare instruction the P1 vector was less than
** equal to, or greater than the P2 vector, respectively.
*/
case OP_Jump: { /* jump */
if( iCompare<0 ){
VdbeBranchTaken(0,4); pOp = &aOp[pOp->p1 - 1];
}else if( iCompare==0 ){
VdbeBranchTaken(1,4); pOp = &aOp[pOp->p2 - 1];
}else{
VdbeBranchTaken(2,4); pOp = &aOp[pOp->p3 - 1];
}
| > > > > | 90659 90660 90661 90662 90663 90664 90665 90666 90667 90668 90669 90670 90671 90672 90673 90674 90675 90676 90677 90678 90679 90680 90681 90682 90683 90684 90685 90686 |
){
iCompare = -iCompare;
}
if( bRev ) iCompare = -iCompare;
break;
}
}
assert( pOp[1].opcode==OP_Jump );
break;
}
/* Opcode: Jump P1 P2 P3 * *
**
** Jump to the instruction at address P1, P2, or P3 depending on whether
** in the most recent OP_Compare instruction the P1 vector was less than
** equal to, or greater than the P2 vector, respectively.
**
** This opcode must immediately follow an OP_Compare opcode.
*/
case OP_Jump: { /* jump */
assert( pOp>aOp && pOp[-1].opcode==OP_Compare );
if( iCompare<0 ){
VdbeBranchTaken(0,4); pOp = &aOp[pOp->p1 - 1];
}else if( iCompare==0 ){
VdbeBranchTaken(1,4); pOp = &aOp[pOp->p2 - 1];
}else{
VdbeBranchTaken(2,4); pOp = &aOp[pOp->p3 - 1];
}
|
| ︙ | ︙ | |||
90257 90258 90259 90260 90261 90262 90263 |
}
}
break;
}
#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */
/* Opcode: Column P1 P2 P3 P4 P5
| | | 90977 90978 90979 90980 90981 90982 90983 90984 90985 90986 90987 90988 90989 90990 90991 |
}
}
break;
}
#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */
/* Opcode: Column P1 P2 P3 P4 P5
** Synopsis: r[P3]=PX cursor P1 column P2
**
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction. (See the MakeRecord opcode for additional
** information about the format of the data.) Extract the P2-th column
** from this record. If there are less that (P2+1)
** values in the record, extract a NULL.
**
|
| ︙ | ︙ | |||
90299 90300 90301 90302 90303 90304 90305 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); pC = p->apCsr[pOp->p1]; p2 = (u32)pOp->p2; op_column_restart: assert( pC!=0 ); | | > | < | 91019 91020 91021 91022 91023 91024 91025 91026 91027 91028 91029 91030 91031 91032 91033 91034 91035 91036 91037 91038 91039 91040 91041 91042 91043 91044 91045 |
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pC = p->apCsr[pOp->p1];
p2 = (u32)pOp->p2;
op_column_restart:
assert( pC!=0 );
assert( p2<(u32)pC->nField
|| (pC->eCurType==CURTYPE_PSEUDO && pC->seekResult==0) );
aOffset = pC->aOffset;
assert( aOffset==pC->aType+pC->nField );
assert( pC->eCurType!=CURTYPE_VTAB );
assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
assert( pC->eCurType!=CURTYPE_SORTER );
if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/
if( pC->nullRow ){
if( pC->eCurType==CURTYPE_PSEUDO && pC->seekResult>0 ){
/* For the special case of as pseudo-cursor, the seekResult field
** identifies the register that holds the record */
pReg = &aMem[pC->seekResult];
assert( pReg->flags & MEM_Blob );
assert( memIsValid(pReg) );
pC->payloadSize = pC->szRow = pReg->n;
pC->aRow = (u8*)pReg->z;
}else{
pDest = &aMem[pOp->p3];
|
| ︙ | ︙ | |||
90349 90350 90351 90352 90353 90354 90355 |
assert( sqlite3BtreeCursorIsValid(pCrsr) );
pC->payloadSize = sqlite3BtreePayloadSize(pCrsr);
pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &pC->szRow);
assert( pC->szRow<=pC->payloadSize );
assert( pC->szRow<=65536 ); /* Maximum page size is 64KiB */
}
pC->cacheStatus = p->cacheCtr;
| > | > > > | 91069 91070 91071 91072 91073 91074 91075 91076 91077 91078 91079 91080 91081 91082 91083 91084 91085 91086 91087 |
assert( sqlite3BtreeCursorIsValid(pCrsr) );
pC->payloadSize = sqlite3BtreePayloadSize(pCrsr);
pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &pC->szRow);
assert( pC->szRow<=pC->payloadSize );
assert( pC->szRow<=65536 ); /* Maximum page size is 64KiB */
}
pC->cacheStatus = p->cacheCtr;
if( (aOffset[0] = pC->aRow[0])<0x80 ){
pC->iHdrOffset = 1;
}else{
pC->iHdrOffset = sqlite3GetVarint32(pC->aRow, aOffset);
}
pC->nHdrParsed = 0;
if( pC->szRow<aOffset[0] ){ /*OPTIMIZATION-IF-FALSE*/
/* pC->aRow does not have to hold the entire row, but it does at least
** need to cover the header of the record. If pC->aRow does not contain
** the complete header, then set it to zero, forcing the header to be
** dynamically allocated. */
|
| ︙ | ︙ | |||
90984 90985 90986 90987 90988 90989 90990 |
pOut->flags |= MEM_Zero;
}
UPDATE_MAX_BLOBSIZE(pOut);
zHdr = (u8 *)pOut->z;
zPayload = zHdr + nHdr;
/* Write the record */
| > > > | > < > | < | > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > | > | 91708 91709 91710 91711 91712 91713 91714 91715 91716 91717 91718 91719 91720 91721 91722 91723 91724 91725 91726 91727 91728 91729 91730 91731 91732 91733 91734 91735 91736 91737 91738 91739 91740 91741 91742 91743 91744 91745 91746 91747 91748 91749 91750 91751 91752 91753 91754 91755 91756 91757 91758 91759 91760 91761 91762 91763 91764 91765 91766 91767 91768 91769 91770 91771 91772 91773 91774 91775 |
pOut->flags |= MEM_Zero;
}
UPDATE_MAX_BLOBSIZE(pOut);
zHdr = (u8 *)pOut->z;
zPayload = zHdr + nHdr;
/* Write the record */
if( nHdr<0x80 ){
*(zHdr++) = nHdr;
}else{
zHdr += sqlite3PutVarint(zHdr,nHdr);
}
assert( pData0<=pLast );
pRec = pData0;
while( 1 /*exit-by-break*/ ){
serial_type = pRec->uTemp;
/* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more
** additional varints, one per column.
** EVIDENCE-OF: R-64536-51728 The values for each column in the record
** immediately follow the header. */
if( serial_type<=7 ){
*(zHdr++) = serial_type;
if( serial_type==0 ){
/* NULL value. No change in zPayload */
}else{
u64 v;
u32 i;
if( serial_type==7 ){
assert( sizeof(v)==sizeof(pRec->u.r) );
memcpy(&v, &pRec->u.r, sizeof(v));
swapMixedEndianFloat(v);
}else{
v = pRec->u.i;
}
len = i = sqlite3SmallTypeSizes[serial_type];
assert( i>0 );
while( 1 /*exit-by-break*/ ){
zPayload[--i] = (u8)(v&0xFF);
if( i==0 ) break;
v >>= 8;
}
zPayload += len;
}
}else if( serial_type<0x80 ){
*(zHdr++) = serial_type;
if( serial_type>=14 && pRec->n>0 ){
assert( pRec->z!=0 );
memcpy(zPayload, pRec->z, pRec->n);
zPayload += pRec->n;
}
}else{
zHdr += sqlite3PutVarint(zHdr, serial_type);
if( pRec->n ){
assert( pRec->z!=0 );
memcpy(zPayload, pRec->z, pRec->n);
zPayload += pRec->n;
}
}
if( pRec==pLast ) break;
pRec++;
}
assert( nHdr==(int)(zHdr - (u8*)pOut->z) );
assert( nByte==(int)(zPayload - (u8*)pOut->z) );
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
REGISTER_TRACE(pOp->p3, pOut);
break;
}
|
| ︙ | ︙ | |||
91214 91215 91216 91217 91218 91219 91220 |
if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){
rc = sqlite3VtabSavepoint(db, p1, iSavepoint);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
}
}
if( rc ) goto abort_due_to_error;
| > > > | | 91980 91981 91982 91983 91984 91985 91986 91987 91988 91989 91990 91991 91992 91993 91994 91995 91996 91997 |
if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){
rc = sqlite3VtabSavepoint(db, p1, iSavepoint);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
}
}
if( rc ) goto abort_due_to_error;
if( p->eVdbeState==VDBE_HALT_STATE ){
rc = SQLITE_DONE;
goto vdbe_return;
}
break;
}
/* Opcode: AutoCommit P1 P2 * * *
**
** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll
** back any currently active btree transactions. If there are any active
|
| ︙ | ︙ | |||
91318 91319 91320 91321 91322 91323 91324 91325 91326 91327 91328 91329 91330 91331 91332 91333 91334 91335 91336 91337 91338 91339 91340 91341 91342 91343 |
** if the schema generation counter in P4 differs from the current
** generation counter, then an SQLITE_SCHEMA error is raised and execution
** halts. The sqlite3_step() wrapper function might then reprepare the
** statement and rerun it from the beginning.
*/
case OP_Transaction: {
Btree *pBt;
int iMeta = 0;
assert( p->bIsReader );
assert( p->readOnly==0 || pOp->p2==0 );
assert( pOp->p2>=0 && pOp->p2<=2 );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
assert( rc==SQLITE_OK );
if( pOp->p2 && (db->flags & (SQLITE_QueryOnly|SQLITE_CorruptRdOnly))!=0 ){
if( db->flags & SQLITE_QueryOnly ){
/* Writes prohibited by the "PRAGMA query_only=TRUE" statement */
rc = SQLITE_READONLY;
}else{
/* Writes prohibited due to a prior SQLITE_CORRUPT in the current
** transaction */
rc = SQLITE_CORRUPT;
}
goto abort_due_to_error;
}
| > | > | 92087 92088 92089 92090 92091 92092 92093 92094 92095 92096 92097 92098 92099 92100 92101 92102 92103 92104 92105 92106 92107 92108 92109 92110 92111 92112 92113 92114 92115 92116 92117 92118 92119 92120 92121 92122 |
** if the schema generation counter in P4 differs from the current
** generation counter, then an SQLITE_SCHEMA error is raised and execution
** halts. The sqlite3_step() wrapper function might then reprepare the
** statement and rerun it from the beginning.
*/
case OP_Transaction: {
Btree *pBt;
Db *pDb;
int iMeta = 0;
assert( p->bIsReader );
assert( p->readOnly==0 || pOp->p2==0 );
assert( pOp->p2>=0 && pOp->p2<=2 );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
assert( rc==SQLITE_OK );
if( pOp->p2 && (db->flags & (SQLITE_QueryOnly|SQLITE_CorruptRdOnly))!=0 ){
if( db->flags & SQLITE_QueryOnly ){
/* Writes prohibited by the "PRAGMA query_only=TRUE" statement */
rc = SQLITE_READONLY;
}else{
/* Writes prohibited due to a prior SQLITE_CORRUPT in the current
** transaction */
rc = SQLITE_CORRUPT;
}
goto abort_due_to_error;
}
pDb = &db->aDb[pOp->p1];
pBt = pDb->pBt;
if( pBt ){
rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta);
testcase( rc==SQLITE_BUSY_SNAPSHOT );
testcase( rc==SQLITE_BUSY_RECOVERY );
if( rc!=SQLITE_OK ){
if( (rc&0xff)==SQLITE_BUSY ){
|
| ︙ | ︙ | |||
91378 91379 91380 91381 91382 91383 91384 |
p->nStmtDefCons = db->nDeferredCons;
p->nStmtDefImmCons = db->nDeferredImmCons;
}
}
assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
if( rc==SQLITE_OK
&& pOp->p5
| | < | 92149 92150 92151 92152 92153 92154 92155 92156 92157 92158 92159 92160 92161 92162 92163 |
p->nStmtDefCons = db->nDeferredCons;
p->nStmtDefImmCons = db->nDeferredImmCons;
}
}
assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
if( rc==SQLITE_OK
&& pOp->p5
&& (iMeta!=pOp->p3 || pDb->pSchema->iGeneration!=pOp->p4.i)
){
/*
** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
** version is checked to ensure that the schema has not changed since the
** SQL statement was prepared.
*/
sqlite3DbFree(db, p->zErrMsg);
|
| ︙ | ︙ | |||
91406 91407 91408 91409 91410 91411 91412 91413 91414 91415 91416 91417 91418 91419 |
** a v-table method.
*/
if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
sqlite3ResetOneSchema(db, pOp->p1);
}
p->expired = 1;
rc = SQLITE_SCHEMA;
}
if( rc ) goto abort_due_to_error;
break;
}
/* Opcode: ReadCookie P1 P2 P3 * *
**
| > > > > > | 92176 92177 92178 92179 92180 92181 92182 92183 92184 92185 92186 92187 92188 92189 92190 92191 92192 92193 92194 |
** a v-table method.
*/
if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
sqlite3ResetOneSchema(db, pOp->p1);
}
p->expired = 1;
rc = SQLITE_SCHEMA;
/* Set changeCntOn to 0 to prevent the value returned by sqlite3_changes()
** from being modified in sqlite3VdbeHalt(). If this statement is
** reprepared, changeCntOn will be set again. */
p->changeCntOn = 0;
}
if( rc ) goto abort_due_to_error;
break;
}
/* Opcode: ReadCookie P1 P2 P3 * *
**
|
| ︙ | ︙ | |||
91705 91706 91707 91708 91709 91710 91711 | pCx->nullRow = 1; pCx->isEphemeral = 1; pCx->pKeyInfo = pOrig->pKeyInfo; pCx->isTable = pOrig->isTable; pCx->pgnoRoot = pOrig->pgnoRoot; pCx->isOrdered = pOrig->isOrdered; pCx->ub.pBtx = pOrig->ub.pBtx; | | | | 92480 92481 92482 92483 92484 92485 92486 92487 92488 92489 92490 92491 92492 92493 92494 92495 |
pCx->nullRow = 1;
pCx->isEphemeral = 1;
pCx->pKeyInfo = pOrig->pKeyInfo;
pCx->isTable = pOrig->isTable;
pCx->pgnoRoot = pOrig->pgnoRoot;
pCx->isOrdered = pOrig->isOrdered;
pCx->ub.pBtx = pOrig->ub.pBtx;
pCx->noReuse = 1;
pOrig->noReuse = 1;
rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR,
pCx->pKeyInfo, pCx->uc.pCursor);
/* The sqlite3BtreeCursor() routine can only fail for the first cursor
** opened for a database. Since there is already an open cursor when this
** opcode is run, the sqlite3BtreeCursor() cannot fail */
assert( rc==SQLITE_OK );
break;
|
| ︙ | ︙ | |||
91773 91774 91775 91776 91777 91778 91779 |
assert( pOp->p2==0 ); /* Only used when number of columns is zero */
assert( pOp->opcode==OP_OpenEphemeral );
assert( aMem[pOp->p3].flags & MEM_Null );
aMem[pOp->p3].n = 0;
aMem[pOp->p3].z = "";
}
pCx = p->apCsr[pOp->p1];
| | | 92548 92549 92550 92551 92552 92553 92554 92555 92556 92557 92558 92559 92560 92561 92562 |
assert( pOp->p2==0 ); /* Only used when number of columns is zero */
assert( pOp->opcode==OP_OpenEphemeral );
assert( aMem[pOp->p3].flags & MEM_Null );
aMem[pOp->p3].n = 0;
aMem[pOp->p3].z = "";
}
pCx = p->apCsr[pOp->p1];
if( pCx && !pCx->noReuse && ALWAYS(pOp->p2<=pCx->nField) ){
/* If the ephermeral table is already open and has no duplicates from
** OP_OpenDup, then erase all existing content so that the table is
** empty again, rather than creating a new table. */
assert( pCx->isEphemeral );
pCx->seqCount = 0;
pCx->cacheStatus = CACHE_STALE;
rc = sqlite3BtreeClearTable(pCx->ub.pBtx, pCx->pgnoRoot, 0);
|
| ︙ | ︙ | |||
92522 92523 92524 92525 92526 92527 92528 |
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
}
case OP_NoConflict: /* jump, in3 */
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
int alreadyExists;
| < < < | | > > < | | < > | > | | | < | < < < < < < < < < < < < | | > < | > | | > > > > > > > > > > > > > | > > | 93297 93298 93299 93300 93301 93302 93303 93304 93305 93306 93307 93308 93309 93310 93311 93312 93313 93314 93315 93316 93317 93318 93319 93320 93321 93322 93323 93324 93325 93326 93327 93328 93329 93330 93331 93332 93333 93334 93335 93336 93337 93338 93339 93340 93341 93342 93343 93344 93345 93346 93347 93348 93349 93350 93351 93352 93353 93354 93355 93356 93357 93358 93359 93360 93361 93362 93363 93364 93365 93366 93367 93368 93369 93370 93371 93372 93373 93374 93375 93376 93377 93378 93379 93380 93381 93382 93383 93384 93385 93386 93387 |
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
}
case OP_NoConflict: /* jump, in3 */
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
int alreadyExists;
int ii;
VdbeCursor *pC;
UnpackedRecord *pIdxKey;
UnpackedRecord r;
#ifdef SQLITE_TEST
if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
#endif
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p4type==P4_INT32 );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
#ifdef SQLITE_DEBUG
pC->seekOp = pOp->opcode;
#endif
r.aMem = &aMem[pOp->p3];
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
assert( pC->isTable==0 );
r.nField = (u16)pOp->p4.i;
if( r.nField>0 ){
/* Key values in an array of registers */
r.pKeyInfo = pC->pKeyInfo;
r.default_rc = 0;
#ifdef SQLITE_DEBUG
for(ii=0; ii<r.nField; ii++){
assert( memIsValid(&r.aMem[ii]) );
assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 );
if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
}
#endif
rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &pC->seekResult);
}else{
/* Composite key generated by OP_MakeRecord */
assert( r.aMem->flags & MEM_Blob );
assert( pOp->opcode!=OP_NoConflict );
rc = ExpandBlob(r.aMem);
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
if( rc ) goto no_mem;
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
if( pIdxKey==0 ) goto no_mem;
sqlite3VdbeRecordUnpack(pC->pKeyInfo, r.aMem->n, r.aMem->z, pIdxKey);
pIdxKey->default_rc = 0;
rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult);
sqlite3DbFreeNN(db, pIdxKey);
}
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
alreadyExists = (pC->seekResult==0);
pC->nullRow = 1-alreadyExists;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
if( pOp->opcode==OP_Found ){
VdbeBranchTaken(alreadyExists!=0,2);
if( alreadyExists ) goto jump_to_p2;
}else{
if( !alreadyExists ){
VdbeBranchTaken(1,2);
goto jump_to_p2;
}
if( pOp->opcode==OP_NoConflict ){
/* For the OP_NoConflict opcode, take the jump if any of the
** input fields are NULL, since any key with a NULL will not
** conflict */
for(ii=0; ii<r.nField; ii++){
if( r.aMem[ii].flags & MEM_Null ){
VdbeBranchTaken(1,2);
goto jump_to_p2;
}
}
}
VdbeBranchTaken(0,2);
if( pOp->opcode==OP_IfNoHope ){
pC->seekHit = pOp->p4.i;
}
}
break;
}
/* Opcode: SeekRowid P1 P2 P3 * *
** Synopsis: intkey=r[P3]
**
|
| ︙ | ︙ | |||
93287 93288 93289 93290 93291 93292 93293 | if( !pOp->p3 ) Deephemeralize(pOut); UPDATE_MAX_BLOBSIZE(pOut); REGISTER_TRACE(pOp->p2, pOut); break; } /* Opcode: Rowid P1 P2 * * * | | | 94064 94065 94066 94067 94068 94069 94070 94071 94072 94073 94074 94075 94076 94077 94078 | if( !pOp->p3 ) Deephemeralize(pOut); UPDATE_MAX_BLOBSIZE(pOut); REGISTER_TRACE(pOp->p2, pOut); break; } /* Opcode: Rowid P1 P2 * * * ** Synopsis: r[P2]=PX rowid of P1 ** ** Store in register P2 an integer which is the key of the table entry that ** P1 is currently point to. ** ** P1 can be either an ordinary table or a virtual table. There used to ** be a separate OP_VRowid opcode for use with virtual tables, but this ** one opcode now works for both table types. |
| ︙ | ︙ | |||
93343 93344 93345 93346 93347 93348 93349 | /* Opcode: NullRow P1 * * * * ** ** Move the cursor P1 to a null row. Any OP_Column operations ** that occur while the cursor is on the null row will always ** write a NULL. ** | | < | | > > > > > > > > > | 94120 94121 94122 94123 94124 94125 94126 94127 94128 94129 94130 94131 94132 94133 94134 94135 94136 94137 94138 94139 94140 94141 94142 94143 94144 94145 94146 94147 94148 94149 94150 94151 |
/* Opcode: NullRow P1 * * * *
**
** Move the cursor P1 to a null row. Any OP_Column operations
** that occur while the cursor is on the null row will always
** write a NULL.
**
** If cursor P1 is not previously opened, open it now to a special
** pseudo-cursor that always returns NULL for every column.
*/
case OP_NullRow: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
if( pC==0 ){
/* If the cursor is not already open, create a special kind of
** pseudo-cursor that always gives null rows. */
pC = allocateCursor(p, pOp->p1, 1, CURTYPE_PSEUDO);
if( pC==0 ) goto no_mem;
pC->seekResult = 0;
pC->isTable = 1;
pC->noReuse = 1;
pC->uc.pCursor = sqlite3BtreeFakeValidCursor();
}
pC->nullRow = 1;
pC->cacheStatus = CACHE_STALE;
if( pC->eCurType==CURTYPE_BTREE ){
assert( pC->uc.pCursor!=0 );
sqlite3BtreeClearCursor(pC->uc.pCursor);
}
#ifdef SQLITE_DEBUG
|
| ︙ | ︙ | |||
93799 93800 93801 93802 93803 93804 93805 | VdbeCursor *pC; /* The P1 index cursor */ VdbeCursor *pTabCur; /* The P2 table cursor (OP_DeferredSeek only) */ i64 rowid; /* Rowid that P1 current points to */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); | | | | 94584 94585 94586 94587 94588 94589 94590 94591 94592 94593 94594 94595 94596 94597 94598 94599 94600 | VdbeCursor *pC; /* The P1 index cursor */ VdbeCursor *pTabCur; /* The P2 table cursor (OP_DeferredSeek only) */ i64 rowid; /* Rowid that P1 current points to */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE || IsNullCursor(pC) ); assert( pC->uc.pCursor!=0 ); assert( pC->isTable==0 || IsNullCursor(pC) ); assert( pC->deferredMoveto==0 ); assert( !pC->nullRow || pOp->opcode==OP_IdxRowid ); /* The IdxRowid and Seek opcodes are combined because of the commonality ** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */ rc = sqlite3VdbeCursorRestore(pC); |
| ︙ | ︙ | |||
94846 94847 94848 94849 94850 94851 94852 94853 94854 94855 94856 94857 94858 94859 | pCtx->pOut = (Mem*)&(pCtx->argv[n]); sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null); pCtx->pFunc = pOp->p4.pFunc; pCtx->iOp = (int)(pOp - aOp); pCtx->pVdbe = p; pCtx->skipFlag = 0; pCtx->isError = 0; pCtx->argc = n; pOp->p4type = P4_FUNCCTX; pOp->p4.pCtx = pCtx; /* OP_AggInverse must have P1==1 and OP_AggStep must have P1==0 */ assert( pOp->p1==(pOp->opcode==OP_AggInverse) ); | > | 95631 95632 95633 95634 95635 95636 95637 95638 95639 95640 95641 95642 95643 95644 95645 | pCtx->pOut = (Mem*)&(pCtx->argv[n]); sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null); pCtx->pFunc = pOp->p4.pFunc; pCtx->iOp = (int)(pOp - aOp); pCtx->pVdbe = p; pCtx->skipFlag = 0; pCtx->isError = 0; pCtx->enc = encoding; pCtx->argc = n; pOp->p4type = P4_FUNCCTX; pOp->p4.pCtx = pCtx; /* OP_AggInverse must have P1==1 and OP_AggStep must have P1==0 */ assert( pOp->p1==(pOp->opcode==OP_AggInverse) ); |
| ︙ | ︙ | |||
94975 94976 94977 94978 94979 94980 94981 |
if( rc ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem));
goto abort_due_to_error;
}
sqlite3VdbeChangeEncoding(pMem, encoding);
UPDATE_MAX_BLOBSIZE(pMem);
| < < < | 95761 95762 95763 95764 95765 95766 95767 95768 95769 95770 95771 95772 95773 95774 |
if( rc ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem));
goto abort_due_to_error;
}
sqlite3VdbeChangeEncoding(pMem, encoding);
UPDATE_MAX_BLOBSIZE(pMem);
break;
}
#ifndef SQLITE_OMIT_WAL
/* Opcode: Checkpoint P1 P2 P3 * *
**
** Checkpoint database P1. This is a no-op if P1 is not currently in
|
| ︙ | ︙ | |||
95485 95486 95487 95488 95489 95490 95491 | sqlite3_vtab *pVtab; const sqlite3_module *pModule; Mem *pDest; sqlite3_context sContext; VdbeCursor *pCur = p->apCsr[pOp->p1]; assert( pCur!=0 ); | < > > < < < | 96268 96269 96270 96271 96272 96273 96274 96275 96276 96277 96278 96279 96280 96281 96282 96283 96284 96285 96286 96287 96288 96289 96290 96291 96292 96293 96294 96295 96296 96297 96298 96299 96300 96301 96302 96303 96304 96305 96306 96307 96308 96309 96310 96311 96312 96313 |
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur!=0 );
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
if( pCur->nullRow ){
sqlite3VdbeMemSetNull(pDest);
break;
}
assert( pCur->eCurType==CURTYPE_VTAB );
pVtab = pCur->uc.pVCur->pVtab;
pModule = pVtab->pModule;
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
sContext.pOut = pDest;
sContext.enc = encoding;
assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 );
if( pOp->p5 & OPFLAG_NOCHNG ){
sqlite3VdbeMemSetNull(pDest);
pDest->flags = MEM_Null|MEM_Zero;
pDest->u.nZero = 0;
}else{
MemSetTypeFlag(pDest, MEM_Null);
}
rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2);
sqlite3VtabImportErrmsg(p, pVtab);
if( sContext.isError>0 ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(pDest));
rc = sContext.isError;
}
sqlite3VdbeChangeEncoding(pDest, encoding);
REGISTER_TRACE(pOp->p3, pDest);
UPDATE_MAX_BLOBSIZE(pDest);
if( rc ) goto abort_due_to_error;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VNext P1 P2 * * *
|
| ︙ | ︙ | |||
95785 95786 95787 95788 95789 95790 95791 95792 95793 95794 95795 95796 95797 95798 |
** might change from one evaluation to the next. The next block of code
** checks to see if the register array has changed, and if so it
** reinitializes the relavant parts of the sqlite3_context object */
pOut = &aMem[pOp->p3];
if( pCtx->pOut != pOut ){
pCtx->pVdbe = p;
pCtx->pOut = pOut;
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
}
assert( pCtx->pVdbe==p );
memAboutToChange(p, pOut);
#ifdef SQLITE_DEBUG
for(i=0; i<pCtx->argc; i++){
| > | 96566 96567 96568 96569 96570 96571 96572 96573 96574 96575 96576 96577 96578 96579 96580 |
** might change from one evaluation to the next. The next block of code
** checks to see if the register array has changed, and if so it
** reinitializes the relavant parts of the sqlite3_context object */
pOut = &aMem[pOp->p3];
if( pCtx->pOut != pOut ){
pCtx->pVdbe = p;
pCtx->pOut = pOut;
pCtx->enc = encoding;
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
}
assert( pCtx->pVdbe==p );
memAboutToChange(p, pOut);
#ifdef SQLITE_DEBUG
for(i=0; i<pCtx->argc; i++){
|
| ︙ | ︙ | |||
95811 95812 95813 95814 95815 95816 95817 |
rc = pCtx->isError;
}
sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
pCtx->isError = 0;
if( rc ) goto abort_due_to_error;
}
| < | | > | < > > > > > > > > > > > | 96593 96594 96595 96596 96597 96598 96599 96600 96601 96602 96603 96604 96605 96606 96607 96608 96609 96610 96611 96612 96613 96614 96615 96616 96617 96618 96619 96620 96621 96622 96623 96624 96625 96626 |
rc = pCtx->isError;
}
sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
pCtx->isError = 0;
if( rc ) goto abort_due_to_error;
}
assert( (pOut->flags&MEM_Str)==0
|| pOut->enc==encoding
|| db->mallocFailed );
assert( !sqlite3VdbeMemTooBig(pOut) );
REGISTER_TRACE(pOp->p3, pOut);
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
/* Opcode: ClrSubtype P1 * * * *
** Synopsis: r[P1].subtype = 0
**
** Clear the subtype from register P1.
*/
case OP_ClrSubtype: { /* in1 */
pIn1 = &aMem[pOp->p1];
pIn1->flags &= ~MEM_Subtype;
break;
}
/* Opcode: FilterAdd P1 * P3 P4 *
** Synopsis: filter(P1) += key(P3@P4)
**
** Compute a hash on the P4 registers starting with r[P3] and
** add that hash to the bloom filter contained in r[P1].
*/
|
| ︙ | ︙ | |||
95941 95942 95943 95944 95945 95946 95947 | assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 ); /* OP_Init is always instruction 0 */ assert( pOp==p->aOp || pOp->opcode==OP_Trace ); #ifndef SQLITE_OMIT_TRACE if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0 | | | 96733 96734 96735 96736 96737 96738 96739 96740 96741 96742 96743 96744 96745 96746 96747 |
assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 );
/* OP_Init is always instruction 0 */
assert( pOp==p->aOp || pOp->opcode==OP_Trace );
#ifndef SQLITE_OMIT_TRACE
if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0
&& p->minWriteFileFormat!=254 /* tag-20220401a */
&& (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
){
#ifndef SQLITE_OMIT_DEPRECATED
if( db->mTrace & SQLITE_TRACE_LEGACY ){
char *z = sqlite3VdbeExpandSql(p, zTrace);
db->trace.xLegacy(db->pTraceArg, z);
sqlite3_free(z);
|
| ︙ | ︙ | |||
96170 96171 96172 96173 96174 96175 96176 |
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
}
p->rc = rc;
sqlite3SystemError(db, rc);
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(rc, "statement aborts at %d: [%s] %s",
(int)(pOp - aOp), p->zSql, p->zErrMsg);
| | | 96962 96963 96964 96965 96966 96967 96968 96969 96970 96971 96972 96973 96974 96975 96976 |
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
}
p->rc = rc;
sqlite3SystemError(db, rc);
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(rc, "statement aborts at %d: [%s] %s",
(int)(pOp - aOp), p->zSql, p->zErrMsg);
if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db);
if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){
db->flags |= SQLITE_CorruptRdOnly;
}
rc = SQLITE_ERROR;
if( resetSchemaOnFault>0 ){
sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
|
| ︙ | ︙ | |||
100762 100763 100764 100765 100766 100767 100768 |
pExpr->y.pWin->pOwner = pExpr;
}
}
sqlite3DbFree(db, pDup);
}
}
| < < < < < < < < < < < < < < < < < | | 101554 101555 101556 101557 101558 101559 101560 101561 101562 101563 101564 101565 101566 101567 101568 101569 101570 101571 101572 101573 101574 101575 101576 101577 101578 101579 101580 101581 101582 101583 |
pExpr->y.pWin->pOwner = pExpr;
}
}
sqlite3DbFree(db, pDup);
}
}
/*
** Subqueries stores the original database, table and column names for their
** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
** Check to see if the zSpan given to this routine matches the zDb, zTab,
** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will
** match anything.
*/
SQLITE_PRIVATE int sqlite3MatchEName(
const struct ExprList_item *pItem,
const char *zCol,
const char *zTab,
const char *zDb
){
int n;
const char *zSpan;
if( pItem->fg.eEName!=ENAME_TAB ) return 0;
zSpan = pItem->zEName;
for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
return 0;
}
zSpan += n+1;
for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
|
| ︙ | ︙ | |||
100854 100855 100856 100857 100858 100859 100860 100861 100862 100863 100864 100865 100866 100867 |
}else{
testcase( n==BMS-1 );
testcase( n==BMS );
if( n>=BMS ) n = BMS-1;
return ((Bitmask)1)<<n;
}
}
/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
** that name in the set of source tables in pSrcList and make the pExpr
** expression node refer back to that source column. The following changes
** are made to pExpr:
**
| > > > > > > > > > > > > > > > > > > > > > > > | 101629 101630 101631 101632 101633 101634 101635 101636 101637 101638 101639 101640 101641 101642 101643 101644 101645 101646 101647 101648 101649 101650 101651 101652 101653 101654 101655 101656 101657 101658 101659 101660 101661 101662 101663 101664 101665 |
}else{
testcase( n==BMS-1 );
testcase( n==BMS );
if( n>=BMS ) n = BMS-1;
return ((Bitmask)1)<<n;
}
}
/*
** Create a new expression term for the column specified by pMatch and
** iColumn. Append this new expression term to the FULL JOIN Match set
** in *ppList. Create a new *ppList if this is the first term in the
** set.
*/
static void extendFJMatch(
Parse *pParse, /* Parsing context */
ExprList **ppList, /* ExprList to extend */
SrcItem *pMatch, /* Source table containing the column */
i16 iColumn /* The column number */
){
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
if( pNew ){
pNew->iTable = pMatch->iCursor;
pNew->iColumn = iColumn;
pNew->y.pTab = pMatch->pTab;
assert( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 );
ExprSetProperty(pNew, EP_CanBeNull);
*ppList = sqlite3ExprListAppend(pParse, *ppList, pNew);
}
}
/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
** that name in the set of source tables in pSrcList and make the pExpr
** expression node refer back to that source column. The following changes
** are made to pExpr:
**
|
| ︙ | ︙ | |||
100900 100901 100902 100903 100904 100905 100906 | int nSubquery = 0; /* How many levels of subquery */ sqlite3 *db = pParse->db; /* The database connection */ SrcItem *pItem; /* Use for looping over pSrcList items */ SrcItem *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ | | > > | 101698 101699 101700 101701 101702 101703 101704 101705 101706 101707 101708 101709 101710 101711 101712 101713 101714 101715 101716 101717 101718 | int nSubquery = 0; /* How many levels of subquery */ sqlite3 *db = pParse->db; /* The database connection */ SrcItem *pItem; /* Use for looping over pSrcList items */ SrcItem *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ Table *pTab = 0; /* Table holding the row */ Column *pCol; /* A column of pTab */ ExprList *pFJMatch = 0; /* Matches for FULL JOIN .. USING */ assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( zDb==0 || zTab!=0 ); assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; ExprSetVVAProperty(pExpr, EP_NoReduce); /* Translate the schema name in zDb into a pointer to the corresponding |
| ︙ | ︙ | |||
100953 100954 100955 100956 100957 100958 100959 |
if( pSrcList ){
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
u8 hCol;
pTab = pItem->pTab;
assert( pTab!=0 && pTab->zName!=0 );
assert( pTab->nCol>0 || pParse->nErr );
| > | > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | > | > | < > > > | | | | < | < < < < | | > > > > > > > > > > | > > > > > > > > > > > > > < < | | 101753 101754 101755 101756 101757 101758 101759 101760 101761 101762 101763 101764 101765 101766 101767 101768 101769 101770 101771 101772 101773 101774 101775 101776 101777 101778 101779 101780 101781 101782 101783 101784 101785 101786 101787 101788 101789 101790 101791 101792 101793 101794 101795 101796 101797 101798 101799 101800 101801 101802 101803 101804 101805 101806 101807 101808 101809 101810 101811 101812 101813 101814 101815 101816 101817 101818 101819 101820 101821 101822 101823 101824 101825 101826 101827 101828 101829 101830 101831 101832 101833 101834 101835 101836 101837 101838 101839 101840 101841 101842 101843 101844 101845 101846 101847 101848 101849 101850 101851 101852 101853 101854 101855 101856 101857 101858 101859 101860 101861 101862 101863 101864 101865 101866 101867 101868 101869 101870 101871 101872 101873 101874 101875 101876 101877 101878 101879 101880 101881 101882 101883 |
if( pSrcList ){
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
u8 hCol;
pTab = pItem->pTab;
assert( pTab!=0 && pTab->zName!=0 );
assert( pTab->nCol>0 || pParse->nErr );
assert( pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
if( pItem->fg.isNestedFrom ){
/* In this case, pItem is a subquery that has been formed from a
** parenthesized subset of the FROM clause terms. Example:
** .... FROM t1 LEFT JOIN (t2 RIGHT JOIN t3 USING(x)) USING(y) ...
** \_________________________/
** This pItem -------------^
*/
int hit = 0;
assert( pItem->pSelect!=0 );
pEList = pItem->pSelect->pEList;
assert( pEList!=0 );
assert( pEList->nExpr==pTab->nCol );
for(j=0; j<pEList->nExpr; j++){
if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){
continue;
}
if( cnt>0 ){
if( pItem->fg.isUsing==0
|| sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
){
/* Two or more tables have the same column name which is
** not joined by USING. This is an error. Signal as much
** by clearing pFJMatch and letting cnt go above 1. */
sqlite3ExprListDelete(db, pFJMatch);
pFJMatch = 0;
}else
if( (pItem->fg.jointype & JT_RIGHT)==0 ){
/* An INNER or LEFT JOIN. Use the left-most table */
continue;
}else
if( (pItem->fg.jointype & JT_LEFT)==0 ){
/* A RIGHT JOIN. Use the right-most table */
cnt = 0;
sqlite3ExprListDelete(db, pFJMatch);
pFJMatch = 0;
}else{
/* For a FULL JOIN, we must construct a coalesce() func */
extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
}
}
cnt++;
cntTab = 2;
pMatch = pItem;
pExpr->iColumn = j;
pEList->a[j].fg.bUsed = 1;
hit = 1;
if( pEList->a[j].fg.bUsingTerm ) break;
}
if( hit || zTab==0 ) continue;
}
assert( zDb==0 || zTab!=0 );
if( zTab ){
const char *zTabName;
if( zDb ){
if( pTab->pSchema!=pSchema ) continue;
if( pSchema==0 && strcmp(zDb,"*")!=0 ) continue;
}
zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
assert( zTabName!=0 );
if( sqlite3StrICmp(zTabName, zTab)!=0 ){
continue;
}
assert( ExprUseYTab(pExpr) );
if( IN_RENAME_OBJECT && pItem->zAlias ){
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
}
}
hCol = sqlite3StrIHash(zCol);
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
if( pCol->hName==hCol
&& sqlite3StrICmp(pCol->zCnName, zCol)==0
){
if( cnt>0 ){
if( pItem->fg.isUsing==0
|| sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
){
/* Two or more tables have the same column name which is
** not joined by USING. This is an error. Signal as much
** by clearing pFJMatch and letting cnt go above 1. */
sqlite3ExprListDelete(db, pFJMatch);
pFJMatch = 0;
}else
if( (pItem->fg.jointype & JT_RIGHT)==0 ){
/* An INNER or LEFT JOIN. Use the left-most table */
continue;
}else
if( (pItem->fg.jointype & JT_LEFT)==0 ){
/* A RIGHT JOIN. Use the right-most table */
cnt = 0;
sqlite3ExprListDelete(db, pFJMatch);
pFJMatch = 0;
}else{
/* For a FULL JOIN, we must construct a coalesce() func */
extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
}
}
cnt++;
pMatch = pItem;
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
if( pItem->fg.isNestedFrom ){
sqlite3SrcItemColumnUsed(pItem, j);
}
break;
}
}
if( 0==cnt && VisibleRowid(pTab) ){
cntTab++;
pMatch = pItem;
}
}
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
assert( ExprUseYTab(pExpr) );
pExpr->y.pTab = pMatch->pTab;
if( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
pSchema = pExpr->y.pTab->pSchema;
}
} /* if( pSrcList ) */
#if !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT)
|
| ︙ | ︙ | |||
101167 101168 101169 101170 101171 101172 101173 |
&& (pNC->ncFlags & NC_UEList)!=0
&& zTab==0
){
pEList = pNC->uNC.pEList;
assert( pEList!=0 );
for(j=0; j<pEList->nExpr; j++){
char *zAs = pEList->a[j].zEName;
| | | 102023 102024 102025 102026 102027 102028 102029 102030 102031 102032 102033 102034 102035 102036 102037 |
&& (pNC->ncFlags & NC_UEList)!=0
&& zTab==0
){
pEList = pNC->uNC.pEList;
assert( pEList!=0 );
for(j=0; j<pEList->nExpr; j++){
char *zAs = pEList->a[j].zEName;
if( pEList->a[j].fg.eEName==ENAME_NAME
&& sqlite3_stricmp(zAs, zCol)==0
){
Expr *pOrig;
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
assert( ExprUseXList(pExpr)==0 || pExpr->x.pList==0 );
assert( ExprUseXSelect(pExpr)==0 || pExpr->x.pSelect==0 );
pOrig = pEList->a[j].pExpr;
|
| ︙ | ︙ | |||
101254 101255 101256 101257 101258 101259 101260 |
}
if( sqlite3ExprIdToTrueFalse(pExpr) ){
return WRC_Prune;
}
}
/*
| | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < < | 102110 102111 102112 102113 102114 102115 102116 102117 102118 102119 102120 102121 102122 102123 102124 102125 102126 102127 102128 102129 102130 102131 102132 102133 102134 102135 102136 102137 102138 102139 102140 102141 102142 102143 102144 102145 102146 102147 102148 102149 102150 102151 102152 102153 102154 102155 102156 102157 102158 102159 102160 102161 102162 102163 102164 102165 102166 102167 102168 102169 102170 102171 102172 102173 102174 102175 102176 102177 102178 102179 102180 102181 102182 102183 102184 102185 102186 102187 102188 102189 102190 102191 102192 102193 102194 102195 102196 |
}
if( sqlite3ExprIdToTrueFalse(pExpr) ){
return WRC_Prune;
}
}
/*
** cnt==0 means there was not match.
** cnt>1 means there were two or more matches.
**
** cnt==0 is always an error. cnt>1 is often an error, but might
** be multiple matches for a NATURAL LEFT JOIN or a LEFT JOIN USING.
*/
assert( pFJMatch==0 || cnt>0 );
assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
if( cnt!=1 ){
const char *zErr;
if( pFJMatch ){
if( pFJMatch->nExpr==cnt-1 ){
if( ExprHasProperty(pExpr,EP_Leaf) ){
ExprClearProperty(pExpr,EP_Leaf);
}else{
sqlite3ExprDelete(db, pExpr->pLeft);
pExpr->pLeft = 0;
sqlite3ExprDelete(db, pExpr->pRight);
pExpr->pRight = 0;
}
extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
pExpr->op = TK_FUNCTION;
pExpr->u.zToken = "coalesce";
pExpr->x.pList = pFJMatch;
cnt = 1;
goto lookupname_end;
}else{
sqlite3ExprListDelete(db, pFJMatch);
pFJMatch = 0;
}
}
zErr = cnt==0 ? "no such column" : "ambiguous column name";
if( zDb ){
sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
}else if( zTab ){
sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
}
sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
pParse->checkSchema = 1;
pTopNC->nNcErr++;
}
assert( pFJMatch==0 );
/* Remove all substructure from pExpr */
if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
sqlite3ExprDelete(db, pExpr->pLeft);
pExpr->pLeft = 0;
sqlite3ExprDelete(db, pExpr->pRight);
pExpr->pRight = 0;
ExprSetProperty(pExpr, EP_Leaf);
}
/* If a column from a table in pSrcList is referenced, then record
** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
** bit 0 to be set. Column 1 sets bit 1. And so forth. Bit 63 is
** set if the 63rd or any subsequent column is used.
**
** The colUsed mask is an optimization used to help determine if an
** index is a covering index. The correct answer is still obtained
** if the mask contains extra set bits. However, it is important to
** avoid setting bits beyond the maximum column number of the table.
** (See ticket [b92e5e8ec2cdbaa1]).
**
** If a generated column is referenced, set bits for every column
** of the table.
*/
if( pExpr->iColumn>=0 && pMatch!=0 ){
pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
}
pExpr->op = eNewExprOp;
lookupname_end:
if( cnt==1 ){
assert( pNC!=0 );
#ifndef SQLITE_OMIT_AUTHORIZATION
if( pParse->db->xAuth
&& (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER)
){
|
| ︙ | ︙ | |||
101484 101485 101486 101487 101488 101489 101490 |
NameContext *p;
int i;
for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
anRef[i] = p->nRef;
}
sqlite3WalkExpr(pWalker, pExpr->pLeft);
if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
| | | 102367 102368 102369 102370 102371 102372 102373 102374 102375 102376 102377 102378 102379 102380 102381 |
NameContext *p;
int i;
for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
anRef[i] = p->nRef;
}
sqlite3WalkExpr(pWalker, pExpr->pLeft);
if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
testcase( ExprHasProperty(pExpr, EP_OuterON) );
assert( !ExprHasProperty(pExpr, EP_IntValue) );
if( pExpr->op==TK_NOTNULL ){
pExpr->u.zToken = "true";
ExprSetProperty(pExpr, EP_IsTrue);
}else{
pExpr->u.zToken = "false";
ExprSetProperty(pExpr, EP_IsFalse);
|
| ︙ | ︙ | |||
101893 101894 101895 101896 101897 101898 101899 |
UNUSED_PARAMETER(pParse);
if( pE->op==TK_ID ){
const char *zCol;
assert( !ExprHasProperty(pE, EP_IntValue) );
zCol = pE->u.zToken;
for(i=0; i<pEList->nExpr; i++){
| | | 102776 102777 102778 102779 102780 102781 102782 102783 102784 102785 102786 102787 102788 102789 102790 |
UNUSED_PARAMETER(pParse);
if( pE->op==TK_ID ){
const char *zCol;
assert( !ExprHasProperty(pE, EP_IntValue) );
zCol = pE->u.zToken;
for(i=0; i<pEList->nExpr; i++){
if( pEList->a[i].fg.eEName==ENAME_NAME
&& sqlite3_stricmp(pEList->a[i].zEName, zCol)==0
){
return i+1;
}
}
}
return 0;
|
| ︙ | ︙ | |||
102014 102015 102016 102017 102018 102019 102020 |
if( pOrderBy==0 ) return 0;
db = pParse->db;
if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
return 1;
}
for(i=0; i<pOrderBy->nExpr; i++){
| | | | 102897 102898 102899 102900 102901 102902 102903 102904 102905 102906 102907 102908 102909 102910 102911 102912 102913 102914 102915 102916 102917 102918 102919 102920 102921 102922 102923 102924 102925 102926 |
if( pOrderBy==0 ) return 0;
db = pParse->db;
if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
return 1;
}
for(i=0; i<pOrderBy->nExpr; i++){
pOrderBy->a[i].fg.done = 0;
}
pSelect->pNext = 0;
while( pSelect->pPrior ){
pSelect->pPrior->pNext = pSelect;
pSelect = pSelect->pPrior;
}
while( pSelect && moreToDo ){
struct ExprList_item *pItem;
moreToDo = 0;
pEList = pSelect->pEList;
assert( pEList!=0 );
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
int iCol = -1;
Expr *pE, *pDup;
if( pItem->fg.done ) continue;
pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
if( NEVER(pE==0) ) continue;
if( sqlite3ExprIsInteger(pE, &iCol) ){
if( iCol<=0 || iCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
return 1;
}
|
| ︙ | ︙ | |||
102082 102083 102084 102085 102086 102087 102088 |
while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft;
assert( pParent->pLeft==pE );
pParent->pLeft = pNew;
}
sqlite3ExprDelete(db, pE);
pItem->u.x.iOrderByCol = (u16)iCol;
}
| | | | 102965 102966 102967 102968 102969 102970 102971 102972 102973 102974 102975 102976 102977 102978 102979 102980 102981 102982 102983 102984 102985 102986 102987 |
while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft;
assert( pParent->pLeft==pE );
pParent->pLeft = pNew;
}
sqlite3ExprDelete(db, pE);
pItem->u.x.iOrderByCol = (u16)iCol;
}
pItem->fg.done = 1;
}else{
moreToDo = 1;
}
}
pSelect = pSelect->pNext;
}
for(i=0; i<pOrderBy->nExpr; i++){
if( pOrderBy->a[i].fg.done==0 ){
sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
"column in the result set", i+1);
return 1;
}
}
return 0;
}
|
| ︙ | ︙ | |||
103775 103776 103777 103778 103779 103780 103781 103782 103783 103784 103785 103786 103787 103788 |
sqlite3 *db = pParse->db;
assert( pToken );
pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1);
if( pNew==0 ){
sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
return 0;
}
pNew->w.iOfst = (int)(pToken->z - pParse->zTail);
if( pList
&& pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG]
&& !pParse->nested
){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
}
| > | 104658 104659 104660 104661 104662 104663 104664 104665 104666 104667 104668 104669 104670 104671 104672 |
sqlite3 *db = pParse->db;
assert( pToken );
pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1);
if( pNew==0 ){
sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
return 0;
}
assert( !ExprHasProperty(pNew, EP_InnerON|EP_OuterON) );
pNew->w.iOfst = (int)(pToken->z - pParse->zTail);
if( pList
&& pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG]
&& !pParse->nested
){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
}
|
| ︙ | ︙ | |||
103955 103956 103957 103958 103959 103960 103961 103962 103963 103964 103965 103966 103967 103968 |
sqlite3DbFreeNN(db, p);
}
}
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
/*
** Arrange to cause pExpr to be deleted when the pParse is deleted.
** This is similar to sqlite3ExprDelete() except that the delete is
** deferred untilthe pParse is deleted.
**
** The pExpr might be deleted immediately on an OOM error.
| > > > > > > > > > > > > | 104839 104840 104841 104842 104843 104844 104845 104846 104847 104848 104849 104850 104851 104852 104853 104854 104855 104856 104857 104858 104859 104860 104861 104862 104863 104864 |
sqlite3DbFreeNN(db, p);
}
}
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
/*
** Clear both elements of an OnOrUsing object
*/
SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){
if( p==0 ){
/* Nothing to clear */
}else if( p->pOn ){
sqlite3ExprDeleteNN(db, p->pOn);
}else if( p->pUsing ){
sqlite3IdListDelete(db, p->pUsing);
}
}
/*
** Arrange to cause pExpr to be deleted when the pParse is deleted.
** This is similar to sqlite3ExprDelete() except that the delete is
** deferred untilthe pParse is deleted.
**
** The pExpr might be deleted immediately on an OOM error.
|
| ︙ | ︙ | |||
104041 104042 104043 104044 104045 104046 104047 |
#ifndef SQLITE_OMIT_WINDOWFUNC
|| ExprHasProperty(p, EP_WinFunc)
#endif
){
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
| | | 104937 104938 104939 104940 104941 104942 104943 104944 104945 104946 104947 104948 104949 104950 104951 |
#ifndef SQLITE_OMIT_WINDOWFUNC
|| ExprHasProperty(p, EP_WinFunc)
#endif
){
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(p, EP_OuterON) );
assert( !ExprHasProperty(p, EP_MemToken) );
assert( !ExprHasVVAProperty(p, EP_NoReduce) );
if( p->pLeft || p->x.pList ){
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
}else{
assert( p->pRight==0 );
nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
|
| ︙ | ︙ | |||
104221 104222 104223 104224 104225 104226 104227 104228 104229 104230 104231 104232 104233 104234 |
if( pRet ){
int i;
pRet->nCte = p->nCte;
for(i=0; i<p->nCte; i++){
pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0);
pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0);
pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName);
}
}
}
return pRet;
}
#else
# define sqlite3WithDup(x,y) 0
| > | 105117 105118 105119 105120 105121 105122 105123 105124 105125 105126 105127 105128 105129 105130 105131 |
if( pRet ){
int i;
pRet->nCte = p->nCte;
for(i=0; i<p->nCte; i++){
pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0);
pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0);
pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName);
pRet->a[i].eM10d = p->a[i].eM10d;
}
}
}
return pRet;
}
#else
# define sqlite3WithDup(x,y) 0
|
| ︙ | ︙ | |||
104321 104322 104323 104324 104325 104326 104327 |
pPriorSelectColNew = sqlite3ExprDup(db, pPriorSelectColOld, flags);
pNewExpr->pRight = pPriorSelectColNew;
}
pNewExpr->pLeft = pPriorSelectColNew;
}
}
pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
| < | | < < | 105218 105219 105220 105221 105222 105223 105224 105225 105226 105227 105228 105229 105230 105231 105232 105233 |
pPriorSelectColNew = sqlite3ExprDup(db, pPriorSelectColOld, flags);
pNewExpr->pRight = pPriorSelectColNew;
}
pNewExpr->pLeft = pPriorSelectColNew;
}
}
pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
pItem->fg = pOldItem->fg;
pItem->fg.done = 0;
pItem->u = pOldItem->u;
}
return pNew;
}
/*
** If cursors, triggers, views and subqueries are all omitted from
|
| ︙ | ︙ | |||
104377 104378 104379 104380 104381 104382 104383 |
sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
}
pTab = pNewItem->pTab = pOldItem->pTab;
if( pTab ){
pTab->nTabRef++;
}
pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
| | > | > > > > | < | < < < < < < | | | 105271 105272 105273 105274 105275 105276 105277 105278 105279 105280 105281 105282 105283 105284 105285 105286 105287 105288 105289 105290 105291 105292 105293 105294 105295 105296 105297 105298 105299 105300 105301 105302 105303 105304 105305 105306 105307 105308 105309 |
sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
}
pTab = pNewItem->pTab = pOldItem->pTab;
if( pTab ){
pTab->nTabRef++;
}
pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
if( pOldItem->fg.isUsing ){
assert( pNewItem->fg.isUsing );
pNewItem->u3.pUsing = sqlite3IdListDup(db, pOldItem->u3.pUsing);
}else{
pNewItem->u3.pOn = sqlite3ExprDup(db, pOldItem->u3.pOn, flags);
}
pNewItem->colUsed = pOldItem->colUsed;
}
return pNew;
}
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){
IdList *pNew;
int i;
assert( db!=0 );
if( p==0 ) return 0;
assert( p->eU4!=EU4_EXPR );
pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) );
if( pNew==0 ) return 0;
pNew->nId = p->nId;
pNew->eU4 = p->eU4;
for(i=0; i<p->nId; i++){
struct IdList_item *pNewItem = &pNew->a[i];
const struct IdList_item *pOldItem = &p->a[i];
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->u4 = pOldItem->u4;
}
return pNew;
}
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int flags){
Select *pRet = 0;
Select *pNext = 0;
Select **pp = &pRet;
|
| ︙ | ︙ | |||
104627 104628 104629 104630 104631 104632 104633 |
);
assert( eNulls==SQLITE_SO_UNDEFINED
|| eNulls==SQLITE_SO_ASC
|| eNulls==SQLITE_SO_DESC
);
pItem = &p->a[p->nExpr-1];
| | | | | | 105519 105520 105521 105522 105523 105524 105525 105526 105527 105528 105529 105530 105531 105532 105533 105534 105535 105536 105537 105538 105539 105540 105541 105542 |
);
assert( eNulls==SQLITE_SO_UNDEFINED
|| eNulls==SQLITE_SO_ASC
|| eNulls==SQLITE_SO_DESC
);
pItem = &p->a[p->nExpr-1];
assert( pItem->fg.bNulls==0 );
if( iSortOrder==SQLITE_SO_UNDEFINED ){
iSortOrder = SQLITE_SO_ASC;
}
pItem->fg.sortFlags = (u8)iSortOrder;
if( eNulls!=SQLITE_SO_UNDEFINED ){
pItem->fg.bNulls = 1;
if( iSortOrder!=eNulls ){
pItem->fg.sortFlags |= KEYINFO_ORDER_BIGNULL;
}
}
}
/*
** Set the ExprList.a[].zEName element of the most recently added item
** on the expression list.
|
| ︙ | ︙ | |||
104662 104663 104664 104665 104666 104667 104668 |
assert( pList!=0 || pParse->db->mallocFailed!=0 );
assert( pParse->eParseMode!=PARSE_MODE_UNMAP || dequote==0 );
if( pList ){
struct ExprList_item *pItem;
assert( pList->nExpr>0 );
pItem = &pList->a[pList->nExpr-1];
assert( pItem->zEName==0 );
| | | 105554 105555 105556 105557 105558 105559 105560 105561 105562 105563 105564 105565 105566 105567 105568 |
assert( pList!=0 || pParse->db->mallocFailed!=0 );
assert( pParse->eParseMode!=PARSE_MODE_UNMAP || dequote==0 );
if( pList ){
struct ExprList_item *pItem;
assert( pList->nExpr>0 );
pItem = &pList->a[pList->nExpr-1];
assert( pItem->zEName==0 );
assert( pItem->fg.eEName==ENAME_NAME );
pItem->zEName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
if( dequote ){
/* If dequote==0, then pName->z does not point to part of a DDL
** statement handled by the parser. And so no token need be added
** to the token-map. */
sqlite3Dequote(pItem->zEName);
if( IN_RENAME_OBJECT ){
|
| ︙ | ︙ | |||
104697 104698 104699 104700 104701 104702 104703 |
sqlite3 *db = pParse->db;
assert( pList!=0 || db->mallocFailed!=0 );
if( pList ){
struct ExprList_item *pItem = &pList->a[pList->nExpr-1];
assert( pList->nExpr>0 );
if( pItem->zEName==0 ){
pItem->zEName = sqlite3DbSpanDup(db, zStart, zEnd);
| | | 105589 105590 105591 105592 105593 105594 105595 105596 105597 105598 105599 105600 105601 105602 105603 |
sqlite3 *db = pParse->db;
assert( pList!=0 || db->mallocFailed!=0 );
if( pList ){
struct ExprList_item *pItem = &pList->a[pList->nExpr-1];
assert( pList->nExpr>0 );
if( pItem->zEName==0 ){
pItem->zEName = sqlite3DbSpanDup(db, zStart, zEnd);
pItem->fg.eEName = ENAME_SPAN;
}
}
}
/*
** If the expression list pEList contains more than iLimit elements,
** leave an error message in pParse.
|
| ︙ | ︙ | |||
104869 104870 104871 104872 104873 104874 104875 |
** contain a bound parameter because they were generated by older versions
** of SQLite to be parsed by newer versions of SQLite without raising a
** malformed schema error.
*/
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
/* If pWalker->eCode is 2 then any term of the expression that comes from
| | | | 105761 105762 105763 105764 105765 105766 105767 105768 105769 105770 105771 105772 105773 105774 105775 105776 105777 |
** contain a bound parameter because they were generated by older versions
** of SQLite to be parsed by newer versions of SQLite without raising a
** malformed schema error.
*/
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
/* If pWalker->eCode is 2 then any term of the expression that comes from
** the ON or USING clauses of an outer join disqualifies the expression
** from being considered constant. */
if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_OuterON) ){
pWalker->eCode = 0;
return WRC_Abort;
}
switch( pExpr->op ){
/* Consider functions to be constant if all their arguments are constant
** and either pWalker->eCode==4 or 5 or the function has the
|
| ︙ | ︙ | |||
104989 104990 104991 104992 104993 104994 104995 104996 104997 104998 104999 105000 105001 105002 |
** for any single row of the table with cursor iCur. In other words, the
** expression must not refer to any non-deterministic function nor any
** table other than iCur.
*/
SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){
return exprIsConst(p, 3, iCur);
}
/*
** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
*/
static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
ExprList *pGroupBy = pWalker->u.pGroupBy;
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 105881 105882 105883 105884 105885 105886 105887 105888 105889 105890 105891 105892 105893 105894 105895 105896 105897 105898 105899 105900 105901 105902 105903 105904 105905 105906 105907 105908 105909 105910 105911 105912 105913 105914 105915 105916 105917 105918 105919 105920 105921 105922 105923 105924 105925 105926 105927 105928 105929 105930 |
** for any single row of the table with cursor iCur. In other words, the
** expression must not refer to any non-deterministic function nor any
** table other than iCur.
*/
SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){
return exprIsConst(p, 3, iCur);
}
/*
** Check pExpr to see if it is an invariant constraint on data source pSrc.
** This is an optimization. False negatives will perhaps cause slower
** queries, but false positives will yield incorrect answers. So when in
** doubt, return 0.
**
** To be an invariant constraint, the following must be true:
**
** (1) pExpr cannot refer to any table other than pSrc->iCursor.
**
** (2) pExpr cannot use subqueries or non-deterministic functions.
**
** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
** (Is there some way to relax this constraint?)
**
** (4) If pSrc is the right operand of a LEFT JOIN, then...
** (4a) pExpr must come from an ON clause..
(4b) and specifically the ON clause associated with the LEFT JOIN.
**
** (5) If pSrc is not the right operand of a LEFT JOIN or the left
** operand of a RIGHT JOIN, then pExpr must be from the WHERE
** clause, not an ON clause.
*/
SQLITE_PRIVATE int sqlite3ExprIsTableConstraint(Expr *pExpr, const SrcItem *pSrc){
if( pSrc->fg.jointype & JT_LTORJ ){
return 0; /* rule (3) */
}
if( pSrc->fg.jointype & JT_LEFT ){
if( !ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (4a) */
if( pExpr->w.iJoin!=pSrc->iCursor ) return 0; /* rule (4b) */
}else{
if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (5) */
}
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
}
/*
** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
*/
static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
ExprList *pGroupBy = pWalker->u.pGroupBy;
|
| ︙ | ︙ | |||
105317 105318 105319 105320 105321 105322 105323 | ** might be either a list of expressions or a subquery. ** ** The job of this routine is to find or create a b-tree object that can ** be used either to test for membership in the RHS set or to iterate through ** all members of the RHS set, skipping duplicates. ** ** A cursor is opened on the b-tree object that is the RHS of the IN operator | | | > > > | 106245 106246 106247 106248 106249 106250 106251 106252 106253 106254 106255 106256 106257 106258 106259 106260 106261 106262 106263 106264 106265 106266 106267 106268 106269 106270 106271 106272 106273 106274 106275 106276 106277 106278 106279 106280 106281 106282 | ** might be either a list of expressions or a subquery. ** ** The job of this routine is to find or create a b-tree object that can ** be used either to test for membership in the RHS set or to iterate through ** all members of the RHS set, skipping duplicates. ** ** A cursor is opened on the b-tree object that is the RHS of the IN operator ** and the *piTab parameter is set to the index of that cursor. ** ** The returned value of this function indicates the b-tree type, as follows: ** ** IN_INDEX_ROWID - The cursor was opened on a database table. ** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index. ** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index. ** IN_INDEX_EPH - The cursor was opened on a specially created and ** populated epheremal table. ** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be ** implemented as a sequence of comparisons. ** ** An existing b-tree might be used if the RHS expression pX is a simple ** subquery such as: ** ** SELECT <column1>, <column2>... FROM <table> ** ** If the RHS of the IN operator is a list or a more complex subquery, then ** an ephemeral table might need to be generated from the RHS and then ** pX->iTable made to point to the ephemeral table instead of an ** existing table. In this case, the creation and initialization of the ** ephmeral table might be put inside of a subroutine, the EP_Subrtn flag ** will be set on pX and the pX->y.sub fields will be set to show where ** the subroutine is coded. ** ** The inFlags parameter must contain, at a minimum, one of the bits ** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP but not both. If inFlags contains ** IN_INDEX_MEMBERSHIP, then the generated table will be used for a fast ** membership test. When the IN_INDEX_LOOP bit is set, the IN index will ** be used to loop over all values of the RHS of the IN operator. ** |
| ︙ | ︙ | |||
105398 105399 105400 105401 105402 105403 105404 |
u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */
int *prRhsHasNull, /* Register holding NULL status. See notes */
int *aiMap, /* Mapping from Index fields to RHS fields */
int *piTab /* OUT: index to use */
){
Select *p; /* SELECT to the right of IN operator */
int eType = 0; /* Type of RHS table. IN_INDEX_* */
| | > | 106329 106330 106331 106332 106333 106334 106335 106336 106337 106338 106339 106340 106341 106342 106343 106344 106345 106346 106347 106348 106349 |
u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */
int *prRhsHasNull, /* Register holding NULL status. See notes */
int *aiMap, /* Mapping from Index fields to RHS fields */
int *piTab /* OUT: index to use */
){
Select *p; /* SELECT to the right of IN operator */
int eType = 0; /* Type of RHS table. IN_INDEX_* */
int iTab; /* Cursor of the RHS table */
int mustBeUnique; /* True if RHS must be unique */
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
assert( pX->op==TK_IN );
mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0;
iTab = pParse->nTab++;
/* If the RHS of this IN(...) operator is a SELECT, and if it matters
** whether or not the SELECT result contains NULL values, check whether
** or not NULL is actually possible (it may not be, for example, due
** to NOT NULL constraints in the schema). If no NULL values are possible,
** set prRhsHasNull to 0 before continuing. */
if( prRhsHasNull && ExprUseXSelect(pX) ){
|
| ︙ | ︙ | |||
105569 105570 105571 105572 105573 105574 105575 105576 105577 105578 105579 105580 105581 105582 |
** the IN operator so return IN_INDEX_NOOP.
*/
if( eType==0
&& (inFlags & IN_INDEX_NOOP_OK)
&& ExprUseXList(pX)
&& (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
){
eType = IN_INDEX_NOOP;
}
if( eType==0 ){
/* Could not find an existing table or index to use as the RHS b-tree.
** We will have to generate an ephemeral table to do the job.
*/
| > > | 106501 106502 106503 106504 106505 106506 106507 106508 106509 106510 106511 106512 106513 106514 106515 106516 |
** the IN operator so return IN_INDEX_NOOP.
*/
if( eType==0
&& (inFlags & IN_INDEX_NOOP_OK)
&& ExprUseXList(pX)
&& (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
){
pParse->nTab--; /* Back out the allocation of the unused cursor */
iTab = -1; /* Cursor is not allocated */
eType = IN_INDEX_NOOP;
}
if( eType==0 ){
/* Could not find an existing table or index to use as the RHS b-tree.
** We will have to generate an ephemeral table to do the job.
*/
|
| ︙ | ︙ | |||
105735 105736 105737 105738 105739 105740 105741 105742 105743 105744 105745 105746 105747 105748 |
if( ExprUseXSelect(pExpr) ){
ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
pExpr->x.pSelect->selId));
}
assert( ExprUseYSub(pExpr) );
sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
pExpr->y.sub.iAddr);
sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
sqlite3VdbeJumpHere(v, addrOnce);
return;
}
/* Begin coding the subroutine */
assert( !ExprUseYWin(pExpr) );
| > | 106669 106670 106671 106672 106673 106674 106675 106676 106677 106678 106679 106680 106681 106682 106683 |
if( ExprUseXSelect(pExpr) ){
ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
pExpr->x.pSelect->selId));
}
assert( ExprUseYSub(pExpr) );
sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
pExpr->y.sub.iAddr);
assert( iTab!=pExpr->iTable );
sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
sqlite3VdbeJumpHere(v, addrOnce);
return;
}
/* Begin coding the subroutine */
assert( !ExprUseYWin(pExpr) );
|
| ︙ | ︙ | |||
105871 105872 105873 105874 105875 105876 105877 |
}
if( addrOnce ){
sqlite3VdbeJumpHere(v, addrOnce);
/* Subroutine return */
assert( ExprUseYSub(pExpr) );
assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
|| pParse->nErr );
| | | | | 106806 106807 106808 106809 106810 106811 106812 106813 106814 106815 106816 106817 106818 106819 106820 106821 106822 |
}
if( addrOnce ){
sqlite3VdbeJumpHere(v, addrOnce);
/* Subroutine return */
assert( ExprUseYSub(pExpr) );
assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
|| pParse->nErr );
sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn,
pExpr->y.sub.iAddr, 1);
VdbeCoverage(v);
sqlite3ClearTempRegCache(pParse);
}
}
#endif /* SQLITE_OMIT_SUBQUERY */
/*
** Generate code for scalar subqueries used as a subquery expression
|
| ︙ | ︙ | |||
106002 106003 106004 106005 106006 106007 106008 |
sqlite3VdbeJumpHere(v, addrOnce);
}
/* Subroutine return */
assert( ExprUseYSub(pExpr) );
assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
|| pParse->nErr );
| | | | | 106937 106938 106939 106940 106941 106942 106943 106944 106945 106946 106947 106948 106949 106950 106951 106952 106953 |
sqlite3VdbeJumpHere(v, addrOnce);
}
/* Subroutine return */
assert( ExprUseYSub(pExpr) );
assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
|| pParse->nErr );
sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn,
pExpr->y.sub.iAddr, 1);
VdbeCoverage(v);
sqlite3ClearTempRegCache(pParse);
return rReg;
}
#endif /* SQLITE_OMIT_SUBQUERY */
#ifndef SQLITE_OMIT_SUBQUERY
/*
|
| ︙ | ︙ | |||
106438 106439 106440 106441 106442 106443 106444 106445 106446 106447 106448 106449 106450 106451 |
assert( v!=0 );
if( pTab==0 ){
sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
return;
}
if( iCol<0 || iCol==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
}else{
int op;
int x;
if( IsVirtual(pTab) ){
op = OP_VColumn;
x = iCol;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
| > | 107373 107374 107375 107376 107377 107378 107379 107380 107381 107382 107383 107384 107385 107386 107387 |
assert( v!=0 );
if( pTab==0 ){
sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
return;
}
if( iCol<0 || iCol==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
VdbeComment((v, "%s.rowid", pTab->zName));
}else{
int op;
int x;
if( IsVirtual(pTab) ){
op = OP_VColumn;
x = iCol;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
| ︙ | ︙ | |||
106608 106609 106610 106611 106612 106613 106614 |
case INLINEFUNC_iif: {
Expr caseExpr;
memset(&caseExpr, 0, sizeof(caseExpr));
caseExpr.op = TK_CASE;
caseExpr.x.pList = pFarg;
return sqlite3ExprCodeTarget(pParse, &caseExpr, target);
}
| > > > > > > > | > > > | 107544 107545 107546 107547 107548 107549 107550 107551 107552 107553 107554 107555 107556 107557 107558 107559 107560 107561 107562 107563 107564 107565 107566 107567 107568 |
case INLINEFUNC_iif: {
Expr caseExpr;
memset(&caseExpr, 0, sizeof(caseExpr));
caseExpr.op = TK_CASE;
caseExpr.x.pList = pFarg;
return sqlite3ExprCodeTarget(pParse, &caseExpr, target);
}
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
case INLINEFUNC_sqlite_offset: {
Expr *pArg = pFarg->a[0].pExpr;
if( pArg->op==TK_COLUMN && pArg->iTable>=0 ){
sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
break;
}
#endif
default: {
/* The UNLIKELY() function is a no-op. The result is the value
** of the first argument.
*/
assert( nFarg==1 || nFarg==2 );
target = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
break;
|
| ︙ | ︙ | |||
107147 107148 107149 107150 107151 107152 107153 |
pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
}
#endif
if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){
if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
| < < < < < < < < < < < | | < | 108093 108094 108095 108096 108097 108098 108099 108100 108101 108102 108103 108104 108105 108106 108107 108108 |
pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
}
#endif
if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){
if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg,
pDef, pExpr->op2);
if( nFarg ){
if( constMask==0 ){
sqlite3ReleaseTempRange(pParse, r1, nFarg);
}else{
sqlite3VdbeReleaseRegisters(pParse, r1, nFarg, constMask, 1);
}
}
|
| ︙ | ︙ | |||
107190 107191 107192 107193 107194 107195 107196 |
}else{
return sqlite3CodeSubselect(pParse, pExpr);
}
break;
}
case TK_SELECT_COLUMN: {
int n;
| | > | > | | | | 108124 108125 108126 108127 108128 108129 108130 108131 108132 108133 108134 108135 108136 108137 108138 108139 108140 108141 108142 108143 108144 108145 108146 108147 108148 108149 |
}else{
return sqlite3CodeSubselect(pParse, pExpr);
}
break;
}
case TK_SELECT_COLUMN: {
int n;
Expr *pLeft = pExpr->pLeft;
if( pLeft->iTable==0 || pParse->withinRJSubrtn > pLeft->op2 ){
pLeft->iTable = sqlite3CodeSubselect(pParse, pLeft);
pLeft->op2 = pParse->withinRJSubrtn;
}
assert( pLeft->op==TK_SELECT || pLeft->op==TK_ERROR );
n = sqlite3ExprVectorSize(pLeft);
if( pExpr->iTable!=n ){
sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
pExpr->iTable, n);
}
return pLeft->iTable + pExpr->iColumn;
}
case TK_IN: {
int destIfFalse = sqlite3VdbeMakeLabel(pParse);
int destIfNull = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
|
| ︙ | ︙ | |||
107229 107230 107231 107232 107233 107234 107235 107236 |
** X is stored in pExpr->pLeft.
** Y is stored in pExpr->pList->a[0].pExpr.
** Z is stored in pExpr->pList->a[1].pExpr.
*/
case TK_BETWEEN: {
exprCodeBetween(pParse, pExpr, target, 0, 0);
return target;
}
| | > > > > > > > > > > > > > > > > | | 108165 108166 108167 108168 108169 108170 108171 108172 108173 108174 108175 108176 108177 108178 108179 108180 108181 108182 108183 108184 108185 108186 108187 108188 108189 108190 108191 108192 108193 108194 108195 108196 108197 |
** X is stored in pExpr->pLeft.
** Y is stored in pExpr->pList->a[0].pExpr.
** Z is stored in pExpr->pList->a[1].pExpr.
*/
case TK_BETWEEN: {
exprCodeBetween(pParse, pExpr, target, 0, 0);
return target;
}
case TK_COLLATE: {
if( !ExprHasProperty(pExpr, EP_Collate)
&& ALWAYS(pExpr->pLeft)
&& pExpr->pLeft->op==TK_FUNCTION
){
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
if( inReg!=target ){
sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
inReg = target;
}
sqlite3VdbeAddOp1(v, OP_ClrSubtype, inReg);
return inReg;
}else{
pExpr = pExpr->pLeft;
goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. */
}
}
case TK_SPAN:
case TK_UPLUS: {
pExpr = pExpr->pLeft;
goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */
}
case TK_TRIGGER: {
/* If the opcode is TK_TRIGGER, then the expression is a reference
|
| ︙ | ︙ | |||
107472 107473 107474 107475 107476 107477 107478 |
ExprList *p;
assert( ConstFactorOk(pParse) );
p = pParse->pConstExpr;
if( regDest<0 && p ){
struct ExprList_item *pItem;
int i;
for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
| > | > | 108424 108425 108426 108427 108428 108429 108430 108431 108432 108433 108434 108435 108436 108437 108438 108439 108440 |
ExprList *p;
assert( ConstFactorOk(pParse) );
p = pParse->pConstExpr;
if( regDest<0 && p ){
struct ExprList_item *pItem;
int i;
for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
if( pItem->fg.reusable
&& sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0
){
return pItem->u.iConstExprReg;
}
}
}
pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
if( pExpr!=0 && ExprHasProperty(pExpr, EP_HasFunc) ){
Vdbe *v = pParse->pVdbe;
|
| ︙ | ︙ | |||
107495 107496 107497 107498 107499 107500 107501 |
pParse->okConstFactor = 1;
sqlite3ExprDelete(pParse->db, pExpr);
sqlite3VdbeJumpHere(v, addr);
}else{
p = sqlite3ExprListAppend(pParse, p, pExpr);
if( p ){
struct ExprList_item *pItem = &p->a[p->nExpr-1];
| | | 108449 108450 108451 108452 108453 108454 108455 108456 108457 108458 108459 108460 108461 108462 108463 |
pParse->okConstFactor = 1;
sqlite3ExprDelete(pParse->db, pExpr);
sqlite3VdbeJumpHere(v, addr);
}else{
p = sqlite3ExprListAppend(pParse, p, pExpr);
if( p ){
struct ExprList_item *pItem = &p->a[p->nExpr-1];
pItem->fg.reusable = regDest<0;
if( regDest<0 ) regDest = ++pParse->nMem;
pItem->u.iConstExprReg = regDest;
}
pParse->pConstExpr = p;
}
return regDest;
}
|
| ︙ | ︙ | |||
107629 107630 107631 107632 107633 107634 107635 |
assert( target>0 );
assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */
n = pList->nExpr;
if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
for(pItem=pList->a, i=0; i<n; i++, pItem++){
Expr *pExpr = pItem->pExpr;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
| | | 108583 108584 108585 108586 108587 108588 108589 108590 108591 108592 108593 108594 108595 108596 108597 |
assert( target>0 );
assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */
n = pList->nExpr;
if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
for(pItem=pList->a, i=0; i<n; i++, pItem++){
Expr *pExpr = pItem->pExpr;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
if( pItem->fg.bSorterRef ){
i--;
n--;
}else
#endif
if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){
if( flags & SQLITE_ECEL_OMITREF ){
i--;
|
| ︙ | ︙ | |||
107723 107724 107725 107726 107727 107728 107729 |
if( xJump ){
xJump(pParse, &exprAnd, dest, jumpIfNull);
}else{
/* Mark the expression is being from the ON or USING clause of a join
** so that the sqlite3ExprCodeTarget() routine will not attempt to move
** it into the Parse.pConstExpr list. We should use a new bit for this,
** for clarity, but we are out of bits in the Expr.flags field so we
| | | | 108677 108678 108679 108680 108681 108682 108683 108684 108685 108686 108687 108688 108689 108690 108691 108692 |
if( xJump ){
xJump(pParse, &exprAnd, dest, jumpIfNull);
}else{
/* Mark the expression is being from the ON or USING clause of a join
** so that the sqlite3ExprCodeTarget() routine will not attempt to move
** it into the Parse.pConstExpr list. We should use a new bit for this,
** for clarity, but we are out of bits in the Expr.flags field so we
** have to reuse the EP_OuterON bit. Bummer. */
pDel->flags |= EP_OuterON;
sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
}
sqlite3ReleaseTempReg(pParse, regFree1);
}
sqlite3ExprDelete(db, pDel);
/* Ensure adequate test coverage */
|
| ︙ | ︙ | |||
108254 108255 108256 108257 108258 108259 108260 |
if( pA==0 && pB==0 ) return 0;
if( pA==0 || pB==0 ) return 1;
if( pA->nExpr!=pB->nExpr ) return 1;
for(i=0; i<pA->nExpr; i++){
int res;
Expr *pExprA = pA->a[i].pExpr;
Expr *pExprB = pB->a[i].pExpr;
| | | 109208 109209 109210 109211 109212 109213 109214 109215 109216 109217 109218 109219 109220 109221 109222 |
if( pA==0 && pB==0 ) return 0;
if( pA==0 || pB==0 ) return 1;
if( pA->nExpr!=pB->nExpr ) return 1;
for(i=0; i<pA->nExpr; i++){
int res;
Expr *pExprA = pA->a[i].pExpr;
Expr *pExprB = pB->a[i].pExpr;
if( pA->a[i].fg.sortFlags!=pB->a[i].fg.sortFlags ) return 1;
if( (res = sqlite3ExprCompare(0, pExprA, pExprB, iTab)) ) return res;
}
return 0;
}
/*
** Like sqlite3ExprCompare() except COLLATE operators at the top-level
|
| ︙ | ︙ | |||
108409 108410 108411 108412 108413 108414 108415 |
** This routine controls an optimization. False positives (setting
** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives
** (never setting pWalker->eCode) is a harmless missed optimization.
*/
static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_AGG_COLUMN );
testcase( pExpr->op==TK_AGG_FUNCTION );
| | | 109363 109364 109365 109366 109367 109368 109369 109370 109371 109372 109373 109374 109375 109376 109377 |
** This routine controls an optimization. False positives (setting
** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives
** (never setting pWalker->eCode) is a harmless missed optimization.
*/
static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_AGG_COLUMN );
testcase( pExpr->op==TK_AGG_FUNCTION );
if( ExprHasProperty(pExpr, EP_OuterON) ) return WRC_Prune;
switch( pExpr->op ){
case TK_ISNOT:
case TK_ISNULL:
case TK_NOTNULL:
case TK_IS:
case TK_OR:
case TK_VECTOR:
|
| ︙ | ︙ | |||
108506 108507 108508 108509 108510 108511 108512 | ** False negatives are acceptable. In other words, it is ok to return ** zero even if expression p will never be true of every column of iTab ** is NULL. A false negative is merely a missed optimization opportunity. ** ** False positives are not allowed, however. A false positive may result ** in an incorrect answer. ** | | | | 109460 109461 109462 109463 109464 109465 109466 109467 109468 109469 109470 109471 109472 109473 109474 109475 | ** False negatives are acceptable. In other words, it is ok to return ** zero even if expression p will never be true of every column of iTab ** is NULL. A false negative is merely a missed optimization opportunity. ** ** False positives are not allowed, however. A false positive may result ** in an incorrect answer. ** ** Terms of p that are marked with EP_OuterON (and hence that come from ** the ON or USING clauses of OUTER JOINS) are excluded from the analysis. ** ** This routine is used to check if a LEFT JOIN can be converted into ** an ordinary JOIN. The p argument is the WHERE clause. If the WHERE ** clause requires that some column of the right table of the LEFT JOIN ** be non-NULL, then the LEFT JOIN can be safely converted into an ** ordinary join. */ |
| ︙ | ︙ | |||
109921 109922 109923 109924 109925 109926 109927 |
/*
** Unmap all tokens in the IdList object passed as the second argument.
*/
static void unmapColumnIdlistNames(
Parse *pParse,
const IdList *pIdList
){
| < | > | | < | > | > | > | 110875 110876 110877 110878 110879 110880 110881 110882 110883 110884 110885 110886 110887 110888 110889 110890 110891 110892 110893 110894 110895 110896 110897 110898 110899 110900 110901 110902 110903 110904 110905 110906 110907 110908 110909 110910 110911 110912 110913 110914 110915 110916 110917 110918 110919 110920 110921 110922 110923 110924 |
/*
** Unmap all tokens in the IdList object passed as the second argument.
*/
static void unmapColumnIdlistNames(
Parse *pParse,
const IdList *pIdList
){
int ii;
assert( pIdList!=0 );
for(ii=0; ii<pIdList->nId; ii++){
sqlite3RenameTokenRemap(pParse, 0, (const void*)pIdList->a[ii].zName);
}
}
/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i;
if( pParse->nErr ) return WRC_Abort;
testcase( p->selFlags & SF_View );
testcase( p->selFlags & SF_CopyCte );
if( p->selFlags & (SF_View|SF_CopyCte) ){
return WRC_Prune;
}
if( ALWAYS(p->pEList) ){
ExprList *pList = p->pEList;
for(i=0; i<pList->nExpr; i++){
if( pList->a[i].zEName && pList->a[i].fg.eEName==ENAME_NAME ){
sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName);
}
}
}
if( ALWAYS(p->pSrc) ){ /* Every Select as a SrcList, even if it is empty */
SrcList *pSrc = p->pSrc;
for(i=0; i<pSrc->nSrc; i++){
sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName);
if( pSrc->a[i].fg.isUsing==0 ){
sqlite3WalkExpr(pWalker, pSrc->a[i].u3.pOn);
}else{
unmapColumnIdlistNames(pParse, pSrc->a[i].u3.pUsing);
}
}
}
renameWalkWith(pWalker, p);
return WRC_Continue;
}
|
| ︙ | ︙ | |||
109990 109991 109992 109993 109994 109995 109996 |
int i;
Walker sWalker;
memset(&sWalker, 0, sizeof(Walker));
sWalker.pParse = pParse;
sWalker.xExprCallback = renameUnmapExprCb;
sqlite3WalkExprList(&sWalker, pEList);
for(i=0; i<pEList->nExpr; i++){
| | | 110946 110947 110948 110949 110950 110951 110952 110953 110954 110955 110956 110957 110958 110959 110960 |
int i;
Walker sWalker;
memset(&sWalker, 0, sizeof(Walker));
sWalker.pParse = pParse;
sWalker.xExprCallback = renameUnmapExprCb;
sqlite3WalkExprList(&sWalker, pEList);
for(i=0; i<pEList->nExpr; i++){
if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) ){
sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zEName);
}
}
}
}
/*
|
| ︙ | ︙ | |||
110148 110149 110150 110151 110152 110153 110154 |
const ExprList *pEList,
const char *zOld
){
if( pEList ){
int i;
for(i=0; i<pEList->nExpr; i++){
const char *zName = pEList->a[i].zEName;
| | | 111104 111105 111106 111107 111108 111109 111110 111111 111112 111113 111114 111115 111116 111117 111118 |
const ExprList *pEList,
const char *zOld
){
if( pEList ){
int i;
for(i=0; i<pEList->nExpr; i++){
const char *zName = pEList->a[i].zEName;
if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME)
&& ALWAYS(zName!=0)
&& 0==sqlite3_stricmp(zName, zOld)
){
renameTokenFind(pParse, pCtx, (const void*)zName);
}
}
}
|
| ︙ | ︙ | |||
110378 110379 110380 110381 110382 110383 110384 |
if( pStep->pSelect ){
sqlite3SelectPrep(pParse, pStep->pSelect, &sNC);
if( pParse->nErr ) rc = pParse->rc;
}
if( rc==SQLITE_OK && pStep->zTarget ){
SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep);
if( pSrc ){
| > > > > > > > > > > > > > > > > > | | | < | | < < < < < < < < < < < > | | 111334 111335 111336 111337 111338 111339 111340 111341 111342 111343 111344 111345 111346 111347 111348 111349 111350 111351 111352 111353 111354 111355 111356 111357 111358 111359 111360 111361 111362 111363 111364 111365 111366 111367 111368 111369 111370 111371 111372 111373 111374 |
if( pStep->pSelect ){
sqlite3SelectPrep(pParse, pStep->pSelect, &sNC);
if( pParse->nErr ) rc = pParse->rc;
}
if( rc==SQLITE_OK && pStep->zTarget ){
SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep);
if( pSrc ){
Select *pSel = sqlite3SelectNew(
pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0
);
if( pSel==0 ){
pStep->pExprList = 0;
pSrc = 0;
rc = SQLITE_NOMEM;
}else{
sqlite3SelectPrep(pParse, pSel, 0);
rc = pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
assert( pStep->pExprList==0 || pStep->pExprList==pSel->pEList );
assert( pSrc==pSel->pSrc );
if( pStep->pExprList ) pSel->pEList = 0;
pSel->pSrc = 0;
sqlite3SelectDelete(db, pSel);
}
if( pStep->pFrom ){
int i;
for(i=0; i<pStep->pFrom->nSrc && rc==SQLITE_OK; i++){
SrcItem *p = &pStep->pFrom->a[i];
if( p->pSelect ){
sqlite3SelectPrep(pParse, p->pSelect, 0);
}
}
}
if( db->mallocFailed ){
rc = SQLITE_NOMEM;
}
sNC.pSrcList = pSrc;
if( rc==SQLITE_OK && pStep->pWhere ){
rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere);
}
if( rc==SQLITE_OK ){
|
| ︙ | ︙ | |||
110849 110850 110851 110852 110853 110854 110855 110856 110857 110858 110859 110860 110861 110862 |
if( isLegacy==0 ){
rc = renameResolveTrigger(&sParse);
if( rc==SQLITE_OK ){
renameWalkTrigger(&sWalker, pTrigger);
for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
renameTokenFind(&sParse, &sCtx, pStep->zTarget);
}
}
}
}
}
#endif
}
| > > > > > > > > > | 111811 111812 111813 111814 111815 111816 111817 111818 111819 111820 111821 111822 111823 111824 111825 111826 111827 111828 111829 111830 111831 111832 111833 |
if( isLegacy==0 ){
rc = renameResolveTrigger(&sParse);
if( rc==SQLITE_OK ){
renameWalkTrigger(&sWalker, pTrigger);
for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
renameTokenFind(&sParse, &sCtx, pStep->zTarget);
}
if( pStep->pFrom ){
int i;
for(i=0; i<pStep->pFrom->nSrc; i++){
SrcItem *pItem = &pStep->pFrom->a[i];
if( 0==sqlite3_stricmp(pItem->zName, zOld) ){
renameTokenFind(&sParse, &sCtx, pItem->zName);
}
}
}
}
}
}
}
#endif
}
|
| ︙ | ︙ | |||
112173 112174 112175 112176 112177 112178 112179 |
** "100 10 2", then SQLite estimates that:
**
** * the index contains 100 rows,
** * "WHERE a=?" matches 10 rows, and
** * "WHERE a=? AND b=?" matches 2 rows.
**
** If D is the count of distinct values and K is the total number of
| | > > > > > > | 113144 113145 113146 113147 113148 113149 113150 113151 113152 113153 113154 113155 113156 113157 113158 113159 113160 113161 113162 113163 113164 113165 113166 113167 113168 113169 113170 113171 113172 113173 113174 113175 113176 |
** "100 10 2", then SQLite estimates that:
**
** * the index contains 100 rows,
** * "WHERE a=?" matches 10 rows, and
** * "WHERE a=? AND b=?" matches 2 rows.
**
** If D is the count of distinct values and K is the total number of
** rows, then each estimate is usually computed as:
**
** I = (K+D-1)/D
**
** In other words, I is K/D rounded up to the next whole integer.
** However, if I is between 1.0 and 1.1 (in other words if I is
** close to 1.0 but just a little larger) then do not round up but
** instead keep the I value at 1.0.
*/
sqlite3_str sStat; /* Text of the constructed "stat" line */
int i; /* Loop counter */
sqlite3StrAccumInit(&sStat, 0, 0, 0, (p->nKeyCol+1)*100);
sqlite3_str_appendf(&sStat, "%llu",
p->nSkipAhead ? (u64)p->nEst : (u64)p->nRow);
for(i=0; i<p->nKeyCol; i++){
u64 nDistinct = p->current.anDLt[i] + 1;
u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1;
sqlite3_str_appendf(&sStat, " %llu", iVal);
assert( p->current.anEq[i] );
}
sqlite3ResultStrAccum(context, &sStat);
}
#ifdef SQLITE_ENABLE_STAT4
else if( eCall==STAT_GET_ROWID ){
|
| ︙ | ︙ | |||
113739 113740 113741 113742 113743 113744 113745 |
pItem->zDatabase = 0;
pItem->fg.notCte = 1;
}
pItem->pSchema = pFix->pSchema;
pItem->fg.fromDDL = 1;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
| > | > > > | 114716 114717 114718 114719 114720 114721 114722 114723 114724 114725 114726 114727 114728 114729 114730 114731 114732 114733 114734 |
pItem->zDatabase = 0;
pItem->fg.notCte = 1;
}
pItem->pSchema = pFix->pSchema;
pItem->fg.fromDDL = 1;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( pList->a[i].fg.isUsing==0
&& sqlite3WalkExpr(&pFix->w, pList->a[i].u3.pOn)
){
return WRC_Abort;
}
#endif
}
if( pSelect->pWith ){
for(i=0; i<pSelect->pWith->nCte; i++){
if( sqlite3WalkSelect(p, pSelect->pWith->a[i].pSelect) ){
return WRC_Abort;
}
|
| ︙ | ︙ | |||
114303 114304 114305 114306 114307 114308 114309 |
if( v ){
if( pParse->bReturning ){
Returning *pReturning = pParse->u1.pReturning;
int addrRewind;
int i;
int reg;
| | < < | 115284 115285 115286 115287 115288 115289 115290 115291 115292 115293 115294 115295 115296 115297 115298 |
if( v ){
if( pParse->bReturning ){
Returning *pReturning = pParse->u1.pReturning;
int addrRewind;
int i;
int reg;
if( pReturning->nRetCol ){
sqlite3VdbeAddOp0(v, OP_FkCheck);
addrRewind =
sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur);
VdbeCoverage(v);
reg = pReturning->iRetReg;
for(i=0; i<pReturning->nRetCol; i++){
sqlite3VdbeAddOp3(v, OP_Column, pReturning->iRetCur, i, reg+i);
|
| ︙ | ︙ | |||
114345 114346 114347 114348 114349 114350 114351 |
*/
if( db->mallocFailed==0
&& (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr)
){
int iDb, i;
assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
sqlite3VdbeJumpHere(v, 0);
| | > > | | 115324 115325 115326 115327 115328 115329 115330 115331 115332 115333 115334 115335 115336 115337 115338 115339 115340 115341 115342 115343 115344 115345 115346 115347 115348 115349 115350 115351 115352 115353 115354 115355 |
*/
if( db->mallocFailed==0
&& (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr)
){
int iDb, i;
assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
sqlite3VdbeJumpHere(v, 0);
assert( db->nDb>0 );
iDb = 0;
do{
Schema *pSchema;
if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
sqlite3VdbeUsesBtree(v, iDb);
pSchema = db->aDb[iDb].pSchema;
sqlite3VdbeAddOp4Int(v,
OP_Transaction, /* Opcode */
iDb, /* P1 */
DbMaskTest(pParse->writeMask,iDb), /* P2 */
pSchema->schema_cookie, /* P3 */
pSchema->iGeneration /* P4 */
);
if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
VdbeComment((v,
"usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
}while( ++iDb<db->nDb );
#ifndef SQLITE_OMIT_VIRTUALTABLE
for(i=0; i<pParse->nVtabLock; i++){
char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
}
pParse->nVtabLock = 0;
#endif
|
| ︙ | ︙ | |||
114399 114400 114401 114402 114403 114404 114405 |
sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg);
}
}
}
if( pParse->bReturning ){
Returning *pRet = pParse->u1.pReturning;
| | < < | 115380 115381 115382 115383 115384 115385 115386 115387 115388 115389 115390 115391 115392 115393 115394 |
sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg);
}
}
}
if( pParse->bReturning ){
Returning *pRet = pParse->u1.pReturning;
if( pRet->nRetCol ){
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
}
}
/* Finally, jump back to the beginning of the executable code. */
sqlite3VdbeGoto(v, 1);
}
|
| ︙ | ︙ | |||
116023 116024 116025 116026 116027 116028 116029 |
Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[0].pExpr);
sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pCExpr);
}
pTab->iPKey = iCol;
pTab->keyConf = (u8)onError;
assert( autoInc==0 || autoInc==1 );
pTab->tabFlags |= autoInc*TF_Autoincrement;
| | | 117002 117003 117004 117005 117006 117007 117008 117009 117010 117011 117012 117013 117014 117015 117016 |
Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[0].pExpr);
sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pCExpr);
}
pTab->iPKey = iCol;
pTab->keyConf = (u8)onError;
assert( autoInc==0 || autoInc==1 );
pTab->tabFlags |= autoInc*TF_Autoincrement;
if( pList ) pParse->iPkSortOrder = pList->a[0].fg.sortFlags;
(void)sqlite3HasExplicitNulls(pParse, pList);
}else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
"INTEGER PRIMARY KEY");
#endif
}else{
|
| ︙ | ︙ | |||
116517 116518 116519 116520 116521 116522 116523 |
if( pList==0 ){
pTab->tabFlags &= ~TF_WithoutRowid;
return;
}
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
}
| | | 117496 117497 117498 117499 117500 117501 117502 117503 117504 117505 117506 117507 117508 117509 117510 |
if( pList==0 ){
pTab->tabFlags &= ~TF_WithoutRowid;
return;
}
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
}
pList->a[0].fg.sortFlags = pParse->iPkSortOrder;
assert( pParse->pNewTable==pTab );
pTab->iPKey = -1;
sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
SQLITE_IDXTYPE_PRIMARYKEY);
if( pParse->nErr ){
pTab->tabFlags &= ~TF_WithoutRowid;
return;
|
| ︙ | ︙ | |||
117188 117189 117190 117191 117192 117193 117194 |
** the columns of the view in the pTable structure. Return the number
** of errors. If an error is seen leave an error message in pParse->zErrMsg.
*/
SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
Table *pSelTab; /* A fake table from which we get the result set */
Select *pSel; /* Copy of the SELECT that implements the view */
int nErr = 0; /* Number of errors encountered */
| < | 118167 118168 118169 118170 118171 118172 118173 118174 118175 118176 118177 118178 118179 118180 |
** the columns of the view in the pTable structure. Return the number
** of errors. If an error is seen leave an error message in pParse->zErrMsg.
*/
SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
Table *pSelTab; /* A fake table from which we get the result set */
Select *pSel; /* Copy of the SELECT that implements the view */
int nErr = 0; /* Number of errors encountered */
sqlite3 *db = pParse->db; /* Database connection for malloc errors */
#ifndef SQLITE_OMIT_VIRTUALTABLE
int rc;
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth; /* Saved xAuth pointer */
#endif
|
| ︙ | ︙ | |||
117246 117247 117248 117249 117250 117251 117252 117253 |
** to be permanent. So the computation is done on a copy of the SELECT
** statement that defines the view.
*/
assert( IsView(pTable) );
pSel = sqlite3SelectDup(db, pTable->u.view.pSelect, 0);
if( pSel ){
u8 eParseMode = pParse->eParseMode;
pParse->eParseMode = PARSE_MODE_NORMAL;
| > > < | > | 118224 118225 118226 118227 118228 118229 118230 118231 118232 118233 118234 118235 118236 118237 118238 118239 118240 118241 118242 118243 118244 118245 118246 118247 118248 118249 118250 118251 118252 118253 |
** to be permanent. So the computation is done on a copy of the SELECT
** statement that defines the view.
*/
assert( IsView(pTable) );
pSel = sqlite3SelectDup(db, pTable->u.view.pSelect, 0);
if( pSel ){
u8 eParseMode = pParse->eParseMode;
int nTab = pParse->nTab;
int nSelect = pParse->nSelect;
pParse->eParseMode = PARSE_MODE_NORMAL;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
DisableLookaside;
#ifndef SQLITE_OMIT_AUTHORIZATION
xAuth = db->xAuth;
db->xAuth = 0;
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
db->xAuth = xAuth;
#else
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
#endif
pParse->nTab = nTab;
pParse->nSelect = nSelect;
if( pSelTab==0 ){
pTable->nCol = 0;
nErr++;
}else if( pTable->pCheck ){
/* CREATE VIEW name(arglist) AS ...
** The names of the columns in the table are taken from
** arglist which is stored in pTable->pCheck. The pCheck field
|
| ︙ | ︙ | |||
118004 118005 118006 118007 118008 118009 118010 |
** an explicit "NULLS FIRST" or "NULLS LAST" clause, leave an error in
** pParse and return non-zero. Otherwise, return zero.
*/
SQLITE_PRIVATE int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){
if( pList ){
int i;
for(i=0; i<pList->nExpr; i++){
| | | | 118984 118985 118986 118987 118988 118989 118990 118991 118992 118993 118994 118995 118996 118997 118998 118999 |
** an explicit "NULLS FIRST" or "NULLS LAST" clause, leave an error in
** pParse and return non-zero. Otherwise, return zero.
*/
SQLITE_PRIVATE int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){
if( pList ){
int i;
for(i=0; i<pList->nExpr; i++){
if( pList->a[i].fg.bNulls ){
u8 sf = pList->a[i].fg.sortFlags;
sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s",
(sf==0 || sf==3) ? "FIRST" : "LAST"
);
return 1;
}
}
}
|
| ︙ | ︙ | |||
118358 118359 118360 118361 118362 118363 118364 |
zColl = sqlite3ColumnColl(&pTab->aCol[j]);
}
if( !zColl ) zColl = sqlite3StrBINARY;
if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
goto exit_create_index;
}
pIndex->azColl[i] = zColl;
| | | 119338 119339 119340 119341 119342 119343 119344 119345 119346 119347 119348 119349 119350 119351 119352 |
zColl = sqlite3ColumnColl(&pTab->aCol[j]);
}
if( !zColl ) zColl = sqlite3StrBINARY;
if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
goto exit_create_index;
}
pIndex->azColl[i] = zColl;
requestedSortOrder = pListItem->fg.sortFlags & sortOrderMask;
pIndex->aSortOrder[i] = (u8)requestedSortOrder;
}
/* Append the table key to the end of the index. For WITHOUT ROWID
** tables (when pPk!=0) this will be the declared PRIMARY KEY. For
** normal tables (when pPk==0) this will be the rowid.
*/
|
| ︙ | ︙ | |||
118801 118802 118803 118804 118805 118806 118807 |
*/
SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){
sqlite3 *db = pParse->db;
int i;
if( pList==0 ){
pList = sqlite3DbMallocZero(db, sizeof(IdList) );
if( pList==0 ) return 0;
| | < < | | | < < | | | | > > > > < | | 119781 119782 119783 119784 119785 119786 119787 119788 119789 119790 119791 119792 119793 119794 119795 119796 119797 119798 119799 119800 119801 119802 119803 119804 119805 119806 119807 119808 119809 119810 119811 119812 119813 119814 119815 119816 119817 119818 119819 119820 119821 119822 119823 119824 119825 119826 119827 119828 119829 119830 119831 119832 |
*/
SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){
sqlite3 *db = pParse->db;
int i;
if( pList==0 ){
pList = sqlite3DbMallocZero(db, sizeof(IdList) );
if( pList==0 ) return 0;
}else{
IdList *pNew;
pNew = sqlite3DbRealloc(db, pList,
sizeof(IdList) + pList->nId*sizeof(pList->a));
if( pNew==0 ){
sqlite3IdListDelete(db, pList);
return 0;
}
pList = pNew;
}
i = pList->nId++;
pList->a[i].zName = sqlite3NameFromToken(db, pToken);
if( IN_RENAME_OBJECT && pList->a[i].zName ){
sqlite3RenameTokenMap(pParse, (void*)pList->a[i].zName, pToken);
}
return pList;
}
/*
** Delete an IdList.
*/
SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
int i;
if( pList==0 ) return;
assert( pList->eU4!=EU4_EXPR ); /* EU4_EXPR mode is not currently used */
for(i=0; i<pList->nId; i++){
sqlite3DbFree(db, pList->a[i].zName);
}
sqlite3DbFreeNN(db, pList);
}
/*
** Return the index in pList of the identifier named zId. Return -1
** if not found.
*/
SQLITE_PRIVATE int sqlite3IdListIndex(IdList *pList, const char *zName){
int i;
assert( pList!=0 );
for(i=0; i<pList->nId; i++){
if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i;
}
return -1;
}
/*
|
| ︙ | ︙ | |||
119042 119043 119044 119045 119046 119047 119048 |
if( pItem->zDatabase ) sqlite3DbFreeNN(db, pItem->zDatabase);
sqlite3DbFree(db, pItem->zName);
if( pItem->zAlias ) sqlite3DbFreeNN(db, pItem->zAlias);
if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
sqlite3DeleteTable(db, pItem->pTab);
if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect);
| | | > > > | 120021 120022 120023 120024 120025 120026 120027 120028 120029 120030 120031 120032 120033 120034 120035 120036 120037 120038 120039 |
if( pItem->zDatabase ) sqlite3DbFreeNN(db, pItem->zDatabase);
sqlite3DbFree(db, pItem->zName);
if( pItem->zAlias ) sqlite3DbFreeNN(db, pItem->zAlias);
if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
sqlite3DeleteTable(db, pItem->pTab);
if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect);
if( pItem->fg.isUsing ){
sqlite3IdListDelete(db, pItem->u3.pUsing);
}else if( pItem->u3.pOn ){
sqlite3ExprDelete(db, pItem->u3.pOn);
}
}
sqlite3DbFreeNN(db, pList);
}
/*
** This routine is called by the parser to add a new term to the
** end of a growing FROM clause. The "p" parameter is the part of
|
| ︙ | ︙ | |||
119071 119072 119073 119074 119075 119076 119077 | SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm( Parse *pParse, /* Parsing context */ SrcList *p, /* The left part of the FROM clause already seen */ Token *pTable, /* Name of the table to add to the FROM clause */ Token *pDatabase, /* Name of the database containing pTable */ Token *pAlias, /* The right-hand side of the AS subexpression */ Select *pSubquery, /* A subquery used in place of a table name */ | < | | | > | > > > > > > > | > | > > > > | < | 120053 120054 120055 120056 120057 120058 120059 120060 120061 120062 120063 120064 120065 120066 120067 120068 120069 120070 120071 120072 120073 120074 120075 120076 120077 120078 120079 120080 120081 120082 120083 120084 120085 120086 120087 120088 120089 120090 120091 120092 120093 120094 120095 120096 120097 120098 120099 120100 120101 120102 120103 120104 120105 120106 120107 120108 120109 120110 120111 120112 120113 |
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
Parse *pParse, /* Parsing context */
SrcList *p, /* The left part of the FROM clause already seen */
Token *pTable, /* Name of the table to add to the FROM clause */
Token *pDatabase, /* Name of the database containing pTable */
Token *pAlias, /* The right-hand side of the AS subexpression */
Select *pSubquery, /* A subquery used in place of a table name */
OnOrUsing *pOnUsing /* Either the ON clause or the USING clause */
){
SrcItem *pItem;
sqlite3 *db = pParse->db;
if( !p && pOnUsing!=0 && (pOnUsing->pOn || pOnUsing->pUsing) ){
sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
(pOnUsing->pOn ? "ON" : "USING")
);
goto append_from_error;
}
p = sqlite3SrcListAppend(pParse, p, pTable, pDatabase);
if( p==0 ){
goto append_from_error;
}
assert( p->nSrc>0 );
pItem = &p->a[p->nSrc-1];
assert( (pTable==0)==(pDatabase==0) );
assert( pItem->zName==0 || pDatabase!=0 );
if( IN_RENAME_OBJECT && pItem->zName ){
Token *pToken = (ALWAYS(pDatabase) && pDatabase->z) ? pDatabase : pTable;
sqlite3RenameTokenMap(pParse, pItem->zName, pToken);
}
assert( pAlias!=0 );
if( pAlias->n ){
pItem->zAlias = sqlite3NameFromToken(db, pAlias);
}
if( pSubquery ){
pItem->pSelect = pSubquery;
if( pSubquery->selFlags & SF_NestedFrom ){
pItem->fg.isNestedFrom = 1;
}
}
assert( pOnUsing==0 || pOnUsing->pOn==0 || pOnUsing->pUsing==0 );
assert( pItem->fg.isUsing==0 );
if( pOnUsing==0 ){
pItem->u3.pOn = 0;
}else if( pOnUsing->pUsing ){
pItem->fg.isUsing = 1;
pItem->u3.pUsing = pOnUsing->pUsing;
}else{
pItem->u3.pOn = pOnUsing->pOn;
}
return p;
append_from_error:
assert( p==0 );
sqlite3ClearOnOrUsing(db, pOnUsing);
sqlite3SelectDelete(db, pSubquery);
return 0;
}
/*
** Add an INDEXED BY or NOT INDEXED clause to the most recently added
** element of the source-list passed as the second argument.
|
| ︙ | ︙ | |||
119151 119152 119153 119154 119155 119156 119157 119158 119159 119160 119161 119162 119163 119164 |
SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, 1);
if( pNew==0 ){
sqlite3SrcListDelete(pParse->db, p2);
}else{
p1 = pNew;
memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem));
sqlite3DbFree(pParse->db, p2);
}
}
return p1;
}
/*
** Add the list of function arguments to the SrcList entry for a
| > | 120144 120145 120146 120147 120148 120149 120150 120151 120152 120153 120154 120155 120156 120157 120158 |
SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, 1);
if( pNew==0 ){
sqlite3SrcListDelete(pParse->db, p2);
}else{
p1 = pNew;
memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem));
sqlite3DbFree(pParse->db, p2);
p1->a[0].fg.jointype |= (JT_LTORJ & p1->a[1].fg.jointype);
}
}
return p1;
}
/*
** Add the list of function arguments to the SrcList entry for a
|
| ︙ | ︙ | |||
119187 119188 119189 119190 119191 119192 119193 119194 | ** Example: Suppose the join is like this: ** ** A natural cross join B ** ** The operator is "natural cross join". The A and B operands are stored ** in p->a[0] and p->a[1], respectively. The parser initially stores the ** operator with A. This routine shifts that operator over to B. */ | > > > > > > > | > | < | > > | > > | > > > > > > > | > > | 120181 120182 120183 120184 120185 120186 120187 120188 120189 120190 120191 120192 120193 120194 120195 120196 120197 120198 120199 120200 120201 120202 120203 120204 120205 120206 120207 120208 120209 120210 120211 120212 120213 120214 120215 120216 120217 120218 120219 120220 120221 120222 |
** Example: Suppose the join is like this:
**
** A natural cross join B
**
** The operator is "natural cross join". The A and B operands are stored
** in p->a[0] and p->a[1], respectively. The parser initially stores the
** operator with A. This routine shifts that operator over to B.
**
** Additional changes:
**
** * All tables to the left of the right-most RIGHT JOIN are tagged with
** JT_LTORJ (mnemonic: Left Table Of Right Join) so that the
** code generator can easily tell that the table is part of
** the left operand of at least one RIGHT JOIN.
*/
SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(Parse *pParse, SrcList *p){
(void)pParse;
if( p && p->nSrc>1 ){
int i = p->nSrc-1;
u8 allFlags = 0;
do{
allFlags |= p->a[i].fg.jointype = p->a[i-1].fg.jointype;
}while( (--i)>0 );
p->a[0].fg.jointype = 0;
/* All terms to the left of a RIGHT JOIN should be tagged with the
** JT_LTORJ flags */
if( allFlags & JT_RIGHT ){
for(i=p->nSrc-1; ALWAYS(i>0) && (p->a[i].fg.jointype&JT_RIGHT)==0; i--){}
i--;
assert( i>=0 );
do{
p->a[i].fg.jointype |= JT_LTORJ;
}while( (--i)>=0 );
}
}
}
/*
** Generate VDBE code for a BEGIN statement.
*/
SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){
|
| ︙ | ︙ | |||
120443 120444 120445 120446 120447 120448 120449 |
int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
pWhere = sqlite3ExprDup(db, pWhere, 0);
pFrom = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pFrom ){
assert( pFrom->nSrc==1 );
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
| | | | 121457 121458 121459 121460 121461 121462 121463 121464 121465 121466 121467 121468 121469 121470 121471 121472 |
int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
pWhere = sqlite3ExprDup(db, pWhere, 0);
pFrom = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pFrom ){
assert( pFrom->nSrc==1 );
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
assert( pFrom->a[0].fg.isUsing==0 );
assert( pFrom->a[0].u3.pOn==0 );
}
pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy,
SF_IncludeHidden, pLimit);
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
sqlite3Select(pParse, pSel, &dest);
sqlite3SelectDelete(db, pSel);
}
|
| ︙ | ︙ | |||
120615 120616 120617 120618 120619 120620 120621 |
assert( db->pParse==pParse );
if( pParse->nErr ){
goto delete_from_cleanup;
}
assert( db->mallocFailed==0 );
assert( pTabList->nSrc==1 );
| < | 121629 121630 121631 121632 121633 121634 121635 121636 121637 121638 121639 121640 121641 121642 |
assert( db->pParse==pParse );
if( pParse->nErr ){
goto delete_from_cleanup;
}
assert( db->mallocFailed==0 );
assert( pTabList->nSrc==1 );
/* Locate the table which we want to delete. This table has to be
** put in an SrcList structure because some of the subroutines we
** will be calling are designed to work with multiple tables and expect
** an SrcList* parameter instead of just a Table* parameter.
*/
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ) goto delete_from_cleanup;
|
| ︙ | ︙ | |||
120639 120640 120641 120642 120643 120644 120645 120646 120647 120648 120649 120650 120651 120652 |
# define isView 0
#endif
bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0);
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( !isView ){
pWhere = sqlite3LimitWhere(
pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE"
);
pOrderBy = 0;
| > > > > > > > > | 121652 121653 121654 121655 121656 121657 121658 121659 121660 121661 121662 121663 121664 121665 121666 121667 121668 121669 121670 121671 121672 121673 |
# define isView 0
#endif
bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0);
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x10000 ){
sqlite3TreeViewLine(0, "In sqlite3Delete() at %s:%d", __FILE__, __LINE__);
sqlite3TreeViewDelete(pParse->pWith, pTabList, pWhere,
pOrderBy, pLimit, pTrigger);
}
#endif
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( !isView ){
pWhere = sqlite3LimitWhere(
pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE"
);
pOrderBy = 0;
|
| ︙ | ︙ | |||
123398 123399 123400 123401 123402 123403 123404 |
}
ans = log(x)/b;
}else{
ans = log(x);
switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){
case 1:
/* Convert from natural logarithm to log base 10 */
| | | | 124419 124420 124421 124422 124423 124424 124425 124426 124427 124428 124429 124430 124431 124432 124433 124434 124435 124436 124437 |
}
ans = log(x)/b;
}else{
ans = log(x);
switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){
case 1:
/* Convert from natural logarithm to log base 10 */
ans /= M_LN10;
break;
case 2:
/* Convert from natural logarithm to log base 2 */
ans /= M_LN2;
break;
default:
break;
}
}
sqlite3_result_double(context, ans);
}
|
| ︙ | ︙ | |||
123541 123542 123543 123544 123545 123546 123547 |
DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
INLINE_FUNC(unlikely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
| < | | 124562 124563 124564 124565 124566 124567 124568 124569 124570 124571 124572 124573 124574 124575 124576 |
DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
INLINE_FUNC(unlikely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
INLINE_FUNC(sqlite_offset, 1, INLINEFUNC_sqlite_offset, 0 ),
#endif
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
FUNCTION(rtrim, 1, 2, 0, trimFunc ),
FUNCTION(rtrim, 2, 2, 0, trimFunc ),
FUNCTION(trim, 1, 3, 0, trimFunc ),
FUNCTION(trim, 2, 3, 0, trimFunc ),
|
| ︙ | ︙ | |||
124077 124078 124079 124080 124081 124082 124083 |
sqlite3VdbeGoto(v, iOk);
sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
sqlite3VdbeJumpHere(v, iMustBeInt);
sqlite3ReleaseTempReg(pParse, regTemp);
}else{
int nCol = pFKey->nCol;
int regTemp = sqlite3GetTempRange(pParse, nCol);
| < | 125097 125098 125099 125100 125101 125102 125103 125104 125105 125106 125107 125108 125109 125110 |
sqlite3VdbeGoto(v, iOk);
sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
sqlite3VdbeJumpHere(v, iMustBeInt);
sqlite3ReleaseTempReg(pParse, regTemp);
}else{
int nCol = pFKey->nCol;
int regTemp = sqlite3GetTempRange(pParse, nCol);
sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp2(v, OP_Copy,
sqlite3TableColumnToStorage(pFKey->pFrom, aiCol[i])+1+regData,
regTemp+i);
|
| ︙ | ︙ | |||
124117 124118 124119 124120 124121 124122 124123 |
}
sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
}
sqlite3VdbeGoto(v, iOk);
}
| | | | < | 125136 125137 125138 125139 125140 125141 125142 125143 125144 125145 125146 125147 125148 125149 125150 125151 125152 125153 |
}
sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
}
sqlite3VdbeGoto(v, iOk);
}
sqlite3VdbeAddOp4(v, OP_Affinity, regTemp, nCol, 0,
sqlite3IndexAffinityStr(pParse->db,pIdx), nCol);
sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regTemp, nCol);
VdbeCoverage(v);
sqlite3ReleaseTempRange(pParse, regTemp, nCol);
}
}
if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs)
&& !pParse->pToplevel
&& !pParse->isMultiWrite
|
| ︙ | ︙ | |||
124223 124224 124225 124226 124227 124228 124229 | ** The code generated by this function scans through the rows in the child ** table that correspond to the parent table row being deleted or inserted. ** For each child row found, one of the following actions is taken: ** ** Operation | FK type | Action taken ** -------------------------------------------------------------------------- ** DELETE immediate Increment the "immediate constraint counter". | < < < < | 125241 125242 125243 125244 125245 125246 125247 125248 125249 125250 125251 125252 125253 125254 125255 125256 125257 125258 | ** The code generated by this function scans through the rows in the child ** table that correspond to the parent table row being deleted or inserted. ** For each child row found, one of the following actions is taken: ** ** Operation | FK type | Action taken ** -------------------------------------------------------------------------- ** DELETE immediate Increment the "immediate constraint counter". ** ** INSERT immediate Decrement the "immediate constraint counter". ** ** DELETE deferred Increment the "deferred constraint counter". ** ** INSERT deferred Decrement the "deferred constraint counter". ** ** These operations are identified in the comment at the top of this file ** (fkey.c) as "I.2" and "D.2". */ static void fkScanChildren( |
| ︙ | ︙ | |||
124878 124879 124880 124881 124882 124883 124884 | ** compiled on table pTab, which is the parent table of foreign-key pFKey. ** If the current operation is an UPDATE, then the pChanges parameter is ** passed a pointer to the list of columns being modified. If it is a ** DELETE, pChanges is passed a NULL pointer. ** ** It returns a pointer to a Trigger structure containing a trigger ** equivalent to the ON UPDATE or ON DELETE action specified by pFKey. | | | | | 125892 125893 125894 125895 125896 125897 125898 125899 125900 125901 125902 125903 125904 125905 125906 125907 125908 | ** compiled on table pTab, which is the parent table of foreign-key pFKey. ** If the current operation is an UPDATE, then the pChanges parameter is ** passed a pointer to the list of columns being modified. If it is a ** DELETE, pChanges is passed a NULL pointer. ** ** It returns a pointer to a Trigger structure containing a trigger ** equivalent to the ON UPDATE or ON DELETE action specified by pFKey. ** If the action is "NO ACTION" then a NULL pointer is returned (these actions ** require no special handling by the triggers sub-system, code for them is ** created by fkScanChildren()). ** ** For example, if pFKey is the foreign key and pTab is table "p" in ** the following schema: ** ** CREATE TABLE p(pk PRIMARY KEY); ** CREATE TABLE c(ck REFERENCES p ON DELETE CASCADE); ** |
| ︙ | ︙ | |||
125009 125010 125011 125012 125013 125014 125015 125016 125017 125018 125019 125020 125021 125022 125023 125024 125025 125026 |
}
sqlite3DbFree(db, aiCol);
zFrom = pFKey->pFrom->zName;
nFrom = sqlite3Strlen30(zFrom);
if( action==OE_Restrict ){
Token tFrom;
Expr *pRaise;
tFrom.z = zFrom;
tFrom.n = nFrom;
pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
if( pRaise ){
pRaise->affExpr = OE_Abort;
}
pSelect = sqlite3SelectNew(pParse,
sqlite3ExprListAppend(pParse, 0, pRaise),
| > > > > > | | 126023 126024 126025 126026 126027 126028 126029 126030 126031 126032 126033 126034 126035 126036 126037 126038 126039 126040 126041 126042 126043 126044 126045 126046 126047 126048 126049 126050 126051 126052 126053 |
}
sqlite3DbFree(db, aiCol);
zFrom = pFKey->pFrom->zName;
nFrom = sqlite3Strlen30(zFrom);
if( action==OE_Restrict ){
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
Token tFrom;
Token tDb;
Expr *pRaise;
tFrom.z = zFrom;
tFrom.n = nFrom;
tDb.z = db->aDb[iDb].zDbSName;
tDb.n = sqlite3Strlen30(tDb.z);
pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
if( pRaise ){
pRaise->affExpr = OE_Abort;
}
pSelect = sqlite3SelectNew(pParse,
sqlite3ExprListAppend(pParse, 0, pRaise),
sqlite3SrcListAppend(pParse, 0, &tDb, &tFrom),
pWhere,
0, 0, 0, 0, 0
);
pWhere = 0;
}
/* Disable lookaside memory allocation */
|
| ︙ | ︙ | |||
125929 125930 125931 125932 125933 125934 125935 125936 125937 125938 125939 125940 125941 125942 |
# define isView 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );
/* If pTab is really a view, make sure it has been initialized.
** ViewGetColumnNames() is a no-op if pTab is not a view.
*/
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
goto insert_cleanup;
}
| > > > > > > > > | 126948 126949 126950 126951 126952 126953 126954 126955 126956 126957 126958 126959 126960 126961 126962 126963 126964 126965 126966 126967 126968 126969 |
# define isView 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x10000 ){
sqlite3TreeViewLine(0, "In sqlite3Insert() at %s:%d", __FILE__, __LINE__);
sqlite3TreeViewInsert(pParse->pWith, pTabList, pColumn, pSelect, pList,
onError, pUpsert, pTrigger);
}
#endif
/* If pTab is really a view, make sure it has been initialized.
** ViewGetColumnNames() is a no-op if pTab is not a view.
*/
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
goto insert_cleanup;
}
|
| ︙ | ︙ | |||
126008 126009 126010 126011 126012 126013 126014 126015 |
** bIdListInOrder is true if the columns in IDLIST are in storage
** order. This enables an optimization that avoids shuffling the
** columns into storage order. False negatives are harmless,
** but false positives will cause database corruption.
*/
bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0;
if( pColumn ){
for(i=0; i<pColumn->nId; i++){
| > > | | | 127035 127036 127037 127038 127039 127040 127041 127042 127043 127044 127045 127046 127047 127048 127049 127050 127051 127052 127053 127054 127055 127056 127057 |
** bIdListInOrder is true if the columns in IDLIST are in storage
** order. This enables an optimization that avoids shuffling the
** columns into storage order. False negatives are harmless,
** but false positives will cause database corruption.
*/
bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0;
if( pColumn ){
assert( pColumn->eU4!=EU4_EXPR );
pColumn->eU4 = EU4_IDX;
for(i=0; i<pColumn->nId; i++){
pColumn->a[i].u4.idx = -1;
}
for(i=0; i<pColumn->nId; i++){
for(j=0; j<pTab->nCol; j++){
if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){
pColumn->a[i].u4.idx = j;
if( i!=j ) bIdListInOrder = 0;
if( j==pTab->iPKey ){
ipkColumn = i; assert( !withoutRowid );
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
sqlite3ErrorMsg(pParse,
|
| ︙ | ︙ | |||
126316 126317 126318 126319 126320 126321 126322 |
sqlite3ExprCodeFactorable(pParse,
sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
iRegStore);
continue;
}
}
if( pColumn ){
| > | | 127345 127346 127347 127348 127349 127350 127351 127352 127353 127354 127355 127356 127357 127358 127359 127360 |
sqlite3ExprCodeFactorable(pParse,
sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
iRegStore);
continue;
}
}
if( pColumn ){
assert( pColumn->eU4==EU4_IDX );
for(j=0; j<pColumn->nId && pColumn->a[j].u4.idx!=i; j++){}
if( j>=pColumn->nId ){
/* A column not named in the insert column list gets its
** default value */
sqlite3ExprCodeFactorable(pParse,
sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
iRegStore);
continue;
|
| ︙ | ︙ | |||
128816 128817 128818 128819 128820 128821 128822 128823 128824 128825 128826 128827 128828 128829 |
int (*vtab_in_first)(sqlite3_value*,sqlite3_value**);
int (*vtab_in_next)(sqlite3_value*,sqlite3_value**);
/* Version 3.39.0 and later */
int (*deserialize)(sqlite3*,const char*,unsigned char*,
sqlite3_int64,sqlite3_int64,unsigned);
unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,
unsigned int);
};
/*
** This is the function signature used for all extension entry points. It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(
| > | 129846 129847 129848 129849 129850 129851 129852 129853 129854 129855 129856 129857 129858 129859 129860 |
int (*vtab_in_first)(sqlite3_value*,sqlite3_value**);
int (*vtab_in_next)(sqlite3_value*,sqlite3_value**);
/* Version 3.39.0 and later */
int (*deserialize)(sqlite3*,const char*,unsigned char*,
sqlite3_int64,sqlite3_int64,unsigned);
unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,
unsigned int);
const char *(*db_name)(sqlite3*,int);
};
/*
** This is the function signature used for all extension entry points. It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(
|
| ︙ | ︙ | |||
129134 129135 129136 129137 129138 129139 129140 129141 129142 129143 129144 129145 129146 129147 129148 129149 129150 129151 | /* Version 3.38.0 and later */ #define sqlite3_error_offset sqlite3_api->error_offset #define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value #define sqlite3_vtab_distinct sqlite3_api->vtab_distinct #define sqlite3_vtab_in sqlite3_api->vtab_in #define sqlite3_vtab_in_first sqlite3_api->vtab_in_first #define sqlite3_vtab_in_next sqlite3_api->vtab_in_next #ifndef SQLITE_OMIT_DESERIALIZE #define sqlite3_deserialize sqlite3_api->deserialize #define sqlite3_serialize sqlite3_api->serialize #endif #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; | > > | 130165 130166 130167 130168 130169 130170 130171 130172 130173 130174 130175 130176 130177 130178 130179 130180 130181 130182 130183 130184 | /* Version 3.38.0 and later */ #define sqlite3_error_offset sqlite3_api->error_offset #define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value #define sqlite3_vtab_distinct sqlite3_api->vtab_distinct #define sqlite3_vtab_in sqlite3_api->vtab_in #define sqlite3_vtab_in_first sqlite3_api->vtab_in_first #define sqlite3_vtab_in_next sqlite3_api->vtab_in_next /* Version 3.39.0 and later */ #ifndef SQLITE_OMIT_DESERIALIZE #define sqlite3_deserialize sqlite3_api->deserialize #define sqlite3_serialize sqlite3_api->serialize #endif #define sqlite3_db_name sqlite3_api->db_name #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; |
| ︙ | ︙ | |||
129629 129630 129631 129632 129633 129634 129635 129636 129637 129638 129639 129640 129641 129642 129643 | /* Version 3.36.1 and later */ sqlite3_changes64, sqlite3_total_changes64, /* Version 3.37.0 and later */ sqlite3_autovacuum_pages, /* Version 3.38.0 and later */ sqlite3_error_offset, sqlite3_vtab_rhs_value, sqlite3_vtab_distinct, sqlite3_vtab_in, sqlite3_vtab_in_first, sqlite3_vtab_in_next, /* Version 3.39.0 and later */ #ifndef SQLITE_OMIT_DESERIALIZE sqlite3_deserialize, | > > > > > > > > | | > | 130662 130663 130664 130665 130666 130667 130668 130669 130670 130671 130672 130673 130674 130675 130676 130677 130678 130679 130680 130681 130682 130683 130684 130685 130686 130687 130688 130689 130690 130691 130692 130693 130694 130695 130696 130697 | /* Version 3.36.1 and later */ sqlite3_changes64, sqlite3_total_changes64, /* Version 3.37.0 and later */ sqlite3_autovacuum_pages, /* Version 3.38.0 and later */ sqlite3_error_offset, #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3_vtab_rhs_value, sqlite3_vtab_distinct, sqlite3_vtab_in, sqlite3_vtab_in_first, sqlite3_vtab_in_next, #else 0, 0, 0, 0, 0, #endif /* Version 3.39.0 and later */ #ifndef SQLITE_OMIT_DESERIALIZE sqlite3_deserialize, sqlite3_serialize, #else 0, 0, #endif sqlite3_db_name }; /* True if x is the directory separator character */ #if SQLITE_OS_WIN # define DirSep(X) ((X)=='/'||(X)=='\\') #else |
| ︙ | ︙ | |||
131501 131502 131503 131504 131505 131506 131507 |
/*
** PRAGMA [schema.]incremental_vacuum(N)
**
** Do N steps of incremental vacuuming on a database.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
case PragTyp_INCREMENTAL_VACUUM: {
| | | 132543 132544 132545 132546 132547 132548 132549 132550 132551 132552 132553 132554 132555 132556 132557 |
/*
** PRAGMA [schema.]incremental_vacuum(N)
**
** Do N steps of incremental vacuuming on a database.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
case PragTyp_INCREMENTAL_VACUUM: {
int iLimit = 0, addr;
if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
iLimit = 0x7fffffff;
}
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); VdbeCoverage(v);
sqlite3VdbeAddOp1(v, OP_ResultRow, 1);
|
| ︙ | ︙ | |||
132189 132190 132191 132192 132193 132194 132195 |
Table *pParent; /* Parent table that child points to */
Index *pIdx; /* Index in the parent table */
int i; /* Loop counter: Foreign key number for pTab */
int j; /* Loop counter: Field of the foreign key */
HashElem *k; /* Loop counter: Next table in schema */
int x; /* result variable */
int regResult; /* 3 registers to hold a result row */
| < < | 133231 133232 133233 133234 133235 133236 133237 133238 133239 133240 133241 133242 133243 133244 133245 133246 133247 133248 133249 133250 133251 |
Table *pParent; /* Parent table that child points to */
Index *pIdx; /* Index in the parent table */
int i; /* Loop counter: Foreign key number for pTab */
int j; /* Loop counter: Field of the foreign key */
HashElem *k; /* Loop counter: Next table in schema */
int x; /* result variable */
int regResult; /* 3 registers to hold a result row */
int regRow; /* Registers to hold a row from pTab */
int addrTop; /* Top of a loop checking foreign keys */
int addrOk; /* Jump here if the key is OK */
int *aiCols; /* child to parent column mapping */
regResult = pParse->nMem+1;
pParse->nMem += 4;
regRow = ++pParse->nMem;
k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
while( k ){
if( zRight ){
pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
k = 0;
}else{
|
| ︙ | ︙ | |||
132264 132265 132266 132267 132268 132269 132270 |
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
}
/* Generate code to query the parent index for a matching parent
** key. If a match is found, jump to addrOk. */
if( pIdx ){
| | | | 133304 133305 133306 133307 133308 133309 133310 133311 133312 133313 133314 133315 133316 133317 133318 133319 133320 |
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
}
/* Generate code to query the parent index for a matching parent
** key. If a match is found, jump to addrOk. */
if( pIdx ){
sqlite3VdbeAddOp4(v, OP_Affinity, regRow, pFK->nCol, 0,
sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regRow, pFK->nCol);
VdbeCoverage(v);
}else if( pParent ){
int jmp = sqlite3VdbeCurrentAddr(v)+2;
sqlite3VdbeAddOp3(v, OP_SeekRowid, i, jmp, regRow); VdbeCoverage(v);
sqlite3VdbeGoto(v, addrOk);
assert( pFK->nCol==1 || db->mallocFailed );
}
|
| ︙ | ︙ | |||
133805 133806 133807 133808 133809 133810 133811 |
}
assert( pDb == &(db->aDb[iDb]) );
if( db->mallocFailed ){
rc = SQLITE_NOMEM_BKPT;
sqlite3ResetAllSchemasOfConnection(db);
pDb = &db->aDb[iDb];
}else
| | | 134845 134846 134847 134848 134849 134850 134851 134852 134853 134854 134855 134856 134857 134858 134859 |
}
assert( pDb == &(db->aDb[iDb]) );
if( db->mallocFailed ){
rc = SQLITE_NOMEM_BKPT;
sqlite3ResetAllSchemasOfConnection(db);
pDb = &db->aDb[iDb];
}else
if( rc==SQLITE_OK || ((db->flags&SQLITE_NoSchemaError) && rc!=SQLITE_NOMEM)){
/* Hack: If the SQLITE_NoSchemaError flag is set, then consider
** the schema loaded, even if errors (other than OOM) occurred. In
** this situation the current sqlite3_prepare() operation will fail,
** but the following one will attempt to compile the supplied statement
** against whatever subset of the schema was loaded before the error
** occurred.
**
|
| ︙ | ︙ | |||
134079 134080 134081 134082 134083 134084 134085 134086 134087 134088 134089 134090 134091 134092 | assert( db->pParse!=pParse ); pParse->pOuterParse = db->pParse; db->pParse = pParse; pParse->db = db; if( db->mallocFailed ) sqlite3ErrorMsg(pParse, "out of memory"); } /* ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. */ static int sqlite3Prepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ | > > > > > > > > | 135119 135120 135121 135122 135123 135124 135125 135126 135127 135128 135129 135130 135131 135132 135133 135134 135135 135136 135137 135138 135139 135140 | assert( db->pParse!=pParse ); pParse->pOuterParse = db->pParse; db->pParse = pParse; pParse->db = db; if( db->mallocFailed ) sqlite3ErrorMsg(pParse, "out of memory"); } /* ** Maximum number of times that we will try again to prepare a statement ** that returns SQLITE_ERROR_RETRY. */ #ifndef SQLITE_MAX_PREPARE_RETRY # define SQLITE_MAX_PREPARE_RETRY 25 #endif /* ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. */ static int sqlite3Prepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ |
| ︙ | ︙ | |||
134253 134254 134255 134256 134257 134258 134259 |
do{
/* Make multiple attempts to compile the SQL, until it either succeeds
** or encounters a permanent error. A schema problem after one schema
** reset is considered a permanent error. */
rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
assert( rc==SQLITE_OK || *ppStmt==0 );
if( rc==SQLITE_OK || db->mallocFailed ) break;
| | | 135301 135302 135303 135304 135305 135306 135307 135308 135309 135310 135311 135312 135313 135314 135315 |
do{
/* Make multiple attempts to compile the SQL, until it either succeeds
** or encounters a permanent error. A schema problem after one schema
** reset is considered a permanent error. */
rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
assert( rc==SQLITE_OK || *ppStmt==0 );
if( rc==SQLITE_OK || db->mallocFailed ) break;
}while( (rc==SQLITE_ERROR_RETRY && (cnt++)<SQLITE_MAX_PREPARE_RETRY)
|| (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
sqlite3BtreeLeaveAll(db);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
db->busyHandler.nBusy = 0;
sqlite3_mutex_leave(db->mutex);
return rc;
|
| ︙ | ︙ | |||
134677 134678 134679 134680 134681 134682 134683 134684 134685 134686 134687 134688 134689 134690 134691 134692 134693 134694 134695 |
** JT_LEFT
** JT_RIGHT
**
** A full outer join is the combination of JT_LEFT and JT_RIGHT.
**
** If an illegal or unsupported join type is seen, then still return
** a join type, but put an error in the pParse structure.
*/
SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
int jointype = 0;
Token *apAll[3];
Token *p;
/* 0123456789 123456789 123456789 123 */
static const char zKeyText[] = "naturaleftouterightfullinnercross";
static const struct {
u8 i; /* Beginning of keyword text in zKeyText[] */
u8 nChar; /* Length of the keyword in characters */
u8 code; /* Join type mask */
} aKeyword[] = {
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | 135725 135726 135727 135728 135729 135730 135731 135732 135733 135734 135735 135736 135737 135738 135739 135740 135741 135742 135743 135744 135745 135746 135747 135748 135749 135750 135751 135752 135753 135754 135755 135756 135757 135758 135759 135760 135761 135762 135763 135764 135765 135766 135767 135768 135769 135770 135771 135772 135773 135774 135775 135776 135777 135778 135779 135780 135781 135782 135783 135784 135785 135786 135787 135788 135789 135790 135791 135792 135793 135794 135795 135796 135797 135798 135799 135800 135801 135802 135803 |
** JT_LEFT
** JT_RIGHT
**
** A full outer join is the combination of JT_LEFT and JT_RIGHT.
**
** If an illegal or unsupported join type is seen, then still return
** a join type, but put an error in the pParse structure.
**
** These are the valid join types:
**
**
** pA pB pC Return Value
** ------- ----- ----- ------------
** CROSS - - JT_CROSS
** INNER - - JT_INNER
** LEFT - - JT_LEFT|JT_OUTER
** LEFT OUTER - JT_LEFT|JT_OUTER
** RIGHT - - JT_RIGHT|JT_OUTER
** RIGHT OUTER - JT_RIGHT|JT_OUTER
** FULL - - JT_LEFT|JT_RIGHT|JT_OUTER
** FULL OUTER - JT_LEFT|JT_RIGHT|JT_OUTER
** NATURAL INNER - JT_NATURAL|JT_INNER
** NATURAL LEFT - JT_NATURAL|JT_LEFT|JT_OUTER
** NATURAL LEFT OUTER JT_NATURAL|JT_LEFT|JT_OUTER
** NATURAL RIGHT - JT_NATURAL|JT_RIGHT|JT_OUTER
** NATURAL RIGHT OUTER JT_NATURAL|JT_RIGHT|JT_OUTER
** NATURAL FULL - JT_NATURAL|JT_LEFT|JT_RIGHT
** NATURAL FULL OUTER JT_NATRUAL|JT_LEFT|JT_RIGHT
**
** To preserve historical compatibly, SQLite also accepts a variety
** of other non-standard and in many cases non-sensical join types.
** This routine makes as much sense at it can from the nonsense join
** type and returns a result. Examples of accepted nonsense join types
** include but are not limited to:
**
** INNER CROSS JOIN -> same as JOIN
** NATURAL CROSS JOIN -> same as NATURAL JOIN
** OUTER LEFT JOIN -> same as LEFT JOIN
** LEFT NATURAL JOIN -> same as NATURAL LEFT JOIN
** LEFT RIGHT JOIN -> same as FULL JOIN
** RIGHT OUTER FULL JOIN -> same as FULL JOIN
** CROSS CROSS CROSS JOIN -> same as JOIN
**
** The only restrictions on the join type name are:
**
** * "INNER" cannot appear together with "OUTER", "LEFT", "RIGHT",
** or "FULL".
**
** * "CROSS" cannot appear together with "OUTER", "LEFT", "RIGHT,
** or "FULL".
**
** * If "OUTER" is present then there must also be one of
** "LEFT", "RIGHT", or "FULL"
*/
SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
int jointype = 0;
Token *apAll[3];
Token *p;
/* 0123456789 123456789 123456789 123 */
static const char zKeyText[] = "naturaleftouterightfullinnercross";
static const struct {
u8 i; /* Beginning of keyword text in zKeyText[] */
u8 nChar; /* Length of the keyword in characters */
u8 code; /* Join type mask */
} aKeyword[] = {
/* (0) natural */ { 0, 7, JT_NATURAL },
/* (1) left */ { 6, 4, JT_LEFT|JT_OUTER },
/* (2) outer */ { 10, 5, JT_OUTER },
/* (3) right */ { 14, 5, JT_RIGHT|JT_OUTER },
/* (4) full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER },
/* (5) inner */ { 23, 5, JT_INNER },
/* (6) cross */ { 28, 5, JT_INNER|JT_CROSS },
};
int i, j;
apAll[0] = pA;
apAll[1] = pB;
apAll[2] = pC;
for(i=0; i<3 && apAll[i]; i++){
p = apAll[i];
|
| ︙ | ︙ | |||
134718 134719 134720 134721 134722 134723 134724 |
if( j>=ArraySize(aKeyword) ){
jointype |= JT_ERROR;
break;
}
}
if(
(jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) ||
| | > | > | | | | < < < < < > > > > > > > > > > > > > > | > > | > | > | > > | > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | > | | | | | | > > > > > > | | | | > | | | > > > > > | > | > | | | | | | | > | < < | | > > | > | | | | < < | < < | > | | < < < < < < < | | > > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > | 135812 135813 135814 135815 135816 135817 135818 135819 135820 135821 135822 135823 135824 135825 135826 135827 135828 135829 135830 135831 135832 135833 135834 135835 135836 135837 135838 135839 135840 135841 135842 135843 135844 135845 135846 135847 135848 135849 135850 135851 135852 135853 135854 135855 135856 135857 135858 135859 135860 135861 135862 135863 135864 135865 135866 135867 135868 135869 135870 135871 135872 135873 135874 135875 135876 135877 135878 135879 135880 135881 135882 135883 135884 135885 135886 135887 135888 135889 135890 135891 135892 135893 135894 135895 135896 135897 135898 135899 135900 135901 135902 135903 135904 135905 135906 135907 135908 135909 135910 135911 135912 135913 135914 135915 135916 135917 135918 135919 135920 135921 135922 135923 135924 135925 135926 135927 135928 135929 135930 135931 135932 135933 135934 135935 135936 135937 135938 135939 135940 135941 135942 135943 135944 135945 135946 135947 135948 135949 135950 135951 135952 135953 135954 135955 135956 135957 135958 135959 135960 135961 135962 135963 135964 135965 135966 135967 135968 135969 135970 135971 135972 135973 135974 135975 135976 135977 135978 135979 135980 135981 135982 135983 135984 135985 135986 135987 135988 135989 135990 135991 135992 135993 135994 135995 135996 135997 135998 135999 136000 136001 136002 136003 136004 136005 136006 136007 136008 136009 136010 136011 136012 136013 136014 136015 136016 136017 136018 136019 136020 136021 136022 136023 136024 136025 136026 136027 136028 136029 136030 136031 136032 136033 136034 136035 136036 136037 136038 136039 136040 136041 136042 136043 136044 136045 136046 136047 136048 136049 136050 136051 136052 136053 136054 136055 136056 136057 136058 136059 136060 136061 136062 136063 136064 136065 136066 136067 136068 136069 136070 136071 136072 136073 136074 136075 136076 136077 136078 136079 136080 136081 136082 136083 136084 136085 136086 136087 136088 136089 136090 136091 136092 136093 136094 136095 136096 136097 136098 136099 136100 136101 136102 136103 136104 136105 136106 136107 136108 136109 136110 136111 136112 136113 136114 136115 136116 136117 136118 136119 136120 136121 136122 136123 136124 136125 136126 136127 136128 136129 136130 136131 136132 136133 136134 136135 136136 136137 136138 136139 136140 136141 136142 136143 136144 136145 136146 136147 136148 136149 136150 136151 136152 |
if( j>=ArraySize(aKeyword) ){
jointype |= JT_ERROR;
break;
}
}
if(
(jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) ||
(jointype & JT_ERROR)!=0 ||
(jointype & (JT_OUTER|JT_LEFT|JT_RIGHT))==JT_OUTER
){
const char *zSp1 = " ";
const char *zSp2 = " ";
if( pB==0 ){ zSp1++; }
if( pC==0 ){ zSp2++; }
sqlite3ErrorMsg(pParse, "unknown join type: "
"%T%s%T%s%T", pA, zSp1, pB, zSp2, pC);
jointype = JT_INNER;
}
return jointype;
}
/*
** Return the index of a column in a table. Return -1 if the column
** is not contained in the table.
*/
SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){
int i;
u8 h = sqlite3StrIHash(zCol);
Column *pCol;
for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){
if( pCol->hName==h && sqlite3StrICmp(pCol->zCnName, zCol)==0 ) return i;
}
return -1;
}
/*
** Mark a subquery result column as having been used.
*/
SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem *pItem, int iCol){
assert( pItem!=0 );
assert( pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
if( pItem->fg.isNestedFrom ){
ExprList *pResults;
assert( pItem->pSelect!=0 );
pResults = pItem->pSelect->pEList;
assert( pResults!=0 );
assert( iCol>=0 && iCol<pResults->nExpr );
pResults->a[iCol].fg.bUsed = 1;
}
}
/*
** Search the tables iStart..iEnd (inclusive) in pSrc, looking for a
** table that has a column named zCol. The search is left-to-right.
** The first match found is returned.
**
** When found, set *piTab and *piCol to the table index and column index
** of the matching column and return TRUE.
**
** If not found, return FALSE.
*/
static int tableAndColumnIndex(
SrcList *pSrc, /* Array of tables to search */
int iStart, /* First member of pSrc->a[] to check */
int iEnd, /* Last member of pSrc->a[] to check */
const char *zCol, /* Name of the column we are looking for */
int *piTab, /* Write index of pSrc->a[] here */
int *piCol, /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
int bIgnoreHidden /* Ignore hidden columns */
){
int i; /* For looping over tables in pSrc */
int iCol; /* Index of column matching zCol */
assert( iEnd<pSrc->nSrc );
assert( iStart>=0 );
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
for(i=iStart; i<=iEnd; i++){
iCol = sqlite3ColumnIndex(pSrc->a[i].pTab, zCol);
if( iCol>=0
&& (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
){
if( piTab ){
sqlite3SrcItemColumnUsed(&pSrc->a[i], iCol);
*piTab = i;
*piCol = iCol;
}
return 1;
}
}
return 0;
}
/*
** Set the EP_OuterON property on all terms of the given expression.
** And set the Expr.w.iJoin to iTable for every term in the
** expression.
**
** The EP_OuterON property is used on terms of an expression to tell
** the OUTER JOIN processing logic that this term is part of the
** join restriction specified in the ON or USING clause and not a part
** of the more general WHERE clause. These terms are moved over to the
** WHERE clause during join processing but we need to remember that they
** originated in the ON or USING clause.
**
** The Expr.w.iJoin tells the WHERE clause processing that the
** expression depends on table w.iJoin even if that table is not
** explicitly mentioned in the expression. That information is needed
** for cases like this:
**
** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5
**
** The where clause needs to defer the handling of the t1.x=5
** term until after the t2 loop of the join. In that way, a
** NULL t2 row will be inserted whenever t1.x!=5. If we do not
** defer the handling of t1.x=5, it will be processed immediately
** after the t1 loop and rows with t1.x!=5 will never appear in
** the output, which is incorrect.
*/
SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){
assert( joinFlag==EP_OuterON || joinFlag==EP_InnerON );
while( p ){
ExprSetProperty(p, joinFlag);
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(p, EP_NoReduce);
p->w.iJoin = iTable;
if( p->op==TK_FUNCTION ){
assert( ExprUseXList(p) );
if( p->x.pList ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable, joinFlag);
}
}
}
sqlite3SetJoinExpr(p->pLeft, iTable, joinFlag);
p = p->pRight;
}
}
/* Undo the work of sqlite3SetJoinExpr(). In the expression p, convert every
** term that is marked with EP_OuterON and w.iJoin==iTable into
** an ordinary term that omits the EP_OuterON mark.
**
** This happens when a LEFT JOIN is simplified into an ordinary JOIN.
**
** If nullable is true, that means that Expr p might evaluate to NULL even
** if it is a reference to a NOT NULL column. This can happen, for example,
** if the table that p references is on the left side of a RIGHT JOIN.
** If nullable is true, then take care to not remove the EP_CanBeNull bit.
** See forum thread https://sqlite.org/forum/forumpost/b40696f50145d21c
*/
static void unsetJoinExpr(Expr *p, int iTable, int nullable){
while( p ){
if( ExprHasProperty(p, EP_OuterON)
&& (iTable<0 || p->w.iJoin==iTable) ){
ExprClearProperty(p, EP_OuterON);
ExprSetProperty(p, EP_InnerON);
}
if( p->op==TK_COLUMN && p->iTable==iTable && !nullable ){
ExprClearProperty(p, EP_CanBeNull);
}
if( p->op==TK_FUNCTION ){
assert( ExprUseXList(p) );
if( p->x.pList ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
unsetJoinExpr(p->x.pList->a[i].pExpr, iTable, nullable);
}
}
}
unsetJoinExpr(p->pLeft, iTable, nullable);
p = p->pRight;
}
}
/*
** This routine processes the join information for a SELECT statement.
**
** * A NATURAL join is converted into a USING join. After that, we
** do not need to be concerned with NATURAL joins and we only have
** think about USING joins.
**
** * ON and USING clauses result in extra terms being added to the
** WHERE clause to enforce the specified constraints. The extra
** WHERE clause terms will be tagged with EP_OuterON or
** EP_InnerON so that we know that they originated in ON/USING.
**
** The terms of a FROM clause are contained in the Select.pSrc structure.
** The left most table is the first entry in Select.pSrc. The right-most
** table is the last entry. The join operator is held in the entry to
** the right. Thus entry 1 contains the join operator for the join between
** entries 0 and 1. Any ON or USING clauses associated with the join are
** also attached to the right entry.
**
** This routine returns the number of errors encountered.
*/
static int sqlite3ProcessJoin(Parse *pParse, Select *p){
SrcList *pSrc; /* All tables in the FROM clause */
int i, j; /* Loop counters */
SrcItem *pLeft; /* Left table being joined */
SrcItem *pRight; /* Right table being joined */
pSrc = p->pSrc;
pLeft = &pSrc->a[0];
pRight = &pLeft[1];
for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){
Table *pRightTab = pRight->pTab;
u32 joinType;
if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue;
joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON;
/* If this is a NATURAL join, synthesize an approprate USING clause
** to specify which columns should be joined.
*/
if( pRight->fg.jointype & JT_NATURAL ){
IdList *pUsing = 0;
if( pRight->fg.isUsing || pRight->u3.pOn ){
sqlite3ErrorMsg(pParse, "a NATURAL join may not have "
"an ON or USING clause", 0);
return 1;
}
for(j=0; j<pRightTab->nCol; j++){
char *zName; /* Name of column in the right table */
if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue;
zName = pRightTab->aCol[j].zCnName;
if( tableAndColumnIndex(pSrc, 0, i, zName, 0, 0, 1) ){
pUsing = sqlite3IdListAppend(pParse, pUsing, 0);
if( pUsing ){
assert( pUsing->nId>0 );
assert( pUsing->a[pUsing->nId-1].zName==0 );
pUsing->a[pUsing->nId-1].zName = sqlite3DbStrDup(pParse->db, zName);
}
}
}
if( pUsing ){
pRight->fg.isUsing = 1;
pRight->fg.isSynthUsing = 1;
pRight->u3.pUsing = pUsing;
}
if( pParse->nErr ) return 1;
}
/* Create extra terms on the WHERE clause for each column named
** in the USING clause. Example: If the two tables to be joined are
** A and B and the USING clause names X, Y, and Z, then add this
** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
** Report an error if any column mentioned in the USING clause is
** not contained in both tables to be joined.
*/
if( pRight->fg.isUsing ){
IdList *pList = pRight->u3.pUsing;
sqlite3 *db = pParse->db;
assert( pList!=0 );
for(j=0; j<pList->nId; j++){
char *zName; /* Name of the term in the USING clause */
int iLeft; /* Table on the left with matching column name */
int iLeftCol; /* Column number of matching column on the left */
int iRightCol; /* Column number of matching column on the right */
Expr *pE1; /* Reference to the column on the LEFT of the join */
Expr *pE2; /* Reference to the column on the RIGHT of the join */
Expr *pEq; /* Equality constraint. pE1 == pE2 */
zName = pList->a[j].zName;
iRightCol = sqlite3ColumnIndex(pRightTab, zName);
if( iRightCol<0
|| tableAndColumnIndex(pSrc, 0, i, zName, &iLeft, &iLeftCol,
pRight->fg.isSynthUsing)==0
){
sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
"not present in both tables", zName);
return 1;
}
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol);
if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
/* This branch runs if the query contains one or more RIGHT or FULL
** JOINs. If only a single table on the left side of this join
** contains the zName column, then this branch is a no-op.
** But if there are two or more tables on the left side
** of the join, construct a coalesce() function that gathers all
** such tables. Raise an error if more than one of those references
** to zName is not also within a prior USING clause.
**
** We really ought to raise an error if there are two or more
** non-USING references to zName on the left of an INNER or LEFT
** JOIN. But older versions of SQLite do not do that, so we avoid
** adding a new error so as to not break legacy applications.
*/
ExprList *pFuncArgs = 0; /* Arguments to the coalesce() */
static const Token tkCoalesce = { "coalesce", 8 };
while( tableAndColumnIndex(pSrc, iLeft+1, i, zName, &iLeft, &iLeftCol,
pRight->fg.isSynthUsing)!=0 ){
if( pSrc->a[iLeft].fg.isUsing==0
|| sqlite3IdListIndex(pSrc->a[iLeft].u3.pUsing, zName)<0
){
sqlite3ErrorMsg(pParse, "ambiguous reference to %s in USING()",
zName);
break;
}
pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol);
}
if( pFuncArgs ){
pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
pE1 = sqlite3ExprFunction(pParse, pFuncArgs, &tkCoalesce, 0);
}
}
pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol);
sqlite3SrcItemColumnUsed(pRight, iRightCol);
pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
assert( pE2!=0 || pEq==0 );
if( pEq ){
ExprSetProperty(pEq, joinType);
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(pEq, EP_NoReduce);
pEq->w.iJoin = pE2->iTable;
}
p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pEq);
}
}
/* Add the ON clause to the end of the WHERE clause, connected by
** an AND operator.
*/
else if( pRight->u3.pOn ){
sqlite3SetJoinExpr(pRight->u3.pOn, pRight->iCursor, joinType);
p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn);
pRight->u3.pOn = 0;
pRight->fg.isOn = 1;
}
}
return 0;
}
/*
** An instance of this object holds information (beyond pParse and pSelect)
** needed to load the next result row that is to be added to the sorter.
|
| ︙ | ︙ | |||
135393 135394 135395 135396 135397 135398 135399 | ** If the optimization is used for expression "bigblob", then instead of ** storing values read from that column in the sorter records, the PK of ** the row from table t1 is stored instead. Then, as records are extracted from ** the sorter to return to the user, the required value of bigblob is ** retrieved directly from table t1. If the values are very large, this ** can be more efficient than storing them directly in the sorter records. ** | | | 136527 136528 136529 136530 136531 136532 136533 136534 136535 136536 136537 136538 136539 136540 136541 | ** If the optimization is used for expression "bigblob", then instead of ** storing values read from that column in the sorter records, the PK of ** the row from table t1 is stored instead. Then, as records are extracted from ** the sorter to return to the user, the required value of bigblob is ** retrieved directly from table t1. If the values are very large, this ** can be more efficient than storing them directly in the sorter records. ** ** The ExprList_item.fg.bSorterRef flag is set for each expression in pEList ** for which the sorter-reference optimization should be enabled. ** Additionally, the pSort->aDefer[] array is populated with entries ** for all cursors required to evaluate all selected expressions. Finally. ** output variable (*ppExtra) is set to an expression list containing ** expressions for all extra PK values that should be stored in the ** sorter records. */ |
| ︙ | ︙ | |||
135453 135454 135455 135456 135457 135458 135459 |
}
pSort->aDefer[nDefer].pTab = pExpr->y.pTab;
pSort->aDefer[nDefer].iCsr = pExpr->iTable;
pSort->aDefer[nDefer].nKey = nKey;
nDefer++;
}
}
| | | 136587 136588 136589 136590 136591 136592 136593 136594 136595 136596 136597 136598 136599 136600 136601 |
}
pSort->aDefer[nDefer].pTab = pExpr->y.pTab;
pSort->aDefer[nDefer].iCsr = pExpr->iTable;
pSort->aDefer[nDefer].nKey = nKey;
nDefer++;
}
}
pItem->fg.bSorterRef = 1;
}
}
}
pSort->nDefer = (u8)nDefer;
*ppExtra = pExtra;
}
#endif
|
| ︙ | ︙ | |||
135584 135585 135586 135587 135588 135589 135590 |
/* Adjust nResultCol to account for columns that are omitted
** from the sorter by the optimizations in this branch */
pEList = p->pEList;
for(i=0; i<pEList->nExpr; i++){
if( pEList->a[i].u.x.iOrderByCol>0
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
| | | 136718 136719 136720 136721 136722 136723 136724 136725 136726 136727 136728 136729 136730 136731 136732 |
/* Adjust nResultCol to account for columns that are omitted
** from the sorter by the optimizations in this branch */
pEList = p->pEList;
for(i=0; i<pEList->nExpr; i++){
if( pEList->a[i].u.x.iOrderByCol>0
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
|| pEList->a[i].fg.bSorterRef
#endif
){
nResultCol--;
regOrig = 0;
}
}
|
| ︙ | ︙ | |||
135946 135947 135948 135949 135950 135951 135952 |
nExpr = pList->nExpr;
pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1);
if( pInfo ){
assert( sqlite3KeyInfoIsWriteable(pInfo) );
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
| | | 137080 137081 137082 137083 137084 137085 137086 137087 137088 137089 137090 137091 137092 137093 137094 |
nExpr = pList->nExpr;
pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1);
if( pInfo ){
assert( sqlite3KeyInfoIsWriteable(pInfo) );
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
pInfo->aSortFlags[i-iStart] = pItem->fg.sortFlags;
}
}
return pInfo;
}
/*
** Name of the connection operator, used for error messages.
|
| ︙ | ︙ | |||
136085 136086 136087 136088 136089 136090 136091 |
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
iSortTab = iTab;
bSeq = 1;
}
for(i=0, iCol=nKey+bSeq-1; i<nColumn; i++){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
| | | 137219 137220 137221 137222 137223 137224 137225 137226 137227 137228 137229 137230 137231 137232 137233 |
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
iSortTab = iTab;
bSeq = 1;
}
for(i=0, iCol=nKey+bSeq-1; i<nColumn; i++){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
if( aOutEx[i].fg.bSorterRef ) continue;
#endif
if( aOutEx[i].u.x.iOrderByCol==0 ) iCol++;
}
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
if( pSort->nDefer ){
int iKey = iCol+1;
int regKey = sqlite3GetTempRange(pParse, nRefKey);
|
| ︙ | ︙ | |||
136122 136123 136124 136125 136126 136127 136128 |
}
}
sqlite3ReleaseTempRange(pParse, regKey, nRefKey);
}
#endif
for(i=nColumn-1; i>=0; i--){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
| | | 137256 137257 137258 137259 137260 137261 137262 137263 137264 137265 137266 137267 137268 137269 137270 |
}
}
sqlite3ReleaseTempRange(pParse, regKey, nRefKey);
}
#endif
for(i=nColumn-1; i>=0; i--){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
if( aOutEx[i].fg.bSorterRef ){
sqlite3ExprCode(pParse, aOutEx[i].pExpr, regRow+i);
}else
#endif
{
int iRead;
if( aOutEx[i].u.x.iOrderByCol ){
iRead = aOutEx[i].u.x.iOrderByCol-1;
|
| ︙ | ︙ | |||
136488 136489 136490 136491 136492 136493 136494 |
for(i=0; i<pEList->nExpr; i++){
Expr *p = pEList->a[i].pExpr;
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
assert( p->op!=TK_COLUMN
|| (ExprUseYTab(p) && p->y.pTab!=0) ); /* Covering idx not yet coded */
| | | 137622 137623 137624 137625 137626 137627 137628 137629 137630 137631 137632 137633 137634 137635 137636 |
for(i=0; i<pEList->nExpr; i++){
Expr *p = pEList->a[i].pExpr;
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
assert( p->op!=TK_COLUMN
|| (ExprUseYTab(p) && p->y.pTab!=0) ); /* Covering idx not yet coded */
if( pEList->a[i].zEName && pEList->a[i].fg.eEName==ENAME_NAME ){
/* An AS clause always takes first priority */
char *zName = pEList->a[i].zEName;
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
}else if( srcName && p->op==TK_COLUMN ){
char *zCol;
int iCol = p->iColumn;
pTab = p->y.pTab;
|
| ︙ | ︙ | |||
136573 136574 136575 136576 136577 136578 136579 136580 136581 |
aCol = 0;
}
assert( nCol==(i16)nCol );
*pnCol = nCol;
*paCol = aCol;
for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){
/* Get an appropriate name for the column
*/
| > > | | | > | | > > > > > > | | 137707 137708 137709 137710 137711 137712 137713 137714 137715 137716 137717 137718 137719 137720 137721 137722 137723 137724 137725 137726 137727 137728 137729 137730 137731 137732 137733 137734 137735 137736 137737 137738 137739 137740 137741 137742 137743 137744 137745 137746 137747 137748 137749 137750 137751 137752 137753 137754 137755 137756 137757 137758 137759 137760 137761 137762 137763 137764 137765 137766 137767 137768 137769 137770 137771 137772 137773 137774 137775 137776 137777 137778 |
aCol = 0;
}
assert( nCol==(i16)nCol );
*pnCol = nCol;
*paCol = aCol;
for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){
struct ExprList_item *pX = &pEList->a[i];
struct ExprList_item *pCollide;
/* Get an appropriate name for the column
*/
if( (zName = pX->zEName)!=0 && pX->fg.eEName==ENAME_NAME ){
/* If the column contains an "AS <name>" phrase, use <name> as the name */
}else{
Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pX->pExpr);
while( ALWAYS(pColExpr!=0) && pColExpr->op==TK_DOT ){
pColExpr = pColExpr->pRight;
assert( pColExpr!=0 );
}
if( pColExpr->op==TK_COLUMN
&& ALWAYS( ExprUseYTab(pColExpr) )
&& ALWAYS( pColExpr->y.pTab!=0 )
){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
pTab = pColExpr->y.pTab;
if( iCol<0 ) iCol = pTab->iPKey;
zName = iCol>=0 ? pTab->aCol[iCol].zCnName : "rowid";
}else if( pColExpr->op==TK_ID ){
assert( !ExprHasProperty(pColExpr, EP_IntValue) );
zName = pColExpr->u.zToken;
}else{
/* Use the original text of the column expression as its name */
assert( zName==pX->zEName ); /* pointer comparison intended */
}
}
if( zName && !sqlite3IsTrueOrFalse(zName) ){
zName = sqlite3DbStrDup(db, zName);
}else{
zName = sqlite3MPrintf(db,"column%d",i+1);
}
/* Make sure the column name is unique. If the name is not unique,
** append an integer to the name so that it becomes unique.
*/
cnt = 0;
while( zName && (pCollide = sqlite3HashFind(&ht, zName))!=0 ){
if( pCollide->fg.bUsingTerm ){
pCol->colFlags |= COLFLAG_NOEXPAND;
}
nName = sqlite3Strlen30(zName);
if( nName>0 ){
for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){}
if( zName[j]==':' ) nName = j;
}
zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt);
if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt);
}
pCol->zCnName = zName;
pCol->hName = sqlite3StrIHash(zName);
if( pX->fg.bNoExpand ){
pCol->colFlags |= COLFLAG_NOEXPAND;
}
sqlite3ColumnPropertiesFromName(0, pCol);
if( zName && sqlite3HashInsert(&ht, zName, pX)==pX ){
sqlite3OomFault(db);
}
}
sqlite3HashClear(&ht);
if( db->mallocFailed ){
for(j=0; j<i; j++){
sqlite3DbFree(db, aCol[j].zCnName);
|
| ︙ | ︙ | |||
136878 136879 136880 136881 136882 136883 136884 |
pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1);
if( pColl==0 ) pColl = db->pDfltColl;
pOrderBy->a[i].pExpr =
sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
}
assert( sqlite3KeyInfoIsWriteable(pRet) );
pRet->aColl[i] = pColl;
| | | 138021 138022 138023 138024 138025 138026 138027 138028 138029 138030 138031 138032 138033 138034 138035 |
pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1);
if( pColl==0 ) pColl = db->pDfltColl;
pOrderBy->a[i].pExpr =
sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
}
assert( sqlite3KeyInfoIsWriteable(pRet) );
pRet->aColl[i] = pColl;
pRet->aSortFlags[i] = pOrderBy->a[i].fg.sortFlags;
}
}
return pRet;
}
#ifndef SQLITE_OMIT_CTE
|
| ︙ | ︙ | |||
138089 138090 138091 138092 138093 138094 138095 138096 138097 138098 138099 138100 |
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/* An instance of the SubstContext object describes an substitution edit
** to be performed on a parse tree.
**
** All references to columns in table iTable are to be replaced by corresponding
** expressions in pEList.
*/
typedef struct SubstContext {
Parse *pParse; /* The parsing context */
int iTable; /* Replace references to this table */
int iNewTable; /* New table number */
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 139232 139233 139234 139235 139236 139237 139238 139239 139240 139241 139242 139243 139244 139245 139246 139247 139248 139249 139250 139251 139252 139253 139254 139255 139256 139257 139258 139259 139260 139261 139262 139263 139264 139265 139266 139267 139268 139269 139270 139271 139272 139273 139274 139275 139276 139277 139278 139279 |
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/* An instance of the SubstContext object describes an substitution edit
** to be performed on a parse tree.
**
** All references to columns in table iTable are to be replaced by corresponding
** expressions in pEList.
**
** ## About "isOuterJoin":
**
** The isOuterJoin column indicates that the replacement will occur into a
** position in the parent that NULL-able due to an OUTER JOIN. Either the
** target slot in the parent is the right operand of a LEFT JOIN, or one of
** the left operands of a RIGHT JOIN. In either case, we need to potentially
** bypass the substituted expression with OP_IfNullRow.
**
** Suppose the original expression integer constant. Even though the table
** has the nullRow flag set, because the expression is an integer constant,
** it will not be NULLed out. So instead, we insert an OP_IfNullRow opcode
** that checks to see if the nullRow flag is set on the table. If the nullRow
** flag is set, then the value in the register is set to NULL and the original
** expression is bypassed. If the nullRow flag is not set, then the original
** expression runs to populate the register.
**
** Example where this is needed:
**
** CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT);
** CREATE TABLE t2(x INT UNIQUE);
**
** SELECT a,b,m,x FROM t1 LEFT JOIN (SELECT 59 AS m,x FROM t2) ON b=x;
**
** When the subquery on the right side of the LEFT JOIN is flattened, we
** have to add OP_IfNullRow in front of the OP_Integer that implements the
** "m" value of the subquery so that a NULL will be loaded instead of 59
** when processing a non-matched row of the left.
*/
typedef struct SubstContext {
Parse *pParse; /* The parsing context */
int iTable; /* Replace references to this table */
int iNewTable; /* New table number */
int isOuterJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */
ExprList *pEList; /* Replacement expressions */
} SubstContext;
/* Forward Declarations */
static void substExprList(SubstContext*, ExprList*);
static void substSelect(SubstContext*, Select*, int);
|
| ︙ | ︙ | |||
138120 138121 138122 138123 138124 138125 138126 |
** of the subquery rather the result set of the subquery.
*/
static Expr *substExpr(
SubstContext *pSubst, /* Description of the substitution */
Expr *pExpr /* Expr in which substitution occurs */
){
if( pExpr==0 ) return 0;
| | | > | | | | | > > > > > > | 139291 139292 139293 139294 139295 139296 139297 139298 139299 139300 139301 139302 139303 139304 139305 139306 139307 139308 139309 139310 139311 139312 139313 139314 139315 139316 139317 139318 139319 139320 139321 139322 139323 139324 139325 139326 139327 139328 139329 139330 139331 139332 139333 139334 139335 139336 139337 139338 139339 139340 139341 139342 139343 139344 139345 139346 139347 139348 139349 139350 139351 139352 139353 139354 139355 139356 139357 |
** of the subquery rather the result set of the subquery.
*/
static Expr *substExpr(
SubstContext *pSubst, /* Description of the substitution */
Expr *pExpr /* Expr in which substitution occurs */
){
if( pExpr==0 ) return 0;
if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON)
&& pExpr->w.iJoin==pSubst->iTable
){
testcase( ExprHasProperty(pExpr, EP_InnerON) );
pExpr->w.iJoin = pSubst->iNewTable;
}
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pSubst->iTable
&& !ExprHasProperty(pExpr, EP_FixedCol)
){
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
}else
#endif
{
Expr *pNew;
Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
Expr ifNullRow;
assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
assert( pExpr->pRight==0 );
if( sqlite3ExprIsVector(pCopy) ){
sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
}else{
sqlite3 *db = pSubst->pParse->db;
if( pSubst->isOuterJoin && pCopy->op!=TK_COLUMN ){
memset(&ifNullRow, 0, sizeof(ifNullRow));
ifNullRow.op = TK_IF_NULL_ROW;
ifNullRow.pLeft = pCopy;
ifNullRow.iTable = pSubst->iNewTable;
ifNullRow.flags = EP_IfNullRow;
pCopy = &ifNullRow;
}
testcase( ExprHasProperty(pCopy, EP_Subquery) );
pNew = sqlite3ExprDup(db, pCopy, 0);
if( db->mallocFailed ){
sqlite3ExprDelete(db, pNew);
return pExpr;
}
if( pSubst->isOuterJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
}
if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){
sqlite3SetJoinExpr(pNew, pExpr->w.iJoin,
pExpr->flags & (EP_OuterON|EP_InnerON));
}
sqlite3ExprDelete(db, pExpr);
pExpr = pNew;
if( pExpr->op==TK_TRUEFALSE ){
pExpr->u.iValue = sqlite3ExprTruthValue(pExpr);
pExpr->op = TK_INTEGER;
ExprSetProperty(pExpr, EP_IntValue);
}
/* Ensure that the expression now has an implicit collation sequence,
** just as it did when it was a column of a view or sub-query. */
if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
(pColl ? pColl->zName : "BINARY")
|
| ︙ | ︙ | |||
138326 138327 138328 138329 138330 138331 138332 |
** Expr objects to match newly assigned cursor numbers.
*/
static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
int op = pExpr->op;
if( op==TK_COLUMN || op==TK_IF_NULL_ROW ){
renumberCursorDoMapping(pWalker, &pExpr->iTable);
}
| | | | 139504 139505 139506 139507 139508 139509 139510 139511 139512 139513 139514 139515 139516 139517 139518 139519 |
** Expr objects to match newly assigned cursor numbers.
*/
static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
int op = pExpr->op;
if( op==TK_COLUMN || op==TK_IF_NULL_ROW ){
renumberCursorDoMapping(pWalker, &pExpr->iTable);
}
if( ExprHasProperty(pExpr, EP_OuterON) ){
renumberCursorDoMapping(pWalker, &pExpr->w.iJoin);
}
return WRC_Continue;
}
/*
** Assign a new cursor number to each cursor in the FROM clause (Select.pSrc)
** of the SELECT statement passed as the second argument, and to each
|
| ︙ | ︙ | |||
138412 138413 138414 138415 138416 138417 138418 138419 138420 138421 138422 138423 138424 138425 | ** ** (3) If the subquery is the right operand of a LEFT JOIN then ** (3a) the subquery may not be a join and ** (3b) the FROM clause of the subquery may not contain a virtual ** table and ** (3c) the outer query may not be an aggregate. ** (3d) the outer query may not be DISTINCT. ** ** (4) The subquery can not be DISTINCT. ** ** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT ** sub-queries that were excluded from this optimization. Restriction ** (4) has since been expanded to exclude all DISTINCT subqueries. ** | > | 139590 139591 139592 139593 139594 139595 139596 139597 139598 139599 139600 139601 139602 139603 139604 | ** ** (3) If the subquery is the right operand of a LEFT JOIN then ** (3a) the subquery may not be a join and ** (3b) the FROM clause of the subquery may not contain a virtual ** table and ** (3c) the outer query may not be an aggregate. ** (3d) the outer query may not be DISTINCT. ** See also (26) for restrictions on RIGHT JOIN. ** ** (4) The subquery can not be DISTINCT. ** ** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT ** sub-queries that were excluded from this optimization. Restriction ** (4) has since been expanded to exclude all DISTINCT subqueries. ** |
| ︙ | ︙ | |||
138510 138511 138512 138513 138514 138515 138516 138517 138518 138519 138520 138521 138522 138523 | ** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily ** return the value X for which Y was maximal.) ** ** (25) If either the subquery or the parent query contains a window ** function in the select list or ORDER BY clause, flattening ** is not attempted. ** ** ** In this routine, the "p" parameter is a pointer to the outer query. ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query ** uses aggregates. ** ** If flattening is not attempted, this routine is a no-op and returns 0. ** If flattening is attempted this routine returns 1. | > > > > > > > > > > > > > | 139689 139690 139691 139692 139693 139694 139695 139696 139697 139698 139699 139700 139701 139702 139703 139704 139705 139706 139707 139708 139709 139710 139711 139712 139713 139714 139715 | ** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily ** return the value X for which Y was maximal.) ** ** (25) If either the subquery or the parent query contains a window ** function in the select list or ORDER BY clause, flattening ** is not attempted. ** ** (26) The subquery may not be the right operand of a RIGHT JOIN. ** See also (3) for restrictions on LEFT JOIN. ** ** (27) The subquery may not contain a FULL or RIGHT JOIN unless it ** is the first element of the parent query. ** ** (28) The subquery is not a MATERIALIZED CTE. ** ** (29) Either the subquery is not the right-hand operand of a join with an ** ON or USING clause nor the right-hand operand of a NATURAL JOIN, or ** the right-most table within the FROM clause of the subquery ** is not part of an outer join. ** ** ** In this routine, the "p" parameter is a pointer to the outer query. ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query ** uses aggregates. ** ** If flattening is not attempted, this routine is a no-op and returns 0. ** If flattening is attempted this routine returns 1. |
| ︙ | ︙ | |||
138535 138536 138537 138538 138539 138540 138541 | Select *pParent; /* Current UNION ALL term of the other query */ Select *pSub; /* The inner query or "subquery" */ Select *pSub1; /* Pointer to the rightmost select in sub-query */ SrcList *pSrc; /* The FROM clause of the outer query */ SrcList *pSubSrc; /* The FROM clause of the subquery */ int iParent; /* VDBE cursor number of the pSub result set temp table */ int iNewParent = -1;/* Replacement table for iParent */ | | | 139727 139728 139729 139730 139731 139732 139733 139734 139735 139736 139737 139738 139739 139740 139741 | Select *pParent; /* Current UNION ALL term of the other query */ Select *pSub; /* The inner query or "subquery" */ Select *pSub1; /* Pointer to the rightmost select in sub-query */ SrcList *pSrc; /* The FROM clause of the outer query */ SrcList *pSubSrc; /* The FROM clause of the subquery */ int iParent; /* VDBE cursor number of the pSub result set temp table */ int iNewParent = -1;/* Replacement table for iParent */ int isOuterJoin = 0; /* True if pSub is the right side of a LEFT JOIN */ int i; /* Loop counter */ Expr *pWhere; /* The WHERE clause */ SrcItem *pSubitem; /* The subquery */ sqlite3 *db = pParse->db; Walker w; /* Walker to persist agginfo data */ int *aCsrMap = 0; |
| ︙ | ︙ | |||
138608 138609 138610 138611 138612 138613 138614 | ** If the subquery is the right operand of a LEFT JOIN, then the outer ** query cannot be an aggregate. (3c) This is an artifact of the way ** aggregates are processed - there is no mechanism to determine if ** the LEFT JOIN table should be all-NULL. ** ** See also tickets #306, #350, and #3300. */ | | < | | | | > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 139800 139801 139802 139803 139804 139805 139806 139807 139808 139809 139810 139811 139812 139813 139814 139815 139816 139817 139818 139819 139820 139821 139822 139823 139824 139825 139826 139827 139828 139829 139830 139831 139832 139833 139834 139835 139836 139837 139838 139839 139840 139841 139842 139843 139844 139845 139846 139847 139848 139849 139850 139851 139852 139853 139854 139855 139856 139857 139858 139859 139860 139861 139862 139863 139864 139865 139866 139867 139868 139869 139870 139871 139872 139873 139874 139875 139876 139877 139878 139879 139880 139881 |
** If the subquery is the right operand of a LEFT JOIN, then the outer
** query cannot be an aggregate. (3c) This is an artifact of the way
** aggregates are processed - there is no mechanism to determine if
** the LEFT JOIN table should be all-NULL.
**
** See also tickets #306, #350, and #3300.
*/
if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
if( pSubSrc->nSrc>1 /* (3a) */
|| isAgg /* (3b) */
|| IsVirtual(pSubSrc->a[0].pTab) /* (3c) */
|| (p->selFlags & SF_Distinct)!=0 /* (3d) */
|| (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */
){
return 0;
}
isOuterJoin = 1;
}
#ifdef SQLITE_EXTRA_IFNULLROW
else if( iFrom>0 && !isAgg ){
/* Setting isOuterJoin to -1 causes OP_IfNullRow opcodes to be generated for
** every reference to any result column from subquery in a join, even
** though they are not necessary. This will stress-test the OP_IfNullRow
** opcode. */
isOuterJoin = -1;
}
#endif
assert( pSubSrc->nSrc>0 ); /* True by restriction (7) */
if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
return 0; /* Restriction (27) */
}
if( pSubitem->fg.isCte && pSubitem->u2.pCteUse->eM10d==M10d_Yes ){
return 0; /* (28) */
}
/* Restriction (29):
**
** We do not want two constraints on the same term of the flattened
** query where one constraint has EP_InnerON and the other is EP_OuterON.
** To prevent this, one or the other of the following conditions must be
** false:
**
** (29a) The right-most entry in the FROM clause of the subquery
** must not be part of an outer join.
**
** (29b) The subquery itself must not be the right operand of a
** NATURAL join or a join that as an ON or USING clause.
**
** These conditions are sufficient to keep an EP_OuterON from being
** flattened into an EP_InnerON. Restrictions (3a) and (27) prevent
** an EP_InnerON from being flattened into an EP_OuterON.
*/
if( pSubSrc->nSrc>=2
&& (pSubSrc->a[pSubSrc->nSrc-1].fg.jointype & JT_OUTER)!=0
){
if( (pSubitem->fg.jointype & JT_NATURAL)!=0
|| pSubitem->fg.isUsing
|| NEVER(pSubitem->u3.pOn!=0) /* ON clause already shifted into WHERE */
|| pSubitem->fg.isOn
){
return 0;
}
}
/* Restriction (17): If the sub-query is a compound SELECT, then it must
** use only the UNION ALL operator. And none of the simple select queries
** that make up the compound SELECT are allowed to be aggregate or distinct
** queries.
*/
if( pSub->pPrior ){
if( pSub->pOrderBy ){
return 0; /* Restriction (20) */
}
if( isAgg || (p->selFlags & SF_Distinct)!=0 || isOuterJoin>0 ){
return 0; /* (17d1), (17d2), or (17f) */
}
for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
assert( pSub->pSrc!=0 );
assert( (pSub->selFlags & SF_Recursive)==0 );
|
| ︙ | ︙ | |||
138671 138672 138673 138674 138675 138676 138677 138678 138679 138680 138681 138682 138683 138684 |
}
/* Restriction (23) */
if( (p->selFlags & SF_Recursive) ) return 0;
if( pSrc->nSrc>1 ){
if( pParse->nSelect>500 ) return 0;
aCsrMap = sqlite3DbMallocZero(db, ((i64)pParse->nTab+1)*sizeof(int));
if( aCsrMap ) aCsrMap[0] = pParse->nTab;
}
}
/***** If we reach this point, flattening is permitted. *****/
SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
| > | 139901 139902 139903 139904 139905 139906 139907 139908 139909 139910 139911 139912 139913 139914 139915 |
}
/* Restriction (23) */
if( (p->selFlags & SF_Recursive) ) return 0;
if( pSrc->nSrc>1 ){
if( pParse->nSelect>500 ) return 0;
if( OptimizationDisabled(db, SQLITE_FlttnUnionAll) ) return 0;
aCsrMap = sqlite3DbMallocZero(db, ((i64)pParse->nTab+1)*sizeof(int));
if( aCsrMap ) aCsrMap[0] = pParse->nTab;
}
}
/***** If we reach this point, flattening is permitted. *****/
SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
|
| ︙ | ︙ | |||
138695 138696 138697 138698 138699 138700 138701 | sqlite3DbFree(db, pSubitem->zDatabase); sqlite3DbFree(db, pSubitem->zName); sqlite3DbFree(db, pSubitem->zAlias); pSubitem->zDatabase = 0; pSubitem->zName = 0; pSubitem->zAlias = 0; pSubitem->pSelect = 0; | | | 139926 139927 139928 139929 139930 139931 139932 139933 139934 139935 139936 139937 139938 139939 139940 | sqlite3DbFree(db, pSubitem->zDatabase); sqlite3DbFree(db, pSubitem->zName); sqlite3DbFree(db, pSubitem->zAlias); pSubitem->zDatabase = 0; pSubitem->zName = 0; pSubitem->zAlias = 0; pSubitem->pSelect = 0; assert( pSubitem->fg.isUsing!=0 || pSubitem->u3.pOn==0 ); /* If the sub-query is a compound SELECT statement, then (by restrictions ** 17 and 18 above) it must be a UNION ALL and the parent query must ** be of the form: ** ** SELECT <expr-list> FROM (<sub-query>) <where-clause> ** |
| ︙ | ︙ | |||
138805 138806 138807 138808 138809 138810 138811 138812 138813 138814 138815 138816 138817 138818 |
** those references with expressions that resolve to the subquery FROM
** elements we are now copying in.
*/
pSub = pSub1;
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc;
u8 jointype = 0;
assert( pSub!=0 );
pSubSrc = pSub->pSrc; /* FROM clause of subquery */
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
pSrc = pParent->pSrc; /* FROM clause of the outer query */
if( pParent==p ){
jointype = pSubitem->fg.jointype; /* First time through the loop */
| > | 140036 140037 140038 140039 140040 140041 140042 140043 140044 140045 140046 140047 140048 140049 140050 |
** those references with expressions that resolve to the subquery FROM
** elements we are now copying in.
*/
pSub = pSub1;
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc;
u8 jointype = 0;
u8 ltorj = pSrc->a[iFrom].fg.jointype & JT_LTORJ;
assert( pSub!=0 );
pSubSrc = pSub->pSrc; /* FROM clause of subquery */
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
pSrc = pParent->pSrc; /* FROM clause of the outer query */
if( pParent==p ){
jointype = pSubitem->fg.jointype; /* First time through the loop */
|
| ︙ | ︙ | |||
138839 138840 138841 138842 138843 138844 138845 |
pParent->pSrc = pSrc;
}
/* Transfer the FROM clause terms from the subquery into the
** outer query.
*/
for(i=0; i<nSubSrc; i++){
| > | | | > > | | 140071 140072 140073 140074 140075 140076 140077 140078 140079 140080 140081 140082 140083 140084 140085 140086 140087 140088 140089 140090 140091 140092 140093 140094 |
pParent->pSrc = pSrc;
}
/* Transfer the FROM clause terms from the subquery into the
** outer query.
*/
for(i=0; i<nSubSrc; i++){
SrcItem *pItem = &pSrc->a[i+iFrom];
if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
assert( pItem->fg.isTabFunc==0 );
*pItem = pSubSrc->a[i];
pItem->fg.jointype |= ltorj;
iNewParent = pSubSrc->a[i].iCursor;
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
pSrc->a[iFrom].fg.jointype &= JT_LTORJ;
pSrc->a[iFrom].fg.jointype |= jointype | ltorj;
/* Now begin substituting subquery result set expressions for
** references to the iParent in the outer query.
**
** Example:
**
** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
|
| ︙ | ︙ | |||
138880 138881 138882 138883 138884 138885 138886 |
}
assert( pParent->pOrderBy==0 );
pParent->pOrderBy = pOrderBy;
pSub->pOrderBy = 0;
}
pWhere = pSub->pWhere;
pSub->pWhere = 0;
| | | | | 140115 140116 140117 140118 140119 140120 140121 140122 140123 140124 140125 140126 140127 140128 140129 140130 140131 140132 140133 140134 140135 140136 140137 140138 140139 140140 140141 140142 140143 140144 |
}
assert( pParent->pOrderBy==0 );
pParent->pOrderBy = pOrderBy;
pSub->pOrderBy = 0;
}
pWhere = pSub->pWhere;
pSub->pWhere = 0;
if( isOuterJoin>0 ){
sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON);
}
if( pWhere ){
if( pParent->pWhere ){
pParent->pWhere = sqlite3PExpr(pParse, TK_AND, pWhere, pParent->pWhere);
}else{
pParent->pWhere = pWhere;
}
}
if( db->mallocFailed==0 ){
SubstContext x;
x.pParse = pParse;
x.iTable = iParent;
x.iNewTable = iNewParent;
x.isOuterJoin = isOuterJoin;
x.pEList = pSub->pEList;
substSelect(&x, pParent, 0);
}
/* The flattened query is a compound if either the inner or the
** outer query is a compound. */
pParent->selFlags |= pSub->selFlags & SF_Compound;
|
| ︙ | ︙ | |||
138930 138931 138932 138933 138934 138935 138936 | /* Finially, delete what is left of the subquery and return ** success. */ sqlite3AggInfoPersistWalkerInit(&w, pParse); sqlite3WalkSelect(&w,pSub1); sqlite3SelectDelete(db, pSub1); | | | | 140165 140166 140167 140168 140169 140170 140171 140172 140173 140174 140175 140176 140177 140178 140179 140180 |
/* Finially, delete what is left of the subquery and return
** success.
*/
sqlite3AggInfoPersistWalkerInit(&w, pParse);
sqlite3WalkSelect(&w,pSub1);
sqlite3SelectDelete(db, pSub1);
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
return 1;
}
|
| ︙ | ︙ | |||
139014 139015 139016 139017 139018 139019 139020 |
** is a constant expression and where the term must be true because it
** is part of the AND-connected terms of the expression. For each term
** found, add it to the pConst structure.
*/
static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
Expr *pRight, *pLeft;
if( NEVER(pExpr==0) ) return;
| | > > > > | 140249 140250 140251 140252 140253 140254 140255 140256 140257 140258 140259 140260 140261 140262 140263 140264 140265 140266 140267 |
** is a constant expression and where the term must be true because it
** is part of the AND-connected terms of the expression. For each term
** found, add it to the pConst structure.
*/
static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
Expr *pRight, *pLeft;
if( NEVER(pExpr==0) ) return;
if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) ){
testcase( ExprHasProperty(pExpr, EP_OuterON) );
testcase( ExprHasProperty(pExpr, EP_InnerON) );
return;
}
if( pExpr->op==TK_AND ){
findConstInWhere(pConst, pExpr->pRight);
findConstInWhere(pConst, pExpr->pLeft);
return;
}
if( pExpr->op!=TK_EQ ) return;
pRight = pExpr->pRight;
|
| ︙ | ︙ | |||
139050 139051 139052 139053 139054 139055 139056 |
WhereConst *pConst,
Expr *pExpr,
int bIgnoreAffBlob
){
int i;
if( pConst->pOomFault[0] ) return WRC_Prune;
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
| | | | 140289 140290 140291 140292 140293 140294 140295 140296 140297 140298 140299 140300 140301 140302 140303 140304 140305 |
WhereConst *pConst,
Expr *pExpr,
int bIgnoreAffBlob
){
int i;
if( pConst->pOomFault[0] ) return WRC_Prune;
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
if( ExprHasProperty(pExpr, EP_FixedCol|EP_OuterON) ){
testcase( ExprHasProperty(pExpr, EP_FixedCol) );
testcase( ExprHasProperty(pExpr, EP_OuterON) );
return WRC_Continue;
}
for(i=0; i<pConst->nConst; i++){
Expr *pColumn = pConst->apExpr[i*2];
if( pColumn==pExpr ) continue;
if( pColumn->iTable!=pExpr->iTable ) continue;
if( pColumn->iColumn!=pExpr->iColumn ) continue;
|
| ︙ | ︙ | |||
139295 139296 139297 139298 139299 139300 139301 | ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. */ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ Expr *pWhere, /* The WHERE clause of the outer query */ | | < > | 140534 140535 140536 140537 140538 140539 140540 140541 140542 140543 140544 140545 140546 140547 140548 140549 140550 140551 140552 140553 140554 |
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
*/
static int pushDownWhereTerms(
Parse *pParse, /* Parse context (for malloc() and error reporting) */
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
Expr *pWhere, /* The WHERE clause of the outer query */
SrcItem *pSrc /* The subquery term of the outer FROM clause */
){
Expr *pNew;
int nChng = 0;
if( pWhere==0 ) return 0;
if( pSubq->selFlags & (SF_Recursive|SF_MultiPart) ) return 0;
if( pSrc->fg.jointype & (JT_LTORJ|JT_RIGHT) ) return 0;
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pSubq->pPrior ){
Select *pSel;
for(pSel=pSubq; pSel; pSel=pSel->pPrior){
if( pSel->pWin ) return 0; /* restriction (6b) */
}
|
| ︙ | ︙ | |||
139331 139332 139333 139334 139335 139336 139337 |
}
#endif
if( pSubq->pLimit!=0 ){
return 0; /* restriction (3) */
}
while( pWhere->op==TK_AND ){
| | < > > | | | | > > | | | | | | 140570 140571 140572 140573 140574 140575 140576 140577 140578 140579 140580 140581 140582 140583 140584 140585 140586 140587 140588 140589 140590 140591 140592 140593 140594 140595 140596 140597 140598 140599 140600 140601 140602 140603 140604 140605 140606 140607 140608 140609 140610 140611 140612 |
}
#endif
if( pSubq->pLimit!=0 ){
return 0; /* restriction (3) */
}
while( pWhere->op==TK_AND ){
nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, pSrc);
pWhere = pWhere->pLeft;
}
#if 0 /* Legacy code. Checks now done by sqlite3ExprIsTableConstraint() */
if( isLeftJoin
&& (ExprHasProperty(pWhere,EP_OuterON)==0
|| pWhere->w.iJoin!=iCursor)
){
return 0; /* restriction (4) */
}
if( ExprHasProperty(pWhere,EP_OuterON)
&& pWhere->w.iJoin!=iCursor
){
return 0; /* restriction (5) */
}
#endif
if( sqlite3ExprIsTableConstraint(pWhere, pSrc) ){
nChng++;
pSubq->selFlags |= SF_PushDown;
while( pSubq ){
SubstContext x;
pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
unsetJoinExpr(pNew, -1, 1);
x.pParse = pParse;
x.iTable = pSrc->iCursor;
x.iNewTable = pSrc->iCursor;
x.isOuterJoin = 0;
x.pEList = pSubq->pEList;
pNew = substExpr(&x, pNew);
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pSubq->pWin && 0==pushDownWindowCheck(pParse, pSubq, pNew) ){
/* Restriction 6c has prevented push-down in this case */
sqlite3ExprDelete(pParse->db, pNew);
nChng--;
|
| ︙ | ︙ | |||
139429 139430 139431 139432 139433 139434 139435 |
eRet = WHERE_ORDERBY_MAX;
sortFlags = KEYINFO_ORDER_DESC;
}else{
return eRet;
}
*ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0);
assert( pOrderBy!=0 || db->mallocFailed );
| | | 140671 140672 140673 140674 140675 140676 140677 140678 140679 140680 140681 140682 140683 140684 140685 |
eRet = WHERE_ORDERBY_MAX;
sortFlags = KEYINFO_ORDER_DESC;
}else{
return eRet;
}
*ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0);
assert( pOrderBy!=0 || db->mallocFailed );
if( pOrderBy ) pOrderBy->a[0].fg.sortFlags = sortFlags;
return eRet;
}
/*
** The select statement passed as the first argument is an aggregate query.
** The second argument is the associated aggregate-info object. This
** function tests if the SELECT is of the form:
|
| ︙ | ︙ | |||
139565 139566 139567 139568 139569 139570 139571 | /* If we reach this point, that means the transformation is required. */ pParse = pWalker->pParse; db = pParse->db; pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); if( pNew==0 ) return WRC_Abort; memset(&dummy, 0, sizeof(dummy)); | | | 140807 140808 140809 140810 140811 140812 140813 140814 140815 140816 140817 140818 140819 140820 140821 | /* If we reach this point, that means the transformation is required. */ pParse = pWalker->pParse; db = pParse->db; pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); if( pNew==0 ) return WRC_Abort; memset(&dummy, 0, sizeof(dummy)); pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0); if( pNewSrc==0 ) return WRC_Abort; *pNew = *p; p->pSrc = pNewSrc; p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0)); p->op = TK_SELECT; p->pWhere = 0; pNew->pGroupBy = 0; |
| ︙ | ︙ | |||
139898 139899 139900 139901 139902 139903 139904 |
assert( pSel );
pFrom->pTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
if( pTab==0 ) return SQLITE_NOMEM;
pTab->nTabRef = 1;
if( pFrom->zAlias ){
pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias);
}else{
| | > | > > > > > > > > > > > > > > > > > > > > > > | > | 141140 141141 141142 141143 141144 141145 141146 141147 141148 141149 141150 141151 141152 141153 141154 141155 141156 141157 141158 141159 141160 141161 141162 141163 141164 141165 141166 141167 141168 141169 141170 141171 141172 141173 141174 141175 141176 141177 141178 141179 141180 141181 141182 141183 141184 141185 141186 141187 141188 141189 141190 141191 141192 141193 |
assert( pSel );
pFrom->pTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
if( pTab==0 ) return SQLITE_NOMEM;
pTab->nTabRef = 1;
if( pFrom->zAlias ){
pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias);
}else{
pTab->zName = sqlite3MPrintf(pParse->db, "%!S", pFrom);
}
while( pSel->pPrior ){ pSel = pSel->pPrior; }
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
/* The usual case - do not allow ROWID on a subquery */
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
#else
pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */
#endif
return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}
/*
** Check the N SrcItem objects to the right of pBase. (N might be zero!)
** If any of those SrcItem objects have a USING clause containing zName
** then return true.
**
** If N is zero, or none of the N SrcItem objects to the right of pBase
** contains a USING clause, or if none of the USING clauses contain zName,
** then return false.
*/
static int inAnyUsingClause(
const char *zName, /* Name we are looking for */
SrcItem *pBase, /* The base SrcItem. Looking at pBase[1] and following */
int N /* How many SrcItems to check */
){
while( N>0 ){
N--;
pBase++;
if( pBase->fg.isUsing==0 ) continue;
if( NEVER(pBase->u3.pUsing==0) ) continue;
if( sqlite3IdListIndex(pBase->u3.pUsing, zName)>=0 ) return 1;
}
return 0;
}
/*
** This routine is a Walker callback for "expanding" a SELECT statement.
** "Expanding" means to do the following:
**
** (1) Make sure VDBE cursor numbers have been assigned to every
** element of the FROM clause.
|
| ︙ | ︙ | |||
140064 140065 140066 140067 140068 140069 140070 |
return WRC_Abort;
}
}
/* Process NATURAL keywords, and ON and USING clauses of joins.
*/
assert( db->mallocFailed==0 || pParse->nErr!=0 );
| | | 141330 141331 141332 141333 141334 141335 141336 141337 141338 141339 141340 141341 141342 141343 141344 |
return WRC_Abort;
}
}
/* Process NATURAL keywords, and ON and USING clauses of joins.
*/
assert( db->mallocFailed==0 || pParse->nErr!=0 );
if( pParse->nErr || sqlite3ProcessJoin(pParse, p) ){
return WRC_Abort;
}
/* For every "*" that occurs in the column list, insert the names of
** all columns in all tables. And for every TABLE.* insert the names
** of all columns in TABLE. The parser inserted a special expression
** with the TK_ASTERISK operator for each "*" that it found in the column
|
| ︙ | ︙ | |||
140112 140113 140114 140115 140116 140117 140118 |
&& (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK)
){
/* This particular expression does not need to be expanded.
*/
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
if( pNew ){
pNew->a[pNew->nExpr-1].zEName = a[k].zEName;
| | | | | | | > | > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > < < < > | > | > > > > > > | | | < < < < < < < | > > > > > > > > > > < < < < < < | > > | | > | | | | > > > > > > | > > > > | > > | 141378 141379 141380 141381 141382 141383 141384 141385 141386 141387 141388 141389 141390 141391 141392 141393 141394 141395 141396 141397 141398 141399 141400 141401 141402 141403 141404 141405 141406 141407 141408 141409 141410 141411 141412 141413 141414 141415 141416 141417 141418 141419 141420 141421 141422 141423 141424 141425 141426 141427 141428 141429 141430 141431 141432 141433 141434 141435 141436 141437 141438 141439 141440 141441 141442 141443 141444 141445 141446 141447 141448 141449 141450 141451 141452 141453 141454 141455 141456 141457 141458 141459 141460 141461 141462 141463 141464 141465 141466 141467 141468 141469 141470 141471 141472 141473 141474 141475 141476 141477 141478 141479 141480 141481 141482 141483 141484 141485 141486 141487 141488 141489 141490 141491 141492 141493 141494 141495 141496 141497 141498 141499 141500 141501 141502 141503 141504 141505 141506 141507 141508 141509 141510 141511 141512 141513 141514 141515 141516 141517 141518 141519 141520 141521 141522 141523 141524 141525 141526 141527 141528 141529 141530 141531 141532 141533 141534 141535 141536 141537 141538 141539 141540 141541 141542 |
&& (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK)
){
/* This particular expression does not need to be expanded.
*/
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
if( pNew ){
pNew->a[pNew->nExpr-1].zEName = a[k].zEName;
pNew->a[pNew->nExpr-1].fg.eEName = a[k].fg.eEName;
a[k].zEName = 0;
}
a[k].pExpr = 0;
}else{
/* This expression is a "*" or a "TABLE.*" and needs to be
** expanded. */
int tableSeen = 0; /* Set to 1 when TABLE matches */
char *zTName = 0; /* text of name of TABLE */
if( pE->op==TK_DOT ){
assert( pE->pLeft!=0 );
assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
zTName = pE->pLeft->u.zToken;
}
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
Table *pTab = pFrom->pTab; /* Table for this data source */
ExprList *pNestedFrom; /* Result-set of a nested FROM clause */
char *zTabName; /* AS name for this data source */
const char *zSchemaName = 0; /* Schema name for this data source */
int iDb; /* Schema index for this data src */
IdList *pUsing; /* USING clause for pFrom[1] */
if( (zTabName = pFrom->zAlias)==0 ){
zTabName = pTab->zName;
}
if( db->mallocFailed ) break;
assert( pFrom->fg.isNestedFrom == IsNestedFrom(pFrom->pSelect) );
if( pFrom->fg.isNestedFrom ){
assert( pFrom->pSelect!=0 );
pNestedFrom = pFrom->pSelect->pEList;
assert( pNestedFrom!=0 );
assert( pNestedFrom->nExpr==pTab->nCol );
}else{
if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
continue;
}
pNestedFrom = 0;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*";
}
if( i+1<pTabList->nSrc
&& pFrom[1].fg.isUsing
&& (selFlags & SF_NestedFrom)!=0
){
int ii;
pUsing = pFrom[1].u3.pUsing;
for(ii=0; ii<pUsing->nId; ii++){
const char *zUName = pUsing->a[ii].zName;
pRight = sqlite3Expr(db, TK_ID, zUName);
pNew = sqlite3ExprListAppend(pParse, pNew, pRight);
if( pNew ){
struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
assert( pX->zEName==0 );
pX->zEName = sqlite3MPrintf(db,"..%s", zUName);
pX->fg.eEName = ENAME_TAB;
pX->fg.bUsingTerm = 1;
}
}
}else{
pUsing = 0;
}
for(j=0; j<pTab->nCol; j++){
char *zName = pTab->aCol[j].zCnName;
struct ExprList_item *pX; /* Newly added ExprList term */
assert( zName );
if( zTName
&& pNestedFrom
&& sqlite3MatchEName(&pNestedFrom->a[j], 0, zTName, 0)==0
){
continue;
}
/* If a column is marked as 'hidden', omit it from the expanded
** result-set list unless the SELECT has the SF_IncludeHidden
** bit set.
*/
if( (p->selFlags & SF_IncludeHidden)==0
&& IsHiddenColumn(&pTab->aCol[j])
){
continue;
}
if( (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0
&& zTName==0
&& (selFlags & (SF_NestedFrom))==0
){
continue;
}
tableSeen = 1;
if( i>0 && zTName==0 && (selFlags & SF_NestedFrom)==0 ){
if( pFrom->fg.isUsing
&& sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0
){
/* In a join with a USING clause, omit columns in the
** using clause from the table on the right. */
continue;
}
}
pRight = sqlite3Expr(db, TK_ID, zName);
if( (pTabList->nSrc>1
&& ( (pFrom->fg.jointype & JT_LTORJ)==0
|| (selFlags & SF_NestedFrom)!=0
|| !inAnyUsingClause(zName,pFrom,pTabList->nSrc-i-1)
)
)
|| IN_RENAME_OBJECT
){
Expr *pLeft;
pLeft = sqlite3Expr(db, TK_ID, zTabName);
pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
if( IN_RENAME_OBJECT && pE->pLeft ){
sqlite3RenameTokenRemap(pParse, pLeft, pE->pLeft);
}
if( zSchemaName ){
pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr);
}
}else{
pExpr = pRight;
}
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
if( pNew==0 ){
break; /* OOM */
}
pX = &pNew->a[pNew->nExpr-1];
assert( pX->zEName==0 );
if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){
if( pNestedFrom ){
pX->zEName = sqlite3DbStrDup(db, pNestedFrom->a[j].zEName);
testcase( pX->zEName==0 );
}else{
pX->zEName = sqlite3MPrintf(db, "%s.%s.%s",
zSchemaName, zTabName, zName);
testcase( pX->zEName==0 );
}
pX->fg.eEName = ENAME_TAB;
if( (pFrom->fg.isUsing
&& sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0)
|| (pUsing && sqlite3IdListIndex(pUsing, zName)>=0)
|| (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0
){
pX->fg.bNoExpand = 1;
}
}else if( longNames ){
pX->zEName = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
pX->fg.eEName = ENAME_NAME;
}else{
pX->zEName = sqlite3DbStrDup(db, zName);
pX->fg.eEName = ENAME_NAME;
}
}
}
if( !tableSeen ){
if( zTName ){
sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
}else{
sqlite3ErrorMsg(pParse, "no tables specified");
|
| ︙ | ︙ | |||
140240 140241 140242 140243 140244 140245 140246 140247 140248 140249 140250 140251 140252 140253 |
sqlite3ErrorMsg(pParse, "too many columns in result set");
return WRC_Abort;
}
if( (elistFlags & (EP_HasFunc|EP_Subquery))!=0 ){
p->selFlags |= SF_ComplexResult;
}
}
return WRC_Continue;
}
#if SQLITE_DEBUG
/*
** Always assert. This xSelectCallback2 implementation proves that the
** xSelectCallback2 is never invoked.
| > > > > > > | 141552 141553 141554 141555 141556 141557 141558 141559 141560 141561 141562 141563 141564 141565 141566 141567 141568 141569 141570 141571 |
sqlite3ErrorMsg(pParse, "too many columns in result set");
return WRC_Abort;
}
if( (elistFlags & (EP_HasFunc|EP_Subquery))!=0 ){
p->selFlags |= SF_ComplexResult;
}
}
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After result-set wildcard expansion:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
return WRC_Continue;
}
#if SQLITE_DEBUG
/*
** Always assert. This xSelectCallback2 implementation proves that the
** xSelectCallback2 is never invoked.
|
| ︙ | ︙ | |||
140630 140631 140632 140633 140634 140635 140636 |
static void havingToWhere(Parse *pParse, Select *p){
Walker sWalker;
memset(&sWalker, 0, sizeof(sWalker));
sWalker.pParse = pParse;
sWalker.xExprCallback = havingToWhereExprCb;
sWalker.u.pSelect = p;
sqlite3WalkExpr(&sWalker, p->pHaving);
| | | | 141948 141949 141950 141951 141952 141953 141954 141955 141956 141957 141958 141959 141960 141961 141962 141963 |
static void havingToWhere(Parse *pParse, Select *p){
Walker sWalker;
memset(&sWalker, 0, sizeof(sWalker));
sWalker.pParse = pParse;
sWalker.xExprCallback = havingToWhereExprCb;
sWalker.u.pSelect = p;
sqlite3WalkExpr(&sWalker, p->pHaving);
#if TREETRACE_ENABLED
if( sWalker.eCode && (sqlite3TreeTrace & 0x100)!=0 ){
SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
}
/*
|
| ︙ | ︙ | |||
140763 140764 140765 140766 140767 140768 140769 |
pExpr = sqlite3PExpr(pParse, TK_PLUS, pTerm, pExpr);
}
pSub = pPrior;
}
p->pEList->a[0].pExpr = pExpr;
p->selFlags &= ~SF_Aggregate;
| | | > > > > > > > > > > > > > > > > > > > > > > > | 142081 142082 142083 142084 142085 142086 142087 142088 142089 142090 142091 142092 142093 142094 142095 142096 142097 142098 142099 142100 142101 142102 142103 142104 142105 142106 142107 142108 142109 142110 142111 142112 142113 142114 142115 142116 142117 142118 142119 142120 142121 142122 142123 142124 142125 142126 |
pExpr = sqlite3PExpr(pParse, TK_PLUS, pTerm, pExpr);
}
pSub = pPrior;
}
p->pEList->a[0].pExpr = pExpr;
p->selFlags &= ~SF_Aggregate;
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
return 1;
}
#endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */
/*
** If any term of pSrc, or any SF_NestedFrom sub-query, is not the same
** as pSrcItem but has the same alias as p0, then return true.
** Otherwise return false.
*/
static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){
int i;
for(i=0; i<pSrc->nSrc; i++){
SrcItem *p1 = &pSrc->a[i];
if( p1==p0 ) continue;
if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
return 1;
}
if( p1->pSelect
&& (p1->pSelect->selFlags & SF_NestedFrom)!=0
&& sameSrcAlias(p0, p1->pSelect->pSrc)
){
return 1;
}
}
return 0;
}
/*
** Generate code for the SELECT statement given in the p argument.
**
** The results are returned according to the SelectDest structure.
** See comments in sqliteInt.h for further information.
**
|
| ︙ | ︙ | |||
140817 140818 140819 140820 140821 140822 140823 |
assert( pParse==db->pParse );
v = sqlite3GetVdbe(pParse);
if( p==0 || pParse->nErr ){
return 1;
}
assert( db->mallocFailed==0 );
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
| | | > | > > > | | | | | < < | | | | | < | | | 142158 142159 142160 142161 142162 142163 142164 142165 142166 142167 142168 142169 142170 142171 142172 142173 142174 142175 142176 142177 142178 142179 142180 142181 142182 142183 142184 142185 142186 142187 142188 142189 142190 142191 142192 142193 142194 142195 142196 142197 142198 142199 142200 142201 142202 142203 142204 142205 142206 142207 142208 142209 142210 142211 142212 142213 142214 142215 142216 142217 142218 142219 142220 142221 142222 142223 142224 142225 142226 142227 142228 142229 142230 142231 142232 142233 142234 142235 142236 142237 142238 142239 142240 142241 142242 142243 142244 142245 142246 142247 142248 142249 142250 142251 142252 142253 142254 142255 142256 142257 |
assert( pParse==db->pParse );
v = sqlite3GetVdbe(pParse);
if( p==0 || pParse->nErr ){
return 1;
}
assert( db->mallocFailed==0 );
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
#if TREETRACE_ENABLED
SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
if( sqlite3TreeTrace & 0x10100 ){
if( (sqlite3TreeTrace & 0x10001)==0x10000 ){
sqlite3TreeViewLine(0, "In sqlite3Select() at %s:%d",
__FILE__, __LINE__);
}
sqlite3ShowSelect(p);
}
#endif
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
if( IgnorableDistinct(pDest) ){
assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo );
/* All of these destinations are also able to ignore the ORDER BY clause */
if( p->pOrderBy ){
#if TREETRACE_ENABLED
SELECTTRACE(1,pParse,p, ("dropping superfluous ORDER BY:\n"));
if( sqlite3TreeTrace & 0x100 ){
sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY");
}
#endif
sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))sqlite3ExprListDelete,
p->pOrderBy);
testcase( pParse->earlyCleanup );
p->pOrderBy = 0;
}
p->selFlags &= ~SF_Distinct;
p->selFlags |= SF_NoopOrderBy;
}
sqlite3SelectPrep(pParse, p, 0);
if( pParse->nErr ){
goto select_end;
}
assert( db->mallocFailed==0 );
assert( p->pEList!=0 );
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x104 ){
SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
/* If the SF_UFSrcCheck flag is set, then this function is being called
** as part of populating the temp table for an UPDATE...FROM statement.
** In this case, it is an error if the target object (pSrc->a[0]) name
** or alias is duplicated within FROM clause (pSrc->a[1..n]).
**
** Postgres disallows this case too. The reason is that some other
** systems handle this case differently, and not all the same way,
** which is just confusing. To avoid this, we follow PG's lead and
** disallow it altogether. */
if( p->selFlags & SF_UFSrcCheck ){
SrcItem *p0 = &p->pSrc->a[0];
if( sameSrcAlias(p0, p->pSrc) ){
sqlite3ErrorMsg(pParse,
"target object/alias may not appear in FROM clause: %s",
p0->zAlias ? p0->zAlias : p0->pTab->zName
);
goto select_end;
}
/* Clear the SF_UFSrcCheck flag. The check has already been performed,
** and leaving this flag set can cause errors if a compound sub-query
** in p->pSrc is flattened into this query and this function called
** again as part of compound SELECT processing. */
p->selFlags &= ~SF_UFSrcCheck;
}
if( pDest->eDest==SRT_Output ){
sqlite3GenerateColumnNames(pParse, p);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( sqlite3WindowRewrite(pParse, p) ){
assert( pParse->nErr );
goto select_end;
}
#if TREETRACE_ENABLED
if( p->pWin && (sqlite3TreeTrace & 0x108)!=0 ){
SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
#endif /* SQLITE_OMIT_WINDOWFUNC */
pTabList = p->pSrc;
isAgg = (p->selFlags & SF_Aggregate)!=0;
|
| ︙ | ︙ | |||
140929 140930 140931 140932 140933 140934 140935 |
** even for FROM clause elements such as subqueries that do not correspond
** to a real table */
assert( pTab!=0 );
/* Convert LEFT JOIN into JOIN if there are terms of the right table
** of the LEFT JOIN used in the WHERE clause.
*/
| | | > | 142271 142272 142273 142274 142275 142276 142277 142278 142279 142280 142281 142282 142283 142284 142285 142286 142287 142288 142289 142290 142291 142292 142293 |
** even for FROM clause elements such as subqueries that do not correspond
** to a real table */
assert( pTab!=0 );
/* Convert LEFT JOIN into JOIN if there are terms of the right table
** of the LEFT JOIN used in the WHERE clause.
*/
if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==JT_LEFT
&& sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor)
&& OptimizationEnabled(db, SQLITE_SimplifyJoin)
){
SELECTTRACE(0x100,pParse,p,
("LEFT-JOIN simplifies to JOIN on term %d\n",i));
pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER);
unsetJoinExpr(p->pWhere, pItem->iCursor,
pTabList->a[0].fg.jointype & JT_LTORJ);
}
/* No futher action if this term of the FROM clause is no a subquery */
if( pSub==0 ) continue;
/* Catch mismatch in the declared columns of a view and the number of
** columns in the SELECT on the RHS */
|
| ︙ | ︙ | |||
141015 141016 141017 141018 141019 141020 141021 |
**
** SELECT x FROM (SELECT x FROM tab ORDER BY y LIMIT 10);
*/
if( pSub->pOrderBy!=0
&& i==0
&& (p->selFlags & SF_ComplexResult)!=0
&& (pTabList->nSrc==1
| | | 142358 142359 142360 142361 142362 142363 142364 142365 142366 142367 142368 142369 142370 142371 142372 |
**
** SELECT x FROM (SELECT x FROM tab ORDER BY y LIMIT 10);
*/
if( pSub->pOrderBy!=0
&& i==0
&& (p->selFlags & SF_ComplexResult)!=0
&& (pTabList->nSrc==1
|| (pTabList->a[1].fg.jointype&(JT_OUTER|JT_CROSS))!=0)
){
continue;
}
if( flattenSubquery(pParse, p, i, isAgg) ){
if( pParse->nErr ) goto select_end;
/* This subquery can be absorbed into its parent. */
|
| ︙ | ︙ | |||
141039 141040 141041 141042 141043 141044 141045 |
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* Handle compound SELECT statements using the separate multiSelect()
** procedure.
*/
if( p->pPrior ){
rc = multiSelect(pParse, p, pDest);
| | | | | | 142382 142383 142384 142385 142386 142387 142388 142389 142390 142391 142392 142393 142394 142395 142396 142397 142398 142399 142400 142401 142402 142403 142404 142405 142406 142407 142408 142409 142410 142411 142412 142413 142414 142415 142416 142417 142418 |
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* Handle compound SELECT statements using the separate multiSelect()
** procedure.
*/
if( p->pPrior ){
rc = multiSelect(pParse, p, pDest);
#if TREETRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end compound-select processing\n"));
if( (sqlite3TreeTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
if( p->pNext==0 ) ExplainQueryPlanPop(pParse);
return rc;
}
#endif
/* Do the WHERE-clause constant propagation optimization if this is
** a join. No need to speed time on this operation for non-join queries
** as the equivalent optimization will be handled by query planner in
** sqlite3WhereBegin().
*/
if( p->pWhere!=0
&& p->pWhere->op==TK_AND
&& OptimizationEnabled(db, SQLITE_PropagateConst)
&& propagateConstants(pParse, p)
){
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After constant propagation:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
}else{
SELECTTRACE(0x100,pParse,p,("Constant propagation not helpful\n"));
}
|
| ︙ | ︙ | |||
141137 141138 141139 141140 141141 141142 141143 |
/* Make copies of constant WHERE-clause terms in the outer query down
** inside the subquery. This can help the subquery to run more efficiently.
*/
if( OptimizationEnabled(db, SQLITE_PushDown)
&& (pItem->fg.isCte==0
|| (pItem->u2.pCteUse->eM10d!=M10d_Yes && pItem->u2.pCteUse->nUse<2))
| | < | | | > > | < < | | > | 142480 142481 142482 142483 142484 142485 142486 142487 142488 142489 142490 142491 142492 142493 142494 142495 142496 142497 142498 142499 142500 142501 142502 142503 142504 142505 142506 142507 142508 142509 142510 142511 142512 142513 142514 142515 142516 142517 142518 142519 142520 142521 142522 142523 142524 142525 |
/* Make copies of constant WHERE-clause terms in the outer query down
** inside the subquery. This can help the subquery to run more efficiently.
*/
if( OptimizationEnabled(db, SQLITE_PushDown)
&& (pItem->fg.isCte==0
|| (pItem->u2.pCteUse->eM10d!=M10d_Yes && pItem->u2.pCteUse->nUse<2))
&& pushDownWhereTerms(pParse, pSub, p->pWhere, pItem)
){
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,
("After WHERE-clause push-down into subquery %d:\n", pSub->selId));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
}else{
SELECTTRACE(0x100,pParse,p,("Push-down not possible\n"));
}
zSavedAuthContext = pParse->zAuthContext;
pParse->zAuthContext = pItem->zName;
/* Generate code to implement the subquery
**
** The subquery is implemented as a co-routine all if the following are
** true:
**
** (1) the subquery is guaranteed to be the outer loop (so that
** it does not need to be computed more than once), and
** (2) the subquery is not a CTE that should be materialized
** (3) the subquery is not part of a left operand for a RIGHT JOIN
*/
if( i==0
&& (pTabList->nSrc==1
|| (pTabList->a[1].fg.jointype&(JT_OUTER|JT_CROSS))!=0) /* (1) */
&& (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes) /* (2) */
&& (pTabList->a[0].fg.jointype & JT_LTORJ)==0 /* (3) */
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
*/
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
pItem->regReturn = ++pParse->nMem;
|
| ︙ | ︙ | |||
141214 141215 141216 141217 141218 141219 141220 |
pSub->nSelectRow = pPrior->pSelect->nSelectRow;
}else{
/* Materialize the view. If the view is not correlated, generate a
** subroutine to do the materialization so that subsequent uses of
** the same view can reuse the materialization. */
int topAddr;
int onceAddr = 0;
| < | > | | | 142557 142558 142559 142560 142561 142562 142563 142564 142565 142566 142567 142568 142569 142570 142571 142572 142573 142574 142575 142576 142577 142578 142579 142580 142581 142582 142583 142584 142585 142586 142587 142588 142589 142590 142591 142592 |
pSub->nSelectRow = pPrior->pSelect->nSelectRow;
}else{
/* Materialize the view. If the view is not correlated, generate a
** subroutine to do the materialization so that subsequent uses of
** the same view can reuse the materialization. */
int topAddr;
int onceAddr = 0;
pItem->regReturn = ++pParse->nMem;
topAddr = sqlite3VdbeAddOp0(v, OP_Goto);
pItem->addrFillSub = topAddr+1;
pItem->fg.isMaterialized = 1;
if( pItem->fg.isCorrelated==0 ){
/* If the subquery is not correlated and if we are not inside of
** a trigger, then we only need to compute the value of the subquery
** once. */
onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
VdbeComment((v, "materialize %!S", pItem));
}else{
VdbeNoopComment((v, "materialize %!S", pItem));
}
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
ExplainQueryPlan((pParse, 1, "MATERIALIZE %!S", pItem));
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = pSub->nSelectRow;
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
sqlite3VdbeAddOp2(v, OP_Return, pItem->regReturn, topAddr+1);
VdbeComment((v, "end %!S", pItem));
sqlite3VdbeJumpHere(v, topAddr);
sqlite3ClearTempRegCache(pParse);
if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){
CteUse *pCteUse = pItem->u2.pCteUse;
pCteUse->addrM9e = pItem->addrFillSub;
pCteUse->regRtn = pItem->regReturn;
pCteUse->iCur = pItem->iCursor;
pCteUse->nRowEst = pSub->nSelectRow;
|
| ︙ | ︙ | |||
141259 141260 141261 141262 141263 141264 141265 | ** convenience */ pEList = p->pEList; pWhere = p->pWhere; pGroupBy = p->pGroupBy; pHaving = p->pHaving; sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0; | | | | 142602 142603 142604 142605 142606 142607 142608 142609 142610 142611 142612 142613 142614 142615 142616 142617 |
** convenience */
pEList = p->pEList;
pWhere = p->pWhere;
pGroupBy = p->pGroupBy;
pHaving = p->pHaving;
sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
/* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
** if the select-list is the same as the ORDER BY list, then this query
|
| ︙ | ︙ | |||
141296 141297 141298 141299 141300 141301 141302 |
p->selFlags |= SF_Aggregate;
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
** the sDistinct.isTnct is still set. Hence, isTnct represents the
** original setting of the SF_Distinct flag, not the current setting */
assert( sDistinct.isTnct );
sDistinct.isTnct = 2;
| | | | 142639 142640 142641 142642 142643 142644 142645 142646 142647 142648 142649 142650 142651 142652 142653 142654 |
p->selFlags |= SF_Aggregate;
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
** the sDistinct.isTnct is still set. Hence, isTnct represents the
** original setting of the SF_Distinct flag, not the current setting */
assert( sDistinct.isTnct );
sDistinct.isTnct = 2;
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
}
/* If there is an ORDER BY clause, then create an ephemeral index to
|
| ︙ | ︙ | |||
141330 141331 141332 141333 141334 141335 141336 141337 141338 141339 141340 141341 141342 141343 |
sSort.addrSortIndex = -1;
}
/* If the output is destined for a temporary table, open that table.
*/
if( pDest->eDest==SRT_EphemTab ){
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
}
/* Set the limiter.
*/
iEnd = sqlite3VdbeMakeLabel(pParse);
if( (p->selFlags & SF_FixedLimit)==0 ){
p->nSelectRow = 320; /* 4 billion rows */
| > > > > > > > > > > > > | 142673 142674 142675 142676 142677 142678 142679 142680 142681 142682 142683 142684 142685 142686 142687 142688 142689 142690 142691 142692 142693 142694 142695 142696 142697 142698 |
sSort.addrSortIndex = -1;
}
/* If the output is destined for a temporary table, open that table.
*/
if( pDest->eDest==SRT_EphemTab ){
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
if( p->selFlags & SF_NestedFrom ){
/* Delete or NULL-out result columns that will never be used */
int ii;
for(ii=pEList->nExpr-1; ii>0 && pEList->a[ii].fg.bUsed==0; ii--){
sqlite3ExprDelete(db, pEList->a[ii].pExpr);
sqlite3DbFree(db, pEList->a[ii].zEName);
pEList->nExpr--;
}
for(ii=0; ii<pEList->nExpr; ii++){
if( pEList->a[ii].fg.bUsed==0 ) pEList->a[ii].pExpr->op = TK_NULL;
}
}
}
/* Set the limiter.
*/
iEnd = sqlite3VdbeMakeLabel(pParse);
if( (p->selFlags & SF_FixedLimit)==0 ){
p->nSelectRow = 320; /* 4 billion rows */
|
| ︙ | ︙ | |||
141479 141480 141481 141482 141483 141484 141485 |
int ii;
/* The GROUP BY processing doesn't care whether rows are delivered in
** ASC or DESC order - only that each group is returned contiguously.
** So set the ASC/DESC flags in the GROUP BY to match those in the
** ORDER BY to maximize the chances of rows being delivered in an
** order that makes the ORDER BY redundant. */
for(ii=0; ii<pGroupBy->nExpr; ii++){
| > | | | 142834 142835 142836 142837 142838 142839 142840 142841 142842 142843 142844 142845 142846 142847 142848 142849 142850 |
int ii;
/* The GROUP BY processing doesn't care whether rows are delivered in
** ASC or DESC order - only that each group is returned contiguously.
** So set the ASC/DESC flags in the GROUP BY to match those in the
** ORDER BY to maximize the chances of rows being delivered in an
** order that makes the ORDER BY redundant. */
for(ii=0; ii<pGroupBy->nExpr; ii++){
u8 sortFlags;
sortFlags = sSort.pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC;
pGroupBy->a[ii].fg.sortFlags = sortFlags;
}
if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
orderByGrp = 1;
}
}
}else{
assert( 0==sqlite3LogEst(1) );
|
| ︙ | ︙ | |||
141549 141550 141551 141552 141553 141554 141555 |
sqlite3ExprAnalyzeAggregates(&sNC, pExpr->y.pWin->pFilter);
}
#endif
sNC.ncFlags &= ~NC_InAggFunc;
}
pAggInfo->mxReg = pParse->nMem;
if( db->mallocFailed ) goto select_end;
| | | | 142905 142906 142907 142908 142909 142910 142911 142912 142913 142914 142915 142916 142917 142918 142919 142920 |
sqlite3ExprAnalyzeAggregates(&sNC, pExpr->y.pWin->pFilter);
}
#endif
sNC.ncFlags &= ~NC_InAggFunc;
}
pAggInfo->mxReg = pParse->nMem;
if( db->mallocFailed ) goto select_end;
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x400 ){
int ii;
SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", pAggInfo));
sqlite3TreeViewSelect(0, p, 0);
if( minMaxFlag ){
sqlite3DebugPrintf("MIN/MAX Optimization (0x%02x) adds:\n", minMaxFlag);
sqlite3TreeViewExprList(0, pMinMaxOrderBy, 0, "ORDERBY");
}
|
| ︙ | ︙ | |||
141945 141946 141947 141948 141949 141950 141951 |
if( pWInfo==0 ){
goto select_end;
}
SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
eDist = sqlite3WhereIsDistinct(pWInfo);
updateAccumulator(pParse, regAcc, pAggInfo, eDist);
if( eDist!=WHERE_DISTINCT_NOOP ){
| | > | > | 143301 143302 143303 143304 143305 143306 143307 143308 143309 143310 143311 143312 143313 143314 143315 143316 143317 143318 |
if( pWInfo==0 ){
goto select_end;
}
SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
eDist = sqlite3WhereIsDistinct(pWInfo);
updateAccumulator(pParse, regAcc, pAggInfo, eDist);
if( eDist!=WHERE_DISTINCT_NOOP ){
struct AggInfo_func *pF = pAggInfo->aFunc;
if( pF ){
fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
}
}
if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
if( minMaxFlag ){
sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
}
SELECTTRACE(1,pParse,p,("WhereEnd\n"));
|
| ︙ | ︙ | |||
142013 142014 142015 142016 142017 142018 142019 |
assert( pExpr!=0 );
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
}
#endif
| | | | 143371 143372 143373 143374 143375 143376 143377 143378 143379 143380 143381 143382 143383 143384 143385 143386 143387 |
assert( pExpr!=0 );
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
}
#endif
#if TREETRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end processing\n"));
if( (sqlite3TreeTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
ExplainQueryPlanPop(pParse);
return rc;
}
|
| ︙ | ︙ | |||
142280 142281 142282 142283 142284 142285 142286 |
** pTab as well as the triggers lised in pTab->pTrigger.
*/
SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
Schema *pTmpSchema; /* Schema of the pTab table */
Trigger *pList; /* List of triggers to return */
HashElem *p; /* Loop variable for TEMP triggers */
| | < < | 143638 143639 143640 143641 143642 143643 143644 143645 143646 143647 143648 143649 143650 143651 143652 |
** pTab as well as the triggers lised in pTab->pTrigger.
*/
SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
Schema *pTmpSchema; /* Schema of the pTab table */
Trigger *pList; /* List of triggers to return */
HashElem *p; /* Loop variable for TEMP triggers */
assert( pParse->disableTriggers==0 );
pTmpSchema = pParse->db->aDb[1].pSchema;
p = sqliteHashFirst(&pTmpSchema->trigHash);
pList = pTab->pTrigger;
while( p ){
Trigger *pTrig = (Trigger *)sqliteHashData(p);
if( pTrig->pTabSchema==pTab->pSchema
&& pTrig->table
|
| ︙ | ︙ | |||
142744 142745 142746 142747 142748 142749 142750 | ** Construct a trigger step that implements an UPDATE statement and return ** a pointer to that trigger step. The parser calls this routine when it ** sees an UPDATE statement inside the body of a CREATE TRIGGER. */ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( Parse *pParse, /* Parser */ Token *pTableName, /* Name of the table to be updated */ | | | 144100 144101 144102 144103 144104 144105 144106 144107 144108 144109 144110 144111 144112 144113 144114 |
** Construct a trigger step that implements an UPDATE statement and return
** a pointer to that trigger step. The parser calls this routine when it
** sees an UPDATE statement inside the body of a CREATE TRIGGER.
*/
SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(
Parse *pParse, /* Parser */
Token *pTableName, /* Name of the table to be updated */
SrcList *pFrom, /* FROM clause for an UPDATE-FROM, or NULL */
ExprList *pEList, /* The SET clause: list of column and new values */
Expr *pWhere, /* The WHERE clause */
u8 orconf, /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
const char *zStart, /* Start of SQL text */
const char *zEnd /* End of SQL text */
){
sqlite3 *db = pParse->db;
|
| ︙ | ︙ | |||
142956 142957 142958 142959 142960 142961 142962 142963 142964 142965 142966 142967 142968 142969 |
int e;
if( pIdList==0 || NEVER(pEList==0) ) return 1;
for(e=0; e<pEList->nExpr; e++){
if( sqlite3IdListIndex(pIdList, pEList->a[e].zEName)>=0 ) return 1;
}
return 0;
}
/*
** Return a list of all triggers on table pTab if there exists at least
** one trigger that must be fired when an operation of type 'op' is
** performed on the table, and, if that operation is an UPDATE, if at
** least one of the columns in pChanges is being modified.
*/
| > > > > > > > > > | | 144312 144313 144314 144315 144316 144317 144318 144319 144320 144321 144322 144323 144324 144325 144326 144327 144328 144329 144330 144331 144332 144333 144334 144335 144336 144337 144338 144339 144340 144341 144342 |
int e;
if( pIdList==0 || NEVER(pEList==0) ) return 1;
for(e=0; e<pEList->nExpr; e++){
if( sqlite3IdListIndex(pIdList, pEList->a[e].zEName)>=0 ) return 1;
}
return 0;
}
/*
** Return true if any TEMP triggers exist
*/
static int tempTriggersExist(sqlite3 *db){
if( NEVER(db->aDb[1].pSchema==0) ) return 0;
if( sqliteHashFirst(&db->aDb[1].pSchema->trigHash)==0 ) return 0;
return 1;
}
/*
** Return a list of all triggers on table pTab if there exists at least
** one trigger that must be fired when an operation of type 'op' is
** performed on the table, and, if that operation is an UPDATE, if at
** least one of the columns in pChanges is being modified.
*/
static SQLITE_NOINLINE Trigger *triggersReallyExist(
Parse *pParse, /* Parse context */
Table *pTab, /* The table the contains the triggers */
int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
ExprList *pChanges, /* Columns that change in an UPDATE statement */
int *pMask /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
){
int mask = 0;
|
| ︙ | ︙ | |||
143026 143027 143028 143029 143030 143031 143032 143033 143034 143035 143036 143037 143038 143039 |
}
exit_triggers_exist:
if( pMask ){
*pMask = mask;
}
return (mask ? pList : 0);
}
/*
** Convert the pStep->zTarget string into a SrcList and return a pointer
** to that SrcList.
**
** This routine adds a specific database name, if needed, to the target when
** forming the SrcList. This prevents a trigger in one database from
| > > > > > > > > > > > > > > > > | 144391 144392 144393 144394 144395 144396 144397 144398 144399 144400 144401 144402 144403 144404 144405 144406 144407 144408 144409 144410 144411 144412 144413 144414 144415 144416 144417 144418 144419 144420 |
}
exit_triggers_exist:
if( pMask ){
*pMask = mask;
}
return (mask ? pList : 0);
}
SQLITE_PRIVATE Trigger *sqlite3TriggersExist(
Parse *pParse, /* Parse context */
Table *pTab, /* The table the contains the triggers */
int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
ExprList *pChanges, /* Columns that change in an UPDATE statement */
int *pMask /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
){
assert( pTab!=0 );
if( (pTab->pTrigger==0 && !tempTriggersExist(pParse->db))
|| pParse->disableTriggers
){
if( pMask ) *pMask = 0;
return 0;
}
return triggersReallyExist(pParse,pTab,op,pChanges,pMask);
}
/*
** Convert the pStep->zTarget string into a SrcList and return a pointer
** to that SrcList.
**
** This routine adds a specific database name, if needed, to the target when
** forming the SrcList. This prevents a trigger in one database from
|
| ︙ | ︙ | |||
143055 143056 143057 143058 143059 143060 143061 143062 143063 143064 143065 143066 143067 143068 |
Schema *pSchema = pStep->pTrig->pSchema;
pSrc->a[0].zName = zName;
if( pSchema!=db->aDb[1].pSchema ){
pSrc->a[0].pSchema = pSchema;
}
if( pStep->pFrom ){
SrcList *pDup = sqlite3SrcListDup(db, pStep->pFrom, 0);
pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup);
}
}else{
sqlite3DbFree(db, zName);
}
return pSrc;
}
| > > > > > > > > | 144436 144437 144438 144439 144440 144441 144442 144443 144444 144445 144446 144447 144448 144449 144450 144451 144452 144453 144454 144455 144456 144457 |
Schema *pSchema = pStep->pTrig->pSchema;
pSrc->a[0].zName = zName;
if( pSchema!=db->aDb[1].pSchema ){
pSrc->a[0].pSchema = pSchema;
}
if( pStep->pFrom ){
SrcList *pDup = sqlite3SrcListDup(db, pStep->pFrom, 0);
if( pDup && pDup->nSrc>1 && !IN_RENAME_OBJECT ){
Select *pSubquery;
Token as;
pSubquery = sqlite3SelectNew(pParse,0,pDup,0,0,0,0,SF_NestedFrom,0);
as.n = 0;
as.z = 0;
pDup = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0);
}
pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup);
}
}else{
sqlite3DbFree(db, zName);
}
return pSrc;
}
|
| ︙ | ︙ | |||
143110 143111 143112 143113 143114 143115 143116 |
Expr *pNewExpr;
if( IsHiddenColumn(pTab->aCol+jj) ) continue;
pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zCnName);
pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
if( !db->mallocFailed ){
struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zCnName);
| | | | 144499 144500 144501 144502 144503 144504 144505 144506 144507 144508 144509 144510 144511 144512 144513 144514 144515 144516 144517 144518 144519 144520 144521 144522 |
Expr *pNewExpr;
if( IsHiddenColumn(pTab->aCol+jj) ) continue;
pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zCnName);
pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
if( !db->mallocFailed ){
struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zCnName);
pItem->fg.eEName = ENAME_NAME;
}
}
}else{
Expr *pNewExpr = sqlite3ExprDup(db, pOldExpr, 0);
pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){
struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
pItem->zEName = sqlite3DbStrDup(db, pList->a[i].zEName);
pItem->fg.eEName = pList->a[i].fg.eEName;
}
}
}
return pNew;
}
/*
|
| ︙ | ︙ | |||
144033 144034 144035 144036 144037 144038 144039 144040 144041 144042 144043 144044 144045 144046 | # define isView 0 # define tmask 0 #endif #ifdef SQLITE_OMIT_VIEW # undef isView # define isView 0 #endif /* If there was a FROM clause, set nChangeFrom to the number of expressions ** in the change-list. Otherwise, set it to 0. There cannot be a FROM ** clause if this function is being called to generate code for part of ** an UPSERT statement. */ nChangeFrom = (pTabList->nSrc>1) ? pChanges->nExpr : 0; assert( nChangeFrom==0 || pUpsert==0 ); | > > > > > > > > | 145422 145423 145424 145425 145426 145427 145428 145429 145430 145431 145432 145433 145434 145435 145436 145437 145438 145439 145440 145441 145442 145443 |
# define isView 0
# define tmask 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x10000 ){
sqlite3TreeViewLine(0, "In sqlite3Update() at %s:%d", __FILE__, __LINE__);
sqlite3TreeViewUpdate(pParse->pWith, pTabList, pChanges, pWhere,
onError, pOrderBy, pLimit, pUpsert, pTrigger);
}
#endif
/* If there was a FROM clause, set nChangeFrom to the number of expressions
** in the change-list. Otherwise, set it to 0. There cannot be a FROM
** clause if this function is being called to generate code for part of
** an UPSERT statement. */
nChangeFrom = (pTabList->nSrc>1) ? pChanges->nExpr : 0;
assert( nChangeFrom==0 || pUpsert==0 );
|
| ︙ | ︙ | |||
144678 144679 144680 144681 144682 144683 144684 |
** moved cursor iDataCur. Reseek it. */
if( bReplace || chngKey ){
if( pPk ){
sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey);
}else{
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid);
}
| | | 146075 146076 146077 146078 146079 146080 146081 146082 146083 146084 146085 146086 146087 146088 146089 |
** moved cursor iDataCur. Reseek it. */
if( bReplace || chngKey ){
if( pPk ){
sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey);
}else{
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid);
}
VdbeCoverage(v);
}
/* Do FK constraint checks. */
if( hasFK ){
sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
}
|
| ︙ | ︙ | |||
145684 145685 145686 145687 145688 145689 145690 145691 145692 145693 145694 145695 145696 145697 |
sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
}
#endif
}
assert( rc==SQLITE_OK );
if( pOut==0 ){
rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
}
end_of_vacuum:
/* Restore the original value of db->flags */
db->init.iDb = 0;
db->mDbFlags = saved_mDbFlags;
| > | 147081 147082 147083 147084 147085 147086 147087 147088 147089 147090 147091 147092 147093 147094 147095 |
sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
}
#endif
}
assert( rc==SQLITE_OK );
if( pOut==0 ){
nRes = sqlite3BtreeGetRequestedReserve(pTemp);
rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
}
end_of_vacuum:
/* Restore the original value of db->flags */
db->init.iDb = 0;
db->mDbFlags = saved_mDbFlags;
|
| ︙ | ︙ | |||
147126 147127 147128 147129 147130 147131 147132 147133 147134 147135 147136 147137 147138 147139 | typedef struct WhereLoop WhereLoop; typedef struct WherePath WherePath; typedef struct WhereTerm WhereTerm; typedef struct WhereLoopBuilder WhereLoopBuilder; typedef struct WhereScan WhereScan; typedef struct WhereOrCost WhereOrCost; typedef struct WhereOrSet WhereOrSet; /* ** This object contains information needed to implement a single nested ** loop in WHERE clause. ** ** Contrast this object with WhereLoop. This object describes the ** implementation of the loop. WhereLoop describes the algorithm. | > > > > > > > > > > > > > > > > > > > > > > | 148524 148525 148526 148527 148528 148529 148530 148531 148532 148533 148534 148535 148536 148537 148538 148539 148540 148541 148542 148543 148544 148545 148546 148547 148548 148549 148550 148551 148552 148553 148554 148555 148556 148557 148558 148559 |
typedef struct WhereLoop WhereLoop;
typedef struct WherePath WherePath;
typedef struct WhereTerm WhereTerm;
typedef struct WhereLoopBuilder WhereLoopBuilder;
typedef struct WhereScan WhereScan;
typedef struct WhereOrCost WhereOrCost;
typedef struct WhereOrSet WhereOrSet;
typedef struct WhereMemBlock WhereMemBlock;
typedef struct WhereRightJoin WhereRightJoin;
/*
** This object is a header on a block of allocated memory that will be
** automatically freed when its WInfo oject is destructed.
*/
struct WhereMemBlock {
WhereMemBlock *pNext; /* Next block in the chain */
u64 sz; /* Bytes of space */
};
/*
** Extra information attached to a WhereLevel that is a RIGHT JOIN.
*/
struct WhereRightJoin {
int iMatch; /* Cursor used to determine prior matched rows */
int regBloom; /* Bloom filter for iRJMatch */
int regReturn; /* Return register for the interior subroutine */
int addrSubrtn; /* Starting address for the interior subroutine */
int endSubrtn; /* The last opcode in the interior subroutine */
};
/*
** This object contains information needed to implement a single nested
** loop in WHERE clause.
**
** Contrast this object with WhereLoop. This object describes the
** implementation of the loop. WhereLoop describes the algorithm.
|
| ︙ | ︙ | |||
147159 147160 147161 147162 147163 147164 147165 147166 147167 147168 147169 147170 147171 147172 |
int regBignull; /* big-null flag reg. True if a NULL-scan is needed */
int addrBignull; /* Jump here for next part of big-null scan */
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */
int addrLikeRep; /* LIKE range processing address */
#endif
int regFilter; /* Bloom filter */
u8 iFrom; /* Which entry in the FROM clause */
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
int p1, p2; /* Operands of the opcode used to end the loop */
union { /* Information that depends on pWLoop->wsFlags */
struct {
int nIn; /* Number of entries in aInLoop[] */
struct InLoop {
| > | 148579 148580 148581 148582 148583 148584 148585 148586 148587 148588 148589 148590 148591 148592 148593 |
int regBignull; /* big-null flag reg. True if a NULL-scan is needed */
int addrBignull; /* Jump here for next part of big-null scan */
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */
int addrLikeRep; /* LIKE range processing address */
#endif
int regFilter; /* Bloom filter */
WhereRightJoin *pRJ; /* Extra information for RIGHT JOIN */
u8 iFrom; /* Which entry in the FROM clause */
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
int p1, p2; /* Operands of the opcode used to end the loop */
union { /* Information that depends on pWLoop->wsFlags */
struct {
int nIn; /* Number of entries in aInLoop[] */
struct InLoop {
|
| ︙ | ︙ | |||
147572 147573 147574 147575 147576 147577 147578 147579 147580 147581 147582 147583 147584 147585 | unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */ unsigned sorted :1; /* True if really sorted (not just grouped) */ LogEst nRowOut; /* Estimated number of output rows */ int iTop; /* The very beginning of the WHERE loop */ int iEndWhere; /* End of the WHERE clause itself */ WhereLoop *pLoops; /* List of all WhereLoop objects */ WhereExprMod *pExprMods; /* Expression modifications */ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ WhereClause sWC; /* Decomposition of the WHERE clause */ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; /* | > | 148993 148994 148995 148996 148997 148998 148999 149000 149001 149002 149003 149004 149005 149006 149007 | unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */ unsigned sorted :1; /* True if really sorted (not just grouped) */ LogEst nRowOut; /* Estimated number of output rows */ int iTop; /* The very beginning of the WHERE loop */ int iEndWhere; /* End of the WHERE clause itself */ WhereLoop *pLoops; /* List of all WhereLoop objects */ WhereExprMod *pExprMods; /* Expression modifications */ WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ WhereClause sWC; /* Decomposition of the WHERE clause */ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; /* |
| ︙ | ︙ | |||
147597 147598 147599 147600 147601 147602 147603 147604 147605 147606 147607 147608 147609 147610 | WhereClause *pWC, /* The WHERE clause to be searched */ int iCur, /* Cursor number of LHS */ int iColumn, /* Column number of LHS */ Bitmask notReady, /* RHS must not overlap with this mask */ u32 op, /* Mask of WO_xx values describing operator */ Index *pIdx /* Must be compatible with this index, if not NULL */ ); /* wherecode.c: */ #ifndef SQLITE_OMIT_EXPLAIN SQLITE_PRIVATE int sqlite3WhereExplainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ | > > | 149019 149020 149021 149022 149023 149024 149025 149026 149027 149028 149029 149030 149031 149032 149033 149034 | WhereClause *pWC, /* The WHERE clause to be searched */ int iCur, /* Cursor number of LHS */ int iColumn, /* Column number of LHS */ Bitmask notReady, /* RHS must not overlap with this mask */ u32 op, /* Mask of WO_xx values describing operator */ Index *pIdx /* Must be compatible with this index, if not NULL */ ); SQLITE_PRIVATE void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte); SQLITE_PRIVATE void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte); /* wherecode.c: */ #ifndef SQLITE_OMIT_EXPLAIN SQLITE_PRIVATE int sqlite3WhereExplainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ |
| ︙ | ︙ | |||
147632 147633 147634 147635 147636 147637 147638 147639 147640 147641 147642 147643 147644 147645 | SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( Parse *pParse, /* Parsing context */ Vdbe *v, /* Prepared statement under construction */ WhereInfo *pWInfo, /* Complete information about the WHERE clause */ int iLevel, /* Which level of pWInfo->a[] should be coded */ WhereLevel *pLevel, /* The current level pointer */ Bitmask notReady /* Which tables are currently available */ ); /* whereexpr.c: */ SQLITE_PRIVATE void sqlite3WhereClauseInit(WhereClause*,WhereInfo*); SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause*); SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause*,Expr*,u8); SQLITE_PRIVATE void sqlite3WhereAddLimit(WhereClause*, Select*); | > > > > > | 149056 149057 149058 149059 149060 149061 149062 149063 149064 149065 149066 149067 149068 149069 149070 149071 149072 149073 149074 | SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( Parse *pParse, /* Parsing context */ Vdbe *v, /* Prepared statement under construction */ WhereInfo *pWInfo, /* Complete information about the WHERE clause */ int iLevel, /* Which level of pWInfo->a[] should be coded */ WhereLevel *pLevel, /* The current level pointer */ Bitmask notReady /* Which tables are currently available */ ); SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( WhereInfo *pWInfo, int iLevel, WhereLevel *pLevel ); /* whereexpr.c: */ SQLITE_PRIVATE void sqlite3WhereClauseInit(WhereClause*,WhereInfo*); SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause*); SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause*,Expr*,u8); SQLITE_PRIVATE void sqlite3WhereAddLimit(WhereClause*, Select*); |
| ︙ | ︙ | |||
147675 147676 147677 147678 147679 147680 147681 147682 | #define WO_AUX 0x0040 /* Op useful to virtual tables only */ #define WO_IS 0x0080 #define WO_ISNULL 0x0100 #define WO_OR 0x0200 /* Two or more OR-connected terms */ #define WO_AND 0x0400 /* Two or more AND-connected terms */ #define WO_EQUIV 0x0800 /* Of the form A==B, both columns */ #define WO_NOOP 0x1000 /* This term does not restrict search space */ | > | | 149104 149105 149106 149107 149108 149109 149110 149111 149112 149113 149114 149115 149116 149117 149118 149119 149120 | #define WO_AUX 0x0040 /* Op useful to virtual tables only */ #define WO_IS 0x0080 #define WO_ISNULL 0x0100 #define WO_OR 0x0200 /* Two or more OR-connected terms */ #define WO_AND 0x0400 /* Two or more AND-connected terms */ #define WO_EQUIV 0x0800 /* Of the form A==B, both columns */ #define WO_NOOP 0x1000 /* This term does not restrict search space */ #define WO_ROWVAL 0x2000 /* A row-value term */ #define WO_ALL 0x3fff /* Mask of all possible WO_* values */ #define WO_SINGLE 0x01ff /* Mask of all non-compound WO_* values */ /* ** These are definitions of bits in the WhereLoop.wsFlags field. ** The particular combination of bits in each WhereLoop help to ** determine the algorithm that WhereLoop represents. */ |
| ︙ | ︙ | |||
147900 147901 147902 147903 147904 147905 147906 147907 147908 147909 147910 147911 147912 147913 |
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s",
pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
}
#endif
#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
if( pLoop->nOut>=10 ){
sqlite3_str_appendf(&str, " (~%llu rows)",
sqlite3LogEstToInt(pLoop->nOut));
}else{
sqlite3_str_append(&str, " (~1 row)", 9);
}
| > > > | 149330 149331 149332 149333 149334 149335 149336 149337 149338 149339 149340 149341 149342 149343 149344 149345 149346 |
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s",
pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
}
#endif
if( pItem->fg.jointype & JT_LEFT ){
sqlite3_str_appendf(&str, " LEFT-JOIN");
}
#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
if( pLoop->nOut>=10 ){
sqlite3_str_appendf(&str, " (~%llu rows)",
sqlite3LogEstToInt(pLoop->nOut));
}else{
sqlite3_str_append(&str, " (~1 row)", 9);
}
|
| ︙ | ︙ | |||
148043 148044 148045 148046 148047 148048 148049 |
** a conditional such that is only evaluated on the second pass of a
** LIKE-optimization loop, when scanning BLOBs instead of strings.
*/
static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
int nLoop = 0;
assert( pTerm!=0 );
while( (pTerm->wtFlags & TERM_CODED)==0
| | | 149476 149477 149478 149479 149480 149481 149482 149483 149484 149485 149486 149487 149488 149489 149490 |
** a conditional such that is only evaluated on the second pass of a
** LIKE-optimization loop, when scanning BLOBs instead of strings.
*/
static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
int nLoop = 0;
assert( pTerm!=0 );
while( (pTerm->wtFlags & TERM_CODED)==0
&& (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_OuterON))
&& (pLevel->notReady & pTerm->prereqAll)==0
){
if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
pTerm->wtFlags |= TERM_LIKECOND;
}else{
pTerm->wtFlags |= TERM_CODED;
}
|
| ︙ | ︙ | |||
148304 148305 148306 148307 148308 148309 148310 |
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
}
iTab = 0;
if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
}else{
| > > | | < | | | | | | > > > > | | 149737 149738 149739 149740 149741 149742 149743 149744 149745 149746 149747 149748 149749 149750 149751 149752 149753 149754 149755 149756 149757 149758 149759 149760 149761 149762 149763 149764 149765 |
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
}
iTab = 0;
if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
}else{
Expr *pExpr = pTerm->pExpr;
if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
sqlite3 *db = pParse->db;
pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
if( !db->mallocFailed ){
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
pExpr->iTable = iTab;
}
sqlite3ExprDelete(db, pX);
}else{
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
}
pX = pExpr;
}
if( eType==IN_INDEX_INDEX_DESC ){
testcase( bRev );
bRev = !bRev;
}
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
|
| ︙ | ︙ | |||
148336 148337 148338 148339 148340 148341 148342 |
if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
pLoop->wsFlags |= WHERE_IN_EARLYOUT;
}
i = pLevel->u.in.nIn;
pLevel->u.in.nIn += nEq;
pLevel->u.in.aInLoop =
| > | | | 149774 149775 149776 149777 149778 149779 149780 149781 149782 149783 149784 149785 149786 149787 149788 149789 149790 |
if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
pLoop->wsFlags |= WHERE_IN_EARLYOUT;
}
i = pLevel->u.in.nIn;
pLevel->u.in.nIn += nEq;
pLevel->u.in.aInLoop =
sqlite3WhereRealloc(pTerm->pWC->pWInfo,
pLevel->u.in.aInLoop,
sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
pIn = pLevel->u.in.aInLoop;
if( pIn ){
int iMap = 0; /* Index in aiMap[] */
pIn += i;
for(i=iEq;i<pLoop->nLTerm; i++){
if( pLoop->aLTerm[i]->pExpr==pX ){
int iOut = iReg + i - iEq;
|
| ︙ | ︙ | |||
148758 148759 148760 148761 148762 148763 148764 |
**
** WHERE 1 = (t2.c IS NULL)
**
** are also excluded. See codeCursorHintIsOrFunction() for details.
*/
if( pTabItem->fg.jointype & JT_LEFT ){
Expr *pExpr = pTerm->pExpr;
| | | | | 150197 150198 150199 150200 150201 150202 150203 150204 150205 150206 150207 150208 150209 150210 150211 150212 150213 150214 150215 150216 150217 150218 150219 150220 |
**
** WHERE 1 = (t2.c IS NULL)
**
** are also excluded. See codeCursorHintIsOrFunction() for details.
*/
if( pTabItem->fg.jointype & JT_LEFT ){
Expr *pExpr = pTerm->pExpr;
if( !ExprHasProperty(pExpr, EP_OuterON)
|| pExpr->w.iJoin!=pTabItem->iCursor
){
sWalker.eCode = 0;
sWalker.xExprCallback = codeCursorHintIsOrFunction;
sqlite3WalkExpr(&sWalker, pTerm->pExpr);
if( sWalker.eCode ) continue;
}
}else{
if( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) continue;
}
/* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize
** the cursor. These terms are not needed as hints for a pure range
** scan (that has no == terms) so omit them. */
if( pLoop->u.btree.nEq==0 && pTerm!=pEndRange ){
for(j=0; j<pLoop->nLTerm && pLoop->aLTerm[j]!=pTerm; j++){}
|
| ︙ | ︙ | |||
148845 148846 148847 148848 148849 148850 148851 | Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */ assert( iIdxCur>0 ); assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); pWInfo->bDeferredSeek = 1; sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur); | | | 150284 150285 150286 150287 150288 150289 150290 150291 150292 150293 150294 150295 150296 150297 150298 |
Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */
assert( iIdxCur>0 );
assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
pWInfo->bDeferredSeek = 1;
sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))
&& DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask)
){
int i;
Table *pTab = pIdx->pTable;
u32 *ai = (u32*)sqlite3DbMallocZero(pParse->db, sizeof(u32)*(pTab->nCol+1));
if( ai ){
ai[0] = pTab->nCol;
|
| ︙ | ︙ | |||
148939 148940 148941 148942 148943 148944 148945 148946 148947 148948 148949 148950 |
**
** If pExpr matches, then transform it into a reference to the index column
** that contains the value of pExpr.
*/
static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
IdxExprTrans *pX = p->u.pIdxTrans;
if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
preserveExpr(pX, pExpr);
pExpr->affExpr = sqlite3ExprAffinity(pExpr);
pExpr->op = TK_COLUMN;
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
| > < | 150378 150379 150380 150381 150382 150383 150384 150385 150386 150387 150388 150389 150390 150391 150392 150393 150394 150395 150396 150397 |
**
** If pExpr matches, then transform it into a reference to the index column
** that contains the value of pExpr.
*/
static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
IdxExprTrans *pX = p->u.pIdxTrans;
if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
pExpr = sqlite3ExprSkipCollate(pExpr);
preserveExpr(pX, pExpr);
pExpr->affExpr = sqlite3ExprAffinity(pExpr);
pExpr->op = TK_COLUMN;
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
testcase( ExprHasProperty(pExpr, EP_Unlikely) );
ExprClearProperty(pExpr, EP_Skip|EP_Unlikely|EP_WinFunc|EP_Subrtn);
pExpr->y.pTab = 0;
return WRC_Prune;
}else{
return WRC_Continue;
}
|
| ︙ | ︙ | |||
149098 149099 149100 149101 149102 149103 149104 149105 149106 149107 149108 149109 149110 149111 |
WhereLevel *pLevel = &pWInfo->a[iLevel];
WhereLoop *pLoop = pLevel->pWLoop;
if( pLevel->regFilter==0 ) continue;
if( pLevel->pWLoop->nSkip ) continue;
/* ,--- Because sqlite3ConstructBloomFilter() has will not have set
** vvvvv--' pLevel->regFilter if this were true. */
if( NEVER(pLoop->prereq & notReady) ) continue;
if( pLoop->wsFlags & WHERE_IPK ){
WhereTerm *pTerm = pLoop->aLTerm[0];
int regRowid;
assert( pTerm!=0 );
assert( pTerm->pExpr!=0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL );
regRowid = sqlite3GetTempReg(pParse);
| > > | 150537 150538 150539 150540 150541 150542 150543 150544 150545 150546 150547 150548 150549 150550 150551 150552 |
WhereLevel *pLevel = &pWInfo->a[iLevel];
WhereLoop *pLoop = pLevel->pWLoop;
if( pLevel->regFilter==0 ) continue;
if( pLevel->pWLoop->nSkip ) continue;
/* ,--- Because sqlite3ConstructBloomFilter() has will not have set
** vvvvv--' pLevel->regFilter if this were true. */
if( NEVER(pLoop->prereq & notReady) ) continue;
assert( pLevel->addrBrk==0 );
pLevel->addrBrk = addrNxt;
if( pLoop->wsFlags & WHERE_IPK ){
WhereTerm *pTerm = pLoop->aLTerm[0];
int regRowid;
assert( pTerm!=0 );
assert( pTerm->pExpr!=0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL );
regRowid = sqlite3GetTempReg(pParse);
|
| ︙ | ︙ | |||
149124 149125 149126 149127 149128 149129 149130 149131 149132 149133 149134 149135 149136 149137 |
codeApplyAffinity(pParse, r1, nEq, zStartAff);
sqlite3DbFree(pParse->db, zStartAff);
sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
addrNxt, r1, nEq);
VdbeCoverage(pParse->pVdbe);
}
pLevel->regFilter = 0;
}
}
/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
| > | 150565 150566 150567 150568 150569 150570 150571 150572 150573 150574 150575 150576 150577 150578 150579 |
codeApplyAffinity(pParse, r1, nEq, zStartAff);
sqlite3DbFree(pParse->db, zStartAff);
sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
addrNxt, r1, nEq);
VdbeCoverage(pParse->pVdbe);
}
pLevel->regFilter = 0;
pLevel->addrBrk = 0;
}
}
/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
|
| ︙ | ︙ | |||
149197 149198 149199 149200 149201 149202 149203 | addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse); addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(pParse); /* If this is the right table of a LEFT OUTER JOIN, allocate and ** initialize a memory cell that records if this table matches any ** row of the left table of the join. */ | | | > > > | 150639 150640 150641 150642 150643 150644 150645 150646 150647 150648 150649 150650 150651 150652 150653 150654 150655 150656 150657 150658 150659 150660 150661 150662 150663 150664 150665 150666 150667 |
addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(pParse);
/* If this is the right table of a LEFT OUTER JOIN, allocate and
** initialize a memory cell that records if this table matches any
** row of the left table of the join.
*/
assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))
|| pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0
);
if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){
pLevel->iLeftJoin = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
VdbeComment((v, "init LEFT JOIN no-match flag"));
}
/* Compute a safe address to jump to if we discover that the table for
** this loop is empty and can never contribute content. */
for(j=iLevel; j>0; j--){
if( pWInfo->a[j].iLeftJoin ) break;
if( pWInfo->a[j].pRJ ) break;
}
addrHalt = pWInfo->a[j].addrBrk;
/* Special case of a FROM clause subquery implemented as a co-routine */
if( pTabItem->fg.viaCoroutine ){
int regYield = pTabItem->regReturn;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
|
| ︙ | ︙ | |||
149835 149836 149837 149838 149839 149840 149841 |
if( (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0 ){
sqlite3VdbeAddOp3(v, OP_SeekHit, iIdxCur, nEq, nEq);
}
/* Seek the table cursor, if required */
omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
| | | 151280 151281 151282 151283 151284 151285 151286 151287 151288 151289 151290 151291 151292 151293 151294 |
if( (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0 ){
sqlite3VdbeAddOp3(v, OP_SeekHit, iIdxCur, nEq, nEq);
}
/* Seek the table cursor, if required */
omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
&& (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0;
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
}else if( iCur!=iIdxCur ){
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
|
| ︙ | ︙ | |||
149869 149870 149871 149872 149873 149874 149875 |
** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a
**
** Also, do not do this when processing one index an a multi-index
** OR clause, since the transformation will become invalid once we
** move forward to the next index.
** https://sqlite.org/src/info/4e8e4857d32d401f
*/
| | | | 151314 151315 151316 151317 151318 151319 151320 151321 151322 151323 151324 151325 151326 151327 151328 151329 151330 151331 151332 151333 151334 151335 151336 151337 151338 151339 151340 151341 151342 151343 151344 151345 151346 151347 |
** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a
**
** Also, do not do this when processing one index an a multi-index
** OR clause, since the transformation will become invalid once we
** move forward to the next index.
** https://sqlite.org/src/info/4e8e4857d32d401f
*/
if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 ){
whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
}
/* If a partial index is driving the loop, try to eliminate WHERE clause
** terms from the query that must be true due to the WHERE clause of
** the partial index.
**
** 2019-11-02 ticket 623eff57e76d45f6: This optimization does not work
** for a LEFT JOIN.
*/
if( pIdx->pPartIdxWhere ){
whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
}
}else{
testcase( pIdx->pPartIdxWhere );
/* The following assert() is not a requirement, merely an observation:
** The OR-optimization doesn't work for the right hand table of
** a LEFT JOIN: */
assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 );
}
/* Record the instruction used to terminate the loop. */
if( pLoop->wsFlags & WHERE_ONEROW ){
pLevel->op = OP_Noop;
}else if( bRev ){
pLevel->op = OP_Prev;
|
| ︙ | ︙ | |||
150092 150093 150094 150095 150096 150097 150098 |
WhereTerm *pOrTerm = &pOrWc->a[ii];
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
Expr *pDelete; /* Local copy of OR clause term */
int jmp1 = 0; /* Address of jump operation */
testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0
| | | 151537 151538 151539 151540 151541 151542 151543 151544 151545 151546 151547 151548 151549 151550 151551 |
WhereTerm *pOrTerm = &pOrWc->a[ii];
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
Expr *pDelete; /* Local copy of OR clause term */
int jmp1 = 0; /* Address of jump operation */
testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0
&& !ExprHasProperty(pOrExpr, EP_OuterON)
); /* See TH3 vtab25.400 and ticket 614b25314c766238 */
pDelete = pOrExpr = sqlite3ExprDup(db, pOrExpr, 0);
if( db->mallocFailed ){
sqlite3ExprDelete(db, pDelete);
continue;
}
if( pAndExpr ){
|
| ︙ | ︙ | |||
150229 150230 150231 150232 150233 150234 150235 150236 150237 150238 150239 150240 150241 150242 |
if( pAndExpr ){
pAndExpr->pLeft = 0;
sqlite3ExprDelete(db, pAndExpr);
}
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeGoto(v, pLevel->addrBrk);
sqlite3VdbeResolveLabel(v, iLoopBody);
if( pWInfo->nLevel>1 ){ sqlite3StackFree(db, pOrTab); }
if( !untestedTerms ) disableTerm(pLevel, pTerm);
}else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
{
| > > > > > > > > | 151674 151675 151676 151677 151678 151679 151680 151681 151682 151683 151684 151685 151686 151687 151688 151689 151690 151691 151692 151693 151694 151695 |
if( pAndExpr ){
pAndExpr->pLeft = 0;
sqlite3ExprDelete(db, pAndExpr);
}
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeGoto(v, pLevel->addrBrk);
sqlite3VdbeResolveLabel(v, iLoopBody);
/* Set the P2 operand of the OP_Return opcode that will end the current
** loop to point to this spot, which is the top of the next containing
** loop. The byte-code formatter will use that P2 value as a hint to
** indent everything in between the this point and the final OP_Return.
** See tag-20220407a in vdbe.c and shell.c */
assert( pLevel->op==OP_Return );
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
if( pWInfo->nLevel>1 ){ sqlite3StackFree(db, pOrTab); }
if( !untestedTerms ) disableTerm(pLevel, pTerm);
}else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
{
|
| ︙ | ︙ | |||
150292 150293 150294 150295 150296 150297 150298 |
testcase( pWInfo->untestedTerms==0
&& (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 );
pWInfo->untestedTerms = 1;
continue;
}
pE = pTerm->pExpr;
assert( pE!=0 );
| > > > > > > | | > > > > > | | > | 151745 151746 151747 151748 151749 151750 151751 151752 151753 151754 151755 151756 151757 151758 151759 151760 151761 151762 151763 151764 151765 151766 151767 151768 151769 151770 151771 151772 151773 151774 |
testcase( pWInfo->untestedTerms==0
&& (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 );
pWInfo->untestedTerms = 1;
continue;
}
pE = pTerm->pExpr;
assert( pE!=0 );
if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ){
if( !ExprHasProperty(pE,EP_OuterON|EP_InnerON) ){
/* Defer processing WHERE clause constraints until after outer
** join processing. tag-20220513a */
continue;
}else if( (pTabItem->fg.jointype & JT_LEFT)==JT_LEFT
&& !ExprHasProperty(pE,EP_OuterON) ){
continue;
}else{
Bitmask m = sqlite3WhereGetMask(&pWInfo->sMaskSet, pE->w.iJoin);
if( m & pLevel->notReady ){
/* An ON clause that is not ripe */
continue;
}
}
}
if( iLoop==1 && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){
iNext = 2;
continue;
}
if( iLoop<3 && (pTerm->wtFlags & TERM_VARSELECT) ){
if( iNext==0 ) iNext = 3;
continue;
|
| ︙ | ︙ | |||
150354 150355 150356 150357 150358 150359 150360 |
for(pTerm=pWC->a, j=pWC->nBase; j>0; j--, pTerm++){
Expr *pE, sEAlt;
WhereTerm *pAlt;
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
if( pTerm->leftCursor!=iCur ) continue;
| | | | 151819 151820 151821 151822 151823 151824 151825 151826 151827 151828 151829 151830 151831 151832 151833 151834 151835 151836 151837 151838 151839 151840 151841 |
for(pTerm=pWC->a, j=pWC->nBase; j>0; j--, pTerm++){
Expr *pE, sEAlt;
WhereTerm *pAlt;
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
if( pTerm->leftCursor!=iCur ) continue;
if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ) continue;
pE = pTerm->pExpr;
#ifdef WHERETRACE_ENABLED /* 0x800 */
if( sqlite3WhereTrace & 0x800 ){
sqlite3DebugPrintf("Coding transitive constraint:\n");
sqlite3WhereTermPrint(pTerm, pWC->nTerm-j);
}
#endif
assert( !ExprHasProperty(pE, EP_OuterON) );
assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.x.leftColumn, notReady,
WO_EQ|WO_IN|WO_IS, 0);
if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue;
if( (pAlt->eOperator & WO_IN)
|
| ︙ | ︙ | |||
150384 150385 150386 150387 150388 150389 150390 150391 150392 150393 150394 150395 150396 150397 150398 150399 150400 150401 150402 150403 150404 150405 150406 150407 150408 150409 150410 150411 150412 150413 150414 150415 150416 150417 150418 150419 150420 150421 150422 150423 150424 150425 150426 150427 150428 150429 150430 150431 150432 |
testcase( pAlt->eOperator & WO_IN );
VdbeModuleComment((v, "begin transitive constraint"));
sEAlt = *pAlt->pExpr;
sEAlt.pLeft = pE->pLeft;
sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
pAlt->wtFlags |= TERM_CODED;
}
/* For a LEFT OUTER JOIN, generate code that will record the fact that
** at least one row of the right table has matched the left table.
*/
if( pLevel->iLeftJoin ){
pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
VdbeComment((v, "record LEFT JOIN hit"));
for(pTerm=pWC->a, j=0; j<pWC->nBase; j++, pTerm++){
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
assert( pWInfo->untestedTerms );
continue;
}
assert( pTerm->pExpr );
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
pTerm->wtFlags |= TERM_CODED;
}
}
#if WHERETRACE_ENABLED /* 0x20800 */
if( sqlite3WhereTrace & 0x20000 ){
sqlite3DebugPrintf("All WHERE-clause terms after coding level %d:\n",
iLevel);
sqlite3WhereClausePrint(pWC);
}
if( sqlite3WhereTrace & 0x800 ){
sqlite3DebugPrintf("End Coding level %d: notReady=%llx\n",
iLevel, (u64)pLevel->notReady);
}
#endif
return pLevel->notReady;
}
/************** End of wherecode.c *******************************************/
/************** Begin file whereexpr.c ***************************************/
/*
** 2015-06-08
**
** The author disclaims copyright to this source code. In place of
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 151849 151850 151851 151852 151853 151854 151855 151856 151857 151858 151859 151860 151861 151862 151863 151864 151865 151866 151867 151868 151869 151870 151871 151872 151873 151874 151875 151876 151877 151878 151879 151880 151881 151882 151883 151884 151885 151886 151887 151888 151889 151890 151891 151892 151893 151894 151895 151896 151897 151898 151899 151900 151901 151902 151903 151904 151905 151906 151907 151908 151909 151910 151911 151912 151913 151914 151915 151916 151917 151918 151919 151920 151921 151922 151923 151924 151925 151926 151927 151928 151929 151930 151931 151932 151933 151934 151935 151936 151937 151938 151939 151940 151941 151942 151943 151944 151945 151946 151947 151948 151949 151950 151951 151952 151953 151954 151955 151956 151957 151958 151959 151960 151961 151962 151963 151964 151965 151966 151967 151968 151969 151970 151971 151972 151973 151974 151975 151976 151977 151978 151979 151980 151981 151982 151983 151984 151985 151986 151987 151988 151989 151990 151991 151992 151993 151994 151995 151996 151997 151998 151999 152000 152001 152002 152003 152004 152005 152006 152007 152008 152009 152010 152011 152012 152013 152014 152015 152016 152017 152018 152019 152020 152021 152022 152023 152024 152025 152026 152027 152028 152029 152030 152031 152032 152033 152034 152035 152036 152037 152038 152039 152040 152041 152042 152043 152044 152045 152046 152047 152048 152049 152050 152051 152052 152053 |
testcase( pAlt->eOperator & WO_IN );
VdbeModuleComment((v, "begin transitive constraint"));
sEAlt = *pAlt->pExpr;
sEAlt.pLeft = pE->pLeft;
sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
pAlt->wtFlags |= TERM_CODED;
}
/* For a RIGHT OUTER JOIN, record the fact that the current row has
** been matched at least once.
*/
if( pLevel->pRJ ){
Table *pTab;
int nPk;
int r;
int jmp1 = 0;
WhereRightJoin *pRJ = pLevel->pRJ;
/* pTab is the right-hand table of the RIGHT JOIN. Generate code that
** will record that the current row of that table has been matched at
** least once. This is accomplished by storing the PK for the row in
** both the iMatch index and the regBloom Bloom filter.
*/
pTab = pWInfo->pTabList->a[pLevel->iFrom].pTab;
if( HasRowid(pTab) ){
r = sqlite3GetTempRange(pParse, 2);
sqlite3ExprCodeGetColumnOfTable(v, pTab, pLevel->iTabCur, -1, r+1);
nPk = 1;
}else{
int iPk;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
nPk = pPk->nKeyCol;
r = sqlite3GetTempRange(pParse, nPk+1);
for(iPk=0; iPk<nPk; iPk++){
int iCol = pPk->aiColumn[iPk];
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+1+iPk);
}
}
jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, 0, r+1, nPk);
VdbeCoverage(v);
VdbeComment((v, "match against %s", pTab->zName));
sqlite3VdbeAddOp3(v, OP_MakeRecord, r+1, nPk, r);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pRJ->iMatch, r, r+1, nPk);
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3VdbeJumpHere(v, jmp1);
sqlite3ReleaseTempRange(pParse, r, nPk+1);
}
/* For a LEFT OUTER JOIN, generate code that will record the fact that
** at least one row of the right table has matched the left table.
*/
if( pLevel->iLeftJoin ){
pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
VdbeComment((v, "record LEFT JOIN hit"));
if( pLevel->pRJ==0 ){
goto code_outer_join_constraints; /* WHERE clause constraints */
}
}
if( pLevel->pRJ ){
/* Create a subroutine used to process all interior loops and code
** of the RIGHT JOIN. During normal operation, the subroutine will
** be in-line with the rest of the code. But at the end, a separate
** loop will run that invokes this subroutine for unmatched rows
** of pTab, with all tables to left begin set to NULL.
*/
WhereRightJoin *pRJ = pLevel->pRJ;
sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pRJ->regReturn);
pRJ->addrSubrtn = sqlite3VdbeCurrentAddr(v);
assert( pParse->withinRJSubrtn < 255 );
pParse->withinRJSubrtn++;
/* WHERE clause constraints must be deferred until after outer join
** row elimination has completed, since WHERE clause constraints apply
** to the results of the OUTER JOIN. The following loop generates the
** appropriate WHERE clause constraint checks. tag-20220513a.
*/
code_outer_join_constraints:
for(pTerm=pWC->a, j=0; j<pWC->nBase; j++, pTerm++){
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
assert( pWInfo->untestedTerms );
continue;
}
if( pTabItem->fg.jointype & JT_LTORJ ) continue;
assert( pTerm->pExpr );
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
pTerm->wtFlags |= TERM_CODED;
}
}
#if WHERETRACE_ENABLED /* 0x20800 */
if( sqlite3WhereTrace & 0x20000 ){
sqlite3DebugPrintf("All WHERE-clause terms after coding level %d:\n",
iLevel);
sqlite3WhereClausePrint(pWC);
}
if( sqlite3WhereTrace & 0x800 ){
sqlite3DebugPrintf("End Coding level %d: notReady=%llx\n",
iLevel, (u64)pLevel->notReady);
}
#endif
return pLevel->notReady;
}
/*
** Generate the code for the loop that finds all non-matched terms
** for a RIGHT JOIN.
*/
SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
WhereInfo *pWInfo,
int iLevel,
WhereLevel *pLevel
){
Parse *pParse = pWInfo->pParse;
Vdbe *v = pParse->pVdbe;
WhereRightJoin *pRJ = pLevel->pRJ;
Expr *pSubWhere = 0;
WhereClause *pWC = &pWInfo->sWC;
WhereInfo *pSubWInfo;
WhereLoop *pLoop = pLevel->pWLoop;
SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
SrcList sFrom;
Bitmask mAll = 0;
int k;
ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName));
sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
pRJ->regReturn);
for(k=0; k<iLevel; k++){
int iIdxCur;
mAll |= pWInfo->a[k].pWLoop->maskSelf;
sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
iIdxCur = pWInfo->a[k].iIdxCur;
if( iIdxCur ){
sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
}
}
if( (pTabItem->fg.jointype & JT_LTORJ)==0 ){
mAll |= pLoop->maskSelf;
for(k=0; k<pWC->nTerm; k++){
WhereTerm *pTerm = &pWC->a[k];
if( (pTerm->wtFlags & (TERM_VIRTUAL|TERM_SLICE))!=0
&& pTerm->eOperator!=WO_ROWVAL
){
break;
}
if( pTerm->prereqAll & ~mAll ) continue;
if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue;
pSubWhere = sqlite3ExprAnd(pParse, pSubWhere,
sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
}
}
sFrom.nSrc = 1;
sFrom.nAlloc = 1;
memcpy(&sFrom.a[0], pTabItem, sizeof(SrcItem));
sFrom.a[0].fg.jointype = 0;
assert( pParse->withinRJSubrtn < 100 );
pParse->withinRJSubrtn++;
pSubWInfo = sqlite3WhereBegin(pParse, &sFrom, pSubWhere, 0, 0, 0,
WHERE_RIGHT_JOIN, 0);
if( pSubWInfo ){
int iCur = pLevel->iTabCur;
int r = ++pParse->nMem;
int nPk;
int jmp;
int addrCont = sqlite3WhereContinueLabel(pSubWInfo);
Table *pTab = pTabItem->pTab;
if( HasRowid(pTab) ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, r);
nPk = 1;
}else{
int iPk;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
nPk = pPk->nKeyCol;
pParse->nMem += nPk - 1;
for(iPk=0; iPk<nPk; iPk++){
int iCol = pPk->aiColumn[iPk];
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk);
}
}
jmp = sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, 0, r, nPk);
VdbeCoverage(v);
sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, addrCont, r, nPk);
VdbeCoverage(v);
sqlite3VdbeJumpHere(v, jmp);
sqlite3VdbeAddOp2(v, OP_Gosub, pRJ->regReturn, pRJ->addrSubrtn);
sqlite3WhereEnd(pSubWInfo);
}
sqlite3ExprDelete(pParse->db, pSubWhere);
ExplainQueryPlanPop(pParse);
assert( pParse->withinRJSubrtn>0 );
pParse->withinRJSubrtn--;
}
/************** End of wherecode.c *******************************************/
/************** Begin file whereexpr.c ***************************************/
/*
** 2015-06-08
**
** The author disclaims copyright to this source code. In place of
|
| ︙ | ︙ | |||
150488 150489 150490 150491 150492 150493 150494 |
static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
WhereTerm *pTerm;
int idx;
testcase( wtFlags & TERM_VIRTUAL );
if( pWC->nTerm>=pWC->nSlot ){
WhereTerm *pOld = pWC->a;
sqlite3 *db = pWC->pWInfo->pParse->db;
| | < < < | | 152109 152110 152111 152112 152113 152114 152115 152116 152117 152118 152119 152120 152121 152122 152123 152124 152125 152126 152127 152128 152129 152130 152131 152132 |
static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
WhereTerm *pTerm;
int idx;
testcase( wtFlags & TERM_VIRTUAL );
if( pWC->nTerm>=pWC->nSlot ){
WhereTerm *pOld = pWC->a;
sqlite3 *db = pWC->pWInfo->pParse->db;
pWC->a = sqlite3WhereMalloc(pWC->pWInfo, sizeof(pWC->a[0])*pWC->nSlot*2 );
if( pWC->a==0 ){
if( wtFlags & TERM_DYNAMIC ){
sqlite3ExprDelete(db, p);
}
pWC->a = pOld;
return 0;
}
memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
pWC->nSlot = pWC->nSlot*2;
}
pTerm = &pWC->a[idx = pWC->nTerm++];
if( (wtFlags & TERM_VIRTUAL)==0 ) pWC->nBase = pWC->nTerm;
if( p && ExprHasProperty(p, EP_Unlikely) ){
pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
}else{
pTerm->truthProb = 1;
|
| ︙ | ︙ | |||
150888 150889 150890 150891 150892 150893 150894 |
#endif /* SQLITE_OMIT_VIRTUALTABLE */
/*
** If the pBase expression originated in the ON or USING clause of
** a join, then transfer the appropriate markings over to derived.
*/
static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
| | | | | 152506 152507 152508 152509 152510 152511 152512 152513 152514 152515 152516 152517 152518 152519 152520 152521 152522 |
#endif /* SQLITE_OMIT_VIRTUALTABLE */
/*
** If the pBase expression originated in the ON or USING clause of
** a join, then transfer the appropriate markings over to derived.
*/
static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
if( pDerived && ExprHasProperty(pBase, EP_OuterON|EP_InnerON) ){
pDerived->flags |= pBase->flags & (EP_OuterON|EP_InnerON);
pDerived->w.iJoin = pBase->w.iJoin;
}
}
/*
** Mark term iChild as being a child of term iParent
*/
static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
|
| ︙ | ︙ | |||
151344 151345 151346 151347 151348 151349 151350 |
** returned when it should not be, then incorrect answers might result.
*/
static int termIsEquivalence(Parse *pParse, Expr *pExpr){
char aff1, aff2;
CollSeq *pColl;
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
| | | 152962 152963 152964 152965 152966 152967 152968 152969 152970 152971 152972 152973 152974 152975 152976 |
** returned when it should not be, then incorrect answers might result.
*/
static int termIsEquivalence(Parse *pParse, Expr *pExpr){
char aff1, aff2;
CollSeq *pColl;
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
if( ExprHasProperty(pExpr, EP_OuterON) ) return 0;
aff1 = sqlite3ExprAffinity(pExpr->pLeft);
aff2 = sqlite3ExprAffinity(pExpr->pRight);
if( aff1!=aff2
&& (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
){
return 0;
}
|
| ︙ | ︙ | |||
151375 151376 151377 151378 151379 151380 151381 |
mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pOrderBy);
mask |= sqlite3WhereExprUsage(pMaskSet, pS->pWhere);
mask |= sqlite3WhereExprUsage(pMaskSet, pS->pHaving);
if( ALWAYS(pSrc!=0) ){
int i;
for(i=0; i<pSrc->nSrc; i++){
mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect);
| > | > | 152993 152994 152995 152996 152997 152998 152999 153000 153001 153002 153003 153004 153005 153006 153007 153008 153009 |
mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pOrderBy);
mask |= sqlite3WhereExprUsage(pMaskSet, pS->pWhere);
mask |= sqlite3WhereExprUsage(pMaskSet, pS->pHaving);
if( ALWAYS(pSrc!=0) ){
int i;
for(i=0; i<pSrc->nSrc; i++){
mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect);
if( pSrc->a[i].fg.isUsing==0 ){
mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].u3.pOn);
}
if( pSrc->a[i].fg.isTabFunc ){
mask |= sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg);
}
}
}
pS = pS->pPrior;
}
|
| ︙ | ︙ | |||
151530 151531 151532 151533 151534 151535 151536 |
}
if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT;
#ifdef SQLITE_DEBUG
if( prereqAll!=sqlite3WhereExprUsageNN(pMaskSet, pExpr) ){
printf("\n*** Incorrect prereqAll computed for:\n");
sqlite3TreeViewExpr(0,pExpr,0);
| | | | > | | | | | | > > > > > > > | 153150 153151 153152 153153 153154 153155 153156 153157 153158 153159 153160 153161 153162 153163 153164 153165 153166 153167 153168 153169 153170 153171 153172 153173 153174 153175 153176 153177 153178 153179 153180 153181 153182 153183 |
}
if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT;
#ifdef SQLITE_DEBUG
if( prereqAll!=sqlite3WhereExprUsageNN(pMaskSet, pExpr) ){
printf("\n*** Incorrect prereqAll computed for:\n");
sqlite3TreeViewExpr(0,pExpr,0);
assert( 0 );
}
#endif
if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) ){
Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->w.iJoin);
if( ExprHasProperty(pExpr, EP_OuterON) ){
prereqAll |= x;
extraRight = x-1; /* ON clause terms may not be used with an index
** on left table of a LEFT JOIN. Ticket #3015 */
if( (prereqAll>>1)>=x ){
sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
return;
}
}else if( (prereqAll>>1)>=x ){
/* The ON clause of an INNER JOIN references a table to its right.
** Most other SQL database engines raise an error. But all versions
** of SQLite going back to 3.0.0 have just put the ON clause constraint
** into the WHERE clause and carried on. */
ExprClearProperty(pExpr, EP_InnerON);
}
}
pTerm->prereqAll = prereqAll;
pTerm->leftCursor = -1;
pTerm->iParent = -1;
pTerm->eOperator = 0;
if( allowedOp(op) ){
|
| ︙ | ︙ | |||
151609 151610 151611 151612 151613 151614 151615 |
pNew->u.x.leftColumn = aiCurCol[1];
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
}else
if( op==TK_ISNULL
| | | 153237 153238 153239 153240 153241 153242 153243 153244 153245 153246 153247 153248 153249 153250 153251 |
pNew->u.x.leftColumn = aiCurCol[1];
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
}else
if( op==TK_ISNULL
&& !ExprHasProperty(pExpr,EP_OuterON)
&& 0==sqlite3ExprCanBeNull(pLeft)
){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
pExpr->op = TK_TRUEFALSE;
pExpr->u.zToken = "false";
ExprSetProperty(pExpr, EP_IsFalse);
pTerm->prereqAll = 0;
|
| ︙ | ︙ | |||
151680 151681 151682 151683 151684 151685 151686 |
** virtual term of that form.
**
** The virtual term must be tagged with TERM_VNULL.
*/
else if( pExpr->op==TK_NOTNULL ){
if( pExpr->pLeft->op==TK_COLUMN
&& pExpr->pLeft->iColumn>=0
| | | 153308 153309 153310 153311 153312 153313 153314 153315 153316 153317 153318 153319 153320 153321 153322 |
** virtual term of that form.
**
** The virtual term must be tagged with TERM_VNULL.
*/
else if( pExpr->op==TK_NOTNULL ){
if( pExpr->pLeft->op==TK_COLUMN
&& pExpr->pLeft->iColumn>=0
&& !ExprHasProperty(pExpr, EP_OuterON)
){
Expr *pNewExpr;
Expr *pLeft = pExpr->pLeft;
int idxNew;
WhereTerm *pNewTerm;
pNewExpr = sqlite3PExpr(pParse, TK_GT,
|
| ︙ | ︙ | |||
151828 151829 151830 151831 151832 151833 151834 |
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
transferJoinMarkings(pNew, pExpr);
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_SLICE);
exprAnalyze(pSrc, pWC, idxNew);
}
pTerm = &pWC->a[idxTerm];
pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */
| | | 153456 153457 153458 153459 153460 153461 153462 153463 153464 153465 153466 153467 153468 153469 153470 |
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
transferJoinMarkings(pNew, pExpr);
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_SLICE);
exprAnalyze(pSrc, pWC, idxNew);
}
pTerm = &pWC->a[idxTerm];
pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */
pTerm->eOperator = WO_ROWVAL;
}
/* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create
** a virtual term for each vector component. The expression object
** used by each such virtual term is pExpr (the full vector IN(...)
** expression). The WhereTerm.u.x.iField variable identifies the index within
** the vector on the LHS that the virtual term represents.
|
| ︙ | ︙ | |||
151884 151885 151886 151887 151888 151889 151890 |
prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);
prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
if( (prereqExpr & prereqColumn)==0 ){
Expr *pNewExpr;
pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
0, sqlite3ExprDup(db, pRight, 0));
| | | | | 153512 153513 153514 153515 153516 153517 153518 153519 153520 153521 153522 153523 153524 153525 153526 153527 153528 |
prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);
prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
if( (prereqExpr & prereqColumn)==0 ){
Expr *pNewExpr;
pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
0, sqlite3ExprDup(db, pRight, 0));
if( ExprHasProperty(pExpr, EP_OuterON) && pNewExpr ){
ExprSetProperty(pNewExpr, EP_OuterON);
pNewExpr->w.iJoin = pExpr->w.iJoin;
}
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
pNewTerm = &pWC->a[idxNew];
pNewTerm->prereqRight = prereqExpr;
pNewTerm->leftCursor = pLeft->iTable;
pNewTerm->u.x.leftColumn = pLeft->iColumn;
|
| ︙ | ︙ | |||
152029 152030 152031 152032 152033 152034 152035 |
/* Check condition (4). Return early if it is not met. */
for(ii=0; ii<pWC->nTerm; ii++){
if( pWC->a[ii].wtFlags & TERM_CODED ){
/* This term is a vector operation that has been decomposed into
** other, subsequent terms. It can be ignored. See tag-20220128a */
assert( pWC->a[ii].wtFlags & TERM_VIRTUAL );
| | | | 153657 153658 153659 153660 153661 153662 153663 153664 153665 153666 153667 153668 153669 153670 153671 153672 153673 153674 153675 153676 153677 153678 153679 153680 153681 153682 153683 |
/* Check condition (4). Return early if it is not met. */
for(ii=0; ii<pWC->nTerm; ii++){
if( pWC->a[ii].wtFlags & TERM_CODED ){
/* This term is a vector operation that has been decomposed into
** other, subsequent terms. It can be ignored. See tag-20220128a */
assert( pWC->a[ii].wtFlags & TERM_VIRTUAL );
assert( pWC->a[ii].eOperator==WO_ROWVAL );
continue;
}
if( pWC->a[ii].leftCursor!=iCsr ) return;
}
/* Check condition (5). Return early if it is not met. */
if( pOrderBy ){
for(ii=0; ii<pOrderBy->nExpr; ii++){
Expr *pExpr = pOrderBy->a[ii].pExpr;
if( pExpr->op!=TK_COLUMN ) return;
if( pExpr->iTable!=iCsr ) return;
if( pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) return;
}
}
/* All conditions are met. Add the terms to the where-clause object. */
assert( p->pLimit->op==TK_LIMIT );
whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
|
| ︙ | ︙ | |||
152108 152109 152110 152111 152112 152113 152114 |
whereAndInfoDelete(db, a->u.pAndInfo);
}
}
if( a==aLast ) break;
a++;
}
}
| < < < | 153736 153737 153738 153739 153740 153741 153742 153743 153744 153745 153746 153747 153748 153749 |
whereAndInfoDelete(db, a->u.pAndInfo);
}
}
if( a==aLast ) break;
a++;
}
}
}
/*
** These routines walk (recursively) an expression tree and generate
** a bitmask indicating which tables are used in that expression
** tree.
|
| ︙ | ︙ | |||
152237 152238 152239 152240 152241 152242 152243 152244 152245 152246 152247 152248 152249 152250 152251 152252 152253 152254 152255 152256 152257 152258 152259 |
if( pItem->fg.isTabFunc==0 ) return;
pTab = pItem->pTab;
assert( pTab!=0 );
pArgs = pItem->u1.pFuncArg;
if( pArgs==0 ) return;
for(j=k=0; j<pArgs->nExpr; j++){
Expr *pRhs;
while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;}
if( k>=pTab->nCol ){
sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d",
pTab->zName, j);
return;
}
pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
if( pColRef==0 ) return;
pColRef->iTable = pItem->iCursor;
pColRef->iColumn = k++;
assert( ExprUseYTab(pColRef) );
pColRef->y.pTab = pTab;
pItem->colUsed |= sqlite3ExprColUsed(pColRef);
pRhs = sqlite3PExpr(pParse, TK_UPLUS,
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
| > | | > > > | 153862 153863 153864 153865 153866 153867 153868 153869 153870 153871 153872 153873 153874 153875 153876 153877 153878 153879 153880 153881 153882 153883 153884 153885 153886 153887 153888 153889 153890 153891 153892 153893 153894 153895 153896 153897 153898 |
if( pItem->fg.isTabFunc==0 ) return;
pTab = pItem->pTab;
assert( pTab!=0 );
pArgs = pItem->u1.pFuncArg;
if( pArgs==0 ) return;
for(j=k=0; j<pArgs->nExpr; j++){
Expr *pRhs;
u32 joinType;
while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;}
if( k>=pTab->nCol ){
sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d",
pTab->zName, j);
return;
}
pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
if( pColRef==0 ) return;
pColRef->iTable = pItem->iCursor;
pColRef->iColumn = k++;
assert( ExprUseYTab(pColRef) );
pColRef->y.pTab = pTab;
pItem->colUsed |= sqlite3ExprColUsed(pColRef);
pRhs = sqlite3PExpr(pParse, TK_UPLUS,
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
if( pItem->fg.jointype & (JT_LEFT|JT_LTORJ) ){
joinType = EP_OuterON;
}else{
joinType = EP_InnerON;
}
sqlite3SetJoinExpr(pTerm, pItem->iCursor, joinType);
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
}
}
/************** End of whereexpr.c *******************************************/
/************** Begin file where.c *******************************************/
/*
|
| ︙ | ︙ | |||
152366 152367 152368 152369 152370 152371 152372 |
if( !pWInfo->bOrderedInnerLoop ){
/* The ORDER BY LIMIT optimization does not apply. Jump to the
** continuation of the inner-most loop. */
return pWInfo->iContinue;
}
pInner = &pWInfo->a[pWInfo->nLevel-1];
assert( pInner->addrNxt!=0 );
| | | 153995 153996 153997 153998 153999 154000 154001 154002 154003 154004 154005 154006 154007 154008 154009 |
if( !pWInfo->bOrderedInnerLoop ){
/* The ORDER BY LIMIT optimization does not apply. Jump to the
** continuation of the inner-most loop. */
return pWInfo->iContinue;
}
pInner = &pWInfo->a[pWInfo->nLevel-1];
assert( pInner->addrNxt!=0 );
return pInner->pRJ ? pWInfo->iContinue : pInner->addrNxt;
}
/*
** While generating code for the min/max optimization, after handling
** the aggregate-step call to min() or max(), check to see if any
** additional looping is required. If the output order is such that
** we are certain that the correct answer has already been found, then
|
| ︙ | ︙ | |||
152516 152517 152518 152519 152520 152521 152522 152523 152524 152525 152526 152527 152528 152529 |
for(i=1; i<pMaskSet->n; i++){
if( pMaskSet->ix[i]==iCursor ){
return MASKBIT(i);
}
}
return 0;
}
/*
** Create a new mask for cursor iCursor.
**
** There is one cursor per table in the FROM clause. The number of
** tables in the FROM clause is limited by a test early in the
** sqlite3WhereBegin() routine. So we know that the pMaskSet->ix[]
| > > > > > > > > > > > > > > > > > > > > > > > > | 154145 154146 154147 154148 154149 154150 154151 154152 154153 154154 154155 154156 154157 154158 154159 154160 154161 154162 154163 154164 154165 154166 154167 154168 154169 154170 154171 154172 154173 154174 154175 154176 154177 154178 154179 154180 154181 154182 |
for(i=1; i<pMaskSet->n; i++){
if( pMaskSet->ix[i]==iCursor ){
return MASKBIT(i);
}
}
return 0;
}
/* Allocate memory that is automatically freed when pWInfo is freed.
*/
SQLITE_PRIVATE void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte){
WhereMemBlock *pBlock;
pBlock = sqlite3DbMallocRawNN(pWInfo->pParse->db, nByte+sizeof(*pBlock));
if( pBlock ){
pBlock->pNext = pWInfo->pMemToFree;
pBlock->sz = nByte;
pWInfo->pMemToFree = pBlock;
pBlock++;
}
return (void*)pBlock;
}
SQLITE_PRIVATE void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte){
void *pNew = sqlite3WhereMalloc(pWInfo, nByte);
if( pNew && pOld ){
WhereMemBlock *pOldBlk = (WhereMemBlock*)pOld;
pOldBlk--;
assert( pOldBlk->sz<nByte );
memcpy(pNew, pOld, pOldBlk->sz);
}
return pNew;
}
/*
** Create a new mask for cursor iCursor.
**
** There is one cursor per table in the FROM clause. The number of
** tables in the FROM clause is limited by a test early in the
** sqlite3WhereBegin() routine. So we know that the pMaskSet->ix[]
|
| ︙ | ︙ | |||
152570 152571 152572 152573 152574 152575 152576 |
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 || pTerm->leftCursor<0 );
if( pTerm->leftCursor==iCur
&& pTerm->u.x.leftColumn==iColumn
&& (iColumn!=XN_EXPR
|| sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
pScan->pIdxExpr,iCur)==0)
| | | 154223 154224 154225 154226 154227 154228 154229 154230 154231 154232 154233 154234 154235 154236 154237 |
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 || pTerm->leftCursor<0 );
if( pTerm->leftCursor==iCur
&& pTerm->u.x.leftColumn==iColumn
&& (iColumn!=XN_EXPR
|| sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
pScan->pIdxExpr,iCur)==0)
&& (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_OuterON))
){
if( (pTerm->eOperator & WO_EQUIV)!=0
&& pScan->nEquiv<ArraySize(pScan->aiCur)
&& (pX = whereRightSubexprIsColumn(pTerm->pExpr))!=0
){
int j;
for(j=0; j<pScan->nEquiv; j++){
|
| ︙ | ︙ | |||
152922 152923 152924 152925 152926 152927 152928 152929 152930 152931 152932 152933 152934 152935 |
for(; iStart<iEnd; iStart++, pOp++){
if( pOp->p1!=iTabCur ) continue;
if( pOp->opcode==OP_Column ){
pOp->opcode = OP_Copy;
pOp->p1 = pOp->p2 + iRegister;
pOp->p2 = pOp->p3;
pOp->p3 = 0;
}else if( pOp->opcode==OP_Rowid ){
pOp->opcode = OP_Sequence;
pOp->p1 = iAutoidxCur;
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( iAutoidxCur==0 ){
pOp->opcode = OP_Null;
pOp->p3 = 0;
| > | 154575 154576 154577 154578 154579 154580 154581 154582 154583 154584 154585 154586 154587 154588 154589 |
for(; iStart<iEnd; iStart++, pOp++){
if( pOp->p1!=iTabCur ) continue;
if( pOp->opcode==OP_Column ){
pOp->opcode = OP_Copy;
pOp->p1 = pOp->p2 + iRegister;
pOp->p2 = pOp->p3;
pOp->p3 = 0;
pOp->p5 = 2; /* Cause the MEM_Subtype flag to be cleared */
}else if( pOp->opcode==OP_Rowid ){
pOp->opcode = OP_Sequence;
pOp->p1 = iAutoidxCur;
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( iAutoidxCur==0 ){
pOp->opcode = OP_Null;
pOp->p3 = 0;
|
| ︙ | ︙ | |||
152996 152997 152998 152999 153000 153001 153002 |
const WhereTerm *pTerm, /* WHERE clause term to check */
const SrcItem *pSrc, /* Table we are trying to access */
const Bitmask notReady /* Tables in outer loops of the join */
){
char aff;
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
| > | > > > > | | | < < < | > | 154650 154651 154652 154653 154654 154655 154656 154657 154658 154659 154660 154661 154662 154663 154664 154665 154666 154667 154668 154669 154670 154671 154672 154673 154674 |
const WhereTerm *pTerm, /* WHERE clause term to check */
const SrcItem *pSrc, /* Table we are trying to access */
const Bitmask notReady /* Tables in outer loops of the join */
){
char aff;
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
assert( (pSrc->fg.jointype & JT_RIGHT)==0 );
if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ){
testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT );
testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ );
testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) )
testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) );
if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON)
|| pTerm->pExpr->w.iJoin != pSrc->iCursor
){
return 0; /* See tag-20191211-001 */
}
}
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
if( pTerm->u.x.leftColumn<0 ) return 0;
aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
testcase( pTerm->pExpr->op==TK_IS );
|
| ︙ | ︙ | |||
153072 153073 153074 153075 153076 153077 153078 |
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr;
/* Make the automatic index a partial index if there are terms in the
** WHERE clause (or the ON clause of a LEFT join) that constrain which
** rows of the target table (pSrc) that can be used. */
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
| < | | 154729 154730 154731 154732 154733 154734 154735 154736 154737 154738 154739 154740 154741 154742 154743 |
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr;
/* Make the automatic index a partial index if there are terms in the
** WHERE clause (or the ON clause of a LEFT join) that constrain which
** rows of the target table (pSrc) that can be used. */
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& sqlite3ExprIsTableConstraint(pExpr, pSrc)
){
pPartial = sqlite3ExprAnd(pParse, pPartial,
sqlite3ExprDup(pParse->db, pExpr, 0));
}
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
int iCol;
Bitmask cMask;
|
| ︙ | ︙ | |||
153312 153313 153314 153315 153316 153317 153318 |
sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter);
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm];
for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr;
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
| | | 154968 154969 154970 154971 154972 154973 154974 154975 154976 154977 154978 154979 154980 154981 154982 |
sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter);
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm];
for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr;
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& sqlite3ExprIsTableConstraint(pExpr, pItem)
){
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
}
}
if( pLoop->wsFlags & WHERE_IPK ){
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1);
|
| ︙ | ︙ | |||
153345 153346 153347 153348 153349 153350 153351 |
sqlite3VdbeJumpHere(v, addrTop);
pLoop->wsFlags &= ~WHERE_BLOOMFILTER;
if( OptimizationDisabled(pParse->db, SQLITE_BloomPulldown) ) break;
while( ++iLevel < pWInfo->nLevel ){
const SrcItem *pTabItem;
pLevel = &pWInfo->a[iLevel];
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
| | | 155001 155002 155003 155004 155005 155006 155007 155008 155009 155010 155011 155012 155013 155014 155015 |
sqlite3VdbeJumpHere(v, addrTop);
pLoop->wsFlags &= ~WHERE_BLOOMFILTER;
if( OptimizationDisabled(pParse->db, SQLITE_BloomPulldown) ) break;
while( ++iLevel < pWInfo->nLevel ){
const SrcItem *pTabItem;
pLevel = &pWInfo->a[iLevel];
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ) ) continue;
pLoop = pLevel->pWLoop;
if( NEVER(pLoop==0) ) continue;
if( pLoop->prereq & notReady ) continue;
if( (pLoop->wsFlags & (WHERE_BLOOMFILTER|WHERE_COLUMN_IN))
==WHERE_BLOOMFILTER
){
/* This is a candidate for bloom-filter pull-down (early evaluation).
|
| ︙ | ︙ | |||
153418 153419 153420 153421 153422 153423 153424 |
if( pTerm->wtFlags & TERM_VNULL ) continue;
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
assert( pTerm->u.x.leftColumn>=XN_ROWID );
assert( pTerm->u.x.leftColumn<pTab->nCol );
/* tag-20191211-002: WHERE-clause constraints are not useful to the
| | > | > > > > > | > | | > | 155074 155075 155076 155077 155078 155079 155080 155081 155082 155083 155084 155085 155086 155087 155088 155089 155090 155091 155092 155093 155094 155095 155096 155097 155098 155099 155100 155101 |
if( pTerm->wtFlags & TERM_VNULL ) continue;
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
assert( pTerm->u.x.leftColumn>=XN_ROWID );
assert( pTerm->u.x.leftColumn<pTab->nCol );
/* tag-20191211-002: WHERE-clause constraints are not useful to the
** right-hand table of a LEFT JOIN nor to the either table of a
** RIGHT JOIN. See tag-20191211-001 for the
** equivalent restriction for ordinary tables. */
if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ){
testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT );
testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_RIGHT );
testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ );
testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) );
testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) );
if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON)
|| pTerm->pExpr->w.iJoin != pSrc->iCursor
){
continue;
}
}
nTerm++;
pTerm->wtFlags |= TERM_OK;
}
/* If the ORDER BY clause contains only columns in the current
** virtual table then allocate space for the aOrderBy part of
|
| ︙ | ︙ | |||
153446 153447 153448 153449 153450 153451 153452 |
/* Skip over constant terms in the ORDER BY clause */
if( sqlite3ExprIsConstant(pExpr) ){
continue;
}
/* Virtual tables are unable to deal with NULLS FIRST */
| | | 155110 155111 155112 155113 155114 155115 155116 155117 155118 155119 155120 155121 155122 155123 155124 |
/* Skip over constant terms in the ORDER BY clause */
if( sqlite3ExprIsConstant(pExpr) ){
continue;
}
/* Virtual tables are unable to deal with NULLS FIRST */
if( pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) break;
/* First case - a direct column references without a COLLATE operator */
if( pExpr->op==TK_COLUMN && pExpr->iTable==pSrc->iCursor ){
assert( pExpr->iColumn>=XN_ROWID && pExpr->iColumn<pTab->nCol );
continue;
}
|
| ︙ | ︙ | |||
153558 153559 153560 153561 153562 153563 153564 |
for(i=j=0; i<nOrderBy; i++){
Expr *pExpr = pOrderBy->a[i].pExpr;
if( sqlite3ExprIsConstant(pExpr) ) continue;
assert( pExpr->op==TK_COLUMN
|| (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN
&& pExpr->iColumn==pExpr->pLeft->iColumn) );
pIdxOrderBy[j].iColumn = pExpr->iColumn;
| | | 155222 155223 155224 155225 155226 155227 155228 155229 155230 155231 155232 155233 155234 155235 155236 |
for(i=j=0; i<nOrderBy; i++){
Expr *pExpr = pOrderBy->a[i].pExpr;
if( sqlite3ExprIsConstant(pExpr) ) continue;
assert( pExpr->op==TK_COLUMN
|| (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN
&& pExpr->iColumn==pExpr->pLeft->iColumn) );
pIdxOrderBy[j].iColumn = pExpr->iColumn;
pIdxOrderBy[j].desc = pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC;
j++;
}
pIdxInfo->nOrderBy = j;
*pmNoOmit = mNoOmit;
return pIdxInfo;
}
|
| ︙ | ︙ | |||
154299 154300 154301 154302 154303 154304 154305 |
sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm);
}else{
char zType[8];
char zLeft[50];
memcpy(zType, "....", 5);
if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
| | | 155963 155964 155965 155966 155967 155968 155969 155970 155971 155972 155973 155974 155975 155976 155977 |
sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm);
}else{
char zType[8];
char zLeft[50];
memcpy(zType, "....", 5);
if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
if( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) zType[2] = 'L';
if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C';
if( pTerm->eOperator & WO_SINGLE ){
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
pTerm->leftCursor, pTerm->u.x.leftColumn);
}else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){
sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%llx",
|
| ︙ | ︙ | |||
154480 154481 154482 154483 154484 154485 154486 |
sqlite3DbFreeNN(db, p);
}
/*
** Free a WhereInfo structure
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
| < < < < < < < < > > > > > | 156144 156145 156146 156147 156148 156149 156150 156151 156152 156153 156154 156155 156156 156157 156158 156159 156160 156161 156162 156163 156164 156165 156166 156167 156168 156169 156170 |
sqlite3DbFreeNN(db, p);
}
/*
** Free a WhereInfo structure
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
assert( pWInfo!=0 );
sqlite3WhereClauseClear(&pWInfo->sWC);
while( pWInfo->pLoops ){
WhereLoop *p = pWInfo->pLoops;
pWInfo->pLoops = p->pNextLoop;
whereLoopDelete(db, p);
}
assert( pWInfo->pExprMods==0 );
while( pWInfo->pMemToFree ){
WhereMemBlock *pNext = pWInfo->pMemToFree->pNext;
sqlite3DbFreeNN(db, pWInfo->pMemToFree);
pWInfo->pMemToFree = pNext;
}
sqlite3DbFreeNN(db, pWInfo);
}
/* Undo all Expr node modifications
*/
static void whereUndoExprMods(WhereInfo *pWInfo){
while( pWInfo->pExprMods ){
|
| ︙ | ︙ | |||
154860 154861 154862 154863 154864 154865 154866 |
if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
}
if( j<0 ){
if( pLoop->maskSelf==pTerm->prereqAll ){
/* If there are extra terms in the WHERE clause not used by an index
** that depend only on the table being scanned, and that will tend to
** cause many rows to be omitted, then mark that table as
| | > > > > > > > > > | > | 156521 156522 156523 156524 156525 156526 156527 156528 156529 156530 156531 156532 156533 156534 156535 156536 156537 156538 156539 156540 156541 156542 156543 156544 156545 156546 |
if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
}
if( j<0 ){
if( pLoop->maskSelf==pTerm->prereqAll ){
/* If there are extra terms in the WHERE clause not used by an index
** that depend only on the table being scanned, and that will tend to
** cause many rows to be omitted, then mark that table as
** "self-culling".
**
** 2022-03-24: Self-culling only applies if either the extra terms
** are straight comparison operators that are non-true with NULL
** operand, or if the loop is not an OUTER JOIN.
*/
if( (pTerm->eOperator & 0x3f)!=0
|| (pWC->pWInfo->pTabList->a[pLoop->iTab].fg.jointype
& (JT_LEFT|JT_LTORJ))==0
){
pLoop->wsFlags |= WHERE_SELFCULL;
}
}
if( pTerm->truthProb<=0 ){
/* If a truth probability is specified using the likelihood() hints,
** then use the probability provided by the application. */
pLoop->nOut += pTerm->truthProb;
}else{
/* In the absence of explicit truth probabilities, use heuristics to
|
| ︙ | ︙ | |||
155065 155066 155067 155068 155069 155070 155071 |
if( pTerm->prereqRight & pNew->maskSelf ) continue;
/* Do not allow the upper bound of a LIKE optimization range constraint
** to mix with a lower range bound from some other source */
if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;
/* tag-20191211-001: Do not allow constraints from the WHERE clause to
| | > | > > > > > > > > > | > > > > > | > | | > | 156736 156737 156738 156739 156740 156741 156742 156743 156744 156745 156746 156747 156748 156749 156750 156751 156752 156753 156754 156755 156756 156757 156758 156759 156760 156761 156762 156763 156764 156765 156766 156767 156768 156769 156770 156771 156772 |
if( pTerm->prereqRight & pNew->maskSelf ) continue;
/* Do not allow the upper bound of a LIKE optimization range constraint
** to mix with a lower range bound from some other source */
if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;
/* tag-20191211-001: Do not allow constraints from the WHERE clause to
** be used by the right table of a LEFT JOIN nor by the left table of a
** RIGHT JOIN. Only constraints in the ON clause are allowed.
** See tag-20191211-002 for the vtab equivalent.
**
** 2022-06-06: See https://sqlite.org/forum/forumpost/206d99a16dd9212f
** for an example of a WHERE clause constraints that may not be used on
** the right table of a RIGHT JOIN because the constraint implies a
** not-NULL condition on the left table of the RIGHT JOIN.
**
** 2022-06-10: The same condition applies to termCanDriveIndex() above.
** https://sqlite.org/forum/forumpost/51e6959f61
*/
if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ){
testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT );
testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_RIGHT );
testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ );
testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) )
testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) );
if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON)
|| pTerm->pExpr->w.iJoin != pSrc->iCursor
){
continue;
}
}
if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){
pBuilder->bldFlags1 |= SQLITE_BLDF1_UNIQUE;
}else{
pBuilder->bldFlags1 |= SQLITE_BLDF1_INDEXED;
}
|
| ︙ | ︙ | |||
155422 155423 155424 155425 155426 155427 155428 | } /* Check to see if a partial index with pPartIndexWhere can be used ** in the current query. Return true if it can be and false if not. */ static int whereUsablePartialIndex( int iTab, /* The table for which we want an index */ | | > > > | | | | | 157110 157111 157112 157113 157114 157115 157116 157117 157118 157119 157120 157121 157122 157123 157124 157125 157126 157127 157128 157129 157130 157131 157132 157133 157134 157135 157136 157137 157138 157139 157140 157141 157142 157143 |
}
/* Check to see if a partial index with pPartIndexWhere can be used
** in the current query. Return true if it can be and false if not.
*/
static int whereUsablePartialIndex(
int iTab, /* The table for which we want an index */
u8 jointype, /* The JT_* flags on the join */
WhereClause *pWC, /* The WHERE clause of the query */
Expr *pWhere /* The WHERE clause from the partial index */
){
int i;
WhereTerm *pTerm;
Parse *pParse;
if( jointype & JT_LTORJ ) return 0;
pParse = pWC->pWInfo->pParse;
while( pWhere->op==TK_AND ){
if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0;
pWhere = pWhere->pRight;
}
if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
Expr *pExpr;
pExpr = pTerm->pExpr;
if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
&& ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
&& (pTerm->wtFlags & TERM_VNULL)==0
){
return 1;
}
}
return 0;
|
| ︙ | ︙ | |||
155547 155548 155549 155550 155551 155552 155553 |
pProbe = &sPk;
}
rSize = pTab->nRowLogEst;
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/* Automatic indexes */
if( !pBuilder->pOrSet /* Not part of an OR optimization */
| | > | 157238 157239 157240 157241 157242 157243 157244 157245 157246 157247 157248 157249 157250 157251 157252 157253 157254 157255 157256 157257 157258 157259 |
pProbe = &sPk;
}
rSize = pTab->nRowLogEst;
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/* Automatic indexes */
if( !pBuilder->pOrSet /* Not part of an OR optimization */
&& (pWInfo->wctrlFlags & (WHERE_RIGHT_JOIN|WHERE_OR_SUBCLAUSE))==0
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
&& !pSrc->fg.isIndexedBy /* Has no INDEXED BY clause */
&& !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */
&& HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */
&& !pSrc->fg.isCorrelated /* Not a correlated subquery */
&& !pSrc->fg.isRecursive /* Not a recursive common table expression. */
&& (pSrc->fg.jointype & JT_RIGHT)==0 /* Not the right tab of a RIGHT JOIN */
){
/* Generate auto-index WhereLoops */
LogEst rLogSize; /* Logarithm of the number of rows in the table */
WhereTerm *pTerm;
WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
rLogSize = estLog(rSize);
for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
|
| ︙ | ︙ | |||
155603 155604 155605 155606 155607 155608 155609 |
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
/* Loop over all indices. If there was an INDEXED BY clause, then only
** consider index pProbe. */
for(; rc==SQLITE_OK && pProbe;
pProbe=(pSrc->fg.isIndexedBy ? 0 : pProbe->pNext), iSortIdx++
){
| < | | 157295 157296 157297 157298 157299 157300 157301 157302 157303 157304 157305 157306 157307 157308 157309 157310 |
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
/* Loop over all indices. If there was an INDEXED BY clause, then only
** consider index pProbe. */
for(; rc==SQLITE_OK && pProbe;
pProbe=(pSrc->fg.isIndexedBy ? 0 : pProbe->pNext), iSortIdx++
){
if( pProbe->pPartIdxWhere!=0
&& !whereUsablePartialIndex(pSrc->iCursor, pSrc->fg.jointype, pWC,
pProbe->pPartIdxWhere)
){
testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */
continue; /* Partial index inappropriate for this query */
}
if( pProbe->bNoQuery ) continue;
rSize = pProbe->aiRowLogEst[0];
|
| ︙ | ︙ | |||
155713 155714 155715 155716 155717 155718 155719 |
}
}
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup);
}
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew, rSize);
| > > > > > > | > | 157404 157405 157406 157407 157408 157409 157410 157411 157412 157413 157414 157415 157416 157417 157418 157419 157420 157421 157422 157423 157424 157425 |
}
}
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup);
}
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew, rSize);
if( (pSrc->fg.jointype & JT_RIGHT)!=0 && pProbe->aColExpr ){
/* Do not do an SCAN of a index-on-expression in a RIGHT JOIN
** because the cursor used to access the index might not be
** positioned to the correct row during the right-join no-match
** loop. */
}else{
rc = whereLoopInsert(pBuilder, pNew);
}
pNew->nOut = rSize;
if( rc ) break;
}
}
pBuilder->bldFlags1 = 0;
rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
|
| ︙ | ︙ | |||
155888 155889 155890 155891 155892 155893 155894 155895 155896 155897 155898 155899 155900 155901 |
** (2) Multiple outputs from a single IN value will not merge
** together. */
pIdxInfo->orderByConsumed = 0;
pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
*pbIn = 1; assert( (mExclude & WO_IN)==0 );
}
if( isLimitTerm(pTerm) && *pbIn ){
/* If there is an IN(...) term handled as an == (separate call to
** xFilter for each value on the RHS of the IN) and a LIMIT or
** OFFSET term handled as well, the plan is unusable. Set output
** variable *pbRetryLimit to true to tell the caller to retry with
** LIMIT and OFFSET disabled. */
if( pIdxInfo->needToFreeIdxStr ){
| > | 157586 157587 157588 157589 157590 157591 157592 157593 157594 157595 157596 157597 157598 157599 157600 |
** (2) Multiple outputs from a single IN value will not merge
** together. */
pIdxInfo->orderByConsumed = 0;
pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
*pbIn = 1; assert( (mExclude & WO_IN)==0 );
}
assert( pbRetryLimit || !isLimitTerm(pTerm) );
if( isLimitTerm(pTerm) && *pbIn ){
/* If there is an IN(...) term handled as an == (separate call to
** xFilter for each value on the RHS of the IN) and a LIMIT or
** OFFSET term handled as well, the plan is unusable. Set output
** variable *pbRetryLimit to true to tell the caller to retry with
** LIMIT and OFFSET disabled. */
if( pIdxInfo->needToFreeIdxStr ){
|
| ︙ | ︙ | |||
156043 156044 156045 156046 156047 156048 156049 |
return pHidden->eDistinct;
}
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
/*
** Cause the prepared statement that is associated with a call to
| | > > > > | > > > > > | > > | 157742 157743 157744 157745 157746 157747 157748 157749 157750 157751 157752 157753 157754 157755 157756 157757 157758 157759 157760 157761 157762 157763 157764 157765 157766 157767 157768 157769 157770 157771 157772 157773 157774 157775 |
return pHidden->eDistinct;
}
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
/*
** Cause the prepared statement that is associated with a call to
** xBestIndex to potentiall use all schemas. If the statement being
** prepared is read-only, then just start read transactions on all
** schemas. But if this is a write operation, start writes on all
** schemas.
**
** This is used by the (built-in) sqlite_dbpage virtual table.
*/
SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(sqlite3_index_info *pIdxInfo){
HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
Parse *pParse = pHidden->pParse;
int nDb = pParse->db->nDb;
int i;
for(i=0; i<nDb; i++){
sqlite3CodeVerifySchema(pParse, i);
}
if( pParse->writeMask ){
for(i=0; i<nDb; i++){
sqlite3BeginWriteOperation(pParse, 0, i);
}
}
}
#endif
/*
** Add all WhereLoop objects for a table of the join identified by
** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table.
**
|
| ︙ | ︙ | |||
156233 156234 156235 156236 156237 156238 156239 156240 156241 156242 156243 156244 156245 156246 |
pWC = pBuilder->pWC;
pWCEnd = pWC->a + pWC->nTerm;
pNew = pBuilder->pNew;
memset(&sSum, 0, sizeof(sSum));
pItem = pWInfo->pTabList->a + pNew->iTab;
iCur = pItem->iCursor;
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
if( (pTerm->eOperator & WO_OR)!=0
&& (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
){
WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
| > > > | 157943 157944 157945 157946 157947 157948 157949 157950 157951 157952 157953 157954 157955 157956 157957 157958 157959 |
pWC = pBuilder->pWC;
pWCEnd = pWC->a + pWC->nTerm;
pNew = pBuilder->pNew;
memset(&sSum, 0, sizeof(sSum));
pItem = pWInfo->pTabList->a + pNew->iTab;
iCur = pItem->iCursor;
/* The multi-index OR optimization does not work for RIGHT and FULL JOIN */
if( pItem->fg.jointype & JT_RIGHT ) return SQLITE_OK;
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
if( (pTerm->eOperator & WO_OR)!=0
&& (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
){
WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
|
| ︙ | ︙ | |||
156347 156348 156349 156350 156351 156352 156353 156354 156355 156356 156357 156358 156359 156360 156361 156362 156363 156364 |
Bitmask mPrior = 0;
int iTab;
SrcList *pTabList = pWInfo->pTabList;
SrcItem *pItem;
SrcItem *pEnd = &pTabList->a[pWInfo->nLevel];
sqlite3 *db = pWInfo->pParse->db;
int rc = SQLITE_OK;
WhereLoop *pNew;
/* Loop over the tables in the join, from left to right */
pNew = pBuilder->pNew;
whereLoopInit(pNew);
pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT;
for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){
Bitmask mUnusable = 0;
pNew->iTab = iTab;
pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR;
pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor);
| > > | | | | | | > | | 158060 158061 158062 158063 158064 158065 158066 158067 158068 158069 158070 158071 158072 158073 158074 158075 158076 158077 158078 158079 158080 158081 158082 158083 158084 158085 158086 158087 158088 158089 158090 158091 158092 158093 158094 158095 158096 158097 158098 158099 |
Bitmask mPrior = 0;
int iTab;
SrcList *pTabList = pWInfo->pTabList;
SrcItem *pItem;
SrcItem *pEnd = &pTabList->a[pWInfo->nLevel];
sqlite3 *db = pWInfo->pParse->db;
int rc = SQLITE_OK;
int bFirstPastRJ = 0;
WhereLoop *pNew;
/* Loop over the tables in the join, from left to right */
pNew = pBuilder->pNew;
whereLoopInit(pNew);
pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT;
for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){
Bitmask mUnusable = 0;
pNew->iTab = iTab;
pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR;
pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor);
if( bFirstPastRJ || (pItem->fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){
/* Add prerequisites to prevent reordering of FROM clause terms
** across CROSS joins and outer joins. The bFirstPastRJ boolean
** prevents the right operand of a RIGHT JOIN from being swapped with
** other elements even further to the right. */
mPrereq |= mPrior;
bFirstPastRJ = (pItem->fg.jointype & JT_RIGHT)!=0;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pItem->pTab) ){
SrcItem *p;
for(p=&pItem[1]; p<pEnd; p++){
if( mUnusable || (p->fg.jointype & (JT_OUTER|JT_CROSS)) ){
mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor);
}
}
rc = whereLoopAddVirtual(pBuilder, mPrereq, mUnusable);
}else
#endif /* SQLITE_OMIT_VIRTUALTABLE */
{
|
| ︙ | ︙ | |||
156674 156675 156676 156677 156678 156679 156680 |
isMatch = 1;
break;
}
if( isMatch && (wctrlFlags & WHERE_GROUPBY)==0 ){
/* Make sure the sort order is compatible in an ORDER BY clause.
** Sort order is irrelevant for a GROUP BY clause. */
if( revSet ){
| | > > | | | 158390 158391 158392 158393 158394 158395 158396 158397 158398 158399 158400 158401 158402 158403 158404 158405 158406 158407 158408 158409 158410 158411 158412 158413 158414 158415 |
isMatch = 1;
break;
}
if( isMatch && (wctrlFlags & WHERE_GROUPBY)==0 ){
/* Make sure the sort order is compatible in an ORDER BY clause.
** Sort order is irrelevant for a GROUP BY clause. */
if( revSet ){
if( (rev ^ revIdx)
!= (pOrderBy->a[i].fg.sortFlags&KEYINFO_ORDER_DESC)
){
isMatch = 0;
}
}else{
rev = revIdx ^ (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC);
if( rev ) *pRevMask |= MASKBIT(iLoop);
revSet = 1;
}
}
if( isMatch && (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL) ){
if( j==pLoop->u.btree.nEq ){
pLoop->wsFlags |= WHERE_BIGNULL_SORT;
}else{
isMatch = 0;
}
}
if( isMatch ){
|
| ︙ | ︙ | |||
157431 157432 157433 157434 157435 157436 157437 |
){
continue;
}
if( (tabUsed & pLoop->maskSelf)!=0 ) continue;
pEnd = pWInfo->sWC.a + pWInfo->sWC.nTerm;
for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
| | | | 159149 159150 159151 159152 159153 159154 159155 159156 159157 159158 159159 159160 159161 159162 159163 159164 |
){
continue;
}
if( (tabUsed & pLoop->maskSelf)!=0 ) continue;
pEnd = pWInfo->sWC.a + pWInfo->sWC.nTerm;
for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
if( !ExprHasProperty(pTerm->pExpr, EP_OuterON)
|| pTerm->pExpr->w.iJoin!=pItem->iCursor
){
break;
}
}
}
if( pTerm<pEnd ) continue;
WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
|
| ︙ | ︙ | |||
157663 157664 157665 157666 157667 157668 157669 | /* Allocate and initialize the WhereInfo structure that will become the ** return value. A single allocation is used to store the WhereInfo ** struct, the contents of WhereInfo.a[], the WhereClause structure ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte ** field (type Bitmask) it must be aligned on an 8-byte boundary on ** some architectures. Hence the ROUND8() below. */ | | | 159381 159382 159383 159384 159385 159386 159387 159388 159389 159390 159391 159392 159393 159394 159395 |
/* Allocate and initialize the WhereInfo structure that will become the
** return value. A single allocation is used to store the WhereInfo
** struct, the contents of WhereInfo.a[], the WhereClause structure
** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
** field (type Bitmask) it must be aligned on an 8-byte boundary on
** some architectures. Hence the ROUND8() below.
*/
nByteWInfo = ROUND8P(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
if( db->mallocFailed ){
sqlite3DbFree(db, pWInfo);
pWInfo = 0;
goto whereBeginError;
}
pWInfo->pParse = pParse;
|
| ︙ | ︙ | |||
157985 157986 157987 157988 157989 157990 157991 |
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
int iCur = pTabItem->iCursor;
sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
}else if( IsVirtual(pTab) ){
/* noop */
}else
#endif
| | | > > | 159703 159704 159705 159706 159707 159708 159709 159710 159711 159712 159713 159714 159715 159716 159717 159718 159719 159720 |
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
int iCur = pTabItem->iCursor;
sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
}else if( IsVirtual(pTab) ){
/* noop */
}else
#endif
if( ((pLoop->wsFlags & WHERE_IDX_ONLY)==0
&& (wctrlFlags & WHERE_OR_SUBCLAUSE)==0)
|| (pTabItem->fg.jointype & (JT_LTORJ|JT_RIGHT))!=0
){
int op = OP_OpenRead;
if( pWInfo->eOnePass!=ONEPASS_OFF ){
op = OP_OpenWrite;
pWInfo->aiCurOnePass[0] = pTabItem->iCursor;
};
sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
assert( pTabItem->iCursor==pLevel->iTabCur );
|
| ︙ | ︙ | |||
158055 158056 158057 158058 158059 158060 158061 158062 158063 158064 158065 158066 158067 158068 |
}else if( iAuxArg && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ){
iIndexCur = iAuxArg;
op = OP_ReopenIdx;
}else{
iIndexCur = pParse->nTab++;
}
pLevel->iIdxCur = iIndexCur;
assert( pIx->pSchema==pTab->pSchema );
assert( iIndexCur>=0 );
if( op ){
sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
&& (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
| > | 159775 159776 159777 159778 159779 159780 159781 159782 159783 159784 159785 159786 159787 159788 159789 |
}else if( iAuxArg && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ){
iIndexCur = iAuxArg;
op = OP_ReopenIdx;
}else{
iIndexCur = pParse->nTab++;
}
pLevel->iIdxCur = iIndexCur;
assert( pIx!=0 );
assert( pIx->pSchema==pTab->pSchema );
assert( iIndexCur>=0 );
if( op ){
sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
&& (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
|
| ︙ | ︙ | |||
158088 158089 158090 158091 158092 158093 158094 158095 158096 158097 158098 158099 158100 158101 158102 158103 158104 158105 158106 158107 158108 158109 158110 158111 158112 158113 158114 158115 |
sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, iIndexCur, 0, 0,
(u8*)&colUsed, P4_INT64);
}
#endif /* SQLITE_ENABLE_COLUMN_USED_MASK */
}
}
if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb);
}
pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
if( db->mallocFailed ) goto whereBeginError;
/* Generate the code to do the search. Each iteration of the for
** loop below generates code for a single nested loop of the VM
** program.
*/
for(ii=0; ii<nTabList; ii++){
int addrExplain;
int wsFlags;
if( pParse->nErr ) goto whereBeginError;
pLevel = &pWInfo->a[ii];
wsFlags = pLevel->pWLoop->wsFlags;
if( (wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))!=0 ){
if( (wsFlags & WHERE_AUTO_INDEX)!=0 ){
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
constructAutomaticIndex(pParse, &pWInfo->sWC,
&pTabList->a[pLevel->iFrom], notReady, pLevel);
#endif
}else{
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 159809 159810 159811 159812 159813 159814 159815 159816 159817 159818 159819 159820 159821 159822 159823 159824 159825 159826 159827 159828 159829 159830 159831 159832 159833 159834 159835 159836 159837 159838 159839 159840 159841 159842 159843 159844 159845 159846 159847 159848 159849 159850 159851 159852 159853 159854 159855 159856 159857 159858 159859 159860 159861 159862 159863 159864 159865 159866 159867 159868 159869 159870 159871 159872 159873 159874 159875 159876 159877 159878 |
sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, iIndexCur, 0, 0,
(u8*)&colUsed, P4_INT64);
}
#endif /* SQLITE_ENABLE_COLUMN_USED_MASK */
}
}
if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb);
if( (pTabItem->fg.jointype & JT_RIGHT)!=0
&& (pLevel->pRJ = sqlite3WhereMalloc(pWInfo, sizeof(WhereRightJoin)))!=0
){
WhereRightJoin *pRJ = pLevel->pRJ;
pRJ->iMatch = pParse->nTab++;
pRJ->regBloom = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom);
pRJ->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, pRJ->regReturn);
assert( pTab==pTabItem->pTab );
if( HasRowid(pTab) ){
KeyInfo *pInfo;
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, 1);
pInfo = sqlite3KeyInfoAlloc(pParse->db, 1, 0);
if( pInfo ){
pInfo->aColl[0] = 0;
pInfo->aSortFlags[0] = 0;
sqlite3VdbeAppendP4(v, pInfo, P4_KEYINFO);
}
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, pPk->nKeyCol);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
}
pLoop->wsFlags &= ~WHERE_IDX_ONLY;
/* The nature of RIGHT JOIN processing is such that it messes up
** the output order. So omit any ORDER BY/GROUP BY elimination
** optimizations. We need to do an actual sort for RIGHT JOIN. */
pWInfo->nOBSat = 0;
pWInfo->eDistinct = WHERE_DISTINCT_UNORDERED;
}
}
pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
if( db->mallocFailed ) goto whereBeginError;
/* Generate the code to do the search. Each iteration of the for
** loop below generates code for a single nested loop of the VM
** program.
*/
for(ii=0; ii<nTabList; ii++){
int addrExplain;
int wsFlags;
SrcItem *pSrc;
if( pParse->nErr ) goto whereBeginError;
pLevel = &pWInfo->a[ii];
wsFlags = pLevel->pWLoop->wsFlags;
pSrc = &pTabList->a[pLevel->iFrom];
if( pSrc->fg.isMaterialized ){
if( pSrc->fg.isCorrelated ){
sqlite3VdbeAddOp2(v, OP_Gosub, pSrc->regReturn, pSrc->addrFillSub);
}else{
int iOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Gosub, pSrc->regReturn, pSrc->addrFillSub);
sqlite3VdbeJumpHere(v, iOnce);
}
}
if( (wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))!=0 ){
if( (wsFlags & WHERE_AUTO_INDEX)!=0 ){
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
constructAutomaticIndex(pParse, &pWInfo->sWC,
&pTabList->a[pLevel->iFrom], notReady, pLevel);
#endif
}else{
|
| ︙ | ︙ | |||
158193 158194 158195 158196 158197 158198 158199 158200 158201 158202 158203 158204 158205 158206 158207 158208 158209 158210 158211 158212 158213 |
Vdbe *v = pParse->pVdbe;
int i;
WhereLevel *pLevel;
WhereLoop *pLoop;
SrcList *pTabList = pWInfo->pTabList;
sqlite3 *db = pParse->db;
int iEnd = sqlite3VdbeCurrentAddr(v);
/* Generate loop termination code.
*/
VdbeModuleComment((v, "End WHERE-core"));
for(i=pWInfo->nLevel-1; i>=0; i--){
int addr;
pLevel = &pWInfo->a[i];
pLoop = pLevel->pWLoop;
if( pLevel->op!=OP_Noop ){
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
int addrSeek = 0;
Index *pIdx;
int n;
if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
| > > > > > > > > > > > > | 159956 159957 159958 159959 159960 159961 159962 159963 159964 159965 159966 159967 159968 159969 159970 159971 159972 159973 159974 159975 159976 159977 159978 159979 159980 159981 159982 159983 159984 159985 159986 159987 159988 |
Vdbe *v = pParse->pVdbe;
int i;
WhereLevel *pLevel;
WhereLoop *pLoop;
SrcList *pTabList = pWInfo->pTabList;
sqlite3 *db = pParse->db;
int iEnd = sqlite3VdbeCurrentAddr(v);
int nRJ = 0;
/* Generate loop termination code.
*/
VdbeModuleComment((v, "End WHERE-core"));
for(i=pWInfo->nLevel-1; i>=0; i--){
int addr;
pLevel = &pWInfo->a[i];
if( pLevel->pRJ ){
/* Terminate the subroutine that forms the interior of the loop of
** the RIGHT JOIN table */
WhereRightJoin *pRJ = pLevel->pRJ;
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
pLevel->addrCont = 0;
pRJ->endSubrtn = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_Return, pRJ->regReturn, pRJ->addrSubrtn, 1);
VdbeCoverage(v);
nRJ++;
}
pLoop = pLevel->pWLoop;
if( pLevel->op!=OP_Noop ){
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
int addrSeek = 0;
Index *pIdx;
int n;
if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
|
| ︙ | ︙ | |||
158227 158228 158229 158230 158231 158232 158233 |
addrSeek = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n);
VdbeCoverageIf(v, op==OP_SeekLT);
VdbeCoverageIf(v, op==OP_SeekGT);
sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
}
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
/* The common case: Advance to the next row */
| | | | 160002 160003 160004 160005 160006 160007 160008 160009 160010 160011 160012 160013 160014 160015 160016 160017 160018 160019 160020 160021 160022 160023 160024 160025 160026 160027 160028 160029 160030 160031 |
addrSeek = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n);
VdbeCoverageIf(v, op==OP_SeekLT);
VdbeCoverageIf(v, op==OP_SeekGT);
sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
}
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
/* The common case: Advance to the next row */
if( pLevel->addrCont ) sqlite3VdbeResolveLabel(v, pLevel->addrCont);
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
sqlite3VdbeChangeP5(v, pLevel->p5);
VdbeCoverage(v);
VdbeCoverageIf(v, pLevel->op==OP_Next);
VdbeCoverageIf(v, pLevel->op==OP_Prev);
VdbeCoverageIf(v, pLevel->op==OP_VNext);
if( pLevel->regBignull ){
sqlite3VdbeResolveLabel(v, pLevel->addrBignull);
sqlite3VdbeAddOp2(v, OP_DecrJumpZero, pLevel->regBignull, pLevel->p2-1);
VdbeCoverage(v);
}
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek);
#endif
}else if( pLevel->addrCont ){
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
}
if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){
struct InLoop *pIn;
int j;
sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
|
| ︙ | ︙ | |||
158292 158293 158294 158295 158296 158297 158298 158299 158300 158301 158302 158303 158304 158305 |
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev);
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next);
}
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
}
}
sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
if( pLevel->addrSkip ){
sqlite3VdbeGoto(v, pLevel->addrSkip);
VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName));
sqlite3VdbeJumpHere(v, pLevel->addrSkip);
sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
}
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
| > > > > | 160067 160068 160069 160070 160071 160072 160073 160074 160075 160076 160077 160078 160079 160080 160081 160082 160083 160084 |
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev);
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next);
}
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
}
}
sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
if( pLevel->pRJ ){
sqlite3VdbeAddOp3(v, OP_Return, pLevel->pRJ->regReturn, 0, 1);
VdbeCoverage(v);
}
if( pLevel->addrSkip ){
sqlite3VdbeGoto(v, pLevel->addrSkip);
VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName));
sqlite3VdbeJumpHere(v, pLevel->addrSkip);
sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
}
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
| ︙ | ︙ | |||
158335 158336 158337 158338 158339 158340 158341 |
}
sqlite3VdbeJumpHere(v, addr);
}
VdbeModuleComment((v, "End WHERE-loop%d: %s", i,
pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
}
| < < < < < > > > > > > > > > > < < < < < < < < < < < < < < < < < < < < < < < | 160114 160115 160116 160117 160118 160119 160120 160121 160122 160123 160124 160125 160126 160127 160128 160129 160130 160131 160132 160133 160134 160135 160136 160137 160138 160139 160140 160141 160142 160143 160144 160145 160146 160147 160148 160149 160150 160151 160152 160153 160154 160155 160156 160157 160158 |
}
sqlite3VdbeJumpHere(v, addr);
}
VdbeModuleComment((v, "End WHERE-loop%d: %s", i,
pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
}
assert( pWInfo->nLevel<=pTabList->nSrc );
if( pWInfo->pExprMods ) whereUndoExprMods(pWInfo);
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
int k, last;
VdbeOp *pOp, *pLastOp;
Index *pIdx = 0;
SrcItem *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
pLoop = pLevel->pWLoop;
/* Do RIGHT JOIN processing. Generate code that will output the
** unmatched rows of the right operand of the RIGHT JOIN with
** all of the columns of the left operand set to NULL.
*/
if( pLevel->pRJ ){
sqlite3WhereRightJoinLoop(pWInfo, i, pLevel);
continue;
}
/* For a co-routine, change all OP_Column references to the table of
** the co-routine into OP_Copy of result contained in a register.
** OP_Rowid becomes OP_Null.
*/
if( pTabItem->fg.viaCoroutine ){
testcase( pParse->db->mallocFailed );
translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur,
pTabItem->regResult, 0);
continue;
}
/* If this scan uses an index, make VDBE code substitutions to read data
** from the index instead of from the table where possible. In some cases
** this optimization prevents the table from ever being read, which can
** yield a significant performance boost.
**
** Calls to the code generator in between sqlite3WhereBegin and
** sqlite3WhereEnd will have created code that references the table
|
| ︙ | ︙ | |||
158484 158485 158486 158487 158488 158489 158490 158491 158492 |
}while( (++pOp)<pLastOp );
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n");
#endif
}
}
/* Final cleanup
*/
| > > > > > < > | 160245 160246 160247 160248 160249 160250 160251 160252 160253 160254 160255 160256 160257 160258 160259 160260 160261 160262 160263 160264 160265 160266 160267 160268 |
}while( (++pOp)<pLastOp );
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n");
#endif
}
}
/* The "break" point is here, just past the end of the outer loop.
** Set it.
*/
sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
/* Final cleanup
*/
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
pParse->withinRJSubrtn -= nRJ;
return;
}
/************** End of where.c ***********************************************/
/************** Begin file window.c ******************************************/
/*
** 2018 May 08
|
| ︙ | ︙ | |||
159412 159413 159414 159415 159416 159417 159418 |
if( sqlite3ExprIsInteger(pSub, &iDummy) ){
pSub->op = TK_NULL;
pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
pSub->u.zToken = 0;
}
}
pList = sqlite3ExprListAppend(pParse, pList, pDup);
| | | 161178 161179 161180 161181 161182 161183 161184 161185 161186 161187 161188 161189 161190 161191 161192 |
if( sqlite3ExprIsInteger(pSub, &iDummy) ){
pSub->op = TK_NULL;
pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
pSub->u.zToken = 0;
}
}
pList = sqlite3ExprListAppend(pParse, pList, pDup);
if( pList ) pList->a[nInit+i].fg.sortFlags = pAppend->a[i].fg.sortFlags;
}
}
return pList;
}
/*
** When rewriting a query, if the new subquery in the FROM clause
|
| ︙ | ︙ | |||
160225 160226 160227 160228 160229 160230 160231 |
assert( ExprUseXList(pWin->pOwner) );
nArg = pWin->pOwner->x.pList->nExpr;
regArg = sqlite3GetTempRange(pParse, nArg);
sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);
for(iEnd=sqlite3VdbeCurrentAddr(v); iOp<iEnd; iOp++){
VdbeOp *pOp = sqlite3VdbeGetOp(v, iOp);
| | | 161991 161992 161993 161994 161995 161996 161997 161998 161999 162000 162001 162002 162003 162004 162005 |
assert( ExprUseXList(pWin->pOwner) );
nArg = pWin->pOwner->x.pList->nExpr;
regArg = sqlite3GetTempRange(pParse, nArg);
sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);
for(iEnd=sqlite3VdbeCurrentAddr(v); iOp<iEnd; iOp++){
VdbeOp *pOp = sqlite3VdbeGetOp(v, iOp);
if( pOp->opcode==OP_Column && pOp->p1==pMWin->iEphCsr ){
pOp->p1 = csr;
}
}
}
if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
CollSeq *pColl;
assert( nArg>0 );
|
| ︙ | ︙ | |||
160613 160614 160615 160616 160617 160618 160619 | /* Read the peer-value from each cursor into a register */ windowReadPeerValues(p, csr1, reg1); windowReadPeerValues(p, csr2, reg2); assert( op==OP_Ge || op==OP_Gt || op==OP_Le ); assert( pOrderBy && pOrderBy->nExpr==1 ); | | | 162379 162380 162381 162382 162383 162384 162385 162386 162387 162388 162389 162390 162391 162392 162393 |
/* Read the peer-value from each cursor into a register */
windowReadPeerValues(p, csr1, reg1);
windowReadPeerValues(p, csr2, reg2);
assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
assert( pOrderBy && pOrderBy->nExpr==1 );
if( pOrderBy->a[0].fg.sortFlags & KEYINFO_ORDER_DESC ){
switch( op ){
case OP_Ge: op = OP_Le; break;
case OP_Gt: op = OP_Lt; break;
default: assert( op==OP_Le ); op = OP_Ge; break;
}
arith = OP_Subtract;
}
|
| ︙ | ︙ | |||
160646 160647 160648 160649 160650 160651 160652 |
** }else if( reg2 IS NULL ){
** if( op==OP_Le ) goto lbl;
** }
**
** Additionally, if either reg1 or reg2 are NULL but the jump to lbl is
** not taken, control jumps over the comparison operator coded below this
** block. */
| | | 162412 162413 162414 162415 162416 162417 162418 162419 162420 162421 162422 162423 162424 162425 162426 |
** }else if( reg2 IS NULL ){
** if( op==OP_Le ) goto lbl;
** }
**
** Additionally, if either reg1 or reg2 are NULL but the jump to lbl is
** not taken, control jumps over the comparison operator coded below this
** block. */
if( pOrderBy->a[0].fg.sortFlags & KEYINFO_ORDER_BIGNULL ){
/* This block runs if reg1 contains a NULL. */
int addr = sqlite3VdbeAddOp1(v, OP_NotNull, reg1); VdbeCoverage(v);
switch( op ){
case OP_Ge:
sqlite3VdbeAddOp2(v, OP_Goto, 0, lbl);
break;
case OP_Gt:
|
| ︙ | ︙ | |||
161764 161765 161766 161767 161768 161769 161770 |
Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1);
if( p ){
/* memset(p, 0, sizeof(Expr)); */
p->op = (u8)op;
p->affExpr = 0;
p->flags = EP_Leaf;
ExprClearVVAProperties(p);
| | | 163530 163531 163532 163533 163534 163535 163536 163537 163538 163539 163540 163541 163542 163543 163544 |
Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1);
if( p ){
/* memset(p, 0, sizeof(Expr)); */
p->op = (u8)op;
p->affExpr = 0;
p->flags = EP_Leaf;
ExprClearVVAProperties(p);
/* p->iAgg = -1; // Not required */
p->pLeft = p->pRight = 0;
p->pAggInfo = 0;
memset(&p->x, 0, sizeof(p->x));
memset(&p->y, 0, sizeof(p->y));
p->op2 = 0;
p->iTable = 0;
p->iColumn = 0;
|
| ︙ | ︙ | |||
162097 162098 162099 162100 162101 162102 162103 162104 162105 162106 162107 162108 162109 162110 162111 162112 162113 162114 162115 162116 162117 162118 162119 | Cte* yy385; int yy394; Upsert* yy444; u8 yy516; With* yy521; const char* yy522; Expr* yy528; struct FrameBound yy595; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 #endif #define sqlite3ParserARG_SDECL #define sqlite3ParserARG_PDECL #define sqlite3ParserARG_PARAM #define sqlite3ParserARG_FETCH #define sqlite3ParserARG_STORE #define sqlite3ParserCTX_SDECL Parse *pParse; #define sqlite3ParserCTX_PDECL ,Parse *pParse #define sqlite3ParserCTX_PARAM ,pParse #define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; #define sqlite3ParserCTX_STORE yypParser->pParse=pParse; #define YYFALLBACK 1 | > | | | | | | | | | | | | 163863 163864 163865 163866 163867 163868 163869 163870 163871 163872 163873 163874 163875 163876 163877 163878 163879 163880 163881 163882 163883 163884 163885 163886 163887 163888 163889 163890 163891 163892 163893 163894 163895 163896 163897 163898 163899 163900 163901 163902 163903 163904 163905 | Cte* yy385; int yy394; Upsert* yy444; u8 yy516; With* yy521; const char* yy522; Expr* yy528; OnOrUsing yy561; struct FrameBound yy595; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 #endif #define sqlite3ParserARG_SDECL #define sqlite3ParserARG_PDECL #define sqlite3ParserARG_PARAM #define sqlite3ParserARG_FETCH #define sqlite3ParserARG_STORE #define sqlite3ParserCTX_SDECL Parse *pParse; #define sqlite3ParserCTX_PDECL ,Parse *pParse #define sqlite3ParserCTX_PARAM ,pParse #define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; #define sqlite3ParserCTX_STORE yypParser->pParse=pParse; #define YYFALLBACK 1 #define YYNSTATE 576 #define YYNRULE 405 #define YYNRULE_WITH_ACTION 342 #define YYNTOKEN 185 #define YY_MAX_SHIFT 575 #define YY_MIN_SHIFTREDUCE 835 #define YY_MAX_SHIFTREDUCE 1239 #define YY_ERROR_ACTION 1240 #define YY_ACCEPT_ACTION 1241 #define YY_NO_ACTION 1242 #define YY_MIN_REDUCE 1243 #define YY_MAX_REDUCE 1647 /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) /* Define the yytestcase() macro to be a no-op if is not already defined ** otherwise. ** ** Applications can choose to define yytestcase() in the %include section |
| ︙ | ︙ | |||
162191 162192 162193 162194 162195 162196 162197 | ** yy_shift_ofst[] For each state, the offset into yy_action for ** shifting terminals. ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 163958 163959 163960 163961 163962 163963 163964 163965 163966 163967 163968 163969 163970 163971 163972 163973 163974 163975 163976 163977 163978 163979 163980 163981 163982 163983 163984 163985 163986 163987 163988 163989 163990 163991 163992 163993 163994 163995 163996 163997 163998 163999 164000 164001 164002 164003 164004 164005 164006 164007 164008 164009 164010 164011 164012 164013 164014 164015 164016 164017 164018 164019 164020 164021 164022 164023 164024 164025 164026 164027 164028 164029 164030 164031 164032 164033 164034 164035 164036 164037 164038 164039 164040 164041 164042 164043 164044 164045 164046 164047 164048 164049 164050 164051 164052 164053 164054 164055 164056 164057 164058 164059 164060 164061 164062 164063 164064 164065 164066 164067 164068 164069 164070 164071 164072 164073 164074 164075 164076 164077 164078 164079 164080 164081 164082 164083 164084 164085 164086 164087 164088 164089 164090 164091 164092 164093 164094 164095 164096 164097 164098 164099 164100 164101 164102 164103 164104 164105 164106 164107 164108 164109 164110 164111 164112 164113 164114 164115 164116 164117 164118 164119 164120 164121 164122 164123 164124 164125 164126 164127 164128 164129 164130 164131 164132 164133 164134 164135 164136 164137 164138 164139 164140 164141 164142 164143 164144 164145 164146 164147 164148 164149 164150 164151 164152 164153 164154 164155 164156 164157 164158 164159 164160 164161 164162 164163 164164 164165 164166 164167 164168 164169 164170 164171 164172 164173 164174 164175 164176 164177 164178 164179 164180 164181 164182 164183 164184 164185 164186 164187 164188 164189 164190 164191 164192 164193 164194 164195 164196 164197 164198 164199 164200 164201 164202 164203 164204 164205 164206 164207 164208 164209 164210 164211 164212 164213 164214 164215 164216 164217 164218 164219 164220 164221 164222 164223 164224 164225 164226 164227 164228 164229 164230 164231 164232 164233 164234 164235 164236 164237 164238 164239 164240 164241 164242 164243 164244 164245 164246 164247 164248 164249 164250 164251 164252 164253 164254 164255 164256 164257 164258 164259 164260 164261 164262 164263 164264 164265 164266 164267 164268 164269 164270 164271 164272 164273 164274 164275 164276 164277 164278 164279 164280 164281 164282 164283 164284 164285 164286 164287 164288 164289 164290 164291 164292 164293 164294 164295 164296 164297 164298 164299 164300 164301 164302 164303 164304 164305 164306 164307 164308 164309 164310 164311 164312 164313 164314 164315 164316 164317 164318 164319 164320 164321 164322 164323 164324 164325 164326 164327 164328 164329 164330 164331 164332 164333 164334 164335 164336 164337 164338 164339 164340 164341 164342 164343 164344 164345 164346 164347 164348 164349 164350 164351 164352 164353 164354 164355 164356 164357 164358 164359 164360 164361 164362 164363 164364 164365 164366 164367 164368 164369 164370 164371 164372 164373 164374 164375 164376 164377 164378 164379 164380 164381 164382 164383 164384 164385 164386 164387 164388 164389 164390 164391 164392 164393 164394 164395 164396 164397 164398 164399 164400 164401 164402 164403 164404 164405 164406 164407 164408 164409 164410 164411 164412 164413 164414 164415 164416 164417 164418 164419 164420 164421 164422 164423 164424 164425 164426 164427 164428 164429 164430 164431 164432 164433 164434 164435 164436 164437 164438 164439 164440 164441 164442 164443 164444 164445 164446 164447 164448 164449 164450 164451 164452 164453 164454 164455 164456 164457 164458 164459 164460 164461 164462 164463 164464 164465 164466 164467 164468 164469 164470 164471 164472 164473 164474 164475 164476 164477 164478 164479 164480 164481 164482 164483 164484 164485 164486 164487 164488 164489 164490 164491 164492 164493 164494 164495 164496 164497 164498 164499 164500 164501 164502 164503 164504 164505 164506 164507 164508 164509 164510 164511 164512 164513 164514 164515 164516 164517 164518 164519 164520 164521 164522 164523 164524 164525 164526 164527 164528 164529 164530 164531 164532 164533 164534 164535 164536 164537 164538 164539 164540 164541 164542 164543 164544 164545 164546 164547 164548 164549 164550 164551 164552 164553 164554 164555 164556 164557 164558 164559 164560 164561 164562 164563 164564 164565 164566 164567 164568 164569 164570 164571 164572 164573 164574 164575 164576 164577 164578 164579 164580 164581 164582 164583 |
** yy_shift_ofst[] For each state, the offset into yy_action for
** shifting terminals.
** yy_reduce_ofst[] For each state, the offset into yy_action for
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
#define YY_ACTTAB_COUNT (2098)
static const YYACTIONTYPE yy_action[] = {
/* 0 */ 568, 208, 568, 118, 115, 229, 568, 118, 115, 229,
/* 10 */ 568, 1314, 377, 1293, 408, 562, 562, 562, 568, 409,
/* 20 */ 378, 1314, 1276, 41, 41, 41, 41, 208, 1526, 71,
/* 30 */ 71, 971, 419, 41, 41, 491, 303, 279, 303, 972,
/* 40 */ 397, 71, 71, 125, 126, 80, 1217, 1217, 1050, 1053,
/* 50 */ 1040, 1040, 123, 123, 124, 124, 124, 124, 476, 409,
/* 60 */ 1241, 1, 1, 575, 2, 1245, 550, 118, 115, 229,
/* 70 */ 317, 480, 146, 480, 524, 118, 115, 229, 529, 1327,
/* 80 */ 417, 523, 142, 125, 126, 80, 1217, 1217, 1050, 1053,
/* 90 */ 1040, 1040, 123, 123, 124, 124, 124, 124, 118, 115,
/* 100 */ 229, 327, 122, 122, 122, 122, 121, 121, 120, 120,
/* 110 */ 120, 119, 116, 444, 284, 284, 284, 284, 442, 442,
/* 120 */ 442, 1567, 376, 1569, 1192, 375, 1163, 565, 1163, 565,
/* 130 */ 409, 1567, 537, 259, 226, 444, 101, 145, 449, 316,
/* 140 */ 559, 240, 122, 122, 122, 122, 121, 121, 120, 120,
/* 150 */ 120, 119, 116, 444, 125, 126, 80, 1217, 1217, 1050,
/* 160 */ 1053, 1040, 1040, 123, 123, 124, 124, 124, 124, 142,
/* 170 */ 294, 1192, 339, 448, 120, 120, 120, 119, 116, 444,
/* 180 */ 127, 1192, 1193, 1194, 148, 441, 440, 568, 119, 116,
/* 190 */ 444, 124, 124, 124, 124, 117, 122, 122, 122, 122,
/* 200 */ 121, 121, 120, 120, 120, 119, 116, 444, 454, 113,
/* 210 */ 13, 13, 546, 122, 122, 122, 122, 121, 121, 120,
/* 220 */ 120, 120, 119, 116, 444, 422, 316, 559, 1192, 1193,
/* 230 */ 1194, 149, 1224, 409, 1224, 124, 124, 124, 124, 122,
/* 240 */ 122, 122, 122, 121, 121, 120, 120, 120, 119, 116,
/* 250 */ 444, 465, 342, 1037, 1037, 1051, 1054, 125, 126, 80,
/* 260 */ 1217, 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124,
/* 270 */ 124, 124, 1279, 522, 222, 1192, 568, 409, 224, 514,
/* 280 */ 175, 82, 83, 122, 122, 122, 122, 121, 121, 120,
/* 290 */ 120, 120, 119, 116, 444, 1007, 16, 16, 1192, 133,
/* 300 */ 133, 125, 126, 80, 1217, 1217, 1050, 1053, 1040, 1040,
/* 310 */ 123, 123, 124, 124, 124, 124, 122, 122, 122, 122,
/* 320 */ 121, 121, 120, 120, 120, 119, 116, 444, 1041, 546,
/* 330 */ 1192, 373, 1192, 1193, 1194, 252, 1434, 399, 504, 501,
/* 340 */ 500, 111, 560, 566, 4, 926, 926, 433, 499, 340,
/* 350 */ 460, 328, 360, 394, 1237, 1192, 1193, 1194, 563, 568,
/* 360 */ 122, 122, 122, 122, 121, 121, 120, 120, 120, 119,
/* 370 */ 116, 444, 284, 284, 369, 1580, 1607, 441, 440, 154,
/* 380 */ 409, 445, 71, 71, 1286, 565, 1221, 1192, 1193, 1194,
/* 390 */ 85, 1223, 271, 557, 543, 515, 1561, 568, 98, 1222,
/* 400 */ 6, 1278, 472, 142, 125, 126, 80, 1217, 1217, 1050,
/* 410 */ 1053, 1040, 1040, 123, 123, 124, 124, 124, 124, 550,
/* 420 */ 13, 13, 1027, 507, 1224, 1192, 1224, 549, 109, 109,
/* 430 */ 222, 568, 1238, 175, 568, 427, 110, 197, 445, 570,
/* 440 */ 569, 430, 1552, 1017, 325, 551, 1192, 270, 287, 368,
/* 450 */ 510, 363, 509, 257, 71, 71, 543, 71, 71, 359,
/* 460 */ 316, 559, 1613, 122, 122, 122, 122, 121, 121, 120,
/* 470 */ 120, 120, 119, 116, 444, 1017, 1017, 1019, 1020, 27,
/* 480 */ 284, 284, 1192, 1193, 1194, 1158, 568, 1612, 409, 901,
/* 490 */ 190, 550, 356, 565, 550, 937, 533, 517, 1158, 516,
/* 500 */ 413, 1158, 552, 1192, 1193, 1194, 568, 544, 1554, 51,
/* 510 */ 51, 214, 125, 126, 80, 1217, 1217, 1050, 1053, 1040,
/* 520 */ 1040, 123, 123, 124, 124, 124, 124, 1192, 474, 135,
/* 530 */ 135, 409, 284, 284, 1490, 505, 121, 121, 120, 120,
/* 540 */ 120, 119, 116, 444, 1007, 565, 518, 217, 541, 1561,
/* 550 */ 316, 559, 142, 6, 532, 125, 126, 80, 1217, 1217,
/* 560 */ 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, 124,
/* 570 */ 1555, 122, 122, 122, 122, 121, 121, 120, 120, 120,
/* 580 */ 119, 116, 444, 485, 1192, 1193, 1194, 482, 281, 1267,
/* 590 */ 957, 252, 1192, 373, 504, 501, 500, 1192, 340, 571,
/* 600 */ 1192, 571, 409, 292, 499, 957, 876, 191, 480, 316,
/* 610 */ 559, 384, 290, 380, 122, 122, 122, 122, 121, 121,
/* 620 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1217,
/* 630 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124,
/* 640 */ 124, 409, 394, 1136, 1192, 869, 100, 284, 284, 1192,
/* 650 */ 1193, 1194, 373, 1093, 1192, 1193, 1194, 1192, 1193, 1194,
/* 660 */ 565, 455, 32, 373, 233, 125, 126, 80, 1217, 1217,
/* 670 */ 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, 124,
/* 680 */ 1433, 959, 568, 228, 958, 122, 122, 122, 122, 121,
/* 690 */ 121, 120, 120, 120, 119, 116, 444, 1158, 228, 1192,
/* 700 */ 157, 1192, 1193, 1194, 1553, 13, 13, 301, 957, 1232,
/* 710 */ 1158, 153, 409, 1158, 373, 1583, 1176, 5, 369, 1580,
/* 720 */ 429, 1238, 3, 957, 122, 122, 122, 122, 121, 121,
/* 730 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1217,
/* 740 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124,
/* 750 */ 124, 409, 208, 567, 1192, 1028, 1192, 1193, 1194, 1192,
/* 760 */ 388, 852, 155, 1552, 286, 402, 1098, 1098, 488, 568,
/* 770 */ 465, 342, 1319, 1319, 1552, 125, 126, 80, 1217, 1217,
/* 780 */ 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, 124,
/* 790 */ 129, 568, 13, 13, 374, 122, 122, 122, 122, 121,
/* 800 */ 121, 120, 120, 120, 119, 116, 444, 302, 568, 453,
/* 810 */ 528, 1192, 1193, 1194, 13, 13, 1192, 1193, 1194, 1297,
/* 820 */ 463, 1267, 409, 1317, 1317, 1552, 1012, 453, 452, 200,
/* 830 */ 299, 71, 71, 1265, 122, 122, 122, 122, 121, 121,
/* 840 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1217,
/* 850 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124,
/* 860 */ 124, 409, 227, 1073, 1158, 284, 284, 419, 312, 278,
/* 870 */ 278, 285, 285, 1419, 406, 405, 382, 1158, 565, 568,
/* 880 */ 1158, 1196, 565, 1600, 565, 125, 126, 80, 1217, 1217,
/* 890 */ 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, 124,
/* 900 */ 453, 1482, 13, 13, 1536, 122, 122, 122, 122, 121,
/* 910 */ 121, 120, 120, 120, 119, 116, 444, 201, 568, 354,
/* 920 */ 1586, 575, 2, 1245, 840, 841, 842, 1562, 317, 1212,
/* 930 */ 146, 6, 409, 255, 254, 253, 206, 1327, 9, 1196,
/* 940 */ 262, 71, 71, 424, 122, 122, 122, 122, 121, 121,
/* 950 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1217,
/* 960 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124,
/* 970 */ 124, 568, 284, 284, 568, 1213, 409, 574, 313, 1245,
/* 980 */ 349, 1296, 352, 419, 317, 565, 146, 491, 525, 1643,
/* 990 */ 395, 371, 491, 1327, 70, 70, 1295, 71, 71, 240,
/* 1000 */ 1325, 104, 80, 1217, 1217, 1050, 1053, 1040, 1040, 123,
/* 1010 */ 123, 124, 124, 124, 124, 122, 122, 122, 122, 121,
/* 1020 */ 121, 120, 120, 120, 119, 116, 444, 1114, 284, 284,
/* 1030 */ 428, 448, 1525, 1213, 439, 284, 284, 1489, 1352, 311,
/* 1040 */ 474, 565, 1115, 971, 491, 491, 217, 1263, 565, 1538,
/* 1050 */ 568, 972, 207, 568, 1027, 240, 383, 1116, 519, 122,
/* 1060 */ 122, 122, 122, 121, 121, 120, 120, 120, 119, 116,
/* 1070 */ 444, 1018, 107, 71, 71, 1017, 13, 13, 912, 568,
/* 1080 */ 1495, 568, 284, 284, 97, 526, 491, 448, 913, 1326,
/* 1090 */ 1322, 545, 409, 284, 284, 565, 151, 209, 1495, 1497,
/* 1100 */ 262, 450, 55, 55, 56, 56, 565, 1017, 1017, 1019,
/* 1110 */ 443, 332, 409, 527, 12, 295, 125, 126, 80, 1217,
/* 1120 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124,
/* 1130 */ 124, 347, 409, 864, 1534, 1213, 125, 126, 80, 1217,
/* 1140 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124,
/* 1150 */ 124, 1137, 1641, 474, 1641, 371, 125, 114, 80, 1217,
/* 1160 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124,
/* 1170 */ 124, 1495, 329, 474, 331, 122, 122, 122, 122, 121,
/* 1180 */ 121, 120, 120, 120, 119, 116, 444, 203, 1419, 568,
/* 1190 */ 1294, 864, 464, 1213, 436, 122, 122, 122, 122, 121,
/* 1200 */ 121, 120, 120, 120, 119, 116, 444, 553, 1137, 1642,
/* 1210 */ 539, 1642, 15, 15, 892, 122, 122, 122, 122, 121,
/* 1220 */ 121, 120, 120, 120, 119, 116, 444, 568, 298, 538,
/* 1230 */ 1135, 1419, 1559, 1560, 1331, 409, 6, 6, 1169, 1268,
/* 1240 */ 415, 320, 284, 284, 1419, 508, 565, 525, 300, 457,
/* 1250 */ 43, 43, 568, 893, 12, 565, 330, 478, 425, 407,
/* 1260 */ 126, 80, 1217, 1217, 1050, 1053, 1040, 1040, 123, 123,
/* 1270 */ 124, 124, 124, 124, 568, 57, 57, 288, 1192, 1419,
/* 1280 */ 496, 458, 392, 392, 391, 273, 389, 1135, 1558, 849,
/* 1290 */ 1169, 407, 6, 568, 321, 1158, 470, 44, 44, 1557,
/* 1300 */ 1114, 426, 234, 6, 323, 256, 540, 256, 1158, 431,
/* 1310 */ 568, 1158, 322, 17, 487, 1115, 58, 58, 122, 122,
/* 1320 */ 122, 122, 121, 121, 120, 120, 120, 119, 116, 444,
/* 1330 */ 1116, 216, 481, 59, 59, 1192, 1193, 1194, 111, 560,
/* 1340 */ 324, 4, 236, 456, 526, 568, 237, 456, 568, 437,
/* 1350 */ 168, 556, 420, 141, 479, 563, 568, 293, 568, 1095,
/* 1360 */ 568, 293, 568, 1095, 531, 568, 872, 8, 60, 60,
/* 1370 */ 235, 61, 61, 568, 414, 568, 414, 568, 445, 62,
/* 1380 */ 62, 45, 45, 46, 46, 47, 47, 199, 49, 49,
/* 1390 */ 557, 568, 359, 568, 100, 486, 50, 50, 63, 63,
/* 1400 */ 64, 64, 561, 415, 535, 410, 568, 1027, 568, 534,
/* 1410 */ 316, 559, 316, 559, 65, 65, 14, 14, 568, 1027,
/* 1420 */ 568, 512, 932, 872, 1018, 109, 109, 931, 1017, 66,
/* 1430 */ 66, 131, 131, 110, 451, 445, 570, 569, 416, 177,
/* 1440 */ 1017, 132, 132, 67, 67, 568, 467, 568, 932, 471,
/* 1450 */ 1364, 283, 226, 931, 315, 1363, 407, 568, 459, 407,
/* 1460 */ 1017, 1017, 1019, 239, 407, 86, 213, 1350, 52, 52,
/* 1470 */ 68, 68, 1017, 1017, 1019, 1020, 27, 1585, 1180, 447,
/* 1480 */ 69, 69, 288, 97, 108, 1541, 106, 392, 392, 391,
/* 1490 */ 273, 389, 568, 879, 849, 883, 568, 111, 560, 466,
/* 1500 */ 4, 568, 152, 30, 38, 568, 1132, 234, 396, 323,
/* 1510 */ 111, 560, 527, 4, 563, 53, 53, 322, 568, 163,
/* 1520 */ 163, 568, 337, 468, 164, 164, 333, 563, 76, 76,
/* 1530 */ 568, 289, 1514, 568, 31, 1513, 568, 445, 338, 483,
/* 1540 */ 100, 54, 54, 344, 72, 72, 296, 236, 1080, 557,
/* 1550 */ 445, 879, 1360, 134, 134, 168, 73, 73, 141, 161,
/* 1560 */ 161, 1574, 557, 535, 568, 319, 568, 348, 536, 1009,
/* 1570 */ 473, 261, 261, 891, 890, 235, 535, 568, 1027, 568,
/* 1580 */ 475, 534, 261, 367, 109, 109, 521, 136, 136, 130,
/* 1590 */ 130, 1027, 110, 366, 445, 570, 569, 109, 109, 1017,
/* 1600 */ 162, 162, 156, 156, 568, 110, 1080, 445, 570, 569,
/* 1610 */ 410, 351, 1017, 568, 353, 316, 559, 568, 343, 568,
/* 1620 */ 100, 497, 357, 258, 100, 898, 899, 140, 140, 355,
/* 1630 */ 1310, 1017, 1017, 1019, 1020, 27, 139, 139, 362, 451,
/* 1640 */ 137, 137, 138, 138, 1017, 1017, 1019, 1020, 27, 1180,
/* 1650 */ 447, 568, 372, 288, 111, 560, 1021, 4, 392, 392,
/* 1660 */ 391, 273, 389, 568, 1141, 849, 568, 1076, 568, 258,
/* 1670 */ 492, 563, 568, 211, 75, 75, 555, 962, 234, 261,
/* 1680 */ 323, 111, 560, 929, 4, 113, 77, 77, 322, 74,
/* 1690 */ 74, 42, 42, 1373, 445, 48, 48, 1418, 563, 974,
/* 1700 */ 975, 1092, 1091, 1092, 1091, 862, 557, 150, 930, 1346,
/* 1710 */ 113, 1358, 554, 1424, 1021, 1275, 1266, 1254, 236, 1253,
/* 1720 */ 1255, 445, 1593, 1343, 308, 276, 168, 309, 11, 141,
/* 1730 */ 393, 310, 232, 557, 1405, 1027, 335, 291, 1400, 219,
/* 1740 */ 336, 109, 109, 936, 297, 1410, 235, 341, 477, 110,
/* 1750 */ 502, 445, 570, 569, 1393, 1409, 1017, 400, 1293, 365,
/* 1760 */ 223, 1486, 1027, 1485, 1355, 1356, 1354, 1353, 109, 109,
/* 1770 */ 204, 1596, 1232, 558, 265, 218, 110, 205, 445, 570,
/* 1780 */ 569, 410, 387, 1017, 1533, 179, 316, 559, 1017, 1017,
/* 1790 */ 1019, 1020, 27, 230, 1531, 1229, 79, 560, 85, 4,
/* 1800 */ 418, 215, 548, 81, 84, 188, 1406, 173, 181, 461,
/* 1810 */ 451, 35, 462, 563, 183, 1017, 1017, 1019, 1020, 27,
/* 1820 */ 184, 1491, 185, 186, 495, 242, 98, 398, 1412, 36,
/* 1830 */ 1411, 484, 91, 469, 401, 1414, 445, 192, 1480, 246,
/* 1840 */ 1502, 490, 346, 277, 248, 196, 493, 511, 557, 350,
/* 1850 */ 1256, 249, 250, 403, 1313, 1312, 111, 560, 432, 4,
/* 1860 */ 1311, 1304, 93, 1611, 883, 1610, 224, 404, 434, 520,
/* 1870 */ 263, 435, 1579, 563, 1283, 1282, 364, 1027, 306, 1281,
/* 1880 */ 264, 1609, 1565, 109, 109, 370, 1303, 307, 1564, 438,
/* 1890 */ 128, 110, 1378, 445, 570, 569, 445, 546, 1017, 10,
/* 1900 */ 1466, 105, 381, 1377, 34, 572, 99, 1336, 557, 314,
/* 1910 */ 1186, 530, 272, 274, 379, 210, 1335, 547, 385, 386,
/* 1920 */ 275, 573, 1251, 1246, 411, 412, 1518, 165, 178, 1519,
/* 1930 */ 1017, 1017, 1019, 1020, 27, 1517, 1516, 1027, 78, 147,
/* 1940 */ 166, 220, 221, 109, 109, 836, 304, 167, 446, 212,
/* 1950 */ 318, 110, 231, 445, 570, 569, 144, 1090, 1017, 1088,
/* 1960 */ 326, 180, 169, 1212, 182, 334, 238, 915, 241, 1104,
/* 1970 */ 187, 170, 171, 421, 87, 88, 423, 189, 89, 90,
/* 1980 */ 172, 1107, 243, 1103, 244, 158, 18, 245, 345, 247,
/* 1990 */ 1017, 1017, 1019, 1020, 27, 261, 1096, 193, 1226, 489,
/* 2000 */ 194, 37, 366, 851, 494, 251, 195, 506, 92, 19,
/* 2010 */ 498, 358, 20, 503, 881, 361, 94, 894, 305, 159,
/* 2020 */ 513, 39, 95, 1174, 160, 1056, 966, 1143, 96, 174,
/* 2030 */ 1142, 225, 280, 282, 198, 960, 113, 1164, 1160, 260,
/* 2040 */ 21, 22, 23, 1162, 1168, 1167, 1148, 24, 33, 25,
/* 2050 */ 202, 542, 26, 100, 1071, 102, 1057, 103, 7, 1055,
/* 2060 */ 1059, 1113, 1060, 1112, 266, 267, 28, 40, 390, 1022,
/* 2070 */ 863, 112, 29, 564, 1182, 1181, 268, 176, 143, 925,
/* 2080 */ 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242,
/* 2090 */ 1242, 1242, 1242, 1242, 269, 1602, 1242, 1601,
};
static const YYCODETYPE yy_lookahead[] = {
/* 0 */ 193, 193, 193, 274, 275, 276, 193, 274, 275, 276,
/* 10 */ 193, 223, 219, 225, 206, 210, 211, 212, 193, 19,
/* 20 */ 219, 233, 216, 216, 217, 216, 217, 193, 295, 216,
/* 30 */ 217, 31, 193, 216, 217, 193, 228, 213, 230, 39,
/* 40 */ 206, 216, 217, 43, 44, 45, 46, 47, 48, 49,
/* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 193, 19,
/* 60 */ 185, 186, 187, 188, 189, 190, 253, 274, 275, 276,
/* 70 */ 195, 193, 197, 193, 261, 274, 275, 276, 253, 204,
/* 80 */ 238, 204, 81, 43, 44, 45, 46, 47, 48, 49,
/* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 274, 275,
/* 100 */ 276, 262, 102, 103, 104, 105, 106, 107, 108, 109,
/* 110 */ 110, 111, 112, 113, 239, 240, 239, 240, 210, 211,
/* 120 */ 212, 314, 315, 314, 59, 316, 86, 252, 88, 252,
/* 130 */ 19, 314, 315, 256, 257, 113, 25, 72, 296, 138,
/* 140 */ 139, 266, 102, 103, 104, 105, 106, 107, 108, 109,
/* 150 */ 110, 111, 112, 113, 43, 44, 45, 46, 47, 48,
/* 160 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 81,
/* 170 */ 292, 59, 292, 298, 108, 109, 110, 111, 112, 113,
/* 180 */ 69, 116, 117, 118, 72, 106, 107, 193, 111, 112,
/* 190 */ 113, 54, 55, 56, 57, 58, 102, 103, 104, 105,
/* 200 */ 106, 107, 108, 109, 110, 111, 112, 113, 120, 25,
/* 210 */ 216, 217, 145, 102, 103, 104, 105, 106, 107, 108,
/* 220 */ 109, 110, 111, 112, 113, 231, 138, 139, 116, 117,
/* 230 */ 118, 164, 153, 19, 155, 54, 55, 56, 57, 102,
/* 240 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
/* 250 */ 113, 128, 129, 46, 47, 48, 49, 43, 44, 45,
/* 260 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
/* 270 */ 56, 57, 216, 193, 25, 59, 193, 19, 165, 166,
/* 280 */ 193, 67, 24, 102, 103, 104, 105, 106, 107, 108,
/* 290 */ 109, 110, 111, 112, 113, 73, 216, 217, 59, 216,
/* 300 */ 217, 43, 44, 45, 46, 47, 48, 49, 50, 51,
/* 310 */ 52, 53, 54, 55, 56, 57, 102, 103, 104, 105,
/* 320 */ 106, 107, 108, 109, 110, 111, 112, 113, 121, 145,
/* 330 */ 59, 193, 116, 117, 118, 119, 273, 204, 122, 123,
/* 340 */ 124, 19, 20, 134, 22, 136, 137, 19, 132, 127,
/* 350 */ 128, 129, 24, 22, 23, 116, 117, 118, 36, 193,
/* 360 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
/* 370 */ 112, 113, 239, 240, 311, 312, 215, 106, 107, 241,
/* 380 */ 19, 59, 216, 217, 223, 252, 115, 116, 117, 118,
/* 390 */ 151, 120, 26, 71, 193, 308, 309, 193, 149, 128,
/* 400 */ 313, 216, 269, 81, 43, 44, 45, 46, 47, 48,
/* 410 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 253,
/* 420 */ 216, 217, 100, 95, 153, 59, 155, 261, 106, 107,
/* 430 */ 25, 193, 101, 193, 193, 231, 114, 25, 116, 117,
/* 440 */ 118, 113, 304, 121, 193, 204, 59, 119, 120, 121,
/* 450 */ 122, 123, 124, 125, 216, 217, 193, 216, 217, 131,
/* 460 */ 138, 139, 230, 102, 103, 104, 105, 106, 107, 108,
/* 470 */ 109, 110, 111, 112, 113, 153, 154, 155, 156, 157,
/* 480 */ 239, 240, 116, 117, 118, 76, 193, 23, 19, 25,
/* 490 */ 22, 253, 23, 252, 253, 108, 87, 204, 89, 261,
/* 500 */ 198, 92, 261, 116, 117, 118, 193, 306, 307, 216,
/* 510 */ 217, 150, 43, 44, 45, 46, 47, 48, 49, 50,
/* 520 */ 51, 52, 53, 54, 55, 56, 57, 59, 193, 216,
/* 530 */ 217, 19, 239, 240, 283, 23, 106, 107, 108, 109,
/* 540 */ 110, 111, 112, 113, 73, 252, 253, 142, 308, 309,
/* 550 */ 138, 139, 81, 313, 145, 43, 44, 45, 46, 47,
/* 560 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
/* 570 */ 307, 102, 103, 104, 105, 106, 107, 108, 109, 110,
/* 580 */ 111, 112, 113, 281, 116, 117, 118, 285, 23, 193,
/* 590 */ 25, 119, 59, 193, 122, 123, 124, 59, 127, 203,
/* 600 */ 59, 205, 19, 268, 132, 25, 23, 22, 193, 138,
/* 610 */ 139, 249, 204, 251, 102, 103, 104, 105, 106, 107,
/* 620 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
/* 630 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
/* 640 */ 57, 19, 22, 23, 59, 23, 25, 239, 240, 116,
/* 650 */ 117, 118, 193, 11, 116, 117, 118, 116, 117, 118,
/* 660 */ 252, 269, 22, 193, 15, 43, 44, 45, 46, 47,
/* 670 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
/* 680 */ 273, 143, 193, 118, 143, 102, 103, 104, 105, 106,
/* 690 */ 107, 108, 109, 110, 111, 112, 113, 76, 118, 59,
/* 700 */ 241, 116, 117, 118, 304, 216, 217, 292, 143, 60,
/* 710 */ 89, 241, 19, 92, 193, 193, 23, 22, 311, 312,
/* 720 */ 231, 101, 22, 143, 102, 103, 104, 105, 106, 107,
/* 730 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
/* 740 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
/* 750 */ 57, 19, 193, 193, 59, 23, 116, 117, 118, 59,
/* 760 */ 201, 21, 241, 304, 22, 206, 127, 128, 129, 193,
/* 770 */ 128, 129, 235, 236, 304, 43, 44, 45, 46, 47,
/* 780 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
/* 790 */ 22, 193, 216, 217, 193, 102, 103, 104, 105, 106,
/* 800 */ 107, 108, 109, 110, 111, 112, 113, 231, 193, 193,
/* 810 */ 193, 116, 117, 118, 216, 217, 116, 117, 118, 226,
/* 820 */ 80, 193, 19, 235, 236, 304, 23, 211, 212, 231,
/* 830 */ 204, 216, 217, 205, 102, 103, 104, 105, 106, 107,
/* 840 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
/* 850 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
/* 860 */ 57, 19, 193, 123, 76, 239, 240, 193, 253, 239,
/* 870 */ 240, 239, 240, 193, 106, 107, 193, 89, 252, 193,
/* 880 */ 92, 59, 252, 141, 252, 43, 44, 45, 46, 47,
/* 890 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
/* 900 */ 284, 161, 216, 217, 193, 102, 103, 104, 105, 106,
/* 910 */ 107, 108, 109, 110, 111, 112, 113, 231, 193, 16,
/* 920 */ 187, 188, 189, 190, 7, 8, 9, 309, 195, 25,
/* 930 */ 197, 313, 19, 127, 128, 129, 262, 204, 22, 117,
/* 940 */ 24, 216, 217, 263, 102, 103, 104, 105, 106, 107,
/* 950 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
/* 960 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
/* 970 */ 57, 193, 239, 240, 193, 59, 19, 188, 253, 190,
/* 980 */ 77, 226, 79, 193, 195, 252, 197, 193, 19, 301,
/* 990 */ 302, 193, 193, 204, 216, 217, 226, 216, 217, 266,
/* 1000 */ 204, 159, 45, 46, 47, 48, 49, 50, 51, 52,
/* 1010 */ 53, 54, 55, 56, 57, 102, 103, 104, 105, 106,
/* 1020 */ 107, 108, 109, 110, 111, 112, 113, 12, 239, 240,
/* 1030 */ 232, 298, 238, 117, 253, 239, 240, 238, 259, 260,
/* 1040 */ 193, 252, 27, 31, 193, 193, 142, 204, 252, 193,
/* 1050 */ 193, 39, 262, 193, 100, 266, 278, 42, 204, 102,
/* 1060 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
/* 1070 */ 113, 117, 159, 216, 217, 121, 216, 217, 63, 193,
/* 1080 */ 193, 193, 239, 240, 115, 116, 193, 298, 73, 238,
/* 1090 */ 238, 231, 19, 239, 240, 252, 22, 24, 211, 212,
/* 1100 */ 24, 193, 216, 217, 216, 217, 252, 153, 154, 155,
/* 1110 */ 253, 16, 19, 144, 213, 268, 43, 44, 45, 46,
/* 1120 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
/* 1130 */ 57, 238, 19, 59, 193, 59, 43, 44, 45, 46,
/* 1140 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
/* 1150 */ 57, 22, 23, 193, 25, 193, 43, 44, 45, 46,
/* 1160 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
/* 1170 */ 57, 284, 77, 193, 79, 102, 103, 104, 105, 106,
/* 1180 */ 107, 108, 109, 110, 111, 112, 113, 286, 193, 193,
/* 1190 */ 193, 117, 291, 117, 232, 102, 103, 104, 105, 106,
/* 1200 */ 107, 108, 109, 110, 111, 112, 113, 204, 22, 23,
/* 1210 */ 66, 25, 216, 217, 35, 102, 103, 104, 105, 106,
/* 1220 */ 107, 108, 109, 110, 111, 112, 113, 193, 268, 85,
/* 1230 */ 101, 193, 309, 309, 240, 19, 313, 313, 94, 208,
/* 1240 */ 209, 193, 239, 240, 193, 66, 252, 19, 268, 244,
/* 1250 */ 216, 217, 193, 74, 213, 252, 161, 19, 263, 254,
/* 1260 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
/* 1270 */ 54, 55, 56, 57, 193, 216, 217, 5, 59, 193,
/* 1280 */ 19, 244, 10, 11, 12, 13, 14, 101, 309, 17,
/* 1290 */ 146, 254, 313, 193, 193, 76, 115, 216, 217, 309,
/* 1300 */ 12, 263, 30, 313, 32, 46, 87, 46, 89, 130,
/* 1310 */ 193, 92, 40, 22, 263, 27, 216, 217, 102, 103,
/* 1320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
/* 1330 */ 42, 150, 291, 216, 217, 116, 117, 118, 19, 20,
/* 1340 */ 193, 22, 70, 260, 116, 193, 24, 264, 193, 263,
/* 1350 */ 78, 63, 61, 81, 116, 36, 193, 260, 193, 29,
/* 1360 */ 193, 264, 193, 33, 145, 193, 59, 48, 216, 217,
/* 1370 */ 98, 216, 217, 193, 115, 193, 115, 193, 59, 216,
/* 1380 */ 217, 216, 217, 216, 217, 216, 217, 255, 216, 217,
/* 1390 */ 71, 193, 131, 193, 25, 65, 216, 217, 216, 217,
/* 1400 */ 216, 217, 208, 209, 85, 133, 193, 100, 193, 90,
/* 1410 */ 138, 139, 138, 139, 216, 217, 216, 217, 193, 100,
/* 1420 */ 193, 108, 135, 116, 117, 106, 107, 140, 121, 216,
/* 1430 */ 217, 216, 217, 114, 162, 116, 117, 118, 299, 300,
/* 1440 */ 121, 216, 217, 216, 217, 193, 244, 193, 135, 244,
/* 1450 */ 193, 256, 257, 140, 244, 193, 254, 193, 193, 254,
/* 1460 */ 153, 154, 155, 141, 254, 149, 150, 258, 216, 217,
/* 1470 */ 216, 217, 153, 154, 155, 156, 157, 0, 1, 2,
/* 1480 */ 216, 217, 5, 115, 158, 193, 160, 10, 11, 12,
/* 1490 */ 13, 14, 193, 59, 17, 126, 193, 19, 20, 129,
/* 1500 */ 22, 193, 22, 22, 24, 193, 23, 30, 25, 32,
/* 1510 */ 19, 20, 144, 22, 36, 216, 217, 40, 193, 216,
/* 1520 */ 217, 193, 152, 129, 216, 217, 193, 36, 216, 217,
/* 1530 */ 193, 99, 193, 193, 53, 193, 193, 59, 23, 193,
/* 1540 */ 25, 216, 217, 193, 216, 217, 152, 70, 59, 71,
/* 1550 */ 59, 117, 193, 216, 217, 78, 216, 217, 81, 216,
/* 1560 */ 217, 318, 71, 85, 193, 133, 193, 193, 90, 23,
/* 1570 */ 23, 25, 25, 120, 121, 98, 85, 193, 100, 193,
/* 1580 */ 23, 90, 25, 121, 106, 107, 19, 216, 217, 216,
/* 1590 */ 217, 100, 114, 131, 116, 117, 118, 106, 107, 121,
/* 1600 */ 216, 217, 216, 217, 193, 114, 117, 116, 117, 118,
/* 1610 */ 133, 193, 121, 193, 193, 138, 139, 193, 23, 193,
/* 1620 */ 25, 23, 23, 25, 25, 7, 8, 216, 217, 193,
/* 1630 */ 193, 153, 154, 155, 156, 157, 216, 217, 193, 162,
/* 1640 */ 216, 217, 216, 217, 153, 154, 155, 156, 157, 1,
/* 1650 */ 2, 193, 193, 5, 19, 20, 59, 22, 10, 11,
/* 1660 */ 12, 13, 14, 193, 97, 17, 193, 23, 193, 25,
/* 1670 */ 288, 36, 193, 242, 216, 217, 236, 23, 30, 25,
/* 1680 */ 32, 19, 20, 23, 22, 25, 216, 217, 40, 216,
/* 1690 */ 217, 216, 217, 193, 59, 216, 217, 193, 36, 83,
/* 1700 */ 84, 153, 153, 155, 155, 23, 71, 25, 23, 193,
/* 1710 */ 25, 193, 193, 193, 117, 193, 193, 193, 70, 193,
/* 1720 */ 193, 59, 193, 255, 255, 287, 78, 255, 243, 81,
/* 1730 */ 191, 255, 297, 71, 271, 100, 293, 245, 267, 214,
/* 1740 */ 246, 106, 107, 108, 246, 271, 98, 245, 293, 114,
/* 1750 */ 220, 116, 117, 118, 267, 271, 121, 271, 225, 219,
/* 1760 */ 229, 219, 100, 219, 259, 259, 259, 259, 106, 107,
/* 1770 */ 249, 196, 60, 280, 141, 243, 114, 249, 116, 117,
/* 1780 */ 118, 133, 245, 121, 200, 297, 138, 139, 153, 154,
/* 1790 */ 155, 156, 157, 297, 200, 38, 19, 20, 151, 22,
/* 1800 */ 200, 150, 140, 294, 294, 22, 272, 43, 234, 18,
/* 1810 */ 162, 270, 200, 36, 237, 153, 154, 155, 156, 157,
/* 1820 */ 237, 283, 237, 237, 18, 199, 149, 246, 272, 270,
/* 1830 */ 272, 200, 158, 246, 246, 234, 59, 234, 246, 199,
/* 1840 */ 290, 62, 289, 200, 199, 22, 221, 115, 71, 200,
/* 1850 */ 200, 199, 199, 221, 218, 218, 19, 20, 64, 22,
/* 1860 */ 218, 227, 22, 224, 126, 224, 165, 221, 24, 305,
/* 1870 */ 200, 113, 312, 36, 218, 220, 218, 100, 282, 218,
/* 1880 */ 91, 218, 317, 106, 107, 221, 227, 282, 317, 82,
/* 1890 */ 148, 114, 265, 116, 117, 118, 59, 145, 121, 22,
/* 1900 */ 277, 158, 200, 265, 25, 202, 147, 250, 71, 279,
/* 1910 */ 13, 146, 194, 194, 249, 248, 250, 140, 247, 246,
/* 1920 */ 6, 192, 192, 192, 303, 303, 213, 207, 300, 213,
/* 1930 */ 153, 154, 155, 156, 157, 213, 213, 100, 213, 222,
/* 1940 */ 207, 214, 214, 106, 107, 4, 222, 207, 3, 22,
/* 1950 */ 163, 114, 15, 116, 117, 118, 16, 23, 121, 23,
/* 1960 */ 139, 151, 130, 25, 142, 16, 24, 20, 144, 1,
/* 1970 */ 142, 130, 130, 61, 53, 53, 37, 151, 53, 53,
/* 1980 */ 130, 116, 34, 1, 141, 5, 22, 115, 161, 141,
/* 1990 */ 153, 154, 155, 156, 157, 25, 68, 68, 75, 41,
/* 2000 */ 115, 24, 131, 20, 19, 125, 22, 96, 22, 22,
/* 2010 */ 67, 23, 22, 67, 59, 24, 22, 28, 67, 23,
/* 2020 */ 22, 22, 149, 23, 23, 23, 116, 23, 25, 37,
/* 2030 */ 97, 141, 23, 23, 22, 143, 25, 75, 88, 34,
/* 2040 */ 34, 34, 34, 86, 75, 93, 23, 34, 22, 34,
/* 2050 */ 25, 24, 34, 25, 23, 142, 23, 142, 44, 23,
/* 2060 */ 23, 23, 11, 23, 25, 22, 22, 22, 15, 23,
/* 2070 */ 23, 22, 22, 25, 1, 1, 141, 25, 23, 135,
/* 2080 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2090 */ 319, 319, 319, 319, 141, 141, 319, 141, 319, 319,
/* 2100 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2110 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2120 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2130 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2140 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2150 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2160 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2170 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2180 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2190 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2200 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2210 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2220 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2230 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2240 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2250 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2260 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2270 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
/* 2280 */ 319, 319, 319,
};
#define YY_SHIFT_COUNT (575)
#define YY_SHIFT_MIN (0)
#define YY_SHIFT_MAX (2074)
static const unsigned short int yy_shift_ofst[] = {
/* 0 */ 1648, 1477, 1272, 322, 322, 1, 1319, 1478, 1491, 1837,
/* 10 */ 1837, 1837, 471, 0, 0, 214, 1093, 1837, 1837, 1837,
/* 20 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837,
/* 30 */ 271, 271, 1219, 1219, 216, 88, 1, 1, 1, 1,
/* 40 */ 1, 40, 111, 258, 361, 469, 512, 583, 622, 693,
/* 50 */ 732, 803, 842, 913, 1073, 1093, 1093, 1093, 1093, 1093,
/* 60 */ 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
/* 70 */ 1093, 1093, 1093, 1113, 1093, 1216, 957, 957, 1635, 1662,
/* 80 */ 1777, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837,
/* 90 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837,
/* 100 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837,
/* 110 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837,
/* 120 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837,
/* 130 */ 137, 181, 181, 181, 181, 181, 181, 181, 94, 430,
/* 140 */ 66, 65, 112, 366, 533, 533, 740, 1261, 533, 533,
/* 150 */ 79, 79, 533, 412, 412, 412, 77, 412, 123, 113,
/* 160 */ 113, 22, 22, 2098, 2098, 328, 328, 328, 239, 468,
/* 170 */ 468, 468, 468, 1015, 1015, 409, 366, 1129, 1186, 533,
/* 180 */ 533, 533, 533, 533, 533, 533, 533, 533, 533, 533,
/* 190 */ 533, 533, 533, 533, 533, 533, 533, 533, 533, 969,
/* 200 */ 621, 621, 533, 642, 788, 788, 1228, 1228, 822, 822,
/* 210 */ 67, 1274, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 1307,
/* 220 */ 954, 954, 585, 472, 640, 387, 695, 538, 541, 700,
/* 230 */ 533, 533, 533, 533, 533, 533, 533, 533, 533, 533,
/* 240 */ 222, 533, 533, 533, 533, 533, 533, 533, 533, 533,
/* 250 */ 533, 533, 533, 1179, 1179, 1179, 533, 533, 533, 565,
/* 260 */ 533, 533, 533, 916, 1144, 533, 533, 1288, 533, 533,
/* 270 */ 533, 533, 533, 533, 533, 533, 639, 1330, 209, 1076,
/* 280 */ 1076, 1076, 1076, 580, 209, 209, 1313, 768, 917, 649,
/* 290 */ 1181, 1316, 405, 1316, 1238, 249, 1181, 1181, 249, 1181,
/* 300 */ 405, 1238, 1369, 464, 1259, 1012, 1012, 1012, 1368, 1368,
/* 310 */ 1368, 1368, 184, 184, 1326, 904, 1287, 1480, 1712, 1712,
/* 320 */ 1633, 1633, 1757, 1757, 1633, 1647, 1651, 1783, 1764, 1791,
/* 330 */ 1791, 1791, 1791, 1633, 1806, 1677, 1651, 1651, 1677, 1783,
/* 340 */ 1764, 1677, 1764, 1677, 1633, 1806, 1674, 1779, 1633, 1806,
/* 350 */ 1823, 1633, 1806, 1633, 1806, 1823, 1732, 1732, 1732, 1794,
/* 360 */ 1840, 1840, 1823, 1732, 1738, 1732, 1794, 1732, 1732, 1701,
/* 370 */ 1844, 1758, 1758, 1823, 1633, 1789, 1789, 1807, 1807, 1742,
/* 380 */ 1752, 1877, 1633, 1743, 1742, 1759, 1765, 1677, 1879, 1897,
/* 390 */ 1897, 1914, 1914, 1914, 2098, 2098, 2098, 2098, 2098, 2098,
/* 400 */ 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 207,
/* 410 */ 1095, 331, 620, 903, 806, 1074, 1483, 1432, 1481, 1322,
/* 420 */ 1370, 1394, 1515, 1291, 1546, 1547, 1557, 1595, 1598, 1599,
/* 430 */ 1434, 1453, 1618, 1462, 1567, 1489, 1644, 1654, 1616, 1660,
/* 440 */ 1548, 1549, 1682, 1685, 1597, 742, 1941, 1945, 1927, 1787,
/* 450 */ 1937, 1940, 1934, 1936, 1821, 1810, 1832, 1938, 1938, 1942,
/* 460 */ 1822, 1947, 1824, 1949, 1968, 1828, 1841, 1938, 1842, 1912,
/* 470 */ 1939, 1938, 1826, 1921, 1922, 1925, 1926, 1850, 1865, 1948,
/* 480 */ 1843, 1982, 1980, 1964, 1872, 1827, 1928, 1970, 1929, 1923,
/* 490 */ 1958, 1848, 1885, 1977, 1983, 1985, 1871, 1880, 1984, 1943,
/* 500 */ 1986, 1987, 1988, 1990, 1946, 1955, 1991, 1911, 1989, 1994,
/* 510 */ 1951, 1992, 1996, 1873, 1998, 2000, 2001, 2002, 2003, 2004,
/* 520 */ 1999, 1933, 1890, 2009, 2010, 1910, 2005, 2012, 1892, 2011,
/* 530 */ 2006, 2007, 2008, 2013, 1950, 1962, 1957, 2014, 1969, 1952,
/* 540 */ 2015, 2023, 2026, 2027, 2025, 2028, 2018, 1913, 1915, 2031,
/* 550 */ 2011, 2033, 2036, 2037, 2038, 2039, 2040, 2043, 2051, 2044,
/* 560 */ 2045, 2046, 2047, 2049, 2050, 2048, 1944, 1935, 1953, 1954,
/* 570 */ 1956, 2052, 2055, 2053, 2073, 2074,
};
#define YY_REDUCE_COUNT (408)
#define YY_REDUCE_MIN (-271)
#define YY_REDUCE_MAX (1740)
static const short yy_reduce_ofst[] = {
/* 0 */ -125, 733, 789, 241, 293, -123, -193, -191, -183, -187,
/* 10 */ 166, 238, 133, -207, -199, -267, -176, -6, 204, 489,
/* 20 */ 576, -175, 598, 686, 615, 725, 860, 778, 781, 857,
/* 30 */ 616, 887, 87, 240, -192, 408, 626, 796, 843, 854,
/* 40 */ 1003, -271, -271, -271, -271, -271, -271, -271, -271, -271,
/* 50 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
/* 60 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
/* 70 */ -271, -271, -271, -271, -271, -271, -271, -271, 80, 83,
/* 80 */ 313, 886, 888, 996, 1034, 1059, 1081, 1100, 1117, 1152,
/* 90 */ 1155, 1163, 1165, 1167, 1169, 1172, 1180, 1182, 1184, 1198,
/* 100 */ 1200, 1213, 1215, 1225, 1227, 1252, 1254, 1264, 1299, 1303,
/* 110 */ 1308, 1312, 1325, 1328, 1337, 1340, 1343, 1371, 1373, 1384,
/* 120 */ 1386, 1411, 1420, 1424, 1426, 1458, 1470, 1473, 1475, 1479,
/* 130 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
/* 140 */ -271, 138, 459, 396, -158, 470, 302, -212, 521, 201,
/* 150 */ -195, -92, 559, 630, 632, 630, -271, 632, 901, 63,
/* 160 */ 407, -271, -271, -271, -271, 161, 161, 161, 251, 335,
/* 170 */ 847, 960, 980, 537, 588, 618, 628, 688, 688, -166,
/* 180 */ -161, 674, 790, 794, 799, 851, 852, -122, 680, -120,
/* 190 */ 995, 1038, 415, 1051, 893, 798, 962, 400, 1086, 779,
/* 200 */ 923, 924, 263, 1041, 979, 990, 1083, 1097, 1031, 1194,
/* 210 */ 362, 994, 1139, 1005, 1037, 1202, 1205, 1195, 1210, -194,
/* 220 */ 56, 185, -135, 232, 522, 560, 601, 617, 669, 683,
/* 230 */ 711, 856, 908, 941, 1048, 1101, 1147, 1257, 1262, 1265,
/* 240 */ 392, 1292, 1333, 1339, 1342, 1346, 1350, 1359, 1374, 1418,
/* 250 */ 1421, 1436, 1437, 593, 755, 770, 997, 1445, 1459, 1209,
/* 260 */ 1500, 1504, 1516, 1132, 1243, 1518, 1519, 1440, 1520, 560,
/* 270 */ 1522, 1523, 1524, 1526, 1527, 1529, 1382, 1438, 1431, 1468,
/* 280 */ 1469, 1472, 1476, 1209, 1431, 1431, 1485, 1525, 1539, 1435,
/* 290 */ 1463, 1471, 1492, 1487, 1443, 1494, 1474, 1484, 1498, 1486,
/* 300 */ 1502, 1455, 1530, 1531, 1533, 1540, 1542, 1544, 1505, 1506,
/* 310 */ 1507, 1508, 1521, 1528, 1493, 1537, 1532, 1575, 1488, 1496,
/* 320 */ 1584, 1594, 1509, 1510, 1600, 1538, 1534, 1541, 1574, 1577,
/* 330 */ 1583, 1585, 1586, 1612, 1626, 1581, 1556, 1558, 1587, 1559,
/* 340 */ 1601, 1588, 1603, 1592, 1631, 1640, 1550, 1553, 1643, 1645,
/* 350 */ 1625, 1649, 1652, 1650, 1653, 1632, 1636, 1637, 1642, 1634,
/* 360 */ 1639, 1641, 1646, 1656, 1655, 1658, 1659, 1661, 1663, 1560,
/* 370 */ 1564, 1596, 1605, 1664, 1670, 1565, 1571, 1627, 1638, 1657,
/* 380 */ 1665, 1623, 1702, 1630, 1666, 1667, 1671, 1673, 1703, 1718,
/* 390 */ 1719, 1729, 1730, 1731, 1621, 1622, 1628, 1720, 1713, 1716,
/* 400 */ 1722, 1723, 1733, 1717, 1724, 1727, 1728, 1725, 1740,
};
static const YYACTIONTYPE yy_default[] = {
/* 0 */ 1647, 1647, 1647, 1475, 1240, 1351, 1240, 1240, 1240, 1475,
/* 10 */ 1475, 1475, 1240, 1381, 1381, 1528, 1273, 1240, 1240, 1240,
/* 20 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1474, 1240, 1240,
/* 30 */ 1240, 1240, 1563, 1563, 1240, 1240, 1240, 1240, 1240, 1240,
/* 40 */ 1240, 1240, 1390, 1240, 1397, 1240, 1240, 1240, 1240, 1240,
/* 50 */ 1476, 1477, 1240, 1240, 1240, 1527, 1529, 1492, 1404, 1403,
/* 60 */ 1402, 1401, 1510, 1369, 1395, 1388, 1392, 1470, 1471, 1469,
/* 70 */ 1473, 1477, 1476, 1240, 1391, 1438, 1454, 1437, 1240, 1240,
/* 80 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 90 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 100 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 110 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 120 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 130 */ 1446, 1453, 1452, 1451, 1460, 1450, 1447, 1440, 1439, 1441,
/* 140 */ 1442, 1240, 1240, 1264, 1240, 1240, 1261, 1315, 1240, 1240,
/* 150 */ 1240, 1240, 1240, 1547, 1546, 1240, 1443, 1240, 1273, 1432,
/* 160 */ 1431, 1457, 1444, 1456, 1455, 1535, 1599, 1598, 1493, 1240,
/* 170 */ 1240, 1240, 1240, 1240, 1240, 1563, 1240, 1240, 1240, 1240,
/* 180 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 190 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1371,
/* 200 */ 1563, 1563, 1240, 1273, 1563, 1563, 1372, 1372, 1269, 1269,
/* 210 */ 1375, 1240, 1542, 1342, 1342, 1342, 1342, 1351, 1342, 1240,
/* 220 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 230 */ 1240, 1240, 1240, 1240, 1532, 1530, 1240, 1240, 1240, 1240,
/* 240 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 250 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 260 */ 1240, 1240, 1240, 1347, 1240, 1240, 1240, 1240, 1240, 1240,
/* 270 */ 1240, 1240, 1240, 1240, 1240, 1592, 1240, 1505, 1329, 1347,
/* 280 */ 1347, 1347, 1347, 1349, 1330, 1328, 1341, 1274, 1247, 1639,
/* 290 */ 1407, 1396, 1348, 1396, 1636, 1394, 1407, 1407, 1394, 1407,
/* 300 */ 1348, 1636, 1290, 1615, 1285, 1381, 1381, 1381, 1371, 1371,
/* 310 */ 1371, 1371, 1375, 1375, 1472, 1348, 1341, 1240, 1639, 1639,
/* 320 */ 1357, 1357, 1638, 1638, 1357, 1493, 1623, 1416, 1318, 1324,
/* 330 */ 1324, 1324, 1324, 1357, 1258, 1394, 1623, 1623, 1394, 1416,
/* 340 */ 1318, 1394, 1318, 1394, 1357, 1258, 1509, 1633, 1357, 1258,
/* 350 */ 1483, 1357, 1258, 1357, 1258, 1483, 1316, 1316, 1316, 1305,
/* 360 */ 1240, 1240, 1483, 1316, 1290, 1316, 1305, 1316, 1316, 1581,
/* 370 */ 1240, 1487, 1487, 1483, 1357, 1573, 1573, 1384, 1384, 1389,
/* 380 */ 1375, 1478, 1357, 1240, 1389, 1387, 1385, 1394, 1308, 1595,
/* 390 */ 1595, 1591, 1591, 1591, 1644, 1644, 1542, 1608, 1273, 1273,
/* 400 */ 1273, 1273, 1608, 1292, 1292, 1274, 1274, 1273, 1608, 1240,
/* 410 */ 1240, 1240, 1240, 1240, 1240, 1603, 1240, 1537, 1494, 1361,
/* 420 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 430 */ 1240, 1240, 1240, 1240, 1548, 1240, 1240, 1240, 1240, 1240,
/* 440 */ 1240, 1240, 1240, 1240, 1240, 1421, 1240, 1243, 1539, 1240,
/* 450 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1398, 1399, 1362,
/* 460 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1413, 1240, 1240,
/* 470 */ 1240, 1408, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 480 */ 1635, 1240, 1240, 1240, 1240, 1240, 1240, 1508, 1507, 1240,
/* 490 */ 1240, 1359, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 500 */ 1240, 1240, 1240, 1240, 1240, 1288, 1240, 1240, 1240, 1240,
/* 510 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 520 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1386,
/* 530 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 540 */ 1240, 1240, 1240, 1240, 1578, 1376, 1240, 1240, 1240, 1240,
/* 550 */ 1626, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
/* 560 */ 1240, 1240, 1240, 1240, 1240, 1619, 1332, 1423, 1240, 1422,
/* 570 */ 1426, 1262, 1240, 1252, 1240, 1240,
};
/********** End of lemon-generated parsing tables *****************************/
/* The next table maps tokens (terminal symbols) into fallback tokens.
** If a construct like the following:
**
** %fallback ID X Y Z.
|
| ︙ | ︙ | |||
163348 163349 163350 163351 163352 163353 163354 | /* 252 */ "values", /* 253 */ "nexprlist", /* 254 */ "sclp", /* 255 */ "as", /* 256 */ "seltablist", /* 257 */ "stl_prefix", /* 258 */ "joinop", | | | | | | | | 165121 165122 165123 165124 165125 165126 165127 165128 165129 165130 165131 165132 165133 165134 165135 165136 165137 165138 165139 165140 | /* 252 */ "values", /* 253 */ "nexprlist", /* 254 */ "sclp", /* 255 */ "as", /* 256 */ "seltablist", /* 257 */ "stl_prefix", /* 258 */ "joinop", /* 259 */ "on_using", /* 260 */ "indexed_by", /* 261 */ "exprlist", /* 262 */ "xfullname", /* 263 */ "idlist", /* 264 */ "indexed_opt", /* 265 */ "nulls", /* 266 */ "with", /* 267 */ "where_opt_ret", /* 268 */ "setlist", /* 269 */ "insert_cmd", /* 270 */ "idlist_opt", /* 271 */ "upsert", |
| ︙ | ︙ | |||
163524 163525 163526 163527 163528 163529 163530 | /* 102 */ "selcollist ::= sclp scanpt nm DOT STAR", /* 103 */ "as ::= AS nm", /* 104 */ "as ::=", /* 105 */ "from ::=", /* 106 */ "from ::= FROM seltablist", /* 107 */ "stl_prefix ::= seltablist joinop", /* 108 */ "stl_prefix ::=", | | | | | | | | | | | | | | | | | | | | | | | | | 165297 165298 165299 165300 165301 165302 165303 165304 165305 165306 165307 165308 165309 165310 165311 165312 165313 165314 165315 165316 165317 165318 165319 165320 165321 165322 165323 165324 165325 165326 165327 165328 165329 165330 165331 165332 165333 | /* 102 */ "selcollist ::= sclp scanpt nm DOT STAR", /* 103 */ "as ::= AS nm", /* 104 */ "as ::=", /* 105 */ "from ::=", /* 106 */ "from ::= FROM seltablist", /* 107 */ "stl_prefix ::= seltablist joinop", /* 108 */ "stl_prefix ::=", /* 109 */ "seltablist ::= stl_prefix nm dbnm as on_using", /* 110 */ "seltablist ::= stl_prefix nm dbnm as indexed_by on_using", /* 111 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using", /* 112 */ "seltablist ::= stl_prefix LP select RP as on_using", /* 113 */ "seltablist ::= stl_prefix LP seltablist RP as on_using", /* 114 */ "dbnm ::=", /* 115 */ "dbnm ::= DOT nm", /* 116 */ "fullname ::= nm", /* 117 */ "fullname ::= nm DOT nm", /* 118 */ "xfullname ::= nm", /* 119 */ "xfullname ::= nm DOT nm", /* 120 */ "xfullname ::= nm DOT nm AS nm", /* 121 */ "xfullname ::= nm AS nm", /* 122 */ "joinop ::= COMMA|JOIN", /* 123 */ "joinop ::= JOIN_KW JOIN", /* 124 */ "joinop ::= JOIN_KW nm JOIN", /* 125 */ "joinop ::= JOIN_KW nm nm JOIN", /* 126 */ "on_using ::= ON expr", /* 127 */ "on_using ::= USING LP idlist RP", /* 128 */ "on_using ::=", /* 129 */ "indexed_opt ::=", /* 130 */ "indexed_by ::= INDEXED BY nm", /* 131 */ "indexed_by ::= NOT INDEXED", /* 132 */ "orderby_opt ::=", /* 133 */ "orderby_opt ::= ORDER BY sortlist", /* 134 */ "sortlist ::= sortlist COMMA expr sortorder nulls", /* 135 */ "sortlist ::= expr sortorder nulls", /* 136 */ "sortorder ::= ASC", /* 137 */ "sortorder ::= DESC", /* 138 */ "sortorder ::=", |
| ︙ | ︙ | |||
163624 163625 163626 163627 163628 163629 163630 | /* 202 */ "likeop ::= NOT LIKE_KW|MATCH", /* 203 */ "expr ::= expr likeop expr", /* 204 */ "expr ::= expr likeop expr ESCAPE expr", /* 205 */ "expr ::= expr ISNULL|NOTNULL", /* 206 */ "expr ::= expr NOT NULL", /* 207 */ "expr ::= expr IS expr", /* 208 */ "expr ::= expr IS NOT expr", | | | | | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | 165397 165398 165399 165400 165401 165402 165403 165404 165405 165406 165407 165408 165409 165410 165411 165412 165413 165414 165415 165416 165417 165418 165419 165420 165421 165422 165423 165424 165425 165426 165427 165428 165429 165430 165431 165432 165433 165434 165435 165436 165437 165438 165439 165440 165441 165442 165443 165444 165445 165446 165447 165448 165449 165450 165451 165452 165453 165454 165455 165456 165457 165458 165459 165460 165461 165462 165463 165464 165465 165466 165467 165468 165469 165470 165471 165472 165473 165474 165475 165476 165477 165478 165479 165480 165481 165482 165483 165484 165485 165486 165487 165488 165489 165490 165491 165492 165493 165494 165495 165496 165497 165498 165499 165500 165501 165502 165503 165504 165505 165506 165507 165508 165509 165510 165511 165512 165513 165514 165515 165516 165517 165518 165519 165520 165521 165522 165523 165524 165525 165526 165527 165528 165529 165530 165531 165532 165533 165534 165535 165536 165537 165538 165539 165540 165541 165542 165543 165544 165545 165546 165547 165548 165549 165550 165551 165552 165553 165554 165555 165556 165557 165558 165559 165560 165561 165562 165563 165564 165565 165566 165567 165568 165569 165570 165571 165572 165573 165574 165575 165576 165577 165578 165579 165580 165581 165582 165583 165584 165585 165586 165587 165588 165589 165590 165591 165592 165593 165594 165595 165596 165597 165598 165599 165600 165601 165602 165603 165604 165605 165606 | /* 202 */ "likeop ::= NOT LIKE_KW|MATCH", /* 203 */ "expr ::= expr likeop expr", /* 204 */ "expr ::= expr likeop expr ESCAPE expr", /* 205 */ "expr ::= expr ISNULL|NOTNULL", /* 206 */ "expr ::= expr NOT NULL", /* 207 */ "expr ::= expr IS expr", /* 208 */ "expr ::= expr IS NOT expr", /* 209 */ "expr ::= expr IS NOT DISTINCT FROM expr", /* 210 */ "expr ::= expr IS DISTINCT FROM expr", /* 211 */ "expr ::= NOT expr", /* 212 */ "expr ::= BITNOT expr", /* 213 */ "expr ::= PLUS|MINUS expr", /* 214 */ "expr ::= expr PTR expr", /* 215 */ "between_op ::= BETWEEN", /* 216 */ "between_op ::= NOT BETWEEN", /* 217 */ "expr ::= expr between_op expr AND expr", /* 218 */ "in_op ::= IN", /* 219 */ "in_op ::= NOT IN", /* 220 */ "expr ::= expr in_op LP exprlist RP", /* 221 */ "expr ::= LP select RP", /* 222 */ "expr ::= expr in_op LP select RP", /* 223 */ "expr ::= expr in_op nm dbnm paren_exprlist", /* 224 */ "expr ::= EXISTS LP select RP", /* 225 */ "expr ::= CASE case_operand case_exprlist case_else END", /* 226 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", /* 227 */ "case_exprlist ::= WHEN expr THEN expr", /* 228 */ "case_else ::= ELSE expr", /* 229 */ "case_else ::=", /* 230 */ "case_operand ::= expr", /* 231 */ "case_operand ::=", /* 232 */ "exprlist ::=", /* 233 */ "nexprlist ::= nexprlist COMMA expr", /* 234 */ "nexprlist ::= expr", /* 235 */ "paren_exprlist ::=", /* 236 */ "paren_exprlist ::= LP exprlist RP", /* 237 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", /* 238 */ "uniqueflag ::= UNIQUE", /* 239 */ "uniqueflag ::=", /* 240 */ "eidlist_opt ::=", /* 241 */ "eidlist_opt ::= LP eidlist RP", /* 242 */ "eidlist ::= eidlist COMMA nm collate sortorder", /* 243 */ "eidlist ::= nm collate sortorder", /* 244 */ "collate ::=", /* 245 */ "collate ::= COLLATE ID|STRING", /* 246 */ "cmd ::= DROP INDEX ifexists fullname", /* 247 */ "cmd ::= VACUUM vinto", /* 248 */ "cmd ::= VACUUM nm vinto", /* 249 */ "vinto ::= INTO expr", /* 250 */ "vinto ::=", /* 251 */ "cmd ::= PRAGMA nm dbnm", /* 252 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", /* 253 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", /* 254 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", /* 255 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", /* 256 */ "plus_num ::= PLUS INTEGER|FLOAT", /* 257 */ "minus_num ::= MINUS INTEGER|FLOAT", /* 258 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", /* 259 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", /* 260 */ "trigger_time ::= BEFORE|AFTER", /* 261 */ "trigger_time ::= INSTEAD OF", /* 262 */ "trigger_time ::=", /* 263 */ "trigger_event ::= DELETE|INSERT", /* 264 */ "trigger_event ::= UPDATE", /* 265 */ "trigger_event ::= UPDATE OF idlist", /* 266 */ "when_clause ::=", /* 267 */ "when_clause ::= WHEN expr", /* 268 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", /* 269 */ "trigger_cmd_list ::= trigger_cmd SEMI", /* 270 */ "trnm ::= nm DOT nm", /* 271 */ "tridxby ::= INDEXED BY nm", /* 272 */ "tridxby ::= NOT INDEXED", /* 273 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt", /* 274 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", /* 275 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", /* 276 */ "trigger_cmd ::= scanpt select scanpt", /* 277 */ "expr ::= RAISE LP IGNORE RP", /* 278 */ "expr ::= RAISE LP raisetype COMMA nm RP", /* 279 */ "raisetype ::= ROLLBACK", /* 280 */ "raisetype ::= ABORT", /* 281 */ "raisetype ::= FAIL", /* 282 */ "cmd ::= DROP TRIGGER ifexists fullname", /* 283 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", /* 284 */ "cmd ::= DETACH database_kw_opt expr", /* 285 */ "key_opt ::=", /* 286 */ "key_opt ::= KEY expr", /* 287 */ "cmd ::= REINDEX", /* 288 */ "cmd ::= REINDEX nm dbnm", /* 289 */ "cmd ::= ANALYZE", /* 290 */ "cmd ::= ANALYZE nm dbnm", /* 291 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", /* 292 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", /* 293 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm", /* 294 */ "add_column_fullname ::= fullname", /* 295 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", /* 296 */ "cmd ::= create_vtab", /* 297 */ "cmd ::= create_vtab LP vtabarglist RP", /* 298 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", /* 299 */ "vtabarg ::=", /* 300 */ "vtabargtoken ::= ANY", /* 301 */ "vtabargtoken ::= lp anylist RP", /* 302 */ "lp ::= LP", /* 303 */ "with ::= WITH wqlist", /* 304 */ "with ::= WITH RECURSIVE wqlist", /* 305 */ "wqas ::= AS", /* 306 */ "wqas ::= AS MATERIALIZED", /* 307 */ "wqas ::= AS NOT MATERIALIZED", /* 308 */ "wqitem ::= nm eidlist_opt wqas LP select RP", /* 309 */ "wqlist ::= wqitem", /* 310 */ "wqlist ::= wqlist COMMA wqitem", /* 311 */ "windowdefn_list ::= windowdefn", /* 312 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", /* 313 */ "windowdefn ::= nm AS LP window RP", /* 314 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", /* 315 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", /* 316 */ "window ::= ORDER BY sortlist frame_opt", /* 317 */ "window ::= nm ORDER BY sortlist frame_opt", /* 318 */ "window ::= frame_opt", /* 319 */ "window ::= nm frame_opt", /* 320 */ "frame_opt ::=", /* 321 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", /* 322 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", /* 323 */ "range_or_rows ::= RANGE|ROWS|GROUPS", /* 324 */ "frame_bound_s ::= frame_bound", /* 325 */ "frame_bound_s ::= UNBOUNDED PRECEDING", /* 326 */ "frame_bound_e ::= frame_bound", /* 327 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", /* 328 */ "frame_bound ::= expr PRECEDING|FOLLOWING", /* 329 */ "frame_bound ::= CURRENT ROW", /* 330 */ "frame_exclude_opt ::=", /* 331 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", /* 332 */ "frame_exclude ::= NO OTHERS", /* 333 */ "frame_exclude ::= CURRENT ROW", /* 334 */ "frame_exclude ::= GROUP|TIES", /* 335 */ "window_clause ::= WINDOW windowdefn_list", /* 336 */ "filter_over ::= filter_clause over_clause", /* 337 */ "filter_over ::= over_clause", /* 338 */ "filter_over ::= filter_clause", /* 339 */ "over_clause ::= OVER LP window RP", /* 340 */ "over_clause ::= OVER nm", /* 341 */ "filter_clause ::= FILTER LP WHERE expr RP", /* 342 */ "input ::= cmdlist", /* 343 */ "cmdlist ::= cmdlist ecmd", /* 344 */ "cmdlist ::= ecmd", /* 345 */ "ecmd ::= SEMI", /* 346 */ "ecmd ::= cmdx SEMI", /* 347 */ "ecmd ::= explain cmdx SEMI", /* 348 */ "trans_opt ::=", /* 349 */ "trans_opt ::= TRANSACTION", /* 350 */ "trans_opt ::= TRANSACTION nm", /* 351 */ "savepoint_opt ::= SAVEPOINT", /* 352 */ "savepoint_opt ::=", /* 353 */ "cmd ::= create_table create_table_args", /* 354 */ "table_option_set ::= table_option", /* 355 */ "columnlist ::= columnlist COMMA columnname carglist", /* 356 */ "columnlist ::= columnname carglist", /* 357 */ "nm ::= ID|INDEXED", /* 358 */ "nm ::= STRING", /* 359 */ "nm ::= JOIN_KW", /* 360 */ "typetoken ::= typename", /* 361 */ "typename ::= ID|STRING", /* 362 */ "signed ::= plus_num", /* 363 */ "signed ::= minus_num", /* 364 */ "carglist ::= carglist ccons", /* 365 */ "carglist ::=", /* 366 */ "ccons ::= NULL onconf", /* 367 */ "ccons ::= GENERATED ALWAYS AS generated", /* 368 */ "ccons ::= AS generated", /* 369 */ "conslist_opt ::= COMMA conslist", /* 370 */ "conslist ::= conslist tconscomma tcons", /* 371 */ "conslist ::= tcons", /* 372 */ "tconscomma ::=", /* 373 */ "defer_subclause_opt ::= defer_subclause", /* 374 */ "resolvetype ::= raisetype", /* 375 */ "selectnowith ::= oneselect", /* 376 */ "oneselect ::= values", /* 377 */ "sclp ::= selcollist COMMA", /* 378 */ "as ::= ID|STRING", /* 379 */ "indexed_opt ::= indexed_by", /* 380 */ "returning ::=", /* 381 */ "expr ::= term", /* 382 */ "likeop ::= LIKE_KW|MATCH", /* 383 */ "exprlist ::= nexprlist", /* 384 */ "nmnum ::= plus_num", /* 385 */ "nmnum ::= nm", /* 386 */ "nmnum ::= ON", /* 387 */ "nmnum ::= DELETE", /* 388 */ "nmnum ::= DEFAULT", /* 389 */ "plus_num ::= INTEGER|FLOAT", /* 390 */ "foreach_clause ::=", /* 391 */ "foreach_clause ::= FOR EACH ROW", /* 392 */ "trnm ::= nm", /* 393 */ "tridxby ::=", /* 394 */ "database_kw_opt ::= DATABASE", /* 395 */ "database_kw_opt ::=", /* 396 */ "kwcolumn_opt ::=", /* 397 */ "kwcolumn_opt ::= COLUMNKW", /* 398 */ "vtabarglist ::= vtabarg", /* 399 */ "vtabarglist ::= vtabarglist COMMA vtabarg", /* 400 */ "vtabarg ::= vtabarg vtabargtoken", /* 401 */ "anylist ::=", /* 402 */ "anylist ::= anylist LP anylist RP", /* 403 */ "anylist ::= anylist ANY", /* 404 */ "with ::=", }; #endif /* NDEBUG */ #if YYSTACKDEPTH<=0 /* ** Try to increase the size of the parser stack. Return the number |
| ︙ | ︙ | |||
163954 163955 163956 163957 163958 163959 163960 |
sqlite3SelectDelete(pParse->db, (yypminor->yy47));
}
break;
case 216: /* term */
case 217: /* expr */
case 246: /* where_opt */
case 248: /* having_opt */
| < | | < | | 165730 165731 165732 165733 165734 165735 165736 165737 165738 165739 165740 165741 165742 165743 165744 165745 165746 165747 165748 165749 165750 165751 165752 165753 165754 165755 165756 165757 165758 165759 165760 165761 165762 165763 165764 165765 165766 165767 165768 165769 165770 165771 165772 165773 165774 165775 165776 165777 165778 165779 165780 165781 165782 165783 165784 165785 165786 165787 165788 165789 165790 165791 165792 |
sqlite3SelectDelete(pParse->db, (yypminor->yy47));
}
break;
case 216: /* term */
case 217: /* expr */
case 246: /* where_opt */
case 248: /* having_opt */
case 267: /* where_opt_ret */
case 278: /* case_operand */
case 280: /* case_else */
case 283: /* vinto */
case 290: /* when_clause */
case 295: /* key_opt */
case 311: /* filter_clause */
{
sqlite3ExprDelete(pParse->db, (yypminor->yy528));
}
break;
case 221: /* eidlist_opt */
case 231: /* sortlist */
case 232: /* eidlist */
case 244: /* selcollist */
case 247: /* groupby_opt */
case 249: /* orderby_opt */
case 253: /* nexprlist */
case 254: /* sclp */
case 261: /* exprlist */
case 268: /* setlist */
case 277: /* paren_exprlist */
case 279: /* case_exprlist */
case 310: /* part_opt */
{
sqlite3ExprListDelete(pParse->db, (yypminor->yy322));
}
break;
case 238: /* fullname */
case 245: /* from */
case 256: /* seltablist */
case 257: /* stl_prefix */
case 262: /* xfullname */
{
sqlite3SrcListDelete(pParse->db, (yypminor->yy131));
}
break;
case 241: /* wqlist */
{
sqlite3WithDelete(pParse->db, (yypminor->yy521));
}
break;
case 251: /* window_clause */
case 306: /* windowdefn_list */
{
sqlite3WindowListDelete(pParse->db, (yypminor->yy41));
}
break;
case 263: /* idlist */
case 270: /* idlist_opt */
{
sqlite3IdListDelete(pParse->db, (yypminor->yy254));
}
break;
case 273: /* filter_over */
case 307: /* windowdefn */
|
| ︙ | ︙ | |||
164434 164435 164436 164437 164438 164439 164440 | 244, /* (102) selcollist ::= sclp scanpt nm DOT STAR */ 255, /* (103) as ::= AS nm */ 255, /* (104) as ::= */ 245, /* (105) from ::= */ 245, /* (106) from ::= FROM seltablist */ 257, /* (107) stl_prefix ::= seltablist joinop */ 257, /* (108) stl_prefix ::= */ | | | | | | | | | | | | | | | | | | | | | | | | | 166208 166209 166210 166211 166212 166213 166214 166215 166216 166217 166218 166219 166220 166221 166222 166223 166224 166225 166226 166227 166228 166229 166230 166231 166232 166233 166234 166235 166236 166237 166238 166239 166240 166241 166242 166243 166244 | 244, /* (102) selcollist ::= sclp scanpt nm DOT STAR */ 255, /* (103) as ::= AS nm */ 255, /* (104) as ::= */ 245, /* (105) from ::= */ 245, /* (106) from ::= FROM seltablist */ 257, /* (107) stl_prefix ::= seltablist joinop */ 257, /* (108) stl_prefix ::= */ 256, /* (109) seltablist ::= stl_prefix nm dbnm as on_using */ 256, /* (110) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ 256, /* (111) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ 256, /* (112) seltablist ::= stl_prefix LP select RP as on_using */ 256, /* (113) seltablist ::= stl_prefix LP seltablist RP as on_using */ 200, /* (114) dbnm ::= */ 200, /* (115) dbnm ::= DOT nm */ 238, /* (116) fullname ::= nm */ 238, /* (117) fullname ::= nm DOT nm */ 262, /* (118) xfullname ::= nm */ 262, /* (119) xfullname ::= nm DOT nm */ 262, /* (120) xfullname ::= nm DOT nm AS nm */ 262, /* (121) xfullname ::= nm AS nm */ 258, /* (122) joinop ::= COMMA|JOIN */ 258, /* (123) joinop ::= JOIN_KW JOIN */ 258, /* (124) joinop ::= JOIN_KW nm JOIN */ 258, /* (125) joinop ::= JOIN_KW nm nm JOIN */ 259, /* (126) on_using ::= ON expr */ 259, /* (127) on_using ::= USING LP idlist RP */ 259, /* (128) on_using ::= */ 264, /* (129) indexed_opt ::= */ 260, /* (130) indexed_by ::= INDEXED BY nm */ 260, /* (131) indexed_by ::= NOT INDEXED */ 249, /* (132) orderby_opt ::= */ 249, /* (133) orderby_opt ::= ORDER BY sortlist */ 231, /* (134) sortlist ::= sortlist COMMA expr sortorder nulls */ 231, /* (135) sortlist ::= expr sortorder nulls */ 219, /* (136) sortorder ::= ASC */ 219, /* (137) sortorder ::= DESC */ 219, /* (138) sortorder ::= */ |
| ︙ | ︙ | |||
164500 164501 164502 164503 164504 164505 164506 | 271, /* (168) upsert ::= ON CONFLICT DO NOTHING returning */ 271, /* (169) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ 272, /* (170) returning ::= RETURNING selcollist */ 269, /* (171) insert_cmd ::= INSERT orconf */ 269, /* (172) insert_cmd ::= REPLACE */ 270, /* (173) idlist_opt ::= */ 270, /* (174) idlist_opt ::= LP idlist RP */ | | | | 166274 166275 166276 166277 166278 166279 166280 166281 166282 166283 166284 166285 166286 166287 166288 166289 | 271, /* (168) upsert ::= ON CONFLICT DO NOTHING returning */ 271, /* (169) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ 272, /* (170) returning ::= RETURNING selcollist */ 269, /* (171) insert_cmd ::= INSERT orconf */ 269, /* (172) insert_cmd ::= REPLACE */ 270, /* (173) idlist_opt ::= */ 270, /* (174) idlist_opt ::= LP idlist RP */ 263, /* (175) idlist ::= idlist COMMA nm */ 263, /* (176) idlist ::= nm */ 217, /* (177) expr ::= LP expr RP */ 217, /* (178) expr ::= ID|INDEXED */ 217, /* (179) expr ::= JOIN_KW */ 217, /* (180) expr ::= nm DOT nm */ 217, /* (181) expr ::= nm DOT nm DOT nm */ 216, /* (182) term ::= NULL|FLOAT|BLOB */ 216, /* (183) term ::= STRING */ |
| ︙ | ︙ | |||
164534 164535 164536 164537 164538 164539 164540 | 274, /* (202) likeop ::= NOT LIKE_KW|MATCH */ 217, /* (203) expr ::= expr likeop expr */ 217, /* (204) expr ::= expr likeop expr ESCAPE expr */ 217, /* (205) expr ::= expr ISNULL|NOTNULL */ 217, /* (206) expr ::= expr NOT NULL */ 217, /* (207) expr ::= expr IS expr */ 217, /* (208) expr ::= expr IS NOT expr */ | | | | | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | 166308 166309 166310 166311 166312 166313 166314 166315 166316 166317 166318 166319 166320 166321 166322 166323 166324 166325 166326 166327 166328 166329 166330 166331 166332 166333 166334 166335 166336 166337 166338 166339 166340 166341 166342 166343 166344 166345 166346 166347 166348 166349 166350 166351 166352 166353 166354 166355 166356 166357 166358 166359 166360 166361 166362 166363 166364 166365 166366 166367 166368 166369 166370 166371 166372 166373 166374 166375 166376 166377 166378 166379 166380 166381 166382 166383 166384 166385 166386 166387 166388 166389 166390 166391 166392 166393 166394 166395 166396 166397 166398 166399 166400 166401 166402 166403 166404 166405 166406 166407 166408 166409 166410 166411 166412 166413 166414 166415 166416 166417 166418 166419 166420 166421 166422 166423 166424 166425 166426 166427 166428 166429 166430 166431 166432 166433 166434 166435 166436 166437 166438 166439 166440 166441 166442 166443 166444 166445 166446 166447 166448 166449 166450 166451 166452 166453 166454 166455 166456 166457 166458 166459 166460 166461 166462 166463 166464 166465 166466 166467 166468 166469 166470 166471 166472 166473 166474 166475 166476 166477 166478 166479 166480 166481 166482 166483 166484 166485 166486 166487 166488 166489 166490 166491 166492 166493 166494 166495 166496 166497 166498 166499 166500 166501 166502 166503 166504 166505 166506 166507 166508 166509 166510 166511 166512 166513 166514 166515 166516 166517 |
274, /* (202) likeop ::= NOT LIKE_KW|MATCH */
217, /* (203) expr ::= expr likeop expr */
217, /* (204) expr ::= expr likeop expr ESCAPE expr */
217, /* (205) expr ::= expr ISNULL|NOTNULL */
217, /* (206) expr ::= expr NOT NULL */
217, /* (207) expr ::= expr IS expr */
217, /* (208) expr ::= expr IS NOT expr */
217, /* (209) expr ::= expr IS NOT DISTINCT FROM expr */
217, /* (210) expr ::= expr IS DISTINCT FROM expr */
217, /* (211) expr ::= NOT expr */
217, /* (212) expr ::= BITNOT expr */
217, /* (213) expr ::= PLUS|MINUS expr */
217, /* (214) expr ::= expr PTR expr */
275, /* (215) between_op ::= BETWEEN */
275, /* (216) between_op ::= NOT BETWEEN */
217, /* (217) expr ::= expr between_op expr AND expr */
276, /* (218) in_op ::= IN */
276, /* (219) in_op ::= NOT IN */
217, /* (220) expr ::= expr in_op LP exprlist RP */
217, /* (221) expr ::= LP select RP */
217, /* (222) expr ::= expr in_op LP select RP */
217, /* (223) expr ::= expr in_op nm dbnm paren_exprlist */
217, /* (224) expr ::= EXISTS LP select RP */
217, /* (225) expr ::= CASE case_operand case_exprlist case_else END */
279, /* (226) case_exprlist ::= case_exprlist WHEN expr THEN expr */
279, /* (227) case_exprlist ::= WHEN expr THEN expr */
280, /* (228) case_else ::= ELSE expr */
280, /* (229) case_else ::= */
278, /* (230) case_operand ::= expr */
278, /* (231) case_operand ::= */
261, /* (232) exprlist ::= */
253, /* (233) nexprlist ::= nexprlist COMMA expr */
253, /* (234) nexprlist ::= expr */
277, /* (235) paren_exprlist ::= */
277, /* (236) paren_exprlist ::= LP exprlist RP */
190, /* (237) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
281, /* (238) uniqueflag ::= UNIQUE */
281, /* (239) uniqueflag ::= */
221, /* (240) eidlist_opt ::= */
221, /* (241) eidlist_opt ::= LP eidlist RP */
232, /* (242) eidlist ::= eidlist COMMA nm collate sortorder */
232, /* (243) eidlist ::= nm collate sortorder */
282, /* (244) collate ::= */
282, /* (245) collate ::= COLLATE ID|STRING */
190, /* (246) cmd ::= DROP INDEX ifexists fullname */
190, /* (247) cmd ::= VACUUM vinto */
190, /* (248) cmd ::= VACUUM nm vinto */
283, /* (249) vinto ::= INTO expr */
283, /* (250) vinto ::= */
190, /* (251) cmd ::= PRAGMA nm dbnm */
190, /* (252) cmd ::= PRAGMA nm dbnm EQ nmnum */
190, /* (253) cmd ::= PRAGMA nm dbnm LP nmnum RP */
190, /* (254) cmd ::= PRAGMA nm dbnm EQ minus_num */
190, /* (255) cmd ::= PRAGMA nm dbnm LP minus_num RP */
211, /* (256) plus_num ::= PLUS INTEGER|FLOAT */
212, /* (257) minus_num ::= MINUS INTEGER|FLOAT */
190, /* (258) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
285, /* (259) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
287, /* (260) trigger_time ::= BEFORE|AFTER */
287, /* (261) trigger_time ::= INSTEAD OF */
287, /* (262) trigger_time ::= */
288, /* (263) trigger_event ::= DELETE|INSERT */
288, /* (264) trigger_event ::= UPDATE */
288, /* (265) trigger_event ::= UPDATE OF idlist */
290, /* (266) when_clause ::= */
290, /* (267) when_clause ::= WHEN expr */
286, /* (268) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
286, /* (269) trigger_cmd_list ::= trigger_cmd SEMI */
292, /* (270) trnm ::= nm DOT nm */
293, /* (271) tridxby ::= INDEXED BY nm */
293, /* (272) tridxby ::= NOT INDEXED */
291, /* (273) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
291, /* (274) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
291, /* (275) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
291, /* (276) trigger_cmd ::= scanpt select scanpt */
217, /* (277) expr ::= RAISE LP IGNORE RP */
217, /* (278) expr ::= RAISE LP raisetype COMMA nm RP */
236, /* (279) raisetype ::= ROLLBACK */
236, /* (280) raisetype ::= ABORT */
236, /* (281) raisetype ::= FAIL */
190, /* (282) cmd ::= DROP TRIGGER ifexists fullname */
190, /* (283) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
190, /* (284) cmd ::= DETACH database_kw_opt expr */
295, /* (285) key_opt ::= */
295, /* (286) key_opt ::= KEY expr */
190, /* (287) cmd ::= REINDEX */
190, /* (288) cmd ::= REINDEX nm dbnm */
190, /* (289) cmd ::= ANALYZE */
190, /* (290) cmd ::= ANALYZE nm dbnm */
190, /* (291) cmd ::= ALTER TABLE fullname RENAME TO nm */
190, /* (292) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
190, /* (293) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
296, /* (294) add_column_fullname ::= fullname */
190, /* (295) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
190, /* (296) cmd ::= create_vtab */
190, /* (297) cmd ::= create_vtab LP vtabarglist RP */
298, /* (298) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
300, /* (299) vtabarg ::= */
301, /* (300) vtabargtoken ::= ANY */
301, /* (301) vtabargtoken ::= lp anylist RP */
302, /* (302) lp ::= LP */
266, /* (303) with ::= WITH wqlist */
266, /* (304) with ::= WITH RECURSIVE wqlist */
305, /* (305) wqas ::= AS */
305, /* (306) wqas ::= AS MATERIALIZED */
305, /* (307) wqas ::= AS NOT MATERIALIZED */
304, /* (308) wqitem ::= nm eidlist_opt wqas LP select RP */
241, /* (309) wqlist ::= wqitem */
241, /* (310) wqlist ::= wqlist COMMA wqitem */
306, /* (311) windowdefn_list ::= windowdefn */
306, /* (312) windowdefn_list ::= windowdefn_list COMMA windowdefn */
307, /* (313) windowdefn ::= nm AS LP window RP */
308, /* (314) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
308, /* (315) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
308, /* (316) window ::= ORDER BY sortlist frame_opt */
308, /* (317) window ::= nm ORDER BY sortlist frame_opt */
308, /* (318) window ::= frame_opt */
308, /* (319) window ::= nm frame_opt */
309, /* (320) frame_opt ::= */
309, /* (321) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
309, /* (322) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
313, /* (323) range_or_rows ::= RANGE|ROWS|GROUPS */
315, /* (324) frame_bound_s ::= frame_bound */
315, /* (325) frame_bound_s ::= UNBOUNDED PRECEDING */
316, /* (326) frame_bound_e ::= frame_bound */
316, /* (327) frame_bound_e ::= UNBOUNDED FOLLOWING */
314, /* (328) frame_bound ::= expr PRECEDING|FOLLOWING */
314, /* (329) frame_bound ::= CURRENT ROW */
317, /* (330) frame_exclude_opt ::= */
317, /* (331) frame_exclude_opt ::= EXCLUDE frame_exclude */
318, /* (332) frame_exclude ::= NO OTHERS */
318, /* (333) frame_exclude ::= CURRENT ROW */
318, /* (334) frame_exclude ::= GROUP|TIES */
251, /* (335) window_clause ::= WINDOW windowdefn_list */
273, /* (336) filter_over ::= filter_clause over_clause */
273, /* (337) filter_over ::= over_clause */
273, /* (338) filter_over ::= filter_clause */
312, /* (339) over_clause ::= OVER LP window RP */
312, /* (340) over_clause ::= OVER nm */
311, /* (341) filter_clause ::= FILTER LP WHERE expr RP */
185, /* (342) input ::= cmdlist */
186, /* (343) cmdlist ::= cmdlist ecmd */
186, /* (344) cmdlist ::= ecmd */
187, /* (345) ecmd ::= SEMI */
187, /* (346) ecmd ::= cmdx SEMI */
187, /* (347) ecmd ::= explain cmdx SEMI */
192, /* (348) trans_opt ::= */
192, /* (349) trans_opt ::= TRANSACTION */
192, /* (350) trans_opt ::= TRANSACTION nm */
194, /* (351) savepoint_opt ::= SAVEPOINT */
194, /* (352) savepoint_opt ::= */
190, /* (353) cmd ::= create_table create_table_args */
203, /* (354) table_option_set ::= table_option */
201, /* (355) columnlist ::= columnlist COMMA columnname carglist */
201, /* (356) columnlist ::= columnname carglist */
193, /* (357) nm ::= ID|INDEXED */
193, /* (358) nm ::= STRING */
193, /* (359) nm ::= JOIN_KW */
208, /* (360) typetoken ::= typename */
209, /* (361) typename ::= ID|STRING */
210, /* (362) signed ::= plus_num */
210, /* (363) signed ::= minus_num */
207, /* (364) carglist ::= carglist ccons */
207, /* (365) carglist ::= */
215, /* (366) ccons ::= NULL onconf */
215, /* (367) ccons ::= GENERATED ALWAYS AS generated */
215, /* (368) ccons ::= AS generated */
202, /* (369) conslist_opt ::= COMMA conslist */
228, /* (370) conslist ::= conslist tconscomma tcons */
228, /* (371) conslist ::= tcons */
229, /* (372) tconscomma ::= */
233, /* (373) defer_subclause_opt ::= defer_subclause */
235, /* (374) resolvetype ::= raisetype */
239, /* (375) selectnowith ::= oneselect */
240, /* (376) oneselect ::= values */
254, /* (377) sclp ::= selcollist COMMA */
255, /* (378) as ::= ID|STRING */
264, /* (379) indexed_opt ::= indexed_by */
272, /* (380) returning ::= */
217, /* (381) expr ::= term */
274, /* (382) likeop ::= LIKE_KW|MATCH */
261, /* (383) exprlist ::= nexprlist */
284, /* (384) nmnum ::= plus_num */
284, /* (385) nmnum ::= nm */
284, /* (386) nmnum ::= ON */
284, /* (387) nmnum ::= DELETE */
284, /* (388) nmnum ::= DEFAULT */
211, /* (389) plus_num ::= INTEGER|FLOAT */
289, /* (390) foreach_clause ::= */
289, /* (391) foreach_clause ::= FOR EACH ROW */
292, /* (392) trnm ::= nm */
293, /* (393) tridxby ::= */
294, /* (394) database_kw_opt ::= DATABASE */
294, /* (395) database_kw_opt ::= */
297, /* (396) kwcolumn_opt ::= */
297, /* (397) kwcolumn_opt ::= COLUMNKW */
299, /* (398) vtabarglist ::= vtabarg */
299, /* (399) vtabarglist ::= vtabarglist COMMA vtabarg */
300, /* (400) vtabarg ::= vtabarg vtabargtoken */
303, /* (401) anylist ::= */
303, /* (402) anylist ::= anylist LP anylist RP */
303, /* (403) anylist ::= anylist ANY */
266, /* (404) with ::= */
};
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
** of symbols on the right-hand side of that rule. */
static const signed char yyRuleInfoNRhs[] = {
-1, /* (0) explain ::= EXPLAIN */
-3, /* (1) explain ::= EXPLAIN QUERY PLAN */
|
| ︙ | ︙ | |||
164841 164842 164843 164844 164845 164846 164847 |
-5, /* (102) selcollist ::= sclp scanpt nm DOT STAR */
-2, /* (103) as ::= AS nm */
0, /* (104) as ::= */
0, /* (105) from ::= */
-2, /* (106) from ::= FROM seltablist */
-2, /* (107) stl_prefix ::= seltablist joinop */
0, /* (108) stl_prefix ::= */
| | > | | | | | | | | | | | | | | | < | | | | | | | 166618 166619 166620 166621 166622 166623 166624 166625 166626 166627 166628 166629 166630 166631 166632 166633 166634 166635 166636 166637 166638 166639 166640 166641 166642 166643 166644 166645 166646 166647 166648 166649 166650 166651 166652 166653 166654 |
-5, /* (102) selcollist ::= sclp scanpt nm DOT STAR */
-2, /* (103) as ::= AS nm */
0, /* (104) as ::= */
0, /* (105) from ::= */
-2, /* (106) from ::= FROM seltablist */
-2, /* (107) stl_prefix ::= seltablist joinop */
0, /* (108) stl_prefix ::= */
-5, /* (109) seltablist ::= stl_prefix nm dbnm as on_using */
-6, /* (110) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */
-8, /* (111) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */
-6, /* (112) seltablist ::= stl_prefix LP select RP as on_using */
-6, /* (113) seltablist ::= stl_prefix LP seltablist RP as on_using */
0, /* (114) dbnm ::= */
-2, /* (115) dbnm ::= DOT nm */
-1, /* (116) fullname ::= nm */
-3, /* (117) fullname ::= nm DOT nm */
-1, /* (118) xfullname ::= nm */
-3, /* (119) xfullname ::= nm DOT nm */
-5, /* (120) xfullname ::= nm DOT nm AS nm */
-3, /* (121) xfullname ::= nm AS nm */
-1, /* (122) joinop ::= COMMA|JOIN */
-2, /* (123) joinop ::= JOIN_KW JOIN */
-3, /* (124) joinop ::= JOIN_KW nm JOIN */
-4, /* (125) joinop ::= JOIN_KW nm nm JOIN */
-2, /* (126) on_using ::= ON expr */
-4, /* (127) on_using ::= USING LP idlist RP */
0, /* (128) on_using ::= */
0, /* (129) indexed_opt ::= */
-3, /* (130) indexed_by ::= INDEXED BY nm */
-2, /* (131) indexed_by ::= NOT INDEXED */
0, /* (132) orderby_opt ::= */
-3, /* (133) orderby_opt ::= ORDER BY sortlist */
-5, /* (134) sortlist ::= sortlist COMMA expr sortorder nulls */
-3, /* (135) sortlist ::= expr sortorder nulls */
-1, /* (136) sortorder ::= ASC */
-1, /* (137) sortorder ::= DESC */
0, /* (138) sortorder ::= */
|
| ︙ | ︙ | |||
164941 164942 164943 164944 164945 164946 164947 | -2, /* (202) likeop ::= NOT LIKE_KW|MATCH */ -3, /* (203) expr ::= expr likeop expr */ -5, /* (204) expr ::= expr likeop expr ESCAPE expr */ -2, /* (205) expr ::= expr ISNULL|NOTNULL */ -3, /* (206) expr ::= expr NOT NULL */ -3, /* (207) expr ::= expr IS expr */ -4, /* (208) expr ::= expr IS NOT expr */ | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | 166718 166719 166720 166721 166722 166723 166724 166725 166726 166727 166728 166729 166730 166731 166732 166733 166734 166735 166736 166737 166738 166739 166740 166741 166742 166743 166744 166745 166746 166747 166748 166749 166750 166751 166752 166753 166754 166755 166756 166757 166758 166759 166760 166761 166762 166763 166764 166765 166766 166767 166768 166769 166770 166771 166772 166773 166774 166775 166776 166777 166778 166779 166780 166781 166782 166783 166784 166785 166786 166787 166788 166789 166790 166791 166792 166793 166794 166795 166796 166797 166798 166799 166800 166801 166802 166803 166804 166805 166806 166807 166808 166809 166810 166811 166812 166813 166814 166815 166816 166817 166818 166819 166820 166821 166822 166823 166824 166825 166826 166827 166828 166829 166830 166831 166832 166833 166834 166835 166836 166837 166838 166839 166840 166841 166842 166843 166844 166845 166846 166847 166848 166849 166850 166851 166852 166853 166854 166855 166856 166857 166858 166859 166860 166861 166862 166863 166864 166865 166866 166867 166868 166869 166870 166871 166872 166873 166874 166875 166876 166877 166878 166879 166880 166881 166882 166883 166884 166885 166886 166887 166888 166889 166890 166891 166892 166893 166894 166895 166896 166897 166898 166899 166900 166901 166902 166903 166904 166905 166906 166907 166908 166909 166910 166911 166912 166913 166914 166915 166916 166917 166918 166919 166920 166921 166922 166923 166924 166925 166926 166927 |
-2, /* (202) likeop ::= NOT LIKE_KW|MATCH */
-3, /* (203) expr ::= expr likeop expr */
-5, /* (204) expr ::= expr likeop expr ESCAPE expr */
-2, /* (205) expr ::= expr ISNULL|NOTNULL */
-3, /* (206) expr ::= expr NOT NULL */
-3, /* (207) expr ::= expr IS expr */
-4, /* (208) expr ::= expr IS NOT expr */
-6, /* (209) expr ::= expr IS NOT DISTINCT FROM expr */
-5, /* (210) expr ::= expr IS DISTINCT FROM expr */
-2, /* (211) expr ::= NOT expr */
-2, /* (212) expr ::= BITNOT expr */
-2, /* (213) expr ::= PLUS|MINUS expr */
-3, /* (214) expr ::= expr PTR expr */
-1, /* (215) between_op ::= BETWEEN */
-2, /* (216) between_op ::= NOT BETWEEN */
-5, /* (217) expr ::= expr between_op expr AND expr */
-1, /* (218) in_op ::= IN */
-2, /* (219) in_op ::= NOT IN */
-5, /* (220) expr ::= expr in_op LP exprlist RP */
-3, /* (221) expr ::= LP select RP */
-5, /* (222) expr ::= expr in_op LP select RP */
-5, /* (223) expr ::= expr in_op nm dbnm paren_exprlist */
-4, /* (224) expr ::= EXISTS LP select RP */
-5, /* (225) expr ::= CASE case_operand case_exprlist case_else END */
-5, /* (226) case_exprlist ::= case_exprlist WHEN expr THEN expr */
-4, /* (227) case_exprlist ::= WHEN expr THEN expr */
-2, /* (228) case_else ::= ELSE expr */
0, /* (229) case_else ::= */
-1, /* (230) case_operand ::= expr */
0, /* (231) case_operand ::= */
0, /* (232) exprlist ::= */
-3, /* (233) nexprlist ::= nexprlist COMMA expr */
-1, /* (234) nexprlist ::= expr */
0, /* (235) paren_exprlist ::= */
-3, /* (236) paren_exprlist ::= LP exprlist RP */
-12, /* (237) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
-1, /* (238) uniqueflag ::= UNIQUE */
0, /* (239) uniqueflag ::= */
0, /* (240) eidlist_opt ::= */
-3, /* (241) eidlist_opt ::= LP eidlist RP */
-5, /* (242) eidlist ::= eidlist COMMA nm collate sortorder */
-3, /* (243) eidlist ::= nm collate sortorder */
0, /* (244) collate ::= */
-2, /* (245) collate ::= COLLATE ID|STRING */
-4, /* (246) cmd ::= DROP INDEX ifexists fullname */
-2, /* (247) cmd ::= VACUUM vinto */
-3, /* (248) cmd ::= VACUUM nm vinto */
-2, /* (249) vinto ::= INTO expr */
0, /* (250) vinto ::= */
-3, /* (251) cmd ::= PRAGMA nm dbnm */
-5, /* (252) cmd ::= PRAGMA nm dbnm EQ nmnum */
-6, /* (253) cmd ::= PRAGMA nm dbnm LP nmnum RP */
-5, /* (254) cmd ::= PRAGMA nm dbnm EQ minus_num */
-6, /* (255) cmd ::= PRAGMA nm dbnm LP minus_num RP */
-2, /* (256) plus_num ::= PLUS INTEGER|FLOAT */
-2, /* (257) minus_num ::= MINUS INTEGER|FLOAT */
-5, /* (258) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
-11, /* (259) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
-1, /* (260) trigger_time ::= BEFORE|AFTER */
-2, /* (261) trigger_time ::= INSTEAD OF */
0, /* (262) trigger_time ::= */
-1, /* (263) trigger_event ::= DELETE|INSERT */
-1, /* (264) trigger_event ::= UPDATE */
-3, /* (265) trigger_event ::= UPDATE OF idlist */
0, /* (266) when_clause ::= */
-2, /* (267) when_clause ::= WHEN expr */
-3, /* (268) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
-2, /* (269) trigger_cmd_list ::= trigger_cmd SEMI */
-3, /* (270) trnm ::= nm DOT nm */
-3, /* (271) tridxby ::= INDEXED BY nm */
-2, /* (272) tridxby ::= NOT INDEXED */
-9, /* (273) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
-8, /* (274) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
-6, /* (275) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
-3, /* (276) trigger_cmd ::= scanpt select scanpt */
-4, /* (277) expr ::= RAISE LP IGNORE RP */
-6, /* (278) expr ::= RAISE LP raisetype COMMA nm RP */
-1, /* (279) raisetype ::= ROLLBACK */
-1, /* (280) raisetype ::= ABORT */
-1, /* (281) raisetype ::= FAIL */
-4, /* (282) cmd ::= DROP TRIGGER ifexists fullname */
-6, /* (283) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
-3, /* (284) cmd ::= DETACH database_kw_opt expr */
0, /* (285) key_opt ::= */
-2, /* (286) key_opt ::= KEY expr */
-1, /* (287) cmd ::= REINDEX */
-3, /* (288) cmd ::= REINDEX nm dbnm */
-1, /* (289) cmd ::= ANALYZE */
-3, /* (290) cmd ::= ANALYZE nm dbnm */
-6, /* (291) cmd ::= ALTER TABLE fullname RENAME TO nm */
-7, /* (292) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
-6, /* (293) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
-1, /* (294) add_column_fullname ::= fullname */
-8, /* (295) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
-1, /* (296) cmd ::= create_vtab */
-4, /* (297) cmd ::= create_vtab LP vtabarglist RP */
-8, /* (298) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
0, /* (299) vtabarg ::= */
-1, /* (300) vtabargtoken ::= ANY */
-3, /* (301) vtabargtoken ::= lp anylist RP */
-1, /* (302) lp ::= LP */
-2, /* (303) with ::= WITH wqlist */
-3, /* (304) with ::= WITH RECURSIVE wqlist */
-1, /* (305) wqas ::= AS */
-2, /* (306) wqas ::= AS MATERIALIZED */
-3, /* (307) wqas ::= AS NOT MATERIALIZED */
-6, /* (308) wqitem ::= nm eidlist_opt wqas LP select RP */
-1, /* (309) wqlist ::= wqitem */
-3, /* (310) wqlist ::= wqlist COMMA wqitem */
-1, /* (311) windowdefn_list ::= windowdefn */
-3, /* (312) windowdefn_list ::= windowdefn_list COMMA windowdefn */
-5, /* (313) windowdefn ::= nm AS LP window RP */
-5, /* (314) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
-6, /* (315) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
-4, /* (316) window ::= ORDER BY sortlist frame_opt */
-5, /* (317) window ::= nm ORDER BY sortlist frame_opt */
-1, /* (318) window ::= frame_opt */
-2, /* (319) window ::= nm frame_opt */
0, /* (320) frame_opt ::= */
-3, /* (321) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
-6, /* (322) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
-1, /* (323) range_or_rows ::= RANGE|ROWS|GROUPS */
-1, /* (324) frame_bound_s ::= frame_bound */
-2, /* (325) frame_bound_s ::= UNBOUNDED PRECEDING */
-1, /* (326) frame_bound_e ::= frame_bound */
-2, /* (327) frame_bound_e ::= UNBOUNDED FOLLOWING */
-2, /* (328) frame_bound ::= expr PRECEDING|FOLLOWING */
-2, /* (329) frame_bound ::= CURRENT ROW */
0, /* (330) frame_exclude_opt ::= */
-2, /* (331) frame_exclude_opt ::= EXCLUDE frame_exclude */
-2, /* (332) frame_exclude ::= NO OTHERS */
-2, /* (333) frame_exclude ::= CURRENT ROW */
-1, /* (334) frame_exclude ::= GROUP|TIES */
-2, /* (335) window_clause ::= WINDOW windowdefn_list */
-2, /* (336) filter_over ::= filter_clause over_clause */
-1, /* (337) filter_over ::= over_clause */
-1, /* (338) filter_over ::= filter_clause */
-4, /* (339) over_clause ::= OVER LP window RP */
-2, /* (340) over_clause ::= OVER nm */
-5, /* (341) filter_clause ::= FILTER LP WHERE expr RP */
-1, /* (342) input ::= cmdlist */
-2, /* (343) cmdlist ::= cmdlist ecmd */
-1, /* (344) cmdlist ::= ecmd */
-1, /* (345) ecmd ::= SEMI */
-2, /* (346) ecmd ::= cmdx SEMI */
-3, /* (347) ecmd ::= explain cmdx SEMI */
0, /* (348) trans_opt ::= */
-1, /* (349) trans_opt ::= TRANSACTION */
-2, /* (350) trans_opt ::= TRANSACTION nm */
-1, /* (351) savepoint_opt ::= SAVEPOINT */
0, /* (352) savepoint_opt ::= */
-2, /* (353) cmd ::= create_table create_table_args */
-1, /* (354) table_option_set ::= table_option */
-4, /* (355) columnlist ::= columnlist COMMA columnname carglist */
-2, /* (356) columnlist ::= columnname carglist */
-1, /* (357) nm ::= ID|INDEXED */
-1, /* (358) nm ::= STRING */
-1, /* (359) nm ::= JOIN_KW */
-1, /* (360) typetoken ::= typename */
-1, /* (361) typename ::= ID|STRING */
-1, /* (362) signed ::= plus_num */
-1, /* (363) signed ::= minus_num */
-2, /* (364) carglist ::= carglist ccons */
0, /* (365) carglist ::= */
-2, /* (366) ccons ::= NULL onconf */
-4, /* (367) ccons ::= GENERATED ALWAYS AS generated */
-2, /* (368) ccons ::= AS generated */
-2, /* (369) conslist_opt ::= COMMA conslist */
-3, /* (370) conslist ::= conslist tconscomma tcons */
-1, /* (371) conslist ::= tcons */
0, /* (372) tconscomma ::= */
-1, /* (373) defer_subclause_opt ::= defer_subclause */
-1, /* (374) resolvetype ::= raisetype */
-1, /* (375) selectnowith ::= oneselect */
-1, /* (376) oneselect ::= values */
-2, /* (377) sclp ::= selcollist COMMA */
-1, /* (378) as ::= ID|STRING */
-1, /* (379) indexed_opt ::= indexed_by */
0, /* (380) returning ::= */
-1, /* (381) expr ::= term */
-1, /* (382) likeop ::= LIKE_KW|MATCH */
-1, /* (383) exprlist ::= nexprlist */
-1, /* (384) nmnum ::= plus_num */
-1, /* (385) nmnum ::= nm */
-1, /* (386) nmnum ::= ON */
-1, /* (387) nmnum ::= DELETE */
-1, /* (388) nmnum ::= DEFAULT */
-1, /* (389) plus_num ::= INTEGER|FLOAT */
0, /* (390) foreach_clause ::= */
-3, /* (391) foreach_clause ::= FOR EACH ROW */
-1, /* (392) trnm ::= nm */
0, /* (393) tridxby ::= */
-1, /* (394) database_kw_opt ::= DATABASE */
0, /* (395) database_kw_opt ::= */
0, /* (396) kwcolumn_opt ::= */
-1, /* (397) kwcolumn_opt ::= COLUMNKW */
-1, /* (398) vtabarglist ::= vtabarg */
-3, /* (399) vtabarglist ::= vtabarglist COMMA vtabarg */
-2, /* (400) vtabarg ::= vtabarg vtabargtoken */
0, /* (401) anylist ::= */
-4, /* (402) anylist ::= anylist LP anylist RP */
-2, /* (403) anylist ::= anylist ANY */
0, /* (404) with ::= */
};
static void yy_accept(yyParser*); /* Forward Declaration */
/*
** Perform a reduce action and the shift that must immediately
** follow the reduce.
|
| ︙ | ︙ | |||
165193 165194 165195 165196 165197 165198 165199 |
break;
case 4: /* transtype ::= */
{yymsp[1].minor.yy394 = TK_DEFERRED;}
break;
case 5: /* transtype ::= DEFERRED */
case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6);
case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7);
| | | 166973 166974 166975 166976 166977 166978 166979 166980 166981 166982 166983 166984 166985 166986 166987 |
break;
case 4: /* transtype ::= */
{yymsp[1].minor.yy394 = TK_DEFERRED;}
break;
case 5: /* transtype ::= DEFERRED */
case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6);
case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7);
case 323: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==323);
{yymsp[0].minor.yy394 = yymsp[0].major; /*A-overwrites-X*/}
break;
case 8: /* cmd ::= COMMIT|END trans_opt */
case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9);
{sqlite3EndTransaction(pParse,yymsp[-1].major);}
break;
case 10: /* cmd ::= SAVEPOINT nm */
|
| ︙ | ︙ | |||
165230 165231 165232 165233 165234 165235 165236 |
case 15: /* ifnotexists ::= */
case 18: /* temp ::= */ yytestcase(yyruleno==18);
case 47: /* autoinc ::= */ yytestcase(yyruleno==47);
case 62: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==62);
case 72: /* defer_subclause_opt ::= */ yytestcase(yyruleno==72);
case 81: /* ifexists ::= */ yytestcase(yyruleno==81);
case 98: /* distinct ::= */ yytestcase(yyruleno==98);
| | | 167010 167011 167012 167013 167014 167015 167016 167017 167018 167019 167020 167021 167022 167023 167024 |
case 15: /* ifnotexists ::= */
case 18: /* temp ::= */ yytestcase(yyruleno==18);
case 47: /* autoinc ::= */ yytestcase(yyruleno==47);
case 62: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==62);
case 72: /* defer_subclause_opt ::= */ yytestcase(yyruleno==72);
case 81: /* ifexists ::= */ yytestcase(yyruleno==81);
case 98: /* distinct ::= */ yytestcase(yyruleno==98);
case 244: /* collate ::= */ yytestcase(yyruleno==244);
{yymsp[1].minor.yy394 = 0;}
break;
case 16: /* ifnotexists ::= IF NOT EXISTS */
{yymsp[-2].minor.yy394 = 1;}
break;
case 17: /* temp ::= TEMP */
{yymsp[0].minor.yy394 = pParse->db->init.busy==0;}
|
| ︙ | ︙ | |||
165414 165415 165416 165417 165418 165419 165420 |
case 61: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
case 76: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==76);
case 171: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==171);
{yymsp[-1].minor.yy394 = yymsp[0].minor.yy394;}
break;
case 63: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
case 80: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==80);
| | | | | 167194 167195 167196 167197 167198 167199 167200 167201 167202 167203 167204 167205 167206 167207 167208 167209 167210 |
case 61: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
case 76: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==76);
case 171: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==171);
{yymsp[-1].minor.yy394 = yymsp[0].minor.yy394;}
break;
case 63: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
case 80: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==80);
case 216: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==216);
case 219: /* in_op ::= NOT IN */ yytestcase(yyruleno==219);
case 245: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==245);
{yymsp[-1].minor.yy394 = 1;}
break;
case 64: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
{yymsp[-1].minor.yy394 = 0;}
break;
case 66: /* tconscomma ::= COMMA */
{pParse->constraintName.n = 0;}
|
| ︙ | ︙ | |||
165501 165502 165503 165504 165505 165506 165507 |
Select *pRhs = yymsp[0].minor.yy47;
Select *pLhs = yymsp[-2].minor.yy47;
if( pRhs && pRhs->pPrior ){
SrcList *pFrom;
Token x;
x.n = 0;
parserDoubleLinkSelect(pParse, pRhs);
| | | 167281 167282 167283 167284 167285 167286 167287 167288 167289 167290 167291 167292 167293 167294 167295 |
Select *pRhs = yymsp[0].minor.yy47;
Select *pLhs = yymsp[-2].minor.yy47;
if( pRhs && pRhs->pPrior ){
SrcList *pFrom;
Token x;
x.n = 0;
parserDoubleLinkSelect(pParse, pRhs);
pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0);
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
}
if( pRhs ){
pRhs->op = (u8)yymsp[-1].minor.yy394;
pRhs->pPrior = pLhs;
if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
pRhs->selFlags &= ~SF_MultiValue;
|
| ︙ | ︙ | |||
165566 165567 165568 165569 165570 165571 165572 |
break;
case 97: /* distinct ::= ALL */
{yymsp[0].minor.yy394 = SF_All;}
break;
case 99: /* sclp ::= */
case 132: /* orderby_opt ::= */ yytestcase(yyruleno==132);
case 142: /* groupby_opt ::= */ yytestcase(yyruleno==142);
| | | | | 167346 167347 167348 167349 167350 167351 167352 167353 167354 167355 167356 167357 167358 167359 167360 167361 167362 |
break;
case 97: /* distinct ::= ALL */
{yymsp[0].minor.yy394 = SF_All;}
break;
case 99: /* sclp ::= */
case 132: /* orderby_opt ::= */ yytestcase(yyruleno==132);
case 142: /* groupby_opt ::= */ yytestcase(yyruleno==142);
case 232: /* exprlist ::= */ yytestcase(yyruleno==232);
case 235: /* paren_exprlist ::= */ yytestcase(yyruleno==235);
case 240: /* eidlist_opt ::= */ yytestcase(yyruleno==240);
{yymsp[1].minor.yy322 = 0;}
break;
case 100: /* selcollist ::= sclp scanpt expr scanpt as */
{
yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[-2].minor.yy528);
if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[0].minor.yy0, 1);
sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy322,yymsp[-3].minor.yy522,yymsp[-1].minor.yy522);
|
| ︙ | ︙ | |||
165593 165594 165595 165596 165597 165598 165599 |
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
Expr *pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0);
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, pDot);
}
break;
case 103: /* as ::= AS nm */
| | | | | | | > > > > > | | | | | | | | | | | | | | > > > | | | | | | | | | | | | | | | | | < < < < < | | < < < < < < > > | | | | < < < < < < < | 167373 167374 167375 167376 167377 167378 167379 167380 167381 167382 167383 167384 167385 167386 167387 167388 167389 167390 167391 167392 167393 167394 167395 167396 167397 167398 167399 167400 167401 167402 167403 167404 167405 167406 167407 167408 167409 167410 167411 167412 167413 167414 167415 167416 167417 167418 167419 167420 167421 167422 167423 167424 167425 167426 167427 167428 167429 167430 167431 167432 167433 167434 167435 167436 167437 167438 167439 167440 167441 167442 167443 167444 167445 167446 167447 167448 167449 167450 167451 167452 167453 167454 167455 167456 167457 167458 167459 167460 167461 167462 167463 167464 167465 167466 167467 167468 167469 167470 167471 167472 167473 167474 167475 167476 167477 167478 167479 167480 167481 167482 167483 167484 167485 167486 167487 167488 167489 167490 167491 167492 167493 167494 167495 167496 167497 167498 167499 167500 167501 167502 167503 167504 167505 167506 167507 167508 167509 167510 167511 167512 167513 167514 167515 167516 167517 167518 167519 167520 167521 167522 167523 167524 |
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
Expr *pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0);
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, pDot);
}
break;
case 103: /* as ::= AS nm */
case 115: /* dbnm ::= DOT nm */ yytestcase(yyruleno==115);
case 256: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==256);
case 257: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==257);
{yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
break;
case 105: /* from ::= */
case 108: /* stl_prefix ::= */ yytestcase(yyruleno==108);
{yymsp[1].minor.yy131 = 0;}
break;
case 106: /* from ::= FROM seltablist */
{
yymsp[-1].minor.yy131 = yymsp[0].minor.yy131;
sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy131);
}
break;
case 107: /* stl_prefix ::= seltablist joinop */
{
if( ALWAYS(yymsp[-1].minor.yy131 && yymsp[-1].minor.yy131->nSrc>0) ) yymsp[-1].minor.yy131->a[yymsp[-1].minor.yy131->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy394;
}
break;
case 109: /* seltablist ::= stl_prefix nm dbnm as on_using */
{
yymsp[-4].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy131,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy561);
}
break;
case 110: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */
{
yymsp[-5].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy561);
sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy131, &yymsp[-1].minor.yy0);
}
break;
case 111: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */
{
yymsp[-7].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy131,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy561);
sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy131, yymsp[-3].minor.yy322);
}
break;
case 112: /* seltablist ::= stl_prefix LP select RP as on_using */
{
yymsp[-5].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy47,&yymsp[0].minor.yy561);
}
break;
case 113: /* seltablist ::= stl_prefix LP seltablist RP as on_using */
{
if( yymsp[-5].minor.yy131==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy561.pOn==0 && yymsp[0].minor.yy561.pUsing==0 ){
yymsp[-5].minor.yy131 = yymsp[-3].minor.yy131;
}else if( yymsp[-3].minor.yy131->nSrc==1 ){
yymsp[-5].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy561);
if( yymsp[-5].minor.yy131 ){
SrcItem *pNew = &yymsp[-5].minor.yy131->a[yymsp[-5].minor.yy131->nSrc-1];
SrcItem *pOld = yymsp[-3].minor.yy131->a;
pNew->zName = pOld->zName;
pNew->zDatabase = pOld->zDatabase;
pNew->pSelect = pOld->pSelect;
if( pNew->pSelect && (pNew->pSelect->selFlags & SF_NestedFrom)!=0 ){
pNew->fg.isNestedFrom = 1;
}
if( pOld->fg.isTabFunc ){
pNew->u1.pFuncArg = pOld->u1.pFuncArg;
pOld->u1.pFuncArg = 0;
pOld->fg.isTabFunc = 0;
pNew->fg.isTabFunc = 1;
}
pOld->zName = pOld->zDatabase = 0;
pOld->pSelect = 0;
}
sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy131);
}else{
Select *pSubquery;
sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy131);
pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy131,0,0,0,0,SF_NestedFrom,0);
yymsp[-5].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy561);
}
}
break;
case 114: /* dbnm ::= */
case 129: /* indexed_opt ::= */ yytestcase(yyruleno==129);
{yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;}
break;
case 116: /* fullname ::= nm */
{
yylhsminor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
if( IN_RENAME_OBJECT && yylhsminor.yy131 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy131->a[0].zName, &yymsp[0].minor.yy0);
}
yymsp[0].minor.yy131 = yylhsminor.yy131;
break;
case 117: /* fullname ::= nm DOT nm */
{
yylhsminor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
if( IN_RENAME_OBJECT && yylhsminor.yy131 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy131->a[0].zName, &yymsp[0].minor.yy0);
}
yymsp[-2].minor.yy131 = yylhsminor.yy131;
break;
case 118: /* xfullname ::= nm */
{yymsp[0].minor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
break;
case 119: /* xfullname ::= nm DOT nm */
{yymsp[-2].minor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
case 120: /* xfullname ::= nm DOT nm AS nm */
{
yymsp[-4].minor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
if( yymsp[-4].minor.yy131 ) yymsp[-4].minor.yy131->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
case 121: /* xfullname ::= nm AS nm */
{
yymsp[-2].minor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
if( yymsp[-2].minor.yy131 ) yymsp[-2].minor.yy131->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
case 122: /* joinop ::= COMMA|JOIN */
{ yymsp[0].minor.yy394 = JT_INNER; }
break;
case 123: /* joinop ::= JOIN_KW JOIN */
{yymsp[-1].minor.yy394 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
break;
case 124: /* joinop ::= JOIN_KW nm JOIN */
{yymsp[-2].minor.yy394 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
break;
case 125: /* joinop ::= JOIN_KW nm nm JOIN */
{yymsp[-3].minor.yy394 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
break;
case 126: /* on_using ::= ON expr */
{yymsp[-1].minor.yy561.pOn = yymsp[0].minor.yy528; yymsp[-1].minor.yy561.pUsing = 0;}
break;
case 127: /* on_using ::= USING LP idlist RP */
{yymsp[-3].minor.yy561.pOn = 0; yymsp[-3].minor.yy561.pUsing = yymsp[-1].minor.yy254;}
break;
case 128: /* on_using ::= */
{yymsp[1].minor.yy561.pOn = 0; yymsp[1].minor.yy561.pUsing = 0;}
break;
case 130: /* indexed_by ::= INDEXED BY nm */
{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
break;
case 131: /* indexed_by ::= NOT INDEXED */
{yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
break;
case 133: /* orderby_opt ::= ORDER BY sortlist */
case 143: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==143);
{yymsp[-2].minor.yy322 = yymsp[0].minor.yy322;}
break;
case 134: /* sortlist ::= sortlist COMMA expr sortorder nulls */
{
yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322,yymsp[-2].minor.yy528);
|
| ︙ | ︙ | |||
165771 165772 165773 165774 165775 165776 165777 165778 165779 165780 165781 165782 165783 165784 |
break;
case 139: /* nulls ::= NULLS FIRST */
{yymsp[-1].minor.yy394 = SQLITE_SO_ASC;}
break;
case 140: /* nulls ::= NULLS LAST */
{yymsp[-1].minor.yy394 = SQLITE_SO_DESC;}
break;
case 147: /* limit_opt ::= LIMIT expr */
{yymsp[-1].minor.yy528 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy528,0);}
break;
case 148: /* limit_opt ::= LIMIT expr OFFSET expr */
{yymsp[-3].minor.yy528 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy528,yymsp[0].minor.yy528);}
break;
case 149: /* limit_opt ::= LIMIT expr COMMA expr */
| > > > > > > > > > > > > > > > > | 167543 167544 167545 167546 167547 167548 167549 167550 167551 167552 167553 167554 167555 167556 167557 167558 167559 167560 167561 167562 167563 167564 167565 167566 167567 167568 167569 167570 167571 167572 |
break;
case 139: /* nulls ::= NULLS FIRST */
{yymsp[-1].minor.yy394 = SQLITE_SO_ASC;}
break;
case 140: /* nulls ::= NULLS LAST */
{yymsp[-1].minor.yy394 = SQLITE_SO_DESC;}
break;
case 144: /* having_opt ::= */
case 146: /* limit_opt ::= */ yytestcase(yyruleno==146);
case 151: /* where_opt ::= */ yytestcase(yyruleno==151);
case 153: /* where_opt_ret ::= */ yytestcase(yyruleno==153);
case 229: /* case_else ::= */ yytestcase(yyruleno==229);
case 231: /* case_operand ::= */ yytestcase(yyruleno==231);
case 250: /* vinto ::= */ yytestcase(yyruleno==250);
{yymsp[1].minor.yy528 = 0;}
break;
case 145: /* having_opt ::= HAVING expr */
case 152: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==152);
case 154: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==154);
case 228: /* case_else ::= ELSE expr */ yytestcase(yyruleno==228);
case 249: /* vinto ::= INTO expr */ yytestcase(yyruleno==249);
{yymsp[-1].minor.yy528 = yymsp[0].minor.yy528;}
break;
case 147: /* limit_opt ::= LIMIT expr */
{yymsp[-1].minor.yy528 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy528,0);}
break;
case 148: /* limit_opt ::= LIMIT expr OFFSET expr */
{yymsp[-3].minor.yy528 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy528,yymsp[0].minor.yy528);}
break;
case 149: /* limit_opt ::= LIMIT expr COMMA expr */
|
| ︙ | ︙ | |||
165796 165797 165798 165799 165800 165801 165802 |
case 156: /* where_opt_ret ::= WHERE expr RETURNING selcollist */
{sqlite3AddReturning(pParse,yymsp[0].minor.yy322); yymsp[-3].minor.yy528 = yymsp[-2].minor.yy528;}
break;
case 157: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */
{
sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy131, &yymsp[-4].minor.yy0);
sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy322,"set list");
| > > > > > > > > > > | > | 167584 167585 167586 167587 167588 167589 167590 167591 167592 167593 167594 167595 167596 167597 167598 167599 167600 167601 167602 167603 167604 167605 167606 167607 167608 167609 |
case 156: /* where_opt_ret ::= WHERE expr RETURNING selcollist */
{sqlite3AddReturning(pParse,yymsp[0].minor.yy322); yymsp[-3].minor.yy528 = yymsp[-2].minor.yy528;}
break;
case 157: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */
{
sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy131, &yymsp[-4].minor.yy0);
sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy322,"set list");
if( yymsp[-1].minor.yy131 ){
SrcList *pFromClause = yymsp[-1].minor.yy131;
if( pFromClause->nSrc>1 ){
Select *pSubquery;
Token as;
pSubquery = sqlite3SelectNew(pParse,0,pFromClause,0,0,0,0,SF_NestedFrom,0);
as.n = 0;
as.z = 0;
pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0);
}
yymsp[-5].minor.yy131 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy131, pFromClause);
}
sqlite3Update(pParse,yymsp[-5].minor.yy131,yymsp[-2].minor.yy322,yymsp[0].minor.yy528,yymsp[-6].minor.yy394,0,0,0);
}
break;
case 158: /* setlist ::= setlist COMMA nm EQ expr */
{
yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[0].minor.yy528);
sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, 1);
|
| ︙ | ︙ | |||
165853 165854 165855 165856 165857 165858 165859 165860 165861 165862 165863 165864 165865 165866 |
{ yymsp[-4].minor.yy444 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); }
break;
case 169: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
{ yymsp[-7].minor.yy444 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy322,yymsp[-1].minor.yy528,0);}
break;
case 170: /* returning ::= RETURNING selcollist */
{sqlite3AddReturning(pParse,yymsp[0].minor.yy322);}
break;
case 174: /* idlist_opt ::= LP idlist RP */
{yymsp[-2].minor.yy254 = yymsp[-1].minor.yy254;}
break;
case 175: /* idlist ::= idlist COMMA nm */
{yymsp[-2].minor.yy254 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);}
break;
| > > > | 167652 167653 167654 167655 167656 167657 167658 167659 167660 167661 167662 167663 167664 167665 167666 167667 167668 |
{ yymsp[-4].minor.yy444 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); }
break;
case 169: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
{ yymsp[-7].minor.yy444 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy322,yymsp[-1].minor.yy528,0);}
break;
case 170: /* returning ::= RETURNING selcollist */
{sqlite3AddReturning(pParse,yymsp[0].minor.yy322);}
break;
case 173: /* idlist_opt ::= */
{yymsp[1].minor.yy254 = 0;}
break;
case 174: /* idlist_opt ::= LP idlist RP */
{yymsp[-2].minor.yy254 = yymsp[-1].minor.yy254;}
break;
case 175: /* idlist ::= idlist COMMA nm */
{yymsp[-2].minor.yy254 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);}
break;
|
| ︙ | ︙ | |||
166039 166040 166041 166042 166043 166044 166045 |
break;
case 208: /* expr ::= expr IS NOT expr */
{
yymsp[-3].minor.yy528 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy528,yymsp[0].minor.yy528);
binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-3].minor.yy528, TK_NOTNULL);
}
break;
| | > > > > > > > > > > > > | | | | | | | | > | 167841 167842 167843 167844 167845 167846 167847 167848 167849 167850 167851 167852 167853 167854 167855 167856 167857 167858 167859 167860 167861 167862 167863 167864 167865 167866 167867 167868 167869 167870 167871 167872 167873 167874 167875 167876 167877 167878 167879 167880 167881 167882 167883 167884 167885 167886 167887 167888 167889 167890 167891 167892 167893 167894 167895 167896 167897 167898 167899 167900 167901 167902 167903 167904 167905 167906 167907 167908 167909 167910 167911 167912 167913 167914 167915 |
break;
case 208: /* expr ::= expr IS NOT expr */
{
yymsp[-3].minor.yy528 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy528,yymsp[0].minor.yy528);
binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-3].minor.yy528, TK_NOTNULL);
}
break;
case 209: /* expr ::= expr IS NOT DISTINCT FROM expr */
{
yymsp[-5].minor.yy528 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy528,yymsp[0].minor.yy528);
binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-5].minor.yy528, TK_ISNULL);
}
break;
case 210: /* expr ::= expr IS DISTINCT FROM expr */
{
yymsp[-4].minor.yy528 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy528,yymsp[0].minor.yy528);
binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-4].minor.yy528, TK_NOTNULL);
}
break;
case 211: /* expr ::= NOT expr */
case 212: /* expr ::= BITNOT expr */ yytestcase(yyruleno==212);
{yymsp[-1].minor.yy528 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy528, 0);/*A-overwrites-B*/}
break;
case 213: /* expr ::= PLUS|MINUS expr */
{
yymsp[-1].minor.yy528 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy528, 0);
/*A-overwrites-B*/
}
break;
case 214: /* expr ::= expr PTR expr */
{
ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy528);
pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy528);
yylhsminor.yy528 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
}
yymsp[-2].minor.yy528 = yylhsminor.yy528;
break;
case 215: /* between_op ::= BETWEEN */
case 218: /* in_op ::= IN */ yytestcase(yyruleno==218);
{yymsp[0].minor.yy394 = 0;}
break;
case 217: /* expr ::= expr between_op expr AND expr */
{
ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy528);
pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy528);
yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy528, 0);
if( yymsp[-4].minor.yy528 ){
yymsp[-4].minor.yy528->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0);
}
break;
case 220: /* expr ::= expr in_op LP exprlist RP */
{
if( yymsp[-1].minor.yy322==0 ){
/* Expressions of the form
**
** expr1 IN ()
** expr1 NOT IN ()
**
** simplify to constants 0 (false) and 1 (true), respectively,
** regardless of the value of expr1.
*/
sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy528);
yymsp[-4].minor.yy528 = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy394 ? "true" : "false");
if( yymsp[-4].minor.yy528 ) sqlite3ExprIdToTrueFalse(yymsp[-4].minor.yy528);
}else{
Expr *pRHS = yymsp[-1].minor.yy322->a[0].pExpr;
if( yymsp[-1].minor.yy322->nExpr==1 && sqlite3ExprIsConstant(pRHS) && yymsp[-4].minor.yy528->op!=TK_VECTOR ){
yymsp[-1].minor.yy322->a[0].pExpr = 0;
sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322);
pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy528, pRHS);
|
| ︙ | ︙ | |||
166114 166115 166116 166117 166118 166119 166120 |
sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy528);
}
}
if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0);
}
}
break;
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | 167929 167930 167931 167932 167933 167934 167935 167936 167937 167938 167939 167940 167941 167942 167943 167944 167945 167946 167947 167948 167949 167950 167951 167952 167953 167954 167955 167956 167957 167958 167959 167960 167961 167962 167963 167964 167965 167966 167967 167968 167969 167970 167971 167972 167973 167974 167975 167976 167977 167978 167979 167980 167981 167982 167983 167984 167985 167986 167987 167988 167989 167990 167991 167992 167993 167994 167995 167996 167997 167998 167999 168000 168001 168002 168003 168004 168005 168006 168007 168008 168009 168010 168011 168012 168013 168014 168015 168016 168017 168018 168019 168020 168021 168022 168023 168024 168025 168026 168027 168028 168029 168030 168031 168032 168033 168034 168035 168036 168037 168038 168039 168040 168041 168042 168043 168044 168045 168046 168047 168048 168049 168050 168051 168052 168053 168054 168055 168056 168057 168058 168059 168060 168061 168062 168063 168064 168065 168066 168067 168068 168069 168070 168071 168072 168073 168074 168075 168076 168077 168078 168079 168080 168081 168082 168083 168084 168085 168086 168087 168088 168089 168090 168091 168092 168093 168094 168095 168096 168097 168098 168099 168100 168101 168102 168103 168104 168105 168106 168107 168108 168109 168110 168111 168112 168113 168114 168115 168116 168117 168118 168119 168120 168121 168122 168123 168124 168125 168126 168127 168128 168129 168130 168131 168132 168133 168134 168135 168136 168137 168138 168139 168140 168141 168142 168143 168144 168145 168146 168147 168148 168149 168150 168151 168152 168153 168154 168155 168156 168157 168158 168159 168160 168161 168162 168163 168164 168165 168166 168167 168168 168169 168170 168171 168172 168173 168174 168175 168176 168177 168178 168179 168180 168181 168182 168183 168184 168185 168186 168187 168188 168189 168190 168191 168192 168193 168194 168195 168196 168197 168198 168199 168200 168201 168202 168203 168204 168205 168206 168207 168208 168209 168210 168211 168212 168213 168214 168215 168216 168217 168218 168219 168220 168221 168222 168223 168224 168225 168226 168227 168228 168229 168230 168231 168232 168233 168234 168235 168236 168237 168238 168239 168240 168241 168242 168243 168244 168245 168246 168247 168248 168249 168250 168251 168252 168253 168254 168255 168256 168257 168258 168259 168260 168261 168262 168263 168264 168265 168266 168267 168268 168269 168270 168271 168272 168273 168274 168275 168276 168277 168278 168279 168280 168281 168282 168283 168284 168285 168286 168287 168288 168289 168290 168291 168292 168293 168294 168295 168296 168297 168298 168299 168300 168301 168302 168303 168304 168305 168306 168307 168308 168309 168310 168311 168312 168313 168314 168315 168316 168317 168318 168319 168320 168321 168322 168323 168324 168325 168326 168327 168328 168329 168330 168331 168332 168333 168334 168335 168336 168337 168338 168339 168340 168341 168342 168343 168344 168345 168346 168347 168348 168349 168350 168351 168352 168353 168354 168355 168356 168357 168358 168359 168360 168361 168362 168363 168364 168365 168366 168367 168368 168369 168370 168371 168372 168373 168374 168375 168376 168377 168378 168379 168380 168381 168382 168383 168384 168385 168386 168387 168388 168389 168390 168391 168392 168393 168394 168395 168396 168397 168398 168399 168400 168401 168402 168403 168404 168405 168406 168407 168408 168409 168410 168411 168412 168413 168414 168415 168416 168417 168418 168419 168420 168421 168422 168423 168424 168425 168426 168427 168428 168429 168430 168431 168432 168433 168434 168435 168436 168437 168438 168439 168440 168441 168442 168443 168444 168445 168446 168447 168448 168449 168450 168451 168452 168453 168454 168455 168456 168457 168458 168459 168460 168461 168462 168463 168464 168465 168466 168467 168468 168469 168470 168471 168472 168473 168474 168475 168476 168477 168478 168479 168480 168481 168482 168483 |
sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy528);
}
}
if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0);
}
}
break;
case 221: /* expr ::= LP select RP */
{
yymsp[-2].minor.yy528 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy528, yymsp[-1].minor.yy47);
}
break;
case 222: /* expr ::= expr in_op LP select RP */
{
yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy528, 0);
sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy528, yymsp[-1].minor.yy47);
if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0);
}
break;
case 223: /* expr ::= expr in_op nm dbnm paren_exprlist */
{
SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
if( yymsp[0].minor.yy322 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy322);
yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy528, 0);
sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy528, pSelect);
if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0);
}
break;
case 224: /* expr ::= EXISTS LP select RP */
{
Expr *p;
p = yymsp[-3].minor.yy528 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy47);
}
break;
case 225: /* expr ::= CASE case_operand case_exprlist case_else END */
{
yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy528, 0);
if( yymsp[-4].minor.yy528 ){
yymsp[-4].minor.yy528->x.pList = yymsp[-1].minor.yy528 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[-1].minor.yy528) : yymsp[-2].minor.yy322;
sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy528);
}else{
sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy322);
sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy528);
}
}
break;
case 226: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[-2].minor.yy528);
yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[0].minor.yy528);
}
break;
case 227: /* case_exprlist ::= WHEN expr THEN expr */
{
yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy528);
yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322, yymsp[0].minor.yy528);
}
break;
case 230: /* case_operand ::= expr */
{yymsp[0].minor.yy528 = yymsp[0].minor.yy528; /*A-overwrites-X*/}
break;
case 233: /* nexprlist ::= nexprlist COMMA expr */
{yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[0].minor.yy528);}
break;
case 234: /* nexprlist ::= expr */
{yymsp[0].minor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy528); /*A-overwrites-Y*/}
break;
case 236: /* paren_exprlist ::= LP exprlist RP */
case 241: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==241);
{yymsp[-2].minor.yy322 = yymsp[-1].minor.yy322;}
break;
case 237: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
{
sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy322, yymsp[-10].minor.yy394,
&yymsp[-11].minor.yy0, yymsp[0].minor.yy528, SQLITE_SO_ASC, yymsp[-8].minor.yy394, SQLITE_IDXTYPE_APPDEF);
if( IN_RENAME_OBJECT && pParse->pNewIndex ){
sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0);
}
}
break;
case 238: /* uniqueflag ::= UNIQUE */
case 280: /* raisetype ::= ABORT */ yytestcase(yyruleno==280);
{yymsp[0].minor.yy394 = OE_Abort;}
break;
case 239: /* uniqueflag ::= */
{yymsp[1].minor.yy394 = OE_None;}
break;
case 242: /* eidlist ::= eidlist COMMA nm collate sortorder */
{
yymsp[-4].minor.yy322 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy394, yymsp[0].minor.yy394);
}
break;
case 243: /* eidlist ::= nm collate sortorder */
{
yymsp[-2].minor.yy322 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy394, yymsp[0].minor.yy394); /*A-overwrites-Y*/
}
break;
case 246: /* cmd ::= DROP INDEX ifexists fullname */
{sqlite3DropIndex(pParse, yymsp[0].minor.yy131, yymsp[-1].minor.yy394);}
break;
case 247: /* cmd ::= VACUUM vinto */
{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy528);}
break;
case 248: /* cmd ::= VACUUM nm vinto */
{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy528);}
break;
case 251: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
case 252: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
break;
case 253: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
break;
case 254: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
break;
case 255: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
break;
case 258: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
Token all;
all.z = yymsp[-3].minor.yy0.z;
all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy33, &all);
}
break;
case 259: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy394, yymsp[-4].minor.yy180.a, yymsp[-4].minor.yy180.b, yymsp[-2].minor.yy131, yymsp[0].minor.yy528, yymsp[-10].minor.yy394, yymsp[-8].minor.yy394);
yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/
}
break;
case 260: /* trigger_time ::= BEFORE|AFTER */
{ yymsp[0].minor.yy394 = yymsp[0].major; /*A-overwrites-X*/ }
break;
case 261: /* trigger_time ::= INSTEAD OF */
{ yymsp[-1].minor.yy394 = TK_INSTEAD;}
break;
case 262: /* trigger_time ::= */
{ yymsp[1].minor.yy394 = TK_BEFORE; }
break;
case 263: /* trigger_event ::= DELETE|INSERT */
case 264: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==264);
{yymsp[0].minor.yy180.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy180.b = 0;}
break;
case 265: /* trigger_event ::= UPDATE OF idlist */
{yymsp[-2].minor.yy180.a = TK_UPDATE; yymsp[-2].minor.yy180.b = yymsp[0].minor.yy254;}
break;
case 266: /* when_clause ::= */
case 285: /* key_opt ::= */ yytestcase(yyruleno==285);
{ yymsp[1].minor.yy528 = 0; }
break;
case 267: /* when_clause ::= WHEN expr */
case 286: /* key_opt ::= KEY expr */ yytestcase(yyruleno==286);
{ yymsp[-1].minor.yy528 = yymsp[0].minor.yy528; }
break;
case 268: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
assert( yymsp[-2].minor.yy33!=0 );
yymsp[-2].minor.yy33->pLast->pNext = yymsp[-1].minor.yy33;
yymsp[-2].minor.yy33->pLast = yymsp[-1].minor.yy33;
}
break;
case 269: /* trigger_cmd_list ::= trigger_cmd SEMI */
{
assert( yymsp[-1].minor.yy33!=0 );
yymsp[-1].minor.yy33->pLast = yymsp[-1].minor.yy33;
}
break;
case 270: /* trnm ::= nm DOT nm */
{
yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
sqlite3ErrorMsg(pParse,
"qualified table names are not allowed on INSERT, UPDATE, and DELETE "
"statements within triggers");
}
break;
case 271: /* tridxby ::= INDEXED BY nm */
{
sqlite3ErrorMsg(pParse,
"the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
case 272: /* tridxby ::= NOT INDEXED */
{
sqlite3ErrorMsg(pParse,
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
case 273: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
{yylhsminor.yy33 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy131, yymsp[-3].minor.yy322, yymsp[-1].minor.yy528, yymsp[-7].minor.yy394, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy522);}
yymsp[-8].minor.yy33 = yylhsminor.yy33;
break;
case 274: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
{
yylhsminor.yy33 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy254,yymsp[-2].minor.yy47,yymsp[-6].minor.yy394,yymsp[-1].minor.yy444,yymsp[-7].minor.yy522,yymsp[0].minor.yy522);/*yylhsminor.yy33-overwrites-yymsp[-6].minor.yy394*/
}
yymsp[-7].minor.yy33 = yylhsminor.yy33;
break;
case 275: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
{yylhsminor.yy33 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy528, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy522);}
yymsp[-5].minor.yy33 = yylhsminor.yy33;
break;
case 276: /* trigger_cmd ::= scanpt select scanpt */
{yylhsminor.yy33 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy47, yymsp[-2].minor.yy522, yymsp[0].minor.yy522); /*yylhsminor.yy33-overwrites-yymsp[-1].minor.yy47*/}
yymsp[-2].minor.yy33 = yylhsminor.yy33;
break;
case 277: /* expr ::= RAISE LP IGNORE RP */
{
yymsp[-3].minor.yy528 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
if( yymsp[-3].minor.yy528 ){
yymsp[-3].minor.yy528->affExpr = OE_Ignore;
}
}
break;
case 278: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
yymsp[-5].minor.yy528 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
if( yymsp[-5].minor.yy528 ) {
yymsp[-5].minor.yy528->affExpr = (char)yymsp[-3].minor.yy394;
}
}
break;
case 279: /* raisetype ::= ROLLBACK */
{yymsp[0].minor.yy394 = OE_Rollback;}
break;
case 281: /* raisetype ::= FAIL */
{yymsp[0].minor.yy394 = OE_Fail;}
break;
case 282: /* cmd ::= DROP TRIGGER ifexists fullname */
{
sqlite3DropTrigger(pParse,yymsp[0].minor.yy131,yymsp[-1].minor.yy394);
}
break;
case 283: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
sqlite3Attach(pParse, yymsp[-3].minor.yy528, yymsp[-1].minor.yy528, yymsp[0].minor.yy528);
}
break;
case 284: /* cmd ::= DETACH database_kw_opt expr */
{
sqlite3Detach(pParse, yymsp[0].minor.yy528);
}
break;
case 287: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
case 288: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
case 289: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
case 290: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
case 291: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy131,&yymsp[0].minor.yy0);
}
break;
case 292: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
{
yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n;
sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0);
}
break;
case 293: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
{
sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy131, &yymsp[0].minor.yy0);
}
break;
case 294: /* add_column_fullname ::= fullname */
{
disableLookaside(pParse);
sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy131);
}
break;
case 295: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
{
sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy131, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
}
break;
case 296: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
case 297: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
case 298: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
{
sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy394);
}
break;
case 299: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
case 300: /* vtabargtoken ::= ANY */
case 301: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==301);
case 302: /* lp ::= LP */ yytestcase(yyruleno==302);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
case 303: /* with ::= WITH wqlist */
case 304: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==304);
{ sqlite3WithPush(pParse, yymsp[0].minor.yy521, 1); }
break;
case 305: /* wqas ::= AS */
{yymsp[0].minor.yy516 = M10d_Any;}
break;
case 306: /* wqas ::= AS MATERIALIZED */
{yymsp[-1].minor.yy516 = M10d_Yes;}
break;
case 307: /* wqas ::= AS NOT MATERIALIZED */
{yymsp[-2].minor.yy516 = M10d_No;}
break;
case 308: /* wqitem ::= nm eidlist_opt wqas LP select RP */
{
yymsp[-5].minor.yy385 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy322, yymsp[-1].minor.yy47, yymsp[-3].minor.yy516); /*A-overwrites-X*/
}
break;
case 309: /* wqlist ::= wqitem */
{
yymsp[0].minor.yy521 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy385); /*A-overwrites-X*/
}
break;
case 310: /* wqlist ::= wqlist COMMA wqitem */
{
yymsp[-2].minor.yy521 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy521, yymsp[0].minor.yy385);
}
break;
case 311: /* windowdefn_list ::= windowdefn */
{ yylhsminor.yy41 = yymsp[0].minor.yy41; }
yymsp[0].minor.yy41 = yylhsminor.yy41;
break;
case 312: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */
{
assert( yymsp[0].minor.yy41!=0 );
sqlite3WindowChain(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy41);
yymsp[0].minor.yy41->pNextWin = yymsp[-2].minor.yy41;
yylhsminor.yy41 = yymsp[0].minor.yy41;
}
yymsp[-2].minor.yy41 = yylhsminor.yy41;
break;
case 313: /* windowdefn ::= nm AS LP window RP */
{
if( ALWAYS(yymsp[-1].minor.yy41) ){
yymsp[-1].minor.yy41->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n);
}
yylhsminor.yy41 = yymsp[-1].minor.yy41;
}
yymsp[-4].minor.yy41 = yylhsminor.yy41;
break;
case 314: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */
{
yymsp[-4].minor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy322, yymsp[-1].minor.yy322, 0);
}
break;
case 315: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
{
yylhsminor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy322, yymsp[-1].minor.yy322, &yymsp[-5].minor.yy0);
}
yymsp[-5].minor.yy41 = yylhsminor.yy41;
break;
case 316: /* window ::= ORDER BY sortlist frame_opt */
{
yymsp[-3].minor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, yymsp[-1].minor.yy322, 0);
}
break;
case 317: /* window ::= nm ORDER BY sortlist frame_opt */
{
yylhsminor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0);
}
yymsp[-4].minor.yy41 = yylhsminor.yy41;
break;
case 318: /* window ::= frame_opt */
case 337: /* filter_over ::= over_clause */ yytestcase(yyruleno==337);
{
yylhsminor.yy41 = yymsp[0].minor.yy41;
}
yymsp[0].minor.yy41 = yylhsminor.yy41;
break;
case 319: /* window ::= nm frame_opt */
{
yylhsminor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, 0, &yymsp[-1].minor.yy0);
}
yymsp[-1].minor.yy41 = yylhsminor.yy41;
break;
case 320: /* frame_opt ::= */
{
yymsp[1].minor.yy41 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
}
break;
case 321: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
{
yylhsminor.yy41 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy394, yymsp[-1].minor.yy595.eType, yymsp[-1].minor.yy595.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy516);
}
yymsp[-2].minor.yy41 = yylhsminor.yy41;
break;
case 322: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
{
yylhsminor.yy41 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy394, yymsp[-3].minor.yy595.eType, yymsp[-3].minor.yy595.pExpr, yymsp[-1].minor.yy595.eType, yymsp[-1].minor.yy595.pExpr, yymsp[0].minor.yy516);
}
yymsp[-5].minor.yy41 = yylhsminor.yy41;
break;
case 324: /* frame_bound_s ::= frame_bound */
case 326: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==326);
{yylhsminor.yy595 = yymsp[0].minor.yy595;}
yymsp[0].minor.yy595 = yylhsminor.yy595;
break;
case 325: /* frame_bound_s ::= UNBOUNDED PRECEDING */
case 327: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==327);
case 329: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==329);
{yylhsminor.yy595.eType = yymsp[-1].major; yylhsminor.yy595.pExpr = 0;}
yymsp[-1].minor.yy595 = yylhsminor.yy595;
break;
case 328: /* frame_bound ::= expr PRECEDING|FOLLOWING */
{yylhsminor.yy595.eType = yymsp[0].major; yylhsminor.yy595.pExpr = yymsp[-1].minor.yy528;}
yymsp[-1].minor.yy595 = yylhsminor.yy595;
break;
case 330: /* frame_exclude_opt ::= */
{yymsp[1].minor.yy516 = 0;}
break;
case 331: /* frame_exclude_opt ::= EXCLUDE frame_exclude */
{yymsp[-1].minor.yy516 = yymsp[0].minor.yy516;}
break;
case 332: /* frame_exclude ::= NO OTHERS */
case 333: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==333);
{yymsp[-1].minor.yy516 = yymsp[-1].major; /*A-overwrites-X*/}
break;
case 334: /* frame_exclude ::= GROUP|TIES */
{yymsp[0].minor.yy516 = yymsp[0].major; /*A-overwrites-X*/}
break;
case 335: /* window_clause ::= WINDOW windowdefn_list */
{ yymsp[-1].minor.yy41 = yymsp[0].minor.yy41; }
break;
case 336: /* filter_over ::= filter_clause over_clause */
{
if( yymsp[0].minor.yy41 ){
yymsp[0].minor.yy41->pFilter = yymsp[-1].minor.yy528;
}else{
sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy528);
}
yylhsminor.yy41 = yymsp[0].minor.yy41;
}
yymsp[-1].minor.yy41 = yylhsminor.yy41;
break;
case 338: /* filter_over ::= filter_clause */
{
yylhsminor.yy41 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
if( yylhsminor.yy41 ){
yylhsminor.yy41->eFrmType = TK_FILTER;
yylhsminor.yy41->pFilter = yymsp[0].minor.yy528;
}else{
sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy528);
}
}
yymsp[0].minor.yy41 = yylhsminor.yy41;
break;
case 339: /* over_clause ::= OVER LP window RP */
{
yymsp[-3].minor.yy41 = yymsp[-1].minor.yy41;
assert( yymsp[-3].minor.yy41!=0 );
}
break;
case 340: /* over_clause ::= OVER nm */
{
yymsp[-1].minor.yy41 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
if( yymsp[-1].minor.yy41 ){
yymsp[-1].minor.yy41->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
}
}
break;
case 341: /* filter_clause ::= FILTER LP WHERE expr RP */
{ yymsp[-4].minor.yy528 = yymsp[-1].minor.yy528; }
break;
default:
/* (342) input ::= cmdlist */ yytestcase(yyruleno==342);
/* (343) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==343);
/* (344) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=344);
/* (345) ecmd ::= SEMI */ yytestcase(yyruleno==345);
/* (346) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==346);
/* (347) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=347);
/* (348) trans_opt ::= */ yytestcase(yyruleno==348);
/* (349) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==349);
/* (350) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==350);
/* (351) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==351);
/* (352) savepoint_opt ::= */ yytestcase(yyruleno==352);
/* (353) cmd ::= create_table create_table_args */ yytestcase(yyruleno==353);
/* (354) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=354);
/* (355) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==355);
/* (356) columnlist ::= columnname carglist */ yytestcase(yyruleno==356);
/* (357) nm ::= ID|INDEXED */ yytestcase(yyruleno==357);
/* (358) nm ::= STRING */ yytestcase(yyruleno==358);
/* (359) nm ::= JOIN_KW */ yytestcase(yyruleno==359);
/* (360) typetoken ::= typename */ yytestcase(yyruleno==360);
/* (361) typename ::= ID|STRING */ yytestcase(yyruleno==361);
/* (362) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=362);
/* (363) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=363);
/* (364) carglist ::= carglist ccons */ yytestcase(yyruleno==364);
/* (365) carglist ::= */ yytestcase(yyruleno==365);
/* (366) ccons ::= NULL onconf */ yytestcase(yyruleno==366);
/* (367) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==367);
/* (368) ccons ::= AS generated */ yytestcase(yyruleno==368);
/* (369) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==369);
/* (370) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==370);
/* (371) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=371);
/* (372) tconscomma ::= */ yytestcase(yyruleno==372);
/* (373) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=373);
/* (374) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=374);
/* (375) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=375);
/* (376) oneselect ::= values */ yytestcase(yyruleno==376);
/* (377) sclp ::= selcollist COMMA */ yytestcase(yyruleno==377);
/* (378) as ::= ID|STRING */ yytestcase(yyruleno==378);
/* (379) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=379);
/* (380) returning ::= */ yytestcase(yyruleno==380);
/* (381) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=381);
/* (382) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==382);
/* (383) exprlist ::= nexprlist */ yytestcase(yyruleno==383);
/* (384) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=384);
/* (385) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=385);
/* (386) nmnum ::= ON */ yytestcase(yyruleno==386);
/* (387) nmnum ::= DELETE */ yytestcase(yyruleno==387);
/* (388) nmnum ::= DEFAULT */ yytestcase(yyruleno==388);
/* (389) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==389);
/* (390) foreach_clause ::= */ yytestcase(yyruleno==390);
/* (391) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==391);
/* (392) trnm ::= nm */ yytestcase(yyruleno==392);
/* (393) tridxby ::= */ yytestcase(yyruleno==393);
/* (394) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==394);
/* (395) database_kw_opt ::= */ yytestcase(yyruleno==395);
/* (396) kwcolumn_opt ::= */ yytestcase(yyruleno==396);
/* (397) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==397);
/* (398) vtabarglist ::= vtabarg */ yytestcase(yyruleno==398);
/* (399) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==399);
/* (400) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==400);
/* (401) anylist ::= */ yytestcase(yyruleno==401);
/* (402) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==402);
/* (403) anylist ::= anylist ANY */ yytestcase(yyruleno==403);
/* (404) with ::= */ yytestcase(yyruleno==404);
break;
/********** End reduce actions ************************************************/
};
assert( yyruleno<sizeof(yyRuleInfoLhs)/sizeof(yyRuleInfoLhs[0]) );
yygoto = yyRuleInfoLhs[yyruleno];
yysize = yyRuleInfoNRhs[yyruleno];
yyact = yy_find_reduce_action(yymsp[yysize].stateno,(YYCODETYPE)yygoto);
|
| ︙ | ︙ | |||
168196 168197 168198 168199 168200 168201 168202 |
** will take responsibility for freeing the Table structure.
*/
sqlite3DeleteTable(db, pParse->pNewTable);
}
if( pParse->pNewTrigger && !IN_RENAME_OBJECT ){
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
}
| | | 170012 170013 170014 170015 170016 170017 170018 170019 170020 170021 170022 170023 170024 170025 170026 |
** will take responsibility for freeing the Table structure.
*/
sqlite3DeleteTable(db, pParse->pNewTable);
}
if( pParse->pNewTrigger && !IN_RENAME_OBJECT ){
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
}
if( pParse->pVList ) sqlite3DbFreeNN(db, pParse->pVList);
db->pParse = pParentParse;
assert( nErr==0 || pParse->rc!=SQLITE_OK );
return nErr;
}
#ifdef SQLITE_ENABLE_NORMALIZE
|
| ︙ | ︙ | |||
172825 172826 172827 172828 172829 172830 172831 172832 172833 172834 172835 172836 172837 172838 |
** process aborts. If X is false and assert() is disabled, then the
** return value is zero.
*/
case SQLITE_TESTCTRL_ASSERT: {
volatile int x = 0;
assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 );
rc = x;
break;
}
/*
** sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, int X)
**
| > > > > > > > > > > > > > > > > > > > | 174641 174642 174643 174644 174645 174646 174647 174648 174649 174650 174651 174652 174653 174654 174655 174656 174657 174658 174659 174660 174661 174662 174663 174664 174665 174666 174667 174668 174669 174670 174671 174672 174673 |
** process aborts. If X is false and assert() is disabled, then the
** return value is zero.
*/
case SQLITE_TESTCTRL_ASSERT: {
volatile int x = 0;
assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 );
rc = x;
#if defined(SQLITE_DEBUG)
/* Invoke these debugging routines so that the compiler does not
** issue "defined but not used" warnings. */
if( x==9999 ){
sqlite3ShowExpr(0);
sqlite3ShowExpr(0);
sqlite3ShowExprList(0);
sqlite3ShowIdList(0);
sqlite3ShowSrcList(0);
sqlite3ShowWith(0);
sqlite3ShowUpsert(0);
sqlite3ShowTriggerStep(0);
sqlite3ShowTriggerStepList(0);
sqlite3ShowTrigger(0);
sqlite3ShowTriggerList(0);
sqlite3ShowWindow(0);
sqlite3ShowWinFunc(0);
}
#endif
break;
}
/*
** sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, int X)
**
|
| ︙ | ︙ | |||
173086 173087 173088 173089 173090 173091 173092 |
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, op, ptr)
**
** "ptr" is a pointer to a u32.
**
| | | | | | | | 174921 174922 174923 174924 174925 174926 174927 174928 174929 174930 174931 174932 174933 174934 174935 174936 174937 174938 174939 174940 174941 174942 174943 174944 174945 174946 174947 |
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, op, ptr)
**
** "ptr" is a pointer to a u32.
**
** op==0 Store the current sqlite3TreeTrace in *ptr
** op==1 Set sqlite3TreeTrace to the value *ptr
** op==3 Store the current sqlite3WhereTrace in *ptr
** op==3 Set sqlite3WhereTrace to the value *ptr
*/
case SQLITE_TESTCTRL_TRACEFLAGS: {
int opTrace = va_arg(ap, int);
u32 *ptr = va_arg(ap, u32*);
switch( opTrace ){
case 0: *ptr = sqlite3TreeTrace; break;
case 1: sqlite3TreeTrace = *ptr; break;
case 2: *ptr = sqlite3WhereTrace; break;
case 3: sqlite3WhereTrace = *ptr; break;
}
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_LOGEST,
** double fIn, // Input value
** int *pLogEst, // sqlite3LogEstFromDouble(fIn)
|
| ︙ | ︙ | |||
173334 173335 173336 173337 173338 173339 173340 173341 173342 173343 173344 173345 173346 173347 |
/*
** Return the Btree pointer identified by zDbName. Return NULL if not found.
*/
SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0;
return iDb<0 ? 0 : db->aDb[iDb].pBt;
}
/*
** Return the filename of the database associated with a database
** connection.
*/
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
Btree *pBt;
| > > > > > > > > > > > > > > > > > > | 175169 175170 175171 175172 175173 175174 175175 175176 175177 175178 175179 175180 175181 175182 175183 175184 175185 175186 175187 175188 175189 175190 175191 175192 175193 175194 175195 175196 175197 175198 175199 175200 |
/*
** Return the Btree pointer identified by zDbName. Return NULL if not found.
*/
SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0;
return iDb<0 ? 0 : db->aDb[iDb].pBt;
}
/*
** Return the name of the N-th database schema. Return NULL if N is out
** of range.
*/
SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
if( N<0 || N>=db->nDb ){
return 0;
}else{
return db->aDb[N].zDbSName;
}
}
/*
** Return the filename of the database associated with a database
** connection.
*/
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
Btree *pBt;
|
| ︙ | ︙ | |||
188973 188974 188975 188976 188977 188978 188979 188980 188981 188982 188983 188984 188985 188986 |
blobGrowBuffer(&pNode->key, nTerm, &rc);
if( rc==SQLITE_OK ){
if( pNode->key.n ){
pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix);
}
pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix);
memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix);
pBlk->n += nSuffix;
memcpy(pNode->key.a, zTerm, nTerm);
pNode->key.n = nTerm;
}
}else{
| > > | 190826 190827 190828 190829 190830 190831 190832 190833 190834 190835 190836 190837 190838 190839 190840 190841 |
blobGrowBuffer(&pNode->key, nTerm, &rc);
if( rc==SQLITE_OK ){
if( pNode->key.n ){
pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix);
}
pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix);
assert( nPrefix+nSuffix<=nTerm );
assert( nPrefix>=0 );
memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix);
pBlk->n += nSuffix;
memcpy(pNode->key.a, zTerm, nTerm);
pNode->key.n = nTerm;
}
}else{
|
| ︙ | ︙ | |||
189095 189096 189097 189098 189099 189100 189101 189102 189103 189104 189105 189106 189107 189108 | int nPrefix; /* Size of prefix shared with previous term */ int nSuffix; /* Size of suffix (nTerm - nPrefix) */ NodeWriter *pLeaf; /* Object used to write leaf nodes */ pLeaf = &pWriter->aNodeWriter[0]; nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm); nSuffix = nTerm - nPrefix; nSpace = sqlite3Fts3VarintLen(nPrefix); nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; /* If the current block is not empty, and if adding this term/doclist ** to the current block would make it larger than Fts3Table.nNodeSize | > | 190950 190951 190952 190953 190954 190955 190956 190957 190958 190959 190960 190961 190962 190963 190964 | int nPrefix; /* Size of prefix shared with previous term */ int nSuffix; /* Size of suffix (nTerm - nPrefix) */ NodeWriter *pLeaf; /* Object used to write leaf nodes */ pLeaf = &pWriter->aNodeWriter[0]; nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm); nSuffix = nTerm - nPrefix; if(nSuffix<=0 ) return FTS_CORRUPT_VTAB; nSpace = sqlite3Fts3VarintLen(nPrefix); nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; /* If the current block is not empty, and if adding this term/doclist ** to the current block would make it larger than Fts3Table.nNodeSize |
| ︙ | ︙ | |||
194545 194546 194547 194548 194549 194550 194551 194552 194553 194554 194555 |
nKey = i-1;
if( zPath[i] ){
i++;
}else{
*pzErr = zPath;
return 0;
}
}else{
zKey = zPath;
for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
nKey = i;
| > < | | | > | 196401 196402 196403 196404 196405 196406 196407 196408 196409 196410 196411 196412 196413 196414 196415 196416 196417 196418 196419 196420 196421 196422 196423 |
nKey = i-1;
if( zPath[i] ){
i++;
}else{
*pzErr = zPath;
return 0;
}
testcase( nKey==0 );
}else{
zKey = zPath;
for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
nKey = i;
if( nKey==0 ){
*pzErr = zPath;
return 0;
}
}
j = 1;
for(;;){
while( j<=pRoot->n ){
if( jsonLabelCompare(pRoot+j, zKey, nKey) ){
return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr);
}
|
| ︙ | ︙ | |||
195699 195700 195701 195702 195703 195704 195705 195706 195707 195708 195709 195710 195711 195712 |
p->i = p->iEnd;
break;
}
}
}
return SQLITE_OK;
}
/* Append the name of the path for element i to pStr
*/
static void jsonEachComputePath(
JsonEachCursor *p, /* The cursor */
JsonString *pStr, /* Write the path here */
u32 i /* Path to this element */
| > > > > > > > > > > > > > > > > > > > > > > > > > > > | 197556 197557 197558 197559 197560 197561 197562 197563 197564 197565 197566 197567 197568 197569 197570 197571 197572 197573 197574 197575 197576 197577 197578 197579 197580 197581 197582 197583 197584 197585 197586 197587 197588 197589 197590 197591 197592 197593 197594 197595 197596 |
p->i = p->iEnd;
break;
}
}
}
return SQLITE_OK;
}
/* Append an object label to the JSON Path being constructed
** in pStr.
*/
static void jsonAppendObjectPathElement(
JsonString *pStr,
JsonNode *pNode
){
int jj, nn;
const char *z;
assert( pNode->eType==JSON_STRING );
assert( pNode->jnFlags & JNODE_LABEL );
assert( pNode->eU==1 );
z = pNode->u.zJContent;
nn = pNode->n;
assert( nn>=2 );
assert( z[0]=='"' );
assert( z[nn-1]=='"' );
if( nn>2 && sqlite3Isalpha(z[1]) ){
for(jj=2; jj<nn-1 && sqlite3Isalnum(z[jj]); jj++){}
if( jj==nn-1 ){
z++;
nn -= 2;
}
}
jsonPrintf(nn+2, pStr, ".%.*s", nn, z);
}
/* Append the name of the path for element i to pStr
*/
static void jsonEachComputePath(
JsonEachCursor *p, /* The cursor */
JsonString *pStr, /* Write the path here */
u32 i /* Path to this element */
|
| ︙ | ︙ | |||
195724 195725 195726 195727 195728 195729 195730 |
if( pUp->eType==JSON_ARRAY ){
assert( pUp->eU==3 || (pUp->eU==0 && pUp->u.iKey==0) );
testcase( pUp->eU==0 );
jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
}else{
assert( pUp->eType==JSON_OBJECT );
if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
| < < | < | 197608 197609 197610 197611 197612 197613 197614 197615 197616 197617 197618 197619 197620 197621 197622 |
if( pUp->eType==JSON_ARRAY ){
assert( pUp->eU==3 || (pUp->eU==0 && pUp->u.iKey==0) );
testcase( pUp->eU==0 );
jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
}else{
assert( pUp->eType==JSON_OBJECT );
if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
jsonAppendObjectPathElement(pStr, pNode);
}
}
/* Return the value of a column */
static int jsonEachColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
|
| ︙ | ︙ | |||
195798 195799 195800 195801 195802 195803 195804 |
jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot));
}else{
jsonAppendChar(&x, '$');
}
if( p->eType==JSON_ARRAY ){
jsonPrintf(30, &x, "[%d]", p->iRowid);
}else if( p->eType==JSON_OBJECT ){
| | < | 197679 197680 197681 197682 197683 197684 197685 197686 197687 197688 197689 197690 197691 197692 197693 |
jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot));
}else{
jsonAppendChar(&x, '$');
}
if( p->eType==JSON_ARRAY ){
jsonPrintf(30, &x, "[%d]", p->iRowid);
}else if( p->eType==JSON_OBJECT ){
jsonAppendObjectPathElement(&x, pThis);
}
}
jsonResult(&x);
break;
}
case JEACH_PATH: {
if( p->bRecursive ){
|
| ︙ | ︙ | |||
210346 210347 210348 210349 210350 210351 210352 |
if( pIdxInfo->nOrderBy>=1
&& pIdxInfo->aOrderBy[0].iColumn<=0
&& pIdxInfo->aOrderBy[0].desc==0
){
pIdxInfo->orderByConsumed = 1;
}
| | | 212226 212227 212228 212229 212230 212231 212232 212233 212234 212235 212236 212237 212238 212239 212240 |
if( pIdxInfo->nOrderBy>=1
&& pIdxInfo->aOrderBy[0].iColumn<=0
&& pIdxInfo->aOrderBy[0].desc==0
){
pIdxInfo->orderByConsumed = 1;
}
sqlite3VtabUsesAllSchemas(pIdxInfo);
return SQLITE_OK;
}
/*
** Open a new dbpagevfs cursor.
*/
static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
| ︙ | ︙ | |||
223074 223075 223076 223077 223078 223079 223080 223081 223082 223083 223084 223085 223086 223087 |
if( pRet==0 ){
assert( pParse->rc!=SQLITE_OK );
sqlite3Fts5ParseNearsetFree(pNear);
sqlite3Fts5ParsePhraseFree(pPhrase);
}else{
if( pRet->nPhrase>0 ){
Fts5ExprPhrase *pLast = pRet->apPhrase[pRet->nPhrase-1];
assert( pLast==pParse->apPhrase[pParse->nPhrase-2] );
if( pPhrase->nTerm==0 ){
fts5ExprPhraseFree(pPhrase);
pRet->nPhrase--;
pParse->nPhrase--;
pPhrase = pLast;
}else if( pLast->nTerm==0 ){
| > > > | 224954 224955 224956 224957 224958 224959 224960 224961 224962 224963 224964 224965 224966 224967 224968 224969 224970 |
if( pRet==0 ){
assert( pParse->rc!=SQLITE_OK );
sqlite3Fts5ParseNearsetFree(pNear);
sqlite3Fts5ParsePhraseFree(pPhrase);
}else{
if( pRet->nPhrase>0 ){
Fts5ExprPhrase *pLast = pRet->apPhrase[pRet->nPhrase-1];
assert( pParse!=0 );
assert( pParse->apPhrase!=0 );
assert( pParse->nPhrase>=2 );
assert( pLast==pParse->apPhrase[pParse->nPhrase-2] );
if( pPhrase->nTerm==0 ){
fts5ExprPhraseFree(pPhrase);
pRet->nPhrase--;
pParse->nPhrase--;
pPhrase = pLast;
}else if( pLast->nTerm==0 ){
|
| ︙ | ︙ | |||
225373 225374 225375 225376 225377 225378 225379 | int rc; /* Current error code */ /* State used by the fts5DataXXX() functions. */ sqlite3_blob *pReader; /* RO incr-blob open on %_data table */ sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */ sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */ sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */ | | | 227256 227257 227258 227259 227260 227261 227262 227263 227264 227265 227266 227267 227268 227269 227270 | int rc; /* Current error code */ /* State used by the fts5DataXXX() functions. */ sqlite3_blob *pReader; /* RO incr-blob open on %_data table */ sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */ sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */ sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */ sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=?" */ sqlite3_stmt *pIdxSelect; int nRead; /* Total number of blocks read */ sqlite3_stmt *pDataVersion; i64 iStructVersion; /* data_version when pStruct read */ Fts5Structure *pStruct; /* Current db structure (or NULL) */ }; |
| ︙ | ︙ | |||
234690 234691 234692 234693 234694 234695 234696 |
static void fts5SourceIdFunc(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
sqlite3_value **apUnused /* Function arguments */
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
| | | 236573 236574 236575 236576 236577 236578 236579 236580 236581 236582 236583 236584 236585 236586 236587 |
static void fts5SourceIdFunc(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
sqlite3_value **apUnused /* Function arguments */
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
sqlite3_result_text(pCtx, "fts5: 2022-06-15 16:26:37 56c60a35ea457f06db58ec3f694a1ae16fd03e6625da1d7879d63d72bbcb1c62", -1, SQLITE_TRANSIENT);
}
/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
*/
static int fts5ShadowName(const char *zName){
|
| ︙ | ︙ |
Changes to extsrc/sqlite3.h.
| ︙ | ︙ | |||
144 145 146 147 148 149 150 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.39.0" #define SQLITE_VERSION_NUMBER 3039000 | | | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.39.0" #define SQLITE_VERSION_NUMBER 3039000 #define SQLITE_SOURCE_ID "2022-06-15 16:26:37 56c60a35ea457f06db58ec3f694a1ae16fd03e6625da1d7879d63d72bbcb1c62" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| ︙ | ︙ | |||
6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 | ** returned by sqlite3_db_handle is the same [database connection] ** that was the first argument ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection ** METHOD: sqlite3 ** ** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename ** associated with database N of connection D. ** ^If there is no attached database N on the database | > > > > > > > > > > > > > > > > > > > > > > | 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 | ** returned by sqlite3_db_handle is the same [database connection] ** that was the first argument ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Schema Name For A Database Connection ** METHOD: sqlite3 ** ** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name ** for the N-th database on database connection D, or a NULL pointer of N is ** out of range. An N alue of 0 means the main database file. An N of 1 is ** the "temp" schema. Larger values of N correspond to various ATTACH-ed ** databases. ** ** Space to hold the string that is returned by sqlite3_db_name() is managed ** by SQLite itself. The string might be deallocated by any operation that ** changes the schema, including [ATTACH] or [DETACH] or calls to ** [sqlite3_serialize()] or [sqlite3_deserialize()], even operations that ** occur on a different thread. Applications that need to ** remember the string long-term should make their own copy. Applications that ** are accessing the same database connection simultaneously on multiple ** threads should mutex-protect calls to this API and should make their own ** private copy of the result prior to releasing the mutex. */ SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N); /* ** CAPI3REF: Return The Filename For A Database Connection ** METHOD: sqlite3 ** ** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename ** associated with database N of connection D. ** ^If there is no attached database N on the database |
| ︙ | ︙ |
Changes to skins/darkmode/css.txt.
| ︙ | ︙ | |||
129 130 131 132 133 134 135 |
outline: 0
}
.button:focus,
button:focus,
input[type=button]:focus,
input[type=reset]:focus,
input[type=submit]:focus {
| | < | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
outline: 0
}
.button:focus,
button:focus,
input[type=button]:focus,
input[type=reset]:focus,
input[type=submit]:focus {
outline: 2px outset #333;
border-color: #888;
}
/* All page content from the bottom of the menu or submenu down to
** the footer */
div.content {
padding: 0ex 1ex 1ex 1ex;
}
|
| ︙ | ︙ |
Changes to src/add.c.
| ︙ | ︙ | |||
881 882 883 884 885 886 887 |
fossil_print("DELETED %s\n", zFile);
nDelete++;
}
}
db_finalize(&q);
/* show command summary */
fossil_print("added %d files, deleted %d files\n", nAdd, nDelete);
| > > | | 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 |
fossil_print("DELETED %s\n", zFile);
nDelete++;
}
}
db_finalize(&q);
/* show command summary */
fossil_print("added %d files, deleted %d files\n", nAdd, nDelete);
if(dryRunFlag!=0){
fossil_print("Dry-run mode: no changes were made.\n");
}
db_end_transaction(dryRunFlag);
}
/*
** Rename a single file.
**
** The original name of the file is zOrig. The new filename is zNew.
|
| ︙ | ︙ |
Changes to src/alerts.c.
| ︙ | ︙ | |||
276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
@ In cases where the email notification does not align with a specific
@ Fossil login account (for example, digest messages), this is also
@ the "From:" address of the email notification.
@ The system administrator should arrange for emails sent to this address
@ to be handed off to the "fossil email incoming" command so that Fossil
@ can handle bounces. (Property: "email-self")</p>
@ <hr>
entry_attribute("Repository Nickname", 16, "email-subname",
"enn", "", 0);
@ <p><b>Required.</b>
@ This is short name used to identifies the repository in the
@ Subject: line of email alerts. Traditionally this name is
@ included in square brackets. Examples: "[fossil-src]", "[sqlite-src]".
| > > > > > > > > | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
@ In cases where the email notification does not align with a specific
@ Fossil login account (for example, digest messages), this is also
@ the "From:" address of the email notification.
@ The system administrator should arrange for emails sent to this address
@ to be handed off to the "fossil email incoming" command so that Fossil
@ can handle bounces. (Property: "email-self")</p>
@ <hr>
entry_attribute("List-ID", 40, "email-listid",
"elistid", "", 0);
@ <p>
@ If this is not an empty string, then it becomes the argument to
@ a "List-ID:" header on all out-bound notification emails.
@ (Property: "email-listid")</p>
@ <hr>
entry_attribute("Repository Nickname", 16, "email-subname",
"enn", "", 0);
@ <p><b>Required.</b>
@ This is short name used to identifies the repository in the
@ Subject: line of email alerts. Traditionally this name is
@ included in square brackets. Examples: "[fossil-src]", "[sqlite-src]".
|
| ︙ | ︙ | |||
407 408 409 410 411 412 413 414 415 416 417 418 419 420 | sqlite3 *db; /* Database emails are sent to */ sqlite3_stmt *pStmt; /* Stmt to insert into the database */ const char *zDest; /* How to send email. */ const char *zDb; /* Name of database file */ const char *zDir; /* Directory in which to store as email files */ const char *zCmd; /* Command to run for each email */ const char *zFrom; /* Emails come from here */ SmtpSession *pSmtp; /* SMTP relay connection */ Blob out; /* For zDest=="blob" */ char *zErr; /* Error message */ u32 mFlags; /* Flags */ int bImmediateFail; /* On any error, call fossil_fatal() */ }; | > | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 | sqlite3 *db; /* Database emails are sent to */ sqlite3_stmt *pStmt; /* Stmt to insert into the database */ const char *zDest; /* How to send email. */ const char *zDb; /* Name of database file */ const char *zDir; /* Directory in which to store as email files */ const char *zCmd; /* Command to run for each email */ const char *zFrom; /* Emails come from here */ const char *zListId; /* Argument to List-ID header */ SmtpSession *pSmtp; /* SMTP relay connection */ Blob out; /* For zDest=="blob" */ char *zErr; /* Error message */ u32 mFlags; /* Flags */ int bImmediateFail; /* On any error, call fossil_fatal() */ }; |
| ︙ | ︙ | |||
432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
sqlite3_finalize(p->pStmt);
p->pStmt = 0;
sqlite3_close(p->db);
p->db = 0;
p->zDb = 0;
p->zDir = 0;
p->zCmd = 0;
if( p->pSmtp ){
smtp_client_quit(p->pSmtp);
smtp_session_free(p->pSmtp);
p->pSmtp = 0;
}
blob_reset(&p->out);
}
| > | 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 |
sqlite3_finalize(p->pStmt);
p->pStmt = 0;
sqlite3_close(p->db);
p->db = 0;
p->zDb = 0;
p->zDir = 0;
p->zCmd = 0;
p->zListId = 0;
if( p->pSmtp ){
smtp_client_quit(p->pSmtp);
smtp_session_free(p->pSmtp);
p->pSmtp = 0;
}
blob_reset(&p->out);
}
|
| ︙ | ︙ | |||
512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
if( zAltDest ){
p->zDest = zAltDest;
}else{
p->zDest = db_get("email-send-method",0);
}
if( fossil_strcmp(p->zDest,"off")==0 ) return p;
if( emailerGetSetting(p, &p->zFrom, "email-self") ) return p;
if( fossil_strcmp(p->zDest,"db")==0 ){
char *zErr;
int rc;
if( emailerGetSetting(p, &p->zDb, "email-send-db") ) return p;
rc = sqlite3_open(p->zDb, &p->db);
if( rc ){
emailerError(p, "unable to open output database file \"%s\": %s",
| > | 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 |
if( zAltDest ){
p->zDest = zAltDest;
}else{
p->zDest = db_get("email-send-method",0);
}
if( fossil_strcmp(p->zDest,"off")==0 ) return p;
if( emailerGetSetting(p, &p->zFrom, "email-self") ) return p;
p->zListId = db_get("email-listid", 0);
if( fossil_strcmp(p->zDest,"db")==0 ){
char *zErr;
int rc;
if( emailerGetSetting(p, &p->zDb, "email-send-db") ) return p;
rc = sqlite3_open(p->zDb, &p->db);
if( rc ){
emailerError(p, "unable to open output database file \"%s\": %s",
|
| ︙ | ︙ | |||
879 880 881 882 883 884 885 886 887 888 889 890 891 892 |
blob_appendf(pOut, "From: %s <%s@%s>\r\n",
zFromName, alert_mailbox_name(zFromName), alert_hostname(p->zFrom));
blob_appendf(pOut, "Sender: <%s>\r\n", p->zFrom);
}else{
blob_appendf(pOut, "From: <%s>\r\n", p->zFrom);
}
blob_appendf(pOut, "Date: %z\r\n", cgi_rfc822_datestamp(time(0)));
if( strstr(blob_str(pHdr), "\r\nMessage-Id:")==0 ){
/* Message-id format: "<$(date)x$(random)@$(from-host)>" where $(date) is
** the current unix-time in hex, $(random) is a 64-bit random number,
** and $(from) is the domain part of the email-self setting. */
sqlite3_randomness(sizeof(r1), &r1);
r2 = time(0);
blob_appendf(pOut, "Message-Id: <%llxx%016llx@%s>\r\n",
| > > > | 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 |
blob_appendf(pOut, "From: %s <%s@%s>\r\n",
zFromName, alert_mailbox_name(zFromName), alert_hostname(p->zFrom));
blob_appendf(pOut, "Sender: <%s>\r\n", p->zFrom);
}else{
blob_appendf(pOut, "From: <%s>\r\n", p->zFrom);
}
blob_appendf(pOut, "Date: %z\r\n", cgi_rfc822_datestamp(time(0)));
if( p->zListId && p->zListId[0] ){
blob_appendf(pOut, "List-Id: %s\r\n", p->zListId);
}
if( strstr(blob_str(pHdr), "\r\nMessage-Id:")==0 ){
/* Message-id format: "<$(date)x$(random)@$(from-host)>" where $(date) is
** the current unix-time in hex, $(random) is a 64-bit random number,
** and $(from) is the domain part of the email-self setting. */
sqlite3_randomness(sizeof(r1), &r1);
r2 = time(0);
blob_appendf(pOut, "Message-Id: <%llxx%016llx@%s>\r\n",
|
| ︙ | ︙ | |||
967 968 969 970 971 972 973 | ** This is a short name used to identifies the repository in the Subject: ** line of email alerts. Traditionally this name is included in square ** brackets. Examples: "[fossil-src]", "[sqlite-src]". */ /* ** SETTING: email-renew-interval width=16 ** If this setting as an integer N that is 14 or greater then email | | | 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 | ** This is a short name used to identifies the repository in the Subject: ** line of email alerts. Traditionally this name is included in square ** brackets. Examples: "[fossil-src]", "[sqlite-src]". */ /* ** SETTING: email-renew-interval width=16 ** If this setting as an integer N that is 14 or greater then email ** notification is suspended for subscriptions that have a "last contact ** time" of more than N days ago. The "last contact time" is recorded ** in the SUBSCRIBER.LASTCONTACT entry of the database. Logging in, ** sending a forum post, editing a wiki page, changing subscription settings ** at /alerts, or visiting /renew all update the last contact time. ** If this setting is not an integer value or is less than 14 or undefined, ** then subscriptions never expire. */ |
| ︙ | ︙ | |||
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 | ** if the email-send-method is set to "db". */ /* ** SETTING: email-self width=40 ** This is the email address for the repository. Outbound emails add ** this email address as the "From:" field. */ /* ** SETTING: email-send-relayhost width=40 sensitive ** This is the hostname and TCP port to which output email messages ** are sent when email-send-method is "relay". There should be an ** SMTP server configured as a Mail Submission Agent listening on the ** designated host and port and all times. */ | > > > > > | 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 | ** if the email-send-method is set to "db". */ /* ** SETTING: email-self width=40 ** This is the email address for the repository. Outbound emails add ** this email address as the "From:" field. */ /* ** SETTING: email-listid width=40 ** If this setting is not an empty string, then it becomes the argument to ** a "List-ID:" header that is added to all out-bound notification emails. */ /* ** SETTING: email-send-relayhost width=40 sensitive ** This is the hostname and TCP port to which output email messages ** are sent when email-send-method is "relay". There should be an ** SMTP server configured as a Mail Submission Agent listening on the ** designated host and port and all times. */ |
| ︙ | ︙ |
Changes to src/backlink.c.
| ︙ | ︙ | |||
177 178 179 180 181 182 183 |
Manifest *pWiki;
if( tagid==0 ) return;
rid = db_int(0, "SELECT rid FROM tagxref WHERE tagid=%d"
" ORDER BY mtime DESC LIMIT 1", tagid);
if( rid==0 ) return;
pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
if( pWiki ){
| > | | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
Manifest *pWiki;
if( tagid==0 ) return;
rid = db_int(0, "SELECT rid FROM tagxref WHERE tagid=%d"
" ORDER BY mtime DESC LIMIT 1", tagid);
if( rid==0 ) return;
pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
if( pWiki ){
int mimetype = parse_mimetype( pWiki->zMimetype );
backlink_extract(pWiki->zWiki, mimetype, tagid, BKLNK_WIKI,
pWiki->rDate, 1);
manifest_destroy(pWiki);
}
}
/*
** Structure used to pass down state information through the
|
| ︙ | ︙ | |||
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
void markdown_extract_links(
char *zInputText,
Backlink *p
){
struct mkd_renderer html_renderer = {
/* prolog */ (void(*)(Blob*,void*))mkdn_noop0,
/* epilog */ (void(*)(Blob*,void*))mkdn_noop0,
/* blockcode */ (void(*)(Blob*,Blob*,void*))mkdn_noop0,
/* blockquote */ (void(*)(Blob*,Blob*,void*))mkdn_noop0,
/* blockhtml */ (void(*)(Blob*,Blob*,void*))mkdn_noop0,
/* header */ (void(*)(Blob*,Blob*,int,void*))mkdn_noop0,
/* hrule */ (void(*)(Blob*,void*))mkdn_noop0,
/* list */ (void(*)(Blob*,Blob*,int,void*))mkdn_noop0,
/* listitem */ (void(*)(Blob*,Blob*,int,void*))mkdn_noop0,
/* paragraph */ (void(*)(Blob*,Blob*,void*))mkdn_noop0,
/* table */ (void(*)(Blob*,Blob*,Blob*,void*))mkdn_noop0,
/* table_cell */ (void(*)(Blob*,Blob*,int,void*))mkdn_noop0,
/* table_row */ (void(*)(Blob*,Blob*,int,void*))mkdn_noop0,
/* autolink */ (int(*)(Blob*,Blob*,enum mkd_autolink,void*))mkdn_noop1,
/* codespan */ (int(*)(Blob*,Blob*,int,void*))mkdn_noop1,
/* dbl_emphas */ (int(*)(Blob*,Blob*,char,void*))mkdn_noop1,
/* emphasis */ (int(*)(Blob*,Blob*,char,void*))mkdn_noop1,
/* image */ (int(*)(Blob*,Blob*,Blob*,Blob*,void*))mkdn_noop1,
/* linebreak */ (int(*)(Blob*,void*))mkdn_noop1,
/* link */ backlink_md_link,
/* r_html_tag */ (int(*)(Blob*,Blob*,void*))mkdn_noop1,
/* tri_emphas */ (int(*)(Blob*,Blob*,char,void*))mkdn_noop1,
0, /* entity */
0, /* normal_text */
"*_", /* emphasis characters */
0 /* client data */
};
Blob out, in;
html_renderer.opaque = (void*)p;
blob_init(&out, 0, 0);
blob_init(&in, zInputText, -1);
markdown(&out, &in, &html_renderer);
blob_reset(&out);
blob_reset(&in);
}
/*
** Parse text looking for hyperlinks. Insert references into the
** BACKLINK table.
*/
void backlink_extract(
char *zSrc, /* Input text from which links are extracted */
| > > > > > > > > > > > > > > > > > | > | | | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
void markdown_extract_links(
char *zInputText,
Backlink *p
){
struct mkd_renderer html_renderer = {
/* prolog */ (void(*)(Blob*,void*))mkdn_noop0,
/* epilog */ (void(*)(Blob*,void*))mkdn_noop0,
/* footnotes */ (void(*)(Blob*,const Blob*, void*))mkdn_noop0,
/* blockcode */ (void(*)(Blob*,Blob*,void*))mkdn_noop0,
/* blockquote */ (void(*)(Blob*,Blob*,void*))mkdn_noop0,
/* blockhtml */ (void(*)(Blob*,Blob*,void*))mkdn_noop0,
/* header */ (void(*)(Blob*,Blob*,int,void*))mkdn_noop0,
/* hrule */ (void(*)(Blob*,void*))mkdn_noop0,
/* list */ (void(*)(Blob*,Blob*,int,void*))mkdn_noop0,
/* listitem */ (void(*)(Blob*,Blob*,int,void*))mkdn_noop0,
/* paragraph */ (void(*)(Blob*,Blob*,void*))mkdn_noop0,
/* table */ (void(*)(Blob*,Blob*,Blob*,void*))mkdn_noop0,
/* table_cell */ (void(*)(Blob*,Blob*,int,void*))mkdn_noop0,
/* table_row */ (void(*)(Blob*,Blob*,int,void*))mkdn_noop0,
/* footnoteitm*/ (void(*)(Blob*,const Blob*,int,int,void*))mkdn_noop0,
/* autolink */ (int(*)(Blob*,Blob*,enum mkd_autolink,void*))mkdn_noop1,
/* codespan */ (int(*)(Blob*,Blob*,int,void*))mkdn_noop1,
/* dbl_emphas */ (int(*)(Blob*,Blob*,char,void*))mkdn_noop1,
/* emphasis */ (int(*)(Blob*,Blob*,char,void*))mkdn_noop1,
/* image */ (int(*)(Blob*,Blob*,Blob*,Blob*,void*))mkdn_noop1,
/* linebreak */ (int(*)(Blob*,void*))mkdn_noop1,
/* link */ backlink_md_link,
/* r_html_tag */ (int(*)(Blob*,Blob*,void*))mkdn_noop1,
/* tri_emphas */ (int(*)(Blob*,Blob*,char,void*))mkdn_noop1,
/* footnoteref*/ (int(*)(Blob*,const Blob*,const Blob*,int,int,void*))mkdn_noop1,
0, /* entity */
0, /* normal_text */
"*_", /* emphasis characters */
0 /* client data */
};
Blob out, in;
html_renderer.opaque = (void*)p;
blob_init(&out, 0, 0);
blob_init(&in, zInputText, -1);
markdown(&out, &in, &html_renderer);
blob_reset(&out);
blob_reset(&in);
}
/*
** Transform mimetype string into an integer code.
** NOTE: In the sake of compatability empty string is parsed as MT_UNKNOWN;
** it is yet unclear whether it can safely be changed to MT_NONE.
*/
int parse_mimetype(const char* zMimetype){
if( zMimetype==0 ) return MT_NONE;
if( strstr(zMimetype,"wiki")!=0 ) return MT_WIKI;
if( strstr(zMimetype,"markdown")!=0 ) return MT_MARKDOWN;
return MT_UNKNOWN;
}
/*
** Parse text looking for hyperlinks. Insert references into the
** BACKLINK table.
*/
void backlink_extract(
char *zSrc, /* Input text from which links are extracted */
int mimetype, /* Mimetype of input. MT_NONE works as MT_WIKI */
int srcid, /* srcid for the source document */
int srctype, /* One of BKLNK_*. 0=comment 1=ticket 2=wiki */
double mtime, /* mtime field for new BACKLINK table entries */
int replaceFlag /* True to overwrite prior BACKLINK entries */
){
Backlink bklnk;
if( replaceFlag ){
db_multi_exec("DELETE FROM backlink WHERE srctype=%d AND srcid=%d",
srctype, srcid);
}
bklnk.srcid = srcid;
assert( ValidBklnk(srctype) );
assert( ValidMTC(mimetype) );
bklnk.srctype = srctype;
bklnk.mtime = mtime;
if( mimetype==MT_NONE || mimetype==MT_WIKI ){
wiki_extract_links(zSrc, &bklnk, srctype==BKLNK_COMMENT ? WIKI_INLINE : 0);
}else if( mimetype==MT_MARKDOWN ){
markdown_extract_links(zSrc, &bklnk);
}
}
/*
** COMMAND: test-backlinks
**
|
| ︙ | ︙ | |||
332 333 334 335 336 337 338 339 340 341 342 343 344 345 |
** --mtime DATETIME Use an alternative date/time. Defaults to the
** current date/time.
** --mimetype TYPE Use an alternative mimetype.
*/
void test_backlinks_cmd(void){
const char *zMTime = find_option("mtime",0,1);
const char *zMimetype = find_option("mimetype",0,1);
Blob in;
int srcid;
int srctype;
double mtime;
verify_all_options();
if( g.argc!=5 ){
| > | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 |
** --mtime DATETIME Use an alternative date/time. Defaults to the
** current date/time.
** --mimetype TYPE Use an alternative mimetype.
*/
void test_backlinks_cmd(void){
const char *zMTime = find_option("mtime",0,1);
const char *zMimetype = find_option("mimetype",0,1);
const int mimetype = parse_mimetype(zMimetype);
Blob in;
int srcid;
int srctype;
double mtime;
verify_all_options();
if( g.argc!=5 ){
|
| ︙ | ︙ | |||
363 364 365 366 367 368 369 |
" 'target='||quote(new.target)||"
" ' srctype='||quote(new.srctype)||"
" ' srcid='||quote(new.srcid)||"
" ' mtime='||datetime(new.mtime));\n"
" SELECT raise(ignore);\n"
"END;"
);
| | | 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 |
" 'target='||quote(new.target)||"
" ' srctype='||quote(new.srctype)||"
" ' srcid='||quote(new.srcid)||"
" ' mtime='||datetime(new.mtime));\n"
" SELECT raise(ignore);\n"
"END;"
);
backlink_extract(blob_str(&in),mimetype,srcid,srctype,mtime,0);
blob_reset(&in);
}
/*
** COMMAND: test-wiki-relink
**
|
| ︙ | ︙ |
Changes to src/bisect.c.
| ︙ | ︙ | |||
79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
{ "auto-next", "on", "Automatically run \"bisect next\" after each "
"\"bisect good\", \"bisect bad\", or \"bisect "
"skip\"" },
{ "direct-only", "on", "Follow only primary parent-child links, not "
"merges\n" },
{ "display", "chart", "Command to run after \"next\". \"chart\", "
"\"log\", \"status\", or \"none\"" },
};
/*
** Return the value of a boolean bisect option.
*/
int bisect_option(const char *zName){
unsigned int i;
| > | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
{ "auto-next", "on", "Automatically run \"bisect next\" after each "
"\"bisect good\", \"bisect bad\", or \"bisect "
"skip\"" },
{ "direct-only", "on", "Follow only primary parent-child links, not "
"merges\n" },
{ "display", "chart", "Command to run after \"next\". \"chart\", "
"\"log\", \"status\", or \"none\"" },
{ "linear", "off", "Do a linear scan rather than a true bisect" },
};
/*
** Return the value of a boolean bisect option.
*/
int bisect_option(const char *zName){
unsigned int i;
|
| ︙ | ︙ | |||
373 374 375 376 377 378 379 |
/*
** Reset the bisect subsystem.
*/
void bisect_reset(void){
db_multi_exec(
"DELETE FROM vvar WHERE name IN "
| | > | 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
/*
** Reset the bisect subsystem.
*/
void bisect_reset(void){
db_multi_exec(
"DELETE FROM vvar WHERE name IN "
" ('bisect-good', 'bisect-bad', 'bisect-log', 'bisect-complete',"
" 'bisect-linear')"
);
}
/*
** fossil bisect run [OPTIONS] COMMAND
**
** Invoke COMMAND (with arguments) repeatedly to perform the bisect.
|
| ︙ | ︙ | |||
628 629 630 631 632 633 634 |
/* No else here so that the above commands can morph themselves into
** a "next" command */
if( strncmp(zCmd, "next", n)==0 ){
PathNode *pMid;
char *zDisplay = db_lget("bisect-display","chart");
int m = (int)strlen(zDisplay);
bisect_path();
| > > > > | > | 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 |
/* No else here so that the above commands can morph themselves into
** a "next" command */
if( strncmp(zCmd, "next", n)==0 ){
PathNode *pMid;
char *zDisplay = db_lget("bisect-display","chart");
int m = (int)strlen(zDisplay);
bisect_path();
if( db_lget_boolean("bisect-linear",0) ){
pMid = path_next();
if( pMid && pMid->rid==db_lget_int("checkout",0) ) pMid = 0;
}else{
pMid = path_midpoint();
}
if( pMid==0 ){
fossil_print("bisect complete\n");
db_lset_int("bisect-complete",1);
}else{
int nSpan = path_length_not_hidden();
int nStep = path_search_depth();
g.argv[1] = "update";
|
| ︙ | ︙ |
Changes to src/blob.c.
| ︙ | ︙ | |||
51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #define blob_size(X) ((X)->nUsed) /* ** The buffer holding the blob data */ #define blob_buffer(X) ((X)->aData) /* ** Seek whence parameter values */ #define BLOB_SEEK_SET 1 #define BLOB_SEEK_CUR 2 #endif /* INTERFACE */ | > > > > > > > > > > > > > > > > > > > > > > > | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | #define blob_size(X) ((X)->nUsed) /* ** The buffer holding the blob data */ #define blob_buffer(X) ((X)->aData) /* ** Append blob contents to another */ #define blob_appendb(dest, src) \ blob_append((dest), blob_buffer(src), blob_size(src)) /* ** Append a string literal to a blob ** TODO: Consider renaming to blob_appendl() */ #define blob_append_literal(blob, literal) \ blob_append((blob), "" literal, (sizeof literal)-1) /* * The empty string in the second argument leads to a syntax error * when the macro is not used with a string literal. Unfortunately * the error is not overly explicit. */ /* ** TODO: Suggested for removal because the name seems misleading. */ #define blob_append_string blob_append_literal /* ** Seek whence parameter values */ #define BLOB_SEEK_SET 1 #define BLOB_SEEK_CUR 2 #endif /* INTERFACE */ |
| ︙ | ︙ | |||
323 324 325 326 327 328 329 | } nUsed = pBlob->nUsed; pBlob->nUsed += nData; pBlob->aData[pBlob->nUsed] = 0; memcpy(&pBlob->aData[nUsed], aData, nData); } | < < < < < < < | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
}
nUsed = pBlob->nUsed;
pBlob->nUsed += nData;
pBlob->aData[pBlob->nUsed] = 0;
memcpy(&pBlob->aData[nUsed], aData, nData);
}
/*
** Append a single character to the blob. If pBlob is zero then the
** character is written directly to stdout.
*/
void blob_append_char(Blob *pBlob, char c){
if( pBlob==0 || pBlob->nUsed+1 >= pBlob->nAlloc ){
blob_append_full(pBlob, &c, 1);
|
| ︙ | ︙ | |||
501 502 503 504 505 506 507 | return p->aData; } /* ** Compare two blobs. Return negative, zero, or positive if the first ** blob is less then, equal to, or greater than the second. */ | | | 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 |
return p->aData;
}
/*
** Compare two blobs. Return negative, zero, or positive if the first
** blob is less then, equal to, or greater than the second.
*/
int blob_compare(const Blob *pA, const Blob *pB){
int szA, szB, sz, rc;
blob_is_init(pA);
blob_is_init(pB);
szA = blob_size(pA);
szB = blob_size(pB);
sz = szA<szB ? szA : szB;
rc = memcmp(blob_buffer(pA), blob_buffer(pB), sz);
|
| ︙ | ︙ |
Changes to src/branch.c.
| ︙ | ︙ | |||
219 220 221 222 223 224 225 | } /* Commit */ db_end_transaction(0); /* Do an autosync push, if requested */ | | | 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | } /* Commit */ db_end_transaction(0); /* Do an autosync push, if requested */ if( !isPrivate ) autosync_loop(SYNC_PUSH, 0, "branch"); } /* ** Create a TEMP table named "tmp_brlist" with 7 columns: ** ** name Name of the branch ** mtime Time of last checkin on this branch |
| ︙ | ︙ |
Changes to src/builtin.c.
| ︙ | ︙ | |||
128 129 130 131 132 133 134 | blob_init(&x, (const char*)pData, nByte); blob_write_to_file(&x, g.argc==4 ? g.argv[3] : "-"); blob_reset(&x); } /* ** Input zList is a list of numeric identifiers for files in | | | < | | | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
blob_init(&x, (const char*)pData, nByte);
blob_write_to_file(&x, g.argc==4 ? g.argv[3] : "-");
blob_reset(&x);
}
/*
** Input zList is a list of numeric identifiers for files in
** aBuiltinFiles[]. Return the concatenation of all of those files
** using mimetype zType, or as text/javascript if zType is 0.
*/
static void builtin_deliver_multiple_js_files(
const char *zList, /* List of numeric identifiers */
const char *zType /* Override mimetype */
){
Blob *pOut;
if( zType==0 ) zType = "text/javascript";
cgi_set_content_type(zType);
pOut = cgi_output_blob();
while( zList[0] ){
int i = atoi(zList);
if( i>0 && i<=count(aBuiltinFiles) ){
blob_appendf(pOut, "/* %s */\n", aBuiltinFiles[i-1].zName);
blob_append(pOut, (const char*)aBuiltinFiles[i-1].pData,
aBuiltinFiles[i-1].nByte);
}
while( fossil_isdigit(zList[0]) ) zList++;
if( zList[0]==',' ) zList++;
}
return;
}
/*
** WEBPAGE: builtin loadavg-exempt
**
** Return one of many built-in content files. Query parameters:
**
** name=FILENAME Return the single file whose name is FILENAME.
** mimetype=TYPE Override the mimetype in the returned file to
** be TYPE. If this query parameter is omitted
** (the usual case) then the mimetype is inferred
|
| ︙ | ︙ | |||
201 202 203 204 205 206 207 |
}
cgi_set_status(404, "Not Found");
@ File "%h(zName)" not found
return;
}
if( zType==0 ){
if( sqlite3_strglob("*.js", zName)==0 ){
| | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
}
cgi_set_status(404, "Not Found");
@ File "%h(zName)" not found
return;
}
if( zType==0 ){
if( sqlite3_strglob("*.js", zName)==0 ){
zType = "text/javascript";
}else{
zType = mimetype_from_name(zName);
}
}
cgi_set_content_type(zType);
if( zId
&& (nId = (int)strlen(zId))>=8
|
| ︙ | ︙ | |||
229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
int nReq; /* Number of slots in aReq[] currently used */
int nSent; /* Number of slots in aReq[] fulfilled */
int eDelivery; /* Delivery mechanism */
} builtin;
#if INTERFACE
/* Various delivery mechanisms. The 0 option is the default.
*/
#define JS_INLINE 0 /* inline, batched together at end of file */
#define JS_SEPARATE 1 /* Separate HTTP request for each JS file */
#define JS_BUNDLED 2 /* One HTTP request to load all JS files */
/* concatenated together into a bundle */
#endif /* INTERFACE */
| > > | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
int nReq; /* Number of slots in aReq[] currently used */
int nSent; /* Number of slots in aReq[] fulfilled */
int eDelivery; /* Delivery mechanism */
} builtin;
#if INTERFACE
/* Various delivery mechanisms. The 0 option is the default.
** MAINTENANCE NOTE: Review/update the builtin_set_js_delivery_mode() and
** builtin_get_js_delivery_mode_name() functions if values are changed/added.
*/
#define JS_INLINE 0 /* inline, batched together at end of file */
#define JS_SEPARATE 1 /* Separate HTTP request for each JS file */
#define JS_BUNDLED 2 /* One HTTP request to load all JS files */
/* concatenated together into a bundle */
#endif /* INTERFACE */
|
| ︙ | ︙ | |||
266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
/*
** Returns the current JS delivery mode: one of JS_INLINE,
** JS_SEPARATE, JS_BUNDLED.
*/
int builtin_get_js_delivery_mode(void){
return builtin.eDelivery;
}
/*
** The caller wants the Javascript file named by zFilename to be
** included in the generated page. Add the file to the queue of
** requested javascript resources, if it is not there already.
**
** The current implementation queues the file to be included in the
| > > > > > > > > > > > > > > > > > > > > | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
/*
** Returns the current JS delivery mode: one of JS_INLINE,
** JS_SEPARATE, JS_BUNDLED.
*/
int builtin_get_js_delivery_mode(void){
return builtin.eDelivery;
}
/*
** Returns the name of the current JS delivery mode for reuse with the --jsmode
** option, i.e. the other way around than builtin_set_js_delivery_mode().
*/
const char *builtin_get_js_delivery_mode_name(void){
switch( builtin.eDelivery ){
case JS_SEPARATE: {
return "separate";
}
case JS_BUNDLED: {
return "bundled";
}
case JS_INLINE:
/*FALLTHROUGH*/
default: {
return "inline";
}
}
}
/*
** The caller wants the Javascript file named by zFilename to be
** included in the generated page. Add the file to the queue of
** requested javascript resources, if it is not there already.
**
** The current implementation queues the file to be included in the
|
| ︙ | ︙ |
Changes to src/cgi.c.
| ︙ | ︙ | |||
305 306 307 308 309 310 311 |
){
char const *zSecure = "";
if(!g.isHTTP) return /* e.g. JSON CLI mode, where g.zTop is not set */;
else if( zPath==0 ){
zPath = g.zTop;
if( zPath[0]==0 ) zPath = "/";
}
| | | 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
){
char const *zSecure = "";
if(!g.isHTTP) return /* e.g. JSON CLI mode, where g.zTop is not set */;
else if( zPath==0 ){
zPath = g.zTop;
if( zPath[0]==0 ) zPath = "/";
}
if( g.zBaseURL!=0 && fossil_strncmp(g.zBaseURL, "https:", 6)==0 ){
zSecure = " secure;";
}
if( lifetime!=0 ){
blob_appendf(&extraHeader,
"Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly; "
"%s Version=1\r\n",
zName, lifetime>0 ? zValue : "null", zPath, lifetime, zSecure);
|
| ︙ | ︙ | |||
328 329 330 331 332 333 334 |
/*
** Return true if the response should be sent with Content-Encoding: gzip.
*/
static int is_gzippable(void){
if( g.fNoHttpCompress ) return 0;
if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
| > > > | > > | > > > > > > > > > | > > > > > > > > > > | 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
/*
** Return true if the response should be sent with Content-Encoding: gzip.
*/
static int is_gzippable(void){
if( g.fNoHttpCompress ) return 0;
if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
/* Maintenance note: this oddball structure is intended to make
** adding new mimetypes to this list less of a performance hit than
** doing a strcmp/glob over a growing set of compressible types. */
switch(zContentType ? *zContentType : 0){
case (int)'a':
if(0==fossil_strncmp("application/",zContentType,12)){
const char * z = &zContentType[12];
switch(*z){
case (int)'j':
return fossil_strcmp("javascript", z)==0
|| fossil_strcmp("json", z)==0;
case (int)'w': return fossil_strcmp("wasm", z)==0;
case (int)'x':
return fossil_strcmp("x-tcl", z)==0
|| fossil_strcmp("x-tar", z)==0;
default:
return sqlite3_strglob("*xml", z)==0;
}
}
break;
case (int)'i':
return fossil_strcmp(zContentType, "image/svg+xml")==0
|| fossil_strcmp(zContentType, "image/vnd.microsoft.icon")==0;
case (int)'t':
return fossil_strncmp(zContentType, "text/", 5)==0;
}
return 0;
}
/*
** The following routines read or write content from/to the wire for
** an HTTP request. Depending on settings the content might be coming
** from or going to a socket, or a file, or it might come from or go
|
| ︙ | ︙ | |||
417 418 419 420 421 422 423 424 425 426 427 428 429 430 |
*/
static void cgi_fflush(void){
if( !g.httpUseSSL ){
fflush(g.httpOut);
}
}
/*
** Generate the reply to a web request. The output might be an
** full HTTP response, or a CGI response, depending on how things have
** be set up.
**
** The reply consists of a response header (an HTTP or CGI response header)
| > > > > > > > > > > > > > > > > > > > | 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
*/
static void cgi_fflush(void){
if( !g.httpUseSSL ){
fflush(g.httpOut);
}
}
/*
** Given a Content-Type value, returns a string suitable for appending
** to the Content-Type header for adding (or not) the "; charset=..."
** part. It returns an empty string for most types or if zContentType
** is NULL.
**
** See forum post f60dece061c364d1 for the discussions which lead to
** this. Previously we always appended the charset, but WASM loaders
** are pedantic and refuse to load any responses which have a
** charset. Also, adding a charset is not strictly appropriate for
** most types (and not required for many others which may ostensibly
** benefit from one, as detailed in that forum post).
*/
static const char * content_type_charset(const char *zContentType){
if(0==fossil_strncmp(zContentType,"text/",5)){
return "; charset=utf-8";
}
return "";
}
/*
** Generate the reply to a web request. The output might be an
** full HTTP response, or a CGI response, depending on how things have
** be set up.
**
** The reply consists of a response header (an HTTP or CGI response header)
|
| ︙ | ︙ | |||
491 492 493 494 495 496 497 |
** a CGI script.
*/
/* Content intended for logged in users should only be cached in
** the browser, not some shared location.
*/
if( iReplyStatus!=304 ) {
| | > | 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 |
** a CGI script.
*/
/* Content intended for logged in users should only be cached in
** the browser, not some shared location.
*/
if( iReplyStatus!=304 ) {
blob_appendf(&hdr, "Content-Type: %s%s\r\n", zContentType,
content_type_charset(zContentType));
if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
cgi_combine_header_and_body();
blob_compress(&cgiContent[0], &cgiContent[0]);
}
if( is_gzippable() && iReplyStatus!=206 ){
int i;
|
| ︙ | ︙ | |||
567 568 569 570 571 572 573 |
NORETURN void cgi_redirect_with_status(
const char *zURL,
int iStat,
const char *zStat
){
char *zLocation;
CGIDEBUG(("redirect to %s\n", zURL));
| > | | 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 |
NORETURN void cgi_redirect_with_status(
const char *zURL,
int iStat,
const char *zStat
){
char *zLocation;
CGIDEBUG(("redirect to %s\n", zURL));
if( fossil_strncmp(zURL,"http:",5)==0
|| fossil_strncmp(zURL,"https:",6)==0 ){
zLocation = mprintf("Location: %s\r\n", zURL);
}else if( *zURL=='/' ){
int n1 = (int)strlen(g.zBaseURL);
int n2 = (int)strlen(g.zTop);
if( g.zBaseURL[n1-1]=='/' ) zURL++;
zLocation = mprintf("Location: %.*s%s\r\n", n1-n2, g.zBaseURL, zURL);
}else{
|
| ︙ | ︙ | |||
651 652 653 654 655 656 657 |
if( zRef==0 ) return 0;
if( requirePost ){
const char *zMethod = P("REQUEST_METHOD");
if( zMethod==0 ) return 0;
if( strcmp(zMethod,"POST")!=0 ) return 0;
}
nBase = (int)strlen(g.zBaseURL);
| | | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 |
if( zRef==0 ) return 0;
if( requirePost ){
const char *zMethod = P("REQUEST_METHOD");
if( zMethod==0 ) return 0;
if( strcmp(zMethod,"POST")!=0 ) return 0;
}
nBase = (int)strlen(g.zBaseURL);
if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0;
if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0;
return 1;
}
/*
** Information about all query parameters, post parameter, cookies and
** CGI environment variables are stored in a hash table as follows:
|
| ︙ | ︙ | |||
918 919 920 921 922 923 924 |
){
char *z = *pz;
int len = *pLen;
int i;
int nBoundary = strlen(zBoundary);
*pnContent = len;
for(i=0; i<len; i++){
| | > | 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 |
){
char *z = *pz;
int len = *pLen;
int i;
int nBoundary = strlen(zBoundary);
*pnContent = len;
for(i=0; i<len; i++){
if( z[i]=='\n' && fossil_strncmp(zBoundary, &z[i+1],
nBoundary)==0 ){
if( i>0 && z[i-1]=='\r' ) i--;
z[i] = 0;
*pnContent = i;
i += nBoundary;
break;
}
}
|
| ︙ | ︙ | |||
1346 1347 1348 1349 1350 1351 1352 |
/*
** Decode POST parameter information in the cgiIn content, if any.
*/
void cgi_decode_post_parameters(void){
int len = blob_size(&g.cgiIn);
if( len==0 ) return;
if( fossil_strcmp(g.zContentType,"application/x-www-form-urlencoded")==0
| | | 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 |
/*
** Decode POST parameter information in the cgiIn content, if any.
*/
void cgi_decode_post_parameters(void){
int len = blob_size(&g.cgiIn);
if( len==0 ) return;
if( fossil_strcmp(g.zContentType,"application/x-www-form-urlencoded")==0
|| fossil_strncmp(g.zContentType,"multipart/form-data",19)==0
){
char *z = blob_str(&g.cgiIn);
cgi_trace(z);
if( g.zContentType[0]=='a' ){
add_param_list(z, '&');
}else{
process_multipart_form_data(z, len);
|
| ︙ | ︙ | |||
2307 2308 2309 2310 2311 2312 2313 |
iPort++;
continue;
}
break;
}
if( iPort>mxPort ){
if( mnPort==mxPort ){
| | | | 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 |
iPort++;
continue;
}
break;
}
if( iPort>mxPort ){
if( mnPort==mxPort ){
fossil_fatal("unable to open listening socket on port %d", mnPort);
}else{
fossil_fatal("unable to open listening socket on any"
" port in the range %d..%d", mnPort, mxPort);
}
}
if( iPort>mxPort ) return 1;
listen(listener,10);
fossil_print("Listening for %s requests on TCP port %d\n",
(flags & HTTP_SERVER_SCGI)!=0 ? "SCGI" :
g.httpUseSSL?"TLS-encrypted HTTPS":"HTTP", iPort);
fflush(stdout);
if( zBrowser ){
assert( strstr(zBrowser,"%d")!=0 );
zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
#if defined(__CYGWIN__)
/* On Cygwin, we can do better than "echo" */
if( fossil_strncmp(zBrowser, "echo ", 5)==0 ){
wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5);
wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */
if( (size_t)ShellExecuteW(0, L"open", wUrl, 0, 0, 1)<33 ){
fossil_warning("cannot start browser\n");
}
}else
#endif
|
| ︙ | ︙ | |||
2484 2485 2486 2487 2488 2489 2490 |
static const char *const azMonths[] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};
if( 7==sscanf(zDate, "%3[A-Za-z], %d %3[A-Za-z] %d %d:%d:%d", zIgnore,
&mday, zMonth, &year, &hour, &min, &sec)){
if( year > 1900 ) year -= 1900;
for(mon=0; azMonths[mon]; mon++){
| | | 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 |
static const char *const azMonths[] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};
if( 7==sscanf(zDate, "%3[A-Za-z], %d %3[A-Za-z] %d %d:%d:%d", zIgnore,
&mday, zMonth, &year, &hour, &min, &sec)){
if( year > 1900 ) year -= 1900;
for(mon=0; azMonths[mon]; mon++){
if( !fossil_strncmp( azMonths[mon], zMonth, 3 )){
int nDay;
int isLeapYr;
static int priorDays[] =
{ 0, 31, 59, 90,120,151,181,212,243,273,304,334 };
if( mon<0 ){
int nYear = (11 - mon)/12;
year -= nYear;
|
| ︙ | ︙ |
Changes to src/chat.c.
| ︙ | ︙ | |||
126 127 128 129 130 131 132 | /* ** SETTING: chat-alert-sound width=10 ** ** This is the name of the builtin sound file to use for the alert tone. ** The value must be the name of a builtin WAV file. */ /* | | | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | /* ** SETTING: chat-alert-sound width=10 ** ** This is the name of the builtin sound file to use for the alert tone. ** The value must be the name of a builtin WAV file. */ /* ** WEBPAGE: chat loadavg-exempt ** ** Start up a browser-based chat session. ** ** This is the main page that humans use to access the chatroom. Simply ** point a web-browser at /chat and the screen fills with the latest ** chat messages, and waits for new one. ** |
| ︙ | ︙ | |||
340 341 342 343 344 345 346 |
}else{
CX("}");
}
fossil_free(zTime);
}
/*
| | | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 |
}else{
CX("}");
}
fossil_free(zTime);
}
/*
** WEBPAGE: chat-send hidden loadavg-exempt
**
** This page receives (via XHR) a new chat-message and/or a new file
** to be entered into the chat history.
**
** On success it responds with an empty response: the new message
** should be fetched via /chat-poll. On error, e.g. login expiry,
** it emits a JSON response in the same form as described for
|
| ︙ | ︙ | |||
446 447 448 449 450 451 452 |
zOut = chat_format_to_html(g.argv[i]);
fossil_print("[%d]: %s\n", i, zOut);
fossil_free(zOut);
}
}
/*
| | | 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 |
zOut = chat_format_to_html(g.argv[i]);
fossil_print("[%d]: %s\n", i, zOut);
fossil_free(zOut);
}
}
/*
** WEBPAGE: chat-poll hidden loadavg-exempt
**
** The chat page generated by /chat using an XHR to this page to
** request new chat content. A typical invocation is:
**
** /chat-poll/N
** /chat-poll?name=N
**
|
| ︙ | ︙ | |||
665 666 667 668 669 670 671 | db_finalize(&q1); blob_append(&json, "\n]}", 3); cgi_set_content(&json); return; } /* | | | 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 | db_finalize(&q1); blob_append(&json, "\n]}", 3); cgi_set_content(&json); return; } /* ** WEBPAGE: chat-fetch-one hidden loadavg-exempt ** ** /chat-fetch-one/N ** ** Fetches a single message with the given ID, if available. ** ** Options: ** |
| ︙ | ︙ | |||
742 743 744 745 746 747 748 |
}else{
ajax_route_error(404,"Chat message #%d not found.", msgid);
}
db_finalize(&q);
}
/*
| | | 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 |
}else{
ajax_route_error(404,"Chat message #%d not found.", msgid);
}
db_finalize(&q);
}
/*
** WEBPAGE: chat-download hidden loadavg-exempt
**
** Download the CHAT.FILE attachment associated with a single chat
** entry. The "name" query parameter begins with an integer that
** identifies the particular chat message. The integer may be followed
** by a / and a filename, which will indicate to the browser to use
** the indicated name when saving the file.
*/
|
| ︙ | ︙ | |||
775 776 777 778 779 780 781 | db_blob(&r, "SELECT file FROM chat WHERE msgid=%d", msgid); cgi_set_content_type(zMime); cgi_set_content(&r); } /* | | | 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 |
db_blob(&r, "SELECT file FROM chat WHERE msgid=%d", msgid);
cgi_set_content_type(zMime);
cgi_set_content(&r);
}
/*
** WEBPAGE: chat-delete hidden loadavg-exempt
**
** Delete the chat entry identified by the name query parameter.
** Invoking fetch("chat-delete/"+msgid) from javascript in the client
** will delete a chat entry from the CHAT table.
**
** This routine both deletes the identified chat entry and also inserts
** a new entry with the current timestamp and with:
|
| ︙ | ︙ |
Changes to src/checkin.c.
| ︙ | ︙ | |||
2346 2347 2348 2349 2350 2351 2352 |
** Autosync if autosync is enabled and this is not a private check-in.
*/
if( !g.markPrivate ){
int syncFlags = SYNC_PULL;
if( vid!=0 && !allowFork && !forceFlag ){
syncFlags |= SYNC_CKIN_LOCK;
}
| | | 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 |
** Autosync if autosync is enabled and this is not a private check-in.
*/
if( !g.markPrivate ){
int syncFlags = SYNC_PULL;
if( vid!=0 && !allowFork && !forceFlag ){
syncFlags |= SYNC_CKIN_LOCK;
}
if( autosync_loop(syncFlags, 1, "commit") ){
fossil_exit(1);
}
}
/* So that older versions of Fossil (that do not understand delta-
** manifest) can continue to use this repository, do not create a new
** delta-manifest unless this repository already contains one or more
|
| ︙ | ︙ | |||
2552 2553 2554 2555 2556 2557 2558 |
db_end_transaction(0);
db_begin_transaction();
if( !g.markPrivate && vid!=0 && !allowFork && !forceFlag ){
/* Do another auto-pull, renewing the check-in lock. Then set
** bRecheck so that we loop back above to verify that the check-in
** is still not against a closed branch and still won't fork. */
int syncFlags = SYNC_PULL|SYNC_CKIN_LOCK;
| | | 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 |
db_end_transaction(0);
db_begin_transaction();
if( !g.markPrivate && vid!=0 && !allowFork && !forceFlag ){
/* Do another auto-pull, renewing the check-in lock. Then set
** bRecheck so that we loop back above to verify that the check-in
** is still not against a closed branch and still won't fork. */
int syncFlags = SYNC_PULL|SYNC_CKIN_LOCK;
if( autosync_loop(syncFlags, 1, "commit") ){
fossil_fatal("Auto-pull failed. Commit aborted.");
}
bRecheck = 1;
}
}else{
blob_zero(&comment);
}
|
| ︙ | ︙ | |||
2877 2878 2879 2880 2881 2882 2883 |
blob_write_to_file(&tagslist, zManifestFile);
blob_reset(&tagslist);
free(zManifestFile);
}
if( !g.markPrivate ){
int syncFlags = SYNC_PUSH | SYNC_PULL | SYNC_IFABLE;
| < | | 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 |
blob_write_to_file(&tagslist, zManifestFile);
blob_reset(&tagslist);
free(zManifestFile);
}
if( !g.markPrivate ){
int syncFlags = SYNC_PUSH | SYNC_PULL | SYNC_IFABLE;
autosync_loop(syncFlags, 0, "commit");
}
if( count_nonbranch_children(vid)>1 ){
fossil_print("**** warning: a fork has occurred *****\n");
}else{
leaf_ambiguity_warning(nvid,nvid);
}
}
|
Changes to src/db.c.
| ︙ | ︙ | |||
3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 |
"SELECT value FROM vvar WHERE name=%Q", zName);
}
void db_lset(const char *zName, const char *zValue){
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%Q)", zName, zValue);
}
int db_lget_int(const char *zName, int dflt){
return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
}
void db_lset_int(const char *zName, int value){
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
}
/* Va-args versions of db_get(), db_set(), and db_unset()
**
| > > > > > > > > > > | 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 |
"SELECT value FROM vvar WHERE name=%Q", zName);
}
void db_lset(const char *zName, const char *zValue){
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%Q)", zName, zValue);
}
int db_lget_int(const char *zName, int dflt){
return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
}
int db_lget_boolean(const char *zName, int dflt){
char *zVal = db_lget(zName, dflt ? "on" : "off");
if( is_truth(zVal) ){
dflt = 1;
}else if( is_false(zVal) ){
dflt = 0;
}
fossil_free(zVal);
return dflt;
}
void db_lset_int(const char *zName, int value){
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
}
/* Va-args versions of db_get(), db_set(), and db_unset()
**
|
| ︙ | ︙ | |||
3476 3477 3478 3479 3480 3481 3482 | va_start(ap, zFormat); zName = vmprintf(zFormat, ap); va_end(ap); db_unset(zName/*works-like:"x"*/, iGlobal); fossil_free(zName); } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > | 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 |
va_start(ap, zFormat);
zName = vmprintf(zFormat, ap);
va_end(ap);
db_unset(zName/*works-like:"x"*/, iGlobal);
fossil_free(zName);
}
/*
** Get a setting that is tailored to subsystem. The return value is
** NULL if the setting does not exist, or a string obtained from mprintf()
** if the setting is available.
**
** The actual setting can be a comma-separated list of values of the form:
**
** * VALUE
** * SUBSYSTEM=VALUE
**
** A VALUE without the SUBSYSTEM= prefix is the default. This routine
** returns the VALUE that with the matching SUBSYSTEM, or the default
** VALUE if there is no match.
*/
char *db_get_for_subsystem(const char *zName, const char *zSubsys){
int nSubsys;
char *zToFree = 0;
char *zCopy;
char *zNext;
char *zResult = 0;
const char *zSetting = db_get(zName, 0);
if( zSetting==0 ) return 0;
zCopy = zToFree = fossil_strdup(zSetting);
if( zSubsys==0 ) zSubsys = "";
nSubsys = (int)strlen(zSubsys);
while( zCopy ){
zNext = strchr(zCopy, ',');
if( zNext ){
zNext[0] = 0;
do{ zNext++; }while( fossil_isspace(zNext[0]) );
if( zNext[0]==0 ) zNext = 0;
}
if( strchr(zCopy,'=')==0 ){
if( zResult==0 ) zResult = zCopy;
}else
if( nSubsys
&& strncmp(zCopy, zSubsys, nSubsys)==0
&& zCopy[nSubsys]=='='
){
zResult = &zCopy[nSubsys+1];
break;
}
zCopy = zNext;
}
if( zResult ) zResult = fossil_strdup(zResult);
fossil_free(zToFree);
return zResult;
}
#if INTERFACE
/* Manifest generation flags */
#define MFESTFLG_RAW 0x01
#define MFESTFLG_UUID 0x02
#define MFESTFLG_TAGS 0x04
#define MFESTFLG_DESCR 0x08
|
| ︙ | ︙ | |||
3624 3625 3626 3627 3628 3629 3630 | ** with the local repository. If you commit this checkout, ** it will become a new "initial" commit in the repository. ** -f|--force Continue with the open even if the working directory is ** not empty. ** --force-missing Force opening a repository with missing content ** -k|--keep Only modify the manifest and manifest.uuid files ** --nested Allow opening a repository inside an opened checkout | | > > > | 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 | ** with the local repository. If you commit this checkout, ** it will become a new "initial" commit in the repository. ** -f|--force Continue with the open even if the working directory is ** not empty. ** --force-missing Force opening a repository with missing content ** -k|--keep Only modify the manifest and manifest.uuid files ** --nested Allow opening a repository inside an opened checkout ** --nosync Do not auto-sync the repository prior to opening even ** if the autosync setting is on. ** --repodir DIR If REPOSITORY is a URI that will be cloned, store ** the clone in DIR rather than in "." ** --setmtime Set timestamps of all files to match their SCM-side ** times (the timestamp of the last checkin which modified ** them). ** --sync Auto-sync prior to opening even if the autosync setting ** is off. ** --verbose If passed a URI then this flag is passed on to the clone ** operation, otherwise it has no effect. ** --workdir DIR Use DIR as the working directory instead of ".". The DIR ** directory is created if it does not exist. ** ** See also: [[close]], [[clone]] */ |
| ︙ | ︙ | |||
3651 3652 3653 3654 3655 3656 3657 |
static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
const char *zWorkDir; /* --workdir value */
const char *zRepo = 0; /* Name of the repository file */
const char *zRepoDir = 0; /* --repodir value */
char *zPwd; /* Initial working directory */
int isUri = 0; /* True if REPOSITORY is a URI */
int nLocal; /* Number of preexisting files in cwd */
| < | | < | 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 |
static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
const char *zWorkDir; /* --workdir value */
const char *zRepo = 0; /* Name of the repository file */
const char *zRepoDir = 0; /* --repodir value */
char *zPwd; /* Initial working directory */
int isUri = 0; /* True if REPOSITORY is a URI */
int nLocal; /* Number of preexisting files in cwd */
int bVerbose = 0; /* --verbose option for clone */
url_proxy_options();
emptyFlag = find_option("empty",0,0)!=0;
keepFlag = find_option("keep","k",0)!=0;
forceMissingFlag = find_option("force-missing",0,0)!=0;
allowNested = find_option("nested",0,0)!=0;
setmtimeFlag = find_option("setmtime",0,0)!=0;
zWorkDir = find_option("workdir",0,1);
zRepoDir = find_option("repodir",0,1);
bForce = find_option("force","f",0)!=0;
if( find_option("nosync",0,0) ) g.fNoSync = 1;
bVerbose = find_option("verbose",0,0)!=0;
zPwd = file_getcwd(0,0);
/* We should be done with options.. */
verify_all_options();
if( g.argc!=3 && g.argc!=4 ){
usage("REPOSITORY-FILENAME ?VERSION?");
}
|
| ︙ | ︙ | |||
3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 |
if( zWorkDir ) file_chdir(zWorkDir, 0);
}else if( zRepoDir ){
fossil_fatal("the --repodir option only makes sense if the REPOSITORY "
"argument is a URI that begins with http:, https:, ssh:, "
"or file:");
}
db_open_repository(zRepo);
/* Figure out which revision to open. */
if( !emptyFlag ){
if( g.argc==4 ){
g.zOpenRevision = g.argv[3];
}else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
g.zOpenRevision = db_get("main-branch", 0);
}
| > < | < < | 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 |
if( zWorkDir ) file_chdir(zWorkDir, 0);
}else if( zRepoDir ){
fossil_fatal("the --repodir option only makes sense if the REPOSITORY "
"argument is a URI that begins with http:, https:, ssh:, "
"or file:");
}
db_open_config(0,0);
db_open_repository(zRepo);
/* Figure out which revision to open. */
if( !emptyFlag ){
if( g.argc==4 ){
g.zOpenRevision = g.argv[3];
}else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
g.zOpenRevision = db_get("main-branch", 0);
}
if( autosync_loop(SYNC_PULL, !bForce, "open") && !bForce ){
fossil_fatal("unable to auto-sync the repository");
}
}
#if defined(_WIN32) || defined(__CYGWIN__)
# define LOCALDB_NAME "./_FOSSIL_"
|
| ︙ | ︙ | |||
3949 3950 3951 3952 3953 3954 3955 | ** ** Better robot exclusion is obtained when this setting is 1 versus 2. ** However, a value of 1 causes the visited/unvisited colors of hyperlinks ** to stop working on Safari-derived web browsers. When this setting is 2, ** the hyperlinks work better on Safari, but more robots are able to sneak ** in. */ | > | > | | > | < | | | | | > | > > > > > > > > > | 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 |
**
** Better robot exclusion is obtained when this setting is 1 versus 2.
** However, a value of 1 causes the visited/unvisited colors of hyperlinks
** to stop working on Safari-derived web browsers. When this setting is 2,
** the hyperlinks work better on Safari, but more robots are able to sneak
** in.
*/
/*
** SETTING: auto-hyperlink-delay width=16 default=0
**
** When the auto-hyperlink setting is 1, the javascript that runs to set
** the href= attributes of hyperlinks delays by this many milliseconds
** after the page load. Suggested values: 50 to 200.
*/
/*
** SETTING: auto-hyperlink-mouseover boolean default=off
**
** When the auto-hyperlink setting is 1 and this setting is on, the
** javascript that runs to set the href= attributes of hyperlinks waits
** until either a mousedown or mousemove event is seen. This helps
** to distinguish real users from robots. For maximum robot defense,
** the recommended setting is ON.
*/
/*
** SETTING: auto-shun boolean default=on
** If enabled, automatically pull the shunning list
** from a server to which the client autosyncs.
*/
/*
** SETTING: autosync width=16 default=on
** This setting determines when autosync occurs. The setting is a
** string that provides a lot of flexibility for determining when and
** when not to autosync. Examples:
**
** on Always autosync for command where autosync
** makes sense ("commit", "merge", "open", "update")
**
** off Never autosync.
**
** pullonly Only to pull autosyncs
**
** on,open=off Autosync for most commands, but not for "open"
**
** off,commit=pullonly Do not autosync, except do a pull before each
** "commit", presumably to avoid undesirable
** forks.
**
** The syntax is a comma-separated list of VALUE and COMMAND=VALUE entries.
** A plain VALUE entry is the default that is used if no COMMAND matches.
** Otherwise, the VALUE of the matching command is used.
*/
/*
** SETTING: autosync-tries width=16 default=1
** If autosync is enabled setting this to a value greater
** than zero will cause autosync to try no more than this
** number of attempts if there is a sync failure.
*/
|
| ︙ | ︙ | |||
4311 4312 4313 4314 4315 4316 4317 | ** to obtain a check-in lock during auto-sync, the server will ** send the "pragma avoid-delta-manifests" statement in its reply, ** which will cause the client to avoid generating a delta ** manifest. */ /* ** SETTING: proxy width=32 default=off | < | < | | 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 | ** to obtain a check-in lock during auto-sync, the server will ** send the "pragma avoid-delta-manifests" statement in its reply, ** which will cause the client to avoid generating a delta ** manifest. */ /* ** SETTING: proxy width=32 default=off ** URL of the HTTP proxy. If "system", the "http_proxy" environment variable is ** consulted. If undefined or "off", a direct HTTP connection is used. */ /* ** SETTING: redirect-to-https default=0 width=-1 ** Specifies whether or not to redirect http:// requests to ** https:// URIs. A value of 0 (the default) means not to ** redirect, 1 means to redirect only the /login page, and 2 ** means to always redirect. |
| ︙ | ︙ | |||
4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 |
**
** See also: [[configuration]]
*/
void setting_cmd(void){
int i;
int globalFlag = find_option("global","g",0)!=0;
int exactFlag = find_option("exact",0,0)!=0;
int unsetFlag = g.argv[1][0]=='u';
int nSetting;
const Setting *aSetting = setting_info(&nSetting);
find_repository_option();
verify_all_options();
db_open_config(1, 0);
if( !globalFlag ){
| > > > | 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 |
**
** See also: [[configuration]]
*/
void setting_cmd(void){
int i;
int globalFlag = find_option("global","g",0)!=0;
int exactFlag = find_option("exact",0,0)!=0;
/* Undocumented "--test-for-subsystem SUBSYS" option used to test
** the db_get_for_subsystem() interface: */
const char *zSubsys = find_option("test-for-subsystem",0,1);
int unsetFlag = g.argv[1][0]=='u';
int nSetting;
const Setting *aSetting = setting_info(&nSetting);
find_repository_option();
verify_all_options();
db_open_config(1, 0);
if( !globalFlag ){
|
| ︙ | ︙ | |||
4623 4624 4625 4626 4627 4628 4629 |
}else{
while( pSetting->name ){
if( exactFlag ){
if( fossil_strcmp(pSetting->name,zName)!=0 ) break;
}else{
if( fossil_strncmp(pSetting->name,zName,n)!=0 ) break;
}
| > > > > > > > > > | > | 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 |
}else{
while( pSetting->name ){
if( exactFlag ){
if( fossil_strcmp(pSetting->name,zName)!=0 ) break;
}else{
if( fossil_strncmp(pSetting->name,zName,n)!=0 ) break;
}
if( zSubsys ){
char *zValue = db_get_for_subsystem(pSetting->name, zSubsys);
fossil_print("%s (subsystem %s) ->", pSetting->name, zSubsys);
if( zValue ){
fossil_print(" [%s]", zValue);
fossil_free(zValue);
}
fossil_print("\n");
}else{
print_setting(pSetting);
}
pSetting++;
}
}
}else{
usage("?PROPERTY? ?VALUE? ?-global?");
}
}
|
| ︙ | ︙ |
Changes to src/default.css.
| ︙ | ︙ | |||
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 |
}
.capsumWrite {
background-color: #ffb;
}
label {
white-space: nowrap;
}
.copy-button {
display: inline-block;
width: 14px;
height: 14px;
/*Note: .24em is slightly smaller than the average width of a normal space.*/
margin: -2px .24em 0 0;
padding: 0;
| > > > | 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 |
}
.capsumWrite {
background-color: #ffb;
}
label {
white-space: nowrap;
}
label[for] {
cursor: pointer;
}
.copy-button {
display: inline-block;
width: 14px;
height: 14px;
/*Note: .24em is slightly smaller than the average width of a normal space.*/
margin: -2px .24em 0 0;
padding: 0;
|
| ︙ | ︙ | |||
1073 1074 1075 1076 1077 1078 1079 |
color: darkred;
background: yellow;
}
.warning {
color: black;
background: yellow;
}
| | | | | | > > > > > | | 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 |
color: darkred;
background: yellow;
}
.warning {
color: black;
background: yellow;
}
.hidden, .initially-hidden {
/* The framework-wide way of hiding elements is to assign them th
.hidden class. To make them visible again, remove it. The
!important qualifiers are unfortunate but sometimes necessary
when hidden element has other classes which specify
visibility-related options. The .initially-hidden class is for
pages which need to show, e.g., a progress widget while a large
WASM blob loads. Elements aside from that load-time widget can be
made .initially-hidden and then have that class removed once the
long-running startup process is done. See /pikchrshow for an
example. */
position: absolute !important;
opacity: 0 !important;
pointer-events: none !important;
display: none !important;
}
input {
max-width: 95%;
|
| ︙ | ︙ | |||
1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 |
body.branch .submenu > a.timeline-link.selected {
display: inline;
}
.monospace {
font-family: monospace;
}
/* Objects in the "desktoponly" class are invisible on mobile */
@media screen and (max-width: 600px) {
.desktoponly {
display: none;
}
}
/* Objects in the "wideonly" class are invisible only on wide-screen desktops */
@media screen and (max-width: 1200px) {
.wideonly {
display: none;
}
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 |
body.branch .submenu > a.timeline-link.selected {
display: inline;
}
.monospace {
font-family: monospace;
}
div.markdown > ol.footnotes {
font-size: 90%;
}
div.markdown > ol.footnotes > li {
margin-bottom: 0.5em;
}
div.markdown ol.footnotes > li.fn-joined > sup.fn-joined {
color: gray;
font-family: monospace;
}
div.markdown ol.footnotes > li.fn-joined > sup.fn-joined::after {
content: "(joined from multiple locations) ";
}
div.markdown ol.footnotes > li.fn-misreference {
margin-top: 0.75em;
margin-bottom: 0.75em;
}
div.markdown ol.footnotes > li.fn-toodeep > i,
div.markdown ol.footnotes > li.fn-misreference,
div.markdown ol.footnotes > li.fn-unreferenced {
color: gray;
}
div.markdown ol.footnotes > li.fn-misreference > span {
color: red;
}
div.markdown ol.footnotes > li.fn-misreference > span::after {
content: " (use of undefined label).";
}
div.markdown ol.footnotes > li.fn-unreferenced {
padding-left: 0.5em;
}
div.markdown ol.footnotes > li.fn-unreferenced > code {
color: red;
}
div.markdown ol.footnotes > li.fn-unreferenced > i::after {
content: " was defined but is not referenced";
}
div.markdown ol.footnotes > li.fn-toodeep > i::after {
content: " depth of nesting of inline footnotes exceeded the limit";
}
div.markdown ol.footnotes > li.fn-toodeep > pre,
div.markdown ol.footnotes > li.fn-unreferenced > pre {
color: gray;
font-size: 85%;
padding-left: 0.5em;
margin-top: 0.25em;
border-left: 2px solid red;
}
div.markdown ol.footnotes > li.fn-toodeep > pre {
margin-left: 0.5em;
}
div.markdown > ol.footnotes > li > .fn-backrefs {
margin-right: 0.5em;
font-weight: bold;
}
div.markdown > ol.footnotes > li > .fn-backrefs > a,
div.markdown sup.noteref > a {
padding-left: 2px;
padding-right: 2px;
}
div.markdown sup.noteref.misref,
div.markdown sup.noteref.misref > a {
color: red;
font-size: 90%;
}
div.markdown sup.noteref > a:target,
div.markdown span.notescope:target > sup.noteref > a,
div.markdown span.notescope:hover > sup.noteref > a,
div.markdown > ol.footnotes > li > .fn-backrefs > a:target {
background: gold;
}
div.markdown span.notescope:hover,
div.markdown span.notescope:target {
border-bottom: 2px solid gold;
}
/* Objects in the "desktoponly" class are invisible on mobile */
@media screen and (max-width: 600px) {
.desktoponly {
display: none;
}
}
/* Objects in the "wideonly" class are invisible only on wide-screen desktops */
@media screen and (max-width: 1200px) {
.wideonly {
display: none;
}
}
|
Changes to src/diff.c.
| ︙ | ︙ | |||
2209 2210 2211 2212 2213 2214 2215 | DLine *B; /* Right side of the diff */ unsigned int a = 0; /* Index of next line in A[] */ unsigned int b = 0; /* Index of next line in B[] */ const int *R; /* Array of COPY/DELETE/INSERT triples */ unsigned int r; /* Index into R[] */ unsigned int nr; /* Number of COPY/DELETE/INSERT triples to process */ unsigned int mxr; /* Maximum value for r */ | < | 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 | DLine *B; /* Right side of the diff */ unsigned int a = 0; /* Index of next line in A[] */ unsigned int b = 0; /* Index of next line in B[] */ const int *R; /* Array of COPY/DELETE/INSERT triples */ unsigned int r; /* Index into R[] */ unsigned int nr; /* Number of COPY/DELETE/INSERT triples to process */ unsigned int mxr; /* Maximum value for r */ unsigned int i, j; /* Loop counters */ unsigned int m, ma, mb;/* Number of lines to output */ signed int skip = 0; /* Number of lines to skip */ unsigned int nContext; /* Lines of context above and below each change */ nContext = diff_context_lines(pCfg); A = p->aFrom; |
| ︙ | ︙ | |||
2255 2256 2257 2258 2259 2260 2261 |
}
}
/* Figure out how many lines of A and B are to be displayed
** for this change block.
*/
if( R[r]>nContext ){
| < < < < < < < < < < < < < < < < < < | 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 |
}
}
/* Figure out how many lines of A and B are to be displayed
** for this change block.
*/
if( R[r]>nContext ){
skip = R[r] - nContext;
}else{
skip = 0;
}
/* Show the initial common area */
a += skip;
b += skip;
m = R[r] - skip;
if( r ) skip -= nContext;
if( skip>0 ){
if( skip<nContext ){
|
| ︙ | ︙ | |||
3592 3593 3594 3595 3596 3597 3598 |
unsigned clr1, clr2, clr;
int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */
/* Gather query parameters */
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
if( exclude_spiders() ) return;
| | | 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 |
unsigned clr1, clr2, clr;
int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */
/* Gather query parameters */
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
if( exclude_spiders() ) return;
fossil_nice_default();
zFilename = P("filename");
zRevision = PD("checkin",0);
zOrigin = P("origin");
zLimit = P("limit");
showLog = PB("log");
fileVers = PB("filevers");
ignoreWs = PB("w");
|
| ︙ | ︙ |
Changes to src/diffcmd.c.
| ︙ | ︙ | |||
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 |
const char *zFrom = P("from");
const char *zTo = P("to");
DiffConfig DCfg;
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
if( zFrom==0 || zTo==0 ) fossil_redirect_home();
cgi_set_content_type("text/plain");
diff_config_init(&DCfg, DIFF_VERBOSE);
diff_two_versions(zFrom, zTo, &DCfg, 0);
}
| > | 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 |
const char *zFrom = P("from");
const char *zTo = P("to");
DiffConfig DCfg;
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
if( zFrom==0 || zTo==0 ) fossil_redirect_home();
fossil_nice_default();
cgi_set_content_type("text/plain");
diff_config_init(&DCfg, DIFF_VERBOSE);
diff_two_versions(zFrom, zTo, &DCfg, 0);
}
|
Changes to src/dispatch.c.
| ︙ | ︙ | |||
36 37 38 39 40 41 42 | unsigned int eCmdFlags; /* Flags */ }; /*************************************************************************** ** These macros must match similar macros in mkindex.c ** Allowed values for CmdOrPage.eCmdFlags. */ | | | | | | | | | | | | | > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | unsigned int eCmdFlags; /* Flags */ }; /*************************************************************************** ** These macros must match similar macros in mkindex.c ** Allowed values for CmdOrPage.eCmdFlags. */ #define CMDFLAG_1ST_TIER 0x0001 /* Most important commands */ #define CMDFLAG_2ND_TIER 0x0002 /* Obscure and seldom used commands */ #define CMDFLAG_TEST 0x0004 /* Commands for testing only */ #define CMDFLAG_WEBPAGE 0x0008 /* Web pages */ #define CMDFLAG_COMMAND 0x0010 /* A command */ #define CMDFLAG_SETTING 0x0020 /* A setting */ #define CMDFLAG_VERSIONABLE 0x0040 /* A versionable setting */ #define CMDFLAG_BLOCKTEXT 0x0080 /* Multi-line text setting */ #define CMDFLAG_BOOLEAN 0x0100 /* A boolean setting */ #define CMDFLAG_RAWCONTENT 0x0200 /* Do not interpret POST content */ /* NOTE: 0x0400 = CMDFLAG_SENSITIVE in mkindex.c! */ #define CMDFLAG_HIDDEN 0x0800 /* Elide from most listings */ #define CMDFLAG_LDAVG_EXEMPT 0x1000 /* Exempt from load_control() */ /**************************************************************************/ /* Values for the 2nd parameter to dispatch_name_search() */ #define CMDFLAG_ANY 0x0038 /* Match anything */ #define CMDFLAG_PREFIX 0x0200 /* Prefix match is ok */ #endif /* INTERFACE */ |
| ︙ | ︙ | |||
123 124 125 126 127 128 129 |
* exactly one entry with this prefix and the requested type. */
for( mid=-1; lwr<MX_COMMAND
&& strncmp(zName, aCommand[lwr].zName, nName)==0; ++lwr ){
if( aCommand[lwr].eCmdFlags & eType ){
if( mid<0 ){
mid = lwr; /* Potential ambiguous prefix */
}else{
| > | > | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
* exactly one entry with this prefix and the requested type. */
for( mid=-1; lwr<MX_COMMAND
&& strncmp(zName, aCommand[lwr].zName, nName)==0; ++lwr ){
if( aCommand[lwr].eCmdFlags & eType ){
if( mid<0 ){
mid = lwr; /* Potential ambiguous prefix */
}else{
if( aCommand[lwr].xFunc != aCommand[mid].xFunc ){
return 2; /* Confirmed ambiguous prefix */
}
}
}
}
if( mid>=0 ){
*ppCmd = &aCommand[mid];
return 0; /* Prefix match */
}
|
| ︙ | ︙ | |||
205 206 207 208 209 210 211 |
}
}
return 0;
}
/*
** Fill Blob with a space-separated list of all command names that
| | | > > > > > | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
}
}
return 0;
}
/*
** Fill Blob with a space-separated list of all command names that
** match the prefix zPrefix and the eType CMDFLAGS_ bits.
*/
void dispatch_matching_names(
const char *zPrefix, /* name prefix */
unsigned eType, /* CMDFLAG_ bits */
Blob *pList /* space-separated list of command names */
){
int i;
int nPrefix = (int)strlen(zPrefix);
for(i=FOSSIL_FIRST_CMD; i<MX_COMMAND; i++){
if( (aCommand[i].eCmdFlags & eType)==0 ) continue;
if( strncmp(zPrefix, aCommand[i].zName, nPrefix)==0 ){
blob_appendf(pList, " %s", aCommand[i].zName);
}
}
}
/*
|
| ︙ | ︙ |
Changes to src/doc.c.
| ︙ | ︙ | |||
154 155 156 157 158 159 160 |
{ "ips", 3, "application/x-ipscript" },
{ "ipx", 3, "application/x-ipix" },
{ "jad", 3, "text/vnd.sun.j2me.app-descriptor" },
{ "jar", 3, "application/java-archive" },
{ "jpe", 3, "image/jpeg" },
{ "jpeg", 4, "image/jpeg" },
{ "jpg", 3, "image/jpeg" },
| | > > > > > > | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
{ "ips", 3, "application/x-ipscript" },
{ "ipx", 3, "application/x-ipix" },
{ "jad", 3, "text/vnd.sun.j2me.app-descriptor" },
{ "jar", 3, "application/java-archive" },
{ "jpe", 3, "image/jpeg" },
{ "jpeg", 4, "image/jpeg" },
{ "jpg", 3, "image/jpeg" },
{ "js", 2, "text/javascript" },
/* application/javascript is commonly used for JS, but the
** spec says text/javascript is correct:
** https://html.spec.whatwg.org/multipage/scripting.html
** #scriptingLanguages:javascript-mime-type */
{ "json", 4, "application/json" },
{ "kar", 3, "audio/midi" },
{ "latex", 5, "application/x-latex" },
{ "lha", 3, "application/octet-stream" },
{ "lsp", 3, "application/x-lisp" },
{ "lzh", 3, "application/octet-stream" },
{ "m", 1, "text/plain" },
{ "m3u", 3, "audio/x-mpegurl" },
{ "man", 3, "text/plain" },
{ "markdown", 8, "text/x-markdown" },
{ "md", 2, "text/x-markdown" },
{ "me", 2, "application/x-troff-me" },
{ "mesh", 4, "model/mesh" },
{ "mid", 3, "audio/midi" },
{ "midi", 4, "audio/midi" },
{ "mif", 3, "application/x-mif" },
{ "mime", 4, "www/mime" },
{ "mjs", 3, "text/javascript" /*EM6 modules*/ },
{ "mkd", 3, "text/x-markdown" },
{ "mov", 3, "video/quicktime" },
{ "movie", 5, "video/x-sgi-movie" },
{ "mp2", 3, "audio/mpeg" },
{ "mp3", 3, "audio/mpeg" },
{ "mp4", 3, "video/mp4" },
{ "mpe", 3, "video/mpeg" },
|
| ︙ | ︙ | |||
275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
{ "ustar", 5, "application/x-ustar" },
{ "vb", 2, "text/plain" },
{ "vcd", 3, "application/x-cdlink" },
{ "vda", 3, "application/vda" },
{ "viv", 3, "video/vnd.vivo" },
{ "vivo", 4, "video/vnd.vivo" },
{ "vrml", 4, "model/vrml" },
{ "wav", 3, "audio/x-wav" },
{ "wax", 3, "audio/x-ms-wax" },
{ "webp", 4, "image/webp" },
{ "wiki", 4, "text/x-fossil-wiki" },
{ "wma", 3, "audio/x-ms-wma" },
{ "wmv", 3, "video/x-ms-wmv" },
{ "wmx", 3, "video/x-ms-wmx" },
| > | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
{ "ustar", 5, "application/x-ustar" },
{ "vb", 2, "text/plain" },
{ "vcd", 3, "application/x-cdlink" },
{ "vda", 3, "application/vda" },
{ "viv", 3, "video/vnd.vivo" },
{ "vivo", 4, "video/vnd.vivo" },
{ "vrml", 4, "model/vrml" },
{ "wasm", 4, "application/wasm" },
{ "wav", 3, "audio/x-wav" },
{ "wax", 3, "audio/x-ms-wax" },
{ "webp", 4, "image/webp" },
{ "wiki", 4, "text/x-fossil-wiki" },
{ "wma", 3, "audio/x-ms-wma" },
{ "wmv", 3, "video/x-ms-wmv" },
{ "wmx", 3, "video/x-ms-wmx" },
|
| ︙ | ︙ |
Changes to src/encode.c.
| ︙ | ︙ | |||
203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
** characters are encoded as "%HH" where HH is a two-digit hexidecimal
** representation of the character. The "/" character is not encoded
** by this routine.
*/
char *urlize(const char *z, int n){
return EncodeHttp(z, n, 0);
}
/*
** Convert a single HEX digit to an integer
*/
static int AsciiToHex(int c){
if( c>='a' && c<='f' ){
c += 10 - 'a';
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
** characters are encoded as "%HH" where HH is a two-digit hexidecimal
** representation of the character. The "/" character is not encoded
** by this routine.
*/
char *urlize(const char *z, int n){
return EncodeHttp(z, n, 0);
}
/*
** If input string does not contain quotes (niether ' nor ")
** then return the argument itself. Otherwise return a newly allocated
** copy of input with all quotes %-escaped.
*/
const char* escape_quotes(const char *zIn){
char *zRet, *zOut;
size_t i, n = 0;
for(i=0; zIn[i]; i++){
if( zIn[i]== '"' || zIn[i]== '\'' ) n++;
}
if( !n ) return zIn;
zRet = zOut = fossil_malloc( i + 2*n + 1 );
for(i=0; zIn[i]; i++){
if( zIn[i]=='"' ){
*(zOut++) = '%';
*(zOut++) = '2';
*(zOut++) = '2';
}else if( zIn[i]=='\'' ){
*(zOut++) = '%';
*(zOut++) = '2';
*(zOut++) = '7';
}else{
*(zOut++) = zIn[i];
}
}
*zOut = 0;
return zRet;
}
/*
** Convert a single HEX digit to an integer
*/
static int AsciiToHex(int c){
if( c>='a' && c<='f' ){
c += 10 - 'a';
|
| ︙ | ︙ |
Changes to src/fossil.copybutton.js.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 |
Options:
.copyFromElement: DOM element
.copyFromId: DOM element ID
| < < < > > > > > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
Options:
.copyFromElement: DOM element
.copyFromId: DOM element ID
.extractText: optional callback which is triggered when the copy
button is clicked. It must return the text to copy to the
clipboard. The default is to extract it from the copy-from
element, using its [value] member, if it has one, else its
[innerText]. A client-provided callback may use any data source
it likes, so long as it's synchronous. If this function returns a
falsy value then the clipboard is not modified. This function is
called with the fully expanded/resolved options object as its
"this" (that's a different instance than the one passed to this
function!).
At least one of copyFromElement, copyFromId, or extractText must
be provided, but if copyFromId is not set and e.dataset.copyFromId
is then that value is used in its place. extractText() trumps the
other two options.
.cssClass: optional CSS class, or list of classes, to apply to e.
.style: optional object of properties to copy directly into
e.style.
.oncopy: an optional callback function which is added as an event
|
| ︙ | ︙ |
Changes to src/fossil.page.chat.js.
| ︙ | ︙ | |||
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 |
}else{
e = this.getMessageElemById(id);
}
if(!e || !id) return false;
else if(e.$isToggling) return;
e.$isToggling = true;
const content = e.querySelector('.content-target');
if(!content.$elems){
content.$elems = [
content.firstElementChild, // parsed elem
undefined // plaintext elem
];
}else if(content.$elems[1]){
// We have both content types. Simply toggle them.
const child = (
content.firstElementChild===content.$elems[0]
? content.$elems[1]
: content.$elems[0]
);
delete e.$isToggling;
| > > > > > > > > > > > > > > > > > > > > > > | > | 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 |
}else{
e = this.getMessageElemById(id);
}
if(!e || !id) return false;
else if(e.$isToggling) return;
e.$isToggling = true;
const content = e.querySelector('.content-target');
if(!content){
console.warn("Should not be possible: trying to toggle text",
"mode of a message with no .content-target.", e);
return;
}
if(!content.$elems){
content.$elems = [
content.firstElementChild, // parsed elem
undefined // plaintext elem
];
}else if(content.$elems[1]){
// We have both content types. Simply toggle them.
const child = (
content.firstElementChild===content.$elems[0]
? content.$elems[1]
: content.$elems[0]
);
D.clearElement(content);
if(child===content.$elems[1]){
/* When showing the unformatted version, inject a
copy-to-clipboard button. This is a workaround for
mouse-copying from that field collecting twice as many
newlines as it should (for unknown reasons). */
const cpId = 'copy-to-clipboard-'+id;
/* ^^^ copy button element ID, needed for LABEL element
pairing. Recall that we destroy all child elements of
`content` each time we hit this block, so we can reuse
that element ID on subsequent toggles. */
const btnCp = D.attr(D.addClass(D.span(),'copy-button'), 'id', cpId);
F.copyButton(btnCp, {extractText: ()=>child._xmsgRaw});
const lblCp = D.label(cpId, "Copy unformatted text");
lblCp.addEventListener('click',()=>btnCp.click(), false);
D.append(content, D.append(D.addClass(D.span(), 'nobr'), btnCp, lblCp));
}
delete e.$isToggling;
D.append(content, child);
return;
}
// We need to fetch the plain-text version...
const self = this;
F.fetch('chat-fetch-one',{
urlParams:{ name: id, raw: true},
responseType: 'json',
onload: function(msg){
content.$elems[1] = D.append(D.pre(),msg.xmsg);
content.$elems[1]._xmsgRaw = msg.xmsg/*used for copy-to-clipboard feature*/;
self.toggleTextMode(e);
},
aftersend:function(){
delete e.$isToggling;
Chat.ajaxEnd();
}
});
|
| ︙ | ︙ | |||
1133 1134 1135 1136 1137 1138 1139 |
e = n;
}
eMsg.scrollIntoView();
}
));
const toolbar2 = D.addClass(D.div(), 'toolbar');
D.append(this.e, toolbar2);
| > > > | | | | | > | 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 |
e = n;
}
eMsg.scrollIntoView();
}
));
const toolbar2 = D.addClass(D.div(), 'toolbar');
D.append(this.e, toolbar2);
if(eMsg.querySelector('.content-target')){
/* ^^^ messages with only an embedded image have no
.content-target area. */
D.append(toolbar2, D.button(
"Toggle text mode", function(){
self.hide();
Chat.toggleTextMode(eMsg);
}));
}
if(eMsg.dataset.xfrom){
/* Add a link to the /timeline filtered on this user. */
const timelineLink = D.attr(
D.a(F.repoUrl('timeline',{
u: eMsg.dataset.xfrom,
y: 'a'
}), "User's Timeline"),
|
| ︙ | ︙ | |||
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 |
and/or the file attachment field to the server. If both are
empty, this is a no-op.
*/
Chat.submitMessage = function f(){
if(!f.spaces){
f.spaces = /\s+$/;
f.markdownContinuation = /\\\s+$/;
}
this.setCurrentView(this.e.viewMessages);
const fd = new FormData();
const fallback = {msg: this.inputValue()};
| > | | > | | > > > > | | 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 |
and/or the file attachment field to the server. If both are
empty, this is a no-op.
*/
Chat.submitMessage = function f(){
if(!f.spaces){
f.spaces = /\s+$/;
f.markdownContinuation = /\\\s+$/;
f.spaces2 = /\s{3,}$/;
}
this.setCurrentView(this.e.viewMessages);
const fd = new FormData();
const fallback = {msg: this.inputValue()};
var msg = fallback.msg;
if(msg && (msg.indexOf('\n')>0 || f.spaces.test(msg))){
/* Cosmetic: trim most whitespace from the ends of lines to try to
keep copy/paste from terminals, especially wide ones, from
forcing a horizontal scrollbar on all clients. This breaks
markdown's use of blackslash-space-space for paragraph
continuation, but *not* doing this affects all clients every
time someone pastes in console copy/paste from an affected
platform. We seem to have narrowed to the console pasting
problem to users of tmux together with certain apps (vim, at
a minimum). Most consoles don't behave that way.
We retain two trailing spaces so that markdown conventions
which use end-of-line spacing aren't broken by this
stripping.
*/
const xmsg = msg.split('\n');
xmsg.forEach(function(line,ndx){
if(!f.markdownContinuation.test(line)){
xmsg[ndx] = line.replace(f.spaces2, ' ');
}
});
msg = xmsg.join('\n');
}
if(msg) fd.set('msg',msg);
const file = BlobXferState.blob || this.e.inputFile.files[0];
if(file) fd.set("file", file);
|
| ︙ | ︙ |
Changes to src/fossil.page.pikchrshow.js.
1 2 3 |
(function(F/*the fossil object*/){
"use strict";
/**
| | > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
(function(F/*the fossil object*/){
"use strict";
/**
Client-side implementation of the /pikchrshowcs app. Requires that
the fossil JS bootstrapping is complete and that these fossil JS
APIs have been installed: fossil.fetch, fossil.dom,
fossil.copybutton, fossil.popupwidget, fossil.storage
Maintenance funkiness note: this file is for the legacy
/pikchrshowcs app, which was formerly named /pikchrshow. This
file and its replacement were not renamed because the replacement
impl would end up getting this file's name and cause confusion in
the file history. Whether that confusion would be less than this
file's name matching the _other_ /pikchrshow impl will cause more
or less confusion than that remains to be seen.
*/
const E = (s)=>document.querySelector(s),
D = F.dom,
P = F.page;
P.previewMode = 0 /*0==rendered SVG, 1==pikchr text markdown,
2==pikchr text fossil, 3==raw SVG. */
|
| ︙ | ︙ |
Added src/fossil.page.pikchrshowasm.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 |
/*
2022-05-20
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
This is the main entry point for the WASM rendition of fossil's
/pikchrshow app. It sets up the various UI bits, loads a Worker for
the pikchr process, and manages the communication between the UI and
worker.
API dependencies: fossil.dom, fossil.copybutton, fossil.storage
*/
(function(F/*fossil object*/){
'use strict';
/* Recall that the 'self' symbol, except where locally
overwritten, refers to the global window or worker object. */
const D = F.dom;
/** Name of the stored copy of this app's config. */
const configStorageKey = 'pikchrshow-config';
/* querySelectorAll() proxy */
const EAll = function(/*[element=document,] cssSelector*/){
return (arguments.length>1 ? arguments[0] : document)
.querySelectorAll(arguments[arguments.length-1]);
};
/* querySelector() proxy */
const E = function(/*[element=document,] cssSelector*/){
return (arguments.length>1 ? arguments[0] : document)
.querySelector(arguments[arguments.length-1]);
};
/** The main application object. */
const PS = {
/* Config options. */
config: {
/* If true, display input/output areas side-by-side, else stack
them vertically. */
sideBySide: true,
/* If true, swap positions of the input/output areas. */
swapInOut: false,
/* If true, the SVG is allowed to resize to fit the parent
content area, else the parent is resized to fit the rendered
SVG (as sized by pikchr). */
renderAutofit: false,
/* If true, automatically render while the user is typing. */
renderWhileTyping: false
},
/* Various DOM elements. */
e: {
previewCopyButton: E('#preview-copy-button'),
previewModeLabel: E('label[for=preview-copy-button]'),
zoneInputButtons: E('.zone-wrapper.input > legend > .button-bar'),
zoneOutputButtons: E('.zone-wrapper.output > legend > .button-bar'),
outText: E('#pikchr-output-text'),
pikOutWrapper: E('#pikchr-output-wrapper'),
pikOut: E('#pikchr-output'),
btnRender: E('#btn-render')
},
renderModes: ['svg'/*SVG must be at index 0*/,'markdown', 'wiki', 'text'],
renderModeLabels: {
svg: 'SVG', markdown: 'Markdown', wiki: 'Fossil Wiki', text: 'Text'
},
_msgMap: {},
/** Adds a worker message handler for messages of the given
type. */
addMsgHandler: function f(type,callback){
if(Array.isArray(type)){
type.forEach((t)=>this.addMsgHandler(t, callback));
return this;
}
(this._msgMap.hasOwnProperty(type)
? this._msgMap[type]
: (this._msgMap[type] = [])).push(callback);
return this;
},
/** Given a worker message, runs all handlers for msg.type. */
runMsgHandlers: function(msg){
const list = (this._msgMap.hasOwnProperty(msg.type)
? this._msgMap[msg.type] : false);
if(!list){
console.warn("No handlers found for message type:",msg);
return false;
}
list.forEach((f)=>f(msg));
return true;
},
/** Removes all message handlers for the given message type. */
clearMsgHandlers: function(type){
delete this._msgMap[type];
return this;
},
/* Posts a message in the form {type, data} to the db worker. Returns this. */
wMsg: function(type,data){
this.worker.postMessage({type, data});
return this;
},
/** Stores this object's config in the browser's storage. */
storeConfig: function(){
F.storage.setJSON(configStorageKey,this.config);
}
};
PS.renderModes.selectedIndex = 0;
PS._config = F.storage.getJSON(configStorageKey);
if(PS._config){
/* Copy all properties to PS.config which are currently in
PS._config. We don't bother copying any other properties: those
would be stale/removed config entries. */
Object.keys(PS.config).forEach(function(k){
if(PS._config.hasOwnProperty(k)){
PS.config[k] = PS._config[k];
}
});
delete PS._config;
}
PS.worker = new Worker('builtin/extsrc/pikchr-worker.js');
PS.worker.onmessage = (ev)=>PS.runMsgHandlers(ev.data);
PS.addMsgHandler('stdout', console.log.bind(console));
PS.addMsgHandler('stderr', console.error.bind(console));
/** Handles status updates from the Module object. */
PS.addMsgHandler('module', function f(ev){
ev = ev.data;
if('status'!==ev.type){
console.warn("Unexpected module-type message:",ev);
return;
}
if(!f.ui){
f.ui = {
status: E('#module-status'),
progress: E('#module-progress'),
spinner: E('#module-spinner')
};
}
const msg = ev.data;
if(f.ui.progres){
progress.value = msg.step;
progress.max = msg.step + 1/*we don't know how many steps to expect*/;
}
if(1==msg.step){
f.ui.progress.classList.remove('hidden');
f.ui.spinner.classList.remove('hidden');
}
if(msg.text){
f.ui.status.classList.remove('hidden');
f.ui.status.innerText = msg.text;
}else{
if(f.ui.progress){
f.ui.progress.remove();
f.ui.spinner.remove();
delete f.ui.progress;
delete f.ui.spinner;
}
f.ui.status.classList.add('hidden');
/* The module can post messages about fatal problems,
e.g. an exit() being triggered or assertion failure,
after the last "load" message has arrived, so
leave f.ui.status and message listener intact. */
}
});
PS.e.previewModeLabel.innerText =
PS.renderModeLabels[PS.renderModes[PS.renderModes.selectedIndex]];
/**
The 'pikchrshow-ready' event is fired (with no payload) when the
wasm module has finished loading. */
PS.addMsgHandler('pikchrshow-ready', function(){
PS.clearMsgHandlers('pikchrshow-ready');
F.page.onPikchrshowLoaded();
});
/**
Performs all app initialization which must wait until after the
worker module is loaded. This function removes itself when it's
called.
*/
F.page.onPikchrshowLoaded = function(){
delete this.onPikchrshowLoaded;
// Unhide all elements which start out hidden
EAll('.initially-hidden').forEach((e)=>e.classList.remove('initially-hidden'));
const taInput = E('#input');
const btnClearIn = E('#btn-clear');
btnClearIn.addEventListener('click',function(){
taInput.value = '';
},false);
const getCurrentText = function(){
let text;
if(taInput.selectionStart<taInput.selectionEnd){
text = taInput.value.substring(taInput.selectionStart,taInput.selectionEnd).trim();
}else{
text = taInput.value.trim();
}
return text;;
};
const renderCurrentText = function(){
const text = getCurrentText();
if(text) PS.render(text);
};
const setCurrentText = function(txt){
taInput.value = txt;
renderCurrentText();
};
PS.e.btnRender.addEventListener('click',function(ev){
ev.preventDefault();
renderCurrentText();
},false);
/** To be called immediately before work is sent to the
worker. Updates some UI elements. The 'working'/'end'
event will apply the inverse, undoing the bits this
function does. This impl is not in the 'working'/'start'
event handler because that event is given to us
asynchronously _after_ we need to have performed this
work.
*/
const preStartWork = function f(){
if(!f._){
const title = E('title');
f._ = {
pageTitle: title,
pageTitleOrig: title.innerText
};
}
//f._.pageTitle.innerText = "[working...] "+f._.pageTitleOrig;
PS.e.btnRender.setAttribute('disabled','disabled');
};
/**
Submits the current input text to pikchr and renders the
result. */
PS.render = function f(txt){
preStartWork();
this.wMsg('pikchr',{
pikchr: txt,
darkMode: !!window.fossil.config.skin.isDark
});
};
/**
Event handler for 'pikchr' messages from the Worker thread.
*/
PS.addMsgHandler('pikchr', function(ev){
const m = ev.data, pikOut = this.e.pikOut;
pikOut.classList[m.isError ? 'add' : 'remove']('error');
pikOut.dataset.pikchr = m.pikchr;
const mode = this.renderModes[this.renderModes.selectedIndex];
switch(mode){
case 'text': case 'markdown': case 'wiki': {
let body;
switch(mode){
case 'markdown':
body = ['```pikchr', m.pikchr, '```'].join('\n');
break;
case 'wiki':
body = ['<verbatim type="pikchr">', m.pikchr, '</verbatim>'].join('');
break;
default:
body = m.result;
}
this.e.outText.value = body;
this.e.outText.classList.remove('hidden');
pikOut.classList.add('hidden');
this.e.pikOutWrapper.classList.add('text');
break;
}
case 'svg':
this.e.outText.classList.add('hidden');
pikOut.classList.remove('hidden');
this.e.pikOutWrapper.classList.remove('text');
pikOut.innerHTML = m.result;
this.e.outText.value = m.result/*for clipboard copy*/;
break;
default: throw new Error("Unhandled render mode: "+mode);
}
let vw = null, vh = null;
if('svg'===mode){
if(m.isError){
vw = vh = '100%';
}else if(this.config.renderAutofit){
/* FIXME: current behavior doesn't work as desired when width>height
(e.g. non-side-by-side mode).*/
vw = vh = '98%';
}else{
vw = m.width+1+'px'; vh = m.height+1+'px';
/* +1 is b/c the SVG uses floating point sizes but pikchr()
returns truncated integers. */
}
pikOut.style.width = vw;
pikOut.style.height = vh;
}
}.bind(PS))/*'pikchr' msg handler*/;
E('#btn-render-mode').addEventListener('click',function(){
const modes = this.renderModes;
modes.selectedIndex = (modes.selectedIndex + 1) % modes.length;
this.e.previewModeLabel.innerText = this.renderModeLabels[modes[modes.selectedIndex]];
if(this.e.pikOut.dataset.pikchr){
this.render(this.e.pikOut.dataset.pikchr);
}
}.bind(PS));
F.copyButton(PS.e.previewCopyButton, {copyFromElement: PS.e.outText});
PS.e.previewModeLabel.addEventListener('click', ()=>PS.e.previewCopyButton.click(), false);
PS.addMsgHandler('working',function f(ev){
switch(ev.data){
case 'start': /* See notes in preStartWork(). */; return;
case 'end':
//preStartWork._.pageTitle.innerText = preStartWork._.pageTitleOrig;
this.e.btnRender.removeAttribute('disabled');
this.e.pikOutWrapper.classList[this.config.renderAutofit ? 'add' : 'remove']('autofit');
return;
}
console.warn("Unhandled 'working' event:",ev.data);
}.bind(PS));
/* For each checkbox with data-csstgt, set up a handler which
toggles the given CSS class on the element matching
E(data-csstgt). */
EAll('input[type=checkbox][data-csstgt]')
.forEach(function(e){
const tgt = E(e.dataset.csstgt);
const cssClass = e.dataset.cssclass || 'error';
e.checked = tgt.classList.contains(cssClass);
e.addEventListener('change', function(){
tgt.classList[
this.checked ? 'add' : 'remove'
](cssClass)
}, false);
});
/* For each checkbox with data-config=X, set up a binding to
PS.config[X]. These must be set up AFTER data-csstgt
checkboxes so that those two states can be synced properly. */
EAll('input[type=checkbox][data-config]')
.forEach(function(e){
const confVal = !!PS.config[e.dataset.config];
if(e.checked !== confVal){
/* Ensure that data-csstgt mappings (if any) get
synced properly. */
e.checked = confVal;
e.dispatchEvent(new Event('change'));
}
e.addEventListener('change', function(){
PS.config[this.dataset.config] = this.checked;
PS.storeConfig();
}, false);
});
E('#opt-cb-autofit').addEventListener('change',function(){
/* PS.config.renderAutofit was set by the data-config
event handler. */
if(0==PS.renderModes.selectedIndex && PS.e.pikOut.dataset.pikchr){
PS.render(PS.e.pikOut.dataset.pikchr);
}
});
/* For each button with data-cmd=X, map a click handler which
calls PS.render(X). */
const cmdClick = function(){PS.render(this.dataset.cmd);};
EAll('button[data-cmd]').forEach(
e => e.addEventListener('click', cmdClick, false)
);
////////////////////////////////////////////////////////////
// Set up selection list of predefined scripts...
if(true){
const selectScript = PS.e.selectScript = D.select();
D.append(PS.e.zoneInputButtons, selectScript);
PS.predefinedPiks.forEach(function(script,ndx){
const opt = D.option(script.code ? script.code.trim() :'', script.name);
D.append(selectScript, opt);
if(!ndx) selectScript.selectedIndex = 0 /*timing/ordering workaround*/;
if(ndx && !script.code){
/* Treat entries w/ no code as separators EXCEPT for the
first one, which we want to keep selectable solely for
cosmetic reasons. */
D.disable(opt);
}
});
delete PS.predefinedPiks;
selectScript.addEventListener('change', function(ev){
const val = ev.target.value;
if(!val) return;
setCurrentText(val);
}, false);
}/*Examples*/
/**
TODO: Handle load/import of an external pikchr file.
*/
if(0) E('#load-pikchr').addEventListener('change',function(){
const f = this.files[0];
const r = new FileReader();
const status = {loaded: 0, total: 0};
this.setAttribute('disabled','disabled');
const that = this;
r.addEventListener('load', function(){
that.removeAttribute('disabled');
stdout("Loaded",f.name+". Opening pikchr...");
PS.wMsg('open',{
filename: f.name,
buffer: this.result
});
});
r.addEventListener('error',function(){
that.removeAttribute('disabled');
stderr("Loading",f.name,"failed for unknown reasons.");
});
r.addEventListener('abort',function(){
that.removeAttribute('disabled');
stdout("Cancelled loading of",f.name+".");
});
r.readAsArrayBuffer(f);
});
EAll('fieldset.collapsible').forEach(function(fs){
const btnToggle = E(fs,'legend > .fieldset-toggle'),
content = EAll(fs,':scope > div');
btnToggle.addEventListener('click', function(){
fs.classList.toggle('collapsed');
content.forEach((d)=>d.classList.toggle('hidden'));
}, false);
});
PS.e.btnRender.click();
/** Debounce handler for auto-rendering while typing. */
const debounceAutoRender = F.debounce(function f(){
if(!PS._isDirty) return;
const text = getCurrentText();
if(f._ === text){
PS._isDirty = false;
return;
}
f._ = text;
PS._isDirty = false;
PS.render(text || '');
}, 800, false);
taInput.addEventListener('keydown',function f(ev){
if((ev.ctrlKey || ev.shiftKey) && 13 === ev.keyCode){
// Ctrl-enter and shift-enter both run the current input
PS._isDirty = false/*prevent a pending debounce from re-rendering*/;
ev.preventDefault();
ev.stopPropagation();
renderCurrentText();
return;
}
if(!PS.config.renderWhileTyping) return;
/* Auto-render while typing... */
switch(ev.keyCode){
case (ev.keyCode<32): /*any ctrl char*/
/* ^^^ w/o that, simply tapping ctrl is enough to
force a re-render. Similarly, TAB-ing focus away
should not re-render. */
case 33: case 34: /* page up/down */
case 35: case 36: /* home/end */
case 37: case 38: case 39: case 40: /* arrows */
return;
}
PS._isDirty = true;
debounceAutoRender();
}, false);
const ForceResizeKludge = (function(){
/* Workaround for Safari mayhem regarding use of vh CSS
units.... We cannot use vh units to set the main view
size because Safari chokes on that, so we calculate
that height here. Larger than ~95% is too big for
Firefox on Android, causing the input area to move
off-screen. */
const appViews = EAll('.app-view');
const elemsToCount = [
/* Elements which we need to always count in the
visible body size. */
E('body > div.header'),
E('body > div.mainmenu'),
E('body > div.footer')
];
const resized = function f(){
if(f.$disabled) return;
const wh = window.innerHeight;
var ht;
var extra = 0;
elemsToCount.forEach((e)=>e ? extra += F.dom.effectiveHeight(e) : false);
ht = wh - extra;
appViews.forEach(function(e){
e.style.height =
e.style.maxHeight = [
"calc(", (ht>=100 ? ht : 100), "px",
" - 2em"/*fudge value*/,")"
/* ^^^^ hypothetically not needed, but both
Chrome/FF on Linux will force scrollbars on the
body if this value is too small. */
].join('');
});
};
resized.$disabled = true/*gets deleted when setup is finished*/;
window.addEventListener('resize', F.debounce(resized, 250), false);
return resized;
})()/*ForceResizeKludge*/;
delete ForceResizeKludge.$disabled;
ForceResizeKludge();
}/*onPikchrshowLoaded()*/;
/**
Predefined scripts. Each entry is an object:
{
name: required string,
code: optional code string. An entry with a falsy code is treated
like a separator in the resulting SELECT element (a
disabled OPTION).
}
*/
PS.predefinedPiks = [
{name: "-- Example Scripts --", code: false},
/*
The following were imported from the pikchr test scripts:
https://fossil-scm.org/pikchr/dir/examples
*/
{name:"Cardinal headings",code:` linerad = 5px
C: circle "Center" rad 150%
circle "N" at 1.0 n of C; arrow from C to last chop ->
circle "NE" at 1.0 ne of C; arrow from C to last chop <-
circle "E" at 1.0 e of C; arrow from C to last chop <->
circle "SE" at 1.0 se of C; arrow from C to last chop ->
circle "S" at 1.0 s of C; arrow from C to last chop <-
circle "SW" at 1.0 sw of C; arrow from C to last chop <->
circle "W" at 1.0 w of C; arrow from C to last chop ->
circle "NW" at 1.0 nw of C; arrow from C to last chop <-
arrow from 2nd circle to 3rd circle chop
arrow from 4th circle to 3rd circle chop
arrow from SW to S chop <->
circle "ESE" at 2.0 heading 112.5 from Center \
thickness 150% fill lightblue radius 75%
arrow from Center to ESE thickness 150% <-> chop
arrow from ESE up 1.35 then to NE chop
line dashed <- from E.e to (ESE.x,E.y)
line dotted <-> thickness 50% from N to NW chop
`},{name:"Core object types",code:`AllObjects: [
# First row of objects
box "box"
box rad 10px "box (with" "rounded" "corners)" at 1in right of previous
circle "circle" at 1in right of previous
ellipse "ellipse" at 1in right of previous
# second row of objects
OVAL1: oval "oval" at 1in below first box
oval "(tall &" "thin)" "oval" width OVAL1.height height OVAL1.width \
at 1in right of previous
cylinder "cylinder" at 1in right of previous
file "file" at 1in right of previous
# third row shows line-type objects
dot "dot" above at 1in below first oval
line right from 1.8cm right of previous "lines" above
arrow right from 1.8cm right of previous "arrows" above
spline from 1.8cm right of previous \
go right .15 then .3 heading 30 then .5 heading 160 then .4 heading 20 \
then right .15
"splines" at 3rd vertex of previous
# The third vertex of the spline is not actually on the drawn
# curve. The third vertex is a control point. To see its actual
# position, uncomment the following line:
#dot color red at 3rd vertex of previous spline
# Draw various lines below the first line
line dashed right from 0.3cm below start of previous line
line dotted right from 0.3cm below start of previous
line thin right from 0.3cm below start of previous
line thick right from 0.3cm below start of previous
# Draw arrows with different arrowhead configurations below
# the first arrow
arrow <- right from 0.4cm below start of previous arrow
arrow <-> right from 0.4cm below start of previous
# Draw splines with different arrowhead configurations below
# the first spline
spline same from .4cm below start of first spline ->
spline same from .4cm below start of previous <-
spline same from .4cm below start of previous <->
] # end of AllObjects
# Label the whole diagram
text "Examples Of Pikchr Objects" big bold at .8cm above north of AllObjects
`},{name:"Swimlanes",code:` $laneh = 0.75
# Draw the lanes
down
box width 3.5in height $laneh fill 0xacc9e3
box same fill 0xc5d8ef
box same as first box
box same as 2nd box
line from 1st box.sw+(0.2,0) up until even with 1st box.n \
"Alan" above aligned
line from 2nd box.sw+(0.2,0) up until even with 2nd box.n \
"Betty" above aligned
line from 3rd box.sw+(0.2,0) up until even with 3rd box.n \
"Charlie" above aligned
line from 4th box.sw+(0.2,0) up until even with 4th box.n \
"Darlene" above aligned
# fill in content for the Alice lane
right
A1: circle rad 0.1in at end of first line + (0.2,-0.2) \
fill white thickness 1.5px "1"
arrow right 50%
circle same "2"
arrow right until even with first box.e - (0.65,0.0)
ellipse "future" fit fill white height 0.2 width 0.5 thickness 1.5px
A3: circle same at A1+(0.8,-0.3) "3" fill 0xc0c0c0
arrow from A1 to last circle chop "fork!" below aligned
# content for the Betty lane
B1: circle same as A1 at A1-(0,$laneh) "1"
arrow right 50%
circle same "2"
arrow right until even with first ellipse.w
ellipse same "future"
B3: circle same at A3-(0,$laneh) "3"
arrow right 50%
circle same as A3 "4"
arrow from B1 to 2nd last circle chop
# content for the Charlie lane
C1: circle same as A1 at B1-(0,$laneh) "1"
arrow 50%
circle same "2"
arrow right 0.8in "goes" "offline"
C5: circle same as A3 "5"
arrow right until even with first ellipse.w \
"back online" above "pushes 5" below "pulls 3 & 4" below
ellipse same "future"
# content for the Darlene lane
D1: circle same as A1 at C1-(0,$laneh) "1"
arrow 50%
circle same "2"
arrow right until even with C5.w
circle same "5"
arrow 50%
circle same as A3 "6"
arrow right until even with first ellipse.w
ellipse same "future"
D3: circle same as B3 at B3-(0,2*$laneh) "3"
arrow 50%
circle same "4"
arrow from D1 to D3 chop
`},{
name: "The Stuff of Dreams",
code:`
O: text "DREAMS" color grey
circle rad 0.9 at 0.6 above O thick color red
text "INEXPENSIVE" big bold at 0.9 above O color red
circle rad 0.9 at 0.6 heading 120 from O thick color green
text "FAST" big bold at 0.9 heading 120 from O color green
circle rad 0.9 at 0.6 heading -120 from O thick color blue
text "HIGH" big bold "QUALITY" big bold at 0.9 heading -120 from O color blue
text "EXPENSIVE" at 0.55 below O color cyan
text "SLOW" at 0.55 heading -60 from O color magenta
text "POOR" "QUALITY" at 0.55 heading 60 from O color gold
`}
];
})(window.fossil);
|
Changes to src/fuzz.c.
| ︙ | ︙ | |||
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
#if LOCAL_INTERFACE
/*
** Type of fuzzing:
*/
#define FUZZ_WIKI 0 /* The Fossil-Wiki formatter */
#define FUZZ_MARKDOWN 1 /* The Markdown formatter */
#define FUZZ_ARTIFACT 2 /* Fuzz the artifact parser */
#endif
/* The type of fuzzing to do */
static int eFuzzType = FUZZ_WIKI;
/* The fuzzer invokes this routine once for each fuzzer input
*/
int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){
Blob in, out;
blob_init(&in, 0, 0);
blob_append(&in, (char*)aData, (int)nByte);
blob_zero(&out);
switch( eFuzzType ){
case FUZZ_WIKI: {
Blob title = BLOB_INITIALIZER;
wiki_convert(&in, &out, 0);
blob_reset(&out);
markdown_to_html(&in, &title, &out);
blob_reset(&title);
break;
}
}
blob_reset(&in);
blob_reset(&out);
return 0;
}
/*
** Check fuzzer command-line options.
*/
static void fuzzer_options(void){
const char *zType;
db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
db_multi_exec("PRAGMA query_only=1;");
zType = find_option("fuzztype",0,1);
if( zType==0 || fossil_strcmp(zType,"wiki")==0 ){
eFuzzType = FUZZ_WIKI;
}else if( fossil_strcmp(zType,"markdown")==0 ){
eFuzzType = FUZZ_MARKDOWN;
}else{
fossil_fatal("unknown fuzz type: \"%s\"", zType);
}
}
/* Libfuzzer invokes this routine once prior to start-up to
** process command-line options.
*/
int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){
expand_args_option(*pArgc, *pArgv);
fuzzer_options();
*pArgc = g.argc;
*pArgv = g.argv;
return 0;
}
/*
** COMMAND: test-fuzz
**
| > > > > > > > > > > > > > > > > > > | > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
#if LOCAL_INTERFACE
/*
** Type of fuzzing:
*/
#define FUZZ_WIKI 0 /* The Fossil-Wiki formatter */
#define FUZZ_MARKDOWN 1 /* The Markdown formatter */
#define FUZZ_ARTIFACT 2 /* Fuzz the artifact parser */
#define FUZZ_WIKI2 3 /* FOSSIL_WIKI and FOSSIL_MARKDOWN */
#endif
/* The type of fuzzing to do */
static int eFuzzType = FUZZ_WIKI;
/* The fuzzer invokes this routine once for each fuzzer input
*/
int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){
Blob in, out;
blob_init(&in, 0, 0);
blob_append(&in, (char*)aData, (int)nByte);
blob_zero(&out);
switch( eFuzzType ){
case FUZZ_WIKI: {
wiki_convert(&in, &out, 0);
blob_reset(&out);
break;
}
case FUZZ_MARKDOWN: {
Blob title = BLOB_INITIALIZER;
blob_reset(&out);
markdown_to_html(&in, &title, &out);
blob_reset(&title);
break;
}
case FUZZ_WIKI2: {
Blob title = BLOB_INITIALIZER;
wiki_convert(&in, &out, 0);
blob_reset(&out);
markdown_to_html(&in, &title, &out);
blob_reset(&title);
break;
}
case FUZZ_ARTIFACT:
fossil_fatal("FUZZ_ARTIFACT is not implemented.");
break;
}
blob_reset(&in);
blob_reset(&out);
return 0;
}
/*
** Check fuzzer command-line options.
*/
static void fuzzer_options(void){
const char *zType;
db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
db_multi_exec("PRAGMA query_only=1;");
zType = find_option("fuzztype",0,1);
if( zType==0 || fossil_strcmp(zType,"wiki")==0 ){
eFuzzType = FUZZ_WIKI;
}else if( fossil_strcmp(zType,"markdown")==0 ){
eFuzzType = FUZZ_MARKDOWN;
}else if( fossil_strcmp(zType,"wiki2")==0 ){
eFuzzType = FUZZ_WIKI2;
}else{
fossil_fatal("unknown fuzz type: \"%s\"", zType);
}
}
/* Libfuzzer invokes this routine once prior to start-up to
** process command-line options.
*/
int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){
expand_args_option(*pArgc, *pArgv);
fuzzer_options();
*pArgc = g.argc;
*pArgv = g.argv;
return 0;
}
/*
** COMMAND: test-fuzz
**
** Usage: %fossil test-fuzz [-fuzztype TYPE] INPUTFILE...
**
** Run a fuzz test using INPUTFILE as the test data. TYPE can be one of:
**
** wiki Fuzz the Fossil-wiki translator
** markdown Fuzz the markdown translator
** artifact Fuzz the artifact parser
** wiki2 Fuzz the Fossil-wiki and markdown translator
*/
void fuzz_command(void){
Blob in;
int i;
fuzzer_options();
verify_all_options();
for(i=2; i<g.argc; i++){
blob_read_from_file(&in, g.argv[i], ExtFILE);
LLVMFuzzerTestOneInput((const uint8_t*)in.aData, (size_t)in.nUsed);
fossil_print("%s\n", g.argv[i]);
blob_reset(&in);
}
}
|
Changes to src/gzip.c.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 |
#include "gzip.h"
/*
** State information for the GZIP file under construction.
*/
struct gzip_state {
int eState; /* 0: idle 1: header 2: compressing */
| | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include "gzip.h"
/*
** State information for the GZIP file under construction.
*/
struct gzip_state {
int eState; /* 0: idle 1: header 2: compressing */
unsigned long iCRC; /* The checksum */
z_stream stream; /* The working compressor */
Blob out; /* Results stored here */
} gzip;
/*
** Write a 32-bit integer as little-endian into the given buffer.
*/
|
| ︙ | ︙ |
Changes to src/hook.c.
| ︙ | ︙ | |||
474 475 476 477 478 479 480 |
int fdFromChild;
FILE *toChild;
int childPid;
if( cnt==0 ){
hook_changes(&chng, zLastRcvid, 0);
}
zCmd = hook_subst(db_column_text(&q,0), 0);
| | | 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 |
int fdFromChild;
FILE *toChild;
int childPid;
if( cnt==0 ){
hook_changes(&chng, zLastRcvid, 0);
}
zCmd = hook_subst(db_column_text(&q,0), 0);
if( popen2(zCmd, &fdFromChild, &toChild, &childPid, 0)==0 ){
if( toChild ){
fwrite(blob_buffer(&chng),1,blob_size(&chng),toChild);
}
pclose2(fdFromChild, toChild, childPid);
}
fossil_free(zCmd);
cnt++;
|
| ︙ | ︙ |
Changes to src/http_ssl.c.
| ︙ | ︙ | |||
1176 1177 1178 1179 1180 1181 1182 | return; wellknown_notfound: fossil_free(zPath); webpage_notfound_error(0); return; } | > > > > > > > > > > > > > > | 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 |
return;
wellknown_notfound:
fossil_free(zPath);
webpage_notfound_error(0);
return;
}
/*
** Return the OpenSSL version number being used. Space to hold
** this name is obtained from fossil_malloc() and should be
** freed by the caller.
*/
char *fossil_openssl_version(void){
#if defined(FOSSIL_ENABLE_SSL)
return mprintf("%s (0x%09x)\n",
SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_NUMBER);
#else
return mprintf("none");
#endif
}
|
Changes to src/info.c.
| ︙ | ︙ | |||
733 734 735 736 737 738 739 |
if( fossil_strcmp(zTagName,zBrName)==0 ){
cgi_printf(" | ");
style_copy_button(1, "name-br", 0, 0, "%z%h</a>",
href("%R/timeline?r=%T&unhide",zTagName), zTagName);
cgi_printf("\n");
if( wiki_tagid2("branch",zTagName)!=0 ){
blob_appendf(&wiki_read_links, " | %z%h</a>",
| > > > | | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 |
if( fossil_strcmp(zTagName,zBrName)==0 ){
cgi_printf(" | ");
style_copy_button(1, "name-br", 0, 0, "%z%h</a>",
href("%R/timeline?r=%T&unhide",zTagName), zTagName);
cgi_printf("\n");
if( wiki_tagid2("branch",zTagName)!=0 ){
blob_appendf(&wiki_read_links, " | %z%h</a>",
href("%R/%s?name=branch/%h",
(g.perm.Write && g.perm.WrWiki)
? "wikiedit" : "wiki",
zTagName), zTagName);
}else if( g.perm.Write && g.perm.WrWiki ){
blob_appendf(&wiki_add_links, " | %z%h</a>",
href("%R/wikiedit?name=branch/%h",zTagName), zTagName);
}
}else{
@ | %z(href("%R/timeline?t=%T&unhide",zTagName))%h(zTagName)</a>
if( wiki_tagid2("tag",zTagName)!=0 ){
|
| ︙ | ︙ | |||
983 984 985 986 987 988 989 |
}
if( strcmp(zModAction,"approve")==0 ){
moderation_approve('w', rid);
}
}
style_header("Update of \"%h\"", pWiki->zWikiTitle);
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
| | | 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 |
}
if( strcmp(zModAction,"approve")==0 ){
moderation_approve('w', rid);
}
}
style_header("Update of \"%h\"", pWiki->zWikiTitle);
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
zDate = db_text(0, "SELECT datetime(%.17g,toLocal())", pWiki->rDate);
style_submenu_element("Raw", "%R/artifact/%s", zUuid);
style_submenu_element("History", "%R/whistory?name=%t", pWiki->zWikiTitle);
style_submenu_element("Page", "%R/wiki?name=%t", pWiki->zWikiTitle);
login_anonymous_available();
@ <div class="section">Overview</div>
@ <p><table class="label-value">
@ <tr><th>Artifact ID:</th>
|
| ︙ | ︙ | |||
1177 1178 1179 1180 1181 1182 1183 |
int graphFlags = 0;
Blob qp;
int bInvert = PB("inv");
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
login_anonymous_available();
| | | 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 |
int graphFlags = 0;
Blob qp;
int bInvert = PB("inv");
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
login_anonymous_available();
fossil_nice_default();
blob_init(&qp, 0, 0);
diffType = preferred_diff_type();
zRe = P("regex");
if( zRe ) re_compile(&pRe, zRe, 0);
zBranch = P("branch");
if( zBranch && zBranch[0]==0 ) zBranch = 0;
if( zBranch ){
|
| ︙ | ︙ | |||
3679 3680 3681 3682 3683 3684 3685 |
db_column_text(&q,3));
}
db_finalize(&q);
}
#if INTERFACE
/*
| | | | | | | | > > | > | 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 |
db_column_text(&q,3));
}
db_finalize(&q);
}
#if INTERFACE
/*
** Description of a check-in relative to an earlier, tagged check-in.
*/
typedef struct CommitDescr {
char *zRelTagname; /* Tag name on the relative check-in */
int nCommitsSince; /* Number of commits since then */
char *zCommitHash; /* Hash of the described check-in */
int isDirty; /* Working directory has uncommitted changes */
} CommitDescr;
#endif
/*
** Describe the check-in given by 'zName', and possibly matching 'matchGlob',
** relative to an earlier, tagged check-in. Use 'descr' for the output.
**
** Finds the closest ancestor (ignoring merge-ins) that has a non-propagating
** label tag and the number of steps backwards that we had to search in
** order to find that tag. Tags applied to more than one check-in are ignored.
**
** Return values:
** 0: ok
** -1: zName does not resolve to a commit
** -2: zName resolves to more than a commit
** -3: no ancestor commit with a fitting non-propagating tag found
*/
int describe_commit(
const char *zName, /* Name of the commit to be described */
const char *matchGlob, /* Glob pattern for the tag */
CommitDescr *descr /* Write the description here */
){
int rid; /* rid for zName */
const char *zUuid; /* Hash of rid */
int nRet = 0; /* Value to be returned */
Stmt q; /* Query for tagged ancestors */
rid = symbolic_name_to_rid(zName, "ci"); /* only commits */
|
| ︙ | ︙ | |||
3726 3727 3728 3729 3730 3731 3732 |
}
zUuid = rid_to_uuid(rid);
descr->zCommitHash = mprintf("%s", zUuid);
descr->isDirty = unsaved_changes(0);
db_multi_exec(
| | | > > > | | | | | < < | | | < < < < < < < < | < < < < < < < < < < | < < | > > | | | > | > > | | | > > > > > > | < > | | | < | | > > > | | > | | 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 |
}
zUuid = rid_to_uuid(rid);
descr->zCommitHash = mprintf("%s", zUuid);
descr->isDirty = unsaved_changes(0);
db_multi_exec(
"DROP TABLE IF EXISTS temp.singletonTag;"
"CREATE TEMP TABLE singletonTag("
" rid INT,"
" tagname TEXT,"
" PRIMARY KEY (rid,tagname)"
") WITHOUT ROWID;"
"INSERT OR IGNORE INTO singletonTag(rid, tagname)"
" SELECT min(rid),"
" substr(tagname,5)"
" FROM tag, tagxref"
" WHERE tag.tagid=tagxref.tagid"
" AND tagxref.tagtype=1"
" AND tagname GLOB 'sym-%q'"
" GROUP BY tagname"
" HAVING count(*)==1;",
(matchGlob ? matchGlob : "*")
);
db_prepare(&q,
"WITH RECURSIVE"
" ancestor(rid,mtime,tagname,n) AS ("
" SELECT %d, event.mtime, singletonTag.tagname, 0 "
" FROM event"
" LEFT JOIN singletonTag ON singletonTag.rid=event.objid"
" WHERE event.objid=%d"
" UNION ALL"
" SELECT plink.pid, event.mtime, singletonTag.tagname, n+1"
" FROM ancestor, plink, event"
" LEFT JOIN singletonTag ON singletonTag.rid=plink.pid"
" WHERE plink.cid=ancestor.rid"
" AND event.objid=plink.pid"
" AND ancestor.tagname IS NULL"
" ORDER BY mtime DESC"
" )"
"SELECT tagname, n"
" FROM ancestor"
" WHERE tagname IS NOT NULL"
" ORDER BY n LIMIT 1;",
rid, rid
);
if( db_step(&q)==SQLITE_ROW ){
const char *lastTag = db_column_text(&q, 0);
descr->zRelTagname = mprintf("%s", lastTag);
descr->nCommitsSince = db_column_int(&q, 1);
nRet = 0;
}else{
/* no ancestor commit with a fitting singleton tag found */
descr->zRelTagname = mprintf("");
descr->nCommitsSince = -1;
nRet = -3;
}
db_finalize(&q);
return nRet;
}
/*
** COMMAND: describe
**
** Usage: %fossil describe ?VERSION? ?OPTIONS?
**
** Provide a description of the given VERSION by showing a non-propagating
** tag of the youngest tagged ancestor, followed by the number of commits
** since that, and the short hash of VERSION. Only tags applied to a single
** check-in are considered.
**
** If no VERSION is provided, describe the current checked-out version.
**
** If VERSION and the found ancestor refer to the same commit, the last two
** components are omitted, unless --long is provided. When no fitting tagged
** ancestor is found, show only the short hash of VERSION.
**
** Options:
**
** --digits Display so many hex digits of the hash
** (default: the larger of 6 and the 'hash-digit' setting)
** -d|--dirty Show whether there are changes to be committed
** --long Always show all three components
** --match GLOB Consider only non-propagating tags matching GLOB
*/
void describe_cmd(void){
const char *zName;
const char *zMatchGlob;
const char *zDigits;
int nDigits;
int bDirtyFlag = 0;
int bLongFlag = 0;
CommitDescr descr;
db_find_and_open_repository(0,0);
bDirtyFlag = find_option("dirty","d",0)!=0;
bLongFlag = find_option("long","",0)!=0;
zMatchGlob = find_option("match", 0, 1);
zDigits = find_option("digits", 0, 1);
if ( !zDigits || ((nDigits=atoi(zDigits))==0) ){
nDigits = hash_digits(0);
}
/* We should be done with options.. */
verify_all_options();
if( g.argc<3 ){
zName = "current";
}else{
|
| ︙ | ︙ |
Changes to src/json.c.
| ︙ | ︙ | |||
556 557 558 559 560 561 562 | } /* ** Guesses a RESPONSE Content-Type value based (primarily) on the ** HTTP_ACCEPT header. ** ** It will try to figure out if the client can support | | | | | 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 |
}
/*
** Guesses a RESPONSE Content-Type value based (primarily) on the
** HTTP_ACCEPT header.
**
** It will try to figure out if the client can support
** application/json, text/javascript, and will fall back to
** text/plain if it cannot figure out anything more specific.
**
** Returned memory is static and immutable, but if the environment
** changes after calling this then subsequent calls to this function
** might return different (also static/immutable) values.
*/
char const * json_guess_content_type(){
char const * cset;
char doUtf8;
cset = PD("HTTP_ACCEPT_CHARSET",NULL);
doUtf8 = ((NULL == cset) || (NULL!=strstr("utf-8",cset)))
? 1 : 0;
if( g.json.jsonp ){
return doUtf8
? "text/javascript; charset=utf-8"
: "text/javascript";
}else{
/*
Content-type
If the browser does not sent an ACCEPT for application/json
then we fall back to text/plain.
*/
|
| ︙ | ︙ | |||
603 604 605 606 607 608 609 | } } /* ** Given a request CONTENT_TYPE value, this function returns true ** if it is of a type which the JSON API can ostensibly read. ** | | | | | > | > | 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 |
}
}
/*
** Given a request CONTENT_TYPE value, this function returns true
** if it is of a type which the JSON API can ostensibly read.
**
** It accepts any of application/json, text/plain,
** application/javascript, or text/javascript. The former is
** preferred, but was not widespread when this API was initially
** built, so the latter forms are permitted as fallbacks.
*/
int json_can_consume_content_type(const char * zType){
return fossil_strcmp(zType, "application/json")==0
|| fossil_strcmp(zType,"text/plain")==0/*assume this MIGHT be JSON*/
|| fossil_strcmp(zType,"text/javascript")==0
|| fossil_strcmp(zType,"application/javascript")==0;
}
/*
** Sends pResponse to the output stream as the response object. This
** function does no validation of pResponse except to assert() that it
** is not NULL. The caller is responsible for ensuring that it meets
** API response envelope conventions.
**
** In CLI mode pResponse is sent to stdout immediately. In HTTP
** mode pResponse replaces any current CGI content but cgi_reply()
** is not called to flush the output.
**
** If g.json.jsonp is not NULL then the content type is set to
** text/javascript and the output is wrapped in a jsonp
** wrapper.
*/
void json_send_response( cson_value const * pResponse ){
assert( NULL != pResponse );
if( g.isHTTP ){
cgi_reset_content();
if( g.json.jsonp ){
cgi_set_content_type("text/javascript");
cgi_printf("%s(",g.json.jsonp);
}
cson_output( pResponse, cson_data_dest_cgi, NULL, &g.json.outOpt );
if( g.json.jsonp ){
cgi_append_content(")",1);
}
}else{/*CLI mode*/
|
| ︙ | ︙ | |||
737 738 739 740 741 742 743 | /* ** Returns non-zero if the json_bootstrap_early() function has already ** been called. In general, this function should be used sparingly, ** e.g. from low-level support functions like fossil_warning() where ** there is genuine uncertainty about whether (or not) the JSON setup ** has already been called. */ | | | | 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 |
/*
** Returns non-zero if the json_bootstrap_early() function has already
** been called. In general, this function should be used sparingly,
** e.g. from low-level support functions like fossil_warning() where
** there is genuine uncertainty about whether (or not) the JSON setup
** has already been called.
*/
int json_is_bootstrapped_early(void){
return ((g.json.gc.v != NULL) && (g.json.gc.a != NULL));
}
/*
** Initializes some JSON bits which need to be initialized relatively
** early on. It should be called by any routine which might need to
** call into JSON relatively early on in the init process.
** Specifically, early on in cgi_init() and json_cmd_top(), but also
** from any error reporting routines which might be triggered (early
** on in those functions).
**
** Initializes g.json.gc and g.json.param. This code does not (and
** must not) rely on any of the fossil environment having been set
** up. e.g. it must not use cgi_parameter() and friends because this
** must be called before those data are initialized.
**
** If called multiple times, calls after the first are a no-op.
*/
void json_bootstrap_early(void){
cson_value * v;
if(g.json.gc.v!=NULL){
/* Avoid multiple bootstrappings. */
return;
}
g.json.timerId = fossil_timer_start();
|
| ︙ | ︙ |
Changes to src/json_branch.c.
| ︙ | ︙ | |||
304 305 306 307 308 309 310 |
if( zNewRid ){
*zNewRid = brid;
}
/* Commit */
db_end_transaction(0);
| < < < < | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
if( zNewRid ){
*zNewRid = brid;
}
/* Commit */
db_end_transaction(0);
return 0;
}
/*
** Impl of /json/branch/create.
*/
|
| ︙ | ︙ |
Changes to src/loadctrl.c.
| ︙ | ︙ | |||
43 44 45 46 47 48 49 |
** Print the load average on the host machine.
*/
void loadavg_test_cmd(void){
fossil_print("load-average: %f\n", load_average());
}
/*
| | | > > > > > > > > > | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
** Print the load average on the host machine.
*/
void loadavg_test_cmd(void){
fossil_print("load-average: %f\n", load_average());
}
/*
** Abort the current page request if the load average of the host
** computer is too high. Admin and Setup users are exempt from this
** restriction.
*/
void load_control(void){
double mxLoad = atof(db_get("max-loadavg", 0));
#if 1
/* Disable this block only to test load restrictions */
if( mxLoad<=0.0 || mxLoad>=load_average() ) return;
login_check_credentials();
if(g.perm.Admin || g.perm.Setup){
return;
}
#endif
style_set_current_feature("test");
style_header("Server Overload");
@ <h2>The server load is currently too high.
@ Please try again later.</h2>
@ <p>Current load average: %f(load_average()).<br />
@ Load average limit: %f(mxLoad)</p>
|
| ︙ | ︙ |
Changes to src/login.c.
| ︙ | ︙ | |||
983 984 985 986 987 988 989 990 991 992 993 994 995 996 |
** variables appropriately.
**
** g.userUid Database USER.UID value. Might be -1 for "nobody"
** g.zLogin Database USER.LOGIN value. NULL for user "nobody"
** g.perm Permissions granted to this user
** g.anon Permissions that would be available to anonymous
** g.isHuman True if the user is human, not a spider or robot
**
*/
void login_check_credentials(void){
int uid = 0; /* User id */
const char *zCookie; /* Text of the login cookie */
const char *zIpAddr; /* Raw IP address of the requestor */
const char *zCap = 0; /* Capability string */
| > | 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 |
** variables appropriately.
**
** g.userUid Database USER.UID value. Might be -1 for "nobody"
** g.zLogin Database USER.LOGIN value. NULL for user "nobody"
** g.perm Permissions granted to this user
** g.anon Permissions that would be available to anonymous
** g.isHuman True if the user is human, not a spider or robot
** g.perm Populated based on user account's capabilities
**
*/
void login_check_credentials(void){
int uid = 0; /* User id */
const char *zCookie; /* Text of the login cookie */
const char *zIpAddr; /* Raw IP address of the requestor */
const char *zCap = 0; /* Capability string */
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
136 137 138 139 140 141 142 |
};
#endif
struct Global {
int argc; char **argv; /* Command-line arguments to the program */
char *nameOfExe; /* Full path of executable. */
const char *zErrlog; /* Log errors to this file, if not NULL */
| | > | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
};
#endif
struct Global {
int argc; char **argv; /* Command-line arguments to the program */
char *nameOfExe; /* Full path of executable. */
const char *zErrlog; /* Log errors to this file, if not NULL */
const char *zPhase; /* Phase of operation, for use by the error log
** and for deriving $canonical_page TH1 variable */
int isConst; /* True if the output is unchanging & cacheable */
const char *zVfsName; /* The VFS to use for database connections */
sqlite3 *db; /* The connection to the databases */
sqlite3 *dbConfig; /* Separate connection for global_config table */
char *zAuxSchema; /* Main repository aux-schema */
int dbIgnoreErrors; /* Ignore database errors if true */
char *zConfigDbName; /* Path of the config database. NULL if not open */
|
| ︙ | ︙ | |||
174 175 176 177 178 179 180 | int fSshTrace; /* Trace the SSH setup traffic */ int fSshClient; /* HTTP client flags for SSH client */ int fNoHttpCompress; /* Do not compress HTTP traffic (for debugging) */ char *zSshCmd; /* SSH command string */ const char *zHttpCmd; /* External program to do HTTP requests */ int fNoSync; /* Do not do an autosync ever. --nosync */ int fIPv4; /* Use only IPv4, not IPv6. --ipv4 */ | | | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | int fSshTrace; /* Trace the SSH setup traffic */ int fSshClient; /* HTTP client flags for SSH client */ int fNoHttpCompress; /* Do not compress HTTP traffic (for debugging) */ char *zSshCmd; /* SSH command string */ const char *zHttpCmd; /* External program to do HTTP requests */ int fNoSync; /* Do not do an autosync ever. --nosync */ int fIPv4; /* Use only IPv4, not IPv6. --ipv4 */ char *zPath; /* Name of webpage being served (may be NULL) */ char *zExtra; /* Extra path information past the webpage name */ char *zBaseURL; /* Full text of the URL being served */ char *zHttpsURL; /* zBaseURL translated to https: */ char *zTop; /* Parent directory of zPath */ int nExtraURL; /* Extra bytes added to SCRIPT_NAME */ const char *zExtRoot; /* Document root for the /ext sub-website */ const char *zContentType; /* The content type of the input HTTP request */ |
| ︙ | ︙ | |||
322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
cson_value *v;
cson_object *o;
} reqPayload; /* request payload object (if any) */
cson_array *warnings; /* response warnings */
int timerId; /* fetched from fossil_timer_start() */
} json;
#endif /* FOSSIL_ENABLE_JSON */
int diffCnt[3]; /* Counts for DIFF_NUMSTAT: files, ins, del */
};
/*
** Macro for debugging:
*/
#define CGIDEBUG(X) if( g.fDebug ) cgi_debug X
| > | 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
cson_value *v;
cson_object *o;
} reqPayload; /* request payload object (if any) */
cson_array *warnings; /* response warnings */
int timerId; /* fetched from fossil_timer_start() */
} json;
#endif /* FOSSIL_ENABLE_JSON */
int ftntsIssues[4]; /* Counts for misref, strayed, joined, overnested */
int diffCnt[3]; /* Counts for DIFF_NUMSTAT: files, ins, del */
};
/*
** Macro for debugging:
*/
#define CGIDEBUG(X) if( g.fDebug ) cgi_debug X
|
| ︙ | ︙ | |||
909 910 911 912 913 914 915 |
}
}
fossil_exit(0);
#endif
}else if( rc==2 ){
Blob couldbe;
blob_init(&couldbe,0,0);
| | | 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 |
}
}
fossil_exit(0);
#endif
}else if( rc==2 ){
Blob couldbe;
blob_init(&couldbe,0,0);
dispatch_matching_names(zCmdName, CMDFLAG_COMMAND, &couldbe);
fossil_print("%s: ambiguous command prefix: %s\n"
"%s: could be any of:%s\n"
"%s: use \"help\" for more information\n",
g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
fossil_exit(1);
}
#ifdef FOSSIL_ENABLE_JSON
|
| ︙ | ︙ | |||
1898 1899 1900 1901 1902 1903 1904 |
}
}
/* At this point, the appropriate repository database file will have
** been opened.
*/
| < | 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 |
}
}
/* At this point, the appropriate repository database file will have
** been opened.
*/
/*
** Check to see if the first term of PATH_INFO specifies an
** alternative skin. This will be the case if the first term of
** PATH_INFO begins with "draftN/" where N is an integer between 1
** and 9. If so, activate the skin associated with that draft.
*/
if( zPathInfo && strncmp(zPathInfo,"/draft",6)==0
|
| ︙ | ︙ | |||
2041 2042 2043 2044 2045 2046 2047 2048 |
#endif
{
@ <h1>Server Configuration Error</h1>
@ <p>The database schema on the server is out-of-date. Please ask
@ the administrator to run <b>fossil rebuild</b>.</p>
}
}else{
#ifdef FOSSIL_ENABLE_JSON
| > > > > | | | | | > | 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 |
#endif
{
@ <h1>Server Configuration Error</h1>
@ <p>The database schema on the server is out-of-date. Please ask
@ the administrator to run <b>fossil rebuild</b>.</p>
}
}else{
if(0==(CMDFLAG_LDAVG_EXEMPT & pCmd->eCmdFlags)){
load_control();
}
#ifdef FOSSIL_ENABLE_JSON
{
static int jsonOnce = 0;
if( jsonOnce==0 && g.json.isJsonMode!=0 ){
assert(json_is_bootstrapped_early());
json_bootstrap_late();
jsonOnce = 1;
}
}
#endif
if( (pCmd->eCmdFlags & CMDFLAG_RAWCONTENT)==0 ){
cgi_decode_post_parameters();
}
if( g.fCgiTrace ){
fossil_trace("######## Calling %s #########\n", pCmd->zName);
|
| ︙ | ︙ |
Changes to src/main.mk.
| ︙ | ︙ | |||
161 162 163 164 165 166 167 168 169 170 171 172 173 174 | $(SRCDIR)/winfile.c \ $(SRCDIR)/winhttp.c \ $(SRCDIR)/xfer.c \ $(SRCDIR)/xfersetup.c \ $(SRCDIR)/zip.c EXTRA_FILES = \ $(SRCDIR)/../skins/ardoise/css.txt \ $(SRCDIR)/../skins/ardoise/details.txt \ $(SRCDIR)/../skins/ardoise/footer.txt \ $(SRCDIR)/../skins/ardoise/header.txt \ $(SRCDIR)/../skins/black_and_white/css.txt \ $(SRCDIR)/../skins/black_and_white/details.txt \ $(SRCDIR)/../skins/black_and_white/footer.txt \ | > > > | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | $(SRCDIR)/winfile.c \ $(SRCDIR)/winhttp.c \ $(SRCDIR)/xfer.c \ $(SRCDIR)/xfersetup.c \ $(SRCDIR)/zip.c EXTRA_FILES = \ $(SRCDIR)/../extsrc/pikchr-worker.js \ $(SRCDIR)/../extsrc/pikchr.js \ $(SRCDIR)/../extsrc/pikchr.wasm \ $(SRCDIR)/../skins/ardoise/css.txt \ $(SRCDIR)/../skins/ardoise/details.txt \ $(SRCDIR)/../skins/ardoise/footer.txt \ $(SRCDIR)/../skins/ardoise/header.txt \ $(SRCDIR)/../skins/black_and_white/css.txt \ $(SRCDIR)/../skins/black_and_white/details.txt \ $(SRCDIR)/../skins/black_and_white/footer.txt \ |
| ︙ | ︙ | |||
229 230 231 232 233 234 235 236 237 238 239 240 241 242 | $(SRCDIR)/fossil.fetch.js \ $(SRCDIR)/fossil.numbered-lines.js \ $(SRCDIR)/fossil.page.brlist.js \ $(SRCDIR)/fossil.page.chat.js \ $(SRCDIR)/fossil.page.fileedit.js \ $(SRCDIR)/fossil.page.forumpost.js \ $(SRCDIR)/fossil.page.pikchrshow.js \ $(SRCDIR)/fossil.page.whistory.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.js \ $(SRCDIR)/fossil.popupwidget.js \ $(SRCDIR)/fossil.storage.js \ $(SRCDIR)/fossil.tabs.js \ $(SRCDIR)/fossil.wikiedit-wysiwyg.js \ | > | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | $(SRCDIR)/fossil.fetch.js \ $(SRCDIR)/fossil.numbered-lines.js \ $(SRCDIR)/fossil.page.brlist.js \ $(SRCDIR)/fossil.page.chat.js \ $(SRCDIR)/fossil.page.fileedit.js \ $(SRCDIR)/fossil.page.forumpost.js \ $(SRCDIR)/fossil.page.pikchrshow.js \ $(SRCDIR)/fossil.page.pikchrshowasm.js \ $(SRCDIR)/fossil.page.whistory.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.js \ $(SRCDIR)/fossil.popupwidget.js \ $(SRCDIR)/fossil.storage.js \ $(SRCDIR)/fossil.tabs.js \ $(SRCDIR)/fossil.wikiedit-wysiwyg.js \ |
| ︙ | ︙ | |||
264 265 266 267 268 269 270 271 272 273 274 275 276 277 | $(SRCDIR)/sounds/c.wav \ $(SRCDIR)/sounds/d.wav \ $(SRCDIR)/sounds/e.wav \ $(SRCDIR)/sounds/f.wav \ $(SRCDIR)/style.admin_log.css \ $(SRCDIR)/style.chat.css \ $(SRCDIR)/style.fileedit.css \ $(SRCDIR)/style.wikiedit.css \ $(SRCDIR)/tree.js \ $(SRCDIR)/useredit.js \ $(SRCDIR)/wiki.wiki TRANS_SRC = \ $(OBJDIR)/add_.c \ | > | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | $(SRCDIR)/sounds/c.wav \ $(SRCDIR)/sounds/d.wav \ $(SRCDIR)/sounds/e.wav \ $(SRCDIR)/sounds/f.wav \ $(SRCDIR)/style.admin_log.css \ $(SRCDIR)/style.chat.css \ $(SRCDIR)/style.fileedit.css \ $(SRCDIR)/style.pikchrshow.css \ $(SRCDIR)/style.wikiedit.css \ $(SRCDIR)/tree.js \ $(SRCDIR)/useredit.js \ $(SRCDIR)/wiki.wiki TRANS_SRC = \ $(OBJDIR)/add_.c \ |
| ︙ | ︙ | |||
674 675 676 677 678 679 680 681 682 683 684 685 686 687 |
-DSQLITE_TRUSTED_SCHEMA=0 \
-Dmain=sqlite3_shell \
-DSQLITE_SHELL_IS_UTF8=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
-DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
-DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0 or 1.
# If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system SQLite will be linked
# using -lsqlite3.
#
# Closely related is SQLITE3_ORIGIN, with the same numeric mapping plus
| > > > | 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 |
-DSQLITE_TRUSTED_SCHEMA=0 \
-Dmain=sqlite3_shell \
-DSQLITE_SHELL_IS_UTF8=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
-DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
-DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc
# Setup the options used to compile the included Pikchr formatter.
PIKCHR_OPTIONS = -DPIKCHR_TOKEN_LIMIT=10000
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0 or 1.
# If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system SQLite will be linked
# using -lsqlite3.
#
# Closely related is SQLITE3_ORIGIN, with the same numeric mapping plus
|
| ︙ | ︙ | |||
2100 2101 2102 2103 2104 2105 2106 | $(XTCC) -c $(SRCDIR)/th_lang.c -o $@ $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@ $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c | | > > > > > | 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 | $(XTCC) -c $(SRCDIR)/th_lang.c -o $@ $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@ $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c $(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@ $(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c $(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@ $(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c $(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry -sEXPORTED_RUNTIME_METHODS=cwrap,setValue,getValue,stackSave,stackRestore -sEXPORTED_FUNCTIONS=_pikchr $(SRCDIR_extsrc)/pikchr.c -sENVIRONMENT=web -sMODULARIZE -sEXPORT_NAME=initPikchrModule --minify 0 @chmod -x $(SRCDIR_extsrc)/pikchr.wasm wasm: $(SRCDIR_extsrc)/pikchr.js # # The list of all the targets that do not correspond to real files. This stops # 'make' from getting confused when someone makes an error in a rule. # .PHONY: all install test clean |
Changes to src/manifest.c.
| ︙ | ︙ | |||
2393 2394 2395 2396 2397 2398 2399 |
"RETURNING coalesce(ecomment,comment);",
TAG_DATE, rid, p->rDate,
rid, p->zUser, p->zComment,
TAG_BGCOLOR, rid,
TAG_USER, rid,
TAG_COMMENT, rid, p->rDate
);
| | | 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 |
"RETURNING coalesce(ecomment,comment);",
TAG_DATE, rid, p->rDate,
rid, p->zUser, p->zComment,
TAG_BGCOLOR, rid,
TAG_USER, rid,
TAG_COMMENT, rid, p->rDate
);
backlink_extract(zCom, MT_NONE, rid, BKLNK_COMMENT, p->rDate, 1);
fossil_free(zCom);
/* If this is a delta-manifest, record the fact that this repository
** contains delta manifests, to free the "commit" logic to generate
** new delta manifests.
*/
if( p->zBaseline!=0 ){
|
| ︙ | ︙ | |||
2851 2852 2853 2854 2855 2856 2857 |
"REPLACE INTO event(type,mtime,objid,user,comment)"
"VALUES('f',%.17g,%d,%Q,'%q: %q')",
p->rDate, rid, p->zUser, zFType, zTitle
);
fossil_free(zTitle);
}
if( p->zWiki[0] ){
| > | | 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 |
"REPLACE INTO event(type,mtime,objid,user,comment)"
"VALUES('f',%.17g,%d,%Q,'%q: %q')",
p->rDate, rid, p->zUser, zFType, zTitle
);
fossil_free(zTitle);
}
if( p->zWiki[0] ){
int mimetype = parse_mimetype(p->zMimetype);
backlink_extract(p->zWiki, mimetype, rid, BKLNK_FORUM, p->rDate, 1);
}
}
db_end_transaction(0);
if( permitHooks ){
rc = xfer_run_common_script();
if( rc==TH_OK ){
|
| ︙ | ︙ |
Changes to src/markdown.c.
| ︙ | ︙ | |||
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
};
/* mkd_renderer -- functions for rendering parsed data */
struct mkd_renderer {
/* document level callbacks */
void (*prolog)(struct Blob *ob, void *opaque);
void (*epilog)(struct Blob *ob, void *opaque);
/* block level callbacks - NULL skips the block */
void (*blockcode)(struct Blob *ob, struct Blob *text, void *opaque);
void (*blockquote)(struct Blob *ob, struct Blob *text, void *opaque);
void (*blockhtml)(struct Blob *ob, struct Blob *text, void *opaque);
void (*header)(struct Blob *ob, struct Blob *text,
int level, void *opaque);
void (*hrule)(struct Blob *ob, void *opaque);
void (*list)(struct Blob *ob, struct Blob *text, int flags, void *opaque);
void (*listitem)(struct Blob *ob, struct Blob *text,
int flags, void *opaque);
void (*paragraph)(struct Blob *ob, struct Blob *text, void *opaque);
void (*table)(struct Blob *ob, struct Blob *head_row, struct Blob *rows,
void *opaque);
void (*table_cell)(struct Blob *ob, struct Blob *text, int flags,
void *opaque);
void (*table_row)(struct Blob *ob, struct Blob *cells, int flags,
void *opaque);
/* span level callbacks - NULL or return 0 prints the span verbatim */
int (*autolink)(struct Blob *ob, struct Blob *link,
enum mkd_autolink type, void *opaque);
int (*codespan)(struct Blob *ob, struct Blob *text, int nSep, void *opaque);
int (*double_emphasis)(struct Blob *ob, struct Blob *text,
char c, void *opaque);
int (*emphasis)(struct Blob *ob, struct Blob *text, char c,void*opaque);
int (*image)(struct Blob *ob, struct Blob *link, struct Blob *title,
struct Blob *alt, void *opaque);
int (*linebreak)(struct Blob *ob, void *opaque);
int (*link)(struct Blob *ob, struct Blob *link, struct Blob *title,
struct Blob *content, void *opaque);
int (*raw_html_tag)(struct Blob *ob, struct Blob *tag, void *opaque);
int (*triple_emphasis)(struct Blob *ob, struct Blob *text,
char c, void *opaque);
/* low level callbacks - NULL copies input directly into the output */
void (*entity)(struct Blob *ob, struct Blob *entity, void *opaque);
void (*normal_text)(struct Blob *ob, struct Blob *text, void *opaque);
/* renderer data */
const char *emph_chars; /* chars that trigger emphasis rendering */
| > > > > > | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
};
/* mkd_renderer -- functions for rendering parsed data */
struct mkd_renderer {
/* document level callbacks */
void (*prolog)(struct Blob *ob, void *opaque);
void (*epilog)(struct Blob *ob, void *opaque);
void (*footnotes)(struct Blob *ob, const struct Blob *items, void *opaque);
/* block level callbacks - NULL skips the block */
void (*blockcode)(struct Blob *ob, struct Blob *text, void *opaque);
void (*blockquote)(struct Blob *ob, struct Blob *text, void *opaque);
void (*blockhtml)(struct Blob *ob, struct Blob *text, void *opaque);
void (*header)(struct Blob *ob, struct Blob *text,
int level, void *opaque);
void (*hrule)(struct Blob *ob, void *opaque);
void (*list)(struct Blob *ob, struct Blob *text, int flags, void *opaque);
void (*listitem)(struct Blob *ob, struct Blob *text,
int flags, void *opaque);
void (*paragraph)(struct Blob *ob, struct Blob *text, void *opaque);
void (*table)(struct Blob *ob, struct Blob *head_row, struct Blob *rows,
void *opaque);
void (*table_cell)(struct Blob *ob, struct Blob *text, int flags,
void *opaque);
void (*table_row)(struct Blob *ob, struct Blob *cells, int flags,
void *opaque);
void (*footnote_item)(struct Blob *ob, const struct Blob *text,
int index, int nUsed, void *opaque);
/* span level callbacks - NULL or return 0 prints the span verbatim */
int (*autolink)(struct Blob *ob, struct Blob *link,
enum mkd_autolink type, void *opaque);
int (*codespan)(struct Blob *ob, struct Blob *text, int nSep, void *opaque);
int (*double_emphasis)(struct Blob *ob, struct Blob *text,
char c, void *opaque);
int (*emphasis)(struct Blob *ob, struct Blob *text, char c,void*opaque);
int (*image)(struct Blob *ob, struct Blob *link, struct Blob *title,
struct Blob *alt, void *opaque);
int (*linebreak)(struct Blob *ob, void *opaque);
int (*link)(struct Blob *ob, struct Blob *link, struct Blob *title,
struct Blob *content, void *opaque);
int (*raw_html_tag)(struct Blob *ob, struct Blob *tag, void *opaque);
int (*triple_emphasis)(struct Blob *ob, struct Blob *text,
char c, void *opaque);
int (*footnote_ref)(struct Blob *ob, const struct Blob *span,
const struct Blob *upc, int index, int locus, void *opaque);
/* low level callbacks - NULL copies input directly into the output */
void (*entity)(struct Blob *ob, struct Blob *entity, void *opaque);
void (*normal_text)(struct Blob *ob, struct Blob *text, void *opaque);
/* renderer data */
const char *emph_chars; /* chars that trigger emphasis rendering */
|
| ︙ | ︙ | |||
111 112 113 114 115 116 117 | /********************** * EXPORTED FUNCTIONS * **********************/ | > | > | > > > > | > | > > > > > > > > > > > > > > > > | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
/**********************
* EXPORTED FUNCTIONS *
**********************/
/*
** markdown -- parses the input buffer and renders it into the output buffer.
*/
void markdown(
struct Blob *ob,
const struct Blob *ib,
const struct mkd_renderer *rndr);
#endif /* INTERFACE */
#define BLOB_COUNT(pBlob,el_type) (blob_size(pBlob)/sizeof(el_type))
#define COUNT_FOOTNOTES(pBlob) BLOB_COUNT(pBlob,struct footnote)
#define CAST_AS_FOOTNOTES(pBlob) ((struct footnote*)blob_buffer(pBlob))
/***************
* LOCAL TYPES *
***************/
/*
** link_ref -- reference to a link.
*/
struct link_ref {
struct Blob id; /* must be the first field as in footnote struct */
struct Blob link;
struct Blob title;
};
/*
** A footnote's data.
** id, text, and upc fields must be in that particular order.
*/
struct footnote {
struct Blob id; /* must be the first field as in link_ref struct */
struct Blob text; /* footnote's content that is rendered at the end */
struct Blob upc; /* user-provided classes .ASCII-alnum.or-hypen: */
int bRndred; /* indicates if `text` holds a rendered content */
int defno; /* serial number of definition, set during the first pass */
int index; /* set to the index within array after ordering by id */
int iMark; /* user-visible numeric marker, assigned upon the first use*/
int nUsed; /* counts references to this note, increments upon each use*/
};
#define FOOTNOTE_INITIALIZER {empty_blob,empty_blob,empty_blob, 0,0,0,0,0}
/* char_trigger -- function pointer to render active chars */
/* returns the number of chars taken care of */
/* data is the pointer of the beginning of the span */
/* offset is the number of valid chars before data */
struct render;
typedef size_t (*char_trigger)(
|
| ︙ | ︙ | |||
154 155 156 157 158 159 160 |
struct render {
struct mkd_renderer make;
struct Blob refs;
char_trigger active_char[256];
int iDepth; /* Depth of recursion */
int nBlobCache; /* Number of entries in aBlobCache */
struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */
| < > > > > > > > > | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
struct render {
struct mkd_renderer make;
struct Blob refs;
char_trigger active_char[256];
int iDepth; /* Depth of recursion */
int nBlobCache; /* Number of entries in aBlobCache */
struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */
struct {
Blob all; /* Buffer that holds array of footnotes. Its underline
memory may be reallocated when a new footnote is added. */
int nLbled; /* number of labeled footnotes found during the first pass */
int nMarks; /* counts distinct indices found during the second pass */
struct footnote misref; /* nUsed counts misreferences, iMark must be -1 */
} notes;
};
/* html_tag -- structure for quick HTML tag search (inspired from discount) */
struct html_tag {
const char *text;
int size;
};
|
| ︙ | ︙ | |||
181 182 183 184 185 186 187 |
*/
static const struct html_tag block_tags[] = {
{ "html", 4 },
{ "pre", 3 },
{ "script", 6 },
};
| < > | > > | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
*/
static const struct html_tag block_tags[] = {
{ "html", 4 },
{ "pre", 3 },
{ "script", 6 },
};
/***************************
* STATIC HELPER FUNCTIONS *
***************************/
/*
** build_ref_id -- collapse whitespace from input text to make it a ref id.
** Potential TODO: maybe also handle CR+LF line endings?
*/
static int build_ref_id(struct Blob *id, const char *data, size_t size){
size_t beg, i;
char *id_data;
/* skip leading whitespace */
while( size>0 && (data[0]==' ' || data[0]=='\t' || data[0]=='\n') ){
data++;
|
| ︙ | ︙ | |||
245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
/* cmp_link_ref_sort -- comparison function for link_ref qsort */
static int cmp_link_ref_sort(const void *a, const void *b){
struct link_ref *lra = (void *)a;
struct link_ref *lrb = (void *)b;
return blob_compare(&lra->id, &lrb->id);
}
/* cmp_html_tag -- comparison function for bsearch() (stolen from discount) */
static int cmp_html_tag(const void *a, const void *b){
const struct html_tag *hta = a;
const struct html_tag *htb = b;
int sz = hta->size;
int c;
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
/* cmp_link_ref_sort -- comparison function for link_ref qsort */
static int cmp_link_ref_sort(const void *a, const void *b){
struct link_ref *lra = (void *)a;
struct link_ref *lrb = (void *)b;
return blob_compare(&lra->id, &lrb->id);
}
/*
** cmp_footnote_id -- comparison function for footnotes qsort.
** Empty IDs sort last (in undetermined order).
** Equal IDs are sorted in the order of definition in the source.
*/
static int cmp_footnote_id(const void *fna, const void *fnb){
const struct footnote *a = fna, *b = fnb;
const int szA = blob_size(&a->id), szB = blob_size(&b->id);
if( szA ){
if( szB ){
int cmp = blob_compare(&a->id, &b->id);
if( cmp ) return cmp;
}else return -1;
}else return szB ? 1 : 0;
/* IDs are equal and non-empty */
if( a->defno < b->defno ) return -1;
if( a->defno > b->defno ) return 1;
assert(!"reachable");
return 0; /* should never reach here */
}
/*
** cmp_footnote_sort -- comparison function for footnotes qsort.
** Unreferenced footnotes (when nUsed == 0) sort last and
** are sorted in the order of definition in the source.
*/
static int cmp_footnote_sort(const void *fna, const void *fnb){
const struct footnote *a = fna, *b = fnb;
int i, j;
assert( a->nUsed >= 0 );
assert( b->nUsed >= 0 );
assert( a->defno >= 0 );
assert( b->defno >= 0 );
if( a->nUsed ){
assert( a->iMark > 0 );
if( !b->nUsed ) return -1;
assert( b->iMark > 0 );
i = a->iMark;
j = b->iMark;
}else{
if( b->nUsed ) return 1;
i = a->defno;
j = b->defno;
}
if( i < j ) return -1;
if( i > j ) return 1;
return 0;
}
/* cmp_html_tag -- comparison function for bsearch() (stolen from discount) */
static int cmp_html_tag(const void *a, const void *b){
const struct html_tag *hta = a;
const struct html_tag *htb = b;
int sz = hta->size;
int c;
|
| ︙ | ︙ | |||
577 578 579 580 581 582 583 | if( fossil_isspace(before) ) return 0; if( fossil_isalnum(before) ) return 1; if( fossil_isalnum(after) ) return 0; return 1; } | > | | > | 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 |
if( fossil_isspace(before) ) return 0;
if( fossil_isalnum(before) ) return 1;
if( fossil_isalnum(after) ) return 0;
return 1;
}
/*
** parse_emph1 -- parsing single emphasis.
** closed by a symbol not preceded by whitespace and not followed by symbol.
*/
static size_t parse_emph1(
struct Blob *ob,
struct render *rndr,
char *data,
size_t size,
char c
){
|
| ︙ | ︙ | |||
622 623 624 625 626 627 628 |
release_work_buffer(rndr, work);
return r ? i+1 : 0;
}
}
return 0;
}
| | | > | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 |
release_work_buffer(rndr, work);
return r ? i+1 : 0;
}
}
return 0;
}
/*
** parse_emph2 -- parsing single emphasis.
*/
static size_t parse_emph2(
struct Blob *ob,
struct render *rndr,
char *data,
size_t size,
char c
){
|
| ︙ | ︙ | |||
661 662 663 664 665 666 667 |
return r ? i+2 : 0;
}
i++;
}
return 0;
}
| | | | > | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 |
return r ? i+2 : 0;
}
i++;
}
return 0;
}
/*
** parse_emph3 -- parsing single emphasis.
** finds the first closing tag, and delegates to the other emph.
*/
static size_t parse_emph3(
struct Blob *ob,
struct render *rndr,
char *data,
size_t size,
char c
){
|
| ︙ | ︙ | |||
709 710 711 712 713 714 715 |
len = parse_emph2(ob, rndr, data-1, size+1, c);
return len ? len-1 : 0;
}
}
return 0;
}
| | | > | 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 |
len = parse_emph2(ob, rndr, data-1, size+1, c);
return len ? len-1 : 0;
}
}
return 0;
}
/*
** char_emphasis -- single and double emphasis parsing.
*/
static size_t char_emphasis(
struct Blob *ob,
struct render *rndr,
char *data,
size_t offset,
size_t size
){
|
| ︙ | ︙ | |||
754 755 756 757 758 759 760 |
return 0;
}
return ret+3;
}
return 0;
}
| | | > | | > | 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 |
return 0;
}
return ret+3;
}
return 0;
}
/*
** char_linebreak -- '\n' preceded by two spaces (assuming linebreak != 0).
*/
static size_t char_linebreak(
struct Blob *ob,
struct render *rndr,
char *data,
size_t offset,
size_t size
){
if( offset<2 || data[-1]!=' ' || data[-2]!=' ' ) return 0;
/* removing the last space from ob and rendering */
if( blob_size(ob)>0 && blob_buffer(ob)[blob_size(ob)-1]==' ' ) ob->nUsed--;
return rndr->make.linebreak(ob, rndr->make.opaque) ? 1 : 0;
}
/*
** char_codespan -- '`' parsing a code span (assuming codespan != 0).
*/
static size_t char_codespan(
struct Blob *ob,
struct render *rndr,
char *data,
size_t offset,
size_t size
){
|
| ︙ | ︙ | |||
811 812 813 814 815 816 817 |
}else{
if( !rndr->make.codespan(ob, 0, nb, rndr->make.opaque) ) end = 0;
}
return end;
}
| > | > | | | > | 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 |
}else{
if( !rndr->make.codespan(ob, 0, nb, rndr->make.opaque) ) end = 0;
}
return end;
}
/*
** char_escape -- '\\' backslash escape.
*/
static size_t char_escape(
struct Blob *ob,
struct render *rndr,
char *data,
size_t offset,
size_t size
){
struct Blob work = BLOB_INITIALIZER;
if( size>1 ){
if( rndr->make.normal_text ){
blob_init(&work, data+1,1);
rndr->make.normal_text(ob, &work, rndr->make.opaque);
}else{
blob_append(ob, data+1, 1);
}
}
return 2;
}
/*
** char_entity -- '&' escaped when it doesn't belong to an entity.
** valid entities are assumed to be anything matching &#?[A-Za-z0-9]+;
*/
static size_t char_entity(
struct Blob *ob,
struct render *rndr,
char *data,
size_t offset,
size_t size
){
|
| ︙ | ︙ | |||
867 868 869 870 871 872 873 |
rndr->make.entity(ob, &work, rndr->make.opaque);
}else{
blob_append(ob, data, end);
}
return end;
}
| | | > | 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 |
rndr->make.entity(ob, &work, rndr->make.opaque);
}else{
blob_append(ob, data, end);
}
return end;
}
/*
** char_langle_tag -- '<' when tags or autolinks are allowed.
*/
static size_t char_langle_tag(
struct Blob *ob,
struct render *rndr,
char *data,
size_t offset,
size_t size
){
|
| ︙ | ︙ | |||
897 898 899 900 901 902 903 |
if( !ret ){
return 0;
}else{
return end;
}
}
| | | | 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 |
if( !ret ){
return 0;
}else{
return end;
}
}
/*
** get_link_inline -- extract inline-style link and title from
** parenthesed data
*/
static int get_link_inline(
struct Blob *link,
struct Blob *title,
char *data,
size_t size
|
| ︙ | ︙ | |||
952 953 954 955 956 957 958 |
|| data[link_e-1]=='\n')
){
link_e--;
}
/* remove optional angle brackets around the link */
if( data[link_b]=='<' ) link_b += 1;
| | > | > > | | > > > > | > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | > | < < < < < < < < | | < < < < < < < < < < > | | | > | > > | | > | > > | > > | | < | < > > > > > > > > | > > > > | | | | | | > | < | | | | | | | | | | > > > | | > > | | | < | < | | | | | < | | | | | | > > > > > > > < | 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 |
|| data[link_e-1]=='\n')
){
link_e--;
}
/* remove optional angle brackets around the link */
if( data[link_b]=='<' ) link_b += 1;
if( link_e && data[link_e-1]=='>' ) link_e -= 1;
/* escape backslashed character from link */
blob_reset(link);
i = link_b;
while( i<link_e ){
mark = i;
while( i<link_e && data[i]!='\\' ){ i++; }
blob_append(link, data+mark, i-mark);
while( i<link_e && data[i]=='\\' ){ i++; }
}
/* handing back title */
blob_reset(title);
if( title_e>title_b ) blob_append(title, data+title_b, title_e-title_b);
/* this function always succeed */
return 0;
}
/*
** get_link_ref -- extract referenced link and title from id.
*/
static int get_link_ref(
struct render *rndr,
struct Blob *link,
struct Blob *title,
char *data,
size_t size
){
struct link_ref *lr;
const size_t sz = blob_size(&rndr->refs);
/* find the link from its id (stored temporarily in link) */
blob_reset(link);
if( !sz || build_ref_id(link, data, size)<0 ) return -1;
lr = bsearch(link,
blob_buffer(&rndr->refs),
sz/sizeof(struct link_ref),
sizeof (struct link_ref),
cmp_link_ref);
if( !lr ) return -1;
/* fill the output buffers */
blob_reset(link);
blob_reset(title);
blob_appendb(link, &lr->link);
blob_appendb(title, &lr->title);
return 0;
}
/*
** get_footnote() -- find a footnote by label, invoked during the 2nd pass.
** If found then return a shallow copy of the corresponding footnote;
** otherwise return a shallow copy of rndr->notes.misref.
** In both cases corresponding `nUsed` field is incremented before return.
*/
static struct footnote get_footnote(
struct render *rndr,
const char *data,
size_t size
){
struct footnote *fn = 0;
struct Blob *id;
if( !rndr->notes.nLbled ) goto fallback;
id = new_work_buffer(rndr);
if( build_ref_id(id, data, size)<0 ) goto cleanup;
fn = bsearch(id, blob_buffer(&rndr->notes.all),
rndr->notes.nLbled,
sizeof (struct footnote),
cmp_link_ref);
if( !fn ) goto cleanup;
if( fn->nUsed == 0 ){ /* the first reference to the footnote */
assert( fn->iMark == 0 );
fn->iMark = ++(rndr->notes.nMarks);
}
assert( fn->iMark > 0 );
cleanup:
release_work_buffer( rndr, id );
fallback:
if( !fn ) fn = &rndr->notes.misref;
fn->nUsed++;
assert( fn->nUsed > 0 );
return *fn;
}
/*
** Counts characters in the blank prefix within at most nHalfLines.
** A sequence of spaces and tabs counts as odd halfline,
** a newline counts as even halfline.
** If nHalfLines < 0 then proceed without constraints.
*/
static inline size_t sizeof_blank_prefix(
const char *data, size_t size, int nHalfLines
){
const char *p = data;
const char * const end = data+size;
if( nHalfLines < 0 ){
while( p!=end && fossil_isspace(*p) ){
p++;
}
}else while( nHalfLines > 0 ){
while( p!=end && (*p==' ' || *p=='\t' ) ){ p++; }
if( p==end || --nHalfLines == 0 ) break;
if( *p=='\n' || *p=='\r' ){
p++;
if( p==end ) break;
if( *p=='\n' && p[-1]=='\r' ){
p++;
}
}
nHalfLines--;
}
return p-data;
}
/*
** Check if the data starts with a classlist token of the special form.
** If so then return the length of that token, otherwise return 0.
**
** The token must start with a dot and must end with a colon;
** in between of these it must be a dot-separated list of words;
** each word may contain only alphanumeric characters and hyphens.
**
** If `bBlank` is non-zero then a blank character must follow
** the token's ending colon: otherwise function returns 0
** despite the well-formed token.
*/
static size_t is_footnote_classlist(const char * const data, size_t size,
int bBlank){
const char *p;
const char * const end = data+size;
if( data==end || *data != '.' ) return 0;
for(p=data+1; p!=end; p++){
if( fossil_isalnum(*p) || *p=='-' ) continue;
if( p[-1]=='.' ) break;
if( *p==':' ){
p++;
if( bBlank ){
if( p==end || !fossil_isspace(*p) ) break;
}
return p-data;
}
if( *p!='.' ) break;
}
return 0;
}
/*
** Adds unlabeled footnote to the rndr->notes.all.
** On success puts a shallow copy of the constructed footnote into pFN
** and returns 1, otherwise pFN is unchanged and 0 is returned.
*/
static inline int add_inline_footnote(
struct render *rndr,
const char *text,
size_t size,
struct footnote* pFN
){
struct footnote fn = FOOTNOTE_INITIALIZER, *last;
const char *zUPC = 0;
size_t nUPC = 0, n = sizeof_blank_prefix(text, size, 3);
if( n >= size ) return 0;
text += n;
size -= n;
nUPC = is_footnote_classlist(text, size, 1);
if( nUPC ){
assert( nUPC<size );
zUPC = text;
text += nUPC;
size -= nUPC;
}
if( sizeof_blank_prefix(text,size,-1)==size ){
if( !nUPC ) return 0; /* empty inline footnote */
text = zUPC;
size = nUPC; /* bare classlist is treated */
nUPC = 0; /* as plain text */
}
fn.iMark = ++(rndr->notes.nMarks);
fn.nUsed = 1;
fn.index = COUNT_FOOTNOTES(&rndr->notes.all);
assert( fn.iMark > 0 );
blob_append(&fn.text, text, size);
if(nUPC) blob_append(&fn.upc, zUPC, nUPC);
blob_append(&rndr->notes.all, (char *)&fn, sizeof fn);
last = (struct footnote*)( blob_buffer(&rndr->notes.all)
+( blob_size(&rndr->notes.all)-sizeof fn ));
assert( pFN );
memcpy( pFN, last, sizeof fn );
return 1;
}
/*
** Return the byte offset of the matching closing bracket or 0 if not
** found. begin[0] must be either '[' or '('.
**
** TODO: It seems that things like "\\(" are not handled correctly.
** That is historical behavior for a corner-case,
** so it's left as it is until somebody complains.
*/
static inline size_t matching_bracket_offset(
const char* begin,
const char* end
){
const char *i;
int level;
const char bra = *begin;
const char ket = bra=='[' ? ']' : ')';
assert( bra=='[' || bra=='(' );
for(i=begin+1,level=1; i!=end; i++){
if( *i=='\n' ) /* do nothing */;
else if( i[-1]=='\\' ) continue;
else if( *i==bra ) level++;
else if( *i==ket ){
if( --level<=0 ) return i-begin;
}
}
return 0;
}
/*
** char_footnote -- '(': parsing a standalone inline footnote.
*/
static size_t char_footnote(
struct Blob *ob,
struct render *rndr,
char *data,
size_t offset,
size_t size
){
size_t end;
struct footnote fn;
if( size<4 || data[1]!='^' ) return 0;
end = matching_bracket_offset(data, data+size);
if( !end ) return 0;
if( !add_inline_footnote(rndr, data+2, end-2, &fn) ) return 0;
if( rndr->make.footnote_ref ){
rndr->make.footnote_ref(ob,0,&fn.upc,fn.iMark,1,rndr->make.opaque);
}
return end+1;
}
/*
** char_link -- '[': parsing a link or an image.
*/
static size_t char_link(
struct Blob *ob,
struct render *rndr,
char *data,
size_t offset,
size_t size /* parse_inline() ensures that size > 0 */
){
const int is_img = (offset && data[-1] == '!');
size_t i = 1, txt_e;
struct Blob *content = 0;
struct Blob *link = 0;
struct Blob *title = 0;
struct footnote fn;
int ret;
/* checking whether the correct renderer exists */
if( (is_img && !rndr->make.image) || (!is_img && !rndr->make.link) ){
return 0;
}
/* looking for the matching closing bracket */
txt_e = matching_bracket_offset(data, data+size);
if( !txt_e ) return 0;
i = txt_e + 1;
ret = 0; /* error if we don't get to the callback */
fn.nUsed = 0;
/* free-standing footnote refernece */
if(!is_img && size>3 && data[1]=='^'){
fn = get_footnote(rndr, data+2, txt_e-2);
}else{
/* skip "inter-bracket-whitespace" - any amount of whitespace or newline */
/* (this is much more lax than original markdown syntax) */
while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; }
/* allocate temporary buffers to store content, link and title */
title = new_work_buffer(rndr);
content = new_work_buffer(rndr);
link = new_work_buffer(rndr);
if( i<size && data[i]=='(' ){
if( i+2<size && data[i+1]=='^' ){ /* span-bounded inline footnote */
const size_t k = matching_bracket_offset(data+i, data+size);
if( !k ) goto char_link_cleanup;
add_inline_footnote(rndr, data+(i+2), k-2, &fn);
i += k+1;
}else{ /* inline style link */
size_t span_end = i;
while( span_end<size
&& !(data[span_end]==')'
&& (span_end==i || data[span_end-1]!='\\')) ){
span_end++;
}
if( span_end>=size
|| get_link_inline(link, title, data+i+1, span_end-(i+1))<0 ){
goto char_link_cleanup;
}
i = span_end+1;
}
/* reference style link or span-bounded footnote reference */
}else if( i<size && data[i]=='[' ){
char *id_data;
size_t id_size, id_end = i;
int bFootnote;
while( id_end<size && data[id_end]!=']' ){ id_end++; }
if( id_end>=size ) goto char_link_cleanup;
bFootnote = data[i+1]=='^';
if( i+1==id_end || (bFootnote && i+2==id_end) ){
/* implicit id - use the contents */
id_data = data+1;
id_size = txt_e-1;
}else{
/* explicit id - between brackets */
id_data = data+i+1;
id_size = id_end-(i+1);
if( bFootnote ){
id_data++;
id_size--;
}
}
if( bFootnote ){
fn = get_footnote(rndr, id_data, id_size);
}else if( get_link_ref(rndr, link, title, id_data, id_size)<0 ){
goto char_link_cleanup;
}
i = id_end+1;
/* shortcut reference style link */
}else{
if( get_link_ref(rndr, link, title, data+1, txt_e-1)<0 ){
goto char_link_cleanup;
}
/* rewinding an "inter-bracket-whitespace" */
i = txt_e+1;
}
}
/* building content: img alt is escaped, link content is parsed */
if( txt_e>1 && content ){
if( is_img ) blob_append(content, data+1, txt_e-1);
else parse_inline(content, rndr, data+1, txt_e-1);
}
/* calling the relevant rendering function */
if( is_img ){
if( blob_size(ob)>0 && blob_buffer(ob)[blob_size(ob)-1]=='!' ){
ob->nUsed--;
}
ret = rndr->make.image(ob, link, title, content, rndr->make.opaque);
}else if( fn.nUsed ){
if( rndr->make.footnote_ref ){
ret = rndr->make.footnote_ref(ob, content, &fn.upc, fn.iMark,
fn.nUsed, rndr->make.opaque);
}
}else{
ret = rndr->make.link(ob, link, title, content, rndr->make.opaque);
}
/* cleanup */
char_link_cleanup:
release_work_buffer(rndr, title);
release_work_buffer(rndr, link);
release_work_buffer(rndr, content);
return ret ? i : 0;
}
/*********************************
* BLOCK-LEVEL PARSING FUNCTIONS *
*********************************/
/* is_empty -- returns the line length when it is empty, 0 otherwise */
|
| ︙ | ︙ | |||
1804 1805 1806 1807 1808 1809 1810 |
if( !found ) return 0;
/* the end of the block has been found */
if( strcmp(curtag->text,"html")==0 ){
/* Omit <html> tags */
enum mkd_autolink dummy;
int k = tag_length(data, size, &dummy);
| > | | 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 |
if( !found ) return 0;
/* the end of the block has been found */
if( strcmp(curtag->text,"html")==0 ){
/* Omit <html> tags */
enum mkd_autolink dummy;
int k = tag_length(data, size, &dummy);
int sz = i - (j+k);
if( sz>0 ) blob_init(&work, data+k, sz);
}else{
blob_init(&work, data, i);
}
if( rndr->make.blockhtml ){
rndr->make.blockhtml(ob, &work, rndr->make.opaque);
}
return i;
|
| ︙ | ︙ | |||
2011 2012 2013 2014 2015 2016 2017 |
struct Blob *ob, /* output blob */
struct render *rndr, /* renderer internal state */
char *data, /* input text */
size_t size /* input text size */
){
size_t beg, end, i;
char *txt_data;
| > > | | 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 |
struct Blob *ob, /* output blob */
struct render *rndr, /* renderer internal state */
char *data, /* input text */
size_t size /* input text size */
){
size_t beg, end, i;
char *txt_data;
int has_table;
if( !size ) return;
has_table = (rndr->make.table
&& rndr->make.table_row
&& rndr->make.table_cell
&& memchr(data, '|', size)!=0);
beg = 0;
while( beg<size ){
txt_data = data+beg;
|
| ︙ | ︙ | |||
2061 2062 2063 2064 2065 2066 2067 | /********************* * REFERENCE PARSING * *********************/ /* is_ref -- returns whether a line is a reference or not */ static int is_ref( | | | 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 |
/*********************
* REFERENCE PARSING *
*********************/
/* is_ref -- returns whether a line is a reference or not */
static int is_ref(
const char *data, /* input text */
size_t beg, /* offset of the beginning of the line */
size_t end, /* offset of the end of the text */
size_t *last, /* last character of the link */
struct Blob *refs /* array of link references */
){
size_t i = 0;
size_t id_offset, id_end;
|
| ︙ | ︙ | |||
2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 |
}
}
i += beg;
/* id part: anything but a newline between brackets */
if( data[i]!='[' ) return 0;
i++;
id_offset = i;
while( i<end && data[i]!='\n' && data[i]!='\r' && data[i]!=']' ){ i++; }
if( i>=end || data[i]!=']' ) return 0;
id_end = i;
/* spacer: colon (space | tab)* newline? (space | tab)* */
i++;
| > > | 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 |
}
}
i += beg;
/* id part: anything but a newline between brackets */
if( data[i]!='[' ) return 0;
i++;
if( i>=end || data[i]=='^' ) return 0; /* see is_footnote() */
id_offset = i;
while( i<end && data[i]!='\n' && data[i]!='\r' && data[i]!=']' ){ i++; }
if( i>=end || data[i]!=']' ) return 0;
id_end = i;
/* spacer: colon (space | tab)* newline? (space | tab)* */
i++;
|
| ︙ | ︙ | |||
2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 |
&& data[i]!=' '
&& data[i]!='\t'
&& data[i]!='\n'
&& data[i]!='\r'
){
i += 1;
}
if( data[i-1]=='>' ) link_end = i-1; else link_end = i;
/* optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) */
while( i<end && (data[i]==' ' || data[i]=='\t') ){ i++; }
if( i<end
&& data[i]!='\n'
&& data[i]!='\r'
| > | 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 |
&& data[i]!=' '
&& data[i]!='\t'
&& data[i]!='\n'
&& data[i]!='\r'
){
i += 1;
}
/* TODO: maybe require both data[i-1]=='>' && data[link_offset-1]=='<' ? */
if( data[i-1]=='>' ) link_end = i-1; else link_end = i;
/* optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) */
while( i<end && (data[i]==' ' || data[i]=='\t') ){ i++; }
if( i<end
&& data[i]!='\n'
&& data[i]!='\r'
|
| ︙ | ︙ | |||
2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 |
if( title_end>title_offset ){
blob_append(&lr.title, data+title_offset, title_end-title_offset);
}
blob_append(refs, (char *)&lr, sizeof lr);
return 1;
}
/**********************
* EXPORTED FUNCTIONS *
**********************/
/* markdown -- parses the input buffer and renders it into the output buffer */
void markdown(
struct Blob *ob, /* output blob for rendered text */
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > < > | > | > > > > > > > > > > > | > | < | > > | | | | < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 |
if( title_end>title_offset ){
blob_append(&lr.title, data+title_offset, title_end-title_offset);
}
blob_append(refs, (char *)&lr, sizeof lr);
return 1;
}
/*********************
* FOOTNOTE PARSING *
*********************/
/* is_footnote -- check if data holds a definition of a labeled footnote.
* If so then append the corresponding element to `footnotes` array */
static int is_footnote(
const char *data, /* input text */
size_t beg, /* offset of the beginning of the line */
size_t end, /* offset of the end of the text */
size_t *last, /* last character of the link */
struct Blob * footnotes
){
size_t i, id_offset, id_end, upc_offset, upc_size;
struct footnote fn = FOOTNOTE_INITIALIZER;
/* failfast if data is too short */
if( beg+5>=end ) return 0;
i = beg;
/* footnote definition must start at the begining of a line */
if( data[i]!='[' ) return 0;
i++;
if( data[i]!='^' ) return 0;
id_offset = ++i;
/* id part: anything but a newline between brackets */
while( i<end && data[i]!=']' && data[i]!='\n' && data[i]!='\r' ){ i++; }
if( i>=end || data[i]!=']' ) return 0;
id_end = i++;
/* spacer: colon (space | tab)* */
if( i>=end || data[i]!=':' ) return 0;
i++;
while( i<end && (data[i]==' ' || data[i]=='\t') ){ i++; }
/* passthrough truncated footnote definition */
if( i>=end ) return 0;
if( build_ref_id(&fn.id, data+id_offset, id_end-id_offset)<0 ) return 0;
/* footnote's text may start on the same line after [^id]: */
upc_offset = upc_size = 0;
if( data[i]!='\n' && data[i]!='\r' ){
size_t j;
upc_size = is_footnote_classlist(data+i, end-i, 1);
upc_offset = i; /* prevent further checks for a classlist */
i += upc_size;
j = i;
while( i<end && data[i]!='\n' && data[i]!='\r' ){ i++; };
if( i!=j )blob_append(&fn.text, data+j, i-j);
if( i<end ){
blob_append_char(&fn.text, data[i]);
i++;
if( i<end && data[i]=='\n' && data[i-1]=='\r' ){
blob_append_char(&fn.text, data[i]);
i++;
}
}
}else{
i++;
if( i<end && data[i]=='\n' && data[i-1]=='\r' ) i++;
}
if( i<end ){
/* compute the indentation from the 2nd line */
size_t indent = i;
const char *spaces = data+i;
while( indent<end && data[indent]==' ' ){ indent++; }
if( indent>=end ) goto footnote_finish;
indent -= i;
if( indent<2 ) goto footnote_finish;
/* process the 2nd and subsequent lines */
while( i+indent<end && memcmp(data+i,spaces,indent)==0 ){
size_t j;
i += indent;
if( !upc_offset ){
/* a classlist must be provided no later than at the 2nd line */
upc_offset = i + sizeof_blank_prefix(data+i, end-i, 1);
upc_size = is_footnote_classlist(data+upc_offset,
end-upc_offset, 1);
if( upc_size ){
i = upc_offset + upc_size;
}
}
j = i;
while( i<end && data[i]!='\n' && data[i]!='\r' ){ i++; }
if( i!=j ) blob_append(&fn.text, data+j, i-j);
if( i>=end ) break;
blob_append_char(&fn.text, data[i]);
i++;
if( i<end && data[i]=='\n' && data[i-1]=='\r' ){
blob_append_char(&fn.text, data[i]);
i++;
}
}
}
footnote_finish:
if( !blob_size(&fn.text) ){
blob_reset(&fn.id);
return 0;
}
if( !blob_trim(&fn.text) ){ /* if the content is all-blank */
if( upc_size ){ /* interpret UPC as plain text */
blob_append(&fn.text, data+upc_offset, upc_size);
upc_size = 0;
}else{
blob_reset(&fn.id); /* or clean up and fail */
blob_reset(&fn.text);
return 0;
}
}
/* a valid note has been found */
if( last ) *last = i;
if( footnotes ){
fn.defno = COUNT_FOOTNOTES( footnotes );
if( upc_size ){
assert( upc_offset && upc_offset+upc_size<end );
blob_append(&fn.upc, data+upc_offset, upc_size);
}
blob_append(footnotes, (char *)&fn, sizeof fn);
}
return 1;
}
/**********************
* EXPORTED FUNCTIONS *
**********************/
/* markdown -- parses the input buffer and renders it into the output buffer */
void markdown(
struct Blob *ob, /* output blob for rendered text */
const struct Blob *ib, /* input blob in markdown */
const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */
){
struct link_ref *lr;
struct footnote *fn;
size_t i, beg, end = 0;
struct render rndr;
size_t size;
Blob text = BLOB_INITIALIZER; /* input after the first pass */
Blob * const allNotes = &rndr.notes.all;
/* filling the render structure */
if( !rndrer ) return;
rndr.make = *rndrer;
rndr.nBlobCache = 0;
rndr.iDepth = 0;
rndr.refs = empty_blob;
rndr.notes.all = empty_blob;
rndr.notes.nMarks = 0;
rndr.notes.misref.id = empty_blob;
rndr.notes.misref.text = empty_blob;
rndr.notes.misref.upc = empty_blob;
rndr.notes.misref.bRndred = 0;
rndr.notes.misref.nUsed = 0;
rndr.notes.misref.iMark = -1;
for(i=0; i<256; i++) rndr.active_char[i] = 0;
if( (rndr.make.emphasis
|| rndr.make.double_emphasis
|| rndr.make.triple_emphasis)
&& rndr.make.emph_chars
){
for(i=0; rndr.make.emph_chars[i]; i++){
rndr.active_char[(unsigned char)rndr.make.emph_chars[i]] = char_emphasis;
}
}
if( rndr.make.codespan ) rndr.active_char['`'] = char_codespan;
if( rndr.make.linebreak ) rndr.active_char['\n'] = char_linebreak;
if( rndr.make.image || rndr.make.link ) rndr.active_char['['] = char_link;
if( rndr.make.footnote_ref ) rndr.active_char['('] = char_footnote;
rndr.active_char['<'] = char_langle_tag;
rndr.active_char['\\'] = char_escape;
rndr.active_char['&'] = char_entity;
/* first pass: iterate over lines looking for references,
* copying everything else into "text" */
beg = 0;
for(size = blob_size(ib); beg<size ;){
const char* const data = blob_buffer(ib);
if( is_ref(data, beg, size, &end, &rndr.refs) ){
beg = end;
}else if(is_footnote(data, beg, size, &end, &rndr.notes.all)){
beg = end;
}else{ /* skipping to the next line */
end = beg;
while( end<size && data[end]!='\n' && data[end]!='\r' ){
end += 1;
}
/* adding the line body if present */
if( end>beg ) blob_append(&text, data + beg, end - beg);
while( end<size && (data[end]=='\n' || data[end]=='\r') ){
/* add one \n per newline */
if( data[end]=='\n' || (end+1<size && data[end+1]!='\n') ){
blob_append_char(&text, '\n');
}
end += 1;
}
beg = end;
}
}
/* sorting the reference array */
if( blob_size(&rndr.refs) ){
qsort(blob_buffer(&rndr.refs),
blob_size(&rndr.refs)/sizeof(struct link_ref),
sizeof(struct link_ref),
cmp_link_ref_sort);
}
rndr.notes.nLbled = COUNT_FOOTNOTES( allNotes );
/* sort footnotes by ID and join duplicates */
if( rndr.notes.nLbled > 1 ){
int nDups = 0;
fn = CAST_AS_FOOTNOTES( allNotes );
qsort(fn, rndr.notes.nLbled, sizeof(struct footnote), cmp_footnote_id);
/* concatenate footnotes with equal labels */
for(i=0; i<rndr.notes.nLbled ;){
struct footnote *x = fn + i;
size_t j = i+1, k = blob_size(&x->text) + 64 + blob_size(&x->upc);
while(j<rndr.notes.nLbled && !blob_compare(&x->id, &fn[j].id)){
k += blob_size(&fn[j].text) + 10 + blob_size(&fn[j].upc);
j++;
nDups++;
}
if( i+1<j ){
Blob list = empty_blob;
blob_reserve(&list, k);
/* must match _joined_footnote_indicator in html_footnote_item() */
blob_append_literal(&list, "<ul class='fn-joined'>\n");
for(k=i; k<j; k++){
struct footnote *y = fn + k;
blob_append_literal(&list, "<li>");
if( blob_size(&y->upc) ){
blob_appendb(&list, &y->upc);
blob_reset(&y->upc);
}
blob_appendb(&list, &y->text);
blob_append_literal(&list, "</li>\n");
/* free memory buffer */
blob_reset(&y->text);
if( k!=i ) blob_reset(&y->id);
}
blob_append_literal(&list, "</ul>\n");
x->text = list;
g.ftntsIssues[2]++;
}
i = j;
}
if( nDups ){ /* clean rndr.notes.all from invalidated footnotes */
const int n = rndr.notes.nLbled - nDups;
struct Blob filtered = empty_blob;
blob_reserve(&filtered, n*sizeof(struct footnote));
for(i=0; i<rndr.notes.nLbled; i++){
if( blob_size(&fn[i].id) ){
blob_append(&filtered, (char*)(fn+i), sizeof(struct footnote));
}
}
blob_reset( allNotes );
rndr.notes.all = filtered;
rndr.notes.nLbled = n;
assert( COUNT_FOOTNOTES(allNotes) == rndr.notes.nLbled );
}
}
fn = CAST_AS_FOOTNOTES( allNotes );
for(i=0; i<rndr.notes.nLbled; i++){
fn[i].index = i;
}
assert( rndr.notes.nMarks==0 );
/* second pass: actual rendering */
if( rndr.make.prolog ) rndr.make.prolog(ob, rndr.make.opaque);
parse_block(ob, &rndr, blob_buffer(&text), blob_size(&text));
if( blob_size(allNotes) || rndr.notes.misref.nUsed ){
/* Footnotes must be parsed for the correct discovery of (back)links */
Blob *notes = new_work_buffer( &rndr );
if( blob_size(allNotes) ){
Blob *tmp = new_work_buffer( &rndr );
int nMarks = -1, maxDepth = 5;
/* inline notes may get appended to rndr.notes.all while rendering */
while(1){
struct footnote *aNotes;
const int N = COUNT_FOOTNOTES( allNotes );
/* make a shallow copy of `allNotes` */
blob_truncate(notes,0);
blob_appendb(notes, allNotes);
aNotes = CAST_AS_FOOTNOTES(notes);
qsort(aNotes, N, sizeof(struct footnote), cmp_footnote_sort);
if( --maxDepth < 0 || nMarks == rndr.notes.nMarks ) break;
nMarks = rndr.notes.nMarks;
for(i=0; i<N; i++){
const int j = aNotes[i].index;
struct footnote *x = CAST_AS_FOOTNOTES(allNotes) + j;
assert( 0<=j && j<N );
if( x->bRndred || !x->nUsed ) continue;
assert( x->iMark > 0 );
assert( blob_size(&x->text) );
blob_truncate(tmp,0);
/* `allNotes` may be altered and extended through this call */
parse_inline(tmp, &rndr, blob_buffer(&x->text), blob_size(&x->text));
x = CAST_AS_FOOTNOTES(allNotes) + j;
blob_truncate(&x->text,0);
blob_appendb(&x->text, tmp);
x->bRndred = 1;
}
}
release_work_buffer(&rndr,tmp);
}
/* footnotes rendering */
if( rndr.make.footnote_item && rndr.make.footnotes ){
Blob *all_items = new_work_buffer(&rndr);
int j = -1;
/* Assert that the in-memory layout of id, text and upc within
** footnote struct matches the expectations of html_footnote_item()
** If it doesn't then a compiler has done something very weird.
*/
assert( &(rndr.notes.misref.id) == &(rndr.notes.misref.text) - 1 );
assert( &(rndr.notes.misref.upc) == &(rndr.notes.misref.text) + 1 );
for(i=0; i<COUNT_FOOTNOTES(notes); i++){
const struct footnote* x = CAST_AS_FOOTNOTES(notes) + i;
const int xUsed = x->bRndred ? x->nUsed : 0;
if( !x->iMark ) break;
assert( x->nUsed );
rndr.make.footnote_item(all_items, &x->text, x->iMark,
xUsed, rndr.make.opaque);
if( !xUsed ) g.ftntsIssues[3]++; /* an overnested footnote */
j = i;
}
if( rndr.notes.misref.nUsed ){
rndr.make.footnote_item(all_items, 0, -1,
rndr.notes.misref.nUsed, rndr.make.opaque);
g.ftntsIssues[0] += rndr.notes.misref.nUsed;
}
while( ++j < COUNT_FOOTNOTES(notes) ){
const struct footnote* x = CAST_AS_FOOTNOTES(notes) + j;
assert( !x->iMark );
assert( !x->nUsed );
assert( !x->bRndred );
rndr.make.footnote_item(all_items,&x->text,0,0,rndr.make.opaque);
g.ftntsIssues[1]++;
}
rndr.make.footnotes(ob, all_items, rndr.make.opaque);
release_work_buffer(&rndr, all_items);
}
release_work_buffer(&rndr, notes);
}
if( rndr.make.epilog ) rndr.make.epilog(ob, rndr.make.opaque);
/* clean-up */
assert( rndr.iDepth==0 );
blob_reset(&text);
lr = (struct link_ref *)blob_buffer(&rndr.refs);
end = blob_size(&rndr.refs)/sizeof(struct link_ref);
for(i=0; i<end; i++){
blob_reset(&lr[i].id);
blob_reset(&lr[i].link);
blob_reset(&lr[i].title);
}
blob_reset(&rndr.refs);
fn = CAST_AS_FOOTNOTES( allNotes );
end = COUNT_FOOTNOTES( allNotes );
for(i=0; i<end; i++){
if(blob_size(&fn[i].id)) blob_reset(&fn[i].id);
if(blob_size(&fn[i].upc)) blob_reset(&fn[i].upc);
blob_reset(&fn[i].text);
}
blob_reset(&rndr.notes.all);
for(i=0; i<rndr.nBlobCache; i++){
fossil_free(rndr.aBlobCache[i]);
}
}
|
Changes to src/markdown.md.
| ︙ | ︙ | |||
150 151 152 153 154 155 156 157 158 159 | > Formatted using [Pikchr](https://pikchr.org/home), resulting in: > ~~~ pikchr oval "Start" fit; arrow; box "Hello, World!" fit; arrow; oval "Done" fit ~~~ ## Miscellaneous ## > * In-line images are made using **\!\[alt-text\]\(image-URL\)**. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
> Formatted using [Pikchr](https://pikchr.org/home), resulting in:
>
~~~ pikchr
oval "Start" fit; arrow; box "Hello, World!" fit; arrow; oval "Done" fit
~~~
<a id="ftnts"></a>
## Footnotes ##
> Footnotes (or "endnotes") is a Fossil's extention of classical Markdown.
> Fossil's syntax for footnotes is similar to links and
> is distinguished by the use of character **^**
> that *immediately* follows an opening bracket.
> 1. **\(^** footnote's text **)**
> 2. **\[** fragment of text **]\(^** a comment about that fragment **\)**
> 3. **\[^** label **\]**
> 4. **\[** fragment of text **\]\[^** label **\]**
> 5. **\[** fragment of text **\]\[^\]**
> With formats 1 and 2 ("inline footnotes") text of a footnote is provided
> in the place where the corresponding numeric mark will be rendered.
> With formats 3, 4, and 5 ("reference footnotes") text of a footnote
> is supplied elsewhere in the document, as shown below.
> Formats 2, 4 and 5 ("span-specific footnotes") mark a specific fragment
> that is being commented in the footnote.
> Format 5 reuses a fragment of text as a label.
> Labels are case-insensitive.
> ```
> [^label]: Footnote definition must start on the first column.
> The second line (if any) must be indented by two or more spaces.
> Definition continues until indentation drops below that of the 2nd line.
>```
> Character **^** is not part of a label, it is part of the syntax.
> Both a footnote's text and a fragment to which a footnote applies
> are subject to further interpretation as Markdown sources.
## Miscellaneous ##
> * In-line images are made using **\!\[alt-text\]\(image-URL\)**.
> * Use HTML for advanced formatting such as forms, noting that certain
> tags are [disallowed in some contexts](/help?cmd=safe-html).
> * **\<!--** HTML-style comments **-->** are supported.
> * Escape special characters (ex: **\[** **\(** **\|** **\***)
> using backslash (ex: **\\\[** **\\\(** **\\\|** **\\\***).
> * A line consisting of **---**, **\*\*\***, or **\_\_\_** is a horizontal
> rule. Spaces and extra **-**/**\***/**_** are allowed.
> * Paragraphs enclosed in **\<html\>...\</html\>** is passed through unchanged.
> * See [daringfireball.net][] for additional information.
|
| ︙ | ︙ |
Changes to src/markdown_html.c.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
void markdown_to_html(
struct Blob *input_markdown,
struct Blob *output_title,
struct Blob *output_body);
#endif /* INTERFACE */
/*
** An instance of the following structure is passed through the
** "opaque" pointer.
*/
typedef struct MarkdownToHtml MarkdownToHtml;
struct MarkdownToHtml {
Blob *output_title; /* Store the title here */
};
/* INTER_BLOCK -- skip a line between block level elements */
#define INTER_BLOCK(ob) \
do { if( blob_size(ob)>0 ) blob_append_char(ob, '\n'); } while (0)
| > > > > > > > > > > > > > > > < < < | > > > | | | | | | > | > | > > > > > > > > > > > | > > > > > > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
void markdown_to_html(
struct Blob *input_markdown,
struct Blob *output_title,
struct Blob *output_body);
#endif /* INTERFACE */
/*
** Markdown-internal helper for generating unique link reference IDs.
** Fields provide typed interpretation of the underline memory buffer.
*/
typedef union bitfield64_t bitfield64_t;
union bitfield64_t{
char c[8]; /* interpret as the array of signed characters */
unsigned char b[8]; /* interpret as the array of unsigned characters */
};
/*
** An instance of the following structure is passed through the
** "opaque" pointer.
*/
typedef struct MarkdownToHtml MarkdownToHtml;
struct MarkdownToHtml {
Blob *output_title; /* Store the title here */
bitfield64_t unique; /* Enables construction of unique #id elements */
#ifndef FOOTNOTES_WITHOUT_URI
Blob reqURI; /* REQUEST_URI with escaped quotes */
#endif
};
/* INTER_BLOCK -- skip a line between block level elements */
#define INTER_BLOCK(ob) \
do { if( blob_size(ob)>0 ) blob_append_char(ob, '\n'); } while (0)
/*
** FOOTNOTES_WITHOUT_URI macro was introduced by [2c1f8f3592ef00e0]
** to enable flexibility in rendering of footnote-specific hyperlinks.
** It may be defined for a particular build in order to omit
** full REQUEST_URIs within footnote-specific (and page-local) hyperlinks.
** This *is* used for the builds that incorporate 'base-href-fix' branch
** (which in turn fixes footnotes on the preview tab of /wikiedit page).
*/
#ifndef FOOTNOTES_WITHOUT_URI
#define BLOB_APPEND_URI(dest,ctx) blob_appendb(dest,&((ctx)->reqURI))
#else
#define BLOB_APPEND_URI(dest,ctx)
#endif
/* Converts an integer to a textual base26 representation
** with proper null-termination.
* Return empty string if that integer is negative. */
static bitfield64_t to_base26(int i, int uppercase){
bitfield64_t x;
int j;
memset( &x, 0, sizeof(x) );
if( i >= 0 ){
for(j=7; j >= 0; j--){
x.b[j] = (unsigned char)(uppercase?'A':'a') + i%26;
if( (i /= 26) == 0 ) break;
}
assert( j > 0 ); /* because 2^32 < 26^7 */
for(i=0; i<8-j; i++) x.b[i] = x.b[i+j];
for( ; i<8 ; i++) x.b[i] = 0;
}
assert( x.c[7] == 0 );
return x;
}
/* HTML escapes
**
** html_escape() converts < to <, > to >, and & to &.
** html_quote() goes further and converts " into " and ' in '.
*/
static void html_quote(struct Blob *ob, const char *data, size_t size){
|
| ︙ | ︙ | |||
76 77 78 79 80 81 82 |
&& data[i]!='\''
){
i++;
}
blob_append(ob, data+beg, i-beg);
while( i<size ){
if( data[i]=='<' ){
| | | | | | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
&& data[i]!='\''
){
i++;
}
blob_append(ob, data+beg, i-beg);
while( i<size ){
if( data[i]=='<' ){
blob_append_literal(ob, "<");
}else if( data[i]=='>' ){
blob_append_literal(ob, ">");
}else if( data[i]=='&' ){
blob_append_literal(ob, "&");
}else if( data[i]=='"' ){
blob_append_literal(ob, """);
}else if( data[i]=='\'' ){
blob_append_literal(ob, "'");
}else{
break;
}
i++;
}
}
}
|
| ︙ | ︙ | |||
106 107 108 109 110 111 112 |
&& data[i]!='&'
){
i++;
}
blob_append(ob, data+beg, i-beg);
while( i<size ){
if( data[i]=='<' ){
| | | | | | | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
&& data[i]!='&'
){
i++;
}
blob_append(ob, data+beg, i-beg);
while( i<size ){
if( data[i]=='<' ){
blob_append_literal(ob, "<");
}else if( data[i]=='>' ){
blob_append_literal(ob, ">");
}else if( data[i]=='&' ){
blob_append_literal(ob, "&");
}else{
break;
}
i++;
}
}
}
/* HTML block tags */
/* Size of the prolog: "<div class='markdown'>\n" */
#define PROLOG_SIZE 23
static void html_prolog(struct Blob *ob, void *opaque){
INTER_BLOCK(ob);
blob_append_literal(ob, "<div class=\"markdown\">\n");
assert( blob_size(ob)==PROLOG_SIZE );
}
static void html_epilog(struct Blob *ob, void *opaque){
INTER_BLOCK(ob);
blob_append_literal(ob, "</div>\n");
}
static void html_blockhtml(struct Blob *ob, struct Blob *text, void *opaque){
char *data = blob_buffer(text);
size_t size = blob_size(text);
Blob *title = ((MarkdownToHtml*)opaque)->output_title;
while( size>0 && fossil_isspace(data[0]) ){ data++; size--; }
|
| ︙ | ︙ | |||
155 156 157 158 159 160 161 |
){
int nTag = html_tag_length(data);
blob_append(title, data+nTag, size - nTag - 5);
return;
}
INTER_BLOCK(ob);
blob_append(ob, data, size);
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | | | | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 |
){
int nTag = html_tag_length(data);
blob_append(title, data+nTag, size - nTag - 5);
return;
}
INTER_BLOCK(ob);
blob_append(ob, data, size);
blob_append_literal(ob, "\n");
}
static void html_blockcode(struct Blob *ob, struct Blob *text, void *opaque){
INTER_BLOCK(ob);
blob_append_literal(ob, "<pre><code>");
html_escape(ob, blob_buffer(text), blob_size(text));
blob_append_literal(ob, "</code></pre>\n");
}
static void html_blockquote(struct Blob *ob, struct Blob *text, void *opaque){
INTER_BLOCK(ob);
blob_append_literal(ob, "<blockquote>\n");
blob_appendb(ob, text);
blob_append_literal(ob, "</blockquote>\n");
}
static void html_header(
struct Blob *ob,
struct Blob *text,
int level,
void *opaque
){
struct Blob *title = ((MarkdownToHtml*)opaque)->output_title;
/* The first header at the beginning of a text is considered as
* a title and not output. */
if( blob_size(ob)<=PROLOG_SIZE && title!=0 && blob_size(title)==0 ){
blob_appendb(title, text);
return;
}
INTER_BLOCK(ob);
blob_appendf(ob, "<h%d>", level);
blob_appendb(ob, text);
blob_appendf(ob, "</h%d>", level);
}
static void html_hrule(struct Blob *ob, void *opaque){
INTER_BLOCK(ob);
blob_append_literal(ob, "<hr />\n");
}
static void html_list(
struct Blob *ob,
struct Blob *text,
int flags,
void *opaque
){
char ol[] = "ol";
char ul[] = "ul";
char *tag = (flags & MKD_LIST_ORDERED) ? ol : ul;
INTER_BLOCK(ob);
blob_appendf(ob, "<%s>\n", tag);
blob_appendb(ob, text);
blob_appendf(ob, "</%s>\n", tag);
}
static void html_list_item(
struct Blob *ob,
struct Blob *text,
int flags,
void *opaque
){
char *text_data = blob_buffer(text);
size_t text_size = blob_size(text);
while( text_size>0 && text_data[text_size-1]=='\n' ) text_size--;
blob_append_literal(ob, "<li>");
blob_append(ob, text_data, text_size);
blob_append_literal(ob, "</li>\n");
}
static void html_paragraph(struct Blob *ob, struct Blob *text, void *opaque){
INTER_BLOCK(ob);
blob_append_literal(ob, "<p>");
blob_appendb(ob, text);
blob_append_literal(ob, "</p>\n");
}
static void html_table(
struct Blob *ob,
struct Blob *head_row,
struct Blob *rows,
void *opaque
){
INTER_BLOCK(ob);
blob_append_literal(ob, "<table>\n");
if( head_row && blob_size(head_row)>0 ){
blob_append_literal(ob, "<thead>\n");
blob_appendb(ob, head_row);
blob_append_literal(ob, "</thead>\n<tbody>\n");
}
if( rows ){
blob_appendb(ob, rows);
}
if( head_row && blob_size(head_row)>0 ){
blob_append_literal(ob, "</tbody>\n");
}
blob_append_literal(ob, "</table>\n");
}
static void html_table_cell(
struct Blob *ob,
struct Blob *text,
int flags,
void *opaque
){
if( flags & MKD_CELL_HEAD ){
blob_append_literal(ob, " <th");
}else{
blob_append_literal(ob, " <td");
}
switch( flags & MKD_CELL_ALIGN_MASK ){
case MKD_CELL_ALIGN_LEFT: {
blob_append_literal(ob, " align=\"left\"");
break;
}
case MKD_CELL_ALIGN_RIGHT: {
blob_append_literal(ob, " align=\"right\"");
break;
}
case MKD_CELL_ALIGN_CENTER: {
blob_append_literal(ob, " align=\"center\"");
break;
}
}
blob_append_literal(ob, ">");
blob_appendb(ob, text);
if( flags & MKD_CELL_HEAD ){
blob_append_literal(ob, "</th>\n");
}else{
blob_append_literal(ob, "</td>\n");
}
}
static void html_table_row(
struct Blob *ob,
struct Blob *cells,
int flags,
void *opaque
){
blob_append_literal(ob, " <tr>\n");
blob_appendb(ob, cells);
blob_append_literal(ob, " </tr>\n");
}
/*
** Render a token of user provided classes.
** If bHTML is true then render HTML for (presumably) visible text,
** otherwise just a space-separated list of the derived classes.
*/
static void append_footnote_upc(
struct Blob *ob,
const struct Blob *upc, /* token of user-provided classes */
int bHTML
){
const char *z = blob_buffer(upc);
int i, n = blob_size(upc);
if( n<3 ) return;
assert( z[0]=='.' && z[n-1] == ':' );
if( bHTML ){
blob_append_literal(ob, "<span class='fn-upc'>"
"<span class='fn-upcDot'>.</span>");
}
n = 0;
do{
z++;
if( *z!='.' && *z!=':' ){
assert( fossil_isalnum(*z) || *z=='-' );
n++;
continue;
}
assert( n );
if( bHTML ) blob_append_literal(ob, "<span class='");
blob_append_literal(ob, "fn-upc-");
for(i=-n; i<0; i++){
blob_append_char(ob, fossil_tolower(z[i]) );
}
if( bHTML ){
blob_append_literal(ob, "'>");
blob_append(ob, z-n, n);
blob_append_literal(ob, "</span>");
}else{
blob_append_char(ob, ' ');
}
n = 0;
if( bHTML ){
if( *z==':' ){
blob_append_literal(ob,"<span class='fn-upcColon'>:</span>");
}else{
blob_append_literal(ob,"<span class='fn-upcDot'>.</span>");
}
}
}while( *z != ':' );
if( bHTML ) blob_append_literal(ob,"</span>\n");
}
static int html_footnote_ref(
struct Blob *ob, const struct Blob *span, const struct Blob *upc,
int iMark, int locus, void *opaque
){
const struct MarkdownToHtml* ctx = (struct MarkdownToHtml*)opaque;
const bitfield64_t l = to_base26(locus-1,0);
char pos[32];
memset(pos,0,32);
assert( locus > 0 );
/* expect BUGs if the following yields compiler warnings */
if( iMark > 0 ){ /* a regular reference to a footnote */
sprintf(pos, "%s-%d-%s", ctx->unique.c, iMark, l.c);
if(span && blob_size(span)) {
blob_append_literal(ob,"<span class='");
append_footnote_upc(ob, upc, 0);
blob_append_literal(ob,"notescope' id='noteref");
blob_appendf(ob,"%s'>",pos);
blob_appendb(ob, span);
blob_trim(ob);
blob_append_literal(ob,"<sup class='noteref'><a href='");
BLOB_APPEND_URI(ob, ctx);
blob_appendf(ob,"#footnote%s'>%d</a></sup></span>", pos, iMark);
}else{
blob_trim(ob);
blob_append_literal(ob,"<sup class='");
append_footnote_upc(ob, upc, 0);
blob_append_literal(ob,"noteref'><a href='");
BLOB_APPEND_URI(ob, ctx);
blob_appendf(ob,"#footnote%s' id='noteref%s'>%d</a></sup>",
pos, pos, iMark);
}
}else{ /* misreference */
assert( iMark == -1 );
sprintf(pos, "%s-%s", ctx->unique.c, l.c);
if(span && blob_size(span)) {
blob_appendf(ob, "<span class='notescope' id='misref%s'>", pos);
blob_appendb(ob, span);
blob_trim(ob);
blob_append_literal(ob, "<sup class='noteref misref'><a href='");
BLOB_APPEND_URI(ob, ctx);
blob_appendf(ob, "#misreference%s'>misref</a></sup></span>", pos);
}else{
blob_trim(ob);
blob_append_literal(ob, "<sup class='noteref misref'><a href='");
BLOB_APPEND_URI(ob, ctx);
blob_appendf(ob, "#misreference%s' id='misref%s'>", pos, pos);
blob_append_literal(ob, "misref</a></sup>");
}
}
return 1;
}
/* Render a single item of the footnotes list.
* Each backref gets a unique id to enable dynamic styling. */
static void html_footnote_item(
struct Blob *ob, const struct Blob *text, int iMark, int nUsed, void *opaque
){
const struct MarkdownToHtml* ctx = (struct MarkdownToHtml*)opaque;
const char * const unique = ctx->unique.c;
assert( nUsed >= 0 );
/* expect BUGs if the following yields compiler warnings */
if( iMark < 0 ){ /* misreferences */
assert( iMark == -1 );
assert( nUsed );
blob_append_literal(ob,"<li class='fn-misreference'>"
"<sup class='fn-backrefs'>");
if( nUsed == 1 ){
blob_appendf(ob,"<a id='misreference%s-a' href='", unique);
BLOB_APPEND_URI(ob, ctx);
blob_appendf(ob,"#misref%s-a'>^</a>", unique);
}else{
int i;
blob_append_char(ob, '^');
for(i=0; i<nUsed && i<26; i++){
const int c = i + (unsigned)'a';
blob_appendf(ob," <a id='misreference%s-%c' href='", unique,c);
BLOB_APPEND_URI(ob, ctx);
blob_appendf(ob,"#misref%s-%c'>%c</a>", unique,c, c);
}
if( i < nUsed ) blob_append_literal(ob," …");
}
blob_append_literal(ob,"</sup>\n<span>Misreference</span>");
}else if( iMark > 0 ){ /* regular, joined and overnested footnotes */
char pos[24];
int bJoin = 0;
#define _joined_footnote_indicator "<ul class='fn-joined'>"
#define _jfi_sz (sizeof(_joined_footnote_indicator)-1)
/* make.footnote_item() invocations should pass args accordingly */
const struct Blob *upc = text+1;
assert( text );
/* allow blob_size(text)==0 for constructs like [...](^ [] ()) */
memset(pos,0,24);
sprintf(pos, "%s-%d", unique, iMark);
blob_appendf(ob, "<li id='footnote%s' class='", pos);
if( nUsed ){
if( blob_size(text)>=_jfi_sz &&
!memcmp(blob_buffer(text),_joined_footnote_indicator,_jfi_sz)){
bJoin = 1;
blob_append_literal(ob, "fn-joined ");
}
append_footnote_upc(ob, upc, 0);
}else{
blob_append_literal(ob, "fn-toodeep ");
}
if( nUsed <= 1 ){
blob_append_literal(ob, "fn-monoref'><sup class='fn-backrefs'>");
blob_appendf(ob,"<a id='footnote%s-a' href='", pos);
BLOB_APPEND_URI(ob, ctx);
blob_appendf(ob,"#noteref%s-a'>^</a>", pos);
}else{
int i;
blob_append_literal(ob, "fn-polyref'><sup class='fn-backrefs'>^");
for(i=0; i<nUsed && i<26; i++){
const int c = i + (unsigned)'a';
blob_appendf(ob," <a id='footnote%s-%c' href='", pos,c);
BLOB_APPEND_URI(ob, ctx);
blob_appendf(ob,"#noteref%s-%c'>%c</a>", pos,c, c);
}
/* It's unlikely that so many backrefs will be usefull */
/* but maybe for some machine generated documents... */
for(; i<nUsed && i<676; i++){
const bitfield64_t l = to_base26(i,0);
blob_appendf(ob," <a id='footnote%s-%s' href='", pos, l.c);
BLOB_APPEND_URI(ob, ctx);
blob_appendf(ob,"#noteref%s-%s'>%s</a>", pos,l.c, l.c);
}
if( i < nUsed ) blob_append_literal(ob," …");
}
blob_append_literal(ob,"</sup>\n");
if( bJoin ){
blob_append_literal(ob,"<sup class='fn-joined'></sup><ul>");
blob_append(ob,blob_buffer(text)+_jfi_sz,blob_size(text)-_jfi_sz);
}else if( nUsed ){
append_footnote_upc(ob, upc, 1);
blob_appendb(ob, text);
}else{
blob_append_literal(ob,"<i></i>\n"
"<pre><code class='language-markdown'>");
if( blob_size(upc) ){
blob_appendb(ob, upc);
}
html_escape(ob, blob_buffer(text), blob_size(text));
blob_append_literal(ob,"</code></pre>");
}
#undef _joined_footnote_indicator
#undef _jfi_sz
}else{ /* a footnote was defined but wasn't referenced */
/* make.footnote_item() invocations should pass args accordingly */
const struct Blob *id = text-1, *upc = text+1;
assert( !nUsed );
assert( text );
assert( blob_size(text) );
assert( blob_size(id) );
blob_append_literal(ob,"<li class='fn-unreferenced'>\n[^ <code>");
html_escape(ob, blob_buffer(id), blob_size(id));
blob_append_literal(ob, "</code> ]<i></i>\n"
"<pre><code class='language-markdown'>");
if( blob_size(upc) ){
blob_appendb(ob, upc);
}
html_escape(ob, blob_buffer(text), blob_size(text));
blob_append_literal(ob,"</code></pre>");
}
blob_append_literal(ob, "\n</li>\n");
}
static void html_footnotes(
struct Blob *ob, const struct Blob *items, void *opaque
){
if( items && blob_size(items) ){
blob_append_literal(ob,
"\n<hr class='footnotes-separator'/>\n<ol class='footnotes'>\n");
blob_appendb(ob, items);
blob_append_literal(ob, "</ol>\n");
}
}
/* HTML span tags */
static int html_raw_html_tag(struct Blob *ob, struct Blob *text, void *opaque){
blob_append(ob, blob_buffer(text), blob_size(text));
return 1;
}
static int html_autolink(
struct Blob *ob,
struct Blob *link,
enum mkd_autolink type,
void *opaque
){
if( !link || blob_size(link)<=0 ) return 0;
blob_append_literal(ob, "<a href=\"");
if( type==MKDA_IMPLICIT_EMAIL ) blob_append_literal(ob, "mailto:");
html_quote(ob, blob_buffer(link), blob_size(link));
blob_append_literal(ob, "\">");
if( type==MKDA_EXPLICIT_EMAIL && blob_size(link)>7 ){
/* remove "mailto:" from displayed text */
html_escape(ob, blob_buffer(link)+7, blob_size(link)-7);
}else{
html_escape(ob, blob_buffer(link), blob_size(link));
}
blob_append_literal(ob, "</a>");
return 1;
}
/*
** The nSrc bytes at zSrc[] are Pikchr input text (allegedly). Process that
** text and insert the result in place of the original.
*/
|
| ︙ | ︙ | |||
420 421 422 423 424 425 426 |
int nSep, /* Number of grave accents marks as delimiters */
void *opaque
){
if( text==0 ){
/* no-op */
}else if( nSep<=2 ){
/* One or two graves: an in-line code span */
| | | | 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 |
int nSep, /* Number of grave accents marks as delimiters */
void *opaque
){
if( text==0 ){
/* no-op */
}else if( nSep<=2 ){
/* One or two graves: an in-line code span */
blob_append_literal(ob, "<code>");
html_escape(ob, blob_buffer(text), blob_size(text));
blob_append_literal(ob, "</code>");
}else{
/* Three or more graves: a fenced code block */
int n = blob_size(text);
const char *z = blob_buffer(text);
int i;
for(i=0; i<n && z[i]!='\n'; i++){}
if( i>=n ){
|
| ︙ | ︙ | |||
458 459 460 461 462 463 464 |
static int html_double_emphasis(
struct Blob *ob,
struct Blob *text,
char c,
void *opaque
){
| | | | | | | | | | | | | 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 |
static int html_double_emphasis(
struct Blob *ob,
struct Blob *text,
char c,
void *opaque
){
blob_append_literal(ob, "<strong>");
blob_appendb(ob, text);
blob_append_literal(ob, "</strong>");
return 1;
}
static int html_emphasis(
struct Blob *ob,
struct Blob *text,
char c,
void *opaque
){
blob_append_literal(ob, "<em>");
blob_appendb(ob, text);
blob_append_literal(ob, "</em>");
return 1;
}
static int html_image(
struct Blob *ob,
struct Blob *link,
struct Blob *title,
struct Blob *alt,
void *opaque
){
blob_append_literal(ob, "<img src=\"");
html_quote(ob, blob_buffer(link), blob_size(link));
blob_append_literal(ob, "\" alt=\"");
html_quote(ob, blob_buffer(alt), blob_size(alt));
if( title && blob_size(title)>0 ){
blob_append_literal(ob, "\" title=\"");
html_quote(ob, blob_buffer(title), blob_size(title));
}
blob_append_literal(ob, "\" />");
return 1;
}
static int html_linebreak(struct Blob *ob, void *opaque){
blob_append_literal(ob, "<br />\n");
return 1;
}
static int html_link(
struct Blob *ob,
struct Blob *link,
struct Blob *title,
|
| ︙ | ︙ | |||
521 522 523 524 525 526 527 |
static const int flags =
WIKI_NOBADLINKS |
WIKI_MARKDOWNLINKS
;
wiki_resolve_hyperlink(ob, flags, zLink, zClose, sizeof(zClose), 0, zTitle);
}
if( blob_size(content)==0 ){
| | | | | | | 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 |
static const int flags =
WIKI_NOBADLINKS |
WIKI_MARKDOWNLINKS
;
wiki_resolve_hyperlink(ob, flags, zLink, zClose, sizeof(zClose), 0, zTitle);
}
if( blob_size(content)==0 ){
if( link ) blob_appendb(ob, link);
}else{
blob_appendb(ob, content);
}
blob_append(ob, zClose, -1);
return 1;
}
static int html_triple_emphasis(
struct Blob *ob,
struct Blob *text,
char c,
void *opaque
){
blob_append_literal(ob, "<strong><em>");
blob_appendb(ob, text);
blob_append_literal(ob, "</em></strong>");
return 1;
}
static void html_normal_text(struct Blob *ob, struct Blob *text, void *opaque){
html_escape(ob, blob_buffer(text), blob_size(text));
}
|
| ︙ | ︙ | |||
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 |
struct Blob *output_title, /* Put title here. May be NULL */
struct Blob *output_body /* Put document body here. */
){
struct mkd_renderer html_renderer = {
/* prolog and epilog */
html_prolog,
html_epilog,
/* block level elements */
html_blockcode,
html_blockquote,
html_blockhtml,
html_header,
html_hrule,
html_list,
html_list_item,
html_paragraph,
html_table,
html_table_cell,
html_table_row,
/* span level elements */
html_autolink,
html_codespan,
html_double_emphasis,
html_emphasis,
html_image,
html_linebreak,
html_link,
html_raw_html_tag,
html_triple_emphasis,
/* low level elements */
0, /* entity */
html_normal_text,
/* misc. parameters */
"*_", /* emph_chars */
0 /* opaque */
};
MarkdownToHtml context;
memset(&context, 0, sizeof(context));
context.output_title = output_title;
html_renderer.opaque = &context;
if( output_title ) blob_reset(output_title);
blob_reset(output_body);
markdown(output_body, input_markdown, &html_renderer);
}
| > > > > > > > > > > | 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 |
struct Blob *output_title, /* Put title here. May be NULL */
struct Blob *output_body /* Put document body here. */
){
struct mkd_renderer html_renderer = {
/* prolog and epilog */
html_prolog,
html_epilog,
html_footnotes,
/* block level elements */
html_blockcode,
html_blockquote,
html_blockhtml,
html_header,
html_hrule,
html_list,
html_list_item,
html_paragraph,
html_table,
html_table_cell,
html_table_row,
html_footnote_item,
/* span level elements */
html_autolink,
html_codespan,
html_double_emphasis,
html_emphasis,
html_image,
html_linebreak,
html_link,
html_raw_html_tag,
html_triple_emphasis,
html_footnote_ref,
/* low level elements */
0, /* entity */
html_normal_text,
/* misc. parameters */
"*_", /* emph_chars */
0 /* opaque */
};
static int invocation = -1; /* no marker for the first document */
static const char* zRU = 0; /* REQUEST_URI with escaped quotes */
MarkdownToHtml context;
memset(&context, 0, sizeof(context));
context.output_title = output_title;
context.unique = to_base26(invocation++,1);
if( !zRU ) zRU = escape_quotes(PD("REQUEST_URI",""));
#ifndef FOOTNOTES_WITHOUT_URI
blob_set( &context.reqURI, zRU );
#endif
html_renderer.opaque = &context;
if( output_title ) blob_reset(output_title);
blob_reset(output_body);
markdown(output_body, input_markdown, &html_renderer);
}
|
Changes to src/merge.c.
| ︙ | ︙ | |||
405 406 407 408 409 410 411 |
if( vid==0 ){
fossil_fatal("nothing is checked out");
}
if( forceFlag==0 && leaf_is_closed(vid) ){
fossil_fatal("cannot merge into a closed leaf. Use --force to override");
}
if( !dryRunFlag ){
| | < | 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 |
if( vid==0 ){
fossil_fatal("nothing is checked out");
}
if( forceFlag==0 && leaf_is_closed(vid) ){
fossil_fatal("cannot merge into a closed leaf. Use --force to override");
}
if( !dryRunFlag ){
if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag, 1, "merge") ){
fossil_fatal("merge abandoned due to sync failure");
}
}
/* Find mid, the artifactID of the version to be merged into the current
** check-out */
if( g.argc==3 ){
|
| ︙ | ︙ |
Changes to src/name.c.
| ︙ | ︙ | |||
259 260 261 262 263 264 265 266 267 268 269 270 271 272 | ** * "current" ** * "prev" or "previous" ** * "next" ** ** The following modifier prefixes may be applied to the above forms: ** ** * "root:BR" = The origin of the branch named BR. ** * "merge-in:BR" = The most recent merge-in for the branch named BR. ** ** In those forms, BR may be any symbolic form but is assumed to be a ** checkin. Thus root:2021-02-01 would resolve to a checkin, possibly ** in a branch and possibly in the trunk, but never a wiki edit or ** forum post. ** | > | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | ** * "current" ** * "prev" or "previous" ** * "next" ** ** The following modifier prefixes may be applied to the above forms: ** ** * "root:BR" = The origin of the branch named BR. ** * "start:BR" = The first check-in of the branch named BR. ** * "merge-in:BR" = The most recent merge-in for the branch named BR. ** ** In those forms, BR may be any symbolic form but is assumed to be a ** checkin. Thus root:2021-02-01 would resolve to a checkin, possibly ** in a branch and possibly in the trunk, but never a wiki edit or ** forum post. ** |
| ︙ | ︙ | |||
376 377 378 379 380 381 382 |
}
/* root:BR -> The origin of the branch named BR */
if( strncmp(zTag, "root:", 5)==0 ){
rid = symbolic_name_to_rid(zTag+5, zType);
return start_of_branch(rid, 0);
}
| > > > > > > > | | 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
}
/* root:BR -> The origin of the branch named BR */
if( strncmp(zTag, "root:", 5)==0 ){
rid = symbolic_name_to_rid(zTag+5, zType);
return start_of_branch(rid, 0);
}
/* start:BR -> The first check-in on branch named BR */
if( strncmp(zTag, "start:", 6)==0 ){
rid = symbolic_name_to_rid(zTag+6, zType);
return start_of_branch(rid, 1);
}
/* merge-in:BR -> Most recent merge-in for the branch named BR */
if( strncmp(zTag, "merge-in:", 9)==0 ){
rid = symbolic_name_to_rid(zTag+9, zType);
return start_of_branch(rid, 2);
}
/* symbolic-name ":" date-time */
nTag = strlen(zTag);
|
| ︙ | ︙ | |||
1741 1742 1743 1744 1745 1746 1747 |
#define MAX_COLLIDE 25
/*
** Generate a report on the number of collisions in artifact hashes
** generated by the SQL given in the argument.
*/
static void collision_report(const char *zSql){
| | | 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 |
#define MAX_COLLIDE 25
/*
** Generate a report on the number of collisions in artifact hashes
** generated by the SQL given in the argument.
*/
static void collision_report(const char *zSql){
int i, j;
int nHash = 0;
Stmt q;
char zPrev[HNAME_MAX+1];
struct {
int cnt;
char *azHit[MAX_COLLIDE];
char z[HNAME_MAX+1];
|
| ︙ | ︙ | |||
1778 1779 1780 1781 1782 1783 1784 |
@ </thead><tbody>
for(i=1; i<=HNAME_MAX; i++){
if( aCollide[i].cnt==0 ) continue;
@ <tr><td>%d(i)<td>%d(aCollide[i].cnt)<td>%h(aCollide[i].z)</tr>
}
@ </tbody></table>
@ <p>Total number of hashes: %d(nHash)</p>
| < < | 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 |
@ </thead><tbody>
for(i=1; i<=HNAME_MAX; i++){
if( aCollide[i].cnt==0 ) continue;
@ <tr><td>%d(i)<td>%d(aCollide[i].cnt)<td>%h(aCollide[i].z)</tr>
}
@ </tbody></table>
@ <p>Total number of hashes: %d(nHash)</p>
for(i=HNAME_MAX; i>=4; i--){
if( aCollide[i].cnt==0 ) continue;
if( aCollide[i].cnt>200 ) break;
if( aCollide[i].cnt<25 ){
@ <p>Collisions of length %d(i):
}else{
@ <p>First 25 collisions of length %d(i):
}
for(j=0; j<aCollide[i].cnt && j<MAX_COLLIDE; j++){
char *zId = aCollide[i].azHit[j];
|
| ︙ | ︙ |
Changes to src/path.c.
| ︙ | ︙ | |||
203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
int i;
if( path.nNotHidden<2 ) return 0;
for(p=path.pEnd, i=0; p && (p->isHidden || i<path.nNotHidden/2); p=p->pFrom){
if( !p->isHidden ) i++;
}
return p;
}
/*
** Return an estimate of the number of comparisons remaining in order
** to bisect path. This is based on the log2() of path.nStep.
*/
int path_search_depth(void){
int i, j;
| > > > > > > > > > > | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
int i;
if( path.nNotHidden<2 ) return 0;
for(p=path.pEnd, i=0; p && (p->isHidden || i<path.nNotHidden/2); p=p->pFrom){
if( !p->isHidden ) i++;
}
return p;
}
/*
** Find the next most recent node on a path.
*/
PathNode *path_next(void){
PathNode *p;
p = path.pStart;
if( p ) p = p->u.pTo;
return p;
}
/*
** Return an estimate of the number of comparisons remaining in order
** to bisect path. This is based on the log2() of path.nStep.
*/
int path_search_depth(void){
int i, j;
|
| ︙ | ︙ |
Changes to src/pikchrshow.c.
| ︙ | ︙ | |||
228 229 230 231 232 233 234 |
blob_appendf(pOut, "%s\n", zNonce);
}
blob_reset(&bIn);
return isErr;
}
/*
| | > | > > > | < < | | > > > > | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
blob_appendf(pOut, "%s\n", zNonce);
}
blob_reset(&bIn);
return isErr;
}
/*
** Legacy impl of /pikchrshow. pikchrshow_page() will delegate to
** this one if the "legacy" or "ajax" request arguments are set.
**
** A pikchr code editor and previewer, allowing users to experiment
** with pikchr code or prototype it for use in copy/pasting into forum
** posts, wiki pages, or embedded docs. This version of pikchrshow
** uses JavaScript to send pikchr code to the server for
** processing. The newer /pikchrshow applications runs pikchr on the
** client machine, without the need for back-and-forth network
** traffic.
*/
void pikchrshowcs_page(void){
const char *zContent = 0;
int isDark; /* true if the current skin is "dark" */
int pikFlags =
PIKCHR_PROCESS_DIV
| PIKCHR_PROCESS_SRC
| PIKCHR_PROCESS_ERR_PRE;
login_check_credentials();
if( !g.perm.RdWiki && !g.perm.Read && !g.perm.RdForum ){
cgi_redirectf("%R/login?g=pikchrshowcs");
}
if(P("wasm")){
pikchrshow_page();
return;
}
zContent = PD("content",P("p"));
if(P("ajax")!=0){
/* Called from the JS-side preview updater.
TODO: respond with JSON instead.*/
cgi_set_content_type("text/html");
if(zContent && *zContent){
|
| ︙ | ︙ | |||
277 278 279 280 281 282 283 |
if(!zContent){
zContent = "arrow right 200% \"Markdown\" \"Source\"\n"
"box rad 10px \"Markdown\" \"Formatter\" \"(markdown.c)\" fit\n"
"arrow right 200% \"HTML+SVG\" \"Output\"\n"
"arrow <-> down from last box.s\n"
"box same \"Pikchr\" \"Formatter\" \"(pikchr.c)\" fit\n";
}
| | | 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
if(!zContent){
zContent = "arrow right 200% \"Markdown\" \"Source\"\n"
"box rad 10px \"Markdown\" \"Formatter\" \"(markdown.c)\" fit\n"
"arrow right 200% \"HTML+SVG\" \"Output\"\n"
"arrow <-> down from last box.s\n"
"box same \"Pikchr\" \"Formatter\" \"(pikchr.c)\" fit\n";
}
style_header("PikchrShow Client/Server");
CX("<style>"); {
CX("div.content { padding-top: 0.5em }\n");
CX("#sbs-wrapper {"
"display: flex; flex-direction: column;"
"}\n");
CX("#sbs-wrapper > * {"
"margin: 0 0.25em 0.5em 0; flex: 1 10 auto;"
|
| ︙ | ︙ | |||
334 335 336 337 338 339 340 |
"}\n");
CX("body.pikchrshow .v-align-middle{"
"vertical-align: middle"
"}\n");
CX(".dragover {border: 3px dotted rgba(0,255,0,0.6)}\n");
} CX("</style>");
CX("<div>Input pikchr code and tap Preview (or Shift-Enter) to render "
| | | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 |
"}\n");
CX("body.pikchrshow .v-align-middle{"
"vertical-align: middle"
"}\n");
CX(".dragover {border: 3px dotted rgba(0,255,0,0.6)}\n");
} CX("</style>");
CX("<div>Input pikchr code and tap Preview (or Shift-Enter) to render "
"it. <a href='?wasm'>Switch to WASM mode</a>.</div>");
CX("<div id='sbs-wrapper'>"); {
CX("<div id='pikchrshow-form'>"); {
CX("<textarea id='content' name='content' rows='15'>"
"%s</textarea>",zContent/*safe-for-%s*/);
CX("<div id='pikchrshow-controls'>"); {
CX("<button id='pikchr-submit-preview'>Preview</button>");
CX("<div class='input-with-label'>"); {
|
| ︙ | ︙ | |||
374 375 376 377 378 379 380 381 382 383 384 385 386 387 |
} CX("</div>"/*sbs-wrapper*/);
builtin_fossil_js_bundle_or("fetch", "copybutton", "popupwidget",
"storage", "pikchr", NULL);
builtin_request_js("fossil.page.pikchrshow.js");
builtin_fulfill_js_requests();
style_finish_page();
}
/*
** COMMAND: pikchr*
**
** Usage: %fossil pikchr [options] ?INFILE? ?OUTFILE?
**
** Accepts a pikchr script as input and outputs the rendered script as
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 |
} CX("</div>"/*sbs-wrapper*/);
builtin_fossil_js_bundle_or("fetch", "copybutton", "popupwidget",
"storage", "pikchr", NULL);
builtin_request_js("fossil.page.pikchrshow.js");
builtin_fulfill_js_requests();
style_finish_page();
}
/*
** WEBPAGE: pikchrshow
**
** A pikchr code editor and previewer, allowing users to experiment
** with pikchr code or prototype it for use in copy/pasting into forum
** posts, wiki pages, or embedded docs. This version of pikchrshow
** uses WebAssembly to run entirely in the client browser, without a
** need for back-and-forth client/server traffic to perform the
** rendering. The "legacy" version of this application, which sends
** all input to the server for rendering, can be accessed by adding
** the "legacy" URL argument.
**
** It optionally accepts a p=pikchr-script-code URL parameter or POST
** value to pre-populate the editor with that code.
*/
void pikchrshow_page(void){
const char *zContent = 0;
if(P("legacy") || P("ajax")){
pikchrshowcs_page();
return;
}
login_check_credentials();
if( !g.perm.RdWiki && !g.perm.Read && !g.perm.RdForum ){
cgi_redirectf("%R/login?g=pikchrshow");
}
style_emit_noscript_for_js_page();
style_header("PikchrShow");
zContent = PD("content",P("p"));
if(!zContent){
zContent = "arrow right 200% \"Markdown\" \"Source\"\n"
"box rad 10px \"Markdown\" \"Formatter\" \"(markdown.c)\" fit\n"
"arrow right 200% \"HTML+SVG\" \"Output\"\n"
"arrow <-> down from last box.s\n"
"box same \"Pikchr\" \"Formatter\" \"(pikchr.c)\" fit\n";
}
/* Wasm load/init progress widget... */
CX("<div class='emscripten'>"); {
CX("<figure id='module-spinner'>");
CX("<div class='spinner'></div>");
CX("<div class='center'><strong>Initializing app...</strong></div>");
CX("<div class='center'>");
CX("On a slow internet connection this may take a moment. If this ");
CX("message displays for \"a long time\", intialization may have ");
CX("failed and the JavaScript console may contain clues as to why. ");
CX("</div>");
CX("<div><a href='?legacy'>Switch to legacy mode</a></div>");
CX("</figure>");
CX("<div class='emscripten' id='module-status'>Downloading...</div>");
CX("<progress value='0' max='100' id='module-progress' hidden='1'>"
"</progress>");
} CX("</div><!-- .emscripten -->");
/* Main view... */
CX("<div id='view-split' class='app-view initially-hidden'>"); {
CX("<fieldset class='options collapsible'>"); {
CX("<legend><button class='fieldset-toggle'>Options</button></legend>");
CX("<div>");
CX("<span class='labeled-input'>");
CX("<input type='checkbox' id='opt-cb-sbs' ");
CX("data-csstgt='#main-wrapper' ");
CX("data-cssclass='side-by-side' ");
CX("data-config='sideBySide'>");
CX("<label for='opt-cb-sbs'>Side-by-side</label>");
CX("</span>");
CX("<span class='labeled-input'>");
CX("<input type='checkbox' id='opt-cb-swapio' ");
CX("data-csstgt='#main-wrapper' ");
CX("data-cssclass='swapio' ");
CX("data-config='swapInOut'>");
CX("<label for='opt-cb-swapio'>Swap in/out</label>");
CX("</span>");
CX("<span class='labeled-input'>");
CX("<input type='checkbox' id='opt-cb-autofit' ");
CX("data-config='renderAutofit'>");
CX("<label for='opt-cb-autofit' "
"title='Attempt to scale SVG to fit viewport. "
"Whether it will work depends in part on the size "
"and shape of the image and the viewport.'"
">Auto-fit SVG</label>");
CX("</span>");
CX("<span class='labeled-input'>");
CX("<input type='checkbox' id='opt-cb-autorender' ");
CX("data-csstgt='#main-wrapper' ");
CX("data-cssclass='auto-render' ");
CX("data-config='renderWhileTyping'>");
CX("<label for='opt-cb-autorender'>Render while typing</label>");
CX("</span>");
CX("<span class='labeled-input'>");
CX("<a href='?legacy'>Legacy mode</a>");
CX("</span>");
CX("</div><!-- options wrapper -->");
} CX("</fieldset>");
CX("<div id='main-wrapper' class=''>"); {
CX("<fieldset class='zone-wrapper input'>"); {
CX("<legend><div class='button-bar'>");
CX("<button id='btn-render' "
"title='Ctrl-Enter/Shift-Enter'>Render</button>");
CX("<button id='btn-clear'>Clear Input</button>");
CX("</div></legend>");
CX("<div><textarea id='input'");
CX("placeholder='Pikchr input. Ctrl-enter/shift-enter runs it.'>");
CX("/**\n");
CX(" Use ctrl-enter or shift-enter to execute\n");
CX(" pikchr code. If only a subset is currently\n");
CX(" selected, only that part is evaluated.\n*/\n");
CX("%s</textarea></div>",zContent/*safe-for-%s*/);
} CX("</fieldset><!-- .zone-wrapper.input -->");
CX("<fieldset class='zone-wrapper output'>"); {
CX("<legend><div class='button-bar'>");
CX("<button id='btn-render-mode'>Render Mode</button> ");
CX("<span style='white-space:nowrap'>"
"<span id='preview-copy-button' "
"title='Tap to copy to clipboard.'></span>"
"<label for='preview-copy-button' "
"title='Tap to copy to clipboard.'></label>"
"</span>");
CX("</div></legend>");
CX("<div id='pikchr-output-wrapper'>");
CX("<div id='pikchr-output'></div>");
CX("<textarea class='hidden' id='pikchr-output-text'></textarea>");
CX("</div>");
} CX("</fieldset> <!-- .zone-wrapper.output -->");
} CX("</div><!-- #main-wrapper -->");
} CX("</div><!-- #view-split -->");
builtin_fossil_js_bundle_or("dom", "storage", "copybutton", NULL);
builtin_request_js("fossil.page.pikchrshowasm.js");
builtin_fulfill_js_requests();
style_finish_page();
}
/*
** COMMAND: pikchr*
**
** Usage: %fossil pikchr [options] ?INFILE? ?OUTFILE?
**
** Accepts a pikchr script as input and outputs the rendered script as
|
| ︙ | ︙ |
Changes to src/repolist.c.
| ︙ | ︙ | |||
208 209 210 211 212 213 214 |
continue;
}
if( rNow <= x.rMTime ){
x.rMTime = rNow;
}else if( x.rMTime<0.0 ){
x.rMTime = rNow;
}
| | | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
continue;
}
if( rNow <= x.rMTime ){
x.rMTime = rNow;
}else if( x.rMTime<0.0 ){
x.rMTime = rNow;
}
iAge = (sqlite3_int64)((rNow - x.rMTime)*86400);
zAge = human_readable_age(rNow - x.rMTime);
if( x.rMTime==0.0 ){
/* This repository has no entry in the "event" table.
** Its age will still be maximum, so data-sortkey will work. */
zAge = mprintf("unknown");
}
blob_append_sql(&html, "<tr><td valign='top'>");
|
| ︙ | ︙ |
Changes to src/schema.c.
| ︙ | ︙ | |||
456 457 458 459 460 461 462 463 464 465 466 467 468 469 | @ comment TEXT @ ); @ CREATE TABLE ticketchng( @ -- Do not change any column that begins with tkt_ @ tkt_id INTEGER REFERENCES ticket, @ tkt_rid INTEGER REFERENCES blob, @ tkt_mtime DATE, @ -- Add as many fields as required below this line @ login TEXT, @ username TEXT, @ mimetype TEXT, @ icomment TEXT @ ); @ CREATE INDEX ticketchng_idx1 ON ticketchng(tkt_id, tkt_mtime); | > | 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 | @ comment TEXT @ ); @ CREATE TABLE ticketchng( @ -- Do not change any column that begins with tkt_ @ tkt_id INTEGER REFERENCES ticket, @ tkt_rid INTEGER REFERENCES blob, @ tkt_mtime DATE, @ tkt_user TEXT, @ -- Add as many fields as required below this line @ login TEXT, @ username TEXT, @ mimetype TEXT, @ icomment TEXT @ ); @ CREATE INDEX ticketchng_idx1 ON ticketchng(tkt_id, tkt_mtime); |
| ︙ | ︙ | |||
486 487 488 489 490 491 492 493 494 495 496 497 498 499 | # define BKLNK_TICKET 1 /* Ticket body or title */ # define BKLNK_WIKI 2 /* Wiki */ # define BKLNK_EVENT 3 /* Technote */ # define BKLNK_FORUM 4 /* Forum post */ # define ValidBklnk(X) (X>=0 && X<=4) /* True if backlink.srctype is valid */ #endif /* ** Predefined tagid values */ #if INTERFACE # define TAG_BGCOLOR 1 /* Set the background color for display */ # define TAG_COMMENT 2 /* The check-in comment */ # define TAG_USER 3 /* User who made a checking */ | > > > > > > > > > > > | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 | # define BKLNK_TICKET 1 /* Ticket body or title */ # define BKLNK_WIKI 2 /* Wiki */ # define BKLNK_EVENT 3 /* Technote */ # define BKLNK_FORUM 4 /* Forum post */ # define ValidBklnk(X) (X>=0 && X<=4) /* True if backlink.srctype is valid */ #endif /* ** Allowed values for MIMEtype codes */ #if INTERFACE # define MT_NONE 0 /* unspecified */ # define MT_WIKI 1 /* Wiki */ # define MT_MARKDOWN 2 /* Markdonw */ # define MT_UNKNOWN 3 /* unknown */ # define ValidMTC(X) ((X)>=0 && (X)<=3) /* True if MIMEtype code is valid */ #endif /* ** Predefined tagid values */ #if INTERFACE # define TAG_BGCOLOR 1 /* Set the background color for display */ # define TAG_COMMENT 2 /* The check-in comment */ # define TAG_USER 3 /* User who made a checking */ |
| ︙ | ︙ |
Changes to src/search.c.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 | ******************************************************************************* ** ** This file contains code to implement a search functions ** against timeline comments, check-in content, wiki pages, tickets, ** and/or forum posts. ** ** The search can be either a per-query "grep"-like search that scans | | | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ******************************************************************************* ** ** This file contains code to implement a search functions ** against timeline comments, check-in content, wiki pages, tickets, ** and/or forum posts. ** ** The search can be either a per-query "grep"-like search that scans ** the entire corpus. Or it can use the FTS4 search engine of SQLite. ** The choice is a administrator configuration option. ** ** The first option is referred to as "full-scan search". The second ** option is called "indexed search". ** ** The code in this file is ordered approximately as follows: ** ** (1) The full-scan search engine |
| ︙ | ︙ |
Changes to src/setup.c.
| ︙ | ︙ | |||
358 359 360 361 362 363 364 | @ every historical version of every file and creating ZIPs and tarballs of @ every historical check-in, which can use a lot of CPU and bandwidth @ even for relatively small projects.</p> @ @ <p>The "UserAgent and Javascript" value for this setting provides @ superior protection from robots. However, that setting also prevents @ the visited/unvisited colors on hyperlinks from displaying correctly | | | 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
@ every historical version of every file and creating ZIPs and tarballs of
@ every historical check-in, which can use a lot of CPU and bandwidth
@ even for relatively small projects.</p>
@
@ <p>The "UserAgent and Javascript" value for this setting provides
@ superior protection from robots. However, that setting also prevents
@ the visited/unvisited colors on hyperlinks from displaying correctly
@ on Safari-derived browsers. (Chrome and Firefox work fine.) Since
@ Safari is the underlying rendering engine on all iPhones and iPads,
@ this means that hyperlink visited/unvisited colors will not operate
@ on those platforms when "UserAgent and Javascript" is selected.</p>
@
@ <p>Additional parameters that control the behavior of Javascript:</p>
@ <blockquote>
entry_attribute("Delay in milliseconds before enabling hyperlinks", 5,
|
| ︙ | ︙ |
Changes to src/skins.c.
| ︙ | ︙ | |||
1012 1013 1014 1015 1016 1017 1018 |
style_set_current_feature("skins");
style_header("Customize Skin");
@ <p>Customize the look of this Fossil repository by making changes
@ to the CSS, Header, Footer, and Detail Settings in one of nine "draft"
@ configurations. Then, after verifying that all is working correctly,
| | > > | 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 |
style_set_current_feature("skins");
style_header("Customize Skin");
@ <p>Customize the look of this Fossil repository by making changes
@ to the CSS, Header, Footer, and Detail Settings in one of nine "draft"
@ configurations. Then, after verifying that all is working correctly,
@ publish the draft to become the new main Skin. Users can select a skin
@ of their choice from the built-in ones or the locally-edited one via
@ <a href='%R/skins'>the /skins page</a>.</p>
@
@ <a name='step1'></a>
@ <h1>Step 1: Identify Which Draft To Use</h1>
@
@ <p>The main skin of Fossil cannot be edited directly. Instead,
@ edits are made to one of nine draft skins. A draft skin can then
@ be published to become the default skin.
|
| ︙ | ︙ |
Changes to src/stash.c.
| ︙ | ︙ | |||
595 596 597 598 599 600 601 602 603 604 605 606 607 608 |
if( nFile==0 ) return;
}
/* Make sure the stash has committed before running the revert, so that
** we have a copy of the changes before deleting them. */
db_commit_transaction();
g.argv[1] = "revert";
revert_cmd();
return;
}else
if( memcmp(zCmd, "snapshot", nCmd)==0 ){
stash_create();
}else
if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){
Stmt q, q2;
| > | 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 |
if( nFile==0 ) return;
}
/* Make sure the stash has committed before running the revert, so that
** we have a copy of the changes before deleting them. */
db_commit_transaction();
g.argv[1] = "revert";
revert_cmd();
fossil_print("stash %d saved\n", stashid);
return;
}else
if( memcmp(zCmd, "snapshot", nCmd)==0 ){
stash_create();
}else
if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){
Stmt q, q2;
|
| ︙ | ︙ |
Changes to src/stat.c.
| ︙ | ︙ | |||
278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
@ <tr><th>Fossil Version:</th><td>
@ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
@ (%h(RELEASE_VERSION)) <a href='version?verbose'>(details)</a>
@ </td></tr>
@ <tr><th>SQLite Version:</th><td>%.19s(sqlite3_sourceid())
@ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))
@ <a href='version?verbose'>(details)</a></td></tr>
if( g.eHashPolicy!=HPOLICY_AUTO ){
@ <tr><th>Schema Version:</th><td>%h(g.zAuxSchema),
@ %s(hpolicy_name())</td></tr>
}else{
@ <tr><th>Schema Version:</th><td>%h(g.zAuxSchema)</td></tr>
}
@ <tr><th>Repository Rebuilt:</th><td>
| > > > > > > > > | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
@ <tr><th>Fossil Version:</th><td>
@ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
@ (%h(RELEASE_VERSION)) <a href='version?verbose'>(details)</a>
@ </td></tr>
@ <tr><th>SQLite Version:</th><td>%.19s(sqlite3_sourceid())
@ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))
@ <a href='version?verbose'>(details)</a></td></tr>
if( g.perm.Admin ){
const char *zCgi = P("SERVER_SOFTWARE");
@ <tr><th>OpenSSL Version:</th>
@ <td>%z(fossil_openssl_version())</td></tr>
if( zCgi ){
@ <tr><th>Web Server:</th><td>%s(zCgi)</td></tr>
}
}
if( g.eHashPolicy!=HPOLICY_AUTO ){
@ <tr><th>Schema Version:</th><td>%h(g.zAuxSchema),
@ %s(hpolicy_name())</td></tr>
}else{
@ <tr><th>Schema Version:</th><td>%h(g.zAuxSchema)</td></tr>
}
@ <tr><th>Repository Rebuilt:</th><td>
|
| ︙ | ︙ | |||
961 962 963 964 965 966 967 |
** user without check-in privileges, to prevent excessive usage by
** robots and random passers-by on the internet
*/
if( !g.perm.Write && !db_get_boolean("artifact_stats_enable",0) ){
login_needed(g.anon.Write);
return;
}
| | | 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 |
** user without check-in privileges, to prevent excessive usage by
** robots and random passers-by on the internet
*/
if( !g.perm.Write && !db_get_boolean("artifact_stats_enable",0) ){
login_needed(g.anon.Write);
return;
}
fossil_nice_default();
style_set_current_feature("stat");
style_header("Artifact Statistics");
style_submenu_element("Repository Stats", "stat");
style_submenu_element("Artifact List", "bloblist");
gather_artifact_stats(1);
|
| ︙ | ︙ |
Changes to src/statrep.c.
| ︙ | ︙ | |||
342 343 344 345 346 347 348 |
/*
** Implements the "byuser" view for /reports.
*/
static void stats_report_by_user(){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
| < | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 |
/*
** Implements the "byuser" view for /reports.
*/
static void stats_report_by_user(){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
int rowClass = 0; /* counter for alternating
row colors */
int nMaxEvents = 1; /* max number of events for
all rows. */
stats_report_init_view();
@ <h1>Timeline Events
@ (%s(stats_report_label_for_type())) by User</h1>
|
| ︙ | ︙ | |||
390 391 392 393 394 395 396 |
char y = (char)statsReportType;
int nSize = nCount
? (int)(100 * nCount / nMaxEvents)
: 0;
if(!nCount) continue /* arguable! Possible? */;
else if(!nSize) nSize = 1;
rowClass = ++nRowNumber % 2;
| < | 389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
char y = (char)statsReportType;
int nSize = nCount
? (int)(100 * nCount / nMaxEvents)
: 0;
if(!nCount) continue /* arguable! Possible? */;
else if(!nSize) nSize = 1;
rowClass = ++nRowNumber % 2;
@ <tr class='row%d(rowClass)'>
@ <td>
@ <a href="?view=bymonth&user=%h(zUser)&type=%c(y)">%h(zUser)</a>
@ </td><td data-sortkey='%08x(-nCount)'>%d(nCount)</td>
@ <td>
@ <div class='statistics-report-graph-line'
@ style='width:%d(nSize)%%;'> </div>
|
| ︙ | ︙ | |||
473 474 475 476 477 478 479 |
/*
** Implements the "byweekday" view for /reports. If zUserName is not NULL then
** the report is restricted to events created by the named user account.
*/
static void stats_report_day_of_week(const char *zUserName){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
| < | 471 472 473 474 475 476 477 478 479 480 481 482 483 484 |
/*
** Implements the "byweekday" view for /reports. If zUserName is not NULL then
** the report is restricted to events created by the named user account.
*/
static void stats_report_day_of_week(const char *zUserName){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
int rowClass = 0; /* counter for alternating
row colors */
int nMaxEvents = 1; /* max number of events for
all rows. */
Blob userFilter = empty_blob; /* Optional user=johndoe query string */
static const char *const daysOfWeek[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
|
| ︙ | ︙ | |||
547 548 549 550 551 552 553 |
const int nCount = db_column_int(&query, 1);
int nSize = nCount
? (int)(100 * nCount / nMaxEvents)
: 0;
if(!nCount) continue /* arguable! Possible? */;
else if(!nSize) nSize = 1;
rowClass = ++nRowNumber % 2;
| < | 544 545 546 547 548 549 550 551 552 553 554 555 556 557 |
const int nCount = db_column_int(&query, 1);
int nSize = nCount
? (int)(100 * nCount / nMaxEvents)
: 0;
if(!nCount) continue /* arguable! Possible? */;
else if(!nSize) nSize = 1;
rowClass = ++nRowNumber % 2;
@<tr class='row%d(rowClass)'>
@ <td>%d(dayNum)</td>
@ <td>%s(daysOfWeek[dayNum])</td>
@ <td>%d(nCount)</td>
@ <td>
@ <div class='statistics-report-graph-line'
@ style='width:%d(nSize)%%;'> </div>
|
| ︙ | ︙ |
Changes to src/style.c.
| ︙ | ︙ | |||
645 646 647 648 649 650 651 | ** Default HTML page header text through <body>. If the repository-specific ** header template lacks a <body> tag, then all of the following is ** prepended. */ static const char zDfltHeader[] = @ <html> @ <head> | < > | | 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 |
** Default HTML page header text through <body>. If the repository-specific
** header template lacks a <body> tag, then all of the following is
** prepended.
*/
static const char zDfltHeader[] =
@ <html>
@ <head>
@ <meta charset="UTF-8">
@ <base href="$baseurl/$current_page" />
@ <meta http-equiv="Content-Security-Policy" content="$default_csp" />
@ <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed" \
@ href="$home/timeline.rss" />
@ <link rel="stylesheet" href="$stylesheet_url" type="text/css" />
@ </head>
@ <body class="$current_feature rpage-$requested_page cpage-$canonical_page">
;
/*
** Returns the default page header.
*/
const char *get_default_header(){
return zDfltHeader;
|
| ︙ | ︙ | |||
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 |
if( zTitle ) Th_Store("title", zTitle);
Th_Store("baseurl", g.zBaseURL);
Th_Store("secureurl", fossil_wants_https(1)? g.zHttpsURL: g.zBaseURL);
Th_Store("home", g.zTop);
Th_Store("index_page", db_get("index-page","/home"));
if( local_zCurrentPage==0 ) style_set_current_page("%T", g.zPath);
Th_Store("current_page", local_zCurrentPage);
Th_Store("csrf_token", g.zCsrfToken);
Th_Store("release_version", RELEASE_VERSION);
Th_Store("manifest_version", MANIFEST_VERSION);
Th_Store("manifest_date", MANIFEST_DATE);
Th_Store("compiler_name", COMPILER_NAME);
Th_Store("mainmenu", style_get_mainmenu());
stylesheet_url_var();
image_url_var("logo");
image_url_var("background");
if( !login_is_nobody() ){
Th_Store("login", g.zLogin);
}
Th_MaybeStore("current_feature", feature_from_page_path(local_zCurrentPage) );
}
/*
** Draw the header.
*/
void style_header(const char *zTitleFormat, ...){
va_list ap;
| > > > > > > > > > > > > > > > > | 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 |
if( zTitle ) Th_Store("title", zTitle);
Th_Store("baseurl", g.zBaseURL);
Th_Store("secureurl", fossil_wants_https(1)? g.zHttpsURL: g.zBaseURL);
Th_Store("home", g.zTop);
Th_Store("index_page", db_get("index-page","/home"));
if( local_zCurrentPage==0 ) style_set_current_page("%T", g.zPath);
Th_Store("current_page", local_zCurrentPage);
if( g.zPath ){ /* store the first segment of a path; */
char *pSlash = strchr(g.zPath,'/');
if( pSlash ) *pSlash = 0; /* make a temporary cut if necessary */
Th_Store("requested_page", escape_quotes(g.zPath));
if( pSlash ) *pSlash = '/';
}else{
Th_Store("requested_page", "");
}
Th_Store("canonical_page", escape_quotes(g.zPhase+1));
Th_Store("csrf_token", g.zCsrfToken);
Th_Store("release_version", RELEASE_VERSION);
Th_Store("manifest_version", MANIFEST_VERSION);
Th_Store("manifest_date", MANIFEST_DATE);
Th_Store("compiler_name", COMPILER_NAME);
Th_Store("mainmenu", style_get_mainmenu());
stylesheet_url_var();
image_url_var("logo");
image_url_var("background");
if( !login_is_nobody() ){
Th_Store("login", g.zLogin);
}
Th_MaybeStore("current_feature", feature_from_page_path(local_zCurrentPage) );
if( g.ftntsIssues[0] || g.ftntsIssues[1] ||
g.ftntsIssues[2] || g.ftntsIssues[3] ){
char buf[80];
sprintf(&buf[0],"%i %i %i %i",g.ftntsIssues[0],g.ftntsIssues[1],
g.ftntsIssues[2],g.ftntsIssues[3]);
Th_Store("footnotes_issues_counters", buf);
}
}
/*
** Draw the header.
*/
void style_header(const char *zTitleFormat, ...){
va_list ap;
|
| ︙ | ︙ | |||
883 884 885 886 887 888 889 |
** Generate code to load all required javascript files.
*/
static void style_load_all_js_files(void){
if( needHrefJs && g.perm.Hyperlink ){
int nDelay = db_get_int("auto-hyperlink-delay",0);
int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0)
&& sqlite3_strglob("*Android*",PD("HTTP_USER_AGENT",""));
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 |
** Generate code to load all required javascript files.
*/
static void style_load_all_js_files(void){
if( needHrefJs && g.perm.Hyperlink ){
int nDelay = db_get_int("auto-hyperlink-delay",0);
int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0)
&& sqlite3_strglob("*Android*",PD("HTTP_USER_AGENT",""));
@ <script id='href-data' type='text/json'>\
@ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
}
@ <script nonce="%h(style_nonce())">/* style.c:%d(__LINE__) */
@ function debugMsg(msg){
@ var n = document.getElementById("debugMsg");
@ if(n){n.textContent=msg;}
@ }
if( needHrefJs && g.perm.Hyperlink ){
@ /* href.js */
cgi_append_content(builtin_text("href.js"),-1);
}
if( blob_size(&blobOnLoad)>0 ){
@ window.onload = function(){
cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad));
cgi_append_content("\n}\n", -1);
}
@ </script>
builtin_fulfill_js_requests();
}
/*
** Transorm input string into a token that is safe for inclusion into
** class attribute. Digits and low-case letter are passed unchanged,
** upper-case letters are transformed to low-case, everything else is
** tranformed into hyphens; consequtive and pending hyphens are squeezed.
** If result does not fit into szOut chars then it is truncated.
** Result is always terminated with null.
*/
void style_derive_classname(const char *zIn, char *zOut, int szOut){
assert( zOut );
assert( szOut>0 );
if( zIn ){
int n = 0; /* number of chars written to zOut */
char c;
for(--szOut; (c=*zIn) && n<szOut; zIn++) {
if( ('a'<=c && c<='z') || ('0'<=c && c<='9') ){
*zOut = c;
}else if( 'A'<=c && c<='Z' ){
*zOut = c - 'A' + 'a';
}else{
if( n==0 || zOut[-1]=='-' ) continue;
*zOut = '-';
}
zOut++;
n++;
}
if( n && zOut[-1]=='-' ) zOut--;
}
*zOut = 0;
}
/*
** Invoke this routine after all of the content for a webpage has been
** generated. This routine should be called once for every webpage, at
** or near the end of page generation. This routine does the following:
**
** * Populates the header of the page, including setting up appropriate
|
| ︙ | ︙ | |||
932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 |
/* Go back and put the submenu at the top of the page. We delay the
** creation of the submenu until the end so that we can add elements
** to the submenu while generating page text.
*/
cgi_destination(CGI_HEADER);
if( submenuEnable && nSubmenu+nSubmenuCtrl>0 ){
int i;
if( nSubmenuCtrl ){
@ <form id='f01' method='GET' action='%R/%s(g.zPath)'>
@ <input type='hidden' name='udc' value='1'>
cgi_tag_query_parameter("udc");
}
@ <div class="submenu">
if( nSubmenu>0 ){
qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare);
for(i=0; i<nSubmenu; i++){
struct Submenu *p = &aSubmenu[i];
/* switching away from the %h formatting below might be dangerous
** because some places use %s to compose zLabel and zLink;
| > > | | | > > | | | | 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 |
/* Go back and put the submenu at the top of the page. We delay the
** creation of the submenu until the end so that we can add elements
** to the submenu while generating page text.
*/
cgi_destination(CGI_HEADER);
if( submenuEnable && nSubmenu+nSubmenuCtrl>0 ){
int i;
char zClass[32]; /* reduced form of the main attribute */
if( nSubmenuCtrl ){
@ <form id='f01' method='GET' action='%R/%s(g.zPath)'>
@ <input type='hidden' name='udc' value='1'>
cgi_tag_query_parameter("udc");
}
@ <div class="submenu">
if( nSubmenu>0 ){
qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare);
for(i=0; i<nSubmenu; i++){
struct Submenu *p = &aSubmenu[i];
style_derive_classname(p->zLabel, zClass, sizeof zClass);
/* switching away from the %h formatting below might be dangerous
** because some places use %s to compose zLabel and zLink;
** e.g. /rptview page. "sml" stands for submenu link.
*/
if( p->zLink==0 ){
@ <span class="label sml-%s(zClass)">%h(p->zLabel)</span>
}else{
@ <a class="label sml-%s(zClass)" href="%h(p->zLink)">%h(p->zLabel)</a>
}
}
}
strcpy(zClass,"smc-"); /* common prefix for submenu controls */
for(i=0; i<nSubmenuCtrl; i++){
const char *zQPN = aSubmenuCtrl[i].zName;
const char *zDisabled = "";
const char *zXtraClass = "";
if( aSubmenuCtrl[i].eVisible & STYLE_DISABLED ){
zDisabled = " disabled";
}else if( zQPN ){
cgi_tag_query_parameter(zQPN);
}
style_derive_classname(zQPN, zClass+4, sizeof(zClass)-4);
switch( aSubmenuCtrl[i].eType ){
case FF_ENTRY:
@ <span class='submenuctrl%s(zXtraClass) %s(zClass)'>\
@ %h(aSubmenuCtrl[i].zLabel)\
@ <input type='text' name='%s(zQPN)' value='%h(PD(zQPN, ""))' \
if( aSubmenuCtrl[i].iSize<0 ){
@ size='%d(-aSubmenuCtrl[i].iSize)' \
}else if( aSubmenuCtrl[i].iSize>0 ){
@ size='%d(aSubmenuCtrl[i].iSize)' \
@ maxlength='%d(aSubmenuCtrl[i].iSize)' \
}
@ id='submenuctrl-%d(i)'%s(zDisabled)></span>
break;
case FF_MULTI: {
int j;
const char *zVal = P(zQPN);
if( zXtraClass[0] ){
@ <span class='%s(zXtraClass+1) %s(zClass)'>
}
if( aSubmenuCtrl[i].zLabel ){
@ %h(aSubmenuCtrl[i].zLabel)\
}
@ <select class='submenuctrl %s(zClass)' size='1' name='%s(zQPN)' \
@ id='submenuctrl-%d(i)'%s(zDisabled)>
for(j=0; j<aSubmenuCtrl[i].iSize*2; j+=2){
const char *zQPV = aSubmenuCtrl[i].azChoice[j];
@ <option value='%h(zQPV)'\
if( fossil_strcmp(zVal, zQPV)==0 ){
@ selected\
}
|
| ︙ | ︙ | |||
1018 1019 1020 1021 1022 1023 1024 |
@ selected\
}
@ >%h(aSubmenuCtrl[i].zFalse)</option>
@ </select>
break;
}
case FF_CHECKBOX: {
| | | 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 |
@ selected\
}
@ >%h(aSubmenuCtrl[i].zFalse)</option>
@ </select>
break;
}
case FF_CHECKBOX: {
@ <label class='submenuctrl submenuckbox%s(zXtraClass) %s(zClass)'>\
@ <input type='checkbox' name='%s(zQPN)' id='submenuctrl-%d(i)' \
if( PB(zQPN) ){
@ checked \
}
if( aSubmenuCtrl[i].zJS ){
@ data-ctrl='%s(aSubmenuCtrl[i].zJS)'%s(zDisabled)>\
}else{
|
| ︙ | ︙ | |||
1167 1168 1169 1170 1171 1172 1173 |
const char *zScript = skin_get("js");
if( P("test") ){
/* Render the script as plain-text for testing purposes, if the "test"
** query parameter is present */
cgi_set_content_type("text/plain");
}else{
/* Default behavior is to return javascript */
| | | 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 |
const char *zScript = skin_get("js");
if( P("test") ){
/* Render the script as plain-text for testing purposes, if the "test"
** query parameter is present */
cgi_set_content_type("text/plain");
}else{
/* Default behavior is to return javascript */
cgi_set_content_type("text/javascript");
}
style_init_th1_vars(0);
Th_Render(zScript?zScript:"");
}
/*
** Check for "name" or "page" query parameters on an /style.css
|
| ︙ | ︙ | |||
1208 1209 1210 1211 1212 1213 1214 | ** /forumXYZ CSS into one file, all /setupXYZ into another, etc. As ** of this writing, doing so would only shave a few kb from ** default.css. */ fossil_free(zFile); } /* | | | 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 | ** /forumXYZ CSS into one file, all /setupXYZ into another, etc. As ** of this writing, doing so would only shave a few kb from ** default.css. */ fossil_free(zFile); } /* ** WEBPAGE: style.css loadavg-exempt ** ** Return the style sheet. The style sheet is assemblied from ** multiple sources, in order: ** ** (1) The built-in "default.css" style sheet containing basic defaults. ** ** (2) The page-specific style sheet taken from the built-in |
| ︙ | ︙ |
Added src/style.pikchrshow.css.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
/* CSS for the WASM /pikchrshow app. */
/* emcscript-related styling, used during the module load/intialization processes... */
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
div.emscripten { text-align: center; }
div.emscripten_border { border: 1px solid black; }
#module-spinner { overflow: visible; }
#module-spinner > * {
margin-top: 1em;
}
.spinner {
height: 50px;
width: 50px;
margin: 0px auto;
animation: rotation 0.8s linear infinite;
border-left: 10px solid rgb(0,150,240);
border-right: 10px solid rgb(0,150,240);
border-bottom: 10px solid rgb(0,150,240);
border-top: 10px solid rgb(100,0,200);
border-radius: 100%;
background-color: rgb(200,100,250);
}
@keyframes rotation {
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}
/* The following styles are for app-level use. */
/* TODO: consolidate the WASM- and legacy-mode CSS into this file.
Since both versions of /pikchrshow share a URI, they both load this
file. */
textarea {
font-family: monospace;
flex: 1 1 auto;
}
#main-wrapper {
display: flex;
flex-direction: column-reverse;
flex: 1 1 auto;
margin: 0.5em 0;
overflow: hidden;
}
#main-wrapper.side-by-side {
flex-direction: row;
}
#main-wrapper.side-by-side > fieldset {
margin-left: 0.25em;
margin-right: 0.25em;
}
#main-wrapper:not(.side-by-side) > fieldset {
margin-bottom: 0.25em;
}
#main-wrapper.swapio {
flex-direction: column;
}
#main-wrapper.side-by-side.swapio {
flex-direction: row-reverse;
}
.zone-wrapper{
display: flex;
margin: 0;
flex: 1 1 0%;
border-radius: 0.5em;
min-width: inherit/*important: resolves inability to scroll fieldset child element!*/;
padding: 0.35em 0 0 0;
}
.zone-wrapper > div {
display:flex;
flex: 1 1 0%;
}
.zone-wrapper.output {
}
#main-wrapper.side-by-side .zone-wrapper {
/* Keep the layout from "flopping around" when
render-while-typing mode is on. */
/*max-width: 50%;*/
}
#pikchr-output {
padding: 0;
margin: 0 auto/*auto resolves a weird left-shift truncation of the SVG*/;
}
#pikchr-output-wrapper {
flex: 1 1 auto;
overflow: auto;
}
#pikchr-output-wrapper.text {
display: flex;
align-items: stretch;
}
#pikchr-output-wrapper.text > #pikchr-output {
display: flex;
align-items: stretch;
flex: 1 1 auto;
}
#pikchr-output-wrapper.text > #pikchr-output > textarea {
flex: 1 1 auto;
}
fieldset > legend {
font-size: 85%;
}
.zone-wrapper textarea {
border-radius: 0.5em;
flex: 1 1 auto;
/*min/max width resolve an inexplicable margin on the RHS. The -1em
is for the padding, else we overlap the parent boundaries.*/
min-width: calc(100% - 1em);
max-width: calc(100% - 1em);
padding: 0 0.5em;
}
.zone-wrapper.input {
min-height: 10em;
/*width: 50%;*/
min-width: 20em;
}
.zone-wrapper textarea {
border: 0;
outline: 0;
}
.zone-wrapper.output {
overflow: auto;
justify-content: space-between;
}
.button-bar {
display: flex;
flex-wrap: wrap;
align-items: center;
align-content: space-between;
justify-content: flex-start;
}
.button-bar > * {
margin: 0.05em 0.5em 0.05em 0;
flex: 0 1 auto;
align-self: auto;
}
fieldset.options {
border-radius: 0.5em;
border: 1px inset;
display: flex;
flex-direction: column;
padding: 0.25em;
}
fieldset.options > div {
display: flex;
flex-wrap: wrap;
font-size: 85%;
}
fieldset.collapsible.options > legend > .fieldset-toggle::after {
content: " [hide]";
position: relative;
}
fieldset.collapsible.collapsed > legend > .fieldset-toggle::after {
content: " [show]";
position: relative;
}
span.labeled-input {
padding: 0.25em;
margin: 0.25em 0.5em;
border-radius: 0.25em;
white-space: nowrap;
background: #0002;
display: flex;
align-items: center;
}
span.labeled-input > *:nth-child(2) {
margin-left: 0.3em;
}
.center { text-align: center; }
.app-view {
flex: 20 1 auto;
}
#titlebar {
display: flex;
justify-content: space-between;
margin-bottom: 0.5em;
}
#view-split {
display: flex;
flex-direction: column-reverse;
}
|
Changes to src/sync.c.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 29 |
#include <assert.h>
/*
** Explain what type of sync operation is about to occur
*/
static void sync_explain(unsigned syncFlags){
if( g.url.isAlias ){
if( (syncFlags & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
| > > > > > > | | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#include <assert.h>
/*
** Explain what type of sync operation is about to occur
*/
static void sync_explain(unsigned syncFlags){
if( g.url.isAlias ){
const char *url;
if( g.url.useProxy ){
url = g.url.proxyUrlCanonical;
}else{
url = g.url.canonical;
}
if( (syncFlags & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
fossil_print("Sync with %s\n", url);
}else if( syncFlags & SYNC_PUSH ){
fossil_print("Push to %s\n", url);
}else if( syncFlags & SYNC_PULL ){
fossil_print("Pull from %s\n", url);
}
}
}
/*
** Call client_sync() one or more times in order to complete a
|
| ︙ | ︙ | |||
110 111 112 113 114 115 116 | ** is attempted if the autosync setting is off, and only auto-pull is ** attempted if autosync is set to "pullonly". The check-in lock is ** not acquired unless autosync is set to "on". ** ** If dont-push setting is true, that is the same as having autosync ** set to pullonly. */ | | | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
** is attempted if the autosync setting is off, and only auto-pull is
** attempted if autosync is set to "pullonly". The check-in lock is
** not acquired unless autosync is set to "on".
**
** If dont-push setting is true, that is the same as having autosync
** set to pullonly.
*/
static int autosync(int flags, const char *zSubsys){
const char *zAutosync;
int rc;
int configSync = 0; /* configuration changes transferred */
if( g.fNoSync ){
return 0;
}
zAutosync = db_get_for_subsystem("autosync", zSubsys);
if( zAutosync==0 ) zAutosync = "on"; /* defend against misconfig */
if( is_false(zAutosync) ) return 0;
if( db_get_boolean("dont-push",0)
|| sqlite3_strglob("*pull*", zAutosync)==0
){
flags &= ~SYNC_CKIN_LOCK;
if( flags & SYNC_PUSH ) return 0;
|
| ︙ | ︙ | |||
148 149 150 151 152 153 154 |
rc = client_sync(flags, configSync, 0, 0);
}
return rc;
}
/*
** This routine will try a number of times to perform autosync with a
| | > | > > | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
rc = client_sync(flags, configSync, 0, 0);
}
return rc;
}
/*
** This routine will try a number of times to perform autosync with a
** 0.5 second sleep between attempts. The number of attempts is determined
** by the "autosync-tries" setting, which defaults to 1.
**
** Return zero on success and non-zero on a failure. If failure occurs
** and doPrompt flag is true, ask the user if they want to continue, and
** if they answer "yes" then return zero in spite of the failure.
*/
int autosync_loop(int flags, int doPrompt, const char *zSubsystem){
int n = 0;
int rc = 0;
int nTries = db_get_int("autosync-tries", 1);
if( (flags & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL)
&& db_get_boolean("uv-sync",0)
){
flags |= SYNC_UNVERSIONED;
}
if( nTries<1 ) nTries = 1;
while( (n==0 || n<nTries) && (rc=autosync(flags, zSubsystem)) ){
if( rc ){
if( ++n<nTries ){
fossil_warning("Autosync failed, making another attempt.");
sqlite3_sleep(500);
}else{
fossil_warning("Autosync failed.");
}
|
| ︙ | ︙ |
Changes to src/tag.c.
| ︙ | ︙ | |||
218 219 220 221 222 223 224 |
}
}
if( zCol ){
db_multi_exec("UPDATE event SET \"%w\"=%Q WHERE objid=%d",
zCol, zValue, rid);
if( tagid==TAG_COMMENT ){
char *zCopy = mprintf("%s", zValue);
| | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
}
}
if( zCol ){
db_multi_exec("UPDATE event SET \"%w\"=%Q WHERE objid=%d",
zCol, zValue, rid);
if( tagid==TAG_COMMENT ){
char *zCopy = mprintf("%s", zValue);
backlink_extract(zCopy, MT_NONE, rid, BKLNK_COMMENT, mtime, 1);
free(zCopy);
}
}
if( tagid==TAG_DATE ){
db_multi_exec("UPDATE event "
" SET mtime=julianday(%Q),"
" omtime=coalesce(omtime,mtime)"
|
| ︙ | ︙ | |||
654 655 656 657 658 659 660 |
const int nTagPrefix = zTagPrefix ? (int)strlen(zTagPrefix) : 0;
db_prepare(&q,
"SELECT tagname FROM tag"
" WHERE EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=tag.tagid"
" AND tagtype%s%d)"
" AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' "
| | | 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 |
const int nTagPrefix = zTagPrefix ? (int)strlen(zTagPrefix) : 0;
db_prepare(&q,
"SELECT tagname FROM tag"
" WHERE EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=tag.tagid"
" AND tagtype%s%d)"
" AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' "
" END ORDER BY tagname COLLATE uintnocase",
zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
nTagType, zTagPrefix, zTagPrefix
);
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
if( fRaw ){
fossil_print("%s\n", zName);
|
| ︙ | ︙ | |||
696 697 698 699 700 701 702 |
nTagOffset = (int)strlen(zTagPrefix);
}
}
db_prepare(&q,
"SELECT tagname, value FROM tagxref, tag"
" WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid"
" AND tagtype%s%d"
| | | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 |
nTagOffset = (int)strlen(zTagPrefix);
}
}
db_prepare(&q,
"SELECT tagname, value FROM tagxref, tag"
" WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid"
" AND tagtype%s%d"
" ORDER BY tagname COLLATE uintnocase",
rid,
zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
nTagType
);
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
const char *zValue = db_column_text(&q, 1);
|
| ︙ | ︙ | |||
815 816 817 818 819 820 821 |
db_prepare(&q,
"SELECT substr(tagname,5)"
" FROM tag"
" WHERE EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=tag.tagid"
" AND tagtype=1)"
" AND tagname GLOB 'sym-*'"
| | | 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 |
db_prepare(&q,
"SELECT substr(tagname,5)"
" FROM tag"
" WHERE EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=tag.tagid"
" AND tagtype=1)"
" AND tagname GLOB 'sym-*'"
" ORDER BY tagname COLLATE uintnocase"
);
@ <ul>
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
if( g.perm.Hyperlink ){
@ <li>%z(chref("taglink","%R/timeline?t=%T",zName))
@ %h(zName)</a></li>
|
| ︙ | ︙ |
Changes to src/tar.c.
| ︙ | ︙ | |||
774 775 776 777 778 779 780 |
Glob *pInclude = 0; /* The compiled in= glob pattern */
Glob *pExclude = 0; /* The compiled ex= glob pattern */
Blob tarball; /* Tarball accumulated here */
const char *z;
login_check_credentials();
if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; }
| | | 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 |
Glob *pInclude = 0; /* The compiled in= glob pattern */
Glob *pExclude = 0; /* The compiled ex= glob pattern */
Blob tarball; /* Tarball accumulated here */
const char *z;
login_check_credentials();
if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; }
fossil_nice_default();
zName = fossil_strdup(PD("name",""));
z = P("r");
if( z==0 ) z = P("uuid");
if( z==0 ) z = tar_uuid_from_name(&zName);
if( z==0 ) z = "trunk";
g.zOpenRevision = zRid = fossil_strdup(z);
nRid = strlen(zRid);
|
| ︙ | ︙ |
Changes to src/timeline.c.
| ︙ | ︙ | |||
522 523 524 525 526 527 528 |
@ Wiki page "%z(href("%R/wiki?name=%t",zCom+1))%h(zCom+1)</a>"
}else if( zCom[0]=='+' ){
@ Added wiki page "%z(href("%R/wiki?name=%t",zCom+1))%h(zCom+1)</a>"
}else if( zCom[0]==':' ){
@ Changes to wiki page "%z(href("%R/wiki?name=%t",zCom+1))\
@ %h(zCom+1)</a>"
}else{
| | | | > | 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 |
@ Wiki page "%z(href("%R/wiki?name=%t",zCom+1))%h(zCom+1)</a>"
}else if( zCom[0]=='+' ){
@ Added wiki page "%z(href("%R/wiki?name=%t",zCom+1))%h(zCom+1)</a>"
}else if( zCom[0]==':' ){
@ Changes to wiki page "%z(href("%R/wiki?name=%t",zCom+1))\
@ %h(zCom+1)</a>"
}else{
/* Assume this is an attachment message. It _might_ also
** be a legacy-format wiki log entry, in which case it
** will simply be rendered in the older format. */
wiki_convert(&comment, 0, WIKI_INLINE);
}
wiki_hyperlink_override(0);
}else{
wiki_convert(&comment, 0, WIKI_INLINE);
}
}else{
if( bCommentGitStyle ){
|
| ︙ | ︙ |
Changes to src/tkt.c.
| ︙ | ︙ | |||
21 22 23 24 25 26 27 | #include "config.h" #include "tkt.h" #include <assert.h> /* ** The list of database user-defined fields in the TICKET table. ** The real table also contains some addition fields for internal | | > > > > | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
#include "config.h"
#include "tkt.h"
#include <assert.h>
/*
** The list of database user-defined fields in the TICKET table.
** The real table also contains some addition fields for internal
** use. The internal-use fields begin with "tkt_".
*/
static int nField = 0;
static struct tktFieldInfo {
char *zName; /* Name of the database field */
char *zValue; /* Value to store */
char *zAppend; /* Value to append */
unsigned mUsed; /* 01: TICKET 02: TICKETCHNG */
} *aField;
#define USEDBY_TICKET 01
#define USEDBY_TICKETCHNG 02
#define USEDBY_BOTH 03
static u8 haveTicket = 0; /* True if the TICKET table exists */
static u8 haveTicketCTime = 0; /* True if TICKET.TKT_CTIME exists */
static u8 haveTicketChng = 0; /* True if the TICKETCHNG table exists */
static u8 haveTicketChngRid = 0; /* True if TICKETCHNG.TKT_RID exists */
static u8 haveTicketChngUser = 0;/* True if TICKETCHNG.TKT_USER exists */
static u8 useTicketGenMt = 0; /* use generated TICKET.MIMETYPE */
static u8 useTicketChngGenMt = 0;/* use generated TICKETCHNG.MIMETYPE */
/*
** Compare two entries in aField[] for sorting purposes
*/
static int nameCmpr(const void *a, const void *b){
return fossil_strcmp(((const struct tktFieldInfo*)a)->zName,
((const struct tktFieldInfo*)b)->zName);
|
| ︙ | ︙ | |||
67 68 69 70 71 72 73 |
** in sorted order in aField[].
**
** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and
** TICKETCHANGE tables exist, respectively.
*/
static void getAllTicketFields(void){
Stmt q;
| | > | > > > > > > > > > > > > > > > > > | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
** in sorted order in aField[].
**
** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and
** TICKETCHANGE tables exist, respectively.
*/
static void getAllTicketFields(void){
Stmt q;
int i, noRegularMimetype;
static int once = 0;
if( once ) return;
once = 1;
db_prepare(&q, "PRAGMA table_info(ticket)");
while( db_step(&q)==SQLITE_ROW ){
const char *zFieldName = db_column_text(&q, 1);
haveTicket = 1;
if( memcmp(zFieldName,"tkt_",4)==0 ){
if( strcmp(zFieldName, "tkt_ctime")==0 ) haveTicketCTime = 1;
continue;
}
if( strchr(zFieldName,' ')!=0 ) continue;
if( nField%10==0 ){
aField = fossil_realloc(aField, sizeof(aField[0])*(nField+10) );
}
aField[nField].zName = mprintf("%s", zFieldName);
aField[nField].mUsed = USEDBY_TICKET;
nField++;
}
db_finalize(&q);
db_prepare(&q, "PRAGMA table_info(ticketchng)");
while( db_step(&q)==SQLITE_ROW ){
const char *zFieldName = db_column_text(&q, 1);
haveTicketChng = 1;
if( memcmp(zFieldName,"tkt_",4)==0 ){
if( strcmp(zFieldName+4,"rid")==0 ){
haveTicketChngRid = 1; /* tkt_rid */
}else if( strcmp(zFieldName+4,"user")==0 ){
haveTicketChngUser = 1; /* tkt_user */
}
continue;
}
if( strchr(zFieldName,' ')!=0 ) continue;
if( (i = fieldId(zFieldName))>=0 ){
aField[i].mUsed |= USEDBY_TICKETCHNG;
continue;
}
if( nField%10==0 ){
aField = fossil_realloc(aField, sizeof(aField[0])*(nField+10) );
}
aField[nField].zName = mprintf("%s", zFieldName);
aField[nField].mUsed = USEDBY_TICKETCHNG;
nField++;
}
db_finalize(&q);
qsort(aField, nField, sizeof(aField[0]), nameCmpr);
noRegularMimetype = 1;
for(i=0; i<nField; i++){
aField[i].zValue = "";
aField[i].zAppend = 0;
if( strcmp(aField[i].zName,"mimetype")==0 ){
noRegularMimetype = 0;
}
}
if( noRegularMimetype ){ /* check for generated "mimetype" columns */
useTicketGenMt = db_exists(
"SELECT 1 FROM pragma_table_xinfo('ticket') "
"WHERE name = 'mimetype'");
useTicketChngGenMt = db_exists(
"SELECT 1 FROM pragma_table_xinfo('ticketchng') "
"WHERE name = 'mimetype'");
}
}
/*
** Query the database for all TICKET fields for the specific
** ticket whose name is given by the "name" CGI parameter.
** Load the values for all fields into the interpreter.
|
| ︙ | ︙ | |||
187 188 189 190 191 192 193 | ** the appropriate TICKET table entry if tktid is zero. If tktid is nonzero ** then it will be the ROWID of an existing TICKET entry. ** ** Parameter rid is the recordID for the ticket artifact in the BLOB table. ** ** Return the new rowid of the TICKET table entry. */ | | | > > | | | < | < | | < < < < | | < < > > | < < < < < | < > > > > > > > > > | | > > > > | | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 |
** the appropriate TICKET table entry if tktid is zero. If tktid is nonzero
** then it will be the ROWID of an existing TICKET entry.
**
** Parameter rid is the recordID for the ticket artifact in the BLOB table.
**
** Return the new rowid of the TICKET table entry.
*/
static int ticket_insert(const Manifest *p, const int rid, int tktid){
Blob sql1; /* update or replace TICKET ... */
Blob sql2; /* list of TICKETCHNG's fields that are in the manifest */
Blob sql3; /* list of values which correspond to the previous list */
Stmt q;
int i, j;
char *aUsed;
int mimetype_tkt = MT_NONE, mimetype_tktchng = MT_NONE;
if( tktid==0 ){
db_multi_exec("INSERT INTO ticket(tkt_uuid, tkt_mtime) "
"VALUES(%Q, 0)", p->zTicketUuid);
tktid = db_last_insert_rowid();
}
blob_zero(&sql1);
blob_zero(&sql2);
blob_zero(&sql3);
blob_append_sql(&sql1, "UPDATE OR REPLACE ticket SET tkt_mtime=:mtime");
if( haveTicketCTime ){
blob_append_sql(&sql1, ", tkt_ctime=coalesce(tkt_ctime,:mtime)");
}
aUsed = fossil_malloc( nField );
memset(aUsed, 0, nField);
for(i=0; i<p->nField; i++){
const char * const zName = p->aField[i].zName;
const char * const zBaseName = zName[0]=='+' ? zName+1 : zName;
j = fieldId(zBaseName);
if( j<0 ) continue;
aUsed[j] = 1;
if( aField[j].mUsed & USEDBY_TICKET ){
if( zName[0]=='+' ){
blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q",
zBaseName, zBaseName, p->aField[i].zValue);
}else{
blob_append_sql(&sql1,", \"%w\"=%Q", zBaseName, p->aField[i].zValue);
}
}
if( aField[j].mUsed & USEDBY_TICKETCHNG ){
blob_append_sql(&sql2, ",\"%w\"", zBaseName);
blob_append_sql(&sql3, ",%Q", p->aField[i].zValue);
}
if( strcmp(zBaseName,"mimetype")==0 ){
const char *zMimetype = p->aField[i].zValue;
/* "mimetype" is a regular column => these two flags must be 0 */
assert(!useTicketGenMt);
assert(!useTicketChngGenMt);
mimetype_tkt = mimetype_tktchng = parse_mimetype( zMimetype );
}
}
blob_append_sql(&sql1, " WHERE tkt_id=%d", tktid);
if( useTicketGenMt ){
blob_append_literal(&sql1, " RETURNING mimetype");
}
db_prepare(&q, "%s", blob_sql_text(&sql1));
db_bind_double(&q, ":mtime", p->rDate);
db_step(&q);
if( useTicketGenMt ){
mimetype_tkt = parse_mimetype( db_column_text(&q,0) );
if( !useTicketChngGenMt ){
mimetype_tktchng = mimetype_tkt;
}
}
db_finalize(&q);
blob_reset(&sql1);
if( blob_size(&sql2)>0 || haveTicketChngRid || haveTicketChngUser ){
int fromTkt = 0;
if( haveTicketChngRid ){
blob_append_literal(&sql2, ",tkt_rid");
blob_append_sql(&sql3, ",%d", rid);
}
if( haveTicketChngUser && p->zUser ){
blob_append_literal(&sql2, ",tkt_user");
blob_append_sql(&sql3, ",%Q", p->zUser);
}
for(i=0; i<nField; i++){
if( aUsed[i]==0
&& (aField[i].mUsed & USEDBY_BOTH)==USEDBY_BOTH
){
const char *z = aField[i].zName;
if( z[0]=='+' ) z++;
fromTkt = 1;
blob_append_sql(&sql2, ",\"%w\"", z);
blob_append_sql(&sql3, ",\"%w\"", z);
}
}
if( fromTkt ){
db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
"SELECT %d,:mtime%s FROM ticket WHERE tkt_id=%d%s",
blob_sql_text(&sql2), tktid,
blob_sql_text(&sql3), tktid,
useTicketChngGenMt ? " RETURNING mimetype" : "");
}else{
db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
"VALUES(%d,:mtime%s)%s",
blob_sql_text(&sql2), tktid, blob_sql_text(&sql3),
useTicketChngGenMt ? " RETURNING mimetype" : "");
}
db_bind_double(&q, ":mtime", p->rDate);
db_step(&q);
if( useTicketChngGenMt ){
mimetype_tktchng = parse_mimetype( db_column_text(&q, 0) );
/* substitute NULL with a value generated within another table */
if( !useTicketGenMt ){
mimetype_tkt = mimetype_tktchng;
}else if( mimetype_tktchng==MT_NONE ){
mimetype_tktchng = mimetype_tkt;
}else if( mimetype_tkt==MT_NONE ){
mimetype_tkt = mimetype_tktchng;
}
}
db_finalize(&q);
}
blob_reset(&sql2);
blob_reset(&sql3);
fossil_free(aUsed);
if( rid>0 ){ /* extract backlinks */
int bReplace = 1, mimetype;
for(i=0; i<p->nField; i++){
const char *zName = p->aField[i].zName;
const char *zBaseName = zName[0]=='+' ? zName+1 : zName;
j = fieldId(zBaseName);
if( j<0 ) continue;
if( aField[j].mUsed & USEDBY_TICKETCHNG ){
mimetype = mimetype_tktchng;
}else{
mimetype = mimetype_tkt;
}
backlink_extract(p->aField[i].zValue, mimetype, rid, BKLNK_TICKET,
p->rDate, bReplace);
bReplace = 0;
}
}
return tktid;
}
/*
** Returns non-zero if moderation is required for ticket changes and ticket
** attachments.
*/
|
| ︙ | ︙ |
Changes to src/tktsetup.c.
| ︙ | ︙ | |||
84 85 86 87 88 89 90 91 92 93 94 95 96 97 | @ comment TEXT @ ); @ CREATE TABLE ticketchng( @ -- Do not change any column that begins with tkt_ @ tkt_id INTEGER REFERENCES ticket, @ tkt_rid INTEGER REFERENCES blob, @ tkt_mtime DATE, @ -- Add as many fields as required below this line @ login TEXT, @ username TEXT, @ mimetype TEXT, @ icomment TEXT @ ); @ CREATE INDEX ticketchng_idx1 ON ticketchng(tkt_id, tkt_mtime); | > | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | @ comment TEXT @ ); @ CREATE TABLE ticketchng( @ -- Do not change any column that begins with tkt_ @ tkt_id INTEGER REFERENCES ticket, @ tkt_rid INTEGER REFERENCES blob, @ tkt_mtime DATE, @ tkt_user TEXT, @ -- Add as many fields as required below this line @ login TEXT, @ username TEXT, @ mimetype TEXT, @ icomment TEXT @ ); @ CREATE INDEX ticketchng_idx1 ON ticketchng(tkt_id, tkt_mtime); |
| ︙ | ︙ |
Changes to src/update.c.
| ︙ | ︙ | |||
163 164 165 166 167 168 169 |
/* We should be done with options.. */
verify_all_options();
db_must_be_within_tree();
vid = db_lget_int("checkout", 0);
user_select();
if( !dryRunFlag && !internalUpdate && !bNosync ){
| | < | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
/* We should be done with options.. */
verify_all_options();
db_must_be_within_tree();
vid = db_lget_int("checkout", 0);
user_select();
if( !dryRunFlag && !internalUpdate && !bNosync ){
if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag, 1, "update") ){
fossil_fatal("update abandoned due to sync failure");
}
}
/* Create any empty directories now, as well as after the update,
** so changes in settings are reflected now */
if( !dryRunFlag ) ensure_empty_dirs_created(0);
|
| ︙ | ︙ |
Changes to src/url.c.
| ︙ | ︙ | |||
61 62 63 64 65 66 67 | char *user; /* User id for http: */ char *passwd; /* Password for http: */ char *canonical; /* Canonical representation of the URL */ char *proxyAuth; /* Proxy-Authorizer: string */ char *fossil; /* The fossil query parameter on ssh: */ unsigned flags; /* Boolean flags controlling URL processing */ int useProxy; /* Used to remember that a proxy is in use */ | | > | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | char *user; /* User id for http: */ char *passwd; /* Password for http: */ char *canonical; /* Canonical representation of the URL */ char *proxyAuth; /* Proxy-Authorizer: string */ char *fossil; /* The fossil query parameter on ssh: */ unsigned flags; /* Boolean flags controlling URL processing */ int useProxy; /* Used to remember that a proxy is in use */ char *proxyUrlPath; /* Remember path when proxy is use */ char *proxyUrlCanonical; /* Remember canonical path when proxy is use */ int proxyOrigPort; /* Tunneled port number for https through proxy */ }; #endif /* INTERFACE */ /* ** Parse the URL in the zUrl argument. Store results in the pUrlData object. |
| ︙ | ︙ | |||
532 533 534 535 536 537 538 |
** by the canonical name of the proxy (with userid and password suppressed).
*/
void url_enable_proxy(const char *zMsg){
const char *zProxy;
zProxy = zProxyOpt;
if( zProxy==0 ){
zProxy = db_get("proxy", 0);
| | | 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 |
** by the canonical name of the proxy (with userid and password suppressed).
*/
void url_enable_proxy(const char *zMsg){
const char *zProxy;
zProxy = zProxyOpt;
if( zProxy==0 ){
zProxy = db_get("proxy", 0);
if( fossil_strcmp(zProxy, "system")==0 ){
zProxy = fossil_getenv("http_proxy");
}
}
if( zProxy && zProxy[0] && !is_false(zProxy)
&& !g.url.isSsh && !g.url.isFile ){
char *zOriginalUrl = g.url.canonical;
char *zOriginalHost = g.url.hostname;
|
| ︙ | ︙ | |||
562 563 564 565 566 567 568 569 570 571 572 573 574 575 |
g.url.proxyAuth = mprintf("Basic %z", zCredentials2);
free(zCredentials1);
}
g.url.user = zOriginalUser;
g.url.passwd = zOriginalPasswd;
g.url.isHttps = fOriginalIsHttps;
g.url.useProxy = 1;
g.url.proxyUrlPath = zOriginalUrlPath;
g.url.proxyOrigPort = iOriginalPort;
g.url.flags = uOriginalFlags;
}
}
#if INTERFACE
| > | 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 |
g.url.proxyAuth = mprintf("Basic %z", zCredentials2);
free(zCredentials1);
}
g.url.user = zOriginalUser;
g.url.passwd = zOriginalPasswd;
g.url.isHttps = fOriginalIsHttps;
g.url.useProxy = 1;
g.url.proxyUrlCanonical = zOriginalUrl;;
g.url.proxyUrlPath = zOriginalUrlPath;
g.url.proxyOrigPort = iOriginalPort;
g.url.flags = uOriginalFlags;
}
}
#if INTERFACE
|
| ︙ | ︙ | |||
720 721 722 723 724 725 726 727 |
}
/*
** Remember the URL and password if requested.
*/
void url_remember(void){
if( g.url.flags & URL_REMEMBER ){
if( g.url.flags & URL_USE_PARENT ){
| > > > > > > | | | 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 |
}
/*
** Remember the URL and password if requested.
*/
void url_remember(void){
if( g.url.flags & URL_REMEMBER ){
const char *url;
if( g.url.useProxy ){
url = g.url.proxyUrlCanonical;
}else{
url = g.url.canonical;
}
if( g.url.flags & URL_USE_PARENT ){
db_set("parent-project-url", url, 0);
}else{
db_set("last-sync-url", url, 0);
}
if( g.url.user!=0 && g.url.passwd!=0 && ( g.url.flags & URL_REMEMBER_PW ) ){
if( g.url.flags & URL_USE_PARENT ){
db_set("parent-project-pw", obscure(g.url.passwd), 0);
}else{
db_set("last-sync-pw", obscure(g.url.passwd), 0);
}
|
| ︙ | ︙ |
Changes to src/util.c.
| ︙ | ︙ | |||
894 895 896 897 898 899 900 |
break;
}
}
}
#endif
return zBrowser;
}
| > > > > > > > > > > > > > > > > > > > > > | 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 |
break;
}
}
}
#endif
return zBrowser;
}
/*
** On non-Windows systems, calls nice(2) with the given level. Errors
** are ignored. On Windows this is a no-op.
*/
void fossil_nice(int level){
#ifndef _WIN32
/* dummy if() condition to avoid nuisance warning about unused result on
certain compiler */
if( nice(level) ){ /*ignored*/ }
#else
(void)level;
#endif
}
/*
** Calls fossil_nice() with a default level.
*/
void fossil_nice_default(void){
fossil_nice(19);
}
|
Changes to src/wiki.c.
| ︙ | ︙ | |||
1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 |
** List all available wiki pages with date created and last modified.
*/
void wcontent_page(void){
Stmt q;
double rNow;
int showAll = P("all")!=0;
int showRid = P("showid")!=0;
login_check_credentials();
if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
style_set_current_feature("wiki");
style_header("Available Wiki Pages");
if( showAll ){
style_submenu_element("Active", "%R/wcontent");
}else{
style_submenu_element("All", "%R/wcontent?all=1");
}
wiki_standard_submenu(W_ALL_BUT(W_LIST));
db_prepare(&q, listAllWikiPages/*works-like:""*/);
@ <div class="brlist">
@ <table class='sortable' data-column-types='tKN' data-init-sort='1'>
@ <thead><tr>
@ <th>Name</th>
@ <th>Last Change</th>
| > > | 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 |
** List all available wiki pages with date created and last modified.
*/
void wcontent_page(void){
Stmt q;
double rNow;
int showAll = P("all")!=0;
int showRid = P("showid")!=0;
int showCkBr = P("showckbr")!=0;
login_check_credentials();
if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
style_set_current_feature("wiki");
style_header("Available Wiki Pages");
if( showAll ){
style_submenu_element("Active", "%R/wcontent");
}else{
style_submenu_element("All", "%R/wcontent?all=1");
}
style_submenu_checkbox("showckbr", "Show associated wikis", 0, 0);
wiki_standard_submenu(W_ALL_BUT(W_LIST));
db_prepare(&q, listAllWikiPages/*works-like:""*/);
@ <div class="brlist">
@ <table class='sortable' data-column-types='tKN' data-init-sort='1'>
@ <thead><tr>
@ <th>Name</th>
@ <th>Last Change</th>
|
| ︙ | ︙ | |||
1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 |
int wcnt = db_column_int(&q, 4);
char *zWDisplayName;
if( sqlite3_strglob("checkin/*", zWName)==0 ){
zWDisplayName = mprintf("%.25s...", zWName);
}else{
zWDisplayName = mprintf("%s", zWName);
}
if( wrid==0 ){
if( !showAll ) continue;
@ <tr><td data-sortkey="%h(zSort)">\
@ %z(href("%R/whistory?name=%T",zWName))<s>%h(zWDisplayName)</s></a></td>
}else{
@ <tr><td data-sortkey="%h(zSort)">\
| > > > > > | 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 |
int wcnt = db_column_int(&q, 4);
char *zWDisplayName;
if( sqlite3_strglob("checkin/*", zWName)==0 ){
zWDisplayName = mprintf("%.25s...", zWName);
}else{
zWDisplayName = mprintf("%s", zWName);
}
if( !showCkBr &&
(sqlite3_strglob("checkin/*", zWName)==0 ||
sqlite3_strglob("branch/*", zWName)==0) ){
continue;
}
if( wrid==0 ){
if( !showAll ) continue;
@ <tr><td data-sortkey="%h(zSort)">\
@ %z(href("%R/whistory?name=%T",zWName))<s>%h(zWDisplayName)</s></a></td>
}else{
@ <tr><td data-sortkey="%h(zSort)">\
|
| ︙ | ︙ | |||
2180 2181 2182 2183 2184 2185 2186 | ** --technote-bgcolor COLOR The color used for the technote ** on the timeline. ** ** > fossil wiki list ?OPTIONS? ** > fossil wiki ls ?OPTIONS? ** ** Lists all wiki entries, one per line, ordered | | > > > | 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 | ** --technote-bgcolor COLOR The color used for the technote ** on the timeline. ** ** > fossil wiki list ?OPTIONS? ** > fossil wiki ls ?OPTIONS? ** ** Lists all wiki entries, one per line, ordered ** case-insensitively by name. Wiki pages associated with ** check-ins and branches are NOT shown, unless -a is given. ** ** Options: ** --all Include "deleted" pages in output. ** By default deleted pages are elided. ** -t|--technote Technotes will be listed instead of ** pages. The technotes will be in order ** of timestamp with the most recent ** first. ** -a|--show-associated Show wiki pages associated with ** check-ins and branches. ** -s|--show-technote-ids The id of the tech note will be listed ** along side the timestamp. The tech note ** id will be the first word on each line. ** This option only applies if the ** --technote option is also specified. ** ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in |
| ︙ | ︙ | |||
2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 |
}
fossil_fatal("delete not yet implemented.");
}else if(( strncmp(g.argv[2],"list",n)==0 )
|| ( strncmp(g.argv[2],"ls",n)==0 )){
Stmt q;
const int fTechnote = find_option("technote","t",0)!=0;
const int showIds = find_option("show-technote-ids","s",0)!=0;
verify_all_options();
if (fTechnote==0){
db_prepare(&q, listAllWikiPages/*works-like:""*/);
}else{
db_prepare(&q,
"SELECT datetime(e.mtime), substr(t.tagname,7), e.objid"
" FROM event e, tag t"
" WHERE e.type='e'"
" AND e.tagid IS NOT NULL"
" AND t.tagid=e.tagid"
" ORDER BY e.mtime DESC /*sort*/"
);
}
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
const int wrid = db_column_int(&q, 2);
if(!showAll && !wrid){
continue;
}
if( showIds ){
const char *zUuid = db_column_text(&q, 1);
fossil_print("%s ",zUuid);
}
fossil_print( "%s\n",zName);
}
| > > > > > > | 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 |
}
fossil_fatal("delete not yet implemented.");
}else if(( strncmp(g.argv[2],"list",n)==0 )
|| ( strncmp(g.argv[2],"ls",n)==0 )){
Stmt q;
const int fTechnote = find_option("technote","t",0)!=0;
const int showIds = find_option("show-technote-ids","s",0)!=0;
const int showCkBr = find_option("show-associated","a",0)!=0;
verify_all_options();
if (fTechnote==0){
db_prepare(&q, listAllWikiPages/*works-like:""*/);
}else{
db_prepare(&q,
"SELECT datetime(e.mtime), substr(t.tagname,7), e.objid"
" FROM event e, tag t"
" WHERE e.type='e'"
" AND e.tagid IS NOT NULL"
" AND t.tagid=e.tagid"
" ORDER BY e.mtime DESC /*sort*/"
);
}
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
const int wrid = db_column_int(&q, 2);
if(!showAll && !wrid){
continue;
}
if( !showCkBr &&
(sqlite3_strglob("checkin/*", zName)==0 ||
sqlite3_strglob("branch/*", zName)==0) ){
continue;
}
if( showIds ){
const char *zUuid = db_column_text(&q, 1);
fossil_print("%s ",zUuid);
}
fossil_print( "%s\n",zName);
}
|
| ︙ | ︙ |
Changes to src/wikiformat.c.
| ︙ | ︙ | |||
173 174 175 176 177 178 179 | /* ** Allowed markup. ** ** Except for MARKUP_INVALID, this must all be in alphabetical order ** and in numerical sequence. The first markup type must be zero. ** The value for MARKUP_XYZ must correspond to the <xyz> entry | | > | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
/*
** Allowed markup.
**
** Except for MARKUP_INVALID, this must all be in alphabetical order
** and in numerical sequence. The first markup type must be zero.
** The value for MARKUP_XYZ must correspond to the <xyz> entry
** in aMarkup[].
*/
enum markup_t {
MARKUP_INVALID = 0,
MARKUP_A,
MARKUP_ABBR,
MARKUP_ADDRESS,
MARKUP_HTML5_ARTICLE,
MARKUP_HTML5_ASIDE,
MARKUP_B,
MARKUP_BIG,
MARKUP_BLOCKQUOTE,
MARKUP_BR,
MARKUP_CENTER,
MARKUP_CITE,
MARKUP_CODE,
MARKUP_COL,
MARKUP_COLGROUP,
MARKUP_DD,
MARKUP_DEL,
MARKUP_DFN,
MARKUP_DIV,
MARKUP_DL,
MARKUP_DT,
MARKUP_EM,
MARKUP_FONT,
MARKUP_HTML5_FOOTER,
MARKUP_H1,
MARKUP_H2,
MARKUP_H3,
MARKUP_H4,
MARKUP_H5,
MARKUP_H6,
MARKUP_HTML5_HEADER,
MARKUP_HR,
MARKUP_I,
MARKUP_IMG,
MARKUP_INS,
MARKUP_KBD,
MARKUP_LI,
MARKUP_HTML5_NAV,
MARKUP_NOBR,
MARKUP_NOWIKI,
MARKUP_OL,
MARKUP_P,
MARKUP_PRE,
MARKUP_S,
MARKUP_SAMP,
MARKUP_HTML5_SECTION,
MARKUP_SMALL,
MARKUP_SPAN,
MARKUP_STRIKE,
MARKUP_STRONG,
MARKUP_SUB,
MARKUP_SUP,
MARKUP_TABLE,
MARKUP_TBODY,
MARKUP_TD,
MARKUP_TFOOT,
MARKUP_TH,
MARKUP_THEAD,
MARKUP_TITLE,
MARKUP_TR,
MARKUP_TT,
MARKUP_U,
MARKUP_UL,
MARKUP_VAR,
MARKUP_VERBATIM
};
/*
** The various markup is divided into the following types:
*/
#define MUTYPE_SINGLE 0x0001 /* <img>, <br>, or <hr> */
#define MUTYPE_BLOCK 0x0002 /* Forms a new paragraph. ex: <p>, <h2> */
#define MUTYPE_FONT 0x0004 /* Font changes. ex: <b>, <font>, <sub> */
|
| ︙ | ︙ | |||
277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
short int iType; /* The MUTYPE_* code */
int allowedAttr; /* Allowed attributes on this markup */
} aMarkup[] = {
{ 0, MARKUP_INVALID, 0, 0 },
{ "a", MARKUP_A, MUTYPE_HYPERLINK,
AMSK_HREF|AMSK_NAME|AMSK_CLASS|AMSK_TARGET|AMSK_STYLE|
AMSK_TITLE},
{ "address", MARKUP_ADDRESS, MUTYPE_BLOCK, AMSK_STYLE },
{ "article", MARKUP_HTML5_ARTICLE, MUTYPE_BLOCK,
AMSK_ID|AMSK_CLASS|AMSK_STYLE },
{ "aside", MARKUP_HTML5_ASIDE, MUTYPE_BLOCK,
AMSK_ID|AMSK_CLASS|AMSK_STYLE },
{ "b", MARKUP_B, MUTYPE_FONT, AMSK_STYLE },
| > > | 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
short int iType; /* The MUTYPE_* code */
int allowedAttr; /* Allowed attributes on this markup */
} aMarkup[] = {
{ 0, MARKUP_INVALID, 0, 0 },
{ "a", MARKUP_A, MUTYPE_HYPERLINK,
AMSK_HREF|AMSK_NAME|AMSK_CLASS|AMSK_TARGET|AMSK_STYLE|
AMSK_TITLE},
{ "abbr", MARKUP_ABBR, MUTYPE_FONT,
AMSK_ID|AMSK_CLASS|AMSK_STYLE|AMSK_TITLE },
{ "address", MARKUP_ADDRESS, MUTYPE_BLOCK, AMSK_STYLE },
{ "article", MARKUP_HTML5_ARTICLE, MUTYPE_BLOCK,
AMSK_ID|AMSK_CLASS|AMSK_STYLE },
{ "aside", MARKUP_HTML5_ASIDE, MUTYPE_BLOCK,
AMSK_ID|AMSK_CLASS|AMSK_STYLE },
{ "b", MARKUP_B, MUTYPE_FONT, AMSK_STYLE },
|
| ︙ | ︙ | |||
1891 1892 1893 1894 1895 1896 1897 | ** COMMAND: test-markdown-render ** ** Usage: %fossil test-markdown-render FILE ... ** ** Render markdown in FILE as HTML on stdout. ** Options: ** | | > | > > > > > > > > > > > | 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 |
** COMMAND: test-markdown-render
**
** Usage: %fossil test-markdown-render FILE ...
**
** Render markdown in FILE as HTML on stdout.
** Options:
**
** --safe Restrict the output to use only "safe" HTML
** --lint-footnotes Print stats for footnotes-related issues
*/
void test_markdown_render(void){
Blob in, out;
int i;
int bSafe = 0, bFnLint = 0;
db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
bSafe = find_option("safe",0,0)!=0;
bFnLint = find_option("lint-footnotes",0,0)!=0;
verify_all_options();
for(i=2; i<g.argc; i++){
blob_zero(&out);
blob_read_from_file(&in, g.argv[i], ExtFILE);
if( g.argc>3 ){
fossil_print("<!------ %h ------->\n", g.argv[i]);
}
markdown_to_html(&in, 0, &out);
safe_html_context( bSafe ? DOCSRC_UNTRUSTED : DOCSRC_TRUSTED );
safe_html(&out);
blob_write_to_file(&out, "-");
blob_reset(&in);
blob_reset(&out);
}
if( bFnLint && (g.ftntsIssues[0] || g.ftntsIssues[1]
|| g.ftntsIssues[2] || g.ftntsIssues[3] )){
fossil_fatal("There were issues with footnotes:\n"
" %8d misreference%s\n"
" %8d unreferenced\n"
" %8d splitted\n"
" %8d overnested",
g.ftntsIssues[0], g.ftntsIssues[0]==1?"":"s",
g.ftntsIssues[1], g.ftntsIssues[2], g.ftntsIssues[3]);
}
}
/*
** Search for a <title>...</title> at the beginning of a wiki page.
** Return true (nonzero) if a title is found. Return zero if there is
** not title.
**
|
| ︙ | ︙ |
Changes to src/winhttp.c.
| ︙ | ︙ | |||
614 615 616 617 618 619 620 621 622 623 624 625 626 627 |
if( zSkin ){
blob_appendf(&options, " --skin %s", zSkin);
}
if( g.zMainMenuFile ){
blob_appendf(&options, " --mainmenu ");
blob_append_escaped_arg(&options, g.zMainMenuFile, 1);
}
#if USE_SEE
zSavedKey = db_get_saved_encryption_key();
savedKeySize = db_get_saved_encryption_key_size();
if( zSavedKey!=0 && savedKeySize>0 ){
blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(),
zSavedKey, savedKeySize);
}
| > > > > | 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 |
if( zSkin ){
blob_appendf(&options, " --skin %s", zSkin);
}
if( g.zMainMenuFile ){
blob_appendf(&options, " --mainmenu ");
blob_append_escaped_arg(&options, g.zMainMenuFile, 1);
}
if( builtin_get_js_delivery_mode()!=0 /* JS_INLINE==0 may change? */ ){
blob_appendf(&options, " --jsmode ");
blob_append_escaped_arg(&options, builtin_get_js_delivery_mode_name(), 0);
}
#if USE_SEE
zSavedKey = db_get_saved_encryption_key();
savedKeySize = db_get_saved_encryption_key_size();
if( zSavedKey!=0 && savedKeySize>0 ){
blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(),
zSavedKey, savedKeySize);
}
|
| ︙ | ︙ |
Changes to src/zip.c.
| ︙ | ︙ | |||
253 254 255 256 257 258 259 |
const Blob *pFile,
int mPerm
){
z_stream stream;
int nameLen;
int toOut = 0;
int iStart;
| | | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
const Blob *pFile,
int mPerm
){
z_stream stream;
int nameLen;
int toOut = 0;
int iStart;
unsigned long iCRC = 0;
int nByte = 0;
int nByteCompr = 0;
int nBlob; /* Size of the blob */
int iMethod; /* Compression method. */
int iMode = 0644; /* Access permissions */
char *z;
char zHdr[30];
|
| ︙ | ︙ | |||
940 941 942 943 944 945 946 |
if( fossil_strcmp(g.zPath, "sqlar")==0 ){
eType = ARCHIVE_SQLAR;
zType = "SQL";
}else{
eType = ARCHIVE_ZIP;
zType = "ZIP";
}
| | | 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 |
if( fossil_strcmp(g.zPath, "sqlar")==0 ){
eType = ARCHIVE_SQLAR;
zType = "SQL";
}else{
eType = ARCHIVE_ZIP;
zType = "ZIP";
}
fossil_nice_default();
zName = fossil_strdup(PD("name",""));
z = P("r");
if( z==0 ) z = P("uuid");
if( z==0 ) z = tar_uuid_from_name(&zName);
if( z==0 ) z = "trunk";
nName = strlen(zName);
g.zOpenRevision = zRid = fossil_strdup(z);
|
| ︙ | ︙ |
Added test/markdown-test3.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
Markdown Footnotes Test Document
================================
**This document** should help with testing of footnotes support that
is introduced by the ["`markdown-footnotes`"][branch] branch.
It **might look pretty misformatted unless rendered by the proper Fossil
executable** that incorporates the abovementioned branch.[^1]
That is also a humble attempt to explore the robustness of the Markdown parser.
So please excuse for the mess in the [source code of this document][src].
By no means the normal use of footnotes should look that scarry.
Developers are invited to add test cases here[^here].
It is suggested that the more simple is a test case the earlier it should
appear in this document.[^ if glitch occurs ]
[^lost3]: This note was defined at the begining of the document.
[^duplicate]: This came from the begining of the document.
A footnote's label should be case insensitive[^ case INSENSITIVE ],
it is whitespace-savvy and can even contain newlines.[^ a
multiline
label]
A labeled footnote may be [referenced several times][^many-refs].
A footnote's text should support Markdown [markup][^].
Markup within [a [text fragment](https://en.wikipedia.org/wiki/Lorem_ipsum)
of a *span-bounded footnote*][^markup] should also be rendered.
Another reference[^many-refs] to the preveously used footnote.
[^lost2]: This note was defined in the middle of the document.
It references [its previous][^lost3]
and [the forthcoming][^lost1] siblings.
[^i am strayed]:
This should be presented **verbatim** (without any [markup][^])
in the end of the footnotes.
Default skin renders label in red font and the main text in gray.
Other styling may also apply.
Inline footnotes are supported.(^These may be usefull for adding
<s>small</s> comments.)
This is a corner case that is rendered as [an empty footnote](^ [] ()).
If [undefined label is used][^] then red "`misref`" is emited instead of
a numeric marker.[^ see it yourself ]
This can be overridden by the skin though.
The refenrence at the end of this sentence is the sole reason of
rendering of <s>`lost1` and</s> [lost2][^].
If several labeled footnote definitions have the same equal label then texts
from all these definitions are joined.[^duplicate]
Several references should be recognized as several distinct numbers.
(^There should be an interval between numbers.) [^many-refs]
If markup is ambigous between a span-bounded footnote and
a "free-standing" footnote followed by another footnote
then interpret as the later case.
This facilitates the usage in the usual case
when several footnotes are refenrenced at the end
of a phrase.[^scipub][^many-refs](^All these four should
be parsed as "free-standing" footnotes)[^Coelurosauria]
A footnote may not be empty(^)
or consist just of blank characters.(^
)
The same holds for labeled footnotes. If definition of a labeled footnote
is blank then it is not accepted by the first pass of the parser and
is recognized during the second pass as misreference.
[^ This definition consists of just blanks ]:
<style>
li.fn-upc-example span.fn-upc {
border: solid 2px lightgreen;
border-radius: 0.25em;
padding-left: 2px;
padding-right: 2px;
margin-bottom: 0.2em;
}
li.fn-upc-example span.fn-upcDot:first-child {
font-weight: bold;
}
sup.noteref.fn-upc-example,
span.notescope.fn-upc-example sup.noteref {
border: solid 2px lightgreen;
[^duplicate]:
Labeled footnote definition may appear anywhere.
That part came from inside of an inline style definition.
border-radius: 0.4em;
padding: 2px;
}
sup.noteref.fn-upc-example::after,
span.notescope.fn-upc-example sup.noteref::after {
content: " ⛄";
}
sup.noteref.fn-upc-example:hover::after,
span.notescope.fn-upc-example sup.noteref:hover::after {
content: " 👻";
}
li.fn-upc-l span.fn-upc {
font-size: 60%;
color: orange;
}
li.fn-upc-l span.fn-upc span.fn-upcDot {
display: none;
}
</style>
It is possible to provide a list of classes for a particular footnote and
all its references. This is achieved by prepending a footnote's text with
a special token that starts with dot and ends with colon.
(^
.alpha-Numeric123.EXAMPLE:
This token defines a dot-separated list of CSS classes
which are added to that particular footnote and also to the
corresponding reference(s). Hypens ('-') are also allowed.
Classes from the token are tranformed to lowercase and are prepended
with `"fn-upc-"` to avoid collisions.
)
This feature is "*opt-in*": there is nothing wrong in starting a footnote's
text with a token of that form while not defining any corresponding classes
in the stylesheet.[^nostyle]
If a footnote consists just of a valid userclass token then this token
is not interpreted as such, instead it is emitted as plain text.
(^
.bare.classlist.inside.inline.footnote:
)[^bare1]
[^bare2]
[^duplicate]: .with.UPC.token:
When duplicates are joined their UPC tokens are treated as plain-text.
Blank characters between token and main text must be preserved.
<html>
Click
<a href="?a=B"e='&nonASCII=😂&script=<script>alert('Broken!');</script>">
here</a> and
<a href='?a=B"e="&nonASCII=😂&script=<script>alert("Broken!");</script>'>
here</a>
to test escaping of REQUEST_URI in the generated footnote markers.
</html>
A depth of nesting must be limited.
(^
.L.1: A long chain of nested inline footnotes...
(^
.L.2: is a rather unusual thing...
(^
.L.3: and requires extra CPU cycles for processing.
(^
.L.4: Theoretically speaking O(n<sup>2</sup>).
(^
.L.5: Thus it is worth dismissing those footnotes...
(^
.L.6: that are nested deeper than on a certain level.
(^
.L.7: A particular value for that limit...
(^
is hard-coded in src/markdown.c ...
(^
in function `markdown()` ...
(^
in variable named `maxDepth`.
(^
For the time being, its value is **5**
)
)
)
)
)
)
)
)
)
)
)
## Footnotes
[branch]: /timeline?r=markdown-footnotes&nowiki
[^ 1]: Footnotes is a Fossil' extention of
Markdown. Your other tools may have limited support for these.
[^here]: [History of test/markdown-test3.md](/finfo/test/markdown-test3.md)
[src]: /file/test/markdown-test3.md?ci=markdown-footnotes&txt&ln
[^if glitch occurs]:
So that simple cases are processed even if
a glitch happens for more tricky cases.
[^ CASE insensitive ]: And also tolerate whitespaces.
[^ a multiline label ]: But at a footnote's definition it should still
be written within square brackets
on a single line.
[^duplicate]: And that came from the end of the document.
[^many-refs]:
Each letter on the left is a back-reference to the place of use.
Highlighted back-reference indicates a place from which navigation
occurred[^lost1].
[^lost1]: This note was defined at the end of the document.
It defines an inline note.
(^This is inline note defined inside of [a labeled note][^lost1].)
[^markup]: E.g. *emphasis*, and [so on](/md_rules).
BTW, this note may not have a backreference to the "stray".
[^undefined label is used]: For example due to a typo.
[^another stray]: Just to verify the correctness of ordering and styling.
[^scipub]: Which is common in the scientific publications.
[^bare1]: .at.the.1st.line.of.labeled.footnote.definition:
[^bare2]:
.at.the.2nd.line.of.labeled.footnote.definition:
[^stray with UPC]: .UPC-token:
A token of user-provided classes must be rendered within strays.
Aslo: this and the previous line may not have extra indentation.
[^nostyle]:
.unused.classes:
In that case text of the footnote just looks like as if
no special processing occured.
[^ <script>alert("You have been pwned!");</script> ]: Labels are escaped
[^ <textarea>"Last words here...' ]:
<textarea>Content is also escaped</textarea>
|
Added tools/emcc.sh.in.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
#!/usr/bin/bash
########################################################################
# WARNING: emcc.sh is generated from emcc.sh.in by the configure
# process. Do not edit emcc.sh directly, as it may be deleted or
# overwritten by the configure script.
#
# A wrapper around the emcc compiler which uses configure-time state
# to locate the Emscripten SDK and import the SDK's environment
# script, if needed.
########################################################################
# EMSDK_HOME comes from the configure --with-emsdk=/dir flag.
# EMSDK_ENV is ${thatDir}/emsdk_env.sh and is also set by the
# configure process.
EMSDK_HOME="@EMSDK_HOME@"
EMSDK_ENV="@EMSDK_ENV@"
emcc=$(which emcc 2>/dev/null)
if [ x = "x${emcc}" ]; then
# If emcc is not found in the path, try to find it via an emsdk
# installation. The SDK variant is the official installation
# style supported by the Emscripten folks, but emcc is also
# available via package managers on some OSes.
if [ x = "x${EMSDK_HOME}" ]; then
echo "EMSDK_HOME is not set. Pass --with-emsdk=/path/to/emsdk" \
"to the configure script." 1>&2
exit 1
fi
if [ x = "x${EMSDK_ENV}" ]; then
if [ -f "${EMSDK_HOME}/emsdk_env.sh" ]; then
EMSDK_ENV="${EMSDK_HOME}/emsdk_env.sh"
else
echo "EMSDK_ENV is not set. Expecting configure script to set it." 1>&2
exit 2
fi
fi
if [ ! -f "${EMSDK_ENV}" ]; then
echo "emsdk_env script not found: $EMSDK_ENV" 1>&2
exit 3
fi
# $EMSDK is part of the state set by emsdk_env.sh.
if [ x = "x${EMSDK}" ]; then
source "${EMSDK_ENV}" >/dev/null 2>&1 || {
# ^^^ unfortunately outputs lots of noise to stderr
rc=$?
echo "Error sourcing ${EMSDK_ENV}"
exit $rc
}
fi
emcc=$(which emcc 2>/dev/null)
if [ x = "x${emcc}" ]; then
echo "emcc not found in PATH. Normally that's set up by EMSDK_ENV." 1>&2
exit 4
fi
fi
exec emcc "$@"
|
Changes to tools/makeheaders.c.
| ︙ | ︙ | |||
2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 |
*/
zArg = &zCmd[2];
while( *zArg && isspace(*zArg) && *zArg!='\n' ){
zArg++;
}
if( *zArg==0 || *zArg=='\n' ){ return 0; }
nArg = pToken->nText + (int)(pToken->zText - zArg);
if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Interface);
}else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Export);
}else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Local);
}else if( nArg==15 && strncmp(zArg,"MAKEHEADERS_STOPLOCAL_INTERFACE",15)==0 ){
| > | 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 |
*/
zArg = &zCmd[2];
while( *zArg && isspace(*zArg) && *zArg!='\n' ){
zArg++;
}
if( *zArg==0 || *zArg=='\n' ){ return 0; }
nArg = pToken->nText + (int)(pToken->zText - zArg);
if (pToken->zText[pToken->nText-1] == '\r') { nArg--; }
if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Interface);
}else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Export);
}else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Local);
}else if( nArg==15 && strncmp(zArg,"MAKEHEADERS_STOPLOCAL_INTERFACE",15)==0 ){
|
| ︙ | ︙ | |||
2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 |
*/
zArg = &zCmd[5];
while( *zArg && isspace(*zArg) && *zArg!='\n' ){
zArg++;
}
if( *zArg==0 || *zArg=='\n' ){ return 0; }
nArg = pToken->nText + (int)(pToken->zText - zArg);
PushIfMacro("defined",zArg,nArg,pToken->nLine,0);
}else if( nCmd==6 && strncmp(zCmd,"ifndef",6)==0 ){
/*
** Push an #ifndef.
*/
zArg = &zCmd[6];
while( *zArg && isspace(*zArg) && *zArg!='\n' ){
zArg++;
}
if( *zArg==0 || *zArg=='\n' ){ return 0; }
nArg = pToken->nText + (int)(pToken->zText - zArg);
PushIfMacro("!defined",zArg,nArg,pToken->nLine,0);
}else if( nCmd==4 && strncmp(zCmd,"else",4)==0 ){
/*
** Invert the #if on the top of the stack
*/
if( ifStack==0 ){
fprintf(stderr,"%s:%d: '#else' without an '#if'\n",zFilename,
| > > | 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 |
*/
zArg = &zCmd[5];
while( *zArg && isspace(*zArg) && *zArg!='\n' ){
zArg++;
}
if( *zArg==0 || *zArg=='\n' ){ return 0; }
nArg = pToken->nText + (int)(pToken->zText - zArg);
if (pToken->zText[pToken->nText-1] == '\r') { nArg--; }
PushIfMacro("defined",zArg,nArg,pToken->nLine,0);
}else if( nCmd==6 && strncmp(zCmd,"ifndef",6)==0 ){
/*
** Push an #ifndef.
*/
zArg = &zCmd[6];
while( *zArg && isspace(*zArg) && *zArg!='\n' ){
zArg++;
}
if( *zArg==0 || *zArg=='\n' ){ return 0; }
nArg = pToken->nText + (int)(pToken->zText - zArg);
if (pToken->zText[pToken->nText-1] == '\r') { nArg--; }
PushIfMacro("!defined",zArg,nArg,pToken->nLine,0);
}else if( nCmd==4 && strncmp(zCmd,"else",4)==0 ){
/*
** Invert the #if on the top of the stack
*/
if( ifStack==0 ){
fprintf(stderr,"%s:%d: '#else' without an '#if'\n",zFilename,
|
| ︙ | ︙ |
Changes to tools/makemake.tcl.
| ︙ | ︙ | |||
215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
wiki.wiki
*.js
default.css
style.*.css
../skins/*/*.txt
sounds/*.wav
alerts/*.wav
}
# Options used to compile the included SQLite library.
#
set SQLITE_OPTIONS {
-DNDEBUG=1
-DSQLITE_DQS=0
| > > | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
wiki.wiki
*.js
default.css
style.*.css
../skins/*/*.txt
sounds/*.wav
alerts/*.wav
../extsrc/pikchr.wasm
../extsrc/pikchr*.js
}
# Options used to compile the included SQLite library.
#
set SQLITE_OPTIONS {
-DNDEBUG=1
-DSQLITE_DQS=0
|
| ︙ | ︙ | |||
247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
-DSQLITE_ENABLE_DBPAGE_VTAB
-DSQLITE_TRUSTED_SCHEMA=0
}
#lappend SQLITE_OPTIONS -DSQLITE_ENABLE_FTS3=1
#lappend SQLITE_OPTIONS -DSQLITE_ENABLE_STAT4
#lappend SQLITE_OPTIONS -DSQLITE_WIN32_NO_ANSI
#lappend SQLITE_OPTIONS -DSQLITE_WINNT_MAX_PATH_CHARS=4096
# Options used to compile the included SQLite shell.
#
set SHELL_OPTIONS [concat $SQLITE_OPTIONS {
-Dmain=sqlite3_shell
-DSQLITE_SHELL_IS_UTF8=1
-DSQLITE_OMIT_LOAD_EXTENSION=1
| > > > > > > | 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
-DSQLITE_ENABLE_DBPAGE_VTAB
-DSQLITE_TRUSTED_SCHEMA=0
}
#lappend SQLITE_OPTIONS -DSQLITE_ENABLE_FTS3=1
#lappend SQLITE_OPTIONS -DSQLITE_ENABLE_STAT4
#lappend SQLITE_OPTIONS -DSQLITE_WIN32_NO_ANSI
#lappend SQLITE_OPTIONS -DSQLITE_WINNT_MAX_PATH_CHARS=4096
# Options used to compile the Pikchr library.
#
set PIKCHR_OPTIONS {
-DPIKCHR_TOKEN_LIMIT=10000
}
# Options used to compile the included SQLite shell.
#
set SHELL_OPTIONS [concat $SQLITE_OPTIONS {
-Dmain=sqlite3_shell
-DSQLITE_SHELL_IS_UTF8=1
-DSQLITE_OMIT_LOAD_EXTENSION=1
|
| ︙ | ︙ | |||
352 353 354 355 356 357 358 359 360 361 362 363 364 365 |
foreach s [lsort $src] {
writeln -nonewline " \\\n \$(OBJDIR)/$s.o"
}
writeln [string map [list \
<<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
<<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
<<<NEXT_LINE>>> \\] {
all: $(OBJDIR) $(APPNAME)
install: all
mkdir -p $(INSTALLDIR)
cp $(APPNAME) $(INSTALLDIR)
| > | 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 |
foreach s [lsort $src] {
writeln -nonewline " \\\n \$(OBJDIR)/$s.o"
}
writeln [string map [list \
<<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
<<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
<<<PIKCHR_OPTIONS>>> [join $PIKCHR_OPTIONS " \\\n "] \
<<<NEXT_LINE>>> \\] {
all: $(OBJDIR) $(APPNAME)
install: all
mkdir -p $(INSTALLDIR)
cp $(APPNAME) $(INSTALLDIR)
|
| ︙ | ︙ | |||
413 414 415 416 417 418 419 420 421 422 423 424 425 426 | # Force rebuild of VERSION.h every time we run "make" # Setup the options used to compile the included SQLite library. SQLITE_OPTIONS = <<<SQLITE_OPTIONS>>> # Setup the options used to compile the included SQLite shell. SHELL_OPTIONS = <<<SHELL_OPTIONS>>> # The USE_SYSTEM_SQLITE variable may be undefined, set to 0 or 1. # If it is set to 1, then there is no need to build or link # the sqlite3.o object. Instead, the system SQLite will be linked # using -lsqlite3. # # Closely related is SQLITE3_ORIGIN, with the same numeric mapping plus | > > > | 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | # Force rebuild of VERSION.h every time we run "make" # Setup the options used to compile the included SQLite library. SQLITE_OPTIONS = <<<SQLITE_OPTIONS>>> # Setup the options used to compile the included SQLite shell. SHELL_OPTIONS = <<<SHELL_OPTIONS>>> # Setup the options used to compile the included Pikchr formatter. PIKCHR_OPTIONS = <<<PIKCHR_OPTIONS>>> # The USE_SYSTEM_SQLITE variable may be undefined, set to 0 or 1. # If it is set to 1, then there is no need to build or link # the sqlite3.o object. Instead, the system SQLite will be linked # using -lsqlite3. # # Closely related is SQLITE3_ORIGIN, with the same numeric mapping plus |
| ︙ | ︙ | |||
543 544 545 546 547 548 549 |
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$@\n"
writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
writeln {
$(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
| | > > > > > > > > > > > | 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 |
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$@\n"
writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
writeln {
$(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
$(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
$(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
$(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c
$(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry \
-sEXPORTED_RUNTIME_METHODS=cwrap,setValue,getValue,stackSave,stackRestore \
-sEXPORTED_FUNCTIONS=_pikchr $(SRCDIR_extsrc)/pikchr.c \
-sENVIRONMENT=web \
-sMODULARIZE \
-sEXPORT_NAME=initPikchrModule \
--minify 0
@chmod -x $(SRCDIR_extsrc)/pikchr.wasm
wasm: $(SRCDIR_extsrc)/pikchr.js
#
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#
.PHONY: all install test clean
|
| ︙ | ︙ | |||
626 627 628 629 630 631 632 | # BCC = $(BCCEXE) #### Enable compiling with debug symbols (much larger binary) # # FOSSIL_ENABLE_SYMBOLS = 1 | | | 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 | # BCC = $(BCCEXE) #### Enable compiling with debug symbols (much larger binary) # # FOSSIL_ENABLE_SYMBOLS = 1 #### Enable JSON (https://www.json.org) support using "cson" # # FOSSIL_ENABLE_JSON = 1 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto) # # FOSSIL_ENABLE_SSL = 1 |
| ︙ | ︙ | |||
1246 1247 1248 1249 1250 1251 1252 1253 1254 |
lappend SQLITE_WIN32_OPTIONS -DSQLITE_WIN32_NO_ANSI
set MINGW_SQLITE_OPTIONS $SQLITE_WIN32_OPTIONS
lappend MINGW_SQLITE_OPTIONS {$(MINGW_OPTIONS)}
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE
set j " \\\n "
writeln "SQLITE_OPTIONS = [join $MINGW_SQLITE_OPTIONS $j]\n"
| > > < > | 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 |
lappend SQLITE_WIN32_OPTIONS -DSQLITE_WIN32_NO_ANSI
set MINGW_SQLITE_OPTIONS $SQLITE_WIN32_OPTIONS
lappend MINGW_SQLITE_OPTIONS {$(MINGW_OPTIONS)}
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE
set MINGW_PIKCHR_OPTIONS $PIKCHR_OPTIONS
set j " \\\n "
writeln "SQLITE_OPTIONS = [join $MINGW_SQLITE_OPTIONS $j]\n"
writeln "SHELL_OPTIONS = [join $SHELL_WIN32_OPTIONS $j]\n"
writeln "PIKCHR_OPTIONS = [join $MINGW_PIKCHR_OPTIONS $j]\n"
writeln "\$(OBJDIR)/sqlite3.o:\t\$(SQLITE3_SRC) \$(SRCDIR)/../win/Makefile.mingw"
writeln "\t\$(XTCC) \$(SQLITE_OPTIONS) \$(SQLITE_CFLAGS) \$(SEE_FLAGS) \\"
writeln "\t\t-c \$(SQLITE3_SRC) -o \$@\n"
writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR_extsrc)/cson_amalgamation.c"
writeln "\t\$(XTCC) -c \$(SRCDIR_extsrc)/cson_amalgamation.c -o \$@\n"
|
| ︙ | ︙ | |||
1272 1273 1274 1275 1276 1277 1278 | writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c" writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$@\n" writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c" writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n" writeln "\$(OBJDIR)/pikchr.o:\t\$(SRCDIR_extsrc)/pikchr.c" | | | 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 | writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c" writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$@\n" writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c" writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n" writeln "\$(OBJDIR)/pikchr.o:\t\$(SRCDIR_extsrc)/pikchr.c" writeln "\t\$(XTCC) \$(PIKCHR_OPTIONS) -c \$(SRCDIR_extsrc)/pikchr.c -o \$@\n" close $output_file # # End of the win/Makefile.mingw output ############################################################################## ############################################################################## ############################################################################## |
| ︙ | ︙ | |||
1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 |
CFLAGS = -o
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi
}
writeln "SQLITE_OPTIONS = [join $SQLITE_OPTIONS { }]\n"
writeln "SHELL_OPTIONS = [join $SHELL_WIN32_OPTIONS { }]\n"
writeln -nonewline "SRC ="
foreach s [lsort $src] {
writeln -nonewline " ${s}_.c"
}
writeln "\n"
writeln -nonewline "OBJ = "
foreach s [lsort $src] {
| > | 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 |
CFLAGS = -o
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi
}
writeln "SQLITE_OPTIONS = [join $SQLITE_OPTIONS { }]\n"
writeln "SHELL_OPTIONS = [join $SHELL_WIN32_OPTIONS { }]\n"
writeln "PIKCHR_OPTIONS = [join $PIKCHR_OPTIONS { }]\n"
writeln -nonewline "SRC ="
foreach s [lsort $src] {
writeln -nonewline " ${s}_.c"
}
writeln "\n"
writeln -nonewline "OBJ = "
foreach s [lsort $src] {
|
| ︙ | ︙ | |||
1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 |
set j " \\\n "
writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
regsub -all {[-]D} [join $SHELL_WIN32_OPTIONS { }] {/D} MSC_SHELL_OPTIONS
set j " \\\n "
writeln "SHELL_OPTIONS = [join $MSC_SHELL_OPTIONS $j]\n"
writeln -nonewline "SRC = "
set i 0
foreach s [lsort $src] {
if {$i > 0} {
writeln " \\"
writeln -nonewline " "
}
| > > > > | 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 |
set j " \\\n "
writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
regsub -all {[-]D} [join $SHELL_WIN32_OPTIONS { }] {/D} MSC_SHELL_OPTIONS
set j " \\\n "
writeln "SHELL_OPTIONS = [join $MSC_SHELL_OPTIONS $j]\n"
regsub -all {[-]D} [join $PIKCHR_OPTIONS { }] {/D} MSC_PIKCHR_OPTIONS
set j " \\\n "
writeln "PIKCHR_OPTIONS = [join $MSC_PIKCHR_OPTIONS $j]\n"
writeln -nonewline "SRC = "
set i 0
foreach s [lsort $src] {
if {$i > 0} {
writeln " \\"
writeln -nonewline " "
}
|
| ︙ | ︙ | |||
1947 1948 1949 1950 1951 1952 1953 | "$(OX)\th_lang$O" : "$(SRCDIR)\th_lang.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\th_tcl$O" : "$(SRCDIR)\th_tcl.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\pikchr$O" : "$(SRCDIR_extsrc)\pikchr.c" | | | 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 | "$(OX)\th_lang$O" : "$(SRCDIR)\th_lang.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\th_tcl$O" : "$(SRCDIR)\th_tcl.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\pikchr$O" : "$(SRCDIR_extsrc)\pikchr.c" $(TCC) $(PIKCHR_OPTIONS) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\manifest.descr" "$(B)\phony.h" "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\manifest.descr" > $@ "$(B)\phony.h" : rem Force rebuild of VERSION.h whenever nmake is run |
| ︙ | ︙ |
Changes to tools/mkindex.c.
| ︙ | ︙ | |||
78 79 80 81 82 83 84 | #include <assert.h> #include <string.h> /*************************************************************************** ** These macros must match similar macros in dispatch.c. ** ** Allowed values for CmdOrPage.eCmdFlags. */ | | | | | | | | | | | | | > | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
#include <assert.h>
#include <string.h>
/***************************************************************************
** These macros must match similar macros in dispatch.c.
**
** Allowed values for CmdOrPage.eCmdFlags. */
#define CMDFLAG_1ST_TIER 0x0001 /* Most important commands */
#define CMDFLAG_2ND_TIER 0x0002 /* Obscure and seldom used commands */
#define CMDFLAG_TEST 0x0004 /* Commands for testing only */
#define CMDFLAG_WEBPAGE 0x0008 /* Web pages */
#define CMDFLAG_COMMAND 0x0010 /* A command */
#define CMDFLAG_SETTING 0x0020 /* A setting */
#define CMDFLAG_VERSIONABLE 0x0040 /* A versionable setting */
#define CMDFLAG_BLOCKTEXT 0x0080 /* Multi-line text setting */
#define CMDFLAG_BOOLEAN 0x0100 /* A boolean setting */
#define CMDFLAG_RAWCONTENT 0x0200 /* Do not interpret webpage content */
#define CMDFLAG_SENSITIVE 0x0400 /* Security-sensitive setting */
#define CMDFLAG_HIDDEN 0x0800 /* Elide from most listings */
#define CMDFLAG_LDAVG_EXEMPT 0x1000 /* Exempt from load_control() */
/**************************************************************************/
/*
** Each entry looks like this:
*/
typedef struct Entry {
int eType; /* CMDFLAG_* values */
|
| ︙ | ︙ | |||
258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
aEntry[nUsed].iWidth = atoi(&zLine[i+6]);
}else if( j>8 && strncmp(&zLine[i], "default=", 8)==0 ){
aEntry[nUsed].zDflt = string_dup(&zLine[i+8], j-8);
}else if( j>9 && strncmp(&zLine[i], "variable=", 9)==0 ){
aEntry[nUsed].zVar = string_dup(&zLine[i+9], j-9);
}else if( j==6 && strncmp(&zLine[i], "hidden", 6)==0 ){
aEntry[nUsed].eType |= CMDFLAG_HIDDEN;
}else{
fprintf(stderr, "%s:%d: unknown option: '%.*s'\n",
zFile, nLine, j, &zLine[i]);
nErr++;
}
}
| > > | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
aEntry[nUsed].iWidth = atoi(&zLine[i+6]);
}else if( j>8 && strncmp(&zLine[i], "default=", 8)==0 ){
aEntry[nUsed].zDflt = string_dup(&zLine[i+8], j-8);
}else if( j>9 && strncmp(&zLine[i], "variable=", 9)==0 ){
aEntry[nUsed].zVar = string_dup(&zLine[i+9], j-9);
}else if( j==6 && strncmp(&zLine[i], "hidden", 6)==0 ){
aEntry[nUsed].eType |= CMDFLAG_HIDDEN;
}else if( j==14 && strncmp(&zLine[i], "loadavg-exempt", 14)==0 ){
aEntry[nUsed].eType |= CMDFLAG_LDAVG_EXEMPT;
}else{
fprintf(stderr, "%s:%d: unknown option: '%.*s'\n",
zFile, nLine, j, &zLine[i]);
nErr++;
}
}
|
| ︙ | ︙ |
Changes to win/Makefile.dmc.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | BCC = $(DMDIR)\bin\dmc $(CFLAGS) TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen SRC = add_.c ajax_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c patch_.c path_.c piechart_.c pikchrshow_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c zip_.c OBJ = $(OBJDIR)\add$O $(OBJDIR)\ajax$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\chat$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\color$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\hook$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\interwiki$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\patch$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pikchrshow$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\terminal$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O RC=$(DMDIR)\bin\rcc | > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | BCC = $(DMDIR)\bin\dmc $(CFLAGS) TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen PIKCHR_OPTIONS = -DPIKCHR_TOKEN_LIMIT=10000 SRC = add_.c ajax_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c patch_.c path_.c piechart_.c pikchrshow_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c zip_.c OBJ = $(OBJDIR)\add$O $(OBJDIR)\ajax$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\chat$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\color$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\hook$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\interwiki$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\patch$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pikchrshow$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\terminal$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O RC=$(DMDIR)\bin\rcc |
| ︙ | ︙ |
Changes to win/Makefile.mingw.
| ︙ | ︙ | |||
52 53 54 55 56 57 58 | # BCC = $(BCCEXE) #### Enable compiling with debug symbols (much larger binary) # # FOSSIL_ENABLE_SYMBOLS = 1 | | | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | # BCC = $(BCCEXE) #### Enable compiling with debug symbols (much larger binary) # # FOSSIL_ENABLE_SYMBOLS = 1 #### Enable JSON (https://www.json.org) support using "cson" # # FOSSIL_ENABLE_JSON = 1 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto) # # FOSSIL_ENABLE_SSL = 1 |
| ︙ | ︙ | |||
547 548 549 550 551 552 553 554 555 556 557 558 559 560 | $(SRCDIR)/winfile.c \ $(SRCDIR)/winhttp.c \ $(SRCDIR)/xfer.c \ $(SRCDIR)/xfersetup.c \ $(SRCDIR)/zip.c EXTRA_FILES = \ $(SRCDIR)/../skins/ardoise/css.txt \ $(SRCDIR)/../skins/ardoise/details.txt \ $(SRCDIR)/../skins/ardoise/footer.txt \ $(SRCDIR)/../skins/ardoise/header.txt \ $(SRCDIR)/../skins/black_and_white/css.txt \ $(SRCDIR)/../skins/black_and_white/details.txt \ $(SRCDIR)/../skins/black_and_white/footer.txt \ | > > > | 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | $(SRCDIR)/winfile.c \ $(SRCDIR)/winhttp.c \ $(SRCDIR)/xfer.c \ $(SRCDIR)/xfersetup.c \ $(SRCDIR)/zip.c EXTRA_FILES = \ $(SRCDIR)/../extsrc/pikchr-worker.js \ $(SRCDIR)/../extsrc/pikchr.js \ $(SRCDIR)/../extsrc/pikchr.wasm \ $(SRCDIR)/../skins/ardoise/css.txt \ $(SRCDIR)/../skins/ardoise/details.txt \ $(SRCDIR)/../skins/ardoise/footer.txt \ $(SRCDIR)/../skins/ardoise/header.txt \ $(SRCDIR)/../skins/black_and_white/css.txt \ $(SRCDIR)/../skins/black_and_white/details.txt \ $(SRCDIR)/../skins/black_and_white/footer.txt \ |
| ︙ | ︙ | |||
615 616 617 618 619 620 621 622 623 624 625 626 627 628 | $(SRCDIR)/fossil.fetch.js \ $(SRCDIR)/fossil.numbered-lines.js \ $(SRCDIR)/fossil.page.brlist.js \ $(SRCDIR)/fossil.page.chat.js \ $(SRCDIR)/fossil.page.fileedit.js \ $(SRCDIR)/fossil.page.forumpost.js \ $(SRCDIR)/fossil.page.pikchrshow.js \ $(SRCDIR)/fossil.page.whistory.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.js \ $(SRCDIR)/fossil.popupwidget.js \ $(SRCDIR)/fossil.storage.js \ $(SRCDIR)/fossil.tabs.js \ $(SRCDIR)/fossil.wikiedit-wysiwyg.js \ | > | 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 | $(SRCDIR)/fossil.fetch.js \ $(SRCDIR)/fossil.numbered-lines.js \ $(SRCDIR)/fossil.page.brlist.js \ $(SRCDIR)/fossil.page.chat.js \ $(SRCDIR)/fossil.page.fileedit.js \ $(SRCDIR)/fossil.page.forumpost.js \ $(SRCDIR)/fossil.page.pikchrshow.js \ $(SRCDIR)/fossil.page.pikchrshowasm.js \ $(SRCDIR)/fossil.page.whistory.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.js \ $(SRCDIR)/fossil.popupwidget.js \ $(SRCDIR)/fossil.storage.js \ $(SRCDIR)/fossil.tabs.js \ $(SRCDIR)/fossil.wikiedit-wysiwyg.js \ |
| ︙ | ︙ | |||
650 651 652 653 654 655 656 657 658 659 660 661 662 663 | $(SRCDIR)/sounds/c.wav \ $(SRCDIR)/sounds/d.wav \ $(SRCDIR)/sounds/e.wav \ $(SRCDIR)/sounds/f.wav \ $(SRCDIR)/style.admin_log.css \ $(SRCDIR)/style.chat.css \ $(SRCDIR)/style.fileedit.css \ $(SRCDIR)/style.wikiedit.css \ $(SRCDIR)/tree.js \ $(SRCDIR)/useredit.js \ $(SRCDIR)/wiki.wiki TRANS_SRC = \ $(OBJDIR)/add_.c \ | > | 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 | $(SRCDIR)/sounds/c.wav \ $(SRCDIR)/sounds/d.wav \ $(SRCDIR)/sounds/e.wav \ $(SRCDIR)/sounds/f.wav \ $(SRCDIR)/style.admin_log.css \ $(SRCDIR)/style.chat.css \ $(SRCDIR)/style.fileedit.css \ $(SRCDIR)/style.pikchrshow.css \ $(SRCDIR)/style.wikiedit.css \ $(SRCDIR)/tree.js \ $(SRCDIR)/useredit.js \ $(SRCDIR)/wiki.wiki TRANS_SRC = \ $(OBJDIR)/add_.c \ |
| ︙ | ︙ | |||
2526 2527 2528 2529 2530 2531 2532 |
-DSQLITE_TRUSTED_SCHEMA=0 \
-DSQLITE_WIN32_NO_ANSI \
$(MINGW_OPTIONS) \
-DSQLITE_USE_MALLOC_H \
-DSQLITE_USE_MSIZE
SHELL_OPTIONS = -DNDEBUG=1 \
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > | 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 |
-DSQLITE_TRUSTED_SCHEMA=0 \
-DSQLITE_WIN32_NO_ANSI \
$(MINGW_OPTIONS) \
-DSQLITE_USE_MALLOC_H \
-DSQLITE_USE_MSIZE
SHELL_OPTIONS = -DNDEBUG=1 \
-DSQLITE_DQS=0 \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_DEFAULT_MEMSTATUS=0 \
-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
-DSQLITE_OMIT_DECLTYPE \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_OMIT_PROGRESS_CALLBACK \
-DSQLITE_OMIT_SHARED_CACHE \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_MAX_EXPR_DEPTH=0 \
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_ENABLE_STMTVTAB \
-DSQLITE_HAVE_ZLIB \
-DSQLITE_ENABLE_DBPAGE_VTAB \
-DSQLITE_TRUSTED_SCHEMA=0 \
-Dmain=sqlite3_shell \
-DSQLITE_SHELL_IS_UTF8=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
-DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
-DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
-Daccess=file_access \
-Dsystem=fossil_system \
-Dgetenv=fossil_getenv \
-Dfopen=fossil_fopen
PIKCHR_OPTIONS = -DPIKCHR_TOKEN_LIMIT=10000
$(OBJDIR)/sqlite3.o: $(SQLITE3_SRC) $(SRCDIR)/../win/Makefile.mingw
$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) \
-c $(SQLITE3_SRC) -o $@
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
$(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
|
| ︙ | ︙ | |||
2580 2581 2582 2583 2584 2585 2586 | $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c $(XTCC) -c $(SRCDIR)/th_lang.c -o $@ $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@ $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c | | | 2587 2588 2589 2590 2591 2592 2593 2594 2595 | $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c $(XTCC) -c $(SRCDIR)/th_lang.c -o $@ $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@ $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c $(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@ |
Changes to win/Makefile.msc.
| ︙ | ︙ | |||
352 353 354 355 356 357 358 359 360 361 362 363 364 365 |
/DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
/DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
/Daccess=file_access \
/Dsystem=fossil_system \
/Dgetenv=fossil_getenv \
/Dfopen=fossil_fopen
SRC = "$(OX)\add_.c" \
"$(OX)\ajax_.c" \
"$(OX)\alerts_.c" \
"$(OX)\allrepo_.c" \
"$(OX)\attach_.c" \
"$(OX)\backlink_.c" \
"$(OX)\backoffice_.c" \
| > > | 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
/DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
/DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
/Daccess=file_access \
/Dsystem=fossil_system \
/Dgetenv=fossil_getenv \
/Dfopen=fossil_fopen
PIKCHR_OPTIONS = /DPIKCHR_TOKEN_LIMIT=10000
SRC = "$(OX)\add_.c" \
"$(OX)\ajax_.c" \
"$(OX)\alerts_.c" \
"$(OX)\allrepo_.c" \
"$(OX)\attach_.c" \
"$(OX)\backlink_.c" \
"$(OX)\backoffice_.c" \
|
| ︙ | ︙ | |||
501 502 503 504 505 506 507 |
"$(OX)\winfile_.c" \
"$(OX)\winhttp_.c" \
"$(OX)\xfer_.c" \
"$(OX)\xfersetup_.c" \
"$(OX)\zip_.c" \
"$(SRCDIR_extsrc)\pikchr.c"
| > > > | | 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 |
"$(OX)\winfile_.c" \
"$(OX)\winhttp_.c" \
"$(OX)\xfer_.c" \
"$(OX)\xfersetup_.c" \
"$(OX)\zip_.c" \
"$(SRCDIR_extsrc)\pikchr.c"
EXTRA_FILES = "$(SRCDIR)\..\extsrc\pikchr-worker.js" \
"$(SRCDIR)\..\extsrc\pikchr.js" \
"$(SRCDIR)\..\extsrc\pikchr.wasm" \
"$(SRCDIR)\..\skins\ardoise\css.txt" \
"$(SRCDIR)\..\skins\ardoise\details.txt" \
"$(SRCDIR)\..\skins\ardoise\footer.txt" \
"$(SRCDIR)\..\skins\ardoise\header.txt" \
"$(SRCDIR)\..\skins\black_and_white\css.txt" \
"$(SRCDIR)\..\skins\black_and_white\details.txt" \
"$(SRCDIR)\..\skins\black_and_white\footer.txt" \
"$(SRCDIR)\..\skins\black_and_white\header.txt" \
|
| ︙ | ︙ | |||
569 570 571 572 573 574 575 576 577 578 579 580 581 582 |
"$(SRCDIR)\fossil.fetch.js" \
"$(SRCDIR)\fossil.numbered-lines.js" \
"$(SRCDIR)\fossil.page.brlist.js" \
"$(SRCDIR)\fossil.page.chat.js" \
"$(SRCDIR)\fossil.page.fileedit.js" \
"$(SRCDIR)\fossil.page.forumpost.js" \
"$(SRCDIR)\fossil.page.pikchrshow.js" \
"$(SRCDIR)\fossil.page.whistory.js" \
"$(SRCDIR)\fossil.page.wikiedit.js" \
"$(SRCDIR)\fossil.pikchr.js" \
"$(SRCDIR)\fossil.popupwidget.js" \
"$(SRCDIR)\fossil.storage.js" \
"$(SRCDIR)\fossil.tabs.js" \
"$(SRCDIR)\fossil.wikiedit-wysiwyg.js" \
| > | 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 |
"$(SRCDIR)\fossil.fetch.js" \
"$(SRCDIR)\fossil.numbered-lines.js" \
"$(SRCDIR)\fossil.page.brlist.js" \
"$(SRCDIR)\fossil.page.chat.js" \
"$(SRCDIR)\fossil.page.fileedit.js" \
"$(SRCDIR)\fossil.page.forumpost.js" \
"$(SRCDIR)\fossil.page.pikchrshow.js" \
"$(SRCDIR)\fossil.page.pikchrshowasm.js" \
"$(SRCDIR)\fossil.page.whistory.js" \
"$(SRCDIR)\fossil.page.wikiedit.js" \
"$(SRCDIR)\fossil.pikchr.js" \
"$(SRCDIR)\fossil.popupwidget.js" \
"$(SRCDIR)\fossil.storage.js" \
"$(SRCDIR)\fossil.tabs.js" \
"$(SRCDIR)\fossil.wikiedit-wysiwyg.js" \
|
| ︙ | ︙ | |||
604 605 606 607 608 609 610 611 612 613 614 615 616 617 |
"$(SRCDIR)\sounds\c.wav" \
"$(SRCDIR)\sounds\d.wav" \
"$(SRCDIR)\sounds\e.wav" \
"$(SRCDIR)\sounds\f.wav" \
"$(SRCDIR)\style.admin_log.css" \
"$(SRCDIR)\style.chat.css" \
"$(SRCDIR)\style.fileedit.css" \
"$(SRCDIR)\style.wikiedit.css" \
"$(SRCDIR)\tree.js" \
"$(SRCDIR)\useredit.js" \
"$(SRCDIR)\wiki.wiki"
OBJ = "$(OX)\add$O" \
"$(OX)\ajax$O" \
| > | 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 |
"$(SRCDIR)\sounds\c.wav" \
"$(SRCDIR)\sounds\d.wav" \
"$(SRCDIR)\sounds\e.wav" \
"$(SRCDIR)\sounds\f.wav" \
"$(SRCDIR)\style.admin_log.css" \
"$(SRCDIR)\style.chat.css" \
"$(SRCDIR)\style.fileedit.css" \
"$(SRCDIR)\style.pikchrshow.css" \
"$(SRCDIR)\style.wikiedit.css" \
"$(SRCDIR)\tree.js" \
"$(SRCDIR)\useredit.js" \
"$(SRCDIR)\wiki.wiki"
OBJ = "$(OX)\add$O" \
"$(OX)\ajax$O" \
|
| ︙ | ︙ | |||
1058 1059 1060 1061 1062 1063 1064 | "$(OX)\th_lang$O" : "$(SRCDIR)\th_lang.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\th_tcl$O" : "$(SRCDIR)\th_tcl.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\pikchr$O" : "$(SRCDIR_extsrc)\pikchr.c" | | | 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 | "$(OX)\th_lang$O" : "$(SRCDIR)\th_lang.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\th_tcl$O" : "$(SRCDIR)\th_tcl.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\pikchr$O" : "$(SRCDIR_extsrc)\pikchr.c" $(TCC) $(PIKCHR_OPTIONS) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\manifest.descr" "$(B)\phony.h" "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\manifest.descr" > $@ "$(B)\phony.h" : rem Force rebuild of VERSION.h whenever nmake is run |
| ︙ | ︙ | |||
1128 1129 1130 1131 1132 1133 1134 | "$(OBJDIR)\json_status$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_tag$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_timeline$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_user$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_wiki$O" : "$(SRCDIR)\json_detail.h" "$(OX)\builtin_data.reslist": $(EXTRA_FILES) "$(B)\win\Makefile.msc" | > > > | | 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 | "$(OBJDIR)\json_status$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_tag$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_timeline$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_user$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_wiki$O" : "$(SRCDIR)\json_detail.h" "$(OX)\builtin_data.reslist": $(EXTRA_FILES) "$(B)\win\Makefile.msc" echo "$(SRCDIR)\../extsrc/pikchr-worker.js" > $@ echo "$(SRCDIR)\../extsrc/pikchr.js" >> $@ echo "$(SRCDIR)\../extsrc/pikchr.wasm" >> $@ echo "$(SRCDIR)\../skins/ardoise/css.txt" >> $@ echo "$(SRCDIR)\../skins/ardoise/details.txt" >> $@ echo "$(SRCDIR)\../skins/ardoise/footer.txt" >> $@ echo "$(SRCDIR)\../skins/ardoise/header.txt" >> $@ echo "$(SRCDIR)\../skins/black_and_white/css.txt" >> $@ echo "$(SRCDIR)\../skins/black_and_white/details.txt" >> $@ echo "$(SRCDIR)\../skins/black_and_white/footer.txt" >> $@ echo "$(SRCDIR)\../skins/black_and_white/header.txt" >> $@ |
| ︙ | ︙ | |||
1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 | echo "$(SRCDIR)\fossil.fetch.js" >> $@ echo "$(SRCDIR)\fossil.numbered-lines.js" >> $@ echo "$(SRCDIR)\fossil.page.brlist.js" >> $@ echo "$(SRCDIR)\fossil.page.chat.js" >> $@ echo "$(SRCDIR)\fossil.page.fileedit.js" >> $@ echo "$(SRCDIR)\fossil.page.forumpost.js" >> $@ echo "$(SRCDIR)\fossil.page.pikchrshow.js" >> $@ echo "$(SRCDIR)\fossil.page.whistory.js" >> $@ echo "$(SRCDIR)\fossil.page.wikiedit.js" >> $@ echo "$(SRCDIR)\fossil.pikchr.js" >> $@ echo "$(SRCDIR)\fossil.popupwidget.js" >> $@ echo "$(SRCDIR)\fossil.storage.js" >> $@ echo "$(SRCDIR)\fossil.tabs.js" >> $@ echo "$(SRCDIR)\fossil.wikiedit-wysiwyg.js" >> $@ | > | 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 | echo "$(SRCDIR)\fossil.fetch.js" >> $@ echo "$(SRCDIR)\fossil.numbered-lines.js" >> $@ echo "$(SRCDIR)\fossil.page.brlist.js" >> $@ echo "$(SRCDIR)\fossil.page.chat.js" >> $@ echo "$(SRCDIR)\fossil.page.fileedit.js" >> $@ echo "$(SRCDIR)\fossil.page.forumpost.js" >> $@ echo "$(SRCDIR)\fossil.page.pikchrshow.js" >> $@ echo "$(SRCDIR)\fossil.page.pikchrshowasm.js" >> $@ echo "$(SRCDIR)\fossil.page.whistory.js" >> $@ echo "$(SRCDIR)\fossil.page.wikiedit.js" >> $@ echo "$(SRCDIR)\fossil.pikchr.js" >> $@ echo "$(SRCDIR)\fossil.popupwidget.js" >> $@ echo "$(SRCDIR)\fossil.storage.js" >> $@ echo "$(SRCDIR)\fossil.tabs.js" >> $@ echo "$(SRCDIR)\fossil.wikiedit-wysiwyg.js" >> $@ |
| ︙ | ︙ | |||
1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 | echo "$(SRCDIR)\sounds/c.wav" >> $@ echo "$(SRCDIR)\sounds/d.wav" >> $@ echo "$(SRCDIR)\sounds/e.wav" >> $@ echo "$(SRCDIR)\sounds/f.wav" >> $@ echo "$(SRCDIR)\style.admin_log.css" >> $@ echo "$(SRCDIR)\style.chat.css" >> $@ echo "$(SRCDIR)\style.fileedit.css" >> $@ echo "$(SRCDIR)\style.wikiedit.css" >> $@ echo "$(SRCDIR)\tree.js" >> $@ echo "$(SRCDIR)\useredit.js" >> $@ echo "$(SRCDIR)\wiki.wiki" >> $@ "$(OX)\add$O" : "$(OX)\add_.c" "$(OX)\add.h" $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\add_.c" | > | 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 | echo "$(SRCDIR)\sounds/c.wav" >> $@ echo "$(SRCDIR)\sounds/d.wav" >> $@ echo "$(SRCDIR)\sounds/e.wav" >> $@ echo "$(SRCDIR)\sounds/f.wav" >> $@ echo "$(SRCDIR)\style.admin_log.css" >> $@ echo "$(SRCDIR)\style.chat.css" >> $@ echo "$(SRCDIR)\style.fileedit.css" >> $@ echo "$(SRCDIR)\style.pikchrshow.css" >> $@ echo "$(SRCDIR)\style.wikiedit.css" >> $@ echo "$(SRCDIR)\tree.js" >> $@ echo "$(SRCDIR)\useredit.js" >> $@ echo "$(SRCDIR)\wiki.wiki" >> $@ "$(OX)\add$O" : "$(OX)\add_.c" "$(OX)\add.h" $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\add_.c" |
| ︙ | ︙ |
Changes to www/build.wiki.
| ︙ | ︙ | |||
263 264 265 266 267 268 269 | These instructions assume that docker is installed and that the user running these instructions has permission to do so (i.e., they are <tt>root</tt> or are a member of the <tt>docker</tt> group). First, create a file named <tt>Dockerfile</tt> with the following contents: <pre><code> | < < | < | 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
These instructions assume that docker is installed and that the user running
these instructions has permission to do so (i.e., they are <tt>root</tt> or
are a member of the <tt>docker</tt> group).
First, create a file named <tt>Dockerfile</tt> with the following contents:
<pre><code>
FROM alpine:edge
RUN apk update \
&& apk upgrade \
&& apk add --no-cache \
curl gcc make tcl \
musl-dev \
openssl-dev zlib-dev \
openssl-libs-static zlib-static \
|
| ︙ | ︙ | |||
330 331 332 333 334 335 336 | <pre><code>docker image rm THE_FOSSIL_ID THE_ALPINE_ID</code></pre> <h2>6.0 Building on/for Android</h2> <h3>6.1 Cross-compiling from Linux</h3> | | | 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | <pre><code>docker image rm THE_FOSSIL_ID THE_ALPINE_ID</code></pre> <h2>6.0 Building on/for Android</h2> <h3>6.1 Cross-compiling from Linux</h3> The following instructions for building Fossil for Android via Linux, without requiring a rooted OS, are adapted from [https://fossil-scm.org/forum/forumpost/e0e9de4a7e | forumpost/e0e9de4a7e]. On the development machine, from the fossil source tree: <pre><code>export CC=$NDK_PATH/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang ./configure --with-openssl=none |
| ︙ | ︙ | |||
377 378 379 380 381 382 383 | WARNING: linker: ./fossil: unused DT entry: type 0x6fffffff arg 0x2 </code></pre> The source of such warnings is not 100% certain. Some information about these (reportedly harmless) warnings can be found [https://stackoverflow.com/a/41900551 | on this StackOverflow post]. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 |
WARNING: linker: ./fossil: unused DT entry: type 0x6fffffff arg 0x2
</code></pre>
The source of such warnings is not 100% certain.
Some information about these (reportedly harmless) warnings can
be found
[https://stackoverflow.com/a/41900551 | on this StackOverflow post].
<a id='fuzzer'></a>
<h2>7.0 Building for Fuzz Testing</h2>
This feature is primarily intended for fossil's developers and may
change at any time. It is only known to work on Linux systems and has
been seen to work on x86/64 and ARM.
Fossil has builtin support for processing specific features using
<tt>libfuzzer</tt>. The features which can be tested this way are
found in the help text for the [/help?cmd=test-fuzz|test-fuzz
command].
Fuzzing requires:
* Customizing the build of fossil a small bit.
* The clang C compiler.
* libfuzzer. On Ubuntu-derived systems, it can be installed with
<tt>apt install libfuzzer-XYZ</tt>, where XYZ is a version number
(several versions may be available on any given system)
First, modify the top-level <tt>Makefile.in</tt>:
* Extend the <tt>TCCFLAGS</tt> variable with: <tt>-fsanitize=fuzzer
-DFOSSIL_FUZZ</tt> (and see [/finfo/src/fuzz.c | src/fuzz.c] for
more options).
* Rename <tt>APPNAME</tt> from <tt>fossil</tt> to <tt>fossil-fuzz</tt>.
Then rebuild:
<pre></code>$ make clean
$ ./configure CC=/path/to/clang
$ make
</code></pre>
If clang is your default compiler, the <tt>CC</tt> configure option is
not required.
The resulting <tt>fossil-fuzz</tt> binary differs from the standard
one primarily in that it runs the <tt>test-fuzz</tt> command by
default. It needs to be told what to fuzz and needs to be given a
directory of input files to seed the fuzzer with:
<pre></code>$ mkdir cases
# Copy input files into ./cases. e.g. when fuzzing the markdown
# processor, copy any to-be-tested .md files into that directory.
# Then start the fuzzer:
$ ./fossil-fuzz --fuzztype markdown cases
</code></pre>
As it works, it writes its mutated test files into the test-input
directory, each one named in the form of a hash. When it finds a
problem it will produce a stack trace for the offending code, will
output the name of the file which triggered the crash (named
<tt>cases/SOME_HASH</tt>) and may, depending on the nature of the
problem, produce a file named <tt>crash-SOMETHING</tt>. In theory the
crash file can be fed directly back into the fuzzer to reproduce the
problem:
<pre></code>$ ./fossil-fuzz --fuzztype markdown crash-SOMETHING
</code></pre>
But whether or not it will genuinely crash may depend on static
app-level state which might not trigger the crash when running an
individual test.
For a detailed information about the fuzzer's flags and features, see:
* [https://llvm.org/docs/LibFuzzer.html]
* [https://github.com/google/fuzzing/blob/master/tutorial/libFuzzerTutorial.md]
Flags for the fuzzer can be passed directly to fossil,
e.g. <tt>-jobs=4</tt> to start four fuzzer jobs in parallel, but doing
so may cause the fuzzer to <em>strip the --fuzztype flag</em>, leading
to it testing the wrong thing. When passing on fuzzer-specific flags
along with <tt>--fuzztype</tt>, be sure to check your system's process
list to ensure that your <tt>--fuzztype</tt> flag is there.
<a id='wasm'></a>
<h2>8.0 Building WebAssembly Components</h2>
As of version 2.19, fossil uses one component built as
[https://developer.mozilla.org/en-US/docs/WebAssembly | WebAssembly]
a.k.a. WASM. Because compiling WASM code requires non-trivial
client-side tooling, the repository includes compiled copies of these
pieces. Most Fossil hackers should never need to concern themselves
with the WASM parts, but this section describes how to for those who
want or need to do so.
<strong>The bits described in this section are necessary when updating
<tt>extsrc/pikchr.c</tt></strong> from the upstream source, or the
fossil binary will use a different version of pikchr than
[/pikchrshow] does (as the latter runs the WASM build of pikchr).
These instructions have only ever been tested on Linux systems. They
"should" work on any Unix-like system supported by Emscripten. The
fossil makefiles for Windows builds <em>do not</em> include any of the
WASM-related components (patches to add that would be welcomed, of
course).
The first step is to configure the tree with support for
[https://emscripten.org/|Emscripten]. This requires that the system
has the Emscripten SDK (a.k.a. emsdk) installed, as documented at:
[https://emscripten.org/docs/getting_started/downloads.html]
For instructions on keeping the SDK up to date, see:
[https://emscripten.org/docs/tools_reference/emsdk.html]
Sidebar: getting Emscripten up and running is trivial and
painless, at least on Linux systems, but the installer downloads
many hundreds of megabytes of tools and dependencies, all of which
will be installed under the single SDK directory (as opposed to
being installed at the system level). It does, however, require
that python3 be installed at the system level and it can
optionally make use of a system-level cmake for certain tasks
unrelated to how fossil uses the SDK.
After installing the SDK, configure the fossil tree with emsdk
support:
<pre><code>$ ./configure --with-emsdk=/path/to/emsdk ...other options...
</code></pre>
If the <tt>--with-emsdk</tt> flag is not provided, the configure
script will check for the environment variable <tt>EMSDK</tt>, which
is one of the standard variables the SDK environment uses. If that
variable is found, its value will implicitly be used in place of the
missing <tt>--with-emsdk</tt> flag. Thus, if the <tt>emsdk_env.sh</tt>
script is sourced into the shell before running the configure script,
the SDK will be detected even without the config flag.
The configure script installs some makefile variables which tell the
build where to find the SDK and it generates a script named
<tt>tools/emcc.sh</tt> (from the template file
<tt>[/file/tools/emcc.sh.in|/tools/emcc.sh.in]</tt>), which is a
wrapper around the Emscripten C compiler (<tt>emcc</tt>). The wrapper
script uses the configure-time state to attempt to set up the various
environment variables which are required by <tt>emcc</tt> and will
fail if it cannot do so. Once it's set up the environment, it passes
on all of its arguments to <tt>emcc</tt>.
The WASM-related build parts are set up such that none of them should
ever trigger implicity (e.g. via dependencies resolution) in a normal
build cycle. They are instead explicitly built as described below.
From the top of the source tree, all WASM-related components can be
built with:
<pre><code>$ make wasm</code></pre>
As of this writing, those parts include:
* <tt>extsrc/pikchr.wasm</tt> is a WASM-compiled form of
<tt>extsrc/pikchr.c</tt>.
* <tt>extsrc/pikchr.js</tt> is JS/WASM glue code generated by Emscripten
to give JS code access to the API exported by the WASM file.
Sidebar: The file
<tt>[/file/extsrc/pikcher-worker.js|extsrc/pikcher-worker.js]</tt>
is hand-coded and intended to be loaded as a "Worker" in
JavaScript. That file loads the main module and provides an
interface via which a main JavaScript thread can communicate with
pikchr running in a Worker thread. The file
<tt>[/file/src/fossil.page.pikchrshowasm.js|src/fossil.page.pikchrshowasm.js]</tt>
implements the [/pikchrshow] app and demonstrates how
<tt>pikchr-worker.js</tt> is used.
When a new version of <tt>extsrc/pikchr.c</tt> is installed, the
files <tt>pikchr.{js,wasm}</tt> will need to be recompiled to account
for that. Running <tt>make wasm</tt> will, if the build is set up for
the emsdk, recompile those:
<pre><code>$ make wasm
./tools/emcc.sh -o extsrc/pikchr.js ...
$ ls -la extsrc/pikchr.{js,wasm}
-rw-rw-r-- 1 stephan stephan 17263 Jun 8 03:59 extsrc/pikchr.js
-rw-rw-r-- 1 stephan stephan 97578 Jun 8 03:59 extsrc/pikchr.wasm
</code></pre>
<blockquote>Sidebar: if that fails with a message along the lines of:
<pre><code>setting `EXPORTED_RUNTIME_METHODS` expects `<class 'list'>` but got `<class 'str'>`</code></pre>
then the emcc being invoked is too old: emcc changed the format of
list-type arguments at some point. The required minimum version is
unknown, but any SDK version from May 2022 or later "should" (as of
this writing) suffice. Any older version may or may not work.
</blockquote>
After that succeeds, we need to run the normal build so that those
generated files can be compiled in to the fossil binary, accessible
via the [/help?cmd=/builtin|/builtin page]:
<pre><code>$ make</code></pre>
Before checking in those newly-built files, they need to be tested by
running the [/pikchrshow] page. If that page loads, the compilation
process fundamentally worked (a load failure will be made obvious to
the viewer). If it fails to load then the browser's dev tools console
likely provides at least a small hint (and <em>sometimes</em> a useful
hint) about the nature of the problem. Don't check those files in
until [/pikchrshow] runs, though!
Should pikchr's C interface ever change, <tt>pikchr-worker.js</tt>
will need to be updated to accommodate it, but such modification is
typically trivial.
<h3>8.1 Solutions other than Emscripten?</h3>
Emscripten is not the only option for building C as WASM, but it
provides a complete toolchain which eliminates many other steps which
must otherwise be accounted for on a per-project basis. Despite its
convenience, it behooves us to explore other build options for the
sake of portability and avoiding what amounts to vendor lock-in.
For later refererence, here are articles specifically covering
building WASM projects without using Emscripten:
* [https://surma.dev/things/c-to-webassembly/]
* [https://schellcode.github.io/webassembly-without-emscripten]
|
Changes to www/caps/index.md.
| ︙ | ︙ | |||
191 192 193 194 195 196 197 | machine, you can do any reading you want on that repository irrespective of whether your local user within that repo has <b>Read</b> capability. The repo clone is completely under your user’s power at that point, affected only by OS file permissions and such. If you need to prevent that, you want to deny **Clone** capability instead. Withholding the **Read** capability has a different effect: it | | | | | | | | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | machine, you can do any reading you want on that repository irrespective of whether your local user within that repo has <b>Read</b> capability. The repo clone is completely under your user’s power at that point, affected only by OS file permissions and such. If you need to prevent that, you want to deny **Clone** capability instead. Withholding the **Read** capability has a different effect: it prevents a web client from viewing [embedded documentation][edoc], using [the file browser](/help?name=/dir), exploring the [history](/help?name=/timeline) of check-ins, and pulling file content via the [`/artifact`](/help?name=/artifact), [`/file`](/help?name=/file), and [`/raw`](/help?name=/raw) URLs. It is common to withhold **Read** capability from low-status visitors on private or semi-private repos to prevent them from pulling individual elements of the repo over the web one at a time, as someone may do when denied the bulk **Clone** capability. [edoc]: ../embeddeddoc.wiki |
| ︙ | ︙ |
Changes to www/caps/login-groups.md.
1 2 3 4 | # Login Groups The Admin → Login-Groups UI feature and its corresponding [`login-group` command][lg] solve a common problem with Fossil: you’ve created multiple | | > > | | > > > > > | > > | > > | > > > > > > > > > | > > > > | | > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > > > > > | > > > | > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# Login Groups
The Admin → Login-Groups UI feature and its corresponding [`login-group`
command][lg] solve a common problem with Fossil: you’ve created multiple
repositories that some subset of users need access to, and you
don’t want to redundantly administer the user credentials for each
repository.
## Restrictions
This feature ties changes to the “`user`” table in one repo to that in
one or more other repos, keyed by the user’s name. The interactions are
non-obvious because although the goal is for the end result to “just
work,” there are practical security and administration matters that
complicate things:
1. Login group handling only works between joined repositories for the
subset of users with the same name.
1. If you’re logged in on one repo in a group, any other repo in that
group that has a matching user record will accept your valid login.
1. When you set up a login group between two repos, the user tables
aren’t merged, so even though you may have users that appear in
both, they will retain their initial passwords, credentials, and so
forth.
1. The same is true after the login group is created: changes you make
to the user table in one repo in the group only propagate to the
other repos in the group when you check the “Apply changes to all
repositories“ box in the “Scope” section of the user edit screen.
Otherwise, user changes remain local to the repo you made them on.
1. Login groups only affect [the HTTP interfaces][wo]. Contrast things
like `ssh://` clones, where unless you [go out of your way][sh] to
force them to run over one of the HTTP interfaces that pays
attention to Fossil’s RBAC system, login groups aren’t consulted.
## Interactions
These restrictions combine in subtle and interesting ways. Examples:
* **#1 and #2**: If you are logged into repo C as “charlie” and then
try to visit joined repo A where “charlie” doesn’t exist, your valid
login on C won’t get you into A.
* **#2 and #3**: If “alice” exists in both of these same repos,
logging in on A gets her into C, but if she has different user
capabilities on each from the time before the two repos joined the
login group, her caps on A don’t apply to C, nor vice versa.
Let us say F is a forum-only repo, and W is a wiki-only repo, and
that Alice has forum-posting rights on F and wiki-editing rights on
W. If both repos are joined by a login group, Alice can log in on F
and then access W without logging in on it separately, but she
cannot then post a forum message on W even though she could on F.
* **#3 and #4**: If you change the caps for user “alice” on one repo
in a group and tell Fossil to apply the changes to all repos in the
group, the new caps will *overwrite* those on the other repos, not
merge with them.
To extend the practical example from the prior point, let us say you
wish to grant Alice the “write unversioned” capability on both F and
W. If you check that single user cap box on F plus the “apply to
all” option, then “Apply Changes,” she will end up with forum +
unversioned caps on repo W, losing her wiki-editing caps in the
process.
If you want user caps to differ on each repo, you must administer
them separately even if there is a common subset of caps between all
repos in the group for that user. Remember: selecting the “apply to
all” box calls for an overwrite operation, not a merge.
* **#4 and #1**: If you make a change to an existing user “bob” in
repo B and select the “apply to all” option, it will only affect
other repos in the group that have a user “bob” configured.
But, if you are instead creating user “bob” for the first time and
select that option, that user *will* be created in all repos. The
same is true of user deletion: that destructive action will
propagate through the group if you request it.
* **#5 and #1**: If you have a user “daisy” on both repos A and B in a
login group, logging in over the web to A doesn’t let you push
changes into B over SSH. Without the workaround linked above, SSH
only pays attention to the operating system’s user authentication
system, not Fossil’s.
Inversely, if Daisy successfully logs in over SSH to repo B, she
gains no access to any of the other repos in that group. She needs
at least one valid login over HTTP to one of the group’s repos.
## Discussion
The end result of all of this is that you can have a subset of users
with credentials only on repo A, a different subset only on B, and a
third subset common to both. The only thing selecting which case applies
is restriction #1 above.
Login groups have names. A repo can be in only one of these named login
groups at a time.
Trust in login groups is transitive within a single server. Consider
this sequence:
```
$ cd /path/to/A/checkout
$ fossil login-group join --name G ~/museum/B.fossil
$ cd /path/to/C/checkout
$ fossil login-group join ~/museum/B.fossil
```
That creates login group G joining repo A to B, then joins C to B.
Although we didn’t explicitly tie C to A, a successful login on C gets
you into both A and B, within the restrictions set out above.
Changes are transitive in the same way, provided you check that “apply
to all” box on the user edit screen.
[lg]: /help?cmd=login-group
[sh]: ../server/any/http-over-ssh.md
[wo]: ./index.md#webonly
-----
*[Back to Administering User Capabilities](./)*
|
Changes to www/caps/ref.html.
| ︙ | ︙ | |||
117 118 119 120 121 122 123 |
</tr>
<tr id="g">
<th>g</th>
<th>Clone</th>
<td>
Clone the repository. Note that this is distinct from <a
| | > | | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
</tr>
<tr id="g">
<th>g</th>
<th>Clone</th>
<td>
Clone the repository. Note that this is distinct from <a
href="#o">check-out capability, <b>o</b></a>; and that upon cloning
not just files, but also tickets, wikis, technotes and forum posts
are tranferred. Mnemonic: <b>g</b>et.
</td>
</tr>
<tr id="h">
<th>h</th>
<th>Hyperlink</th>
<td>
|
| ︙ | ︙ | |||
143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
<th>i</th>
<th>Write</th>
<td>
Check changes into the repository. Note that a lack of this
capability does not prevent you from checking changes into your
local clone, only from syncing those changes up to the parent
repo, and then <a href="./basics.md#webonly">only over HTTP</a>.
Granting this capability also grants <b>o (Read)</b> Mnemonics:
<b>i</b>nput, check <b>i</b>n changes.
</td>
</tr>
<tr id="j">
<th>j</th>
| > > | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
<th>i</th>
<th>Write</th>
<td>
Check changes into the repository. Note that a lack of this
capability does not prevent you from checking changes into your
local clone, only from syncing those changes up to the parent
repo, and then <a href="./basics.md#webonly">only over HTTP</a>.
Also note that not just files, but also tickets, wikis, technotes
and forum posts will be accepted from clones upon syncronization.
Granting this capability also grants <b>o (Read)</b> Mnemonics:
<b>i</b>nput, check <b>i</b>n changes.
</td>
</tr>
<tr id="j">
<th>j</th>
|
| ︙ | ︙ | |||
200 201 202 203 204 205 206 |
</td>
</tr>
<tr id="o">
<th>o</th>
<th>Read</th>
<td>
| | | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
</td>
</tr>
<tr id="o">
<th>o</th>
<th>Read</th>
<td>
Read content and history of files from a remote Fossil instance over
HTTP. See <a href="index.md#read-v-clone">Reading vs.
Cloning</a>. Mnemonic: check <b>o</b>ut remote repo contents.
</td>
</tr>
<tr id="p">
<th>p</th>
|
| ︙ | ︙ |
Changes to www/changes.wiki.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<title>Change Log</title>
<h2 id='v2_19'>Changes for version 2.19 (pending)</h2>
* On file listing pages, sort filenames using the "uintnocase" collating
sequence, so that filenames that contains embedded integers sort in
numeric order even if they contain a different number of digits.
(Example: "fossil_80_..." comes before "fossil_100.png" in the
[/dir?ci=92fd091703a28c07&name=skins/blitz|/skins/blitz] directory listing.)
* Enhancements to the graph layout algorithm design to improve readability
and promote better situational awareness.
* Performance enhancement for the
[./checkin_names.wiki#root|"root:BRANCHNAME" style of tag],
accomplished using a Common Table Expression in the underlying SQL.
<h2 id='v2_18'>Changes for version 2.18 (2022-02-23)</h2>
* Added support for [./ssl-server.md|SSL/TLS server mode] for commands
like "[/help?cmd=server|fossil server]" and "[/help?cmd=http|fossil http]"
* The new [/help?cmd=cherry-pick|cherry-pick command] is an alias for
[/help?cmd=merge|merge --cherrypick].
* Add new setting "[/help?cmd=large-file-size|large-file-size]". If the size
| > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<title>Change Log</title>
<h2 id='v2_19'>Changes for version 2.19 (pending)</h2>
* On file listing pages, sort filenames using the "uintnocase" collating
sequence, so that filenames that contains embedded integers sort in
numeric order even if they contain a different number of digits.
(Example: "fossil_80_..." comes before "fossil_100.png" in the
[/dir?ci=92fd091703a28c07&name=skins/blitz|/skins/blitz] directory listing.)
* Enhancements to the graph layout algorithm design to improve readability
and promote better situational awareness.
* Performance enhancement for the
[./checkin_names.wiki#root|"root:BRANCHNAME" style of tag],
accomplished using a Common Table Expression in the underlying SQL.
* Sort tag listings (command line and webpage) by taking numbers into
consideration so as to cater for tags that follow semantic versioning.
* On the wiki listings, omit by default wiki pages that are associated with
check-ins and branches.
* Add the new "[/help?cmd=describe|fossil describe]" command.
* Markdown subsystem extended with [../src/markdown.md#ftnts|footnotes support].
See corresponding [../test/markdown-test3.md|test cases],
[/wiki?name=branch/markdown-footnotes#il|known limitations] and
[forum:/forumthread/ee1f1597e46ec07a|discussion].
* Add the new special name "start:BRANCH" to refer to the first check-in of
the branch.
* Support [/wiki?name=branch/generated-tkt-mimetype&p|generated "mimetype"]
columns in the <var>TICKET</var> and <var>TICKETCHNG</var> tables.
* Fix [/timeline?r=fix_remote_url_overwrite_with_proxy|remote-url-overwrite]
bug where remote-url is overwritten by the proxy setting during sync
operation. Also require explicit "system" proxy setting to use
"http_proxy" environment variable.
* Reimplemented the [/pikchrshow] app to use a WebAssembly build of
pikchr so that it can render pikchrs on the client instead of requiring
a server round-trip.
* Add the [/help?cmd=email-listid|email-listid setting]. If set, it is
used as the List-ID header for all outbound notification emails.
<h2 id='v2_18'>Changes for version 2.18 (2022-02-23)</h2>
* Added support for [./ssl-server.md|SSL/TLS server mode] for commands
like "[/help?cmd=server|fossil server]" and "[/help?cmd=http|fossil http]"
* The new [/help?cmd=cherry-pick|cherry-pick command] is an alias for
[/help?cmd=merge|merge --cherrypick].
* Add new setting "[/help?cmd=large-file-size|large-file-size]". If the size
|
| ︙ | ︙ |
Changes to www/checkin_names.wiki.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <title>Check-in Names</title> <table align="right" border="1" width="33%" cellpadding="10"> <tr><td> <h3>Quick Reference</h3> <ul> <li> Hash prefix <li> Branch name <li> Tag name <li> Timestamp: <i>YYYY-MM-DD HH:MM:SS</i> <li> <i>tag-name</i> <big><b>:</b></big> <i>timestamp</i> <li> <b>root <big>:</big></b> <i>branchname</i> <li> <b>merge-in <big>:</big></b> <i>branchname</i> <li> Special names: <ul> <li> <b>tip</b> <li> <b>current</b> <li> <b>next</b> <li> <b>previous</b> or <b>prev</b> | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <title>Check-in Names</title> <table align="right" border="1" width="33%" cellpadding="10"> <tr><td> <h3>Quick Reference</h3> <ul> <li> Hash prefix <li> Branch name <li> Tag name <li> Timestamp: <i>YYYY-MM-DD HH:MM:SS</i> <li> <i>tag-name</i> <big><b>:</b></big> <i>timestamp</i> <li> <b>root <big>:</big></b> <i>branchname</i> <li> <b>start <big>:</big></b> <i>branchname</i> <li> <b>merge-in <big>:</big></b> <i>branchname</i> <li> Special names: <ul> <li> <b>tip</b> <li> <b>current</b> <li> <b>next</b> <li> <b>previous</b> or <b>prev</b> |
| ︙ | ︙ | |||
96 97 98 99 100 101 102 | Note that unlike some other version control systems, a "branch" in Fossil is not anything special: it is simply a sequence of check-ins that share a common tag, so the same mechanism that resolves tag names also resolves branch names. <a id="tagpfx"></a> | | | | | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | Note that unlike some other version control systems, a "branch" in Fossil is not anything special: it is simply a sequence of check-ins that share a common tag, so the same mechanism that resolves tag names also resolves branch names. <a id="tagpfx"></a> Note also that there can — in theory, if rarely in practice — be an ambiguity between tag names and canonical names. Suppose, for example, you had a check-in with the canonical name deed28aa99… and you also happened to have tagged a different check-in with "deed2". If you use the "deed2" name, does it choose the canonical name or the tag name? In such cases, you can prefix the tag name with "tag:". For example: <blockquote><tt> fossil info tag:deed2 |
| ︙ | ︙ | |||
181 182 183 184 185 186 187 | For an example of how timestamps are useful, consider the homepage for the Fossil website itself: <blockquote> http://fossil-scm.org/home/doc/<b>trunk</b>/www/index.wiki </blockquote> | | | | | | | > > > > > > > > > > > > | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | For an example of how timestamps are useful, consider the homepage for the Fossil website itself: <blockquote> http://fossil-scm.org/home/doc/<b>trunk</b>/www/index.wiki </blockquote> The bold component of that URL is a check-in name. To see the stored content of the Fossil website repository as of January 1, 2009, one has merely to change the URL to the following: <blockquote> http://fossil-scm.org/home/doc/<b>2009-01-01</b>/www/index.wiki </blockquote> (Note that this won't roll you back to the <i>skin</i> and other cosmetic configurations as of that date. It also won't change screens like the timeline, which has an independent date selector.) <h2 id="tag-ts">Tag And Timestamp</h2> A check-in name can also take the form of a tag or branch name followed by a colon and then a timestamp. The combination means to take the most recent check-in with the given tag or branch which is not more recent than the timestamp. So, for example: <blockquote><tt> fossil update trunk:2010-07-01T14:30 </tt></blockquote> Would cause Fossil to update the working check-out to be the most recent check-in on the trunk that is not more recent than 14:30 (UTC) on July 1, 2010. <h2 id="root">Root Of A Branch</h2> A branch name that begins with the "<tt>root:</tt>" prefix refers to the last check-in on the parent branch prior to the beginning of the branch. Such a label is useful, for example, in computing all diffs for a single branch. The following example will show all changes in the hypothetical branch "xyzzy": <blockquote><tt> fossil diff --from root:xyzzy --to xyzzy </tt></blockquote> <a id="merge-in"></a> That doesn't do what you might expect after you merge the parent branch's changes into the child branch: the above command will include changes made on the parent branch as well. You can solve this by using the prefix "<tt>merge-in:</tt>" instead of "<tt>root:</tt>" to tell Fossil to find the most recent merge-in point for that branch. The resulting diff will then show only the changes in the branch itself, omitting any changes that have already been merged in from the parent branch. <a id="start"></a> The prefix "<tt>start:</tt>" gives the first check-in of the named branch. The prefixes "<tt>root:</tt>" and "<tt>merge-in:</tt>" can be chained: one can say for example <blockquote><tt> fossil info merge-in:xyzzy:2022-03-01 </tt></blockquote> to get informations about the most recent merge-in point on the branch "xyzzy" that happened on or before March 1, 2022. <h2 id="special">Special Tags</h2> The tag "tip" means the most recent check-in. The "tip" tag is practically equivalent to the timestamp "9999-12-31". This special name works anywhere you can pass a "NAME", such as with |
| ︙ | ︙ | |||
288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
Fossil currently resolves name strings to artifact hashes in the
following order:
# Exact matches on [#special | the special names]
# [#timestamps | Timestamps], with preference to ISO8601 forms
# [#tagpfx | tag:TAGNAME]
# [#root | root:BRANCH]
# [#merge-in | merge-in:BRANCH]
# [#tag-ts | TAGNAME:timestamp]
# Full artifact hash or hash prefix.
# Any other type of symbolic name that Fossil extracts from
artifacts.
<div style="height:50em" id="this-space-intentionally-left-blank"></div>
| > | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
Fossil currently resolves name strings to artifact hashes in the
following order:
# Exact matches on [#special | the special names]
# [#timestamps | Timestamps], with preference to ISO8601 forms
# [#tagpfx | tag:TAGNAME]
# [#root | root:BRANCH]
# [#start | start:BRANCH]
# [#merge-in | merge-in:BRANCH]
# [#tag-ts | TAGNAME:timestamp]
# Full artifact hash or hash prefix.
# Any other type of symbolic name that Fossil extracts from
artifacts.
<div style="height:50em" id="this-space-intentionally-left-blank"></div>
|
Changes to www/glossary.md.
| ︙ | ︙ | |||
296 297 298 299 300 301 302 303 304 | [commit]: /help?cmd=commit [cwork]: ./ckout-workflows.md [h2cflp]: https://www.sqlite.org/howtocorrupt.html#_file_locking_problems [fpvsc]: https://marketplace.visualstudio.com/items?itemName=koog1000.fossil [open]: /help?cmd=open [mwd]: ./ckout-workflows.md#mcw [update]: /help?cmd=update <div style="height:50em" id="this-space-intentionally-left-blank"></div> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
[commit]: /help?cmd=commit
[cwork]: ./ckout-workflows.md
[h2cflp]: https://www.sqlite.org/howtocorrupt.html#_file_locking_problems
[fpvsc]: https://marketplace.visualstudio.com/items?itemName=koog1000.fossil
[open]: /help?cmd=open
[mwd]: ./ckout-workflows.md#mcw
[update]: /help?cmd=update
## <a id="docs"></a>Embedded Documentation
Serving as an alternative to Fossil’s built-in [wiki], the [embedded
documentation feature][edoc] stores the same type of marked-up text
files, but under Fossil’s powerful version control features.
* The simple rule for determining whether to use the wiki or embedded
docs for any given document is whether the content is considered
“evergreen,” as with a Wikipedia article.
While Fossil’s wiki feature does store the history of each
document’s changes, Fossil always presents the current version of
the document unless you manually go out of your way to dig back into
the history. Then, having done so, links from that historical
version of the wiki document take you to the current versions of the
target documents, not to the version contemporaneous with the source
document.
The consequence is that if you say something like…
$ fossil up 2020-04-01
$ fossil ui --page wcontent
…you will **not** see the list of wiki articles as of April Fool’s Day in 2020, but
instead the list of *current* wiki article versions, the same as if you ran it
from a check-out of the tip-of-trunk.
Contrast embedded docs, which are not only version-controlled as
normal files are in Fossil, they participate in all the tagging,
branching, and other versioning features. There are several
consequences of this, such as that Fossil’s [special check-in
names][ciname] work with embedded doc URLs:
* <p>If you visit an embedded doc as `/doc/release/file.md` and
then click on a relative link from that document, you will remain on
the release branch. This lets you see not only the release
version of a software project but also the documentation as of
that release.</p>
* <p>If you visit `/doc/2020-04-01/file.md`, you will not only
pull up the version of `file.md` as of that date, relative links
will take you to contemporaneous versions of those embedded docs
as well.</p>
* <p>If you say `fossil up 2020-04-01 && fossil ui` and then visit
`/doc/ckout/file.md`, you’ll not only see the checked-out
version of the file as of that date, relative links will show
you other files within that checkout.</p>
* Fossil’s wiki presents a flat list of articles, while embedded docs
are stored in the repository’s file hierarchy, a powerful
organizational tool well-suited to complicated documentation.
* Your repository’s Home page is a good candidate for the wiki, as is
documentation meant for use only with the current version of the
repository’s contents.
* If you are at all uncertain whether to use the wiki or the embedded
documentation feature, prefer the latter, since it is more powerful
and, with the addition of the [`/fileedit` feature][fef] in Fossil
2.12, it’s nearly as easy to use.
(This very file is embedded documentation: clone
[Fossil’s self-hosting repository][fshr] and you will find it as
`www/glossary.md`.)
[edoc]: ./embeddeddoc.wiki
[fef]: ./fileedit-page.md
[fshr]: ./selfhost.wiki
[wiki]: ./wikitheory.wiki
<div style="height:50em" id="this-space-intentionally-left-blank"></div>
|
Changes to www/grep.md.
1 2 3 | # Fossil grep vs POSIX grep As of Fossil 2.7, there is a `grep` command which acts roughly like | | | > > > | | < < < | | > > < < | < | < | > | | > | > > | > > > > > > | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# Fossil grep vs POSIX grep
As of Fossil 2.7, there is a `grep` command which acts roughly like
POSIX's `grep -E` over all historical versions of one or more managed files.
This document explains the commonalities and divergences between [POSIX
`grep`](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html)
and Fossil `grep`.
## Options
Fossil `grep` implements about half of the options specified for
POSIX `grep`:
| Option | Meaning
|--------|-------------------------------------------------------------
| `-c` | report the count of matches rather than the matched text
| `-i` | ignore case in matches
| `-l` | list a checkin ID prefix for matching historical versions of the file
| `-q` | no output; return only a status code indicating the success of the match
| `-s` | suppress error output about missing files
| `-v` | invert the sense of the match
That leaves several divergences at the option level from POSIX `grep`:
* You cannot give more than one pattern, as with `grep -e` or
`grep -f`.
* There is no equivalent of `grep -F` to do literal fixed-string
matches only.
* There is no `-x` option for doing a whole-line match.
* `fossil grep -l` does not do precisely the same thing as POSIX
`grep -l`: it lists checkin ID prefixes, not file names.
* Fossil always gives the line number in its output, which is to say
that it acts like `grep -n`. There is no way to disable the line
number in `fossil grep` output.
Patches to remove those limitations will be thoughtfully considered.
Fossil `grep` doesn’t support any of the GNU and BSD `grep` extensions.
For instance, it doesn’t support the common `-R` extension to POSIX,
which would presumably search a subtree of managed files. If Fossil does
one day get this feature, it would have a different option letter, since
`-R` in Fossil has a different meaning, by convention. Until then, you
can get the same effect on systems with a POSIX shell like so:
$ fossil grep COMMAND: $(fossil ls src)
If you run that in a check-out of the [Fossil self-hosting source
repository][fshsr], that returns the first line of the built-in
documentation for each Fossil command, across all historical verisons.
Fossil `grep` has extensions relative to these other `grep` standards,
such as `--verbose` to print each checkin ID considered, regardless of
whether it matches. This one is noteworthy here because the behavior
used to be under `-v` before we reassigned it to give POSIX-like `grep
-v` behavior.
[fshsr]: ./selfhost.wiki
## Regular Expression Dialect
Fossil contains a built-in regular expression engine implementing a
subset of the [POSIX extended regular expression][ere] dialect:
|
| ︙ | ︙ |
Changes to www/json-api/conventions.md.
| ︙ | ︙ | |||
179 180 181 182 183 184 185 | likely be interpreted as the integer 123. No APIs currently rely on integer parameters with more than 32 bits (signedness is call-dependent but few, if any, use negative values). **Boolean** parameters are a bit schizophrenic... In **CLI mode**, boolean flags do not have a value, per se, and thus | | | | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | likely be interpreted as the integer 123. No APIs currently rely on integer parameters with more than 32 bits (signedness is call-dependent but few, if any, use negative values). **Boolean** parameters are a bit schizophrenic... In **CLI mode**, boolean flags do not have a value, per se, and thus require no string-to-bool conversion. e.g. `fossil foo -aBoolOpt -non-bool-opt value`. Those which arrive as strings via **GET parameters** treat any of the following as true: a string starting with a character in the set `[1-9tT]`. All other string values are considered to be false for this purpose. Those which are part of the **POST data** are normally (but not always - |
| ︙ | ︙ |
Changes to www/json-api/hacking.md.
| ︙ | ︙ | |||
36 37 38 39 40 41 42 | 3. The Golden Rule is: *do not break the trunk build*. <a id="json-c-api"></a> # JSON C API libcson, the underlying JSON API, is a separate project, included in | | | | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | 3. The Golden Rule is: *do not break the trunk build*. <a id="json-c-api"></a> # JSON C API libcson, the underlying JSON API, is a separate project, included in fossil in "amalgamation" form: see `extsrc/cson_amalgamation.[ch]`. It has thorough API docs and a good deal of information is in its wiki: [](https://fossil.wanderinghorse.net/wikis/cson/) In particular: [](https://fossil.wanderinghorse.net/wikis/cson/?page=CsonArchitecture) gives an overview of its architecture. Occasionally new versions of it are pulled into the Fossil tree, but other developers generally need not concern themselves with that. (Trivia: the cson wiki's back-end is fossil using this very JSON API, living on top of a custom JavaScript+HTML5 application.) Only a small handful of low-level fossil routines actually input or output JSON text (only for reading in POST data and sending the response). In the C code we work with the higher-level JSON value abstractions provided by cson (conceptually similar to an XML DOM). All of the JSON-defined data types are supported, and we can construct JSON output of near arbitrary complexity with the caveat that *cyclic data |
| ︙ | ︙ | |||
307 308 309 310 311 312 313 | ## Converting SQL Query Results to JSON The `cson_sqlite3_xxx()` family of functions convert `sqlite3_stmt` rows to Arrays or Objects, or convert single columns to a JSON-compatible form. See `json_stmt_to_array_of_obj()`, `json_stmt_to_array_of_array()` (both in `src/json.c`), and `cson_sqlite3_column_to_value()` and friends (in | | | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | ## Converting SQL Query Results to JSON The `cson_sqlite3_xxx()` family of functions convert `sqlite3_stmt` rows to Arrays or Objects, or convert single columns to a JSON-compatible form. See `json_stmt_to_array_of_obj()`, `json_stmt_to_array_of_array()` (both in `src/json.c`), and `cson_sqlite3_column_to_value()` and friends (in `extsrc/cson_amalgamation.h`). They work in an intuitive way for numeric types, but they optimistically/natively *assume* that any fields of type TEXT or BLOB are actually UTF8 data, and treat them as such. cson's string class only handles UTF8 data and it is semantically illegal to feed them anything but UTF8. Violating this will likely result in down-stream errors (e.g. when emiting the JSON string output). **The moral of this story is:** *do not use these APIs to fetch binary data*. JSON doesn't do binary and the `cson_string` class does not |
| ︙ | ︙ |
Changes to www/mkindex.tcl.
| ︙ | ︙ | |||
76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
hints.wiki {Fossil Tips And Usage Hints}
history.md {The Purpose And History Of Fossil}
index.wiki {Home Page}
inout.wiki {Import And Export To And From Git}
interwiki.md {Interwiki Links}
image-format-vs-repo-size.md {Image Format vs Fossil Repo Size}
javascript.md {Use of JavaScript in Fossil}
loadmgmt.md {Managing Server Load}
makefile.wiki {The Fossil Build Process}
mirrorlimitations.md {Limitations On Git Mirrors}
mirrortogithub.md {How To Mirror A Fossil Repository On GitHub}
/md_rules {Markdown Formatting Rules}
newrepo.wiki {How To Create A New Fossil Repository}
patchcmd.md {The "fossil patch" Command}
| > | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
hints.wiki {Fossil Tips And Usage Hints}
history.md {The Purpose And History Of Fossil}
index.wiki {Home Page}
inout.wiki {Import And Export To And From Git}
interwiki.md {Interwiki Links}
image-format-vs-repo-size.md {Image Format vs Fossil Repo Size}
javascript.md {Use of JavaScript in Fossil}
json-api/index.md {JSON API}
loadmgmt.md {Managing Server Load}
makefile.wiki {The Fossil Build Process}
mirrorlimitations.md {Limitations On Git Mirrors}
mirrortogithub.md {How To Mirror A Fossil Repository On GitHub}
/md_rules {Markdown Formatting Rules}
newrepo.wiki {How To Create A New Fossil Repository}
patchcmd.md {The "fossil patch" Command}
|
| ︙ | ︙ |
Changes to www/permutedindex.html.
| ︙ | ︙ | |||
38 39 40 41 42 43 44 | <li><a href="childprojects.wiki">Child Projects</a></li> <li><a href="build.wiki">Compiling and Installing Fossil</a></li> <li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li> <li><a href="copyright-release.html">Contributor License Agreement</a></li> <li><a href="private.wiki">Creating, Syncing, and Deleting Private Branches</a></li> <li><a href="customskin.md">Custom Skins</a></li> <li><a href="custom_ticket.wiki">Customizing The Ticket System</a></li> | | | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <li><a href="childprojects.wiki">Child Projects</a></li> <li><a href="build.wiki">Compiling and Installing Fossil</a></li> <li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li> <li><a href="copyright-release.html">Contributor License Agreement</a></li> <li><a href="private.wiki">Creating, Syncing, and Deleting Private Branches</a></li> <li><a href="customskin.md">Custom Skins</a></li> <li><a href="custom_ticket.wiki">Customizing The Ticket System</a></li> <li><a href="antibot.wiki">Defense against Spiders and Robots</a></li> <li><a href="delta-manifests.md">Delta Manifests</a></li> <li><a href="contact.md">Developer Contact Information</a></li> <li><a href="caps/admin-v-setup.md">Differences Between Setup and Admin Users</a></li> <li><a href="alerts.md">Email Alerts And Notifications</a></li> <li><a href="embeddeddoc.wiki">Embedded Project Documentation</a></li> <li><a href="env-opts.md">Environment Variables and Global Options</a></li> <li><a href="event.wiki">Events</a></li> |
| ︙ | ︙ | |||
85 86 87 88 89 90 91 92 93 94 95 96 97 98 | <li><a href="encryptedrepos.wiki">How To Use Encrypted Repositories</a></li> <li><a href="image-format-vs-repo-size.md">Image Format vs Fossil Repo Size</a></li> <li><a href="inout.wiki">Import And Export To And From Git</a></li> <li><a href="fossil-from-msvc.wiki">Integrating Fossil in the Microsoft Express 2010 IDE</a></li> <li><a href="interwiki.md">Interwiki Links</a></li> <li><a href="fossil-is-not-relational.md">Introduction to the (Non-relational) Fossil Data Model</a></li> <li><a href="blockchain.md">Is Fossil A Blockchain?</a></li> <li><a href="mirrorlimitations.md">Limitations On Git Mirrors</a></li> <li><a href="../../../help">Lists of Commands and Webpages</a></li> <li><a href="loadmgmt.md">Managing Server Load</a></li> <li><a href="../../../md_rules">Markdown Formatting Rules</a></li> <li><a href="password.wiki">Password Management And Authentication</a></li> <li><a href="stats.wiki">Performance Statistics</a></li> <li><a href="../test/release-checklist.wiki">Pre-Release Testing Checklist</a></li> | > | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | <li><a href="encryptedrepos.wiki">How To Use Encrypted Repositories</a></li> <li><a href="image-format-vs-repo-size.md">Image Format vs Fossil Repo Size</a></li> <li><a href="inout.wiki">Import And Export To And From Git</a></li> <li><a href="fossil-from-msvc.wiki">Integrating Fossil in the Microsoft Express 2010 IDE</a></li> <li><a href="interwiki.md">Interwiki Links</a></li> <li><a href="fossil-is-not-relational.md">Introduction to the (Non-relational) Fossil Data Model</a></li> <li><a href="blockchain.md">Is Fossil A Blockchain?</a></li> <li><a href="json-api/index.md">JSON API</a></li> <li><a href="mirrorlimitations.md">Limitations On Git Mirrors</a></li> <li><a href="../../../help">Lists of Commands and Webpages</a></li> <li><a href="loadmgmt.md">Managing Server Load</a></li> <li><a href="../../../md_rules">Markdown Formatting Rules</a></li> <li><a href="password.wiki">Password Management And Authentication</a></li> <li><a href="stats.wiki">Performance Statistics</a></li> <li><a href="../test/release-checklist.wiki">Pre-Release Testing Checklist</a></li> |
| ︙ | ︙ |
Changes to www/reviews.wiki.
1 2 3 4 5 |
<title>Reviews</title>
<b>External links:</b>
* [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html |
Fossil DVCS on the Go - First Impressions]
| < < < | 1 2 3 4 5 6 7 8 9 10 11 12 |
<title>Reviews</title>
<b>External links:</b>
* [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html |
Fossil DVCS on the Go - First Impressions]
<b>See Also:</b>
* [./quotes.wiki | Short Quotes on Fossil, Git, And DVCSes]
<b>Daniel writes on 2009-01-06:</b>
|
| ︙ | ︙ |
Changes to www/tech_overview.wiki.
| ︙ | ︙ | |||
175 176 177 178 179 180 181 | the configuration database on a line that starts with "config-db:". <h3>2.2 Repository Databases</h3> The repository database is the file that is commonly referred to as "the repository". This is because the repository database contains, among other things, the complete revision, ticket, and wiki history for | | | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | the configuration database on a line that starts with "config-db:". <h3>2.2 Repository Databases</h3> The repository database is the file that is commonly referred to as "the repository". This is because the repository database contains, among other things, the complete revision, ticket, and wiki history for a project. It is customary to name the repository database after the name of the project, with a ".fossil" suffix. For example, the repository database for the self-hosting Fossil repository is called "fossil.fossil" and the repository database for SQLite is called "sqlite.fossil". <h4>2.2.1 Global Project State</h4> The bulk of the repository database (typically 75 to 85%) consists |
| ︙ | ︙ |