# if !defined(__RTP__) && !defined(_WRS_KERNEL) && !defined(SQLITE_WASI) /* popen and pclose are not C89 functions and so are
** sometimes omitted from the <stdio.h> header */ extern FILE *popen(constchar*,constchar*); externint pclose(FILE*); # else # define SQLITE_OMIT_POPEN 1 # endif #endif
#ifdefined(_WIN32_WCE) /* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty() *thuswealwaysassumethatwehaveaconsole.Thatcanbe *overriddenwiththe-batchcommandlineoption.
*/ #define isatty(x) 1 #endif
/* ctype macros that work with signed characters */ #define IsSpace(X) isspace((unsignedchar)X) #define IsDigit(X) isdigit((unsignedchar)X) #define ToLower(X) (char)tolower((unsignedchar)X) #define IsAlnum(X) isalnum((unsignedchar)X) #define IsAlpha(X) isalpha((unsignedchar)X)
/* **Work-alikeforfputs()fromthestandardClibrary.
*/ int sqlite3_fputs(constchar *z, FILE *out){ if( !UseWtextForOutput(out) ){ /* Writing to a file or other destination, just write bytes without
** any translation. */ return fputs(z, out);
}else{ /* One must use UTF16 in order to get unicode support when writing **totheconsoleonWindows.
*/ int sz = (int)strlen(z); wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(wchar_t) ); if( b1==0 ) return0;
sz = MultiByteToWideChar(CP_UTF8, 0, z, sz, b1, sz);
b1[sz] = 0;
#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO
DWORD nWr = 0; if( IsConsole(out)
&& WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),b1,sz,&nWr,0)
){ /* If writing to the console, then the WriteConsoleW() is all we
** need to do. */
}else #endif
{ /* As long as SQLITE_USE_W32_FOR_CONSOLE_IO is not defined, or for **non-consoleI/Oevenifthatmacroisdefined,writeusingthe
** standard library. */
_setmode(_fileno(out), _O_U8TEXT); if( UseBinaryWText(out) ){
piecemealOutput(b1, sz, out);
}else{
fputws(b1, out);
}
}
sqlite3_free(b1); return0;
}
}
/* **Work-alikesforfprintf()andvfprintf()fromthestandardClibrary.
*/ int sqlite3_fprintf(FILE *out, constchar *zFormat, ...){ int rc; if( UseWtextForOutput(out) ){ /* When writing to the command-prompt in Windows, it is necessary **touse_O_WTEXTinputmodeandwriteUTF-16characters.
*/ char *z;
va_list ap;
va_start(ap, zFormat);
z = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
sqlite3_fputs(z, out);
rc = (int)strlen(z);
sqlite3_free(z);
}else{ /* Writing to a file or other destination, just write bytes without
** any translation. */
va_list ap;
va_start(ap, zFormat);
rc = vfprintf(out, zFormat, ap);
va_end(ap);
} return rc;
} int sqlite3_vfprintf(FILE *out, constchar *zFormat, va_list ap){ int rc; if( UseWtextForOutput(out) ){ /* When writing to the command-prompt in Windows, it is necessary **touse_O_WTEXTinputmodeandwriteUTF-16characters.
*/ char *z;
z = sqlite3_vmprintf(zFormat, ap);
sqlite3_fputs(z, out);
rc = (int)strlen(z);
sqlite3_free(z);
}else{ /* Writing to a file or other destination, just write bytes without
** any translation. */
rc = vfprintf(out, zFormat, ap);
} return rc;
}
/* **Specificationusedbyclientstodefinetheoutputformattheywant
*/ typedefstruct sqlite3_qrf_spec sqlite3_qrf_spec; struct sqlite3_qrf_spec { unsignedchar iVersion; /* Version number of this structure */ unsignedchar eStyle; /* Formatting style. "box", "csv", etc... */ unsignedchar eEsc; /* How to escape control characters in text */ unsignedchar eText; /* Quoting style for text */ unsignedchar eTitle; /* Quating style for the text of column names */ unsignedchar eBlob; /* Quoting style for BLOBs */ unsignedchar bTitles; /* True to show column names */ unsignedchar bWordWrap; /* Try to wrap on word boundaries */ unsignedchar bTextJsonb; /* Render JSONB blobs as JSON text */ unsignedchar eDfltAlign; /* Default alignment, no covered by aAlignment */ unsignedchar eTitleAlign; /* Alignment for column headers */ unsignedchar bSplitColumn; /* Wrap single-column output into many columns */ unsignedchar bBorder; /* Show outer border in Box and Table styles */ shortint nWrap; /* Wrap columns wider than this */ shortint nScreenWidth; /* Maximum overall table width */ shortint nLineLimit; /* Maximum number of lines for any row */ shortint nTitleLimit; /* Maximum number of characters in a title */ unsignedint nMultiInsert; /* Add rows to one INSERT until size exceeds */ int nCharLimit; /* Maximum number of characters in a cell */ int nWidth; /* Number of entries in aWidth[] */ int nAlign; /* Number of entries in aAlignment[] */ shortint *aWidth; /* Column widths */ unsignedchar *aAlign; /* Column alignments */ char *zColumnSep; /* Alternative column separator */ char *zRowSep; /* Alternative row separator */ char *zTableName; /* Output table name */ char *zNull; /* Rendering of NULL */ char *(*xRender)(void*,sqlite3_value*); /* Render a value */ int (*xWrite)(void*,constchar*,sqlite3_int64); /* Write output */ void *pRenderArg; /* First argument to the xRender callback */ void *pWriteArg; /* First argument to the xWrite callback */ char **pzOutput; /* Storage location for output string */ /* Additional fields may be added in the future */
};
/* **Interfaces
*/ int sqlite3_format_query_result(
sqlite3_stmt *pStmt, /* SQL statement to run */ const sqlite3_qrf_spec *pSpec, /* Result format specification */ char **pzErr /* OUT: Write error message here */
);
/* **Allowedvaluesfor"boolean"fields,suchas"bColumnNames","bWordWrap", **and"bTextJsonb".Thereisanextra"auto"variantssotheseareactually **tri-statesettings,notbooleans.
*/ #define QRF_SW_Auto 0/* Let QRF choose the best value */ #define QRF_SW_Off 1/* This setting is forced off */ #define QRF_SW_On 2/* This setting is forced on */ #define QRF_Auto 0/* Alternate spelling for QRF_*_Auto */ #define QRF_No 1/* Alternate spelling for QRF_SW_Off */ #define QRF_Yes 2/* Alternate spelling for QRF_SW_On */
/* **Possiblealignmentvaluesalignmentsettings ** **HorizontalVertial
** ---------- -------- */ #define QRF_ALIGN_Auto 0/* auto auto */ #define QRF_ALIGN_Left 1/* left auto */ #define QRF_ALIGN_Center 2/* center auto */ #define QRF_ALIGN_Right 3/* right auto */ #define QRF_ALIGN_Top 4/* auto top */ #define QRF_ALIGN_NW 5/* left top */ #define QRF_ALIGN_N 6/* center top */ #define QRF_ALIGN_NE 7/* right top */ #define QRF_ALIGN_Middle 8/* auto middle */ #define QRF_ALIGN_W 9/* left middle */ #define QRF_ALIGN_C 10/* center middle */ #define QRF_ALIGN_E 11/* right middle */ #define QRF_ALIGN_Bottom 12/* auto bottom */ #define QRF_ALIGN_SW 13/* left bottom */ #define QRF_ALIGN_S 14/* center bottom */ #define QRF_ALIGN_SE 15/* right bottom */ #define QRF_ALIGN_HMASK 3/* Horizontal alignment mask */ #define QRF_ALIGN_VMASK 12/* Vertical alignment mask */
/* A single line in the EQP output */ typedefstruct qrfEQPGraphRow qrfEQPGraphRow; struct qrfEQPGraphRow { int iEqpId; /* ID for this row */ int iParentId; /* ID of the parent row */
qrfEQPGraphRow *pNext; /* Next row in sequence */ char zText[1]; /* Text to display for this row */
};
/* All EQP output is collected into an instance of the following */ typedefstruct qrfEQPGraph qrfEQPGraph; struct qrfEQPGraph {
qrfEQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
qrfEQPGraphRow *pLast; /* Last element of the pRow list */ int nWidth; /* Width of the graph */ char zPrefix[400]; /* Graph prefix */
};
/* **Privatestateinformation.Subjecttochangefromonereleasetothe **next.
*/ typedefstruct Qrf Qrf; struct Qrf {
sqlite3_stmt *pStmt; /* The statement whose output is to be rendered */
sqlite3 *db; /* The corresponding database connection */
sqlite3_stmt *pJTrans; /* JSONB to JSON translator statement */ char **pzErr; /* Write error message here, if not NULL */
sqlite3_str *pOut; /* Accumulated output */ int iErr; /* Error code */ int nCol; /* Number of output columns */ int expMode; /* Original sqlite3_stmt_isexplain() plus 1 */ int mxWidth; /* Screen width */ int mxHeight; /* nLineLimit */ union { struct { /* Content for QRF_STYLE_Line */ int mxColWth; /* Maximum display width of any column */ char **azCol; /* Names of output columns (MODE_Line) */
} sLine;
qrfEQPGraph *pGraph; /* EQP graph (Eqp, Stats, and StatsEst) */ struct { /* Content for QRF_STYLE_Explain */ int nIndent; /* Slots allocated for aiIndent */ int iIndent; /* Current slot */ int *aiIndent; /* Indentation for each opcode */
} sExpln; unsignedint nIns; /* Bytes used for current INSERT stmt */
} u;
sqlite3_int64 nRow; /* Number of rows handled so far */ int *actualWidth; /* Actual width of each column */
sqlite3_qrf_spec spec; /* Copy of the original spec */
};
/* **Returnthelengthofastringindisplaycharacters. ** **Mostcharactersoftheinputstringcountas1,including **multi-byteUTF8characters.However,zero-widthunicode **charactersandVT100escapesequencescountaszero,and **double-widthcharacterscountastwo. ** **Thedefinitionof"zero-width"and"double-width"characters **isnotprecise.Itdependsontheoutputdevice,tosomeextent, **anditvariesaccordingtotheUnicodeversion.Thisroutine **makesthebestguessthatitcan.
*/
size_t sqlite3_qrf_wcswidth(constchar *zIn){ constunsignedchar *z = (constunsignedchar*)zIn;
size_t n = 0; while( *z ){ if( z[0]<' ' ){ int k; if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
z += k;
}else{
z++;
}
}elseif( (0x80&z[0])==0 ){
n++;
z++;
}else{ int u = 0; int len = sqlite3_qrf_decode_utf8(z, &u);
z += len;
n += sqlite3_qrf_wcwidth(u);
}
} return n;
}
/* **Returnthedisplaywidthofthelongestlineoftext **inthe(possibly)multi-lineinputstringzIn[0..nByte]. **zIn[]isnotnecessarilyzero-terminated.Take **intoaccounttabcharacters,zero-anddouble-width **characters,CRandNL,andVT100escapecodes. ** **Writethenumberofnewlinesinto*pnNL.So,*pnNLwill **return0ifeverythingfitsononeline,orpositiveit **itwillneedtobesplit.
*/ staticint qrfDisplayWidth(constchar *zIn, sqlite3_int64 nByte, int *pnNL){ constunsignedchar *z; constunsignedchar *zEnd; int mx = 0; int n = 0; int nNL = 0; if( zIn==0 ) zIn = "";
z = (constunsignedchar*)zIn;
zEnd = &z[nByte]; while( z<zEnd ){ if( z[0]<' ' ){ int k; if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
z += k;
}else{ if( z[0]=='\t' ){
n = (n+8)&~7;
}elseif( z[0]=='\n' || z[0]=='\r' ){
nNL++; if( n>mx ) mx = n;
n = 0;
}
z++;
}
}elseif( (0x80&z[0])==0 ){
n++;
z++;
}else{ int u = 0; int len = sqlite3_qrf_decode_utf8(z, &u);
z += len;
n += sqlite3_qrf_wcwidth(u);
}
} if( mx>n ) n = mx; if( pnNL ) *pnNL = nNL; return n;
}
/* **Escapetheinputstringifitisneededandinaccordancewith **eEsc,whichiseitherQRF_ESC_AsciiorQRF_ESC_Symbol. ** **Escapingisneededifthestringcontainsanycontrolcharacters **otherthan\t,\n,and\r\n ** **Ifnoescapingisneeded(thecommoncase)thenset*ppOuttoNULL **andreturn0.Ifescapingisneeded,writetheescapedstringinto **memoryobtainedfromsqlite3_malloc64()andmake*ppOutpointtothat **memoryandreturn0.Ifanerroroccurs,returnnon-zero. ** **Thecallerisresponsibleforfreeing*ppFreeifitisnon-NULLinorder **toreclaimmemory.
*/ staticvoid qrfEscape( int eEsc, /* QRF_ESC_Ascii or QRF_ESC_Symbol */
sqlite3_str *pStr, /* String to be escaped */ int iStart /* Begin escapding on this byte of pStr */
){
sqlite3_int64 i, j; /* Loop counters */
sqlite3_int64 sz; /* Size of the string prior to escaping */
sqlite3_int64 nCtrl = 0;/* Number of control characters to escape */ unsignedchar *zIn; /* Text to be escaped */ unsignedchar c; /* A single character of the text */ unsignedchar *zOut; /* Where to write the results */
/* Find the text to be escaped */
zIn = (unsignedchar*)sqlite3_str_value(pStr); if( zIn==0 ) return;
zIn += iStart;
/* Count the control characters */ for(i=0; (c = zIn[i])!=0; i++){ if( c<=0x1f
&& c!='\t'
&& c!='\n'
&& (c!='\r' || zIn[i+1]!='\n')
){
nCtrl++;
}
} if( nCtrl==0 ) return; /* Early out if no control characters */
/* Make space to hold the escapes. Copy the original text to the end
** of the available space. */
sz = sqlite3_str_length(pStr) - iStart; if( eEsc==QRF_ESC_Symbol ) nCtrl *= 2;
sqlite3_str_appendchar(pStr, nCtrl, ' ');
zOut = (unsignedchar*)sqlite3_str_value(pStr); if( zOut==0 ) return;
zOut += iStart;
zIn = zOut + nCtrl;
memmove(zIn,zOut,sz);
/* Trim spaces of the end if pOut
*/ staticvoid qrfRTrim(sqlite3_str *pOut){ #if SQLITE_VERSION_NUMBER>=3052000 int nByte = sqlite3_str_length(pOut); constchar *zOut = sqlite3_str_value(pOut); while( nByte>0 && zOut[nByte-1]==' ' ){ nByte--; }
sqlite3_str_truncate(pOut, nByte); #endif
}
/* **StorestringzUtftopOutaswcharacters.Ifwisnegative, **thenright-justifythetext.Wisthewidthindisplaycharacters,not **inbytes.Double-widthunicodecharacterscountastwocharacters. **VT100escapesequencescountaszero.Andsoforth.
*/ staticvoid qrfWidthPrint(Qrf *p, sqlite3_str *pOut, int w, constchar *zUtf){ constunsignedchar *a = (constunsignedchar*)zUtf; staticconstint mxW = 10000000; unsignedchar c; int i = 0; int n = 0; int k; int aw;
(void)p; if( w<-mxW ){
w = -mxW;
}elseif( w>mxW ){
w= mxW;
}
aw = w<0 ? -w : w; if( a==0 ) a = (constunsignedchar*)""; while( (c = a[i])!=0 ){ if( (c&0xc0)==0xc0 ){ int u; int len = sqlite3_qrf_decode_utf8(a+i, &u); int x = sqlite3_qrf_wcwidth(u); if( x+n>aw ){ break;
}
i += len;
n += x;
}elseif( c==0x1b && (k = qrfIsVt100(&a[i]))>0 ){
i += k;
}elseif( n>=aw ){ break;
}else{
n++;
i++;
}
} if( n>=aw ){
sqlite3_str_append(pOut, zUtf, i);
}elseif( w<0 ){ if( aw>n ) sqlite3_str_appendchar(pOut, aw-n, ' ');
sqlite3_str_append(pOut, zUtf, i);
}else{
sqlite3_str_append(pOut, zUtf, i); if( aw>n ) sqlite3_str_appendchar(pOut, aw-n, ' ');
}
}
/* **(*pz)[]isalineoftextthatistobedisplayedtheboxortableor **similartabularformats.z[]containnewlinesormightbetoowide **tofitinthecolumnssowillneedtobesplitintomultipleline. ** **Thisroutinedetermines: ** ***Howmanybytesofz[]shouldbeshownonthecurrentline. ***Howmanycharacterpositionsthosebyteswillcover. ***Thebyteoffsettothestartofthenextline.
*/ staticvoid qrfWrapLine( constchar *zIn, /* Input text to be displayed */ int w, /* Column width in characters (not bytes) */ int bWrap, /* True if we should do word-wrapping */ int *pnThis, /* OUT: How many bytes of z[] for the current line */ int *pnWide, /* OUT: How wide is the text of this line */ int *piNext /* OUT: Offset into z[] to start of the next line */
){ int i; /* Input bytes consumed */ int k; /* Bytes in a VT100 code */ int n; /* Output column number */ constunsignedchar *z = (constunsignedchar*)zIn; unsignedchar c = 0;
if( z[0]==0 ){
*pnThis = 0;
*pnWide = 0;
*piNext = 0; return;
}
n = 0; for(i=0; n<=w; i++){
c = z[i]; if( c>=0xc0 ){ int u; int len = sqlite3_qrf_decode_utf8(&z[i], &u); int wcw = sqlite3_qrf_wcwidth(u); if( wcw+n>w ) break;
i += len-1;
n += wcw; continue;
} if( c>=' ' ){ if( n==w ) break;
n++; continue;
} if( c==0 || c=='\n' ) break; if( c=='\r' && z[i+1]=='\n' ){ c = z[++i]; break; } if( c=='\t' ){ int wcw = 8 - (n&7); if( n+wcw>w ) break;
n += wcw; continue;
} if( c==0x1b && (k = qrfIsVt100(&z[i]))>0 ){
i += k-1;
}elseif( n==w ){ break;
}else{
n++;
}
} if( c==0 ){
*pnThis = i;
*pnWide = n;
*piNext = i; return;
} if( c=='\n' ){
*pnThis = i;
*pnWide = n;
*piNext = i+1; return;
}
/* If we get this far, that means the current line will end at some **pointthatisneithera"\n"ora0x00.Figureoutwherethat **splitshouldoccur
*/ if( bWrap && z[i]!=0 && !qrfSpace(z[i]) && qrfAlnum(c)==qrfAlnum(z[i]) ){ /* Perhaps try to back up to a better place to break the line */ for(k=i-1; k>=i/2; k--){ if( qrfSpace(z[k]) ) break;
} if( k<i/2 ){ for(k=i; k>=i/2; k--){ if( qrfAlnum(z[k-1])!=qrfAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
}
} if( k>=i/2 ){
i = k;
n = qrfDisplayWidth((const char*)z, k, 0);
}
}
*pnThis = i;
*pnWide = n;
while( zIn[i]==' ' || zIn[i]=='\t' || zIn[i]=='\r' ){ i++; }
*piNext = i;
}
/*
** Append nVal bytes of text from zVal onto the end of pOut.
** Convert tab characters in zVal to the appropriate number of
** spaces.
*/
static void qrfAppendWithTabs(
sqlite3_str *pOut, /* Append text here */
const char *zVal, /* Text to append */
int nVal /* Use only the first nVal bytes of zVal[] */
){
int i = 0;
unsigned int col = 0;
unsigned char *z = (unsigned char *)zVal;
while( i<nVal ){
unsigned char c = z[i];
if( c<' ' ){
int k;
sqlite3_str_append(pOut, (const char*)z, i);
nVal -= i;
z += i;
i = 0;
if( c=='\033' && (k = qrfIsVt100(z))>0 ){
sqlite3_str_append(pOut, (const char*)z, k);
z += k;
nVal -= k;
}else if( c=='\t' ){
k = 8 - (col&7);
sqlite3_str_appendchar(pOut, k, ' ');
col += k;
z++;
nVal--;
}else if( c=='\r' && nVal==1 ){
z++;
nVal--;
}else{
char zCtrlPik[4];
col++;
zCtrlPik[0] = 0xe2;
zCtrlPik[1] = 0x90;
zCtrlPik[2] = 0x80+c;
sqlite3_str_append(pOut, zCtrlPik, 3);
z++;
nVal--;
}
}else if( (0x80&c)==0 ){
i++;
col++;
}else{
int u = 0;
int len = sqlite3_qrf_decode_utf8(&z[i], &u);
i += len;
col += sqlite3_qrf_wcwidth(u);
}
}
sqlite3_str_append(pOut, (const char*)z, i);
}
/*
** GCC does not define the offsetof() macro so we'll have to do it
** ourselves.
*/
#ifndef offsetof
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
#endif
/*
** Data for columnar layout, collected into a single object so
** that it can be more easily passed into subroutines.
*/
typedef struct qrfColData qrfColData;
struct qrfColData {
Qrf *p; /* The QRF instance */
int nCol; /* Number of columns in the table */
unsigned char bMultiRow; /* One or more cells will span multiple lines */
unsigned char nMargin; /* Width of column margins */
sqlite3_int64 nRow; /* Number of rows */
sqlite3_int64 nAlloc; /* Number of cells allocated */
sqlite3_int64 n; /* Number of cells. nCol*nRow */
char **az; /* Content of all cells */
int *aiWth; /* Width of each cell */
unsigned char *abNum; /* True for each numeric cell */
struct qrfPerCol { /* Per-column data */
char *z; /* Cache of text for current row */
int w; /* Computed width of this column */
int mxW; /* Maximum natural (unwrapped) width */
unsigned char e; /* Alignment */
unsigned char fx; /* Width is fixed */
unsigned char bNum; /* True if is numeric */
} *a; /* One per column */
};
/*
** Output horizontally justified text into pOut. The text is the
** first nVal bytes of zVal. Include nWS bytes of whitespace, either
** split between both sides, or on the left, or on the right, depending
** on eAlign.
*/
static void qrfPrintAligned(
sqlite3_str *pOut, /* Append text here */
struct qrfPerCol *pCol, /* Information about the text to print */
int nVal, /* Use only the first nVal bytes of zVal[] */
int nWS /* Whitespace for horizonal alignment */
){
unsigned char eAlign = pCol->e & QRF_ALIGN_HMASK;
if( eAlign==QRF_Auto && pCol->bNum ) eAlign = QRF_ALIGN_Right;
if( eAlign==QRF_ALIGN_Center ){
/* Center the text */
sqlite3_str_appendchar(pOut, nWS/2, ' ');
qrfAppendWithTabs(pOut, pCol->z, nVal);
sqlite3_str_appendchar(pOut, nWS - nWS/2, ' ');
}else if( eAlign==QRF_ALIGN_Right ){
/* Right justify the text */
sqlite3_str_appendchar(pOut, nWS, ' ');
qrfAppendWithTabs(pOut, pCol->z, nVal);
}else{
/* Left justify the text */
qrfAppendWithTabs(pOut, pCol->z, nVal);
sqlite3_str_appendchar(pOut, nWS, ' ');
}
}
/*
** Free all the memory allocates in the qrfColData object
*/
static void qrfColDataFree(qrfColData *p){
sqlite3_int64 i;
for(i=0; i<p->n; i++) sqlite3_free(p->az[i]);
sqlite3_free(p->az);
sqlite3_free(p->aiWth);
sqlite3_free(p->abNum);
sqlite3_free(p->a);
memset(p, 0, sizeof(*p));
}
/*
** Allocate space for more cells in the qrfColData object.
** Return non-zero if a memory allocation fails.
*/
static int qrfColDataEnlarge(qrfColData *p){
char **azData;
int *aiWth;
unsigned char *abNum;
p->nAlloc = 2*p->nAlloc + 10*p->nCol;
azData = sqlite3_realloc64(p->az, p->nAlloc*sizeof(char*));
if( azData==0 ){
qrfOom(p->p);
qrfColDataFree(p);
return 1;
}
p->az = azData;
aiWth = sqlite3_realloc64(p->aiWth, p->nAlloc*sizeof(int));
if( aiWth==0 ){
qrfOom(p->p);
qrfColDataFree(p);
return 1;
}
p->aiWth = aiWth;
abNum = sqlite3_realloc64(p->abNum, p->nAlloc);
if( abNum==0 ){
qrfOom(p->p);
qrfColDataFree(p);
return 1;
}
p->abNum = abNum;
return 0;
}
/*
** Load into pData the default alignment for the body of a table.
*/
static void qrfLoadAlignment(qrfColData *pData, Qrf *p){
sqlite3_int64 i;
for(i=0; i<pData->nCol; i++){
pData->a[i].e = p->spec.eDfltAlign;
if( i<p->spec.nAlign ){
unsigned char ax = p->spec.aAlign[i];
if( (ax & QRF_ALIGN_HMASK)!=0 ){
pData->a[i].e = (ax & QRF_ALIGN_HMASK) |
(pData->a[i].e & QRF_ALIGN_VMASK);
}
}else if( i<p->spec.nWidth ){
if( p->spec.aWidth[i]<0 ){
pData->a[i].e = QRF_ALIGN_Right |
(pData->a[i].e & QRF_ALIGN_VMASK);
}
}
}
}
/*
** If the single column in pData->a[] with pData->n entries can be
** laid out as nCol columns with a 2-space gap between each such
** that all columns fit within nSW, then return a pointer to an array
** of integers which is the width of each column from left to right.
**
** If the layout is not possible, return a NULL pointer.
**
** Space to hold the returned array is from sqlite_malloc64().
*/
static int *qrfValidLayout(
qrfColData *pData, /* Collected query results */
Qrf *p, /* On which to report an OOM */
int nCol, /* Attempt this many columns */
int nSW /* Screen width */
){
int i; /* Loop counter */
int nr; /* Number of rows */
int w = 0; /* Width of the current column */
int t; /* Total width of all columns */
int *aw; /* Array of individual column widths */
/*
** Adjust the layout for the screen width restriction
*/
static void qrfRestrictScreenWidth(qrfColData *pData, Qrf *p){
int sepW; /* Width of all box separators and margins */
int sumW; /* Total width of data area over all columns */
int targetW; /* Desired total data area */
int i; /* Loop counters */
int nCol; /* Number of columns */
/* First thing to do is reduce the separation between columns */
pData->nMargin = 0;
if( p->spec.eStyle==QRF_STYLE_Column ){
sepW = pData->nCol - 1;
}else{
sepW = pData->nCol + 1;
if( p->spec.bBorder==QRF_No ) sepW -= 2;
}
targetW = p->spec.nScreenWidth - sepW;
#define MIN_SQUOZE 8
#define MIN_EX_SQUOZE 16
/* Reduce the width of the widest eligible column. A column is
** eligible for narrowing if:
**
** * It is not a fixed-width column (a[0].fx is false)
** * The current width is more than MIN_SQUOZE
** * Either:
** + The current width is more then MIN_EX_SQUOZE, or
** + The current width is more than half the max width (a[].mxW)
**
** Keep making reductions until either no more reductions are
** possible or until the size target is reached.
*/
while( sumW > targetW ){
int gain, w;
int ix = -1;
int mx = 0;
for(i=0; i<nCol; i++){
if( pData->a[i].fx==0
&& (w = pData->a[i].w)>mx
&& w>MIN_SQUOZE
&& (w>MIN_EX_SQUOZE || w*2>pData->a[i].mxW)
){
ix = i;
mx = w;
}
}
if( ix<0 ) break;
if( mx>=MIN_SQUOZE*2 ){
gain = mx/2;
}else{
gain = mx - MIN_SQUOZE;
}
if( sumW - gain < targetW ){
gain = sumW - targetW;
}
sumW -= gain;
pData->a[ix].w -= gain;
pData->bMultiRow = 1;
}
}
/*
** Columnar modes require that the entire query be evaluated first, with
** results written into memory, so that we can compute appropriate column
** widths.
*/
static void qrfColumnar(Qrf *p){
sqlite3_int64 i, j; /* Loop counters */
const char *colSep = 0; /* Column separator text */
const char *rowSep = 0; /* Row terminator text */
const char *rowStart = 0; /* Row start text */
int szColSep, szRowSep, szRowStart; /* Size in bytes of previous 3 */
int rc; /* Result code */
int nColumn = p->nCol; /* Number of columns */
int bWW; /* True to do word-wrap */
sqlite3_str *pStr; /* Temporary rendering */
qrfColData data; /* Columnar layout data */
int bRTrim; /* Trim trailing space */
/* Load the column header names and all cell content into data */
if( p->spec.bTitles==QRF_Yes ){
unsigned char saved_eText = p->spec.eText;
p->spec.eText = p->spec.eTitle;
memset(data.abNum, 0, nColumn);
for(i=0; i<nColumn; i++){
const char *z = (const char*)sqlite3_column_name(p->pStmt,i);
int nNL = 0;
int n, w;
pStr = sqlite3_str_new(p->db);
qrfEncodeText(p, pStr, z ? z : "");
n = sqlite3_str_length(pStr);
qrfStrErr(p, pStr);
z = data.az[data.n] = sqlite3_str_finish(pStr);
if( p->spec.nTitleLimit ){
nNL = 0;
data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n],
p->spec.nTitleLimit );
}else{
data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
}
data.n++;
if( w>data.a[i].mxW ) data.a[i].mxW = w;
if( nNL ) data.bMultiRow = 1;
}
p->spec.eText = saved_eText;
p->nRow++;
}
do{
if( data.n+nColumn > data.nAlloc ){
if( qrfColDataEnlarge(&data) ) return;
}
for(i=0; i<nColumn; i++){
char *z;
int nNL = 0;
int n, w;
int eType = sqlite3_column_type(p->pStmt,i);
pStr = sqlite3_str_new(p->db);
qrfRenderValue(p, pStr, i);
n = sqlite3_str_length(pStr);
qrfStrErr(p, pStr);
z = data.az[data.n] = sqlite3_str_finish(pStr);
data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT;
data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
data.n++;
if( w>data.a[i].mxW ) data.a[i].mxW = w;
if( nNL ) data.bMultiRow = 1;
}
p->nRow++;
}while( sqlite3_step(p->pStmt)==SQLITE_ROW && p->iErr==SQLITE_OK );
if( p->iErr ){
qrfColDataFree(&data);
return;
}
/* Compute the width and alignment of every column */
if( p->spec.bTitles==QRF_No ){
qrfLoadAlignment(&data, p);
}else{
unsigned char e;
if( p->spec.eTitleAlign==QRF_Auto ){
e = QRF_ALIGN_Center;
}else{
e = p->spec.eTitleAlign;
}
for(i=0; i<nColumn; i++) data.a[i].e = e;
}
for(i=0; i<nColumn; i++){
int w = 0;
if( i<p->spec.nWidth ){
w = p->spec.aWidth[i];
if( w==(-32768) ){
w = 0;
if( p->spec.nAlign>i && (p->spec.aAlign[i] & QRF_ALIGN_HMASK)==0 ){
data.a[i].e |= QRF_ALIGN_Right;
}
}else if( w<0 ){
w = -w;
if( p->spec.nAlign>i && (p->spec.aAlign[i] & QRF_ALIGN_HMASK)==0 ){
data.a[i].e |= QRF_ALIGN_Right;
}
}
if( w ) data.a[i].fx = 1;
}
if( w==0 ){
w = data.a[i].mxW;
if( p->spec.nWrap>0 && w>p->spec.nWrap ){
w = p->spec.nWrap;
data.bMultiRow = 1;
}
}else if( (data.bMultiRow==0 || w==1) && data.a[i].mxW>w ){
data.bMultiRow = 1;
if( w==1 ){
/* If aiWth[j] is 2 or more, then there might be a double-wide
** character somewhere. So make the column width at least 2. */
w = 2;
}
}
data.a[i].w = w;
}
if( nColumn==1
&& data.n>1
&& p->spec.bSplitColumn==QRF_Yes
&& p->spec.eStyle==QRF_STYLE_Column
&& p->spec.bTitles==QRF_No
&& p->spec.nScreenWidth>data.a[0].w+3
){
/* Attempt to convert single-column tables into multi-column by
** verticle wrapping, if the screen is wide enough and if the
** bSplitColumn flag is set. */
qrfSplitColumn(&data, p);
nColumn = data.nCol;
}else{
/* Adjust the column widths due to screen width restrictions */
qrfRestrictScreenWidth(&data, p);
}
/* Draw a single row of the table. This might be the title line
** (if there is a title line) or a row in the body of the table.
** The column number will be j. The row number is i/nColumn.
*/
for(j=0; j<nColumn; j++){
data.a[j].z = data.az[i+j];
if( data.a[j].z==0 ) data.a[j].z = "";
data.a[j].bNum = data.abNum[i+j];
}
do{
sqlite3_str_append(p->pOut, rowStart, szRowStart);
bMore = 0;
for(j=0; j<nColumn; j++){
int nThis = 0;
int nWide = 0;
int iNext = 0;
int nWS;
qrfWrapLine(data.a[j].z, data.a[j].w, bWW, &nThis, &nWide, &iNext);
nWS = data.a[j].w - nWide;
qrfPrintAligned(p->pOut, &data.a[j], nThis, nWS);
data.a[j].z += iNext;
if( data.a[j].z[0]!=0 ){
bMore = 1;
}
if( j<nColumn-1 ){
sqlite3_str_append(p->pOut, colSep, szColSep);
}else{
if( bRTrim ) qrfRTrim(p->pOut);
sqlite3_str_append(p->pOut, rowSep, szRowSep);
}
}
}while( bMore && ++nRow < p->mxHeight );
if( bMore ){
/* This row was terminated by nLineLimit. Show ellipsis. */
sqlite3_str_append(p->pOut, rowStart, szRowStart);
for(j=0; j<nColumn; j++){
if( data.a[j].z[0]==0 ){
sqlite3_str_appendchar(p->pOut, data.a[j].w, ' ');
}else{
int nE = 3;
if( nE>data.a[j].w ) nE = data.a[j].w;
data.a[j].z = "...";
qrfPrintAligned(p->pOut, &data.a[j], nE, data.a[j].w-nE);
}
if( j<nColumn-1 ){
sqlite3_str_append(p->pOut, colSep, szColSep);
}else{
if( bRTrim ) qrfRTrim(p->pOut);
sqlite3_str_append(p->pOut, rowSep, szRowSep);
}
}
}
/* Draw either (1) the separator between the title line and the body
** of the table, or (2) separators between individual rows of the table
** body. isTitleDataSeparator will be true if we are doing (1).
*/
if( (i==0 || data.bMultiRow) && i+nColumn<data.n ){
int isTitleDataSeparator = (i==0 && p->spec.bTitles==QRF_Yes);
if( isTitleDataSeparator ){
qrfLoadAlignment(&data, p);
}
switch( p->spec.eStyle ){
case QRF_STYLE_Table: {
if( isTitleDataSeparator || data.bMultiRow ){
qrfRowSeparator(p->pOut, &data, '+');
}
break;
}
case QRF_STYLE_Box: {
if( isTitleDataSeparator ){
qrfBoxSeparator(p->pOut, &data, DBL_123, DBL_1234, DBL_134, 1);
}else if( data.bMultiRow ){
qrfBoxSeparator(p->pOut, &data, BOX_123, BOX_1234, BOX_134, 0);
}
break;
}
case QRF_STYLE_Markdown: {
if( isTitleDataSeparator ){
qrfRowSeparator(p->pOut, &data, '|');
}
break;
}
case QRF_STYLE_Column: {
if( isTitleDataSeparator ){
for(j=0; j<nColumn; j++){
sqlite3_str_appendchar(p->pOut, data.a[j].w, '-');
if( j<nColumn-1 ){
sqlite3_str_append(p->pOut, colSep, szColSep);
}else{
qrfRTrim(p->pOut);
sqlite3_str_append(p->pOut, rowSep, szRowSep);
}
}
}else if( data.bMultiRow ){
qrfRTrim(p->pOut);
sqlite3_str_append(p->pOut, "\n", 1);
}
break;
}
}
}
}
/* Draw the line across the bottom of the table */
if( p->spec.bBorder!=QRF_No ){
switch( p->spec.eStyle ){
case QRF_STYLE_Box:
qrfBoxSeparator(p->pOut, &data, BOX_R12, BOX_124, BOX_R14, 0);
break;
case QRF_STYLE_Table:
qrfRowSeparator(p->pOut, &data, '+');
break;
}
}
qrfWrite(p);
qrfColDataFree(&data);
return;
}
/*
** Parameter azArray points to a zero-terminated array of strings. zStr
** points to a single nul-terminated string. Return non-zero if zStr
** is equal, according to strcmp(), to any of the strings in the array.
** Otherwise, return zero.
*/
static int qrfStringInArray(const char *zStr, const char **azArray){
int i;
if( zStr==0 ) return 0;
for(i=0; azArray[i]; i++){
if( 0==strcmp(zStr, azArray[i]) ) return 1;
}
return 0;
}
/*
** Print out an EXPLAIN with indentation. This is a two-pass algorithm.
**
** On the first pass, we compute aiIndent[iOp] which is the amount of
** indentation to apply to the iOp-th opcode. The output actually occurs
** on the second pass.
**
** 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 qrfExplain(Qrf *p){
int *abYield = 0; /* abYield[iOp] is rue if opcode iOp is an OP_Yield */
int *aiIndent = 0; /* Indent the iOp-th opcode by aiIndent[iOp] */
i64 nAlloc = 0; /* Allocated size of aiIndent[], abYield */
int nIndent = 0; /* Number of entries in aiIndent[] */
int iOp; /* Opcode number */
int i; /* Column loop counter */
/* The caller guarantees that the leftmost 4 columns of the statement
** passed to this function are equivalent to the leftmost 4 columns
** of EXPLAIN statement output. In practice the statement may be
** an EXPLAIN, or it may be a query on the bytecode() virtual table. */
assert( sqlite3_column_count(p->pStmt)>=4 );
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) );
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) );
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) );
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) );
for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt) && !p->iErr; iOp++){
int iAddr = sqlite3_column_int(p->pStmt, 0);
const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1);
int p1 = sqlite3_column_int(p->pStmt, 2);
int p2 = sqlite3_column_int(p->pStmt, 3);
/* Assuming that p2 is an instruction address, set variable p2op to the
** index of that instruction in the aiIndent[] array. p2 and p2op may be
** different if the current instruction is part of a sub-program generated
** by an SQL trigger or foreign key. */
int p2op = (p2 + (iOp-iAddr));
/*
** Do a "scanstatus vm" style EXPLAIN listing on p->pStmt.
**
** p->pStmt is probably not an EXPLAIN query. Instead, construct a
** new query that is a bytecode() rendering of p->pStmt with extra
** columns for the "scanstatus vm" outputs, and run the results of
** that new query through the normal EXPLAIN formatting.
*/
static void qrfScanStatusVm(Qrf *p){
sqlite3_stmt *pOrigStmt = p->pStmt;
sqlite3_stmt *pExplain;
int rc;
static const char *zSql =
" SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec,"
" format('% 6s (%.2f%%)',"
" CASE WHEN ncycle<100_000 THEN ncycle || ' '"
" WHEN ncycle<100_000_000 THEN (ncycle/1_000) || 'K'"
" WHEN ncycle<100_000_000_000 THEN (ncycle/1_000_000) || 'M'"
" ELSE (ncycle/1000_000_000) || 'G' END,"
" ncycle*100.0/(sum(ncycle) OVER ())"
" ) AS cycles"
" FROM bytecode(?1)";
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pExplain, 0);
if( rc ){
qrfError(p, rc, "%s", sqlite3_errmsg(p->db));
sqlite3_finalize(pExplain);
return;
}
sqlite3_bind_pointer(pExplain, 1, pOrigStmt, "stmt-pointer", 0);
p->pStmt = pExplain;
p->nCol = 10;
qrfExplain(p);
sqlite3_finalize(pExplain);
p->pStmt = pOrigStmt;
}
/*
** Attempt to determine if identifier zName needs to be quoted, either
** because it contains non-alphanumeric characters, or because it is an
** SQLite keyword. Be conservative in this estimate: When in doubt assume
** that quoting is required.
**
** Return 1 if quoting is required. Return 0 if no quoting is required.
*/
/*
** Helper function for QRF_STYLE_Json and QRF_STYLE_JObject.
** The initial "{" for a JSON object that will contain row content
** has been output. Now output all the content.
*/
static void qrfOneJsonRow(Qrf *p){
int i, nItem;
for(nItem=i=0; i<p->nCol; i++){
const char *zCName;
zCName = sqlite3_column_name(p->pStmt, i);
if( nItem>0 ) sqlite3_str_append(p->pOut, ",", 1);
nItem++;
qrfEncodeText(p, p->pOut, zCName);
sqlite3_str_append(p->pOut, ":", 1);
qrfRenderValue(p, p->pOut, i);
}
qrfWrite(p);
}
/*
** Run the prepared statement pStmt and format the results according
** to the specification provided in pSpec. Return an error code.
** If pzErr is not NULL and if an error occurs, write an error message
** into *pzErr.
*/
int sqlite3_format_query_result(
sqlite3_stmt *pStmt, /* Statement to evaluate */
const sqlite3_qrf_spec *pSpec, /* Format specification */
char **pzErr /* Write error message here */
){
Qrf qrf; /* The new Qrf being created */
if( pStmt==0 ) return SQLITE_OK; /* No-op */
if( pSpec==0 ) return SQLITE_MISUSE;
qrfInitialize(&qrf, pStmt, pSpec, pzErr);
switch( qrf.spec.eStyle ){
case QRF_STYLE_Box:
case QRF_STYLE_Column:
case QRF_STYLE_Markdown:
case QRF_STYLE_Table: {
/* Columnar modes require that the entire query be evaluated and the
** results stored in memory, so that we can compute column widths */
qrfColumnar(&qrf);
break;
}
case QRF_STYLE_Explain: {
qrfExplain(&qrf);
break;
}
case QRF_STYLE_StatsVm: {
qrfScanStatusVm(&qrf);
break;
}
case QRF_STYLE_Stats:
case QRF_STYLE_StatsEst: {
qrfEqpStats(&qrf);
break;
}
default: {
/* Non-columnar modes where the output can occur after each row
** of result is received */
while( qrf.iErr==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
qrfOneSimpleRow(&qrf);
}
break;
}
}
qrfResetStmt(&qrf);
qrfFinalize(&qrf);
return qrf.iErr;
}
/************************* End ext/qrf/qrf.c ********************/
/* Use console I/O package as a direct INCLUDE. */
#define SQLITE_INTERNAL_LINKAGE static
#ifdef SQLITE_SHELL_FIDDLE
/* Deselect most features from the console I/O package for Fiddle. */
# define SQLITE_CIO_NO_REDIRECT
# define SQLITE_CIO_NO_CLASSIFY
# define SQLITE_CIO_NO_TRANSLATE
# define SQLITE_CIO_NO_SETMODE
# define SQLITE_CIO_NO_FLUSH
#endif
/*
** The source code for several run-time loadable extensions is inserted
** below by the ../tool/mkshellc.tcl script. Before processing that included
** code, we need to override some macros to make the included program code
** work here in the middle of this regular program.
*/
#define SQLITE_EXTENSION_INIT1
#define SQLITE_EXTENSION_INIT2(X) (void)(X)
/************************* Begin ext/misc/windirent.h ******************/
/*
** 2025-06-05
**
** 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.
**
*************************************************************************
**
** An implementation of opendir(), readdir(), and closedir() for Windows,
** based on the FindFirstFile(), FindNextFile(), and FindClose() APIs
** of Win32.
**
** #include this file inside any C-code module that needs to use
** opendir()/readdir()/closedir(). This file is a no-op on non-Windows
** machines. On Windows, static functions are defined that implement
** those standard interfaces.
*/
#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
#define SQLITE_WINDIRENT_H
/* The dirent object for Windows is abbreviated. The only field really
** usable by applications is d_name[].
*/
struct dirent {
int d_ino; /* Inode number (synthesized) */
unsigned d_attributes; /* File attributes */
char d_name[FILENAME_MAX]; /* Null-terminated filename */
};
/* The internals of DIR are opaque according to standards. So it
** does not matter what we put here. */
typedef struct DIR DIR;
struct DIR {
intptr_t d_handle; /* Handle for findfirst()/findnext() */
struct dirent cur; /* Current entry */
};
/* Ignore hidden and system files */
#define WindowsFileToIgnore(a) \
((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
/*
** Close a previously opened directory
*/
static int closedir(DIR *pDir){
int rc = 0;
if( pDir==0 ){
return EINVAL;
}
if( pDir->d_handle!=0 && pDir->d_handle!=(-1) ){
rc = _findclose(pDir->d_handle);
}
sqlite3_free(pDir);
return rc;
}
/*
** Open a new directory. The directory name should be UTF-8 encoded.
** appropriate translations happen automatically.
*/
static DIR *opendir(const char *zDirName){
DIR *pDir;
wchar_t *b1;
sqlite3_int64 sz;
struct _wfinddata_t data;
/*
** Read the next entry from a directory.
**
** The returned struct-dirent object is managed by DIR. It is only
** valid until the next readdir() or closedir() call. Only the
** d_name[] field is meaningful. The d_name[] value has been
** translated into UTF8.
*/
static struct dirent *readdir(DIR *pDir){
struct _wfinddata_t data;
if( pDir==0 ) return 0;
if( (pDir->cur.d_ino++)==0 ){
return &pDir->cur;
}
do{
memset(&data, 0, sizeof(data));
if( _wfindnext(pDir->d_handle, &data)==-1 ){
return NULL;
}
}while( WindowsFileToIgnore(data) );
pDir->cur.d_attributes = data.attrib;
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
pDir->cur.d_name, FILENAME_MAX, 0, 0);
return &pDir->cur;
}
#endif /* defined(_WIN32) && defined(_MSC_VER) */
/************************* End ext/misc/windirent.h ********************/
/************************* 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;
/************************* End ext/misc/memtrace.c ********************/
/************************* Begin ext/misc/pcachetrace.c ******************/
/*
** 2023-06-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_PCACHE2
** mechanism to add a tracing layer on top of pluggable page cache of
** SQLite. If this extension is registered prior to sqlite3_initialize(),
** it will cause all page cache 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 --pcachetrace option of the
** command-line shell.
*/
#include <assert.h>
#include <string.h>
#include <stdio.h>
/* The original page cache routines */
static sqlite3_pcache_methods2 pcacheBase;
static FILE *pcachetraceOut;
/************************* End ext/misc/pcachetrace.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:
**
** 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 functions that compute SHA3 hashes
** in the way described by the (U.S.) NIST FIPS 202 SHA-3 Standard.
** Three SQL functions are implemented:
**
** sha3(X,SIZE)
** sha3_agg(Y,SIZE)
** sha3_query(Z,SIZE)
**
** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
** X is NULL. If inputs X is text, the UTF-8 rendering of that text is
** used to compute the hash. If X is a BLOB, then the binary data of the
** blob is used to compute the hash. If X is an integer or real number,
** then that number if converted into UTF-8 text and the hash is computed
** over the text.
**
** The sha3_agg(Y) function computes the SHA3 hash of all Y inputs. Since
** order is important for the hash, it is recommended that the Y expression
** by followed by an ORDER BY clause to guarantee that the inputs occur
** in the desired order.
**
** The sha3_query(Y) function evaluates all queries in the SQL statements of Y
** and returns a hash of their results.
**
** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
** is used. If SIZE is included it must be one of the integers 224, 256,
** 384, or 512, to determine SHA3 hash variant that is computed.
**
** Because the sha3_agg() and sha3_query() functions compute a hash over
** multiple values, the values are encode to use include type information.
**
** In sha3_agg(), the sequence of bytes that gets hashed for each input
** Y depends on the datatype of Y:
**
** typeof(Y)='null' A single "N" is hashed. (One byte)
**
** typeof(Y)='integer' The data hash is the character "I" followed
** by an 8-byte big-endian binary of the
** 64-bit signed integer. (Nine bytes total.)
**
** typeof(Y)='real' The character "F" followed by an 8-byte
** big-ending binary of the double. (Nine
** bytes total.)
**
** typeof(Y)='text' The hash is over prefix "Tnnn:" followed
** by the UTF8 encoding of the text. The "nnn"
** in the prefix is the minimum-length decimal
** representation of the octet_length of the text.
** Notice the ":" at the end of the prefix, which
** is needed to separate the prefix from the
** content in cases where the content starts
** with a digit.
**
** typeof(Y)='blob' The hash is taken over prefix "Bnnn:" followed
** by the binary content of the blob. The "nnn"
** in the prefix is the minimum-length decimal
** representation of the byte-length of the blob.
**
** According to the rules above, all of the following SELECT statements
** should return TRUE:
**
** SELECT sha3(1) = sha3('1');
**
** SELECT sha3('hello') = sha3(x'68656c6c6f');
**
** WITH a(x) AS (VALUES('xyzzy'))
** SELECT sha3_agg(x) = sha3('T5:xyzzy') FROM a;
**
** WITH a(x) AS (VALUES(x'010203'))
** SELECT sha3_agg(x) = sha3(x'42333a010203') FROM a;
**
** WITH a(x) AS (VALUES(0x123456))
** SELECT sha3_agg(x) = sha3(x'490000000000123456') FROM a;
**
** WITH a(x) AS (VALUES(100.015625))
** SELECT sha3_agg(x) = sha3(x'464059010000000000') FROM a;
**
** WITH a(x) AS (VALUES(NULL))
** SELECT sha3_agg(x) = sha3('N') FROM a;
**
**
** In sha3_query(), individual column values are encoded as with
** sha3_agg(), but with the addition that a single "R" character is
** inserted at the start of each row.
**
** Note that sha3_agg() hashes rows for which Y is NULL. Add a FILTER
** clause if NULL rows should be excluded:
**
** SELECT sha3_agg(x ORDER BY rowid) FILTER(WHERE x NOT NULL) FROM t1;
*/
/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <stdarg.h>
/******************************************************************************
** The Hash Engine
*/
/*
** Macros to determine whether the machine is big or little endian,
** and whether or not that determination is run-time or compile-time.
**
** For best performance, an attempt is made to guess at the byte-order
** using C-preprocessor macros. If that is unsuccessful, or if
** -DSHA3_BYTEORDER=0 is set, then byte-order is determined
** at run-time.
*/
#ifndef SHA3_BYTEORDER
# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
defined(__arm__)
# define SHA3_BYTEORDER 1234
# elif defined(sparc) || defined(__ppc__)
# define SHA3_BYTEORDER 4321
# else
# define SHA3_BYTEORDER 0
# endif
#endif
/*
** State structure for a SHA3 hash in progress
*/
typedef struct SHA3Context SHA3Context;
struct SHA3Context {
union {
u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */
unsigned char x[1600]; /* ... or 1600 bytes */
} u;
unsigned nRate; /* Bytes of input accepted per Keccak iteration */
unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */
unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */
unsigned iSize; /* 224, 256, 358, or 512 */
};
/*
** Initialize a new hash. iSize determines the size of the hash
** in bits and should be one of 224, 256, 384, or 512. Or iSize
** can be zero to use the default hash size of 256 bits.
*/
static void SHA3Init(SHA3Context *p, int iSize){
memset(p, 0, sizeof(*p));
p->iSize = iSize;
if( iSize>=128 && iSize<=512 ){
p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
}else{
p->nRate = (1600 - 2*256)/8;
}
#if SHA3_BYTEORDER==1234
/* Known to be little-endian at compile-time. No-op */
#elif SHA3_BYTEORDER==4321
p->ixMask = 7; /* Big-endian */
#else
{
static unsigned int one = 1;
if( 1==*(unsigned char*)&one ){
/* Little endian. No byte swapping. */
p->ixMask = 0;
}else{
/* Big endian. Byte swap. */
p->ixMask = 7;
}
}
#endif
}
/*
** Make consecutive calls to the SHA3Update function to add new content
** to the hash
*/
static void SHA3Update(
SHA3Context *p,
const unsigned char *aData,
unsigned int nData
){
unsigned int i = 0;
if( aData==0 ) return;
#if SHA3_BYTEORDER==1234
if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0){
for(; i+7<nData; i+=8){
p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
p->nLoaded += 8;
if( p->nLoaded>=p->nRate ){
KeccakF1600Step(p);
p->nLoaded = 0;
}
}
}
#endif
for(; i<nData; i++){
#if SHA3_BYTEORDER==1234
p->u.x[p->nLoaded] ^= aData[i];
#elif SHA3_BYTEORDER==4321
p->u.x[p->nLoaded^0x07] ^= aData[i];
#else
p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
#endif
p->nLoaded++;
if( p->nLoaded==p->nRate ){
KeccakF1600Step(p);
p->nLoaded = 0;
}
}
}
/*
** After all content has been added, invoke SHA3Final() to compute
** the final hash. The function returns a pointer to the binary
** hash value.
*/
static unsigned char *SHA3Final(SHA3Context *p){
unsigned int i;
if( p->nLoaded==p->nRate-1 ){
const unsigned char c1 = 0x86;
SHA3Update(p, &c1, 1);
}else{
const unsigned char c2 = 0x06;
const unsigned char c3 = 0x80;
SHA3Update(p, &c2, 1);
p->nLoaded = p->nRate - 1;
SHA3Update(p, &c3, 1);
}
for(i=0; i<p->nRate; i++){
p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
}
return &p->u.x[p->nRate];
}
/* End of the hashing logic
*****************************************************************************/
/*
** Implementation of the sha3(X,SIZE) function.
**
** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default
** size is 256. If X is a BLOB, it is hashed as is.
** For all other non-NULL types of input, X is converted into a UTF-8 string
** and the string is hashed without the trailing 0x00 terminator. The hash
** of a NULL value is NULL.
*/
static void sha3Func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
SHA3Context cx;
int eType = sqlite3_value_type(argv[0]);
int nByte = sqlite3_value_bytes(argv[0]);
int iSize;
if( argc==1 ){
iSize = 256;
}else{
iSize = sqlite3_value_int(argv[1]);
if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
sqlite3_result_error(context, "SHA3 size should be one of: 224256 "
"384512", -1);
return;
}
}
if( eType==SQLITE_NULL ) return;
SHA3Init(&cx, iSize);
if( eType==SQLITE_BLOB ){
SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte);
}else{
SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte);
}
sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
}
/* Compute a string using sqlite3_vsnprintf() with a maximum length
** of 50 bytes and add it to the hash.
*/
static void sha3_step_vformat(
SHA3Context *p, /* Add content to this context */
const char *zFormat,
...
){
va_list ap;
int n;
char zBuf[50];
va_start(ap, zFormat);
sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
va_end(ap);
n = (int)strlen(zBuf);
SHA3Update(p, (unsigned char*)zBuf, n);
}
/*
** Update a SHA3Context using a single sqlite3_value.
*/
static void sha3UpdateFromValue(SHA3Context *p, sqlite3_value *pVal){
switch( sqlite3_value_type(pVal) ){
case SQLITE_NULL: {
SHA3Update(p, (const unsigned char*)"N",1);
break;
}
case SQLITE_INTEGER: {
sqlite3_uint64 u;
int j;
unsigned char x[9];
sqlite3_int64 v = sqlite3_value_int64(pVal);
memcpy(&u, &v, 8);
for(j=8; j>=1; j--){
x[j] = u & 0xff;
u >>= 8;
}
x[0] = 'I';
SHA3Update(p, x, 9);
break;
}
case SQLITE_FLOAT: {
sqlite3_uint64 u;
int j;
unsigned char x[9];
double r = sqlite3_value_double(pVal);
memcpy(&u, &r, 8);
for(j=8; j>=1; j--){
x[j] = u & 0xff;
u >>= 8;
}
x[0] = 'F';
SHA3Update(p,x,9);
break;
}
case SQLITE_TEXT: {
int n2 = sqlite3_value_bytes(pVal);
const unsigned char *z2 = sqlite3_value_text(pVal);
sha3_step_vformat(p,"T%d:",n2);
SHA3Update(p, z2, n2);
break;
}
case SQLITE_BLOB: {
int n2 = sqlite3_value_bytes(pVal);
const unsigned char *z2 = sqlite3_value_blob(pVal);
sha3_step_vformat(p,"B%d:",n2);
SHA3Update(p, z2, n2);
break;
}
}
}
/*
** Implementation of the sha3_query(SQL,SIZE) function.
**
** This function compiles and runs the SQL statement(s) given in the
** argument. The results are hashed using a SIZE-bit SHA3. The default
** size is 256.
**
** The format of the byte stream that is hashed is summarized as follows:
**
** S<n>:<sql>
** R
** N
** I<int>
** F<ieee-float>
** B<size>:<bytes>
** T<size>:<text>
**
** <sql> is the original SQL text for each statement run and <n> is
** the size of that text. The SQL text is UTF-8. A single R character
** occurs before the start of each row. N means a NULL value.
** I mean an 8-byte little-endian integer <int>. F is a floating point
** number with an 8-byte little-endian IEEE floating point value <ieee-float>.
** B means blobs of <size> bytes. T means text rendered as <size>
** bytes of UTF-8. The <n> and <size> values are expressed as an ASCII
** text integers.
**
** For each SQL statement in the X input, there is one S segment. Each
** S segment is followed by zero or more R segments, one for each row in the
** result set. After each R, there are one or more N, I, F, B, or T segments,
** one for each column in the result set. Segments are concatentated directly
** with no delimiters of any kind.
*/
static void sha3QueryFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3 *db = sqlite3_context_db_handle(context);
const char *zSql = (const char*)sqlite3_value_text(argv[0]);
sqlite3_stmt *pStmt = 0;
int nCol; /* Number of columns in the result set */
int i; /* Loop counter */
int rc;
int n;
const char *z;
SHA3Context cx;
int iSize;
/************************* End ext/misc/shathree.c ********************/
/************************* Begin ext/misc/sha1.c ******************/
/*
** 2017-01-27
**
** 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 functions that compute SHA1 hashes.
** Two SQL functions are implemented:
**
** sha1(X)
** sha1_query(Y)
**
** The sha1(X) function computes the SHA1 hash of the input X, or NULL if
** X is NULL.
**
** The sha1_query(Y) function evalutes all queries in the SQL statements of Y
** and returns a hash of their results.
*/
/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <stdarg.h>
/******************************************************************************
** The Hash Engine
*/
/* Context for the SHA1 hash */
typedef struct SHA1Context SHA1Context;
struct SHA1Context {
unsigned int state[5];
unsigned int count[2];
unsigned char buffer[64];
};
/*
* (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
*
* Rl0() for little-endian and Rb0() for big-endian. Endianness is
* determined at run-time.
*/
#define Rl0(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define Rb0(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R1(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R2(v,w,x,y,z,i) \
z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
#define R3(v,w,x,y,z,i) \
z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
#define R4(v,w,x,y,z,i) \
z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);
/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/
static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
unsigned int qq[5]; /* a, b, c, d, e; */
static int one = 1;
unsigned int block[16];
memcpy(block, buffer, 64);
memcpy(qq,state,5*sizeof(unsigned int));
#define a qq[0]
#define b qq[1]
#define c qq[2]
#define d qq[3]
#define e qq[4]
/* Copy p->state[] to working vars */
/*
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
*/
/* Add new content to the SHA1 hash */
static void hash_step(
SHA1Context *p, /* Add content to this context */
const unsigned char *data, /* Data to be added */
unsigned int len /* Number of bytes in data */
){
unsigned int i, j;
/* Compute a string using sqlite3_vsnprintf() and hash it */
static void hash_step_vformat(
SHA1Context *p, /* Add content to this context */
const char *zFormat,
...
){
va_list ap;
int n;
char zBuf[50];
va_start(ap, zFormat);
sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
va_end(ap);
n = (int)strlen(zBuf);
hash_step(p, (unsigned char*)zBuf, n);
}
/* Add padding and compute the message digest. Render the
** message digest as lower-case hexadecimal and put it into
** zOut[]. zOut[] must be at least 41 bytes long. */
static void hash_finish(
SHA1Context *p, /* The SHA1 context to finish and render */
char *zOut, /* Store hex or binary hash here */
int bAsBinary /* 1 for binary hash, 0 for hex hash */
){
unsigned int i;
unsigned char finalcount[8];
unsigned char digest[20];
static const char zEncode[] = "0123456789abcdef";
for (i = 0; i < 8; i++){
finalcount[i] = (unsigned char)((p->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
hash_step(p, (const unsigned char *)"\200", 1);
while ((p->count[0] & 504) != 448){
hash_step(p, (const unsigned char *)"\0", 1);
}
hash_step(p, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++){
digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
if( bAsBinary ){
memcpy(zOut, digest, 20);
}else{
for(i=0; i<20; i++){
zOut[i*2] = zEncode[(digest[i]>>4)&0xf];
zOut[i*2+1] = zEncode[digest[i] & 0xf];
}
zOut[i*2]= 0;
}
}
/* End of the hashing logic
*****************************************************************************/
/*
** Two SQL functions: sha1(X) and sha1b(X).
**
** sha1(X) returns a lower-case hexadecimal rendering of the SHA1 hash
** of the argument X. If X is a BLOB, it is hashed as is. For all other
** types of input, X is converted into a UTF-8 string and the string
** is hashed without the trailing 0x00 terminator. The hash of a NULL
** value is NULL.
**
** sha1b(X) is the same except that it returns a 20-byte BLOB containing
** the binary hash instead of a hexadecimal string.
*/
static void sha1Func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
SHA1Context cx;
int eType = sqlite3_value_type(argv[0]);
int nByte = sqlite3_value_bytes(argv[0]);
const unsigned char *pData;
char zOut[44];
/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */ #ifndef UNUSED_PARAMETER # define UNUSED_PARAMETER(X) (void)(X) #endif
/* A decimal object */ typedefstruct Decimal Decimal; struct Decimal { char sign; /* 0 for positive, 1 for negative */ char oom; /* True if an OOM is encountered */ char isNull; /* True if holds a NULL rather than a number */ char isInit; /* True upon initialization */ int nDigit; /* Total number of digits */ int nFrac; /* Number of digits to the right of the decimal point */ signedchar *a; /* Array of digits. Most significant first. */
};
/* **AllocateanewDecimalobjectfromansqlite3_value.Returnapointer **tothenewobject,orNULLifthereisanerror.IfthepCtxargument **isnotNULL,thenerrorsarereportedonitaswell. ** **IfthepInargumentisSQLITE_TEXTorSQLITE_INTEGER,itisconverted **directlyintoaDecimal.ForSQLITE_FLOATorforSQLITE_BLOBoflength **8bytes,theresultingdoublevalueisexpandedintoitsdecimalequivalent. **IfpInisNULLorifitisaBLOBthatisnotexactly8bytesinlength, **thenNULLisreturned. */ staticDecimal*decimal_new(
sqlite3_context *pCtx, /* Report error here, if not null */
sqlite3_value *pIn, /* Construct the decimal object from this */
){
Decimalinclude global.hjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19 int eType if bTextOnly& e=SQLITE_FLOAT|| eType==QLITE_BLOB){
eType =SQLITE_TEXT;
}
)java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18 casetruejava.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
TEGER
* c java.lang.StringIndexOutOfBoundsException: Range [36, 35) out of bounds for length 61 int colp=)-))
p=,n; if( p==0 ) -]=''
java.lang.StringIndexOutOfBoundsException: Range [8, 1) out of bounds for length 46
}
case SQLITE_FLOAT: {
p**********************************java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73 break
}
SQLITE_BLOB: constunsigned,sizeof->essage) MSGFWRITE_ERROR strerror);
;
sqlite3_uint64 v }java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
Tdbp->SetLi+*;
if((pIn!sizeofjava.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 26
x = RC_OK fori0 <sizeof) i+){
v=(v<8)|x[];
}
memcpy(if(){
r; break;
}
caseSQLITE_NULL:{
;
}
} return p;
new_failed:
sqlite3_free(p /*********************************************************************/
java.lang.StringIndexOutOfBoundsException: Range [73, 1) out of bounds for length 73
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
/* **MakethegivenDecimalthe*****************/
*/ static /
* int i, int n; if( p==0 || if (RenameTempFileg)
sqlite3_result_error_nomem(pCtx) return; } if(p->isNullsnprintf(-Message,sizeof(-,),() (pCtx; java.lang.StringIndexOutOfBoundsException: Range [11, 10) out of bounds for length 11 } z=sqlite3_malloc64((sqlite3_int64)p->(g->essage,sizeofg>),MSGREAD_SEEK_ERROR(); (z=0{ java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 16 java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 0 } i=0; if(p->nDigit=/java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49 p->sign= } p-java.lang.StringIndexOutOfBoundsException: Range [14, 13) out of bounds for length 16 z[0]= i=1; n=p->(FORMAT_MESSAGE_FLAGS,NULL,drc,0 if(n<=0){ z[i++]='0int::BigRead(PGLOBALg__((unused), } j=0; while(n>&-aj=0) j++;
nbw,len,drc,g->Message); while(n>0){ +]-aj'' ++ n--; } if snprintf(-Message,sizeof(-)(FILE_OPEN_YET)To_File)java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74 do{ z[i++]=p->a[j=Cardinality() j++; le(j<-nDigit); } z[i]=0; sqlite3_result_text(Ctx,z,i,sqlite3_free; }
/* *RoundavaluetoNdigits.Nmustpositivejava.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
*/ staticvoid decimal_round(Decimal *p, int N){ int i;
tnZerojava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12 char [MAX_PATH; if#fdefined(WIN32) // OB if( p->nDigit< if H = INVALID_HANDLE_VALUE { for(nZero=0; if(rc =GetLastError()! ) {
+ java.lang.StringIndexOutOfBoundsException: Range [22, 23) out of bounds for length 22 if( p->nDigit<=N ) return; if( p->a[N]>4 ){
p->a[N-1]++; for(i=N-1; i>0 && p->a[i]>9; i--){
p->a[i] = 0;
p->a[i-1]++;
} if( p->a[0]>9 ){
p->a[0] = 1;
p->nFrac--;
}
}
memset(&p->a[N], 0, p->nDigit - N);
}
/* **MakethegivenDecimaltheresultinanformatsimilarto'%+#e'. **Inotherwords,showexponentialnotationwithleadingandtrailing **zerosomitted.
*/ staticvoid decimal_result_sci(sqlite3_context *pCtx, Decimal *p, int N){ char *z; /* The output buffer */ int i; /* Loop counter */ int nZero; /* Number of leading zeros */ int nDigit; /* Number of digits not counting trailing zeros */ int nFrac; /* Digits to the right of the decimal point */ int exp; /* Exponent value */ signedchar zero; /* Zero value */ signedchar *a; /* Array of digits */
/* **ExpandtheDecimalsothatithasaleastnDigitdigitsandnFrac **=g,To_BufLrecl*Nrec);
*/ staticvoid decimal_expand(Decimal *p, int nDigit, int nFrac){
;
-GetMode)= ){ signedchar*a; if(p=0 )return
nAddFrac = nFrac - p->nFrac;
nAddSig = (nDigit Tdbp-(); ifnAddFrac= & =0)return; if +>SQLITE_DECIMAL_MAX_DIGIT ) p-oom =;return }
a = java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 12 if( a==0 ){
java.lang.StringIndexOutOfBoundsException: Range [73, 74) out of bounds for length 73 return;
}
p->a = a; if( nAddSig ){
} // Fpos is the deleted line position
memset(p->a, 0, /* First line to delete. Move of eventual preceding lines is */ if (seTemp {
}
nAddFrac)
memset(p->a+p->nDigit, 0,/********************************************************
p->nDigit += nAddFrac;
p> += nAddFrac;
}
}
/* **AddthevaluepBintopA.A:=A(sizeof(-)MSG(TRUNCATE_ERROR,strerrorerrno))java.lang.StringIndexOutOfBoundsException: Index 87 out of bounds for length 87
**Bothjava.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
*/
*pB int nSig; int i, rc; if( pA=/ java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16 return;
} if( pA->oom || pB==0 || pB->java.lang.StringIndexOutOfBoundsException: Range [73, 32) out of bounds for length 73
pA->oom = 1; return;
} if( pA !)
pA-isNull =1; return;
}
nSig java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30 if( nSig & / Some more inserted lines remain to be written if( nSig< // endif Abort
}
nFrac = java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 0 if( nFrac<pB->nFrac ) nFrac = pB->nFrac;
nDigit = nSig + nFrac + 1;
decimal_expand(pA, nDigit, nFrac);
decimal_expand(pB, nDigit, nFrac); if( pA->oom #fdefined(_IN32) //OB
pA->oom = 1;
}else{ if( pA->sign==pB->sign ){ int carry = 0; for(i=nDigit-1; i>=0; i--){ int x = pA->a[i] + pB->a[i] + carry; if( x>=10 ){
carry = 1;
pA->a[i] = x - 10;
}else{
carry = 0;
pA->a[i] = x;
}
}
}else{ signedchar *aA, *aB; int borrow = 0;
rc = memcmp(pA->a, pB->a, nDigit); if( rc<0 ){
aA = pB->a;
aB = pA->a;
pA->sign = !pA->sign;
}else{
aA = pA->a;
aB = pB->a;
} for(i=nDigit-1; i>=0; i--){ int x = aA[i] - aB[i] - borrow; if( x<0 ){
pA->a[i] = x+10;
borrow = 1;
}else{
pA->a[i] = x;
borrow = 0;
}
}
}
}
}
/* **MultiplyAbyB.A:=A*B ** **Allsignificantdigitsafterthedecimalpointareretained. **Trailingzerosafterthedecimalpointareomittedaslongas **thenumberofdigitsafterthedecimalpointisnolessthan **eitherthenumberofdigitsineitherinput.
*/ staticvoid decimalMul(Decimal *pA, Decimal *pB){ signedchar *acc = 0; int i, j, k; int minFrac;
sqlite3_int64 sumDigit;
/* **UseanIEEE754binary64("double")togenerateanewDecimalobject.
*/ static Decimal *decimalFromDouble(double r){
sqlite3_int64 m, a; int e; int isNeg;
Decimal *pA;
Decimal *pX; char zNum[100]; if( r<0.0 ){
isNeg = 1;
r = -r;
}else{
isNeg = 0;
}
memcpy(&a,&r,sizeof(a)); if( a==0 || a==(sqlite3_int64)0x8000000000000000LL){
e = 0;
m = 0;
}else{
e = a>>52;
m = a & ((((sqlite3_int64)1)<<52)-1); if( e==0 ){
m <<= 1;
}else{
m |= ((sqlite3_int64)1)<<52;
} while( e<1075 && m>0 && (m&1)==0 ){
m >>= 1;
e++;
} if( isNeg ) m = -m;
e = e - 1075; if( e>971 ){ return0; /* A NaN or an Infinity */
}
}
/* At this point m is the integer significand and e is the exponent */
sqlite3_snprintf(sizeof(zNum), zNum, "%lld", m);
pA = decimalNewFromText(zNum, (int)strlen(zNum));
pX = decimalPow2(e);
decimalMul(pA, pX);
decimal_free(pX); return pA;
}
# ifdef _WIN32 # include <io.h> # include <fcntl.h> # else # define setmode(fd,m) # endif
staticchar *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"
;
/* Classify c according to interval within USASCII set w.r.t. base85 *Valuesof1and3arebase85numerals.Valuesof0,2,or4arenot.
*/ #define B85_CLASS( c ) (((c)>='#')+((c)>'&')+((c)>='*')+((c)>'z'))
/* Provide digitValue to b85Numeral offset as a function of above class. */ static u8 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)
#if0/* Not used, */ static u8 base85DigitValue( char c ){
u8 dv = (u8)(c - '#'); if( dv>87 ) return0xff; return (dv > 3)? dv-3 : dv;
} #endif
/* Width of base64 lines. Should be an integer multiple of 5. */ #define B85_DARK_MAX 80
/* 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.*/ #if0 staticchar base85Numeral( u8 b ){ return (b < 4)? (char)(b + '#') : (char)(b - 4 + '*');
} #else # define base85Numeral( dn )\
((char)(((dn) < 4)? (char)((dn) + '#') : (char)((dn) - 4 + '*'))) #endif
#ifndef OMIT_BASE85_CHECKER /* Say whether input char sequence is all (base85 and/or whitespace).*/ staticint allBase85( char *p, int len ){ char c; while( len-- > 0 && (c = *p++) != 0 ){ if( !IS_B85(c) && !isspace(c) ) return0;
} return1;
} #endif
#ifndef BASE85_STANDALONE
#ifndef OMIT_BASE85_CHECKER /* This function does the work for the SQLite is_base85(t) UDF. */ staticvoid 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. */ staticvoid base85(sqlite3_context *context, int na, sqlite3_value *av[]){
sqlite3_int64 nb, nc, nv = sqlite3_value_bytes(av[0]); int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
SQLITE_LIMIT_LENGTH, -1); char *cBuf;
u8 *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;
}
bBuf = (u8*)sqlite3_value_blob(av[0]); if( !bBuf ){ if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){ goto memFail;
}
sqlite3_result_text(context,"",-1,SQLITE_STATIC); break;
}
cBuf = sqlite3_malloc64(nc); if( !cBuf ) goto memFail;
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;
}elseif( nb<1 ){
nb = 1;
}
cBuf = (char *)sqlite3_value_text(av[0]); if( !cBuf ){ if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){ goto memFail;
}
sqlite3_result_zeroblob(context, 0); break;
}
bBuf = sqlite3_malloc64(nb); if( !bBuf ) goto memFail;
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);
}
/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */ #ifndef UNUSED_PARAMETER # define UNUSED_PARAMETER(X) (void)(X) #endif
/* **Implementationoftheieee754()function
*/ staticvoid ieee754func(
sqlite3_context *context, int argc,
sqlite3_value **argv
){ if( argc==1 ){
sqlite3_int64 m, a; double r; int e; int isNeg; char zResult[100];
assert( sizeof(m)==sizeof(r) ); if( sqlite3_value_type(argv[0])==SQLITE_BLOB
&& sqlite3_value_bytes(argv[0])==sizeof(r)
){ constunsignedchar *x = sqlite3_value_blob(argv[0]); unsignedint i;
sqlite3_uint64 v = 0; for(i=0; i<sizeof(r); i++){
v = (v<<8) | x[i];
}
memcpy(&r, &v, sizeof(r));
}else{
r = sqlite3_value_double(argv[0]);
} if( r<0.0 ){
isNeg = 1;
r = -r;
}else{
isNeg = 0;
}
memcpy(&a,&r,sizeof(a)); if( a==0 ){
e = 0;
m = 0;
}elseif( a==(sqlite3_int64)0x8000000000000000LL ){
e = -1996;
m = -1;
}else{
e = a>>52;
m = a & ((((sqlite3_int64)1)<<52)-1); if( e==0 ){
m <<= 1;
}else{
m |= ((sqlite3_int64)1)<<52;
} while( e<1075 && m>0 && (m&1)==0 ){
m >>= 1;
e++;
} if( isNeg ) m = -m;
} switch( *(int*)sqlite3_user_data(context) ){ case0:
sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
m, e-1075);
sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT); break; case1:
sqlite3_result_int64(context, m); break; case2:
sqlite3_result_int(context, e-1075); break;
}
}else{
sqlite3_int64 m, e, a; double r; int isNeg = 0;
m = sqlite3_value_int64(argv[0]);
e = sqlite3_value_int64(argv[1]);
/* Limit the range of e. Ticket 22dea1cfdb9151e4 2021-03-02 */ if( e>10000 ){
e = 10000;
}elseif( e<-10000 ){
e = -10000;
}
if( m<0 ){ if( m<(-9223372036854775807LL) ) return;
isNeg = 1;
m = -m;
}elseif( m==0 && e>-1000 && e<1000 ){
sqlite3_result_double(context, 0.0); return;
} while( (m>>32)&0xffe00000 ){
m >>= 1;
e++;
} while( m!=0 && ((m>>32)&0xfff00000)==0 ){
m <<= 1;
e--;
}
e += 1075; if( e<=0 ){ /* Subnormal */ if( 1-e >= 64 ){
m = 0;
}else{
m >>= 1-e;
}
e = 0;
}elseif( e>0x7ff ){
e = 0x7ff;
}
a = m & ((((sqlite3_int64)1)<<52)-1);
a |= e<<52; if( isNeg ) a |= ((sqlite3_uint64)1)<<63;
memcpy(&r, &a, sizeof(r));
sqlite3_result_double(context, r);
}
}
/* The end-of-input character */ #define RE_EOF 0/* End of input */ #define RE_START 0xfffffff /* Start of input - larger than an UTF-8 */
/* The NFA is implemented as sequence of opcodes taken from the following **set.Eachopcodehasasingleintegerargument.
*/ #define RE_OP_MATCH 1/* Match the one character in the argument */ #define RE_OP_ANY 2/* Match any one character. (Implements ".") */ #define RE_OP_ANYSTAR 3/* Special optimized version of .* */ #define RE_OP_FORK 4/* Continue to both next and opcode at iArg */ #define RE_OP_GOTO 5/* Jump to opcode at iArg */ #define RE_OP_ACCEPT 6/* Halt and indicate a successful match */ #define RE_OP_CC_INC 7/* Beginning of a [...] character class */ #define RE_OP_CC_EXC 8/* Beginning of a [^...] character class */ #define RE_OP_CC_VALUE 9/* Single value in a character class */ #define RE_OP_CC_RANGE 10/* Range of values in a character class */ #define RE_OP_WORD 11/* Perl word character [A-Za-z0-9_] */ #define RE_OP_NOTWORD 12/* Not a perl word character */ #define RE_OP_DIGIT 13/* digit: [0-9] */ #define RE_OP_NOTDIGIT 14/* Not a digit */ #define RE_OP_SPACE 15/* space: [ \t\n\r\v\f] */ #define RE_OP_NOTSPACE 16/* Not a digit */ #define RE_OP_BOUNDARY 17/* Boundary between word and non-word */ #define RE_OP_ATSTART 18/* Currently at the start of the string */
/* Each opcode is a "state" in the NFA */ typedefunsignedshort ReStateNumber;
/* Because this is an NFA and not a DFA, multiple states can be active at **once.Aninstanceofthefollowingobjectrecordsallactivestatesin **theNFA.Theimplementationisoptimizedforthecommoncasewherethe **numberofactivesstatesissmall.
*/
typedef struct ReStateSet {
unsigned nState; /* Number of current states */
ReStateNumber *aState; /* Current states */
} ReStateSet;
/* An input string read one character at a time.
*/
typedef struct ReInput ReInput;
struct ReInput {
const unsigned char *z; /* All text */
int i; /* Next byte to read */
int mx; /* EOF when i>=mx */
};
/* A compiled NFA (or an NFA that is in the process of being compiled) is
** an instance of the following object.
*/
typedef struct ReCompiled ReCompiled;
struct ReCompiled {
ReInput sIn; /* Regular expression text */
const char *zErr; /* Error message to return */
char *aOp; /* Operators for the virtual machine */
int *aArg; /* Arguments to each operator */
unsigned (*xNextChar)(ReInput*); /* Next character function */
unsigned char zInit[12]; /* Initial text to match */
int nInit; /* Number of bytes in zInit */
unsigned nState; /* Number of entries in aOp[] and aArg[] */
unsigned nAlloc; /* Slots allocated for aOp[] and aArg[] */
unsigned mxAlloc; /* Complexity limit */
};
/* Add a state to the given state set if it is not already there */
static void re_add_state(ReStateSet *pSet, int newState){
unsigned i;
for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
pSet->aState[pSet->nState++] = (ReStateNumber)newState;
}
/* Extract the next unicode character from *pzIn and return it. Advance
** *pzIn to the first byte past the end of the character returned. To
** be clear: this routine converts utf8 to unicode. This routine is
** optimized for the common case where the next character is a single byte.
*/
static unsigned re_next_char(ReInput *p){
unsigned c;
if( p->i>=p->mx ) return 0;
c = p->z[p->i++];
if( c>=0x80 ){
if( (c&0xe0)==0xc0 && p->i<p->mx && (p->z[p->i]&0xc0)==0x80 ){
c = (c&0x1f)<<6 | (p->z[p->i++]&0x3f);
if( c<0x80 ) c = 0xfffd;
}else if( (c&0xf0)==0xe0 && p->i+1<p->mx && (p->z[p->i]&0xc0)==0x80
&& (p->z[p->i+1]&0xc0)==0x80 ){
c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f);
p->i += 2;
if( c<=0x7ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd;
}else if( (c&0xf8)==0xf0 && p->i+2<p->mx && (p->z[p->i]&0xc0)==0x80
&& (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){
c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6)
| (p->z[p->i+2]&0x3f);
p->i += 3;
if( c<=0xffff || c>0x10ffff ) c = 0xfffd;
}else{
c = 0xfffd;
}
}
return c;
}
static unsigned re_next_char_nocase(ReInput *p){
unsigned c = re_next_char(p);
if( c>='A' && c<='Z' ) c += 'a' - 'A';
return c;
}
/* Return true if c is a perl "word" character: [A-Za-z0-9_] */
static int re_word_char(int c){
return (c>='0' && c<='9') || (c>='a' && c<='z')
|| (c>='A' && c<='Z') || c=='_';
}
/* Return true if c is a "digit" character: [0-9] */
static int re_digit_char(int c){
return (c>='0' && c<='9');
}
/* Return true if c is a perl "space" character: [ \t\r\n\v\f] */
static int re_space_char(int c){
return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
}
/* Run a compiled regular expression on the zero-terminated input
** string zIn[]. Return true on a match and false if there is no match.
*/
static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
ReStateSet aStateSet[2], *pThis, *pNext;
ReStateNumber aSpace[100];
ReStateNumber *pToFree;
unsigned int i = 0;
unsigned int iSwap = 0;
int c = RE_START;
int cPrev = 0;
int rc = 0;
ReInput in;
/* Resize the opcode and argument arrays for an RE under construction.
*/
static int re_resize(ReCompiled *p, unsigned int N){
char *aOp;
int *aArg;
if( N>p->mxAlloc ){ p->zErr = "REGEXP pattern too big"; return 1; }
aOp = sqlite3_realloc64(p->aOp, N*sizeof(p->aOp[0]));
if( aOp==0 ){ p->zErr = "out of memory"; return 1; }
p->aOp = aOp;
aArg = sqlite3_realloc64(p->aArg, N*sizeof(p->aArg[0]));
if( aArg==0 ){ p->zErr = "out of memory"; return 1; }
p->aArg = aArg;
p->nAlloc = N;
return 0;
}
/* Insert a new opcode and argument into an RE under construction. The
** insertion point is just prior to existing opcode iBefore.
*/
static int re_insert(ReCompiled *p, int iBefore, int op, int arg){
int i;
if( p->nAlloc<=p->nState && re_resize(p, p->nAlloc*2) ) return 0;
for(i=p->nState; i>iBefore; i--){
p->aOp[i] = p->aOp[i-1];
p->aArg[i] = p->aArg[i-1];
}
p->nState++;
p->aOp[iBefore] = (char)op;
p->aArg[iBefore] = arg;
return iBefore;
}
/* Append a new opcode and argument to the end of the RE under construction.
*/
static int re_append(ReCompiled *p, int op, int arg){
return re_insert(p, p->nState, op, arg);
}
/* Make a copy of N opcodes starting at iStart onto the end of the RE
** under construction.
*/
static void re_copy(ReCompiled *p, int iStart, unsigned int N){
if( p->nState+N>=p->nAlloc && re_resize(p, p->nAlloc*2+N) ) return;
memcpy(&p->aOp[p->nState], &p->aOp[iStart], N*sizeof(p->aOp[0]));
memcpy(&p->aArg[p->nState], &p->aArg[iStart], N*sizeof(p->aArg[0]));
p->nState += N;
}
/* Return true if c is a hexadecimal digit character: [0-9a-fA-F]
** If c is a hex digit, also set *pV = (*pV)*16 + valueof(c). If
** c is not a hex digit *pV is unchanged.
*/
static int re_hex(int c, int *pV){
if( c>='0' && c<='9' ){
c -= '0';
}else if( c>='a' && c<='f' ){
c -= 'a' - 10;
}else if( c>='A' && c<='F' ){
c -= 'A' - 10;
}else{
return 0;
}
*pV = (*pV)*16 + (c & 0xff);
return 1;
}
/* A backslash character has been seen, read the next character and
** return its interpretation.
*/
static unsigned re_esc_char(ReCompiled *p){
static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]-";
static const char zTrans[] = "\a\f\n\r\t\v";
int i, v = 0;
char c;
if( p->sIn.i>=p->sIn.mx ) return 0;
c = p->sIn.z[p->sIn.i];
if( c=='u' && p->sIn.i+4<p->sIn.mx ){
const unsigned char *zIn = p->sIn.z + p->sIn.i;
if( re_hex(zIn[1],&v)
&& re_hex(zIn[2],&v)
&& re_hex(zIn[3],&v)
&& re_hex(zIn[4],&v)
){
p->sIn.i += 5;
return v;
}
}
if( c=='x' && p->sIn.i+2<p->sIn.mx ){
const unsigned char *zIn = p->sIn.z + p->sIn.i;
if( re_hex(zIn[1],&v)
&& re_hex(zIn[2],&v)
){
p->sIn.i += 3;
return v;
}
}
for(i=0; zEsc[i] && zEsc[i]!=c; i++){}
if( zEsc[i] ){
if( i<6 ) c = zTrans[i];
p->sIn.i++;
}else{
p->zErr = "unknown \\ escape";
}
return c;
}
/* Peek at the next byte of input */
static unsigned char rePeek(ReCompiled *p){
return p->sIn.i<p->sIn.mx ? p->sIn.z[p->sIn.i] : 0;
}
/* Compile RE text into a sequence of opcodes. Continue up to the
** first unmatched ")" character, then return. If an error is found,
** return a pointer to the error message string.
*/
static const char *re_subcompile_re(ReCompiled *p){
const char *zErr;
int iStart, iEnd, iGoto;
iStart = p->nState;
zErr = re_subcompile_string(p);
if( zErr ) return zErr;
while( rePeek(p)=='|' ){
iEnd = p->nState;
re_insert(p, iStart, RE_OP_FORK, iEnd + 2 - iStart);
iGoto = re_append(p, RE_OP_GOTO, 0);
p->sIn.i++;
zErr = re_subcompile_string(p);
if( zErr ) return zErr;
p->aArg[iGoto] = p->nState - iGoto;
}
return 0;
}
/* Compile an element of regular expression text (anything that can be
** an operand to the "|" operator). Return NULL on success or a pointer
** to the error message if there is a problem.
*/
static const char *re_subcompile_string(ReCompiled *p){
int iPrev = -1;
int iStart;
unsigned c;
const char *zErr;
while( (c = p->xNextChar(&p->sIn))!=0 ){
iStart = p->nState;
switch( c ){
case '|':
case ')': {
p->sIn.i--;
return 0;
}
case '(': {
zErr = re_subcompile_re(p);
if( zErr ) return zErr;
if( rePeek(p)!=')' ) return "unmatched '('";
p->sIn.i++;
break;
}
case '.': {
if( rePeek(p)=='*' ){
re_append(p, RE_OP_ANYSTAR, 0);
p->sIn.i++;
}else{
re_append(p, RE_OP_ANY, 0);
}
break;
}
case '*': {
if( iPrev<0 ) return "'*' without operand";
re_insert(p, iPrev, RE_OP_GOTO, p->nState - iPrev + 1);
re_append(p, RE_OP_FORK, iPrev - p->nState + 1);
break;
}
case '+': {
if( iPrev<0 ) return "'+' without operand";
re_append(p, RE_OP_FORK, iPrev - p->nState);
break;
}
case '?': {
if( iPrev<0 ) return "'?' without operand";
re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1);
break;
}
case '$': {
re_append(p, RE_OP_MATCH, RE_EOF);
break;
}
case '^': {
re_append(p, RE_OP_ATSTART, 0);
break;
}
case '{': {
unsigned int m = 0, n = 0;
unsigned int sz, j;
if( iPrev<0 ) return "'{m,n}' without operand";
while( (c=rePeek(p))>='0' && c<='9' ){
m = m*10 + c - '0';
if( m*2>p->mxAlloc ) return "REGEXP pattern too big";
p->sIn.i++;
}
n = m;
if( c==',' ){
p->sIn.i++;
n = 0;
while( (c=rePeek(p))>='0' && c<='9' ){
n = n*10 + c-'0';
if( n*2>p->mxAlloc ) return "REGEXP pattern too big";
p->sIn.i++;
}
}
if( c!='}' ) return "unmatched '{'";
if( n<m ) return "n less than m in '{m,n}'";
p->sIn.i++;
sz = p->nState - iPrev;
if( m==0 ){
if( n==0 ) return "both m and n are zero in '{m,n}'";
re_insert(p, iPrev, RE_OP_FORK, sz+1);
iPrev++;
n--;
}else{
for(j=1; j<m; j++) re_copy(p, iPrev, sz);
}
for(j=m; j<n; j++){
re_append(p, RE_OP_FORK, sz+1);
re_copy(p, iPrev, sz);
}
if( n==0 && m>0 ){
re_append(p, RE_OP_FORK, -(int)sz);
}
break;
}
case '[': {
unsigned int iFirst = p->nState;
if( rePeek(p)=='^' ){
re_append(p, RE_OP_CC_EXC, 0);
p->sIn.i++;
}else{
re_append(p, RE_OP_CC_INC, 0);
}
while( (c = p->xNextChar(&p->sIn))!=0 ){
if( c=='[' && rePeek(p)==':' ){
return "POSIX character classes not supported";
}
if( c=='\\' ) c = re_esc_char(p);
if( rePeek(p)=='-' ){
re_append(p, RE_OP_CC_RANGE, c);
p->sIn.i++;
c = p->xNextChar(&p->sIn);
if( c=='\\' ) c = re_esc_char(p);
re_append(p, RE_OP_CC_RANGE, c);
}else{
re_append(p, RE_OP_CC_VALUE, c);
}
if( rePeek(p)==']' ){ p->sIn.i++; break; }
}
if( c==0 ) return "unclosed '['";
if( p->nState>iFirst ) p->aArg[iFirst] = p->nState - iFirst;
break;
}
case '\\': {
int specialOp = 0;
switch( rePeek(p) ){
case 'b': specialOp = RE_OP_BOUNDARY; break;
case 'd': specialOp = RE_OP_DIGIT; break;
case 'D': specialOp = RE_OP_NOTDIGIT; break;
case 's': specialOp = RE_OP_SPACE; break;
case 'S': specialOp = RE_OP_NOTSPACE; break;
case 'w': specialOp = RE_OP_WORD; break;
case 'W': specialOp = RE_OP_NOTWORD; break;
}
if( specialOp ){
p->sIn.i++;
re_append(p, specialOp, 0);
}else{
c = re_esc_char(p);
re_append(p, RE_OP_MATCH, c);
}
break;
}
default: {
re_append(p, RE_OP_MATCH, c);
break;
}
}
iPrev = iStart;
}
return 0;
}
/* Free and reclaim all the memory used by a previously compiled
** regular expression. Applications should invoke this routine once
** for every call to re_compile() to avoid memory leaks.
*/
static void re_free(ReCompiled *pRe){
if( pRe ){
sqlite3_free(pRe->aOp);
sqlite3_free(pRe->aArg);
sqlite3_free(pRe);
}
}
/*
** Version of re_free() that accepts a pointer of type (void*). Required
** to satisfy sanitizers when the re_free() function is called via a
** function pointer.
*/
static void re_free_voidptr(void *p){
re_free((ReCompiled*)p);
}
/*
** Compile a textual regular expression in zIn[] into a compiled regular
** expression suitable for us by re_match() and return a pointer to the
** compiled regular expression in *ppRe. Return NULL on success or an
** error message if something goes wrong.
*/
static const char *re_compile(
ReCompiled **ppRe, /* OUT: write compiled NFA here */
const char *zIn, /* Input regular expression */
int mxRe, /* Complexity limit */
int noCase /* True for caseless comparisons */
){
ReCompiled *pRe;
const char *zErr;
int i, j;
/* The following is a performance optimization. If the regex begins with
** ".*" (if the input regex lacks an initial "^") and afterwards there are
** one or more matching characters, enter those matching characters into
** zInit[]. The re_match() routine can then search ahead in the input
** string looking for the initial match without having to run the whole
** regex engine over the string. Do not worry about trying to match
** unicode characters beyond plane 0 - those are very rare and this is
** just an optimization. */
if( pRe->aOp[0]==RE_OP_ANYSTAR && !noCase ){
for(j=0, i=1; j<(int)sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
unsigned x = pRe->aArg[i];
if( x<=0x7f ){
pRe->zInit[j++] = (unsigned char)x;
}else if( x<=0x7ff ){
pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
pRe->zInit[j++] = 0x80 | (x&0x3f);
}else if( x<=0xffff ){
pRe->zInit[j++] = (unsigned char)(0xe0 | (x>>12));
pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
pRe->zInit[j++] = 0x80 | (x&0x3f);
}else{
break;
}
}
if( j>0 && pRe->zInit[j-1]==0 ) j--;
pRe->nInit = j;
}
return pRe->zErr;
}
/*
** The value of LIMIT_MAX_PATTERN_LENGTH.
*/
static int re_maxlen(sqlite3_context *context){
sqlite3 *db = sqlite3_context_db_handle(context);
return sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1);
}
/*
** Maximum NFA size given a maximum pattern length.
*/
static int re_maxnfa(int mxlen){
return 75+mxlen/2;
}
/*
** Implementation of the regexp() SQL function. This function implements
** the build-in REGEXP operator. The first argument to the function is the
** pattern and the second argument is the string. So, the SQL statements:
**
** A REGEXP B
**
** is implemented as regexp(B,A).
*/
static void re_sql_func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
ReCompiled *pRe; /* Compiled regular expression */
const char *zPattern; /* The regular expression */
const unsigned char *zStr;/* String being searched */
const char *zErr; /* Compile error message */
int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
#if defined(SQLITE_DEBUG)
/*
** This function is used for testing and debugging only. It is only available
** if the SQLITE_DEBUG compile-time option is used.
**
** Compile a regular expression and then convert the compiled expression into
** text and return that text.
*/
static void re_bytecode_func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zPattern;
const char *zErr;
ReCompiled *pRe;
sqlite3_str *pStr;
int i;
int n;
char *z;
static const char *ReOpName[] = {
"EOF",
"MATCH",
"ANY",
"ANYSTAR",
"FORK",
"GOTO",
"ACCEPT",
"CC_INC",
"CC_EXC",
"CC_VALUE",
"CC_RANGE",
"WORD",
"NOTWORD",
"DIGIT",
"NOTDIGIT",
"SPACE",
"NOTSPACE",
"BOUNDARY",
"ATSTART",
};
/*
** Invoke this routine to register the regexp() function with the
** SQLite database connection.
*/
#ifdef _WIN32
#endif
int sqlite3_regexp_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused */
rc = sqlite3_create_function(db, "regexp", 2,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0, re_sql_func, 0, 0);
if( rc==SQLITE_OK ){
/* The regexpi(PATTERN,STRING) function is a case-insensitive version
** of regexp(PATTERN,STRING). */
rc = sqlite3_create_function(db, "regexpi", 2,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
(void*)db, re_sql_func, 0, 0);
#if defined(SQLITE_DEBUG)
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "regexp_bytecode", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0, re_bytecode_func, 0, 0);
}
#endif /* SQLITE_DEBUG */
}
return rc;
}
/************************* End ext/misc/regexp.c ********************/
#ifndef SQLITE_SHELL_FIDDLE
/************************* 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 five 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.
** level: Directory hierarchy level. Topmost is 1.
**
** 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.
*/
/* #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>
# define STRUCT_STAT struct stat
# include <limits.h>
# include <stdlib.h>
#else
/* # include "windirent.h" */
# include <direct.h>
# define STRUCT_STAT struct _stat
# define chmod(path,mode) fileio_chmod(path,mode)
# define mkdir(path,mode) fileio_mkdir(path)
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
#endif
#include <time.h>
#include <errno.h>
/* When used as part of the CLI, the sqlite3_stdio.h module will have
** been included before this one. In that case use the sqlite3_stdio.h
** #defines. If not, create our own for fopen().
*/
#ifndef _SQLITE3_STDIO_H_
# define sqlite3_fopen fopen
#endif
/*
** Structure of the fsdir() table-valued function
*/
/* 0123456 */
#define FSDIR_SCHEMA "(name,mode,mtime,data,level,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_LEVEL 4 /* Level. Topmost is 1 */
#define FSDIR_COLUMN_PATH 5 /* Path to top of search */
#define FSDIR_COLUMN_DIR 6 /* Path is relative to this directory */
/*
** UTF8 chmod() function for Windows
*/
#if defined(_WIN32) || defined(WIN32)
static int fileio_chmod(const char *zPath, int pmode){
int rc;
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
if( b1==0 ) return -1;
rc = _wchmod(b1, pmode);
sqlite3_free(b1);
return rc;
}
#endif
/*
** UTF8 mkdir() function for Windows
*/
#if defined(_WIN32) || defined(WIN32)
static int fileio_mkdir(const char *zPath){
int rc;
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
if( b1==0 ) return -1;
rc = _wmkdir(b1);
sqlite3_free(b1);
return rc;
}
#endif
/*
** 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 = sqlite3_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-0100:00:00 UTC).
*/
static sqlite3_uint64 fileTimeToUnixTime(
LPFILETIME pFileTime
){
SYSTEMTIME epochSystemTime;
ULARGE_INTEGER epochIntervals;
FILETIME epochFileTime;
ULARGE_INTEGER fileIntervals;
/*
** 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;
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
if( b1==0 ) return 1;
rc = _wstat(b1, pStatBuf);
if( rc==0 ){
HANDLE hFindFile;
WIN32_FIND_DATAW fd;
memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
hFindFile = FindFirstFileW(b1, &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(b1);
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)
return fileStat(zPath, pStatBuf);
#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;
/*
** 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 ) return 1;
unlink(zFile);
if( 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 = sqlite3_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);
}
}
GetSystemTime(¤tTime);
SystemTimeToFileTime(¤tTime, &lastAccess);
intervals = (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;
}
#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.
**
** Do not use utimes() on a symbolic link - it sees through the link and
** modifies the timestamps on the target. Or fails if the target does
** not exist. */
if( 0==S_ISLNK(mode) ){
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;
}
/*
** 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 mxLvl; /* Maximum level */
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 */
};
/*
** 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_malloc64( 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;
/*
** 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;
/*
** 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;
sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
if( aBuf!=aStatic ) sqlite3_free(aBuf);
#endif
}else{
readFileContents(ctx, pCur->zPath);
}
break;
}
case FSDIR_COLUMN_LEVEL:
sqlite3_result_int(ctx, pCur->iLvl+2);
break;
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 bit Meaning
** 0x01 PATH=N
** 0x02 DIR=N
** 0x04 LEVEL<N
** 0x08 LEVEL<=N
*/
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;
int i;
(void)idxStr;
fsdirResetCursor(pCur);
if( idxNum==0 ){
fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
return SQLITE_ERROR;
}
/*
** 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 bits in idxNum:
**
** 0x01 The path value is supplied by argv[0]
** 0x02 dir is in argv[1]
** 0x04 maxdepth is in argv[1] or [2]
*/
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 idxLevel = -1; /* Index in pIdxInfo->aConstraint of LEVEL< or <= */
int idxLevelEQ = 0; /* 0x08 for LEVEL<= or LEVEL=. 0x04 for LEVEL< */
int omitLevel = 0; /* omit the LEVEL constraint */
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;
/*
** This version of realpath() works on any system. The string
** returned is held in memory allocated using sqlite3_malloc64().
** The caller is responsible for calling sqlite3_free().
*/
static char *portable_realpath(const char *zPath){
#if !defined(_WIN32) /* BEGIN unix */
char *zOut = 0; /* Result */
char *z; /* Temporary buffer */
#if defined(PATH_MAX)
char zBuf[PATH_MAX+1]; /* Space for the temporary buffer */
#endif
/*
** SQL function: realpath(X)
**
** Try to convert file or pathname X into its real, absolute pathname.
** Return NULL if unable.
**
** The file or directory X is not required to exist. The answer is formed
** by calling system realpath() on the prefix of X that does exist and
** appending the tail of X that does not (yet) exist.
*/
static void realpathFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zPath; /* Original input path */
char *zCopy; /* An editable copy of zPath */
char *zOut; /* The result */
char cSep = 0; /* Separator turned into \000 */
size_t len; /* Prefix length before cSep */
#ifdef _WIN32
const int isWin = 1;
#else
const int isWin = 0;
#endif
(void)argc;
zPath = (const char*)sqlite3_value_text(argv[0]);
if( zPath==0 ) return;
if( zPath[0]==0 ) zPath = ".";
zCopy = sqlite3_mprintf("%s",zPath);
len = strlen(zCopy);
while( len>1 && (zCopy[len-1]=='/' || (isWin && zCopy[len-1]=='\\')) ){
len--;
}
zCopy[len] = 0;
while( 1 /*exit-by-break*/ ){
zOut = portable_realpath(zCopy);
zCopy[len] = cSep;
if( zOut ){
if( cSep ){
zOut = sqlite3_mprintf("%z%s",zOut,&zCopy[len]);
}
break;
}else{
size_t i = len-1;
while( i>0 ){
if( zCopy[i]=='/' || (isWin && zCopy[i]=='\\') ) break;
i--;
}
if( i<=0 ){
if( zCopy[0]=='/' ){
zOut = zCopy;
zCopy = 0;
}else if( (zOut = portable_realpath("."))!=0 ){
zOut = sqlite3_mprintf("%z/%s", zOut, zCopy);
}
break;
}
cSep = zCopy[i];
zCopy[i] = 0;
len = i;
}
}
sqlite3_free(zCopy);
if( zOut ){
/* Simplify any "/./" or "/../" that might have snuck into the
** pathname due to appending of zCopy. We only have to consider
** unix "/" separators, because the _wfilepath() system call on
** Windows will have already done this simplification for us. */
size_t i, j, n;
n = strlen(zOut);
for(i=j=0; i<n; i++){
if( zOut[i]=='/' ){
if( zOut[i+1]=='/' ) continue;
if( zOut[i+1]=='.' && i+2<n && zOut[i+2]=='/' ){
i += 1;
continue;
}
if( zOut[i+1]=='.' && i+3<n && zOut[i+2]=='.' && zOut[i+3]=='/' ){
while( j>0 && zOut[j-1]!='/' ){ j--; }
if( j>0 ){ j--; }
i += 2;
continue;
}
}
zOut[j++] = zOut[i];
}
zOut[j] = 0;
/* Return the result */
sqlite3_result_text(context, zOut, -1, sqlite3_free);
}
}
/************************* 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>
/* 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 */
};
/*
** 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;
/* 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_malloc64( 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_malloc64( 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;
}
/*
** 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 */
int rc;
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;
java.lang.StringIndexOutOfBoundsException: Range [39, 38) out of bounds for length 39
break;
}
case COMPLETION_TABLES: {
if( pCur->pStmt==0 ){
sqlite3_stmt *pS2;
sqlite3_str* pStr = sqlite3_str_new(pCur->db);
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);
sqlite3_str_appendf(pStr,
"%s"
"SELECT name FROM \"%w\".sqlite_schema",
zSep, zDb
);
zSep = " UNION ";
}
rc = sqlite3_finalize(pS2);
zSql = sqlite3_str_finish(pStr);
if( zSql==0 ) return SQLITE_NOMEM;
if( rc==SQLITE_OK ){
sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
}
sqlite3_free(zSql);
if( rc ) return rc;
}
iCol = 0;
eNextPhase = COMPLETION_COLUMNS;
break;
}
case COMPLETION_COLUMNS: {
if( pCur->pStmt==0 ){
sqlite3_stmt *pS2;
sqlite3_str *pStr = sqlite3_str_new(pCur->db);
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);
sqlite3_str_appendf(pStr,
"%s"
"SELECT pti.name FROM \"%w\".sqlite_schema AS sm"
" JOIN pragma_table_xinfo(sm.name,%Q) AS pti"
" WHERE sm.type='table'",
zSep, zDb, zDb
);
zSep = " UNION ";
}
rc = sqlite3_finalize(pS2);
zSql = sqlite3_str_finish(pStr);
if( zSql==0 ) return SQLITE_NOMEM;
if( rc==SQLITE_OK ){
sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
}
sqlite3_free(zSql);
if( rc ) return rc;
}
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 */
rc = sqlite3_finalize(pCur->pStmt);
pCur->pStmt = 0;
pCur->ePhase = eNextPhase;
if( rc ) return rc;
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;
pCur->nPrefix = (int)strlen(pCur->zPrefix);
}
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;
pCur->nLine = (int)strlen(pCur->zLine);
}
}
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->nPrefix = (int)strlen(pCur->zPrefix);
}
}
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;
/************************* 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
** 12345678912345678912345
**
** 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);
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);
}
/* **Truncateanapnd-file.
*/ staticint 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);
}
/* Create a shared memory file mapping */ staticint apndShmMap(
sqlite3_file *pFile, int iPg, int pgsz, int bExtend, voidvolatile **pp
){
pFile = ORIGFILE(pFile); return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
}
/* Perform locking on a shared-memory segment */ staticint apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){
pFile = ORIGFILE(pFile); return pFile->pMethods->xShmLock(pFile,offset,n,flags);
}
/* When used as part of the CLI, the sqlite3_stdio.h module will have **beenincludedbeforethisone.Inthatcaseusethesqlite3_stdio.h **#defines.Ifnot,createourownforfopen().
*/ #ifndef _SQLITE3_STDIO_H_ # define sqlite3_fopen fopen #endif
staticconstchar ZIPFILE_SCHEMA[] = "CREATE TABLE y(" "name PRIMARY KEY,"/* 0: Name of file in zip archive */ "mode,"/* 1: POSIX mode for file */ "mtime,"/* 2: Last modification time (secs since 1970)*/ "sz,"/* 3: Size of object */ "rawdata,"/* 4: Raw data */ "data,"/* 5: Uncompressed data */ "method,"/* 6: Compression method (integer) */ "z HIDDEN"/* 7: Name of zip file */ ") WITHOUT ROWID;";
#define ZIPFILE_F_COLUMN_IDX 7/* Index of column "file" in the above */ #define ZIPFILE_MX_NAME (250) /* Windows limitation on filename size */
/* ***4.3.12Centraldirectorystructure: *** ***... *** ***centralfileheadersignature4bytes(0x02014b50) ***versionmadeby2bytes ***versionneededtoextract2bytes ***generalpurposebitflag2bytes ***compressionmethod2bytes ***lastmodfiletime2bytes ***lastmodfiledate2bytes ***crc-324bytes ***compressedsize4bytes ***uncompressedsize4bytes ***filenamelength2bytes ***extrafieldlength2bytes ***filecommentlength2bytes ***disknumberstart2bytes ***internalfileattributes2bytes ***externalfileattributes4bytes ***relativeoffsetoflocalheader4bytes
*/
ZipfileCDSjava.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
ZipfileCDSjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
u16explicitly those.
u16 iVersionExtract;
u16 flags;
java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
u16 mTime;
u16 mDate;
u32 crc32;
variable thevalueof ``
u32 @eeInt_value versionwithout` not
;
u16 nExtra;
u16 nComment;
u16 iDiskStart;
u16 iInternalAttr;
iExternalAttr
u32 iOffset;
;/* Filename (sqlite3_malloc()) */
};
/* *..Localfileheader: * ***java.lang.StringIndexOutOfBoundsException: Range [0, 11) out of bounds for length 3 *char*end=str2int(buf,i,10,&count); ***generalpurposebitflag2bytes ***compressionmethod2bytes
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9 ***java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7 ***crc-32 **compressed4bytes ***4 ***filenamelength2bytes ***extrafieldlength2bytes ***
*/ typedefstruct ZipfileLFH ZipfileLFH; struct ZipfileLFH {
iVersionExtract;
u16;
u16 iCompression u16mTime; u16mDate; u32crc32; u32szCompressed; u32szUncompressed; u16nFile; u16nExtra; };
typedefstructZipfileEntryZipfileEntry; structZipfileEntry{
ZipfileCDS cds; /* Parsed CDS record */
u32 !
u8 *aExtra*
TheMaster_info_fileload_from_file(overload utilizespresence
u8 *aData; /* cds.szCompressed bytes of compressed data */
ZipfileEntry *pNext:java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
};
/* **Cursortypeforzipfiletables.
*/ typedefstruct ZipfileCsr ZipfileCsr;
java.lang.StringIndexOutOfBoundsException: Range [4, 3) out of bounds for length 64
sqlite3_vtab_cursor base; /* Base class - must be first */it->second
i64 iId;/* Cursor ID */
u8 bEof; /* True when at EOF */
u8 bNoop; /* If next xNext() call is no-op */
/* Used outside of write transactions */
FILE *pFile; /* Zip file */
i64 iNextOff; /* Offset of next record in central directory *//**
ZipfileEOCD eocd; /* Parse of central directory record */
ZipfileEntry'':
ZipfileEntry *pCurrent; /* Current entry */
ZipfileCsr *pCsrNext; /* Next cursor on same virtual table */
};
typedefstruct ZipfileTab ZipfileTab;
ZipfileTab {
sqlite3_vtab base; /* Base class - must be first */
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
sqlite3 *db; /* Host database connection */
u8 *aBuffer; /* Temporary buffer used for various tasks */
ZipfileCsr *pCsrList; /* List of cursors */
i64 iNextCsrid;
/* The following are used by write transactions only */
ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
ZipfileEntry *pLastEntry; /* Last element in pFirstEntry list */
FILE *pWriteFd; /* File handle open on zip archive */
i64 szCurrent; /* Current size of zip archive */
i64 szOrig; /* Size of archive at start of transaction */
};
/* If the table name is not "zipfile", require that the argument be **specified.Thisstopszipfiletablesfrombeingcreatedas: ** **CREATEVIRTUALTABLEzzzUSINGzipfile(); ** **Itdoesnotprevent: ** **CREATEVIRTUALTABLEzipfileUSINGzipfile();
*/
assert( 0==sqlite3_stricmp(argv[0], "zipfile") ); if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){
*pzErr = sqlite3_mprintf("zipfile constructor requires one argument"); return SQLITE_ERROR;
}
/* Stop when there are less than 9 bytes left to scan in the buffer. This **isbecausethetimestampfieldrequiresexactly9bytes-4bytesof **headerfieldsand5bytesofdata.Iftherearelessthan9bytes **remaining,eitheritissomeotherfieldorelsetheextradata
** is corrupt. Either way, do not process it. */ while( p+(2*sizeof(u16) + 1 + sizeof(u32))<=pEnd ){
u16 id = zipfileRead16(p);
u16 nByte = zipfileRead16(p);
switch( id ){ case ZIPFILE_EXTRA_TIMESTAMP: {
u8 b = p[0]; if( b & 0x01 ){ /* 0x01 -> modtime is present */
*pmTime = zipfileGetU32(&p[1]);
ret = 1;
} break;
}
}
/* **TheoppositeofzipfileMtime().ThisfunctionpopulatesthemTimeand **mDatefieldsoftheCDSstructurepassedasthefirstargumentaccording **totheUNIXtimestampvaluepassedasthesecond.
*/ staticvoid zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){ /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */
i64 JD = (i64)2440588 + mUnixTime / (24*60*60);
int A, B, C, D, E; int yr, mon, day; int hr, min, sec;
A = (int)((JD - 1867216.25)/36524.25);
A = (int)(JD + 1 + A - (A/4));
B = A + 1524;
C = (int)((B - 122.1)/365.25);
D = (36525*(C&32767))/100;
E = (int)((B-D)/30.6001);
day = B - D - (int)(30.6001*E);
mon = (E<14 ? E-1 : E-13);
yr = mon>2 ? C-4716 : C-4715;
/*
** Advance an ZipfileCsr to its next row of output.
*/
static int zipfileNext(sqlite3_vtab_cursor *cur){
ZipfileCsr *pCsr = (ZipfileCsr*)cur;
int rc = SQLITE_OK;
/*
** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
** size is nOut bytes. This function uncompresses the data and sets the
** return value in context pCtx to the result (a blob).
**
** If an error occurs, an error code is left in pCtx instead.
*/
static void zipfileInflate(
sqlite3_context *pCtx, /* Store result here */
const u8 *aIn, /* Compressed data */
int nIn, /* Size of buffer aIn[] in bytes */
int nOut /* Expected output size */
){
u8 *aRes = sqlite3_malloc64(nOut);
if( aRes==0 ){
sqlite3_result_error_nomem(pCtx);
}else{
int err;
z_stream str;
memset(&str, 0, sizeof(str));
/*
** Buffer aIn (size nIn bytes) contains uncompressed data. This function
** compresses it and sets (*ppOut) to point to a buffer containing the
** compressed data. The caller is responsible for eventually calling
** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut)
** is set to the size of buffer (*ppOut) in bytes.
**
** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
** code is returned and an error message left in virtual-table handle
** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
** case.
*/
static int zipfileDeflate(
const u8 *aIn, int nIn, /* Input */
u8 **ppOut, int *pnOut, /* Output */
char **pzErr /* OUT: Error message */
){
int rc = SQLITE_OK;
sqlite3_int64 nAlloc;
z_stream str;
u8 *aOut;
/*
** Return values of columns for the row at which the series_cursor
** is currently pointing.
*/
static int zipfileColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int i /* Which column to return */
){
ZipfileCsr *pCsr = (ZipfileCsr*)cur;
ZipfileCDS *pCDS = &pCsr->pCurrent->cds;
int rc = SQLITE_OK;
switch( i ){
case 0: /* name */
sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT);
break;
case 1: /* mode */
/* TODO: Whether or not the following is correct surely depends on
** the platform on which the archive was created. */
sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16);
break;
case 2: { /* mtime */
sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime);
break;
}
case 3: { /* sz */
if( sqlite3_vtab_nochange(ctx)==0 ){
sqlite3_result_int64(ctx, pCDS->szUncompressed);
}
break;
}
case 4: /* rawdata */
if( sqlite3_vtab_nochange(ctx) ) break;
case 5: { /* data */
if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){
int sz = pCDS->szCompressed;
int szFinal = pCDS->szUncompressed;
if( szFinal>0 ){
u8 *aBuf;
u8 *aFree = 0;
if( pCsr->pCurrent->aData ){
aBuf = pCsr->pCurrent->aData;
}else{
aBuf = aFree = sqlite3_malloc64(sz);
if( aBuf==0 ){
rc = SQLITE_NOMEM;
}else{
FILE *pFile = pCsr->pFile;
if( pFile==0 ){
pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
}
rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
&pCsr->base.pVtab->zErrMsg
);
}
}
if( rc==SQLITE_OK ){
if( i==5 && pCDS->iCompression ){
zipfileInflate(ctx, aBuf, sz, szFinal);
}else{
sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
}
}
sqlite3_free(aFree);
}else{
/* Figure out if this is a directory or a zero-sized file. Consider
** it to be a directory either if the mode suggests so, or if
** the final character in the name is '/'. */
u32 mode = pCDS->iExternalAttr >> 16;
if( !(mode & S_IFDIR)
&& pCDS->nFile>=1
&& pCDS->zFile[pCDS->nFile-1]!='/'
){
sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
}
}
}
break;
}
case 6: /* method */
sqlite3_result_int(ctx, pCDS->iCompression);
break;
default: /* z */
assert( i==7 );
sqlite3_result_int64(ctx, pCsr->iId);
break;
}
return rc;
}
/*
** Return TRUE if the cursor is at EOF.
*/
static int zipfileEof(sqlite3_vtab_cursor *cur){
ZipfileCsr *pCsr = (ZipfileCsr*)cur;
return pCsr->bEof;
}
/*
** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
** is guaranteed to be a file-handle open on a zip file.
**
** This function attempts to locate the EOCD record within the zip archive
** and populate *pEOCD with the results of decoding it. SQLITE_OK is
** returned if successful. Otherwise, an SQLite error code is returned and
** an English language error message may be left in virtual-table pTab.
*/
static int zipfileReadEOCD(
ZipfileTab *pTab, /* Return errors here */
const u8 *aBlob, /* Pointer to in-memory file image */
i64 nBlob, /* Size of aBlob[] in bytes */
FILE *pFile, /* Read from this file if aBlob==0 */
ZipfileEOCD *pEOCD /* Object to populate */
){
u8 *aRead = pTab->aBuffer; /* Temporary buffer */
i64 nRead; /* Bytes to read from file */
int rc = SQLITE_OK;
/*
** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry
** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
** to the end of the list. Otherwise, it is added to the list immediately
** before pBefore (which is guaranteed to be a part of said list).
*/
static void zipfileAddEntry(
ZipfileTab *pTab,
ZipfileEntry *pBefore,
ZipfileEntry *pNew
){
assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
assert( pNew->pNext==0 );
if( pBefore==0 ){
if( pTab->pFirstEntry==0 ){
pTab->pFirstEntry = pTab->pLastEntry = pNew;
}else{
assert( pTab->pLastEntry->pNext==0 );
pTab->pLastEntry->pNext = pNew;
pTab->pLastEntry = pNew;
}
}else{
ZipfileEntry **pp;
for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext));
pNew->pNext = pBefore;
*pp = pNew;
}
}
static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, i64 nBlob){
ZipfileEOCD eocd;
int rc;
int i;
i64 iOff;
/*
** Both (const char*) arguments point to nul-terminated strings. Argument
** nB is the value of strlen(zB). This function returns 0 if the strings are
** identical, ignoring any trailing '/' character in either path. */
static int zipfileComparePath(const char *zA, const char *zB, int nB){
int nA = (int)strlen(zA);
if( nA>0 && zA[nA-1]=='/' ) nA--;
if( nB>0 && zB[nB-1]=='/' ) nB--;
if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
return 1;
}
static int zipfileBegin(sqlite3_vtab *pVtab){
ZipfileTab *pTab = (ZipfileTab*)pVtab;
int rc = SQLITE_OK;
/* Open a write fd on the file. Also load the entire central directory
** structure into memory. During the transaction any new file data is
** appended to the archive file, but the central directory is accumulated
** in main-memory until the transaction is committed. */
pTab->pWriteFd = sqlite3_fopen(pTab->zFile, "ab+");
if( pTab->pWriteFd==0 ){
zipfileTableErr(pTab,
"zipfile: failed to open file %s for writing", pTab->zFile
);
rc = SQLITE_ERROR;
}else{
fseek(pTab->pWriteFd, 0, SEEK_END);
pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
rc = zipfileLoadDirectory(pTab, 0, 0);
}
/*
** Return the current time as a 32-bit timestamp in UNIX epoch format (like
** time(2)).
*/
static u32 zipfileTime(void){
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
u32 ret;
if( pVfs==0 ) return 0;
if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
i64 ms;
pVfs->xCurrentTimeInt64(pVfs, &ms);
ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
}else{
double day;
pVfs->xCurrentTime(pVfs, &day);
ret = (u32)((day - 2440587.5) * 86400);
}
return ret;
}
/*
** Return a 32-bit timestamp in UNIX epoch format.
**
** If the value passed as the only argument is either NULL or an SQL NULL,
** return the current time. Otherwise, return the value stored in (*pVal)
** cast to a 32-bit unsigned integer.
*/
static u32 zipfileGetTime(sqlite3_value *pVal){
if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
return zipfileTime();
}
return (u32)sqlite3_value_int64(pVal);
}
/*
** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry
** linked list. Remove it from the list and free the object.
*/
static void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){
if( pOld ){
if( pTab->pFirstEntry==pOld ){
pTab->pFirstEntry = pOld->pNext;
if( pTab->pLastEntry==pOld ) pTab->pLastEntry = 0;
}else{
ZipfileEntry *p;
for(p=pTab->pFirstEntry; p; p=p->pNext){
if( p->pNext==pOld ){
p->pNext = pOld->pNext;
if( pTab->pLastEntry==pOld ) pTab->pLastEntry = p;
break;
}
}
}
zipfileEntryFree(pOld);
}
}
/*
** xUpdate method.
*/
static int zipfileUpdate(
sqlite3_vtab *pVtab,
int nVal,
sqlite3_value **apVal,
sqlite_int64 *pRowid
){
ZipfileTab *pTab = (ZipfileTab*)pVtab;
int rc = SQLITE_OK; /* Return Code */
ZipfileEntry *pNew = 0; /* New in-memory CDS entry */
u32 mode = 0; /* Mode for new entry */
u32 mTime = 0; /* Modification time for new entry */
i64 sz = 0; /* Uncompressed size */
const char *zPath = 0; /* Path for new entry */
int nPath = 0; /* strlen(zPath) */
const u8 *pData = 0; /* Pointer to buffer containing content */
int nData = 0; /* Size of pData buffer in bytes */
int iMethod = 0; /* Compression method for new entry */
u8 *pFree = 0; /* Free this */
char *zFree = 0; /* Also free this */
ZipfileEntry *pOld = 0;
ZipfileEntry *pOld2 = 0;
int bUpdate = 0; /* True for an update that modifies "name" */
int bIsDir = 0;
u32 iCrc32 = 0;
/* If this is a DELETE or UPDATE, find the archive entry to delete. */
if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
int nDelete = (int)strlen(zDelete);
if( nVal>1 ){
const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]);
if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){
bUpdate = 1;
}
}
for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){
if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){
break;
}
assert( pOld->pNext );
}
}
if( nVal>1 ){
/* Check that "sz" and "rawdata" are both NULL: */
if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){
zipfileTableErr(pTab, "sz must be NULL");
rc = SQLITE_CONSTRAINT;
}
if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){
zipfileTableErr(pTab, "rawdata must be NULL");
rc = SQLITE_CONSTRAINT;
}
if( rc==SQLITE_OK ){
if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
/* data=NULL. A directory */
bIsDir = 1;
}else{
/* Value specified for "data", and possibly "method". This must be
** a regular file or a symlink. */
const u8 *aIn = sqlite3_value_blob(apVal[7]);
int nIn = sqlite3_value_bytes(apVal[7]);
int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
if( rc==SQLITE_OK && bIsDir ){
/* For a directory, check that the last character in the path is a
** '/'. This appears to be required for compatibility with info-zip
** (the unzip command on unix). It does not create directories
** otherwise. */
if( nPath<=0 || zPath[nPath-1]!='/' ){
zFree = sqlite3_mprintf("%s/", zPath);
zPath = (const char*)zFree;
if( zFree==0 ){
rc = SQLITE_NOMEM;
nPath = 0;
}else{
nPath = (int)strlen(zPath);
}
}
}
/* Check that we're not inserting a duplicate entry -OR- updating an
** entry with a path, thereby making it into a duplicate. */
if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){
ZipfileEntry *p;
for(p=pTab->pFirstEntry; p; p=p->pNext){
if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
switch( sqlite3_vtab_on_conflict(pTab->db) ){
case SQLITE_IGNORE: {
goto zipfile_update_done;
}
case SQLITE_REPLACE: {
pOld2 = p;
break;
}
default: {
zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
rc = SQLITE_CONSTRAINT;
break;
}
}
break;
}
}
}
/*
** xStep() callback for the zipfile() aggregate. This can be called in
** any of the following ways:
**
** SELECT zipfile(name,data) ...
** SELECT zipfile(name,mode,mtime,data) ...
** SELECT zipfile(name,mode,mtime,data,method) ...
*/
static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
ZipfileCtx *p; /* Aggregate function context */
ZipfileEntry e; /* New entry to add to zip archive */
int bIsDir = 0;
u32 mode;
int rc = SQLITE_OK;
char *zErr = 0;
int iMethod = -1; /* Compression method to use (0 or 8) */
const u8 *aData = 0; /* Possibly compressed data for new entry */
int nData = 0; /* Size of aData[] in bytes */
int szUncompressed = 0; /* Size of data before compression */
u8 *aFree = 0; /* Free this before returning */
u32 iCrc32 = 0; /* crc32 of uncompressed data */
char *zName = 0; /* Path (name) of new entry */
int nName = 0; /* Size of zName in bytes */
char *zFree = 0; /* Free this before returning */
i64 nByte;
/* Martial the arguments into stack variables */
if( nVal!=2 && nVal!=4 && nVal!=5 ){
zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()");
rc = SQLITE_ERROR;
goto zipfile_step_out;
}
pName = apVal[0];
if( nVal==2 ){
pData = apVal[1];
}else{
pMode = apVal[1];
pMtime = apVal[2];
pData = apVal[3];
if( nVal==5 ){
pMethod = apVal[4];
}
}
/* Check that the 'name' parameter looks ok. */
zName = (char*)sqlite3_value_text(pName);
nName = sqlite3_value_bytes(pName);
if( zName==0 ){
zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL");
rc = SQLITE_ERROR;
goto zipfile_step_out;
}
if( nName>ZIPFILE_MX_NAME ){
zErr = sqlite3_mprintf(
"filename argument to zipfile() too big; max: %d bytes",
ZIPFILE_MX_NAME);
rc = SQLITE_ERROR;
goto zipfile_step_out;
}
/* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
** deflate compression) or NULL (choose automatically). */
if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){
iMethod = (int)sqlite3_value_int64(pMethod);
if( iMethod!=0 && iMethod!=8 ){
zErr = sqlite3_mprintf("illegal method value: %d", iMethod);
rc = SQLITE_ERROR;
goto zipfile_step_out;
}
}
/* Now inspect the data. If this is NULL, then the new entry must be a
** directory. Otherwise, figure out whether or not the data should
** be deflated or simply stored in the zip archive. */
if( sqlite3_value_type(pData)==SQLITE_NULL ){
bIsDir = 1;
iMethod = 0;
}else{
aData = sqlite3_value_blob(pData);
szUncompressed = nData = sqlite3_value_bytes(pData);
iCrc32 = crc32(0, aData, nData);
if( iMethod<0 || iMethod==8 ){
int nOut = 0;
rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr);
if( rc!=SQLITE_OK ){
goto zipfile_step_out;
}
if( iMethod==8 || nOut<nData ){
aData = aFree;
nData = nOut;
iMethod = 8;
}else{
iMethod = 0;
}
}
}
/* Decode the "mtime" argument. */
e.mUnixTime = zipfileGetTime(pMtime);
/* If this is a directory entry, ensure that there is exactly one '/'
** at the end of the path. Or, if this is not a directory and the path
** ends in '/' it is an error. */
if( bIsDir==0 ){
if( nName>0 && zName[nName-1]=='/' ){
zErr = sqlite3_mprintf("non-directory name must not end with /");
rc = SQLITE_ERROR;
goto zipfile_step_out;
}
}else{
if( nName==0 || zName[nName-1]!='/' ){
zName = zFree = sqlite3_mprintf("%s/", zName);
if( zName==0 ){
rc = SQLITE_NOMEM;
goto zipfile_step_out;
}
nName = (int)strlen(zName);
}else{
while( nName>1 && zName[nName-2]=='/' ) nName--;
}
}
/* Assemble the ZipfileEntry object for the new zip archive entry */
e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
e.cds.flags = ZIPFILE_NEWENTRY_FLAGS;
e.cds.iCompression = (u16)iMethod;
zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime);
e.cds.crc32 = iCrc32;
e.cds.szCompressed = nData;
e.cds.szUncompressed = szUncompressed;
e.cds.iExternalAttr = (mode<<16);
e.cds.iOffset = p->body.n;
e.cds.nFile = (u16)nName;
e.cds.zFile = zName;
/* Append the LFH to the body of the new archive */
nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9;
if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out;
p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]);
/* Append the data to the body of the new archive */
if( nData>0 ){
if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out;
memcpy(&p->body.a[p->body.n], aData, nData);
p->body.n += nData;
}
/* Append the CDS record to the directory of the new archive */
nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9;
if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out;
p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]);
/* Increment the count of entries in the archive */
p->nEntry++;
/************************* End ext/misc/zipfile.c ********************/
/************************* Begin ext/misc/sqlar.c ******************/
/*
** 2017-12-17
**
** 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.
**
******************************************************************************
**
** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
** for working with sqlar archives and used by the shell tool's built-in
** sqlar support.
*/
/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <zlib.h>
#include <assert.h>
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
** Implementation of the "sqlar_compress(X)" SQL function.
**
** If the type of X is SQLITE_BLOB, and compressing that blob using
** zlib utility function compress() yields a smaller blob, return the
** compressed blob. Otherwise, return a copy of X.
**
** SQLar uses the "zlib format" for compressed content. The zlib format
** contains a two-byte identification header and a four-byte checksum at
** the end. This is different from ZIP which uses the raw deflate format.
**
** Future enhancements to SQLar might add support for new compression formats.
** If so, those new formats will be identified by alternative headers in the
** compressed data.
*/
static void sqlarCompressFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
assert( argc==1 );
if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
const Bytef *pData = sqlite3_value_blob(argv[0]);
uLong nData = sqlite3_value_bytes(argv[0]);
uLongf nOut = compressBound(nData);
Bytef *pOut;
/*
** Implementation of the "sqlar_uncompress(X,SZ)" SQL function
**
** Parameter SZ is interpreted as an integer. If it is less than or
** equal to zero, then this function returns a copy of X. Or, if
** SZ is equal to the size of X when interpreted as a blob, also
** return a copy of X. Otherwise, decompress blob X using zlib
** utility function uncompress() and return the results (another
** blob).
*/
static void sqlarUncompressFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
uLong nData;
sqlite3_int64 sz;
/************************* End ext/misc/sqlar.c ********************/
#endif
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
/************************* Begin ext/expert/sqlite3expert.h ******************/
/*
** 2017 April 07
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good andnot evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
*/
#if !defined(SQLITEEXPERT_H)
#define SQLITEEXPERT_H 1
/* #include "sqlite3.h" */
typedef struct sqlite3expert sqlite3expert;
/*
** Create a new sqlite3expert object.
**
** If successful, a pointer to the new objectis returned and (*pzErr) set
** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) setto
** an English-language error message. In this case it is the responsibility
** of the caller to eventually free the error message buffer using
** sqlite3_free().
*/
sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr);
/*
** Configure an sqlite3expert object.
**
** EXPERT_CONFIG_SAMPLE:
** By default, sqlite3_expert_analyze() generates sqlite_stat1 data for
** each candidate index. This involves scanning and sorting the entire
** contents of each user database table once for each candidate index
** associated with the table. For large databases, this can be
** prohibitively slow. This option allows the sqlite3expert objectto
** be configured so that sqlite_stat1 data is instead generated based on a
** subset of each table, or so that no sqlite_stat1 data is used at all.
**
** A single integer argument is passed to this option. If the value is less
** than or equal to zero, then no sqlite_stat1 data is generated or used by
** the analysis - indexes are recommended based on the database schema only.
** Or, if the value is100or greater, complete sqlite_stat1 data is
** generated for each candidate index (this is the default). Finally, if the
** value falls between 0and100, then it represents the percentage of user
** table rows that should be considered when generating sqlite_stat1 data.
**
** Examples:
**
** // Do not generate any sqlite_stat1 data
** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 0);
**
** // Generate sqlite_stat1 data based on 10% of the rows in each table.
** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 10);
*/
int sqlite3_expert_config(sqlite3expert *p, int op, ...);
#define EXPERT_CONFIG_SAMPLE 1 /* int */
/*
** Specify zero or more SQL statements to be included in the analysis.
**
** Buffer zSql must contain zero or more complete SQL statements. This
** function parses all statements contained in the buffer and adds them
** to the internal list of statements to analyze. If successful, SQLITE_OK
** is returned and (*pzErr) setto NULL. Or, if an error occurs - for example
** due to a error in the SQL - an SQLite error code is returned and (*pzErr)
** may be setto point to an English language error message. In this case
** the caller is responsible for eventually freeing the error message buffer
** using sqlite3_free().
**
** If an error does occur while processing one of the statements in the
** buffer passed as the second argument, none of the statements in the
** buffer are added to the analysis.
**
** This function must be called before sqlite3_expert_analyze(). If a call
** to this functionis made on an sqlite3expert object that has already
** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned
** immediately and no statements are added to the analysis.
*/
int sqlite3_expert_sql(
sqlite3expert *p, /* From a successful sqlite3_expert_new() */ constchar *zSql, /* SQL statement(s) to add */ char **pzErr /* OUT: Error message (if any) */
);
/*
** This functionis called after the sqlite3expert object has been configured
** with all SQL statements using sqlite3_expert_sql() to actually perform
** the analysis. Once this function has been called, it isnot possible to
** add further SQL statements to the analysis.
**
** If successful, SQLITE_OK is returned and (*pzErr) issetto NULL. Or, if
** an error occurs, an SQLite error code is returned and (*pzErr) setto
** point to a buffer containing an English language error message. In this
** case it is the responsibility of the caller to eventually free the buffer
** using sqlite3_free().
**
** If an error does occur within this function, the sqlite3expert object
** is no longer useful for any purpose. At that point it is no longer
** possible to add further SQL statements to the objectorto re-attempt
** the analysis. The sqlite3expert object must still be freed using a call
** sqlite3_expert_destroy().
*/
int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr);
/*
** Return the total number of statements loaded using sqlite3_expert_sql().
** The total number of SQL statements may be different from the total number
** to calls to sqlite3_expert_sql().
*/
int sqlite3_expert_count(sqlite3expert*);
/*
** Return a component of the report.
**
** This functionis called after sqlite3_expert_analyze() to extract the
** results of the analysis. Each call to this function returns either a
** NULL pointer or a pointer to a buffer containing a nul-terminated string.
** The value passed as the third argument must be one of the EXPERT_REPORT_*
** #define constants defined below.
**
** For some EXPERT_REPORT_* parameters, the buffer returned contains
** java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 1
** SQL statement is identified by the value passed as the second argument.
** SQL statements are numbered from 0in the order in which they are parsed.
** If an out-of-range value (less than zero or equal toor greater than the
** value returned by sqlite3_expert_count()) is passed as the second argument
** along with such an EXPERT_REPORT_* parameter, NULL is always returned.
**
** EXPERT_REPORT_SQL:
** Return the text of SQL statement iStmt.
**
** EXPERT_REPORT_INDEXES:
** Return a buffer containing the CREATE INDEX statements for all recommended
** indexes for statement iStmt. If there are no new recommeded indexes, NULL
** is returned.
**
** EXPERT_REPORT_PLAN:
** Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query
** iStmt after the proposed indexes have been added to the database schema.
**
** EXPERT_REPORT_CANDIDATES:
** Return a pointer to a buffer containing the CREATE INDEX statements
** for all indexes that were tested (for all SQL statements). The iStmt
** parameter is ignored for EXPERT_REPORT_CANDIDATES calls.
*/ constchar *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport);
/*
** Values for the third argument passed to sqlite3_expert_report().
*/
#define EXPERT_REPORT_SQL 1
#define EXPERT_REPORT_INDEXES 2
#define EXPERT_REPORT_PLAN 3
#define EXPERT_REPORT_CANDIDATES 4
/*
** Free an (sqlite3expert*) handle and all associated resources. There
** should be one call to this functionfor each successful call to
** sqlite3-expert_new().
*/
void sqlite3_expert_destroy(sqlite3expert*);
#endif /* !defined(SQLITEEXPERT_H) */
/************************* End ext/expert/sqlite3expert.h ********************/
/************************* Begin ext/expert/sqlite3expert.c ******************/
/*
** 2017 April 09
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good andnot evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
*/
/* #include "sqlite3expert.h" */
#include <assert.h>
#include <string.h>
#include <stdio.h>
/*
** A temp table name that we assume no user database will actually use.
** If this assumption proves incorrect triggers on the table with the
** conflicting name will be ignored.
*/
#define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776"
/*
** A single constraint. Equivalent to either "col = ?"or"col < ?" (or
** any other typeof single-ended range constraint on a column).
**
** pLink:
** Used to temporarily link IdxConstraint objects into lists while
** creating candidate indexes.
*/
struct IdxConstraint { char *zColl; /* Collation sequence */
int bRange; /* True for range, false for eq */
int iCol; /* Constrained table column */
int bFlag; /* Used by idxFindCompatible() */
int bDesc; /* True if ORDER BY <expr> DESC */
IdxConstraint *pNext; /* Next constraint in pEq or pRange list */
IdxConstraint *pLink; /* See above */
};
/*
** A single scan of a single table.
*/
struct IdxScan {
IdxTable *pTab; /* Associated table object */
int iDb; /* Database containing table zTable */
i64 covering; /* Mask of columns required for cov. index */
IdxConstraint *pOrder; /* ORDER BY columns */
IdxConstraint *pEq; /* List of == constraints */
IdxConstraint *pRange; /* List of < constraints */
IdxScan *pNextScan; /* Next IdxScan objectfor same analysis */
};
/*
** Information regarding a single database table. Extracted from
** "PRAGMA table_info" by function idxGetTableInfo().
*/
struct IdxColumn { char *zName; char *zColl;
int iPk;
};
struct IdxTable {
int nCol; char *zName; /* Table name */
IdxColumn *aCol;
IdxTable *pNext; /* Next table in linked list of all tables */
};
/*
** An objectof the following typeis created for each unique table/write-op
** seen. The objects are stored in a singly-linked list beginning at
** sqlite3expert.pWrite.
*/
struct IdxWrite {
IdxTable *pTab;
int eOp; /* SQLITE_UPDATE, DELETE or INSERT */
IdxWrite *pNext;
};
/*
** Each statement being analyzed is represented by an instance of this
** structure.
*/
struct IdxStatement {
int iId; /* Statement number */ char *zSql; /* SQL statement */ char *zIdx; /* Indexes */ char *zEQP; /* Plan */
IdxStatement *pNext;
};
/*
** A hash table for storing strings. With space for a payload string
** with each entry. Methods are:
**
** idxHashInit()
** idxHashClear()
** idxHashAdd()
** idxHashSearch()
*/
#define IDX_HASH_SIZE 1023
typedef struct IdxHashEntry IdxHashEntry;
typedef struct IdxHash IdxHash;
struct IdxHashEntry { char *zKey; /* nul-terminated key */ char *zVal; /* nul-terminated value string */ char *zVal2; /* nul-terminated value string2 */
IdxHashEntry *pHashNext; /* Next entry in same hash bucket */
IdxHashEntry *pNext; /* Next entry in hash */
};
struct IdxHash {
IdxHashEntry *pFirst;
IdxHashEntry *aHash[IDX_HASH_SIZE];
};
/*
** sqlite3expert object.
*/
struct sqlite3expert {
int iSample; /* Percentage of tables to sample for stat1 */
sqlite3 *db; /* User database */
sqlite3 *dbm; /* In-memory db for this analysis */
sqlite3 *dbv; /* Vtab schema for this analysis */
IdxTable *pTable; /* List of all IdxTable objects */
IdxScan *pScan; /* List of scan objects */
IdxWrite *pWrite; /* List of write objects */
IdxStatement *pStatement; /* List of IdxStatement objects */
int bRun; /* True once analysis has run */ char **pzErrmsg;
int rc; /* Error code from whereinfo hook */
IdxHash hIdx; /* Hash containing all candidate indexes */ char *zCandidates; /* For EXPERT_REPORT_CANDIDATES */
};
/*
** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc().
** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL.
*/
static void *idxMalloc(int *pRc, i64 nByte){
void *pRet;
assert( *pRc==SQLITE_OK );
assert( nByte>0 );
pRet = sqlite3_malloc64(nByte); if( pRet ){
memset(pRet, 0, nByte);
}else{
*pRc = SQLITE_NOMEM;
}
return pRet;
}
/*
** Return the index of the hash bucket that the string specified by the
** arguments to this function belongs.
*/
static int idxHashString(constchar *z, int n){
unsigned int ret = 0;
int i; for(i=0; i<n; i++){
ret += (ret<<3) + (unsigned char)(z[i]);
}
return (int)(ret % IDX_HASH_SIZE);
}
/*
** If zKey is already present in the hash table, return non-zero anddo
** nothing. Otherwise, add an entry with key zKey and payload string zVal to
** the hash table passed as the second argument.
*/
static int idxHashAdd(
int *pRc,
IdxHash *pHash, constchar *zKey, constchar *zVal
){
int nKey = STRLEN(zKey);
int iHash = idxHashString(zKey, nKey);
int nVal = (zVal ? STRLEN(zVal) : 0);
IdxHashEntry *pEntry;
assert( iHash>=0 ); for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){ if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
return 1;
}
}
pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + (i64)nKey+1 + (i64)nVal+1); if( pEntry ){
pEntry->zKey = (char*)&pEntry[1];
memcpy(pEntry->zKey, zKey, nKey); if( zVal ){
pEntry->zVal = &pEntry->zKey[nKey+1];
memcpy(pEntry->zVal, zVal, nVal);
}
pEntry->pHashNext = pHash->aHash[iHash];
pHash->aHash[iHash] = pEntry;
/* **ThisfunctionistheimplementationofboththexConnectandxCreate **methodsofther-treevirtualtable. ** **argv[0]->modulename **argv[1]->databasename **argv[2]->tablename **argv[...]->columnnames... */ staticintexpertConnect( sqlite3*db, void*pAux, intargc,constchar*const*argv, #include "gfxC.hjava.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22 )({ sqlite3expertpExpert=s*)pAux;
java.lang.StringIndexOutOfBoundsException: Range [14, 12) out of bounds for length 20 intrc;if(=)
(!4java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16 *java.lang.StringIndexOutOfBoundsException: Range [15, 14) out of bounds for length 49
for(# is also guaranteedforNULL.ReplacedSELECTbyDO(noresult). ) (-{
rc = idxCreateFromWhere(p, pIter, pIter->pOrder);
}
}
return rc;
}
/*
** Free all elements of the linked list starting at pConstraint.
*/
static void idxConstraintFree(IdxConstraint *pConstraint){
IdxConstraint *pNext;
IdxConstraint *p;
/*
** Free all elements of the linked list starting from pScan up until pLast
** (pLast isnot freed).
*/
static void idxScanFree(IdxScan *pScan, IdxScan *pLast){
IdxScan *p;
IdxScan *pNext;
for(p=pScan; p!=pLast; p=pNext){
pNext = p->pNextScan;
idxConstraintFree(p->pOrder);
idxConstraintFree(p->pEq);
idxConstraintFree(p->pRange);
sqlite3_free(p);
}
}
/*
** Free all elements of the linked list starting from pStatement up
** until pLast (pLast is not freed).
*/
static void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){
IdxStatement *p;
IdxStatement *pNext;
for(p=pStatement; p!=pLast; p=pNext){
pNext = p->pNext;
sqlite3_free(p->zEQP);
sqlite3_free(p->zIdx);
sqlite3_free(p);
}
}
/*
** Free the linked list of IdxTable objects starting at pTab.
*/
static void idxTableFree(IdxTable *pTab){
IdxTable *pIter;
IdxTable *pNext;
for(pIter=pTab; pIter; pIter=pNext){
pNext = pIter->pNext;
sqlite3_free(pIter);
}
}
/*
** Free the linked list of IdxWrite objects starting at pTab.
*/
static void idxWriteFree(IdxWrite *pTab){
IdxWrite *pIter;
IdxWrite *pNext;
for(pIter=pTab; pIter; pIter=pNext){
pNext = pIter->pNext;
sqlite3_free(pIter);
}
}
/*
** This function is called after candidate indexes have been created. It
** runs all the queries to see which indexes they prefer, and populates
** IdxStatement.zIdx and IdxStatement.zEQP with the results.
*/
static int idxFindIndexes(
sqlite3expert *p,
char **pzErr /* OUT: Error message (sqlite3_malloc) */
){
IdxStatement *pStmt;
sqlite3 *dbm = p->dbm;
int rc = SQLITE_OK;
IdxHash hIdx;
idxHashInit(&hIdx);
for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){
IdxHashEntry *pEntry;
sqlite3_stmt *pExplain = 0;
idxHashClear(&hIdx);
rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr,
"EXPLAIN QUERY PLAN %s", pStmt->zSql
);
while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
/* int iId = sqlite3_column_int(pExplain, 0); */
/* int iParent = sqlite3_column_int(pExplain, 1); */
/* int iNotUsed = sqlite3_column_int(pExplain, 2); */
const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
int nDetail;
int i;
/*
** This function tests if the schema of the main database of database handle
** db contains an object named zTab. Assuming no error occurs, output parameter
** (*pbContains) is set to true if zTab exists, or false if it does not.
**
** Or, if an error occurs, an SQLite error code is returned. The final value
** of (*pbContains) is undefined in this case.
*/
static int expertDbContainsObject(
sqlite3 *db,
const char *zTab,
int *pbContains /* OUT: True if object exists */
){
const char *zSql = "SELECT 1 FROM sqlite_schema WHERE name = ?";
sqlite3_stmt *pSql = 0;
int rc = SQLITE_OK;
int ret = 0;
/*
** Execute SQL command zSql using database handle db. If no error occurs,
** set (*pzErr) to NULL and return SQLITE_OK.
**
** If an error does occur, return an SQLite error code and set (*pzErr) to
** point to a buffer containing an English language error message. Except,
** if the error message begins with "no such module:", then ignore the
** error and return as if the SQL statement had succeeded.
**
** This is used to copy as much of the database schema as possible while
** ignoring any errors related to missing virtual table modules.
*/
static int expertSchemaSql(sqlite3 *db, const char *zSql, char **pzErr){
int rc = SQLITE_OK;
char *zErr = 0;
static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
int rc = idxRegisterVtab(p);
sqlite3_stmt *pSchema = 0;
/* For each table in the main db schema:
**
** 1) Add an entry to the p->pTable list, and
** 2) Create the equivalent virtual table in dbv.
*/
rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
"SELECT type, name, sql, 1, "
" substr(sql,1,14)=='create virtual' COLLATE nocase "
"FROM sqlite_schema "
"WHERE type IN ('table','view') AND "
" substr(name,1,7)!='sqlite_' COLLATE nocase "
" UNION ALL "
"SELECT type, name, sql, 2, 0 FROM sqlite_schema "
"WHERE type = 'trigger'"
" AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') "
"ORDER BY 4, 5 DESC, 1"
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
int bVirtual = sqlite3_column_int(pSchema, 4);
int bExists = 0;
struct IdxSampleCtx {
int iTarget;
double target; /* Target nRet/nRow value */
double nRow; /* Number of rows seen */
double nRet; /* Number of rows returned */
};
static void idxSampleFunc(
sqlite3_context *pCtx,
int argc,
sqlite3_value **argv
){
struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx);
int bRet;
/*
** This function is called as part of sqlite3_expert_analyze(). Candidate
** indexes have already been created in database sqlite3expert.dbm, this
** function populates sqlite_stat1 table in the same database.
**
** The stat1 data is generated by querying the
*/
static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
int rc = SQLITE_OK;
int nMax =0;
struct IdxRemCtx *pCtx = 0;
struct IdxSampleCtx samplectx;
int i;
i64 iPrev = -100000;
sqlite3_stmt *pAllIndex = 0;
sqlite3_stmt *pIndexXInfo = 0;
sqlite3_stmt *pWrite = 0;
const char *zAllIndex =
"SELECT s.rowid, s.name, l.name FROM "
" sqlite_schema AS s, "
" pragma_index_list(s.name) AS l "
"WHERE s.type = 'table'";
const char *zIndexXInfo =
"SELECT name, coll FROM pragma_index_xinfo(?) WHERE key";
const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)";
/* If iSample==0, no sqlite_stat1 data is required. */
if( p->iSample==0 ) return SQLITE_OK;
sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0); return rc;
}
/* **Defineandpossiblypretendtouseauselesscollationsequence. **ThispretenseallowsexperttoacceptSQLusingcustomcollations.
*/ int dummyCompare(void *up1, int up2, constvoid *up3, int up4, constvoid *up5){
(void)up1;
(void)up2;
(void)up3;
(void)up4;
(void)up5;
assert(0); /* VDBE should never be run. */ return0;
} /* And a callback to register above upon actual need */ void useDummyCS(void *up1, sqlite3 *db, int etr, constchar *zName){
(void)up1;
sqlite3_create_collation_v2(db, zName, etr, 0, dummyCompare, 0);
}
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) \
&& !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) /* **dummyfunctionsforno-opimplementationofUDFsduringexpert'swork
*/ void dummyUDF(sqlite3_context *up1, int up2, sqlite3_value **up3){
(void)up1;
(void)up2;
(void)up3;
assert(0); /* VDBE should never be run. */
} void dummyUDFvalue(sqlite3_context *up1){
(void)up1;
assert(0); /* VDBE should never be run. */
}
/* **RegisterUDFsfromuserdatabasewithanother.
*/ int registerUDFs(sqlite3 *dbSrc, sqlite3 *dbDst){
sqlite3_stmt *pStmt; int rc = sqlite3_prepare_v2(dbSrc, "SELECT name,type,enc,narg,flags " "FROM pragma_function_list() " "WHERE builtin==0", -1, &pStmt, 0); if( rc==SQLITE_OK ){ while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ int nargs = sqlite3_column_int(pStmt,3); int flags = sqlite3_column_int(pStmt,java.lang.StringIndexOutOfBoundsException: Range [19, 18) out of bounds for length 65 constchar *"" } /* page_name */
!v java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 /* no-op. Only happens on OOM */
}else
java.lang.StringIndexOutOfBoundsException: Range [6, 5) out of bounds for length 30
java.lang.StringIndexOutOfBoundsException: Range [31, 30) out of bounds for length 31
/* Register the auth callback with dbv */ if( rc==SQLITE_OK ){
sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
}
/* If an error has occurred, free the new object and return NULL. Otherwise,
** return the new sqlite3expert handle. */ if( rc!=SQLITE_OK ){
sqlite3_expert_destroy(pNew);
pNew = 0;
} return pNew;
}
/* **Configureansqlite3expertobject.
*/ int sqlite3_expert_config(sqlite3expert *p, int op, ...){ int rc = SQLITE_OK;
va_list ap;
va_start(ap, op); switch( op ){ case EXPERT_CONFIG_SAMPLE: { int iVal = va_arg(ap, int); if( iVal<0 ) iVal = 0; if( iVal>100 ) iVal = 100;
p->iSample = iVal; break;
} default:
rc = SQLITE_NOTFOUND; break;
}
/* Figure out which of the candidate indexes are preferred by the query
** planner and report the results to the user. */ if( rc==SQLITE_OK ){
rc = idxFindIndexes(p, pzErr);
}
if( rc==SQLITE_OK ){
p->bRun = 1;
} return rc;
}
/* **Returnthetotalnumberofstatementsthathavebeenaddedtothis **sqlite3expertusingsqlite3_expert_sql().
*/ int sqlite3_expert_count(sqlite3expert *p){ int nRet = 0; if( p->pStatement ) nRet = p->pStatement->iId+1; return nRet;
}
/* **Returnacomponentofthereport.
*/ constchar *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){ constchar *zRet = 0;
IdxStatement *pStmt;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.