Merge trunk changes into covering-index-expr branch.
FossilOrigin-Name: 89d775ada39aed4dc532374ace02156d07dc06e8ae54a194608af0c5a582d20f
This commit is contained in:
@@ -446,6 +446,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/expert/test_expert.c \
|
||||
$(TOP)/ext/misc/amatch.c \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/misc/basexx.c \
|
||||
$(TOP)/ext/misc/carray.c \
|
||||
$(TOP)/ext/misc/cksumvfs.c \
|
||||
$(TOP)/ext/misc/closure.c \
|
||||
|
||||
Executable
+269
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
** 2022-11-18
|
||||
**
|
||||
** 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 SQLite extension for converting in either direction
|
||||
** between a (binary) blob and base64 text. Base64 can transit a
|
||||
** sane USASCII channel unmolested. It also plays nicely in CSV or
|
||||
** written as TCL brace-enclosed literals or SQL string literals,
|
||||
** and can be used unmodified in XML-like documents.
|
||||
**
|
||||
** This is an independent implementation of conversions specified in
|
||||
** RFC 4648, done on the above date by the author (Larry Brasfield)
|
||||
** who thereby has the right to put this into the public domain.
|
||||
**
|
||||
** The conversions meet RFC 4648 requirements, provided that this
|
||||
** C source specifies that line-feeds are included in the encoded
|
||||
** data to limit visible line lengths to 72 characters and to
|
||||
** terminate any encoded blob having non-zero length.
|
||||
**
|
||||
** Length limitations are not imposed except that the runtime
|
||||
** SQLite string or blob length limits are respected. Otherwise,
|
||||
** any length binary sequence can be represented and recovered.
|
||||
** Generated base64 sequences, with their line-feeds included,
|
||||
** can be concatenated; the result converted back to binary will
|
||||
** be the concatenation of the represented binary sequences.
|
||||
**
|
||||
** This SQLite3 extension creates a function, base64(x), which
|
||||
** either: converts text x containing base64 to a returned blob;
|
||||
** or converts a blob x to returned text containing base64. An
|
||||
** error will be thrown for other input argument types.
|
||||
**
|
||||
** This code relies on UTF-8 encoding only with respect to the
|
||||
** meaning of the first 128 (7-bit) codes matching that of USASCII.
|
||||
** It will fail miserably if somehow made to try to convert EBCDIC.
|
||||
** Because it is table-driven, it could be enhanced to handle that,
|
||||
** but the world and SQLite have moved on from that anachronism.
|
||||
**
|
||||
** To build the extension:
|
||||
** Set shell variable SQDIR=<your favorite SQLite checkout directory>
|
||||
** *Nix: gcc -O2 -shared -I$SQDIR -fPIC -o base64.so base64.c
|
||||
** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR -o base64.dylib base64.c
|
||||
** Win32: gcc -O2 -shared -I%SQDIR% -o base64.dll base64.c
|
||||
** Win32: cl /Os -I%SQDIR% base64.c -link -dll -out:base64.dll
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef SQLITE_SHELL_EXTFUNCS /* Guard for #include as built-in extension. */
|
||||
#include "sqlite3ext.h"
|
||||
#endif
|
||||
|
||||
SQLITE_EXTENSION_INIT1;
|
||||
|
||||
#define PC 0x80 /* pad character */
|
||||
#define WS 0x81 /* whitespace */
|
||||
#define ND 0x82 /* Not above or digit-value */
|
||||
#define PAD_CHAR '='
|
||||
|
||||
#ifndef UBYTE_TYPEDEF
|
||||
typedef unsigned char ubyte;
|
||||
# define UBYTE_TYPEDEF
|
||||
#endif
|
||||
|
||||
static const ubyte b64DigitValues[128] = {
|
||||
/* HT LF VT FF CR */
|
||||
ND,ND,ND,ND, ND,ND,ND,ND, ND,WS,WS,WS, WS,WS,ND,ND,
|
||||
/* US */
|
||||
ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND,
|
||||
/*sp + / */
|
||||
WS,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,62, ND,ND,ND,63,
|
||||
/* 0 1 5 9 = */
|
||||
52,53,54,55, 56,57,58,59, 60,61,ND,ND, ND,PC,ND,ND,
|
||||
/* A O */
|
||||
ND, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
|
||||
/* P Z */
|
||||
15,16,17,18, 19,20,21,22, 23,24,25,ND, ND,ND,ND,ND,
|
||||
/* a o */
|
||||
ND,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
|
||||
/* p z */
|
||||
41,42,43,44, 45,46,47,48, 49,50,51,ND, ND,ND,ND,ND
|
||||
};
|
||||
|
||||
static const char b64Numerals[64+1]
|
||||
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
#define BX_DV_PROTO(c) ((((ubyte)(c))<0x80)? b64DigitValues[c] : 0x80)
|
||||
#define IS_BX_DIGIT(bdp) (((ubyte)(bdp))<0x80)
|
||||
#define IS_BX_WS(bdp) ((bdp)==WS)
|
||||
#define IS_BX_PAD(bdp) ((bdp)==PC)
|
||||
#define BX_NUMERAL(dv) (b64Numerals[(ubyte)(dv)])
|
||||
/* Width of base64 lines. Should be an integer multiple of 4. */
|
||||
#define B64_DARK_MAX 72
|
||||
|
||||
/* Encode a byte buffer into base64 text with linefeeds appended to limit
|
||||
** encoded group lengths to B64_DARK_MAX or to terminate the last group.
|
||||
*/
|
||||
static char* toBase64( ubyte *pIn, int nbIn, char *pOut ){
|
||||
int nCol = 0;
|
||||
while( nbIn >= 3 ){
|
||||
/* Do the bit-shuffle, exploiting unsigned input to avoid masking. */
|
||||
pOut[0] = BX_NUMERAL(pIn[0]>>2);
|
||||
pOut[1] = BX_NUMERAL(((pIn[0]<<4)|(pIn[1]>>4))&0x3f);
|
||||
pOut[2] = BX_NUMERAL(((pIn[1]&0xf)<<2)|(pIn[2]>>6));
|
||||
pOut[3] = BX_NUMERAL(pIn[2]&0x3f);
|
||||
pOut += 4;
|
||||
nbIn -= 3;
|
||||
pIn += 3;
|
||||
if( (nCol += 4)>=B64_DARK_MAX || nbIn<=0 ){
|
||||
*pOut++ = '\n';
|
||||
nCol = 0;
|
||||
}
|
||||
}
|
||||
if( nbIn > 0 ){
|
||||
signed char nco = nbIn+1;
|
||||
int nbe;
|
||||
unsigned long qv = *pIn++;
|
||||
for( nbe=1; nbe<3; ++nbe ){
|
||||
qv <<= 8;
|
||||
if( nbe<nbIn ) qv |= *pIn++;
|
||||
}
|
||||
for( nbe=3; nbe>=0; --nbe ){
|
||||
char ce = (nbe<nco)? BX_NUMERAL((ubyte)(qv & 0x3f)) : PAD_CHAR;
|
||||
qv >>= 6;
|
||||
pOut[nbe] = ce;
|
||||
}
|
||||
pOut += 4;
|
||||
*pOut++ = '\n';
|
||||
}
|
||||
*pOut = 0;
|
||||
return pOut;
|
||||
}
|
||||
|
||||
/* Skip over text which is not base64 numeral(s). */
|
||||
static char * skipNonB64( char *s ){
|
||||
char c;
|
||||
while( (c = *s) && !IS_BX_DIGIT(BX_DV_PROTO(c)) ) ++s;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Decode base64 text into a byte buffer. */
|
||||
static ubyte* fromBase64( char *pIn, int ncIn, ubyte *pOut ){
|
||||
if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn;
|
||||
while( ncIn>0 && *pIn!=PAD_CHAR ){
|
||||
static signed char nboi[] = { 0, 0, 1, 2, 3 };
|
||||
char *pUse = skipNonB64(pIn);
|
||||
unsigned long qv = 0L;
|
||||
int nti, nbo, nac;
|
||||
ncIn -= (pUse - pIn);
|
||||
pIn = pUse;
|
||||
nti = (ncIn>4)? 4 : ncIn;
|
||||
ncIn -= nti;
|
||||
nbo = nboi[nti];
|
||||
if( nbo==0 ) break;
|
||||
for( nac=0; nac<4; ++nac ){
|
||||
char c = (nac<nti)? *pIn++ : b64Numerals[0];
|
||||
ubyte bdp = BX_DV_PROTO(c);
|
||||
switch( bdp ){
|
||||
case ND:
|
||||
/* Treat dark non-digits as pad, but they terminate decode too. */
|
||||
ncIn = 0;
|
||||
/* fall thru */
|
||||
case WS:
|
||||
/* Treat whitespace as pad and terminate this group.*/
|
||||
nti = nac;
|
||||
/* fall thru */
|
||||
case PC:
|
||||
bdp = 0;
|
||||
--nbo;
|
||||
/* fall thru */
|
||||
default: /* bdp is the digit value. */
|
||||
qv = qv<<6 | bdp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch( nbo ){
|
||||
case 3:
|
||||
pOut[2] = (qv) & 0xff;
|
||||
case 2:
|
||||
pOut[1] = (qv>>8) & 0xff;
|
||||
case 1:
|
||||
pOut[0] = (qv>>16) & 0xff;
|
||||
}
|
||||
pOut += nbo;
|
||||
}
|
||||
return pOut;
|
||||
}
|
||||
|
||||
/* This function does the work for the SQLite base64(x) UDF. */
|
||||
static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){
|
||||
int nb, nc, nv = sqlite3_value_bytes(av[0]);
|
||||
int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
|
||||
SQLITE_LIMIT_LENGTH, -1);
|
||||
char *cBuf;
|
||||
ubyte *bBuf;
|
||||
assert(na==1);
|
||||
switch( sqlite3_value_type(av[0]) ){
|
||||
case SQLITE_BLOB:
|
||||
nb = nv;
|
||||
nc = 4*(nv+2/3); /* quads needed */
|
||||
nc += (nc+(B64_DARK_MAX-1))/B64_DARK_MAX + 1; /* LFs and a 0-terminator */
|
||||
if( nvMax < nc ){
|
||||
sqlite3_result_error(context, "blob expanded to base64 too big", -1);
|
||||
return;
|
||||
}
|
||||
cBuf = sqlite3_malloc(nc);
|
||||
if( !cBuf ) goto memFail;
|
||||
bBuf = (ubyte*)sqlite3_value_blob(av[0]);
|
||||
nc = (int)(toBase64(bBuf, nb, cBuf) - cBuf);
|
||||
sqlite3_result_text(context, cBuf, nc, sqlite3_free);
|
||||
break;
|
||||
case SQLITE_TEXT:
|
||||
nc = nv;
|
||||
nb = 3*((nv+3)/4); /* may overestimate due to LF and padding */
|
||||
if( nvMax < nb ){
|
||||
sqlite3_result_error(context, "blob from base64 may be too big", -1);
|
||||
return;
|
||||
}else if( nb<1 ){
|
||||
nb = 1;
|
||||
}
|
||||
bBuf = sqlite3_malloc(nb);
|
||||
if( !bBuf ) goto memFail;
|
||||
cBuf = (char *)sqlite3_value_text(av[0]);
|
||||
nb = (int)(fromBase64(cBuf, nc, bBuf) - bBuf);
|
||||
sqlite3_result_blob(context, bBuf, nb, sqlite3_free);
|
||||
break;
|
||||
default:
|
||||
sqlite3_result_error(context, "base64 accepts only blob or text", -1);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
memFail:
|
||||
sqlite3_result_error(context, "base64 OOM", -1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Establish linkage to running SQLite library.
|
||||
*/
|
||||
#ifndef SQLITE_SHELL_EXTFUNCS
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_base_init
|
||||
#else
|
||||
static int sqlite3_base64_init
|
||||
#endif
|
||||
(sqlite3 *db, char **pzErr, const sqlite3_api_routines *pApi){
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErr;
|
||||
return sqlite3_create_function
|
||||
(db, "base64", 1,
|
||||
SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_DIRECTONLY|SQLITE_UTF8,
|
||||
0, base64, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Define some macros to allow this extension to be built into the shell
|
||||
** conveniently, in conjunction with use of SQLITE_SHELL_EXTFUNCS. This
|
||||
** allows shell.c, as distributed, to have this extension built in.
|
||||
*/
|
||||
#define BASE64_INIT(db) sqlite3_base64_init(db, 0, 0)
|
||||
#define BASE64_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */
|
||||
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
** 2022-11-16
|
||||
**
|
||||
** 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 utility for converting binary to base85 or vice-versa.
|
||||
** It can be built as a standalone program or an SQLite3 extension.
|
||||
**
|
||||
** Much like base64 representations, base85 can be sent through a
|
||||
** sane USASCII channel unmolested. It also plays nicely in CSV or
|
||||
** written as TCL brace-enclosed literals or SQL string literals.
|
||||
** It is not suited for unmodified use in XML-like documents.
|
||||
**
|
||||
** The encoding used resembles Ascii85, but was devised by the author
|
||||
** (Larry Brasfield) before Mozilla, Adobe, ZMODEM or other Ascii85
|
||||
** variant sources existed, in the 1984 timeframe on a VAX mainframe.
|
||||
** Further, this is an independent implementation of a base85 system.
|
||||
** Hence, the author has rightfully put this into the public domain.
|
||||
**
|
||||
** Base85 numerals are taken from the set of 7-bit USASCII codes,
|
||||
** excluding control characters and Space ! " ' ( ) { | } ~ Del
|
||||
** in code order representing digit values 0 to 84 (base 10.)
|
||||
**
|
||||
** Groups of 4 bytes, interpreted as big-endian 32-bit values,
|
||||
** are represented as 5-digit base85 numbers with MS to LS digit
|
||||
** order. Groups of 1-3 bytes are represented with 2-4 digits,
|
||||
** still big-endian but 8-24 bit values. (Using big-endian yields
|
||||
** the simplest transition to byte groups smaller than 4 bytes.
|
||||
** These byte groups can also be considered base-256 numbers.)
|
||||
** Groups of 0 bytes are represented with 0 digits and vice-versa.
|
||||
** No pad characters are used; Encoded base85 numeral sequence
|
||||
** (aka "group") length maps 1-to-1 to the decoded binary length.
|
||||
**
|
||||
** Any character not in the base85 numeral set delimits groups.
|
||||
** When base85 is streamed or stored in containers of indefinite
|
||||
** size, newline is used to separate it into sub-sequences of no
|
||||
** more than 80 digits so that fgets() can be used to read it.
|
||||
**
|
||||
** Length limitations are not imposed except that the runtime
|
||||
** SQLite string or blob length limits are respected. Otherwise,
|
||||
** any length binary sequence can be represented and recovered.
|
||||
** Base85 sequences can be concatenated by separating them with
|
||||
** a non-base85 character; the conversion to binary will then
|
||||
** be the concatenation of the represented binary sequences.
|
||||
|
||||
** The standalone program either converts base85 on stdin to create
|
||||
** a binary file or converts a binary file to base85 on stdout.
|
||||
** Read or make it blurt its help for invocation details.
|
||||
**
|
||||
** The SQLite3 extension creates a function, base85(x), which will
|
||||
** either convert text base85 to a blob or a blob to text base85
|
||||
** and return the result (or throw an error for other types.)
|
||||
** Unless built with OMIT_BASE85_CHECKER defined, it also creates a
|
||||
** function, is_base85(t), which returns 1 iff the text t contains
|
||||
** nothing other than base85 numerals and whitespace, or 0 otherwise.
|
||||
**
|
||||
** To build the extension:
|
||||
** Set shell variable SQDIR=<your favorite SQLite checkout directory>
|
||||
** and variable OPTS to -DOMIT_BASE85_CHECKER if is_base85() unwanted.
|
||||
** *Nix: gcc -O2 -shared -I$SQDIR $OPTS -fPIC -o base85.so base85.c
|
||||
** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR $OPTS -o base85.dylib base85.c
|
||||
** Win32: gcc -O2 -shared -I%SQDIR% %OPTS% -o base85.dll base85.c
|
||||
** Win32: cl /Os -I%SQDIR% %OPTS% base85.c -link -dll -out:base85.dll
|
||||
**
|
||||
** To build the standalone program, define PP symbol BASE85_STANDALONE. Eg.
|
||||
** *Nix or OSX: gcc -O2 -DBASE85_STANDALONE base85.c -o base85
|
||||
** Win32: gcc -O2 -DBASE85_STANDALONE -o base85.exe base85.c
|
||||
** Win32: cl /Os /MD -DBASE85_STANDALONE base85.c
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#ifndef OMIT_BASE85_CHECKER
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
|
||||
#ifndef BASE85_STANDALONE
|
||||
|
||||
#ifndef SQLITE_SHELL_EXTFUNCS /* Guard for #include as built-in extension. */
|
||||
# include "sqlite3ext.h"
|
||||
#endif
|
||||
|
||||
SQLITE_EXTENSION_INIT1;
|
||||
|
||||
#else
|
||||
|
||||
# ifdef _WIN32
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
# else
|
||||
# define setmode(fd,m)
|
||||
# endif
|
||||
|
||||
static char *zHelp =
|
||||
"Usage: base85 <dirFlag> <binFile>\n"
|
||||
" <dirFlag> is either -r to read or -w to write <binFile>,\n"
|
||||
" content to be converted to/from base85 on stdout/stdin.\n"
|
||||
" <binFile> names a binary file to be rendered or created.\n"
|
||||
" Or, the name '-' refers to the stdin or stdout stream.\n"
|
||||
;
|
||||
|
||||
static void sayHelp(){
|
||||
printf("%s", zHelp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef UBYTE_TYPEDEF
|
||||
typedef unsigned char ubyte;
|
||||
# define UBYTE_TYPEDEF
|
||||
#endif
|
||||
|
||||
/* Classify c according to interval within USASCII set w.r.t. base85
|
||||
* Values of 1 and 3 are base85 numerals. Values of 0, 2, or 4 are not.
|
||||
*/
|
||||
#define B85_CLASS( c ) (((c)>='#')+((c)>'&')+((c)>='*')+((c)>'z'))
|
||||
|
||||
/* Provide digitValue to b85Numeral offset as a function of above class. */
|
||||
static ubyte b85_cOffset[] = { 0, '#', 0, '*'-4, 0 };
|
||||
#define B85_DNOS( c ) b85_cOffset[B85_CLASS(c)]
|
||||
|
||||
/* Say whether c is a base85 numeral. */
|
||||
#define IS_B85( c ) (B85_CLASS(c) & 1)
|
||||
|
||||
#if 0 /* Not used, */
|
||||
static ubyte base85DigitValue( char c ){
|
||||
ubyte dv = (ubyte)(c - '#');
|
||||
if( dv>87 ) return 0xff;
|
||||
return (dv > 3)? dv-3 : dv;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Width of base64 lines. Should be an integer multiple of 5. */
|
||||
#define B85_DARK_MAX 80
|
||||
|
||||
|
||||
static char * skipNonB85( char *s ){
|
||||
char c;
|
||||
while( (c = *s) && !IS_B85(c) ) ++s;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Convert small integer, known to be in 0..84 inclusive, to base85 numeral.
|
||||
* Do not use the macro form with argument expression having a side-effect.*/
|
||||
#if 0
|
||||
static char base85Numeral( ubyte b ){
|
||||
return (b < 4)? (char)(b + '#') : (char)(b - 4 + '*');
|
||||
}
|
||||
#else
|
||||
# define base85Numeral( dn )\
|
||||
((char)(((dn) < 4)? (char)((dn) + '#') : (char)((dn) - 4 + '*')))
|
||||
#endif
|
||||
|
||||
static char *putcs(char *pc, char *s){
|
||||
char c;
|
||||
while( (c = *s++)!=0 ) *pc++ = c;
|
||||
return pc;
|
||||
}
|
||||
|
||||
/* Encode a byte buffer into base85 text. If pSep!=0, it's a C string
|
||||
** to be appended to encoded groups to limit their length to B85_DARK_MAX
|
||||
** or to terminate the last group (to aid concatenation.)
|
||||
*/
|
||||
static char* toBase85( ubyte *pIn, int nbIn, char *pOut, char *pSep ){
|
||||
int nCol = 0;
|
||||
while( nbIn >= 4 ){
|
||||
int nco = 5;
|
||||
unsigned long qbv = (pIn[0]<<24)|(pIn[1]<<16)|(pIn[2]<<8)|pIn[3];
|
||||
while( nco > 0 ){
|
||||
unsigned nqv = (unsigned)(qbv/85UL);
|
||||
unsigned char dv = qbv - 85UL*nqv;
|
||||
qbv = nqv;
|
||||
pOut[--nco] = base85Numeral(dv);
|
||||
}
|
||||
nbIn -= 4;
|
||||
pIn += 4;
|
||||
pOut += 5;
|
||||
if( pSep && (nCol += 5)>=B85_DARK_MAX ){
|
||||
pOut = putcs(pOut, pSep);
|
||||
nCol = 0;
|
||||
}
|
||||
}
|
||||
if( nbIn > 0 ){
|
||||
int nco = nbIn + 1;
|
||||
unsigned long qv = *pIn++;
|
||||
int nbe = 1;
|
||||
while( nbe++ < nbIn ){
|
||||
qv = (qv<<8) | *pIn++;
|
||||
}
|
||||
nCol += nco;
|
||||
while( nco > 0 ){
|
||||
ubyte dv = (ubyte)(qv % 85);
|
||||
qv /= 85;
|
||||
pOut[--nco] = base85Numeral(dv);
|
||||
}
|
||||
pOut += (nbIn+1);
|
||||
}
|
||||
if( pSep && nCol>0 ) pOut = putcs(pOut, pSep);
|
||||
*pOut = 0;
|
||||
return pOut;
|
||||
}
|
||||
|
||||
/* Decode base85 text into a byte buffer. */
|
||||
static ubyte* fromBase85( char *pIn, int ncIn, ubyte *pOut ){
|
||||
if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn;
|
||||
while( ncIn>0 ){
|
||||
static signed char nboi[] = { 0, 0, 1, 2, 3, 4 };
|
||||
char *pUse = skipNonB85(pIn);
|
||||
unsigned long qv = 0L;
|
||||
int nti, nbo;
|
||||
ncIn -= (pUse - pIn);
|
||||
pIn = pUse;
|
||||
nti = (ncIn>5)? 5 : ncIn;
|
||||
nbo = nboi[nti];
|
||||
if( nbo==0 ) break;
|
||||
while( nti>0 ){
|
||||
char c = *pIn++;
|
||||
ubyte cdo = B85_DNOS(c);
|
||||
--ncIn;
|
||||
if( cdo==0 ) break;
|
||||
qv = 85 * qv + (c - cdo);
|
||||
--nti;
|
||||
}
|
||||
nbo -= nti; /* Adjust for early (non-digit) end of group. */
|
||||
switch( nbo ){
|
||||
case 4:
|
||||
*pOut++ = (qv >> 24)&0xff;
|
||||
case 3:
|
||||
*pOut++ = (qv >> 16)&0xff;
|
||||
case 2:
|
||||
*pOut++ = (qv >> 8)&0xff;
|
||||
case 1:
|
||||
*pOut++ = qv&0xff;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pOut;
|
||||
}
|
||||
|
||||
#ifndef OMIT_BASE85_CHECKER
|
||||
/* Say whether input char sequence is all (base85 and/or whitespace).*/
|
||||
static int allBase85( char *p, int len ){
|
||||
char c;
|
||||
while( len-- > 0 && (c = *p++) != 0 ){
|
||||
if( !IS_B85(c) && !isspace(c) ) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BASE85_STANDALONE
|
||||
|
||||
# ifndef OMIT_BASE85_CHECKER
|
||||
/* This function does the work for the SQLite is_base85(t) UDF. */
|
||||
static void is_base85(sqlite3_context *context, int na, sqlite3_value *av[]){
|
||||
assert(na==1);
|
||||
switch( sqlite3_value_type(av[0]) ){
|
||||
case SQLITE_TEXT:
|
||||
{
|
||||
int rv = allBase85( (char *)sqlite3_value_text(av[0]),
|
||||
sqlite3_value_bytes(av[0]) );
|
||||
sqlite3_result_int(context, rv);
|
||||
}
|
||||
break;
|
||||
case SQLITE_NULL:
|
||||
sqlite3_result_null(context);
|
||||
break;
|
||||
default:
|
||||
sqlite3_result_error(context, "is_base85 accepts only text or NULL", -1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
/* This function does the work for the SQLite base85(x) UDF. */
|
||||
static void base85(sqlite3_context *context, int na, sqlite3_value *av[]){
|
||||
int nb, nc, nv = sqlite3_value_bytes(av[0]);
|
||||
int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
|
||||
SQLITE_LIMIT_LENGTH, -1);
|
||||
char *cBuf;
|
||||
ubyte *bBuf;
|
||||
assert(na==1);
|
||||
switch( sqlite3_value_type(av[0]) ){
|
||||
case SQLITE_BLOB:
|
||||
nb = nv;
|
||||
/* ulongs tail newlines tailenc+nul*/
|
||||
nc = 5*(nv/4) + nv%4 + nv/64+1 + 2;
|
||||
if( nvMax < nc ){
|
||||
sqlite3_result_error(context, "blob expanded to base85 too big", -1);
|
||||
return;
|
||||
}
|
||||
cBuf = sqlite3_malloc(nc);
|
||||
if( !cBuf ) goto memFail;
|
||||
bBuf = (ubyte*)sqlite3_value_blob(av[0]);
|
||||
nc = (int)(toBase85(bBuf, nb, cBuf, "\n") - cBuf);
|
||||
sqlite3_result_text(context, cBuf, nc, sqlite3_free);
|
||||
break;
|
||||
case SQLITE_TEXT:
|
||||
nc = nv;
|
||||
nb = 4*(nv/5) + nv%5; /* may overestimate */
|
||||
if( nvMax < nb ){
|
||||
sqlite3_result_error(context, "blob from base85 may be too big", -1);
|
||||
return;
|
||||
}else if( nb<1 ){
|
||||
nb = 1;
|
||||
}
|
||||
bBuf = sqlite3_malloc(nb);
|
||||
if( !bBuf ) goto memFail;
|
||||
cBuf = (char *)sqlite3_value_text(av[0]);
|
||||
nb = (int)(fromBase85(cBuf, nc, bBuf) - bBuf);
|
||||
sqlite3_result_blob(context, bBuf, nb, sqlite3_free);
|
||||
break;
|
||||
default:
|
||||
sqlite3_result_error(context, "base85 accepts only blob or text.", -1);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
memFail:
|
||||
sqlite3_result_error(context, "base85 OOM", -1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Establish linkage to running SQLite library.
|
||||
*/
|
||||
#ifndef SQLITE_SHELL_EXTFUNCS
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_base_init
|
||||
#else
|
||||
static int sqlite3_base85_init
|
||||
#endif
|
||||
(sqlite3 *db, char **pzErr, const sqlite3_api_routines *pApi){
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErr;
|
||||
# ifndef OMIT_BASE85_CHECKER
|
||||
{
|
||||
int rc = sqlite3_create_function
|
||||
(db, "is_base85", 1,
|
||||
SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_UTF8,
|
||||
0, is_base85, 0, 0);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
# endif
|
||||
return sqlite3_create_function
|
||||
(db, "base85", 1,
|
||||
SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_DIRECTONLY|SQLITE_UTF8,
|
||||
0, base85, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Define some macros to allow this extension to be built into the shell
|
||||
** conveniently, in conjunction with use of SQLITE_SHELL_EXTFUNCS. This
|
||||
** allows shell.c, as distributed, to have this extension built in.
|
||||
*/
|
||||
# define BASE85_INIT(db) sqlite3_base85_init(db, 0, 0)
|
||||
# define BASE85_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */
|
||||
|
||||
#else /* standalone program */
|
||||
|
||||
int main(int na, char *av[]){
|
||||
int cin;
|
||||
int rc = 0;
|
||||
ubyte bBuf[4*(B85_DARK_MAX/5)];
|
||||
char cBuf[5*(sizeof(bBuf)/4)+2];
|
||||
size_t nio;
|
||||
# ifndef OMIT_BASE85_CHECKER
|
||||
int b85Clean = 1;
|
||||
# endif
|
||||
char rw;
|
||||
FILE *fb = 0, *foc = 0;
|
||||
char fmode[3] = "xb";
|
||||
if( na < 3 || av[1][0]!='-' || (rw = av[1][1])==0 || (rw!='r' && rw!='w') ){
|
||||
sayHelp();
|
||||
return 0;
|
||||
}
|
||||
fmode[0] = rw;
|
||||
if( av[2][0]=='-' && av[2][1]==0 ){
|
||||
switch( rw ){
|
||||
case 'r':
|
||||
fb = stdin;
|
||||
setmode(fileno(stdin), O_BINARY);
|
||||
break;
|
||||
case 'w':
|
||||
fb = stdout;
|
||||
setmode(fileno(stdout), O_BINARY);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
fb = fopen(av[2], fmode);
|
||||
foc = fb;
|
||||
}
|
||||
if( !fb ){
|
||||
fprintf(stderr, "Cannot open %s for %c\n", av[2], rw);
|
||||
rc = 1;
|
||||
}else{
|
||||
switch( rw ){
|
||||
case 'r':
|
||||
while( (nio = fread( bBuf, 1, sizeof(bBuf), fb))>0 ){
|
||||
toBase85( bBuf, (int)nio, cBuf, 0 );
|
||||
fprintf(stdout, "%s\n", cBuf);
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
while( 0 != fgets(cBuf, sizeof(cBuf), stdin) ){
|
||||
int nc = strlen(cBuf);
|
||||
size_t nbo = fromBase85( cBuf, nc, bBuf ) - bBuf;
|
||||
if( 1 != fwrite(bBuf, nbo, 1, fb) ) rc = 1;
|
||||
# ifndef OMIT_BASE85_CHECKER
|
||||
b85Clean &= allBase85( cBuf, nc );
|
||||
# endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sayHelp();
|
||||
rc = 1;
|
||||
}
|
||||
if( foc ) fclose(foc);
|
||||
}
|
||||
# ifndef OMIT_BASE85_CHECKER
|
||||
if( !b85Clean ){
|
||||
fprintf(stderr, "Base85 input had non-base85 dark or control content.\n");
|
||||
}
|
||||
# endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
** 2022-11-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 source allows multiple SQLite extensions to be either: combined
|
||||
** into a single runtime-loadable library; or built into the SQLite shell
|
||||
** using a preprocessing convention set by src/shell.c.in (and shell.c).
|
||||
**
|
||||
** Presently, it combines the base64.c and base85.c extensions. However,
|
||||
** it can be used as a template for other combinations.
|
||||
**
|
||||
** Example usages:
|
||||
**
|
||||
** - Build a runtime-loadable extension from SQLite checkout directory:
|
||||
** *Nix, OSX: gcc -O2 -shared -I. -fPIC -o basexx.so ext/misc/basexx.c
|
||||
** Win32: cl /Os -I. ext/misc/basexx.c -link -dll -out:basexx.dll
|
||||
**
|
||||
** - Incorporate as built-in in sqlite3 shell:
|
||||
** *Nix, OSX with gcc on a like platform:
|
||||
** export mop1=-DSQLITE_SHELL_EXTSRC=ext/misc/basexx.c
|
||||
** export mop2=-DSQLITE_SHELL_EXTFUNCS=BASEXX
|
||||
** make sqlite3 "OPTS=$mop1 $mop2"
|
||||
** Win32 with Microsoft toolset on Windows:
|
||||
** set mop1=-DSQLITE_SHELL_EXTSRC=ext/misc/basexx.c
|
||||
** set mop2=-DSQLITE_SHELL_EXTFUNCS=BASEXX
|
||||
** set mops="OPTS=%mop1% %mop2%"
|
||||
** nmake -f Makefile.msc sqlite3.exe %mops%
|
||||
*/
|
||||
|
||||
#ifndef SQLITE_SHELL_EXTFUNCS /* Guard for #include as built-in extension. */
|
||||
# include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1;
|
||||
#endif
|
||||
|
||||
static void init_api_ptr(const sqlite3_api_routines *pApi){
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
}
|
||||
|
||||
#undef SQLITE_EXTENSION_INIT1
|
||||
#define SQLITE_EXTENSION_INIT1 /* */
|
||||
#undef SQLITE_EXTENSION_INIT2
|
||||
#define SQLITE_EXTENSION_INIT2(v) (void)v
|
||||
|
||||
/* These next 2 undef's are only needed because the entry point names
|
||||
* collide when formulated per the rules stated for loadable extension
|
||||
* entry point names that will be deduced from the file basenames.
|
||||
*/
|
||||
#undef sqlite3_base_init
|
||||
#define sqlite3_base_init sqlite3_base64_init
|
||||
#include "base64.c"
|
||||
|
||||
#undef sqlite3_base_init
|
||||
#define sqlite3_base_init sqlite3_base85_init
|
||||
#include "base85.c"
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_basexx_init(sqlite3 *db, char **pzErr,
|
||||
const sqlite3_api_routines *pApi){
|
||||
init_api_ptr(pApi);
|
||||
int rc1 = BASE64_INIT(db);
|
||||
int rc2 = BASE85_INIT(db);
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( rc1==SQLITE_OK && rc2==SQLITE_OK ){
|
||||
BASE64_EXPOSE(db, pzErr);
|
||||
BASE64_EXPOSE(db, pzErr);
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
# define BASEXX_INIT(db) sqlite3_basexx_init(db, 0, 0)
|
||||
# define BASEXX_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */
|
||||
@@ -29,6 +29,22 @@
|
||||
This file represents an implementation detail of a larger piece of
|
||||
code, and not a public interface. Its details may change at any time
|
||||
and are not intended to be used by any client-level code.
|
||||
|
||||
2022-11-27: Chrome v108 changes some async methods to synchronous, as
|
||||
documented at:
|
||||
|
||||
https://developer.chrome.com/blog/sync-methods-for-accesshandles/
|
||||
|
||||
We cannot change to the sync forms at this point without breaking
|
||||
clients who use Chrome v104-ish or higher. truncate(), getSize(),
|
||||
flush(), and close() are now (as of v108) synchronous. Calling them
|
||||
with an "await", as we have to for the async forms, is still legal
|
||||
with the sync forms but is superfluous. Calling the async forms with
|
||||
theFunc().then(...) is not compatible with the change to
|
||||
synchronous, but we do do not use those APIs that way. i.e. we don't
|
||||
_need_ to change anything for this, but at some point (after Chrome
|
||||
versions (approximately) 104-107 are extinct) should change our
|
||||
usage of those methods to remove the "await".
|
||||
*/
|
||||
"use strict";
|
||||
const toss = function(...args){throw new Error(args.join(' '))};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
C Rework\sthe\scovering\sindex\schecking\sroutine,\swhereIsCoveringIndex(),\sso\sthat\nit\scan\sreturn\sa\s"maybe"\sresult\sfor\saggregate\squeries\swhere\swe\sare\snot\sexactly\nsure.\s\sThe\sindex\sis\sscored\sas\sif\sit\sis\scovering,\sbut\sthe\smain\stable\sis\nstill\sopened.
|
||||
D 2022-11-28T15:23:53.775
|
||||
C Merge\strunk\schanges\sinto\scovering-index-expr\sbranch.
|
||||
D 2022-11-28T16:11:10.036
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
F Makefile.in 9a1228fd6406cc607958ccf1386a9a8f74f8255a7e98bc9c0a2792b56bd3a309
|
||||
F Makefile.in c223963d7b0828f26cb62ea3e0f583d26839b7d3ef0d1cca87f35c4b222ff01b
|
||||
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
|
||||
F Makefile.msc e7a564ceec71f0d9666031d5638cf0d4f88b050b44e8df5d32125137cd259ac0
|
||||
F README.md 8b8df9ca852aeac4864eb1e400002633ee6db84065bd01b78c33817f97d31f5e
|
||||
@@ -289,6 +289,9 @@ F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f23
|
||||
F ext/misc/amatch.c e3ad5532799cee9a97647f483f67f43b38796b84b5a8c60594fe782a4338f358
|
||||
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
|
||||
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
|
||||
F ext/misc/base64.c fb140039d4e15710298e28cafe12d2bdff1b927fc57540cbcd07996f82bf9800 x
|
||||
F ext/misc/base85.c ace591246855806a70e63eb6705ce8736f4b782da2137bdbb5d39cc337346e0d
|
||||
F ext/misc/basexx.c b37ea21f00deea1029d2ddc670f5701d9370ae06f7d173c5bed79d0f26a67ec1
|
||||
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
|
||||
F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
|
||||
F ext/misc/carray.c b752f46411e4e47e34dce6f0c88bc8e51bb821ba9e49bfcd882506451c928f69
|
||||
@@ -506,7 +509,7 @@ F ext/wasm/api/sqlite3-api-opfs.js e98a8bd67dea8c20b0ec17332698b44658a6fbc4be18d
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 7fce4c6a138ec3d7c285b7c125cee809e6b668d2cb0d2328a1b790b7037765bd
|
||||
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
|
||||
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js d933d4a3c84e6dc614b57355fc9029645cfcdfbfde096ed42f4c979a6f60c18a
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 798383f6b46fd5dac122d6e35962d25b10401ddb825b5c66df1d21e6b1d8aacc
|
||||
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
|
||||
F ext/wasm/api/sqlite3-wasm.c 8b32787a3b6bb2990cbaba2304bd5b75a9652acbc8d29909b3279019b6cbaef5
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b
|
||||
@@ -642,7 +645,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c c1eb8f3ee25152327f2e7e87db8cea549e57c104b63638bff4fc584d479c33f0
|
||||
F src/shell.c.in 09cb15d7421c475f2d308f6a4312d8d690916ea5cb62ea1618f2f4ce5703af35
|
||||
F src/shell.c.in 9fda74d40b206a707aaa69fc5dc38e2c6a9137a3f4a1dcd7af581d59d92c063c
|
||||
F src/sqlite.h.in 100fc660c2f19961b8ed8437b9d53d687de2f8eb2b96437ec6da216adcb643ca
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h c4b9fa7a7e2bcdf850cfeb4b8a91d5ec47b7a00033bc996fd2ee96cbf2741f5f
|
||||
@@ -651,7 +654,7 @@ F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a3
|
||||
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c 4e64ba300a5a26e0f1170e09032429faeb65e45e8f3d1a7833e8edb69fc2979e
|
||||
F src/test1.c 40c9a40975512985762f87b83d0c63e4904833a9fe78cbcca664a37095301b1d
|
||||
F src/test1.c 09ad3f2bf5f0efe70eb16e460054954b36be8ed09dfcafa0642b37d25d379f6f
|
||||
F src/test2.c 827446e259a3b7ab949da1542953edda7b5117982576d3e6f1c24a0dd20a5cef
|
||||
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
|
||||
F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
|
||||
@@ -707,7 +710,7 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 1305797eab3542a0896b552c6e7669c972c1468e11e92b370533c1f37a37082b
|
||||
F src/treeview.c 29b1dc7e0f84ba090734febe27393d4719682af0cae1b902d5ebf0236ecebea4
|
||||
F src/trigger.c 4163ada044af89d51caba1cb713a73165347b2ec05fe84a283737c134d61fcd5
|
||||
F src/trigger.c 5e68b790f022b8dafbfb0eb244786512a95c9575fc198719d2557d73e5795858
|
||||
F src/update.c 5b0302c47cf31b533d5dff04c497ca1d8b9d89c39727e633fbe7b882fd5ac5aa
|
||||
F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
|
||||
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
|
||||
@@ -813,6 +816,7 @@ F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
|
||||
F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027
|
||||
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
|
||||
F test/badutf2.test f310fd3b24a491b6b77bccdf14923b85d6ebcce751068c180d93a6b8ff854399
|
||||
F test/basexx1.test d8a50f0744b93dca656625597bcd3499ff4b9a4ea2a82432b119b7d46e3e0c08
|
||||
F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
|
||||
F test/bestindex1.test 856a453dff8c68b4568601eed5a8b5e20b4763af9229f3947c215729ed878db0
|
||||
F test/bestindex2.test 394ff8fbf34703391247116d6a44e1c50ee7282236ee77909044573cefc37bc0
|
||||
@@ -1421,7 +1425,7 @@ F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2
|
||||
F test/releasetest_data.tcl 0db8aee0c348090fd06da47020ab4ed8ec692e0723427b2f3947d4dfb806f3b0
|
||||
F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/returning1.test c43b8370a351f77aec6d71f4a2cde59b849369ed1933261a2c2c69e23e34ff5e
|
||||
F test/returning1.test 1366e04566cfe1a082d17b1e0f195ec64473c79374b3a5d4ae00c43d885dea31
|
||||
F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4
|
||||
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
|
||||
F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
|
||||
@@ -1497,7 +1501,7 @@ F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test e4b4de56f454708e0747b52915135baa2cbfec4965406d6eaf02a4a5c22a9880
|
||||
F test/shell2.test c536c2aab4852608f8a606262330797abc4d964a4c2c782a7760f54ea1f17a6a
|
||||
F test/shell3.test 91febeac0412812bf6370abb8ed72700e32bf8f9878849414518f662dfd55e8a
|
||||
F test/shell4.test 7dc8a515705bc093d8ffe381670e8fa7a969661e8ed177c35c847e3c6dfc35e2
|
||||
F test/shell4.test 9abd0c12a7e20a4c49e84d5be208d2124fa6c09e728f56f1f4bee0f02853935f
|
||||
F test/shell5.test c8b6c54f26ec537f8558273d7ed293ca3725ef42e6b12b8f151718628bd1473b
|
||||
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
|
||||
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
|
||||
@@ -2060,8 +2064,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 17ebcf316b91042c823eea7bb6f1309325023cb5c70538cdb2ce932caee2ef05
|
||||
R 254ab4db9b1e239ec16eb2e1a31dc657
|
||||
P b8eec4214363192e6f3e12b3faa5810d8269a5fdaecab3ec09b02e5002cf798a b44ab10c49bc2895483a9d40813be3798710ee713cc4bf04e449dce55a68452a
|
||||
R 5944640ae5b4a3237e1d8a4c46c48db4
|
||||
U drh
|
||||
Z 489a805b1f3c740affbc27a0febf881c
|
||||
Z 9aa95e661b7edb77eed478b829e7796d
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
b8eec4214363192e6f3e12b3faa5810d8269a5fdaecab3ec09b02e5002cf798a
|
||||
89d775ada39aed4dc532374ace02156d07dc06e8ae54a194608af0c5a582d20f
|
||||
+34
-1
@@ -1072,6 +1072,9 @@ INCLUDE ../ext/recover/dbdata.c
|
||||
INCLUDE ../ext/recover/sqlite3recover.c
|
||||
# endif
|
||||
#endif
|
||||
#ifdef SQLITE_SHELL_EXTSRC
|
||||
# include SHELL_STRINGIFY(SQLITE_SHELL_EXTSRC)
|
||||
#endif
|
||||
|
||||
#if defined(SQLITE_ENABLE_SESSION)
|
||||
/*
|
||||
@@ -5117,6 +5120,7 @@ static void open_db(ShellState *p, int openFlags){
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
sqlite3_enable_load_extension(p->db, 1);
|
||||
#endif
|
||||
@@ -5139,6 +5143,34 @@ static void open_db(ShellState *p, int openFlags){
|
||||
sqlite3_sqlar_init(p->db, 0, 0);
|
||||
}
|
||||
#endif
|
||||
#ifdef SQLITE_SHELL_EXTFUNCS
|
||||
/* Create a preprocessing mechanism for extensions to make
|
||||
* their own provisions for being built into the shell.
|
||||
* This is a short-span macro. See further below for usage.
|
||||
*/
|
||||
#define SHELL_SUB_MACRO(base, variant) base ## _ ## variant
|
||||
#define SHELL_SUBMACRO(base, variant) SHELL_SUB_MACRO(base, variant)
|
||||
/* Let custom-included extensions get their ..._init() called.
|
||||
* The WHATEVER_INIT( db, pzErrorMsg, pApi ) macro should cause
|
||||
* the extension's sqlite3_*_init( db, pzErrorMsg, pApi )
|
||||
* inititialization routine to be called.
|
||||
*/
|
||||
{
|
||||
int irc = SHELL_SUBMACRO(SQLITE_SHELL_EXTFUNCS, INIT)(p->db);
|
||||
/* Let custom-included extensions expose their functionality.
|
||||
* The WHATEVER_EXPOSE( db, pzErrorMsg ) macro should cause
|
||||
* the SQL functions, virtual tables, collating sequences or
|
||||
* VFS's implemented by the extension to be registered.
|
||||
*/
|
||||
if( irc==SQLITE_OK
|
||||
|| irc==SQLITE_OK_LOAD_PERMANENTLY ){
|
||||
SHELL_SUBMACRO(SQLITE_SHELL_EXTFUNCS, EXPOSE)(p->db, 0);
|
||||
}
|
||||
#undef SHELL_SUB_MACRO
|
||||
#undef SHELL_SUBMACRO
|
||||
}
|
||||
#endif
|
||||
|
||||
sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
|
||||
shellAddSchemaName, 0, 0);
|
||||
sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
|
||||
@@ -5159,6 +5191,7 @@ static void open_db(ShellState *p, int openFlags){
|
||||
sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
|
||||
editFunc, 0, 0);
|
||||
#endif
|
||||
|
||||
if( p->openMode==SHELL_OPEN_ZIPFILE ){
|
||||
char *zSql = sqlite3_mprintf(
|
||||
"CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
|
||||
@@ -10658,7 +10691,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
}else{
|
||||
output_file_close(p->traceOut);
|
||||
p->traceOut = output_file_open(azArg[1], 0);
|
||||
p->traceOut = output_file_open(z, 0);
|
||||
}
|
||||
}
|
||||
if( p->traceOut==0 ){
|
||||
|
||||
@@ -7709,6 +7709,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
|
||||
){
|
||||
extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_appendvfs_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_basexx_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_carray_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
@@ -7740,6 +7741,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
|
||||
} aExtension[] = {
|
||||
{ "amatch", sqlite3_amatch_init },
|
||||
{ "appendvfs", sqlite3_appendvfs_init },
|
||||
{ "basexx", sqlite3_basexx_init },
|
||||
{ "carray", sqlite3_carray_init },
|
||||
{ "closure", sqlite3_closure_init },
|
||||
{ "csv", sqlite3_csv_init },
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
|
||||
if( pTrig->pTabSchema==pTab->pSchema
|
||||
&& pTrig->table
|
||||
&& 0==sqlite3StrICmp(pTrig->table, pTab->zName)
|
||||
&& pTrig->pTabSchema!=pTmpSchema
|
||||
&& (pTrig->pTabSchema!=pTmpSchema || pTrig->bReturning)
|
||||
){
|
||||
pTrig->pNext = pList;
|
||||
pList = pTrig;
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
# 2022 November 22
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix basexx
|
||||
|
||||
if {[catch {load_static_extension db basexx} error]} {
|
||||
puts "Skipping basexx tests, hit load error: $error"
|
||||
finish_test; return
|
||||
}
|
||||
|
||||
# Empty blobs encode to empty strings.
|
||||
do_execsql_test 100 {
|
||||
SELECT base64(x'')||base85(x'');
|
||||
} {{}}
|
||||
|
||||
# Empty strings decode to empty blobs.
|
||||
do_execsql_test 101 {
|
||||
SELECT hex(x'01'||base64('')||base85('')||x'02');
|
||||
} {0102}
|
||||
|
||||
# Basic base64 encoding
|
||||
do_execsql_test 102 {
|
||||
SELECT base64(x'000102030405');
|
||||
SELECT base64(x'0001020304');
|
||||
SELECT base64(x'00010203');
|
||||
} {{AAECAwQF
|
||||
} {AAECAwQ=
|
||||
} {AAECAw==
|
||||
}}
|
||||
|
||||
# Basic base64 decoding with pad chars
|
||||
do_execsql_test 103 {
|
||||
SELECT hex(base64('AAECAwQF'));
|
||||
SELECT hex(base64('AAECAwQ='));
|
||||
SELECT hex(base64('AAECAw=='));
|
||||
} {000102030405 0001020304 00010203}
|
||||
|
||||
# Basic base64 decoding without pad chars and with whitespace
|
||||
do_execsql_test 104 {
|
||||
SELECT hex(base64(' AAECAwQF '));
|
||||
SELECT hex(base64(' AAECAwQ'));
|
||||
SELECT hex(base64('AAECAw '));
|
||||
} {000102030405 0001020304 00010203}
|
||||
|
||||
# Basic base85 encoding
|
||||
do_execsql_test 105 {
|
||||
SELECT base85(x'000102030405');
|
||||
SELECT base85(x'0001020304');
|
||||
SELECT base85(x'00010203');
|
||||
} {{##/2,#2/
|
||||
} {##/2,#*
|
||||
} {##/2,
|
||||
}}
|
||||
|
||||
# Basic base85 decoding with and without whitespace
|
||||
do_execsql_test 106 {
|
||||
SELECT hex(base85('##/2,#2/'));
|
||||
SELECT hex(base85('##/2,#*'));
|
||||
SELECT hex(base85('##/2,'));
|
||||
SELECT hex(base85(' ##/2,#2/ '));
|
||||
SELECT hex(base85(' ##/2,#*'));
|
||||
SELECT hex(base85('##/2, '));
|
||||
} {000102030405 0001020304 00010203 000102030405 0001020304 00010203}
|
||||
|
||||
# Round-trip some random blobs.
|
||||
do_execsql_test 107 {
|
||||
CREATE TEMP TABLE rb( len int, b blob ) STRICT;
|
||||
INSERT INTO rb(len) VALUES (1),(2),(3),(4),(5),(150),(151),(152),(153),(1054);
|
||||
UPDATE rb SET b = randomblob(len);
|
||||
SELECT len, base64(base64(b))=b, base85(base85(b))=b
|
||||
FROM rb ORDER BY len;
|
||||
} {1 1 1 2 1 1 3 1 1 4 1 1 5 1 1 150 1 1 151 1 1 152 1 1 153 1 1 1054 1 1}
|
||||
|
||||
# Same round-trip but with space or junk prepended and/or appended or not.
|
||||
do_execsql_test 108 {
|
||||
CREATE TEMP TABLE junk(j text, rank int);
|
||||
INSERT INTO junk VALUES ('',0),(' ',1),('~',2);
|
||||
SELECT len, base64(j.j||base64(b)||j.j)=b, base85(j.j||base85(b)||j.j)=b
|
||||
FROM rb r, junk j WHERE j.rank=(r.len+r.len/25)%3 ORDER BY len;
|
||||
} {1 1 1 2 1 1 3 1 1 4 1 1 5 1 1 150 1 1 151 1 1 152 1 1 153 1 1 1054 1 1}
|
||||
|
||||
# Exercise the fail-on-too-large result feature.
|
||||
|
||||
set inLimit [sqlite3_limit db SQLITE_LIMIT_LENGTH -1]
|
||||
sqlite3_limit db SQLITE_LIMIT_LENGTH 1300
|
||||
|
||||
do_catchsql_test 109 {
|
||||
SELECT len, base64(b) FROM rb WHERE len>200;
|
||||
} {1 {blob expanded to base64 too big}}
|
||||
|
||||
do_catchsql_test 110 {
|
||||
SELECT len, base85(b) FROM rb WHERE len>200;
|
||||
} {1 {blob expanded to base85 too big}}
|
||||
|
||||
do_catchsql_test 111 {
|
||||
SELECT length(base85(b))=1335 FROM rb WHERE len=1054;
|
||||
} {1 {blob expanded to base85 too big}}
|
||||
|
||||
sqlite3_limit db SQLITE_LIMIT_LENGTH $inLimit
|
||||
|
||||
# Exercise is_base85(t)
|
||||
|
||||
do_execsql_test 112 {
|
||||
SELECT is_base85(' '||base85(x'123456')||char(10)),
|
||||
is_base85('#$%&*+,-./0123456789:;<=>?@'
|
||||
||'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
||'[\]^_`'
|
||||
||'abcdefghijklmnopqrstuvwxyz'),
|
||||
is_base85('!'), is_base85('"'), is_base85(''''), is_base85('('),
|
||||
is_base85(')'), is_base85(char(123)), is_base85('|'), is_base85(char(125)),
|
||||
is_base85('~'), is_base85(char(127));
|
||||
} {1 1 0 0 0 0 0 0 0 0 0 0}
|
||||
|
||||
do_execsql_test 113 {
|
||||
SELECT is_base85(NULL) IS NULL;
|
||||
} {1}
|
||||
|
||||
do_catchsql_test 114 {
|
||||
SELECT is_base85(1);
|
||||
} {1 {is_base85 accepts only text or NULL}}
|
||||
|
||||
do_catchsql_test 115 {
|
||||
SELECT is_base85(1.1);
|
||||
} {1 {is_base85 accepts only text or NULL}}
|
||||
|
||||
do_catchsql_test 116 {
|
||||
SELECT is_base85(x'00');
|
||||
} {1 {is_base85 accepts only text or NULL}}
|
||||
|
||||
# Round-trip many bigger random blobs.
|
||||
|
||||
do_execsql_test 117 {
|
||||
CREATE TABLE bs(b blob, num);
|
||||
INSERT INTO bs SELECT randomblob(4000 + n%3), n
|
||||
FROM (
|
||||
WITH RECURSIVE seq(n) AS (
|
||||
VALUES(1) UNION ALL SELECT n+1
|
||||
FROM seq WHERE n<100
|
||||
) SELECT n FROM seq);
|
||||
SELECT num FROM bs WHERE base64(base64(b))!=b;
|
||||
SELECT num FROM bs WHERE base85(base85(b))!=b;
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
@@ -376,4 +376,28 @@ do_execsql_test 16.1 {
|
||||
SELECT * FROM t2;
|
||||
} {1 2 3 a b c}
|
||||
|
||||
|
||||
foreach {tn temp} {
|
||||
1 ""
|
||||
2 TEMP
|
||||
} {
|
||||
reset_db
|
||||
do_execsql_test 17.$tn.0 "
|
||||
CREATE $temp TABLE foo (
|
||||
fooid INTEGER PRIMARY KEY,
|
||||
fooval INTEGER NOT NULL UNIQUE,
|
||||
refcnt INTEGER NOT NULL DEFAULT 1
|
||||
);
|
||||
"
|
||||
do_execsql_test 17.$tn.1 {
|
||||
INSERT INTO foo (fooval) VALUES (17), (4711), (17)
|
||||
ON CONFLICT DO
|
||||
UPDATE SET refcnt = refcnt+1
|
||||
RETURNING fooid;
|
||||
} {
|
||||
1 2 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -125,6 +125,12 @@ SELECT * FROM t1;}}
|
||||
do_test shell4-2.5 {
|
||||
catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace stdout\nSELECT * FROM t1;"
|
||||
} {0 {SELECT * FROM t1;}}
|
||||
do_test shell4-2.6 {
|
||||
catchcmd ":memory:" {
|
||||
CREATE TABLE t1(x);
|
||||
.trace --stmt stdout
|
||||
SELECT * FROM t1;}
|
||||
} {0 {SELECT * FROM t1;}}
|
||||
}
|
||||
|
||||
do_test shell4-3.1 {
|
||||
|
||||
Reference in New Issue
Block a user