Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Bring the built-in SQLite and the regexp implementation into alignment with upstream. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
9642cde38468682b797d1138102c23bd |
| User & Date: | drh 2025-09-26 13:36:14.507 |
Context
|
2025-09-26
| ||
| 14:12 | Update the change log. check-in: 3a0dfc8920 user: drh tags: trunk | |
| 13:36 | Bring the built-in SQLite and the regexp implementation into alignment with upstream. check-in: 9642cde384 user: drh tags: trunk | |
| 12:48 | Prevent the cell background colors from extending beyond the outer rounded borders of the diff table in WebKit-based browsers. check-in: b666bbc54d user: florian tags: trunk | |
Changes
Changes to extsrc/shell.c.
| ︙ | ︙ | |||
1510 1511 1512 1513 1514 1515 1516 |
v *= aMult[i].iMult;
break;
}
}
if( isNeg && v>0x7fffffffffffffffULL ) goto integer_overflow;
return isNeg? -(sqlite3_int64)v : (sqlite3_int64)v;
integer_overflow:
| | | | | | | 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 |
v *= aMult[i].iMult;
break;
}
}
if( isNeg && v>0x7fffffffffffffffULL ) goto integer_overflow;
return isNeg? -(sqlite3_int64)v : (sqlite3_int64)v;
integer_overflow:
return isNeg ? (i64)0x8000000000000000LL : 0x7fffffffffffffffLL;
}
/*
** A variable length string to which one can append text.
*/
typedef struct ShellText ShellText;
struct ShellText {
char *zTxt; /* The text */
i64 n; /* Number of bytes of zTxt[] actually used */
i64 nAlloc; /* Number of bytes allocated for zTxt[] */
};
/*
** Initialize and destroy a ShellText object
*/
static void initText(ShellText *p){
memset(p, 0, sizeof(*p));
}
static void freeText(ShellText *p){
sqlite3_free(p->zTxt);
initText(p);
}
/* zIn is either a pointer to a NULL-terminated string in memory obtained
** from malloc(), or a NULL pointer. The string pointed to by zAppend is
** added to zIn, and the result returned in memory obtained from malloc().
** zIn, if it was not NULL, is freed.
|
| ︙ | ︙ | |||
1555 1556 1557 1558 1559 1560 1561 |
if( quote ){
len += 2;
for(i=0; i<nAppend; i++){
if( zAppend[i]==quote ) len++;
}
}
| | | | | | | | | 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 |
if( quote ){
len += 2;
for(i=0; i<nAppend; i++){
if( zAppend[i]==quote ) len++;
}
}
if( p->zTxt==0 || p->n+len>=p->nAlloc ){
p->nAlloc = p->nAlloc*2 + len + 20;
p->zTxt = sqlite3_realloc64(p->zTxt, p->nAlloc);
shell_check_oom(p->zTxt);
}
if( quote ){
char *zCsr = p->zTxt+p->n;
*zCsr++ = quote;
for(i=0; i<nAppend; i++){
*zCsr++ = zAppend[i];
if( zAppend[i]==quote ) *zCsr++ = quote;
}
*zCsr++ = quote;
p->n = (i64)(zCsr - p->zTxt);
*zCsr = '\0';
}else{
memcpy(p->zTxt+p->n, zAppend, nAppend);
p->n += nAppend;
p->zTxt[p->n] = '\0';
}
}
/*
** 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
|
| ︙ | ︙ | |||
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 |
}
return sqlite3_keyword_check(zName, i) ? '"' : 0;
}
/*
** Construct a fake object name and column list to describe the structure
** of the view, virtual table, or table valued function zSchema.zName.
*/
static char *shellFakeSchema(
sqlite3 *db, /* The database connection containing the vtab */
const char *zSchema, /* Schema of the database holding the vtab */
const char *zName /* The name of the virtual table */
){
sqlite3_stmt *pStmt = 0;
| > > > | 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 |
}
return sqlite3_keyword_check(zName, i) ? '"' : 0;
}
/*
** Construct a fake object name and column list to describe the structure
** of the view, virtual table, or table valued function zSchema.zName.
**
** The returned string comes from sqlite3_mprintf() and should be freed
** by the caller using sqlite3_free().
*/
static char *shellFakeSchema(
sqlite3 *db, /* The database connection containing the vtab */
const char *zSchema, /* Schema of the database holding the vtab */
const char *zName /* The name of the virtual table */
){
sqlite3_stmt *pStmt = 0;
|
| ︙ | ︙ | |||
1639 1640 1641 1642 1643 1644 1645 |
cQuote = quoteChar(zCol);
appendText(&s, zCol, cQuote);
}
appendText(&s, ")", 0);
sqlite3_finalize(pStmt);
if( nRow==0 ){
freeText(&s);
| | | | 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 |
cQuote = quoteChar(zCol);
appendText(&s, zCol, cQuote);
}
appendText(&s, ")", 0);
sqlite3_finalize(pStmt);
if( nRow==0 ){
freeText(&s);
s.zTxt = 0;
}
return s.zTxt;
}
/*
** SQL function: strtod(X)
**
** Use the C-library strtod() function to convert string X into a double.
** Used for comparing the accuracy of SQLite's internal text-to-float conversion
|
| ︙ | ︙ | |||
1744 1745 1746 1747 1748 1749 1750 |
&& (zFake = shellFakeSchema(db, zSchema, zName))!=0
){
if( z==0 ){
z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
}else{
z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
}
| | | 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 |
&& (zFake = shellFakeSchema(db, zSchema, zName))!=0
){
if( z==0 ){
z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
}else{
z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
}
sqlite3_free(zFake);
}
if( z ){
sqlite3_result_text(pCtx, z, -1, sqlite3_free);
return;
}
}
}
|
| ︙ | ︙ | |||
6991 6992 6993 6994 6995 6996 6997 | ** second. ** ** The following regular expression syntax is supported: ** ** X* zero or more occurrences of X ** X+ one or more occurrences of X ** X? zero or one occurrences of X | | | 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 |
** second.
**
** The following regular expression syntax is supported:
**
** X* zero or more occurrences of X
** X+ one or more occurrences of X
** X? zero or one occurrences of X
** X{p,q} between p and q occurrences of X, 0 <= p,q <= 999
** (X) match X
** X|Y X or Y
** ^X X occurring at the beginning of the string
** X$ X occurring at the end of the string
** . Match any single character
** \c Character c where c is one of \{}()[]|*+?.
** \c C-language escapes for c in afnrtv. ex: \t or \n
|
| ︙ | ︙ | |||
7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 |
** A nondeterministic finite automaton (NFA) is used for matching, so the
** performance is bounded by O(N*M) where N is the size of the regular
** expression and M is the size of the input string. The matcher never
** exhibits exponential behavior. Note that the X{p,q} operator expands
** to p copies of X following by q-p copies of X? and that the size of the
** regular expression in the O(N*M) performance bound is computed after
** this expansion.
*/
#include <string.h>
#include <stdlib.h>
/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
/*
** The following #defines change the names of some functions implemented in
** this file to prevent name collisions with C-library functions of the
** same name.
*/
#define re_match sqlite3re_match
| > > > > > > > | 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 |
** A nondeterministic finite automaton (NFA) is used for matching, so the
** performance is bounded by O(N*M) where N is the size of the regular
** expression and M is the size of the input string. The matcher never
** exhibits exponential behavior. Note that the X{p,q} operator expands
** to p copies of X following by q-p copies of X? and that the size of the
** regular expression in the O(N*M) performance bound is computed after
** this expansion.
**
** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax
** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999.
*/
#include <string.h>
#include <stdlib.h>
/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#ifndef SQLITE_MAX_REGEXP_REPEAT
# define SQLITE_MAX_REGEXP_REPEAT 999
#endif
/*
** The following #defines change the names of some functions implemented in
** this file to prevent name collisions with C-library functions of the
** same name.
*/
#define re_match sqlite3re_match
|
| ︙ | ︙ | |||
7528 7529 7530 7531 7532 7533 7534 |
break;
}
case '^': {
re_append(p, RE_OP_ATSTART, 0);
break;
}
case '{': {
| | | | > > > > | > > > | > | | 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 |
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>SQLITE_MAX_REGEXP_REPEAT ) return "integer too large";
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>SQLITE_MAX_REGEXP_REPEAT ) return "integer too large";
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--;
|
| ︙ | ︙ | |||
22096 22097 22098 22099 22100 22101 22102 |
/*
** Output the given string as a hex-encoded blob (eg. X'1234' )
*/
static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
int i;
unsigned char *aBlob = (unsigned char*)pBlob;
| | | 22114 22115 22116 22117 22118 22119 22120 22121 22122 22123 22124 22125 22126 22127 22128 |
/*
** Output the given string as a hex-encoded blob (eg. X'1234' )
*/
static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
int i;
unsigned char *aBlob = (unsigned char*)pBlob;
char *zStr = sqlite3_malloc64((i64)nBlob*2 + 1);
shell_check_oom(zStr);
for(i=0; i<nBlob; i++){
static const char aHex[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
|
| ︙ | ︙ | |||
23373 23374 23375 23376 23377 23378 23379 |
*/
static void set_table_name(ShellState *p, const char *zName){
if( p->zDestTable ){
sqlite3_free(p->zDestTable);
p->zDestTable = 0;
}
if( zName==0 ) return;
| > | > > > > | 23391 23392 23393 23394 23395 23396 23397 23398 23399 23400 23401 23402 23403 23404 23405 23406 23407 23408 23409 23410 |
*/
static void set_table_name(ShellState *p, const char *zName){
if( p->zDestTable ){
sqlite3_free(p->zDestTable);
p->zDestTable = 0;
}
if( zName==0 ) return;
if( quoteChar(zName) ){
p->zDestTable = sqlite3_mprintf("\"%w\"", zName);
}else{
p->zDestTable = sqlite3_mprintf("%s", zName);
}
shell_check_oom(p->zDestTable);
}
/*
** Maybe construct two lines of text that point out the position of a
** syntax error. Return a pointer to the text, in memory obtained from
** sqlite3_malloc(). Or, if the most recent error does not involve a
** specific token that we can point to, return an empty string.
|
| ︙ | ︙ | |||
25180 25181 25182 25183 25184 25185 25186 |
}
freeColumnList(azCol);
appendText(&sSelect, " FROM ", 0);
appendText(&sSelect, zTable, quoteChar(zTable));
savedDestTable = p->zDestTable;
savedMode = p->mode;
| | | | | 25203 25204 25205 25206 25207 25208 25209 25210 25211 25212 25213 25214 25215 25216 25217 25218 25219 25220 25221 25222 25223 |
}
freeColumnList(azCol);
appendText(&sSelect, " FROM ", 0);
appendText(&sSelect, zTable, quoteChar(zTable));
savedDestTable = p->zDestTable;
savedMode = p->mode;
p->zDestTable = sTable.zTxt;
p->mode = p->cMode = MODE_Insert;
rc = shell_exec(p, sSelect.zTxt, 0);
if( (rc&0xff)==SQLITE_CORRUPT ){
sqlite3_fputs("/****** CORRUPTION ERROR *******/\n", p->out);
toggleSelectOrder(p->db);
shell_exec(p, sSelect.zTxt, 0);
toggleSelectOrder(p->db);
}
p->zDestTable = savedDestTable;
p->mode = savedMode;
freeText(&sTable);
freeText(&sSelect);
if( rc ) p->nErr++;
|
| ︙ | ︙ | |||
25800 25801 25802 25803 25804 25805 25806 |
** Reconstruct an in-memory database using the output from the "dbtotxt"
** program. Read content from the file in p->aAuxDb[].zDbFilename.
** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
*/
static unsigned char *readHexDb(ShellState *p, int *pnData){
unsigned char *a = 0;
int nLine;
| | > | < | 25823 25824 25825 25826 25827 25828 25829 25830 25831 25832 25833 25834 25835 25836 25837 25838 25839 25840 |
** Reconstruct an in-memory database using the output from the "dbtotxt"
** program. Read content from the file in p->aAuxDb[].zDbFilename.
** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
*/
static unsigned char *readHexDb(ShellState *p, int *pnData){
unsigned char *a = 0;
int nLine;
int n = 0; /* Size of db per first line of hex dump */
i64 sz = 0; /* n rounded up to nearest page boundary */
int pgsz = 0;
i64 iOffset = 0;
int rc;
FILE *in;
const char *zDbFilename = p->pAuxDb->zDbFilename;
unsigned int x[16];
char zLine[1000];
if( zDbFilename ){
in = sqlite3_fopen(zDbFilename, "r");
|
| ︙ | ︙ | |||
25827 25828 25829 25830 25831 25832 25833 | } *pnData = 0; nLine++; if( sqlite3_fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error; rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz); if( rc!=2 ) goto readHexDb_error; if( n<0 ) goto readHexDb_error; | < < < < < > > > > > > | | | | | 25850 25851 25852 25853 25854 25855 25856 25857 25858 25859 25860 25861 25862 25863 25864 25865 25866 25867 25868 25869 25870 25871 25872 25873 25874 25875 25876 25877 25878 25879 25880 25881 25882 25883 25884 25885 25886 25887 25888 25889 25890 25891 25892 25893 25894 |
}
*pnData = 0;
nLine++;
if( sqlite3_fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
if( rc!=2 ) goto readHexDb_error;
if( n<0 ) goto readHexDb_error;
if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
sqlite3_fputs("invalid pagesize\n", stderr);
goto readHexDb_error;
}
sz = ((i64)n+pgsz-1)&~(pgsz-1); /* Round up to nearest multiple of pgsz */
a = sqlite3_malloc( sz ? sz : 1 );
shell_check_oom(a);
memset(a, 0, sz);
for(nLine++; sqlite3_fgets(zLine, sizeof(zLine), in)!=0; nLine++){
int j = 0; /* Page number from "| page" line */
int k = 0; /* Offset from "| page" line */
rc = sscanf(zLine, "| page %d offset %d", &j, &k);
if( rc==2 ){
iOffset = k;
continue;
}
if( cli_strncmp(zLine, "| end ", 6)==0 ){
break;
}
rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
&j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
&x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
if( rc==17 ){
i64 iOff = iOffset+j;
if( iOff+16<=sz && iOff>=0 ){
int ii;
for(ii=0; ii<16; ii++) a[iOff+ii] = x[ii]&0xff;
}
}
}
*pnData = sz;
if( in!=p->in ){
fclose(in);
}else{
p->lineno = nLine;
}
return a;
|
| ︙ | ︙ | |||
25923 25924 25925 25926 25927 25928 25929 |
p->pLog = 0;
zFake = zName? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
p->pLog = pSavedLog;
if( zFake ){
sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
-1, sqlite3_free);
| | | 25947 25948 25949 25950 25951 25952 25953 25954 25955 25956 25957 25958 25959 25960 25961 |
p->pLog = 0;
zFake = zName? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
p->pLog = pSavedLog;
if( zFake ){
sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
-1, sqlite3_free);
sqlite3_free(zFake);
}
}
/* Flags for open_db().
**
** The default behavior of open_db() is to exit(1) if the database fails to
** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
|
| ︙ | ︙ | |||
31007 31008 31009 31010 31011 31012 31013 |
}
if( bNoSystemTabs ){
appendText(&sSelect, "name NOT LIKE 'sqlite__%%' ESCAPE '_' AND ", 0);
}
appendText(&sSelect, "sql IS NOT NULL"
" ORDER BY snum, rowid", 0);
if( bDebug ){
| | | | 31031 31032 31033 31034 31035 31036 31037 31038 31039 31040 31041 31042 31043 31044 31045 31046 31047 |
}
if( bNoSystemTabs ){
appendText(&sSelect, "name NOT LIKE 'sqlite__%%' ESCAPE '_' AND ", 0);
}
appendText(&sSelect, "sql IS NOT NULL"
" ORDER BY snum, rowid", 0);
if( bDebug ){
sqlite3_fprintf(p->out, "SQL: %s;\n", sSelect.zTxt);
}else{
rc = sqlite3_exec(p->db, sSelect.zTxt, callback, &data, &zErrMsg);
}
freeText(&sSelect);
}
if( zErrMsg ){
shellEmitError(zErrMsg);
sqlite3_free(zErrMsg);
rc = 1;
|
| ︙ | ︙ | |||
31333 31334 31335 31336 31337 31338 31339 |
}
if( cli_strcmp(zOp,"memo")==0 ){
sqlite3_fprintf(p->out, "%s\n", zSql);
}else
if( cli_strcmp(zOp,"run")==0 ){
char *zErrMsg = 0;
str.n = 0;
| | | | | | 31357 31358 31359 31360 31361 31362 31363 31364 31365 31366 31367 31368 31369 31370 31371 31372 31373 31374 31375 31376 31377 31378 31379 31380 31381 31382 31383 31384 31385 31386 |
}
if( cli_strcmp(zOp,"memo")==0 ){
sqlite3_fprintf(p->out, "%s\n", zSql);
}else
if( cli_strcmp(zOp,"run")==0 ){
char *zErrMsg = 0;
str.n = 0;
str.zTxt[0] = 0;
rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
nTest++;
if( bVerbose ){
sqlite3_fprintf(p->out, "Result: %s\n", str.zTxt);
}
if( rc || zErrMsg ){
nErr++;
rc = 1;
sqlite3_fprintf(p->out, "%d: error-code-%d: %s\n", tno, rc,zErrMsg);
sqlite3_free(zErrMsg);
}else if( cli_strcmp(zAns,str.zTxt)!=0 ){
nErr++;
rc = 1;
sqlite3_fprintf(p->out, "%d: Expected: [%s]\n", tno, zAns);
sqlite3_fprintf(p->out, "%d: Got: [%s]\n", tno, str.zTxt);
}
}
else{
sqlite3_fprintf(stderr,
"Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
rc = 1;
break;
|
| ︙ | ︙ | |||
31464 31465 31466 31467 31468 31469 31470 |
" ORDER BY tbl,idx;", 0);
}else if( cli_strcmp(zTab, "sqlite_stat4")==0 ){
appendText(&sQuery, "SELECT * FROM ", 0);
appendText(&sQuery, zTab, 0);
appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
}
appendText(&sSql, zSep, 0);
| | | | | 31488 31489 31490 31491 31492 31493 31494 31495 31496 31497 31498 31499 31500 31501 31502 31503 31504 31505 31506 31507 31508 31509 31510 31511 31512 31513 31514 31515 31516 31517 31518 31519 31520 |
" ORDER BY tbl,idx;", 0);
}else if( cli_strcmp(zTab, "sqlite_stat4")==0 ){
appendText(&sQuery, "SELECT * FROM ", 0);
appendText(&sQuery, zTab, 0);
appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
}
appendText(&sSql, zSep, 0);
appendText(&sSql, sQuery.zTxt, '\'');
sQuery.n = 0;
appendText(&sSql, ",", 0);
appendText(&sSql, zTab, '\'');
zSep = "),(";
}
sqlite3_finalize(pStmt);
if( bSeparate ){
zSql = sqlite3_mprintf(
"%s))"
" SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
" FROM [sha3sum$query]",
sSql.zTxt, iSize);
}else{
zSql = sqlite3_mprintf(
"%s))"
" SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
" FROM [sha3sum$query]",
sSql.zTxt, iSize);
}
shell_check_oom(zSql);
freeText(&sQuery);
freeText(&sSql);
if( bDebug ){
sqlite3_fprintf(p->out, "%s\n", zSql);
}else{
|
| ︙ | ︙ | |||
31682 31683 31684 31685 31686 31687 31688 |
rc = 1;
sqlite3_finalize(pStmt);
goto meta_command_exit;
}
for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
if( zDbName==0 ) continue;
| | | 31706 31707 31708 31709 31710 31711 31712 31713 31714 31715 31716 31717 31718 31719 31720 |
rc = 1;
sqlite3_finalize(pStmt);
goto meta_command_exit;
}
for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
if( zDbName==0 ) continue;
if( s.zTxt && s.zTxt[0] ) appendText(&s, " UNION ALL ", 0);
if( sqlite3_stricmp(zDbName, "main")==0 ){
appendText(&s, "SELECT name FROM ", 0);
}else{
appendText(&s, "SELECT ", 0);
appendText(&s, zDbName, '\'');
appendText(&s, "||'.'||name FROM ", 0);
}
|
| ︙ | ︙ | |||
31704 31705 31706 31707 31708 31709 31710 |
appendText(&s," WHERE type='index'"
" AND tbl_name LIKE ?1", 0);
}
}
rc = sqlite3_finalize(pStmt);
if( rc==SQLITE_OK ){
appendText(&s, " ORDER BY 1", 0);
| | | 31728 31729 31730 31731 31732 31733 31734 31735 31736 31737 31738 31739 31740 31741 31742 |
appendText(&s," WHERE type='index'"
" AND tbl_name LIKE ?1", 0);
}
}
rc = sqlite3_finalize(pStmt);
if( rc==SQLITE_OK ){
appendText(&s, " ORDER BY 1", 0);
rc = sqlite3_prepare_v2(p->db, s.zTxt, -1, &pStmt, 0);
}
freeText(&s);
if( rc ) return shellDatabaseError(p->db);
/* Run the SQL statement prepared by the above block. Store the results
** as an array of nul-terminated strings in azResult[]. */
nRow = nAlloc = 0;
|
| ︙ | ︙ |
Changes to extsrc/sqlite3.c.
| ︙ | ︙ | |||
14 15 16 17 18 19 20 | ** the text of this file. Search for "Begin file sqlite3.h" to find the start ** of the embedded sqlite3.h header file.) Additional code files may be needed ** if you want a wrapper to interface SQLite with your choice of programming ** language. The code for the "sqlite3" command-line shell is also in a ** separate file. This file contains only code for the core SQLite library. ** ** The content in this amalgamation comes from Fossil check-in | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** the text of this file. Search for "Begin file sqlite3.h" to find the start ** of the embedded sqlite3.h header file.) Additional code files may be needed ** if you want a wrapper to interface SQLite with your choice of programming ** language. The code for the "sqlite3" command-line shell is also in a ** separate file. This file contains only code for the core SQLite library. ** ** The content in this amalgamation comes from Fossil check-in ** 911c745f88c0ee8569e67bbcbbab034264f8 with changes in files: ** ** */ #ifndef SQLITE_AMALGAMATION #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 #ifndef SQLITE_PRIVATE |
| ︙ | ︙ | |||
465 466 467 468 469 470 471 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.51.0" #define SQLITE_VERSION_NUMBER 3051000 | | | | 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.51.0" #define SQLITE_VERSION_NUMBER 3051000 #define SQLITE_SOURCE_ID "2025-09-26 13:14:20 911c745f88c0ee8569e67bbcbbab034264f8c981b505aadac3ce7289486a1a68" #define SQLITE_SCM_BRANCH "trunk" #define SQLITE_SCM_TAGS "" #define SQLITE_SCM_DATETIME "2025-09-26T13:14:20.156Z" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| ︙ | ︙ | |||
21705 21706 21707 21708 21709 21710 21711 | SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum*,sqlite3_value*,int); SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char*, u32); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void); SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void); SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) | | | 21705 21706 21707 21708 21709 21710 21711 21712 21713 21714 21715 21716 21717 21718 21719 | SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum*,sqlite3_value*,int); SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char*, u32); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void); SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void); SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) SQLITE_PRIVATE Module *sqlite3JsonVtabRegister(sqlite3*,const char*); #endif SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p); #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) |
| ︙ | ︙ | |||
124260 124261 124262 124263 124264 124265 124266 124267 124268 124269 124270 124271 124272 124273 |
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
if( (pParse->prepFlags & SQLITE_PREPARE_NO_VTAB)==0 && db->init.busy==0 ){
Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(db, zName);
}
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
testcase( pMod->pEpoTab==0 );
return pMod->pEpoTab;
}
}
#endif
if( flags & LOCATE_NOERR ) return 0;
| > > > > > | 124260 124261 124262 124263 124264 124265 124266 124267 124268 124269 124270 124271 124272 124273 124274 124275 124276 124277 124278 |
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
if( (pParse->prepFlags & SQLITE_PREPARE_NO_VTAB)==0 && db->init.busy==0 ){
Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(db, zName);
}
#ifndef SQLITE_OMIT_JSON
if( pMod==0 && sqlite3_strnicmp(zName, "json", 4)==0 ){
pMod = sqlite3JsonVtabRegister(db, zName);
}
#endif
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
testcase( pMod->pEpoTab==0 );
return pMod->pEpoTab;
}
}
#endif
if( flags & LOCATE_NOERR ) return 0;
|
| ︙ | ︙ | |||
183860 183861 183862 183863 183864 183865 183866 | #ifdef SQLITE_ENABLE_DBPAGE_VTAB sqlite3DbpageRegister, #endif #ifdef SQLITE_ENABLE_DBSTAT_VTAB sqlite3DbstatRegister, #endif sqlite3TestExtInit, | < < < | 183865 183866 183867 183868 183869 183870 183871 183872 183873 183874 183875 183876 183877 183878 | #ifdef SQLITE_ENABLE_DBPAGE_VTAB sqlite3DbpageRegister, #endif #ifdef SQLITE_ENABLE_DBSTAT_VTAB sqlite3DbstatRegister, #endif sqlite3TestExtInit, #ifdef SQLITE_ENABLE_STMTVTAB sqlite3StmtVtabInit, #endif #ifdef SQLITE_ENABLE_BYTECODE_VTAB sqlite3VdbeBytecodeVtabInit, #endif #ifdef SQLITE_EXTRA_AUTOEXT |
| ︙ | ︙ | |||
211321 211322 211323 211324 211325 211326 211327 |
break;
}
switch( (u8)zIn[1] ){
case '\'':
jsonAppendChar(pOut, '\'');
break;
case 'v':
| | | 211323 211324 211325 211326 211327 211328 211329 211330 211331 211332 211333 211334 211335 211336 211337 |
break;
}
switch( (u8)zIn[1] ){
case '\'':
jsonAppendChar(pOut, '\'');
break;
case 'v':
jsonAppendRawNZ(pOut, "\\u000b", 6);
break;
case 'x':
if( sz2<4 ){
pOut->eErr |= JSTRING_MALFORMED;
sz2 = 2;
break;
}
|
| ︙ | ︙ | |||
212171 212172 212173 212174 212175 212176 212177 | /* ** Return the value of the BLOB node at index i. ** ** If the value is a primitive, return it as an SQL value. ** If the value is an array or object, return it as either | | > > > | > > > > | > | 212173 212174 212175 212176 212177 212178 212179 212180 212181 212182 212183 212184 212185 212186 212187 212188 212189 212190 212191 212192 212193 212194 212195 212196 212197 212198 212199 212200 212201 212202 212203 212204 212205 212206 212207 |
/*
** Return the value of the BLOB node at index i.
**
** If the value is a primitive, return it as an SQL value.
** If the value is an array or object, return it as either
** JSON text or the BLOB encoding, depending on the eMode flag
** as follows:
**
** eMode==0 JSONB if the JSON_B flag is set in userdata or
** text if the JSON_B flag is omitted from userdata.
**
** eMode==1 Text
**
** eMode==2 JSONB
*/
static void jsonReturnFromBlob(
JsonParse *pParse, /* Complete JSON parse tree */
u32 i, /* Index of the node */
sqlite3_context *pCtx, /* Return value for this function */
int eMode /* Format of return: text of JSONB */
){
u32 n, sz;
int rc;
sqlite3 *db = sqlite3_context_db_handle(pCtx);
assert( eMode>=0 && eMode<=2 );
n = jsonbPayloadSize(pParse, i, &sz);
if( n==0 ){
sqlite3_result_error(pCtx, "malformed JSON", -1);
return;
}
switch( pParse->aBlob[i] & 0x0f ){
case JSONB_NULL: {
|
| ︙ | ︙ | |||
212302 212303 212304 212305 212306 212307 212308 |
assert( iOut<=nOut );
zOut[iOut] = 0;
sqlite3_result_text(pCtx, zOut, iOut, SQLITE_DYNAMIC);
break;
}
case JSONB_ARRAY:
case JSONB_OBJECT: {
| > | > > > > > | | 212312 212313 212314 212315 212316 212317 212318 212319 212320 212321 212322 212323 212324 212325 212326 212327 212328 212329 212330 212331 212332 212333 |
assert( iOut<=nOut );
zOut[iOut] = 0;
sqlite3_result_text(pCtx, zOut, iOut, SQLITE_DYNAMIC);
break;
}
case JSONB_ARRAY:
case JSONB_OBJECT: {
if( eMode==0 ){
if( (SQLITE_PTR_TO_INT(sqlite3_user_data(pCtx)) & JSON_BLOB)!=0 ){
eMode = 2;
}else{
eMode = 1;
}
}
if( eMode==2 ){
sqlite3_result_blob(pCtx, &pParse->aBlob[i], sz+n, SQLITE_TRANSIENT);
}else{
jsonReturnTextJsonFromBlob(pCtx, &pParse->aBlob[i], sz+n);
}
break;
}
default: {
|
| ︙ | ︙ | |||
213950 213951 213952 213953 213954 213955 213956 213957 213958 213959 213960 213961 213962 213963 213964 213965 213966 213967 213968 213969 213970 213971 213972 213973 213974 |
sqlite3_vtab_cursor base; /* Base class - must be first */
u32 iRowid; /* The rowid */
u32 i; /* Index in sParse.aBlob[] of current row */
u32 iEnd; /* EOF when i equals or exceeds this value */
u32 nRoot; /* Size of the root path in bytes */
u8 eType; /* Type of the container for element i */
u8 bRecursive; /* True for json_tree(). False for json_each() */
u32 nParent; /* Current nesting depth */
u32 nParentAlloc; /* Space allocated for aParent[] */
JsonParent *aParent; /* Parent elements of i */
sqlite3 *db; /* Database connection */
JsonString path; /* Current path */
JsonParse sParse; /* Parse of the input JSON */
};
typedef struct JsonEachConnection JsonEachConnection;
struct JsonEachConnection {
sqlite3_vtab base; /* Base class - must be first */
sqlite3 *db; /* Database connection */
};
/* Constructor for the json_each virtual table */
static int jsonEachConnect(
sqlite3 *db,
void *pAux,
| > > > | 213966 213967 213968 213969 213970 213971 213972 213973 213974 213975 213976 213977 213978 213979 213980 213981 213982 213983 213984 213985 213986 213987 213988 213989 213990 213991 213992 213993 |
sqlite3_vtab_cursor base; /* Base class - must be first */
u32 iRowid; /* The rowid */
u32 i; /* Index in sParse.aBlob[] of current row */
u32 iEnd; /* EOF when i equals or exceeds this value */
u32 nRoot; /* Size of the root path in bytes */
u8 eType; /* Type of the container for element i */
u8 bRecursive; /* True for json_tree(). False for json_each() */
u8 eMode; /* 1 for json_each(). 2 for jsonb_each() */
u32 nParent; /* Current nesting depth */
u32 nParentAlloc; /* Space allocated for aParent[] */
JsonParent *aParent; /* Parent elements of i */
sqlite3 *db; /* Database connection */
JsonString path; /* Current path */
JsonParse sParse; /* Parse of the input JSON */
};
typedef struct JsonEachConnection JsonEachConnection;
struct JsonEachConnection {
sqlite3_vtab base; /* Base class - must be first */
sqlite3 *db; /* Database connection */
u8 eMode; /* 1 for json_each(). 2 for jsonb_each() */
u8 bRecursive; /* True for json_tree(). False for json_each() */
};
/* Constructor for the json_each virtual table */
static int jsonEachConnect(
sqlite3 *db,
void *pAux,
|
| ︙ | ︙ | |||
214003 214004 214005 214006 214007 214008 214009 214010 214011 214012 214013 214014 214015 214016 214017 214018 214019 214020 |
"json HIDDEN,root HIDDEN)");
if( rc==SQLITE_OK ){
pNew = (JsonEachConnection*)sqlite3DbMallocZero(db, sizeof(*pNew));
*ppVtab = (sqlite3_vtab*)pNew;
if( pNew==0 ) return SQLITE_NOMEM;
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
pNew->db = db;
}
return rc;
}
/* destructor for json_each virtual table */
static int jsonEachDisconnect(sqlite3_vtab *pVtab){
JsonEachConnection *p = (JsonEachConnection*)pVtab;
sqlite3DbFree(p->db, pVtab);
return SQLITE_OK;
}
| > > | | > > < < < < < < < < < < | 214022 214023 214024 214025 214026 214027 214028 214029 214030 214031 214032 214033 214034 214035 214036 214037 214038 214039 214040 214041 214042 214043 214044 214045 214046 214047 214048 214049 214050 214051 214052 214053 214054 214055 214056 214057 214058 214059 214060 214061 214062 214063 214064 |
"json HIDDEN,root HIDDEN)");
if( rc==SQLITE_OK ){
pNew = (JsonEachConnection*)sqlite3DbMallocZero(db, sizeof(*pNew));
*ppVtab = (sqlite3_vtab*)pNew;
if( pNew==0 ) return SQLITE_NOMEM;
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
pNew->db = db;
pNew->eMode = argv[0][4]=='b' ? 2 : 1;
pNew->bRecursive = argv[0][4+pNew->eMode]=='t';
}
return rc;
}
/* destructor for json_each virtual table */
static int jsonEachDisconnect(sqlite3_vtab *pVtab){
JsonEachConnection *p = (JsonEachConnection*)pVtab;
sqlite3DbFree(p->db, pVtab);
return SQLITE_OK;
}
/* constructor for a JsonEachCursor object for json_each()/json_tree(). */
static int jsonEachOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
JsonEachConnection *pVtab = (JsonEachConnection*)p;
JsonEachCursor *pCur;
UNUSED_PARAMETER(p);
pCur = sqlite3DbMallocZero(pVtab->db, sizeof(*pCur));
if( pCur==0 ) return SQLITE_NOMEM;
pCur->db = pVtab->db;
pCur->eMode = pVtab->eMode;
pCur->bRecursive = pVtab->bRecursive;
jsonStringZero(&pCur->path);
*ppCursor = &pCur->base;
return SQLITE_OK;
}
/* Reset a JsonEachCursor back to its original state. Free any memory
** held. */
static void jsonEachCursorReset(JsonEachCursor *p){
jsonParseReset(&p->sParse);
jsonStringReset(&p->path);
sqlite3DbFree(p->db, p->aParent);
p->iRowid = 0;
|
| ︙ | ︙ | |||
214242 214243 214244 214245 214246 214247 214248 |
assert( p->eType==JSONB_ARRAY );
sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iKey);
}
break;
}
case JEACH_VALUE: {
u32 i = jsonSkipLabel(p);
| | | 214255 214256 214257 214258 214259 214260 214261 214262 214263 214264 214265 214266 214267 214268 214269 |
assert( p->eType==JSONB_ARRAY );
sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iKey);
}
break;
}
case JEACH_VALUE: {
u32 i = jsonSkipLabel(p);
jsonReturnFromBlob(&p->sParse, i, ctx, p->eMode);
if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY ){
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
break;
}
case JEACH_TYPE: {
u32 i = jsonSkipLabel(p);
|
| ︙ | ︙ | |||
214486 214487 214488 214489 214490 214491 214492 |
static sqlite3_module jsonEachModule = {
0, /* iVersion */
0, /* xCreate */
jsonEachConnect, /* xConnect */
jsonEachBestIndex, /* xBestIndex */
jsonEachDisconnect, /* xDisconnect */
0, /* xDestroy */
| | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 214499 214500 214501 214502 214503 214504 214505 214506 214507 214508 214509 214510 214511 214512 214513 |
static sqlite3_module jsonEachModule = {
0, /* iVersion */
0, /* xCreate */
jsonEachConnect, /* xConnect */
jsonEachBestIndex, /* xBestIndex */
jsonEachDisconnect, /* xDisconnect */
0, /* xDestroy */
jsonEachOpen, /* xOpen - open a cursor */
jsonEachClose, /* xClose - close a cursor */
jsonEachFilter, /* xFilter - configure scan constraints */
jsonEachNext, /* xNext - advance a cursor */
jsonEachEof, /* xEof - check for end of scan */
jsonEachColumn, /* xColumn - read data */
jsonEachRowid, /* xRowid - read data */
0, /* xUpdate */
|
| ︙ | ︙ | |||
214604 214605 214606 214607 214608 214609 214610 | }; sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc)); #endif } #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) /* | | > | | | < < < < | < > | > | | > | | 214588 214589 214590 214591 214592 214593 214594 214595 214596 214597 214598 214599 214600 214601 214602 214603 214604 214605 214606 214607 214608 214609 214610 214611 214612 214613 214614 214615 214616 |
};
sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc));
#endif
}
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
/*
** Register the JSON table-valued function named zName and return a
** pointer to its Module object. Return NULL if something goes wrong.
*/
SQLITE_PRIVATE Module *sqlite3JsonVtabRegister(sqlite3 *db, const char *zName){
unsigned int i;
static const char *azModule[] = {
"json_each", "json_tree", "jsonb_each", "jsonb_tree"
};
assert( sqlite3HashFind(&db->aModule, zName)==0 );
for(i=0; i<sizeof(azModule)/sizeof(azModule[0]); i++){
if( sqlite3StrICmp(azModule[i],zName)==0 ){
return sqlite3VtabCreateModule(db, azModule[i], &jsonEachModule, 0, 0);
}
}
return 0;
}
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) */
/************** End of json.c ************************************************/
/************** Begin file rtree.c *******************************************/
/*
** 2001 September 15
|
| ︙ | ︙ | |||
234699 234700 234701 234702 234703 234704 234705 234706 234707 234708 234709 234710 234711 234712 |
sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0);
sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
}
}
assert( sApply.bRebase || sApply.rebase.nBuf==0 );
if( rc==SQLITE_OK && bPatchset==0 && sApply.bRebase ){
*ppRebase = (void*)sApply.rebase.aBuf;
*pnRebase = sApply.rebase.nBuf;
sApply.rebase.aBuf = 0;
}
sessionUpdateFree(&sApply);
sqlite3_finalize(sApply.pInsert);
sqlite3_finalize(sApply.pDelete);
| > | 234682 234683 234684 234685 234686 234687 234688 234689 234690 234691 234692 234693 234694 234695 234696 |
sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0);
sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
}
}
assert( sApply.bRebase || sApply.rebase.nBuf==0 );
if( rc==SQLITE_OK && bPatchset==0 && sApply.bRebase ){
assert( ppRebase!=0 && pnRebase!=0 );
*ppRebase = (void*)sApply.rebase.aBuf;
*pnRebase = sApply.rebase.nBuf;
sApply.rebase.aBuf = 0;
}
sessionUpdateFree(&sApply);
sqlite3_finalize(sApply.pInsert);
sqlite3_finalize(sApply.pDelete);
|
| ︙ | ︙ | |||
252412 252413 252414 252415 252416 252417 252418 |
union {
Fts5Structure sFts;
u8 tmpSpace[SZ_FTS5STRUCTURE(1)];
} uFts;
fts5StructureInvalidate(p);
fts5IndexDiscardData(p);
pTmp = &uFts.sFts;
| | | 252396 252397 252398 252399 252400 252401 252402 252403 252404 252405 252406 252407 252408 252409 252410 |
union {
Fts5Structure sFts;
u8 tmpSpace[SZ_FTS5STRUCTURE(1)];
} uFts;
fts5StructureInvalidate(p);
fts5IndexDiscardData(p);
pTmp = &uFts.sFts;
memset(uFts.tmpSpace, 0, sizeof(uFts.tmpSpace));
if( p->pConfig->bContentlessDelete ){
pTmp->nOriginCntr = 1;
}
fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
fts5StructureWrite(p, pTmp);
return fts5IndexReturn(p);
}
|
| ︙ | ︙ | |||
258720 258721 258722 258723 258724 258725 258726 |
static void fts5SourceIdFunc(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
sqlite3_value **apUnused /* Function arguments */
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
| | | 258704 258705 258706 258707 258708 258709 258710 258711 258712 258713 258714 258715 258716 258717 258718 |
static void fts5SourceIdFunc(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
sqlite3_value **apUnused /* Function arguments */
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
sqlite3_result_text(pCtx, "fts5: 2025-09-26 11:47:13 d022ee167b90a7c32049a93d476e869270018017f60551185024409730d77640", -1, SQLITE_TRANSIENT);
}
/*
** Implementation of fts5_locale(LOCALE, TEXT) function.
**
** If parameter LOCALE is NULL, or a zero-length string, then a copy of
** TEXT is returned. Otherwise, both LOCALE and TEXT are interpreted as
|
| ︙ | ︙ |
Changes to extsrc/sqlite3.h.
| ︙ | ︙ | |||
144 145 146 147 148 149 150 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.51.0" #define SQLITE_VERSION_NUMBER 3051000 | | | | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.51.0" #define SQLITE_VERSION_NUMBER 3051000 #define SQLITE_SOURCE_ID "2025-09-26 13:14:20 911c745f88c0ee8569e67bbcbbab034264f8c981b505aadac3ce7289486a1a68" #define SQLITE_SCM_BRANCH "trunk" #define SQLITE_SCM_TAGS "" #define SQLITE_SCM_DATETIME "2025-09-26T13:14:20.156Z" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| ︙ | ︙ |
Changes to src/regexp.c.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 | ** ** ** The following regular expression syntax is supported: ** ** X* zero or more occurrences of X ** X+ one or more occurrences of X ** X? zero or one occurrences of X | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
**
**
** The following regular expression syntax is supported:
**
** X* zero or more occurrences of X
** X+ one or more occurrences of X
** X? zero or one occurrences of X
** X{p,q} between p and q occurrences of X, 0 <= p,q <= 999
** (X) match X
** X|Y X or Y
** ^X X occurring at the beginning of the string
** X$ X occurring at the end of the string
** . Match any single character
** \c Character c where c is one of \{}()[]|*+?.
** \c C-language escapes for c in afnrtv. ex: \t or \n
|
| ︙ | ︙ | |||
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
** A nondeterministic finite automaton (NFA) is used for matching, so the
** performance is bounded by O(N*M) where N is the size of the regular
** expression and M is the size of the input string. The matcher never
** exhibits exponential behavior. Note that the X{p,q} operator expands
** to p copies of X following by q-p copies of X? and that the size of the
** regular expression in the O(N*M) performance bound is computed after
** this expansion.
*/
#include "config.h"
#include "regexp.h"
/* The end-of-input character */
#define RE_EOF 0 /* End of input */
/* The NFA is implemented as sequence of opcodes taken from the following
** set. Each opcode has a single integer argument.
*/
#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 .* */
| > > > > > > > > | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
** A nondeterministic finite automaton (NFA) is used for matching, so the
** performance is bounded by O(N*M) where N is the size of the regular
** expression and M is the size of the input string. The matcher never
** exhibits exponential behavior. Note that the X{p,q} operator expands
** to p copies of X following by q-p copies of X? and that the size of the
** regular expression in the O(N*M) performance bound is computed after
** this expansion.
**
** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax
** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999.
*/
#include "config.h"
#include "regexp.h"
#ifndef SQLITE_MAX_REGEXP_REPEAT
# define SQLITE_MAX_REGEXP_REPEAT 999
#endif
/* 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. Each opcode has a single integer argument.
*/
#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 .* */
|
| ︙ | ︙ | |||
78 79 80 81 82 83 84 85 86 87 88 89 90 91 | #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 */ /* Each opcode is a "state" in the NFA */ typedef unsigned short ReStateNumber; /* Because this is an NFA and not a DFA, multiple states can be active at ** once. An instance of the following object records all active states in ** the NFA. The implementation is optimized for the common case where the | > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #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 */ typedef unsigned short ReStateNumber; /* Because this is an NFA and not a DFA, multiple states can be active at ** once. An instance of the following object records all active states in ** the NFA. The implementation is optimized for the common case where the |
| ︙ | ︙ | |||
183 184 185 186 187 188 189 |
*/
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;
| | > | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
*/
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;
in.z = zIn;
in.i = 0;
in.mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn);
/* Look for the initial prefix match, if there is one. */
if( pRe->nInit ){
unsigned char x = pRe->zInit[0];
while( in.i+pRe->nInit<=in.mx
&& (zIn[in.i]!=x ||
strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
){
in.i++;
}
if( in.i+pRe->nInit>in.mx ) return 0;
c = RE_START-1;
}
if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
pToFree = 0;
aStateSet[0].aState = aSpace;
}else{
pToFree = fossil_malloc( sizeof(ReStateNumber)*2*pRe->nState );
|
| ︙ | ︙ | |||
229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
pNext->nState = 0;
for(i=0; i<pThis->nState; i++){
int x = pThis->aState[i];
switch( pRe->aOp[x] ){
case RE_OP_MATCH: {
if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
break;
}
case RE_OP_ANY: {
if( c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_WORD: {
if( re_word_char(c) ) re_add_state(pNext, x+1);
| > > > > | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
pNext->nState = 0;
for(i=0; i<pThis->nState; i++){
int x = pThis->aState[i];
switch( pRe->aOp[x] ){
case RE_OP_MATCH: {
if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
break;
}
case RE_OP_ATSTART: {
if( cPrev==RE_START ) re_add_state(pThis, x+1);
break;
}
case RE_OP_ANY: {
if( c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_WORD: {
if( re_word_char(c) ) re_add_state(pNext, x+1);
|
| ︙ | ︙ | |||
311 312 313 314 315 316 317 |
if( hit ) re_add_state(pNext, x+n);
break;
}
}
}
}
for(i=0; i<pNext->nState; i++){
| > > | | 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
if( hit ) re_add_state(pNext, x+n);
break;
}
}
}
}
for(i=0; i<pNext->nState; i++){
int x = pNext->aState[i];
while( pRe->aOp[x]==RE_OP_GOTO ) x += pRe->aArg[x];
if( pRe->aOp[x]==RE_OP_ACCEPT ){ rc = 1; break; }
}
re_match_end:
fossil_free(pToFree);
return rc;
}
/* Resize the opcode and argument arrays for an RE under construction.
|
| ︙ | ︙ | |||
466 467 468 469 470 471 472 |
int iStart;
unsigned c;
const char *zErr;
while( (c = p->xNextChar(&p->sIn))!=0 ){
iStart = p->nState;
switch( c ){
case '|':
| < | 482 483 484 485 486 487 488 489 490 491 492 493 494 495 |
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;
|
| ︙ | ︙ | |||
502 503 504 505 506 507 508 509 510 |
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 '{': {
| > > > > > > > > | | | > > > > | > > > > > | | 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 |
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>SQLITE_MAX_REGEXP_REPEAT ) return "integer too large";
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>SQLITE_MAX_REGEXP_REPEAT ) return "integer too large";
p->sIn.i++;
}
}
if( c!='}' ) return "unmatched '{'";
if( n>0 && 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, -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 ){
|
| ︙ | ︙ | |||
559 560 561 562 563 564 565 |
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 '['";
| | | 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 |
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;
|
| ︙ | ︙ | |||
639 640 641 642 643 644 645 |
pRe->sIn.i = 0;
pRe->sIn.mx = (int)strlen(zIn);
zErr = re_subcompile_re(pRe);
if( zErr ){
re_free(pRe);
return zErr;
}
| < < < < | | | | | | 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 |
pRe->sIn.i = 0;
pRe->sIn.mx = (int)strlen(zIn);
zErr = re_subcompile_re(pRe);
if( zErr ){
re_free(pRe);
return zErr;
}
if( pRe->sIn.i>=pRe->sIn.mx ){
re_append(pRe, RE_OP_ACCEPT, 0);
*ppRe = pRe;
}else{
re_free(pRe);
return "unrecognized character";
}
/* 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--;
|
| ︙ | ︙ |
Changes to www/grep.md.
| ︙ | ︙ | |||
97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
| `\S` | Non-whitespace character: `[^ \t\r\n\v\f]`
There are several restrictions in Fossil `grep` relative to a fully
POSIX compatible regular expression engine. Among them are:
* There is currently no support for POSIX character classes such as
`[:lower:]`.
* Fossil `grep` does not currently attempt to take your operating
system's locale settings into account when doing this match. Since
Fossil has no way to mark a given file as having a particular
encoding, Fossil `grep` assumes the input files are in UTF-8 format.
This means Fossil `grep` will not work correctly if the files in
| > > > > > | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
| `\S` | Non-whitespace character: `[^ \t\r\n\v\f]`
There are several restrictions in Fossil `grep` relative to a fully
POSIX compatible regular expression engine. Among them are:
* There is currently no support for POSIX character classes such as
`[:lower:]`.
* The values of `p` and `q` in the "`{p,q}`" syntax can be no greater
than 999. This is because the NFA that is used for regular expression
matching is proportional in size to the largest p or q value, and hence
allowing arbitrarily large values could result in a DoS attack.
* Fossil `grep` does not currently attempt to take your operating
system's locale settings into account when doing this match. Since
Fossil has no way to mark a given file as having a particular
encoding, Fossil `grep` assumes the input files are in UTF-8 format.
This means Fossil `grep` will not work correctly if the files in
|
| ︙ | ︙ |